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 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 b2-b3, p is #p, o is b2

space b2 is P

2 P b2-b3 27 61 59 61 59 61 59 29

11011 111101 111011 111101 111011 111101 111011 11101

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

space g8 is g1

3 g1 g8-f6 27 61 59 61 59 61 59 29

11011 111101 111011 111101 111011 111101 111011 11101

5 one bits in var g1

11011 111101 111011 111101 111011 111101 1 11101

q end g8-f6 27 61 59 61 59 61 1 29

bb end g8-f6 27 61 59 61 59 61 1 29

bw end g8-f6 27 61 59 61 59 61 1 29

firstr is a1, and lastr is h1

r g8-f6 27 61 59 61 59 61 1 29

first 27 61 59 61 59 61 1 29

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

space e4 is P

4 P e4-e5 27 61 59 61 59 61 1 29

11011 111101 111011 111101 111011 111101 1 11101

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

space f6 is g1

5 g1 f6-h5 27 61 59 61 59 61 1 29

11011 111101 111011 111101 111011 111101 1 11101

1 one bits in var g1

11011 111101 111011 111101 111011 111101 1 11101

q end f6-h5 27 61 59 61 59 61 1 29

bb end f6-h5 27 61 59 61 59 61 1 29

bw end f6-h5 27 61 59 61 59 61 1 29

firstr is a1, and lastr is h1

r f6-h5 27 61 59 61 59 61 1 29

first 27 61 59 61 59 61 1 29

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

space f1 is f1

6 f1 f1-e2 27 61 59 61 59 61 1 29

11011 111101 111011 111101 111011 111101 1 11101

5 one bits in var f1

11011 111101 111011 111101 111011 110100 1 11101

q end f1-e2 27 61 59 61 59 52 1 29

bb end f1-e2 27 61 59 61 59 52 1 29

bw end f1-e2 27 61 59 61 59 52 1 29

firstr is a1, and lastr is h1

r f1-e2 27 61 59 61 59 52 1 29

first 27 61 59 61 59 52 1 29

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

space f8 is f1

7 f1 f8-g7 27 61 59 61 59 52 1 29

11011 111101 111011 111101 111011 110100 1 11101

3 one bits in var f1

11011 111101 111011 111101 111011 110100 1 11101

q end f8-g7 27 61 59 61 59 52 1 29

bb end f8-g7 27 61 59 61 59 52 1 29

bw end f8-g7 27 61 59 61 59 52 1 29

firstr is a1, and lastr is h1

r f8-g7 27 61 59 61 59 52 1 29

first 27 61 59 61 59 52 1 29

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

space e2 is f1

8 f1 e2-f3 27 61 59 61 59 52 1 29

11011 111101 111011 111101 111011 110100 1 11101

3 one bits in var f1

11011 111101 111011 111101 111011 110100 1 11101

q end e2-f3 27 61 59 61 59 52 1 29

bb end e2-f3 27 61 59 61 59 52 1 29

bw end e2-f3 27 61 59 61 59 52 1 29

firstr is a1, and lastr is h1

r e2-f3 27 61 59 61 59 52 1 29

first 27 61 59 61 59 52 1 29

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

space d7 is p

9 p d7-d6 27 61 59 61 59 52 1 29

11011 111101 111011 111101 111011 110100 1 11101

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

space c1 is c1

10 c1 c1-b2 27 61 59 61 59 52 1 29

11011 111101 111011 111101 111011 110100 1 11101

5 one bits in var c1

11011 111101 110010 111101 111011 110100 1 11101

q end c1-b2 27 61 50 61 59 52 1 29

bb end c1-b2 27 61 50 61 59 52 1 29

bw end c1-b2 27 61 50 61 59 52 1 29

firstr is a1, and lastr is h1

r c1-b2 27 61 50 61 59 52 1 29

first 27 61 50 61 59 52 1 29

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

space c7 is p

11 p c7-c5 27 61 50 61 59 52 1 29

11011 111101 110010 111101 111011 110100 1 11101

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

space e5 is P

12 P e5-d6 27 61 50 61 59 52 1 29

11011 111101 110010 111101 111011 110100 1 11101

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

space g7 is f1

13 f1 g7-b2 27 61 50 61 59 52 1 29

11011 111101 110010 111101 111011 110100 1 11101

3 one bits in var f1

11011 111101 110010 111101 111011 10100 1 11101

q end g7-b2 27 61 50 61 59 20 1 29

bb end g7-b2 27 61 50 61 59 20 1 29

bw end g7-b2 27 61 50 61 59 20 1 29

firstr is a1, and lastr is h1

r g7-b2 27 61 50 61 59 20 1 29

first 27 61 50 61 59 20 1 29

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

space a1 is a1

14 a1 a1-b2 27 61 50 61 59 20 1 29

11011 111101 110010 111101 111011 10100 1 11101

4 one bits in var a1

10010 111101 110010 111101 111011 10100 1 11101

q end a1-b2 18 61 50 61 59 20 1 29

bb end a1-b2 18 61 50 61 59 20 1 29

bw end a1-b2 18 61 50 61 59 20 1 29

firstr is b1, and lastr is h1

r a1-b2 18 29 50 61 59 20 1 29

first 18 29 50 61 59 20 1 29

10010 11101 110010 111101 111011 10100 1 11101

q end a1-b2 18 29 50 61 59 20 1 29

bb end a1-b2 18 29 50 61 59 20 1 29

bw end a1-b2 18 29 50 61 59 20 1 29

firstr is b1, and lastr is h1

r a1-b2 18 29 50 61 59 20 1 29

first 18 29 50 61 59 20 1 29

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

space f7 is p

15 p f7-f6 18 29 50 61 59 20 1 29

10010 11101 110010 111101 111011 10100 1 11101

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

space d6 is P

16 P d6-e7 18 29 50 61 59 20 1 29

10010 11101 110010 111101 111011 10100 1 11101

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

space e8 is e1

17 e1 e8-e7 18 29 50 61 59 20 1 29

10010 11101 110010 111101 111011 10100 1 11101

5 one bits in var e1

10010 11101 110010 111101 111000 10100 1 11101

q end e8-e7 18 29 50 61 56 20 1 29

bb end e8-e7 18 29 50 61 56 20 1 29

bw end e8-e7 18 29 50 61 56 20 1 29

firstr is b1, and lastr is h1

r e8-e7 18 29 50 61 56 20 1 29

first 18 29 50 61 56 20 1 29

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

space d1 is d1

18 d1 d1-c3 18 29 50 61 56 20 1 29

10010 11101 110010 111101 111000 10100 1 11101

5 one bits in var d1

10010 11101 110010 1 111000 10100 1 11101

q end d1-c3 18 29 50 1 56 20 1 29

bb end d1-c3 18 29 50 1 56 20 1 29

bw end d1-c3 18 29 50 1 56 20 1 29

firstr is b1, and lastr is h1

One Rook found

c1 50

r d1-c3 18 8 50 1 56 20 1 29

first 18 8 50 1 56 20 1 29

10010 1000 110010 1 111000 10100 1 11100

q end d1-c3 18 8 50 1 56 20 1 28

bb end d1-c3 18 8 50 1 56 20 1 28

bw end d1-c3 18 8 50 1 56 20 1 28

firstr is b1, and lastr is h1

One Rook found

c1 50

r d1-c3 18 8 50 1 56 20 1 28

first 18 8 50 1 56 20 1 28

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

space h5 is g1

19 g1 h5-f4 18 8 50 1 56 20 1 28

10010 1000 110010 1 111000 10100 1 11100

1 one bits in var g1

10010 1000 110010 1 111000 10100 1 11100

q end h5-f4 18 8 50 1 56 20 1 28

bb end h5-f4 18 8 50 1 56 20 1 28

bw end h5-f4 18 8 50 1 56 20 1 28

firstr is b1, and lastr is h1

One Rook found

c1 50

r h5-f4 18 8 50 1 56 20 1 28

first 18 8 50 1 56 20 1 28

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

space g2 is P

20 P g2-g3 18 8 50 1 56 20 1 28

10010 1000 110010 1 111000 10100 1 11100

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

space f4 is g1

21 g1 f4-e6 18 8 50 1 56 20 1 28

10010 1000 110010 1 111000 10100 1 11100

1 one bits in var g1

10010 1000 110010 1 111000 10100 1 11100

q end f4-e6 18 8 50 1 56 20 1 28

bb end f4-e6 18 8 50 1 56 20 1 28

bw end f4-e6 18 8 50 1 56 20 1 28

firstr is b1, and lastr is h1

One Rook found

c1 50

r f4-e6 18 8 50 1 56 20 1 28

first 18 8 50 1 56 20 1 28

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

space c3 is d1

22 d1 c3-d5 18 8 50 1 56 20 1 28

10010 1000 110010 1 111000 10100 1 11100

1 one bits in var d1

10010 1000 110010 1 111000 10100 1 11100

q end c3-d5 18 8 50 1 56 20 1 28

bb end c3-d5 18 8 50 1 56 20 1 28

bw end c3-d5 18 8 50 1 56 20 1 28

firstr is b1, and lastr is h1

One Rook found

c1 50

r c3-d5 18 8 50 1 56 20 1 28

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