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

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

space g2 is P

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

11011 111101 111011 111101 111011 111101 111011 11101

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

space f7 is p

1 p f7-f5 27 61 59 61 59 61 59 29

11011 111101 111011 111101 111011 111101 111011 11101

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

space b1 is b1

2 b1 b1-c3 27 61 59 61 59 61 59 29

11011 111101 111011 111101 111011 111101 111011 11101

5 one bits in var b1

11011 1 111011 111101 111011 111101 111011 11101

q end b1-c3 27 1 59 61 59 61 59 29

bb end b1-c3 27 1 59 61 59 61 59 29

bw end b1-c3 27 1 59 61 59 61 59 29

firstr is a1, and lastr is h1

r b1-c3 27 1 59 61 59 61 59 29

first 27 1 59 61 59 61 59 29

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

space b8 is b1

3 b1 b8-c6 27 1 59 61 59 61 59 29

11011 1 111011 111101 111011 111101 111011 11101

1 one bits in var b1

11011 1 111011 111101 111011 111101 111011 11101

q end b8-c6 27 1 59 61 59 61 59 29

bb end b8-c6 27 1 59 61 59 61 59 29

bw end b8-c6 27 1 59 61 59 61 59 29

firstr is a1, and lastr is h1

r b8-c6 27 1 59 61 59 61 59 29

first 27 1 59 61 59 61 59 29

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

space d1 is d1

4 d1 d1-e3 27 1 59 61 59 61 59 29

11011 1 111011 111101 111011 111101 111011 11101

5 one bits in var d1

11011 1 111011 1 111011 111101 111011 11101

q end d1-e3 27 1 59 1 59 61 59 29

bb end d1-e3 27 1 59 1 59 61 59 29

bw end d1-e3 27 1 59 1 59 61 59 29

firstr is a1, and lastr is h1

r d1-e3 27 1 59 1 59 61 59 29

first 27 1 59 1 59 61 59 29

11010 1 111010 1 111010 111100 111010 11100

q end d1-e3 26 1 58 1 58 60 58 28

bb end d1-e3 26 1 58 1 58 60 58 28

bw end d1-e3 26 1 58 1 58 60 58 28

firstr is a1, and lastr is h1

r d1-e3 26 1 58 1 58 60 58 28

first 26 1 58 1 58 60 58 28

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

space g7 is p

5 p g7-g5 26 1 58 1 58 60 58 28

11010 1 111010 1 111010 111100 111010 11100

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

space f2 is P

6 P f2-f4 26 1 58 1 58 60 58 28

11010 1 111010 1 111010 111100 111010 11100

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

space g5 is p

7 p g5-g4 26 1 58 1 58 60 58 28

11010 1 111010 1 111010 111100 111010 11100

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

space a2 is P

8 P a2-a4 26 1 58 1 58 60 58 28

11010 1 111010 1 111010 111100 111010 11100

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

space e7 is p

9 p e7-e6 26 1 58 1 58 60 58 28

11010 1 111010 1 111010 111100 111010 11100

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

space a1 is a1

10 a1 a1-b1 26 1 58 1 58 60 58 28

11010 1 111010 1 111010 111100 111010 11100

3 one bits in var a1

11000 1 111010 1 111010 111100 111010 11100

q end a1-b1 24 1 58 1 58 60 58 28

bb end a1-b1 24 1 58 1 58 60 58 28

bw end a1-b1 24 1 58 1 58 60 58 28

firstr is a1, and lastr is h1

r a1-b1 24 1 58 1 58 60 58 28

first 24 1 58 1 58 60 58 28

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

space d7 is p

11 p d7-d5 24 1 58 1 58 60 58 28

11000 1 111010 1 111010 111100 111010 11100

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

space c3 is b1

12 b1 c3-a2 24 1 58 1 58 60 58 28

11000 1 111010 1 111010 111100 111010 11100

1 one bits in var b1

11000 1 111010 1 111010 111100 111010 11100

q end c3-a2 24 1 58 1 58 60 58 28

bb end c3-a2 24 1 58 1 58 60 58 28

bw end c3-a2 24 1 58 1 58 60 58 28

firstr is a1, and lastr is h1

r c3-a2 24 1 58 1 58 60 58 28

first 24 1 58 1 58 60 58 28

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

space b7 is p

13 p b7-b6 24 1 58 1 58 60 58 28

11000 1 111010 1 111010 111100 111010 11100

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

space c2 is P

14 P c2-c4 24 1 58 1 58 60 58 28

11000 1 111010 1 111010 111100 111010 11100

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

space h7 is p

15 p h7-h5 24 1 58 1 58 60 58 28

11000 1 111010 1 111010 111100 111010 11100

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

space c4 is P

16 P c4-d5 24 1 58 1 58 60 58 28

11000 1 111010 1 111010 111100 111010 11100

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

space e6 is p

17 p e6-d5 24 1 58 1 58 60 58 28

11000 1 111010 1 111010 111100 111010 11100

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

space e3 is d1

18 d1 e3-d5 24 1 58 1 58 60 58 28

11000 1 111010 1 111010 111100 111010 11100

1 one bits in var d1

11000 1 111010 1 111010 111100 111010 11100

q end e3-d5 24 1 58 1 58 60 58 28

bb end e3-d5 24 1 58 1 58 60 58 28

bw end e3-d5 24 1 58 1 58 60 58 28

firstr is a1, and lastr is h1

r e3-d5 24 1 58 1 58 60 58 28

first 24 1 58 1 58 60 58 28

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

space c8 is c1

19 c1 c8-d7 24 1 58 1 58 60 58 28

11000 1 111010 1 111010 111100 111010 11100

4 one bits in var c1

11000 1 110010 1 111010 111100 111010 11100

q end c8-d7 24 1 50 1 58 60 58 28

bb end c8-d7 24 1 50 1 58 60 58 28

bw end c8-d7 24 1 50 1 58 60 58 28

firstr is a1, and lastr is h1

r c8-d7 24 1 50 1 58 60 58 28

first 24 1 50 1 58 60 58 28

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

space a2 is b1

20 b1 a2-c3 24 1 50 1 58 60 58 28

11000 1 110010 1 111010 111100 111010 11100

1 one bits in var b1

11000 1 110010 1 111010 111100 111010 11100

q end a2-c3 24 1 50 1 58 60 58 28

bb end a2-c3 24 1 50 1 58 60 58 28

bw end a2-c3 24 1 50 1 58 60 58 28

firstr is a1, and lastr is h1

r a2-c3 24 1 50 1 58 60 58 28

first 24 1 50 1 58 60 58 28

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

space d8 is d1

21 d1 d8-b7 24 1 50 1 58 60 58 28

11000 1 110010 1 111010 111100 111010 11100

1 one bits in var d1

11000 1 110010 1 111010 111100 111010 11100

q end d8-b7 24 1 50 1 58 60 58 28

bb end d8-b7 24 1 50 1 58 60 58 28

bw end d8-b7 24 1 50 1 58 60 58 28

firstr is a1, and lastr is h1

r d8-b7 24 1 50 1 58 60 58 28

first 24 1 50 1 58 60 58 28

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

space b2 is P

22 P b2-b4 24 1 50 1 58 60 58 28

11000 1 110010 1 111010 111100 111010 11100

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

space h8 is h1

23 h1 h8-c3 24 1 50 1 58 60 58 28

11000 1 110010 1 111010 111100 111010 11100

3 one bits in var h1

11000 1 110010 1 111010 111100 111010 10100

q end h8-c3 24 1 50 1 58 60 58 20

bb end h8-c3 24 1 50 1 58 60 58 20

bw end h8-c3 24 1 50 1 58 60 58 20

firstr is a1, and lastr is g1

r h8-c3 24 1 50 1 58 60 26 20

first 24 1 50 1 58 60 26 20

11000 1 110010 1 111010 111100 11010 10100

q end h8-c3 24 1 50 1 58 60 26 20

bb end h8-c3 24 1 50 1 58 60 26 20

bw end h8-c3 24 1 50 1 58 60 26 20

firstr is a1, and lastr is g1

r h8-c3 24 1 50 1 58 60 26 20

first 24 1 50 1 58 60 26 20

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

space d5 is d1

24 d1 d5-c3 24 1 50 1 58 60 26 20

11000 1 110010 1 111010 111100 11010 10100

1 one bits in var d1

11000 1 110010 1 111010 111100 11010 10100

q end d5-c3 24 1 50 1 58 60 26 20

bb end d5-c3 24 1 50 1 58 60 26 20

bw end d5-c3 24 1 50 1 58 60 26 20

firstr is a1, and lastr is g1

r d5-c3 24 1 50 1 58 60 26 20

first 24 1 50 1 58 60 26 20

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

space e8 is e1

25 e1 e8-c8 24 1 50 1 58 60 26 20

11000 1 110010 1 111010 111100 11010 10100

4 one bits in var e1

rook ride

King castling by moving 2+ spaces

Assuming not actually a castling move.

11000 1 110010 1 11000 111100 11010 10100

q end e8-c8 24 1 50 1 24 60 26 20

bb end e8-c8 24 1 50 1 24 60 26 20

bw end e8-c8 24 1 50 1 24 60 26 20

firstr is a1, and lastr is g1

r e8-c8 24 1 50 1 24 60 26 20

first 24 1 50 1 24 60 26 20

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

space d2 is P

26 P d2-d3 24 1 50 1 24 60 26 20

11000 1 110010 1 11000 111100 11010 10100

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

space f8 is f1

27 f1 f8-e8 24 1 50 1 24 60 26 20

11000 1 110010 1 11000 111100 11010 10100

4 one bits in var f1

11000 1 110010 1 11000 111000 11010 10100

q end f8-e8 24 1 50 1 24 56 26 20

bb end f8-e8 24 1 50 1 24 56 26 20

bw end f8-e8 24 1 50 1 24 56 26 4

firstr is a1, and lastr is g1

r f8-e8 24 1 50 1 24 56 26 4

first 24 1 50 1 24 56 26 4

11000 1 110010 1 11000 111000 11010 100

q end f8-e8 24 1 50 1 24 56 26 4

bb end f8-e8 24 1 50 1 24 56 26 4

bw end f8-e8 24 1 50 1 24 56 26 4

firstr is a1, and lastr is g1

r f8-e8 24 1 50 1 24 56 26 4

first 24 1 50 1 24 56 26 4

mv is b4-b5, p is #p, o is b4

space b4 is P

28 P b4-b5 24 1 50 1 24 56 26 4

11000 1 110010 1 11000 111000 11010 100

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

space c6 is b1

29 b1 c6-d4 24 1 50 1 24 56 26 4

11000 1 110010 1 11000 111000 11010 100

1 one bits in var b1

11000 1 110010 1 11000 111000 11010 100

q end c6-d4 24 1 50 1 24 56 26 4

bb end c6-d4 24 1 50 1 24 56 26 4

bw end c6-d4 24 1 50 1 24 56 26 4

firstr is a1, and lastr is g1

r c6-d4 24 1 50 1 24 56 26 4

first 24 1 50 1 24 56 26 4

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

space h1 is h1

30 h1 h1-b7 24 1 50 1 24 56 26 4

11000 1 110010 1 11000 111000 11010 100

1 one bits in var h1

11000 1 110010 1 11000 111000 11010 100

q end h1-b7 24 1 50 1 24 56 26 4

bb end h1-b7 24 1 50 1 24 56 26 4

bw end h1-b7 24 1 50 1 24 56 26 4

firstr is a1, and lastr is g1

r h1-b7 24 1 50 1 24 56 26 4

first 24 1 50 1 24 56 26 4

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

space c8 is e1

31 e1 c8-b7 24 1 50 1 24 56 26 4

11000 1 110010 1 11000 111000 11010 100

2 one bits in var e1

11000 1 110010 1 10000 111000 11010 100

queen before c8-b7 24 1 50 1 16 56 26 4

queen after c8-b7 8 1 34 1 16 40 10 4

q end c8-b7 8 1 34 1 16 40 10 4

bb end c8-b7 8 1 34 1 16 40 10 4

bw end c8-b7 8 1 34 1 16 40 10 4

firstr is a1, and lastr is g1

One Rook found

b1 1

c1 34

r c8-b7 8 1 34 1 16 40 10 4

first 8 1 34 1 16 40 10 4

1000 1 100010 1 10000 101000 1010 100

q end c8-b7 8 1 34 1 16 40 10 4

bb end c8-b7 8 1 34 1 16 40 10 4

bw end c8-b7 8 1 34 1 16 40 10 4

firstr is a1, and lastr is g1

One Rook found

b1 1

c1 34

r c8-b7 8 1 34 1 16 40 10 4

first 8 1 34 1 16 40 10 4

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

space g1 is g1

32 g1 g1-d4 8 1 34 1 16 40 10 4

1000 1 100010 1 10000 101000 1010 100

2 one bits in var g1

1000 1 100010 1 10000 101000 10 100

q end g1-d4 8 1 34 1 16 40 2 4

bb end g1-d4 8 1 32 1 16 40 2 4

bw end g1-d4 8 1 32 1 16 40 2 4

first 8 1 32 1 16 8 2 4

1000 1 100000 1 10000 1000 10 100

c1

Array
(
    [0] => a1
    [1] => b1
)

q end g1-d4 8 1 32 1 16 8 2 4

bb end g1-d4 8 1 32 1 16 8 2 4

bw end g1-d4 8 1 32 1 16 8 2 4

first 8 1 32 1 16 8 2 4

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

space d7 is c1

33 c1 d7-d4 8 1 32 1 16 8 2 4

1000 1 100000 1 10000 1000 10 100

1 one bits in var c1

1000 1 100000 1 10000 1000 10 100

c1

Array
(
    [0] => a1
    [1] => b1
)

q end d7-d4 8 1 32 1 16 8 2 4

bb end d7-d4 8 1 32 1 16 8 2 4

bw end d7-d4 8 1 32 1 16 8 2 4

first 8 1 32 1 16 8 2 4

Continue because mv is empty

firstrank is RNKNQRBB

You may not move a k from d7 to d4

Use your browser's BACK button to go back to the previous page, then reload if necessary.

For general reference, here is the complete list of moves:

1. g2-g3 
1... f7-f5 
2. b1-c3 
2... b8-c6 
3. d1-e3 
3... g7-g5 
4. f2-f4 
4... g5-g4 
5. a2-a4 
5... e7-e6 
6. a1-b1 
6... d7-d5 
7. c3-a2 
7... b7-b6 
8. c2-c4 
8... h7-h5 
9. c4-d5 
9... e6-d5 
10. e3-d5 
10... c8-d7 
11. a2-c3 
11... d8-b7 
12. b2-b4 
12... h8-c3 
13. d5-c3 
13... e8-c8 
14. d2-d3 
14... f8-e8 
15. b4-b5 
15... c6-d4 
16. h1-b7 
16... c8-b7 
17. g1-d4 
17... d7-d4

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

Here is a code listing:

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