This preset now uses the new code for identifying check, checkmate, and stalemate. Let me know of any problems with it.

You may not move a F from f1 to d2

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. d2-d4 
1... d7-d5 
2. f1-d2 
2... c8-c6 
3. b1-c3 
3... e7-e6 
4. g1-f3 
4... f8-f6 
5. e1-g1 
5... g8-g6 
6. e2-e3 
6... b8-b6 
7. c1-d3 
7... e8-g8 
8. d1-e2 
8... a7-a6 
9. f3-e5 
9... f6-e7 
10. a2-a4 
10... a6-a5 
11. h2-h3 
11... f7-f6 
12. e5-f3 
12... b6-a6 
13. b2-b3 
13... c6-d7 
14. c3-b2 
14... b7-b6 
15. c2-c4 
15... d5-c4 
16. b2-c4 
16... c7-c6 
17. d2-c2 
17... a8-b8 
18. c4-d2 
18... b6-b5 
19. c2-b2 
19... b5-b4 
20. e2-d1 
20... d7-d5 
21. d3-c5

If this is your settings file, you may edit it at https://www.chessvariants.com/play/pbm/play.php?game=Chess+with+Different+Armies&settings=Unequal+Armies&submit=Edit

Here is a code listing:

   0 echo This preset now uses the new code for identifying check, checkmate, and stalemate. Let me know of any problems with it.
   1 setflag a1 a8 h1 h8 e1 e8
   2 set k findpiece k spaces
   3 set K findpiece K spaces
   4 set ep false
   5 setflag neversame
   6 include cwda
   7 sub postauto1
   8   if isupper old
   9     die You may not capture your own pieces.
  10   endif
  11   if not equal moved P
  12     set ep false
  13     if unequal space dest moved
  14       die You may not change the type of this piece.
  15     endif
  16   endif
  17   set legal false
  18   if match moved P K
  19     gosub moved origin dest
  20     if equal moved K
  21       set K dest
  22     endif
  23   elseif match moved Q R B N A E F C I M D G L W J H
  24     set legal fn moved origin dest
  25     if match moved R A I L
  26       unsetflag origin
  27     endif
  28   endif
  29   if not var legal
  30     die You may not move a moved from origin to dest
  31   endif
  32   if fn ATTACKEDBYB #K
  33     die You may not move into check.
  34   endif
  35 endsub
  36 sub postauto2
  37   if islower old
  38     die You may not capture your own pieces.
  39   endif
  40   if not equal moved p
  41     set ep false
  42     if unequal space dest moved
  43       die You may not change the type of this piece.
  44     endif
  45   endif
  46   set legal false
  47   if match moved p k
  48     gosub moved origin dest
  49     if equal moved k
  50       set k dest
  51     endif
  52   elseif match moved q r b n a e f c i m d g l w j h
  53     set legal fn moved origin dest
  54     if equal moved r a i l
  55       unsetflag origin
  56     endif
  57   endif
  58   if not var legal
  59     die You may not move a moved from origin to dest
  60   endif
  61   if fn ATTACKEDBYW #k
  62     die You may not move into check.
  63   endif
  64 endsub
  65 moveindex 1
  66 MOVE: d2-d4
  67 postauto1
  68 moveindex 2
  69 MOVE: d7-d5
  70 postauto2
  71 moveindex 3
  72 MOVE: f1-d2
  73 postauto1
  74 moveindex 4
  75 MOVE: c8-c6
  76 postauto2
  77 moveindex 5
  78 MOVE: b1-c3
  79 postauto1
  80 moveindex 6
  81 MOVE: e7-e6
  82 postauto2
  83 moveindex 7
  84 MOVE: g1-f3
  85 postauto1
  86 moveindex 8
  87 MOVE: f8-f6
  88 postauto2
  89 moveindex 9
  90 MOVE: e1-g1
  91 postauto1
  92 moveindex 10
  93 MOVE: g8-g6
  94 postauto2
  95 moveindex 11
  96 MOVE: e2-e3
  97 postauto1
  98 moveindex 12
  99 MOVE: b8-b6
 100 postauto2
 101 moveindex 13
 102 MOVE: c1-d3
 103 postauto1
 104 moveindex 14
 105 MOVE: e8-g8
 106 postauto2
 107 moveindex 15
 108 MOVE: d1-e2
 109 postauto1
 110 moveindex 16
 111 MOVE: a7-a6
 112 postauto2
 113 moveindex 17
 114 MOVE: f3-e5
 115 postauto1
 116 moveindex 18
 117 MOVE: f6-e7
 118 postauto2
 119 moveindex 19
 120 MOVE: a2-a4
 121 postauto1
 122 moveindex 20
 123 MOVE: a6-a5
 124 postauto2
 125 moveindex 21
 126 MOVE: h2-h3
 127 postauto1
 128 moveindex 22
 129 MOVE: f7-f6
 130 postauto2
 131 moveindex 23
 132 MOVE: e5-f3
 133 postauto1
 134 moveindex 24
 135 MOVE: b6-a6
 136 postauto2
 137 moveindex 25
 138 MOVE: b2-b3
 139 postauto1
 140 moveindex 26
 141 MOVE: c6-d7
 142 postauto2
 143 moveindex 27
 144 MOVE: c3-b2
 145 postauto1
 146 moveindex 28
 147 MOVE: b7-b6
 148 postauto2
 149 moveindex 29
 150 MOVE: c2-c4
 151 postauto1
 152 moveindex 30
 153 MOVE: d5-c4
 154 postauto2
 155 moveindex 31
 156 MOVE: b2-c4
 157 postauto1
 158 moveindex 32
 159 MOVE: c7-c6
 160 postauto2
 161 moveindex 33
 162 MOVE: d2-c2
 163 postauto1
 164 moveindex 34
 165 MOVE: a8-b8
 166 postauto2
 167 moveindex 35
 168 MOVE: c4-d2
 169 postauto1
 170 moveindex 36
 171 MOVE: b6-b5
 172 postauto2
 173 moveindex 37
 174 MOVE: c2-b2
 175 postauto1
 176 moveindex 38
 177 MOVE: b5-b4
 178 postauto2
 179 moveindex 39
 180 MOVE: e2-d1
 181 postauto1
 182 moveindex 40
 183 MOVE: d7-d5
 184 postauto2
 185 moveindex 41
 186 MOVE: d3-c5
 187 postauto1
 188 set checks sub checks #k
 189 if var checks
 190   if sub checkmated #k #checks
 191     say Checkmate! White has won!
 192     won
 193   else
 194     say Check!
 195   endif
 196 elseif sub stalemated #k
 197   say Stalemate! The game is drawn.
 198   drawn
 199 endif
 200 end
 201 
 202 lib cwda
 203 include chess
 204 alias BD A WA E FA F CA C CR I FN M CN D CO G SR L WR W HD J CH H bd a wa e fa f ca c cr i fn m cn d co g sr l wr w hd j ch h
 205 def AF checkleap #0 #1 2 2
 206 def DB checkleap #0 #1 2 0
 207 def FZ checkleap #0 #1 1 1
 208 def WZ checkleap #0 #1 1 0
 209 def A fn B #0 #1 or fn DB #0 #1
 210 def E fn WZ #0 #1 or fn AF #0 #1
 211 def F fn FZ #0 #1 or fn AF #0 #1 or fn DB #0 #1
 212 def C fn B #0 #1 or fn N #0 #1
 213 def a fn b #0 #1 or fn DB #0 #1
 214 def e fn WZ #0 #1 or fn AF #0 #1
 215 def f fn FZ #0 #1 or fn AF #0 #1 or fn DB #0 #1
 216 def c fn b #0 #1 or fn n #0 #1
 217 def AL merge rays #0 1 1 leaps #0 2 0
 218 def EL merge leaps #0 1 0 leaps #0 2 2
 219 def FL merge leaps #0 1 1 merge leaps #0 2 2 leaps #0 2 0
 220 def CL merge rays #0 1 1 leaps #0 1 2
 221 def aL merge rays #0 1 1 leaps #0 2 0
 222 def eL merge leaps #0 1 0 leaps #0 2 2
 223 def fL merge leaps #0 1 1 merge leaps #0 2 2 leaps #0 2 0
 224 def cL merge rays #0 1 1 leaps #0 1 2
 225 def I checkaride #0 #1 1 0 or checkaride #0 #1 -1 0 or checkaride #0 #1 0 1 or checkaleap #0 #1 -1 -1 or checkaleap #0 #1 1 -1 or checkaleap #0 #1 0 -1
 226 def M checkaleap #0 #1 1 2 or checkaleap #0 #1 -1 2 or checkaleap #0 #1 1 -2 or checkaleap #0 #1 -1 -2 or fn FZ #0 #1
 227 def D checkaleap #0 #1 1 2 or checkaleap #0 #1 -1 2 or checkaleap #0 #1 2 1 or checkaleap #0 #1 -2 1 or checkaleap #0 #1 -1 -1 or checkaleap #0 #1 1 -1 or checkaleap #0 #1 -1 0 or checkaleap #0 #1 1 0 or checkaleap #0 #1 0 -1
 228 def G checkaride #0 #1 1 0 or checkaride #0 #1 -1 0 or checkaride #0 #1 0 1 or checkaleap #0 #1 1 2 or checkaleap #0 #1 -1 2 or checkaleap #0 #1 2 1 or checkaleap #0 #1 -2 1 or fn FZ #0 #1 or fn WZ #0 #1
 229 def i checkaride #0 #1 1 0 or checkaride #0 #1 -1 0 or checkaride #0 #1 0 -1 or checkaleap #0 #1 -1 1 or checkaleap #0 #1 1 1 or checkaleap #0 #1 0 1
 230 def m checkaleap #0 #1 1 2 or checkaleap #0 #1 -1 2 or checkaleap #0 #1 1 -2 or checkaleap #0 #1 -1 -2 or fn FZ #0 #1
 231 def d checkaleap #0 #1 1 -2 or checkaleap #0 #1 -1 -2 or checkaleap #0 #1 2 -1 or checkaleap #0 #1 -2 -1 or checkaleap #0 #1 -1 1 or checkaleap #0 #1 1 1 or checkaleap #0 #1 -1 0 or checkaleap #0 #1 1 0 or checkaleap #0 #1 0 1
 232 def g checkaride #0 #1 1 0 or checkaride #0 #1 -1 0 or checkaride #0 #1 0 -1 or checkaleap #0 #1 1 -2 or checkaleap #0 #1 -1 -2 or checkaleap #0 #1 2 -1 or checkaleap #0 #1 -2 -1 or fn FZ #0 #1 or fn WZ #0 #1
 233 def IL merge rays #0 1 0 array where #0 -1 -1 where #0 1 -1
 234 def iL merge rays #0 1 0 array where #0 -1 1 where #0 1 1
 235 def ML merge leaps #0 1 1 array where #0 1 2 where #0 -1 2 where #0 1 -2 where #0 -1 -2
 236 def mL merge leaps #0 1 1 array where #0 1 2 where #0 -1 2 where #0 1 -2 where #0 -1 -2
 237 def DL array where #0 1 2 where #0 -1 2 where #0 2 1 where #0 -2 1 where #0 -1 0 where #0 1 0 where #0 0 -1 where #0 -1 -1 where #0 1 -1
 238 def dL array where #0 1 -2 where #0 -1 -2 where #0 2 -1 where #0 -2 -1 where #0 -1 0 where #0 1 0 where #0 0 1 where #0 -1 1 where #0 1 1
 239 def GL merge merge leaps #0 1 1 rays #0 1 0 array where #0 1 2 where #0 -1 2 where #0 2 1 where #0 -2 1
 240 def gL merge merge leaps #0 1 1 rays #0 1 0 array where #0 1 -2 where #0 -1 -2 where #0 2 -1 where #0 -2 -1
 241 def L fn R #0 #1 and <= distance #0 #1 4
 242 def W fn DB #0 #1 or fn WZ #0 #1
 243 def J fn DB #0 #1 or fn FZ #0 #1 or checkleap #0 #1 0 3
 244 def H fn N #0 #1 or fn R #0 #1
 245 def l fn r #0 #1 and <= distance #0 #1 4
 246 def w fn DB #0 #1 or fn WZ #0 #1
 247 def j fn DB #0 #1 or fn FZ #0 #1 or checkleap #0 #1 0 3
 248 def h fn n #0 #1 or fn r #0 #1
 249 def LL merge merge leaps #0 1 0 leaps #0 2 0 merge leaps #0 3 0 leaps #0 4 0
 250 def WL merge leaps #0 1 0 leaps #0 2 0
 251 def JL merge leaps #0 3 0 merge leaps #0 1 1 leaps #0 2 0
 252 def HL merge rays #0 1 0 leaps #0 1 2
 253 def lL merge merge leaps #0 1 0 leaps #0 2 0 merge leaps #0 3 0 leaps #0 4 0
 254 def wL merge leaps #0 1 0 leaps #0 2 0
 255 def jL merge leaps #0 3 0 merge leaps #0 1 1 leaps #0 2 0
 256 def hL merge rays #0 1 0 leaps #0 1 2
 257 def DABBABAH check what #0 0 -2 check what #0 -2 0 check what #0 0 2 check what #0 2 0 target #1
 258 def ALFIL check what #0 -2 -2 check what #0 -2 2 check what #0 2 -2 check what #0 2 2 target #1
 259 def LONGKNIGHT check what #0 1 2 check what #0 -1 2 check what #0 1 -2 check what #0 -1 -2 target #1
 260 def FOREKNIGHT check what #0 1 2 check what #0 -1 2 check what #0 2 1 check what #0 -2 1 target #1
 261 def BACKKNIGHT check what #0 1 -2 check what #0 -1 -2 check what #0 2 -1 check what #0 -2 -1 target #1
 262 def FOREKING check what #0 -1 1 check what #0 0 1 check what #0 1 1 target #1
 263 def BACKKING check what #0 -1 -1 check what #0 0 -1 check what #0 1 -1 target #1
 264 def SIDEKING check what #0 1 0 check what #0 -1 0 target #1
 265 def FOREROOK match insight #0 0 1 #1
 266 def BACKROOK match insight #0 0 -1 #1
 267 def SIDEROOK check insight #0 1 0 check insight #0 -1 0 target #1
 268 def SHORTROOK check inrange #0 0 -1 4 check inrange #0 -1 0 4 check inrange #0 0 1 4 check inrange #0 1 0 4 target #1
 269 def O3 check what #0 0 -3 check what #0 -3 0 check what #0 0 3 check what #0 3 0 target #1
 270 def WAZIR check what #0 0 -1 check what #0 -1 0 check what #0 0 1 check what #0 1 0 target #1
 271 def FERZ check what #0 -1 -1 check what #0 -1 1 check what #0 1 -1 check what #0 1 1 target #1
 272 def ATTACKEDBYW fn WPAWN #0 or fn O3 #0 J or fn SIDEKING #0 D or fn LONGKNIGHT #0 M or fn SHORTROOK #0 L or fn FOREKING #0 (I D) or fn ALFIL #0 (E F) or fn DABBABAH #0 (A F W J) or fn WAZIR #0 (E W K G) or fn FERZ #0 (F J K G M) or fn FOREROOK #0 (H Q R) or fn BACKROOK #0 (I G H Q R) or fn SIDEROOK #0 (I G H Q R) or fn FOREKNIGHT #0 (C H N) or fn BACKKNIGHT #0 (D G C H N) or fn BISHOP #0 (A C B Q)
 273 def ATTACKEDBYB fn BPAWN #0 or fn O3 #0 j or fn SIDEKING #0 d or fn LONGKNIGHT #0 m or fn SHORTROOK #0 l or fn BACKKING #0 (i d) or fn ALFIL #0 (e f) or fn DABBABAH #0 (a f w j) or fn WAZIR #0 (e w k g) or fn FERZ #0 (f j k g m) or fn BACKROOK #0 (h q r) or fn FOREROOK #0 (i g h q r) or fn SIDEROOK #0 (i g h q r) or fn BACKKNIGHT #0 (c h n) or fn FOREKNIGHT #0 (d g c h n) or fn BISHOP #0 (a c b q)
 274 sub checkedthru king loc
 275   my dir c
 276   set c revealed #king #loc
 277   if samecase space #king space #c or not #c
 278     return false
 279   endif
 280   set dir direction #king #loc
 281   switch #dir
 282     case n
 283     if match space #c R r Q q i g H h
 284       return #c
 285     endif
 286     if <= distance #king #loc 4 and match space #c L l
 287       return #c
 288     endif
 289     return false
 290     case s
 291     if match space #c R r Q q I G H h
 292       return #c
 293     endif
 294     if <= distance #king #loc 4 and match space #c L l
 295       return #c
 296     endif
 297     return false
 298     case e w
 299     if match space #c R r Q q I i G g H h
 300       return #c
 301     endif
 302     if <= distance #king #loc 4 and match space #c L l
 303       return #c
 304     endif
 305     return false
 306     case nw sw ne se
 307     if match space #c B b Q q A a C c
 308       return #c
 309     endif
 310     return false
 311     default
 312     return false
 313   endswitch
 314 endsub
 315 set cdist 2
 316 set CDIST 2
 317 sub K from to
 318   set legal fn K #from #to
 319   if match #to where #from 2 0 where #from neg #CDIST 0
 320     set legal sub castle
 321   endif
 322   set K #to
 323   unsetflag #from
 324 endsub
 325 sub k from to
 326   set legal fn K #from #to
 327   if match #to where #from 2 0 where #from neg #cdist 0
 328     set legal sub castle
 329   endif
 330   set k #to
 331   unsetflag #from
 332 endsub
 333 set x 0
 334 switch space d1
 335   case C
 336   set x 1
 337   break
 338   case G
 339   set x 2
 340   break
 341   case H
 342   set x 3
 343   break
 344   default
 345   break
 346 endswitch
 347 switch space d8
 348   case c
 349   set x plus #x 4
 350   break
 351   case g
 352   set x plus #x 8
 353   break
 354   case h
 355   set x plus #x 12
 356   break
 357   default
 358   break
 359 endswitch
 360 if == #x 0
 361   if flag neversame
 362     set x rand 1 12
 363     if > #x 4
 364       inc x
 365     endif
 366     if > #x 9
 367       inc x
 368     endif
 369   else
 370     set x rand 1 15
 371   endif
 372 endif
 373 set wx mod #x 4
 374 set bx / - #x #wx 4
 375 switch #wx
 376   case 0
 377   add R a1
 378   add N b1
 379   add B c1
 380   add Q d1
 381   add B f1
 382   add N g1
 383   add R h1
 384   pushall wprom R N B Q
 385   pushall bprom r n b q
 386   break
 387   case 1
 388   add A a1
 389   add E b1
 390   add F c1
 391   add C d1
 392   add F f1
 393   add E g1
 394   add A h1
 395   pushall wprom A E F C
 396   pushall bprom a e f c
 397   set CDIST 3
 398   set wcastle b1 g1
 399   break
 400   case 2
 401   add I a1
 402   add M b1
 403   add D c1
 404   add G d1
 405   add D f1
 406   add M g1
 407   add I h1
 408   pushall wprom I M D G
 409   pushall bprom i m d g
 410   break
 411   case 3
 412   add L a1
 413   add W b1
 414   add J c1
 415   add H d1
 416   add J f1
 417   add W g1
 418   add L h1
 419   pushall wprom L W J H
 420   pushall bprom l w j h
 421   break
 422   default
 423   break
 424 endswitch
 425 switch #bx
 426   case 0
 427   add r a8
 428   add n b8
 429   add b c8
 430   add q d8
 431   add b f8
 432   add n g8
 433   add r h8
 434   if != #wx 0
 435     pushall wprom R N B Q
 436     pushall bprom r n b q
 437   endif
 438   break
 439   case 1
 440   add a a8
 441   add e b8
 442   add f c8
 443   add c d8
 444   add f f8
 445   add e g8
 446   add a h8
 447   if != #wx 1
 448     pushall wprom A E F C
 449     pushall bprom a e f c
 450   endif
 451   set cdist 3
 452   set bcastle b8 g8
 453   break
 454   case 2
 455   add i a8
 456   add m b8
 457   add d c8
 458   add g d8
 459   add d f8
 460   add m g8
 461   add i h8
 462   if != #wx 2
 463     pushall wprom I M D G
 464     pushall bprom i m d g
 465   endif
 466   break
 467   case 3
 468   add l a8
 469   add w b8
 470   add j c8
 471   add h d8
 472   add j f8
 473   add w g8
 474   add l h8
 475   if != #wx 3
 476     pushall wprom L W J H
 477     pushall bprom l w j h
 478   endif
 479   break
 480   default
 481   break
 482 endswitch
 483 setglobal piecekeys merge var wprom var bprom
 484 endlib
 485 lib chess
 486 set wpr 2
 487 set bpr 7
 488 set fps 2
 489 set pzs 1
 490 set wcastle c1 g1
 491 set bcastle c8 g8
 492 do
 493   local x
 494   for x piecekeys
 495     if match #x P K p k
 496       continue
 497     elseif isupper #x
 498       push wprom #x
 499     elseif islower #x
 500       push bprom #x
 501     endif
 502   next
 503 loop never
 504 setsystem maxmove 2
 505 ban commands allmoves
 506 allow moves 1 captures 1 promotions 2
 507 def N checkleap #0 #1 1 2
 508 def B checkride #0 #1 1 1
 509 def R checkride #0 #1 1 0
 510 def Q fn B #0 #1 or fn R #0 #1
 511 def K checkleap #0 #1 1 1 or checkleap #0 #1 1 0
 512 def M fn N #0 #1 or fn R #0 #1
 513 def A fn N #0 #1 or fn B #0 #1
 514 def n checkleap #0 #1 1 2
 515 def b checkride #0 #1 1 1
 516 def r checkride #0 #1 1 0
 517 def q fn b #0 #1 or fn r #0 #1
 518 def k checkleap #0 #1 1 1 or checkleap #0 #1 1 0
 519 def m fn n #0 #1 or fn r #0 #1
 520 def a fn n #0 #1 or fn b #0 #1
 521 def P
remove var ep
and checkleap #0 #1 1 1
and == var ep join filename #1 rankname #0
or and checkride #0 #1 0 1 == rankname #0 var wpr
or checkleap #0 #1 0 1
and empty #1
or and islower space #1 checkleap #0 #1 1 1
and <= distance #0 #1 var fps
and > rank #1 rank #0
 522 def p
remove var ep
and checkleap #0 #1 1 1
and == var ep join filename #1 rankname #0
or and checkride #0 #1 0 1 == rankname #0 var bpr
or checkleap #0 #1 0 1
and empty #1
or and isupper space #1 checkleap #0 #1 1 1
and <= distance #0 #1 var fps
and < rank #1 rank #0
 523 sub capturep p
 524   empty #p
 525   return true
 526 endsub
 527 sub checks king
 528   if not dest
 529     return false
 530   endif
 531   my checks c
 532   set checks ()
 533   if fn space dest dest #king
 534     setelem checks dest space dest
 535   endif
 536   set c sub checkedthru #king origin
 537   if #c
 538     setelem checks #c space #c
 539   elseif #epc
 540     set c sub checkedthru #king #epc
 541     if #c
 542       setelem checks #c space #c
 543     endif
 544   endif
 545   return var checks
 546 endsub
 547 sub checkmated king checks
 548   local from piece to key legalmove piece nopawn
 549   store
 550   if isupper space #king
 551     def friends onlyupper
 552     def friend isupper #0
 553     set attacked ATTACKEDBYB
 554   else
 555     def friends onlylower
 556     def friend islower #0
 557     set attacked ATTACKEDBYW
 558   endif
 559   set kingmoves fn KL #king
 560   for to #kingmoves
 561     if not fn friend space #to and onboard #to
 562       move #king #to
 563       set incheck fn var attacked #to
 564       restore
 565       if not #incheck
 566         setlegal #king #to
 567       endif
 568     endif
 569   next
 570   if == count var checks 1
 571     for (key enemy) var checks
 572       set possible path #king #key
 573       push possible #key
 574       if == #key #ep
 575         push possible cond isupper space #ep where #ep 0 -1 where #ep 0 1
 576       endif
 577       for (from piece) fn friends
 578         if == #from #king
 579           continue
 580         endif
 581         for to #possible
 582           if fn #piece #from #to
 583             move #from #to
 584             set incheck fn var attacked #king
 585             if not #incheck
 586               setlegal #from #to
 587             endif
 588           endif
 589           restore
 590         next
 591       next
 592     next
 593   endif
 594   return cond count system legalmoves false true and checks
 595 endsub
 596 def PL array where #0 0 2 where #0 0 1 where #0 -1 1 where #0 1 1
 597 def pL array where #0 0 -2 where #0 0 -1 where #0 -1 -1 where #0 1 -1
 598 def NL leaps #0 1 2
 599 def BL rays #0 1 1
 600 def RL rays #0 1 0
 601 def VL rays #0 1 1
 602 def CL rays #0 1 0
 603 def QL merge rays #0 1 0 rays #0 1 1
 604 def KL merge leaps #0 1 0 leaps #0 1 1
 605 def AL merge leaps #0 1 2 rays #0 1 1
 606 def ML merge rays #0 1 0 leaps #0 1 2
 607 def nL leaps #0 1 2
 608 def bL rays #0 1 1
 609 def rL rays #0 1 0
 610 def vL rays #0 1 1
 611 def cL rays #0 1 0
 612 def qL merge rays #0 1 0 rays #0 1 1
 613 def kL merge leaps #0 1 0 leaps #0 1 1
 614 def aL merge leaps #0 1 2 rays #0 1 1
 615 def mL merge rays #0 1 0 leaps #0 1 2
 616 sub castlepos from to
 617   local c RPOS RDEST xdir safe
 618   verify flag #from
 619   verify empty #to
 620   if isupper space #king
 621     def friend isupper #0
 622     def friends onlyupper
 623     set attacked ATTACKEDBYB
 624   else
 625     def friend islower #0
 626     def friends onlylower
 627     set attacked ATTACKEDBYW
 628   endif
 629   set xdir sign minus file #to file #from
 630   verify checkaride #from #to #xdir 0
 631   verify not fn var attacked #from
 632   set c #to
 633   do
 634     set c where #c #xdir 0
 635     if flag #c
 636       break
 637     endif
 638     verify onboard #c
 639     verify empty #c
 640   loop
 641   verify flag #c
 642   set RPOS #c
 643   store
 644   for c path #from #to
 645     move #from #c
 646     set safe not fn var attacked #c
 647     restore
 648     verify #safe
 649   next
 650   move #from #to
 651   set RDEST where #to neg #xdir 0
 652   move #RPOS #RDEST
 653   return true
 654 endsub
 655 sub stalemated king
 656   local legalmove temp from piece to attacked ra
 657   if isupper space #king
 658     def friend isupper #0
 659     def friends onlyupper
 660     set attacked ATTACKEDBYB
 661     set cspaces var wcastle
 662   else
 663     def friend islower #0
 664     def friends onlylower
 665     set attacked ATTACKEDBYW
 666     set cspaces var bcastle
 667   endif
 668   store
 669   set kingmoves fn KL #king
 670   for to #kingmoves
 671     if not fn friend space #to and onboard #to
 672       move #king #to
 673       set incheck fn var attacked #to
 674       restore
 675       if not #incheck
 676         setlegal #king #to
 677       endif
 678     endif
 679   next
 680   for to var cspaces
 681     if sub castlepos #king #to
 682       set incheck fn var attacked #to
 683       restore
 684       if not #incheck
 685         setlegal #king #to
 686       endif
 687     endif
 688   next
 689   restore
 690   for (from piece) fn friends
 691     if == #from #king
 692       continue
 693     endif
 694     for to fn join #piece L #from
 695       if fn #piece #from #to and not fn friend space #to and onboard #to
 696         move #from #to
 697         set incheck fn var attacked #king
 698         if not #incheck
 699           setlegal #from #to
 700         endif
 701       endif
 702       restore
 703     next
 704   next
 705   return cond count system legalmoves false true
 706 endsub
 707 def WPAWN match P what #0 1 -1 what #0 -1 -1
 708 def BPAWN match p what #0 1 1 what #0 -1 1
 709 def KNIGHT check what #0 1 2 check what #0 -1 2 check what #0 1 -2 check what #0 -1 -2 check what #0 2 1 check what #0 -2 1 check what #0 2 -1 check what #0 -2 -1 target #1
 710 def WAZIR check what #0 0 -1 check what #0 -1 0 check what #0 0 1 check what #0 1 0 target #1
 711 def FERZ check what #0 -1 -1 check what #0 -1 1 check what #0 1 -1 check what #0 1 1 target #1
 712 def KING fn WAZIR #0 #1 or fn FERZ #0 #1
 713 def ROOK check insight #0 0 -1 check insight #0 -1 0 check insight #0 0 1 check insight #0 1 0 target #1
 714 def BISHOP check insight #0 -1 -1 check insight #0 -1 1 check insight #0 1 -1 check insight #0 1 1 target #1
 715 def ATTACKEDBYB fn KING #0 k or fn BPAWN #0 or fn KNIGHT #0 (n a m) or fn ROOK #0 (r q m) or fn BISHOP #0 (b q a)
 716 def ATTACKEDBYW fn KING #0 K or fn WPAWN #0 or fn KNIGHT #0 (N A M) or fn ROOK #0 (R Q M) or fn BISHOP #0 (B Q A)
 717 sub P from to
 718   local ydir
 719   if == file #from file #to and not capture
 720     set legal checkaleap #from #to 0 1
 721     if var legal
 722       set ep false
 723     else
 724       set legal checkaride #from #to 0 1 and <= distance #from #to #fps and or == rankname #from #wpr < #wpr 0
 725       set ep #to
 726     endif
 727     set epc false
 728   elseif capture or #ep
 729     set legal checkaleap #from #to -1 1 or checkaleap #from #to 1 1
 730     set epc false
 731     if not capture and var legal
 732       set legal > rank #to rank #ep and < rankname #to #bpr and == file #to file #ep
 733       if var legal
 734         capture #ep
 735         set epc #ep
 736       endif
 737     endif
 738     set ep false
 739   endif
 740   if != space #to moved and onboard where #to 0 #pzs
 741     die "You may not promote a Pawn until it reaches the promotion zone."
 742   endif
 743   if not onboard where #to 0 1
 744     if == P space #to
 745       askpromote #wprom
 746     elseif not match space #to var wprom
 747       set np space #to
 748       die "You may not promote your Pawn to a" #np
 749     endif
 750   endif
 751 endsub
 752 sub p from to
 753   if == file #from file #to and not capture
 754     set legal checkaleap #from #to 0 -1
 755     if var legal
 756       set ep false
 757     else
 758       set legal checkaride #from #to 0 -1 and <= distance #from #to #fps and or == rankname #from #bpr > #bpr lastrank
 759       set ep #to
 760     endif
 761     set epc false
 762   elseif capture or #ep
 763     set legal checkaleap #from #to -1 -1 or checkaleap #from #to 1 -1
 764     set epc false
 765     if not capture and var legal
 766       set legal < rank #to rank #ep and > rankname #to #wpr and == file #to file #ep
 767       if var legal
 768         capture #ep
 769         set epc #ep
 770       endif
 771     endif
 772     set ep false
 773   endif
 774   if != space #to moved and onboard where #to 0 neg #pzs
 775     die You may not promote a Pawn until it reaches the promotion zone.
 776   endif
 777   if not onboard where #to 0 -1
 778     if == p space #to
 779       askpromote #bprom
 780     elseif not match space #to var bprom
 781       set np space #to
 782       die You may not promote your Pawn to a #np
 783     endif
 784   endif
 785 endsub
 786 sub K from to
 787   if match #to var wcastle and flag #from
 788     set legal sub castle
 789   else
 790     set legal fn K #from #to
 791   endif
 792   set K #to
 793   unsetflag e1
 794 endsub
 795 sub k from to
 796   if match #to var bcastle and flag #from
 797     set legal sub castle
 798   else
 799     set legal fn k #from #to
 800   endif
 801   set k #to
 802   unsetflag e8
 803 endsub
 804 sub castle
 805   local ATTACKED c RPOS RDEST xdir
 806   if not flag #from
 807     die A King may not castle after it moves.
 808   endif
 809   if capture
 810     die A King may not castle to an occupied space.
 811   endif
 812   set xdir sign minus file #to file #from
 813   if not checkaride #from #to #xdir 0
 814     die A King may not castle across any occupied space.
 815   endif
 816   set c #to
 817   do
 818     set c where #c #xdir 0
 819     if flag #c
 820       break
 821     elseif not onboard #c
 822       die No piece was found to castle with.
 823     elseif not empty #c
 824       die The King cannot castle with the piece at #c
 825     endif
 826   loop
 827   set RPOS #c
 828   set ATTACKED ATTACKEDBYW unless isupper moved ATTACKEDBYB
 829   if fn var ATTACKED #from
 830     die A King may not castle out of check.
 831   endif
 832   for c path #from #to
 833     if fn var ATTACKED #c
 834       die A King may not castle through check.
 835     endif
 836   next
 837   if == count var subargs 0
 838     set RDEST where #to neg #xdir 0
 839   else
 840     set RDEST elem 0 subarg
 841   endif
 842   unsetflag #RPOS
 843   move #RPOS #RDEST
 844   return true
 845 endsub
 846 sub checkedthru king loc
 847   my dir c
 848   set c revealed #king #loc
 849   verify fn space #c #c #king and not samecase space #king space #c and onboard #c and #c
 850   return #c
 851 endsub
 852 def fn checkedfrom fn space #1 #0 and xor isupper space #0 isupper space #1 and not empty #1
 853 sub P1 from to
 854   if == file #from file #to
 855     return not capture
 856   elseif capture
 857     return true
 858   elseif == file #to file #ep and == rank #from rank #ep and #ep
 859     capture #ep
 860     return true
 861   endif
 862   return false
 863 endsub
 864 sub PP from to
 865   if checkatwostep #from #to 0 1 0 1 or checkaleap #from #to 0 1
 866     return empty #to
 867   elseif not checkaleap #from #to 1 1 and not checkaleap #from #to -1 1
 868     return false
 869   elseif not empty #to
 870     return true
 871   elseif == file #to file #ep and == rank #from rank #ep and #ep
 872     capture #ep
 873     return true
 874   endif
 875   return false
 876 endsub
 877 sub pp from to
 878   if checkatwostep #from #to 0 -1 0 -1 or checkaleap #from #to 0 -1
 879     return empty #to
 880   elseif not checkaleap #from #to 1 -1 and not checkaleap #from #to -1 -1
 881     return false
 882   elseif not empty #to
 883     return true
 884   elseif == file #to file #ep and == rank #from rank #ep and #ep
 885     capture #ep
 886     return true
 887   endif
 888   return false
 889 endsub
 890 endlib