####################################################################### # CheckMate: Save this file as CheckMate. To use it, # # stay in the # # same directory, get into Maple (by typing: maple ) # # and then type: read CheckMate : # # Then follow the instructions given there # #IMPORTANT: For Many Sample Problems also download files EVANS and # #CARPETNER from Zeilberger's website # # # Written by Doron Zeilberger, Rutgers University , # #zeilberg@math.rutgers.edu. # ####################################################################### read Evans: read Carpenter: #Created: Nov. 2003- Feb. 2004 #Previous version: Feb. 2, 2004 #This version: Nov. 13, 2004 (more problems addede in Carpenter and Evans) #CheckMate: A Maple package to solve Mate-in-k-Moves Chess Problems #Please report bugs to zeilberg@math.rutgers.edu print(` CheckMate: A Maple package to solve Mate-in-k-Moves Chess Problems.`): print(`Written by Doron Zeilberger, zeilberg@math.rutgers.edu .`): print(): print(`Created: Nov. 2003- Feb. 2004.`): print(`This version: Feb. 2, 2004.`): print(): print(`Please report bugs to zeilberg@math.rutgers.edu .`): print(): print(`For a list of the MAIN procedures type: ezra();` ): print(`For a list of Sample Problems, type: SampleProblems(); .` ): print(`The Sample problems are in files EVANS and CARPENTER that should`): print(`downloaded from`): print(`http://www.math.rutgers.edu/~zeilberg/tokhniot/EVANS and `): print(`http://www.math.rutgers.edu/~zeilberg/tokhniot/CARPENTER . `): print(`The most current version of this Maple program is at`): print(`http://www.math.rutgers.edu/~zeilberg/tokhniot/CheckMate . `): print(`For a list of ALL procedures type: ezra1(); .` ): SampleProblems:=proc(): print(`Mate -in-1-moves`): print(`E1,E2,E3`): print(`Mate -in-2-moves`): print(`E30,E31,E32,E33,E34,E35,E36,E37,E38,E65, DE23, Y276, Ha7, Ha10, Y291 `): print(` Y289, Y295, Y297, Y298, Y304, Y306, LevL, Y314, Y315, Y318, Y319 `): print(` Y320, Y321, Y324, Y326, Y328, Y330, Y011108, Y332, Y333, Y334 `): print(` Y335, Y336, Y338, Y339, Y342 `): print(`Mate-in-3-moves `): print(`Ca1,Ca2,Ca3,Ca4,Ca5,Ca6,Ca7,Ca8, G132, Y263, Ha1, Ha3, `): print(`Ha4, Ha5,Ha6,Ha7,Ha8, Y296, Y300, Y303, Y310, Y312, Y313, Y340, Y341 `); print(`Mate-in-4-moves Ha3 (too long for my computer), Y302, Y309 `): print(`Mate-in-5-moves Ha11`): end: ezra:=proc() if args=NULL then print(`The Main Procedures are: `): print(` MATE, MATEv, MATEvv, MateInTwo`): print(`For help with a specific procedure, type`): print(`ezra(Procedure_Name);, for example ezra(MATE);`): fi: if nops([args])=1 and op(1,[args])=BlackLost then print(`BlackLost(POS): Did Black Lose?`): fi: if nops([args])=1 and op(1,[args])=BlackMoves then print(`BlackMoves(POS): all the legal moves of Black`): fi: if nops([args])=1 and op(1,[args])=ExecMove then print(`ExecMove(POS,Move1): Given a position POS, and a move Move1`): print(`( a triple [piece,startLocation,EndLocation]) performs it `): print(`For example try ExecMove(IniPOS(),[1,[1,2],[1,3]]);`): fi: if nops([args])=1 and op(1,[args])=HopeLessB then print(`HopeLessB(POS,k): is the position POS hopeless for Black`): print(`in the sense that whatever it does will lead to`): print(`a Mate in k moves for White`): fi: if nops([args])=1 and op(1,[args])=IniPos then print(`IniPos(): The initial position in Chess`): print(`in terms of a list [White,Black], where`): print(`White and Black are lists of length 6`): print(`indicating the sets [Pawn,Knight, Bishop, Rook, Queen, King]`): print(`in that order. Each of the sets Pawn, ..., King`): print(`is the set of sequares occopied by the pieces`): print(`we use Cartesian notation [i,j], so [3,5] means c5`): fi: if nops([args])=1 and op(1,[args])=IsStallMate then print(`IsStallMate(POS): Is it a stall-mate?`): fi: if nops([args])=1 and op(1,[args])=MateInk then print(`MateInk(POS,k): Can White force CheckMate in k moves,`): print(` followed by how?`): print(`For example, try MateInk(C2b,1);, or MateInk(C2,2);`): fi: if nops([args])=1 and op(1,[args])=MateInk1 then print(`MateInk(POS,k): Can White force CheckMate in k moves, followed`): print(`by one way of doing it`): fi: if nops([args])=1 and op(1,[args])=MateIn then print(`MateIn(POS,k): Can White force CheckMate in k moves, followed`): print(`by one way of doing it, POS is given in "algebraic notation"`): fi: if nops([args])=1 and op(1,[args])=MateInTwo then print(`MateInTwo(POS): compact form of displaying the solution for`): print(`Mate in-two-probems. `): fi: if nops([args])=1 and op(1,[args])=PICT then print(`PICT(POS): draws the position in terms of a matrix`): fi: if nops([args])=1 and op(1,[args])=PICTm then print(`PICTm(POS): draws the position in terms of a matrix`): print(`with the grid shown in algebraic notation`): fi: if nops([args])=1 and op(1,[args])=ProveCheckMate then print(`ProveCheckMate(POS,lu): A formal(verbose) proof that position POS`): print(`is CheckMate aided by the list lu, 2nd component of`): print(`of IsCheckMate if the first component is true. For example`): print(`try ProveCheckMate(C2c,IsCheckMate(C2c)[2]);`): fi: if nops([args])=1 and op(1,[args])=RandGame then print(`RandGame(): A random game, outputs who won, and in how many`): print(`moves, where 1 is White and -1 is Black. For example`): print(`The output [1,90] means that White won in 90 moves`): print(`and [-1,69] that Black won in 69 moves`): fi: if nops([args])=1 and op(1,[args])=RandGameV then print(`RandGameV(): A random game, Verbose style`): fi: if nops([args])=1 and op(1,[args])=RandStatx then print(`RandStatx(K,x): The outcomes of K random games`): print(`Outputs polynomials W(x) and B(x) such that the`): print(`coeff. of x^j in W(x) is the number of games won by`): print(`by White in j moves, and similarly for B(x)`): print(`For example, try RandStatx(100,x); `): fi: if nops([args])=1 and op(1,[args])=Solve1 then print(`Solve1(POS): Solves a Mate-In-One-Move Chess Problem`): print(`Given in algebraic notation`): print(`For example, try: Solve1(E1);`): fi: if nops([args])=1 and op(1,[args])=Solve2 then print(`Solve2(POS): Solves a Mate-In-Two-Moves Chess Problem`): print(`Given in algebraic notation`): print(`For example, try: Solve2(E30);`): fi: if nops([args])=1 and op(1,[args])=Solve2V then print(`Solve2(POSV): Solves a Mate-In-Two-Moves Chess Problem`): print(`in Verbose style`): print(`Given in algebraic notation`): print(`For example, try: Solve2(E311);`): fi: if nops([args])=1 and op(1,[args])=MATE then print(`MATE(POS,k): Solves a Mate-In-k-Moves Chess Problem`): print(`Given in algebraic notation. Terse style`): print(`For example, try: MATE(E1,1);`): fi: if nops([args])=1 and op(1,[args])=MATEv then print(`MATEv(POS,k): Solves a Mate-In-k-Moves Chess Problem`): print(`Given in algebraic notation. Verbose style`): print(`For example, try: MATEv(E1,1);`): fi: if nops([args])=1 and op(1,[args])=MATEvv then print(`MATEvv(POS,k): Solves a Mate-In-k-Moves Chess Problem`): print(`Given in algebraic notation. Very Verbose style`): print(`For example, try: MATEvv(E1,1);`): fi: if nops([args])=1 and op(1,[args])=WhiteLost then print(`WhiteLost(POS): Did White Lose?`): fi: if nops([args])=1 and op(1,[args])=WhiteMoves then print(`WhiteMoves(POS): all the legal moves of White`): fi: if nops([args])=1 and op(1,[args])=WinningMove0W then print(`WinningMove0W(POS): Can White Win right away?`): fi: end: ezra1:=proc() if args=NULL then print(`For help with a specific procedure, type`): print(`ezra(Procedure_Name);, for example ezra(WhiteMoves);`): print(`All the Procedures are: `): print(` BlackLost, BlackMoves, ExecMove, HopeLessB, IniPos, `): print(`IsStallMate, MateIn`): print(` PICT, PICTm,ProveCheckMate `): print(`RandGame,RandGameV, RandStatx, SampleP, Solve1,Solve2, Solve2V `): print(` Solvek, SolvekV, SolvekVv `): print(` WhiteLost, WhiteMoves `): print(` WinningMove0W `): else ezra(args): fi: end: ##Sample Positions Y1:=[[{},{},{},{},{[7,1]},{[8,2]}],[{[8,3],[8,5]},{[5,4]},{},{},{}, {[8,4]}]]: Y2:=[[{[7,4]},{},{[4,2],[7,6]},{},{[8,2]},{[3,5]}], [{[5,5]},{},{},{},{},{[6,3]}]]: Y2a:=[[{},{},{[4,2],[7,6]},{},{[8,2]},{[3,5]}], [{[5,5]},{},{},{},{},{[6,3]}]]: Y3:=[[{[6,4]},{[6,3]},{[3,6],[7,7]},{},{[3,8]},{[4,1]}], [{},{},{},{},{},{[5,3]}]]: C1:=[ [{[2,5],[7,7],[8,7]},{[5,4],[5,5]},{[6,3]},{[4,5],[6,7]}, {[5,2]},{[2,1]}],[{[2,6],[6,4]},{},{},{[4,7],[6,5]},{}, {[5,6]}]]: C1a:=[ [{[2,5],[7,7],[8,7]},{[5,4],[3,6]},{[6,3]},{[6,7]}, {[5,2]},{[2,1]}],[{[2,6],[6,4]},{},{},{[4,7],[6,5]},{}, {[4,5]}]]: C1b:=[ [{[2,5],[7,7],[8,7]},{[5,4],[3,6]},{[6,3]},{[6,7]}, {[1,2]},{[2,1]}],[{[2,6],[6,4]},{},{},{[4,7],[6,5]},{}, {[4,5]}]]: C2:=[[{[2,3],[3,2]},{},{[1,2],[8,8]},{[1,4],[5,1]},{},{[3,1]}], [{[5,2]},{[3,3]},{},{[2,2]},{},{[1,1]}]]; C2a:=[[{[2,3],[3,2]},{},{[1,2],[8,8]},{[1,3],[5,1]},{},{[3,1]}], [{[5,2]},{[3,3]},{},{[2,2]},{},{[1,1]}]]; C2b:=[[{[2,3],[3,2]},{},{[1,2],[8,8]},{[1,3],[5,1]},{},{[3,1]}], [{[5,2]},{[3,3]},{},{[2,1]},{},{[1,1]}]]; C2c:=[[{[2,3],[3,2]},{},{[2,1],[8,8]},{[1,3],[5,1]},{},{[3,1]}], [{[5,2]},{[3,3]},{},{},{},{[1,1]}]]; C3:=[[ {[5,2],[6,3],[7,3],[8,4]}, {[7,2],[8,3]}, {[1,3],[4,3]}, {[2,2],[8,1]}, {[1,4]}, {[6,1]} ], [ {[1,7],[2,6],[3,7],[6,7],[8,7]}, {[5,1]}, {[2,7],[7,7]}, {[4,8], [8,8]}, {[8,6]}, {[3,1]} ]]: #Yediot #261 (Dec. 26, 2003) C4:= [ [ {[8,3]},{[3,4]},{[6,1],[8,2]},{[5,6],[6,3]},{[1,4]},{[3,6]} ], [ {[3,5],[5,3],[5,5],[6,2],[7,5]},{},{},{},{[6,4]},{[5,4]} ] ]: C4a:= [ [ {[8,3]},{[3,4]},{[6,1],[8,2]},{[5,6],[6,3]},{[2,3]},{[3,6]} ], [ {[3,5],[5,3],[5,5],[6,2],[7,5]},{},{},{},{[6,4]},{[5,4]} ] ]: ## #PICT(POS): draws the position in terms of a matrix PICT:=proc(POS) local A,i,j,a,b,wP,wKt,wB,wR,wK,wQ, bP,bKt,bB,bR,bK,bQ: A:=matrix(8,8): for i from 1 to 8 do for j from 1 to 8 do A[i,j]:=`-`: od: od: for i from 1 to nops(POS[1][1]) do a:=POS[1][1][i][1]:b:=POS[1][1][i][2]: A[9-b,a]:=wP: od: for i from 1 to nops(POS[1][2]) do a:=POS[1][2][i][1]:b:=POS[1][2][i][2]: A[9-b,a]:=wKt: od: for i from 1 to nops(POS[1][3]) do a:=POS[1][3][i][1]:b:=POS[1][3][i][2]: A[9-b,a]:=wB: od: for i from 1 to nops(POS[1][4]) do a:=POS[1][4][i][1]:b:=POS[1][4][i][2]: A[9-b,a]:=wR: od: for i from 1 to nops(POS[1][5]) do a:=POS[1][5][i][1]:b:=POS[1][5][i][2]: A[9-b,a]:=wQ: od: for i from 1 to nops(POS[1][6]) do a:=POS[1][6][i][1]:b:=POS[1][6][i][2]: A[9-b,a]:=wK: od: for i from 1 to nops(POS[2][1]) do a:=POS[2][1][i][1]:b:=POS[2][1][i][2]: A[9-b,a]:=bP: od: for i from 1 to nops(POS[2][2]) do a:=POS[2][2][i][1]:b:=POS[2][2][i][2]: A[9-b,a]:=bKt: od: for i from 1 to nops(POS[2][3]) do a:=POS[2][3][i][1]:b:=POS[2][3][i][2]: A[9-b,a]:=bB: od: for i from 1 to nops(POS[2][4]) do a:=POS[2][4][i][1]:b:=POS[2][4][i][2]: A[9-b,a]:=bR: od: for i from 1 to nops(POS[2][5]) do a:=POS[2][5][i][1]:b:=POS[2][5][i][2]: A[9-b,a]:=bQ: od: for i from 1 to nops(POS[2][6]) do a:=POS[2][6][i][1]:b:=POS[2][6][i][2]: A[9-b,a]:=bK: od: print(A): end: #IniPos(): The initial position in Chess #in terms of a list [White,Black], where #White and Black are lists of length 6 #indicating the sets [Pawn,Knight, Bishop, Rook, Queen, King] #in that order. Each of the sets Pawn, ..., King #is the set of sequares occopied by the pieces #we use Cartesian notation [i,j], so [3,5] means c5 IniPos:=proc() local i: [ [{seq([i,2],i=1..8)},{[2,1],[7,1]}, {[3,1],[6,1]},{[1,1],[8,1]}, {[4,1]}, {[5,1]}], [{seq([i,7],i=1..8)},{[2,8],[7,8]}, {[3,8],[6,8]},{[1,8],[8,8]}, {[4,8]}, {[5,8]}] ]: end: #ExecWhiteMove(POS,Move1): Given a position POS, and a move Move1 #( a triple [piece,startLocation,EndLocation]) performs it (for White) #For example try ExecWhiteMove(IniPOS(),[1,[1,2],[1,3]]); ExecWhiteMove:=proc(POS,Move1) local a,j, WhitePieces, BlackPieces,POS1: WhitePieces:={seq(op(POS[1][j]),j=1..6)}: BlackPieces:={seq(op(POS[2][j]),j=1..6)}: a:=Move1[1]: if a<0 then ERROR(`Black piece`): fi: if not member(Move1[2],POS[1][a]) then RETURN(FAIL): fi: if member(Move1[3],WhitePieces) then RETURN(FAIL): fi: if not member(Move1[3],BlackPieces) then POS1:=[[op(1..a-1,POS[1]), POS[1][a] minus {Move1[2]} union {Move1[3]}, op(a+1..6,POS[1])],POS[2]]: else for j from 1 to 6 while not member(Move1[3],POS[2][j]) do od: POS1:=[[op(1..a-1,POS[1]), POS[1][a] minus {Move1[2]} union {Move1[3]}, op(a+1..6,POS[1])], [op(1..j-1,POS[2]), POS[2][j] minus {Move1[3]}, op(j+1..6,POS[2])]]: fi: if a=1 and Move1[2][2]=7 and Move1[3][2]=8 then POS1:=[[POS1[1][1] minus {Move1[3]}, op(2..4,POS1[1]), POS1[1][5] union {Move1[3]},POS1[1][6]],POS1[2]]: fi: POS1: end: #ExecBlackMove(POS,Move1): Given a position POS, and a move Move1 #( a triple [piece,startLocation,EndLocation]) performs it (for White) #For example try ExecWhiteMove(IniPOS(),[1,[1,2],[1,3]]); ExecBlackMove:=proc(POS,Move1) local a,j, WhitePieces, BlackPieces,POS1: WhitePieces:={seq(op(POS[1][j]),j=1..6)}: BlackPieces:={seq(op(POS[2][j]),j=1..6)}: a:=Move1[1]: if a>0 then ERROR(`White piece`): fi: a:=-a: if not member(Move1[2],POS[2][a]) then RETURN(FAIL): fi: if member(Move1[3],BlackPieces) then RETURN(FAIL): fi: if not member(Move1[3],WhitePieces) then POS1:=[POS[1], [op(1..a-1,POS[2]), POS[2][a] minus {Move1[2]} union {Move1[3]}, op(a+1..6,POS[2])]]: else for j from 1 to 6 while not member(Move1[3],POS[1][j]) do od: POS1:=[ [op(1..j-1,POS[1]), POS[1][j] minus {Move1[3]}, op(j+1..6,POS[1])], [op(1..a-1,POS[2]), POS[2][a] minus {Move1[2]} union {Move1[3]}, op(a+1..6,POS[2])]]: fi: if a=1 and Move1[2][2]=2 and Move1[3][2]=1 then POS1:=[ POS1[1], [POS1[2][1] minus {Move1[3]}, op(2..4,POS1[2]), POS1[2][5] union {Move1[3]},POS1[2][6]]]: fi: POS1: end: #ExecMove(POS,Move1): Given a position POS, and a move Move1 #( a triple [piece,startLocation,EndLocation]) performs it #For example try ExecMove(IniPOS(),[1,[1,2],[1,3]]); ExecMove:=proc(POS,Move1): if Move1[1]>0 then ExecWhiteMove(POS,Move1) else ExecBlackMove(POS,Move1) fi: end: #########Pawn Moves########### #PawnMovesWN1(POS,Sq): Given a position POS, and a square Sq #occupied by a White Pawn outputs all the legal moves (w/o capture) #For White using that Pawn PawnMovesWN1:=proc(POS,Sq) local WhitePieces, BlackPieces,a,b,Sq1,j,gu: gu:={}: WhitePieces:={seq(op(POS[1][j]),j=1..6)}: BlackPieces:={seq(op(POS[2][j]),j=1..6)}: if not member(Sq,POS[1][1]) then RETURN(FAIL): fi: a:=Sq[1]: b:=Sq[2]: if b>=8 then ERROR(`Something is wrong`): fi: if b>2 then Sq1:=[a,b+1]: if not member(Sq1,BlackPieces union WhitePieces) then RETURN({[1,Sq,Sq1]}): else RETURN({}): fi: elif b=2 then Sq1:=[a,b+1]: if not member(Sq1,BlackPieces union WhitePieces) then gu:=gu union {[1,Sq,Sq1]}: fi: Sq1:=[a,b+2]: if not (member([a,b+1],BlackPieces union WhitePieces) or member([a,b+2],BlackPieces union WhitePieces) ) then gu:=gu union {[1,Sq,Sq1]}: fi: RETURN(gu): fi: end: #PawnMovesBN1(POS,Sq): Given a position POS, and a square Sq #occupied by a Pawn outputs all the legal moves (w/o capture) #For Black using that Pawn PawnMovesBN1:=proc(POS,Sq) local WhitePieces, BlackPieces,a,b,Sq1,j,gu: gu:={}: WhitePieces:={seq(op(POS[1][j]),j=1..6)}: BlackPieces:={seq(op(POS[2][j]),j=1..6)}: if not member(Sq,POS[2][1]) then RETURN(FAIL): fi: a:=Sq[1]: b:=Sq[2]: if b=1 then ERROR(`Something is wrong`): fi: if b<7 then Sq1:=[a,b-1]: if not member(Sq1,BlackPieces union WhitePieces) then RETURN({[-1,Sq,Sq1]}): else RETURN({}): fi: elif b=7 then Sq1:=[a,b-1]: if not member(Sq1,BlackPieces union WhitePieces) then gu:=gu union {[-1,Sq,Sq1]}: fi: Sq1:=[a,b-2]: if not (member([a,b-1],BlackPieces union WhitePieces) or member([a,b-2],BlackPieces union WhitePieces) ) then gu:=gu union {[-1,Sq,Sq1]}: fi: RETURN(gu): fi: end: #PawnMovesWC1(POS,Sq): Given a position POS, and a square Sq #occupied by a White Pawn outputs all the legal moves (with capture) #For White using that Pawn PawnMovesWC1:=proc(POS,Sq) local BlackPieces,a,b,Sq1,j,gu: gu:={}: BlackPieces:={seq(op(POS[2][j]),j=1..6)}: if not member(Sq,POS[1][1]) then RETURN(FAIL): fi: a:=Sq[1]: b:=Sq[2]: if b>=8 then ERROR(`Something is wrong`): fi: Sq1:=[a+1,b+1]: if member(Sq1,BlackPieces) then gu:= gu union {[1,Sq,Sq1]}: fi: Sq1:=[a-1,b+1]: if member(Sq1,BlackPieces) then gu:=gu union {[1,Sq,Sq1]}: fi: gu: end: #PawnMovesBC1(POS,Sq): Given a position POS, and a square Sq #occupied by a Black Pawn outputs all the legal moves (with capture) #For Black using that Pawn PawnMovesBC1:=proc(POS,Sq) local WhitePieces,a,b,Sq1,j,gu: gu:={}: WhitePieces:={seq(op(POS[1][j]),j=1..6)}: if not member(Sq,POS[2][1]) then RETURN(FAIL): fi: a:=Sq[1]: b:=Sq[2]: if b<=1 then ERROR(`Something is wrong`): fi: Sq1:=[a+1,b-1]: if member(Sq1,WhitePieces) then gu:= gu union {[-1,Sq,Sq1]}: fi: Sq1:=[a-1,b-1]: if member(Sq1,WhitePieces) then gu:=gu union {[-1,Sq,Sq1]}: fi: gu: end: #PawnMovesW(POS): All the legal moves of Pawns for White PawnMovesW:=proc(POS) local gu,Sq,i: gu:={}: for i from 1 to nops(POS[1][1]) do Sq:=POS[1][1][i]: gu:=gu union PawnMovesWN1(POS,Sq) union PawnMovesWC1(POS,Sq): od: gu: end: #PawnMovesB(POS): All the legal moves of Pawns for White PawnMovesB:=proc(POS) local gu,Sq,i: gu:={}: for i from 1 to nops(POS[2][1]) do Sq:=POS[2][1][i]: gu:=gu union PawnMovesBN1(POS,Sq) union PawnMovesBC1(POS,Sq): od: gu: end: #######End Pawn Moves ####Knight Moves #KnightMovesW1(POS,Sq): Given a position POS, and a square Sq #occupied by a White Knight outputs all the legal moves #For White using that Knight KnightMovesW1:=proc(POS,Sq) local WhitePieces,a,b,Sq1,j,mu,gu: gu:={}: WhitePieces:={seq(op(POS[1][j]),j=1..6)}: if not member(Sq,POS[1][2]) then RETURN(FAIL): fi: a:=Sq[1]: b:=Sq[2]: mu:={[a+1,b+2],[a+1,b-2],[a-1,b+2],[a-1,b-2], [a+2,b+1],[a+2,b-1],[a-2,b+1],[a-2,b-1]}: gu:={}: for j from 1 to nops(mu) do Sq1:=mu[j]: if Sq1[1]>=1 and Sq1[1]<=8 and Sq1[2]>=1 and Sq1[2]<=8 and not member(Sq1,WhitePieces) then gu:=gu union {[2,Sq,Sq1]}: fi: od: gu: end: #KnightMovesW(POS): All the legal moves of Knight for White KnightMovesW:=proc(POS) local gu,Sq,i: gu:={}: for i from 1 to nops(POS[1][2]) do Sq:=POS[1][2][i]: gu:=gu union KnightMovesW1(POS,Sq) : od: gu: end: #KnightMovesB1(POS,Sq): Given a position POS, and a square Sq #occupied by a Black Knight outputs all the legal moves #For Black using that Knight KnightMovesB1:=proc(POS,Sq) local BlackPieces,a,b,Sq1,j,mu,gu: gu:={}: BlackPieces:={seq(op(POS[2][j]),j=1..6)}: if not member(Sq,POS[2][2]) then RETURN(FAIL): fi: a:=Sq[1]: b:=Sq[2]: mu:={[a+1,b+2],[a+1,b-2],[a-1,b+2],[a-1,b-2], [a+2,b+1],[a+2,b-1],[a-2,b+1],[a-2,b-1]}: gu:={}: for j from 1 to nops(mu) do Sq1:=mu[j]: if Sq1[1]>=1 and Sq1[1]<=8 and Sq1[2]>=1 and Sq1[2]<=8 and not member(Sq1,BlackPieces) then gu:=gu union {[-2,Sq,Sq1]}: fi: od: gu: end: #KnightMovesB(POS): All the legal moves of Knights for White KnightMovesB:=proc(POS) local gu,Sq,i: gu:={}: for i from 1 to nops(POS[2][2]) do Sq:=POS[2][2][i]: gu:=gu union KnightMovesB1(POS,Sq) : od: gu: end: ##########End Knight Moves #######Bishop Moves #BishopMovesW1(POS,Sq): Given a position POS, and a square Sq #occupied by a White Bishop outputs all the legal moves #For White using that Bishop BishopMovesW1:=proc(POS,Sq) local BlackPieces, WhitePieces,a,b,i,j,gu: gu:={}: WhitePieces:={seq(op(POS[1][j]),j=1..6)}: BlackPieces:={seq(op(POS[2][j]),j=1..6)}: if not member(Sq,POS[1][3]) then RETURN(FAIL): fi: a:=Sq[1]: b:=Sq[2]: gu:={}: for i from 1 while a+i<=8 and b+i<=8 and not member([a+i,b+i],WhitePieces union BlackPieces) do od: gu:=gu union {seq([3,Sq,[a+j,b+j]],j=1..i-1)}: if member([a+i,b+i],BlackPieces) then gu:=gu union {[3,Sq,[a+i,b+i]]}: fi: for i from 1 while a+i<=8 and b-i>=1 and not member([a+i,b-i],WhitePieces union BlackPieces) do od: gu:=gu union {seq([3,Sq,[a+j,b-j]],j=1..i-1)}: if member([a+i,b-i],BlackPieces) then gu:=gu union {[3,Sq,[a+i,b-i]]}: fi: for i from 1 while a-i>=1 and b+i<=8 and not member([a-i,b+i],WhitePieces union BlackPieces) do od: gu:=gu union {seq([3,Sq,[a-j,b+j]],j=1..i-1)}: if member([a-i,b+i],BlackPieces) then gu:=gu union {[3,Sq,[a-i,b+i]]}: fi: for i from 1 while a-i>=1 and b-i>=1 and not member([a-i,b-i],WhitePieces union BlackPieces) do od: gu:=gu union {seq([3,Sq,[a-j,b-j]],j=1..i-1)}: if member([a-i,b-i],BlackPieces) then gu:=gu union {[3,Sq,[a-i,b-i]]}: fi: gu: end: #BishopMovesW(POS): All the legal moves of Bishop for White BishopMovesW:=proc(POS) local gu,Sq,i: gu:={}: for i from 1 to nops(POS[1][3]) do Sq:=POS[1][3][i]: gu:=gu union BishopMovesW1(POS,Sq) : od: gu: end: #BishopMovesB1(POS,Sq): Given a position POS, and a square Sq #occupied by a Black Bishop outputs all the legal moves #For Black using that Bishop BishopMovesB1:=proc(POS,Sq) local BlackPieces, WhitePieces,a,b,i,j,gu: gu:={}: WhitePieces:={seq(op(POS[1][j]),j=1..6)}: BlackPieces:={seq(op(POS[2][j]),j=1..6)}: if not member(Sq,POS[2][3]) then RETURN(FAIL): fi: a:=Sq[1]: b:=Sq[2]: gu:={}: for i from 1 while a+i<=8 and b+i<=8 and not member([a+i,b+i],WhitePieces union BlackPieces) do od: gu:=gu union {seq([-3,Sq,[a+j,b+j]],j=1..i-1)}: if member([a+i,b+i],WhitePieces) then gu:=gu union {[-3,Sq,[a+i,b+i]]}: fi: for i from 1 while a+i<=8 and b-i>=1 and not member([a+i,b-i],WhitePieces union BlackPieces) do od: gu:=gu union {seq([-3,Sq,[a+j,b-j]],j=1..i-1)}: if member([a+i,b-i],WhitePieces) then gu:=gu union {[-3,Sq,[a+i,b-i]]}: fi: for i from 1 while a-i>=1 and b+i<=8 and not member([a-i,b+i],WhitePieces union BlackPieces) do od: gu:=gu union {seq([-3,Sq,[a-j,b+j]],j=1..i-1)}: if member([a-i,b+i],WhitePieces) then gu:=gu union {[-3,Sq,[a-i,b+i]]}: fi: for i from 1 while a-i>=1 and b-i>=1 and not member([a-i,b-i],WhitePieces union BlackPieces) do od: gu:=gu union {seq([-3,Sq,[a-j,b-j]],j=1..i-1)}: if member([a-i,b-i],WhitePieces) then gu:=gu union {[-3,Sq,[a-i,b-i]]}: fi: gu: end: #BishopMovesB(POS): All the legal moves of Bishop for White BishopMovesB:=proc(POS) local gu,Sq,i: gu:={}: for i from 1 to nops(POS[2][3]) do Sq:=POS[2][3][i]: gu:=gu union BishopMovesB1(POS,Sq) : od: gu: end: ###End Bishop Moves #######Rook Moves #RookMovesW1(POS,Sq): Given a position POS, and a square Sq #occupied by a White Rook outputs all the legal moves #For White using that Rook RookMovesW1:=proc(POS,Sq) local BlackPieces, WhitePieces,a,b,i,j,gu: gu:={}: WhitePieces:={seq(op(POS[1][j]),j=1..6)}: BlackPieces:={seq(op(POS[2][j]),j=1..6)}: if not member(Sq,POS[1][4]) then RETURN(FAIL): fi: a:=Sq[1]: b:=Sq[2]: gu:={}: for i from 1 while a+i<=8 and not member([a+i,b],WhitePieces union BlackPieces) do od: gu:=gu union {seq([4,Sq,[a+j,b]],j=1..i-1)}: if member([a+i,b],BlackPieces) then gu:=gu union {[4,Sq,[a+i,b]]}: fi: for i from 1 while a-i>=1 and not member([a-i,b],WhitePieces union BlackPieces) do od: gu:=gu union {seq([4,Sq,[a-j,b]],j=1..i-1)}: if member([a-i,b],BlackPieces) then gu:=gu union {[4,Sq,[a-i,b]]}: fi: for i from 1 while b+i<=8 and not member([a,b+i],WhitePieces union BlackPieces) do od: gu:=gu union {seq([4,Sq,[a,b+j]],j=1..i-1)}: if member([a,b+i],BlackPieces) then gu:=gu union {[4,Sq,[a,b+i]]}: fi: for i from 1 while b-i>=1 and not member([a,b-i],WhitePieces union BlackPieces) do od: gu:=gu union {seq([4,Sq,[a,b-j]],j=1..i-1)}: if member([a,b-i],BlackPieces) then gu:=gu union {[4,Sq,[a,b-i]]}: fi: gu: end: #RookMovesW(POS): All the legal moves of Rook for White RookMovesW:=proc(POS) local gu,Sq,i: gu:={}: for i from 1 to nops(POS[1][4]) do Sq:=POS[1][4][i]: gu:=gu union RookMovesW1(POS,Sq) : od: gu: end: #RookMovesB1(POS,Sq): Given a position POS, and a square Sq #occupied by a Black Rook outputs all the legal moves #For Black using that Rook RookMovesB1:=proc(POS,Sq) local BlackPieces, WhitePieces,a,b,i,j,gu: gu:={}: WhitePieces:={seq(op(POS[1][j]),j=1..6)}: BlackPieces:={seq(op(POS[2][j]),j=1..6)}: if not member(Sq,POS[2][4]) then RETURN(FAIL): fi: a:=Sq[1]: b:=Sq[2]: gu:={}: for i from 1 while a+i<=8 and not member([a+i,b],WhitePieces union BlackPieces) do od: gu:=gu union {seq([-4,Sq,[a+j,b]],j=1..i-1)}: if member([a+i,b],WhitePieces) then gu:=gu union {[-4,Sq,[a+i,b]]}: fi: for i from 1 while a-i>=1 and not member([a-i,b],WhitePieces union BlackPieces) do od: gu:=gu union {seq([-4,Sq,[a-j,b]],j=1..i-1)}: if member([a-i,b],WhitePieces) then gu:=gu union {[-4,Sq,[a-i,b]]}: fi: for i from 1 while b+i<=8 and not member([a,b+i],WhitePieces union BlackPieces) do od: gu:=gu union {seq([-4,Sq,[a,b+j]],j=1..i-1)}: if member([a,b+i],WhitePieces) then gu:=gu union {[-4,Sq,[a,b+i]]}: fi: for i from 1 while b-i>=1 and not member([a,b-i],WhitePieces union BlackPieces) do od: gu:=gu union {seq([-4,Sq,[a,b-j]],j=1..i-1)}: if member([a,b-i],WhitePieces) then gu:=gu union {[-4,Sq,[a,b-i]]}: fi: gu: end: #RookMovesB(POS): All the legal moves of Rook for White RookMovesB:=proc(POS) local gu,Sq,i: gu:={}: for i from 1 to nops(POS[2][4]) do Sq:=POS[2][4][i]: gu:=gu union RookMovesB1(POS,Sq) : od: gu: end: ###End Rook Moves ###Queen Moves####### #QueenMovesW1(POS,Sq): Given a position POS, and a square Sq #occupied by a White Queen outputs all the legal moves #For White using that Queen QueenMovesW1:=proc(POS,Sq) local BlackPieces, WhitePieces,a,b,i,j,gu: gu:={}: WhitePieces:={seq(op(POS[1][j]),j=1..6)}: BlackPieces:={seq(op(POS[2][j]),j=1..6)}: if not member(Sq,POS[1][5]) then RETURN(FAIL): fi: a:=Sq[1]: b:=Sq[2]: gu:={}: ##begin rook-like moves for i from 1 while a+i<=8 and not member([a+i,b],WhitePieces union BlackPieces) do od: gu:=gu union {seq([5,Sq,[a+j,b]],j=1..i-1)}: if member([a+i,b],BlackPieces) then gu:=gu union {[5,Sq,[a+i,b]]}: fi: for i from 1 while a-i>=1 and not member([a-i,b],WhitePieces union BlackPieces) do od: gu:=gu union {seq([5,Sq,[a-j,b]],j=1..i-1)}: if member([a-i,b],BlackPieces) then gu:=gu union {[5,Sq,[a-i,b]]}: fi: for i from 1 while b+i<=8 and not member([a,b+i],WhitePieces union BlackPieces) do od: gu:=gu union {seq([5,Sq,[a,b+j]],j=1..i-1)}: if member([a,b+i],BlackPieces) then gu:=gu union {[5,Sq,[a,b+i]]}: fi: for i from 1 while b-i>=1 and not member([a,b-i],WhitePieces union BlackPieces) do od: gu:=gu union {seq([5,Sq,[a,b-j]],j=1..i-1)}: if member([a,b-i],BlackPieces) then gu:=gu union {[5,Sq,[a,b-i]]}: fi: ##end rook-like moves ##begin bishop-like moves for i from 1 while a+i<=8 and b+i<=8 and not member([a+i,b+i],WhitePieces union BlackPieces) do od: gu:=gu union {seq([5,Sq,[a+j,b+j]],j=1..i-1)}: if member([a+i,b+i],BlackPieces) then gu:=gu union {[5,Sq,[a+i,b+i]]}: fi: for i from 1 while a+i<=8 and b-i>=1 and not member([a+i,b-i],WhitePieces union BlackPieces) do od: gu:=gu union {seq([5,Sq,[a+j,b-j]],j=1..i-1)}: if member([a+i,b-i],BlackPieces) then gu:=gu union {[5,Sq,[a+i,b-i]]}: fi: for i from 1 while a-i>=1 and b+i<=8 and not member([a-i,b+i],WhitePieces union BlackPieces) do od: gu:=gu union {seq([5,Sq,[a-j,b+j]],j=1..i-1)}: if member([a-i,b+i],BlackPieces) then gu:=gu union {[5,Sq,[a-i,b+i]]}: fi: for i from 1 while a-i>=1 and b-i>=1 and not member([a-i,b-i],WhitePieces union BlackPieces) do od: gu:=gu union {seq([5,Sq,[a-j,b-j]],j=1..i-1)}: if member([a-i,b-i],BlackPieces) then gu:=gu union {[5,Sq,[a-i,b-i]]}: fi: ##end bishop-like moves gu: end: #QueenMovesW(POS): All the legal moves of Queen for White QueenMovesW:=proc(POS) local gu,Sq,i: gu:={}: for i from 1 to nops(POS[1][5]) do Sq:=POS[1][5][i]: gu:=gu union QueenMovesW1(POS,Sq) : od: gu: end: #QueenMovesB1(POS,Sq): Given a position POS, and a square Sq #occupied by a Black Queen outputs all the legal moves #For Black using that Queen QueenMovesB1:=proc(POS,Sq) local BlackPieces, WhitePieces,a,b,i,j,gu: gu:={}: WhitePieces:={seq(op(POS[1][j]),j=1..6)}: BlackPieces:={seq(op(POS[2][j]),j=1..6)}: if not member(Sq,POS[2][5]) then RETURN(FAIL): fi: a:=Sq[1]: b:=Sq[2]: gu:={}: ##begin rook-like moves for i from 1 while a+i<=8 and not member([a+i,b],WhitePieces union BlackPieces) do od: gu:=gu union {seq([-5,Sq,[a+j,b]],j=1..i-1)}: if member([a+i,b],WhitePieces) then gu:=gu union {[-5,Sq,[a+i,b]]}: fi: for i from 1 while a-i>=1 and not member([a-i,b],WhitePieces union BlackPieces) do od: gu:=gu union {seq([-5,Sq,[a-j,b]],j=1..i-1)}: if member([a-i,b],WhitePieces) then gu:=gu union {[-5,Sq,[a-i,b]]}: fi: for i from 1 while b+i<=8 and not member([a,b+i],WhitePieces union BlackPieces) do od: gu:=gu union {seq([-5,Sq,[a,b+j]],j=1..i-1)}: if member([a,b+i],WhitePieces) then gu:=gu union {[-5,Sq,[a,b+i]]}: fi: for i from 1 while b-i>=1 and not member([a,b-i],WhitePieces union BlackPieces) do od: gu:=gu union {seq([-5,Sq,[a,b-j]],j=1..i-1)}: if member([a,b-i],WhitePieces) then gu:=gu union {[-5,Sq,[a,b-i]]}: fi: ##end rook-like moves ##begin bishop-like moves for i from 1 while a+i<=8 and b+i<=8 and not member([a+i,b+i],WhitePieces union BlackPieces) do od: gu:=gu union {seq([-5,Sq,[a+j,b+j]],j=1..i-1)}: if member([a+i,b+i],WhitePieces) then gu:=gu union {[-5,Sq,[a+i,b+i]]}: fi: for i from 1 while a+i<=8 and b-i>=1 and not member([a+i,b-i],WhitePieces union BlackPieces) do od: gu:=gu union {seq([-5,Sq,[a+j,b-j]],j=1..i-1)}: if member([a+i,b-i],WhitePieces) then gu:=gu union {[-5,Sq,[a+i,b-i]]}: fi: for i from 1 while a-i>=1 and b+i<=8 and not member([a-i,b+i],WhitePieces union BlackPieces) do od: gu:=gu union {seq([-5,Sq,[a-j,b+j]],j=1..i-1)}: if member([a-i,b+i],WhitePieces) then gu:=gu union {[-5,Sq,[a-i,b+i]]}: fi: for i from 1 while a-i>=1 and b-i>=1 and not member([a-i,b-i],WhitePieces union BlackPieces) do od: gu:=gu union {seq([-5,Sq,[a-j,b-j]],j=1..i-1)}: if member([a-i,b-i],WhitePieces) then gu:=gu union {[-5,Sq,[a-i,b-i]]}: fi: ##end bishop-like moves gu: end: #QueenMovesB(POS): All the legal moves of Queen for Black QueenMovesB:=proc(POS) local gu,Sq,i: gu:={}: for i from 1 to nops(POS[2][5]) do Sq:=POS[2][5][i]: gu:=gu union QueenMovesB1(POS,Sq) : od: gu: end: ##begin King's Moves #KingMovesW1(POS,Sq): Given a position POS, and a square Sq #occupied by a White King outputs all the legal moves #For White using that King KingMovesW1:=proc(POS,Sq) local WhitePieces,a,b,Sq1,j,mu,gu: gu:={}: WhitePieces:={seq(op(POS[1][j]),j=1..6)}: if not member(Sq,POS[1][6]) then RETURN(FAIL): fi: a:=Sq[1]: b:=Sq[2]: mu:={[a+1,b+1],[a+1,b-1],[a-1,b+1],[a-1,b-1], [a,b-1],[a,b+1],[a-1,b],[a+1,b]}: gu:={}: for j from 1 to nops(mu) do Sq1:=mu[j]: if Sq1[1]>=1 and Sq1[1]<=8 and Sq1[2]>=1 and Sq1[2]<=8 and not member(Sq1,WhitePieces) then gu:=gu union {[6,Sq,Sq1]}: fi: od: gu: end: #KingMovesW(POS): All the legal moves of King for White KingMovesW:=proc(POS) local gu,Sq,i: gu:={}: for i from 1 to nops(POS[1][6]) do Sq:=POS[1][6][i]: gu:=gu union KingMovesW1(POS,Sq) : od: gu: end: #KingMovesB1(POS,Sq): Given a position POS, and a square Sq #occupied by a Black King outputs all the legal moves #For Black using that King KingMovesB1:=proc(POS,Sq) local BlackPieces,a,b,Sq1,j,mu,gu: gu:={}: BlackPieces:={seq(op(POS[2][j]),j=1..6)}: if not member(Sq,POS[2][6]) then RETURN(FAIL): fi: a:=Sq[1]: b:=Sq[2]: mu:={[a+1,b+1],[a+1,b-1],[a-1,b+1],[a-1,b-1], [a,b-1],[a,b+1],[a-1,b],[a+1,b]}: gu:={}: for j from 1 to nops(mu) do Sq1:=mu[j]: if Sq1[1]>=1 and Sq1[1]<=8 and Sq1[2]>=1 and Sq1[2]<=8 and not member(Sq1,BlackPieces) then gu:=gu union {[-6,Sq,Sq1]}: fi: od: gu: end: #KingMovesB(POS): All the legal moves of King for Black KingMovesB:=proc(POS) local gu,Sq,i: gu:={}: for i from 1 to nops(POS[2][6]) do Sq:=POS[2][6][i]: gu:=gu union KingMovesB1(POS,Sq) : od: gu: end: ###end of King moves #WhiteMoves(POS): all the legal White moves WhiteMoves:=proc(POS) [ op(QueenMovesW(POS)),op(BishopMovesW(POS)),op(RookMovesW(POS)), op(KnightMovesW(POS)),op( KingMovesW(POS)),op(PawnMovesW(POS))]: end: #BlackMoves(POS): all the legal Black moves BlackMoves:=proc(POS) PawnMovesB(POS) union KnightMovesB(POS) union BishopMovesB(POS) union RookMovesB(POS) union QueenMovesB(POS) union KingMovesB(POS): end: WhiteLost:=proc(POS):evalb(POS[1][6]={}):end: BlackLost:=proc(POS):evalb(POS[2][6]={}):end: #RandGameV(): A random game, Verbose style RandGameV:=proc() local P,i,ra,lu,gu: P:=IniPos(): for i from 1 do gu:=WhiteMoves(P): ra:=rand(1..nops(gu)): lu:=gu[ra()]: print(`The `, i, `move of White is `, lu): P:=ExecMove(P,lu): print(`The position now is`): PICT(P): if BlackLost(P) then print(`Black lost in`, i, `moves `): RETURN([1,i]): fi: gu:=BlackMoves(P): ra:=rand(1..nops(gu)): lu:=gu[ra()]: print(`The `, i, `move of Black is `, lu): P:=ExecMove(P,lu): print(`The position now is`): PICT(P): if WhiteLost(P) then print(`White lost in`, i, `moves `): RETURN([-1,i]): fi: od: end: #RandGame(): A random game, just outputs who won and the number of moves RandGame:=proc() local P,i,ra,lu,gu: P:=IniPos(): for i from 1 do gu:=WhiteMoves(P): ra:=rand(1..nops(gu)): lu:=gu[ra()]: P:=ExecMove(P,lu): if BlackLost(P) then RETURN([1,i]): fi: gu:=BlackMoves(P): ra:=rand(1..nops(gu)): lu:=gu[ra()]: P:=ExecMove(P,lu): if WhiteLost(P) then RETURN([-1,i]): fi: od: end: #RandStatx(K,x): The outcomes of K random games #Outputs polynomials W(x) and B(x) such that the #coeff. of x^j in W(x) is the number of games won by #by White in j moves, and similarly for B(x) #For example, try RandStat(100,x); RandStatx:=proc(K,x) local W,B,gu,i,mu1,mu2: W:=0: B:=0: for i from 1 to K do gu:=RandGame(): if gu[1]=1 then W:=W+x^gu[2]: else B:=B+x^gu[2]: fi: od: if W<>0 then mu1:=subs(x=1.0,diff(W,x))/subs(x=1,W): else mu1:=0: fi: if B<>0 then mu2:=subs(x=1.0,diff(B,x))/subs(x=1,B): else mu2:=0: fi: [W,B, subs(x=1,W),subs(x=1,B),mu1,mu2]: end: #WinningMove0W(POS): Can White Win right away? WinningMove0W:=proc(POS) local gu,i,M,P1: gu:=WhiteMoves(POS): for i from 1 to nops(gu) do M:=gu[i]: P1:=ExecMove(POS,M): if BlackLost(P1) then RETURN(true,M): fi: od: false: end: #RandGameD(): A random game, with details #just outputs who won and the number of moves RandGameD:=proc() local P,i,ra,lu,gu,GU: P:=IniPos(): GU:=[]: for i from 1 do gu:=WhiteMoves(P): ra:=rand(1..nops(gu)): lu:=gu[ra()]: P:=ExecMove(P,lu): GU:=[op(GU),P]: if BlackLost(P) then RETURN([1,i],GU): fi: gu:=BlackMoves(P): ra:=rand(1..nops(gu)): lu:=gu[ra()]: P:=ExecMove(P,lu): GU:=[op(GU),P]: if WhiteLost(P) then RETURN([-1,i],GU): fi: od: end: #WinningMove0W(POS): Can White Win right away? WinningMove0W:=proc(POS) local gu,i,M,P1: gu:=WhiteMoves(POS): for i from 1 to nops(gu) do M:=gu[i]: P1:=ExecMove(POS,M): if BlackLost(P1) then RETURN(true,M): fi: od: false,{}: end: #IsCheck(POS): Is the White Checking the Black King? IsCheck:=proc(POS) local gu,i: gu:=WhiteMoves(POS): for i from 1 to nops(gu) do if BlackLost(ExecMove(POS,gu[i])) then RETURN(true): fi: od: false: end: #IsCheckMate(POS): Is White Check-Mating the Black? IsCheckMate:=proc(POS) local lu,i,mu,gu: if not IsCheck(POS) then RETURN(false,{}): fi: mu:=WinningMove0B(POS): if mu[1] then RETURN(false, mu[2]): fi: gu:={}: lu:=BlackMoves(POS): for i from 1 to nops(lu) do mu:=WinningMove0W(ExecMove(POS,lu[i])): if not mu[1] then RETURN(false,lu[i]): else gu:=gu union {[lu[i],mu[2]]}: fi: od: true,gu: end: #HopeLessB(POS,k): is the position POS hopeless for Black #in the sense that whatever it does will lead to #a Mate in k moves for White HopeLessB:=proc(POS,k) local mu,gu1,gu2,Move1,POS1,i,lu: if k=0 then RETURN(IsCheckMate(POS)): fi: mu:=BlackMoves(POS): gu1:={}: gu2:={}: for i from 1 to nops(mu) do Move1:=mu[i]: POS1:=ExecMove(POS,Move1): lu:=MateInk(POS1,k): if lu[1] then gu1:=gu1 union {[Move1, lu[2]]}: else gu2:=gu2 union {[Move1,lu[2]]}: fi: od: if gu2={} then RETURN(true,gu1): else RETURN(false, gu2): fi: end: #MateInk(POS,k): Can White force CheckMate in k moves, followed by how? #For example, try MateInk(C2b,1); MateInk:=proc(POS,k) local mu,gu1,gu2,Move1,POS1,i,lu: mu:=WhiteMoves(POS): gu1:={}: gu2:={}: for i from 1 to nops(mu) do Move1:=mu[i]: POS1:=ExecMove(POS,Move1): if not IsStallMate(POS1) then lu:=HopeLessB(POS1,k-1): if lu[1] then gu1:=gu1 union {[Move1,lu[2]]}: else gu2:=gu2 union {[Move1,lu[2]]}: fi: fi: od: if gu1<>{} then RETURN(true,gu1): else RETURN(false, gu2): fi: end: #WinningMove0B(POS): Can Black Win right away? WinningMove0B:=proc(POS) local gu,i,M,P1: gu:=BlackMoves(POS): for i from 1 to nops(gu) do M:=gu[i]: P1:=ExecMove(POS,M): if WhiteLost(P1) then RETURN(true,M): fi: od: false,{}: end: #IsStallMate(POS): Is it a stall-mate? IsStallMate:=proc(POS) local gu,i: if IsCheck(POS) then RETURN(false): fi: gu:=BlackMoves(POS): for i from 1 to nops(gu) do if not WinningMove0W(ExecMove(POS,gu[i]))[1] then RETURN(false): fi: od: true: end: #MateInk1(POS,k): Can White force CheckMate in k moves, followed by how? #For example, try MateInk1(C2b,1); MateInk1:=proc(POS,k) local mu,gu2,Move1,POS1,i,lu: option remember: if k=0 then RETURN(WinningMove0W(POS)): fi: mu:=WhiteMoves1(POS): gu2:={}: for i from 1 to nops(mu) do Move1:=mu[i]: POS1:=ExecMove(POS,Move1): if not IsStallMate(POS1) then lu:=HopeLessB1(POS1,k-1): if lu[1] then RETURN(true,[Move1,lu[2]]): else gu2:=gu2 union {[Move1,lu[2]]}: fi: fi: od: RETURN(false, gu2): end: #HopeLessB1(POS,k): is the position POS hopeless for Black #in the sense that whatever it does will lead to #a Mate in k moves for White HopeLessB1:=proc(POS,k) local mu,gu1,gu2,Move1,POS1,i,lu: option remember: if k=0 then RETURN(IsCheckMate(POS)): fi: lu:=WinningMove0B(POS): if lu[1] then RETURN(false,lu[2]): fi: mu:=BlackMoves(POS): gu1:={}: gu2:={}: for i from 1 to nops(mu) do Move1:=mu[i]: POS1:=ExecMove(POS,Move1): lu:=MateInk1Ad(POS1,k): if lu=-1 then RETURN(false,Move1): fi: if lu[1]>0 then if lu[1]<=k then gu1:=gu1 union {[k,Move1, lu[2]]}: fi: fi: od: true,gu1: end: WhiteMoves1:=proc(POS) local i,mu,KB,kv,T,pu,S: option remember: mu:=WhiteMoves(POS): KB:=POS[2][6][1]: kv:={}: for i from 1 to nops(mu) do pu:=abs(KB[1]-mu[i][3][1])+abs(KB[2]-mu[i][3][2]): T[mu[i]]:=pu: kv:=kv union {pu}: od: for i from 1 to nops(kv) do S[kv[i]]:={}: od: for i from 1 to nops(mu) do S[T[mu[i]]]:=S[T[mu[i]]] union {mu[i]}: od: kv:=sort(convert(kv,list)): [seq(op(S[kv[i]]),i=1..nops(kv))]: end: #ProveCheckMate1(POS,lu): A formal(verbose) proof that position POS #is CheckMate aided by the list lu, 2nd component of #of IsCheckMate if the first component is true. For example #using numerical notation #try ProveCheckMate1(C2c,IsCheckMate(C2c)[2]); ProveCheckMate1:=proc(POS,lu) local gu,mu,i: gu:=BlackMoves(POS): mu:={seq(lu[i][1],i=1..nops(lu))}: if gu<>mu then ERROR(`Something is wrong`): fi: print(): print(`Theorem: The following position is a CheckMate of White to Black`): PICT(POS): lprint(): print(`Proof: Black has`, nops(gu), `legal moves`): for i from 1 to nops(gu) do print(`if Black makes the move`,lu[i][1], `then the position becomes`): PICT(ExecMove(POS,lu[i][1])): print(`and then White can capture the Black King by the move`, lu[i][2]): od: print(`Since for every legal move of Black, White can capture the Black King`): print(`it follows that the position is indeed a checkmate of White to Black`): print(` QED. `): end: Tar1:=proc(i): if i=1 then (`White Pawn`): elif i=2 then (`White Knight`): elif i=3 then (`White Bishop`): elif i=4 then (`White Rook`): elif i=5 then (`White Queen`): elif i=6 then (`White King`): elif i=-1 then (`Black Pawn`): elif i=-2 then (`Black Knight`): elif i=-3 then (`Black Bishop`): elif i=-4 then (`Black Rook`): elif i=-5 then (`Black Queen`): elif i=-6 then (`Black King`): else ERROR(`Bad input`): fi: end: Tar2:=proc(zug) local a,b,c,d,e,f,g,h: if zug[1]=1 then cat(a,zug[2]): elif zug[1]=2 then cat(b,zug[2]): elif zug[1]=3 then cat(c,zug[2]): elif zug[1]=4 then cat(d,zug[2]): elif zug[1]=5 then cat(e,zug[2]): elif zug[1]=6 then cat(f,zug[2]): elif zug[1]=7 then cat(g,zug[2]): elif zug[1]=8 then cat(h,zug[2]): else ERROR(`bad input`): fi: end: #Targem(move1): translates the move move1 to human language Targem:=proc(move1) cat(Tar1(move1[1]), " from " , Tar2(move1[2]) , " to ", Tar2(move1[3]) ): end: #ProveCheckMate(POS,lu): A formal(verbose) proof that position POS #is CheckMate aided by the list lu, 2nd component of #of IsCheckMate if the first component is true. For example #using human (algebraic) notation #try ProveCheckMate(C2c,IsCheckMate(C2c)[2]); ProveCheckMate:=proc(POS,lu) local gu,mu,i: gu:=BlackMoves(POS): mu:={seq(lu[i][1],i=1..nops(lu))}: if gu<>mu then ERROR(`Something is wrong`): fi: print(): print(`Theorem: The following position is a CheckMate of White to Black`): PICT(POS): print(``): print(`Proof: Black has`, nops(gu), `legal moves`): for i from 1 to nops(gu) do print(`if Black makes the move:`): print(Targem(lu[i][1])), print(`then the position becomes:`): PICT(ExecMove(POS,lu[i][1])): print(`and then White can capture the Black King by the move:`): print(Targem( lu[i][2])): od: print(`Since for every legal move of Black, White can capture the Black King`): print(`it follows that the position is indeed a checkmate of White to Black`): print(` QED. `): end: #MateInk1Ad(POS,k): Can White force CheckMate in<=k moves, followed by how? #output is [r,move], where White can force a checkmate in r moves #For example, try MateInk(C2b); MateInk1Ad:=proc(POS,k) local r,lu: option remember: for r from 0 to k do lu:=MateInk1(POS,r): if lu[1] then RETURN(r,lu[2]): fi: od: -1: end: #Solve2V(POS): Solves a Mate-In-Two-Moves Chess Problem (verbosely) #For example, try: Solve2(C1); Solve2V:= proc(POS) local lu,i: lu:=MateInk1(POS,2): if not lu[1] then RETURN(FAIL): fi: print(cat(`1. ` , Targem(lu[2][1]))): for i from 1 to nops(lu[2][2]) do print(Targem(lu[2][2][i][2])): print(cat(`2. ` , Targem(lu[2][2][i][3][1]))): if i1 then print(` The moves: `): for i from 1 to nops(BM1) do bm1:=BM1[i]: if nops(bm1[2])>1 then print(Tar1(bm1[1][1]), ` from `, Tar2(bm1[1][2]),`to one of the follwing:`, seq(Tar2(a), a in bm1[2]) , `; ` ): else print(Tar1(bm1[1][1]), ` from `, Tar2(bm1[1][2]),` to `, seq(Tar2(a), a in bm1[2]) , `; ` ): fi: od: print(`enables White to checkmate with:`, Targem(cm)): print(`-------------------------`): else print(` The move `): for i from 1 to nops(BM1) do bm1:=BM1[i]: if nops(bm1[2])>1 then print(Tar1(bm1[1][1]), ` from `, Tar2(bm1[1][2]),`to one of the follwing:`, seq(Tar2(a), a in bm1[2]) , `; ` ): else print(Tar1(bm1[1][1]), ` from `, Tar2(bm1[1][2]),` to `, seq(Tar2(a), a in bm1[2]) , `; ` ): fi: od: print(`enables White to checkmate with:`, Targem(cm)): print(`-------------------------`): fi: od: end: