#!/usr/bin/perl -w #-------------------------------------------------------------- # Javvle.pl # Manage Javvle Games (Java Scrabble) # Author: Ray Wilson #-------------------------------------------------------------- #-------------------------------------------------------------- # Using GET method to deliver data to this program. #-------------------------------------------------------------- # # Get the values from the QUERY_STRING and put them into an # associative array named %user_data; # #-------------------------------------------------------------- $user_string = $ENV{"QUERY_STRING"}; #-------------------------------------------------------------- # Change pluses to spaces #-------------------------------------------------------------- $user_string =~ s/\+/ /g; #-------------------------------------------------------------- # Split string on ampersands to otain list of name value pairs. #-------------------------------------------------------------- @name_value_pairs = split(/&/,$user_string); foreach $name_value_pair (@name_value_pairs) { #-------------------------------------------------------------- # Split name value pairs on equal sign to otain $name, &value. #-------------------------------------------------------------- ($name,$value) = split(/=/, $name_value_pair); #-------------------------------------------------------------- # Search for %HH terms and replace them with the character # each represents. ($1) is the value found in each instance. #-------------------------------------------------------------- $name =~ s/%([a-fA-F0-9][a-fA-F0-9])/pack("C",hex($1))/ge; $value =~ s/%([a-fA-F0-9][a-fA-F0-9])/pack("C",hex($1))/ge; #-------------------------------------------------------------- # If a name already exists in the hash then append : and the # new value to it. Otherwise add it to the list. #-------------------------------------------------------------- if(defined($user_data{$name})) { $user_data{$name} .= " : " . $value; } else { $user_data{$name} = $value; } } #-------------------------------------------------------------- # # QUERY_STRING is now in associative array %user_data. # #-------------------------------------------------------------- #-------------------------------------------------------------- # Send HTML header. #-------------------------------------------------------------- print "Content-type: text/html\n\n"; #-------------------------------------------------------------- # # read $user_data{"COMMAND"}; and take appropriate action. # #-------------------------------------------------------------- $command = $user_data{"COMMAND"}; %letter_freq = ( A => 9, B => 2, C => 2, D => 4, E => 12, F => 2, G => 3, H => 2, I => 9, J => 1, K => 1, L => 4, M => 2, N => 6, O => 8, P => 2, Q => 1, R => 6, S => 4, T => 6, U => 4, V => 2, W => 2, X => 1, Y => 2, Z => 1, " " => 2); %letter_vals = ( A => 1, B => 3, C => 3, D => 2, E => 1, F => 4, G => 2, H => 4, I => 1, J => 8, K => 5, L => 1, M => 3, N => 1, O => 1, P => 3, Q => 10, R => 1, S => 1, T => 1, U => 1, V => 4, W => 4, X => 8, Y => 4, Z => 10, " " => 0); #-------------------------------------------------------------- # SENDSCORE # # A player has completed their turn and is sending the state of # the game including their new word and score to the server. # # PLAYERNUMBER e.g. (1 - 4) # BOARDSTRING e.g. (000000MAP000000... 225 chars 0) # WORDPOSITIONS e.g. (6,7,8) indexes of positions used to make word. # SCORE e.g. (25) # TRAYTILES e.g. (STYD) symbols of letters left in tray. # NPLAYERS (number of players in this game.) # GAMENAME # #-------------------------------------------------------------- if ($command eq "SENDSCORE") { $playernumber = $user_data{"PLAYERNUMBER"}; --$playernumber; $boardstring = $user_data{"BOARDSTRING"}; $wordpositions = $user_data{"WORDPOSITIONS"}; $score = $user_data{"SCORE"}; $traytiles = $user_data{"TRAYTILES"}; $nplayers = $user_data{"NPLAYERS"}; $gamename = $user_data{"GAMENAME"}; #------------------------------ # Write gamename.javvle file #------------------------------ $ftest = 1; open(OUT, ">$gamename".".javvle") or $ftest = 0; if($ftest) { print OUT $boardstring."|".$wordpositions; close(OUT); } else { print "ERROR\nSENDSCORE can't open $gamename".".javvle\n"; exit; } #------------------------------ # Append score to score file. #------------------------------ $ftest = 1; open(OUT, ">>$gamename".".scores") or $ftest = 0; if($ftest) { print OUT "X".$score; close(OUT); } else { print "ERROR\nSENDSCORE can't open $gamename".".scores\n"; exit; } #------------------------------------------------------ # Calculate number of tiles to return and obtain them. #------------------------------------------------------ $picks = 7 - length($traytiles); $newletters = getletters($gamename,$picks); $currentletters = "".$traytiles.$newletters; for($c = 0; $c < length($currentletters); ++$c) { $k = substr($currentletters,$c,1); $trayscore += $letter_vals{$k}; } #------------------------------------------------------ # Check for GAME-OVER condition. #------------------------------------------------------ if((length($newletters) == 0) && (length($traytiles) == 0)) { #----------------- # GAME OVER #----------------- # Get the tray scores of the other players. @tscores = (); $ftest = 1; open(IN, "<$gamename".".players") or $ftest = 0; if($ftest) { @players = ; close(IN); $trayscores = 0; for($i=0; $i<$nplayers; ++$i) { $line = $players[$i]; @parts = split(/\|/,$line); $tscores[$i] = $parts[3]; if($i != $playernumber) { $trayscores += $parts[3]; } } } else { print "ERROR\nSENDSCORE can't open $gamename".".players\n"; exit; } # Calculate everyone's score. $ftest = 1; open(IN, "<$gamename".".scores") or $ftest = 0; if($ftest) { $scores = ; close(IN); @pscores = (0,0,0,0); @allscores = split(/X/,$scores); for($i=0; $i<@allscores; ++$i) { $pscores[$i % $nplayers] += $allscores[$i]; } # Add other player's tray scores to this player's score. $pscores[$playernumber] += $trayscores; $winner = 0; $hiscore = 0; for($i=0; $i<$nplayers; ++$i) { #---------------------------------------------------------------------- # Reduce non-'out of letters' player's score by their tray score. #---------------------------------------------------------------------- if($i != $playernumber) { $pscores[$i] -= $tscores[$i]; } #---------------------------------------------------------------------- # Track winning score. #---------------------------------------------------------------------- if($pscores[$i] > $hiscore) { $hiscore = $pscores[$i]; $winner = $i+1; } } } else { print "ERROR\nSENDSCORE can't open $gamename".".scores\n"; exit; } $ftest = 1; open(OUT, ">$gamename".".finals") or $ftest = 0; if($ftest) { #----------------------------------------- # Check for ties. #----------------------------------------- @ties = (); $j = 0; for($i=0; $i<$nplayers; ++$i) { if($i != $winner-1) { if($pscores[$i] == $hiscore) { $ties[$j] = $i+1; ++$j; } } } if(@ties > 0) { print OUT "GAME-TIED\n"; print OUT "Game tied between: "; for($i=0; $i<@ties; ++$i) { print OUT "P".($ties[$i]); if($i < @ties-1) { print OUT " and "; } } print OUT "\n"; } for($i=0; $i<$nplayers; ++$i) { print OUT "P".($i+1)."-".$pscores[$i]." "; } print OUT "\n"; close(OUT); } else { print "ERROR\nSENDSCORE can't save final scores.\n"; exit; } $ftest = 1; open(OUT, ">$gamename".".turn") or $ftest = 0; if($ftest) { print OUT ($winner + 100); close(OUT); print "GAMEOVER\n"; exit; } else { print "ERROR\nSENDSCORE can't open $gamename".".turn\n"; exit; } } else { #-------------------------------------- # Update the players file. #-------------------------------------- $ftest = 1; open(IN, "<$gamename".".players") or $ftest = 0; if($ftest) { @players = ; close(IN); for($i=0; $i<$nplayers; ++$i) { if($i == $playernumber) { $line = $players[$i]; @parts = split(/\|/,$line); $nline = $parts[0]."|".$parts[1]."|".$parts[2]."|".$trayscore."\n"; } } } else { print "ERROR\nSENDSCORE can't update $gamename".".players\n"; exit; } $ftest = 1; open(OUT, ">$gamename".".players") or $ftest = 0; if($ftest) { for($i=0; $i<$nplayers; ++$i) { if($i != $playernumber) { print OUT $players[$i]; } else { print OUT $nline; } } } else { print "ERROR\nSENDSCORE can't write $gamename".".players\n"; exit; } $ftest = 1; open(OUT, ">$gamename".".turn") or $ftest = 0; if($ftest) { ++$playernumber; if($playernumber >= $nplayers) { $playernumber = 1; } else { ++$playernumber; } print OUT $playernumber; close(OUT); } else { print "ERROR\nSENDSCORE can't update $gamename".".turn\n"; exit; } } print $newletters."\n"; exit; } #-------------------------------------------------------------- # GETFINALS # # Get final scores. # # GAMENAME # #-------------------------------------------------------------- elsif ($command eq "GETFINALS") { $gamename = $user_data{"GAMENAME"}; if(-e $gamename.".finals") { $ftest = 1; open(IN, "<$gamename".".finals") or $ftest = 0; if($ftest) { $finals = ; close(IN); print $finals; } else { print "ERROR\nError reading finals file.\n"; } } exit; } #-------------------------------------------------------------- # GETGAMELIST # # A potential player wants to see the list of available games. #-------------------------------------------------------------- elsif ($command eq "GETGAMELIST") { opendir(FILELIST,'.'); @AllFiles = readdir(FILELIST); closedir(FILELIST); foreach $Name (@AllFiles) { if( -d $Name) # ignore directories. { next; } if(! ($Name =~ m/\.players/)) # ignore all but .players files. { next; } else { open(IN,$Name); @players = ; close(IN); @parts = split(/\|/,$players[0]); if($parts[0] > @players) { $nd = $parts[0] - @players; ($Name =~ s/\.players//); print $Name."|".$parts[0]."|".$nd."\n"; } } } exit; } #-------------------------------------------------------------- # STARTGAME # # A potential player is starting a new game. # # GAMENAME # USERNAME # NPLAYERS # #-------------------------------------------------------------- elsif ($command eq "STARTGAME") { $gamename = $user_data{"GAMENAME"}; $username = $user_data{"USERNAME"}; $nplayers = $user_data{"NPLAYERS"}; if(-e $gamename.".players") { print "STATUS\nGAMEEXISTS\n"; exit; } else { # Initialize letterturn file. $ftest = 1; open(OUT, ">$gamename".".letterturn") or $ftest = 0; if($ftest) { print OUT "5"; } else { print "ERROR\nSTARTGAME letterturn init.\n"; exit; } # Initialize letterbag file. makenewbag($gamename); # Initialize players file. $ftest = 1; open(OUT, ">$gamename".".players") or $ftest = 0; if($ftest) { print OUT $nplayers."|1|".$username."|0\n"; } else { print "ERROR\nSTARTGAME players init.\n"; exit; } # Initialize turn file. $ftest = 1; open(OUT, ">$gamename".".turn") or $ftest = 0; if($ftest) { print OUT "1\n"; } else { print "ERROR\nSTARTGAME turn file init.\n"; exit; } # Initialize scores file. $ftest = 1; open(OUT, ">$gamename".".scores") or $ftest = 0; if($ftest) { print OUT "0".("X0" x ($nplayers-1)); } else { print "ERROR\nSTARTGAME scores init.\n"; exit; } # Tell user to start polling for LETTERTURN. print "POLLLETTERTURN\n"; exit; } } #-------------------------------------------------------------- # JOINGAME # # A potential player is requesting to join a game. # # GAMENAME # USERNAME # NPLAYERS # #-------------------------------------------------------------- elsif ($command eq "JOINGAME") { $gamename = $user_data{"GAMENAME"}; $username = $user_data{"USERNAME"}; $nplayers = $user_data{"NPLAYERS"}; if(-e $gamename.".players") { $ftest = 1; open(IN, "<$gamename".".players") or $ftest = 0; if($ftest) { @players = ; close(IN); if(@players >= $nplayers) { print "STATUS\nJOINGAME GAMEFULL\n"; exit; } } else { print "ERROR\nJOINGAME can't read players file.\n"; exit; } $ftest = 1; open(OUT, ">>$gamename".".players") or $ftest = 0; if($ftest) { print OUT $nplayers."|".(@players+1)."|".$username."|0\n"; close(OUT); } else { print "ERROR\nJOINGAME can't append players file.\n"; exit; } if(@players+1 == $nplayers) { # Initialize letterturn file. $ftest = 1; open(OUT, ">$gamename".".letterturn") or $ftest = 0; if($ftest) { print OUT "1"; } else { print "ERROR\nJOINGAME can't write letterturn file.\n"; exit; } } print "POLLLETTERTURN\n".(@players+1)."\n"; exit; } else { print "STATUS\nJOINGAME NOGAME\n"; exit; } } #-------------------------------------------------------------- # POLLLETTERTURN # # Used at start of game to indicate which player has access to # obtain their initial letter list. # # GAMENAME # #-------------------------------------------------------------- elsif ($command eq "POLLLETTERTURN") { $gamename = $user_data{"GAMENAME"}; if(-e $gamename.".letterturn") { $ftest = 1; open(IN, "<$gamename".".letterturn") or $ftest = 0; if($ftest) { $player = ; close(IN); print $player."\n"; } else { print "ERROR\nPOLLLETTERTURN can't read letterturn file.\n"; } exit; } else { print "STATUS\nNOGAME\n"; exit; } } #-------------------------------------------------------------- # POLLTURN # # Used throughout the game to indicate which player's turn it # currently is and to retrieve the current state of the game. # # GAMENAME # CURRENTPLAYERNUMBER # #-------------------------------------------------------------- elsif ($command eq "POLLTURN") { $gamename = $user_data{"GAMENAME"}; $currentplayernumber = $user_data{"CURRENTPLAYERNUMBER"}; if(-e $gamename.".javvle") { $turn = 0; $ftest = 1; open(IN, "<$gamename".".turn") or $ftest = 0; if($ftest) { $turn = ; close(IN); } else { print "ERROR\nPOLLTURN can't read turn file.\n"; exit; } if($currentplayernumber != $turn) { $gamestate = ""; $scores = ""; $ftest = 1; open(IN, "<$gamename".".javvle") or $ftest = 0; if($ftest) { $gamestate = ; close(IN); } else { print "ERROR\nPOLLTURN can't read javvle file.\n"; exit; } $ftest = 1; open(IN, "<$gamename".".scores") or $ftest = 0; if($ftest) { $scores = ; close(IN); } else { print "ERROR\nPOLLTURN can't read scores file.\n"; exit; } print "GAMESTATE\n".$gamestate."\n".$scores."\n".$turn."\n"; } else { print $turn."\n"; } exit; } else { print "STATUS\nNOGAME\n"; exit; } } #-------------------------------------------------------------- # SETTURN # # GAMENAME # CURRENTPLAYERNUMBER # # Set the curretlplayer in the .turn file to currentplayernumber. #-------------------------------------------------------------- elsif ($command eq "SETTURN") { $gamename = $user_data{"GAMENAME"}; $currentplayernumber = $user_data{"CURRENTPLAYERNUMBER"}; $ftest = 1; open(OUT, ">$gamename".".turn") or $ftest = 0; if($ftest) { print OUT $currentplayernumber; close(OUT); } else { print "ERROR\nSENDSCORE can't open $gamename".".turn\n"; } exit; } #-------------------------------------------------------------- # WRITECHAT # # GAMENAME # MESSAGE # # Write new message and truncate the file to 10 lines if longer # than that. # #-------------------------------------------------------------- elsif ($command eq "WRITECHAT") { $gamename = $user_data{"GAMENAME"}; $message = $user_data{"MESSAGE"}; #---------------------------------- # Write new chat information. #---------------------------------- $ftest = 1; open(OUT, ">>$gamename".".chat") or $ftest = 0; if($ftest) { print OUT $message; close(OUT); } else { print "ERROR\nWRITECHAT can't write chat file.\n"; exit; } #---------------------------------- # Truncate file to 10 lines. #---------------------------------- $ftest = 1; open(IN, "<$gamename".".chat") or $ftest = 0; if($ftest) { @last10 = ; close(IN) } else { print "ERROR\nWRITECHAT can't read chat file for truncate.\n"; exit; } if(@last10 > 10) { $ftest = 1; open(OUT, ">$gamename".".chat") or $ftest = 0; if($ftest) { $nn = @last10 - 10; for($x = $nn; $x < @last10; ++$x) { print OUT $last10[$x]; } } else { print "ERROR\nWRITECHAT can't write truncated chat file.\n"; exit; } } exit; } #-------------------------------------------------------------- # READCHAT # TIMELASTWRITTEN # GAMENAME #-------------------------------------------------------------- elsif ($command eq "READCHAT") { $gamename = $user_data{"GAMENAME"}; $timelastwritten = $user_data{"TIMELASTWRITTEN"}; #------------------------------------ # If file does not exist just leave. #------------------------------------ if( ! (-e $gamename.".chat")) { print "STATUS\nREADCHAT no chat file exists.\n"; exit; } #------------------------------------ # Get file statistics. #------------------------------------ ($dev,$ino,$mode,$nlink,$uid,$gid,$rdev,$size,$atime,$mtime,$ctime,$blksize,$blocks) = stat $gamename.".chat"; #------------------------------------ # If file did not change just leave. #------------------------------------ if($timelastwritten == $mtime) { print "STATUS\nREADCHAT chat file has not changed.\n"; exit; } $ftest = 1; open(IN, "<$gamename".".chat") or $ftest = 0; if($ftest) { @chatlines = ; close(IN); print "LASTREAD\n".$mtime."\n"; for($x = 0; $x < @chatlines; ++$x) { print $chatlines[$x]; } } else { print "ERROR\nREADCHAT can't read chat file.\n"; exit; } exit; } #-------------------------------------------------------------- # INITLETTERS # # Return initial 7 letters to each player at the start of the # game. # # GAMENAME # PLAYERNUMBER # #-------------------------------------------------------------- elsif ($command eq "INITLETTERS") { $playernumber = $user_data{"PLAYERNUMBER"}; $gamename = $user_data{"GAMENAME"}; if(-e $gamename.".lbag") { $newletters = getletters($gamename,7); $ftest = 1; open(OUT, ">$gamename".".letterturn") or $ftest = 0; if($ftest) { #------------------------------------------------------- # Hard coded 4 because once a player gets their letters # they don't return here. #------------------------------------------------------- if($playernumber < 4) { print OUT ($playernumber + 1)."\n"; } close(OUT); } else { print "ERROR\nINITLETTERS can't write letterturn file.\n"; exit; } } else { print "STATUS\nNOGAME\n"; exit; } print $newletters."\n"; exit; } #-------------------------------------------------------------- # CHALLENGE # # A player has challenged another player. # # GAMENAME # ACTION # LASTLETTERS (challenged player's most recently received letters) # CURRENTPLAYERNUMBER # PLAYERNUMBER # NPLAYERS # #-------------------------------------------------------------- elsif ($command eq "CHALLENGE") { $gamename = $user_data{"GAMENAME"}; $action = $user_data{"ACTION"}; $lastletters = $user_data{"LASTLETTERS"}; $currentplayernumber = $user_data{"CURRENTPLAYERNUMBER"}; $playernumber = $user_data{"PLAYERNUMBER"}; $nplayers = $user_data{"NPLAYERS"}; if($currentplayernumber == 1) { $lastplayer = $nplayers; } else { $lastplayer = $currentplayernumber - 1; } if($action eq "START") { #---------------------------------------------------------------------- # challenger challenged #---------------------------------------------------------------------- $turnvalue = 200 + ($playernumber * 10) + $lastplayer; } elsif($action eq "CONTINUE") { $turnvalue = 300 + ($playernumber * 10) + $lastplayer; } elsif($action eq "UNDO") { $turnvalue = 400 + ($playernumber * 10) + $lastplayer; #---------------------------------------------------------------------- # Get last move's letters back. #---------------------------------------------------------------------- $retlets = undolastplay($gamename); #---------------------------------------------------------------------- # Put most recently received letters back in the lbag an randomize it. #---------------------------------------------------------------------- putletters($gamename,$lastletters); } $ftest = 1; open(OUT, ">$gamename".".turn") or $ftest = 0; if($ftest) { print OUT $turnvalue; close(OUT); if($action eq "UNDO") { print $retlets."\n"; } } else { print "ERROR\nCHALLENGE can't open $gamename".".turn\n"; } exit; } #-------------------------------------------------------------- # EXCHANGELETTERS # # Return initial 7 letters to each player at the start of the # game. # # GAMENAME # RETURNLETTERS # #-------------------------------------------------------------- elsif ($command eq "EXCHANGELETTERS") { $returnletters = $user_data{"RETURNLETTERS"}; $gamename = $user_data{"GAMENAME"}; #------------------------------------------------------------ # Get new letters. #------------------------------------------------------------ $newletters = getletters($gamename,length($returnletters)); #------------------------------------------------------------ # Put old letters back into bag. #------------------------------------------------------------ putletters($gamename,$returnletters); print $newletters."\n"; exit; } #--------------------------------------------------------------------- # This exit catches calls to this program with COMMAND not equal # to any expected value. #--------------------------------------------------------------------- else { exit; } ######################################################################## # # # SUBROUTINES # # ######################################################################## sub undolastplay { $fname = shift(@_); #--------------------------------------------------------------- # Open the javvle file and split it on the pipe '|' # Post-pipe = comma delimited latest used positions. # Pre-pipe = javvle board letters at positions 0 - 224 # Build the letters at the latest used positions into a string. # Fill the latest used positions with 0's # Write the new javvle file back to disk. # Set the last score in the scores file to 0. # Return the latest used letters as a string. #--------------------------------------------------------------- $ftest = 1; open (IN , "<$fname".".javvle") or $ftest = 0; if($ftest) { $contents = ; close(IN); chomp($contents); @parts = split /\|/, $contents; @removes = split /,/,$parts[1]; @letters = unpack "c225", $parts[0]; foreach $m (@letters) { $letterlist .= (pack "c",$m).","; } @letters = split(/,/,$letterlist); foreach $m (@removes) { $takeback .= $letters[$m]; $letters[$m] = '0'; } } else { print "ERROR\nDuring takeback subroutine javvle read.\n"; exit; } $ftest = 1; open (OUT , ">$fname".".javvle") or $ftest = 0; if($ftest) { print OUT @letters; print OUT "|".$parts[1]; } else { print "ERROR\nDuring takeback subroutine javvle write.\n"; exit; } $ftest = 1; open (IN , "<$fname".".scores") or $ftest = 0; if($ftest) { $contents = ; close(IN); chomp($contents); @scores = split /X/, $contents; $scores[$#scores] = '0'; } else { print "ERROR\nDuring takeback subroutine scores read.\n"; exit; } $ftest = 1; open (OUT , ">$fname".".scores") or $ftest = 0; if($ftest) { $i = 0; foreach $m (@scores) { if($i < $#scores) { print OUT $m."X"; } else { print OUT $m; } ++$i; } } else { print "ERROR\nDuring takeback subroutine scores write.\n"; exit; } return $takeback; } sub getletters { $fname = shift(@_); $nletters = shift(@_); #--------------------------------------------------------------- # Open the letterbag (.lbag) file and return $nletters letters. #--------------------------------------------------------------- $ftest = 1; open (IN , "<$fname".".lbag") or $ftest = 0; if($ftest) { $contents = ; close(IN); chomp($contents); @letters = split(/,/, $contents); @picked = splice(@letters,0,$nletters); $retval = ""; foreach $c (@picked) { $retval .= $c; } } else { print "ERROR\nGETLETTERS can't read lbag file.\n"; exit; } #--------------------------------------------------------------- # Write the letterbag (.lbag) file back to disk. #--------------------------------------------------------------- $contents = ""; $ftest = 1; open (OUT, ">$fname".".lbag") or $ftest = 0; if($ftest) { for($x=0;$x<@letters;++$x) { $contents .= $letters[$x]; if($x < @letters-1) { $contents .= ","; } } print OUT $contents; close (OUT); } else { print "ERROR\nGETLETTERS can't write lbag file.\n"; exit; } return($retval); } sub putletters { $fname = shift(@_); $putletters = shift(@_); #--------------------------------------------------------------- # Open the letterbag (.lbag) file and add putletters to it. # then randomize the list and write it back to the .lbag file. #--------------------------------------------------------------- $ftest = 1; open (IN , "<$fname".".lbag") or $ftest = 0; if($ftest) { #------------------------------------------ # Get the contents of the letter bag file. #------------------------------------------ $contents = ; close(IN); chomp($contents); @letters = split(/,/, $contents); @newletters = (); for($i=0;$i 0) { $n = int(rand($m)); $k = $m-1; $tmp = $letters[$k]; $letters[$k] = $letters[$n]; $letters[$n] = $tmp; --$m; } } else { print "ERROR\nPUTLETTERS can't read lbag file.\n"; exit; } #--------------------------------------------------------------- # Write the letterbag (.lbag) file back to disk. #--------------------------------------------------------------- $contents = ""; $ftest = 1; open (OUT, ">$fname".".lbag") or $ftest = 0; if($ftest) { for($x=0;$x<@letters;++$x) { $contents .= $letters[$x]; if($x < @letters-1) { $contents .= ","; } } print OUT $contents; close (OUT); } else { print "ERROR\nPUTLETTERS can't write lbag file.\n"; exit; } return; } #------------------------------------------------------- # Make a new letter bag file. #------------------------------------------------------- sub makenewbag { $fname = shift(@_); #---------------------------------------------------- # Create ordered list of letters based on frequency. #---------------------------------------------------- @letters = (); @TheKeys = keys(%letter_freq); foreach $k (@TheKeys) { for($i=0; $i<$letter_freq{$k}; ++$i) { push(@letters,$k); } } #---------------------------------------------------- # Randomize the list twice. #---------------------------------------------------- srand(); $m = @letters; while($m > 0) { $n = int(rand($m)); $k = $m-1; $tmp = $letters[$k]; $letters[$k] = $letters[$n]; $letters[$n] = $tmp; --$m; } $m = @letters; while($m > 0) { $n = int(rand($m)); $k = $m-1; $tmp = $letters[$k]; $letters[$k] = $letters[$n]; $letters[$n] = $tmp; --$m; } #---------------------------------------------------- # Write the file out to disk; #---------------------------------------------------- $contents = ""; $ftest=1; open (OUT, ">$fname".".lbag") or $ftest=0; if($ftest) { for($x=0;$x<@letters;++$x) { $contents .= $letters[$x]; if($x < @letters-1) { $contents .= ","; } } print OUT $contents; close (OUT); } else { print "ERROR\nMAKENEWBAG can't write lbag file.\n"; exit; } return; }