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 )