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

space b2 is P

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

11011 111101 111011 111101 111011 111101 111011 11101

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

space g7 is p

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

11011 111101 111011 111101 111011 111101 111011 11101

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

space c1 is c1

2 c1 c1-b2 27 61 59 61 59 61 59 29

11011 111101 111011 111101 111011 111101 111011 11101

5 one bits in var c1

11011 111101 110010 111101 111011 111101 111011 11101

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

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

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

firstr is a1, and lastr is h1

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

first 27 61 50 61 59 61 59 29

mv is b h8-b2, p is b, o is h8

space h8 is h1

3 h1 b h8-b2 27 61 50 61 59 61 59 29

11011 111101 110010 111101 111011 111101 111011 11101

4 one bits in var h1

11011 111101 110010 111101 111011 111101 111011 100

q end b h8-b2 27 61 50 61 59 61 59 4

bb end b h8-b2 27 61 50 61 59 61 59 4

bw end b h8-b2 27 57 50 57 59 57 59 4

firstr is a1, and lastr is g1

r b h8-b2 27 57 50 57 59 57 27 4

first 27 57 50 57 59 57 27 4

11011 111001 110010 111001 111011 111001 11011 100

q end b h8-b2 27 57 50 57 59 57 27 4

bb end b h8-b2 27 57 50 57 59 57 27 4

bw end b h8-b2 27 57 50 57 59 57 27 4

firstr is a1, and lastr is g1

r b h8-b2 27 57 50 57 59 57 27 4

first 27 57 50 57 59 57 27 4

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

space b1 is b1

4 b1 b1-b2 27 57 50 57 59 57 27 4

11011 111001 110010 111001 111011 111001 11011 100

4 one bits in var b1

11011 111000 110010 111001 111011 111001 11011 100

q end b1-b2 27 56 50 57 59 57 27 4

bb end b1-b2 27 56 50 57 59 57 27 4

bw end b1-b2 27 56 50 57 59 57 27 4

firstr is a1, and lastr is g1

r b1-b2 27 56 50 57 59 57 27 4

first 27 56 50 57 59 57 27 4

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

space d7 is p

5 p d7-d5 27 56 50 57 59 57 27 4

11011 111000 110010 111001 111011 111001 11011 100

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

space e2 is P

6 P e2-e3 27 56 50 57 59 57 27 4

11011 111000 110010 111001 111011 111001 11011 100

mv is b c8-f5, p is b, o is c8

space c8 is c1

7 c1 b c8-f5 27 56 50 57 59 57 27 4

11011 111000 110010 111001 111011 111001 11011 100

3 one bits in var c1

11011 111000 10 111001 111011 111001 11011 100

q end b c8-f5 27 56 2 57 59 57 27 4

bb end b c8-f5 25 56 2 57 57 57 25 4

bw end b c8-f5 25 56 2 57 57 57 25 4

firstr is a1, and lastr is g1

r b c8-f5 25 56 2 57 57 57 25 4

first 25 56 2 57 57 57 25 4

11001 111000 10 111001 111001 111001 11001 100

q end b c8-f5 25 56 2 57 57 57 25 4

bb end b c8-f5 25 56 2 57 57 57 25 4

bw end b c8-f5 25 56 2 57 57 57 25 4

firstr is a1, and lastr is g1

r b c8-f5 25 56 2 57 57 57 25 4

first 25 56 2 57 57 57 25 4

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

space h2 is P

8 P h2-h3 25 56 2 57 57 57 25 4

11001 111000 10 111001 111001 111001 11001 100

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

space g8 is g1

9 g1 n g8-f6 25 56 2 57 57 57 25 4

11001 111000 10 111001 111001 111001 11001 100

3 one bits in var g1

11001 111000 10 111001 111001 111001 1 100

q end n g8-f6 25 56 2 57 57 57 1 4

bb end n g8-f6 25 56 2 57 57 57 1 4

bw end n g8-f6 25 56 2 57 57 57 1 4

firstr is a1, and lastr is f1

r n g8-f6 25 56 2 57 57 25 1 4

first 25 56 2 57 57 25 1 4

11001 111000 10 111001 111001 11001 1 100

q end n g8-f6 25 56 2 57 57 25 1 4

bb end n g8-f6 25 56 2 57 57 25 1 4

bw end n g8-f6 25 56 2 57 57 25 1 4

firstr is a1, and lastr is f1

r n g8-f6 25 56 2 57 57 25 1 4

first 25 56 2 57 57 25 1 4

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

space d2 is P

10 P d2-d3 25 56 2 57 57 25 1 4

11001 111000 10 111001 111001 11001 1 100

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

space e7 is p

11 p e7-e5 25 56 2 57 57 25 1 4

11001 111000 10 111001 111001 11001 1 100

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

space f2 is P

12 P f2-f3 25 56 2 57 57 25 1 4

11001 111000 10 111001 111001 11001 1 100

mv is b f5-g6, p is b, o is f5

space f5 is c1

13 c1 b f5-g6 25 56 2 57 57 25 1 4

11001 111000 10 111001 111001 11001 1 100

1 one bits in var c1

11001 111000 10 111001 111001 11001 1 100

q end b f5-g6 25 56 2 57 57 25 1 4

bb end b f5-g6 25 56 2 57 57 25 1 4

bw end b f5-g6 25 56 2 57 57 25 1 4

firstr is a1, and lastr is f1

r b f5-g6 25 56 2 57 57 25 1 4

first 25 56 2 57 57 25 1 4

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

space e3 is P

14 P e3-e4 25 56 2 57 57 25 1 4

11001 111000 10 111001 111001 11001 1 100

mv is q d8-d7, p is q, o is d8

space d8 is d1

15 d1 q d8-d7 25 56 2 57 57 25 1 4

11001 111000 10 111001 111001 11001 1 100

4 one bits in var d1

11001 111000 10 10000 111001 11001 1 100

queen before q d8-d7 25 56 2 16 57 25 1 4

queen after q d8-d7 9 40 2 16 41 9 1 4

q end q d8-d7 9 40 2 16 41 9 1 4

bb end q d8-d7 9 40 2 16 41 9 1 4

bw end q d8-d7 9 40 2 16 41 9 1 4

firstr is a1, and lastr is f1

r q d8-d7 9 40 2 16 41 9 1 4

first 9 40 2 16 41 9 1 4

1001 101000 10 10000 101001 1001 1 100

q end q d8-d7 9 40 2 16 41 9 1 4

bb end q d8-d7 9 40 2 16 41 9 1 4

bw end q d8-d7 9 40 2 16 41 9 1 4

firstr is a1, and lastr is f1

r q d8-d7 9 40 2 16 41 9 1 4

first 9 40 2 16 41 9 1 4

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

space d1 is d1

16 d1 d1-d2 9 40 2 16 41 9 1 4

1001 101000 10 10000 101001 1001 1 100

1 one bits in var d1

1001 101000 10 10000 101001 1001 1 100

q end d1-d2 9 40 2 16 41 9 1 4

bb end d1-d2 9 40 2 16 41 9 1 4

bw end d1-d2 9 40 2 16 41 9 1 4

firstr is a1, and lastr is f1

r d1-d2 9 40 2 16 41 9 1 4

first 9 40 2 16 41 9 1 4

mv is h7-h6, p is #p, o is h7

space h7 is p

17 p h7-h6 9 40 2 16 41 9 1 4

1001 101000 10 10000 101001 1001 1 100

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

space a1 is a1

18 a1 a1-c1 9 40 2 16 41 9 1 4

1001 101000 10 10000 101001 1001 1 100

2 one bits in var a1

rook ride

Rook or Queen move

1000 101000 10 10000 101001 1001 1 100

q end a1-c1 8 40 2 16 41 9 1 4

bb end a1-c1 8 40 2 16 41 9 1 4

bw end a1-c1 8 40 2 16 41 9 1 4

firstr is a1, and lastr is f1

One Rook found

b1 40

r a1-c1 8 32 2 16 41 9 1 4

first 8 32 2 16 41 9 1 4

1000 100000 10 10000 101001 1001 1 100

q end a1-c1 8 32 2 16 9 9 1 4

bb end a1-c1 8 32 2 16 9 9 1 4

bw end a1-c1 8 32 2 16 9 9 1 4

firstr is a1, and lastr is f1

One Rook found

b1 32

r a1-c1 8 32 2 16 9 9 1 4

first 8 32 2 16 9 9 1 4

1000 100000 10 10000 1001 1001 1 100

b1

Array
(
    [0] => a1
)

q end a1-c1 8 32 2 16 9 9 1 4

bb end a1-c1 8 32 2 16 9 9 1 4

bw end a1-c1 8 32 2 16 9 9 1 4

firstr is a1, and lastr is f1

One Rook found

b1 32

r a1-c1 8 32 2 16 9 9 1 4

first 8 32 2 16 9 9 1 4

mv is r a8-d8, p is r, o is a8

space a8 is a1

19 a1 r a8-d8 8 32 2 16 9 9 1 4

1000 100000 10 10000 1001 1001 1 100

1 one bits in var a1

1000 100000 10 10000 1001 1001 1 100

b1

Array
(
    [0] => a1
)

q end r a8-d8 8 32 2 16 9 9 1 4

bb end r a8-d8 8 32 2 16 9 9 1 4

bw end r a8-d8 8 32 2 16 9 9 1 4

firstr is a1, and lastr is f1

One Rook found

b1 32

r r a8-d8 8 32 2 16 9 9 1 4

first 8 32 2 16 9 9 1 4

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

space c2 is P

20 P c2-c3 8 32 2 16 9 9 1 4

1000 100000 10 10000 1001 1001 1 100

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

space d5 is p

21 p d5-e4 8 32 2 16 9 9 1 4

1000 100000 10 10000 1001 1001 1 100

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

space f3 is P

22 P f3-e4 8 32 2 16 9 9 1 4

1000 100000 10 10000 1001 1001 1 100

mv is n f6-e4, p is n, o is f6

space f6 is g1

23 g1 n f6-e4 8 32 2 16 9 9 1 4

1000 100000 10 10000 1001 1001 1 100

1 one bits in var g1

1000 100000 10 10000 1001 1001 1 100

b1

Array
(
    [0] => a1
)

q end n f6-e4 8 32 2 16 9 9 1 4

bb end n f6-e4 8 32 2 16 9 9 1 4

bw end n f6-e4 8 32 2 16 9 9 1 4

firstr is a1, and lastr is f1

One Rook found

b1 32

r n f6-e4 8 32 2 16 9 9 1 4

first 8 32 2 16 9 9 1 4

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

space d2 is d1

24 d1 d2-e3 8 32 2 16 9 9 1 4

1000 100000 10 10000 1001 1001 1 100

1 one bits in var d1

1000 100000 10 10000 1001 1001 1 100

b1

Array
(
    [0] => a1
)

q end d2-e3 8 32 2 16 9 9 1 4

bb end d2-e3 8 32 2 16 9 9 1 4

bw end d2-e3 8 32 2 16 9 9 1 4

firstr is a1, and lastr is f1

One Rook found

b1 32

r d2-e3 8 32 2 16 9 9 1 4

first 8 32 2 16 9 9 1 4

mv is n e4-d6, p is n, o is e4

space e4 is g1

25 g1 n e4-d6 8 32 2 16 9 9 1 4

1000 100000 10 10000 1001 1001 1 100

1 one bits in var g1

1000 100000 10 10000 1001 1001 1 100

b1

Array
(
    [0] => a1
)

q end n e4-d6 8 32 2 16 9 9 1 4

bb end n e4-d6 8 32 2 16 9 9 1 4

bw end n e4-d6 8 32 2 16 9 9 1 4

firstr is a1, and lastr is f1

One Rook found

b1 32

r n e4-d6 8 32 2 16 9 9 1 4

first 8 32 2 16 9 9 1 4

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

space e3 is d1

26 d1 e3-a7 8 32 2 16 9 9 1 4

1000 100000 10 10000 1001 1001 1 100

1 one bits in var d1

1000 100000 10 10000 1001 1001 1 100

b1

Array
(
    [0] => a1
)

q end e3-a7 8 32 2 16 9 9 1 4

bb end e3-a7 8 32 2 16 9 9 1 4

bw end e3-a7 8 32 2 16 9 9 1 4

firstr is a1, and lastr is f1

One Rook found

b1 32

r e3-a7 8 32 2 16 9 9 1 4

first 8 32 2 16 9 9 1 4

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

space c7 is p

27 p c7-c6 8 32 2 16 9 9 1 4

1000 100000 10 10000 1001 1001 1 100

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