You may not move a r from b8 to a7

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. f2-f3 
1... a7-a6 
2. c2-c3 
2... e7-e6 
3. e1-d3 
3... b8-a7 
4. d1-e3 
4... f7-f5 
5. g2-g4 
5... f5-g4 
6. f3-g4 
6... f8-c5 
7. b2-b4 
7... c5-e3 
8. g1-g2 
8... e3-g5 
9. h2-h4 
9... g5-f6 
10. b1-b3 
10... d8-c6 
11. g4-g5 
11... f6-e5 
12. a2-a4 
12... b7-b5 
13. d3-e5 
13... c6-e5 
14. b3-c2 
14... e5-g4 
15. c2-e4 
15... c8-b7 
16. e4-f3 
16... b7-f3 
17. e2-f3 
17... a7-f2 
18. g2-h3 
18... f2-f3

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