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 Polish notation expressions, complete with line numbering and syntax highlighting. This code includes all the operators and built-in functions available in GAME Code expressions, including any that may be undocumented. For simplicity of terminology, operator means any operator or built-in function, and operand means an argument to an operator. The operators are grouped by how many operands they take. The outer switch statement directs most operators to an inner switch statement, which is where you will find the code for particular operators. Within the same group, operators should be listed alphabetically. The outer switch also handles operators that take variable numbers of operands. So, you can find code for a particular operator by searching for its name once or twice within double quotation marks. Note that this code is provided here only for educational purposes and should not be copied or downloaded.

Copyright © Fergus Duniho, 2016.

   1.  <?
   2. 
   3. 
// Here is the main function for evaluating Polish notation expressions.
   4. 
   5. 
function polish ($input$linenum$substitutions NULL$myvars NULL) {
   6.     global 
$ALIAS$REALNAME$background$constants$debug$dest$excode$file$filename$filenum$firstplayer$flag$flipped$functions$ifhead$label$legalmoves$lastcaptured$map$maxmln$mline$mln$movenum$piecekeys$pieces$players$prison$puremoves$rank$rankname$ranknum$set$settings$space$scope$starpath$status$sub$submit$userset$uservar;
   7. 
   8.     static 
$target,  $screen;
   9.     static 
$operators = array(
  10. 
"!=" => "2"
  11. 
"!==" => "2"
  12. 
"%" => "2"
  13. 
"&" => "2"
  14. 
"&&" => "1|2"
  15. 
"*" => "2"
  16. 
"+" => "2"
  17. 
"-" => "2"
  18. 
"." => "2"
  19. 
"." => "2"
  20. 
"/" => "2"
  21. 
"<" => "2"
  22. 
"<<" => "2"
  23. 
"<=" => "2"
  24. 
"==" => "2"
  25. 
"===" => "2"
  26. 
">" => "2"
  27. 
">=" => "2"
  28. 
">>" => "2"
  29. 
"abs" => "1"
  30. 
"alias" => "1"
  31. 
"and" => "1|2"
  32. 
"args" => "0",
  33. 
"asort" => "1",
  34. 
"base" => "2"
  35. 
"baseurl" => "0"
  36. 
"behindscreen" => "3"
  37. 
"best2drop" => "0"
  38. 
"best2free" => "0"
  39. 
"bitand" => "2"
  40. 
"bitnot" => "1"
  41. 
"bitor" => "2"
  42. 
"bits" => "1",
  43. 
"bitxor" => "2"
  44. 
"boardflags" => "0"
  45. 
"capture" => "0"
  46. 
"captured" => "0"
  47. 
"capturedpieces" => "0",
  48. 
"char" => "2",
  49. 
"chars" => "1",
  50. 
"check" => "1"
  51. 
"checkahop" => "4a"
  52. 
"checkaleap" => "4a"
  53. 
"checkaride" => "4a"
  54. 
"checkgrasshop" => "4s"
  55. 
"checkhop" => "4s"
  56. 
"checkleap" => "4s"
  57. 
"checklongleap" => "4s"
  58. 
"checkmaxsteps"=> "3"
  59. 
"checknsteps" => "3"
  60. 
"checkrhombus" => "2"
  61. 
"checkride" => "4s"
  62. 
"chr" => "1"
  63. 
"cmp" => "2"
  64. 
"color" => "1"
  65. 
"cond" => "3"
  66. 
"const" => "1"
  67. 
"count" => "1"
  68. 
"currentpieces" => "0",
  69. 
"dec" => "1"
  70. 
"dechex" => "1"
  71. 
"diff" => "2",
  72. 
"direction" => "2"
  73. 
"distance" => "2"
  74. 
"div" => "2"
  75. 
"elem" => "2"
  76. 
"empty" => "1"
  77. 
"equal" => "2"
  78. 
"eval" => "1"
  79. 
"even" => "1"
  80. 
"excode" => "0"
  81. 
"explode" => "2"
  82. 
"false" => "0"
  83. 
"fencode" => "0"
  84. 
"file" => "1"
  85. 
"filename" => "1"
  86. 
"findinhand" => "1"
  87. 
"firstrankname" => "0"
  88. 
"flag" => "1"
  89. 
"flags" => "0"
  90. 
"flipcase" => "1",
  91. 
"flipimg" => "1",
  92. 
"fnmatch" => "2",
  93. 
"function" => "1",
  94. 
"gcd" => "2",
  95. 
"global" => "1"
  96. 
"greater" => "2"
  97. 
"hamming" => "2",
  98. 
"hasalnum" => "1",
  99. 
"hasalpha" => "1",
 100. 
"hasdigit" => "1",
 101. 
"haslower" => "1",
 102. 
"hasupper" => "1",
 103. 
"hexdec" => "1"
 104. 
"htmllink" => "2"
 105. 
"hyphen" => "0"
 106. 
"identical" => "2"
 107. 
"inc" => "1",
 108. 
"int" => "1",
 109. 
"insight" => "3"
 110. 
"invisible" => "1"
 111. 
"isalnum" => "1"
 112. 
"isalpha" => "1"
 113. 
"isarray" => "1",
 114. 
"isconst" => "1"
 115. 
"isdigit" => "1"
 116. 
"isfunc" => "1"
 117. 
"islower" => "1"
 118. 
"isopponent" => "0",
 119. 
"isplayer" => "0",
 120. 
"isplayer1" => "0",
 121. 
"isplayer2" => "0",
 122. 
"isset" => "1"
 123. 
"issub" => "1"
 124. 
"isupper" => "1"
 125. 
"isvisible" => "1"
 126. 
"join" => "2"
 127. 
"keys" => "1"
 128. 
"ksort" => "1",
 129. 
"lambda" => "1"
 130. 
"lastfile" => "0"
 131. 
"lastmoved" => "0"
 132. 
"lastrank" => "0"
 133. 
"lastrankname" => "0"
 134. 
"leaps" => "3",
 135. 
"leftstr" => "2",
 136. 
"less" => "2"
 137. 
"levenshtein" => "2",  
 138. 
"literal" => "1"
 139. 
"markedlegal" => "1"
 140. 
"max" => "2"
 141. 
"maxmovenum" => "0",
 142. 
"merge" => "1|2"
 143. 
"min" => "2"
 144. 
"minus" => "2"
 145. 
"mln" => "0"
 146. 
"mod" => "2"
 147. 
"move" => "1"
 148. 
"movenum" => "0"
 149. 
"mult" => "2"
 150. 
"nand" => "2",
 151. 
"natsort" => "1"
 152. 
"near" => "3"
 153. 
"neg" => "1",
 154. 
"nil" => "0"
 155. 
"nolower" => "0"
 156. 
"nor" => "2"
 157. 
"not" => "1"
 158. 
"noupper" => "0"
 159. 
"null" => "0"
 160. 
"odd" => "1"
 161. 
"onboard" => "1"
 162. 
"onebits" => "1"
 163. 
"onfile" => "2"
 164. 
"onlyif" => "1|2"
 165. 
"onlylower" => "0"
 166. 
"onlyupper" => "0"
 167. 
"opponent" => "0"
 168. 
"or" => "1|2"
 169. 
"ord" => "1",
 170. 
"path" => "2"
 171. 
"piececount" => "0",
 172. 
"pieceimg" => "1",
 173. 
"piecekeys" => "0"
 174. 
"pieces" => "0"
 175. 
"pieceset" => "0",
 176. 
"plus" => "2"
 177. 
"pow" => "2",  
 178. 
"rand" => "2"
 179. 
"range" => "2"
 180. 
"rank" => "1"
 181. 
"rankname" => "1"
 182. 
"ray" => "3"
 183. 
"rays" => "3"
 184. 
"realname" => "1"
 185. 
"regmatch" => "2"
 186. 
"remove" => "1"
 187. 
"revealed" => "2"
 188. 
"reverse" => "1"
 189. 
"ride" => "3",
 190. 
"rightstr" => "2",
 191. 
"same" => "2"
 192. 
"samecase" => "2"
 193. 
"screen" => "0"
 194. 
"search" => "2",
 195. 
"shuffle" => "1",
 196. 
"sign" => "1"
 197. 
"slope" => "2"
 198. 
"space" => "1"
 199. 
"spaces" => "0"
 200. 
"status" => "0"
 201. 
"str_replace" => "3",
 202. 
"string" => "1"
 203. 
"strlen" => "1"
 204. 
"strstr" => "2"
 205. 
"submit" => "0"
 206. 
"substr" => "3"
 207. 
"system" => "1"
 208. 
"target" => "1"
 209. 
"thismove" => "0",
 210. 
"thismovenum" => "0"
 211. 
"time" => "0"
 212. 
"tolower" => "1"
 213. 
"toupper" => "1"
 214. 
"trim" => "1|2"
 215. 
"true" => "0"
 216. 
"turn" => "0"
 217. 
"twinonfile" => "1",
 218. 
"type" => "1",
 219. 
"unequal" => "2"
 220. 
"unique" => "1"
 221. 
"unless" => "1|2"
 222. 
"urlencode" => "1"
 223. 
"user" => "0"
 224. 
"var" => "1",
 225. 
"var_export" => "1",
 226. 
"void" => "0"
 227. 
"voidride" => "4s"
 228. 
"what" => "2|3"
 229. 
"where" => "2|3"
 230. 
"whitespace" => "0"
 231. 
"ws" => "0"
 232. 
"xor" => "2"
 233. 
"|" => "2"
 234. 
"||" => "1|2"); 
 235. 
 236.     
$higherscope $scope 1;
 237.     
$output = array();
 238.     
// $substitions = func_num_args() ? func_get_arg (1) : NULL;
 239.     // $substitutions = func_num_args() ? func_get_arg (1) : NULL;
 240.     
if (!empty($myvars) && is_array($myvars)) {
 241.         
$scope $higherscope;
 242.         
$sub[$scope] = $sub[$scope 1];
 243.         
$ifhead[$scope] = "func";
 244.         foreach (
$myvars as $key => $val) {
 245.             
$uservar[$scope][$sub[$scope]][$key] = $val;
 246.         }
 247.     }
 248.     while (
count($input) > 0) {
 249.         
$arg array_pop($input);
 250.         
// debug2("arg type",  gettype($arg));
 251.         
if (!is_string($arg)) {
 252.             
array_push ($output,  $arg);
 253.             continue;
 254.         }
 255.         
$car = empty($arg[0]) ? "" $arg[0];
 256.         
$cdr substr($arg1);
 257.         if (
$car == "#") {
 258.             if (
ctype_digit($cdr) && isset($substitutions[$cdr])) {
 259.                 
array_push ($output$substitutions[$cdr]);
 260.                 continue;
 261.             }
 262.             
array_push ($outputevalvar($arg));
 263.             continue;
 264.         }
 265.         elseif (!empty(
$cdr) && (($car == "?") || ($car == "$") || ($car == "@"))) {
 266.             
array_push ($outputevalvar($arg));
 267.             continue;
 268.         }
 269.         elseif (
$car == "=") {
 270.             
$scope $higherscope;
 271.             
$sub[$scope] = $sub[$scope 1];
 272.             
$ifhead[$scope] = "func";
 273.             if (!empty(
$cdr) && ctype_alpha($cdr[0]) && ctype_alnum($cdr)) {
 274.                 if (empty(
$output)) {
 275.                     if (!empty(
$substitutions))
 276.                         
$uservar[$scope][$sub[$scope]][$cdr] = array_pop($substitutions);
 277.                 }
 278.                 elseif (
count($output) == 1) {
 279.                     
$uservar[$scope][$sub[$scope]][$cdr] = array_pop($output);
 280.                 }
 281.                 else {
 282.                     
$uservar[$scope][$sub[$scope]][$cdr] = $output;
 283.                     
$output = array();
 284.                 }
 285.                 continue;
 286.             }
 287.         }
 288.         if (isset(
$operators[$arg]))
 289.             
$opcase $operators[$arg];
 290.         elseif (
$car == "#")
 291.             
$opcase "0";
 292.         else
 293.             
$opcase "default";
 294.         switch (
$opcase) {
 295.             case 
"0":    // nullary operators
 296.                 
switch ($arg) {
 297.                     case 
"args":
 298.                         
array_push ($output$substitutions);
 299.                         break;
 300.                     case 
"baseurl":
 301.                         
array_push ($output,  PLAY_SCRIPT "?");
 302.                         break;
 303.                     case 
"best2drop"// Designed for Hostage Chess
 304.                     // Returns highest valued piece in hand
 305.                         
array_push ($output,  best2drop());
 306.                         break;
 307.                     case 
"best2free"// Designed for Hostage Chess
 308.                     // Returns highest valued piece in opponent's prison
 309.                         
array_push ($output,  best2free());
 310.                         break;
 311.                     case 
"boardflags"// Returns sorted list of spaces with flags set
 312.                         
array_push ($output,  boardflags());
 313.                         break;
 314.                     case 
"capture"// Boolean: was last move a capture?
 315.                         
array_push ($output,  (($lastcaptured != "@") && ($lastcaptured != "-")));
 316.                         break;
 317.                     case 
"captured"// Returns piece captured on last move
 318.                     // Returns @ if move was to empty space
 319.                         
array_push ($output,  $lastcaptured);
 320.                         break;
 321.                     case 
"capturedpieces"// Calculates up-to-date list of captured pieces for the current move
 322.                         
array_push ($outputcapturedpieces());
 323.                         break;
 324.                     case 
"currentpieces"// Calculates up-to-date list of pieces currently on the board
 325.                         
array_push ($outputcurrentpieces());
 326.                         break;
 327.                     case 
"destination"// Returns destination of last move
 328.                         
array_push ($output,  $dest);
 329.                         break;
 330.                     case 
"excode"// Returns expanded FEN code,  an array
 331.                     // representing the original position.
 332.                         
array_push ($output,  $excode);
 333.                         break;
 334.                     case 
"false"// Returns Boolean value of false
 335.                         
array_push ($output,  false);
 336.                         break;
 337.                     case 
"fencode"// Returns FEN code for current position
 338.                         
array_push ($output,  fencode());
 339.                         break;
 340.                     case 
"flags"// Returns an array of all flags
 341.                         
array_push ($output,  $flag);
 342.                         break;
 343.                     case 
"hyphen"// Returns the hyphen character
 344.                         
array_push ($output,  "-");
 345.                         break;
 346.                     case 
"isopponent":
 347.                         
array_push ($output, ($_SESSION["userid"] ?? "") == $GLOBALS["opponent"]);
 348.                         break;
 349.                     case 
"isplayer":
 350.                         
array_push ($output, ($_SESSION["userid"] ?? "") == $GLOBALS["player"]);
 351.                         break;
 352.                     case 
"isplayer1":
 353.                         if (!empty(
$_SESSION["userid"]) && !empty($players)) {
 354.                             list(
$player1$player2) = explode(" "$players);
 355.                             
array_push ($output$_SESSION["userid"] == $player1);
 356.                         }
 357.                         else
 358.                             
array_push ($outputfalse);
 359.                         break;
 360.                     case 
"isplayer2":
 361.                         if (!empty(
$_SESSION["userid"]) && !empty($players)) {
 362.                             list(
$player1$player2) = explode(" "$players);
 363.                             
array_push ($output$_SESSION["userid"] == $player2);
 364.                         }
 365.                         else
 366.                             
array_push ($outputfalse);
 367.                         break;
 368.                     case 
"lastfile"// Returns numeric index of last file
 369.                         
array_push ($output,  count($file)-1);
 370.                         break;
 371.                     case 
"lastmoved":
 372.                         
array_push ($output,  $lastmoved);
 373.                         break;
 374.                     case 
"lastrank"// Returns numeric index of last rank
 375.                         
array_push ($output,  count($rank)-1);
 376.                         break;
 377.                     case 
"mln"// Returns index value of array of moves
 378.                         
array_push ($output,  $mln);
 379.                         break;
 380.                     case 
"maxmovenum":
 381.                         if (!empty(
$mline[$maxmln]))
 382.                             
array_push ($output,  $mline[$maxmln]->movenum);
 383.                         else
 384.                             
array_push ($output0);
 385.                         break;
 386.                     case 
"movenum"// Returns latest move number in game, 
 387.                     // no matter how far along the code is in evaluating the moves
 388.                         
array_push ($output,  $movenum);
 389.                         break;
 390.                     case 
"nil"// Returns value of empty space,  the @ string
 391.                         
array_push ($output,  "@");
 392.                         break;
 393.                     case 
"nolower"// Returns array of all piece labels not 
 394.                     // entirely lowercase.
 395.                         
array_push ($output,  array_filter($space,  "notlower"));
 396.                         break;
 397.                     case 
"noupper":
 398.                         
array_push ($output,  array_filter($space,  "notupper"));
 399.                         break;
 400.                     case 
"null"// Returns NULL value
 401.                         
array_push ($output,  NULL);
 402.                         break;
 403.                     case 
"onlylower":
 404.                         
array_push ($output,  array_filter($space,  "ctype_lower"));
 405.                         break;
 406.                     case 
"onlyupper":
 407.                         
array_push ($output,  array_filter($space,  "ctype_upper"));
 408.                         break;
 409.                     case 
"opponent":
 410.                         
array_push ($output,  $GLOBALS["opponent"]);
 411.                         break;
 412.                     case 
"piececount":
 413.                         
$temp = array();
 414.                         foreach (
$space as $p) {
 415.                             if ((
$p != "@") && ($p != "-"))
 416.                                 
$temp[$p] = isset($temp[$p]) ? $temp[$p] + 1;
 417.                         }
 418.                         
array_push ($output,  $temp);
 419.                         break;
 420.                     case 
"piecekeys":
 421.                         
array_push ($output,  is_array($piecekeys) ? $piecekeys : array());
 422.                         break;
 423.                     case 
"pieces":
 424.                         
array_push ($output,  $space);
 425.                         break;
 426.                     case 
"pieceset":
 427.                         if (empty(
$userset) || empty($GLOBALS[$userset]))
 428.                             
array_push ($output$set);
 429.                         else
 430.                             
array_push ($output$GLOBALS[$userset]);
 431.                         break;
 432.                     case 
"screen":
 433.                         
array_push ($output,  $screen);
 434.                         break;
 435.                     case 
"spaces":
 436.                         
array_push ($output,  array_keys($space));
 437.                         break;
 438.                     case 
"status":
 439.                         
array_push ($output,  $status);
 440.                         break;
 441.                     case 
"submit":
 442.                         
array_push ($output,  $submit);
 443.                         break;
 444.                     case 
"thismove":
 445.                         if (!empty(
$mline[$mln]))
 446.                             
array_push ($output,  trim($mline[$mln]->move,  " ;\t\n\r\0\x0B"));
 447.                         else
 448.                             
array_push ($outputnull);
 449.                         break;
 450.                     case 
"thismovenum":
 451.                         if (!empty(
$mline[$mln]))
 452.                             
array_push ($output,  $mline[$mln]->movenum);
 453.                         else
 454.                             
array_push ($output0);
 455.                         break;
 456.                     case 
"time":
 457.                         
array_push ($output,  time());
 458.                         break;
 459.                     case 
"true":
 460.                         
array_push ($output,  true);
 461.                         break;
 462.                     case 
"turn":
 463.                         
array_push ($output,  $mline[$mln]->turn);
 464.                         break;
 465.                     case 
"user":
 466.                         
array_push ($output,  $_SESSION["userid"] ?? "");
 467.                         break;
 468.                     case 
"void":
 469.                         
array_push ($output,  "-");
 470.                         break;
 471.                     case 
"whitespace": case "ws":
 472.                         
array_push ($output,  " ");
 473.                         break;
 474.                     
// Substitutions for function placeholders
 475.                     
case (($arg[0] == "#") ? $arg "false"):
 476.                         
$n substr($arg,  1);
 477.                         
array_push ($output,  (ctype_digit($n) && isset($substitutions[$n])) ? $substitutions[$n] : $arg);
 478.                         break;
 479.                 }
 480.                 break;
 481.             case 
"1":    // Unary operators
 482.                 // This mysteriously caused an error in a line without the designated operator.
 483.                 // if (count($output) < 1)
 484.                     // error("The {$arg} operator requires at least 1 argument.", $linenum);
 485.                 
$op1 array_pop ($output);
 486.                 switch (
$arg) {        
 487.                     case 
"abs":
 488.                         
array_push ($output,  abs($op1));
 489.                         break;
 490.                     case 
"alias":
 491.                         if (!
is_array($op1))
 492.                             
array_push ($output,  isset($ALIAS[$op1]) ? $ALIAS[$op1] : $op1);
 493.                         else
 494.                             
array_push ($outputnull);
 495.                         break;
 496.                     case 
"asort":
 497.                         
asort($op1);
 498.                         
array_push ($output,  $op1);
 499.                         break;
 500.                     case 
"bitnot":
 501.                         
array_push ($output,  ~$op1);
 502.                         break;
 503.                     case 
"bits":
 504.                         
$bits 0;
 505.                         while (
$op1) {
 506.                             
$bits++;
 507.                             
$op1 >>= 1;
 508.                         }
 509.                         
array_push ($output,  $bits);
 510.                         break;
 511.                     case 
"chars":
 512.                         
array_push($outputstr_split($op11));
 513.                         break;
 514.                     case 
"check":
 515.                         
// debug2 ("target",  $target);
 516.                         // debug2 ("op1",  $op1);
 517.                         
if (($target == $op1) || (is_array($target) && in_array($op1,  $target))) {
 518.                             
$output = array(true);
 519.                             
$input = array();
 520.                         }
 521.                         
// debug2 ("match?",  is_array($target) && in_array($op1,  $target));
 522.                         
break;
 523.                     case 
"chr":
 524.                         
array_push ($output,  chr($op1));
 525.                         break;
 526.                     case 
"color":
 527.                         
array_push ($output,  $background[$op1] ?? NULL);
 528.                         break;
 529.                     case 
"const":
 530.                         if (isset(
$constants) && is_array($constants) && !is_array($op1) && array_key_exists($op1$constants))
 531.                             
array_push ($output,  $constants[$op1]);
 532.                         else
 533.                             
array_push ($outputNULL);
 534.                         break;
 535.                     case 
"count":
 536.                         
array_push ($output,  is_array($op1) ? count($op1) : 0);
 537.                         break;
 538.                     case 
"count_values":
 539.                         
array_push ($output,  array_count_values($op1));
 540.                         break;
 541.                     case 
"dec":
 542.                         
array_push ($output,  $op1-1);
 543.                         break;
 544.                     case 
"dechex":
 545.                         
array_push ($output,  dechex($op1));
 546.                         break;
 547.                     case 
"empty":
 548.                         
array_push ($output,  isset($space[$op1]) && ($space[$op1] == "@"));
 549.                         
// debug2("space[$op1] == ",  $space[$op1]);
 550.                         
break;
 551.                     case 
"eval":
 552.                         
array_push ($output,  polish($op1$linenum$substitutions));
 553.                         break;
 554.                     case 
"even":
 555.                         
array_push ($output,  ((int)$op1 1)==0);
 556.                         break;
 557.                     case 
"findinhand":
 558.                         
array_push ($output,  findpiece($op1,  $starpath[$firstplayer]));
 559.                         break;
 560.                     case 
"file":
 561.                         
array_push ($output,  isset($filenum[$op1]) ? $filenum[$op1] : false);
 562.                         break;
 563.                     case 
"filename":
 564.                         
array_push ($output,  isset($filename[$op1]) ? $filename[$op1] : (isset($file[$op1]) ? $file[$op1] : ""));
 565.                         break;
 566.                     case 
"flag":
 567.                         
// Since flags are Booleans, this works.
 568.                         
array_push ($output,  !empty($flag[$op1]));
 569.                         break;
 570.                     case 
"flipcase":
 571.                         
array_push ($output,  flipcase($op1));
 572.                         break;
 573.                     case 
"flipimg":
 574.                         
array_push ($output$flipped[$op1] ?? $pieces[$op1] ?? "");
 575.                         break;
 576.                     case 
"global": case "system":
 577.                         switch (
$op1) {
 578.                             case 
"answered":
 579.                             case 
"board":
 580.                             case 
"cases":
 581.                             case 
"code":
 582.                             case 
"columns":
 583.                             case 
"debug":
 584.                             case 
"dest":
 585.                             case 
"dir":
 586.                             case 
"lastcaptured":
 587.                             case 
"lastmoved":
 588.                             case 
"legalmoves":
 589.                             case 
"maxmln";
 590.                             case 
"maxmove":
 591.                             case 
"movelist";
 592.                             case 
"moves":
 593.                             case 
"noerrorcheck":
 594.                             case 
"omitmoves":
 595.                             case 
"orientation":
 596.                             case 
"origin":
 597.                             case 
"originalpieces":
 598.                             case 
"piecekeys":
 599.                             case 
"piecevals":
 600.                             case 
"prison":
 601.                             case 
"sets":
 602.                             case 
"showoutput":
 603.                             case 
"side";
 604.                             case 
"space";
 605.                             case 
"starpath":
 606.                             case 
"submit":
 607.                                 
array_push ($output,  $GLOBALS[$op1]);
 608.                                 break;
 609.                             default:
 610.                                 
error ("No variable named \${$op1} has been whitelisted for the <b>{$arg}</b> function.",  $linenum);
 611.                         }
 612.                         break;
 613.                     case 
"hasalnum":
 614.                         
array_push ($outputhasalnum($op1));
 615.                         break;
 616.                     case 
"hasalpha":
 617.                         
array_push ($outputhasalpha($op1));
 618.                         break;
 619.                     case 
"hasdigit":
 620.                         
array_push ($outputhasdigit($op1));
 621.                         break;
 622.                     case 
"haslower":
 623.                         
array_push ($outputhaslower($op1));
 624.                         break;
 625.                     case 
"hasupper":
 626.                         
array_push ($outputhasupper($op1));
 627.                         break;
 628.                     case 
"hexdec":
 629.                         
array_push ($output,  hexdec($op1));
 630.                         break;
 631.                     case 
"inc":
 632.                         
array_push ($output,  $op1+1);
 633.                         break;
 634.                     case 
"int":
 635.                         if (
$op1[0] == 0) {
 636.                             if (
$op1[1] == "x")
 637.                                 
$base 16;
 638.                             elseif (
$op1[1] == "b")
 639.                                 
$base 2;
 640.                             else
 641.                                 
$base 7;
 642.                         }
 643.                         else
 644.                             
$base 10;
 645.                         
array_push ($outputintval($op1$base));
 646.                         break;    
 647.                     case 
"isalnum":
 648.                         
array_push ($output,  ctype_alnum((string)$op1));
 649.                         break;
 650.                     case 
"isalpha":
 651.                         
array_push ($output,  ctype_alpha((string)$op1));
 652.                         break;
 653.                     case 
"isarray":
 654.                         
array_push ($output,  is_array($op1));
 655.                         break;
 656.                     case 
"isconst":
 657.                         
array_push ($output,  is_array($constants) && array_key_exists($op1,  $constants));
 658.                         break;
 659.                     case 
"isdigit":
 660.                         
array_push ($output,  ctype_digit($op1));
 661.                         break;
 662.                     case 
"isfunc":
 663.                         
array_push ($output,  isset($functions[$op1]));
 664.                         break;
 665.                     case 
"islower":
 666.                         
array_push ($output,  ctype_lower((string)$op1));
 667.                         break;
 668.                     case 
"isset":
 669.                         
array_push ($output,  issetuservar($op1));
 670.                         break;
 671.                     case 
"issub":
 672.                         
array_push ($output,  isset($label[$op1]));
 673.                         break;
 674.                     case 
"isupper":
 675.                         
array_push ($output,  ctype_upper((string)$op1));
 676.                         break;
 677.                     case 
"invisible":
 678.                         
array_push($output,  ($filename[$op1][0] == "!") || ($rankname[$op1][0] == "!"));
 679.                         break;
 680.                     case 
"isvisible":
 681.                         
array_push($output,  (isset($filename[$op1][0]) && ($filename[$op1][0] != "!")) && (isset($rankname[$op1][0]) && ($rankname[$op1][0] != "!")));
 682.                         break;
 683.                     case 
"keys":
 684.                         
array_push ($output,  array_keys($op1));
 685.                         break;
 686.                     case 
"ksort":
 687.                         
ksort($op1);
 688.                         
array_push ($output,  $op1);
 689.                         break;
 690.                     case 
"lambda":
 691.                         if (
is_array($op1))
 692.                             
array_push ($output,  new Lambda($op1));
 693.                         elseif (isset(
$functions[$op1]))
 694.                             
array_push ($output,  new Lambda($functions[$op1]));
 695.                         elseif (
strstr($op1,  " "))
 696.                             
array_push ($output,  new Lambda(explode(" ",  $op1)));
 697.                         else {
 698.                             
$result = new Lambda($output);
 699.                             unset(
$output);
 700.                             
$output[0] = $result;
 701.                         }
 702.                         break;                        
 703.                     case 
"literal":
 704.                         if (
$op1 instanceof Lambda)
 705.                             
array_push ($output,  array_literal($op1->stack));
 706.                         elseif (
is_array($op1))
 707.                             
array_push ($output,  array_literal($op1));
 708.                         elseif (isset(
$functions[$op1]))
 709.                             
array_push ($output,  function_literal($functions[$op1]));
 710.                         else
 711.                             
array_push ($output,  $op1);
 712.                         break;
 713.                     case 
"markedlegal":
 714.                         
array_push ($outputin_array($op1$legalmoves) ? true false);
 715.                         break;
 716.                     case 
"move":
 717.                         
array_push ($output$puremoves[$op1] ?? "");
 718.                         break;
 719.                     case 
"natsort":
 720.                         
natsort($op1);
 721.                         
array_push ($output,  $op1);
 722.                         break;
 723.                     case 
"neg":
 724.                         
array_push ($output,  -$op1);
 725.                         break;
 726.                     case 
"not":
 727.                         
array_push ($output,  ((array)$op1 === $op1) ? !polish($op1$linenum$substitutions) : !$op1);
 728.                         break;
 729.                     case 
"odd":
 730.                         
array_push ($output,  (int)$op1 1);
 731.                         break;
 732.                     case 
"onboard":
 733.                         if (
is_array($op1))
 734.                             
badinput ("onboard expects a string, not an array.");
 735.                         
array_push ($output,  (!empty($space[(string)$op1])&&($space[(string)$op1] != "-")));
 736.                         break;
 737.                     case 
"onebits":
 738.                         
$bits0;
 739.                         
$op1 intval($op1);
 740.                         while (
$op1) {
 741.                             if (
$op1 1)
 742.                                 
$bits++;
 743.                             
$op1 >>= 1;
 744.                         }                            
 745.                         
array_push ($output,  $bits);
 746.                         break;
 747.                     case 
"ord":
 748.                         
array_push ($output,  ord($op1));
 749.                         break;
 750.                     case 
"pieceimg":
 751.                         
array_push ($output$pieces[$op1] ?? "");
 752.                         break;
 753.                     case 
"rank":
 754.                         
array_push ($output,  get_ranknum($op1));
 755.                         break;
 756.                     case 
"rankname":
 757.                         
array_push ($output,  isset($rankname[$op1]) ? $rankname[$op1] : (isset($rank[$op1]) ? $rank[$op1] : ""));
 758.                         break;
 759.                     case 
"realname":
 760.                         
array_push ($output,  isset($REALNAME[$op1]) ? $REALNAME[$op1] : $op1);
 761.                         break;
 762.                     case 
"remove":
 763.                         if (
is_array($op1)) {
 764.                             foreach (
$op1 as $val) {
 765.                                 if (
array_key_exists($val$space))
 766.                                     
$space[$val] = '@';
 767.                                 else
 768.                                     
error_log (strval($val) . " is not in \$space");
 769.                             }
 770.                         }
 771.                         else    
 772.                             
$space[$op1] = '@';
 773.                         
$output = array(true);
 774.                         
$input = array();
 775.                         break;
 776.                     case 
"reverse":
 777.                         if ((array)
$op1 === $op1)
 778.                             
array_push ($output,  array_reverse($op1,  false));
 779.                         else
 780.                             
array_push ($output,  strrev($op1));
 781.                         break;
 782.                     case 
"shuffle":
 783.                         
array_push($outputshufflearray($op1));
 784.                         break;
 785.                     case 
"sign":
 786.                         
array_push ($output,  (($op1 0) ? -: (($op1 0) ? 0)));
 787.                         break;
 788.                     case 
"space":
 789.                         
array_push ($output,  empty($space[$op1]) ? false $space[$op1]);
 790.                         
// debug2("<FONT COLOR=\"red\">space == </FONT>",  $space);
 791.                         
break;
 792.                     case 
"string":
 793.                         if (
is_array($op1))
 794.                             
array_push($outputimplode(""$op1));
 795.                         else
 796.                             
array_push($outputstrval($op1));
 797.                         break;
 798.                     case 
"strlen":
 799.                         
array_push ($output,  strlen($op1));
 800.                         break;
 801.                     case 
"target":
 802.                         
$target $op1;
 803.                         
// returns no value. used with check.
 804.                         
break;
 805.                     case 
"tolower":
 806.                         
array_push ($output,  strtolower($op1));
 807.                         break;
 808.                     case 
"toupper":
 809.                         
array_push ($output,  strtoupper($op1));
 810.                         break;
 811.                     case 
"twinonfile":
 812.                         foreach (
$rank as $key => $val) {
 813.                             if (
$ranknum[$op1] == $key)
 814.                                 continue;
 815.                             
$c $filename[$op1] . $val;
 816.                             if (
$space[$op1] == $space[$c])
 817.                                 break;
 818.                         }
 819.                         
array_push ($output,  ($space[$op1] == $space[$c]));
 820.                         break;
 821.                     case 
"type":
 822.                         
array_push ($outputgettype($op1));
 823.                         break;
 824.                     case 
"unique":
 825.                         
array_push ($output,  array_unique($op1));
 826.                         break;
 827.                     case 
"urlencode":
 828.                         
array_push ($output,  urlencode($op1));
 829.                         break;
 830.                     case 
"var":
 831.                         
array_push ($output,  getuservar($op1));
 832.                         break;
 833.                     case 
"var_export":
 834.                         
array_push ($output,  var_export($op1true));
 835.                         break;
 836.                 }
 837.                 break;
 838.             case 
"1|2":
 839.                 
// This caused an error with an and operator
 840.                 // if (count($output) < 1)
 841.                     // error("The {$arg} operator requires at least 1 argument.", $linenum);
 842.                 // debug2 ("BEFORE AND Output",  $output);
 843.                 
if (count($output) == 1) {
 844.                     
$op1 array_pop ($output);
 845.                     
$op2 NULL;
 846.                 }
 847.                 else {
 848.                     
$op1 array_pop ($output);
 849.                     
$op2 array_pop ($output);
 850.                 }
 851.                 switch (
$arg) {
 852.                     case 
"and": case "&&":
 853.                         
// debug2 ("AND op1",  $op1);
 854.                         // debug2 ("AND op2",  ($op2 !== NULL) ? $op2 : "NULL");
 855.                         
if ($op2 === NULL) {
 856.                             if (((array)
$op1 === $op1) ? !polish($op1$linenum$substitutions) : !$op1) {
 857.                                 
// debug2 ("FALSE",  "FALSE");
 858.                                 
$output = array(false);
 859.                                 
$input = array();
 860.                             }
 861.                             
// debug2 ("AND1 output",  $output);
 862.                         
}
 863.                         else {
 864.                             
$output[] = (((array)$op1 === $op1) ? polish($op1$linenum$substitutions) : $op1) && (((array)$op2 === $op2) ? polish($op2$linenum$substitutions) : $op2);
 865.                             
// debug2("AND2 Output",  $output);
 866.                         
}
 867.                         break;
 868.                     case 
"merge":
 869.                     
// Just in case merge gets NULL for one value
 870.                         
$ar1 is_array($op1) ? $op1 : array($op1);
 871.                         
$ar2 is_array($op2) ? $op2 : array($op2);
 872.                         
array_push ($output,  array_merge($ar1,  $ar2));
 873.                         break;
 874.                     case 
"onlyif":
 875.                         if (
$op1 == false) {
 876.                             
$output = array(($op2 === NULL) ? $op1 $op2);
 877.                             
$input = array();
 878.                         }
 879.                         break;
 880.                     case 
"or": case "||":
 881.                         
// debug2 ("op1",  $op1);
 882.                         // debug2 ("op2",  $op2);
 883.                         
if ($op2 === NULL) {
 884.                             if (((array)
$op1 === $op1) ? polish($op1$linenum$substitutions) : $op1) {
 885.                                 
$output = array(true);
 886.                                 
$input = array();
 887.                             }
 888.                         }
 889.                         else
 890.                             
$output[] = (((array)$op1 === $op1) ? polish($op1$linenum$substitutions) : $op1
 891.                             || (((array)
$op2 === $op2) ? polish($op2$linenum$substitutions) : $op2);
 892.                         break;
 893.                     case 
"trim":
 894.                         if (
$op2 === NULL)
 895.                             
array_push ($output,  trim($op1));
 896.                         else
 897.                             
array_push ($output,  trim($op1,  $op2));
 898.                         break;                        
 899.                     case 
"unless":
 900.                         if (
$op1 != false) {
 901.                             
$output = array(($op2 === NULL) ? false $op2);
 902.                             
$input = array();
 903.                         }
 904.                         break;
 905.                 }
 906.                 break;
 907.             case 
"2":
 908.                 if (
count($output) < 2)
 909.                     
error ("The {$arg} operator requires at least two arguments."$linenum);
 910.                 
 911.                 
$op1 array_pop($output);
 912.                 
$op2 array_pop($output);
 913.                 switch (
$arg) {
 914.                     case 
"!==":
 915.                         
array_push ($output,  ($op1 !== $op2));
 916.                         break;
 917.                     case 
"<=":
 918.                         
array_push ($output,  ($op1 <= $op2));
 919.                         break;
 920.                     case 
">=":
 921.                         
array_push ($output,  ($op1 >= $op2));
 922.                         break;
 923.                     case 
"<<":
 924.                         
array_push ($output,  ($op1 << $op2));
 925.                         break;
 926.                     case 
">>":
 927.                         
array_push ($output,  ($op1 >> $op2));
 928.                         break;
 929.                     case 
"base":
 930.                         
// op1 is base, op2 is number
 931.                         
array_push ($output,  base_convert($op2,  10,  $op1));
 932.                         break;
 933.                     case 
"bitand": case "&":
 934.                         
array_push($output,  ((int)$op1 & (int)$op2));
 935.                         break;
 936.                     case 
"bitor": case "|":
 937.                         
array_push($output,  ((int)$op1 | (int)$op2));
 938.                         break;
 939.                     case 
"bitxor":
 940.                         
array_push($output,  ((int)$op1 ^ (int)$op2));
 941.                         break;
 942.                     case 
"char":
 943.                         if (!
is_string($op1))
 944.                             
error("The char function requires the first operand to be a string."$linenum);
 945.                         if (
$op2 strlen($op1))
 946.                             
array_push ($output"");
 947.                         else
 948.                             
array_push ($output,  $op1[$op2]);
 949.                         break;
 950.                     case 
"checkrhombus":
 951.                         
$f1 $filenum[$op1]; $r1 $ranknum[$op1];
 952.                         
$f2 $filenum[$op2]; $r2 $ranknum[$op2];
 953.                         
$fdist abs($f1-$f2);
 954.                         
$rdist abs($r1-$r2);
 955.                         
$mindist min($fdist,  $rdist);
 956.                         
$maxdist max($fdist,  $rdist);
 957.                         if (
$maxdist != 2*$mindist)
 958.                             
$legal false;
 959.                         else {
 960.                             
$legal true;
 961.                             
$xdir = ($f2-$f1)/$fdist;
 962.                             
$ydir = ($r2-$r1)/$rdist;
 963.                             if (
$fdist $rdist) {
 964.                                 for (
$i 1$i <= $mindist$i++) {
 965.                                     
$c $file[$f1 $i*$xdir] . $rank[$r1];
 966.                                     if (
$space[$c] != "@") {
 967.                                         
$legal false;
 968.                                         break;
 969.                                     }
 970.                                 }
 971.                                 if (
$legal == true) {
 972.                                     for (
$i 1$i <= $mindist$i++) {
 973.                                         
$c $file[$f2 $i*$xdir] . $rank[$r2 $i*$ydir];
 974.                                         if (
$space[$c] != "@") {
 975.                                             
$legal false;
 976.                                             break;
 977.                                         }
 978.                                     }
 979.                                 }
 980.                                 if (
$legal == false) {
 981.                                     
$legal true;
 982.                                     for (
$i 1$i <= $mindist$i++) {
 983.                                         
$c $file[$f1 $i*$xdir] . $rank[$r1 $i*$ydir];
 984.                                         if (
$space[$c] != "@") {
 985.                                             
$legal false;
 986.                                             break;
 987.                                         }
 988.                                     }
 989.                                     if (
$legal == true) {
 990.                                         for (
$i 1$i <= $mindist$i++) {
 991.                                             
$c $file[$f2 $i*$xdir] . $rank[$r2];
 992.                                             if (
$space[$c] != "@") {
 993.                                                 
$legal false;
 994.                                                 break;
 995.                                             }
 996.                                         }
 997.                                     }
 998.                                 }
 999.                             }
1000.                             else {
1001.                                 for (
$i 1$i <= $mindist$i++) {
1002.                                     
$c $file[$f1] . $rank[$r1 $i*$ydir];
1003.                                     if (
$space[$c] != "@") {
1004.                                         
$legal false;
1005.                                         break;
1006.                                     }
1007.                                 }
1008.                                 if (
$legal == true) {
1009.                                     for (
$i 1$i <= $mindist$i++) {
1010.                                         
$c $file[$f2 $i*$xdir] . $rank[$r2 $i*$ydir];
1011.                                         if (
$space[$c] != "@") {
1012.                                             
$legal false;
1013.                                             break;
1014.                                         }
1015.                                     }
1016.                                 }
1017.                                 if (
$legal == false) {
1018.                                     
$legal true;
1019.                                     for (
$i 1$i <= $mindist$i++) {
1020.                                         
$c $file[$f1 $i*$xdir] . $rank[$r1 $i*$ydir];
1021.                                         if (
$space[$c] != "@") {
1022.                                             
$legal false;
1023.                                             break;
1024.                                         }
1025.                                     }
1026.                                     if (
$legal == true) {
1027.                                         for (
$i 1$i <= $mindist$i++) {
1028.                                             
$c $file[$f2] . $rank[$r2 $i*$ydir];
1029.                                             if (
$space[$c] != "@") {
1030.                                                 
$legal false;
1031.                                                 break;
1032.                                             }
1033.                                         }
1034.                                     }
1035.                                 }
1036.                             }
1037.                         }
1038.                         
array_push ($output,  $legal);
1039.                         break;                                        
1040.                     case 
"cmp":
1041.                         
array_push ($output,  ($op1 == $op2) ? : (($op1 $op2) ? : -1));
1042.                         break;
1043.                     case 
"diff":
1044.                         
$ar1 is_array($op1) ? $op1 : array($op1);
1045.                         
$ar2 is_array($op2) ? $op2 : array($op2);
1046.                         
array_push ($output,  array_diff($ar1,  $ar2));
1047.                         break;
1048.                     case 
"direction":
1049.                         
$f1 get_filenum($op1);
1050.                         if (!
is_numeric($f1))
1051.                             
error("First argument {$op1} has no file number"$linenum);
1052.                         
$r1 get_ranknum($op1);
1053.                         if (!
is_numeric($r1))
1054.                             
error("First argument {$op1} has no rank number"$linenum);
1055.                         
$f2 get_filenum($op2);
1056.                         if (!
is_numeric($f2))
1057.                             
error("Second argument {$op2} has no file number"$linenum);
1058.                         
$r2 get_ranknum($op2);
1059.                         if (!
is_numeric($r2))
1060.                             
error("Second argument {$op2} has no rank number"$linenum);
1061.                         
$rd $r2 $r1;
1062.                         
$fd $f2 $f1;
1063.                         
$gd gcd(abs($rd),  abs($fd));
1064.                         if (
$gd != 0) {
1065.                             
$rd /= $gd;
1066.                             
$fd /= $gd;
1067.                         }
1068.                         
$d = ($rd 0) ? str_pad("",  abs($rd),  "s") : str_pad("",  $rd,  "n");
1069.                         
$d .= ($fd 0) ? str_pad("",  abs($fd),  "w") : str_pad("",  $fd,  "e");
1070.                         
array_push ($output,  $d $d false);
1071.                         break;
1072.                     case 
"distance":
1073.                         
$f1 get_filenum($op1);
1074.                         if (!
is_numeric($f1))
1075.                             
error("First argument {$op1} has no file number"$linenum);
1076.                         
$r1 get_ranknum($op1);
1077.                         if (!
is_numeric($r1))
1078.                             
error("First argument {$op1} has no rank number"$linenum);
1079.                         
$f2 get_filenum($op2);
1080.                         if (!
is_numeric($f2))
1081.                             
error("Second argument {$op2} has no file number"$linenum);
1082.                         
$r2 get_ranknum($op2);
1083.                         if (!
is_numeric($r2))
1084.                             
error("Second argument {$op2} has no rank number"$linenum);
1085.                         
$rd abs ($r2 $r1);
1086.                         
$fd abs ($f2 $f1);
1087.                         
array_push ($output,  max($rd,  $fd));
1088.                         break;
1089.                     case 
"div": case "/":
1090.                         
array_push ($output,  (($op1 - ($op1 $op2)) / $op2));
1091.                         break;
1092.                     case 
"elem":
1093.                         if ((array)
$op1 === $op1)
1094.                             
$op1 current($op1);
1095.                         if ((array)
$op2 === $op2) {
1096.                             
array_push ($output,  $op2[$op1] ?? NULL);
1097.                         }
1098.                         else {
1099.                             
array_push ($output,  getuservar("{$op2}.{$op1}"));
1100.                         }
1101.                         break;
1102.                     case 
"equal": case "==":
1103.                         
array_push ($output,  ($op1 == $op2));
1104.                         break;
1105.                     case 
"explode":
1106.                         if (empty(
$op1))
1107.                             
array_push ($outputstr_split($op21));
1108.                         else
1109.                             
array_push ($output,  explode($op1,  $op2));
1110.                         break;
1111.                     case 
"fnmatch":
1112.                         
array_push ($output,  fnmatch($op1,  $op2));
1113.                         break;
1114.                     case 
"gcd":
1115.                         
array_push($output,  gcd($op1,  $op2));
1116.                         break;
1117.                     case 
"greater": case ">":
1118.                         
array_push ($output,  ($op1 $op2));
1119.                         break;
1120.                     case 
"hamming":
1121.                         
$l strlen($op1);
1122.                         if (
$l != strlen($op2))
1123.                             
error ("The hamming function requires two strings of the same length.",  $linenum);
1124.                         for (
$i 0,  $hd 0$i $l$i++) {
1125.                             if (
$op1[$i] != $op2[$i])
1126.                                 
$hd++;
1127.                         }
1128.                         
array_push ($output,  $hd);
1129.                         break;
1130.                     case 
"htmllink":
1131.                         
array_push ($output,  "<A HREF=\"{$op1}\">{$op2}</A>");
1132.                         break;
1133.                     case 
"identical": case "===":
1134.                         
array_push ($output,  ($op1 === $op2));
1135.                         break;
1136.                     case 
"join": case ".":
1137.                         if (((array)
$op1 === $op1) || ((array)$op2 === $op2)) {
1138.                             
$newarray = array();
1139.                             if ((array)
$op1 !== $op1) {
1140.                                 foreach (
$op1 as $e1)
1141.                                     
array_push ($newarray,  $e1 $op2);
1142.                             }
1143.                             elseif ((array)
$op2 !== $op2) {
1144.                                 foreach (
$op2 as $e2)
1145.                                     
array_push ($newarray,  $op1 $e2);
1146.                             }
1147.                             else {
1148.                                 foreach (
$op2 as $e2)
1149.                                     foreach (
$op1 as $e1)
1150.                                         
array_push ($newarray,  $e1 $e2);
1151.                             }
1152.                             
array_push ($output,  $newarray);
1153.                         }
1154.                         else
1155.                             
array_push ($output,  $op1 $op2);
1156.                         break;
1157.                     case 
"leftstr":
1158.                         
array_push ($outputsubstr($op10$op2));
1159.                         break;
1160.                     case 
"less": case "<":
1161.                         
array_push ($output,  ($op1 $op2));
1162.                         break;
1163.                     case 
"levenshtein":
1164.                         
array_push ($output,  levenshtein($op1,  $op2));
1165.                         break;
1166.                     case 
"max":
1167.                         
array_push ($output,  max($op1,  $op2));
1168.                         break;
1169.                     case 
"min":
1170.                         
array_push ($output,  min($op1,  $op2));
1171.                         break;
1172.                     case 
"minus": case "-":
1173.                         if (
is_string($op1)) {
1174.                             if (
substr_count($op1".") == 1)
1175.                                 
$op1 floatval($op1);
1176.                             else
1177.                                 
$op1 intval($op1);
1178.                         }
1179.                         if (
is_string($op2)) {
1180.                             if (
substr_count($op2".") == 1)
1181.                                 
$op2 floatval($op2);
1182.                             else
1183.                                 
$op2 intval($op2);
1184.                         }
1185.                         if (
is_numeric($op1) && is_numeric($op2))
1186.                             
array_push ($output,  ($op1 $op2));
1187.                         else
1188.                             
error ("<B>minus</B> or <B>-</B> was used with a non-numeric value."$linenum);
1189.                         break;
1190.                     case 
"mod": case "%":
1191.                         
// x mod y = x - floor(x/y)*y
1192.                         // The % operator will return a division by zero error.
1193.                         // But since anything multiplied by zero should be zero, 
1194.                         // the value of (x/y) becomes irrelevant when y is 0.
1195.                         // The product of 0 * (x/0) should still be 0.
1196.                         // Since x - 0 = x,  the value of x is returned.
1197.                         
array_push ($output,  ($op2 ? ($op1 $op2) : $op1));
1198.                         break;
1199.                     case 
"mult": case "*":
1200.                         
array_push ($output,  ($op1 $op2));
1201.                         break;
1202.                     case 
"nand":
1203.                         
// De Morgans: (!p or !q) == !(p and q) == p nand q
1204.                         
$output[] = !(((array)$op1 === $op1) ? polish($op1$linenum$substitutions) : $op1) || !(((array)$op2 === $op2) ? polish($op2$linenum$substitutions) : $op2);
1205.                         break;
1206.                     case 
"nor":
1207.                         
// De Morgans: (!p and !q) == !(p or q) == neither p nor q
1208.                         
$output[] = !(((array)$op1 === $op1) ? polish($op1$linenum$substitutions) : $op1) && !(((array)$op2 === $op2) ? polish($op2$linenum$substitutions) : $op2);
1209.                         break;
1210.                     case 
"onfile":
1211.                         foreach (
$rank as $key => $val) {
1212.                             
$c $op1 $val;
1213.                             if (
$space[$c] == $op2)
1214.                                 break;
1215.                         }
1216.                         
array_push ($output,  ($op2 == $space[$c]));
1217.                         break;
1218.                     case 
"path":
1219.                         if (
array_key_exists($op1$space) && array_key_exists($op2$space)) {
1220.                             
$f1 get_filenum($op1); $r1 get_ranknum($op1);
1221.                             
$f2 get_filenum($op2); $r2 get_ranknum($op2);
1222.                             
$rd $r2 $r1;
1223.                             
$fd $f2 $f1;
1224.                             
$gd gcd(abs($rd),  abs($fd));
1225.                             if (
$gd) {
1226.                                 
$rd /= $gd;
1227.                                 
$fd /= $gd;
1228.                             }
1229.                             
$newarray = array();
1230.                             do {
1231.                                 
$f1 += $fd;
1232.                                 
$r1 += $rd;
1233.                                 
$c get_file($f1) . get_rank($r1);
1234.                                 if (
$c == $op2)
1235.                                     break;
1236.                                 
$newarray[] = $c;
1237.                             } while (
1);
1238.                             
// return $newarray;
1239.                             
array_push ($output,  $newarray);
1240.                         }
1241.                         else
1242.                             
array_push ($output, array());
1243.                         break;
1244.                     case 
"plus": case "+":
1245.                         if (
is_numeric($op1) && is_numeric($op2))
1246.                             
array_push ($output,  ($op1 $op2));
1247.                         else
1248.                             
array_push ($output0);
1249.                         break;
1250.                     case 
"pow":
1251.                         
array_push ($output,  pow($op1,  $op2));
1252.                         break;
1253.                     case 
"rand":
1254.                         
array_push ($output,  mt_rand($op1,  $op2));
1255.                         break;
1256.                     case 
"range":
1257.                         
array_push ($output,  range($op1,  $op2));
1258.                         break;
1259.                     case 
"regmatch":
1260.                         
array_push ($output,  preg_match($op1,  $op2));
1261.                         break;
1262.                     case 
"revealed":
1263.                         
$f1 get_filenum($op1); $r1 get_ranknum($op1);
1264.                         
$f2 get_filenum($op2); $r2 get_ranknum($op2);
1265.                         
$rd $r2 $r1;
1266.                         
$fd $f2 $f1;
1267.                         
$gd gcd(abs($rd),  abs($fd));
1268.                         if (
$gd) {
1269.                             
$rd /= $gd;
1270.                             
$fd /= $gd;
1271.                         }
1272.                         do {
1273.                             
$f1 += $fd;
1274.                             
$r1 += $rd;
1275.                             if (isset(
$file[$f1]) && isset($rank[$r1]))
1276.                                 
$c $file[$f1] . $rank[$r1];
1277.                             else
1278.                                 
$c "";
1279.                         } while (isset(
$space[$c]) && ($space[$c] == "@"));
1280.                         
array_push ($output,  isset($space[$c]) ? $c false);
1281.                         break;
1282.                     case 
"rightstr":
1283.                         
array_push ($outputsubstr($op1, -$op2));
1284.                         break;
1285.                     case 
"same":
1286.                         
array_push ($output,  !strcasecmp($op1,  $op2));
1287.                         break;
1288.                     case 
"samecase":
1289.                         
$case1 $case2 0;
1290.                         if (
$op1 != strtoupper($op1)) $case1 |= 1;
1291.                         if (
$op1 != strtolower($op1)) $case1 |= 2;
1292.                         if (
$op2 != strtoupper($op2)) $case2 |= 1;
1293.                         if (
$op2 != strtolower($op2)) $case2 |= 2;
1294.                         
array_push ($output,  ($case1 == $case2));
1295.                         break;
1296.                     case 
"search":
1297.                         
array_push ($output,  array_search($op1,  $op2));
1298.                         break;
1299.                     case 
"slope":
1300.                         
$f1 $filenum[$op1] ?? 0$r1 $ranknum[$op1] ?? 0;
1301.                         
$f2 $filenum[$op2] ?? 0$r2 $ranknum[$op2] ?? 0;
1302.                         
$d $f1-$f2;
1303.                         
array_push ($output,  $d ? ($r1 $r2)/$d 0);
1304.                         break;
1305.                     case 
"strstr":
1306.                         if (!
is_string($op1) || !is_string($op2))
1307.                             
error ("Tried to pass non-string to strstr"$linenum);
1308.                         
array_push ($output,  strstr($op1,  $op2));
1309.                         break;
1310.                     case 
"unequal": case "!=":
1311.                         
array_push ($output,  ($op1 != $op2));
1312.                         break;
1313.                     case 
"union":
1314.                         if (isset(
$op1) && is_array($op1))
1315.                             if (isset(
$op2) && is_array($op2))
1316.                                 
$newarray array_merge($op1,  $op2);
1317.                             else {
1318.                                 
$newarray $op1;
1319.                                 
array_push($$newarray,  $op2);
1320.                             }
1321.                         elseif (
is_array($op2)) {
1322.                             
$newarray $op2;
1323.                             
array_push($newarray,  $op1);
1324.                         }
1325.                         else
1326.                             
$newarray = array($op1,  $op2);
1327.                         
array_push ($output,  $newarray);
1328.                         break;                            
1329.                     case 
"xor":
1330.                         
array_push ($output,  ($op1 xor $op2));
1331.                         break;
1332.                 }
1333.                 break;
1334.             case 
"2|3":
1335.                 if (
count($output) < 2)
1336.                     
error("The {$arg} operator requires at least two arguments."$linenum);
1337.                 
$op1 array_pop($output);
1338.                 
$op2 array_pop($output);
1339.                 
$op3 array_pop($output);
1340.                 switch (
$arg) {
1341.                     case 
"what":
1342.                     case 
"where":
1343.                         if (
$op3 === NULL) {
1344.                             
// Use logical directions if the third argument is absent
1345.                             
if (array_key_exists($op1$map) && is_array($map[$op1])) {
1346.                                 if (
is_array($op2)) {
1347.                                 
// $op2 should be an array containing a series of logical directions.
1348. //                                    echo "<P>where {$op1} " . implode($op2) . "</P>";
1349.                                     
$c $op1;
1350.                                     foreach (
$op2 as $d) {
1351. 
//                                        echo "<P>d is {$d}</P>";
1352.                                         
if (array_key_exists($d$map[$c])) {
1353.                                             
$c $map[$c][$d];
1354. 
//                                            echo "<P>c is {$c}</P>";
1355.                                         
}
1356.                                         else {
1357.                                             
$c false;
1358. 
//                                            echo "<P>c is false</P>";
1359.                                             
break;
1360.                                         }
1361.                                     }
1362.                                 }
1363.                                 elseif (
array_key_exists($op2,  $map[$op1]))
1364.                                     
$c $map[$op1][$op2]; // $op2 should be a single logical direction
1365.                             
}
1366.                             else
1367.                                 
$c false;
1368.                         }
1369.                         else {
1370.                             
// $op2 and $op3 are the number of files and ranks away that the space to be identified is
1371.                             
$f get_filenum($op1); $r get_ranknum($op1);
1372.                             
$f += (int)$op2;
1373.                             
$r += (int)$op3;
1374.                             
$c get_file($f) . get_rank($r);
1375.                         }
1376.                         if (
$arg == "what")
1377.                             
array_push ($output, empty($space[$c]) ? false $space[$c]);
1378.                         else
1379.                             
array_push ($output, (empty($c) || !array_key_exists($c$space)) ? false $c);
1380.                         break;
1381.                 }
1382.                 break;
1383.             case 
"3":
1384.                 if (
count($output) < 3)
1385.                     
error("The {$arg} operator requires at least three arguments."$linenum);
1386.                 
$op1 array_pop($output);
1387.                 
$op2 array_pop($output);
1388.                 
$op3 array_pop($output);
1389.                 switch (
$arg) {
1390.                     case 
"behindscreen":
1391.                         
$f $filenum[$op1]; $r $ranknum[$op1];
1392.                         for (
$hops 0$hops 2$hops++) {
1393.                             do {
1394.                                 
$f += $op2;
1395.                                 
$r += $op3;
1396.                                 
$c get_file($f) . get_rank($r);
1397.                             } while (isset(
$space[$c]) && ($space[$c] == "@"));
1398.                         }
1399.                         
array_push ($output,  isset($space[$c]) ? $space[$c] : false);
1400.                         break;    
1401.                     case 
"checknsteps": case "checkmaxsteps":
1402.                         
$f1 $filenum[$op1]; $r1 $ranknum[$op1];
1403.                         
$f2 $filenum[$op2]; $r2 $ranknum[$op2];
1404.                         if ((
$f1 === false) || ($f2 === false))
1405.                             
$ret false;
1406.                         else {
1407.                             
$occupant $space[$op1];
1408.                             
$space[$op1] = "@";
1409.                             
$ret checknsteps($f1,  $r1,  $f2,  $r2,  $op3,  $arg == "checkmaxsteps");
1410.                             
$space[$op1] = $occupant;
1411.                         }
1412.                         
array_push ($output,  $ret);
1413.                         break;
1414.                     case 
"cond":
1415.                         if (
$op1) {
1416.                             if ((array)
$op2 === $op2)
1417.                                 
$op2 polish($op2$linenum$substitutions);
1418.                             
array_push ($output$op2);
1419.                         }
1420.                         else {
1421.                             if ((array)
$op3 === $op3)
1422.                                 
$op3 polish($op3$linenum$substitutions);
1423.                             
array_push ($output$op3);
1424.                         }
1425.                         
/*
1426.                         array_push (
1427.                             $output,  $op1 ?
1428.                                 (
1429.                                     ((array)$op2 === $op2)
1430.                                     ?
1431.                                     polish($op2, $linenum, $substitutions)
1432.                                     :
1433.                                     $op2
1434.                                 ) 
1435.                                 :
1436.                                 (
1437.                                     ((array)$op3 === $op3)
1438.                                     ?
1439.                                     polish($op3, $linenum, $substitutions)
1440.                                     :
1441.                                     $op3
1442.                                 )
1443.                         );
1444.                         */
1445.                         
break;
1446.                     case 
"insight":
1447.                         
$f get_filenum($op1); $r get_ranknum($op1);
1448.                         
$c "";
1449.                         do {
1450.                             
$f += $op2;
1451.                             
$r += $op3;
1452.                             if (!isset(
$file[$f]) || !isset($rank[$r]))
1453.                                 break;
1454.                             
$c $file[$f] . $rank[$r];
1455.                         } while (isset(
$space[$c]) && ($space[$c] == "@"));
1456.                         
array_push ($output,  isset($space[$c]) ? $space[$c] : false);
1457.                         break;
1458.                     case 
"leaps":
1459.                         
$f get_filenum($op1); $r get_ranknum($op1);
1460.                         
$op2 abs($op2);
1461.                         
$op3 abs($op3);
1462.                         
$temp = array();
1463.                         if (isset(
$file[$f $op2]) && isset($rank[$r $op3]))
1464.                             
$temp[] = $file[$f $op2] . $rank[$r $op3];
1465.                         if (
$op2 && isset($file[$f $op2]) && isset($rank[$r $op3]))
1466.                             
$temp[] = $file[$f $op2] . $rank[$r $op3];
1467.                         if (
$op3 && isset($rank[$r $op3])) {
1468.                             if (isset(
$file[$f $op2]))
1469.                                 
$temp[] = $file[$f $op2] . $rank[$r $op3];
1470.                             if (
$op2 && isset($file[$f $op2]))
1471.                                 
$temp[] = $file[$f $op2] . $rank[$r $op3];
1472.                         }
1473.                         if (
$op2 != $op3) {
1474.                             if (isset(
$file[$f $op3]) && isset($rank[$r $op2]))
1475.                                 
$temp[] = $file[$f $op3] . $rank[$r $op2];
1476.                             if (
$op3 && isset($file[$f $op3]) && isset($rank[$r $op2]))
1477.                                 
$temp[] = $file[$f $op3] . $rank[$r $op2];
1478.                             if (
$op2 && isset($rank[$r $op2])) {
1479.                                 if (isset(
$file[$f $op3]))
1480.                                     
$temp[] = $file[$f $op3] . $rank[$r $op2];
1481.                                 if (
$op3 && isset($file[$f $op3]))
1482.                                     
$temp[] = $file[$f $op3] . $rank[$r $op2];
1483.                             }
1484.                         }
1485.                         
$leaps = array();
1486.                         
$max count($temp);
1487.                         for (
$j 0$j $max$j++)
1488.                             if (isset(
$space[$temp[$j]]))
1489.                                 
$leaps[] = $temp[$j];
1490.                         
array_push ($output,  $leaps);
1491.                         break;
1492.                     case 
"near"// coordinate,  piece,  distance
1493.                         
$f get_filenum($op1); $r get_ranknum($op1);
1494.                         
$ret false;
1495.                         
$maxx min(count($file)-1,  $f+$op3);
1496.                         
$maxy min(count($rank)-1,  $r+$op3);
1497.                         for (
$x max(0$f $op3); $x <= $maxx$x++) {
1498.                             for (
$y max(0,  $r $op3); $y <= $maxy$y++) {
1499.                                 
$c $file[$x] . $rank[$y];
1500.                                 if (
$space[$c] == $op2) {
1501.                                     
$ret $c;
1502.                                     break 
2;
1503.                                 }
1504.                             }
1505.                         }
1506.                         
array_push ($output,  $ret);
1507.                         break;
1508.                     case 
"ray":
1509.                         
$temp = array();
1510.                         if (
array_key_exists($op1$filenum) && array_key_exists($op1$ranknum)) {
1511.                             
$f get_filenum($op1); $r get_ranknum($op1);
1512.                             for (
$i 1true$i++) {
1513.                                 if ((
get_file($f $i*$op2"null") == "null") || (get_rank($r $i*$op3"null") == "null"))
1514.                                     break;
1515.                                 
$c get_file($f $i*$op2) . get_rank($r $i*$op3);
1516.                                 if (!
array_key_exists($c$space))
1517.                                     break;
1518.                                 
$temp[] = $c;
1519.                             }
1520.                         }
1521.                         
array_push ($output,  $temp);
1522.                         break;
1523.                     case 
"rays":
1524.                         
$temp = array();
1525.                         if (isset(
$filenum[$op1]) && isset($ranknum[$op1])) {
1526.                             
$f $filenum[$op1]; $r $ranknum[$op1];
1527.                             
$op2 abs($op2);
1528.                             
$op3 abs($op3);
1529.                             if (
$space[$op1]) {
1530.                                 for (
$i 1true$i++) {
1531.                                     if (!isset(
$file[$f $i*$op2]) || !isset($rank[$r $i*$op3]))
1532.                                         break;
1533.                                     
$c $file[$f $i*$op2] . $rank[$r $i*$op3];
1534.                                     if (empty(
$space[$c]))
1535.                                         break;
1536.                                     
$temp[] = $c;
1537.                                 }
1538.                                 if (
$op3) {
1539.                                     for (
$i 1true$i++) {
1540.                                         if (!isset(
$file[$f $i*$op2]) || !isset($rank[$r $i*$op3]))
1541.                                             break;
1542.                                         
$c $file[$f $i*$op2] . $rank[$r $i*$op3];
1543.                                         if (empty(
$space[$c]))
1544.                                             break;
1545.                                         
$temp[] = $c;
1546.                                     }
1547.                                 }
1548.                                 if (
$op2) {
1549.                                     for (
$i 1true$i++) {
1550.                                         if (!isset(
$file[$f $i*$op2]) || !isset($rank[$r $i*$op3]))
1551.                                             break;
1552.                                         
$c $file[$f $i*$op2] . $rank[$r $i*$op3];
1553.                                         if (empty(
$space[$c]))
1554.                                             break;
1555.                                         
$temp[] = $c;
1556.                                     }
1557.                                 }
1558.                                 if (
$op2 && $op3) {
1559.                                     for (
$i 1true$i++) {
1560.                                         if (!isset(
$file[$f $i*$op2]) || !isset($rank[$r $i*$op3]))
1561.                                             break;
1562.                                         
$c $file[$f $i*$op2] . $rank[$r $i*$op3];
1563.                                         if (empty(
$space[$c]))
1564.                                             break;
1565.                                         
$temp[] = $c;
1566.                                     }
1567.                                 }
1568.                                 if (
$op2 != $op3) {
1569.                                     for (
$i 1true$i++) {
1570.                                         if (!isset(
$file[$f $i*$op3]) || !isset($rank[$r $i*$op2]))
1571.                                             break;
1572.                                         
$c $file[$f $i*$op3] . $rank[$r $i*$op2];
1573.                                         if (empty(
$space[$c]))
1574.                                             break;
1575.                                         
$temp[] = $c;
1576.                                     }
1577.                                     if (
$op2) {
1578.                                         for (
$i 1true$i++) {
1579.                                             if (!isset(
$file[$f $i*$op3]) || !isset($rank[$r $i*$op2]))
1580.                                                 break;
1581.                                             
$c $file[$f $i*$op3] . $rank[$r $i*$op2];
1582.                                             if (empty(
$space[$c]))
1583.                                                 break;
1584.                                             
$temp[] = $c;
1585.                                         }
1586.                                     }
1587.                                     if (
$op3) {
1588.                                         for (
$i 1true$i++) {
1589.                                             if (!isset(
$file[$f $i*$op3]) || !isset($rank[$r $i*$op2]))
1590.                                                 break;
1591.                                             
$c $file[$f $i*$op3] . $rank[$r $i*$op2];
1592.                                             if (empty(
$space[$c]))
1593.                                                 break;
1594.                                             
$temp[] = $c;
1595.                                         }
1596.                                     }
1597.                                     if (
$op2 && $op3) {
1598.                                         for (
$i 1true$i++) {
1599.                                             if (!isset(
$file[$f $i*$op3]) || !isset($rank[$r $i*$op2]))
1600.                                                 break;
1601.                                             
$c $file[$f $i*$op3] . $rank[$r $i*$op2];
1602.                                             if (empty(
$space[$c]))
1603.                                                 break;
1604.                                             
$temp[] = $c;
1605.                                         }
1606.                                     }
1607.                                 }
1608.                             }
1609.                         }
1610.                         
array_push ($output,  $temp);
1611.                         break;
1612.                     case 
"ride":
1613.                         
$f get_filenum($op1); $r get_ranknum($op1);
1614.                         
$ride = array();
1615.                         do {
1616.                             
$f $f $op2;
1617.                             
$r $r $op3;
1618.                             if (empty(
$file[$f]) || empty($rank[$r])) {
1619.                                 
$c "";
1620.                                 break;
1621.                             }
1622.                             
$c get_file($f) . get_rank($r);
1623.                             if (!isset(
$space[$c]) || ($space[$c] == "-"))
1624.                                 break;
1625.                             
$ride[] = $c;
1626.                         } while (
$space[$c] == "@");
1627.                         
array_push ($output,  $ride);
1628.                         break;
1629.                     case 
"str_replace":
1630.                         
array_push ($output,  str_replace($op1,  $op2,  $op3 ?? ""));
1631.                         break;
1632.                     case 
"substr":
1633.                         
array_push ($output,  $op3 substr($op1,  $op2,  $op3) : substr($op1,  $op2));
1634.                         break;
1635.                 }                            
1636.                 break;            
1637.             case 
"4a":    // Checks asymmetrically-defined moves
1638.                 
if (count($output) < 4)
1639.                     
error("The {$arg} operator requires at least four arguments."$linenum);
1640.                 
$op1 array_pop($output);
1641.                 
$op2 array_pop($output);
1642.                 
$op3 array_pop($output);
1643.                 
$op4 array_pop($output);
1644.                 
// debug2 ("op1",  $op1);// debug2 ("op2",  $op2);// debug2 ("op3",  $op3);// debug2 ("op4",  $op4);
1645.                 
$f1 get_filenum($op1); $r1 get_ranknum($op1);
1646.                 
$f2 get_filenum($op2); $r2 get_ranknum($op2);
1647.                 
$fmove $f2 $f1;
1648.                 
$rmove $r2 $r1;
1649.                 
// debug2("fmove",  $fmove); // debug2("rmove",  $rmove);
1650.                 
$result = (($fmove == $op3) && ($rmove == $op4));
1651.                 switch (
$arg) {
1652.                     case 
"checkaleap":
1653.                         
array_push ($output,  $result);
1654.                         break;
1655.                     case 
"checkaride":
1656.                         if (
$result)
1657.                             
array_push ($output,  true); // made single leap in right direction
1658.                         
elseif (($fmove $op4) != ($rmove $op3))
1659.                             
array_push ($output,  false); // did not move multiple of basic leap
1660.                         
elseif ((sgn($fmove) != sgn($op3)) || (sgn($rmove) != sgn($op4)))
1661.                             
array_push ($output,  false); // wrong direction
1662.                         
else {
1663.                             
$rungs max(abs($fmove),  abs($rmove)) / max(abs($op3),  abs($op4));
1664.                             
$fstep $fmove $rungs;
1665.                             
$rstep $rmove $rungs;
1666.                             
// debug ("rungs",  $rungs);
1667.                             
for ($i 1$i <= $rungs$i++) {
1668.                                 
// debug2 ("i",  $i);
1669.                                 
$c $file[$f1 $i*$fstep] . $rank[$r1 $i*$rstep];
1670.                                 
// debug2 ("c",  $c);
1671.                                 
if (($c == $op2) || ($space[$c] != "@"))
1672.                                     break;
1673.                             }
1674.                             
array_push ($output,  ($c == $op2));
1675.                         }
1676.                         break;
1677.                     case 
"checkahop":
1678.                         if (
$result)
1679.                             
array_push ($output,  false); // made single leap,  not hopping over anything
1680.                         
elseif (($fmove $op4) != ($rmove $op3))
1681.                             
array_push ($output,  false); // did not move multiple of basic leap
1682.                         
elseif ((sgn($fmove) != sgn($op3)) || (sgn($rmove) != sgn($op4)))
1683.                             
array_push ($output,  false); // wrong direction
1684.                         
else {
1685.                             
$rungs = (max(abs($fmove),  abs($rmove)) / max(abs($op3),  abs($op4)));
1686.                             
$fstep $fmove $rungs;
1687.                             
$rstep $rmove $rungs;
1688.                             
$hops 0;
1689.                             for (
$i 1$i $rungs$i++) {
1690.                                 
$c $file[$f1 $i*$fstep] . $rank[$r1 $i*$rstep];
1691.                                 if (
$space[$c] == "-")
1692.                                     break;
1693.                                 if (
$space[$c] != "@") {
1694.                                     
$hops++;
1695.                                     if (
$hops == 1)
1696.                                         
$screen $c;
1697.                                 }
1698.                             }
1699.                             
array_push ($output,  (($space[$c] != "-") && ($hops == 1)));
1700.                         }
1701.                         break;
1702.                 }
1703.                 break;                
1704.             case 
"4s":  // Checks symmetrically-defined moves
1705.                 
if (count($output) < 4)
1706.                     
error("The {$arg} operator requires at least four arguments."$linenum);
1707.                 
$op1 array_pop($output);
1708.                 
$op2 array_pop($output);
1709.                 
$op3 abs(array_pop($output));
1710.                 
$op4 abs(array_pop($output));
1711.                 
$f1 get_filenum($op1); $r1 get_ranknum($op1);
1712.                 
$f2 get_filenum($op2); $r2 get_ranknum($op2);
1713.                 
$fdist abs($f2 $f1);
1714.                 
$rdist abs($r2 $r1);
1715.                 
$result = ((($fdist == $op3) && ($rdist == $op4)) || (($fdist == $op4) && ($rdist == $op3)));
1716.                 
// debug ("Result",  $result);
1717.                 
switch ($arg) {
1718.                     case 
"checkgrasshop":
1719.                         if (
$result)
1720.                             
array_push ($output,  false); // made only a single leap,  not hopping over anything
1721.                         
elseif ((($fdist $op3) != ($rdist $op4)) && (($rdist $op3) != ($fdist $op4)))
1722.                             
array_push ($output,  false); // distance moved is not multiple of basic leap
1723.                         
elseif ((($op3*$op4 == 0) && ($fdist*$rdist == 0)) && (max($fdist,  $rdist) % max($op3,  $op4))) {
1724.                             
array_push ($output,  false); // distance moved is not multiple of basic leap
1725.                         
}
1726.                         elseif (((
$op3==$op4) && ($fdist==$rdist)) && ($rdist $op3)) {
1727.                             
array_push ($output,  false); // distance moved is not multiple of basic leap
1728.                         
}                        
1729.                         else {
1730.                             
$rungs = (max($fdist,  $rdist) / max($op3,  $op4));
1731.                             
$fmove $f2 $f1;
1732.                             
$rmove $r2 $r1;
1733.                             
$fstep $fmove $rungs;
1734.                             
$rstep $rmove $rungs;
1735.                             do {
1736.                                 
$f1 += $fstep;
1737.                                 
$r1 += $rstep;
1738.                                 
$c get_file($f1"null") . get_rank($r1"null");
1739.                             } while (
array_key_exists($c$space) && ($space[$c] == "@"));
1740.                             if (
$c == $op2// no screen
1741.                                 
array_push ($output,  false);
1742.                             else {
1743.                                 
$screen $c;
1744.                                 
$f1 += $fstep;
1745.                                 
$r1 += $rstep;
1746.                                 
$c get_file($f1"null") . get_rank($r1"null");
1747.                                 
array_push ($output,  ($c == $op2));
1748.                             }
1749.                         }
1750.                         break;
1751.                     case 
"checkhop":
1752.                         if (
$result)
1753.                             
array_push ($output,  false); // made only a single leap,  not hopping over anything
1754.                         
elseif ((($fdist $op3) != ($rdist $op4)) && (($rdist $op3) != ($fdist $op4)))
1755.                             
array_push ($output,  false); // distance moved is not multiple of basic leap
1756.                         
elseif ((($op3*$op4 == 0) && ($fdist*$rdist == 0)) && (max($fdist,  $rdist) % max($op3,  $op4))) {
1757.                             
array_push ($output,  false); // distance moved is not multiple of basic leap
1758.                         
}
1759.                         elseif (((
$op3==$op4) && ($fdist==$rdist)) && ($rdist $op3)) {
1760.                             
array_push ($output,  false); // distance moved is not multiple of basic leap
1761.                         
}                        
1762.                         else {
1763.                             
$rungs = (max($fdist,  $rdist) / max($op3,  $op4));
1764.                             
$fmove $f2 $f1;
1765.                             
$rmove $r2 $r1;
1766.                             
$fstep $fmove $rungs;
1767.                             
$rstep $rmove $rungs;
1768.                             do {
1769.                                 
$f1 += $fstep;
1770.                                 
$r1 += $rstep;
1771.                                 
$c get_file($f1) . get_rank($r1);
1772.                             } while (
array_key_exists($c$space) && ($space[$c] == "@"));
1773.                             if (
$c == $op2// no screen
1774.                                 
array_push ($output,  false);
1775.                             else {
1776.                                 
$screen $c;
1777.                                 do {
1778.                                     
$f1 += $fstep;
1779.                                     
$r1 += $rstep;
1780.                                     
$c get_file($f1) . get_rank($r1);
1781.                                 } while ((
$c != $op2) && (array_key_exists($c$space) && ($space[$c] == "@")));
1782.                                 
array_push ($output,  ($c == $op2));
1783.                             }
1784.                         }
1785.                         break;
1786.                     case 
"checkleap":
1787.                         
array_push ($output,  $result);
1788.                         break;
1789.                     case 
"checklongleap":
1790.                         if (
$lastcaptured != "@")
1791.                             
array_push ($output,  false); // Longleapers don't capture by displacement
1792.                         
elseif ($result)
1793.                             
array_push ($output,  true); // made only a single leap,  not capturing
1794.                         
elseif ((($fdist $op3) != ($rdist $op4)) && (($rdist $op3) != ($fdist $op4)))
1795.                             
array_push ($output,  false); // distance moved is not multiple of basic leap
1796.                         
elseif ((($op3*$op4 == 0) && ($fdist*$rdist == 0)) && (max($fdist,  $rdist) % max($op3,  $op4))) {
1797.                             
array_push ($output,  false); // distance moved is not multiple of basic leap
1798.                         
}
1799.                         elseif (((
$op3==$op4) && ($fdist==$rdist)) && ($rdist $op3)) {
1800.                             
array_push ($output,  false); // distance moved is not multiple of basic leap
1801.                         
}                        
1802.                         else {
1803.                             
$rungs = (max($fdist,  $rdist) / max($op3,  $op4));
1804.                             
$fmove $f2 $f1;
1805.                             
$rmove $r2 $r1;
1806.                             
$fstep $fmove $rungs;
1807.                             
$rstep $rmove $rungs;
1808.                             for (
$i 1$i $rungs$i++) {
1809.                                 
$c get_file($f1 $i*$fstep) . get_rank($r1 $i*$rstep);
1810.                                 if ((
$space[$c] != "@") && ($space[$c] == $space[$c-1]))
1811.                                     break;
1812.                             }
1813.                             
array_push ($output,  (($space[$c] != "@") && ($space[$c] == $space[$c-1])));
1814.                         }
1815.                         break;
1816.                     case 
"checkride":
1817.                         if (
$result)
1818.                             
array_push ($output,  true); // made only a single leap
1819.                         
elseif ((($fdist $op3) != ($rdist $op4)) && (($rdist $op3) != ($fdist $op4))) {
1820.                             
array_push ($output,  false); // distance moved is not multiple of basic leap
1821.                         
}
1822.                         elseif (((
$op3*$op4 == 0) && ($fdist*$rdist == 0)) && (max($fdist,  $rdist) % max($op3,  $op4))) {
1823.                             
array_push ($output,  false); // distance moved is not multiple of basic leap
1824.                         
}
1825.                         elseif (((
$op3==$op4) && ($fdist==$rdist)) && ($rdist $op3)) {
1826.                             
array_push ($output,  false); // distance moved is not multiple of basic leap
1827.                         
}                        
1828.                         else {
1829.                             
$rungs = (max($fdist,  $rdist) / max($op3,  $op4));
1830.                             
$fmove $f2 $f1;
1831.                             
$rmove $r2 $r1;
1832.                             
$fstep $rungs ? ($fmove $rungs) : 0;
1833.                             
$rstep $rungs ? ($rmove $rungs) : 0;
1834.                             
$c "";
1835.                             for (
$i 1$i $rungs$i++) {
1836.                                 
$c get_file($f1 $i*$fstep) . get_rank($r1 $i*$rstep);
1837.                                 if (!
array_key_exists($c$space) || ($space[$c] != "@"))
1838.                                     break;
1839.                             }
1840.                             
array_push ($outputarray_key_exists($c$space) && ($space[$c] == "@"));
1841.                         }
1842.                         break;
1843.                     case 
"voidride":
1844.                         if (
$result)
1845.                             
array_push ($output,  true); // made only a single leap
1846.                         
elseif ((($fdist $op3) != ($rdist $op4)) && (($rdist $op3) != ($fdist $op4))) {
1847.                             
array_push ($output,  false); // distance moved is not multiple of basic leap
1848.                         
}
1849.                         elseif (((
$op3*$op4 == 0) && ($fdist*$rdist == 0)) && (max($fdist,  $rdist) % max($op3,  $op4))) {
1850.                             
array_push ($output,  false); // distance moved is not multiple of basic leap
1851.                         
}
1852.                         elseif (((
$op3==$op4) && ($fdist==$rdist)) && ($rdist $op3)) {
1853.                             
array_push ($output,  false); // distance moved is not multiple of basic leap
1854.                         
}                        
1855.                         else {
1856.                             
$rungs = (max($fdist,  $rdist) / max($op3,  $op4));
1857.                             
$fmove $f2 $f1;
1858.                             
$rmove $r2 $r1;
1859.                             
$fstep $rungs ? ($fmove $rungs) : 0;
1860.                             
$rstep $rungs ? ($rmove $rungs) : 0;
1861.                             for (
$i 1$i $rungs$i++) {
1862.                                 
$c get_file($f1 $i*$fstep) . get_rank($r1 $i*$rstep);
1863.                                 if (
$space[$c] != "-")
1864.                                     break;
1865.                             }
1866.                             
array_push ($output,  ($space[$c] == "-"));
1867.                         }
1868.                         break;
1869.                 }
1870.                 break;
1871.             default:
1872.                 switch (
$arg) {
1873.                     case 
"inrange":
1874.                     if (
count($output) < 4)
1875.                         
error("The {$arg} operator requires at least four arguments."$linenum);
1876.                         
$op1 array_pop($output);
1877.                         
$op2 array_pop($output);
1878.                         
$op3 array_pop($output);
1879.                         
$op4 array_pop($output);
1880.                         
$f $filenum[$op1]; $r $ranknum[$op1];
1881.                         for (
$i 0$i $op4$i++) {
1882.                             
$f += $op2;
1883.                             
$r += $op3;
1884.                             if (isset(
$file[$f]) && isset($rank[$r]))
1885.                                 
$c $file[$f] . $rank[$r];
1886.                             else
1887.                                 
$c "";
1888.                             if (!isset(
$space[$c]) || ($space[$c] != "@"))
1889.                                 break;
1890.                         }
1891.                         
array_push ($output,  isset($space[$c]) ? $space[$c] : false);
1892.                         break;
1893.                     case 
"voidleap":
1894.                         if (
count($output) < 2)
1895.                             
error("The {$arg} operator requires at least two arguments."$linenum);
1896.                         
$op1 array_pop($output);
1897.                         
$op2 array_pop($output);
1898.                         
$f1 get_filenum($op1); $r1 get_ranknum($op1);
1899.                         
$f2 get_filenum($op2); $r2 get_ranknum($op2);
1900.                         
$fmove $f2 $f1;
1901.                         
$rmove $r2 $r1;
1902.                         
$fd = ($fmove >= 0) ? : -1;
1903.                         
$rd = ($rmove >= 0) ? : -1;
1904.                         
// debug2 ("fd",  $fd);
1905.                         // debug2 ("rd",  $rd);
1906.                         
$temp $output;
1907.                         
$f $f1;
1908.                         
$r $r1;
1909.                         while (
count($output) > 1) {
1910.                             
$op3 abs(array_pop($output));
1911.                             
$op4 abs(array_pop($output));
1912.                             do {
1913.                                 
$f += $op3*$fd;
1914.                                 
$r += $op4*$rd;
1915.                                 
$c get_file($f"null") . get_rank($r"null");
1916.                             } while (
array_key_exists($c$space) && ($space[$c] == "-"));
1917.                         }
1918.                         if (
$c == $op2) {
1919.                             unset (
$output);
1920.                             unset (
$temp);
1921.                             
$output[0] = true;
1922.                         }
1923.                         else {
1924.                             
$f $f1;
1925.                             
$r $r1;
1926.                             while (
count($temp) > 1) {
1927.                                 
$op3 abs(array_pop($temp));
1928.                                 
$op4 abs(array_pop($temp));
1929.                                 do {
1930.                                     
$f += $op4*$fd;
1931.                                     
$r += $op3*$rd;
1932.                                     
$c get_file($f"null") . get_rank($r"null");
1933.                                 } while (
array_key_exists($c$space) && ($space[$c] == "-"));
1934.                             }
1935.                             unset (
$output);
1936.                             unset (
$temp);                    
1937.                             
$output[0] = ($c == $op2);
1938.                         }
1939.                         break;
1940.                     case 
"checkatwostep":
1941.                         if (
count($output) < 6)
1942.                             
error("The {$arg} operator requires at least six arguments."$linenum);
1943.                         
$op1 array_pop($output);
1944.                         
$op2 array_pop($output);
1945.                         
$op3 array_pop($output);
1946.                         
$op4 array_pop($output);
1947.                         
$op5 array_pop($output);
1948.                         
$op6 array_pop($output);
1949.                         
$f1 $filenum[$op1]; $r1 $ranknum[$op1];
1950.                         
$f2 $filenum[$op2]; $r2 $ranknum[$op2];
1951.                         if (((
$f2 $f1) != ($op3 $op5)) || (($r2 $r1) != ($op4 $op6)))
1952.                             
array_push ($output,  false); // Space cannot be reached by these two steps.
1953.                         
else {
1954.                             
$c get_file($f1 $op3"null") . get_rank($r1 $op4"null");
1955.                             
array_push ($output,  (($space[$c] ?? "") == "@"));
1956.                         }
1957.                         break;
1958.                     case 
"checktwostep":
1959.                         if (
count($output) < 6)
1960.                             
error("The {$arg} operator requires at least six arguments."$linenum);
1961.                         
$op1 array_pop($output);
1962.                         
$op2 array_pop($output);
1963.                         
$op3 abs(array_pop($output));
1964.                         
$op4 abs(array_pop($output));
1965.                         
$op5 abs(array_pop($output));
1966.                         
$op6 abs(array_pop($output));
1967.                         
$f1 get_filenum($op1); $r1 get_ranknum($op1);
1968.                         
$f2 get_filenum($op2); $r2 get_ranknum($op2);
1969.                         
$fdist abs($f2 $f1);
1970.                         
$rdist abs($r2 $r1);
1971.                         
$fsteps $op3 $op5;
1972.                         
$rsteps $op4 $op6;
1973.                         if (((
$fdist != $fsteps) || ($rdist != $rsteps)) && (($fdist != $rsteps) || ($rdist != $fsteps)))
1974.                             
array_push ($output,  false); // Space cannot be reached by these two steps.
1975.                         
else {
1976.                             
$fdir = (($f2 $f1) < 0) ? -1;
1977.                             
$rdir = (($r2 $r1) < 0) ? -1;
1978.                             if ((
$fdist == $fsteps) && ($rdist == $rsteps)) {
1979.                                 
$fstep $op3 $fdir;
1980.                                 
$rstep $op4 $rdir;
1981.                             }
1982.                             else {
1983.                                 
$fstep $op4 $fdir;
1984.                                 
$rstep $op3 $rdir;
1985.                             }
1986.                             
$passthru $file[$f1 $fstep] . $rank[$r1 $rstep];
1987.                             
array_push ($output,  ($space[$passthru] == "@"));
1988.                         }
1989.                         break;
1990.                     
// True multiple arity operators
1991.                     
case "aggregate":
1992.                         if (
count($output) < 2)
1993.                             
error("The {$arg} operator requires at least two arguments."$linenum);
1994.                         
$op1 array_pop($output);
1995.                         
$op2 array_pop($output);
1996.                         if (!
is_array($op2)) {
1997.                             
array_push ($output,  $op2);
1998.                             
$op2 $output;
1999.                             
$output = array();
2000.                         }
2001.                         
$result = array();
2002.                         if (
$op1 instanceof Lambda) {
2003.                             foreach (
$op2 as $key => $temp) {
2004.                                 if (
is_array($temp))
2005.                                     
$args $temp;
2006.                                 else
2007.                                     
$args = array($temp);
2008.                                 
$r polish($op1->stack,  $linenum,  $args, array("key" => $key));
2009.                                 if (
$r) {
2010.                                     
array_push ($result,  $r);
2011.                                 }
2012.                             }
2013.                             
array_push ($output,  $result);
2014.                         }
2015.                         break;
2016.                     case 
"allequal":
2017.                         if (
count($output) < 2)
2018.                             
error("The {$arg} operator requires at least two arguments."$linenum);
2019.                         
$op1 array_pop($output);
2020.                         if ((array)
$op1 === $op1)
2021.                             
array_push ($output,  allequal($op1));
2022.                         else {
2023.                             
array_push ($output,  $op1);
2024.                             
$temp $output;
2025.                             unset (
$output);
2026.                             
$output[0] = allequal($temp);
2027.                         }
2028.                         break;
2029.                     case 
"allfalse":
2030.                     case 
"nonetrue":
2031.                         if (
count($output) < 2)
2032.                             
error("The {$arg} operator requires at least two arguments."$linenum);
2033.                         
$op1 array_pop($output);
2034.                         if (
$op1 instanceof Lambda) {
2035.                             
$op2 array_pop($output);
2036.                             
$result true;
2037.                             foreach (
$op2 as $key => $temp) {
2038.                                 if (
is_array($temp))
2039.                                     
$args $temp;
2040.                                 else
2041.                                     
$args = array($temp);
2042.                                 
$r polish($op1->stack,  $linenum,  $args, array("key" => $key));
2043.                                 if (
$r) {
2044.                                     
$result false;
2045.                                     break;
2046.                                 }
2047.                             }
2048.                             
array_push ($output,  $result);
2049.                         }
2050.                         elseif ((array)
$op1 === $op1)
2051.                             
array_push ($output,  allfalse($op1));
2052.                         else {
2053.                             
array_push ($output,  $op1);
2054.                             
$temp $output;
2055.                             unset (
$output);
2056.                             
$output[0] = allfalse($temp);
2057.                         }
2058.                         break;
2059.                     case 
"alltrue":
2060.                         if (
count($output) < 2)
2061.                             
error("The {$arg} operator requires at least two arguments."$linenum);
2062.                         
$op1 array_pop($output);
2063.                         if (
$op1 instanceof Lambda) {
2064.                             
$op2 array_pop($output);
2065.                             
$result true;
2066.                             foreach (
$op2 as $key => $temp) {
2067.                                 if (
is_array($temp))
2068.                                     
$args $temp;
2069.                                 else
2070.                                     
$args = array($temp);
2071.                                 
$r polish($op1->stack,  $linenum,  $args, array("key" => $key));
2072.                                 if (!
$r) {
2073.                                     
$result false;
2074.                                     break;
2075.                                 }
2076.                             }
2077.                             
array_push ($output,  $result);
2078.                         }
2079.                         elseif ((array)
$op1 === $op1)
2080.                             
array_push ($output,  alltrue($op1));
2081.                         else {
2082.                             
array_push ($output,  $op1);
2083.                             
$temp $output;
2084.                             unset (
$output);
2085.                             
$output[0] = alltrue($temp);
2086.                         }
2087.                         break;
2088.                     case 
"anyfalse":
2089.                         if (
count($output) < 2)
2090.                             
error("The {$arg} operator requires at least two arguments."$linenum);
2091.                         
$op1 array_pop($output);
2092.                         if (
$op1 instanceof Lambda) {
2093.                             
$op2 array_pop($output);
2094.                             
$result false;
2095.                             foreach (
$op2 as $key => $temp) {
2096.                                 if (
is_array($temp))
2097.                                     
$args $temp;
2098.                                 else
2099.                                     
$args = array($temp);
2100.                                 
$r polish($op1->stack,  $linenum,  $args, array("key" => $key));
2101.                                 if (!
$r) {
2102.                                     
$result true;
2103.                                     break;
2104.                                 }
2105.                             }
2106.                             
array_push ($output,  $result);
2107.                         }
2108.                         elseif ((array)
$op1 === $op1)
2109.                             
array_push ($output,  anyfalse($op1));
2110.                         else {
2111.                             
array_push ($output,  $op1);
2112.                             
$temp $output;
2113.                             unset (
$output);
2114.                             
$output[0] = anyfalse($temp);
2115.                         }
2116.                         break;
2117.                     case 
"anytrue": case "any":
2118.                         if (
count($output) < 2)
2119.                             
error("The {$arg} operator requires at least two arguments."$linenum);
2120.                         
$op1 array_pop($output);
2121.                         if (
$op1 instanceof Lambda) {
2122.                             
$op2 array_pop($output);
2123.                             
// print_r ($op1);
2124.                             // print_r ($op2);
2125.                             
$result false;
2126.                             foreach (
$op2 as $key => $temp) {
2127.                                 if (
is_array($temp))
2128.                                     
$args $temp;
2129.                                 else
2130.                                     
$args = array($temp);
2131.                                 
$r polish($op1->stack,  $linenum,  $args, array("key" => $key));
2132.                                 if (
$r) {
2133.                                     
$result $r;
2134.                                     break;
2135.                                 }
2136.                             }
2137.                             
array_push ($output,  $result);
2138.                         }
2139.                         elseif ((array)
$op1 === $op1) {
2140.                             echo 
"Array";
2141.                             
array_push ($output,  anytrue($op1));
2142.                         }
2143.                         else {
2144.                             
array_push ($output,  $op1);
2145.                             
$temp $output;
2146.                             unset (
$output);
2147.                             
$output[0] = anytrue($temp);
2148.                         }
2149.                         break;
2150.                     case 
"andsum":
2151.                         if (
count($output) < 1)
2152.                             
error("The {$arg} operator requires at least one argument."$linenum);
2153.                         
$op1 array_pop($output);
2154.                         if ((array)
$op1 === $op1)
2155.                             
array_push ($output,  and_sum($op1));
2156.                         else {
2157.                             
array_push ($output,  $op1);
2158.                             
$temp $output;
2159.                             unset (
$output);
2160.                             
$output[0] = and_sum($temp);
2161.                         }
2162.                         break;
2163.                     case 
"values":
2164.                     case 
"array":
2165.                         
$op1 array_pop($output);
2166.                         if (
$op1 === NULL) {
2167.                             
$output[0] = $output = array();
2168.                         }
2169.                         elseif (
$op1 instanceof Lambda) {
2170.                             
$op2 array_pop($output);
2171.                             if (!
is_array($op2)) {
2172.                                 
array_push ($output,  $op2);
2173.                                 
$op2 $output;
2174.                                 
$output = array();
2175.                             }
2176.                             
$result = array();
2177.                             foreach (
$op2 as $key => $val) {
2178.                                 
$args = array($key);
2179.                                 if (
is_array($val)) {
2180.                                     foreach (
$val as $v) {
2181.                                         
$args[] = $v;
2182.                                     }
2183.                                 }
2184.                                 else
2185.                                     
$args[] = $val;
2186.                                 
$args = array($key,  $val);
2187.                                 
array_push ($resultpolish($op1->stack,  $linenum,  $args));
2188.                             }
2189.                             
array_push ($output,  $result);
2190.                         }
2191.                         elseif ((
$arg == "values") && is_array($op1)) {
2192.                             
array_push ($outputarray_values($op1));
2193.                         }
2194.                         else {
2195.                             
array_push ($output$op1);
2196.                             
$newarray array_reverse($output);
2197.                             unset(
$output);
2198.                             
$output[0] = $newarray;
2199.                         }
2200.                         break;
2201. 
/*
2202.                     case "array":
2203.                         if (count($output) == 1)
2204.                             $newarray = explode(" ", $output[0]);
2205.                         else 
2206.                             $newarray = array_reverse($output);
2207.                         // debug2("newarray", $newarray);
2208.                         unset($output);
2209.                         $output[0] = $newarray;
2210.                         break;
2211. */                        
2212.                     
case "assoc":
2213.                         
$newarray = array();
2214.                         while (
count($output) > 1) {
2215.                             
$key array_pop($output);
2216.                             
$val array_pop($output);
2217.                             
$newarray[$key] = $val;
2218.                         }
2219.                         unset(
$output);
2220.                         
$output[0] = $newarray;
2221.                         break;
2222.                     case 
"checkapath":
2223.                         if (
count($output) < 2)
2224.                             
error("The {$arg} operator requires at least two arguments."$linenum);
2225.                         
$op1 array_pop($output);
2226.                         
$op2 array_pop($output);
2227.                         
$f $filenum[$op1]; $r $ranknum[$op1];
2228.                         if ((
$f === false) || ($r === false)) {
2229.                             
array_push ($outputfalse);
2230.                             break;
2231.                         }
2232.                         
$path array_pop($output);
2233.                         if (!
is_array($path)) {
2234.                             
$output[] = $path;
2235.                             
$path $output;
2236.                             unset (
$output);
2237.                         }
2238.                         if (
count($path) & 1)
2239.                             
error ("The checkapath operator requires an even number of operands.",  $linenum);
2240.                         while (
count($path)) {
2241.                             
$f += array_pop($path);
2242.                             
$r += array_pop($path);
2243.                             
$c $file[$f] . $rank[$r];
2244.                             if (!isset(
$space[$c]) || ($space[$c] != "@"))
2245.                                 break;
2246.                         }
2247.                         if (
count($path) > 0)
2248.                             
$output[] = false;
2249.                         else
2250.                             
$output[] = ($c == $op2);
2251.                         break;
2252.                     case 
"checkpath":
2253.                         if (
count($output) < 2)
2254.                             
error("The {$arg} operator requires at least two arguments."$linenum);
2255.                         
$op1 array_pop($output);
2256.                         
$op2 array_pop($output);
2257.                         
$f1 get_filenum($op1); $r1 get_ranknum($op1);
2258.                         
$f2 get_filenum($op2); $r2 get_ranknum($op2);
2259.                         
$fmove $f2 $f1;
2260.                         
$rmove $r2 $r1;
2261.                         
$fd = ($fmove >= 0) ? : -1;
2262.                         
$rd = ($rmove >= 0) ? : -1;
2263.                         
$temp $output;
2264.                         
$f $f1;
2265.                         
$r $r1;
2266.                         while (
count($output) > 1) {
2267.                             
$op3 abs(array_pop($output));
2268.                             
$op4 abs(array_pop($output));
2269.                             
$f += $op3*$fd;
2270.                             
$r += $op4*$rd;
2271.                             
$c get_file($f) . get_rank($r);
2272.                             if (!isset(
$space[$c]) || ($space[$c] != "@"))
2273.                                 break;
2274.                         }
2275.                         if ((
$c == $op2) && empty($output)) {
2276.                             unset (
$output);
2277.                             unset (
$temp);
2278.                             
$output[0] = true;
2279.                         }
2280.                         else {
2281.                             
$f $f1;
2282.                             
$r $r1;
2283.                             while (
count($temp) > 1) {
2284.                                 
$op3 abs(array_pop($temp));
2285.                                 
$op4 abs(array_pop($temp));
2286.                                 
$f += $op4*$fd;
2287.                                 
$r += $op3*$rd;
2288.                                 
$c get_file($f) . get_rank($r);
2289.                                 if (!isset(
$space[$c]) || ($space[$c] != "@"))
2290.                                     break;
2291.                             }
2292.                             if (empty(
$temp) && ($c == $op2)) {
2293.                                 
$output[0] = true;
2294.                             }
2295.                             else {
2296.                                 unset (
$output);
2297.                                 
$output[0]= false;
2298.                             }
2299.                             unset (
$temp);                    
2300.                         }
2301.                         break;
2302.                     case 
"filter":
2303.                         if (
count($output) < 2)
2304.                             
error("The {$arg} operator requires at least two arguments."$linenum);
2305.                         
$op1 array_pop($output);
2306.                         
$op2 array_pop($output);
2307.                         if (!
is_array($op2)) {
2308.                             
array_push ($output,  $op2);
2309.                             
$op2 $output;
2310.                             
$output = array();
2311.                         }
2312.                         
$result = array();
2313.                         if (
$op1 instanceof Lambda) {
2314.                             foreach (
$op2 as $key => $val) {
2315.                                 
$args = array($key);
2316.                                 if (
is_array($val)) {
2317.                                     foreach (
$val as $v) {
2318.                                         
$args[] = $v;
2319.                                     }
2320.                                 }
2321.                                 else
2322.                                     
$args[] = $val;
2323.                                 
$args = array($key,  $val);
2324.                                 
$r polish($op1->stack,  $linenum,  $args);
2325.                                 if (
$r) {
2326.                                     
$result[$key] = $val;
2327.                                 }
2328.                             }
2329.                             
array_push ($output,  $result);
2330.                         }
2331.                         break;
2332.                     case 
"findpiece":
2333.                         if (
count($output) < 1)
2334.                             
error("The {$arg} operator requires at least two arguments."$linenum);
2335.                         
$op1 array_pop($output);
2336.                         
$op2 array_pop($output);
2337.                         
$op3 array_pop($output);
2338.                         if (
$op2 === NULL)
2339.                             
array_push ($output,  findpiece($op1,  array_keys($space)));
2340.                         elseif ((array)
$op2 === $op2)
2341.                             
array_push ($output,  findpiece($op1,  $op2));
2342.                         elseif (isset(
$op3) && (is_array($op3))) {
2343.                             
array_push ($output,  findpiece($op1,  $op3,  $op2));
2344.                         }
2345.                         elseif ((
$op2 == "first") || ($op2 == "last")) {
2346.                             if (isset(
$op3))
2347.                                 
array_push ($output$op3);
2348.                             
$temp array_reverse($output);
2349.                             unset (
$output);
2350.                             
$output[0] = findpiece($op1,  $temp,  $op2);
2351.                         }
2352.                         else {
2353.                             if (isset(
$op2) !== NULL)
2354.                                 
array_push ($output$op2);
2355.                             
$temp array_reverse($output);
2356.                             unset (
$output);
2357.                             
$output[0] = findpiece($op1,  $temp,  "first");
2358.                         }                            
2359.                         break;
2360.                     case 
"fn":
2361.                         if (
count($output) < 1)
2362.                             
error("The {$arg} operator requires at least one arguments."$linenum);
2363.                         
$op1 array_pop($output);
2364.                         if (
$op1 instanceof Lambda)
2365.                             
$fn $op1->stack;
2366.                         elseif (
is_array($op1))
2367.                             
$fn $op1;
2368.                         elseif (
str_contains($op1 ?? "",  " "))
2369.                             
$fn explode(" ",  $op1);
2370.                         elseif (isset(
$functions[$op1])) {
2371.                             
$fn $functions[$op1];
2372.                             
// $sub[$scope] = $op1;
2373.                         
}
2374.                         else
2375.                             
error ("The function '{$op1}' has not been defined. Its arguments are " implode(" "array_reverse($output)),  $linenum);
2376.                         if (empty(
$fn))
2377.                             
error ("The <B>fn</B> built-in function has not been given a valid function name or lambda function."$linenum);
2378.                         
$maxargs 0;
2379.                         
$max count($fn);
2380.                         for (
$i 0$i $max$i++) {
2381.                             if (
array_key_exists($i$fn) && !empty($fn[$i]) && ($fn[$i][0] == "#")) {
2382.                                 
$n substr($fn[$i],  1);
2383.                                 if (
ctype_digit($n))
2384.                                     
$maxargs max($maxargs,  $n+1);
2385.                             }
2386.                         }
2387.                         if (
$maxargs 0) {
2388.                             if (
$maxargs count($output))
2389.                                 
error ("Function {$op1} requires more arguments than have been passed to it.",  $linenum);
2390.                             for (
$i 0$i $maxargs$i++)
2391.                                 
$args[$i] = array_pop($output);
2392.                             
// // debug2 ("Entering",  $op1);
2393.                         
}
2394.                         else {
2395.                             
$args array_reverse($output);
2396.                             
$output = array();
2397.                         }                            
2398.                         
$temp polish($fn,  $linenum,  $args);
2399.                         
array_push ($output,  $temp);
2400.                         
// // debug2 ("Exited from",  $op1);
2401.                         
break;
2402.                     case 
"intersection":
2403.                         if (
count($output) < 2)
2404.                             
error("The {$arg} operator requires at least two arguments."$linenum);
2405.                         
$op1 array_pop($output);
2406.                         
$op2 array_pop($output);
2407.                         if (!
is_array($op1))
2408.                             die (
"The first argument to intersection must be an array");
2409.                         if (!
is_array($op2)) {
2410.                             
array_push($output,  $op2);
2411.                             
$op2 $output;
2412.                             
$output = array();
2413.                         }
2414.                         
array_push ($output,  array_intersect($op1,  $op2));
2415.                         break;
2416.                     case 
"isort":
2417.                         if (
count($output) < 1)
2418.                             
error("The {$arg} operator requires at least two arguments."$linenum);
2419.                         
$op1 array_pop($output);
2420.                         if (
is_array($op1)) {
2421.                             
sort($op1SORT_NATURAL SORT_FLAG_CASE);
2422.                             
array_push ($output,  $op1);
2423.                         }
2424.                         else {
2425.                             
array_push($output$op1);
2426.                             
$op1 $output;
2427.                             unset(
$output);
2428.                             
sort($op1SORT_NATURAL SORT_FLAG_CASE);
2429.                             
$output[0] = $op1;
2430.                         }
2431.                         break;
2432.                     case 
"list":
2433.                         
$op1 array_pop($output);
2434.                         if ((array)
$op1 === $op1)
2435.                             
array_push ($output,  implode(" ",  $op1));
2436.                         else {
2437.                             
array_push ($output,  $op1);
2438.                             
$temp array_reverse($output);
2439.                             unset (
$output);
2440.                             
$output[0] = implode(" ",  $temp);
2441.                         }
2442.                         break;
2443.                     case 
"logleap":
2444.                         
// Determines whether a logical leap from one space to another is
2445.                         // possible through any of the directions provided.
2446.                         
if (count($output) < 2)
2447.                             
error("The {$arg} operator requires at least two arguments."$linenum);
2448.                         
$op1 array_pop($output);
2449.                         
$op2 array_pop($output);
2450.                         do {
2451.                             
$op3 array_pop($output);
2452.                             if (
is_array($op3))
2453.                                 
$ns logleap($op1,  $op2,  $op3);
2454.                             elseif (isset(
$map[$op1][$op3]))
2455.                                 
$ns $map[$op1][$op3];
2456.                             else {
2457.                                 
$ns false;
2458.                             }
2459.                         } while ((
$ns != $op2) && (count($output) > 0));
2460.                         unset (
$output);
2461.                         
$output[0] = !empty($ns) && ($ns == $op2);
2462.                         break;
2463.                     case 
"logleaps":
2464.                         
// Returns array of spaces that may be reached through single leaps in any
2465.                         // of the directions provided.
2466.                         
if (count($output) < 2)
2467.                             
error("The {$arg} operator requires at least two arguments."$linenum);
2468.                         
$op1 array_pop($output);
2469.                         
$tmp = array();
2470.                         while (
count($output) > 0) {
2471.                             
$op2 array_pop($output);
2472.                             if (
is_array($op2)) {
2473.                                 
$cc $op1;
2474.                                 for (
$i 0$i count($op2); $i++) {
2475.                                     if (
array_key_exists ($cc$map) && is_array($map[$cc]) && array_key_exists($i$op2) && array_key_exists($op2[$i],  $map[$cc]))
2476.                                         
$cc $map[$cc][$op2[$i]];
2477.                                     else
2478.                                         break;
2479.                                 }
2480.                                 if (
$i == count($op2))
2481.                                     
array_push ($tmp,  $cc);
2482.                             }
2483.                             elseif (
array_key_exists ($op1$map) && is_array($map[$op1]) && array_key_exists($op2,  $map[$op1]))
2484.                                 
array_push ($tmp,  $map[$op1][$op2]);
2485.                         }
2486.                         unset (
$output);
2487.                         
$output[0] = $tmp;
2488.                         break;
2489.                     case 
"lograys":
2490. 
/*
2491.                         if (count($output) < 2)
2492.                             error("The {$arg} operator requires at least two arguments.", $linenum);
2493.                         $op1 = array_pop($output);
2494.                         $allrays = array();
2495.                         while (count($output) > 0) {
2496.                             $ray = array();
2497.                             $op2 = array_pop($output);
2498.                             $cc = $op1;
2499.                             if (is_array($op2)) {
2500.                                 foreach ($op2 as $d) {
2501.                                     if (array_key_exists($d,  $map[$cc])) {
2502.                                         $cc = $map[$cc][$d];
2503.                                         if ($cc == $op1)
2504.                                             break;
2505.                                         array_push ($ray,  $cc);
2506.                                     }
2507.                                     else
2508.                                         break;
2509.                                 }
2510.                                 $op2 = $d;
2511.                             }
2512.                             if (array_key_exists($cc, $map)) {
2513.                                 while (array_key_exists($op2,  $map[$cc])) {
2514.                                     $cc = $map[$cc][$op2];
2515.                                     if (($cc == $op1) || in_array($cc, $ray))
2516.                                         break;
2517.                                     array_push ($ray,  $cc);
2518.                                 }
2519.                             }
2520.                             $allrays = array_merge($allrays, $ray);
2521.                         }
2522.                         unset ($output);
2523.                         $output[0] = array_unique($allrays);
2524.                         break;
2525.                     case "lograise": // copy of lograys for testing
2526. */                    
2527.                         
if (count($output) < 2)
2528.                             
error("The {$arg} operator requires at least two arguments."$linenum);
2529.                         
$op1 array_pop($output);
2530.                         
$allrays = array();
2531.                         foreach (
$output as $op2) {
2532.                             
$ray lograys($op1$op2);
2533.                             
$allrays array_merge($ray$allrays);
2534.                         }
2535.                         unset (
$output);
2536.                         
$output[0] = array_unique($allrays);
2537.                         break;
2538.                     case 
"logride":
2539.                         if (
count($output) < 2)
2540.                             
error("The {$arg} operator requires at least two arguments."$linenum);
2541.                         
$op1 array_pop($output);
2542.                         
$op2 array_pop($output);
2543.                         do {
2544.                             
$op3 array_pop($output);
2545.                             if (
is_array($op3))
2546.                                 
$ns logride($op1,  $op2,  $op3);
2547.                             else
2548.                                 
$ns logride($op1$op2, array($op3));
2549.                         } while ((
$ns != $op1) && ($ns != $op2) && (count($output) > 0));
2550.                         unset (
$output);
2551.                         
$output[0] = ($ns == $op2);
2552.                         break;
2553.                     case 
"match":
2554.                         if (
count($output) < 2)
2555.                             
error("The {$arg} operator requires at least two arguments."$linenum);
2556.                         
$op1 array_pop($output);
2557.                         
$op2 array_pop($output);
2558.                         
// if op2 is not an array,  make it one matching the remaining arguments
2559.                         
if ((array)$op2 !== $op2) {
2560.                             
array_push ($output,  $op2);
2561.                             
$op2 $output;
2562.                             unset (
$output);
2563.                         }                    
2564.                         if ((array)
$op1 === $op1)
2565.                             
$output[] = count(array_intersect($op1,  $op2));
2566.                         else
2567.                             
$output[] = in_array($op1,  $op2);
2568.                         break;
2569.                     case 
"mates":
2570.                         if (
count($output) < 2)
2571.                             
error("The {$arg} operator requires at least two arguments."$linenum);
2572.                         
$newarray = array();
2573.                         while (
count($output) > 1) {
2574.                             
$key array_pop($output);
2575.                             
$val array_pop($output);
2576.                             
$newarray[$key] = $val;
2577.                             
$newarray[$val] = $key;
2578.                         }
2579.                         unset(
$output);
2580.                         
$output[0] = $newarray;
2581.                         break;
2582.                     case 
"mergeall":
2583.                         if (
count($output) < 2)
2584.                             
$output $output[0];
2585.                         
$newarray $strays = array();
2586.                         foreach (
$output as $val) {
2587.                             if (
$val === (array)$val)
2588.                                 
$newarray[] = $val;
2589.                             elseif (
$val)
2590.                                 
$strays[] = $val;
2591.                         }
2592.                         if (
count($strays) > 0)
2593.                             
$newarray[] = $strays;
2594.                         unset(
$output);
2595.                         
$output[0] = array_unique(array_merge(...$newarray));
2596.                         break;
2597.                     case 
"poleride":
2598.                         if (
count($output) < 3)
2599.                             
error("The {$arg} operator requires at least 3 arguments."$linenum);
2600.                         
$op1 array_pop($output);
2601.                         
$op2 array_pop($output);
2602.                         
$op3 array_pop($output);
2603.                         if (
is_array($op3)) {
2604.                             do {
2605.                                 if (
count($op3) == 4)
2606.                                     
$bool poleride($op1$op2$op3[0], $op3[1], $op3[2], $op3[3]);
2607.                                 else
2608.                                     
error("poleride requires four directions to work"$linenum);
2609.                                 if (
$bool == true)
2610.                                     break;
2611.                             } while (
$op3 array_pop($output));
2612.                         }
2613.                         elseif (
count($output) >= 3) {
2614.                             
$op4 array_pop($output);
2615.                             
$op5 array_pop($output);
2616.                             
$op6 array_pop($output);
2617.                             
$bool poleride($op1$op2$op3$op4$op5$op6);
2618.                         }
2619.                         unset (
$output);
2620.                         
$output[0] = $bool;
2621.                         break;
2622.                     case 
"sort":
2623.                         if (
count($output) < 1)
2624.                             
error("The {$arg} operator requires at least one argument."$linenum);
2625.                         
$op1 array_pop($output);
2626.                         if (
is_array($op1)) {
2627.                             
sort($op1);
2628.                             
array_push ($output,  $op1);
2629.                         }
2630.                         else {
2631.                             
array_push($output$op1);
2632.                             
$op1 $output;
2633.                             unset(
$output);
2634.                             
sort($op1);
2635.                             
$output[0] = $op1;
2636.                         }
2637.                         break;
2638.                     case 
"sub":
2639.                         if (
count($output) < 1)
2640.                             
error("The {$arg} operator requires at least one argument."$linenum);
2641.                         
$gosub array_pop($output);
2642.                         
$subargs array_reverse($output);
2643.                         unset(
$output);
2644.                         
$output[0] = runsubroutine($gosub,  $subargs$linenum);
2645.                         break;
2646.                     case 
"sum":
2647.                         if (
count($output) < 1)
2648.                             
error("The {$arg} operator requires at least one argument."$linenum);
2649.                         
$op1 array_pop($output);
2650.                         if (
$op1 instanceof Lambda) {
2651.                             
$op2 array_pop($output);
2652.                             
$result 0;
2653.                             foreach (
$op2 as $temp) {
2654.                                 if (
is_array($temp))
2655.                                     
$args $temp;
2656.                                 else
2657.                                     
$args = array($temp);
2658.                                 
$result += polish($op1->stack,  $linenum,  $args);
2659.                             }
2660.                             
array_push ($output,  $result);
2661.                         }
2662.                         elseif ((array)
$op1 === $op1)
2663.                             
array_push ($output,  array_sum($op1));
2664.                         else {
2665.                             
array_push ($output,  $op1);
2666.                             
$temp $output;
2667.                             unset (
$output);
2668.                             
$output[0] = array_sum($temp);
2669.                         }
2670.                         break;
2671.                     case 
"orsum":
2672.                         if (
count($output) < 1)
2673.                             
error("The {$arg} operator requires at least one argument."$linenum);
2674.                         
$op1 array_pop($output);
2675.                         if ((array)
$op1 === $op1)
2676.                             
array_push ($output,  or_sum($op1));
2677.                         else {
2678.                             
array_push ($output,  $op1);
2679.                             
$temp $output;
2680.                             unset (
$output);
2681.                             
$output[0] = or_sum($temp);
2682.                         }
2683.                         break;
2684.                     case 
"windingrays":
2685.                         if (
count($output) < 2)
2686.                             
error("The {$arg} operator requires at least two arguments."$linenum);
2687.                         
$op1 array_pop($output);
2688.                         
$f1 $filenum[$op1]; $r1 $ranknum[$op1];
2689.                         
$hstep $vstep $tmp = array();
2690.                         if (empty(
$output))
2691.                             
error ("windingrays requires arguments for the directions of the move."$linenum);
2692.                         while (!empty(
$output)) {
2693.                             
$hstep[] = abs(array_pop($output));
2694.                             if (empty(
$output))
2695.                                 
error ("windingrays requires an even number of arguments."$linenum);
2696.                             
$vstep[] = abs(array_pop($output));
2697.                         }
2698.                         
$n count($hstep);
2699.                         
$nc "";
2700.                         for (
$fd = -1$fd 2$fd += 2) {
2701.                             for (
$rd = -1$rd 2$rd +=2) {
2702.                                 
$f $f1;
2703.                                 
$r $r1;
2704.                                 do {
2705.                                     
$oc $nc;
2706.                                     for (
$i 0$i $n$i++) {
2707.                                         
$f += $hstep[$i] * $fd;
2708.                                         
$r += $vstep[$i] * $rd;
2709.                                         if (!isset(
$file[$f]) || !isset($rank[$r]))
2710.                                             break;
2711.                                         
$nc $file[$f] . $rank[$r];
2712.                                         if (empty(
$space[$nc]) || ($space[$nc] == "-"))
2713.                                             break;
2714.                                         else
2715.                                             
array_push ($tmp$nc);
2716.                                     }
2717.                                 } while ((
$oc != $nc) && !empty($space[$nc]) && ($space[$nc] != "-"));
2718.                             }
2719.                         }
2720.                         
$tmp array_unique($tmp);
2721.                         unset (
$output);
2722.                         
$output[0] = $tmp;
2723.                         break;                                
2724.                     case 
"windingride":
2725.                         if (
count($output) < 2)
2726.                             
error("The {$arg} operator requires at least two arguments."$linenum);
2727.                         
$op1 array_pop($output);
2728.                         
$op2 array_pop($output);
2729.                         
$f1 $filenum[$op1]; $r1 $ranknum[$op1];
2730.                         
$f2 $filenum[$op2]; $r2 $ranknum[$op2];
2731.                         
$fmove $f2 $f1;
2732.                         
$rmove $r2 $r1;
2733.                         
$fd = ($fmove >= 0) ? : -1;
2734.                         
$rd = ($rmove >= 0) ? : -1;
2735.                         
$hstep $vstep = array();
2736.                         if (empty(
$output))
2737.                             
error ("windingride requires arguments for the directions of the move."$linenum);
2738.                         while (!empty(
$output)) {
2739.                             
$hstep[] = abs(array_pop($output));
2740.                             if (empty(
$output))
2741.                                 
error ("windingride requires an even number of arguments."$linenum);
2742.                             
$vstep[] = abs(array_pop($output));
2743.                         }
2744.                         
print_r($hstep);
2745.                         
print_r($vstep);
2746.                         
$n count($hstep);
2747.                         
$f $f1;
2748.                         
$r $r1;
2749.                         
$nc "";
2750.                         do {
2751.                             
$oc $nc;
2752.                             for (
$i 0$i $n$i++) {
2753.                                 
$f += $hstep[$i] * $fd;
2754.                                 
$r += $vstep[$i] * $rd;
2755.                                 if (!isset(
$file[$f]) || !isset($rank[$r]))
2756.                                     break;
2757.                                 
$nc $file[$f] . $rank[$r];
2758.                                 if ((
$nc == $op2) || empty($space[$nc]) || ($space[$nc] != "@"))
2759.                                     break;
2760.                             }
2761.                             if (
$nc == $op1)
2762.                                 
error ("windingride buggy"$linenum);
2763.                             
// echo "<P STYLE=\"display:block\">{$nc}</P>";
2764.                         
} while (($oc != $nc) && ($nc != $op2) && !empty($space[$nc]) && ($space[$nc] == "@"));
2765.                         unset (
$output);
2766.                         
$output[0] = ($nc == $op2);
2767.                         break;
2768.                     default:
2769.                         
array_push ($output,  $arg);
2770.                         break;
2771.                 }
2772.         }
2773.     }
2774.     
$cnt count($output);
2775.     
$retval = ($cnt 1) ? $output : ($cnt array_pop($output) : false);
2776.     
// debug2 ("retval",  $retval);
2777.     
if ($scope == $higherscope)
2778.         
unsetlocals ($scope, --$scope);
2779.     return 
$retval;
2780. }
2781. 
2782. function 
parse_coord($coord) {
2783.     global 
$filenum,  $ranknum;
2784.     
2785.     return array(
$filenum[$op1],  $ranknum[$op1]);
2786. 
/*
2787.     $lastlen = 0;
2788.     foreach ($file as $fkey => $fval) {
2789.         $len = strlen($fval);
2790.         if ($len != $lastlen) {
2791.             $left = substr($coord,  0,  $len);
2792.             $rest = substr($coord,  $len);
2793.         }
2794.         if ($left == $fval) {
2795.             foreach ($rank as $rkey => $rval) {
2796.                 if ($rest == $rval)
2797.                     return array ($fkey,  $rkey);
2798.             }
2799.         }
2800.     }
2801. 
2802.     return array(false,  false);
2803. */
2804. 
}
2805. 
2806. function 
sgn ($n) {
2807.     return (
$n 0) ? -: ($n 0);
2808. }
2809. 
2810. function 
checknsteps ($f1,  $r1,  $f2,  $r2,  $steps,  $any) {
2811.     global 
$file,  $rank,  $space;
2812.     
2813.     if (!isset(
$file[$f1]) || !isset($rank[$r1]) || !isset($file[$f2]) || !isset($rank[$r2]))
2814. 
2815.     if (
$steps 1// Path has stopped. Did we make it?
2816.         
return (($f1 == $f2) && ($r1 == $r2));
2817.         
2818.     
// If any number of steps up to n is allowed, 
2819.     // check if we have made it already.
2820.     
if ($any && ($f1 == $f2) && ($r1 == $r2))
2821.         return 
true;
2822.     
2823.     
// Verify that initial file and rank are real
2824.     
if (!isset($file[$f1]) || !isset($rank[$r1]))
2825.         return 
false;
2826.     
2827.     
$c $file[$f1] . $rank[$r1];
2828.     if (!isset(
$space[$c]) || ($space[$c] != "@"))
2829.         return 
false// Path blocked
2830. 
2831.     
$f abs($f1 $f2);
2832.     
$r abs($r1 $r2);
2833.     
2834.     if ((
$f $steps) || ($r $steps))
2835.         return 
false// Too far away
2836.         
2837.     
if (($steps 1) && ($f <= 1) && ($r <= 1))
2838.         return 
true// Success! Destination is one step away.
2839. 
2840.     
$steps--;
2841. 
2842.     return 
checknsteps($f1 1,  $r1 1,  $f2,  $r2,  $steps,  $any)
2843.         || 
checknsteps($f1 1,  $r1,  $f2,  $r2,  $steps,  $any)
2844.         || 
checknsteps($f1 1,  $r1 1,  $f2,  $r2,  $steps,  $any)
2845.         || 
checknsteps($f1,  $r1 1,  $f2,  $r2,  $steps,  $any)
2846.         || 
checknsteps($f1,  $r1 1,  $f2,  $r2,  $steps,  $any)
2847.         || 
checknsteps($f1 1,  $r1 1,  $f2,  $r2,  $steps,  $any)
2848.         || 
checknsteps($f1 1,  $r1,  $f2,  $r2,  $steps,  $any)
2849.         || 
checknsteps($f1 1,  $r1 1,  $f2,  $r2,  $steps,  $any);
2850. }
2851. 
2852. function 
allequal ($arr) {
2853.     
$op array_pop($arr);
2854.     while (isset(
$arr[0])) {
2855.         if (
array_pop($arr) != $op)
2856.             return 
false;
2857.     }
2858.     return 
true;
2859. }
2860. 
2861. function 
matchstr ($arr) {
2862.     
$op array_pop($arr);
2863.     while (isset(
$arr[0])) {
2864.         if (
array_pop($arr) == $op)
2865.             return 
true;
2866.     }
2867.     return 
false;
2868. }
2869. 
2870. function 
nomatchstr ($arr) {
2871.     
$op array_pop($arr);
2872.     while (isset(
$arr[0])) {
2873.         if (
array_pop($arr) == $op)
2874.             return 
false;
2875.     }
2876.     return 
true;
2877. }
2878. 
2879. function 
allfalse ($arr) {
2880.     while (isset(
$arr[0])) {
2881.         if (
array_pop($arr))
2882.             return 
false;
2883.     }
2884.     return 
true;
2885. }
2886. 
2887. function 
alltrue ($arr) {
2888.     while (isset(
$arr[0])) {
2889.         if (!
array_pop($arr))
2890.             return 
false;
2891.     }
2892.     return 
true;
2893. }
2894. 
2895. function 
anyfalse ($arr) {
2896.     while (isset(
$arr[0])) {
2897.         if (!
array_pop($arr))
2898.             return 
true;
2899.     }
2900.     return 
false;
2901. }
2902. 
2903. function 
anytrue ($arr) {
2904.     while (isset(
$arr[0])) {
2905.         if (
array_pop($arr))
2906.             return 
true;
2907.     }
2908.     return 
false;
2909. }
2910. 
2911. function 
gcd($m,  $n) {
2912.     
$d $m;
2913.     
$r $n;
2914.     
2915.     while (
$r != 0) {
2916.         
$m $d;
2917.         
$d $r;
2918.         
$r $m $r;
2919.     }
2920.     return 
$d;
2921. }
2922. 
2923. 
// Used for Hostage Chess.
2924. // Indicates most valuable piece that may be dropped.
2925. // Used with code for checking possible moves.
2926. 
2927. 
function best2drop () {
2928.     global 
$starpath,  $piecevals,  $firstplayer,  $space;
2929.     
2930.     
$bestdrop "";
2931.     for (
$i 0$i count($starpath[$firstplayer]); $i++) {
2932.         if ((
$piecevals[$starpath[$firstplayer][$i]] ?? 0) > ($piecevals[$bestdrop] ?? 0))
2933.             
$bestdrop $starpath[$firstplayer][$i];
2934.     }
2935.     if (
$bestdrop == "")
2936.         return 
false;
2937.     return 
$bestdrop;
2938. }
2939. 
2940. 
// Used for Hostage Chess.
2941. // Indicates most valuable hostage that may be freed.
2942. // Used with code for checking possible moves.
2943. 
2944. 
function best2free () {
2945.     global 
$prison,  $piecevals,  $firstplayer,  $space;
2946.     
2947.     
$capital 0;
2948.     for (
$i 0$i count($prison[$firstplayer]); $i++) {
2949.         
$piece $space[$prison[$firstplayer][$i]] ?? "";
2950.         
$capital max($piecevals[$piece] ?? 0$capital);
2951.     }
2952.     if (
$capital == 0)
2953.         return 
false;
2954.     
2955.     
$bestbuy "";
2956.     for (
$i 0$i count($prison[!$firstplayer]); $i++) {
2957.         
$piece $space[$prison[!$firstplayer][$i]];
2958.         if ((
$piecevals[$piece] ?? 0) == $capital)
2959.             return 
$piece;
2960.         elseif ((
$piecevals[$piece] ?? 0) < $capital)
2961.             
$bestbuy = (($piecevals[$piece] ?? 0) > ($piecevals[$bestbuy] ?? 0)) ? $piece $bestbuy;
2962.     }
2963.     if (
$bestbuy == "")
2964.         return 
false;
2965.     return 
$bestbuy;
2966. }
2967. 
2968. function 
function_literal ($ra) {
2969.     
$max count($ra);
2970.     for (
$i 0$i $max$i++) {
2971.         if (
is_array($ra[$i]))
2972.             
$ra[$i] = array_literal($ra[$i]);
2973.         elseif (
strstr($ra[$i],  " "))
2974.             
$ra[$i] = '"' $ra[$i] . '"';
2975.     }
2976.     return 
implode(" ",  $ra);
2977. }
2978. 
2979. function 
array_literal ($ra) {
2980.     
$max count($ra);
2981.     for (
$i 0$i $max$i++) {
2982.         if (
is_array($ra[$i]))
2983.             
$ra[$i] = array_literal($ra[$i]);
2984.     }
2985.     return 
"(" implode(" ",  $ra) . ")";
2986. }
2987. 
2988. function 
logleap ($from,  $to,  $ra) {
2989.     global 
$map,  $space;
2990.     
2991.     
$ns $from;
2992.     if (!
array_key_exists($ns$space))
2993.         
error("The first argument to logleap does not match any space on the board."$GLOBALS["linenum"]);
2994.     for (
$i 0$i count($ra); $i++) {
2995.         if ((
$i 0) && (($space[$ns] ?? "") != '@'))
2996.             break;
2997.         
$dir $ra[$i];
2998.         
$temp false;
2999.         if (
is_array($dir)) {
3000.             if ((
$temp logleap($from,  $to,  $dir)) == $to)
3001.                 return 
$temp;
3002.         }
3003.         elseif (isset(
$map[$ns][$dir]))
3004.             
$ns $map[$ns][$dir];
3005.         else
3006.             
$ns false;
3007.     }
3008.     if ((
$temp == false) && ($i count($ra)))
3009.         return 
false;
3010.     return 
$temp $temp $ns;
3011. }
3012. 
3013. function 
logride ($from,  $to,  $ra) {
3014.     global 
$map,  $space;
3015.     if (!
is_array($ra))
3016.         
$ra = array($ra);
3017.     
$ns $from;
3018.     
$counter 0;
3019.     do {
3020.         
$cnt count($ra);
3021.         for (
$i 0$i $cnt$i++) {
3022.             
$dir $ra[$i];
3023.             
$temp false;
3024.             if (
is_array($dir)) {
3025.                 if ((
$temp logride($ns,  $to,  $dir)) == $to)
3026.                     return 
$temp;
3027.             }
3028.             elseif (!
array_key_exists($ns$map) || !array_key_exists($dir,  $map[$ns]))
3029.                 break 
2;
3030.             elseif (
$ns == $map[$ns][$dir])
3031.                 break 
2;
3032.             else
3033.                 
$ns $map[$ns][$dir];
3034.             if ((
$ns == $from) || ($ns == $to) || ($space[$ns] != '@'))
3035.                 break 
2;
3036.             if (
$counter++ > 1000) {
3037.                 
error_log("logride {$from} {$to} " implode(" "$ra));
3038.                 
error_log ("ns is '{$ns}, space[ns] is {$space[$ns]}'");
3039.                 if (
$counter 1003) {
3040.                     echo 
"<PRE>";
3041.                     
print_r($map);
3042.                     echo 
"</PRE>";
3043.                     exit();
3044.                 }
3045.             }
3046.         }
3047.     } while (!
is_array($ra[$cnt-1]) && ($ns != $to) && ($ns != $from));
3048.     return (
$ns == $to) ? $to false;
3049. }
3050. 
3051. function 
lograys ($from$ra) {
3052.     global 
$map,  $space;
3053.     if (!
is_array($ra))
3054.         
$ra = array($ra);
3055.     
$legal = array();
3056.     
$counter 0;
3057.     
$ns $from;
3058.     do {
3059.         
$cnt count($ra);
3060.         for (
$i 0$i $cnt$i++) {
3061.             
$dir $ra[$i];
3062.             if (
is_array($dir)) {
3063.                 
$legal array_merge($legallograys($ns$dir));
3064.             }
3065.             else {
3066.                 if (!
array_key_exists($ns$map) || !array_key_exists($dir,  $map[$ns]))
3067.                     break 
2;
3068.                 
$ns $map[$ns][$dir];
3069.                 
$legal[] = $ns;
3070.                 if (
$counter++ > 100) {
3071.                     
error_log("lograys {$from} " implode(" "$ra));
3072.                     
error_log ("ns is '{$ns}, space[ns] is {$space[$ns]}'");
3073.                     if (
$counter 1003) {
3074.                         echo 
"<PRE>";
3075.                         
print_r($map);
3076.                         echo 
"</PRE>";
3077.                         exit();
3078.                     }
3079.                 }
3080.             }
3081.         }
3082.     } while (!
is_array($ra[$cnt-1]) && ($ns != $from));
3083.     return 
$legal;
3084. }
3085. 
3086. function 
poleride ($from$to$dir1$dir2$dir3$dir4) {
3087.     global 
$map$space$rankname$linenum;
3088.     
$ns $from;
3089.     
$cnt 0;
3090.     
$max count($space)*2;
3091.     do {
3092.         
// Normal board movement until it reaches a pole
3093.         
while (array_key_exists($dir1$map[$ns])) {
3094.             
$cnt++;
3095.             
$ns $map[$ns][$dir1];
3096.             if (
$ns == $to)
3097.                 return 
true;
3098.             if ((
$ns == $from) || ($space[$ns] != '@'))
3099.                 return 
false;
3100.             if (
$cnt $max)
3101.                 
error ("Infinite Loop in poleride"$linenum);
3102.         };
3103.         
// Single step in dir2 to cross the pole
3104.         // If it didn't skip the previous loop, it is already by this pole.
3105.         // If it went through the previous loop, it was brought to this pole.
3106.         
if (array_key_exists($dir2$map[$ns])) {
3107.             
$cnt++;
3108.             
$ns $map[$ns][$dir2];
3109.             if (
$ns == $to)
3110.                 return 
true;
3111.             if ((
$ns == $from) || ($space[$ns] != '@'))
3112.                 return 
false;
3113.         }
3114.         else 
// So if it is not by this pole at this point, there is an error.
3115.             
return false;
3116.         
// Changes direction to move away from the pole it just crossed
3117.         
while (array_key_exists($dir3$map[$ns])) {
3118.             
$cnt++;
3119.             
$ns $map[$ns][$dir3];
3120.             if (
$ns == $to)
3121.                 return 
true;
3122.             if ((
$ns == $from) || ($space[$ns] != '@'))
3123.                 return 
false;
3124.             if (
$cnt $max)
3125.                 
error ("Infinite Loop in poleride"$linenum);
3126.         };
3127.         
// Single step in dir4 to cross the other pole
3128.         
if (array_key_exists($dir4$map[$ns])) {
3129.             
$cnt++;
3130.             
$ns $map[$ns][$dir4];
3131.             if (
$ns == $to)
3132.                 return 
true;
3133.             if ((
$ns == $from) || ($space[$ns] != '@'))
3134.                 return 
false;
3135.         }
3136.         else
3137.             return 
false;
3138.         
// Loop back in case the move initially skipped the first loop, or in case the move 
3139.         // path is more complicated than a simple non-intersecting, non-overlapping circuit.
3140.     
} while ($cnt $max); // This is to prevent an infinite loop.
3141. 
}
3142. 
3143. function 
fencode($w 0) {
3144.     global 
$space$excode;
3145.     
$fen ""$cnt 0$total 0;
3146.     if (!
is_array($space))
3147.         return 
false;
3148.     
reset ($space);
3149.     
reset ($excode);
3150.     foreach (
$excode as $key => $val) {
3151.         if (((
$total 0) && ($w 0)) && (($total $w) == 0)) {
3152.             
$fen .= "/";
3153.         }
3154.         
$total++;
3155.         if (
key($space) == "")
3156.             continue;
3157.         
$sp current($space);
3158.         if ((
$val == "-") && ($sp != "-")) {
3159.             if (
$cnt 0) {
3160.                 
$fen .= $cnt;
3161.                 
$cnt 0;
3162.             }
3163.             
$fen .= "-";
3164.             continue;
3165.         }
3166.         if (
$sp == "@") {
3167.             
$cnt++;
3168.             if ((
$w 0) && (($total $w) == 0)) {
3169.                 
$fen .= $cnt;
3170.                 
$cnt 0;
3171.             }
3172.         }    
3173.         else {
3174.             if (
$cnt 0) {
3175.                 
$fen .= $cnt;
3176.                 
$cnt 0;
3177.             }
3178.             if (
strlen($sp ?? "") == 1)
3179.                 
$fen .= $sp;
3180.             else
3181.                 
$fen .= "{" $sp "}";
3182.         }
3183.         
next ($space);
3184.     }
3185.     if (
$cnt 0)
3186.         
$fen .= $cnt;
3187.     return 
$fen;
3188. }
3189. 
3190. function 
boardflags() {
3191.     global 
$space,  $flag;
3192.     
// reset ($space);
3193.     // reset ($flag);
3194.     
$onflags = array();
3195.     
3196.     if (empty(
$flag))
3197.         return 
false;
3198.     foreach (
$flag as $key => $val) {
3199.         if (
$val && isset($space[$key]))
3200.             
$onflags[] = $key;
3201.     }
3202.     
sort ($onflags);
3203.     return 
"," implode(",",  $onflags);
3204. }
3205. 
3206. function 
and_sum ($a) {
3207.     
$s $a[0];
3208.     foreach (
$a as $v) {
3209.         
$s &= $v;
3210.     }
3211.     return 
$s;
3212. }
3213. 
3214. function 
or_sum ($a) {
3215.     
$s = (int)$a[0];
3216.     foreach (
$a as $v) {
3217.         
$s = (int)$s | (int)$v;
3218.     }
3219.     return (int)
$s;
3220. }
3221. 
3222. 
// Wrapper functions used with array_filter
3223. 
3224. 
function notlower ($s) {
3225.     return !
ctype_lower($s);
3226. }
3227. 
3228. function 
notupper ($s) {
3229.     return !
ctype_upper($s);
3230. }
3231. 
3232. 
/*
3233. function systemvar ($name) {
3234.     if (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|scope|showoutput|side|space|sub|starpath|submit)$/", $name))
3235.         return $GLOBALS[$name];
3236.     elseif (preg_match("/^(capturedpieces|originalpieces|piecekeys|piecevals|prison|starpath|sub)\./", $name))
3237.         return getvar($GLOBALS, $name);
3238.     else switch ($name) {
3239.         case "old":
3240.             return $lastcaptured;
3241.             break;
3242.         case "moved":
3243.             return $lastmoved;
3244.         case "prevsub":
3245.             return prevsub();
3246.             break;
3247.         case "subname":
3248.             return $sub[$scope];
3249.             break;
3250.     }
3251. }
3252. */
3253. 
function prevsub () {
3254.     global 
$sub$scope$ifhead;
3255.     
3256.     
$i $scope;
3257.     while ((
$ifhead[$i] != "sub") && ($ifhead[$i] != "main"))
3258.         
$i--;
3259.     return 
$sub[$i];
3260. }
3261. 
3262. 
?>