Since no firstrank constant has been stored for this game, one will be calculated by analyzing the moves in the game. This will work only if the game lasted long enough to put enough pieces into play.

mv is g2-g3, p is #p, o is g2

space g2 is P

0 P g2-g3 27 61 59 61 59 61 59 29

11011 111101 111011 111101 111011 111101 111011 11101

mv is g7-g6, p is #p, o is g7

space g7 is p

1 p g7-g6 27 61 59 61 59 61 59 29

11011 111101 111011 111101 111011 111101 111011 11101

mv is a1-b3, p is #p, o is a1

space a1 is a1

2 a1 a1-b3 27 61 59 61 59 61 59 29

11011 111101 111011 111101 111011 111101 111011 11101

4 one bits in var a1

1 111101 111011 111101 111011 111101 111011 11101

q end a1-b3 1 61 59 61 59 61 59 29

bb end a1-b3 1 61 59 61 59 61 59 29

bw end a1-b3 1 61 59 61 59 61 59 29

firstr is b1, and lastr is h1

r a1-b3 1 29 59 61 59 61 59 29

first 1 29 59 61 59 61 59 29

1 11101 111011 111101 111011 111101 111011 11101

q end a1-b3 1 29 59 61 59 61 59 29

bb end a1-b3 1 29 59 61 59 61 59 29

bw end a1-b3 1 29 59 61 59 61 59 29

firstr is b1, and lastr is h1

r a1-b3 1 29 59 61 59 61 59 29

first 1 29 59 61 59 61 59 29

mv is c7-c6, p is #p, o is c7

space c7 is p

3 p c7-c6 1 29 59 61 59 61 59 29

1 11101 111011 111101 111011 111101 111011 11101

mv is e2-e4, p is #p, o is e2

space e2 is P

4 P e2-e4 1 29 59 61 59 61 59 29

1 11101 111011 111101 111011 111101 111011 11101

mv is d8-e6, p is #p, o is d8

space d8 is d1

5 d1 d8-e6 1 29 59 61 59 61 59 29

1 11101 111011 111101 111011 111101 111011 11101

5 one bits in var d1

1 11101 111011 1 111011 111101 111011 11101

q end d8-e6 1 29 59 1 59 61 59 29

bb end d8-e6 1 29 59 1 59 61 59 29

bw end d8-e6 1 29 59 1 59 61 59 29

firstr is b1, and lastr is h1

r d8-e6 1 29 59 1 59 61 59 29

first 1 29 59 1 59 61 59 29

1 11100 111010 1 111010 111100 111010 11100

q end d8-e6 1 28 58 1 58 60 58 28

bb end d8-e6 1 28 58 1 58 60 58 28

bw end d8-e6 1 28 58 1 58 60 58 28

firstr is b1, and lastr is h1

r d8-e6 1 28 58 1 58 60 58 28

first 1 28 58 1 58 60 58 28

mv is d2-d3, p is #p, o is d2

space d2 is P

6 P d2-d3 1 28 58 1 58 60 58 28

1 11100 111010 1 111010 111100 111010 11100

mv is b8-c7, p is #p, o is b8

space b8 is b1

7 b1 b8-c7 1 28 58 1 58 60 58 28

1 11100 111010 1 111010 111100 111010 11100

3 one bits in var b1

1 10100 111010 1 111010 111100 111010 11100

q end b8-c7 1 20 58 1 58 60 58 28

bb end b8-c7 1 20 58 1 58 60 58 28

bw end b8-c7 1 20 58 1 58 60 58 28

firstr is c1, and lastr is h1

r b8-c7 1 20 26 1 58 60 58 28

first 1 20 26 1 58 60 58 28

1 10100 11010 1 111010 111100 111010 11100

q end b8-c7 1 20 26 1 58 60 58 28

bb end b8-c7 1 20 26 1 58 60 58 28

bw end b8-c7 1 20 26 1 58 60 58 28

firstr is c1, and lastr is h1

r b8-c7 1 20 26 1 58 60 58 28

first 1 20 26 1 58 60 58 28

mv is f2-f4, p is #p, o is f2

space f2 is P

8 P f2-f4 1 20 26 1 58 60 58 28

1 10100 11010 1 111010 111100 111010 11100

mv is f7-f5, p is #p, o is f7

space f7 is p

9 p f7-f5 1 20 26 1 58 60 58 28

1 10100 11010 1 111010 111100 111010 11100

mv is b3-c5, p is #p, o is b3

space b3 is a1

10 a1 b3-c5 1 20 26 1 58 60 58 28

1 10100 11010 1 111010 111100 111010 11100

1 one bits in var a1

1 10100 11010 1 111010 111100 111010 11100

q end b3-c5 1 20 26 1 58 60 58 28

bb end b3-c5 1 20 26 1 58 60 58 28

bw end b3-c5 1 20 26 1 58 60 58 28

firstr is c1, and lastr is h1

r b3-c5 1 20 26 1 58 60 58 28

first 1 20 26 1 58 60 58 28

mv is e6-c5, p is #p, o is e6

space e6 is d1

11 d1 e6-c5 1 20 26 1 58 60 58 28

1 10100 11010 1 111010 111100 111010 11100

1 one bits in var d1

1 10100 11010 1 111010 111100 111010 11100

q end e6-c5 1 20 26 1 58 60 58 28

bb end e6-c5 1 20 26 1 58 60 58 28

bw end e6-c5 1 20 26 1 58 60 58 28

firstr is c1, and lastr is h1

r e6-c5 1 20 26 1 58 60 58 28

first 1 20 26 1 58 60 58 28

mv is g1-c5, p is #p, o is g1

space g1 is g1

12 g1 g1-c5 1 20 26 1 58 60 58 28

1 10100 11010 1 111010 111100 111010 11100

4 one bits in var g1

1 10100 11010 1 111010 111100 10010 11100

q end g1-c5 1 20 26 1 58 60 18 28

bb end g1-c5 1 20 26 1 58 60 18 28

bw end g1-c5 1 20 26 1 58 60 18 28

firstr is c1, and lastr is h1

r g1-c5 1 20 26 1 58 60 18 28

first 1 20 26 1 58 60 18 28

mv is g8-e6, p is #p, o is g8

space g8 is g1

13 g1 g8-e6 1 20 26 1 58 60 18 28

1 10100 11010 1 111010 111100 10010 11100

2 one bits in var g1

1 10100 11010 1 111010 111100 10010 11100

q end g8-e6 1 20 26 1 58 60 18 28

bb end g8-e6 1 20 26 1 58 60 18 28

bw end g8-e6 1 20 26 1 58 60 18 28

firstr is c1, and lastr is h1

r g8-e6 1 20 26 1 58 60 18 28

first 1 20 26 1 58 60 18 28

mv is c2-c3, p is #p, o is c2

space c2 is P

14 P c2-c3 1 20 26 1 58 60 18 28

1 10100 11010 1 111010 111100 10010 11100

mv is f8-f7, p is #p, o is f8

space f8 is f1

15 f1 f8-f7 1 20 26 1 58 60 18 28

1 10100 11010 1 111010 111100 10010 11100

4 one bits in var f1

1 10100 11010 1 111010 111000 10010 11100

q end f8-f7 1 20 26 1 58 56 18 28

bb end f8-f7 1 20 26 1 58 56 18 28

bw end f8-f7 1 20 26 1 58 56 18 28

firstr is c1, and lastr is h1

r f8-f7 1 20 26 1 58 56 18 28

first 1 20 26 1 58 56 18 28

mv is d3-d4, p is #p, o is d3

space d3 is P

16 P d3-d4 1 20 26 1 58 56 18 28

1 10100 11010 1 111010 111000 10010 11100

mv is e6-c4, p is #p, o is e6

space e6 is g1

17 g1 e6-c4 1 20 26 1 58 56 18 28

1 10100 11010 1 111010 111000 10010 11100

2 one bits in var g1

1 10100 11010 1 111010 111000 10010 11100

q end e6-c4 1 20 26 1 58 56 18 28

bb end e6-c4 1 20 26 1 58 56 18 28

bw end e6-c4 1 20 26 1 58 56 18 28

firstr is c1, and lastr is h1

r e6-c4 1 20 26 1 58 56 18 28

first 1 20 26 1 58 56 18 28

mv is f1-f2, p is #p, o is f1

space f1 is f1

18 f1 f1-f2 1 20 26 1 58 56 18 28

1 10100 11010 1 111010 111000 10010 11100

3 one bits in var f1

1 10100 11010 1 111010 111000 10010 11100

q end f1-f2 1 20 26 1 58 56 18 28

bb end f1-f2 1 20 26 1 58 56 18 28

bw end f1-f2 1 20 26 1 58 56 18 28

firstr is c1, and lastr is h1

r f1-f2 1 20 26 1 58 56 18 28

first 1 20 26 1 58 56 18 28

mv is a8-b6, p is #p, o is a8

space a8 is a1

19 a1 a8-b6 1 20 26 1 58 56 18 28

1 10100 11010 1 111010 111000 10010 11100

1 one bits in var a1

1 10100 11010 1 111010 111000 10010 11100

q end a8-b6 1 20 26 1 58 56 18 28

bb end a8-b6 1 20 26 1 58 56 18 28

bw end a8-b6 1 20 26 1 58 56 18 28

firstr is c1, and lastr is h1

r a8-b6 1 20 26 1 58 56 18 28

first 1 20 26 1 58 56 18 28

mv is resign, p is #p, o is resign

Continue because resign is resign

Continue because mv is empty

This game may have been too short to properly calculate the original position, and the calculated pattern of N??N???? is inconsistent with randomly generated value of RNBQNBKR. If you think this game does have enough data to calculate the original position, please report it to Fergus Duniho.

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. g2-g3 
1... g7-g6 
2. a1-b3 
2... c7-c6 
3. e2-e4 
3... d8-e6 
4. d2-d3 
4... b8-c7 
5. f2-f4 
5... f7-f5 
6. b3-c5 
6... e6-c5 
7. g1-c5 
7... g8-e6 
8. c2-c3 
8... f8-f7 
9. d3-d4 
9... e6-c4 
10. f1-f2 
10... a8-b6 
11. resign

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

Here is a code listing:

   0 empty a1 b1 c1 d1 e1 f1 g1 h1 a8 b8 c8 d8 e8 f8 h8
   1 include fischer
   2 if isconst firstrank
   3   for i range 0 7
   4     set c join chr + 97 var i 1
   5     set p substr const firstrank var i 1
   6     add #p #c
   7   next
   8 elseif == status "Ongoing"
   9   drop B any a1 c1 e1 g1
  10   drop B any b1 d1 f1 h1
  11   drop Q any a1 b1 c1 d1 e1 f1 g1 h1
  12   drop N any a1 b1 c1 d1 e1 f1 g1 h1
  13   drop N any a1 b1 c1 d1 e1 f1 g1 h1
  14   drop R first a1 b1 c1 d1 e1 f1
  15   drop K first b1 c1 d1 e1 f1 g1
  16   drop R last c1 d1 e1 f1 g1 h1
  17   set fr null
  18   for i range a h
  19     set fr join var fr space join var i 1
  20   next
  21   setconst firstrank var fr
  22 else
  23   echo "Since no firstrank constant has been stored for this game, one will be calculated by analyzing the moves in the game. This will work only if the game lasted long enough to put enough pieces into play."
  24   gosub calc_original_position
  25 endif
  26 copy a1 a8
  27 copy b1 b8
  28 copy c1 c8
  29 copy d1 d8
  30 copy e1 e8
  31 copy f1 f8
  32 copy g1 g8
  33 copy h1 h8
  34 flip a8 b8 c8 d8 e8 f8 g8 h8
  35 set AR findpiece R first a1 b1 c1 d1 e1 f1
  36 set HR findpiece R first h1 g1 f1 e1 d1 c1
  37 set K findpiece K first b1 c1 d1 e1 f1 g1
  38 set ar findpiece r first a8 b8 c8 d8 e8 f8
  39 set hr findpiece r first h8 g8 f8 e8 d8 c8
  40 set k findpiece k first b8 c8 d8 e8 f8 g8
  41 setflag #AR #HR #K #ar #hr #k
  42 set k findpiece k spaces
  43 set K findpiece K spaces
  44 set ep false
  45 set koo g8
  46 set roo f8
  47 set kooo c8
  48 set rooo d8
  49 set KOO g1
  50 set ROO f1
  51 set KOOO c1
  52 set ROOO d1
  53 setsystem "dest" null
  54 sub postauto1
  55   if not equal moved P
  56     set ep false
  57     if unequal space dest moved
  58       die You may not change the type of this piece.
  59     endif
  60   endif
  61   set legal false
  62   if match moved P K R
  63     gosub moved origin dest
  64     if equal moved K
  65       set K dest
  66     endif
  67   elseif match moved Q B N
  68     set legal fn moved origin dest
  69   endif
  70   if not var legal
  71     die You may not move a moved from origin to dest
  72   endif
  73   if isupper $old and != $old K and != $moved R
  74     die You may not capture your own pieces.
  75   endif
  76   if fn ATTACKEDBYB #K
  77     die You may not move into check.
  78   endif
  79 endsub
  80 sub postauto2
  81   if not equal moved p
  82     set ep false
  83     if unequal space dest moved
  84       die You may not change the type of this piece.
  85     endif
  86   endif
  87   set legal false
  88   if match moved p k r
  89     gosub moved origin dest
  90     if equal moved k
  91       set k dest
  92     endif
  93   elseif match moved q b n
  94     set legal fn toupper moved origin dest
  95   endif
  96   if not var legal
  97     die You may not move a moved from origin to dest
  98   endif
  99   if islower old and != $old k and != $moved r
 100     die You may not capture your own pieces.
 101   endif
 102   if fn ATTACKEDBYW #k
 103     die You may not move into check.
 104   endif
 105 endsub
 106 moveindex 0
 107 MOVE: g2-g3
 108 postauto1
 109 moveindex 1
 110 MOVE: g7-g6
 111 postauto2
 112 moveindex 2
 113 MOVE: a1-b3
 114 postauto1
 115 moveindex 3
 116 MOVE: c7-c6
 117 postauto2
 118 moveindex 4
 119 MOVE: e2-e4
 120 postauto1
 121 moveindex 5
 122 MOVE: d8-e6
 123 postauto2
 124 moveindex 6
 125 MOVE: d2-d3
 126 postauto1
 127 moveindex 7
 128 MOVE: b8-c7
 129 postauto2
 130 moveindex 8
 131 MOVE: f2-f4
 132 postauto1
 133 moveindex 9
 134 MOVE: f7-f5
 135 postauto2
 136 moveindex 10
 137 MOVE: b3-c5
 138 postauto1
 139 moveindex 11
 140 MOVE: e6-c5
 141 postauto2
 142 moveindex 12
 143 MOVE: g1-c5
 144 postauto1
 145 moveindex 13
 146 MOVE: g8-e6
 147 postauto2
 148 moveindex 14
 149 MOVE: c2-c3
 150 postauto1
 151 moveindex 15
 152 MOVE: f8-f7
 153 postauto2
 154 moveindex 16
 155 MOVE: d3-d4
 156 postauto1
 157 moveindex 17
 158 MOVE: e6-c4
 159 postauto2
 160 moveindex 18
 161 MOVE: f1-f2
 162 postauto1
 163 moveindex 19
 164 MOVE: a8-b6
 165 postauto2
 166 moveindex 20
 167 MOVE: resign
 168 postauto1
 169 set checks sub checks #k
 170 if var checks
 171   if sub checkmated #k #checks
 172     say Checkmate! White has won!
 173     won
 174   else
 175     say Check!
 176   endif
 177 elseif sub stalemated #k
 178   say Stalemate! The game is drawn.
 179   drawn
 180 endif
 181 end
 182 
 183 lib fischer
 184 include chess
 185 set wprom (Q R B N)
 186 set bprom (q r b n)
 187 sub K from to
 188   set legal fn K #from #to
 189   if not var legal or == old R
 190     if == #to #KOOO
 191       castle #K #KOOO #AR #ROOO
 192     elseif == #to #KOO
 193       castle #K #KOO #HR #ROO
 194     endif
 195   endif
 196   set K #to
 197   unsetflag #from
 198 endsub
 199 sub k from to
 200   set legal fn K #from #to
 201   if not var legal or == old r
 202     if == #to #kooo
 203       castle #k #kooo #ar #rooo
 204     elseif == #to #koo
 205       castle #k #koo #hr #roo
 206     endif
 207   endif
 208   set k #to
 209   unsetflag #from
 210 endsub
 211 sub R from to
 212   set legal fn R #from #to
 213   if not var legal or == old K
 214     echo "Castling with Rook!" #from #to #AR #ROOO #HR #ROO
 215     if == #from #AR and == #to #ROOO
 216       castle #K #KOOO #from #ROOO
 217       set K #KOOO
 218     elseif == #from #HR and == #to #ROO
 219       castle #K #KOO #from #ROO
 220       set K #KOO
 221     endif
 222   endif
 223   unsetflag #from
 224 endsub
 225 sub r from to
 226   set legal fn R #from #to
 227   if not var legal or == old k
 228     if == #from #ar and == #to #rooo
 229       castle #k #kooo #from #rooo
 230       set k #kooo
 231     elseif == #from #hr and == #to #roo
 232       castle #k #koo #from #roo
 233       set k #koo
 234     endif
 235   endif
 236   unsetflag #from
 237 endsub
 238 sub castle
 239   local ATTACKED c KP RP KF KT RF RT RN
 240   if < count #subargs 4
 241     die The castle suboutine requires at least four arguments.
 242   endif
 243   set KF #subargs.0
 244   set KT #subargs.1
 245   set RF #subargs.2
 246   set RT #subargs.3
 247   if > count #subargs 4
 248     set RN #subargs.4
 249   else
 250     set RN Rook
 251   endif
 252   if not flag #KF
 253     die A King may not castle after it moves.
 254   endif
 255   if not flag #RF
 256     die A #RN may not castle after it moves.
 257   endif
 258   if empty #KF and empty #RF
 259     die Please castle by moving only one piece.
 260   elseif empty #KF
 261     if != #RF #KT
 262       if capture
 263         die The King may not castle to an occupied space.
 264       endif
 265       set RP space #RF
 266     else
 267       set RP old
 268       setglobal lastcaptured nil
 269     endif
 270     set KP space #KT
 271     empty #KT
 272     empty #RF
 273   elseif empty #RF
 274     if != #KF #RT
 275       if capture
 276         die The #RN may not castle to an occupied space.
 277       endif
 278       set KP space #KF
 279     else
 280       set KP old
 281       setglobal lastcaptured nil
 282     endif
 283     set RP space #RT
 284     empty #KF
 285     empty #RT
 286   elseif capture
 287     die You're not allowed to castle with a null move.
 288   else
 289     set RP space #RF
 290     set KP space #KF
 291     empty #KF
 292     empty #RF
 293   endif
 294   unsetflag #KF
 295   unsetflag #RF
 296   if not checkride #KF #KT 1 0 and != #KF #KT
 297     die The King may not castle across an obstructed path.
 298   endif
 299   if not checkride #RF #RT 1 0 and != #RF #RT
 300     die The #RN may not castle across an obstructed path.
 301   endif
 302   add #RP #RF
 303   set ATTACKED ATTACKEDBYW unless isupper moved ATTACKEDBYB
 304   if fn #ATTACKED #KT
 305     die A King may not castle out of check.
 306   endif
 307   for c path #KF #KT
 308     if fn var ATTACKED #c
 309       die A King may not castle through check.
 310     endif
 311   next
 312   move #RF #RT
 313   add #KP #KT
 314   set legal true
 315 endsub
 316 sub castlepos KF KT RF RT
 317   local ATTACKED c safe
 318   verify flag #KF
 319   verify flag #RF
 320   verify empty #KT or match #KT #KF #RF
 321   verify empty #RT or match #RT #KF #RF
 322   verify checkride #KF #RF 1 0
 323   verify checkride #KF #KT 1 0 or checkride #RF #KT 1 0
 324   verify allequal rank #KF rank #KT rank #RF rank #RT
 325   if isupper space #king
 326     def friend isupper #0
 327     def friends onlyupper
 328     set attacked ATTACKEDBYB
 329   else
 330     def friend islower #0
 331     def friends onlylower
 332     set attacked ATTACKEDBYW
 333   endif
 334   verify not fn var attacked #KF
 335   verify not fn var attacked #KT
 336   foreach c path #KF #KT
 337     verify not fn var attacked #c
 338   next
 339   store
 340   if != #KT #RF
 341     move #KF #KT
 342     move #RF #RT
 343   else
 344     move #RF #RT
 345     move #KF #KT
 346   endif
 347   set safe not fn var attacked #KT
 348   restore
 349   return #safe
 350 endsub
 351 sub stalemated king
 352   local legalmove temp from piece to attacked ra
 353   if isupper space #king
 354     def friend isupper #0
 355     def friends onlyupper
 356     set attacked ATTACKEDBYB
 357   else
 358     def friend islower #0
 359     def friends onlylower
 360     set attacked ATTACKEDBYW
 361   endif
 362   store
 363   set kingmoves fn KL #king
 364   for to #kingmoves
 365     if not fn friend space #to and onboard #to
 366       move #king #to
 367       set incheck fn var attacked #to
 368       restore
 369       if not #incheck
 370         setlegal #king #to
 371       endif
 372     endif
 373   next
 374   if isupper space #king
 375     if sub castlepos #king #KOOO #AR #ROOO
 376       if > distance #king #KOOO 1 or == #KOOO #AR
 377         setlegal #king #KOOO
 378       else
 379         setlegal #AR #ROOO
 380       endif
 381     endif
 382     if sub castlepos #king #KOO #HR #ROO
 383       if > distance #king #KOO 1 or == #KOO #HR
 384         setlegal #king #KOO
 385       else
 386         setlegal #HR #ROO
 387       endif
 388     endif
 389   else
 390     if sub castlepos #king #kooo #ar #rooo
 391       if > distance #king #kooo 1 or == #kooo #ar
 392         setlegal #king #kooo
 393       else
 394         setlegal #ar #rooo
 395       endif
 396     endif
 397     if sub castlepos #king #koo #hr #roo
 398       if > distance #king #koo 1 or == #koo #hr
 399         setlegal #king #koo
 400       else
 401         setlegal #hr #roo
 402       endif
 403     endif
 404   endif
 405   restore
 406   for (from piece) fn friends
 407     if == #from #king
 408       continue
 409     endif
 410     for to fn join #piece L #from
 411       if fn #piece #from #to and not fn friend space #to and onboard #to
 412         move #from #to
 413         set incheck fn var attacked #king
 414         if not #incheck
 415           setlegal #from #to
 416         endif
 417       endif
 418       restore
 419     next
 420   next
 421   return cond count system legalmoves false true
 422 endsub
 423 sub calc_original_position
 424   store
 425   local a1 b1 c1 d1 e1 f1 g1 h1 n bb w b r q k K Q R B N ra firstr lastr last
 426   add a1 a1
 427   add b1 b1
 428   add c1 c1
 429   add d1 d1
 430   add e1 e1
 431   add f1 f1
 432   add g1 g1
 433   add h1 h1
 434   add a1 a8
 435   add b1 b8
 436   add c1 c8
 437   add d1 d8
 438   add e1 e8
 439   add f1 f8
 440   add g1 g8
 441   add h1 h8
 442   set many n 1 bb 2 bw 4 b 6 r 8 q 16 k 32
 443   set a1 orsum #r #n #bb #q
 444   set b1 orsum #r #n #bw #q #k
 445   set c1 orsum #r #n #bb #q #k
 446   set d1 orsum #r #n #bw #q #k
 447   set e1 orsum #r #n #bb #q #k
 448   set f1 orsum #r #n #bw #q #k
 449   set g1 orsum #r #n #bb #q #k
 450   set h1 orsum #r #n #bw #q
 451   set many K 1 Q 1 R 2 B 2 N 2
 452   set rank1 array a1 b1 c1 d1 e1 f1 g1 h1
 453   setflag a1 b1 c1 d1 e1 f1 g1 h1 a8 b8 c8 d8 e8 f8 g8 h8
 454   foreach i range 0 $maxmoves
 455     set normal true
 456     set mv move #i
 457     if not var mv
 458       echo "Continue because mv is empty"
 459       continue
 460     endif
 461     set mv str_replace " - " chr 45 var mv
 462     set pm explode " " var mv
 463     set p elem 0 pm
 464     set m elem 1 pm
 465     if != var m null
 466       set od explode hyphen var m
 467     else
 468       set od explode hyphen var mv
 469       unset p
 470     endif
 471     set o elem 0 od
 472     set d elem 1 od
 473     echo "mv is {#mv}, p is {#p}, o is {#o}"
 474     if == #mv #o
 475       echo "Continue because {#mv} is {#o}"
 476       continue
 477     endif
 478     set pp space #o
 479     echo "space {#o} is {#pp}"
 480     echo #i #pp #mv #a1 #b1 #c1 #d1 #e1 #f1 #g1 #h1
 481     set b2 list base 2 #a1 base 2 #b1 base 2 #c1 base 2 #d1 base 2 #e1 base 2 #f1 base 2 #g1 base 2 #h1
 482     echo #b2
 483     if match #pp p P
 484       if checkleap #o #d 1 1 and empty #d
 485         set ep join filename #d rankname #o
 486         if == space #ep flipcase space #0
 487           empty #ep
 488         endif
 489       endif
 490       move #o #d
 491       continue
 492     elseif match #pp n N b B r R q Q
 493       move #o #d
 494       continue
 495     endif
 496     set bp onebits var #pp
 497     echo "{#bp} one bits in var {#pp}"
 498     if > #bp 1 and match var p k q r b n p K Q R B N P and != var p null
 499       set lc tolower var p
 500       set #pp bitand ##pp ##lc
 501     elseif == ##pp "@"
 502       echo "Warning: There is no piece on {#o}"
 503     elseif > #bp 1
 504       if checkleap #o #d 1 2
 505         set #pp bitand ##pp #n
 506       elseif checkleap #o #d 1 0
 507         set os orsum #r #q #k
 508         set #pp bitand ##pp orsum #r #q #k
 509       elseif checkleap #o #d 1 1
 510         set #pp bitand ##pp orsum #b #q #k
 511       elseif checkride #o #d 1 1
 512         set #pp bitand ##pp orsum #b #q
 513       elseif checkride #o #d 1 0
 514         echo "rook ride"
 515         if == rank #o rank #d and match rankname #d 1 8
 516           if match #d c1 g1 c8 g8 and flag #o
 517             if not empty #d
 518               echo "King castles by moving to Rook's space."
 519               set #pp bitand ##pp #k
 520               set ro #d
 521               set rp space #ro
 522               set #rp #r
 523               echo "rp: {#rp}, val: {##rp}"
 524               if == #d c1
 525                 set rd d1
 526               elseif == #d c8
 527                 set rd d8
 528               elseif == #d g1
 529                 set rd f1
 530               else
 531                 set rd f8
 532               endif
 533               move #o temp
 534               move #d #rd
 535               move temp #d
 536               foreach f flags
 537                 if == rank f rank #o
 538                   unsetflag #f
 539                 endif
 540               next
 541               set normal false
 542             elseif empty #d and bitand ##pp #k
 543               echo "King castling by moving 2+ spaces"
 544               if == #d c1
 545                 if empty b1
 546                   set ro a1
 547                 else
 548                   set ro b1
 549                 endif
 550                 set rd d1
 551               elseif == #d g1
 552                 set ro h1
 553                 set rd f1
 554               elseif == #d c8
 555                 if empty b8
 556                   set ro a8
 557                 else
 558                   set ro b8
 559                 endif
 560                 set rd d8
 561               elseif == #d g8
 562                 set ro h8
 563                 set rd f8
 564               endif
 565               set rp space #ro
 566               if not bitand #ko #r or not bitand #a1 #r or match file #ro a h bitand ##rp #r and not bitand ##pp #q and flag #ro
 567                 move #o #d
 568                 move #ro #rd
 569                 set #pp #k
 570                 set #rp #r
 571                 foreach f flags
 572                   if == rank f rank #o
 573                     unsetflag #f
 574                   endif
 575                 next
 576                 set normal false
 577               else
 578                 echo "Assuming not actually a castling move."
 579                 set #pp bitand ##pp orsum #r #q
 580               endif
 581             else
 582               echo "Rook or Queen move"
 583               set #pp bitand ##pp orsum #r #q
 584             endif
 585           elseif not empty #d and match #d f1 d1 f8 d8 and flag #o
 586             echo "Rook castles by moving to King's space."
 587             set #pp bitand ##pp #r
 588             set ko #d
 589             echo "ko set to {#ko}"
 590             set kp space #ko
 591             set #kp #k
 592             echo "{#kp} set to {##kp}"
 593             if == #d f1
 594               set kd g1
 595             elseif == #d d1
 596               set kd c1
 597             elseif == #d f8
 598               set kd g8
 599             elseif == #d d8
 600               set kd c8
 601             endif
 602             if == #kd #o
 603               swap #kd #o
 604             else
 605               move #o #d
 606               move #ko #kd
 607             endif
 608             foreach f flags
 609               if == rank f rank #o
 610                 unsetflag #f
 611               endif
 612             next
 613             set normal false
 614           else
 615             echo "Rook or Queen move"
 616             set #pp bitand ##pp orsum #r #q
 617           endif
 618         else
 619           echo "{#pp} currently set to {##pp}"
 620           set #pp bitand ##pp bitor #r #q
 621           echo "{#pp} now set to {##pp}"
 622         endif
 623       elseif checkhop #o #d 1 0 and match rankname #o 1 8 and flag #o
 624         echo "rook hopping king to castle"
 625         if and match #d f1 d1 f8 d8
 626           set #pp bitand ##pp #r
 627           set ko screen
 628           set kp var space #ko
 629           set #kp #k
 630           if == #d f1
 631             set kd g1
 632           elseif == #d d1
 633             set kd c1
 634           elseif == #d f8
 635             set kd g8
 636           elseif == #d d8
 637             set kd c8
 638           endif
 639           if == #kd #o and == #d #ko
 640             swap #kd #o
 641           elseif == #d #ko
 642             move #o temp
 643             move #ko #kd
 644             move temp #d
 645           else
 646             move #o #d
 647             move #ko #kd
 648           endif
 649           foreach f flags
 650             if == rank f rank #o
 651               unsetflag #f
 652             endif
 653           next
 654           set normal false
 655         elseif match #d c1 g1 c8 g8 and flag #o
 656           echo "King castling by hopping over Rook"
 657           set #pp bitand ##pp #k
 658           set ro screen
 659           set rp var space #ro
 660           set #rp #r
 661           if == #d c1
 662             set rd d1
 663           elseif == #d c8
 664             set rd d8
 665           elseif == #d g1
 666             set rd f1
 667           else
 668             set rd f8
 669           endif
 670           move #o #d
 671           move #ro #rd
 672           foreach f flags
 673             if == rank f rank #o
 674               unsetflag #f
 675             endif
 676           next
 677           set normal false
 678         endif
 679       endif
 680       if == ##pp 0
 681         echo "ERROR: Potential piece value set to zero"
 682       endif
 683     endif
 684     do
 685       set b2 list base 2 #a1 base 2 #b1 base 2 #c1 base 2 #d1 base 2 #e1 base 2 #f1 base 2 #g1 base 2 #h1
 686       echo #b2
 687       set changed false
 688       set ra aggregate lambda (cond bitand var #0 #k #0 false) #rank1
 689       if == count #ra 1
 690         set kp #ra.0
 691         if != ##kp #k
 692           set #kp #k
 693           set changed true
 694         endif
 695         set ra aggregate lambda (cond == var #0 #k #0 false) #rank1
 696         set kp #ra.0
 697         echo #kp
 698         set leftside aggregate lambda (cond < #0 #kp #0 false) #rank1
 699         printr #leftside
 700         set ra aggregate lambda (cond bitand var #0 #r #0 false) #leftside
 701         if == count #ra 1
 702           foreach sp #ra
 703             if != ##sp #r
 704               set #sp #r
 705               set changed true
 706             endif
 707           next
 708         else
 709           set ra aggregate lambda (cond == var #0 #r #0 false) #leftside
 710           if == count #ra 1
 711             foreach sp #leftside
 712               if != ##sp #r
 713                 set #sp bitand ##sp bitxor 63 #r
 714                 set changed true
 715               endif
 716             next
 717           endif
 718         endif
 719         set rightside aggregate lambda (cond > #0 #kp #0 false) #rank1
 720         set ra aggregate lambda (cond bitand var #0 #r #0 false) #rightside
 721         if == count #ra 1
 722           foreach sp #ra
 723             if != ##sp #r
 724               set #sp #r
 725               set changed true
 726             endif
 727           next
 728         else
 729           set ra aggregate lambda (cond == var #0 #r #0 false) #rightside
 730           if == count #ra 1
 731             foreach sp #rightside
 732               if != ##sp #r
 733                 set #sp bitand ##sp bitxor 63 #r
 734                 set changed true
 735               endif
 736             next
 737           endif
 738         endif
 739       else
 740         set ra aggregate lambda (cond != var #0 #k #0 false) #rank1
 741         if == count #ra 7
 742           foreach sp #ra
 743             if bitand ##sp #k
 744               set #sp bitand ##sp bitxor 63 #k
 745               set changed true
 746             endif
 747           next
 748         endif
 749       endif
 750       set ra aggregate lambda (cond bitand var #0 #q #0 false) #rank1
 751       if == count #ra 1
 752         foreach sp #ra
 753           if != ##sp #q
 754             set #sp #q
 755             set changed true
 756           endif
 757         next
 758       else
 759         set ra aggregate lambda (cond != var #0 #q #0 false) #rank1
 760         if == count #ra 7
 761           echo queen before #mv #a1 #b1 #c1 #d1 #e1 #f1 #g1 #h1
 762           foreach sp #ra
 763             if bitand ##sp #q
 764               set #sp bitand ##sp bitxor 63 #q
 765               set changed true
 766             endif
 767           next
 768           echo queen after #mv #a1 #b1 #c1 #d1 #e1 #f1 #g1 #h1
 769         endif
 770       endif
 771       echo q end #mv #a1 #b1 #c1 #d1 #e1 #f1 #g1 #h1
 772       set ra aggregate lambda (cond bitand var #0 #bb #0 false) #rank1
 773       if == count #ra 1
 774         foreach sp #ra
 775           if != ##sp #bb
 776             set #sp #bb
 777             set changed true
 778           endif
 779         next
 780       else
 781         set ra aggregate lambda (cond != var #0 #bb #0 false) #rank1
 782         if == count #ra 7
 783           foreach sp #ra
 784             if bitand ##sp #bb
 785               set #sp bitand ##sp bitxor 63 #bb
 786               set changed true
 787             endif
 788           next
 789         endif
 790       endif
 791       echo bb end #mv #a1 #b1 #c1 #d1 #e1 #f1 #g1 #h1
 792       set ra aggregate lambda (cond bitand var #0 #bw #0 false) #rank1
 793       if == count #ra 1
 794         foreach sp #ra
 795           if != ##sp #bw
 796             set #sp #bw
 797             set changed true
 798           endif
 799         next
 800       else
 801         set ra aggregate lambda (cond != var #0 #bw #0 false) #rank1
 802         if == count #ra 7
 803           foreach sp #ra
 804             if bitand ##sp #bw
 805               set #sp bitand ##sp bitxor 63 #bw
 806               set changed true
 807             endif
 808           next
 809         endif
 810       endif
 811       echo bw end #mv #a1 #b1 #c1 #d1 #e1 #f1 #g1 #h1
 812       set ra aggregate lambda (cond bitand var #0 #r #0 false) #rank1
 813       if == count #ra 2
 814         foreach sp #ra
 815           if != ##sp #r
 816             set #sp #r
 817             set changed true
 818           endif
 819         next
 820         set betweenrooks aggregate lambda (cond and < #ra.0 #0 > #ra.1 #0 #0 false) #rank1
 821         set ra2 aggregate lambda (cond bitand var #0 #k #0 false) #betweenrooks
 822         if == count #ra2 1
 823           foreach sp #ra2
 824             if != ##sp #k
 825               set #sp #k
 826               set changed true
 827             endif
 828           next
 829         else
 830           set ra2 aggregate lambda (cond == var #0 #r #0 false) #rank1
 831           foreach sp #rank1
 832             echo #ra2.0 #ra2.1
 833             if < #sp #ra2.0 or > #sp #ra2.1 and bitand ##sp #k
 834               set #sp bitand ##sp bitxor 63 #k
 835               set changed true
 836             endif
 837           next
 838         endif
 839       else
 840         set firstr #ra.0
 841         set last - count #ra 1
 842         set lastr #ra.{#last}
 843         echo "firstr is {#firstr}, and lastr is {#lastr}"
 844         set rooks 0
 845         foreach sp #rank1
 846           if match #sp #firstr #lastr
 847             inc rooks
 848             if bitand ##sp #k
 849               set #sp bitand ##sp bitxor 63 #k
 850               set changed true
 851             endif
 852           elseif != #rooks 1
 853             if bitand ##sp #k
 854               set #sp bitand ##sp bitxor 63 #k
 855               set changed true
 856             endif
 857           endif
 858         next
 859         if == count #ra 3
 860           set leftking anytrue lambda (bitand var #0 #k and > #0 #ra.0 and < #0 #ra.1) #rank1
 861           set rghtking anytrue lambda (bitand var #0 #k and > #0 #ra.1 and < #0 #ra.2) #rank1
 862           if not #leftking
 863             set #ra.2 #r
 864           elseif not #rghtking
 865             set #ra.0 #r
 866           endif
 867         endif
 868         set ra aggregate lambda (cond != var #0 #r #0 false) #rank1
 869         if == count #ra 6
 870           echo "Two rooks found."
 871           foreach sp #ra
 872             if bitand ##sp #r
 873               set #sp bitand ##sp bitxor 63 #r
 874               set changed true
 875             endif
 876           next
 877         elseif == count #ra 7
 878           echo "One Rook found"
 879           set ra aggregate lambda (cond == var #0 #r #0 false) #rank1
 880           set next where #ra.0 1 0
 881           do while onboard #next
 882             echo #next ##next
 883             if bitand ##next #r
 884               set #next bitand ##next bitxor 63 #r
 885               set changed true
 886             endif
 887             if bitand ##next #k
 888               break
 889             endif
 890             set next where #next 1 0
 891           loop
 892           set prev where #ra.0 -1 0
 893           do while onboard #prev
 894             if bitand ##prev #r
 895               set #prev bitand ##prev bitxor 63 #r
 896               set changed true
 897             endif
 898             if bitand ##prev #k
 899               break
 900             endif
 901             set prev where #prev -1 0
 902           loop
 903         endif
 904         echo r #mv #a1 #b1 #c1 #d1 #e1 #f1 #g1 #h1
 905       endif
 906       echo first #a1 #b1 #c1 #d1 #e1 #f1 #g1 #h1
 907       set ra aggregate lambda (cond bitand var #0 #2 #0 false) #rank1
 908       if == count #ra 2
 909         foreach sp #ra
 910           if != ##sp #n
 911             set #sp #n
 912             set changed true
 913           endif
 914         next
 915       else
 916         set ra aggregate lambda (cond != var #0 #n #0 false) #rank1
 917         if == count #ra 6
 918           foreach sp #ra
 919             if bitand ##sp #n
 920               set #sp bitand ##sp bitxor 63 #n
 921               set changed true
 922             endif
 923           next
 924         endif
 925       endif
 926     loop while #changed
 927     if var normal
 928       move #o #d
 929       unsetflag #o #d
 930     endif
 931   next
 932   set fr ""
 933   foreach c (a1 b1 c1 d1 e1 f1 g1 h1)
 934     if == ##c #n
 935       set fr join #fr "N"
 936     elseif match ##c #bb #bw
 937       set fr join #fr "B"
 938     elseif == ##c #r
 939       set fr join #fr "R"
 940     elseif == ##c #q
 941       set fr join #fr "Q"
 942     elseif == ##c #k
 943       set fr join #fr "K"
 944     else
 945       set fr join #fr "@"
 946     endif
 947   next
 948   if !== false strstr #fr "@"
 949     set pat str_replace "@" "?" #fr
 950     empty a1 b1 c1 d1 e1 f1 g1 h1 a8 b8 c8 d8 e8 f8 h8
 951     drop B any a1 c1 e1 g1
 952     drop B any b1 d1 f1 h1
 953     drop Q any a1 b1 c1 d1 e1 f1 g1 h1
 954     drop N any a1 b1 c1 d1 e1 f1 g1 h1
 955     drop N any a1 b1 c1 d1 e1 f1 g1 h1
 956     drop R first a1 b1 c1 d1 e1 f1
 957     drop K first b1 c1 d1 e1 f1 g1
 958     drop R last c1 d1 e1 f1 g1 h1
 959     set fr null
 960     for i range a h
 961       set fr join var fr space join var i 1
 962     next
 963     if not fnmatch var pat var fr
 964       die "This game may have been too short to properly calculate the original position, and the calculated pattern of {#pat} is inconsistent with randomly generated value of {#fr}. If you think this game does have enough data to calculate the original position, please report it to Fergus Duniho."
 965     endif
 966   endif
 967   restore
 968   setconst firstrank #fr
 969   for i range 0 7
 970     set c join chr + 97 var i 1
 971     set p substr const firstrank var i 1
 972     add #p #c
 973   next
 974   echo "firstrank is" @firstrank
 975 endsub
 976 endlib
 977 lib chess
 978 set wpr 2
 979 set bpr 7
 980 set fps 2
 981 set pzs 1
 982 set wcastle c1 g1
 983 set bcastle c8 g8
 984 do
 985   local x
 986   for x piecekeys
 987     if match #x P K p k
 988       continue
 989     elseif isupper #x
 990       push wprom #x
 991     elseif islower #x
 992       push bprom #x
 993     endif
 994   next
 995 loop never
 996 setsystem maxmove 2
 997 ban commands allmoves
 998 allow moves 1 captures 1 promotions 2
 999 def N checkleap #0 #1 1 2
1000 def B checkride #0 #1 1 1
1001 def R checkride #0 #1 1 0
1002 def Q fn B #0 #1 or fn R #0 #1
1003 def K checkleap #0 #1 1 1 or checkleap #0 #1 1 0
1004 def M fn N #0 #1 or fn R #0 #1
1005 def A fn N #0 #1 or fn B #0 #1
1006 def n checkleap #0 #1 1 2
1007 def b checkride #0 #1 1 1
1008 def r checkride #0 #1 1 0
1009 def q fn b #0 #1 or fn r #0 #1
1010 def k checkleap #0 #1 1 1 or checkleap #0 #1 1 0
1011 def m fn n #0 #1 or fn r #0 #1
1012 def a fn n #0 #1 or fn b #0 #1
1013 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
1014 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
1015 sub capturep p
1016   empty #p
1017   return true
1018 endsub
1019 sub checks king
1020   if not dest
1021     return false
1022   endif
1023   my checks c
1024   set checks ()
1025   if fn space dest dest #king
1026     setelem checks dest space dest
1027   endif
1028   set c sub checkedthru #king origin
1029   if #c
1030     setelem checks #c space #c
1031   elseif #epc
1032     set c sub checkedthru #king #epc
1033     if #c
1034       setelem checks #c space #c
1035     endif
1036   endif
1037   return var checks
1038 endsub
1039 sub checkmated king checks
1040   local from piece to key legalmove piece nopawn
1041   store
1042   if isupper space #king
1043     def friends onlyupper
1044     def friend isupper #0
1045     set attacked ATTACKEDBYB
1046   else
1047     def friends onlylower
1048     def friend islower #0
1049     set attacked ATTACKEDBYW
1050   endif
1051   set kingmoves fn KL #king
1052   for to #kingmoves
1053     if not fn friend space #to and onboard #to
1054       move #king #to
1055       set incheck fn var attacked #to
1056       restore
1057       if not #incheck
1058         setlegal #king #to
1059       endif
1060     endif
1061   next
1062   if == count var checks 1
1063     for (key enemy) var checks
1064       set possible path #king #key
1065       push possible #key
1066       if == #key #ep
1067         push possible cond isupper space #ep where #ep 0 -1 where #ep 0 1
1068       endif
1069       for (from piece) fn friends
1070         if == #from #king
1071           continue
1072         endif
1073         for to #possible
1074           if fn #piece #from #to
1075             move #from #to
1076             set incheck fn var attacked #king
1077             if not #incheck
1078               setlegal #from #to
1079             endif
1080           endif
1081           restore
1082         next
1083       next
1084     next
1085   endif
1086   return cond count system legalmoves false true and checks
1087 endsub
1088 def PL array where #0 0 2 where #0 0 1 where #0 -1 1 where #0 1 1
1089 def pL array where #0 0 -2 where #0 0 -1 where #0 -1 -1 where #0 1 -1
1090 def NL leaps #0 1 2
1091 def BL rays #0 1 1
1092 def RL rays #0 1 0
1093 def VL rays #0 1 1
1094 def CL rays #0 1 0
1095 def QL merge rays #0 1 0 rays #0 1 1
1096 def KL merge leaps #0 1 0 leaps #0 1 1
1097 def AL merge leaps #0 1 2 rays #0 1 1
1098 def ML merge rays #0 1 0 leaps #0 1 2
1099 def nL leaps #0 1 2
1100 def bL rays #0 1 1
1101 def rL rays #0 1 0
1102 def vL rays #0 1 1
1103 def cL rays #0 1 0
1104 def qL merge rays #0 1 0 rays #0 1 1
1105 def kL merge leaps #0 1 0 leaps #0 1 1
1106 def aL merge leaps #0 1 2 rays #0 1 1
1107 def mL merge rays #0 1 0 leaps #0 1 2
1108 sub castlepos from to
1109   local c RPOS RDEST xdir safe
1110   verify flag #from
1111   verify empty #to
1112   if isupper space #king
1113     def friend isupper #0
1114     def friends onlyupper
1115     set attacked ATTACKEDBYB
1116   else
1117     def friend islower #0
1118     def friends onlylower
1119     set attacked ATTACKEDBYW
1120   endif
1121   set xdir sign minus file #to file #from
1122   verify checkaride #from #to #xdir 0
1123   verify not fn var attacked #from
1124   set c #to
1125   do
1126     set c where #c #xdir 0
1127     if flag #c
1128       break
1129     endif
1130     verify onboard #c
1131     verify empty #c
1132   loop
1133   verify flag #c
1134   set RPOS #c
1135   store
1136   for c path #from #to
1137     move #from #c
1138     set safe not fn var attacked #c
1139     restore
1140     verify #safe
1141   next
1142   move #from #to
1143   set RDEST where #to neg #xdir 0
1144   move #RPOS #RDEST
1145   return true
1146 endsub
1147 sub stalemated king
1148   local legalmove temp from piece to attacked ra
1149   if isupper space #king
1150     def friend isupper #0
1151     def friends onlyupper
1152     set attacked ATTACKEDBYB
1153     set cspaces var wcastle
1154   else
1155     def friend islower #0
1156     def friends onlylower
1157     set attacked ATTACKEDBYW
1158     set cspaces var bcastle
1159   endif
1160   store
1161   set kingmoves fn KL #king
1162   for to #kingmoves
1163     if not fn friend space #to and onboard #to
1164       move #king #to
1165       set incheck fn var attacked #to
1166       restore
1167       if not #incheck
1168         setlegal #king #to
1169       endif
1170     endif
1171   next
1172   for to var cspaces
1173     if sub castlepos #king #to
1174       set incheck fn var attacked #to
1175       restore
1176       if not #incheck
1177         setlegal #king #to
1178       endif
1179     endif
1180   next
1181   restore
1182   for (from piece) fn friends
1183     if == #from #king
1184       continue
1185     endif
1186     for to fn join #piece L #from
1187       if fn #piece #from #to and not fn friend space #to and onboard #to
1188         move #from #to
1189         set incheck fn var attacked #king
1190         if not #incheck
1191           setlegal #from #to
1192         endif
1193       endif
1194       restore
1195     next
1196   next
1197   return cond count system legalmoves false true
1198 endsub
1199 def WPAWN match P what #0 1 -1 what #0 -1 -1
1200 def BPAWN match p what #0 1 1 what #0 -1 1
1201 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
1202 def WAZIR check what #0 0 -1 check what #0 -1 0 check what #0 0 1 check what #0 1 0 target #1
1203 def FERZ check what #0 -1 -1 check what #0 -1 1 check what #0 1 -1 check what #0 1 1 target #1
1204 def KING fn WAZIR #0 #1 or fn FERZ #0 #1
1205 def ROOK check insight #0 0 -1 check insight #0 -1 0 check insight #0 0 1 check insight #0 1 0 target #1
1206 def BISHOP check insight #0 -1 -1 check insight #0 -1 1 check insight #0 1 -1 check insight #0 1 1 target #1
1207 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)
1208 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)
1209 sub P from to
1210   local ydir
1211   if == file #from file #to and not capture
1212     set legal checkaleap #from #to 0 1
1213     if var legal
1214       set ep false
1215     else
1216       set legal checkaride #from #to 0 1 and <= distance #from #to #fps and or == rankname #from #wpr < #wpr 0
1217       set ep #to
1218     endif
1219     set epc false
1220   elseif capture or #ep
1221     set legal checkaleap #from #to -1 1 or checkaleap #from #to 1 1
1222     set epc false
1223     if not capture and var legal
1224       set legal > rank #to rank #ep and < rankname #to #bpr and == file #to file #ep
1225       if var legal
1226         capture #ep
1227         set epc #ep
1228       endif
1229     endif
1230     set ep false
1231   endif
1232   if != space #to moved and onboard where #to 0 #pzs
1233     die "You may not promote a Pawn until it reaches the promotion zone."
1234   endif
1235   if not onboard where #to 0 1
1236     if == P space #to
1237       askpromote #wprom
1238     elseif not match space #to var wprom
1239       set np space #to
1240       die "You may not promote your Pawn to a" #np
1241     endif
1242   endif
1243 endsub
1244 sub p from to
1245   if == file #from file #to and not capture
1246     set legal checkaleap #from #to 0 -1
1247     if var legal
1248       set ep false
1249     else
1250       set legal checkaride #from #to 0 -1 and <= distance #from #to #fps and or == rankname #from #bpr > #bpr lastrank
1251       set ep #to
1252     endif
1253     set epc false
1254   elseif capture or #ep
1255     set legal checkaleap #from #to -1 -1 or checkaleap #from #to 1 -1
1256     set epc false
1257     if not capture and var legal
1258       set legal < rank #to rank #ep and > rankname #to #wpr and == file #to file #ep
1259       if var legal
1260         capture #ep
1261         set epc #ep
1262       endif
1263     endif
1264     set ep false
1265   endif
1266   if != space #to moved and onboard where #to 0 neg #pzs
1267     die You may not promote a Pawn until it reaches the promotion zone.
1268   endif
1269   if not onboard where #to 0 -1
1270     if == p space #to
1271       askpromote #bprom
1272     elseif not match space #to var bprom
1273       set np space #to
1274       die You may not promote your Pawn to a #np
1275     endif
1276   endif
1277 endsub
1278 sub K from to
1279   if match #to var wcastle and flag #from
1280     set legal sub castle
1281   else
1282     set legal fn K #from #to
1283   endif
1284   set K #to
1285   unsetflag e1
1286 endsub
1287 sub k from to
1288   if match #to var bcastle and flag #from
1289     set legal sub castle
1290   else
1291     set legal fn k #from #to
1292   endif
1293   set k #to
1294   unsetflag e8
1295 endsub
1296 sub castle
1297   local ATTACKED c RPOS RDEST xdir
1298   if not flag #from
1299     die A King may not castle after it moves.
1300   endif
1301   if capture
1302     die A King may not castle to an occupied space.
1303   endif
1304   set xdir sign minus file #to file #from
1305   if not checkaride #from #to #xdir 0
1306     die A King may not castle across any occupied space.
1307   endif
1308   set c #to
1309   do
1310     set c where #c #xdir 0
1311     if flag #c
1312       break
1313     elseif not onboard #c
1314       die No piece was found to castle with.
1315     elseif not empty #c
1316       die The King cannot castle with the piece at #c
1317     endif
1318   loop
1319   set RPOS #c
1320   set ATTACKED ATTACKEDBYW unless isupper moved ATTACKEDBYB
1321   if fn var ATTACKED #from
1322     die A King may not castle out of check.
1323   endif
1324   for c path #from #to
1325     if fn var ATTACKED #c
1326       die A King may not castle through check.
1327     endif
1328   next
1329   if == count var subargs 0
1330     set RDEST where #to neg #xdir 0
1331   else
1332     set RDEST elem 0 subarg
1333   endif
1334   unsetflag #RPOS
1335   move #RPOS #RDEST
1336   return true
1337 endsub
1338 sub checkedthru king loc
1339   my dir c
1340   set c revealed #king #loc
1341   verify fn space #c #c #king and not samecase space #king space #c and onboard #c and #c
1342   return #c
1343 endsub
1344 def fn checkedfrom fn space #1 #0 and xor isupper space #0 isupper space #1 and not empty #1
1345 sub P1 from to
1346   if == file #from file #to
1347     return not capture
1348   elseif capture
1349     return true
1350   elseif == file #to file #ep and == rank #from rank #ep and #ep
1351     capture #ep
1352     return true
1353   endif
1354   return false
1355 endsub
1356 sub PP from to
1357   if checkatwostep #from #to 0 1 0 1 or checkaleap #from #to 0 1
1358     return empty #to
1359   elseif not checkaleap #from #to 1 1 and not checkaleap #from #to -1 1
1360     return false
1361   elseif not empty #to
1362     return true
1363   elseif == file #to file #ep and == rank #from rank #ep and #ep
1364     capture #ep
1365     return true
1366   endif
1367   return false
1368 endsub
1369 sub pp from to
1370   if checkatwostep #from #to 0 -1 0 -1 or checkaleap #from #to 0 -1
1371     return empty #to
1372   elseif not checkaleap #from #to 1 -1 and not checkaleap #from #to -1 -1
1373     return false
1374   elseif not empty #to
1375     return true
1376   elseif == file #to file #ep and == rank #from rank #ep and #ep
1377     capture #ep
1378     return true
1379   endif
1380   return false
1381 endsub
1382 endlib