For the sake of better helping people who are programming in GAME Code understand the language, this page displays an up-to-date, script-generated copy of the PHP code that handles its processing of commands, complete with line numbering and syntax highlighting. The commands can be found as cases in a long switch statement. You can find a particular command by searching for its name within double quotation marks, or you can browse through it to see what commands are available. Although I tried to keep commands in alphabetical order, it sometimes made sense to group related commands together. So, they are roughly, but not strictly, in alphabetical order. Note that this code is displayed here only for educational purposes, and it should not be copied or downloaded.

Copyright © Fergus Duniho, 2016.

   1.  <?
   2. 
   3. 
// Here is the main function for interpreting the main program and every subroutine
   4. // of a GAME Code program.
   5. 
   6. 
function runsubroutine ($subname$subargs$oldlinenum=-1) {
   7.     global     
$ai$REALNAME$allowed$appendautorules$background$banned$capturedpieces$cardback$cards$cardsdir$cases$coded$codelines$color$comments$constants$customsets$debug$deck$dest$discardpile$drawncards$exit$file$first$firstplayer$flag$flipped$functions$gameover$hand$hand1$hand2$height$jsvar$label$lastcaptured$lastmoved$legalmoves$links$map$maxmove$message$mline$mln$move$movelist$movenum$moves$named$noerrorcheck$oldmovelist$opponent$origin$password$pastmoves$pastmovesfield$piecekeys$pieces$piecevals$playedcards1$playedcards2$player$players$posdata$prevcaptured$prevdest$prevmoved$prevorigin$prevpos$prison$rank$ALIAS$reminder$reserved$returnaliases$scope$side$sidecnt$space$starpath$startbackground$startposition$sub$submit$switchsides$turn$turnorder$userid$uservar$width$winner;
   8.     
   9.     if (!empty(
$exit)) {
  10.         return;
  11.     }
  12.     
  13.     static 
$includes = array();
  14.     static 
$returns = array();
  15.     static 
$ifhead = array();
  16.     static 
$condition = array();
  17.     static 
$store = array();
  18.     static 
$banlist = array();
  19.     static 
$ban false;
  20.     static 
$echos 0;
  21.     
  22.     if (empty(
$posdata) && !is_array($posdata)) {
  23.         
$posdata = array();
  24.         
$moveindex 0;
  25.     }
  26. 
  27.     
$maxlines count($codelines);
  28. 
  29.     if (
$subname == "main") {
  30.         
$subscope $scope 0;
  31.         
$sub = array();
  32.         
$sub[$scope] = "main";
  33.         
$ifhead[$scope] = "main";
  34.         
$linenum = -1;
  35.     }
  36.     else {
  37.         
$scope++;
  38.         
$subscope $scope;
  39.         
$sub[$scope] = $subname;
  40.         
$ifhead[$scope] = "sub";
  41.         if (!
array_key_exists($subname$label))
  42.             
error ("{$subname} is not the name of any known subroutine in your program"$oldlinenum);
  43.         
$linenum $label[$subname];
  44.         
$move trim($codelines[$linenum]);
  45.         
$args parsemove($move);
  46.         
$cnt count($args);
  47.         if (!
array_key_exists(1$args) || ($subname != $args[1])) {
  48.             
print_r ($args);
  49.             
error ("Call to {$subname} subroutine got misrouted in <CODE>{$move}</CODE>."$oldlinenum);
  50.         }
  51.         
$uservar[$scope][$subname]["subargs"] = $subargs;
  52.         for (
$i 2$i $cnt$i++) {
  53.             if (!
array_key_exists($i-2$subargs)) {
  54.                 
error ("A call to the subroutine <CODE>{$move}</CODE>, which is defined on line {$linenum}, is missing an argument."$oldlinenum);
  55.             }
  56.             
$uservar[$scope]["main"][$args[$i]] = $subargs[$i-2];
  57.         }
  58.     }
  59. 
  60.     foreach (
array_keys($sub) as $key) {
  61.         if (
$key $scope)
  62.             unset(
$sub[$key]);
  63.     }
  64.     for (
$linenum++; $linenum $maxlines$linenum++) {
  65.         
$move trim($codelines[$linenum]);
  66.         if (empty(
$move))
  67.             continue;
  68.                 
  69.         
$args parsemove($move);
  70.         if (
$debug || (DEBUG && (($player == "fergus") || ($player == "duniho") || empty($player)))) {
  71.         
//    printf ("%d [%d:%s]: %s<BR>", $linenum, $scope, $ifhead[$scope], $move);
  72.             
printf ("%d [%s %d:%s]: %s<PRE>\n%s\n</PRE>"$linenum$subname$scope$ifhead[$scope], $movevar_export($args));
  73.         }
  74. 
  75.         
$cnt count($args);
  76.         if (empty(
$cnt))
  77.             continue;
  78.         
  79.         
// The eval command is evaluated before any other, because it can change what the command will be.
  80.         // It evaluates the expression that follows it, converts it into a line of code, and prepares it
  81.         // to be executed as through it were the original line of code.
  82.         
if ($args[0] == "eval") {
  83.             
$move polish(array_slice($args1), $linenum);
  84.             if ((array)
$move === $move
  85.                 
$move implode(" "array_reverse($move));
  86.             if (empty(
$move))
  87.                 continue;
  88.             
$args parsemove($move);
  89.             
$cnt count($args);
  90.         }
  91. 
  92.         
// Evaluate player moves.
  93.         // No elseif, because previous block may change value of $args
  94.         
$moveflag false;
  95.         if (
$args[0] == "MOVE:") {
  96.             
$prevcaptured $lastcaptured;
  97.             
$prevmoved $lastmoved;
  98.             
$prevorigin $origin;
  99.             
$prevdest $dest;
 100.             
$named $args[1]; // Initialize default value
 101.             
$movecnt = isset($movecnt) ? $movecnt 1;
 102.             
$moveflag true;
 103.             if ((
$maxmove 0) && ($movecnt $maxmove))
 104.                 
banned ("You may not enter more than {$maxmove} move primitives in a move in this game.");
 105. 
 106.             
// Delete a space
 107.             
if ($args[1] == "-") {
 108.                 if ((
$subname == "main") && !empty($banned["deletions"]) && empty($allowed["deletions"][$movecnt]))
 109.                     
banned ("{$move} and other moves that delete a space with the hyphen operator are banned here.");
 110.                 
$dest $args[2];
 111.                 if (
$dest[0] == "!" && !isset($ALIAS[$dest]) && ($submit!="Compose") && $coded)
 112.                     
badinput ("The exclamation mark at the beginning of coordinate $dest in <B>{$move}</B> indicates you may not enter it as part of a move.");
 113.                 if (isset(
$space[$dest])) {
 114.                     
$lastcaptured $space[$dest];
 115.                     
$space[$dest] = "-";
 116.                 }
 117.                 else
 118.                     
badinput ("You can't remove {$dest} with {$move}, because it is not a valid coordinate.");
 119.             }
 120.             
 121.             
// when the command is a coordinate
 122.             
elseif (isset($space[$args[1]])) {
 123.                 if (
$args[2] != "-") {
 124.                     echo 
"<PRE>";
 125.                     
print_r ($args);
 126.                     echo 
"</PRE>";
 127.                     
illegal ("The move <b>{$move}</b> ain't well-formed. {$args[1]} is a coordinate. So {$args[2]} should be a hyphen.");
 128.                 }
 129.                 if (
$subname == "main") {
 130.                     if (empty(
$args[3]) && !empty($banned["suicides"]) && empty($allowed["suicides"][$movecnt]))
 131.                         
banned ("{$move} and other suicide moves are banned here.");
 132.                     elseif (!empty(
$banned["moves"]) && empty($allowed["moves"][$movecnt]))
 133.                         
banned ("{$move} and other moves from one space to another are banned here.");
 134.                     elseif (!empty(
$banned["offboard"]) && empty($allowed["offboard"][$movecnt]) && isset($args[3]) && ($space[$args[3]] == "-"))
 135.                         
banned ("{$move} and other moves to an off-board space are banned here.");
 136.                     elseif (!empty(
$banned["captures"]) && empty($allowed["captures"][$movecnt]) && (!isset($args[3]) || ($space[$args[3]] != "@")))
 137.                         
banned ("{$move} and other moves to occupied spaces are banned here.");
 138.                 }
 139.                 if (!empty(
$args[3]))
 140.                     
move ($args[1], $args[3]);
 141.                 else {
 142.                     
$lastmoved $lastcaptured $space[$args[1]];
 143.                     
$space[$args[1]] = "@";
 144.                 }
 145.             }
 146. 
 147.             
// when the command places an empty space on a coordinate.
 148.             
elseif (($args[1] == "@") && ($args[2] == "-") && isset($space[$args[3]])) {
 149.                 if (
$subname == "main") {
 150.                     if (!empty(
$banned["suicides"]) && empty($allowed["suicides"][$movecnt]))
 151.                         
banned ("{$move} and other suicide moves are banned here.");
 152.                     elseif (!empty(
$banned["offboard"]) && empty($allowed["offboard"][$movecnt]) && ($space[$args[3]] == "-"))
 153.                         
banned ("{$move} and other moves adding a new space to the board are banned here.");
 154.                 }
 155.                 
$dest $args[3];
 156.                 if (
$dest[0] == "!" && !isset($ALIAS[$dest]) && ($submit!="Compose") && $coded)
 157.                     
badinput ("The exclamation mark at the beginning of coordinate $dest in <B>{$move}</B> indicates you may not enter it as part of a move.");
 158.                 
$lastmoved $lastcaptured $space[$dest];
 159.                 
$space[$dest] = $args[1];
 160.             }                
 161.     
 162.             
// when the command is a piece
 163.             
elseif (isset($pieces[$args[1]])) {
 164.                 
$named $args[1];
 165.             
 166.                 
// full notation for move
 167.                 
if (isset($args[3]) && ($args[3] == "-")) {
 168.                     if (
$subname == "main") {
 169.                         if (!empty(
$banned["moves"]) && empty($allowed["moves"][$movecnt]))
 170.                             
banned ("{$move} and other moves from one space to another are banned here.");
 171.                         if (!empty(
$banned["offboard"]) && empty($allowed["offboard"][$movecnt]) && !empty($space[$args[3]]) && ($space[$args[3]] == "-"))
 172.                             
banned ("{$move} and other moves to an off-board space are banned here.");
 173.                         if (!empty(
$banned["suicides"]) && empty($allowed["suicides"][$movecnt]) && empty($args[4]))
 174.                             
banned ("{$move} and other suicide moves are banned here.");
 175.                         if (!empty(
$banned["captures"]) && empty($allowed["captures"][$movecnt]) && (empty($space[$args[4]]) || ($space[$args[4]] != "@")))
 176.                             
banned ("{$move} and other moves to occupied spaces are banned here.");
 177.                     }
 178.                     if ((
$args[1] == ($space[$args[2]] ?? "")) or ($noerrorcheck == "on")) {
 179.                         if (
array_key_exists(4$args))
 180.                             
move ($args[2], $args[4]);
 181.                         else {
 182.                             
// Suicide move
 183.                             
$lastmoved $lastcaptured $args[1];
 184.                             
$space[$args[2]] = "@";
 185.                         }
 186.                     }
 187.                     else {
 188.                         
$a0 $ALIAS[$args[1]] ?? $args[1];
 189.                         
$a1 $ALIAS[$args[2]] ?? $args[2];
 190.                         
$p0 $ALIAS[$space[$args[2]]] ?? $space[$args[2]];
 191.                         if (
$p0 == "@")
 192.                             
illegal ("There was no $a0 on $a1. It is an empty space.");
 193.                         else
 194.                             
illegal ("There was no $a0 on $a1. The piece on $a1 is a $p0.");
 195.                     }
 196.                 }
 197.                 
 198.                 elseif (
$args[2] == "-") {
 199.     
 200.                     
// promote or introduce piece
 201.                     
if (isset($space[$args[3]])) {
 202.                         if (
$subname == "main") {
 203.                             if (!empty(
$banned["freedrops"]) && empty($allowed["freedrops"][$movecnt]) && ($space[$args[3]] == "@"))
 204.                                 
banned ("{$move} and other moves dropping a new piece onto an empty spaces are banned here.");
 205.                             elseif (!empty(
$banned["promotions"]) && empty($allowed["promotions"][$movecnt]) && ($args[3] == $dest))
 206.                                 
banned ("{$move} and other promotions are banned here.");
 207.                             elseif (!empty(
$banned["offboard"]) && empty($allowed["offboard"][$movecnt]) && ($space[$args[3]] == "-"))
 208.                                 
banned ("{$move} and other moves dropping a piece onto a non-board space are banned here.");
 209.                             elseif (!empty(
$banned["changes"]) && empty($allowed["changes"][$movecnt]) && ($args[3] != $dest) && ctype_alnum($space[$args[3]]))
 210.                                 
banned ("{$move} and other moves changing the type of an arbitrary piece are banned here.");
 211.                         }
 212.                         if (
$args[3] != $dest) {
 213.                             
$dest $args[3];
 214.                             
$origin false;
 215.                             
$lastcaptured $space[$dest];
 216.                         }
 217.                         
$space[$dest] = (isset($alias) && !empty($alias[$args[1]])) ? $alias[$args[1]] : $args[1];
 218.                     }
 219.     
 220.                     
// exchange pieces ala Hostage Chess
 221.                     
elseif (isset($pieces[$args[3]]) && isset($prison) && isset($starpath)) {
 222.                         if ((
$subname == "main") && !empty($banned["hostages"]) && empty($allowed["hostages"][$movecnt]))
 223.                             
banned ("{$move} and other moves for the exchange of hostages are banned here.");
 224.                         if (isset(
$piecevals) && ($piecevals[$args[1]] < $piecevals[$args[3]]))
 225.                             die (
"<P>You may not release a {$args[1]} to rescue your {$args[3]}, because the {$args[1]} is not as valuable.");
 226.                         if ((
$o1 findpiece($args[3], $prison[!$firstplayer])) === false) {
 227.                             die (
"<P>Cannot find {$args[3]} in your opponent's prison.</P>");
 228.                         }
 229.                         if ((
$o2 findpiece($args[1], $prison[$firstplayer])) === false)
 230.                             die (
"<P>Cannot find {$args[1]} in your prison.</P>");
 231.                         if ((
$d1 findpiece("@"$starpath[$firstplayer])) === false)
 232.                             die (
"<P>No vacancy. Your starpath is full.</P>");
 233.                         if ((
$d2 findpiece("@"$starpath[!$firstplayer])) === false)
 234.                             die (
"<P>No vacancy. Opponent's starpath is full.</P>");
 235.                         
$lastmoved $space[$d1] = $space[$o1];
 236.                         
$space[$d2] = $space[$o2];
 237.                         
$lastcaptured $space[$o1] = $space[$o2] = "@";
 238.                         
$dest $d1$origin $o2;
 239.                     }
 240.                     
 241.                     else {
 242.                         
print_r ($args);
 243.                         
print_r ($prison);
 244.                         
print_r ($starpath);
 245.                         
illegal ("Game Courier does not know what to do with this move: {$move}");
 246.                     }
 247.                 }
 248.                 
 249.                 
// drop piece
 250.                 
elseif ($args[2] == "*") {
 251.                     if ((
$subname == "main") && !empty($banned["drops"]) && empty($allowed["drops"][$movecnt]))
 252.                         
banned ("{$move} and other moves dropping a captured piece are banned here.");
 253.                     
$dest $args[3];
 254.                     if (empty(
$space[$dest]))
 255.                         
illegal ("The coordinate \"{$dest}\" is unknown in move: {$move}.");
 256.                     
$p $args[1]; 
 257.                     
$origin findpiece($p$starpath[$firstplayer]);
 258.                     if (
$origin === false) {
 259.                         echo 
"<PRE>";
 260.                         
print_r ($firstplayer);
 261.                         
print_r ($starpath);
 262.                         
print_r ($starpath[$firstplayer]);
 263.                         echo 
"</PRE>";
 264.                         
illegal ("You have no $p to drop with the * operator for move: {$move}.");
 265.                     }
 266.                     
$dest trim($dest);
 267.                     
$lastcaptured $space[$dest];
 268.                     
$lastmoved $space[$dest] = $p;
 269.                     
$space[$origin] = "@";
 270.                 }
 271.                 else {
 272.                     
illegal ("The move <b>{$move}</b> is NOT well-formed.");
 273.                 }
 274.             }
 275.             
/*
 276.             elseif (($args[1] == "resign") || ($args[1] == "lost")) {
 277.                 if (($submit == "Preview") || ($submit == "Send")) {
 278.                     $GLOBALS["winner"] = $opponent;
 279.                     if ($args[1] == "resign")
 280.                         $message = sprintf("%s has resigned.", userid_name($player));
 281.                     else
 282.                         $message = sprintf("%s has accepted a loss.", userid_name($player));
 283.                 }
 284.                 else {
 285.                     echo "<P>first is {$first}, side is {$side}, movenum is {$movenum}</P>";
 286.                     $GLOBALS["status"] = sprintf("%s has won.", $side);
 287.                     $winner = (($movenum & 1) ^ ($side != $first)) ? $opponent : $player;
 288.                     $loser = ($winner == $player) ? $opponent : $player;
 289.                     if ($args[1] == "resign")
 290.                         $message = userid_name($loser) . " has resigned.";
 291.                     else
 292.                         $message = userid_name($loser) . " has accepted a loss.";
 293.                 }
 294.                 $GLOBALS["status"] = sprintf("%s has won.", userid_name($winner));
 295.                 $gameover = true;
 296.                 return;
 297.             }
 298.             elseif ($args[1] == "drawn") {
 299.                 if (empty($submit) || ($submit == "Preview") || ($submit == "Send") || ($submit == "View") || ($submit == "Move")) {
 300.                     $GLOBALS["status"] = "Drawn game.";
 301.                     $GLOBALS["winner"] = "";
 302.                     $GLOBALS["message"] = "The game is declared drawn.";
 303.                     $gameover = true;
 304.                 }
 305.                 return;
 306.             }
 307.             */
 308.             
elseif (($subname == "main") && !empty($banned[$args[1]])) {
 309.                 
banned ("The <b>{$args[1]}</b> command has been explicitly banned from user input on the part of the turn indexed {$movecnt}.");
 310.             }
 311.             elseif ((
$subname == "main") && !empty($banned["commands"]) && empty($allowed[$args[1]][$movecnt]) && ($args[1] != "resign") && ($args[1] != "lost") && ($args[1] != "drawn")) {
 312.                 
banned ("There is a global ban on commands in user input, and no exception has been made for the <b>{$args[1]}</b> command on the part of the turn indexed {$movecnt}.");
 313.             }
 314.             else {
 315.                 
$moveflag false;
 316.                 
array_shift ($args);
 317.             }
 318.         }
 319. 
 320.         
/*
 321.         if ((($sub == "main") && (!$ban xor in_array($args[0], $banlist))) ? $args[0] : "-") {
 322.             printf ("<PRE>");
 323.             print_r ($ban);
 324.             printf ("</PRE>");
 325.             if ($ban)
 326.                 $errmessage = sprintf("All commands except these have been banned from the main level of the program: %s", implode(", ", $banlist));
 327.             else
 328.                 $errmessage = sprintf("The <b>%s</b> command has been banned from the main level of the program.", $args[0]);
 329.             error ($errmessage, $linenum);
 330.         }
 331.         */
 332.         
 333.         // Commands
 334.         
if ($moveflag) {
 335.             
// Do nothing since the move was already handled.
 336.         
}
 337.         elseif (isset(
$label[$args[0]])) { // Silent Gosub
 338.             // You may replace a command with a subroutine by the same name.
 339.             // This is useful for letting me add new commands without breaking
 340.             // code that silently calls subroutines by the same name. You may
 341.             // name a subroutine after a command if you want to change its behavior,
 342.             // but it is generally recommended that you don't.
 343.                 
setuservar("RESULT"runsubroutine ($args[0], array_slice($args1), $linenum));
 344.                 if (!empty(
$exit))
 345.                     return;
 346.         }
 347.         else
 348.             switch (
$args[0]) {
 349.             case 
"MOVE:":
 350.                 break;
 351.             case 
"add":
 352.                 if (
count($args) < 3) {
 353.                     
error("The <b>add</b> command requires at least two arguments."$linenum);
 354.                 }
 355.                 elseif (
$args[2] == "all") {
 356.                     
// Add same piece to all listed spaces
 357.                     
for ($i 3$i $cnt$i++)
 358.                         
$space[$args[$i]] = $args[1];
 359.                 }
 360.                 elseif (
$args[2] == "any") {
 361.                     
// Add one piece to any listed space
 362.                     
$space[$args[mt_rand(3$cnt-1)]] = $args[1];
 363.                 }
 364.                 else {
 365.                     
// Add each piece to singular listed space
 366.                     
for ($i 1$i < ($cnt 1); $i += 2) {
 367.                         
$space[$args[$i+1]] = $args[$i];
 368.                     }
 369.                 }
 370.                 break;
 371.             case 
"alias"// Set alias for piece or coordinate
 372.                 
for ($i 1$i $cnt$i += 2) {
 373.                     if ((
$i 1) < $cnt) {
 374.                         
// Sets realname of alias
 375.                         
$REALNAME[$args[$i]] = $args[$i+1];
 376.                         
// Sets alias used for realname
 377.                         
$ALIAS[$args[$i+1]] = $args[$i];
 378.                     }
 379.                     else
 380.                         
error("The last value passed to alias is unpaired"$linenum);
 381.                 }
 382.                 break;
 383.             case 
"allow"// Make exceptions to ban. See "ban"
 384.                 
for ($i 1$i $cnt$i += 2) {
 385.                     if (!
ctype_alpha($args[$i]) || !ctype_digit($args[$i+1] ?? ""))
 386.                         
error ("Invalid argument for <b>allow</b>. This command must be followed by keyword number pairs."$linenum);
 387.                     
$allowed[$args[$i]][$args[$i+1]] = true;
 388.                 }
 389.                 break;
 390.             case 
"continuemove"// Allow multi-part move to be made with mouse/touch
 391.             
case "redomove"// Allow player to redo illegal move
 392.                 
if ($submit == "Preview")
 393.                     
$submit "";
 394.                 
$pastmovesfield = ($args[0] == "redomove") ? "" $moves;
 395.                 
$movelist $oldmovelist;
 396.                 
$movenum max($movenum 10);
 397.                 if (!
$switchsides) {
 398.                     
$side $turnorder[$movenum $sidecnt];
 399.                 }
 400.                 else
 401.                     
$side $turnorder[($sidecnt 1) - ($movenum $sidecnt)];
 402.                 break;
 403.             case 
"appendmove"// Append value of expression to current move
 404.                 
$moves .= "; " polish(array_slice($args1),$linenum);
 405.                 
$lastmove trim($moves);
 406.                 if (empty(
$oldmovelist))
 407.                     
$movelist "{$turn}{$lastmove}";
 408.                 else
 409.                     
$movelist $oldmovelist "\n{$turn}{$lastmove}";
 410.                 
$mline[count($mline)-1]->move $lastmove;
 411.                 if (!empty(
$comments)) {
 412.                     
$temp trim($comments);
 413.                     
$temp str_replace("\n""\n// "$temp);
 414.                     
$movelist .= "\n// $temp";
 415.                 }
 416.                 break;
 417.             case 
"rewritemove"// Rewrite current move with another move. 
 418.             // Useful for standardizing notation.
 419.                 
$moves polish(array_slice($args1),$linenum);
 420.                 
$lastmove trim($moves);
 421.                 if (empty(
$oldmovelist))
 422.                     
$movelist "{$turn}{$lastmove}";
 423.                 else
 424.                     
$movelist $oldmovelist "\n{$turn}{$lastmove}";
 425.                 
$mline[count($mline)-1]->move $lastmove;
 426.                 if (!empty(
$comments)) {
 427.                     
$temp trim($comments);
 428.                     
$temp str_replace("\n""\n// "$temp);
 429.                     
$movelist .= "\n// $temp";
 430.                 }
 431.                 break;
 432.             case 
"input"// Stores user input in a constant
 433.                 
if (isset($constants[$args[1]]))
 434.                     break;
 435.                 
print_r($constants);
 436.                 echo 
"<FORM NAME=\"move\" ACTION=\"play.php\" METHOD=POST>\n";
 437.                 
copyformdata ();
 438.                 echo 
"<P><B>{$args[2]}</B></P>";
 439.                 if (
$cnt 4// User enters string
 440.                     
echo "<INPUT TYPE=\"text\" NAME=\"constants_{$args[1]}\" VALUE=\"\">\n";
 441.                 elseif (
$cnt == 4)
 442.                     echo 
"<INPUT TYPE=\"checkbox\" NAME=\"constants_{$args[1]}\" VALUE=\"{$args[3]}\"> {$args[3]}\n";
 443.                 else { 
// User is given multiple choices
 444.                     
for ($i 3$i $cnt$i++) {
 445.                         echo 
"<DIV STYLE=\"float: left; border: solid black thin; margin: 1ex; padding: 1ex;\">";
 446.                         
// For an array, first element is value, rest is displayed as text
 447.                         
if ((array)($args[$i]) === $args[$i]) {
 448.                             
$car $args[$i][0];
 449.                             
$cdr $args[$i][1];
 450.                             for (
$j 2$j count($args[$i]); $j++)
 451.                                 
$cdr .= {$args[$i][$j]}";
 452.                             
printf ("<INPUT TYPE=\"radio\" NAME=\"constants_%s\" VALUE=\"%s\"> %s\n"$args[1], $car$cdr);
 453.                         }
 454.                         
// For a piece label, the piece is displayed
 455.                         
elseif (isset($pieces[$args[$i]])) {
 456.                             
printf ("<INPUT TYPE=\"radio\" NAME=\"constants_%s\" VALUE=\"%s\">\n"$args[1], $args[$i]);
 457.                             
drawpiece($args[$i]);
 458.                         }
 459.                         
// For a coordinate, its appropriately colored space
 460.                         // is displayed with whatever piece is on it.
 461.                         
elseif (isset($space[$args[$i]])) {
 462.                             
printf ("<TABLE><TR><TD><INPUT TYPE=\"radio\" NAME=\"constants_%s\" VALUE=\"%s\"></TD><TD HEIGHT=%d WIDTH=%d ALIGN=CENTER VALIGN=MIDDLE BGCOLOR=%s\"><IMG SRC=\"%s%s\"></TD><TD>%s</TD></TR></TABLE>\n"$args[1], $args[$i], $height$width$color[$background[$args[$i]]], $GLOBALS["dir"], $pieces[$space[$args[$i]]], $args[$i]);
 463.                         }
 464.                         
// Any other argument is used as a value and displayed as text
 465.                         
else
 466.                             
printf ("<INPUT TYPE=\"radio\" NAME=\"constants_%s\" VALUE=\"%s\"> %s\n"$args[1], $args[$i], $args[$i]);
 467.                         echo 
"</DIV>";
 468.                     }
 469.                 }
 470.                 if (empty(
$submit))
 471.                     
$submit "Submit";
 472.                 echo 
"<INPUT TYPE=\"submit\" NAME=\"submit\" VALUE=\"{$submit}\">\n";
 473.                 if ((
$submit == "Preview") || ($submit == "Submit"))
 474.                     
hide ("userid"true);
 475.                 
$movelist $oldmovelist;
 476.                 
$moves "";
 477.                 
$movenum--;
 478.                 
hide ();
 479.                 
hide ("game settings"true);
 480.                 echo 
"</FORM>";
 481.                 exit ();
 482.                 break;
 483.             case 
"ask":
 484.             
// Asks a question with multiple answers.
 485.             // Appends move associated with chosen answer to current move.
 486.                 
if (!empty($moves)) {
 487.                     echo 
"<FORM NAME=\"move\" ACTION=\"play.php\" METHOD=POST>\n";
 488.                     
copyformdata ();
 489.                     echo 
"<P><B>{$args[1]}</B></P>";
 490.                     for (
$i 2$i $cnt$i += 2)
 491.                         
printf ("\n<INPUT TYPE=\"radio\" NAME=\"moves\" VALUE=\"{$moves}; %s\"%s> <B>%s:</B> <KBD>%s; %s</KBD><BR>\n"$args[$i+1], $i==" CHECKED" ""$args[$i], $moves$args[$i+1]);
 492.                     
// Is this next line needed? It may relate to the answered operator.
 493.                     
echo "<INPUT TYPE=\"hidden\" NAME=\"answered\" VALUE=true>";
 494.                     echo 
"<INPUT TYPE=\"submit\" NAME=\"submit\" VALUE=\"{$submit}\">\n";
 495.                     if (
$submit == "Preview")
 496.                         
hide ("userid"true);
 497.                     
$movelist $oldmovelist;
 498.                     
$moves "";
 499.                     
$movenum--;
 500.                     
hide ();
 501.                     
hide ("game settings"true);
 502.                     echo 
"</FORM>";
 503.                     exit ();
 504.                 }
 505.                 break;                
 506.             case 
"askpromote":
 507.             
// Asks which piece to promote to, then updates current move.
 508.             // When promotion is optional, include the current piece in the options.
 509.                 
if (!empty($moves)) {
 510.                     
printf ("<FORM NAME=\"move\" ACTION=\"play.php\" METHOD=POST>\n");
 511.                     
copyformdata ();
 512.                     echo 
"<P><B>Which piece will you promote to?</B></P>";
 513.                     if (
is_array($args[1])) {
 514.                         foreach (
$args[1] as $val) {
 515.                             if (
$val != $space[$dest]) {
 516.                                 
printf ("<INPUT NAME=\"moves\" TYPE=\"radio\" VALUE=\"{$moves}; %s-dest\"> ", isset($ALIAS[$val]) ? $ALIAS[$val] : $val);
 517.                                 
drawpiece ($val);
 518.                             }
 519.                             else {
 520.                                 
printf ("<P><B>Decline Promotion:</B></P><INPUT NAME=\"moves\" TYPE=\"radio\" VALUE=\"{$moves}; skip\">");
 521.                                 
drawpiece ($val);
 522.                             }
 523.                         }
 524.                     }
 525.                     else {
 526.                         for (
$i 1$i $cnt$i++) {
 527.                             
printf ("<INPUT TYPE=\"radio\" NAME=\"moves\" VALUE=\"{$moves}; %s-dest\"%s> ", !empty($ALIAS[$args[$i]]) ? $ALIAS[$args[$i]] : $args[$i], $i==" CHECKED" "");
 528.                             
drawpiece ($args[$i]);
 529.                         }
 530.                     }
 531.                     echo 
"<INPUT TYPE=\"hidden\" NAME=\"answered\" VALUE=true>";
 532.                     echo 
"<INPUT TYPE=\"submit\" NAME=\"submit\" VALUE=\"{$submit}\">";
 533.                     
$movelist $oldmovelist;
 534.                     
$moves "";
 535.                     
$movenum--;
 536.                     
hide ();
 537.                     
hide ("game settings"true);
 538.                     echo 
"</FORM>";
 539.                     exit ();
 540.                 }
 541.                 break;                
 542.             case 
"unallow"// Revokes exceptions to banning made by allow
 543.                 
for ($i 1$i $cnt$i += 2) {
 544.                     if (!
ctype_alpha($args[$i]) || !ctype_digit($args[$i+1]))
 545.                         
error ("Invalid argument for <b>unallow</b>. This command must be followed by keyword number pairs."$linenum);
 546.                     
$allowed[$args[$i]][$args[$i+1]] = false;
 547.                 }
 548.                 break;
 549.             case 
"ban"// Bans types of moves or commands from being entered as moves
 550.                 
if ($cnt 2)
 551.                     
error ("The <b>ban</b> command is missing required arguments."$linenum);
 552.                 for (
$i 1$i $cnt$i++) {
 553.                     if (
$args[$i] == "none")
 554.                         unset (
$banned);
 555.                     elseif (
$args[$i] == "allmoves")
 556.                         
$banned["captures"] = $banned["changes"] = $banned["deletions"] = $banned["drops"] = $banned["freedrops"] = $banned["hostages"] = $banned["moves"] = $banned["offboard"] = $banned["promotions"] = $banned["suicides"] = true;
 557.                     elseif (
$args[$i] == "all")
 558.                         
$banned["commands"] = true;
 559.                     else
 560.                         
$banned[$args[$i]] = true;
 561.                 }
 562.                 break;
 563.             case 
"calcset"// Performs the same logical or mathematical operation
 564.             // on each listed variable.
 565.                 
for ($i 3$i $cnt$i++) {
 566.                     
$temp = &refvar($args[$i]) ?? 0;
 567.                     if (
is_numeric($temp))
 568.                         
$temp = (int)$temp;
 569.                     switch (
$args[1]) {
 570.                         case 
"|": case "or":
 571.                             
$temp |= $args[2];
 572.                             break;
 573.                         case 
"&": case "and":
 574.                             
$temp &= $args[2];
 575.                             break;
 576.                         case 
"^": case "xor":
 577.                             
$temp ^= $args[2];
 578.                             break;
 579.                         case 
"<<":
 580.                             
$temp <<= $args[2];
 581.                             break;
 582.                         case 
">>":
 583.                             
$temp >>= $args[2];
 584.                             break;
 585.                         case 
"=":
 586.                             
$temp $args[2];
 587.                             break;
 588.                         case 
"*":
 589.                             
$temp *= $args[2];
 590.                             break;
 591.                         case 
"/":
 592.                             
$temp /= $args[2];
 593.                             break;
 594.                         case 
"-":
 595.                             
$temp -= $args[2];
 596.                             break;
 597.                         case 
"+":
 598.                             
$temp += $args[2];
 599.                             break;
 600.                         case 
"&&":
 601.                             
$temp = ($temp && $args[2]);
 602.                             break;
 603.                         case 
"||":
 604.                             
$temp = ($temp || $args[2]);
 605.                             break;
 606.                         case 
"==":
 607.                             
$temp = ($temp == $args[2]);
 608.                             break;
 609.                         case 
"mod":
 610.                         case 
"%":
 611.                             
$temp %= $args[2];
 612.                             break;
 613.                         default:
 614.                             
error ("The first argument of calcset is illegal: {$args[$i]}"$linenum);
 615.                             break;
 616.                     }
 617.                     unset(
$temp);
 618.                 }
 619.                 break;
 620.             case 
"capture"// Captures pieces on all listed positions
 621.             // Sets $lastcaptured to last position in list.
 622.                 
if (isset($args[$cnt-1])) {
 623.                     if (
array_key_exists($args[$cnt-1], $space))
 624.                         
$lastcaptured $space[$args[$cnt-1]];
 625.                     for (
$i 1$i $cnt$i++)
 626.                         
$space[$args[$i]] = '@';
 627.                 }
 628.                 else
 629.                     
error ("Expected argument for capture could not be found."$linenum);
 630.                 break;
 631.             case 
"change":
 632.             
// Changes piece on coordinate to piece following its piece type in ranked list.
 633.             
case "convert":
 634.             
// Using list of pairs, finds the first pair whose first member matches the type
 635.             // of piece at coordinate and converts it to second member of same pair.
 636.                 
unset ($conversions);
 637.                 
$inc = ($args[0] == "change") ? 2;
 638.                 for (
$cnt--, $i 2$i $cnt$i += $inc)
 639.                     
$conversions[$args[$i]] = $args[$i+1];
 640.                 
$pos $args[1];
 641.                 if (
$pos == "all") {
 642.                     foreach (
$space as $pos => $val) {
 643.                         if (isset(
$conversions[$val]))
 644.                             
$space[$pos] = $conversions[$val];
 645.                     }
 646.                 }
 647.                 elseif (
array_key_exists($pos$space) && isset($conversions[$space[$pos]]))
 648.                     
$space[$pos] = $conversions[$space[$pos]];
 649.                 break;
 650.             case 
"clear"// Moves pieces to off-board area
 651.             // Useful for composing problems. NEEDS WORK.
 652.                 
if (empty($starpath[0])) {
 653.                     
$starpath[0] = array();
 654.                     for (
$x 0$x $GLOBALS["cols"]; $x++) {
 655.                         for (
$y 0$y $GLOBALS["rows"]; $y++) {
 656.                             
$c $file[$x] . $rank[$y];
 657.                             if (!
ctype_alnum($c))
 658.                                 
$starpath[0][] = $c;
 659.                         }
 660.                     }
 661.                 }
 662.                 if (empty(
$starpath[1])) {
 663.                     
$starpath[1] = array();
 664.                     for (
$x $GLOBALS["cols"] - 1$x >= 0$x--) {
 665.                         for (
$y $GLOBALS["rows"] - 1$y >= 0$y--) {
 666.                             
$c $file[$x] . $rank[$y];
 667.                             if (!
ctype_alnum($c))
 668.                                 
array_push($starpath[1], $c);
 669.                         }
 670.                     }
 671.                 }
 672.                 if ((
$cnt 2) || (array_key_exists(1$args) && ($args[1] == "board"))) {
 673.                     foreach (
$space as $sp => $p) {
 674.                         if ((
$p != "@") && ($p != "-") && ($sp[0] != "!")) {
 675.                             
$space[$sp] = "@";
 676.                             
$nsp ctype_lower($p) ? findpiece("@"$starpath[1]) : findpiece("@"$starpath[0]);
 677.                             
$space[$nsp] = $p;
 678.                         }
 679.                     }
 680.                 }
 681.                 else {
 682.                     for (
$i 1$i $cnt$i++) {
 683.                         
$p $space[$args[$i]];
 684.                         
$nsp ctype_lower($p) ? findpiece("@"$starpath[1]) : findpiece("@"$starpath[0]);
 685.                         if (
$nsp != false) {
 686.                             
$space[$args[$i]] = "@";
 687.                             
$space[$nsp] = $p;
 688.                         }
 689.                     }
 690.                 }                    
 691.                 break;
 692.             case 
"conserve":
 693.                 
error ("The conserve command has been removed."$linenum);
 694.                 break;
 695.             case 
"copy"// Copies content of one space to another
 696.                 
$space[$args[2]] = $space[$args[1]];
 697.                 break;
 698.             case 
"copyflag"// Copies value of flag for first argument to flags named 
 699.             // after remaining arguments
 700.                 
for ($i 2$i $cnt$i++)
 701.                     
$flag[$args[$i]] = $flag[$args[1]] ?? false;
 702.                 break;
 703.             case 
"deal"// Shuffles a deck of cards and deals out specified number
 704.             // of cards to each player.
 705.                 
$deck shufflearray(array_keys($cards));
 706.                 
$discardpile = array();
 707.                 
$hand1 = array();
 708.                 
$hand2 = array();
 709.                 for (
$i 0$i $args[1]; $i++) {
 710.                     
$c array_pop($deck);
 711.                     
$hand1[] = $c;
 712.                     
$drawncards[] = $c;
 713.                     
$c array_pop($deck);
 714.                     
$hand2[] = $c;
 715.                     
$drawncards[] = $c;
 716.                 }
 717.                 break;
 718.             case 
"dec"// Decrements integer variable by one
 719.                 
$temp = &refvar($args[1]);
 720.                 
$temp--;
 721.                 unset(
$temp);
 722.                 break;
 723.             case 
"def"// Defines function
 724.                 
$functions[$args[1]] = array_slice($args2);
 725.                  
$tempflags = array();
 726.                 
$maxargs 0;
 727.                 
$fn $functions[$args[1]];
 728.                 
$mn count($fn); 
 729.                 for (
$i 0$i $mn$i++) {
 730.                     
// print_r($fn);
 731.                     
if (array_key_exists($i$fn) && !empty($fn[$i]) && ($fn[$i][0] == "#")) {
 732.                         
$n substr($fn[$i], 1);
 733.                         if (
ctype_digit($n)) {
 734.                             
$tempflags[$n] = true;
 735.                             
$maxargs max($maxargs$n);
 736.                         }
 737.                     }
 738.                 }
 739.                 if (
$maxargs count($tempflags)) {
 740.                     
$ct count($tempflags);
 741.                     
print_r ($tempflags);
 742.                     
error ("Function {$args[0]} requires more arguments than it has placeholders for. maxargs: {$maxargs} tempflags: {$tempflags} count(tempflags): $ct"$linenum);
 743.                 }
 744.                 break;
 745.             case 
"copyfn"// Clones function to new function with new name
 746.                 
if (isset($functions[$args[1]]))
 747.                     
$functions[$args[2]] = $functions[$args[1]];
 748.                 else
 749.                     
error ("The function {$args[1]} does not exist."$linenum);
 750.                 break;
 751.             case 
"empty"// Empties all spaces or listed spaces
 752.                 
if ($args[1] == "all") {
 753.                     foreach (
$space as $key => $val)
 754.                         if (
$val != '-')
 755.                             
$space[$key] = '@';
 756.                 }
 757.                 else {
 758.                     for (
$i 1$i $cnt$i++)
 759.                         
$space[$args[$i]] = '@';
 760.                 }
 761.                 break;
 762.             case 
"delete"// Removes listed spaces from board,
 763.             
case "remove"// leaving behind non-space.
 764.                 
for ($i 1$i $cnt$i++)
 765.                     
$space[$args[$i]] = '-';
 766.                 break;
 767.             case 
"end"// Main level command to mark natural end of program
 768.             // Inserted in right place automatically.
 769.                 
if ($subname != "main")
 770.                     
error ("Misplaced <b>end</b>."$linenum);
 771.             case 
"exit":
 772.                 
$exit true;
 773.                 return;
 774.                 break;
 775.             case 
"stop"// Forcibly exits subroutine.
 776.             // At main level, it forcibly exits the program.
 777.                 
return;
 778.                 break;
 779.             case 
"die"// Forcibly exits program after printing message
 780.                 
echo ("</PRE><P STYLE=\"font-size: 2em; line-height: 1.2em;\">" stripallslashes(join(" "array_slice($args1))) . "</P><PRE>\n");
 781.                 if (
false && $_POST["olddefault"]) {
 782.                     echo 
"<FORM ACTION=\"play.php\" METHOD=POST>";
 783.                     
$formvalues json_decode(urldecode($_POST["olddefault"]));
 784.                     foreach (
$formvalues as $key => $val) {
 785.                         if (
is_array($val))
 786.                             
printf ("<INPUT TYPE='hidden' NAME='%s' VALUE='%s'>"$keyrawurlencode(serialize($val)));
 787.                         else
 788.                             
printf ("<INPUT TYPE=\"hidden\" NAME=\"%s\" VALUE=\"%s\">"$keyrawurlencode($val));
 789.                     }
 790.                     if (
$submit == "Move")
 791.                         echo 
"<INPUT TYPE=\"submit\" NAME=\"submit\" VALUE=\"Move\">\n";
 792.                     echo 
"</FORM>\n";
 793.                 }
 794.                 
 795.                 if (!empty(
$submit))
 796.                     echo (
"<P><BIG>Use your browser's BACK button to go back to the previous page, then reload if necessary.</BIG></P>");
 797.                 else
 798.                     echo 
"<P><B>Since this is not a preview, something may have gone wrong with the code. For diagnostic purposes, this message was produced by calling the <B>die</B> command on line {$linenum}, and the last move played was</P> <P><BIG><B>{$mline[$mln]->turn}{$mline[$mln]->move}</B></BIG></P>";
 799.                 echo 
"<P>For general reference, here is the complete list of moves:</P><PRE>{$movelist}</PRE>";
 800.                 
$url "https://www.chessvariants.com/play/pbm/play.php?game=" urlencode($GLOBALS["game"]) . "&settings=" urlencode($GLOBALS["settings"]) . "&submit=Edit";
 801.                 echo 
"<p>If this is your settings file, you may edit it at <a href=\"{$url}\">{$url}</a></p>";
 802.                 echo 
"<P>Here is a code listing:</P>";
 803.                 
listprog();
 804.                 if (
fpdip()) {
 805.                     echo 
"<PRE>";
 806.                     
print_r($functions);
 807.                     echo 
"</PRE>";
 808.                 }
 809.                     
 810.                 exit();
 811.                 break;
 812.             case 
"discard"// Places listed cards from player's hand into discard pile
 813.                 
if ($firstplayer)
 814.                     
$hand = &$hand1;
 815.                 else
 816.                     
$hand = &$hand2;
 817.                 for (
$i 1$i $cnt$i++) {
 818.                     if (empty(
$args[$i]))
 819.                         continue;
 820.                     if (
in_array($args[$i], $hand)) {
 821.                         
$k array_search($args[$i], $hand);
 822.                         
array_push($discardpile$hand[$k]);
 823.                         unset (
$hand[$k]);
 824.                     }
 825.                     else {
 826.                         echo 
"<PRE>";
 827.                         
print_r ($args[$i]);
 828.                         
print_r ($hand);
 829.                         echo 
"</PRE>";
 830.                         die (
"<P>You can't discard a {$cards[$args[$i]]->alt}, because you don't have one in your hand. Go back and enter a legal move.</P>");
 831.                     }
 832.                 }
 833.                 
$hand array_values($hand);
 834.                 break;
 835.             case 
"displace"// discards continuing effect cards
 836.                 
for ($i 1$i $cnt$i++) {
 837.                     if (
in_array($args[$i], $displayedcards)) {
 838.                         
$k array_search($args[$i], $displayedcards);
 839.                         
array_push($discardpile$displayedcards[$k]);
 840.                         unset (
$displayedcards[$k]);
 841.                     }
 842.                     else
 843.                         die (
"<P>You can't displace a {$cards[$args[$i]]->alt}, because none is displayed.</P>");
 844.                 }
 845.                 
$displayedcards array_values($displayedcards);
 846.                 break;
 847.             case 
"draw"// Draw specified number of cards
 848.                 
if ($firstplayer)
 849.                     
$hand = &$hand1;
 850.                 else
 851.                     
$hand = &$hand2;
 852.                 if (empty(
$args[1])) {
 853.                     die (
"<P>Use the <CODE>drawn</CODE> command if you wish to end a game in a draw. The draw command is for drawing cards from a deck.</P>");
 854.                 }
 855.                 elseif (!empty(
$args[2]) && ($args[2] == "discard")) { // Draw cards from discard pile
 856.                     
for ($i 0$i $args[1]; $i++)
 857.                         
array_push($handarray_pop($discardpile));
 858.                 }
 859.                 else {
 860.                     for (
$i 0$i $args[1]; $i++) {
 861.                         
$c array_pop($deck);
 862.                         
array_push($hand$c);
 863.                         
array_push($drawncards$c);
 864.                         if (
count($deck) == 0) {
 865.                             
$deck shufflearray($discardpile);
 866.                             
$discardpile = array();
 867.                         }
 868.                     }
 869.                 }
 870.                 break;
 871.             case 
"drop"// Drops piece onto empty space(s) in list
 872.             
case "replace"// Drops piece onto space(s) with or without specified piece
 873.                 
if ($args[0] == "drop") {
 874.                     
$trueflag true;
 875.                     
$firstpos 2;
 876.                     
$target '@';
 877.                     
$p $args[1];
 878.                 }
 879.                 elseif (
$args[1] == "not") { // Drops on space(s) without specified piece
 880.                     
$trueflag false;
 881.                     
$firstpos 4;
 882.                     
$target $args[2];
 883.                     
$p $args[3];
 884.                 }
 885.                 else { 
// Drops on space(s) with specified piece
 886.                     
$trueflag true;
 887.                     
$firstpos 3;
 888.                     
$target $args[1];
 889.                     
$p $args[2];
 890.                 }
 891. 
 892.                 if (
preg_match("/^(all|any|first|last|right|left)$/"$args[$firstpos])) {
 893.                     
$keyword $args[$firstpos];
 894.                     
$firstpos++;
 895.                 }
 896.                 else
 897.                     
$keyword "";
 898.                 
 899.                 if ((array)
$args[$firstpos] === $args[$firstpos]) {
 900.                     
$temp $args[$firstpos];
 901.                     unset (
$args);
 902.                     
$args = &$temp;
 903.                     
$firstpos 0;
 904.                     
$cnt count($args);
 905.                 }
 906.                 
$j 0;
 907.                 
$pos = array();
 908.                 switch (
$args[2]) {
 909.                     case 
"first"// Selects first space matching criterion
 910.                         
for ($i $firstpos$i $cnt$i++) {
 911.                             if (
array_key_exists($args[$i], $space)) {
 912.                                 if ((
$space[$args[$i]] == $target) == $trueflag) {
 913.                                     
$pos[$j++] = $args[$i];
 914.                                     break;
 915.                                 }
 916.                             }
 917.                         }
 918.                         break;
 919.                     case 
"last"// Selects last space matching criterion
 920.                         
for ($i $cnt-1$i >= $firstpos$i--) {
 921.                             if (
array_key_exists($args[$i], $space)) {
 922.                                 if ((
$space[$args[$i]] == $target) == $trueflag) {
 923.                                     
$pos[$j++] = $args[$i];
 924.                                     break;
 925.                                 }
 926.                             }
 927.                         }
 928.                         break;
 929.                     case 
"left"// Selects spaces to left not matching criterion
 930.                         
for ($i $firstpos$i $cnt$i++) {
 931.                             if (
array_key_exists($args[$i], $space)) {
 932.                                 if ((
$space[$args[$i]] != $target) == $trueflag)
 933.                                     break;
 934.                                 
$pos[$j++] = $args[$i];
 935.                             }
 936.                         }
 937.                         break;
 938.                     case 
"right"// Selects spaces to right not matching criterion
 939.                         
for ($i $cnt-1$i >= $firstpos$i--) {
 940.                             if (
array_key_exists($args[$i], $space)) {
 941.                                 if ((
$space[$args[$i]] != $target) == $trueflag)
 942.                                     break;
 943.                                 
$pos[$j++] = $args[$i];
 944.                             }
 945.                         }
 946.                         break;
 947.                     default: 
// Selects every space matching criterion
 948.                         
for ($i $firstpos$i $cnt$i++) {
 949.                             if (
array_key_exists($args[$i], $space)) {
 950.                                 if ((
$space[$args[$i]] == $target) == $trueflag)
 951.                                     
$pos[$j++] = $args[$i];
 952.                             }
 953.                         }
 954.                         break;
 955.                 }
 956.                 if ((!isset(
$starpath[$firstplayer])) && ($p == $lastcaptured))
 957.                     
$starpath[$firstplayer] = array_slice($args2);
 958.                 if (
$keyword == "all") { // Drops piece on all selected spaces
 959.                     
for ($i 0$i $j$i++)
 960.                         
$space[$pos[$i]] = $p;
 961.                     if ((
$j 0) && array_key_exists($j-1$pos))
 962.                         
$dest $pos[$j-1];
 963.                 }
 964.                 elseif (
count($pos) > 0) { // Drops piece on random space from selected spaces
 965.                     
if ($j 2)
 966.                         
$poskey 0;
 967.                     else
 968.                         
$poskey mt_rand(0$j-1);
 969.                     
$dest $pos[$poskey];
 970.                     
$space[$dest] = $p;
 971.                 }
 972.                 break;
 973.             case 
"dump"// Dumps array of all variables to output.
 974.             // Used for debugging.
 975.                 
echo "<PRE CLASS=\"dump\">";
 976.                 if (empty(
$args[1]))
 977.                     echo 
var_dump ($uservar);
 978.                 elseif (
$args[1] == "moves")
 979.                     
print_r ($mline);
 980.                 elseif (
fpdip() && ($args[1] == "globals"))
 981.                     echo 
var_dump($GLOBALS);
 982.                 else
 983.                     echo 
var_dump($args[1]);
 984.                 echo 
"</PRE>";
 985.                 break;
 986.             case 
"echo"// Outputs text to screen. Used for debugging.
 987.                 // if ($submit != "Play") { // Inoperative in play mode to prevent messages from moving board.
 988.                     
if (false and (++$echos 64))
 989.                         
error ("The <b>echo</b> command may not be used more than 64 times in a program."$linenum);
 990.                     echo 
"<P>" stripallslashes(join(" "array_slice($args1))) . "</P>\n";
 991.                 
// }
 992.                 
break;
 993.             case 
"print"// Outputs value of expression to screen. Used for debugging.
 994.                 
if (false and (++$echos 64))
 995.                     
error ("The <b>print</b> command may not be used more than 64 times in a program."$linenum);
 996.                 
$t polish(array_slice($args1),$linenum);
 997.                 if (
is_array($t)) {
 998.                     echo 
"<PRE>";
 999.                     
print_r($t);
1000.                     echo 
"</PRE>";
1001.                 }
1002.                 else
1003.                     echo 
"<P>" $t "</P>";
1004.                 break;
1005.             case 
"printr"// Outputs value of variable to screen. Used for debugging.
1006.                 
if (is_string($args[1]) && (strpos($args[1], " ") === false)) {
1007.                     
$printr = &refvar($args[1]);
1008.                     if (!isset(
$printr))
1009.                         
$printr $args[1];
1010.                 }
1011.                 else
1012.                     
$printr $args[1];
1013.                 echo 
"<PRE>";
1014.                 
print_r ($printr);
1015.                 echo 
"</PRE>";
1016.                 unset (
$printr);
1017.                 break;
1018.             case 
"exchange"// NEEDS DOCUMENTATION
1019.                 
switch ($args[1]) {
1020.                     case 
"hands"// Exchange two hands of cards
1021.                         
$temp_array $hand1;
1022.                         
$hand1 $hand2;
1023.                         
$hand2 $temp_array;
1024.                         if (
$firstplayer
1025.                             
$hand = &$hand1;
1026.                         else
1027.                             
$hand = &$hand2;
1028.                         
$drawncards array_merge($drawncards$hand);
1029.                         break;
1030.                     default: 
// Prisoner exchange for Hostage Chess
1031.                         
if (($o1 findpiece($args[2], $prison[!$firstplayer])) === false)
1032.                             die (
"<P>Cannot find {$args[2]}.</P>");
1033.                         if ((
$o2 findpiece($args[3], $prison[$firstplayer])) === false)
1034.                             die (
"<P>Cannot find {$args[3]}.</P>");
1035.                         if ((
$d1 findpiece("@"$starpath[$firstplayer])) === false)
1036.                             die (
"<P>No vacancy. Your starpath is full.</P>");
1037.                         if ((
$d2 findpiece("@"$starpath[!$firstplayer])) === false)
1038.                             die (
"<P>No vacancy. Opponent's starpath is full.</P>");
1039.                         
$space[$d1] = $space[$o1];
1040.                         
$space[$o1] = "@";
1041.                         
$space[$d2] = $space[$o2];
1042.                         
$space[$o2] = "@";
1043.                         break;
1044.                 }
1045.                 break;                            
1046.             case 
"flip"// Flips the case of the piece label at each position.
1047.             // For a two-player game that represents each side with a different
1048.             // case, this changes the side of each piece.
1049.                 
if (is_array($args[1])) {
1050.                     for (
$i 0$i count($args[1]); $i++) {
1051.                         if (
array_key_exists($args[1][$i], $space))
1052.                             
$space[$args[1][$i]] = flipcase($space[$args[1][$i]]);
1053.                     }
1054.                 }
1055.                 else {
1056.                     for (
$i 1$i $cnt$i++) {
1057.                         if (
array_key_exists($args[$i], $space))
1058.                             
$space[$args[$i]] = flipcase($space[$args[$i]]);
1059.                     }
1060.                 }
1061.                 break;
1062.             case 
"for"// An alias for foreach.
1063.             
case "foreach"// Loops through an array
1064.                 
$scope++;
1065.                 
$sub[$scope] = $subname;
1066.                 
$ifhead[$scope] = "for";
1067.                 
$label[$scope] = $linenum;
1068.                 
$array[$scope] = polish(array_slice($args2),$linenum);
1069.                 if (!
is_array($array[$scope]))
1070.                     
error("The last expression is {$array[$scope]}. In for or foreach, it must evaluate to an array."$linenum);
1071.                 if (
count($array[$scope]) == 0) {
1072.                     
$linenum $links[$linenum];
1073.                     
$scope--;
1074.                 }
1075.                 else {
1076.                     if ((array)
$args[1] === $args[1]) {
1077.                         
$forvar[$scope] = $args[1][1];
1078.                         
$keyvar[$scope] = $args[1][0];
1079.                     }
1080.                     else
1081.                         
$forvar[$scope] =  $args[1];
1082.                     
reset ($array[$scope]);
1083.                     if (isset(
$keyvar[$scope]))
1084.                         
setuservar($keyvar[$scope], key($array[$scope]));
1085.                     
$forval current($array[$scope]);
1086.                     
setuservar($forvar[$scope], $forval);
1087.                     
$condition[$scope] = true;
1088.                 }
1089.                 break;
1090.             case 
"next"// The closing part of a foreach loop
1091.                 
if ($ifhead[$scope] != "for")
1092.                     
error ("Misplaced next"$linenum);
1093.                 if (!
is_array($array[$scope]))
1094.                     
error ("Out of scope next"$linenum);
1095.                 
$forval next($array[$scope]);
1096.                 
// After calling next, the key will not be 0
1097.                 // So only the end of the array should yield an empty value
1098.                 
if (empty(key($array[$scope])))
1099.                     
$scope--;
1100.                 else {
1101.                     if (isset(
$keyvar[$scope]))
1102.                         
setuservar($keyvar[$scope], key($array[$scope]));
1103.                     
setuservar($forvar[$scope], $forval);
1104.                     
$linenum $label[$scope];
1105.                 }
1106.                 break;
1107.             case 
"redo"// Restart a loop without checking any conditions
1108.             
case "continue"// Goto the bottom condition of a loop
1109.                 
for ($oldscope $scope$scope 0$scope--) {
1110.                     if ((
$ifhead[$scope] == "for") || ($ifhead[$scope] == "do"))
1111.                         break;
1112.                 }
1113.                 if ((
$ifhead[$scope] != "for") && ($ifhead[$scope] != "do"))
1114.                     
error ("Misplaced {$args[0]}"$linenum);
1115.                 
unsetlocals ($oldscope$scope);
1116.                 if (
$args[0] == "redo")
1117.                     
$linenum $label[$scope];
1118.                 else
1119.                     
$linenum $links[$label[$scope]] - 1;
1120.                 break;
1121.             case 
"break"// Break out of innermost loop or switch statement
1122.                 
for ($oldscope $scope$scope 0$scope--) {
1123.                     switch (
$ifhead[$scope]) {
1124.                         case 
"for": case "do": case "switch":
1125.                             break 
2;
1126.                     }
1127.                 }
1128.                 if (
$scope == 0)
1129.                     
error ("Misplaced {$args[0]}"$linenum);
1130.                 
$linenum $links[$label[$scope]];
1131.                 if ((
$ifhead[$scope] == "switch") && (isset($links[$linenum])))
1132.                     
$linenum $links[$linenum];
1133.                 
unsetlocals ($oldscope, --$scope);
1134.                 break;
1135.             
// NEEDS DOCUMENATION
1136.             
case "give"// Give listed cards from your hand to other player
1137.                 
if ($firstplayer) {
1138.                     
$hand = &$hand1;
1139.                     
$otherhand = &$hand2;
1140.                 }
1141.                 else {
1142.                     
$hand = &$hand2;
1143.                     
$otherhand = &$hand1;
1144.                 }
1145.                 for (
$i 1$i $cnt$i++) {
1146.                     if (
in_array($args[$i], $hand)) {
1147.                         
$k array_search($args[$i], $hand);
1148.                         
array_push($otherhand$hand[$k]);
1149.                         unset (
$hand[$k]);
1150.                     }
1151.                     else
1152.                         die (
"<P>You can't give away a {$cards[$args[$i]]->alt}, because you don't have one in your hand. Go back and enter a legal move.</P>");
1153.                 }
1154.                 
$hand array_values($hand);
1155.                 break;
1156.             case 
"switch"// A computed goto with blocks of code for different cases
1157.                 
$scope++;
1158.                 
$sub[$scope] = $subname;
1159.                 
$ifhead[$scope] = "switch";
1160.                 
$label[$scope] = $linenum;
1161.                 
$temp polish(array_slice($args1),$linenum);
1162.                 if (isset(
$cases[$linenum][$temp]))
1163.                     
$linenum $cases[$linenum][$temp];
1164.                 elseif (isset(
$cases[$linenum]["default:"]))
1165.                     
$linenum $cases[$linenum]["default:"];
1166.                 else
1167.                     
error ("Missing both default and case \"{$temp}\" in switch"$linenum);
1168.                 break;
1169.             case 
"case"// Identifies a label in a switch statement
1170.             
case "default"// Identifies the code a switch statement runs by default when 
1171.             // there are no matching cases.
1172.                 
break;
1173.             case 
"endswitch"// The end of a switch statement
1174.                 
if ($ifhead[$scope] != "switch")
1175.                     
error ("Misplaced <b>{$args[0]}</b>."$linenum);
1176.                 
unsetlocals ($scope, --$scope);
1177.                 break;
1178.             case 
"sub"// Indicates the start of a subroutine definition
1179.                 
if (empty($args[1]))
1180.                     
error ("Every subroutine requires a name."$linenum);
1181.                 if (
in_array($args[1], $reserved))
1182.                     
error ("The name of <b>$args[1]</b> is a reserved keyword. It cannot be used as a subroutine name."$linenum);
1183.                 if (isset(
$space[$args[1]]))
1184.                     
error ("No subroutine may bear the same name as a coordinate."$linenum);
1185.                 if (
ctype_digit($args[1][0]))
1186.                     
error ("No subroutine name may begin with a digit."$linenum);
1187.                 
$label[$args[1]] = $linenum;
1188.                 if (!isset(
$links[$linenum]))
1189.                     
error ("Unknown error concerning the definition of subroutine {$args[1]}."$linenum);
1190.                 
$linenum $links[$linenum];
1191.                 break;
1192.             case 
"endsub"// Indicates the end of a subroutine definition
1193.                 
if ($ifhead[$scope] == "sub")
1194.                     
unsetlocals ($scope, --$scope);
1195.                 else
1196.                     
error ("Misplaced endsub."$linenum);
1197.                 return 
NULL;
1198.                 break;
1199.             case 
"gosub"// Goes to the named subroutine
1200.                 
$gosub $args[1];
1201.                 
$subargs array_slice($args2);
1202.                 if (!isset(
$label[$gosub]))
1203.                     
error ("gosub goes to unknown subroutine {$gosub}"$linenum);
1204.                 
setuservar("RESULT"runsubroutine ($gosub$subargs$linenum));
1205.                 if (!empty(
$exit))
1206.                     return;
1207.                 break;
1208.             case 
"moveindex"// NEEDS DOCUMENTATION. ADDED AUTOMATICALLY BETWEEN MOVES.
1209.                 
$mln $args[1]; // Sets index value for array of moves
1210.                 
$firstplayer = (($mline[$mln]->movenum $sidecnt) == 1);
1211.                 
// $firstplayer = !$firstplayer; // Switches player
1212.                 // Something to do with cards. No effect on most games.
1213.                 
if ($firstplayer)
1214.                     
$playedcards1 = array();
1215.                 else
1216.                     
$playedcards2 = array();
1217.                 
$drawncards = array();
1218.                 
$movecnt 0// Resets $movecnt
1219.                 
$message "";
1220.                 
$posdata[$moveindex] = array();
1221.                 if (
$moveindex == 0) {
1222.                     
$prevpos $posdata[$moveindex]["space"] = aliasedarray($space);
1223.                 }
1224.                 else {
1225.                     
$thispos aliasedarray($space);
1226.                     
$posdata[$moveindex]["space"] = array_diff_assoc($thispos$prevpos);
1227.                     
$prevpos $thispos;
1228.                 }
1229.                 if (isset(
$capturedpieces))
1230.                     
$posdata[$moveindex]["captured"] = $capturedpieces;
1231.                 if ((
$moveindex == 0) || ($posdata[0]["background"] != $background))
1232.                     
$posdata[$moveindex]["background"] = $background;
1233.                 if (
$moveindex 0) {
1234.                     
$posdata[$moveindex]["dest"] = $dest;
1235.                     
$posdata[$moveindex]["origin"] = $origin;
1236.                 }
1237.                 
$moveindex++;
1238.                 break;
1239.             case 
"endlib"// Indicates end of code from include file
1240.                 
if ($scope != 0)
1241.                     
error ("Misplaced endlib."$linenum);
1242.                 
$linenum array_pop($returns);
1243.                 break;
1244.             case 
"return"// Returns execution from a subroutine to where it left off
1245.             // in the previous scope, returning any value of the expression as the value
1246.             // of the subroutine call.
1247.                 
if ($subscope == 0)
1248.                     
error ("Misplaced return."$linenum);
1249.                 
$retval polish(array_slice($args1),$linenum);
1250.                 
unsetlocals ($scope$scope = ($subscope 1));
1251.                 return 
$retval;
1252.                 break;
1253.             case 
"do"// Starts a loop. May include a while or until condition.
1254.                 
$scope++;
1255.                 
$sub[$scope] = $subname;
1256.                 
$ifhead[$scope] = "do";
1257.                 if (empty(
$args[1]))
1258.                     
$condition[$scope] = true;
1259.                 elseif (
$args[1] == "while")
1260.                     
$condition[$scope] = polish(array_slice($args2),$linenum);
1261.                 elseif (
$args[1] == "until")
1262.                     
$condition[$scope] = !polish(array_slice($args2),$linenum);
1263.                 else
1264.                     
$condition[$scope] = true;
1265.                 
$label[$scope] = $linenum;
1266.                 if (!
$condition[$scope]) {
1267.                     
$linenum $links[$linenum];
1268.                     
unsetlocals ($scope, --$scope);
1269.                 }
1270.                 break;
1271.             case 
"loop"// Ends a loop. May include a while, until, or never condition.
1272.                 
if ($ifhead[$scope] != "do")
1273.                     
error ("Misplaced loop within scope of {$ifhead[$scope]} at scope $scope."$linenum);
1274.                 if (empty(
$args[1]))
1275.                     
$condition[$scope] = true;
1276.                 elseif (
$args[1] == "while")
1277.                     
$condition[$scope] = polish(array_slice($args2),$linenum);
1278.                 elseif (
$args[1] == "until")
1279.                     
$condition[$scope] = !polish(array_slice($args2),$linenum);
1280.                 elseif (
$args[1] == "never")
1281.                     
$condition[$scope] = false;
1282.                 else
1283.                     
$condition[$scope] = true;
1284.                 if (
$condition[$scope])
1285.                     
$linenum $label[$scope] - 1;
1286.                 else
1287.                     
unsetlocals ($scope$scope-1);
1288.                 
$scope--;
1289.                 break;
1290.             case 
"if"// Executes code in its block if condition is true.
1291.             // May start an if-block series, consisting of 
1292.             // one if, multiple endifs, and one else.
1293.                 
$scope++;
1294.                 
$sub[$scope] = $subname;
1295.                 
$ifhead[$scope] = "if";
1296.                 
$condition[$scope] = false// Pseudo-previous condition
1297.             
case "elseif"// Indicates code to run when no prior if or endif
1298.             // was true but its own condition is true.
1299.                 
if ($condition[$scope] == false) {
1300.                     
$condition[$scope] = polish(array_slice($args1),$linenum);
1301.                     if (!
$condition[$scope]) {
1302.                         
$linenum $links[$linenum] - 1;
1303.                     }
1304.                 }
1305.                 else {
1306.                     do {
1307.                         
$linenum $links[$linenum];
1308.                     } while (isset(
$links[$linenum]));
1309.                     
$linenum--;
1310.                 }
1311.                 break;
1312.             case 
"else"// Indicates code to run when the if-condition and any
1313.             // prior elseif conditions were all false
1314.                 
if (empty($ifhead[$scope]) || ($ifhead[$scope] != "if")) {
1315.                     
$ifscp $ifhead[$scope] ?? "";
1316.                     
error ("Misplaced <b>else</b> within {$ifscp} scope {$scope}."$linenum);
1317.                 }
1318.                 if (
$condition[$scope] == true) {
1319.                     
$linenum = ($links[$linenum] ?? 0) - 1;
1320.                 }
1321.                 break;
1322.             case 
"endif"// Marks end of if-block series.
1323.             // case "endifs": REMOVED ALIAS
1324.                 
if (empty($ifhead[$scope]) || ($ifhead[$scope] != "if")) {
1325.                     
print_r($ifhead);
1326.                     
print_r($scope);
1327.                     
$ifscp $ifhead[$scope] ?? "";
1328.                     
error ("Misplaced <b>{$args[0]}</b> within {$ifscp} scope {$scope}."$linenum);
1329.                 }
1330.                 
unsetlocals ($scope, --$scope);
1331.                 break;
1332.             case 
"verify"// Returns value of false from subroutine unless condition is true
1333.                 
$condition[$scope] = polish(array_slice($args1),$linenum);
1334.                 if (!
$condition[$scope]) {
1335.                     
unsetlocals ($scope$scope = ($subscope 1));
1336.                     return 
false;
1337.                 }
1338.                 break;
1339.             case 
"inc"// Increments integer variable by one
1340.                 
$temp = &refvar($args[1]);
1341.                 
$temp++;
1342.                 unset (
$temp);
1343.                 break;
1344.             case 
"include"// Places code from include file after end of program,
1345.             // runs it, and returns execution to next line after include.
1346.                 
if (!empty($args[2]) && ($args[2] == "if") && !polish(array_slice($args3),$linenum))
1347.                     break;
1348.                 if (
$ifhead[$scope] != "main") {
1349.                     
printf ("<P>ifhead[$scope] is {$ifhead[$scope]}</P>");
1350.                     
error ("The <b>include</b> command may not be used except at the main level."$linenum);
1351.                 }
1352.                 if (
ctype_digit($args[1][0]))
1353.                     
error ("No include file may have a name beginning with a digit."$linenum);
1354.                 if (
array_search($args[1], $includes))
1355.                     break;
1356.                 
array_push ($includes$args[1]);
1357.                 if (
substr($args[1], -4) != ".txt")
1358.                     
$fname $args[1] . ".txt";
1359.                 if (
$args[1][0] == "/")
1360.                     
$fname CVP_ROOT $args[1];
1361.                 else
1362.                     
$fname "includes/{$fname}";
1363.                 if (
$fc file_get_contents($fname)) {
1364.                     
array_push ($returns$linenum);
1365.                     
$linenum $maxlines;
1366.                     
$fc "lib {$args[1]};" stripcomments($fc) . ";endlib;";
1367.                     
$newlines parseprog($fc);
1368.                     foreach (
$newlines as $nl) {
1369.                         if (!empty(
$nl))
1370.                             
$codelines[] = $nl;
1371.                     }                    
1372.                     
$maxlines count($codelines);
1373.                     
setlinks ($linenum);
1374.                 }
1375.                 else
1376.                     die (
"<P><B>Game Courier Error</B>: Could not include {$fname}</P>");
1377.                 break;
1378.             
/* case "kamikaze": // REMOVED
1379.                 if ($lastcaptured != "@")
1380.                     if ((empty($args[1]) || ($space[$dest]) == $args[1]))
1381.                         $space[$dest] = "@";
1382.                 break; */
1383.             
case "list"// Lists the program
1384.                 
listprog();
1385.                 break;                
1386.             case 
"load"// Loads named deck of cards from server
1387.                 
if ($args[1] == "cards") {
1388.                     
$include_file "cards/" $args[2] . ".php";
1389.                     if (
1) {
1390.                         include_once (
$include_file);
1391.                     }
1392.                 }
1393.                 break;
1394.             case 
"local"// Identifies a new variable as a dynamically indexed local variable
1395.                 
for ($i 1$i $cnt$i++)
1396.                     if (!isset(
$uservar[$scope]["main"][$args[$i]]))
1397.                         
$uservar[$scope]["main"][$args[$i]] = 0;
1398.                 break;
1399.             case 
"my"// Identifies a new variable as both dynamically and lexically 
1400.             // indexed. Such a variable exists only in a single subroutine call.
1401.                 
for ($i 1$i $cnt$i++)
1402.                     if (!isset(
$uservar[$scope][$sub[$scope]][$args[$i]]))
1403.                         
$uservar[$scope][$sub[$scope]][$args[$i]] = 0;
1404.                 break;
1405.             case 
"static"// Identifies variable as a lexically indexed variable that 
1406.             // retains its value between subroutine calls.
1407.                 
if (!isset($uservar[0][$sub[$scope]][$args[1]]))
1408.                     
$uservar[0][$sub[$scope]][$args[1]] = polish(array_slice($args2),$linenum);
1409.                 break;
1410.             case 
"map"// Maps new logical direction(s) from existing relationships
1411.             // between coordinates
1412.                 
$rcnt count($rank);
1413.                 
$fcnt count($file);
1414.                 if (
is_numeric($args[2])) {
1415.                     for (
$i 1$i $cnt$i+=3) {
1416.                         
$direction $args[$i];
1417.                         
$y $args[$i+1];
1418.                         
$x $args[$i+2];
1419.                         for (
$r 0$r $rcnt$r++) {
1420.                             
$rl $rank[$r];
1421.                             if (isset(
$rank[$r $x])) {
1422.                                 
$nr $rank[$r $x];
1423.                                 for (
$f 0$f $fcnt$f++) {
1424.                                     
$c $file[$f] . $rl;
1425.                                     if (isset(
$file[$f $y])) {
1426.                                         
$n $file[$f $y] . $nr;
1427.                                         if (isset(
$space[$n]) && ($space[$n] != '-'))
1428.                                             
$map[$c][$direction] = $n;
1429.                                     }
1430.                                 }
1431.                             }
1432.                         }
1433.                     }
1434.                 }
1435.                 elseif (
is_array($args[2])) {
1436.                     for (
$i 1$i $cnt$i+=2) {
1437.                         
$direction $args[$i];
1438.                         
$directions $args[$i+1];
1439.                         
$jcnt count($directions);
1440.                         foreach (
$space as $c => $discard) {
1441.                             
$n $c;
1442.                             for (
$j 0$j $jcnt$j++) {
1443.                                 if (empty(
$map[$n]) || empty($map[$n][$directions[$j]])) {
1444.                                     
$n "";
1445.                                     break;
1446.                                 }
1447.                                 
$n $map[$n][$directions[$j]];
1448.                             }
1449.                             if (!empty(
$space[$n]) && ($space[$n] != '-'))
1450.                                 
$map[$c][$direction] = $n;
1451.                         }
1452.                     }
1453.                 }
1454.                 else {
1455.                     
$direction $args[1];
1456.                     for (
$r 0$r $rcnt$r++) {
1457.                         
$rl $rank[$r];
1458.                         
$nr $rank[$r $x];
1459.                         for (
$f 0$f $fcnt$f++) {
1460.                             
$c $n $file[$f] . $rl;
1461.                             for (
$i 2$i $cnt$i++) {
1462.                                 
$n $map[$n][$args[$i]];
1463.                                 if (empty(
$n))
1464.                                     break 
2;
1465.                             }
1466.                             if (isset(
$space[$n]) && ($space[$n] != '-'))
1467.                                 
$map[$c][$direction] = $n;
1468.                         }
1469.                     }
1470.                 }                    
1471.                 break;
1472.             case 
"link"// Adds individual links from one space to another to the map
1473.             // for a specific logical direction.
1474.                 
$direction $args[1];
1475.                 for (
$i 2$i $cnt$i++) {
1476.                     if (!
is_array($args[$i]))
1477.                         
error ("<P>Argument {$i}{$args[$i]}, in link is not an array.</P>"$linenum);
1478.                     
$subcnt count($args[$i]) - 1;
1479.                     for (
$j 0$j $subcnt$j++) {
1480.                         
$map[$args[$i][$j]][$direction] = $args[$i][$j+1];
1481.                     }
1482.                 }
1483.                 
/*
1484.                 echo "<PRE>";
1485.                 print_r($map);
1486.                 echo "</PRE>";
1487.                 */
1488.                 
break;
1489.             case 
"rlink"// Adds individual links from one space to another to the map
1490.             // for a specific logical direction.
1491.                 
$direction $args[1];
1492.                 for (
$i 2$i $cnt$i++) {
1493.                     if (!
is_array($args[$i]))
1494.                         
error ("<P>Argument {$i}{$args[$i]}, in rlink is not an array.</P>"$linenum);
1495.                     
$subcnt count($args[$i]) - 1;
1496.                     for (
$j 0$j $subcnt$j++) {
1497.                         
$map[$args[$i][$j+1]][$direction] = $args[$i][$j];
1498.                     }
1499.                 }
1500.                 break;
1501.             case 
"unlink"// CONTINUE;
1502.             // Unlinks specific pairings of coordinates from map for specific direction. 
1503.                 // map[from][dir] = to;
1504.                 // loop through arguments
1505.                 
if (is_array($args[1]) || array_key_exists($args[1], $space) || (strpos("*"$args[1]) !== false)) {
1506.                     for (
$i 1$i $cnt$i++) {
1507.                         
// When coordinates are grouped together in an array, unlink them from each other
1508.                         
$ai $args[$i];
1509.                         if (empty(
$ai))
1510.                             continue;
1511.                         if (
is_array($ai) && (count($ai) > 0)) {
1512.                             
$temp $ai;
1513.                             foreach (
$ai as $f1) {
1514.                                 if (!
is_array($f1) && !ctype_alnum($f1))
1515.                                     
// $f1 = array_filter(array_keys($map), create_function('$v', "return fnmatch(\"$f1\",\$v);"));
1516.                                     
$f1 array_filter(array_keys($map), function($v) use ($f1) {return fnmatch($f1,$v);});
1517.                                 
// When one array is nested within another, unlink the coordinates in the nested 
1518.                                 // array from whatever else is in the first array, but not from each other.
1519.                                 
if (is_array($f1)) {
1520.                                     foreach (
$f1 as $f2) {
1521.                                         if (!
ctype_alnum($f2))
1522.                                             
// $ra = array_filter(array_keys($map), create_function('$v', "return fnmatch(\"$f2\",\$v);"));
1523.                                             
$ra array_filter(array_keys($map), function($v) use ($f2) {return fnmatch($f2,$v);});
1524.                                         else
1525.                                             
$ra = array($f2);
1526.                                         foreach (
$ra as $f3) {
1527.                                             
reset ($map[$f3]);
1528.                                             foreach (
$map[$f3] as $d => $to) {
1529.                                                 
reset ($temp);
1530.                                                 foreach (
$temp as $v1) {
1531.                                                     if (!
is_array($v1) && !ctype_alnum($v1))
1532.                                                         
// $v1 = array_filter(array_keys($map), create_function('$v', "return fnmatch(\"$v1\",\$v);"));
1533.                                                         
$v1 array_filter(array_keys($map), function($v) use ($v1) {return fnmatch($v1,$v);});
1534.                                                     if (
is_array($v1)) {
1535.                                                         if (
$v1 == $f1)
1536.                                                             continue;
1537.                                                         foreach (
$v1 as $v2) {
1538.                                                             if ((
$f3 != $v2) && fnmatch($v2,$to))
1539.                                                                 unset (
$map[$f3][$d]);
1540.                                                         }
1541.                                                     }
1542.                                                     elseif (
fnmatch($v1,$to))
1543.                                                         unset (
$map[$f3][$d]);
1544.                                                 }                                    
1545.                                             }
1546.                                         }
1547.                                     }
1548.                                 }
1549.                                 
// Simple element appears in first array.
1550.                                 
else {
1551.                                     
reset ($map[$f1]);
1552.                                     foreach (
$map[$f1] as $d => $to) {
1553.                                         
reset ($temp);
1554.                                         foreach (
$temp as $v1) {
1555.                                             if (
is_array($v1)) {
1556.                                                 foreach (
$v1 as $v2) {
1557.                                                     if (
fnmatch($v2,$to))
1558.                                                         unset (
$map[$f1][$d]);
1559.                                                 }
1560.                                             }
1561.                                             elseif (
fnmatch($v1,$to))
1562.                                                 unset (
$map[$f1][$d]);
1563.                                         }
1564.                                     }
1565.                                 }
1566.                             }
1567.                         }
1568.                         
// when a single coordinate appears, unlink it from everything
1569.                         
elseif (!is_array($ai) && (isset($space[$ai]) || array_key_exists($ai$space)))
1570.                             
unlink_all ($ai);
1571.                         elseif (!
is_array($ai) && !ctype_alnum($ai)) {
1572.                             
// $ai = array_filter(array_keys($map), create_function('$v', "return fnmatch(\"$ai\",\$v);"));
1573.                             
$ai array_filter(array_keys($map), function($v) use ($ai) {return fnmatch($ai,$v);});
1574.                             foreach (
$ai as $val)
1575.                                 
unlink_all ($val);
1576.                         }
1577.                     }
1578.                 }
1579.                 else {
1580.                     
$direction $args[1];
1581.                     for (
$i 2$i $cnt$i++) {
1582.                         
$ai $args[$i];
1583.                         if (!
is_array($ai)) {
1584.                             if (
array_key_exists($ai$map)) {
1585.                                 if (isset(
$map[$ai][$direction])) {
1586.                                     unset (
$map[$ai][$direction]);
1587.                                 }
1588.                             }
1589.                             elseif (
strpos("*"$ai) !== false) {
1590.                                 foreach (
$map as $key => $val) {
1591.                                     if (
fnmatch ($ai$key) && ($val == $direction)) {
1592.                                         unset (
$map[$key][$val]);
1593.                                     }
1594.                                 }
1595.                             }
1596.                             else {
1597.                                 
$direction $ai;
1598.                             }
1599.                         }
1600.                     }
1601.                 }
1602.                 break;
1603.             case 
"move"// Moves piece from one space to another
1604.                 
if ($args[1] != $args[2]) {
1605.                     if (!
array_key_exists($args[1], $space)) {
1606.                         
printf ("<P>\count is %s</P>"count($args));
1607.                         
fpdebug2("args"$args);
1608.                         
error ("The first argument to the <B>move</B> command, {$args[1]}, is not a recognized coordinate."$linenum);
1609.                     }
1610.                     if (!empty(
$args[2])) {
1611.                         
$space[$args[2]] = $space[$args[1]];
1612.                         
// $flag[$args[2]] = $flag[$args[1]];
1613.                     
}
1614.                     
$space[$args[1]] = "@";
1615.                     
// $flag[$args[1]] = false;
1616.                 
}
1617.                 break;
1618.             case 
"pass"// Pass turn
1619.             
case "skip"// Skip expected portion of move, such as promotion,
1620.             // showing that a move is not incomplete as is.
1621.                 
break;
1622.             case 
"place"// for playing continuing effect cards
1623.                 
if ($firstplayer)
1624.                     
$hand = &$hand1;
1625.                 else
1626.                     
$hand = &$hand2;
1627.                 for (
$i 1$i $cnt$i++) {
1628.                     
$k array_search($args[$i], $hand);
1629.                     if (
in_array($args[$i], $hand)) {
1630.                         
array_push($displayedcards$hand[$k]);
1631.                         unset (
$hand[$k]);
1632.                     }
1633.                 }
1634.                 
$hand array_values($hand);
1635.                 break; 
1636.             case 
"play"// Play cards from hand
1637.             // Displays cards to opponent and moves them to discard pile
1638.                 
if ($firstplayer) {
1639.                     
$hand = &$hand1;
1640.                     
$playedcards = &$playedcards1;
1641.                 }
1642.                 else {
1643.                     
$hand = &$hand2;
1644.                     
$playedcards = &$playedcards2;
1645.                 }
1646.                 for (
$i 1$i $cnt$i++) {
1647.                     
$k array_search($args[$i], $hand);
1648.                     if (
in_array($args[$i], $hand)) {
1649.                         
array_push($discardpile$hand[$k]);
1650.                         
array_push($playedcards$hand[$k]);
1651.                         unset (
$hand[$k]);
1652.                     }
1653.                     else
1654.                         die (
"<P>You can't play a {$cards[$args[$i]]->alt}, because you don't have one in your hand. Go back and enter a legal move.</P>");
1655.                 }
1656.                 
$hand array_values($hand);
1657.                 break;
1658.             case 
"pop"// Pops off last value of array and copies it to variable.
1659.                 
$temp = &refvar($args[1]);
1660.                 
setuservar($args[2], array_pop($temp));
1661.                 unset(
$temp);
1662.                 break;
1663.             case 
"push"// Pushes value of expression to end of array.
1664.                 
$temp = &refvar($args[1]);
1665.                 if (isset(
$temp) && (!is_array($temp)))
1666.                     
$temp = array($temp);
1667.                 
$temp[] = polish(array_slice($args2),$linenum);
1668.                 unset(
$temp);
1669.                 
// pushuservar($args[1], polish(array_slice($args, 2),$linenum));
1670.                 
break;
1671.             
// "pushall" NEEDS DOCUMENTATION
1672.             
case "pushall"// Pushes all listed values to end of array in sequence
1673.                 
$temp = &refvar($args[1]);
1674.                 for (
$i 2$i $cnt$i++)
1675.                     
$temp[] = $args[$i];
1676.                 unset(
$temp);
1677.                 break;
1678.             
// "stopwatch" NEEDS DOCUMENTATION
1679.             
case "stopwatch"// Used to time code. Useful for optimizing.
1680.                 
if (array_key_exists(1$args) && ($args[1] == "reset")) { // Starts stopwatch
1681.                     
$watchstart microtime(true);
1682.                 }
1683.                 else { 
// Outputs time passed
1684.                     
$watchtime microtime(true) - $watchstart;
1685.                     echo 
"<P>Elapsed time: {$watchtime} seconds</P>";
1686.                 }
1687.                 break;
1688.             case 
"reserve"// Place pieces in reserve area, used by games like Chessgi and Shogi.
1689.                 
echo "<PRE>";
1690.                 
print_r ($args);
1691.                 if ((
$args[1] == "left") || ($args[1] == "second")) {
1692.                     
$stpath $starpath[false];
1693.                     
$start 2;
1694.                 }
1695.                 elseif ((
$args[1] == "right") || ($args[1] == "first")) {
1696.                     
$stpath $starpath[true];
1697.                     
$start 2;
1698.                 }
1699.                 else {
1700.                     
$stpath $starpath[true];
1701.                     
$start 1;
1702.                 }
1703.                 echo 
"{$start}<BR>";
1704.                 echo 
"{$cnt}<BR>";
1705.                 for (
$i $start$i $cnt$i++) {
1706.                     echo 
$args[$i];
1707.                     
$jcnt 1;
1708.                     while (
is_numeric($args[$i])) {
1709.                         echo 
"<P>$i is numeric.</P>";
1710.                         
$jcnt $args[$i];
1711.                         
$i++;
1712.                     }
1713.                     if (
$args[$i] == "")
1714.                         continue;
1715.                     for (
$j 0$j $jcnt$j++) {
1716.                         foreach (
$stpath as $k => $v) {
1717.                             if (
$space[$v] == "@") {
1718.                                 echo 
"<P>{$args[$i]} on $v</P>";
1719.                                 
$space[$v] = $args[$i];
1720.                                 break;
1721.                             }
1722.                         }
1723.                     }
1724.                 }
1725.                 echo 
"</PRE>";
1726.                 break;
1727.             case 
"resign"// User command to resign from game
1728.             
case "resigned"// Alias for resign
1729.             
case "resigns"// Alias for resign
1730.                 
if (!$gameover || ($submit != "Fix")) {
1731.                     if ((
$submit == "Move") || ($submit == "Play")) {
1732.                         
$GLOBALS["winner"] = ($side == $turnorder[0]) ? $turnorder[0] : $turnorder[1];
1733.                         
$GLOBALS["status"] = sprintf("%s has won."$GLOBALS["winner"]);
1734.                         
$loser = ($winner == $turnorder[1]) ? $turnorder[0] : $turnorder[1];
1735.                         
$losername userid_name($loser);
1736.                         if (empty(
$losername))
1737.                             
$losername $loser;
1738.                         
$message "{$losername} has resigned.";
1739.                     }
1740.                     elseif (empty(
$player) || empty($opponent)) {
1741.                         
$GLOBALS["winner"] = ($side == $turnorder[0]) ? $turnorder[0] : $turnorder[1];
1742.                         
$GLOBALS["status"] = sprintf("%s has won."$GLOBALS["winner"]);
1743.                         
$loser = ($winner == $turnorder[1]) ? $turnorder[0] : $turnorder[1];
1744.                         
$message "{$loser} has resigned.";
1745.                     }
1746.                     else {
1747.                         if ((
$submit == "Preview") || ($submit == "Send")) {
1748.                             
$GLOBALS["winner"] = $opponent;
1749.                             
$GLOBALS["status"] = sprintf("%s has won."userid_name($winner));
1750.                         }
1751.                         elseif (!empty(
$players)) {
1752.                             
$ps explode(" "$players);
1753.                             
$winner = ($mline[$mln]->movenum 1) ? $ps[1] : $ps[0];
1754.                         }
1755.                         elseif ((
$mline[$mln]->movenum 1) == ($movenum 1)) {
1756.                             
// Last player to move in entire game was the same as the player of this move,
1757.                             // and $player and $opponent values were swapped after completion of move.
1758.                             
$winner $player;
1759.                         }
1760.                         else {
1761.                             
// Last player to move in entire game was not the same as the player of this move,
1762.                             // and $player and $opponent values were swapped after completion of move.
1763.                             
$winner $opponent;
1764.                         }
1765.                         
$GLOBALS["status"] = sprintf("%s has won."userid_name($winner));
1766.                         
$loser = ($winner == $player) ? $opponent $player;
1767.                         
$losername userid_name($loser);
1768.                         if (empty(
$losername))
1769.                             
$losername $loser;
1770.                         
$message "{$losername} has resigned.";
1771.                     }
1772.                 }
1773.                 
$lastcaptured $lastmoved $dest $origin $prevcaptured $prevmoved $prevorigin $prevdest "";
1774.                 
$gameover $exit true;
1775.                 return;
1776.                 break;
1777.             case 
"lost"// Program command to indicate the current player has lost
1778.                 
if (($submit == "Move") || ($submit == "Play")) {
1779.                     
$GLOBALS["winner"] = ($side == $turnorder[0]) ? $turnorder[0] : $turnorder[1];
1780.                     
$GLOBALS["status"] = sprintf("%s has won."$GLOBALS["winner"]);
1781.                 }
1782.                 else {
1783.                     if ((
$submit == "Preview") || ($submit == "Send")) {
1784.                         
$GLOBALS["winner"] = $opponent;
1785.                         
$GLOBALS["status"] = sprintf("%s has won."userid_name($winner));
1786.                     }
1787.                     elseif (!empty(
$players)) {
1788.                         
$ps explode(" "$players);
1789.                         
$winner = ($mline[$mln]->movenum 1) ? $ps[1] : $ps[0];
1790.                     }
1791.                     elseif ((
$mline[$mln]->movenum 1) == ($movenum 1)) {
1792.                         
// Last player to move in entire game was the same as the player of this move,
1793.                         // and $player and $opponent values were swapped after completion of move.
1794.                         
$winner $player;
1795.                     }
1796.                     else {
1797.                         
// Last player to move in entire game was not the same as the player of this move,
1798.                         // and $player and $opponent values were swapped after completion of move.
1799.                         
$winner $opponent;
1800.                     }
1801.                     
$GLOBALS["status"] = sprintf("%s has won."userid_name($winner));
1802.                 }
1803.                 
$gameover $exit true;
1804.                 return;
1805.                 break;
1806.             case 
"won"// Indicates that current player has won
1807.                 
if (($submit == "Move") || ($submit == "Play") || empty($GLOBALS["log"])) {
1808.                     
$GLOBALS["winner"] = ($side != $turnorder[0]) ? $turnorder[0] : $turnorder[1];
1809.                     
$GLOBALS["status"] = sprintf("%s has won."$GLOBALS["winner"]);
1810.                 }
1811.                 else {
1812.                     if ((
$submit == "Preview") || ($submit == "Send")) {
1813.                         
$GLOBALS["winner"] = $player;
1814.                         
$GLOBALS["status"] = sprintf("%s has won."userid_name($winner));
1815.                     }
1816.                     elseif (!empty(
$players)) {
1817.                         
$ps explode(" "$players);
1818.                         
$winner = ($mline[$mln]->movenum 1) ? $ps[0] : $ps[1];
1819.                     }
1820.                     elseif (!empty(
$mline) && (($mline[$mln]->movenum 1) == ($movenum 1))) {
1821.                         
// Last player to move in entire game was the same as the player of this move,
1822.                         // and $player and $opponent values were swapped after completion of move.
1823.                         
$winner $opponent;
1824.                     }
1825.                     else {
1826.                         
// Last player to move in entire game was not the same as the player of this move,
1827.                         // and $player and $opponent values were swapped after completion of move.
1828.                         
$winner $player;
1829.                     }
1830.                     
$GLOBALS["status"] = sprintf("%s has won."userid_name($winner));
1831.                 }
1832.                 
$gameover $exit true;
1833.                 return;
1834.                 break;
1835.             case 
"drawn"// Indicates that the game has ended in a draw
1836.                 
if (empty($submit) || ($submit == "Preview") || ($submit == "Send") || ($submit == "View") || ($submit == "Move")) {
1837.                     
$GLOBALS["status"] = "Drawn game.";
1838.                     
$GLOBALS["winner"] = "";
1839.                     if (empty(
$GLOBALS["message"]))
1840.                         
$GLOBALS["message"] = "The game is declared drawn.";
1841.                 }
1842.                 
$gameover $exit true;
1843.                 return;
1844.                 break;
1845.             case 
"recolor"// Changes color index of space(s) on board
1846.                 
$nc polish(array_slice($args2),$linenum);
1847.                 if (
is_array($args[1])) {
1848.                     foreach (
$args[1] as $val)
1849.                         
$background[$val] = $nc;
1850.                 }
1851.                 else
1852.                     
$background[$args[1]] = $nc;
1853.                 break;
1854.             case 
"reverse"// Reverses the order of the content of the listed coordinates
1855.                 
$halfway ceil($cnt/2);
1856.                 for (
$i 1$i $halfway$i++) {
1857.                     
$temp $space[$args[$i]];
1858.                     
$space[$args[$i]] = $space[$args[$cnt $i]];
1859.                     
$space[$args[$cnt $i]] = $temp;
1860.                 }
1861.                 break;
1862.             case 
"rotate"// Moves each piece in list of coordinates to next position,
1863.             // and piece at last position to first position.
1864.                 
if ($cnt 2) {
1865.                     
$temp $space[$args[$cnt-1]];
1866.                     for (
$i $cnt-1$i 1$i--)
1867.                         
$space[$args[$i]] = $space[$args[$i-1]];
1868.                     
$space[$args[1]] = $temp;
1869.                 }
1870.                 break;
1871.             case 
"set"// Sets a named variable to value of expression
1872.                 
if ($args[1] == "many") {
1873.                     for (
$i 2$i $cnt$i += 2) {
1874.                         if (
ctype_digit($args[$i][0]))
1875.                             
error ("A variable name should not begin with a digit."$linenum);
1876.                         if (
array_key_exists($i+1$args))
1877.                             
setuservar($args[$i], $args[$i+1]);
1878.                         else
1879.                             
error ("set many should be followed by an even number of arguments. No argument has been given for the variable called {$args[$i]}. If you were trying to use 'set many' with an expression, you can enclose it in {braces} or set it on its own line."$linenum);
1880.                     }
1881.                 }
1882.                 elseif (empty(
$args[1])) {
1883.                     
error ("A variable name should not be empty."$linenum);
1884.                 }
1885.                 elseif (
ctype_digit($args[1][0] ?? ""))
1886.                     
error ("A variable name should not begin with a digit."$linenum);
1887.                 else {
1888.                     
setuservar($args[1], polish(array_slice($args2),$linenum));
1889.                 }
1890.                 break;
1891.             case 
"setjsvar"// Passes value from GAME Code to a JavaScript variable
1892.                 
$jsvar[$args[1]] = polish(array_slice($args2),$linenum);
1893.                 break;
1894.             case 
"setlegal"// Records indicated move(s) to $legalmoves array,
1895.             // which will be passed to the JavaScript legalMoves array.
1896.                 
if (empty($legalmoves))
1897.                     
$legalmoves = array();
1898.                 if (
is_array($args[1])) {
1899.                     for (
$i 1$i $cnt$i++) {
1900.                         if (
is_array($args[$i])) {
1901.                             if (
count($args[$i]) < 2) {
1902.                                 
print_r($args[$i]);
1903.                                 
error("setlegal: Array should include at least two coordinates."$linenum);
1904.                             }
1905.                             
$lm compose_move($args[$i]);
1906.                             if (!
in_array($lm$legalmoves))
1907.                                 
$legalmoves[] = $lm;
1908.                         }
1909.                         else {
1910.                             
badinput("setlegal: {$args[$i]} was expected to be an array, but it is not.");
1911.                         }
1912.                     }
1913.                 }
1914.                 elseif (
strpos(trim($args[1]), " ") || (strpos($args[1], "-") !== false) || strpos($args[1], "*")) {
1915.                     for (
$i 1$i $cnt$i++) {
1916.                         if (
valid_move($args[$i]))
1917.                             
$legalmoves[] = $args[$i];
1918.                     }
1919.                 }
1920.                 else {
1921.                     
$k 1;
1922.                     while (
$k $cnt) {
1923.                         if (!
$space[$args[$k]] && !$pieces[$args[$k]] && ($args[$k] != "@")) {
1924.                             
print_r ($space);
1925.                             
badinput ("setlegal: {$args[$k]} is not a valid piece or coordinate.");
1926.                         }
1927.                         for (
$i $k+1$i $cnt$i++) {
1928.                             if ((array)
$args[$i] === $args[$i]) {
1929.                                 
$temp polish($args[$i],$linenum);
1930.                                 if ((array)
$temp == $temp) {
1931.                                     
$tcnt count($temp);
1932.                                     for (
$j 0$j $tcnt$j++) {
1933.                                         if (!
$space[$temp[$j]])
1934.                                             
badinput ("{$temp[$j]} is not a valid coordinate.");
1935.                                         
$lm compose_move($args[$k], $temp[$j]);
1936.                                         if (!
in_array($lm$legalmoves))
1937.                                             
$legalmoves[] = $lm;
1938.                                     }
1939.                                 }
1940.                                 else {
1941.                                     
$lm compose_move($args[$k], $temp);
1942.                                     if (!
in_array($lm$legalmoves))
1943.                                         
$legalmoves[] = $lm;
1944.                                 }
1945.                                 break;
1946.                             }
1947.                             else {
1948.                                 
$lm compose_move($args[$k], $args[$i]);
1949.                                 if (!
in_array($lm$legalmoves))
1950.                                     
$legalmoves[] = $lm;
1951.                             }
1952.                         }
1953.                         
$k $i 1;
1954.                     }
1955.                 }
1956.                 break;
1957.             case 
"setelem"// Sets specific element of array variable
1958.                 
if (ctype_digit($args[1][0]))
1959.                     
error ("A variable name should not begin with a digit."$linenum);
1960.                 
setuservar ("{$args[1]}.{$args[2]}"polish(array_slice($args3),$linenum));
1961.                 break;
1962.             case 
"setflag"// Turns on named boolean flags
1963.                 
for ($i 1$i $cnt$i++)
1964.                     
$flag[$args[$i]] = true;
1965.                 break;
1966.             case 
"setglobal": case "setsystem":
1967.             
// Sets PHP variable used by Game Courier to value of expression
1968.                 
switch ($args[1]) {
1969.                     case 
"answered":
1970.                     case 
"appendautorules":
1971.                     case 
"autorules":
1972.                     case 
"board":
1973.                     case 
"capturedpieces":
1974.                     case 
"code":
1975.                     case 
"columns":
1976.                     case 
"debug":
1977.                     case 
"dest":
1978.                     case 
"dir":
1979.                     case 
"groupsets":
1980.                     case 
"lastcaptured":
1981.                     case 
"lastmoved":
1982.                     case 
"map":
1983.                     case 
"maxmove":
1984.                     case 
"meetingpoint":
1985.                     case 
"movelist";
1986.                     case 
"moves":
1987.                     case 
"noerrorcheck":
1988.                     case 
"omitmoves":
1989.                     case 
"orientation":
1990.                     case 
"origin":
1991.                     case 
"originalpieces":
1992.                     case 
"piecekeys":
1993.                     case 
"pieces":
1994.                     case 
"piecevals":
1995.                     case 
"prison":
1996.                     case 
"secondfirst":
1997.                     case 
"selset":
1998.                     case 
"sets":
1999.                     case 
"showoutput":
2000.                     case 
"space";
2001.                     case 
"submit":
2002.                         
$GLOBALS[$args[1]] = polish(array_slice($args2),$linenum);
2003.                         break;
2004.                     case 
"flipped":
2005.                     case 
"legalmoves":
2006.                     case 
"starpath":
2007.                         
$GLOBALS[$args[1]] = polish(array_slice($args2),$linenum);
2008.                         break;
2009.                     default:
2010.                         if (
preg_match("/^(capturedpieces|originalpieces|piecekeys|pieces|piecevals|prison|sets|starpath)\./"$args[1])) {
2011.                             list(
$ra,$lm) = explode("."$args[1]);
2012.                             
$GLOBALS[$ra][$lm] = polish(array_slice($args2), $linenum);
2013.                         }
2014.                         else {
2015.                             
error ("You may not set \${$args[1]} with {$args[0]}."$linenum);
2016.                         }
2017.                         break;
2018.                 }
2019.                 if (empty(
$customsets) && (($args[1] == "dir") || ($args[1] == "pieces"))) {
2020.                     
$customSet["custom"][$args[1]] = $GLOBALS[$args[1]];
2021.                     if (
is_array($customSet) && array_key_exists("dir"$customSet["custom"]) && array_key_exists("pieces"$customSet["custom"])) {
2022.                         
$customsets json_encode($customSetJSON_PRETTY_PRINT);
2023.                     }
2024.                 }
2025.                 break;
2026.             
// Used because the keyword dest gets converted to the value of $dest
2027.             
case "setdest":
2028.                 
$GLOBALS["dest"] = polish(array_slice($args1),$linenum);
2029.                 break;
2030.             
// Used because the keyword origin gets converted to the value of $origin
2031.             
case "setorigin":
2032.                 
$GLOBALS["origin"] = polish(array_slice($args1),$linenum);
2033.                 break;
2034.             
// Sets reminder text, which is outputted to player
2035.             // Like Say, but prints smaller and lower.
2036.             
case "remind":
2037.                 
$reminder stripallslashes(join(" "array_slice($args1)));
2038.                 break;
2039.             case 
"resetconst"// Changes the value of a constant to the value of expression
2040.                 
if (!is_array($constants))
2041.                     
$constants = array();
2042.                 
$constants[$args[1]] = polish(array_slice($args2),$linenum);
2043.                 break;
2044.             case 
"setconst"// Set new constant to value of expression
2045.                 
if (!is_array($constants))
2046.                     
$constants = array();
2047.                 if (!
array_key_exists($args[1], $constants)) {
2048.                     
$constants[$args[1]] = polish(array_slice($args2),$linenum);
2049.                 }
2050.                 break;
2051.             case 
"unsetconst"// Deletes named constant
2052.                 
if (isset($constants[$args[1]]))
2053.                     unset (
$constants[$args[1]]);
2054.                 break;
2055.             case 
"shift"// Shifts contents of each coordinate to next coordinate, 
2056.             // losing what is on last coordinate.
2057.                 
for ($i $cnt-1$i 1$i--)
2058.                     
$space[$args[$i]] = $space[$args[$i-1]];
2059.                 
$space[$args[1]] = '@';
2060.                 break;
2061.             case 
"shuffle"// Randomly shuffles contents of listed coordinates.
2062.                 
if ($args[1] == "cards") {
2063.                     
$deck shufflearray($deck);
2064.                 }
2065.                 elseif (
is_array($args[1])) {
2066.                     
$tcnt count($args[1]);
2067.                     for (
$i 0$i $tcnt$i++) {
2068.                         
$j mt_rand(0$cnt-1);
2069.                         
$temp $space[$args[1][$i]];
2070.                         
$space[$args[1][$i]] = $space[$args[1][$j]];
2071.                         
$space[$args[1][$j]] = $temp;
2072.                     }
2073.                 }
2074.                 else {                    
2075.                     for (
$i 1$i $cnt$i++) {
2076.                         
$j mt_rand(1$cnt-1);
2077.                         
$temp $space[$args[$i]];
2078.                         
$space[$args[$i]] = $space[$args[$j]];
2079.                         
$space[$args[$j]] = $temp;
2080.                     }
2081.                 }
2082.                 break;
2083.             case 
"store"// Stores board configuration, color indexes, flags, and 
2084.             // information about last move.
2085.                 // Stores to name or to "last".
2086.                 
$storage = empty($args[1]) ? "last" $args[1];
2087.                 
$store[$storage]["space"] = $space;
2088.                 
$store[$storage]["flag"] = $flag;
2089.                 
$store[$storage]["lastcaptured"] = $lastcaptured;
2090.                 
$store[$storage]["lastmoved"] = $lastmoved;
2091.                 
$store[$storage]["dest"] = $dest;
2092.                 
$store[$storage]["origin"] = $origin;
2093.                 
$store[$storage]["background"] = $background;
2094.                 
$store[$storage]["prevcaptured"] = $prevcaptured;
2095.                 
$store[$storage]["prevmoved"] = $prevmoved;
2096.                 
$store[$storage]["prevorigin"] = $prevorigin;
2097.                 
$store[$storage]["prevdest"] = $prevdest;
2098.                 break;
2099.             case 
"restore"// Restores board config, etc., to last stored config.
2100.             // Restores from name or from "last".
2101.                 
$storage = empty($args[1]) ? "last" $args[1];
2102.                 if (isset(
$store[$storage]))
2103.                     
extract ($store[$storage]);
2104.                 break;
2105.             case 
"run"// NEEDS DOCUMENTATION
2106.             // Appears to restart program from beginning.
2107.                 
unsetlocals ($scope0);
2108.                 
$scope 0;
2109.                 
$space $startposition;
2110.                 
$linenum 0;
2111.                 
$flag = array();
2112.                 
$lastcaptured $lastmoved $dest $origin $prevcaptured $prevmoved $prevorigin $prevdest "";
2113.                 
$background $startbackground;
2114.                 break;
2115.             case 
"say"// Copy text to output for player to read.
2116.                 
$message stripallslashes(join(" "array_slice($args1)));
2117.                 break;
2118.             case 
"swap"// Swaps pieces on a pair of spaces.
2119.             // Multiple pairs may be listed.
2120.                 
for ($i 1$i $cnt$i += 2) {
2121.                     if (
array_key_exists($i$args) && array_key_exists($i+1$args)) {
2122.                         
$c1 $args[$i]; $c2 $args[$i+1];
2123.                         if (
array_key_exists($c1$space) && array_key_exists($c2$space)) {
2124.                             
$temp $space[$c1];
2125.                             
$space[$c1] = $space[$c2];
2126.                             
$space[$c2] = $temp;
2127.                         }
2128.                     }
2129.                     elseif (
$i <= 1) {
2130.                         echo 
"<P>\$i is {$i}</P>";
2131.                         
print_r($args);
2132.                         
illegal ("The <b>swap</b> command does not have enough arguments."$linenum);
2133.                     }
2134.                 }
2135.                 break;
2136.             case 
"take"// NEEDS DOCUMENATION
2137.             // Take so many cards from opponent's hand
2138.                 
if ($firstplayer) {
2139.                     
$hand = &$hand1;
2140.                     
$otherhand = &$hand2;
2141.                 }
2142.                 else {
2143.                     
$hand = &$hand2;
2144.                     
$otherhand = &$hand1;
2145.                 }
2146.                 for (
$i 0$i $args[1]; $i++) {
2147.                     
$c array_pop($otherhand);
2148.                     
array_push($hand$c);
2149.                     
array_push($drawncards$c);
2150.                     if (
count($otherhand) == 0) {
2151.                         die (
"Your opponent has only {$i} cards. You can't take {$args[1]}. Go back and take fewer.");
2152.                     }
2153.                 }
2154.                 break;
2155.             case 
"unset"// Unsets variable
2156.             // If multiple variables have the same name, it unsets the one with highest precedence.
2157.                 
for ($i 1$i $cnt$i++)
2158.                     
unsetuservar ($args[$i]);
2159.                 break;
2160.             case 
"unsetflag"// Sets boolean flag to false
2161.                 
for ($i 1$i $cnt$i++)
2162.                     
$flag[$args[$i]] = false;
2163.                 break;
2164.                 
/*
2165.             case "write": // NEEDS DOCUMENTATION
2166.                 write_on_space ($args[1], polish(array_slice($args, 2),$linenum));
2167.                 break;
2168.                 */
2169.             
case "lib"// Marks beginning of code inserted from include file
2170.                 
break;
2171.             default:
2172.                 
error ("<B>$move</B> is not a valid expression, because <B>{$args[0]}</B> is not a recognized piece, coordinate, command, or subroutine."$linenum);
2173.         }
2174.     }
2175.     return 
NULL;
2176. }
2177. 
2178. 
// Gets the value of the most local variable whose name is given
2179. 
2180. /*
2181. function getuservar($name) {
2182.     global $scope, $uservar, $sub;
2183.     for ($i = $scope; $sub[$scope] == $sub[$i]; $i--) 
2184.         if (isset($uservar[$i][$sub[$scope]]) && (isset($uservar[$i][$sub[$scope]][$name]) || array_key_exists($name, $uservar[$i][$sub[$scope]])))
2185.             return $uservar[$i][$sub[$scope]][$name];
2186.     if (isset($uservar[0][$sub[$scope]]) && (isset($uservar[0][$sub[$scope]][$name]) || array_key_exists($name, $uservar[0][$sub[$scope]])))
2187.         return $uservar[0][$sub[$scope]][$name];
2188.     for ($i = $scope; $i >= 0; $i--) 
2189.         if (isset($uservar[$i]["main"]) && (isset($uservar[$i]["main"][$name]) || array_key_exists($name, $uservar[$i]["main"])))
2190.             return $uservar[$i]["main"][$name];
2191.     return NULL;
2192. }
2193. */
2194. 
2195. 
function &refvar($name) {
2196.     global 
$scope$uservar$sub;
2197. 
2198.     
// When array element is specified by including periods in name,
2199.     // get top level array for purposes of determining scope of variable.
2200.     
if ($p strpos($name"."))
2201.         
$top substr($name0$p);
2202.     else
2203.         
$top $name;
2204.     
// covers my variables, as well as global variables when lexical scope is main.
2205.     
for ($i $scope; ($i >= 0) && ($sub[$scope] == $sub[$i]); $i--) {
2206.         if (isset(
$uservar[$i][$sub[$scope]]) && (isset($uservar[$i][$sub[$scope]][$top]) || array_key_exists($top$uservar[$i][$sub[$scope]]))) {
2207.             
$array = &$uservar[$i][$sub[$scope]];
2208.             goto 
ret;
2209.         }
2210.     }
2211.     
// covers static variables
2212.     
if (isset($uservar[0][$sub[$scope]]) && (isset($uservar[0][$sub[$scope]][$top]) || array_key_exists($top$uservar[0][$sub[$scope]]))) {
2213.         
$array = &$uservar[0][$sub[$scope]];
2214.         goto 
ret;
2215.     }
2216.     
// covers local variables, as well as global variables within a subroutine
2217.     
for ($i $scope$i >= 0$i--) {
2218.         if (isset(
$uservar[$i]["main"]) && (isset($uservar[$i]["main"][$top]) || array_key_exists($top$uservar[$i]["main"]))) {
2219.             
$array = &$uservar[$i]["main"];
2220.             goto 
ret;
2221.         }
2222.     }
2223.     
$array = &$uservar[0]["main"];
2224.     
ret:
2225.     if (!
$p)
2226.         return 
$array[$name];
2227.     
$subkeys explode(".",$name);
2228.     
$penult count($subkeys) - 1;
2229.     for (
$i 0$i $penult$i++) {
2230.         
$array = &$array[$subkeys[$i]];
2231.     }
2232.     return 
$array[$subkeys[$penult]];
2233. }
2234. 
2235. 
2236. function &
parentarray (&$array$name) {
2237.     if (
$p strpos($name".")) {
2238.         
$subkeys explode(".",$name);
2239.         
$penult count($subkeys) - 1;
2240.         for (
$i 0$i $penult$i++) {
2241.             
$array = &$array[$subkeys[$i]];
2242.         }
2243.     }
2244.     return 
$array;
2245. }
2246. 
2247. function 
getvar (&$array$name) {
2248.     if (
$p strpos($name".")) {
2249.         
$subkeys explode(".",$name);
2250.         
$penult count($subkeys) - 1;
2251.         for (
$i 0$i $penult$i++) {
2252.             
$array = &$array[$subkeys[$i]];
2253.         }
2254.         return 
$array[$subkeys[$penult]];
2255.     }
2256.     return 
$array[$name];
2257. }
2258. 
2259. 
2260. function 
getuservar($name) {
2261.     global 
$scope$uservar$sub;
2262. 
2263.     if (empty(
$name))
2264.         return 
NULL;
2265.     
// When array element is specified by including periods in name,
2266.     // get top level array for purposes of determining scope of variable.
2267.     
if ($p strpos($name"."))
2268.         
$top substr($name0$p);
2269.     else
2270.         
$top $name;
2271.     if (
array_key_exists($scope$sub)) {
2272.         
// covers my variables, as well as global variables when lexical scope is main.
2273.         
for ($i $scope; ($i >= 0) && ($sub[$scope] == $sub[$i]); $i--) {
2274.             if (isset(
$uservar[$i][$sub[$scope]]) && (isset($uservar[$i][$sub[$scope]][$top]) || array_key_exists($top$uservar[$i][$sub[$scope]]))) {
2275.                 
$array $uservar[$i][$sub[$scope]];
2276.                 goto 
ret;
2277.             }
2278.         }
2279.         
// covers static variables
2280.         
if (isset($uservar[0][$sub[$scope]]) && (isset($uservar[0][$sub[$scope]][$top]) || array_key_exists($top$uservar[0][$sub[$scope]]))) {
2281.             
$array $uservar[0][$sub[$scope]];
2282.             goto 
ret;
2283.         }
2284.     }
2285.     
// covers local variables, as well as global variables within a subroutine
2286.     
for ($i $scope$i >= 0$i--) {
2287.         if (isset(
$uservar[$i]["main"]) && (isset($uservar[$i]["main"][$top]) || array_key_exists($top$uservar[$i]["main"]))) {
2288.             
$array $uservar[$i]["main"];
2289.             goto 
ret;
2290.         }
2291.     }
2292.     return 
NULL;
2293.     
ret:
2294.     if (!
$p)
2295.         return 
$array[$name];
2296.     
$subkeys explode(".",$name);
2297.     
$penult count($subkeys) - 1;
2298.     for (
$i 0$i $penult$i++) {
2299.         
$array = &$array[$subkeys[$i]];
2300.     }
2301.     if (isset(
$array[$subkeys[$penult]]))
2302.         return 
$array[$subkeys[$penult]];
2303.     else
2304.         return 
NULL;
2305. }
2306. 
2307. function 
issetuservar($name) {
2308.     global 
$scope$uservar$sub;
2309. 
2310.     
// When array element is specified by including periods in name,
2311.     // get top level array for purposes of determining scope of variable.
2312.     
if ($p strpos($name"."))
2313.         
$top substr($name0$p);
2314.     else
2315.         
$top $name;
2316.     
// covers my variables, as well as global variables when lexical scope is main.
2317.     
for ($i $scope; ($i >= 0) && ($sub[$scope] == $sub[$i]); $i--) {
2318.         if (isset(
$uservar[$i][$sub[$scope]]) && (isset($uservar[$i][$sub[$scope]][$top]) || array_key_exists($top$uservar[$i][$sub[$scope]]))) {
2319.             
$array = &$uservar[$i][$sub[$scope]];
2320.             goto 
ret;
2321.         }
2322.     }
2323.     
// covers static variables
2324.     
if (isset($uservar[0][$sub[$scope]]) && (isset($uservar[0][$sub[$scope]][$top]) || array_key_exists($top$uservar[0][$sub[$scope]]))) {
2325.         
$array = &$uservar[0][$sub[$scope]];
2326.         goto 
ret;
2327.     }
2328.     
// covers local variables, as well as global variables within a subroutine
2329.     
for ($i $scope$i >= 0$i--) {
2330.         if (isset(
$uservar[$i]["main"]) && (isset($uservar[$i]["main"][$top]) || array_key_exists($top$uservar[$i]["main"]))) {
2331.             
$array = &$uservar[$i]["main"];
2332.             goto 
ret;
2333.         }
2334.     }
2335.     
$array = &$uservar[0]["main"];
2336.     
ret:
2337.     if (!
$p) {
2338.         if (isset(
$array[$name]))
2339.             return 
true;
2340.     }
2341.     
$subkeys explode(".",$name);
2342.     
$penult count($subkeys) - 1;
2343.     for (
$i 0$i $penult$i++) {
2344.         
$array = &$array[$subkeys[$i]];
2345.     }
2346.     if (isset(
$array[$subkeys[$penult]]))
2347.         return 
true;
2348.     return 
false;
2349. }
2350. 
2351. function 
getuserelem($name$elem) {
2352.     return 
getuservar("{$name}.{$elem}");
2353. 
/*    
2354.     global $scope, $uservar, $sub;
2355.     
2356.     for ($i = $scope; $sub[$scope] == $sub[$i]; $i--) 
2357.         if (isset($uservar[$i][$sub[$scope]][$name]) || (is_array($uservar[$i][$sub[$scope]]) && array_key_exists($name, $uservar[$i][$sub[$scope]])))
2358.             return $uservar[$i][$sub[$scope]][$name][$elem];
2359.     if (isset($uservar[0][$sub[$scope]][$name]) || (is_array($uservar[0][$sub[$scope]]) && array_key_exists($name, $uservar[0][$sub[$scope]])))
2360.         return $uservar[0][$sub[$scope]][$name][$elem];
2361.     for ($i = $scope; $i > 0; $i--) 
2362.         if (isset($uservar[$i]["main"][$name]) || (is_array($uservar[$i]["main"]) && array_key_exists($name, $uservar[$i]["main"])))
2363.             return $uservar[$i]["main"][$name][$elem];
2364.     return $uservar[0]["main"][$name][$elem];;
2365. */
2366. 
}
2367. 
2368. 
// Sets the most local variable of the name used to val
2369. 
2370. /*
2371. function setuservar ($name, $val) {
2372.     global $scope, $uservar, $sub;
2373. 
2374.     for ($i = $scope; $sub[$scope] == $sub[$i]; $i--)
2375.         if (isset($uservar[$i][$sub[$scope]]) && array_key_exists($name, $uservar[$i][$sub[$scope]])) {
2376.             $uservar[$i][$sub[$scope]][$name] = $val;
2377.             return;
2378.         }
2379.     if (isset($uservar[0][$sub[$scope]]) && array_key_exists($name, $uservar[0][$sub[$scope]])) {
2380.         $uservar[0][$sub[$scope]][$name] = $val;
2381.         return;
2382.     }
2383.     for ($i = $scope; $i > 0; $i--)
2384.         if (isset($uservar[$i]["main"]) && array_key_exists($name, $uservar[$i]["main"])) {
2385.             $uservar[$i]["main"][$name] = $val;
2386.             return;
2387.         }
2388.     $uservar[0]["main"][$name] = $val;
2389.     return;
2390. }
2391. */
2392. 
2393. // Recursively set variable
2394. 
2395. 
function setuservar ($name$val) {
2396.     global 
$scope$uservar$sub;
2397. 
2398.     if ((
$p strpos($name".")) !== false)
2399.         
$base substr($name0$p);
2400.     else
2401.         
$base $name;
2402.     for (
$i $scope; ($i >= 0) && ($sub[$scope] == $sub[$i]); $i--)
2403.         if (isset(
$uservar[$i][$sub[$scope]]) && array_key_exists($base$uservar[$i][$sub[$scope]])) {
2404.             
recsetvar($uservar[$i][$sub[$scope]],$name,$val);
2405.             return;
2406.         }
2407.     if (isset(
$uservar[0][$sub[$scope]]) && array_key_exists($base$uservar[0][$sub[$scope]])) {
2408.         
recsetvar($uservar[0][$sub[$scope]],$name,$val);
2409.         return;
2410.     }
2411.     for (
$i $scope$i 0$i--)
2412.         if (isset(
$uservar[$i]["main"]) && array_key_exists($base$uservar[$i]["main"])) {
2413.             
recsetvar($uservar[$i]["main"],$name,$val);
2414.             return;
2415.         }
2416.     
recsetvar ($uservar[0]["main"],$name,$val);
2417.     return;
2418. }
2419. 
2420. function 
recsetvar (&$array$key$val) {
2421.     if (
strpos($key".")) {
2422.         
$subkeys explode("."$key);
2423.         
$penult count($subkeys) - 1;
2424.         for (
$i 0$i $penult$i++) {
2425.             
$array = &$array[$subkeys[$i]];
2426.             if (!
is_array($array))
2427.                 
$array = array();
2428.         }
2429.         
$array[$subkeys[$penult]] = $val;
2430.     }
2431.     else {
2432.         if (!
is_array($array))
2433.             
$array = array();
2434.         
$array[$key] = $val;
2435.     }
2436. }
2437. 
2438. function 
setuserelem ($name$elem$val) {
2439.     
setuservar ("{$name}.{$elem}"$val);
2440. 
/*    
2441.     global $scope, $uservar, $sub;
2442. // echo "<P>Testing new code for setelem command to allow multiple dimensions. Problems may arise.</P>";
2443.     for ($i = $scope; $sub[$scope] == $sub[$i]; $i--)
2444.         if (isset($uservar[$i][$sub[$scope]]) && array_key_exists($name, $uservar[$i][$sub[$scope]])) {
2445.             $uservar[$i][$sub[$scope]][$name][$elem] = $val;
2446.             // recsetvar($uservar[$i][$sub[$scope]][$name],$elem,$val);
2447.             return;
2448.         }
2449.     if (isset($uservar[0][$sub[$scope]]) && array_key_exists($name, $uservar[0][$sub[$scope]])) {
2450.         $uservar[0][$sub[$scope]][$name][$elem] = $val;
2451.         // recsetvar($uservar[0][$sub[$scope]][$name], $elem, $val);
2452.         return;
2453.     }
2454.     for ($i = $scope; $i > 0; $i--)
2455.         if (isset($uservar[$i]["main"]) && array_key_exists($name, $uservar[$i]["main"])) {
2456.             $uservar[$i]["main"][$name][$elem] = $val;
2457.             // recsetvar($uservar[$i]["main"][$name], $elem, $val);
2458.             return;
2459.         }
2460.     $uservar[0]["main"][$name][$elem] = $val;
2461.     // recsetvar($uservar[0]["main"][$name], $elem, $val);
2462.     return;
2463.     */
2464. 
}
2465. 
2466. 
/*
2467. function pushuservar ($name, $val) {
2468.     global $scope, $uservar, $sub;
2469.     for ($i = $scope; $sub[$scope] == $sub[$i]; $i--) {
2470.         if (isset($uservar[$i][$sub[$scope]]) && array_key_exists($name, $uservar[$i][$sub[$scope]])) {
2471.             $uservar[$i][$sub[$scope]][$name][] = $val;
2472.             return;
2473.         }
2474.     }
2475.     if (isset($uservar[0][$sub[$scope]]) && array_key_exists($name, $uservar[0][$sub[$scope]])) {
2476.         $uservar[0][$sub[$scope]][$name][] = $val;
2477.         return;
2478.     }
2479.     for ($i = $scope; $i > 0; $i--) {
2480.         if (isset($uservar[$i]["main"]) && array_key_exists($name, $uservar[$i]["main"])) {
2481.             $uservar[$i]["main"][$name][] = $val;
2482.             return;
2483.         }
2484.     }
2485.     $uservar[0]["main"][$name][] = $val;
2486.     return 0;
2487. }
2488. 
2489. function decuservar ($name) {
2490.     global $scope, $uservar, $sub;
2491. 
2492.     for ($i = $scope; $sub[$scope] == $sub[$i]; $i--)
2493.         if (isset($uservar[$i][$sub[$scope]]) && array_key_exists($name, $uservar[$i][$sub[$scope]])) {
2494.             $uservar[$i][$sub[$scope]][$name]--;
2495.             return;
2496.         }
2497.     if (isset($uservar[0][$sub[$scope]]) && array_key_exists($name, $uservar[0][$sub[$scope]])) {
2498.         $uservar[0][$sub[$scope]][$name]--;
2499.         return;
2500.     }
2501.     for ($i = $scope; $i > 0; $i--)
2502.         if (isset($uservar[$i]["main"]) && array_key_exists($name, $uservar[$i]["main"])) {
2503.             $uservar[$i]["main"][$name]--;
2504.             return;
2505.         }
2506.     $uservar[0]["main"][$name]--;
2507.     return;
2508. }
2509. 
2510. function incuservar ($name) {
2511.     global $scope, $uservar, $sub;
2512. 
2513.     for ($i = $scope; $sub[$scope] == $sub[$i]; $i--)
2514.         if (isset($uservar[$i][$sub[$scope]]) && array_key_exists($name, $uservar[$i][$sub[$scope]])) {
2515.             $uservar[$i][$sub[$scope]][$name]++;
2516.             return;
2517.         }
2518.     if (isset($uservar[0][$sub[$scope]]) && array_key_exists($name, $uservar[0][$sub[$scope]])) {
2519.         $uservar[0][$sub[$scope]][$name]++;
2520.         return;
2521.     }
2522.     for ($i = $scope; $i > 0; $i--)
2523.         if (isset($uservar[$i]["main"]) && array_key_exists($name, $uservar[$i]["main"])) {
2524.             $uservar[$i]["main"][$name]++;
2525.             return;
2526.         }
2527.     $uservar[0]["main"][$name]++;
2528.     return;
2529. }
2530. */
2531. 
2532. 
function unsetlocals ($old$new) {
2533.     for (
$i $new+1$i <= $old$i++)
2534.         unset (
$GLOBALS["uservar"][$i]);
2535. }
2536. 
2537. function 
unsetuservar ($name) {
2538.     global 
$scope$uservar$sub;
2539. 
2540.     
// When array element is specified by including periods in name,
2541.     // get top level array for purposes of determining scope of variable.
2542.     
if ($p strpos($name"."))
2543.         
$top substr($name0$p);
2544.     else
2545.         
$top $name;
2546.     
// covers my variables, as well as global variables when lexical scope is main.
2547.     
for ($i $scope$sub[$scope] == $sub[$i]; $i--) {
2548.         if (isset(
$uservar[$i][$sub[$scope]]) && (isset($uservar[$i][$sub[$scope]][$top]) || array_key_exists($top$uservar[$i][$sub[$scope]]))) {
2549.             
$array = &$uservar[$i][$sub[$scope]];
2550.             goto 
ret;
2551.         }
2552.     }
2553.     
// covers static variables
2554.     
if (isset($uservar[0][$sub[$scope]]) && (isset($uservar[0][$sub[$scope]][$top]) || array_key_exists($top$uservar[0][$sub[$scope]]))) {
2555.         
$array = &$uservar[0][$sub[$scope]];
2556.         goto 
ret;
2557.     }
2558.     
// covers local variables, as well as global variables within a subroutine
2559.     
for ($i $scope$i >= 0$i--) {
2560.         if (isset(
$uservar[$i]["main"]) && (isset($uservar[$i]["main"][$top]) || array_key_exists($top$uservar[$i]["main"]))) {
2561.             
$array = &$uservar[$i]["main"];
2562.             goto 
ret;
2563.         }
2564.     }
2565.     
$array = &$uservar[0]["main"];
2566.     
ret:
2567.     if (!
$p) {
2568.         if (isset(
$array[$name]))
2569.             unset (
$array[$name]);
2570.     }
2571.     
$subkeys explode(".",$name);
2572.     
$penult count($subkeys) - 1;
2573.     for (
$i 0$i $penult$i++) {
2574.         
$array = &$array[$subkeys[$i]];
2575.     }
2576.     if (isset(
$array[$subkeys[$penult]]))
2577.         unset (
$array[$subkeys[$penult]]);
2578. }
2579. 
2580. function 
alias ($s) {
2581.     global 
$space$pieces$REALNAME$dest$origin$lastmoved$lastcaptured;
2582.     
2583.     if (isset(
$REALNAME[$s]))
2584.         return 
$REALNAME[$s];
2585.     elseif (isset(
$space[$s]) || isset($pieces[$s]))
2586.         return 
$s;
2587.     elseif (
$s == "old")
2588.         return 
$lastcaptured;
2589.     elseif (
$s == "moved")
2590.         return 
$lastmoved;
2591.     elseif (
$s == "origin")
2592.         return 
$origin;
2593.     elseif (
$s == "dest")
2594.         return 
$dest;
2595.     elseif (
ctype_alnum($s))
2596.         return 
false;
2597.     else
2598.         return 
$s;
2599. }
2600. 
2601. function 
parsemove ($line$requireMOVE true) {
2602.     global 
$space$pieces$dest;
2603.     
2604.     if (
$requireMOVE && strncmp($line"MOVE: "6)) {
2605.         return 
parseline($line);
2606.     }
2607.     
$args = array();
2608.     
$args[0] = "MOVE:";
2609.     
$move trim(substr($line6));
2610.     
$len strlen($move);
2611.     for (
$i 0$i $len$i++) {
2612.         if ((
$move[$i] == "*") || ($move[$i] == "-") || ($move[$i] == " "))
2613.             break;
2614.     }
2615.     
$args[] = $i substr($move0$i) : $move[0];
2616.     
$move $i substr($move$i) : substr($move1);
2617.     
$move trim($move);
2618.     
$args[1] = isset($args[1]) ? alias($args[1]) : "";
2619.     if (
$args[1] == "-") {
2620.         if (!isset(
$space[$move]))
2621.             
illegal ("When the hyphen begins a move, it must be followed by a recognized coordinate in move: {$move}.");
2622.         
$args[] = alias($move);
2623.         return 
$args;
2624.     }
2625.     if (isset(
$pieces[$args[1]]) || ($args[1] == "@")) {
2626.         if ((
$move[0] == "*") || ($move[0] == "-")) {
2627.             
$args[2] = $move[0];
2628.             
$args[3] = alias(trim(substr($move1)));
2629.             return 
$args;
2630.         }
2631.         else {
2632.             
$coords explode("-"$move);
2633.             if (
count($coords) != 2)
2634.                 
illegal ("The move <B>$move</B> is not Well-formed.");
2635.             
$args[2] = alias(trim($coords[0]));
2636.             
$args[3] = "-";
2637.             if (!empty(
$coords[1]))
2638.                 
$args[4] = alias(trim($coords[1]));
2639.             return 
$args;
2640.         }
2641.     }
2642.     if ((
$args[1] != "") && isset($space[$args[1]])) {
2643.         if (empty(
$move))
2644.             
error_log("line in parsemove: {$line}");
2645.         
$args[2] = $move[0] ?? NULL;
2646.         
$temp ltrim(substr($move1));
2647.         
$args[3] = empty($temp) ? NULL alias($temp);
2648.         return 
$args;
2649.     }
2650.     
2651.     return 
parseline($line);
2652. }
2653. 
2654. 
/*
2655. 
2656. // Turned out to be a dead end.
2657. 
2658. function preprocessline ($line) {
2659.     $max = strlen($line);
2660.     for ($i = 0; $i < $max; $i++) {
2661.         if (($line[$i] == "#") && (($i == 0) || ($line{$h=($i-1)} == " ") || ($line[$h] == "(") || ($line[$h] == "#"))) {
2662.             $j = $i + 1;
2663.             if (($line[$j] == "#") || ctype_digit($line[$j]))
2664.                 continue;
2665.             for ($k = $j; ($k < $max) && ($line[$k] != " ") && ($line[$k] != ")"); $k++);
2666.             if ($k == $j)
2667.                 continue;
2668.             $varname = substr($line, $j, $k-$j);
2669.             if (($temp = getuservar($varname)) !== NULL) {
2670.                 if ((array)$temp !== $temp) {
2671.                     $line = substr_replace($line, $temp, $i, $k-$i);
2672.                     $i--;
2673.                 }
2674.                 $max = strlen($line);
2675.             }
2676.         }
2677.     }
2678.     return $line;
2679. }
2680. 
2681. */ 
2682. 
2683. 
function parseline ($line) {
2684.     global 
$origin$dest$lastcaptured$lastmoved$flag$constants$linenum;
2685.     
2686.     
$max strlen($line);
2687.     
$n 0;
2688.     
2689.     for (
$i 0$i $max$i++) {
2690.         if (
$line[$i] == '{') {
2691.             
$start $i+1;
2692.             
$parcnt 1;
2693.             for (
$j $start$j $max$j++) {
2694.                 if (
$line[$j] == '{')
2695.                     
$parcnt++;
2696.                 if (
$line[$j] == '}')
2697.                     
$parcnt--;
2698.                 if (
$parcnt == 0)
2699.                     break;
2700.             }
2701.             
$values parseline(substr($line$start$j $start));
2702.             
// $line = substr($line, 0, $i) . implode(".", $values) . substr($line, $j+1);
2703.             
$val polish($values$linenum);
2704.             if (
is_array($val))
2705.                 
$val array2string($val);
2706.             
$line substr($line0$i) . $val substr($line$j+1);
2707.             
$i--;
2708.             
$max strlen($line); // Recalculate when $line changes
2709.         
}
2710.     }
2711.         
2712.     
$max strlen($line);
2713.     for (
$i 0$i $max$i++) {
2714.         if (
ctype_space($line[$i]))
2715.             continue;
2716.         if (
$line[$i] == '"') {
2717.             
$start $i+1;
2718.             for (
$i $start$i $max$i++) {
2719.                 if (
$line[$i] == '"')
2720.                     break;
2721.             }
2722.             
$args[$n++] = substr($line$start$i $start);
2723.         }
2724. 
/*        elseif ($line[$i] == "'") {
2725.             $start = $i+1;
2726.             for ($i = $start; $i < $max; $i++) {
2727.                 if ($line[$i] == "'")
2728.                     break;
2729.             }
2730.             $args[$n++] = substr($line, $start, $i - $start);
2731.         }
2732. */
2733.         
elseif ($line[$i] == '(') {
2734.             
$start $i+1;
2735.             
$parcnt 1;
2736.             for (
$i $start$i $max$i++) {
2737.                 if (
$line[$i] == '(')
2738.                     
$parcnt++;
2739.                 if (
$line[$i] == ')')
2740.                     
$parcnt--;
2741.                 if (
$parcnt == 0)
2742.                     break;
2743.             }
2744.             
$args[$n++] = parseline(substr($line$start$i $start));
2745.         }
2746.         else {
2747.             
$start $i;
2748.             for (; 
$i $max$i++) {
2749.                 if (
ctype_space($line[$i]))
2750.                     break;
2751.             }
2752.             
$args[$n] = substr($line$start$i $start);
2753.             if (
$args[0] != "def")
2754.                 
$args[$n] = evalvar($args[$n]);
2755.             
$n++;
2756. 
/*                
2757.             $args[$n] = substr($line, $start, $i - $start);
2758.             if ($args[$n][0] == "?") {
2759.                 $name = substr($args[$n], 1);
2760.                 $args[$n] = isset($flag[$name]) ? $flag[$name] : false;
2761.             }
2762.             elseif (($args[$n][0] == "#") && ($args[$n] != "#")) {
2763.                 $name = substr($args[$n], 1);
2764.                 if (($temp = getuservar($name)) !== NULL)
2765.                     $args[$n] = $temp;
2766.                 elseif (isset($constants) && (is_array($constants) && (isset($constants[$name]) || array_key_exists($name, $constants))))
2767.                     $args[$n] = $constants[$name];
2768.             }
2769.             elseif (($args[$n][0] == "@") && ($args[$n] != "@")) {
2770.                 $name = substr($args[$n], 1);
2771.                 if (isset($constants) && (is_array($constants) && (isset($constants[$name]) || array_key_exists($name, $constants))))
2772.                     $args[$n] = $constants[$name];
2773.             }
2774.             elseif (($args[$n][0] == "$") && ($args[$n] != "$")) {
2775.                 $name = substr($args[$n], 1);
2776.                 if ($name == "old")
2777.                     $args[$n] = $lastcaptured;
2778.                 elseif ($name == "moved")
2779.                     $args[$n] = $lastmoved;
2780.                 elseif (preg_match("/^(answered|board|capturedpieces|code|columns|debug|dest|firstplayer|lastcaptured|lastmoved|legalmoves|maxmln|maxmove|mln|movelist|moves|named|noerrorcheck|orientation|origin|originalpieces|piecekeys|piecevals|prevcaptured|prevmoved|prevdest|prevorigin|prison|showoutput|side|space|starpath|submit)$/", $name))
2781.                     $args[$n] = $GLOBALS[$name];
2782.                 elseif (preg_match("/^(capturedpieces|originalpieces|piecekeys|piecevals|prison|starpath)\./", $name))
2783.                     $args[$n] = getvar($GLOBALS, $name);
2784.             }
2785.             elseif ($args[$n] == "old")
2786.                 $args[$n] = $lastcaptured;
2787.             elseif ($args[$n] == "moved")
2788.                 $args[$n] = $lastmoved;
2789.             elseif ($args[$n] == "origin")
2790.                 $args[$n] = $origin;
2791.             elseif ($args[$n] == "dest")
2792.                 $args[$n] = $dest;
2793.             $n++;
2794.             }
2795.             */
2796.         
}
2797.     }
2798.     return empty(
$args) ? array() : $args;
2799. }
2800. 
2801. function 
evalvar ($var) {
2802.     global 
$constants$flag;
2803.     
2804.     
// As in Lisp, a car is the first element of a list,
2805.     // and cdr is the rest of the list. So, the code below
2806.     // treats the string $var as a list of characters.
2807.     
$car $var[0];
2808.     
$cdr substr($var1);
2809.     if (
is_numeric($cdr))
2810.         return 
$var;
2811.     if (empty(
$cdr))
2812.         return 
$car;
2813.     if (
strpos("@#$?"$cdr[0]) !== false)
2814.         
$cdr evalvar($cdr); // Recursion
2815.     
switch ($car) {
2816.     case 
"?":
2817.         return isset(
$flag[$cdr]) ? $flag[$cdr] : false;
2818.         break;
2819.     case 
"#":
2820.         if ((
$temp getuservar($cdr)) !== NULL)
2821.             return 
$temp;
2822.         elseif (isset(
$constants) && (is_array($constants) && (isset($constants[$cdr]) || array_key_exists($cdr$constants))))
2823.             return 
$constants[$cdr];
2824.         else
2825.             return 
$var;
2826.         break;
2827.     case 
"@":
2828.         if (isset(
$constants) && (is_array($constants) && (isset($constants[$cdr]) || array_key_exists($cdr$constants))))
2829.             return 
$constants[$cdr];
2830.         else
2831.             return 
$var;
2832.         break;
2833.     case 
"$":
2834.         if (
$cdr == "old")
2835.             return 
$GLOBALS["lastcaptured"];
2836.         elseif (
$cdr == "moved")
2837.             return 
$GLOBALS["lastmoved"];
2838.         elseif (
preg_match("/^(answered|board|capturedpieces|code|columns|debug|dest|dir|firstplayer|flipped|groupsets|lastcaptured|lastmoved|legalmoves|map|maxmln|maxmove|maxmoves|meetingpoint|mln|movelist|movenum|moves|named|noerrorcheck|oldmovelist|omitmoves|orientation|origin|originalpieces|piecekeys|pieces|piecemoves|piecevals|players|prevcaptured|prevmoved|prevdest|prevorigin|prison|rank|showoutput|selset|sets|side|space|starpath|status|submit|useerid)$/"$cdr))
2839.             return isset(
$GLOBALS[$cdr]) ? $GLOBALS[$cdr] : "";
2840.         elseif (
preg_match("/^(capturedpieces|flipped|originalpieces|piecekeys|pieces|piecevals|prison|sets|starpath)\./"$cdr)) {
2841.             list(
$ra,$ky) = explode("."$cdr);
2842.             if (isset(
$GLOBALS[$ra][$ky]))
2843.                 return 
$GLOBALS[$ra][$ky];
2844.             elseif (isset(
$GLOBALS[$ra]))
2845.                 return 
getvar($GLOBALS[$ra], $ky);
2846.             else
2847.                 return array();
2848.         }
2849.         else
2850.             return 
$var;
2851.         break;
2852.     default:
2853.         switch (
$var) {
2854.         case 
"old":
2855.             return 
$GLOBALS["lastcaptured"];
2856.             break;
2857.         case 
"moved":
2858.             return 
$GLOBALS["lastmoved"];
2859.             break;
2860.         case 
"origin":
2861.         case 
"dest":
2862.             return 
$GLOBALS[$var];
2863.             break;
2864.         default:
2865.             return 
$var;
2866.             break;
2867.         }
2868.     }
2869. }
2870. 
2871. function 
move ($s$d) {
2872.     global 
$origin$dest$lastmoved$lastcaptured$space$linenum$ALIAS$move;
2873.     
2874.     
// Check whether $s is a known coordinate
2875.     
if (!array_key_exists($s$space))
2876.         
illegal ("The coordinate {$s} is unknown in move: {$move}.");
2877. 
2878.     
// Check whether $s is a known coordinate
2879.     
if (!empty($d) && empty($space[$d]))
2880.         
illegal ("The coordinate {$d} is unknown in move {$move}.");
2881.     if (!empty(
$s[0]) && $s[0] == "!" && !isset($ALIAS[$s]) && (empty($submit) || ($submit!="Compose")) && !empty($coded))
2882.         
badinput ("The exclamation mark at the beginning of coordinate $s in <B>{$move}</B> indicates you may not enter it as part of a move.");
2883.     if (!empty(
$d[0]) && $d[0] == "!" && !isset($ALIAS[$d]) && (empty($submit) || ($submit!="Compose")) && !empty($coded))
2884.         
badinput ("The exclamation mark at the beginning of coordinate $d in <B>{$move}</B> indicates you may not enter it as part of a move.");
2885.     
$lastcaptured $space[$d] ?? ""// saves for use with automation
2886.     
$space[$d] = $lastmoved $space[$s]; // saves for use with automation
2887.     
$origin $s// saves for use with automation
2888.     
$dest $d;
2889.     if (
$s != $d)
2890.         
$space[$s] = "@";
2891.     return;
2892. }
2893. 
2894. function 
unlink_all ($c) {
2895.     global 
$map;
2896.     unset(
$map[$c]);
2897.     foreach (
$map as $frm => $ra)
2898.         foreach (
$ra as $d => $v)
2899.             if (
$v == $c)
2900.                 unset (
$map[$frm][$d]);
2901. }
2902. 
2903. 
?>