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 c2-c3, p is #p, o is c2

space c2 is P

0 P c2-c3 27 61 59 61 59 61 59 29

11011 111101 111011 111101 111011 111101 111011 11101

mv is n h8-g6, p is n, o is h8

space h8 is h1

1 h1 n h8-g6 27 61 59 61 59 61 59 29

11011 111101 111011 111101 111011 111101 111011 11101

4 one bits in var h1

11011 111101 111011 111101 111011 111101 111011 1

q end n h8-g6 27 61 59 61 59 61 59 1

bb end n h8-g6 27 61 59 61 59 61 59 1

bw end n h8-g6 27 61 59 61 59 61 59 1

firstr is a1, and lastr is g1

r n h8-g6 27 61 59 61 59 61 27 1

first 27 61 59 61 59 61 27 1

11011 111101 111011 111101 111011 111101 11011 1

q end n h8-g6 27 61 59 61 59 61 27 1

bb end n h8-g6 27 61 59 61 59 61 27 1

bw end n h8-g6 27 61 59 61 59 61 27 1

firstr is a1, and lastr is g1

r n h8-g6 27 61 59 61 59 61 27 1

first 27 61 59 61 59 61 27 1

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

space a1 is a1

2 a1 a1-b3 27 61 59 61 59 61 27 1

11011 111101 111011 111101 111011 111101 11011 1

4 one bits in var a1

1 111101 111011 111101 111011 111101 11011 1

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

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

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

firstr is b1, and lastr is g1

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

first 1 29 59 61 59 61 27 1

1 11100 111010 111100 111010 111100 11010 1

q end a1-b3 1 28 58 60 58 60 26 1

bb end a1-b3 1 28 58 60 58 60 26 1

bw end a1-b3 1 28 58 60 58 60 26 1

firstr is b1, and lastr is g1

r a1-b3 1 28 58 60 58 60 26 1

first 1 28 58 60 58 60 26 1

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

space b7 is p

3 p b7-b6 1 28 58 60 58 60 26 1

1 11100 111010 111100 111010 111100 11010 1

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

space f2 is P

4 P f2-f3 1 28 58 60 58 60 26 1

1 11100 111010 111100 111010 111100 11010 1

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

space c7 is p

5 p c7-c5 1 28 58 60 58 60 26 1

1 11100 111010 111100 111010 111100 11010 1

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

space e1 is e1

6 e1 e1-g3 1 28 58 60 58 60 26 1

1 11100 111010 111100 111010 111100 11010 1

4 one bits in var e1

1 11100 111010 111100 10010 111100 11010 1

q end e1-g3 1 28 58 60 18 60 26 1

bb end e1-g3 1 28 58 60 18 60 26 1

bw end e1-g3 1 28 58 60 18 60 26 1

firstr is b1, and lastr is g1

r e1-g3 1 28 58 60 18 60 26 1

first 1 28 58 60 18 60 26 1

mv is n a8-c7, p is n, o is a8

space a8 is a1

7 a1 n a8-c7 1 28 58 60 18 60 26 1

1 11100 111010 111100 10010 111100 11010 1

1 one bits in var a1

1 11100 111010 111100 10010 111100 11010 1

q end n a8-c7 1 28 58 60 18 60 26 1

bb end n a8-c7 1 28 58 60 18 60 26 1

bw end n a8-c7 1 28 58 60 18 60 26 1

firstr is b1, and lastr is g1

r n a8-c7 1 28 58 60 18 60 26 1

first 1 28 58 60 18 60 26 1

mv is P e2-e3, p is P, o is e2

space e2 is P

8 P P e2-e3 1 28 58 60 18 60 26 1

1 11100 111010 111100 10010 111100 11010 1

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

space d7 is p

9 p p d7-d6 1 28 58 60 18 60 26 1

1 11100 111010 111100 10010 111100 11010 1

mv is P h2-h4, p is P, o is h2

space h2 is P

10 P P h2-h4 1 28 58 60 18 60 26 1

1 11100 111010 111100 10010 111100 11010 1

mv is p h7-h5, p is p, o is h7

space h7 is p

11 p p h7-h5 1 28 58 60 18 60 26 1

1 11100 111010 111100 10010 111100 11010 1

mv is P f3-f4, p is P, o is f3

space f3 is P

12 P P f3-f4 1 28 58 60 18 60 26 1

1 11100 111010 111100 10010 111100 11010 1

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

space f7 is p

13 p f7-f5 1 28 58 60 18 60 26 1

1 11100 111010 111100 10010 111100 11010 1

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

space e3 is P

14 P e3-e4 1 28 58 60 18 60 26 1

1 11100 111010 111100 10010 111100 11010 1

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

space e7 is p

15 p e7-e6 1 28 58 60 18 60 26 1

1 11100 111010 111100 10010 111100 11010 1

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

space e4 is P

16 P e4-f5 1 28 58 60 18 60 26 1

1 11100 111010 111100 10010 111100 11010 1

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

space e6 is p

17 p e6-f5 1 28 58 60 18 60 26 1

1 11100 111010 111100 10010 111100 11010 1

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

space f1 is f1

18 f1 f1-d3 1 28 58 60 18 60 26 1

1 11100 111010 111100 10010 111100 11010 1

4 one bits in var f1

1 11100 111010 111100 10010 10100 11010 1

q end f1-d3 1 28 58 60 18 20 26 1

bb end f1-d3 1 28 58 60 18 20 26 1

bw end f1-d3 1 28 58 60 18 20 26 1

firstr is b1, and lastr is g1

r f1-d3 1 28 58 60 18 20 26 1

first 1 28 58 60 18 20 26 1

mv is n c7-e6, p is n, o is c7

space c7 is a1

19 a1 n c7-e6 1 28 58 60 18 20 26 1

1 11100 111010 111100 10010 10100 11010 1

1 one bits in var a1

1 11100 111010 111100 10010 10100 11010 1

q end n c7-e6 1 28 58 60 18 20 26 1

bb end n c7-e6 1 28 58 60 18 20 26 1

bw end n c7-e6 1 28 58 60 18 20 26 1

firstr is b1, and lastr is g1

r n c7-e6 1 28 58 60 18 20 26 1

first 1 28 58 60 18 20 26 1

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

space g1 is g1

20 g1 g1-f1 1 28 58 60 18 20 26 1

1 11100 111010 111100 10010 10100 11010 1

3 one bits in var g1

1 11100 111010 111100 10010 10100 11000 1

q end g1-f1 1 28 58 60 18 20 24 1

bb end g1-f1 1 28 58 60 18 20 24 1

bw end g1-f1 1 28 58 60 18 20 24 1

firstr is b1, and lastr is g1

r g1-f1 1 28 58 60 18 20 24 1

first 1 28 58 60 18 20 24 1

mv is q f8-e7, p is q, o is f8

space f8 is f1

21 f1 q f8-e7 1 28 58 60 18 20 24 1

1 11100 111010 111100 10010 10100 11000 1

2 one bits in var f1

1 11100 111010 111100 10010 10000 11000 1

queen before q f8-e7 1 28 58 60 18 16 24 1

queen after q f8-e7 1 12 42 44 2 16 8 1

q end q f8-e7 1 12 42 44 2 16 8 1

bb end q f8-e7 1 12 40 44 2 16 8 1

bw end q f8-e7 1 12 40 44 2 16 8 1

firstr is b1, and lastr is g1

One Rook found

h1 1

r q f8-e7 1 12 40 36 2 16 8 1

first 1 12 40 36 2 16 8 1

1 1100 101000 100100 10 10000 1000 1

q end q f8-e7 1 12 40 36 2 16 8 1

bb end q f8-e7 1 12 40 36 2 16 8 1

bw end q f8-e7 1 12 40 36 2 16 8 1

firstr is b1, and lastr is g1

One Rook found

h1 1

r q f8-e7 1 12 40 36 2 16 8 1

first 1 12 40 36 2 16 8 1

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

space d3 is f1

22 f1 d3-e3 1 12 40 36 2 16 8 1

1 1100 101000 100100 10 10000 1000 1

1 one bits in var f1

1 1100 101000 100100 10 10000 1000 1

q end d3-e3 1 12 40 36 2 16 8 1

bb end d3-e3 1 12 40 36 2 16 8 1

bw end d3-e3 1 12 40 36 2 16 8 1

firstr is b1, and lastr is g1

One Rook found

h1 1

r d3-e3 1 12 40 36 2 16 8 1

first 1 12 40 36 2 16 8 1

mv is q e7-f6, p is q, o is e7

space e7 is f1

23 f1 q e7-f6 1 12 40 36 2 16 8 1

1 1100 101000 100100 10 10000 1000 1

1 one bits in var f1

1 1100 101000 100100 10 10000 1000 1

q end q e7-f6 1 12 40 36 2 16 8 1

bb end q e7-f6 1 12 40 36 2 16 8 1

bw end q e7-f6 1 12 40 36 2 16 8 1

firstr is b1, and lastr is g1

One Rook found

h1 1

r q e7-f6 1 12 40 36 2 16 8 1

first 1 12 40 36 2 16 8 1

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

space a2 is P

24 P a2-a3 1 12 40 36 2 16 8 1

1 1100 101000 100100 10 10000 1000 1

Continue because mv is empty

This game may have been too short to properly calculate the original position, and the calculated pattern of N???BQRN is inconsistent with randomly generated value of BRKNRBNQ. 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. c2-c3 
1... n h8-g6 
2. a1-b3 
2... b7-b6 // I don�t know what�s good here.
3. f2-f3 
3... c7-c5 
4. e1-g3 
4... n a8-c7 
5. P e2-e3 
5... p d7-d6 
6. P h2-h4 
6... p h7-h5 // � am feeling sick with this position.
7. P f3-f4 
7... f7-f5 
8. e3-e4 
8... e7-e6 
9. e4-f5 
9... e6-f5 
10. f1-d3 
10... n c7-e6 // Good move
11. g1-f1 
11... q f8-e7 
12. d3-e3 
12... q e7-f6 
13. a2-a3

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