############################################################### # p^3 Generator # Author: John Wilkinson jkw@koth.org # # vestion 2.2: 2000-12-06 # Added ; comments on the output to explain the L/W/T table # that was used to make the output # # version 2.1: 2000-11-26 # Generates p^3 code segment based on state table input file # # Now allows a "start xx" line where xx is the state number # to start off in. If xx is "0", the output is as before. # # Now ;assert's coresize is large enough to accomodate the # numbers in the table. # # Also ;assert's 0 to make sure you notice error messages. # # Checks for invalid state assignements, and for the first # two actions not being identical. ############################################################### use strict; if (scalar(@ARGV) < 1) { print "Usage 'perl p3-2.pl filename'\n"; print "\nWhere filename is a state diagram text file, similar to the following:\n"; print "start 0\n"; print "S A L W T\n"; print "0 w0 1 0 0\n"; print "1 w0 2 0 1\n"; print "2 w1 3 2 2\n"; print "3 w1 0 2 3\n"; print "\nThe S column represents the number of the state.\n"; print "\nThe A column represents the action to be jumped to,\nthis will be a label in your warrior's code.\n"; print "\nThe L/W/T columns represents the state to go to\non a loss/win/tie, respectively.\n"; exit; } open(F,"<".$ARGV[0]); my @file = (); close(F); my %states; my $starting = 0; foreach (@file) { if (/^start (\d+)/) { $starting = $1; } if (/(\d+)\s+(\S+)\s+(\d+)\s+(\d+)\s+(\d+)/) { $states{$1}{action} = $2; $states{$1}{a} = $3; $states{$1}{b} = $4; $states{$1}{c} = $5; } } my $n = scalar keys %states; if ($n < 2) { print "\n;assert 0\n;;;there must be at least 2 states\n\n"; } # 0 =< a < m my $m; if ($n % 2) { $m = $n + 1; } else { $m = $n + 2; } print "PLOC equ ".int(rand(400)+100)."\n\n"; print "think ldp.a #0, in\n"; if ($starting != 0) { print " jmz.b 3, *in\n"; } print " ldp.ba tloc, table\n"; print " mod.ba *in, table\n"; print "tloc stp.b *table, #PLOC\n"; print " mov.i #0, -1 ;; S L W T\n"; foreach my $snum (sort { $a <=> $b } keys %states) { my $a = $states{$snum}{a}; my $b = $states{$snum}{b}; my $c = $states{$snum}{c}; my $i = $b + $c - (2 * $a); my $j; if (($a < 0) || ($a >= $m)) { print "\n;assert 0\n;;;invalid a $a, in state $snum\n\n"; } # 0 =< a < m if (($b < 0) || ($b >= $m - 1)) { print "\n;assert 0\n;;;invalid b $b, in state $snum\n\n"; } # 0 =< b < m-1 if (($c < 0) || ($c >= $m + 1)) { print "\n;assert 0\n;;;invalid c $c, in state $snum\n\n"; } # 0 =< c < m+1 if ($i % 2) { $j = ($i+1+$m)/2; } else { $j = $i/2; } my $p = (($j*($m-1)+$b-$a)*$m+$a) % ($m*($m-1)*($m+1)); if ($snum == 0) { printf "table jmp }%s, %4s ;; %2s %2s %2s %2s\n",$starting,$p,$snum,$states{$snum}{a},$states{$snum}{b},$states{$snum}{c}; if ($states{0}{action} ne $states{1}{action}) { print ";assert 0\n;;; action of state 0 != action of state 1.\n;;; behavior will not be as designed.\n"; } } else { printf " dat %s, %4s ;; %2s %2s %2s %2s\n",$states{$snum}{action},$p,$snum,$states{$snum}{a},$states{$snum}{b},$states{$snum}{c}; } } print ";assert (CORESIZE > ".($m*($m-1)*($m+1)).")\n"; if ($starting != 0) { print " dat 0, 0\n"; } print "in dat ".$states{0}{action}.", ".$m. ((($m - $n) > 0)?" ; brainwashing with ".($n)."\n":"\n"); print " dat ".$states{0}{action}.", ".($m - 1). ((($m - $n) > 1)?" ; brainwashing with ".($n+1)."\n":"\n"); print " dat 0, ".($m + 1)."\n"; exit;