#!/usr/local/bin/perl # Connect, Play -- networking primitives -- Can be improved $whoami = `whoami`; $whoami =~ m/^(\w+)/; $whoami = $1; use Socket; use IO::Handle; sub Connect($$){ my($name,$passwd) = @_; my $PortNumber = $ENV{'SWP_SERVERPORT'} || 5200; my $HostName = $ENV{'SWP_SERVERNAME'} || 'localhost'; print "Trying to connect to $HostName $PortNumber as $name:$passwd\n"; my $iaddr = inet_aton($HostName) || die "Cannot find host named $HostName"; my $paddr = sockaddr_in($PortNumber,$iaddr); my $proto = getprotobyname('tcp'); socket(SOCK, PF_INET, SOCK_STREAM, $proto) || die "socket: $!"; connect(SOCK, $paddr) || die "connect: $!"; SOCK->autoflush(1); my $ServerLine ; $ServerLine = ; die "read error: $!" unless $ServerLine; print "server:$ServerLine\n"; print "client:$name:$passwd\n"; print SOCK "$name:$passwd\n"; $ServerLine = ; die "read error: $!" unless $ServerLine; print "server:$ServerLine\n"; die "Protocol error or bad name:password" unless $ServerLine =~ /^OK/; }; Connect($whoami,$ENV{'SWP_PASSWORD'}) or die "Check passwords: no connection with SWP_PASSWORD $ENV{'SWP_PASSWORD'}\n"; sub Play(@){ my @result = (); my $resline; foreach my $arg (@_){ # print "playing <$arg>\n"; foreach my $ins (split /\W+/, $arg){ while(!print SOCK "$ins\n"){ print "$! writing to server, (re)opening connection:\n"; Connect(`whoami`,$ENV{'SWP_PASSWORD'}) or die "Check passwords: no connection with SWP_PASSWORD $ENV{'SWP_PASSWORD'}\n"; }; #print "client: $ins\n"; # Every command results in a newline-terminated response line $resline = ; # print "server: $resline"; push @result,$resline; }; }; #close(SOCK); return @result; }; #possible ways to move cards @Moves = qw{ 32 31 30 21 20 10 }; #possible ways to pick up four piles of cards @Pickups = qw{ 0123 1230 2301 3012 0231 2310 3102 1023 0312 3120 1203 2031 0132 1320 3201 2013 0321 3210 2103 1032 0213 2130 1302 3021 }; sub Decks(){ my ($status) = Play('status'); $status =~ /(\d+) of (\d+) decks/ or die "status did not match /(\d+) of (\d+) decks/\n"; return ($2 - $1); }; sub Win(){ Play('win')} sub Lay(){ Play('lay')} sub Discard(){ Play('discard')} sub RandomPickup(){ Play($Pickups[rand @Pickups])} sub Round(){ my $Count = $Sets; my $Result; while($Count--){ print Lay; ($Result) = Discard; # Play returns an array. if ($Result =~ m/^OK/){ $Sets--; $RoundsWithNoDiscards=0; print "Only $Sets sets left in this deck!\n"; }else{ #Make all possible moves while ((rand( $RoundsWithNoDiscards) < 10) && (@Successes = grep /^OK/, (map {Play($_)} @Moves)) ){ print @Successes; }; }; }; $RoundsWithNoDiscards++; # endless loops should be defeated by randomizing pickup order ($Result) = RandomPickup; $Result =~ m/^OK/ and return 1; # if we get out of sync: die "RandomPickup returned not OK\n"; }; $Sets = 13; $DecksRemaining=Decks; while ($DecksRemaining >= 0 ){ if ($Sets > 0){ Round; }else{ Win; $DecksRemaining--; print "$DecksRemaining decks remaining at ", `date`; $Sets = 13; }; }; print "No more decks. Finished at ",`date`;