#!/usr/local/bin/perl
#
# game of tic-tac-toe for mosiac 2.0//http 1.0.5
#
# Jason Heirtzler
# 2/10/94
#
$host = "http://scv.bu.edu";
$href = "$host:5111";
#
#
$men = 9;
#$men = 16;
#
$giveup = "$host/Games/puzzle";
$gohome = "
[Return to game page]
[Return to Home page]";
$newgame = "
New game?\n$gohome";
if ( $men == 9 ) {
$blank = 4;
$endgame = "0,1,2,3,4,5,6,7,8,9";
@valid = ( "1,3", "0,2,4", "1,5",
"0,4,6", "1,3,5,7", "2,4,8",
"3,7", "4,6,8", "5,7" );
}
if ( $men == 16 ) {
$blank = 0;
$endgame = "0,1,2,3,4,5,6,7,8,9,10,11,12,13,14,15";
@valid = ("1,4", "0,5,2", "1,6,3", "2,7",
"0,5,8", "1,4,6,9", "2,5,7,10", "3,6,11",
"4,9,12", "5,8,10,13", "6,9,11,14", "7,10,15",
"8,13", "9,12,14", "10,13,15", "11,14" );
}
require 'getopts.pl';
#
&Getopts( 'd' );
#
$done = 0;
$_ = <>;
chop($_);
#
srand(time);
#
# initial board position is random
# called as follows:
#
# http://lobster.bu.edu:5111/-
#
# for ex: GET /ooooooooo HTTP/1.0
$_ =~ s!GET /(\S+) .*!$1! unless ($opt_d);
#
$turn = -1;
/^(\d+)-.*/ && ( $turn = $1); $turn++;
/^.*-(.*)/ && ( $move = $1);
#
print "Content-type: text/html\n\n";
#
# Print banner!
#
if (!$opt_d) {
print "\n
$men PUZZLE\n";
print "$men Puzzle
\n";
print "\n";
}
#
# takes a string of the form "1,2,3" and makes it
# a little harder to understand
#
sub recode {
local( $arg ) = @_;
local( @f, $x, @y );
@f = split( ',', $arg );
foreach (@f) {
$x = $_ + 0;
if ( $x >= 32) { $x = $x & 15; }
else { $x = $x + int(rand(7))*32 + 32; }
$x = $x ^6;
push( @y, $x );
}
return(join( ',', @y ));
}
#
# isvalidmove( "0,1,2,3,4,5,6,7,8,9,10,11,12,13,14,15",
# "4,1,2,3,0,5,6,7,8,9,10,11,12,13,14,15" );
#
sub isvalidmove
{
local( $start, $end ) = @_;
local( @s, @e, $i, $j );
@s = split(/,/, $start);
@e = split(/,/, $end);
#
for ( $i=0; $i<$men; $i++) {
if (@s[$i] eq $blank) {
@v = split(/,/, @valid[$i]);
for ( $j=$#v; $j>=0; $j-- ) {
#print "cmp ", @e[@v[$j]], " 0\n";
if (@e[@v[$j]] eq $blank ) {
# print "valid\n";
return(1);
}
}
#print "not valid\n";
return(0);
}
}
die "no blank in start string?";
}
#
# randomize the board. must work backwards from
# the solved board as random combinations of the
# pieces may not be solvable.
#
sub scramble
{
local( @e, $b, $i, $t, $o );
#
@e = split( /,/, $endgame );
#
# find blank space (always first one, really)
#
for ( $i=length($endgame); $i>=0; $i-- ) {
$b = $i if ( @e[$i] eq $blank );
}
#
#
for ( $i=0; $i<500; $i++ ) {
#
# get list of valid moves
@v = split(/,/, @valid[$b]);
#print " from $b valid moves: ", join( ',', @v ), "($#v)\n";
#print " picking from [0..", $#v, "]\n";
#
$z = int(rand($#v)+0.5);
#print " taking number $z, ie ", @v[$z], "\n";
# randomly pick one of them
$r = @v[$z];
#
print "switch $b and $r elts\n" if ($opt_d);
# now switch $b and $r elements
$t = @e[$r];
@e[$r] = @e[$b];
@e[$b] = $t;
# blank space has now moved
$b = $r;
}
return(join(',',@e));
}
#
sub showboard
{
local( $what ) = @_;
local( @w, $i, $j, $x, $y );
#
# find the blank square
#
@w = split( /,/, $what );
for ( $i= $#w; $i>=0; $i-- ) {
$b = $i if ( @w[$i] eq $blank );
}
print "blank is $b\n" if ($opt_d);
#
$y = 4 if ($men == 16);
$y = 3 if ($men == 9);
#
for ( $i = 0; $i<$y; $i++ ) {
for ( $j = 0; $j<$y; $j++ ) {
$x = $i*$y+$j;
print " n$x " if ($opt_d);
#
# try switching the blank with this
# square.
@s = @w;
$t = @s[$x];
@s[$x] = @s[$b];
@s[$b] = $t;
#
$t = join( ',', @s );
if (&isvalidmove( $t, $what)) {
if ($opt_d) {
print "+";
}
else {
$w = &recode( $t );
print ""
unless ($done);
}
}
else {
print "-" if ($opt_d);
}
print "
\n"
unless ($opt_d);
}
if ($opt_d) { print "\n"; }
else { print "
\n"; }
}
}
#
#print &isvalidmove( "0,1,2,3,4,5,6,7,8,9,10,11,12,13,14,15",
# "2,1,0,3,4,5,6,7,8,9,10,11,12,13,14,15" );
#
if ($move eq "random") {
$turn = 0;
$move = &scramble;
}
else {
$move = &recode($move) unless ($opt_d);
}
#
if ($move eq "$endgame") {
$done++;
&showboard($move);
print "You did it!!
";
print "Solved in $turn moves.
";
print "$newgame";
#
# $MAIL = "/usr/ucb/Mail";
# $MAIL = "/usr/sbin/Mail" if ( -f "/usr/sbin/Mail" );
#
# open( M, "| $MAIL -s puzzle_solved jdh" );
# print M "9-puzzle solved in $turn moves\n";
# close( M );
exit(0);
}
#
#$move = $endgame;
#print "$move
\n";
&showboard($move);
if ($turn == 0) {
print "Ready!
\n";
print "Click on a piece to move it to the black square.\n";
}
else {
print "Moves: $turn
\n";
print "Click on a piece to move it to the black square.\n";
print "Give up? Click here\n"
unless ($turn == 1);
}
exit(0);