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 h2-h3, p is #p, o is h2

space h2 is P

2 P h2-h3 27 61 59 61 59 61 59 29

11011 111101 111011 111101 111011 111101 111011 11101

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

space h7 is p

3 p h7-h6 27 61 59 61 59 61 59 29

11011 111101 111011 111101 111011 111101 111011 11101

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

space g1 is g1

4 g1 g1-h2 27 61 59 61 59 61 59 29

11011 111101 111011 111101 111011 111101 111011 11101

5 one bits in var g1

11011 111101 111011 111101 111011 111101 110010 11101

q end g1-h2 27 61 59 61 59 61 50 29

bb end g1-h2 27 61 59 61 59 61 50 29

bw end g1-h2 27 61 59 61 59 61 50 29

firstr is a1, and lastr is h1

r g1-h2 27 61 59 61 59 61 50 29

first 27 61 59 61 59 61 50 29

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

space f7 is p

5 p f7-f6 27 61 59 61 59 61 50 29

11011 111101 111011 111101 111011 111101 110010 11101

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

space e1 is e1

6 e1 e1-c3 27 61 59 61 59 61 50 29

11011 111101 111011 111101 111011 111101 110010 11101

5 one bits in var e1

11011 111101 111011 111101 10010 111101 110010 11101

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

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

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

firstr is a1, and lastr is h1

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

first 27 61 59 61 18 61 50 29

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

space a8 is a1

7 a1 n a8-b6 27 61 59 61 18 61 50 29

11011 111101 111011 111101 10010 111101 110010 11101

4 one bits in var a1

1 111101 111011 111101 10010 111101 110010 11101

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

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

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

firstr is b1, and lastr is h1

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

first 1 29 59 61 18 61 50 29

1 11101 111011 111101 10010 111101 110010 11101

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

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

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

firstr is b1, and lastr is h1

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

first 1 29 59 61 18 61 50 29

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

space c3 is e1

8 e1 c3-c7 1 29 59 61 18 61 50 29

1 11101 111011 111101 10010 111101 110010 11101

2 one bits in var e1

rook ride

e1 currently set to 18

e1 now set to 16

1 11101 111011 111101 10000 111101 110010 11101

queen before c3-c7 1 29 59 61 16 61 50 29

queen after c3-c7 1 13 43 45 16 45 34 13

q end c3-c7 1 13 43 45 16 45 34 13

bb end c3-c7 1 13 43 45 16 45 34 13

bw end c3-c7 1 13 43 45 16 45 34 13

firstr is b1, and lastr is h1

r c3-c7 1 13 43 45 16 45 34 13

first 1 13 43 45 16 45 34 13

1 1101 101011 101101 10000 101101 100010 1101

q end c3-c7 1 13 43 45 16 45 34 13

bb end c3-c7 1 13 43 45 16 45 34 13

bw end c3-c7 1 13 43 45 16 45 34 13

firstr is b1, and lastr is h1

r c3-c7 1 13 43 45 16 45 34 13

first 1 13 43 45 16 45 34 13

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