Games-AIBots
view release on metacpan or search on metacpan
lib/Games/AIBot.pm view on Meta::CPAN
my $condflag = int($line !~ m/^(?:\$|if|else|elsif|unless|print)/);
$line =~ s/\$(\w+)/exists($bot->[0]->{$1}) ? "\${\$bot}{$1}" : "\${\$bot}{'var'}{$1}"/eg;
$line =~ s/\&(?=\w+)/\$bot->_/g;
$bot->{'lineidx'} .= $condflag; # and (index($line, '$') > -1));
$bot->{'stateidx'}{$1} = $count
if $line =~ /^sub[\s\t]+(.+)[\s\t]+{/ or $line =~ /^(.+):[\s\t]*{/;
$bot->{'condidx'} .= int($line ne '}') +
($line =~ /^(?:if|unless|elsif|else|sub|.+:)[\s\t]/);
}
$bot->{'queue'} = [];
$bot->{'missiles'} = [];
$bot->{'line'} = 0;
return $bot;
}
sub loadfile {
my ($bot, $file) = @_;
my @include;
open _, $file or die "Cannot load bot $file: $!";
while (<_>) {
chomp;
s/#[\s\t].+//;
s/^[\s\t]+//;
s/[\s\t\;]+$//;
s/^(.+)[\s\t]+(if|unless)[\s\t]+(.+)$/$2 ($3) {\n$1\n}\n/g;
if (/^require[\s\t]+\'?([^\']+)\'?/) {
push @include, substr($file, 0, rindex($file, '/')+1).$1;
}
else {
push (@{$bot->{'cmds'}}, split("\n", $_)) if $_;
}
}
close _;
$bot->loadfile($_) foreach @include;
}
sub cond {
my $bot = $_[0];
my $cmd = eval($_[1]);
if ($@) { die "[Cond $_[1] :".$bot->{'name'}.':'.$bot->{'state'}.'] '.$@ };
return $cmd;
}
sub tick {
my $bot = shift;
my $count;
while (my $line = $bot->nextline()) {
next if $line eq '}';
if ($count++ > 100) {
warn "recursion too deep";
return;
}
if ($line =~ /^\$[{\w]/) {
$bot->cond($line);
}
elsif ($line =~ /^(?:else|elsif)[\s\t]/) {
$bot->endif();
}
elsif ($line =~ /^sub[\s\t]+(.+)[\s\t]+{$/ or $line =~ /^(.+):[\s\t]*{$/) {
$bot->{'state'} = $1;
}
elsif ($line =~ /^goto[\s\t]+(.+)/) {
pop @{$bot->{'stack'}};
$bot->gotostate($1);
}
elsif ($line =~ /^call[\s\t]+(.+)/ or $line =~ /^(.+)\(\)$/) {
push @{$bot->{'stack'}}, [@{$bot}{'state', 'line'}];
# print "call from line ",$bot->{'line'},"\n";
$bot->gotostate($1);
}
elsif ($line eq 'redo') {
$bot->gotostate($bot->{'state'});
}
elsif ($line eq 'return') {
warn $bot->{'name'}." cannot return from state ".$bot->{'state'}
unless ($bot->{'stack'} and @{$bot->{'stack'}});
eval{@{$bot}{'state', 'line'} = @{pop(@{$bot->{'stack'}})}};
# print "return to line ",$bot->{'line'},"\n";
}
elsif ($line =~ /^(if|unless)[\s\t]+(.+){$/) {
if ($1 eq 'if' xor $bot->cond($2)) {
while (my $cond = $bot->elseif()) {
($bot->{'line'}++, last) if ($bot->cond($cond));
}
$bot->{'line'}--; # end all blocks
}
}
elsif ($line =~ /^(e|d)(?:nable|isable)[\s\t]+(\w+)/) {
return $line if ($1 eq 'e' xor $bot->{$2});
}
elsif ($line =~ /^print[\s\t]+/) {
$bot->cond($line);
print "\n";
}
else {
# command
my $times = ((int($1) eq $1) ? $1 : $bot->cond($1))
if ($line =~ s/\s*\*\s*(.+)$//);
my @cmds;
push @cmds, $line for (1..($times || 1));
return @cmds;
}
}
}
sub endif {
my $bot = shift;
my $depth = 1;
while ($bot->{'line'}++) {
$depth += substr($bot->{'condidx'}, $bot->{'line'} - 1, 1) - 1;
return unless $depth;
( run in 2.016 seconds using v1.01-cache-2.11-cpan-14f38c9f855 )