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 P e2-e4, p is P, o is e2

space e2 is P

0 P P e2-e4 27 61 59 61 59 61 59 29

11011 111101 111011 111101 111011 111101 111011 11101

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

space e7 is p

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

11011 111101 111011 111101 111011 111101 111011 11101

mv is N f1-e3, p is N, o is f1

space f1 is f1

2 f1 N f1-e3 27 61 59 61 59 61 59 29

11011 111101 111011 111101 111011 111101 111011 11101

5 one bits in var f1

11011 111101 111011 111101 111011 1 111011 11101

q end N f1-e3 27 61 59 61 59 1 59 29

bb end N f1-e3 27 61 59 61 59 1 59 29

bw end N f1-e3 27 61 59 61 59 1 59 29

firstr is a1, and lastr is h1

r N f1-e3 27 61 59 61 59 1 59 29

first 27 61 59 61 59 1 59 29

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

space d7 is p

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

11011 111101 111011 111101 111011 1 111011 11101

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

space c2 is P

4 P P c2-c3 27 61 59 61 59 1 59 29

11011 111101 111011 111101 111011 1 111011 11101

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

space a8 is a1

5 a1 n a8-b6 27 61 59 61 59 1 59 29

11011 111101 111011 111101 111011 1 111011 11101

4 one bits in var a1

1 111101 111011 111101 111011 1 111011 11101

q end n a8-b6 1 61 59 61 59 1 59 29

bb end n a8-b6 1 61 59 61 59 1 59 29

bw end n a8-b6 1 61 59 61 59 1 59 29

firstr is b1, and lastr is h1

r n a8-b6 1 29 59 61 59 1 59 29

first 1 29 59 61 59 1 59 29

1 11100 111010 111100 111010 1 111010 11100

q end n a8-b6 1 28 58 60 58 1 58 28

bb end n a8-b6 1 28 58 60 58 1 58 28

bw end n a8-b6 1 28 58 60 58 1 58 28

firstr is b1, and lastr is h1

r n a8-b6 1 28 58 60 58 1 58 28

first 1 28 58 60 58 1 58 28

mv is P d2-d4, p is P, o is d2

space d2 is P

6 P P d2-d4 1 28 58 60 58 1 58 28

1 11100 111010 111100 111010 1 111010 11100

mv is p e5-d4, p is p, o is e5

space e5 is p

7 p p e5-d4 1 28 58 60 58 1 58 28

1 11100 111010 111100 111010 1 111010 11100

mv is resign, p is #p, o is resign

Continue because resign is resign

Continue because mv is empty

This game may have been too short to properly calculate the original position, and the calculated pattern of N????N?? is inconsistent with randomly generated value of NNRBKRBQ. 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. P e2-e4 
1... p e7-e5 
2. N f1-e3 
2... p d7-d6 
3. P c2-c3 
3... n a8-b6 
4. P d2-d4 
4... p e5-d4 
5. resign

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

Here is a code listing:

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