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 e2-e4, p is #p, o is e2

space e2 is P

0 P e2-e4 27 61 59 61 59 61 59 29

11011 111101 111011 111101 111011 111101 111011 11101

mv is e7-e5, p is #p, o is e7

space e7 is p

1 p e7-e5 27 61 59 61 59 61 59 29

11011 111101 111011 111101 111011 111101 111011 11101

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

space f1 is f1

2 f1 f1-c4 27 61 59 61 59 61 59 29

11011 111101 111011 111101 111011 111101 111011 11101

5 one bits in var f1

11011 111101 111011 111101 111011 10100 111011 11101

q end f1-c4 27 61 59 61 59 20 59 29

bb end f1-c4 27 61 59 61 59 20 59 29

bw end f1-c4 27 61 59 61 59 20 59 29

firstr is a1, and lastr is h1

r f1-c4 27 61 59 61 59 20 59 29

first 27 61 59 61 59 20 59 29

mv is e8-d6, p is #p, o is e8

space e8 is e1

3 e1 e8-d6 27 61 59 61 59 20 59 29

11011 111101 111011 111101 111011 10100 111011 11101

5 one bits in var e1

11011 111101 111011 111101 1 10100 111011 11101

q end e8-d6 27 61 59 61 1 20 59 29

bb end e8-d6 27 61 59 61 1 20 59 29

bw end e8-d6 27 61 59 61 1 20 59 29

firstr is a1, and lastr is h1

r e8-d6 27 61 59 61 1 20 59 29

first 27 61 59 61 1 20 59 29

mv is b1-a3, p is #p, o is b1

space b1 is b1

4 b1 b1-a3 27 61 59 61 1 20 59 29

11011 111101 111011 111101 1 10100 111011 11101

5 one bits in var b1

11011 1 111011 111101 1 10100 111011 11101

q end b1-a3 27 1 59 61 1 20 59 29

bb end b1-a3 27 1 59 61 1 20 59 29

bw end b1-a3 27 1 59 61 1 20 59 29

firstr is a1, and lastr is h1

r b1-a3 27 1 59 61 1 20 59 29

first 27 1 59 61 1 20 59 29

11010 1 111010 111100 1 10100 111010 11100

q end b1-a3 26 1 58 60 1 20 58 28

bb end b1-a3 26 1 58 60 1 20 58 28

bw end b1-a3 26 1 58 60 1 20 58 28

firstr is a1, and lastr is h1

r b1-a3 26 1 58 60 1 20 58 28

first 26 1 58 60 1 20 58 28

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

space d6 is e1

5 e1 d6-c4 26 1 58 60 1 20 58 28

11010 1 111010 111100 1 10100 111010 11100

1 one bits in var e1

11010 1 111010 111100 1 10100 111010 11100

q end d6-c4 26 1 58 60 1 20 58 28

bb end d6-c4 26 1 58 60 1 20 58 28

bw end d6-c4 26 1 58 60 1 20 58 28

firstr is a1, and lastr is h1

r d6-c4 26 1 58 60 1 20 58 28

first 26 1 58 60 1 20 58 28

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

space a3 is b1

6 b1 a3-c4 26 1 58 60 1 20 58 28

11010 1 111010 111100 1 10100 111010 11100

1 one bits in var b1

11010 1 111010 111100 1 10100 111010 11100

q end a3-c4 26 1 58 60 1 20 58 28

bb end a3-c4 26 1 58 60 1 20 58 28

bw end a3-c4 26 1 58 60 1 20 58 28

firstr is a1, and lastr is h1

r a3-c4 26 1 58 60 1 20 58 28

first 26 1 58 60 1 20 58 28

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

space b8 is b1

7 b1 b8-c6 26 1 58 60 1 20 58 28

11010 1 111010 111100 1 10100 111010 11100

1 one bits in var b1

11010 1 111010 111100 1 10100 111010 11100

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

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

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

firstr is a1, and lastr is h1

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

first 26 1 58 60 1 20 58 28

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

space c2 is P

8 P c2-c3 26 1 58 60 1 20 58 28

11010 1 111010 111100 1 10100 111010 11100

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

space f8 is f1

9 f1 f8-c5 26 1 58 60 1 20 58 28

11010 1 111010 111100 1 10100 111010 11100

2 one bits in var f1

11010 1 111010 111100 1 10100 111010 11100

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

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

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

firstr is a1, and lastr is h1

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

first 26 1 58 60 1 20 58 28

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

space h1 is h1

10 h1 h1-f1 26 1 58 60 1 20 58 28

11010 1 111010 111100 1 10100 111010 11100

3 one bits in var h1

rook hopping king to castle

11010 1 111010 111100 1 10100 111010 11100

q end h1-f1 26 1 58 60 1 20 58 28

bb end h1-f1 26 1 58 60 1 20 58 28

bw end h1-f1 26 1 58 60 1 20 58 28

firstr is a1, and lastr is h1

r h1-f1 26 1 58 60 1 20 58 28

first 26 1 58 60 1 20 58 28

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

space h8 is h1

11 h1 h8-f8 26 1 58 60 1 20 58 28

11010 1 111010 111100 1 10100 111010 11100

3 one bits in var h1

rook hopping king to castle

11010 1 111010 111100 1 10100 111010 11100

q end h8-f8 26 1 58 60 1 20 58 28

bb end h8-f8 26 1 58 60 1 20 58 28

bw end h8-f8 26 1 58 60 1 20 58 28

firstr is a1, and lastr is h1

r h8-f8 26 1 58 60 1 20 58 28

first 26 1 58 60 1 20 58 28

mv is e1-f3, p is #p, o is e1

space e1 is e1

12 e1 e1-f3 26 1 58 60 1 20 58 28

11010 1 111010 111100 1 10100 111010 11100

1 one bits in var e1

11010 1 111010 111100 1 10100 111010 11100

q end e1-f3 26 1 58 60 1 20 58 28

bb end e1-f3 26 1 58 60 1 20 58 28

bw end e1-f3 26 1 58 60 1 20 58 28

firstr is a1, and lastr is h1

r e1-f3 26 1 58 60 1 20 58 28

first 26 1 58 60 1 20 58 28

mv is d7-d6, p is #p, o is d7

space d7 is p

13 p d7-d6 26 1 58 60 1 20 58 28

11010 1 111010 111100 1 10100 111010 11100

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

space d2 is P

14 P d2-d3 26 1 58 60 1 20 58 28

11010 1 111010 111100 1 10100 111010 11100

mv is c8-g4, p is #p, o is c8

space c8 is c1

15 c1 c8-g4 26 1 58 60 1 20 58 28

11010 1 111010 111100 1 10100 111010 11100

4 one bits in var c1

11010 1 10010 111100 1 10100 111010 11100

q end c8-g4 26 1 18 60 1 20 58 28

bb end c8-g4 26 1 18 60 1 20 58 28

bw end c8-g4 26 1 18 60 1 20 58 28

firstr is a1, and lastr is h1

r c8-g4 26 1 18 60 1 20 58 28

first 26 1 18 60 1 20 58 28

mv is h2-h3, p is #p, o is h2

space h2 is P

16 P h2-h3 26 1 18 60 1 20 58 28

11010 1 10010 111100 1 10100 111010 11100

mv is g4-h5, p is #p, o is g4

space g4 is c1

17 c1 g4-h5 26 1 18 60 1 20 58 28

11010 1 10010 111100 1 10100 111010 11100

2 one bits in var c1

11010 1 10010 111100 1 10100 111010 11100

q end g4-h5 26 1 18 60 1 20 58 28

bb end g4-h5 26 1 18 60 1 20 58 28

bw end g4-h5 26 1 18 60 1 20 58 28

firstr is a1, and lastr is h1

r g4-h5 26 1 18 60 1 20 58 28

first 26 1 18 60 1 20 58 28

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

space g2 is P

18 P g2-g4 26 1 18 60 1 20 58 28

11010 1 10010 111100 1 10100 111010 11100

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

space h5 is c1

19 c1 h5-g6 26 1 18 60 1 20 58 28

11010 1 10010 111100 1 10100 111010 11100

2 one bits in var c1

11010 1 10010 111100 1 10100 111010 11100

q end h5-g6 26 1 18 60 1 20 58 28

bb end h5-g6 26 1 18 60 1 20 58 28

bw end h5-g6 26 1 18 60 1 20 58 28

firstr is a1, and lastr is h1

r h5-g6 26 1 18 60 1 20 58 28

first 26 1 18 60 1 20 58 28

mv is c1-e3, p is #p, o is c1

space c1 is c1

20 c1 c1-e3 26 1 18 60 1 20 58 28

11010 1 10010 111100 1 10100 111010 11100

2 one bits in var c1

11010 1 10010 111100 1 10100 111010 11100

q end c1-e3 26 1 18 60 1 20 58 28

bb end c1-e3 26 1 18 60 1 20 58 28

bw end c1-e3 26 1 18 60 1 20 58 28

firstr is a1, and lastr is h1

r c1-e3 26 1 18 60 1 20 58 28

first 26 1 18 60 1 20 58 28

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

space c5 is f1

21 f1 c5-e3 26 1 18 60 1 20 58 28

11010 1 10010 111100 1 10100 111010 11100

2 one bits in var f1

11010 1 10010 111100 1 10100 111010 11100

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

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

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

firstr is a1, and lastr is h1

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

first 26 1 18 60 1 20 58 28

Continue because mv is empty

This game may have been too short to properly calculate the original position, and the calculated pattern of is inconsistent with randomly generated value of QNRNKRBB. 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. e2-e4 
1... e7-e5 
2. f1-c4 
2... e8-d6 
3. b1-a3 
3... d6-c4 
4. a3-c4 
4... b8-c6 
5. c2-c3 
5... f8-c5 
6. h1-f1 
6... h8-f8 
7. e1-f3 
7... d7-d6 
8. d2-d3 
8... c8-g4 
9. h2-h3 
9... g4-h5 
10. g2-g4 
10... h5-g6 
11. c1-e3 
11... c5-e3

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