#! # Written by Tomas Rokicki, Radical Eye Software. # # This Perl script and the embedded JavaScript can be used under either # of two licenses, your choice: # # 1. The GPL. This is suitable if you make it part of another # collection of GPL code, in which case all rules and # regulations of the GPL apply. # # 2. Absolutely and completely public domain. Feel free to # use any or part of this script or its code, with or without # attribution, for any purpose whatsoever. # # Run with Perl. To process an adump file: # # perl adump2html.pl foo -m foo )) ; my $packlist = e() ; close P ; my $base ; for $base (@{$packlist}) { my @packs = @{$base->[1]} ; my $i ; for ($i=1; $i<@packs; $i += 2) { my %packdesc = @{$packs[$i]} ; $packw{$packdesc{'uid'}} = $packdesc{'weight'} ; } } } # # Read in the game log. The first part is the map. Use it to build # a board gif. # # We have to flip it if it starts with #, since that indicates a # Simulator game log. # while (<>) { last unless /^#/ ; } ($width, $height) = split " ", $_ ; $mult = 1 ; while (($mult + 1) * $width <= $goalwidth && ($mult + 1) * $height <= $goalheight) { $mult++ ; } ($realwidth, $realheight) = ($width * $mult, $height * $mult) ; @boardlines = () ; for ($i=0; $i<$height; $i++) { $lin = <> ; $newline = "" ; for ($j=0; $j<$width; $j++) { $c = substr($lin, $j, 1) ; if ($c eq '~') { $c = $watercolor ; } elsif ($c eq '.') { $c = $emptycolor ; } elsif ($c eq '#') { $c = $forestcolor ; } elsif ($c eq '@') { $c = $basecolor ; } else { die "Bad map char: $c\n" ; } $newline .= $c . ' ' ; } push @boardlines, "$newline\n" ; } # We are either in adump format or in Simulator log format. # # Simulator log format lines all start with ( or [. adump format # all start with R or I. # # Now read lines. Two sorts of lines, move lines (R), and identity # lines (I). # $movemax = 0 ; $linecount = 0 ; $adumplines = 0 ; $simlines = 0 ; sub mabs { my $r = shift ; return $r < 0 ? -$r : $r ; } my $linemod = 2 ; my %xpos ; my %ypos ; my %money ; my %packs ; while (<>) { chomp ; if (/^R/) { my ($move, $id, $x, $y, $score, $money, $packs, $req) = /^R (\d+) (-?\d+) (-?\d+) (-?\d+) (-?\d+) (-?\d+) (-?\d+) (.*)/ ; die "bad line $_" if !defined($req) ; $status[$move][$id] = "$x $y $score $money $packs" ; ($req, $death) = split '\|', $req ; $req[$move-1][$id] = $req if $move > 0 ; $movemax = $move if $move > $movemax ; if (defined($death)) { $req[$move][$id] = $death ; $movemax = $move + 1 if $move + 1 > $movemax ; } $nameof{$id} = $id if !defined($nameof{$id}) ; $adumplines++ ; } elsif (/^I/) { my ($id, $name) = /^I (\d+) (.*)/ ; $nameof{$id} = $name ; $adumplines++ ; } elsif (/^\[/ || /^\(/) { # # Is this a verbose game log (4 lines per move) or a not-verbose # game log (2 lines per move)? After eating the first line after # the board, the following line has the format # # [(#,#... # # if it's a four-line-per-move game log, and the format # # [(#,(#... # # if it's a two-line-per-move game log. # game log, and then, when we see the third line of the first move or # the first line of the second move, we try to figure out which it is. # # if ($linecount > 0) { # ignore first package line if ($linecount == 1) { # look at the first line to determine linemod $linemod = (/^\[\(\d+,\(/ ? 4 : 2) ; } if ($linecount % $linemod == $linemod-1) { # commands toparse($_) ; $botcmds = e() ; } elsif ($linecount % $linemod == 0) { # events # # The events really tell us everything we need to know, except of course # for the bot requests themselves. We do have to keep running counts of # the x and y positions, the money, and the number of packages carried by # each bot though in order to interpret the events. # toparse($_) ; $botev = e() ; $move = ($linecount / $linemod) - 1 ; $movemax = $move + 1 ; for $i (@{$botcmds}) { my ($id, $bid, @rest) = @{$i} ; $req[$move][$id] = "$bid " . show([@rest]) ; } for $i (@{$botev}) { my ($id, $cmds) = @{$i} ; my $j ; for ($j=0; $j<@{$cmds}; $j++) { my $cmd = $cmds->[$j] ; if ($cmd eq 'Spawned') { my $arg = $cmds->[++$j] ; $xpos{$id} = $arg->[0] ; $ypos{$id} = $arg->[1] ; $money{$id} = $moneyinit ; $packs{$id} = 0 ; $score{$id} = 0 ; } } $status[$move][$id] = "$xpos{$id} $ypos{$id} $score{$id} $money{$id} $packs{$id}" ; } for $i (@{$botcmds}) { my ($id, $bid, @rest) = @{$i} ; $money{$id} -= mabs($bid) ; } for $i (@{$botev}) { my ($id, $cmds) = @{$i} ; my $j ; for ($j=0; $j<@{$cmds}; $j++) { my $cmd = $cmds->[$j] ; if ($cmd eq 'Moved') { my $arg = $cmds->[++$j] ; if ($arg eq 'E') { $xpos{$id}++ ; } elsif ($arg eq 'W') { $xpos{$id}-- ; } elsif ($arg eq 'N') { $ypos{$id}++ ; } elsif ($arg eq 'S') { $ypos{$id}-- ; } } elsif ($cmd eq 'Picked') { $j++ ; $packs{$id}++ ; } elsif ($cmd eq 'Dropped') { $j++ ; $packs{$id}-- ; } elsif ($cmd eq 'Delivered') { my $arg = $cmds->[++$j] ; $packs{$id}-- ; $score{$id} += $packw{$arg} ; } elsif ($cmd eq 'Died') { my $arg = $cmds->[++$j] ; $status[$move+1][$id] = "$xpos{$id} $ypos{$id} $score{$id} $money{$id} $packs{$id}" ; $req[$move+1][$id] = $arg ; $movemax = $move + 2 ; } } $nameof{$id} = $id if !defined($nameof{$id}) ; } } } $simlines++ ; $linecount++ ; } } die "Hmm, saw lines in both adump and sim format?" if $simlines && $adumplines ; open F, ">$board.ppm" or die "Can't open $board.pgm" ; print F "P3\n$width $height\n9\n" ; @boardlines = reverse @boardlines if $simlines ; print F $_ for @boardlines ; close F ; unlink("$board.gif") ; system("ppmtogif <$board.ppm >$board.gif") ; unlink("$board.ppm") ; die "Couldn't build $board.gif" unless -f "$board.gif" ; # @ids = sort { $a <=> $b } keys %nameof ; $title = join " vs ", map { $nameof{$_} } @ids ; open F, ">$board.html" or die "Couldn't open $board.html" ; print F <$title EOF close F ;