Please report any bugs or errors to Fergus Duniho
You may not move into check.
Use your browser's BACK button to go back to the previous page, then reload if necessary.
For general reference, here is the complete list of moves:
1. P f2-f5 1... p g7-g4 2. P f5-g5 2... p h7-h5 3. P g2-g3 3... p f7-f5 4. P d2-d4 4... p a7-a4 5. P c2-c5 5... x f8-h6 6. P b2-b5 6... p e7-e5 7. P a2-a3 7... p d7-d5 8. P b5-a5 8... p b7-b5 9. X c1-c5 9... p c7-b7 10. X c5-b5 10... l b8-a7 11. P a3-b3 11... p b7-b6 12. P e2-e4 12... l a7-a6 13. W e1-f2 13... x h6-g5 14. W f2-e3 14... x c8-c5 15. P e4-f4 15... p e5-e6 16. X f1-f3 16... w d8-d6 17. L b1-c1 17... p b6-c6 18. P f4-h4 18... x c5-b4 19. W e3-c3 19... p c6-b6 20. P a5-b5 20... i h8-h6 21. I a1-a5 21... p f5-f4 22. P d4-a4 22... p d5-c5 23. W c3-d4 23... p e6-e2 24. W d4-f2 24... l g8-a2 25. X f3-a3 25... l a2-a1 26. C h1-c6 26... i h6-d6 27. W f2-g2 27... k e8-d7 28. L g1-a7 28... i d6-c7 29. L a7-f2 29... c a8-e8 30. W g2-e4 30... k d7-c6 31. L f2-f8 31... x g5-d8 32. W e4-e7 32... c e8-g6 33. L f8-a8 33... p h5-d5 34. P b5-b1 34... c g6-e4 35. I a5-b5 35... c e4-h1 36. W e7-e1 36... i c7-b7 37. X a3-d6 37... i b7-d7 38. I b5-c5 38... l a1-c1 39. P g3-b3 39... resignIf this is your settings file, you may edit it at https://www.chessvariants.com/play/pbm/play.php?game=Ultima&settings=Galactic&submit=Edit
Here is a code listing:
0 set movetype MOVE 1 if == thismove null 2 say This preset enforces the rules and displays legal moves. 3 endif 4 echo Please report any bugs or errors to Fergus Duniho 5 set kpos findpiece k spaces 6 set Kpos findpiece K spaces 7 setconst k Black_King 8 setconst K White_King 9 setconst c Black_Coordinator 10 setconst C White_Coordinator 11 setconst l Black_Long_Leaper 12 setconst L White_Long_Leaper 13 setconst x Black_Chameleon 14 setconst X White_Chameleon 15 setconst i Black_Immobilizer 16 setconst I White_Immobilizer 17 setconst w Black_Withdrawer 18 setconst W White_Withdrawer 19 setconst p Black_Pincer_Pawn 20 setconst P White_Pincer_Pawn 21 foreach val (King Coordinator Long_Leaper Chameleon Immobilizer Withdrawer Pincer_Pawn) 22 alias #val White_{#val} 23 alias #val Black_{#val} 24 next 25 include ultima-fairy 26 allow deletions 1 27 sub postauto1 28 if == void space $dest 29 set temp $old 30 add @ $dest 31 setsystem lastmoved #temp 32 setsystem lastcaptured #temp 33 endif 34 set lgl false 35 if not isconst alias $moved 36 die The piece moved is undefined. 37 elseif islower $moved 38 die You may not move one of your opponent's pieces. 39 elseif == $moved $old 40 set from cond $dest $dest $origin 41 if near #from c 1 and == $old I or near #from i 1 and != #from #Kpos 42 set lgl true 43 else 44 die "Your piece may not commit suicide unless it is immobilized and not a King." 45 endif 46 elseif isupper $old 47 die You may not capture your own pieces. 48 endif 49 if capture 50 set nopvc 0 51 else 52 inc nopvc 53 endif 54 set codename const alias $moved 55 if == true #lgl 56 echo "Suicide move from {#from}" 57 elseif sub #codename $origin $dest and issub #codename 58 elseif fn #codename $origin $dest and isfunc #codename and not issub #codename 59 else 60 set name alias #codename 61 set errmsg list thismove "is illegal. You may not move your" #name "from" $origin "to" join $dest ".
" 62 set desc join #name "-Desc" 63 set errmsg str_replace "_" " " join #errmsg str_replace "%s" #name var #desc 64 die #errmsg 65 endif 66 if sub checked var Kpos 67 die You may not move into check. 68 endif 69 unsetflag $origin $dest 70 set posvar join "w" join fencode boardflags 71 inc #posvar 72 endsub 73 sub postauto2 74 if == void space $dest 75 set temp $old 76 add @ $dest 77 setsystem lastmoved #temp 78 setsystem lastcaptured #temp 79 endif 80 set legal false 81 if not isconst alias $moved 82 die The piece $moved is undefined. 83 elseif isupper $moved 84 die You may not move one of your opponent's pieces. 85 elseif == $moved $old 86 set from cond $dest $dest $origin 87 if near #from C 1 and == $old i or near #from I 1 and != #from #kpos 88 set legal true 89 else 90 die "Your piece may not commit suicide unless it is immobilized." 91 endif 92 elseif islower $old 93 die You may not capture your own pieces. 94 endif 95 if capture 96 set nopvc 0 97 else 98 inc nopvc 99 endif 100 set codename const alias $moved 101 if #legal 102 elseif sub #codename $origin $dest and issub #codename 103 elseif fn #codename $origin $dest and isfunc #codename and not issub #codename 104 else 105 set name alias #codename 106 set errmsg list thismove "is illegal. You may not move your" #name "from" $origin "to" join $dest ".
" 107 set desc join #name "-Desc" 108 set errmsg str_replace "_" " " join #errmsg str_replace "%s" #name var #desc 109 die #errmsg 110 endif 111 if sub checked var kpos 112 die You may not move into check. 113 endif 114 unsetflag $origin $dest 115 set posvar join "b" join fencode boardflags 116 inc #posvar 117 endsub 118 moveindex 0 119 MOVE: P f2-f5 120 postauto1 121 moveindex 1 122 MOVE: p g7-g4 123 postauto2 124 moveindex 2 125 MOVE: P f5-g5 126 postauto1 127 moveindex 3 128 MOVE: p h7-h5 129 postauto2 130 moveindex 4 131 MOVE: P g2-g3 132 postauto1 133 moveindex 5 134 MOVE: p f7-f5 135 postauto2 136 moveindex 6 137 MOVE: P d2-d4 138 postauto1 139 moveindex 7 140 MOVE: p a7-a4 141 postauto2 142 moveindex 8 143 MOVE: P c2-c5 144 postauto1 145 moveindex 9 146 MOVE: x f8-h6 147 postauto2 148 moveindex 10 149 MOVE: P b2-b5 150 postauto1 151 moveindex 11 152 MOVE: p e7-e5 153 postauto2 154 moveindex 12 155 MOVE: P a2-a3 156 postauto1 157 moveindex 13 158 MOVE: p d7-d5 159 postauto2 160 moveindex 14 161 MOVE: P b5-a5 162 postauto1 163 moveindex 15 164 MOVE: p b7-b5 165 postauto2 166 moveindex 16 167 MOVE: X c1-c5 168 postauto1 169 moveindex 17 170 MOVE: p c7-b7 171 postauto2 172 moveindex 18 173 MOVE: X c5-b5 174 postauto1 175 moveindex 19 176 MOVE: l b8-a7 177 postauto2 178 moveindex 20 179 MOVE: P a3-b3 180 postauto1 181 moveindex 21 182 MOVE: p b7-b6 183 postauto2 184 moveindex 22 185 MOVE: P e2-e4 186 postauto1 187 moveindex 23 188 MOVE: l a7-a6 189 postauto2 190 moveindex 24 191 MOVE: W e1-f2 192 postauto1 193 moveindex 25 194 MOVE: x h6-g5 195 postauto2 196 moveindex 26 197 MOVE: W f2-e3 198 postauto1 199 moveindex 27 200 MOVE: x c8-c5 201 postauto2 202 moveindex 28 203 MOVE: P e4-f4 204 postauto1 205 moveindex 29 206 MOVE: p e5-e6 207 postauto2 208 moveindex 30 209 MOVE: X f1-f3 210 postauto1 211 moveindex 31 212 MOVE: w d8-d6 213 postauto2 214 moveindex 32 215 MOVE: L b1-c1 216 postauto1 217 moveindex 33 218 MOVE: p b6-c6 219 postauto2 220 moveindex 34 221 MOVE: P f4-h4 222 postauto1 223 moveindex 35 224 MOVE: x c5-b4 225 postauto2 226 moveindex 36 227 MOVE: W e3-c3 228 postauto1 229 moveindex 37 230 MOVE: p c6-b6 231 postauto2 232 moveindex 38 233 MOVE: P a5-b5 234 postauto1 235 moveindex 39 236 MOVE: i h8-h6 237 postauto2 238 moveindex 40 239 MOVE: I a1-a5 240 postauto1 241 moveindex 41 242 MOVE: p f5-f4 243 postauto2 244 moveindex 42 245 MOVE: P d4-a4 246 postauto1 247 moveindex 43 248 MOVE: p d5-c5 249 postauto2 250 moveindex 44 251 MOVE: W c3-d4 252 postauto1 253 moveindex 45 254 MOVE: p e6-e2 255 postauto2 256 moveindex 46 257 MOVE: W d4-f2 258 postauto1 259 moveindex 47 260 MOVE: l g8-a2 261 postauto2 262 moveindex 48 263 MOVE: X f3-a3 264 postauto1 265 moveindex 49 266 MOVE: l a2-a1 267 postauto2 268 moveindex 50 269 MOVE: C h1-c6 270 postauto1 271 moveindex 51 272 MOVE: i h6-d6 273 postauto2 274 moveindex 52 275 MOVE: W f2-g2 276 postauto1 277 moveindex 53 278 MOVE: k e8-d7 279 postauto2 280 moveindex 54 281 MOVE: L g1-a7 282 postauto1 283 moveindex 55 284 MOVE: i d6-c7 285 postauto2 286 moveindex 56 287 MOVE: L a7-f2 288 postauto1 289 moveindex 57 290 MOVE: c a8-e8 291 postauto2 292 moveindex 58 293 MOVE: W g2-e4 294 postauto1 295 moveindex 59 296 MOVE: k d7-c6 297 postauto2 298 moveindex 60 299 MOVE: L f2-f8 300 postauto1 301 moveindex 61 302 MOVE: x g5-d8 303 postauto2 304 moveindex 62 305 MOVE: W e4-e7 306 postauto1 307 moveindex 63 308 MOVE: c e8-g6 309 postauto2 310 moveindex 64 311 MOVE: L f8-a8 312 postauto1 313 moveindex 65 314 MOVE: p h5-d5 315 postauto2 316 moveindex 66 317 MOVE: P b5-b1 318 postauto1 319 moveindex 67 320 MOVE: c g6-e4 321 postauto2 322 moveindex 68 323 MOVE: I a5-b5 324 postauto1 325 moveindex 69 326 MOVE: c e4-h1 327 postauto2 328 moveindex 70 329 MOVE: W e7-e1 330 postauto1 331 moveindex 71 332 MOVE: i c7-b7 333 postauto2 334 moveindex 72 335 MOVE: X a3-d6 336 postauto1 337 moveindex 73 338 MOVE: i b7-d7 339 postauto2 340 moveindex 74 341 MOVE: I b5-c5 342 postauto1 343 moveindex 75 344 MOVE: l a1-c1 345 postauto2 346 moveindex 76 347 MOVE: P g3-b3 348 postauto1 349 moveindex 77 350 MOVE: resign 351 postauto2 352 set posvar join "b" join fencode boardflags 353 if >= var #posvar 3 354 say Three Times Repetition! Drawn Game! 355 drawn 356 elseif sub stalemated var Kpos 357 if sub checked var Kpos 358 say Checkmate! Black has won! 359 won 360 else 361 say Stalemate! Black has won! 362 won 363 endif 364 elseif >= #nopvc 100 365 say Fifty Moves Without Moving a Pawn or Capturing! Game Drawn! 366 drawn 367 elseif sub checked var Kpos 368 say Check! 369 endif 370 end 371 372 lib ultima-fairy 373 include fairychess 374 set Chameleon-Desc "The %s may move as a Queen without capturing by displacement, and it may use another piece's own powers against it. It will immobilize the opponent's Immobilizer if they are adjacent, and it can capture other pieces of the opponent through their own powers of capture. With repect to Long Leapers, it cannot capture or jump over any pieces between it and the Long Leaper even though a Long Leaper would be able to. So, it sometimes cannot capture a Long Leaper that it could capture if it were a Long Leaper. With respect to Pincer Pawns, it can capture them only by moving orthogonally, as Pincer Pawns do. With respect to the King, it can check it from only one space away. Since the %s borrows its capturing power from another piece and has no native capturing power of its own, it cannot capture another %s." 375 def Black_Chameleon fn join "Black_Chameleon_" var movetype #0 #1 376 def Black_Chameleon-Range fn Queen-Range #0 377 def Black_Chameleon_MOVE remove #cap =cap merge #cap aggregate lambda (#0 onlyif == C space #0) array var co1 var co0 =co1 join filename var kpos rankname #to =co0 join filename #to rankname var kpos =cap merge #cap aggregate lambda ( #foe and islower space #ally and == P space #foe and onboard #ally =ally where #foe #0 #1 and onboard #foe =foe where #to #0 #1 and match direction #frm #to n w s e ) ((0 1) (0 -1) (1 0) (-1 0)) =cap merge #cap aggregate lambda (#0 and == W space #0) where #frm sign - file #frm file #to sign - rank #frm rank #to =cap aggregate lambda (#0 onlyif == L space #0) #thepath and not strstr #str "PP" =str string aggregate lambda (cond empty #0 E P) #thepath and alltrue lambda (== L space #0 or empty #0) #thepath =thepath path #frm #to and match direction #frm #to n s e w nw ne sw se and or and empty #frm not capture empty #to and not near #frm I 1 =frm =to 378 def Black_Chameleon_CHECK fn Black_King #0 #1 379 def White_Chameleon fn join "White_Chameleon_" var movetype #0 #1 380 def White_Chameleon-Range fn Queen-Range #0 381 def White_Chameleon_MOVE remove #cap =cap merge #cap aggregate lambda (#0 onlyif == c space #0) array var co1 var co0 =co1 join filename var Kpos rankname #to =co0 join filename #to rankname var Kpos =cap merge #cap aggregate lambda ( #foe and isupper space #ally and == p space #foe and onboard #ally =ally where #foe #0 #1 and onboard #foe =foe where #to #0 #1 and match direction #frm #to n w s e ) ((0 1) (0 -1) (1 0) (-1 0)) =cap merge #cap aggregate lambda (#0 and == w space #0) where #frm sign - file #frm file #to sign - rank #frm rank #to =cap aggregate lambda (#0 onlyif == l space #0) #thepath and not strstr #str "PP" =str string aggregate lambda (cond empty #0 E P) #thepath and alltrue lambda (== l space #0 or empty #0) #thepath =thepath path #frm #to and match direction #frm #to n s e w nw ne sw se and or and empty #frm not capture empty #to and not near #frm i 1 =frm =to 382 def White_Chameleon_CHECK fn White_King #0 #1 383 set Coordinator-Desc "The %s can move as a Queen without capturing by displacement, and it captures any enemy piece on any corner of the rectangle it forms with the King upon its move. This allows it to capture two pieces at once. When it shares a rank or file with its King, the corners are fully occupied by the King and Coordinator, leaving no corner with an enemy piece to be captured." 384 def Black_Coordinator fn join "Black_Coordinator_" var movetype #0 #1 385 def White_Coordinator fn join "White_Coordinator_" var movetype #0 #1 386 def White_Coordinator-Range fn Queen-Range #0 387 def Black_Coordinator-Range fn Queen-Range #0 388 def Black_Coordinator_MOVE remove aggregate lambda (#0 onlyif isupper space #0) array var co0 var co1 =co1 join filename var kpos rankname #to =co0 join filename #to rankname var kpos and fn Queen #frm #to and or and empty #frm not capture empty #to =frm =to 389 def Coordinator_CHECK == #0 #1 390 def White_Coordinator_MOVE remove aggregate lambda (#0 onlyif islower space #0) array var co0 var co1 =co1 join filename var Kpos rankname #to =co0 join filename #to rankname var Kpos and fn Queen #frm #to and or and empty #frm not capture empty #to =frm =to 391 def Black_Coordinator_CHECK anytrue lambda (fn Queen #frm #0 and empty #0 and fnmatch var pat #0) rays #to 1 0 =pat cond var cf join var cf "?" join "?" var cr and or var cf var cr =cr cond == file var kpos file #to rankname #to false =cf cond == rank var kpos rank #to filename #to false =frm =to 392 def White_Coordinator_CHECK anytrue lambda (fn Queen #frm #0 and empty #0 and fnmatch var pat #0) rays #to 1 0 =pat cond var cf join var cf "?" join "?" var cr and or var cf var cr =cr cond == file var Kpos file #to rankname #to false =cf cond == rank var Kpos rank #to filename #to false =frm =to 393 set Immobilizer-Desc "The %s can move as a Queen without capturing. It immobilizes any adjacent piece of the opponent, rendering it completely unable to move or capture except to commit suicide, which will remove it from the board. This should normally be in the form of the piece moving to nothing. Since a King's suicide would be tantamount to resignation, this will be handled through the normal process of resignation and not through letting the King move off its space, which makes it easier to determine stalemate. Unlike other pieces, Immobilizers cannot capture other pieces." 394 def Black_Immobilizer fn join "Black_Immobilizer_" var movetype #0 #1 395 def Black_Immobilizer-Range fn Queen-Range #0 396 def Black_Immobilizer_MOVE fn Queen #frm #to and or and empty #frm not capture empty #to and not near #frm X 1 and not near #frm I 1 =frm =to 397 def Black_Immobilizer_CHECK == #0 #1 398 def White_Immobilizer fn join "White_Immobilizer_" var movetype #0 #1 399 def White_Immobilizer-Range fn Queen-Range #0 400 def White_Immobilizer_MOVE fn Queen #frm #to and or and empty #frm not capture empty #to and not near #frm x 1 and not near #frm i 1 =frm =to 401 def White_Immobilizer_CHECK == #0 #1 402 set King-Desc "The King may move one space in any direction but not into check. Unlike other pieces, it captures by displacement. There is no castling in this game, and unlike other pieces, an immobilized King may not commit suicide, though a player with one may choose to resign instead." 403 def Black_King checkleap #frm #to 1 1 or checkleap #frm #to 1 0 and not near #frm I 1 =frm =to 404 def White_King checkleap #frm #to 1 1 or checkleap #frm #to 1 0 and not near #frm i 1 =frm =to 405 sub Black_King frm to 406 if fn Black_King #frm #to 407 set kpos #to 408 return true 409 endif 410 return false 411 endsub 412 sub White_King frm to 413 if fn White_King #frm #to 414 set Kpos #to 415 return true 416 endif 417 return false 418 endsub 419 copyfn King-Range Black_King-Range 420 copyfn King-Range White_King-Range 421 set Long_Leaper-Desc "The %s moves as a Queen without capturing. To capture pieces, it must hop over them along a single diagonal or orthogonal direction. It may not hop over pieces on the same side, and any enemy piece it hops over must have an empty space immediately behind it. Within the bounds of these restrictions, it can capture as many pieces in one move as the size of the board allows. For the 8x8 board used in Ultima, it may capture up to three pieces at once." 422 def Black_Long_Leaper fn join "Black_Long_Leaper_" var movetype #0 #1 423 def Black_Long_Leaper-Range fn Queen-Range #0 424 def White_Long_Leaper fn join "White_Long_Leaper_" var movetype #0 #1 425 def White_Long_Leaper-Range fn Queen-Range #0 426 def Black_Long_Leaper_MOVE remove aggregate lambda (#0 onlyif isupper space #0) #thepath and not strstr #str "PP" =str string aggregate lambda (cond empty #0 E P) #thepath and allfalse lambda (islower space #0) #thepath =thepath path #frm #to and match direction #frm #to n s e w nw ne sw se or fn Queen #frm #to and or and empty #frm not capture empty #to and not near #frm I 1 =frm =to 427 def White_Long_Leaper_MOVE remove aggregate lambda (#0 onlyif islower space #0) #thepath and not strstr #str "PP" =str string aggregate lambda (cond empty #0 E P) #thepath and allfalse lambda (isupper space #0) #thepath =thepath path #frm #to and match direction #frm #to n s e w nw ne sw se or fn Queen #frm #to and or and empty #frm not capture empty #to and not near #frm i 1 =frm =to 428 def Black_Long_Leaper_CHECK not strstr #str "PP" =str string aggregate lambda (cond empty #0 E P) #thepath and allfalse lambda (islower space #0) #thepath =thepath path #frm #nxt and empty #nxt and onboard #nxt =nxt where #to sign - file #to file #frm sign - rank #to rank #frm and match direction #frm #to n s e w nw ne sw se and not near #frm I 1 =frm =to 429 def White_Long_Leaper_CHECK not strstr #str "PP" =str string aggregate lambda (cond empty #0 E P) #thepath and allfalse lambda (isupper space #0) #thepath =thepath path #frm #nxt and empty #nxt and onboard #nxt =nxt where #to sign - file #to file #frm sign - rank #to rank #frm and match direction #frm #to n s e w nw ne sw se and not near #frm i 1 =frm =to 430 set Pincer_Pawn-Desc "The %s moves as a Rook without capturing by displacement. On reaching its destination, it captures any orthogonally adjacent enemy piece that is adjacent to another of the player's pieces along the same rank or file as it is adjacent with the %s." 431 def Black_Pincer_Pawn fn join "Black_Pincer_Pawn_" var movetype #0 #1 432 def Black_Pincer_Pawn-Range fn Rook-Range #0 433 def White_Pincer_Pawn fn join "White_Pincer_Pawn_" var movetype #0 #1 434 def White_Pincer_Pawn-Range fn Rook-Range #0 435 def Black_Pincer_Pawn_MOVE remove aggregate lambda (#foe and islower space #ally and isupper space #foe and onboard #ally =ally where #foe #0 #1 and onboard #foe =foe where #to #0 #1) ((0 1) (0 -1) (1 0) (-1 0)) and fn Rook #frm #to and or and empty #frm not capture empty #to and not near #frm I 1 =frm =to 436 def White_Pincer_Pawn_MOVE remove aggregate lambda (#foe and isupper space #ally and islower space #foe and onboard #ally =ally where #foe #0 #1 and onboard #foe =foe where #to #0 #1) ((0 1) (0 -1) (1 0) (-1 0)) and fn Rook #frm #to and or and empty #frm not capture empty #to and not near #frm i 1 =frm =to 437 def Black_Pincer_Pawn_CHECK anytrue lambda ( checkride #frm #nbr 1 0 and islower space #ally and onboard #ally =ally where #to neg #0 neg #1 and empty #nbr and onboard #nbr =nbr where #to #0 #1) ((0 1) (0 -1) (1 0) (-1 0)) and > distance #from #to 1 and not near #frm I 1 =frm =to 438 def White_Pincer_Pawn_CHECK anytrue lambda ( checkride #frm #nbr 1 0 and isupper space #ally and onboard #ally =ally where #to neg #0 neg #1 and empty #nbr and onboard #nbr =nbr where #to #0 #1) ((0 1) (0 -1) (1 0) (-1 0)) and > distance #from #to 1 and not near #frm i 1 =frm =to 439 set Withdrawer-Desc "The %s moves as a Queen without capturing by displacement. It captures any enemy piece that was adjacent to it before its move that it moves directly away from. So, it captures only one piece at a time." 440 def Black_Withdrawer fn join "Black_Withdrawer_" var movetype #0 #1 441 def White_Withdrawer fn join "White_Withdrawer_" var movetype #0 #1 442 def Black_Withdrawer-Range fn Queen-Range #0 443 def White_Withdrawer-Range fn Queen-Range #0 444 def Black_Withdrawer_MOVE remove #foe or islower space #foe or empty #foe or not onboard #foe =foe where #frm sign - file #frm file #to sign - rank #frm rank #to and fn Queen #frm #to and or and empty #frm not capture empty #to and not near #frm I 1 =frm =to 445 def White_Withdrawer_MOVE remove #foe or isupper space #foe or empty #foe or not onboard #foe =foe where #frm sign - file #frm file #to sign - rank #frm rank #to and fn Queen #frm #to and or and empty #frm not capture empty #to and not near #frm i 1 =frm =to 446 def Black_Withdrawer_CHECK empty where #frm - file #frm file #to - rank #frm rank #to and == distance #frm #to 1 and not near #frm I 1 =frm =to 447 def White_Withdrawer_CHECK empty where #frm - file #frm file #to - rank #frm rank #to and == distance #frm #to 1 and not near #frm i 1 =frm =to 448 setsystem maxmove 1 449 ban commands allmoves 450 allow moves 1 captures 1 suicides 1 451 sub stalemated kingpos 452 store 453 local cspaces friend friends from king piece to movetype np prom 454 set movetype MOVE 455 set king alias space #kingpos 456 if hasupper #king 457 set friends lambda (onlyupper) 458 set free lambda (haslower #0 or not hasupper #0) 459 set myI I 460 set enemyI i 461 set enemyX x 462 else 463 set friends lambda (onlylower) 464 set free lambda (hasupper #0 or not haslower #0) 465 set myI i 466 set enemyI I 467 set enemyX X 468 endif 469 store 470 for (from piece) fn #friends 471 for to fn join const alias #piece "-Range" #from 472 if fn const alias #piece #from #to and fn #free alias space #to and onboard #to 473 move #from #to 474 if not fn checked cond == #from #kingpos #to #kingpos 475 set pn alias #piece 476 setlegal "{#pn} {#from}-{#to}" 477 endif 478 endif 479 restore 480 next 481 next 482 for (from piece) fn #friends 483 if near #from #enemyX 1 and == #piece #myI or near #from #enemyI 1 and != #from #kingpos 484 empty #from 485 if not fn checked #kingpos 486 set pn alias #piece 487 setlegal "{#pn} {#from}-" 488 endif 489 endif 490 restore 491 next 492 setsystem autorules sub describe_rules 493 return cond count system legalmoves false true 494 endsub 495 endlib 496 lib fairychess 497 if flag use-chess-defaults 498 setconst k King 499 setconst K King 500 setconst q Queen 501 setconst Q Queen 502 setconst r Rook 503 setconst R Rook 504 setconst b Bishop 505 setconst B Bishop 506 setconst n Knight 507 setconst N Knight 508 setconst p Black_Pawn 509 setconst P White_Pawn 510 endif 511 if flag use-chess-defaults 512 set wpr 2 513 set bpr 7 514 set fps 2 515 set pzs 1 516 set wcastle c1 g1 517 set bcastle c8 g8 518 set wprom Q R B N 519 set bprom q r b n 520 set promotable p P 521 elseif not isset wpr 522 set message join "Set the wpr variable to the value of White's Pawn Rank. This is the single rank on which all of White's Pawns start. This would be 2 for Chess.
" var message 523 elseif not isset bpr 524 set message join "Set the bpr variable to the value of Black's Pawn Rank. This is the single rank on which all of Black's Pawns start. This would be 7 for Chess.
" var message 525 elseif not isset fps 526 set message join "Set the fps variable to the value of the maximum number of spaces a Pawn may move on its first move. This would be 2 in Chess.
" var message 527 elseif not isset pzs 528 set message join "Set the pzs variable to the value of the Promotion Zone Size. This is the number of ranks on the opposite side of the board on which Pawns may promote. This would be 1 for Chess.
" var message 529 elseif not isset wcastle 530 set message join "Set the wcastle variable to a space-separated list of the coordinates of the spaces the White King may move to when castling. This would be c1 g1 for Chess.
" var message 531 elseif not isset bcastle 532 set message join "Set the bcastle variable to a space-separated list of the coordinates of the spaces the Black King may move to when castling. This would be c8 g8 for Chess.
" var message 533 elseif not isset wprom 534 set message join "Set the wprom variable to the pieces that a White Pawn may promote to on reaching the Promotion Zone. White's pieces will normally be uppercase, and this would be Q R B N for Chess.
" var message 535 elseif not isset bprom 536 set message join "Set the bprom variable to the pieces that a Black Pawn may promote to on reaching the Promotion Zone. Black's pieces will normally be lowercase, and this would be q r b n for Chess.
" var message 537 endif 538 set ep false 539 setsystem maxmove 2 540 ban commands allmoves 541 allow moves 1 captures 1 promotions 2 542 set Aanca-Desc "The %s may move one space orthgonally, and so long as it is unblocked, it may continue its move in an outward diagonal direction." 543 def Aanca fn (checkride #0 #1 1 1 and empty #0) where #0 0 sign - rank #1 rank #0 #1 or fn (checkride #0 #1 1 1 and empty #0) where #0 sign - file #1 file #0 0 #1 or checkleap #0 #1 1 0 544 def Aanca-Range mergeall leaps #0 1 0 rays where #0 0 1 1 1 rays where #0 0 -1 1 1 rays where #0 1 0 1 1 rays where #0 -1 0 1 1 545 set Amazon-Desc "The %s may move in a straight line in any direction, as a Queen does, or it may leap the the opposite end of a 1x2 rectangle, as a Knight does." 546 def Amazon fn Bishop #0 #1 or fn Rook #0 #1 or fn Knight #0 #1 547 def Amazon-Range merge leaps # 1 2 merge rays #0 1 0 rays #0 1 1 548 set Bede-Desc "The %s may move along any diagonal line, as a Bishop does, or it may leap two spaces away in any orthogonal direction, as a Dabababah does." 549 def Bede checkride #0 #1 1 1 or checkleap #0 #1 0 2 550 def Bede-Range merge rays #0 1 1 leaps #0 0 2 551 def White_Berolina_Pawn remove var epc and checkleap #0 #1 1 0 and == #1 var epp or and checkride #0 #1 1 1 == rankname #0 var wpr or checkleap #0 #1 1 1 and empty #1 or and islower space #1 checkleap #0 #1 1 0 and <= distance #0 #1 var fps and > rank #1 rank #0 552 def Black_Berolina_Pawn remove var epc and checkleap #0 #1 1 0 and == #1 var epp or and checkride #0 #1 1 1 == rankname #0 var bpr or checkleap #0 #1 1 1 and empty #1 or and isupper space #1 checkleap #0 #1 1 0 and <= distance #0 #1 var fps and < rank #1 rank #0 553 def White_Berolina_Pawn-Range filter lambda (onboard #1) mergeall where #ori 0 1 values lambda (where #ori neg #1 #1) range 1 var fps values lambda (where #ori #1 #1) range 1 var fps =ori 554 def Black_Berolina_Pawn-Range filter lambda (onboard #1) mergeall where #ori 0 -1 values lambda (where #ori neg #1 neg #1) range 1 var fps values lambda (where #ori #1 neg #1) range 1 var fps =ori 555 set White_Berolina_Pawn-Desc "The %s may move one space diagonally forward without capturing, or it may move one space straight forward to capture. On its first move, it may move two spaces diagonally forward without capturing so long as it isn't blocked. If this move takes it next to an enemy %s that could have captured it if it had just moved one space, that %s may immediately capture it by en passant, moving to the space it passed over. On reaching the last rank, it may promote." 556 set Black_Berolina_Pawn-Desc var White_Berolina_Pawn-Desc 557 sub White_Berolina_Pawn from to 558 verify > rank #to rank #from 559 verify <= distance #to #from #fps 560 if capture 561 verify checkleap #from #to 1 0 562 set epp false 563 set epc false 564 elseif checkleap #from #to 1 0 and == #to #epp 565 capture #epc 566 set epp false 567 set epc false 568 elseif > distance #to #from 1 569 verify == rankname #from #wpr 570 verify checkride #from #to 1 1 571 set epp elem 0 path #from #to 572 set epc #to 573 else 574 verify checkleap #from #to 1 1 575 set epp false 576 set epc false 577 endif 578 if onboard where #to 0 #pzs 579 if != space #to $moved 580 set name alias const alias $moved 581 die "You may not promote a" #name "until it reaches the promotion zone." 582 endif 583 elseif onboard where #to 0 1 584 if == White_Berolina_Pawn const alias space #to and count var wprom 585 if not $answered and == mln $maxmln 586 push wprom space #to 587 askpromote #wprom 588 endif 589 elseif not match space #to var wprom and != White_Pawn const alias space #to 590 set name alias const alias $moved 591 set newname alias const alias space #to 592 set msg list "You may not promote your" #name "to a" join #newname ".
" 593 set msg str_replace "_" " " var msg 594 die #msg 595 endif 596 elseif count var wprom 597 if == White_Berolina_Pawn const alias space #to 598 if == count var wprom 1 599 set newpiece join list var wprom 600 set newmove join #newpiece "-dest" 601 add #newpiece $dest 602 appendmove #newmove 603 else 604 askpromote #wprom 605 endif 606 elseif not match space #to var wprom 607 set name alias const alias $moved 608 set newname alias const alias space #to 609 set msg list "You may not promote your" #name "to a" join #newname ".
" 610 set msg str_replace "_" " " var msg 611 die #msg 612 endif 613 else 614 set name alias const alias $moved 615 set msg list "You may not advance your" #name "to the last rank, because there is nothing you may promote it to." 616 set msg str_replace "_" " " var msg 617 die #msg 618 endif 619 set nopvc 0 620 return true 621 endsub 622 sub Black_Berolina_Pawn from to 623 verify < rank #to rank #from 624 verify <= distance #to #from #fps 625 if capture 626 verify checkleap #from #to 1 0 627 set epp false 628 set epc false 629 elseif checkleap #from #to 1 0 and == #to #epp 630 capture #epc 631 set epp false 632 set epc false 633 elseif > distance #to #from 1 634 verify == rankname #from #bpr 635 verify checkride #from #to 1 1 636 set epp elem 0 path #from #to 637 set epc #to 638 else 639 verify checkleap #from #to 1 1 640 set epp false 641 set epc false 642 endif 643 if onboard where #to 0 neg #pzs 644 if != space #to $moved 645 set name alias const alias $moved 646 die "You may not promote a" #name "until it reaches the promotion zone." 647 endif 648 elseif onboard where #to 0 -1 649 if == Black_Berolina_Pawn const alias space #to and count var bprom 650 if not $answered and == mln $maxmln 651 push bprom space #to 652 askpromote #bprom 653 endif 654 elseif not match space #to var bprom and != Black_Pawn const alias space #to 655 set name alias const alias $moved 656 set newname alias const alias space #to 657 set msg list "You may not promote your" #name "to a" join #newname ".
" 658 set msg str_replace "_" " " var msg 659 die #msg 660 endif 661 elseif count var bprom 662 if == Black_Berolina_Pawn const alias space #to 663 if == count var bprom 1 664 set newpiece join list var bprom 665 set newmove join #newpiece "-dest" 666 add #newpiece $dest 667 appendmove #newmove 668 else 669 askpromote #bprom 670 endif 671 elseif not match space #to var bprom 672 set name alias const alias $moved 673 set newname alias const alias space #to 674 set msg list "You may not promote your" #name "to a" join #newname ".
" 675 set msg str_replace "_" " " var msg 676 die #msg 677 endif 678 else 679 set name alias const alias $moved 680 set msg list "You may not advance your" #name "to the last rank, because there is nothing you may promote it to." 681 set msg str_replace "_" " " var msg 682 die #msg 683 endif 684 set nopvc 0 685 return true 686 endsub 687 def Bishop checkride #0 #1 1 1 688 def Bishop-Range rays #0 1 1 689 set Bishop-Desc "The %s may move diagonally any number of spaces until it reaches an occupied space." 690 def Cannon cond cond empty #0 capture (not empty #1) (checkhop #0 #1 0 1) (checkride #0 #1 0 1) and #1 691 def Cannon-Range rays #0 1 0 692 set Cannon-Desc "The %s moves any number of spaces orthogonally, as a Rook does, but it must hop over an intervening piece to capture." 693 def Camel checkleap #0 #1 1 3 694 def Camel-Range leaps #0 1 3 695 set Camel-Desc "The %s leaps to any space at the opposite corner of a 1x3 rectangle." 696 def Camelrider checkride #0 #1 1 3 697 def Camelrider-Range rays #0 1 3 698 set Camelrider-Desc "The %s may make any number of Camel moves in the same direction until it lands on an occupied space." 699 def Cardinal fn Bishop #0 #1 or fn Knight #0 #1 700 def Cardinal-Range merge leaps #0 1 2 rays #0 1 1 701 set Cardinal-Desc "The %s may move along diagonals as a Bishop or leap as a Knight." 702 def Centaur checkleap #0 #1 1 1 or checkleap #0 #1 1 0 or checkleap #0 #1 1 2 703 def Centaur-Range merge leaps #0 1 2 merge leaps #0 1 0 leaps #0 1 1 704 set Centaur-Desc "The %s may move to any adjacent space as a King or leap like a Knight." 705 def Champion fn Elephant #0 #1 or fn Dabbabah #0 #1 or fn Wazir #0 #1 706 def Champion-Range mergeall leaps #0 2 2 leaps #0 2 0 leaps #0 1 0 707 set Champion-Desc "The %s may leap one or two spaces orthogonally or two spaces diagonally." 708 def White_Charging_Knight cond < rank #0 rank #1 (checkleap #0 #1 1 2) (checkleap #0 #1 1 1 or checkleap #0 #1 1 0) 709 def White_Charging_Knight-Range mergeall leaps #0 1 2 leaps #0 1 1 leaps #0 1 0 710 set White_Charging_Knight-Desc "The %s may leap forward as a Knight or move one space sideways or backwards like a King." 711 def Black_Charging_Knight cond > rank #0 rank #1 (checkleap #0 #1 1 2) (checkleap #0 #1 1 1 or checkleap #0 #1 1 0) 712 def Black_Charging_Knight-Range mergeall leaps #0 1 2 leaps #0 1 1 leaps #0 1 0 713 set Black_Charging_Knight-Desc "The %s may leap forward as a Knight or move one space sideways or backwards like a King." 714 def White_Charging_Rook checkride #0 #1 1 0 and <= rank #0 rank #1 or checkaleap #0 #1 -1 -1 or checkaleap #0 #1 -1 0 or checkaleap #0 #1 -1 1 715 def White_Charging_Rook-Range mergeall ray #0 0 -1 ray #0 1 0 ray #0 0 1 where #0 -1 1 where #0 1 0 where #0 1 1 716 set White_Charging_Rook-Desc "The %s may move forward or sideways along its file or rank like a Rook, or it may move one space backwards in any direction like a King." 717 def Black_Charging_Rook checkride #0 #1 1 0 and >= rank #0 rank #1 or checkaleap #0 #1 -1 1 or checkaleap #0 #1 1 0 or checkaleap #0 #1 1 1 718 def Black_Charging_Rook-Range mergeall ray #0 0 -1 ray #0 -1 0 ray #0 0 1 where #0 -1 1 where #0 1 0 where #0 1 1 719 set Black_Charging_Rook-Desc "The %s may move forward or sideways along its file or rank like a Rook, or it may move one space backwards in any direction like a King." 720 def Chinese_Elephant checkpath #0 #1 1 1 1 1 721 def Chinese_Elephant-Range leaps #0 2 2 722 set Chinese_Elephant-Desc "The %s may move two spaces diagonally so long as the space in between is empty." 723 def White_Chinese_Elephant checkpath #0 #1 1 1 1 1 and < rank #1 + 1 / lastrank 2 724 def White_Chinese_Elephant-Range leaps #0 2 2 725 set White_Chinese_Elephant-Desc "The %s may move two spaces diagonally so long as the space in between is empty, but it is confined to the ranks on its own side of the board." 726 def Black_Chinese_Elephant checkpath #0 #1 1 1 1 1 and >= rank #1 + 1 / lastrank 2 727 def Black_Chinese_Elephant-Range leaps #0 2 2 728 set Black_Chinese_Elephant-Desc "The %s may move two spaces diagonally so long as the space in between is empty, but it is confined to the ranks on its own side of the board." 729 def Chinese_General checkride #0 #1 1 0 and == Chinese_General const alias cond empty #0 capture space #1 or checkleap #0 #1 0 1 and flag #1 730 def Chinese_General checkride #0 #1 1 0 and == Chinese_General const alias cond empty #0 capture space #1 or checkleap #0 #1 0 1 and flag #1 731 def Chinese_General == distance #0 #1 1 or == var movetype CHECK and checkride #0 #1 1 0 and flag #1 732 def Chinese_General-Range leaps #0 1 0 733 set Chinese_General-Desc "The %s may move one space orthogonally within the confines of the Palace, but it may not face the opponent's %s along an open file." 734 def Chinese_Guard checkleap #0 #1 1 1 and flag #1 735 def Chinese_Guard-Range leaps #0 1 1 736 set Chinese_Guard-Desc "The %s may move one space diagonally within the confines of the palace." 737 def White_Chinese_Pawn checkaleap #0 #1 -1 0 or checkaleap #0 #1 1 0 and >= rank #0 + 1 / lastrank 2 or checkaleap #0 #1 0 1 738 def Black_Chinese_Pawn checkaleap #0 #1 -1 0 or checkaleap #0 #1 1 0 and < rank #0 + 1 / lastrank 2 or checkaleap #0 #1 0 -1 739 def White_Chinese_Pawn-Range leaps #0 1 0 740 def Black_Chinese_Pawn-Range leaps #0 1 0 741 set White_Chinese_Pawn-Desc "The %s may move one space forward. Once it has reached the other side of the board, it may also move one space sideways." 742 set Black_Chinese_Pawn-Desc "The %s may move one space forward. Once it has reached the other side of the board, it may also move one space sideways." 743 def White_Colonel checkride #0 #1 1 0 or checkleap #0 #1 1 2 and >= rank #1 rank #0 or checkleap #0 #1 1 1 or checkleap #0 #1 1 0 744 def White_Colonel mergeall rays #0 1 0 leaps #0 1 2 leaps #0 1 1 745 set White_Colonel-Desc "The %s may move forward or sideways as a Rook, forward as a Knight, and one space in any direction as a King." 746 def Black_Colonel checkride #0 #1 1 0 or checkleap #0 #1 1 2 and <= rank #1 rank #0 or checkleap #0 #1 1 1 or checkleap #0 #1 1 0 747 def Black_Colonel mergeall rays #0 1 0 leaps #0 1 2 leaps #0 1 1 748 set Black_Colonel-Desc "The %s may move forward or sideways as a Rook, forward as a Knight, and one space in any direction as a King." 749 def Dabbabah checkleap #0 #1 0 2 750 def Dabbabah-Range leaps #0 0 2 751 set Dabbabah-Desc "The %s may leap two spaces vertically or horizontally." 752 def Dabbabahrider checkride #0 #1 0 2 753 def Dabbabahrider-Range rays #0 0 2 754 set Dabbabahrider-Desc "The %s may make any number of two space orthogonal leaps in the same direction until it reaches an occupied space." 755 def Dragon_Horse checkride #0 #1 1 1 or checkleap #0 #1 1 0 756 def Dragon_Horse-Range merge leaps #0 1 0 rays #0 1 1 757 set Dragon_Horse-Desc "The %s may move along diagonals as a Bishop or move one space orthogonally as a Wazir." 758 def Dragon_King checkride #0 #1 1 0 or checkleap #0 #1 1 1 759 def Dragon_King-Range merge leaps #0 1 1 rays #0 1 0 760 set Dragon_King-Desc "The %s may move along its rank or file as a Rook or one space diagonally as a Ferz." 761 def Elephant checkleap #0 #1 2 2 762 def Elephant-Range leaps #0 2 2 763 set Elephant-Desc "The %s may leap two spaces in any diagonal direction." 764 def Elephantrider checkride #0 #1 2 2 765 def Elephantrider-Range rays #0 2 2 766 set Elephantrider-Desc "The %s may make a series of two-space diagonal leaps in the same direction. Each leap but the last must be to an empty space, though a leap may take it over an intervening piece." 767 def Eques_Rex checkleap #0 #1 1 1 or checkleap #0 #1 1 0 or checkleap #0 #1 1 2 768 def Eques_Rex-Range merge leaps #0 1 2 merge leaps #0 1 0 leaps #0 1 1 769 set Eques_Rex-Desc "The %s may move to any adjacent space as a King or leap like a Knight." 770 def Fad checkleap #0 #1 1 1 or checkleap #0 #1 2 2 or checkleap #0 #1 2 0 771 def Fad-Range mergeall leaps #0 1 1 leaps #0 2 2 leaps #0 2 0 772 set Fad-Desc "The %s may move one space diagonally, or it may leap two spaces diagonally or orthogonally." 773 def Ferz checkleap #0 #1 1 1 774 def Ferz-Range leaps #0 1 1 775 set Ferz-Desc "The %s may move one space diagonally." 776 def Fibnif checkleap #0 #1 1 2 or checkleap #0 #1 1 1 and == 1 abs - file #0 file #1 777 def Fibnif-Range merge leaps #0 1 2 leaps #0 1 1 778 set Fibnif-Desc "The %s may move one space diagonally or leap as a Knight to any space that is one file and two ranks away." 779 def Giraffe checkleap #0 #1 1 4 780 def Giraffe-Range leaps #0 1 4 781 set Giraffe-Desc "The %s may leap to any space that is one file and four ranks or one rank and four files away." 782 def White_Gold_General checkaleap #0 #1 1 1 or checkaleap #0 #1 -1 1 or checkleap #0 #1 0 1 783 def White_Gold_General-Range mergeall leaps #0 1 0 where #0 1 1 where #0 -1 1 784 set White_Gold_General-Desc "The %s may move one space in any orthgonal direction or one space diagonally forward." 785 def Black_Gold_General checkaleap #0 #1 1 -1 or checkaleap #0 #1 -1 -1 or checkleap #0 #1 0 1 786 def Black_Gold_General-Range mergeall leaps #0 1 0 where #0 1 -1 where #0 -1 -1 787 set Black_Gold_General-Desc "The %s may move one space in any orthgonal direction or one space diagonally forward." 788 def Grasshopper checkgrasshop #0 #1 1 1 or checkgrasshop #0 #1 1 0 789 def Grasshopper-Range merge rays #0 1 0 rays #0 1 1 790 set "The %s moves any number of spaces orthogonally or diagonally like a Queen except that it must hop over exactly one piece, and it must end its move immediately after the piece it hopped over." 791 def Griffon fn (checkride #0 #1 1 0 and empty #0) where #0 sign - file #1 file #0 sign - rank #1 rank #0 #1 and != file #1 file #0 and != rank #1 rank #0 or checkleap #0 #1 1 1 792 def Griffon-Range mergeall leaps #0 1 1 rays where #0 1 1 1 0 rays where #0 1 -1 1 0 rays where #0 -1 -1 1 0 rays where #0 -1 1 1 0 793 set Griffon-Desc "The %s may move one space diagonally, and it may continue its move by moving as a Rook in an outward orthogonal direction. It may not pass over other pieces." 794 def King checkleap #0 #1 1 1 or checkleap #0 #1 1 0 795 def King-Range merge leaps #0 1 0 leaps #0 1 1 796 set King-Desc "The %s leaps one space in any direction. It may castle with a Rook on its first move so long as it is not in check, there is nothing in between it and the Rook, it doesn't pass through check while castling, and the Rook hasn't moved. In castling, it moves two spaces toward the Rook, and the Rook moves to the space the %s passed over." 797 sub King from to 798 if not fn King #from #to 799 verify sub castle #from #to and match #to var cond isupper space #to wcastle bcastle 800 endif 801 if isupper space #to 802 set Kpos #to 803 else 804 set kpos #to 805 endif 806 return true 807 endsub 808 def Knight checkleap #0 #1 1 2 809 def Knight-Range leaps #0 1 2 810 set Knight-Desc "The %s may leap to any space that is one rank and two files away or two ranks and one file away." 811 def Korean_Elephant checkpath #0 #1 1 0 1 1 1 1 812 def Korean_Elephant-Range leaps #0 2 3 813 set "The %s may move one space orthogonally, followed by two more spaces in the same outward diagonal direction. It must complete every part of its move, and it may not pass over an occupied space." 814 def White_Lance checkaride #0 #1 0 1 815 def White_Lance-Range ray #0 0 1 816 set "The %s may move forward in its file as a Rook." 817 def Black_Lance checkaride #0 #1 0 -1 818 def Black_Lance-Range ray #0 0 -1 819 set "The %s may move forward in its file as a Rook." 820 def Leo fn Vao #0 #1 or fn Cannon #0 #1 821 def Leo-Range merge rays #0 1 0 rays #0 1 1 822 set Leo-Desc "The %s may move any number of spaces diagonally or orthogonally, as a Queen does, but it must hop over one intervening piece when it captures." 823 def Mao checktwostep #0 #1 0 1 1 1 824 def Mao-Range leaps #0 1 2 825 set Mao-Desc "The %s moves one space orthogonally, followed by one more space in an outward diagonal direction. It must complete both parts of its move, and it may not pass over an occupied space. It can reach the same spaces as a Knight except that it can be blocked on the first step of its two-space move." 826 def Marshall fn Knight #0 #1 or fn Rook #0 #1 827 def Marshall-Range merge rays #0 1 0 leaps #0 1 2 828 set Marshall-Desc "The %s moves orthogonally as a Rook or leaps as a Knight." 829 def Moa checktwostep #0 #1 1 1 0 1 830 def Moa-Range leaps #0 1 2 831 set Moa-Desc "The %s moves one space diagonally, followed by one more space in an outward orthogonal direction. It must complete both parts of its move, and it may not pass over an occupied space. It can reach the same spaces as a Knight except that it can be blocked on the first step of its two-space move." 832 def Murray_Lion checkleap #0 #1 1 0 or checkleap #0 #1 1 1 and cond empty #0 capture (not empty #1) or checkleap #0 #1 2 2 or checkleap #0 #1 0 2 833 def Murray_Lion-Range merge merge leaps #0 2 0 leaps #0 2 2 merge leaps #0 1 0 leaps #0 1 1 834 set Murray_Lion-Desc "The %s may leap two spaces in any diagonal or orthogonal direction, and it may capture (but not otherwise move) one space in any direction." 835 def Nightrider checkride #0 #1 1 2 836 def Nightrider-Range rays #0 1 2 837 set Nightrider-Desc "The %s may leap as a Knight any number of times in the same direction. While each Knight leap may take it over other pieces, each leap but the last must be to an empty space." 838 set White_Pawn-Desc "The %s may move one space straight forward without capturing, or it may move one space diagonally forward to capture. On its first move, it may move two spaces forward without capturing so long as it isn't blocked. If this move takes it over a space an enemy %s could have captured it on if it had moved there, that %s may immediately capture it by en passant by moving to that space. On reaching the last rank, it must promote to any other piece except the King." 839 set Black_Pawn-Desc var White_Pawn-Desc 840 def White_Pawn remove var ep and < rankname #1 var bpr and < rankname var ep rankname #1 and == filename var ep filename #1 and checkleap #0 #1 1 1 and var ep or and checkride #0 #1 0 1 == rankname #0 var wpr or checkleap #0 #1 0 1 and empty #1 and != var movetype CHECK or and not empty #1 checkleap #0 #1 1 1 and any onboard where #1 0 1 == var movetype CHECK count var wprom and <= distance #0 #1 var fps and > rank #1 rank #0 841 def Black_Pawn remove var ep and > rankname #1 var wpr and > rankname var ep rankname #1 and == filename var ep filename #1 and checkleap #0 #1 1 1 and var ep or and checkride #0 #1 0 1 == rankname #0 var bpr or checkleap #0 #1 0 1 and empty #1 and != var movetype CHECK or and not empty #1 checkleap #0 #1 1 1 and any count var bprom onboard where #1 0 -1 == var movetype CHECK and <= distance #0 #1 var fps and < rank #1 rank #0 842 def White_Pawn-Range filter lambda (onboard #1) mergeall where #ori -1 1 where #ori 1 1 values lambda (where #ori 0 #1) range 1 var fps =ori 843 def Black_Pawn-Range filter lambda (onboard #1) mergeall where #ori -1 -1 where #ori 1 -1 values lambda (where #ori 0 neg #1) range 1 var fps =ori 844 def White_Pawn-Promote var wprom 845 def Black_Pawn-Promote var bprom 846 sub White_Pawn from to 847 my newpiece 848 my newmove 849 my prom 850 verify > rank #to rank #from 851 verify <= distance #to #from #fps 852 if capture 853 verify checkleap #from #to 1 1 854 set ep false 855 elseif checkleap #from #to 1 1 and #ep 856 verify == filename var ep filename #to 857 verify < rankname var ep rankname #to 858 verify < rankname #to var bpr 859 capture #ep 860 set ep false 861 elseif > distance #to #from 1 862 verify == rankname #from #wpr 863 verify checkride #from #to 0 1 864 set ep #to 865 else 866 verify checkleap #from #to 0 1 867 set ep false 868 endif 869 set prom fn White_Pawn-Promote #to 870 if onboard where #to 0 #pzs 871 if != space #to $moved 872 set name alias const alias $moved 873 die "You may not promote a" #name "until it reaches the promotion zone." 874 endif 875 elseif onboard where #to 0 1 876 if == White_Pawn const alias space #to and count var prom 877 if not $answered and == mln $maxmln and not strstr thismove chr 59 878 if not match alias space #to var prom 879 push prom space #to 880 endif 881 askpromote #prom 882 endif 883 elseif not match space #to var prom and != White_Pawn const alias space #to 884 set name alias const alias $moved 885 set newname alias const alias space #to 886 set msg list "You may not promote your" #name "to a" join #newname ".
" 887 set msg str_replace "_" " " var msg 888 die #msg 889 endif 890 elseif count var prom 891 if == White_Pawn const alias space #to 892 if == count var prom 1 893 set newpiece alias list var prom 894 set pieceid realname #newpiece 895 set newmove join #newpiece "-dest" 896 add #pieceid $dest 897 appendmove #newmove 898 else 899 askpromote #prom 900 endif 901 elseif not match alias space #to var prom 902 set name alias const alias $moved 903 set newname alias const alias space #to 904 set msg list "You may not promote your" #name "to a" join #newname ".
" 905 set msg str_replace "_" " " var msg 906 die #msg 907 endif 908 else 909 set name alias const alias $moved 910 set msg list "You may not advance your" #name "to the last rank, because there is nothing you may promote it to." 911 set msg str_replace "_" " " var msg 912 die #msg 913 endif 914 set nopvc 0 915 return true 916 endsub 917 sub Black_Pawn from to 918 my newpiece, pieceid 919 my newmove 920 my prom 921 verify < rank #to rank #from 922 verify <= distance #to #from #fps 923 if capture 924 verify checkleap #from #to 1 1 925 set ep false 926 elseif checkleap #from #to 1 1 and #ep 927 verify == filename var ep filename #to 928 verify > rankname var ep rankname #to 929 verify > rankname #to var wpr 930 capture #ep 931 set ep false 932 elseif > distance #to #from 1 933 verify == rankname #from #bpr 934 verify checkride #from #to 0 1 935 set ep #to 936 else 937 verify checkleap #from #to 0 1 938 set ep false 939 endif 940 set prom fn Black_Pawn-Promote #to 941 if onboard where #to 0 neg #pzs 942 if != space #to $moved 943 set name alias const alias $moved 944 die "You may not promote a" #name "until it reaches the promotion zone." 945 endif 946 elseif onboard where #to 0 -1 947 if == Black_Pawn const alias space #to and count var prom 948 if not $answered and == mln $maxmln and not strstr thismove chr 59 949 push prom space #to 950 askpromote #prom 951 endif 952 elseif not match space #to var prom and != Black_Pawn const alias space #to 953 set name alias const alias $moved 954 set newname alias const alias space #to 955 set msg list "You may not promote your" #name "to a" join #newname ".
" 956 set msg str_replace "_" " " var msg 957 die #msg 958 endif 959 elseif count var prom 960 if == Black_Pawn const alias space #to 961 if == count var prom 1 962 set newpiece alias list var prom 963 set newmove join #newpiece "-dest" 964 set pieceid realname var newpiece 965 add #pieceid $dest 966 appendmove #newmove 967 else 968 askpromote #prom 969 endif 970 elseif not match alias space #to var prom 971 set name alias const alias $moved 972 set newname alias const alias space #to 973 set msg list "You may not promote your" #name "to a" join #newname ".
" 974 set msg str_replace "_" " " var msg 975 die #msg 976 endif 977 else 978 set name alias const alias $moved 979 set msg list "You may not advance your" #name "to the last rank, because there is nothing you may promote it to." 980 set msg str_replace "_" " " var msg 981 die #msg 982 endif 983 set nopvc 0 984 return true 985 endsub 986 set White_Quick_Pawn-Desc "The %s may move one or two spaces straight forward without capturing, or it may move one space diagonally forward to capture. If its two-space move takes it over a space an enemy %s could have captured it on if it had moved there, that %s may immediately capture it by en passant by moving to that space. On reaching the last rank, it must promote to any other piece except the King." 987 set Black_Quick_Pawn-Desc var White_Quick_Pawn-Desc 988 def White_Quick_Pawn remove var ep and < rankname #1 rankname var epf and < rankname var ep rankname #1 and == filename var ep filename #1 and checkleap #0 #1 1 1 and var ep or checkride #0 #1 0 1 and empty #1 and != var movetype CHECK or and or not empty #1 == var movetype CHECK checkleap #0 #1 1 1 and any onboard where #1 0 1 == var movetype CHECK count var wprom and <= distance #0 #1 var fps and > rank #1 rank #0 989 def Black_Quick_Pawn remove var ep and > rankname #1 rankname var epf and > rankname var ep rankname #1 and == filename var ep filename #1 and checkleap #0 #1 1 1 and var ep or checkride #0 #1 0 1 and empty #1 and != var movetype CHECK or and or not empty #1 == var movetype CHECK checkleap #0 #1 1 1 and any count var bprom onboard where #1 0 -1 == var movetype CHECK and <= distance #0 #1 var fps and < rank #1 rank #0 990 def White_Quick_Pawn-Range filter lambda (onboard #1) mergeall where #ori -1 1 where #ori 1 1 values lambda (where #ori 0 #1) range 1 var fps =ori 991 def Black_Quick_Pawn-Range filter lambda (onboard #1) mergeall where #ori -1 -1 where #ori 1 -1 values lambda (where #ori 0 neg #1) range 1 var fps =ori 992 def White_Quick_Pawn-Promote var wprom 993 def Black_Quick_Pawn-Promote var bprom 994 sub White_Quick_Pawn from to 995 my newpiece 996 my newmove 997 my prom 998 verify > rank #to rank #from 999 verify <= distance #to #from #fps 1000 if capture 1001 verify checkleap #from #to 1 1 1002 set epf false 1003 set ep false 1004 elseif checkleap #from #to 1 1 and #ep 1005 verify == filename var ep filename #to 1006 verify < rankname var ep rankname #to 1007 verify < rankname #to rankname var epf 1008 capture #ep 1009 set epf false 1010 set ep false 1011 elseif > distance #to #from 1 1012 verify checkride #from #to 0 1 1013 set epf #from 1014 set ep #to 1015 else 1016 verify checkleap #from #to 0 1 1017 set epf false 1018 set ep false 1019 endif 1020 set prom fn White_Quick_Pawn-Promote #to 1021 if onboard where #to 0 #pzs 1022 if != space #to $moved 1023 set name alias const alias $moved 1024 die "You may not promote a" #name "from" $moved "to" {space #to} "until it reaches the promotion zone." 1025 endif 1026 elseif onboard where #to 0 1 1027 if == White_Quick_Pawn const alias space #to and count var prom 1028 if not $answered and == mln $maxmln and not strstr thismove chr 59 1029 if not match alias space #to var prom 1030 push prom space #to 1031 endif 1032 askpromote #prom 1033 endif 1034 elseif not match space #to var prom and != White_Quick_Pawn const alias space #to 1035 set name alias const alias $moved 1036 set newname alias const alias space #to 1037 set msg list "You may not promote your" #name "to a" join #newname ".
" 1038 set msg str_replace "_" " " var msg 1039 die #msg 1040 endif 1041 elseif count var prom 1042 if == White_Quick_Pawn const alias space #to 1043 if == count var prom 1 1044 set newpiece alias list var prom 1045 set pieceid realname #newpiece 1046 set newmove join #newpiece "-dest" 1047 add #pieceid $dest 1048 appendmove #newmove 1049 else 1050 askpromote #prom 1051 endif 1052 elseif not match alias space #to var prom 1053 set name alias const alias $moved 1054 set newname alias const alias space #to 1055 set msg list "You may not promote your" #name "to a" join #newname ".
" 1056 set msg str_replace "_" " " var msg 1057 die #msg 1058 endif 1059 else 1060 set name alias const alias $moved 1061 set msg list "You may not advance your" #name "to the last rank, because there is nothing you may promote it to." 1062 set msg str_replace "_" " " var msg 1063 die #msg 1064 endif 1065 set nopvc 0 1066 return true 1067 endsub 1068 sub Black_Quick_Pawn from to 1069 my newpiece, pieceid 1070 my newmove 1071 my prom 1072 verify < rank #to rank #from 1073 verify <= distance #to #from #fps 1074 if capture 1075 verify checkleap #from #to 1 1 1076 set ep false 1077 set epf false 1078 elseif checkleap #from #to 1 1 and #ep 1079 verify == filename var ep filename #to 1080 verify > rankname var ep rankname #to 1081 verify > rankname #to rankname var epf 1082 capture #ep 1083 set ep false 1084 set epf false 1085 elseif > distance #to #from 1 1086 verify checkride #from #to 0 1 1087 set ep #to 1088 set epf #from 1089 else 1090 verify checkleap #from #to 0 1 1091 set ep false 1092 set epf false 1093 endif 1094 set prom fn Black_Quick_Pawn-Promote #to 1095 if onboard where #to 0 neg #pzs 1096 if != space #to $moved 1097 set name alias const alias $moved 1098 die "You may not promote a" #name "until it reaches the promotion zone." 1099 endif 1100 elseif onboard where #to 0 -1 1101 if == Black_Quick_Pawn const alias space #to and count var prom 1102 if not $answered and == mln $maxmln and not strstr thismove chr 59 1103 push prom space #to 1104 askpromote #prom 1105 endif 1106 elseif not match space #to var prom and != Black_Quick_Pawn const alias space #to 1107 set name alias const alias $moved 1108 set newname alias const alias space #to 1109 set msg list "You may not promote your" #name "to a" join #newname ".
" 1110 set msg str_replace "_" " " var msg 1111 die #msg 1112 endif 1113 elseif count var prom 1114 if == Black_Quick_Pawn const alias space #to 1115 if == count var prom 1 1116 set newpiece alias list var prom 1117 set newmove join #newpiece "-dest" 1118 set pieceid realname var newpiece 1119 add #pieceid $dest 1120 appendmove #newmove 1121 else 1122 askpromote #prom 1123 endif 1124 elseif not match alias space #to var prom 1125 set name alias const alias $moved 1126 set newname alias const alias space #to 1127 set msg list "You may not promote your" #name "to a" join #newname ".
" 1128 set msg str_replace "_" " " var msg 1129 die #msg 1130 endif 1131 else 1132 set name alias const alias $moved 1133 set msg list "You may not advance your" #name "to the last rank, because there is nothing you may promote it to." 1134 set msg str_replace "_" " " var msg 1135 die #msg 1136 endif 1137 set nopvc 0 1138 return true 1139 endsub 1140 def Queen fn Bishop #0 #1 or fn Rook #0 #1 1141 def Queen-Range merge rays #0 1 0 rays #0 1 1 1142 set Queen-Desc "The %s may move as a Rook or a Bishop." 1143 def Rhino windingride #0 #1 1 0 1 1 or windingride #0 #1 0 1 1 1 1144 def Rhino-Range merge eval (windingrays #0 1 0 1 1) windingrays #0 0 1 1 1 1145 set Rhino-Desc "The %s moves along a winding path that alternates between the same one-space orthogonal move and the same one-space diagonal move both in the same general direction." 1146 def Rook checkride #0 #1 1 0 1147 def Rook-Range rays #0 1 0 1148 set Rook-Desc "The %s may move any number of spaces in any vertical or horizontal direction until it reaches an occupied space." 1149 def Short_Rook checkride #0 #1 1 0 and <= distance #0 #1 4 1150 def Short_Rook-Range merge merge leaps #0 1 0 leaps #0 2 0 merge leaps #0 3 0 leaps #0 4 0 1151 set "The %s may move up to four spaces along its rank or file as a Rook." 1152 def White_Shogi_Knight checkaleap #0 #1 1 2 or checkaleap #0 #1 -1 2 1153 def White_Shogi_Knight-Range array where #0 1 2 where #0 -1 2 1154 set White_Shogi_Knight-Desc "The %s may leap to either space that is two ranks ahead and one file to the side." 1155 def Black_Shogi_Knight checkaleap #0 #1 1 -2 or checkaleap #0 #1 -1 -2 1156 def Black_Shogi_Knight-Range array where #0 1 -2 where #0 -1 -2 1157 set Black_Shogi_Knight-Desc "The %s may leap to either space that is two ranks ahead and one file to the side." 1158 def White_Shogi_Pawn checkaleap #0 #1 0 1 1159 def White_Shogi_Pawn-Range array where #0 0 1 1160 set White_Shogi_Pawn-Desc "The %s map move one space forward in the same file." 1161 def Black_Shogi_Pawn checkaleap #0 #1 0 -1 1162 def Black_Shogi_Pawn-Range array where #0 0 -1 1163 set Black_Shogi_Pawn-Desc "The %s map move one space forward in the same file." 1164 def White_Silver_General checkaleap #0 #1 0 1 or checkleap #0 #1 1 1 1165 def White_Silver_General-Range mergeall leaps #0 1 1 where #0 0 1 1166 set White_Silver_General-Desc "The %s may move one space in any diagonal direction or one space vertically foward." 1167 def Black_Silver_General checkaleap #0 #1 0 -1 or checkleap #0 #1 1 1 1168 def Black_Silver_General-Range mergeall leaps #0 1 1 where #0 0 -1 1169 set Black_Silver_General-Desc "The %s may move one space in any diagonal direction or one space vertically foward." 1170 def Squirrel fn Elephant #0 #1 or fn Dabbabah #0 #1 or fn Knight #0 #1 1171 def Squirrel-Range mergeall leaps #0 2 2 leaps #0 2 0 leaps #0 1 2 1172 set Squirrel-Desc "The %s may leap any non-adjacent space that is no more than two spaces away." 1173 def Spider fn Dabbabah #0 #1 or fn Elephant #0 #1 1174 def Spider-Range merge leaps #0 2 2 leaps #0 0 2 1175 set Spider-Desc "The %s may leap to any space that is two spaces away orthogonally or diagonally." 1176 def Spider-rider fn Dabbabahrider #0 #1 or fn Elephantrider #0 #1 1177 def Spider-rider-Range merge rays #0 2 2 rays #0 0 2 1178 set Spider-rider-Desc "The %s may make any number of two-space leaps in a single orthogonal or diagonal direction. While each leap may take it over an occupied space, each leap but the last must be to an empty space." 1179 def Squire checktwostep #0 #1 0 1 1 1 or checktwostep #0 #1 1 1 0 1 1180 def Squire-Range leaps #0 1 2 1181 set Squire-Desc "The %s may move one space orthogonally, followed by one more space in an outward diagonal direction, or it may move one space diagonally, followed by one more space in an outward orthogonal direction. It must complete both parts of its move, and it may not pass over an occupied space. It can reach the same spaces as a Knight except that it can be blocked on the first step of its two-space move." 1182 def Unicorn fn Nightrider #0 #1 or fn Bishop #0 #1 1183 def Unicorn-Range merge rays #0 1 2 rays #0 1 1 1184 set Unicorn-Desc "The %s may make consecutive Knight moves in the same direction, as a Nightrider does, or it may move diagonally as a Bishop." 1185 def Vao cond cond empty #0 capture (not empty #1) (checkhop #0 #1 1 1) (checkride #0 #1 1 1) and #1 1186 def Vao-Range rays #0 1 1 1187 set Vao-Desc "The %s may move diagonally as a Bishop, but it must hop over exactly one intervening piece when it captures." 1188 def Wazir checkleap #0 #1 1 0 1189 def Wazir-Range leaps #0 1 0 1190 set Wazir-Desc "The %s may move one space horizontally or vertically." 1191 def Wizard fn Ferz #0 #1 or fn Camel #0 #1 1192 def Wizard-Range merge leaps #0 1 1 leaps #0 1 3 1193 set Wizard-Desc "The %s may move one space diagonally, or it may leap to a space three ranks and one file or three files and one rank away, as a Camel does." 1194 def Woody_Rook checkleap #0 #1 0 2 or checkleap #0 #1 0 1 1195 def Woody_Rook-Range merge leaps #0 0 1 leaps #0 0 2 1196 set Woody_Rook-Desc "The %s may leap one or two spaces orthogonally. It may pass over another piece when moving two spaces." 1197 def Zebra checkleap #0 #1 2 3 1198 def Zebra-Range leaps #0 2 3 1199 set Zebra-Desc "The %s may leap to any space that is 2 ranks and 3 files or 2 files and 3 ranks away." 1200 def Elephant_Ferz fn Ferz #0 #1 or fn Elephant #0 #1 1201 def Elephant_Ferz-Range merge leaps #0 2 2 leaps #0 1 1 1202 set Elephant_Ferz-Desc "The %s may leap one or two spaces diagonally. It may pass over another piece when moving two spaces." 1203 def Elephant_Wazir fn Wazir #0 #1 or fn Elephant #0 #1 1204 def Elephant_Wazir-Range merge leaps #0 2 2 leaps #0 1 0 1205 set Elephant_Wazir-Desc "The %s may move one space orthogonally, as a Wazir, or leap two spaces diagonally, as an Elephant." 1206 def Kylin fn Ferz #0 #1 or fn Dabbabah #0 #1 1207 def Kylin-Range mergeall leaps #0 1 1 leaps #0 2 0 1208 set Kylin-Desc "The %s may move one space diagonally, or it may leap 2 spaces orthogonally, passing over any pieces in the way." 1209 def Half_Duck fn Ferz #0 #1 or fn Dabbabah #0 #1 or checkleap #0 #1 3 0 1210 def Half_Duck-Range mergeall leaps #0 1 1 leaps #0 2 0 leaps #0 3 0 1211 set Half_Duck-Desc "The %s may move one space diagonally, or it may leap 2 or 3 spaces orthogonally, passing over any pieces in the way." 1212 def Knight_Wazir fn Knight #0 #1 or fn Wazir #0 #1 1213 def Knight_Wazir-Range merge leaps #0 1 2 leaps #0 1 0 1214 set Knight_Wazir-Desc "The %s may move one space orthogonally, as a Wazir, or it may leap as a Knight to any space one file and two ranks or two files and one rank away." 1215 def Frog fn Ferz #0 #1 or checkleap #0 #1 3 0 1216 def Frog-Range merge leaps #0 1 1 leaps #0 3 0 1217 set Frog-Desc "The %s may move one space diagonally or directly leap 3 spaces orthogonally." 1218 def Buffalo fn Knight #0 #1 or fn Camel #0 #1 or fn Zebra #0 #1 1219 def Buffalo-Range mergeall leaps #0 1 2 leaps #0 1 3 leaps #0 2 3 1220 set Buffalo-Desc "The %s Buffalo may leap (1, 2) as a Knight, (1, 3) as a Camel, or (2, 3) as a Zebra." 1221 def @ false 1222 sub attacked start finish 1223 my from piece actual 1224 local movetype 1225 set movetype MOVE 1226 if empty #start 1227 set actual true 1228 move #finish #start 1229 add $old #finish 1230 endif 1231 if isupper space #start 1232 def enemies onlylower 1233 else 1234 def enemies onlyupper 1235 endif 1236 for (from piece) fn enemies 1237 if fn const alias #piece #from #to 1238 if #actual 1239 move #start #finish 1240 endif 1241 return #from 1242 endif 1243 next 1244 if #actual 1245 move #start #finish 1246 endif 1247 return false 1248 endsub 1249 sub fission-attacked start finish 1250 my from piece p1 p2 1251 local movetype 1252 set p1 space #start 1253 set p2 space #finish 1254 set movetype CHECK 1255 if isupper #p1 1256 def enemies onlylower 1257 else 1258 def enemies onlyupper 1259 endif 1260 empty #finish 1261 for (from piece) fn enemies 1262 if fn const alias #piece #from #start 1263 add #p2 #finish 1264 return #from 1265 endif 1266 next 1267 add #p2 #finish 1268 return false 1269 endsub 1270 sub checked king 1271 my from piece 1272 local movetype 1273 set movetype CHECK 1274 if isupper cond empty var king $moved space var king 1275 def enemies onlylower 1276 else 1277 def enemies onlyupper 1278 endif 1279 for (from piece) fn enemies 1280 if fn const alias #piece #from var king and isfunc const alias #piece 1281 return #from 1282 endif 1283 next 1284 return false 1285 endsub 1286 def checked anytrue lambda (fn const alias #0 var key var king) cond isupper space var king (onlylower) (onlyupper) =movetype CHECK =king 1287 def threatened anytrue lambda (fn const alias space #0 #0 var king) elem var king threats =movetype CHECK =king 1288 sub uncheckedpath start finish 1289 my from to piece kingpos 1290 local movetype 1291 set movetype CHECK 1292 if empty #finish 1293 set kingpos #start 1294 else 1295 set kingpos #finish 1296 endif 1297 if isupper space #kingpos 1298 def enemies onlylower 1299 else 1300 def enemies onlyupper 1301 endif 1302 for to path #start #finish 1303 move #kingpos #to 1304 for (from piece) fn enemies 1305 if fn const alias #piece #from #to 1306 move #to #kingpos 1307 return false 1308 endif 1309 next 1310 move #to #kingpos 1311 next 1312 return true 1313 endif 1314 sub uncheckedknightleap start finish 1315 my from to piece kingpos kingpiece checkedpaths 1316 local movetype 1317 set movetype CHECK 1318 if empty #start 1319 set kingpos #finish 1320 else 1321 set kingpos #start 1322 endif 1323 if isupper space #kingpos 1324 def enemies onlylower 1325 else 1326 def enemies onlyupper 1327 endif 1328 set kingpiece space #kingpos 1329 set avenues merge intersection leaps #start 1 0 leaps #finish 1 1 intersection leaps #start 1 1 leaps #finish 1 0 1330 set checkdpaths 0 1331 for to #avenues 1332 if empty #to 1333 move #kingpos #to 1334 else 1335 empty #kingpos 1336 endif 1337 for (from piece) fn enemies 1338 if fn const alias #piece #from #to 1339 inc checkedpaths 1340 break 1341 endif 1342 next 1343 if == space #to #kingpiece 1344 move #to #kingpos 1345 else 1346 add #kingpiece #kingpos 1347 endif 1348 if == checkedpaths 0 1349 break 1350 endif 1351 next 1352 return < var checkedpaths 2 1353 endif 1354 sub castle from to 1355 local coord RPOS RDEST xdir 1356 if not flag #from 1357 die A King may not castle after it moves. 1358 endif 1359 if capture 1360 die A King may not castle to an occupied space. 1361 endif 1362 set xdir sign minus file #to file #from 1363 if not checkaride #from #to #xdir 0 1364 die A King may not castle across any occupied space. 1365 endif 1366 set coord #to 1367 do 1368 set coord where #coord #xdir 0 1369 if flag #coord 1370 break 1371 elseif not onboard #coord 1372 die No piece was found to castle with. 1373 elseif not empty #coord 1374 die The King cannot castle with the piece at #coord 1375 endif 1376 loop 1377 set RPOS #coord 1378 move #to #from 1379 if sub checked #from 1380 die A King may not castle out of check. 1381 endif 1382 store 1383 for coord path #from #to 1384 move #from #coord 1385 if sub checked #coord 1386 die A King may not castle through check. 1387 endif 1388 restore 1389 next 1390 move #from #to 1391 set RDEST where #to neg #xdir 0 1392 move #RPOS #RDEST 1393 return true 1394 endsub 1395 sub castlepos from to 1396 local coord RPOS RDEST xdir safe 1397 verify flag #from 1398 verify empty #to 1399 set xdir sign minus file #to file #from 1400 verify checkaride #from #to #xdir 0 1401 verify not sub checked #from 1402 set coord #to 1403 do 1404 set coord where #coord #xdir 0 1405 if flag #coord 1406 break 1407 endif 1408 verify onboard #coord 1409 verify empty #coord 1410 loop 1411 verify flag #coord 1412 set RPOS #coord 1413 store 1414 for coord path #from #to 1415 move #from #coord 1416 set safe not sub checked #coord 1417 restore 1418 verify #safe 1419 next 1420 move #from #to 1421 set RDEST where #to neg #xdir 0 1422 move #RPOS #RDEST 1423 set safe not sub checked #to 1424 restore 1425 return #safe 1426 endsub 1427 sub castle2 kingfrom kingto rookfrom rookto 1428 local coord xdir king rook 1429 if not flag #kingfrom 1430 die A King may not castle after it moves. 1431 endif 1432 if not flag #rookfrom 1433 die A King may not castle with a piece that has already moved. 1434 endif 1435 if not match @ $lastcaptured $prevcaptured 1436 die Castling to an occupied space is not allowed. 1437 endif 1438 if empty #kingto 1439 die There is nothing on #kingto. Did you move a piece there and then move it away? 1440 endif 1441 if empty #rookto 1442 die There is nothing on #rookto. Did you move a piece there and then move it away? 1443 endif 1444 set king space #kingto 1445 set rook space #rookto 1446 if == #king #rook 1447 die "Castling must be between different pieces. These two are both {#king}. What happened?" 1448 endif 1449 empty #kingto 1450 empty #rookto 1451 add #king #kingfrom 1452 add #rook #rookfrom 1453 set xdir sign minus file #kingto file #kingfrom 1454 if not checkaride #kingfrom #kingto #xdir 0 1455 die A King may not castle across any occupied space. 1456 endif 1457 if not checkaride #rookto #rookfrom #xdir 0 1458 die A Rook may not castle across an occupied space. 1459 endif 1460 if sub checked #kingfrom 1461 die A King may not castle out of check. 1462 endif 1463 store 1464 for coord path #kingfrom #kingto 1465 move #kingfrom #coord 1466 if sub checked #coord 1467 die A King may not castle through check. 1468 endif 1469 restore 1470 next 1471 empty #kingfrom 1472 empty #rookfrom 1473 add #king #kingto 1474 add #rook #rookto 1475 unsetflag #kingfrom #rookfrom 1476 if isupper space #kingto 1477 set Kpos #kingto 1478 else 1479 set kpos #kingto 1480 endif 1481 return true 1482 endsub 1483 sub castlepos2 kingfrom kingto rookfrom rookto 1484 echo "Calling castlepos2" #kingfrom #kingto #rookfrom #rookto 1485 local coord xdir safe 1486 verify flag #kingfrom and flag #rookfrom 1487 echo "Verified flags" 1488 verify empty #kingto or == #kingto #rookfrom 1489 verify empty #rookto or == #rookto #kingfrom 1490 echo "Verified empty destinations" 1491 set xdir sign minus file #kingto file #kingfrom 1492 echo "xdir is {#xdir}" 1493 verify checkride #kingfrom #kingto #xdir 0 1494 echo "Verified checkride {#kingfrom} {#kingto} {#xdir} 0" 1495 verify checkride #rookto #rookfrom #xdir 0 1496 echo "Verified checkride {#kingto} {#kingfrom} {#xdir} 0" 1497 verify not sub checked #kingfrom 1498 echo "Verified not checked" 1499 store 1500 for coord path #kingfrom #kingto 1501 move #kingfrom #coord 1502 set safe not sub checked #coord 1503 restore 1504 verify #safe 1505 next 1506 move #kingfrom #kingto 1507 move #rookfrom #rookto 1508 set safe not sub checked #kingto 1509 restore 1510 return #safe 1511 endsub 1512 sub stalemated kingpos 1513 store 1514 local cspaces friend friends from king piece to movetype np prom promfn 1515 set movetype MOVE 1516 set king alias space #kingpos 1517 if hasupper #king 1518 set friends lambda (onlyupper) 1519 set free lambda (haslower #0 or not hasupper #0) 1520 set pzone lambda (not onboard where #0 0 var pzs) 1521 set cspaces var wcastle 1522 set prom var wprom 1523 else 1524 set friends lambda (onlylower) 1525 set free lambda (hasupper #0 or not haslower #0) 1526 set pzone lambda (not onboard where #0 0 neg var pzs) 1527 set cspaces var bcastle 1528 set prom var bprom 1529 endif 1530 store 1531 for (from piece) fn #friends 1532 set af alias #from 1533 for to fn join const alias #piece "-Range" #from 1534 set at alias #to 1535 if fn const alias #piece #from #to and fn #free alias space #to and onboard #to 1536 set ap alias #piece 1537 move #from #to 1538 if not sub checked cond == #from #kingpos #to #kingpos 1539 set promfn join const alias #piece "-Promote" 1540 if fn #pzone #to and match #piece #promotable 1541 if > count var prom 0 1542 for np var prom 1543 setlegal "{#ap} {#af}-{#at}; {#np}-{#at}" 1544 next 1545 endif 1546 elseif fn #pzone #to and isfunc var promfn 1547 set prom fn var promfn #to 1548 if > count var prom 0 1549 for np var prom 1550 setlegal "{#ap} {#af}-{#at}; {#np}-{#at}" 1551 next 1552 endif 1553 elseif fn #pzone #to and match #piece #promotable 1554 if > count var prom 0 1555 for np var prom 1556 setlegal "{#ap} {#af}-{#at}; {#np}-{#at}" 1557 next 1558 endif 1559 else 1560 setlegal "{#ap} {#af}-{#at}" 1561 endif 1562 endif 1563 endif 1564 restore 1565 next 1566 next 1567 if > count var cspaces 0 1568 for to var cspaces 1569 if sub castlepos #kingpos #to 1570 setlegal "{#king} {#kingpos}-{#to}" 1571 endif 1572 next 1573 endif 1574 setsystem autorules sub describe_rules 1575 return cond count system legalmoves false true 1576 endsub 1577 sub stalemated-quick kingpos 1578 store 1579 local checked checkpos cspaces enemies friend friends from in king piece threats to movetype np prom promfn 1580 set movetype MOVE 1581 set king alias space #kingpos 1582 if hasupper #king 1583 set friends lambda (onlyupper) 1584 set enemies lambda (onlylower) 1585 set free lambda (haslower #0 or not hasupper #0) 1586 set pzone lambda (not onboard where #0 0 var pzs) 1587 set cspaces var wcastle 1588 set prom var wprom 1589 else 1590 set friends lambda (onlylower) 1591 set enemies lambda (onlyupper) 1592 set free lambda (hasupper #0 or not haslower #0) 1593 set pzone lambda (not onboard where #0 0 neg var pzs) 1594 set cspaces var bcastle 1595 set prom var bprom 1596 endif 1597 set krange merge fn join const alias space #kingpos "-Range" #kingpos #kingpos 1598 set threats () 1599 for to #krange 1600 set threats.{#to} () 1601 next 1602 for (from piece) fn #enemies 1603 set in intersection var krange fn join const alias var piece "-Range" var from 1604 for to #in 1605 push threats.{#to} #from 1606 next 1607 next 1608 store 1609 for (from piece) fn #friends 1610 set af alias #from 1611 for to fn join const alias #piece "-Range" #from 1612 set at alias #to 1613 if fn const alias #piece #from #to and fn #free alias space #to and onboard #to 1614 set ap alias #piece 1615 set checkpos cond == #from #kingpos #to #kingpos 1616 set checked false 1617 if count elem var checkpos threats 1618 move #from #to 1619 set checked fn threatened #checkpos 1620 restore 1621 endif 1622 if not #checked 1623 set promfn join const alias #piece "-Promote" 1624 if fn #pzone #to and match #piece #promotable 1625 if > count var prom 0 1626 for np var prom 1627 setlegal "{#ap} {#af}-{#at}; {#np}-{#at}" 1628 next 1629 endif 1630 elseif fn #pzone #to and isfunc var promfn 1631 set prom fn var promfn #to 1632 if > count var prom 0 1633 for np var prom 1634 setlegal "{#ap} {#af}-{#at}; {#np}-{#at}" 1635 next 1636 endif 1637 elseif fn #pzone #to and match #piece #promotable 1638 if > count var prom 0 1639 for np var prom 1640 setlegal "{#ap} {#af}-{#at}; {#np}-{#at}" 1641 next 1642 endif 1643 else 1644 setlegal "{#ap} {#af}-{#at}" 1645 endif 1646 endif 1647 endif 1648 restore 1649 next 1650 next 1651 if > count var cspaces 0 1652 for to var cspaces 1653 if sub castlepos #kingpos #to 1654 setlegal "{#king} {#kingpos}-{#to}" 1655 endif 1656 next 1657 endif 1658 setsystem autorules sub describe_rules 1659 return cond count system legalmoves false true 1660 endsub 1661 sub stalemated2 kingpos 1662 store 1663 local cspaces friend friends from piece to movetype 1664 set movetype MOVE 1665 if isupper space #kingpos 1666 set friends (onlyupper) 1667 set friend (isupper #0) 1668 set cspaces var wcastle 1669 else 1670 set friends (onlylower) 1671 set friend (islower #0) 1672 set cspaces var bcastle 1673 endif 1674 set royal space var kingpos 1675 store 1676 for (from piece) fn #friends 1677 for to fn join const alias #piece "-Range" #from 1678 if fn const alias #piece #from #to and not fn #friend space #to and onboard #to 1679 move #from #to 1680 if not sub checked cond == #from #kingpos #to #kingpos 1681 set ap alias #piece 1682 setlegal "{#ap} {#from}-{#to}" 1683 endif 1684 endif 1685 restore 1686 next 1687 next 1688 if > count var cspaces 0 and flag #kingpos 1689 for mvs var cspaces 1690 if sub castlepos2 #mvs.0 #mvs.1 #mvs.2 #mvs.3 and == #kingpos #mvs.0 1691 set pk alias space #mvs.0 1692 set pr alias space #mvs.2 1693 setlegal "{#pk} {#mvs.0}-{#mvs.1}; {#pr} {#mvs.2}-{#mvs.3}" 1694 endif 1695 next 1696 endif 1697 setsystem autorules sub describe_rules 1698 return cond count system legalmoves false true 1699 endsub 1700 sub fusion-stalemated kingpos 1701 store 1702 local cspaces friend friends from piece to movetype mv ss 1703 set movetype MOVE 1704 set ss join chr 47 chr 47 1705 if isupper space #kingpos 1706 set friends (onlyupper) 1707 set friend (isupper #0) 1708 set cspaces var wcastle 1709 else 1710 set friends (onlylower) 1711 set friend (islower #0) 1712 set cspaces var bcastle 1713 endif 1714 set royal space var kingpos 1715 store 1716 set kp #kingpos 1717 for (from piece) fn #friends 1718 set ap alias #piece 1719 for to fn join const #ap "-Range" #from 1720 if != space #to #piece and match toupper alias space #to K R B N and match toupper alias #piece R B N or not fn #friend space #to and fn const alias #piece #from #to and onboard #to 1721 move #from #to 1722 if match #ap K KR KB KN k kr kb kn 1723 set kp #to 1724 endif 1725 if not sub checked #kp 1726 setlegal "{#ap} {#from}-{#to}" 1727 endif 1728 restore 1729 set kp #kingpos 1730 endif 1731 if not sub checked #from and empty #to and == strlen alias #piece 2 1732 set compound alias #piece 1733 set simple1 leftstr #compound 1 1734 set simple2 rightstr #compound 1 1735 if != not fn #friend space #to and fn const alias #simple1 #from #to 1736 add #simple1 #to 1737 add #simple2 #from 1738 if match #simple1 K k 1739 set kp #to 1740 endif 1741 if not sub checked #kp 1742 setlegal "{#simple1} {#from}-{#to}; {#ss} {#simple2}-{#from}" 1743 endif 1744 restore 1745 set kp #kingpos 1746 endif 1747 if != not fn #friend space #to and fn const alias #simple2 #from #to 1748 add #simple2 #to 1749 add #simple1 #from 1750 if match #simple1 K k 1751 set kp #from 1752 endif 1753 if not sub checked #kp 1754 setlegal "{#simple2} {#from}-{#to}; {#ss} {#simple1}-{#from}" 1755 endif 1756 restore 1757 set kp #kingpos 1758 endif 1759 endif 1760 next 1761 next 1762 if > count var cspaces 0 1763 for to var cspaces 1764 if sub castlepos #kingpos #to 1765 setlegal (#kingpos #to) 1766 endif 1767 next 1768 endif 1769 setsystem autorules sub describe_rules 1770 return cond count system legalmoves false true 1771 endsub 1772 sub describe_rules 1773 my c piecenames notation values val id ref rules desc name codename rangefn 1774 set c.0 join filename 0 rankname 0 1775 set c.1 join filename >> lastfile 1 rankname 1 1776 set c.2 join filename inc >> lastfile 1 rankname 1 1777 set c.3 join filename >> lastfile 1 rankname inc >> lastrank 1 1778 set c.4 join filename inc >> lastfile 1 rankname >> lastrank 1 1779 set c.5 join filename >> lastfile 1 rankname dec lastrank 1780 set c.6 join filename inc >> lastfile 1 rankname dec lastrank 1781 set c.7 join filename lastfile rankname lastrank 1782 foreach p keys $pieces 1783 if isconst alias #p 1784 set codename const alias #p 1785 set name alias #codename 1786 set notation.{#name} alias #p 1787 if match #codename const alias space #kpos const alias space #Kpos 1788 set values.{#name} * 8 count spaces 1789 else 1790 set rangefn join #codename "-Range" 1791 set values.{#name} sum lambda (count fn #rangefn #0) #c 1792 endif 1793 endif 1794 next 1795 set values reverse asort #values 1796 set rules "" 1797 foreach (name val) #values 1798 set codename realname #name 1799 if == null var #codename 1800 set codename #name 1801 endif 1802 set ref join #codename "-Desc" 1803 set desc str_replace "%s" #name var #ref 1804 set desc str_replace "_" " " #desc 1805 set id realname #notation.{#name} 1806 set rules join #rules "" 1809 return #rules 1810 endsub 1811 sub findmates side 1812 local enemyking king mates moves mv 1813 if match #side 1 white White first 1814 set king #Kpos 1815 set enemyking #kpos 1816 else 1817 set king #kpos 1818 set enemyking #Kpos 1819 endif 1820 set mates () 1821 ban none 1822 setsystem maxmove 0 1823 store main 1824 setsystem legalmoves () 1825 if not sub stalemated #king 1826 set lglmvs $legalmoves 1827 foreach move #lglmvs 1828 set moves explode chr 59 #move 1829 foreach mv #moves 1830 set mv trim #mv 1831 eval "MOVE: {#mv}" 1832 next 1833 if sub checked #enemyking 1834 setsystem legalmoves () 1835 if sub stalemated #enemyking 1836 push mates #move 1837 endif 1838 endif 1839 restore main 1840 next 1841 endif 1842 setsystem legalmoves #mates 1843 endsub 1844 endlib[pc {#id} {#name}]{#desc}[/pc]" 1807 next 1808 set rules join #rules "