include chess2; // Set some variables to reuse some subroutines for different games. set wpr 3; // White's Pawn Rank set bpr 8; // Black's Pawn Rank set fps 2; // How many spaces a Pawn may move on its first turn set pzs 3; // Number of ranks in promotion zone // Kings have different powers of movement in Eurasian Chess // They may not cross the river, and they may capture one another by a Queen's move, // which effectively means they cannot face each other along an empty file or diagonal. def K cond < rank #1 5 (checkleap #0 #1 1 1 or checkleap #0 #1 1 0) (checkride #0 #1 1 1 or checkride #0 #1 1 0 and or == #1 var k == space #1 k) and #0; def k cond > rank #1 4 (checkleap #0 #1 1 1 or checkleap #0 #1 1 0) (checkride #0 #1 1 1 or checkride #0 #1 1 0 and or == #1 var K == space #1 K) and #0; // Same as in chess2 with an extra line for rules affecting Pawn movement in Eurasian Chess // When a Pawn tries to move to the last rank without attacking a King and without there being // anything to promote to, it may not advance. def P remove var ep and checkleap #0 #1 1 1 and == var ep join filename #1 rankname #0 or and checkatwostep #0 #1 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 (< 0 sum var CAP or == space #1 k or != rank #1 9) and > rank #1 rank #0; def p remove var ep and checkleap #0 #1 1 1 and == var ep join filename #1 rankname #0 or and checkatwostep #0 #1 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 (< 0 sum var CAP or == space #1 K or != rank #1 9) and < rank #1 rank #0; // Same as in chess2 except promotion rules are modified. sub P from to; local ydir; if == file #from file #to and not capture: set legal checkaleap #from #to 0 1; if var legal: set ep false; else; set legal checkatwostep #from #to 0 1 0 1 and == rankname #from 3; set ep #to; endif; set epc false; elseif capture or #ep: set legal checkaleap #from #to -1 1 or checkaleap #from #to 1 1; set epc false; if not capture and var legal: set legal == #ep where #to 0 -1; if var legal: capture #ep; set epc #ep; endif; endif; set ep false; endif; set pp space #to; if != #pp P: if < rank #to 7: die "You may not promote a Pawn until it reaches one of the last three ranks."; elseif < elem #pp CAP 1; die "You may not promote your Pawn to a" #pp "until one has been captured."; endif; setelem CAP #pp dec elem #pp CAP; elseif == rank #to 9: die "You may not move a Pawn to the last rank without promoting it."; endif; endsub; sub p from to; if == file #from file #to and not capture: set legal checkaleap #from #to 0 -1; if var legal: set ep false; else: set legal checkatwostep #from #to 0 -1 0 -1 and == rankname #from 8; set ep #to; endif; set epc false; elseif capture or #ep: set legal checkaleap #from #to -1 -1 or checkaleap #from #to 1 -1; set epc false; if not capture and var legal: set legal == #ep where #to 0 1; if var legal: capture #ep; set epc #ep; endif; endif; set ep false; endif; set pp space #to; if != #pp p: if > rank #to 2: die "You may not promote a Pawn until it reaches one of the last three ranks."; elseif < elem #pp cap 1; die "You may not promote your Pawn to a" #pp "until one has been captured."; endif; setelem cap #pp dec elem #pp cap; elseif == rank #to 0: die "You may not move a Pawn to the last rank without promoting it."; endif; endsub; // Same as in chess2 except code for castling is removed. sub stalemated kingpos: store; local from piece to king; set lglmvs (); set king space #kingpos; if isupper space #kingpos: def friends onlyupper; def nofriends noupper; def friend isupper #0; else: def friends onlylower; def nofriends nolower; def friend islower #0; endif; // While the royal piece is called the King in these comments, // it may be any piece. These variables determine what the royal piece is. set royal space var kingpos; // Can the king move? // The King is done separately for two reasons. // (1) Efficiency: The King is always on the board and can usually move. // (2) Accuracy: For a King's potential move, the King's new location must be checked for check. // But for other pieces, the King's actual position must be checked for check. store; for to fn join #royal L #kingpos: if fn #royal #kingpos #to and not fn friend space #to and onboard #to: move #kingpos #to; set incheck sub checked #to; restore; if not #incheck: setlegal "{#king} {#kingpos}-{#to}"; endif; endif; next; // Can another piece legally move? restore; for (from piece) fn friends: if == #from #kingpos: continue; endif; for to fn join #piece L #from: if fn #piece #from #to and not fn friend space #to and onboard #to: move #from #to; set incheck sub checked #kingpos; if not #incheck: setlegal "{#piece} {#from}-{#to}"; endif; endif; restore; next; next; return cond count system legalmoves false true; endsub;