Hi Monks,
With AnyEvent and TermScreen modules, I would like to share with you a 100 lines script which emulate a race horse, I think it is funny :-).
#!/usr/bin/perl -w
use strict;
my $nhorses=10;
my $finished=AnyEvent->condvar;
require Term::Screen;
use AnyEvent;
sub status
{
my ($scr,$string) = @_;
$scr->at ($nhorses,0)->clreol->reverse->bold->puts ("$string")->no
+rmal;
}
sub next_step
{
my ($scr,$horses) = @_;
my $max_jump=4;
foreach my $horse (keys %$horses)
{
my $step=int(rand($max_jump)); $horses->{$horse}+=$step;
if ($step == $max_jump-1 and (int (rand (20)) == 19))
{
$horses->{$horse}+=$max_jump-1;
status $scr, "Wowwww $horse went to infinity!!";
}
}
if (int(rand(10)) == 9)
{
status $scr, "Horses delayed: ". join (",",
((sort {$horses->{$a} <=> $horses->{$b}}
keys %$horses)[0..2]));
}
}
sub draw_horses
{
my ($scr,$horses) = @_;
$scr-> at ( $_-1,$horses->{$_}-length $horses->{$_}+1)->puts($_)
foreach sort { $a <=> $b } keys %$horses;
}
sub draw_end
{
my ($scr,$horses) = @_;
$scr-> at ( $_-1,49)->puts("|") foreach keys %$horses;
}
sub clean_horses
{
my ($scr,$horses) = @_;
$scr-> at ( $_-1, $horses->{$_}-length $horses->{$_}+1)
-> puts(" " x length $_) foreach sort { $a <=> $b } keys %$hor
+ses;
}
sub race_finished
{
my ($scr,$horses) = @_;
my @winers = grep {$horses->{$_} > 50} (keys %$horses);
if (scalar @winers > 0)
{
status $scr, "And the winner is: ".
$winers[int(rand(scalar @winers))]."\r\n";
return 1;
}
return 0;
}
sub init_screen
{
my ($horses) = @_;
my $scr = new Term::Screen;
unless ($scr) { die "Something's wrong\n"; }
$scr->clrscr(); system ("stty isig"); system ("tput civis");
draw_horses ($scr,$horses); draw_end ($scr, $horses);
status $scr, "Ready ..."; sleep 1; status $scr, "Stady ..."; sleep
+ 1;
status $scr, "Go! ...";
return $scr;
}
sub update_screen
{
my ($scr,$horses) = @_;
clean_horses ($scr,$horses);
next_step ($scr,$horses);
draw_horses ($scr, $horses);
$finished -> send if (scalar race_finished($scr,$horses));
}
my $w = AnyEvent->signal (signal => "INT", cb =>
sub { system("tput cvvis"); print "Finished before the end\n"; exi
+t 1 });
my %horses= map { $_ => 0 } (1..$nhorses);
my $scr=init_screen (\%horses);
my $hr = AnyEvent->timer (after => 2, interval => 1,
cb => sub {update_screen ($scr,\%horses); });
$finished->recv;
I hope this script is ok for this section ... and other monks enjoy with the game. I even hacked an telnet server running that horse race using inet and IO::Socket::INET, but I cannot publish it online :-)
Could be many improvements to the game:
Allow bets
using festival if available
Adding ondemand telnet server
Rewrite without Term::Screen / AnyEvent dependencies ?
Please share your comments about the code if you see things done in the wrong way ! thanks!
Regards,
PD: It would be nice to see my patches https://rt.cpan.org/Public/Bug/Display.html?id=75858 and https://rt.cpan.org/Public/Bug/Display.html?id=75862 applied to Term::Screen module, so less tput / stty hacks have to be used.
-
Are you posting in the right place? Check out Where do I post X? to know for sure.
-
Posts may use any of the Perl Monks Approved HTML tags. Currently these include the following:
<code> <a> <b> <big>
<blockquote> <br /> <dd>
<dl> <dt> <em> <font>
<h1> <h2> <h3> <h4>
<h5> <h6> <hr /> <i>
<li> <nbsp> <ol> <p>
<small> <strike> <strong>
<sub> <sup> <table>
<td> <th> <tr> <tt>
<u> <ul>
-
Snippets of code should be wrapped in
<code> tags not
<pre> tags. In fact, <pre>
tags should generally be avoided. If they must
be used, extreme care should be
taken to ensure that their contents do not
have long lines (<70 chars), in order to prevent
horizontal scrolling (and possible janitor
intervention).
-
Want more info? How to link
or How to display code and escape characters
are good places to start.