2014-12-20 15:35:19 +00:00
|
|
|
#! /usr/bin/perl
|
|
|
|
use strict;
|
|
|
|
use warnings;
|
|
|
|
|
2014-12-20 17:17:04 +00:00
|
|
|
our $ttrts_perlai_versioncompat_major = 0;
|
2014-12-29 21:59:59 +00:00
|
|
|
our $ttrts_perlai_versioncompat_minor = 3;
|
|
|
|
|
|
|
|
our $headerDelimiter="~~~~";
|
|
|
|
|
|
|
|
our $VERBOSE = $ENV{"VERBOSE"};
|
|
|
|
|
|
|
|
# Format of the a gamestate header
|
|
|
|
our $headerFormatter = qr/==== ttrts v(\d+)\.(\d+)\.(\d+)+ ====
|
|
|
|
NAME:(.+)
|
|
|
|
SIZE:\[(\d+),(\d+)\]
|
|
|
|
TURN:(\d+)
|
|
|
|
(WALL:.*?)
|
|
|
|
$headerDelimiter/;
|
|
|
|
|
|
|
|
# Formatter for coords
|
|
|
|
our $coordFormatter = qr/\[\d+,\d+\]/;
|
|
|
|
|
|
|
|
# Format of a unit descriptor
|
|
|
|
our $unitFormatterNonCapture = qr/UNIT:\d+ pl:\d+ vs:[^ ]+ dr:[^ ]+ ps:\[\d+,\d+\]\n?/;
|
|
|
|
|
|
|
|
# Format of a unit descriptor
|
|
|
|
our $unitFormatter = qr/UNIT:(\d+) pl:(\d+) vs:([^ ]+) dr:([^ ]+) ps:\[(\d+),(\d+)\]\n?/;
|
|
|
|
|
|
|
|
# Get x and y
|
|
|
|
sub getPositionsXandYString
|
|
|
|
{
|
|
|
|
return (shift =~ /\[(\d+),(\d+)\]/);
|
|
|
|
}
|
|
|
|
|
|
|
|
# Get all positions
|
|
|
|
sub getPositionStringsFromLine
|
|
|
|
{
|
|
|
|
return (shift =~ /$coordFormatter/gm );
|
|
|
|
}
|
2014-12-20 17:17:04 +00:00
|
|
|
|
2014-12-20 15:35:19 +00:00
|
|
|
# Get information about a unit from it's descriptor
|
2014-12-29 21:59:59 +00:00
|
|
|
sub getUnitInfo
|
2014-12-20 15:35:19 +00:00
|
|
|
{
|
2014-12-29 21:59:59 +00:00
|
|
|
return (shift =~ /$unitFormatter/);
|
2014-12-20 15:35:19 +00:00
|
|
|
}
|
|
|
|
|
2014-12-29 21:59:59 +00:00
|
|
|
# Get set of units from a string
|
|
|
|
sub GetUnitStringsFromGamestate
|
2014-12-20 15:35:19 +00:00
|
|
|
{
|
2014-12-29 21:59:59 +00:00
|
|
|
my $gamestate = shift;
|
|
|
|
|
|
|
|
my @units = ( $gamestate =~ /$unitFormatterNonCapture/gm );
|
2014-12-20 15:35:19 +00:00
|
|
|
|
2014-12-29 21:59:59 +00:00
|
|
|
foreach my $unit (@units)
|
2014-12-20 15:35:19 +00:00
|
|
|
{
|
2014-12-29 21:59:59 +00:00
|
|
|
chomp($unit);
|
2014-12-20 15:35:19 +00:00
|
|
|
}
|
|
|
|
|
|
|
|
return @units;
|
|
|
|
}
|
|
|
|
|
2014-12-29 21:59:59 +00:00
|
|
|
# in the format $major,$minor,$patch,$name,$sizex,$sizey,$turn,$invalidpositions+
|
|
|
|
sub GetGameInfoFromGamestate
|
|
|
|
{
|
|
|
|
my $header = shift;
|
|
|
|
(! defined $header) and die "GetGameInfoFromGamestate was not passed valid header parameter";
|
|
|
|
|
|
|
|
my @info = ($header =~ /$headerFormatter/ );
|
|
|
|
|
|
|
|
return @info;
|
|
|
|
}
|
|
|
|
|
|
|
|
# Get the units from a turn file
|
|
|
|
sub GetUnitStringsFromFile
|
|
|
|
{
|
|
|
|
my $turnFile = shift or die "GetUnitStringsFromFile needs file parameter";
|
|
|
|
|
|
|
|
# Read in the whole file method from http://www.perlmonks.org/?node_id=1952
|
|
|
|
my $text;
|
|
|
|
{
|
|
|
|
local $/=undef;
|
|
|
|
open FILE, $turnFile or die "Couldn't open file: $!";
|
|
|
|
$text = <FILE>;
|
|
|
|
close FILE;
|
|
|
|
}
|
|
|
|
|
|
|
|
return GetUnitStringsFromGamestate($text);
|
|
|
|
}
|
|
|
|
|
2014-12-20 17:17:04 +00:00
|
|
|
# Check version numbers against ttrts.pm version
|
2014-12-29 21:59:59 +00:00
|
|
|
sub verifyVersion
|
2014-12-20 17:17:04 +00:00
|
|
|
{
|
|
|
|
my $version_major = shift;
|
2014-12-29 21:59:59 +00:00
|
|
|
(! defined $version_major) and die "verifyVersion needs version_major parameter";
|
2014-12-20 17:17:04 +00:00
|
|
|
my $version_minor = shift;
|
2014-12-29 21:59:59 +00:00
|
|
|
(! defined $version_minor) and die "verifyVersion needs version_minor parameter";
|
2014-12-20 17:17:04 +00:00
|
|
|
if( ($version_major != $ttrts_perlai_versioncompat_major)
|
|
|
|
or ($version_minor != $ttrts_perlai_versioncompat_minor) )
|
|
|
|
{
|
|
|
|
printf "ttrts.pm version does not match with this ttrts version\n";
|
|
|
|
die "ttrts.pm = v$ttrts_perlai_versioncompat_minor.$ttrts_perlai_versioncompat_major ttrts = v$version_major.$version_minor";
|
|
|
|
}
|
|
|
|
}
|
|
|
|
|
2014-12-29 21:59:59 +00:00
|
|
|
|
2014-12-20 15:35:19 +00:00
|
|
|
# Get information from the header for this turn
|
2014-12-29 21:59:59 +00:00
|
|
|
sub GetGameInfoFromFile
|
2014-12-20 15:35:19 +00:00
|
|
|
{
|
2014-12-29 21:59:59 +00:00
|
|
|
my $turnFile = shift or die "GetGameInfoFromFile needs turnFile parameter";
|
2014-12-20 15:35:19 +00:00
|
|
|
|
2014-12-29 21:59:59 +00:00
|
|
|
# Read in the whole file method from http://www.perlmonks.org/?node_id=1952
|
|
|
|
my $text;
|
|
|
|
{
|
|
|
|
local $/=undef;
|
|
|
|
open FILE, $turnFile or die "Couldn't open file: $!";
|
|
|
|
$text = <FILE>;
|
|
|
|
close FILE;
|
|
|
|
}
|
2014-12-20 15:35:19 +00:00
|
|
|
|
2014-12-29 21:59:59 +00:00
|
|
|
my @info = GetGameInfoFromGamestate($text);
|
|
|
|
verifyVersion @info;
|
2014-12-20 15:35:19 +00:00
|
|
|
|
2014-12-29 21:59:59 +00:00
|
|
|
return @info;
|
2014-12-20 15:35:19 +00:00
|
|
|
}
|
|
|
|
|
2014-12-22 20:03:31 +00:00
|
|
|
# Get units from a specific player
|
2014-12-29 21:59:59 +00:00
|
|
|
sub GetPlayerUnits
|
2014-12-20 15:35:19 +00:00
|
|
|
{
|
2014-12-22 20:03:31 +00:00
|
|
|
my $thePlayer = shift;
|
2014-12-29 21:59:59 +00:00
|
|
|
(! defined $thePlayer) and die "GetPlayerUnits needs player parameter";
|
2014-12-20 15:35:19 +00:00
|
|
|
my @allUnits = @_;
|
2014-12-29 21:59:59 +00:00
|
|
|
(! @allUnits) and die "GetPlayerUnits needs units parameters";
|
2014-12-20 15:35:19 +00:00
|
|
|
my @myUnits;
|
|
|
|
|
|
|
|
for my $unit (@allUnits)
|
|
|
|
{
|
2014-12-22 20:03:31 +00:00
|
|
|
my ($unitplayer) = $unit =~ /pl:(\d+)/;
|
|
|
|
if ( $unitplayer == $thePlayer )
|
2014-12-20 15:35:19 +00:00
|
|
|
{
|
|
|
|
push(@myUnits,$unit);
|
|
|
|
}
|
|
|
|
}
|
|
|
|
|
|
|
|
return @myUnits;
|
|
|
|
}
|
|
|
|
|
2014-12-29 21:59:59 +00:00
|
|
|
sub GetTurnFileName
|
2014-12-20 15:35:19 +00:00
|
|
|
{
|
|
|
|
my $turn = shift;
|
2014-12-29 21:59:59 +00:00
|
|
|
(! defined $turn) and die "GetTurnFileName needs turn parameter";
|
2014-12-20 15:35:19 +00:00
|
|
|
my $turnFile = "Turn_TURN.txt";
|
|
|
|
$turnFile =~ s/TURN/$turn/;
|
|
|
|
return $turnFile;
|
|
|
|
}
|
|
|
|
|
2014-12-29 21:59:59 +00:00
|
|
|
sub GetCommandFileName
|
2014-12-20 15:35:19 +00:00
|
|
|
{
|
|
|
|
my $turn = shift;
|
2014-12-29 21:59:59 +00:00
|
|
|
(! defined $turn) and die "GetCommandFileName needs turn parameter";
|
2014-12-22 20:03:31 +00:00
|
|
|
my $player = shift;
|
2014-12-29 21:59:59 +00:00
|
|
|
(! defined $player) and die "GetCommandFileName needs player parameter";
|
2014-12-22 20:03:31 +00:00
|
|
|
my $cmdFileName = "Player_PLAYER_Turn_TURN.txt";
|
2014-12-20 15:35:19 +00:00
|
|
|
$cmdFileName =~ s/TURN/$turn/;
|
2014-12-22 20:03:31 +00:00
|
|
|
$cmdFileName =~ s/PLAYER/$player/;
|
2014-12-20 15:35:19 +00:00
|
|
|
return $cmdFileName;
|
|
|
|
}
|
|
|
|
|
|
|
|
# Output the commands file
|
|
|
|
sub OutputCommandsFile
|
|
|
|
{
|
|
|
|
my $turn = shift;
|
2014-12-29 21:59:59 +00:00
|
|
|
(! defined $turn) and die "OutputCommandsFile needs turn parameter";
|
2014-12-22 20:03:31 +00:00
|
|
|
my $player = shift;
|
2014-12-29 21:59:59 +00:00
|
|
|
(! defined $player) and die "OutputCommandsFile needs player parameter";
|
|
|
|
my $commands = shift or die "OutputCommandsFile needs commands parameter";
|
2014-12-20 15:35:19 +00:00
|
|
|
|
|
|
|
# Get output file
|
2014-12-29 21:59:59 +00:00
|
|
|
our $cmdFileName = GetCommandFileName($turn,$player);
|
2014-12-20 15:35:19 +00:00
|
|
|
|
|
|
|
if (! -e $cmdFileName)
|
|
|
|
{
|
|
|
|
open(my $cmdFile, '>', $cmdFileName) or die "Couldn't open '$cmdFileName' $!";
|
|
|
|
print $cmdFile $commands;
|
2014-12-20 17:17:04 +00:00
|
|
|
print $cmdFile "END";
|
2014-12-20 15:35:19 +00:00
|
|
|
close $cmdFile;
|
|
|
|
|
2014-12-29 21:59:59 +00:00
|
|
|
$VERBOSE and printf "Outputted $cmdFileName\n";
|
2014-12-20 15:35:19 +00:00
|
|
|
printf "$commands";
|
|
|
|
}
|
|
|
|
else
|
|
|
|
{
|
2014-12-29 21:59:59 +00:00
|
|
|
# Read in the whole file method from http://www.perlmonks.org/?node_id=1952
|
|
|
|
my $text;
|
|
|
|
{
|
|
|
|
local $/=undef;
|
|
|
|
open FILE, $cmdFileName or die "Couldn't open file: $!";
|
|
|
|
$text = <FILE>;
|
|
|
|
close FILE;
|
|
|
|
}
|
|
|
|
|
|
|
|
$text =~ s/\nEND//;
|
2014-12-20 15:35:19 +00:00
|
|
|
|
|
|
|
printf "Replaying $cmdFileName\n";
|
2014-12-29 21:59:59 +00:00
|
|
|
printf "$text\n";
|
2014-12-20 15:35:19 +00:00
|
|
|
}
|
|
|
|
}
|
|
|
|
|
|
|
|
# Print a game map
|
2014-12-29 21:59:59 +00:00
|
|
|
sub PrintGameFromGamestateString
|
2014-12-20 15:35:19 +00:00
|
|
|
{
|
2014-12-29 21:59:59 +00:00
|
|
|
my $gamestateString = shift or die "PrintGameFromGamestateString needs string parameter";
|
|
|
|
|
|
|
|
my @info = GetGameInfoFromGamestate($gamestateString);
|
|
|
|
my @units = GetUnitStringsFromGamestate($gamestateString);
|
|
|
|
|
|
|
|
# $major,$minor,$patch,$name,$sizex,$sizey,$turn,$invalidpositions+
|
|
|
|
my $gameX = $info[4];
|
|
|
|
my $gameY = $info[5];
|
|
|
|
|
|
|
|
# Shift into info to where the invalid positions are stored
|
|
|
|
my @invalids = getPositionStringsFromLine($info[7]);
|
2014-12-20 15:35:19 +00:00
|
|
|
|
|
|
|
my @map;
|
|
|
|
|
|
|
|
# Fill with blanks
|
|
|
|
for my $x (0 .. $gameX-1)
|
|
|
|
{
|
|
|
|
for my $y (0 .. $gameY-1)
|
|
|
|
{
|
|
|
|
$map[$x][$y] = "-";
|
|
|
|
}
|
|
|
|
}
|
|
|
|
|
2014-12-29 21:59:59 +00:00
|
|
|
# Fill in all invalid coordinates
|
|
|
|
foreach my $coord (@invalids)
|
|
|
|
{
|
|
|
|
my @invalidPos = getPositionsXandYString($coord);
|
|
|
|
$map[$invalidPos[0]][$invalidPos[1]] = "~";
|
|
|
|
}
|
|
|
|
|
2015-01-06 17:01:15 +00:00
|
|
|
# Fill with walls
|
|
|
|
foreach my $wall ( $info[8] =~ /\[(\d+,\d+)\]/g )
|
|
|
|
{
|
|
|
|
$wall =~ /(\d+),(\d+)/;
|
|
|
|
$map[$1][$2] = "|";
|
|
|
|
}
|
|
|
|
|
2014-12-20 15:35:19 +00:00
|
|
|
# Fill with units
|
|
|
|
for my $unit (@units)
|
|
|
|
{
|
2014-12-29 21:59:59 +00:00
|
|
|
my ($id,$pl,$vs,$dr,$psx,$psy) = getUnitInfo($unit);
|
2014-12-20 15:35:19 +00:00
|
|
|
|
2014-12-22 20:03:31 +00:00
|
|
|
$pl += 31;
|
|
|
|
$vs = "\e[".$pl."m".$vs."\e[0m";
|
2014-12-20 15:35:19 +00:00
|
|
|
|
|
|
|
$map[$psx][$psy] = $vs;
|
|
|
|
}
|
|
|
|
|
|
|
|
# Print whole map bottom left is 0,0
|
|
|
|
for my $y ( reverse 0 .. $gameY-1 )
|
|
|
|
{
|
|
|
|
for my $x (0 .. $gameX-1)
|
|
|
|
{
|
|
|
|
printf($map[$x][$y]);
|
|
|
|
}
|
|
|
|
printf("\n");
|
|
|
|
}
|
|
|
|
}
|
|
|
|
|
2014-12-29 21:59:59 +00:00
|
|
|
# Print a game map
|
|
|
|
sub PrintGameFromFile
|
|
|
|
{
|
|
|
|
my $turnFile = shift or die "PrintGameFromFile needs file parameter";
|
|
|
|
|
|
|
|
# Read in the whole file method from http://www.perlmonks.org/?node_id=1952
|
|
|
|
my $text;
|
|
|
|
{
|
|
|
|
local $/=undef;
|
|
|
|
open FILE, $turnFile or die "Couldn't open file: $!";
|
|
|
|
$text = <FILE>;
|
|
|
|
close FILE;
|
|
|
|
}
|
|
|
|
|
|
|
|
PrintGameFromGamestateString($text);
|
|
|
|
}
|
|
|
|
|
|
|
|
# Print a turn
|
|
|
|
sub PrintGameMapForTurn
|
|
|
|
{
|
|
|
|
my $turn = shift;
|
|
|
|
(! defined $turn) and die "PrintGameMapForTurn needs turn parameter";
|
|
|
|
$turn = GetTurnFileName($turn);
|
|
|
|
PrintGameFromFile( $turn );
|
|
|
|
}
|
|
|
|
|
2014-12-20 15:35:19 +00:00
|
|
|
# Wait for a file to exist
|
|
|
|
sub WaitForFile
|
|
|
|
{
|
2014-12-29 21:59:59 +00:00
|
|
|
my $file = shift or die "WaitForFile needs file parameter";
|
2014-12-20 15:35:19 +00:00
|
|
|
while( ! -e $file )
|
|
|
|
{
|
|
|
|
select(undef, undef, undef, 0.01);
|
|
|
|
}
|
|
|
|
}
|
|
|
|
|
|
|
|
return 1;
|