Please report any bugs or errors to Fergus Duniho

b8 - h2 is illegal. You may not move your Black LongLeaper from b8 to h2.

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. c2-c4 
1... g7 - g3 
2. h2-h3 
2... f7 - f3 
3. c4-f4 
3... g3 - f3 
4. g2-g3 
4... f8 - f5 
5. e2-e3 
5... b7 - b3 
6. g3-g4 
6... c7 - c4 
7. a2-a3 
7... a8 - f3 
8. g4-f4 
8... a7 - b7 
9. c1-c3 
9... b8 - h2 
10. h1-c6 
10... d7 - c7 
11. c6-a6 
11... b7 - a7 
12. g1-h1 
12... h2 - h6 
13. h1-a8 
13... e8 - f7 
14. b2-b4 
14... c4 - d4 
15. a6-a4 
15... f5 - a5 
16. c3-f3 
| 16... g8 - g1 
| 17. f1-h1 
16... c8 - e6 
17. a1-g7 
17... resign 
18. b1-g6

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