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

space b2 is P

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

11011 111101 111011 111101 111011 111101 111011 11101

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

space e7 is p

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

11011 111101 111011 111101 111011 111101 111011 11101

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

space c2 is P

2 P c2-c4 27 61 59 61 59 61 59 29

11011 111101 111011 111101 111011 111101 111011 11101

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

space d7 is p

3 p d7-d6 27 61 59 61 59 61 59 29

11011 111101 111011 111101 111011 111101 111011 11101

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

space d1 is d1

4 d1 d1-b3 27 61 59 61 59 61 59 29

11011 111101 111011 111101 111011 111101 111011 11101

5 one bits in var d1

11011 111101 111011 10100 111011 111101 111011 11101

q end d1-b3 27 61 59 20 59 61 59 29

bb end d1-b3 27 61 59 20 59 61 59 29

bw end d1-b3 27 61 59 20 59 61 59 29

firstr is a1, and lastr is h1

r d1-b3 27 61 59 20 59 61 59 29

first 27 61 59 20 59 61 59 29

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

space b8 is b1

5 b1 b8-d7 27 61 59 20 59 61 59 29

11011 111101 111011 10100 111011 111101 111011 11101

5 one bits in var b1

11011 1 111011 10100 111011 111101 111011 11101

q end b8-d7 27 1 59 20 59 61 59 29

bb end b8-d7 27 1 59 20 59 61 59 29

bw end b8-d7 27 1 59 20 59 61 59 29

firstr is a1, and lastr is h1

r b8-d7 27 1 59 20 59 61 59 29

first 27 1 59 20 59 61 59 29

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

space d2 is P

6 P d2-d3 27 1 59 20 59 61 59 29

11011 1 111011 10100 111011 111101 111011 11101

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

space d8 is d1

7 d1 d8-f6 27 1 59 20 59 61 59 29

11011 1 111011 10100 111011 111101 111011 11101

2 one bits in var d1

11011 1 111011 10100 111011 111101 111011 11101

q end d8-f6 27 1 59 20 59 61 59 29

bb end d8-f6 27 1 59 20 59 61 59 29

bw end d8-f6 27 1 59 20 59 61 59 29

firstr is a1, and lastr is h1

r d8-f6 27 1 59 20 59 61 59 29

first 27 1 59 20 59 61 59 29

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

space b1 is b1

8 b1 b1-c3 27 1 59 20 59 61 59 29

11011 1 111011 10100 111011 111101 111011 11101

1 one bits in var b1

11011 1 111011 10100 111011 111101 111011 11101

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

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

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

firstr is a1, and lastr is h1

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

first 27 1 59 20 59 61 59 29

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

space f8 is f1

9 f1 f8-g6 27 1 59 20 59 61 59 29

11011 1 111011 10100 111011 111101 111011 11101

5 one bits in var f1

11011 1 111011 10100 111011 1 111011 11101

q end f8-g6 27 1 59 20 59 1 59 29

bb end f8-g6 27 1 59 20 59 1 59 29

bw end f8-g6 27 1 59 20 59 1 59 29

firstr is a1, and lastr is h1

r f8-g6 27 1 59 20 59 1 59 29

first 27 1 59 20 59 1 59 29

11010 1 111010 10100 111010 1 111010 11100

q end f8-g6 26 1 58 20 58 1 58 28

bb end f8-g6 26 1 58 20 58 1 58 28

bw end f8-g6 26 1 58 20 58 1 58 28

firstr is a1, and lastr is h1

r f8-g6 26 1 58 20 58 1 58 28

first 26 1 58 20 58 1 58 28

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

space f1 is f1

10 f1 f1-g3 26 1 58 20 58 1 58 28

11010 1 111010 10100 111010 1 111010 11100

1 one bits in var f1

11010 1 111010 10100 111010 1 111010 11100

q end f1-g3 26 1 58 20 58 1 58 28

bb end f1-g3 26 1 58 20 58 1 58 28

bw end f1-g3 26 1 58 20 58 1 58 28

firstr is a1, and lastr is h1

r f1-g3 26 1 58 20 58 1 58 28

first 26 1 58 20 58 1 58 28

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

space c7 is p

11 p c7-c5 26 1 58 20 58 1 58 28

11010 1 111010 10100 111010 1 111010 11100

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

space c3 is b1

12 b1 c3-b5 26 1 58 20 58 1 58 28

11010 1 111010 10100 111010 1 111010 11100

1 one bits in var b1

11010 1 111010 10100 111010 1 111010 11100

q end c3-b5 26 1 58 20 58 1 58 28

bb end c3-b5 26 1 58 20 58 1 58 28

bw end c3-b5 26 1 58 20 58 1 58 28

firstr is a1, and lastr is h1

r c3-b5 26 1 58 20 58 1 58 28

first 26 1 58 20 58 1 58 28

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

space e8 is e1

13 e1 e8-e7 26 1 58 20 58 1 58 28

11010 1 111010 10100 111010 1 111010 11100

4 one bits in var e1

11010 1 111010 10100 111000 1 111010 11100

q end e8-e7 26 1 58 20 56 1 58 28

bb end e8-e7 26 1 58 20 56 1 58 28

bw end e8-e7 26 1 58 20 56 1 58 28

firstr is a1, and lastr is h1

r e8-e7 26 1 58 20 56 1 58 28

first 26 1 58 20 56 1 58 28

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

space b5 is b1

14 b1 b5-a7 26 1 58 20 56 1 58 28

11010 1 111010 10100 111000 1 111010 11100

1 one bits in var b1

11010 1 111010 10100 111000 1 111010 11100

q end b5-a7 26 1 58 20 56 1 58 28

bb end b5-a7 26 1 58 20 56 1 58 28

bw end b5-a7 26 1 58 20 56 1 58 28

firstr is a1, and lastr is h1

r b5-a7 26 1 58 20 56 1 58 28

first 26 1 58 20 56 1 58 28

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

space c8 is c1

15 c1 c8-e8 26 1 58 20 56 1 58 28

11010 1 111010 10100 111000 1 111010 11100

4 one bits in var c1

rook ride

Rook or Queen move

11010 1 11000 10100 111000 1 111010 11100

q end c8-e8 26 1 24 20 56 1 58 28

bb end c8-e8 26 1 24 20 56 1 58 28

bw end c8-e8 26 1 24 20 56 1 58 28

firstr is a1, and lastr is h1

r c8-e8 26 1 24 20 56 1 58 28

first 26 1 24 20 56 1 58 28

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

space b3 is d1

16 d1 b3-a4 26 1 24 20 56 1 58 28

11010 1 11000 10100 111000 1 111010 11100

2 one bits in var d1

11010 1 11000 10100 111000 1 111010 11100

q end b3-a4 26 1 24 20 56 1 58 28

bb end b3-a4 26 1 24 20 56 1 58 28

bw end b3-a4 26 1 24 20 56 1 58 28

firstr is a1, and lastr is h1

r b3-a4 26 1 24 20 56 1 58 28

first 26 1 24 20 56 1 58 28

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

space g6 is f1

17 f1 g6-h4 26 1 24 20 56 1 58 28

11010 1 11000 10100 111000 1 111010 11100

1 one bits in var f1

11010 1 11000 10100 111000 1 111010 11100

q end g6-h4 26 1 24 20 56 1 58 28

bb end g6-h4 26 1 24 20 56 1 58 28

bw end g6-h4 26 1 24 20 56 1 58 28

firstr is a1, and lastr is h1

r g6-h4 26 1 24 20 56 1 58 28

first 26 1 24 20 56 1 58 28

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

space a1 is a1

18 a1 a1-f6 26 1 24 20 56 1 58 28

11010 1 11000 10100 111000 1 111010 11100

3 one bits in var a1

10010 1 11000 10100 111000 1 111010 11100

q end a1-f6 18 1 24 20 56 1 58 28

bb end a1-f6 18 1 24 20 56 1 58 28

bw end a1-f6 18 1 24 20 56 1 58 28

firstr is c1, and lastr is h1

r a1-f6 18 1 24 20 56 1 58 28

first 18 1 24 20 56 1 58 28

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

space e7 is e1

19 e1 e7-f6 18 1 24 20 56 1 58 28

10010 1 11000 10100 111000 1 111010 11100

3 one bits in var e1

10010 1 11000 10100 110000 1 111010 11100

q end e7-f6 18 1 24 20 48 1 58 28

bb end e7-f6 18 1 24 20 48 1 58 28

bw end e7-f6 18 1 24 20 48 1 58 28

firstr is c1, and lastr is h1

One Rook found

d1 20

e1 48

r e7-f6 18 1 8 20 48 1 58 28

first 18 1 8 20 48 1 58 28

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

space a4 is d1

20 d1 a4-d7 18 1 8 20 48 1 58 28

10010 1 1000 10100 110000 1 111010 11100

2 one bits in var d1

10010 1 1000 10100 110000 1 111010 11100

q end a4-d7 18 1 8 20 48 1 58 28

bb end a4-d7 18 1 8 20 48 1 58 28

bw end a4-d7 18 1 8 20 48 1 58 28

firstr is c1, and lastr is h1

One Rook found

d1 20

e1 48

r a4-d7 18 1 8 20 48 1 58 28

first 18 1 8 20 48 1 58 28

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

space e8 is c1

21 c1 e8-d8 18 1 8 20 48 1 58 28

10010 1 1000 10100 110000 1 111010 11100

1 one bits in var c1

10010 1 1000 10100 110000 1 111010 11100

q end e8-d8 18 1 8 20 48 1 58 28

bb end e8-d8 18 1 8 20 48 1 58 28

bw end e8-d8 18 1 8 20 48 1 58 28

firstr is c1, and lastr is h1

One Rook found

d1 20

e1 48

r e8-d8 18 1 8 20 48 1 58 28

first 18 1 8 20 48 1 58 28

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

space d7 is d1

22 d1 d7-a4 18 1 8 20 48 1 58 28

10010 1 1000 10100 110000 1 111010 11100

2 one bits in var d1

10010 1 1000 10100 110000 1 111010 11100

q end d7-a4 18 1 8 20 48 1 58 28

bb end d7-a4 18 1 8 20 48 1 58 28

bw end d7-a4 18 1 8 20 48 1 58 28

firstr is c1, and lastr is h1

One Rook found

d1 20

e1 48

r d7-a4 18 1 8 20 48 1 58 28

first 18 1 8 20 48 1 58 28

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

space b7 is p

23 p b7-b5 18 1 8 20 48 1 58 28

10010 1 1000 10100 110000 1 111010 11100

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

space g3 is f1

24 f1 g3-e4 18 1 8 20 48 1 58 28

10010 1 1000 10100 110000 1 111010 11100

1 one bits in var f1

10010 1 1000 10100 110000 1 111010 11100

q end g3-e4 18 1 8 20 48 1 58 28

bb end g3-e4 18 1 8 20 48 1 58 28

bw end g3-e4 18 1 8 20 48 1 58 28

firstr is c1, and lastr is h1

One Rook found

d1 20

e1 48

r g3-e4 18 1 8 20 48 1 58 28

first 18 1 8 20 48 1 58 28

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

space f6 is e1

25 e1 f6-g6 18 1 8 20 48 1 58 28

10010 1 1000 10100 110000 1 111010 11100

2 one bits in var e1

10010 1 1000 10100 110000 1 111010 11100

q end f6-g6 18 1 8 20 48 1 58 28

bb end f6-g6 18 1 8 20 48 1 58 28

bw end f6-g6 18 1 8 20 48 1 58 28

firstr is c1, and lastr is h1

One Rook found

d1 20

e1 48

r f6-g6 18 1 8 20 48 1 58 28

first 18 1 8 20 48 1 58 28

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

space e1 is e1

26 e1 e1-f1 18 1 8 20 48 1 58 28

10010 1 1000 10100 110000 1 111010 11100

2 one bits in var e1

10010 1 1000 10100 110000 1 111010 11100

q end e1-f1 18 1 8 20 48 1 58 28

bb end e1-f1 18 1 8 20 48 1 58 28

bw end e1-f1 18 1 8 20 48 1 58 28

firstr is c1, and lastr is h1

One Rook found

d1 20

e1 48

r e1-f1 18 1 8 20 48 1 58 28

first 18 1 8 20 48 1 58 28

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

space b5 is p

27 p b5-a4 18 1 8 20 48 1 58 28

10010 1 1000 10100 110000 1 111010 11100

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

space b4 is P

28 P b4-c5 18 1 8 20 48 1 58 28

10010 1 1000 10100 110000 1 111010 11100

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

space d6 is p

29 p d6-c5 18 1 8 20 48 1 58 28

10010 1 1000 10100 110000 1 111010 11100

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

space f2 is P

30 P f2-f3 18 1 8 20 48 1 58 28

10010 1 1000 10100 110000 1 111010 11100

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

space a8 is a1

31 a1 a8-e4 18 1 8 20 48 1 58 28

10010 1 1000 10100 110000 1 111010 11100

2 one bits in var a1

10010 1 1000 10100 110000 1 111010 11100

q end a8-e4 18 1 8 20 48 1 58 28

bb end a8-e4 18 1 8 20 48 1 58 28

bw end a8-e4 18 1 8 20 48 1 58 28

firstr is c1, and lastr is h1

One Rook found

d1 20

e1 48

r a8-e4 18 1 8 20 48 1 58 28

first 18 1 8 20 48 1 58 28

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

space f3 is P

32 P f3-e4 18 1 8 20 48 1 58 28

10010 1 1000 10100 110000 1 111010 11100

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

space h8 is h1

33 h1 h8-f8 18 1 8 20 48 1 58 28

10010 1 1000 10100 110000 1 111010 11100

3 one bits in var h1

rook hopping king to castle

10010 1 1000 10100 110000 1 111010 11100

q end h8-f8 18 1 8 20 48 1 58 28

bb end h8-f8 18 1 8 20 48 1 58 28

bw end h8-f8 18 1 8 20 48 1 58 28

firstr is c1, and lastr is h1

One Rook found

d1 20

e1 48

r h8-f8 18 1 8 20 48 1 58 28

first 18 1 8 20 48 1 58 28

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

space a7 is b1

34 b1 a7-c6 18 1 8 20 48 1 58 28

10010 1 1000 10100 110000 1 111010 11100

1 one bits in var b1

10010 1 1000 10100 110000 1 111010 11100

q end a7-c6 18 1 8 20 48 1 58 28

bb end a7-c6 18 1 8 20 48 1 58 28

bw end a7-c6 18 1 8 20 48 1 58 28

firstr is c1, and lastr is h1

One Rook found

d1 20

e1 48

r a7-c6 18 1 8 20 48 1 58 28

first 18 1 8 20 48 1 58 28

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

space d8 is c1

35 c1 d8-d7 18 1 8 20 48 1 58 28

10010 1 1000 10100 110000 1 111010 11100

1 one bits in var c1

10010 1 1000 10100 110000 1 111010 11100

q end d8-d7 18 1 8 20 48 1 58 28

bb end d8-d7 18 1 8 20 48 1 58 28

bw end d8-d7 18 1 8 20 48 1 58 28

firstr is c1, and lastr is h1

One Rook found

d1 20

e1 48

r d8-d7 18 1 8 20 48 1 58 28

first 18 1 8 20 48 1 58 28

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

space c6 is b1

36 b1 c6-e5 18 1 8 20 48 1 58 28

10010 1 1000 10100 110000 1 111010 11100

1 one bits in var b1

10010 1 1000 10100 110000 1 111010 11100

q end c6-e5 18 1 8 20 48 1 58 28

bb end c6-e5 18 1 8 20 48 1 58 28

bw end c6-e5 18 1 8 20 48 1 58 28

firstr is c1, and lastr is h1

One Rook found

d1 20

e1 48

r c6-e5 18 1 8 20 48 1 58 28

first 18 1 8 20 48 1 58 28

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

space g6 is e1

37 e1 g6-f6 18 1 8 20 48 1 58 28

10010 1 1000 10100 110000 1 111010 11100

2 one bits in var e1

10010 1 1000 10100 110000 1 111010 11100

q end g6-f6 18 1 8 20 48 1 58 28

bb end g6-f6 18 1 8 20 48 1 58 28

bw end g6-f6 18 1 8 20 48 1 58 28

firstr is c1, and lastr is h1

One Rook found

d1 20

e1 48

r g6-f6 18 1 8 20 48 1 58 28

first 18 1 8 20 48 1 58 28

Continue because mv is empty

This game may have been too short to properly calculate the original position, and the calculated pattern of is inconsistent with randomly generated value of NRBQKBNR. 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 - b4 
1... e7-e6 
2. c2 - c4 
2... d7-d6 
3. d1 - b3 
3... b8-d7 
4. d2 - d3 
4... d8-f6 
5. b1 - c3 
5... f8-g6 
6. f1 - g3 
6... c7-c5 
7. c3 - b5 
7... e8-e7 
8. b5 - a7 
8... c8-e8 
9. b3 - a4 
9... g6-h4 
10. a1 - f6 
10... e7-f6 
11. a4 - d7 
11... e8-d8 
12. d7 - a4 
12... b7-b5 
13. g3 - e4 
13... f6-g6 
14. e1 - f1 
14... b5-a4 
15. b4 - c5 
15... d6-c5 
16. f2 - f3 
16... a8-e4 
17. f3 - e4 
17... h8-f8 
18. a7 - c6 
18... d8-d7 
19. c6 - e5 
19... g6-f6

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