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 d2-d4, p is #p, o is d2

space d2 is P

0 P d2-d4 27 61 59 61 59 61 59 29

11011 111101 111011 111101 111011 111101 111011 11101

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

space d7 is p

1 p d7-d5 27 61 59 61 59 61 59 29

11011 111101 111011 111101 111011 111101 111011 11101

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

space g2 is P

2 P g2-g4 27 61 59 61 59 61 59 29

11011 111101 111011 111101 111011 111101 111011 11101

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

space e8 is e1

3 e1 e8-b5 27 61 59 61 59 61 59 29

11011 111101 111011 111101 111011 111101 111011 11101

5 one bits in var e1

11011 111101 111011 111101 10010 111101 111011 11101

q end e8-b5 27 61 59 61 18 61 59 29

bb end e8-b5 27 61 59 61 18 61 59 29

bw end e8-b5 27 61 59 61 18 61 59 29

firstr is a1, and lastr is h1

r e8-b5 27 61 59 61 18 61 59 29

first 27 61 59 61 18 61 59 29

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

space b1 is b1

4 b1 b1-c3 27 61 59 61 18 61 59 29

11011 111101 111011 111101 10010 111101 111011 11101

5 one bits in var b1

11011 1 111011 111101 10010 111101 111011 11101

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

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

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

firstr is a1, and lastr is h1

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

first 27 1 59 61 18 61 59 29

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

space c7 is p

5 p c7-c6 27 1 59 61 18 61 59 29

11011 1 111011 111101 10010 111101 111011 11101

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

space c3 is b1

6 b1 c3-b5 27 1 59 61 18 61 59 29

11011 1 111011 111101 10010 111101 111011 11101

1 one bits in var b1

11011 1 111011 111101 10010 111101 111011 11101

q end c3-b5 27 1 59 61 18 61 59 29

bb end c3-b5 27 1 59 61 18 61 59 29

bw end c3-b5 27 1 59 61 18 61 59 29

firstr is a1, and lastr is h1

r c3-b5 27 1 59 61 18 61 59 29

first 27 1 59 61 18 61 59 29

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

space c6 is p

7 p c6-b5 27 1 59 61 18 61 59 29

11011 1 111011 111101 10010 111101 111011 11101

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

space e1 is e1

8 e1 e1-c3 27 1 59 61 18 61 59 29

11011 1 111011 111101 10010 111101 111011 11101

2 one bits in var e1

11011 1 111011 111101 10010 111101 111011 11101

q end e1-c3 27 1 59 61 18 61 59 29

bb end e1-c3 27 1 59 61 18 61 59 29

bw end e1-c3 27 1 59 61 18 61 59 29

firstr is a1, and lastr is h1

r e1-c3 27 1 59 61 18 61 59 29

first 27 1 59 61 18 61 59 29

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

space f8 is f1

9 f1 f8-g8 27 1 59 61 18 61 59 29

11011 1 111011 111101 10010 111101 111011 11101

5 one bits in var f1

11011 1 111011 111101 10010 111000 111011 11101

q end f8-g8 27 1 59 61 18 56 59 29

bb end f8-g8 27 1 59 61 18 56 59 29

bw end f8-g8 27 1 59 61 18 56 59 29

firstr is a1, and lastr is h1

r f8-g8 27 1 59 61 18 56 59 29

first 27 1 59 61 18 56 59 29

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

space c1 is c1

10 c1 c1-d2 27 1 59 61 18 56 59 29

11011 1 111011 111101 10010 111000 111011 11101

5 one bits in var c1

11011 1 110010 111101 10010 111000 111011 11101

q end c1-d2 27 1 50 61 18 56 59 29

bb end c1-d2 27 1 50 61 18 56 59 29

bw end c1-d2 27 1 50 61 18 56 59 29

firstr is a1, and lastr is h1

r c1-d2 27 1 50 61 18 56 59 29

first 27 1 50 61 18 56 59 29

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

space g7 is p

11 p g7-g6 27 1 50 61 18 56 59 29

11011 1 110010 111101 10010 111000 111011 11101

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

space f1 is f1

12 f1 f1-c1 27 1 50 61 18 56 59 29

11011 1 110010 111101 10010 111000 111011 11101

3 one bits in var f1

rook hopping king to castle

King castling by hopping over Rook

11011 1 110010 111101 10010 100000 111011 11101

q end f1-c1 27 1 18 29 18 32 27 29

bb end f1-c1 27 1 18 29 18 32 27 29

bw end f1-c1 27 1 18 29 18 32 27 29

firstr is a1, and lastr is h1

r f1-c1 27 1 18 29 18 32 27 29

first 27 1 18 29 18 32 27 29

11011 1 10010 11101 10010 100000 11011 11101

f1

Array
(
    [0] => a1
    [1] => b1
    [2] => c1
    [3] => d1
    [4] => e1
)

q end f1-c1 27 1 18 29 18 32 27 29

bb end f1-c1 27 1 18 29 18 32 27 29

bw end f1-c1 27 1 18 29 18 32 27 29

firstr is a1, and lastr is h1

r f1-c1 27 1 18 29 18 32 27 29

first 27 1 18 29 18 32 27 29

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

space b8 is b1

13 b1 b8-c6 27 1 18 29 18 32 27 29

11011 1 10010 11101 10010 100000 11011 11101

1 one bits in var b1

11011 1 10010 11101 10010 100000 11011 11101

f1

Array
(
    [0] => a1
    [1] => b1
    [2] => c1
    [3] => d1
    [4] => e1
)

q end b8-c6 27 1 18 29 18 32 27 29

bb end b8-c6 27 1 18 29 18 32 27 29

bw end b8-c6 27 1 18 29 18 32 27 29

firstr is a1, and lastr is h1

r b8-c6 27 1 18 29 18 32 27 29

first 27 1 18 29 18 32 27 29

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

space e2 is P

14 P e2-e4 27 1 18 29 18 32 27 29

11011 1 10010 11101 10010 100000 11011 11101

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

space d5 is p

15 p d5-e4 27 1 18 29 18 32 27 29

11011 1 10010 11101 10010 100000 11011 11101

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

space d4 is P

16 P d4-d5 27 1 18 29 18 32 27 29

11011 1 10010 11101 10010 100000 11011 11101

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

space h8 is h1

17 h1 h8-c3 27 1 18 29 18 32 27 29

11011 1 10010 11101 10010 100000 11011 11101

4 one bits in var h1

11011 1 10010 11101 10010 100000 11011 10100

f1

Array
(
    [0] => a1
    [1] => b1
    [2] => c1
    [3] => d1
    [4] => e1
)

q end h8-c3 27 1 18 29 18 32 8 20

bb end h8-c3 27 1 18 29 18 32 8 20

bw end h8-c3 27 1 18 29 18 32 8 20

firstr is a1, and lastr is g1

One Rook found

h1 20

r h8-c3 27 1 18 29 18 32 8 20

first 27 1 18 29 18 32 8 20

11011 1 10010 11101 10010 100000 1000 10100

f1

Array
(
    [0] => a1
    [1] => b1
    [2] => c1
    [3] => d1
    [4] => e1
)

q end h8-c3 27 1 18 29 18 32 8 20

bb end h8-c3 27 1 18 29 18 32 8 20

bw end h8-c3 27 1 18 29 18 32 8 20

firstr is a1, and lastr is g1

One Rook found

h1 20

r h8-c3 27 1 18 29 18 32 8 20

first 27 1 18 29 18 32 8 20

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 BBRKQNNR. 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. d2-d4 
1... d7-d5 
2. g2-g4 
2... e8-b5 
3. b1-c3 
3... c7-c6 
4. c3-b5 
4... c6-b5 
5. e1-c3 
5... f8-g8 
6. c1-d2 
6... g7-g6 
7. f1-c1 
7... b8-c6 
8. e2-e4 
8... d5-e4 
9. d4-d5 
9... h8-c3

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