####################################################################### # CheckMate.txt: Save this file as CheckMate.txt. To use it, # # stay in the # # same directory, get into Maple (by typing: maple ) # # and then type: read `CheckMate.txt` : # # Then follow the instructions given there # #IMPORTANT: For Many Sample Problems also download files MateInTwo # #and MateInThree from Zeilberger's website # # # Written by Doron Zeilberger, Rutgers University , # #zeilberg@math.rutgers.edu. # ####################################################################### read MateInTwo: read MateInThree: #Created: Nov. 2003- Feb. 2004 #This version: Aug. 27, 2017 : MateInTwoS became MateInTwoSold, and MateInTwoS is now more succinct #Previous version: Feb. 2, 2004 #Previous Version: Aug. 26, 2012 (adding procedure MateInTwoS(P); that lists the solution in standard chess notation): #penultimate version: Jan. 17, 2011 (more problems addede in files MateInTwo and #file MateInThree) #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: Jan. 17, 2011.`): 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 MateInTWo and `): print(`MateInThree that should`): print(`downloaded from`): print(`http://www.math.rutgers.edu/~zeilberg/tokhniot/MateInTwo and `): print(`http://www.math.rutgers.edu/~zeilberg/tokhniot/MateInThree . `): 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 `): print(``): print(`Har8, Har12, Har15, Har27, Har36, Har37, Har40, Har41`): print(``): print(`RLB1, RLB20, RLB32,RLB93,RLB96,RLB111,RLB130,RLB155,RLB155a,RLB156,`): print(`R1,R18,R33,R46,R49,R78,R82,R82c,R89,R113,R166,R216,R218,R254,R286,R287,R288,R319,R343,`): print(`R368,R372,R372a,R383,R384,R398, R399, `): print(` Y291, 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, Y348, Y349, Y350, Y352, Y354, Y355 `): print(` Y355a, Y359, Y360, Y360a, Y365, Y365a, Y368 `): print(`Y369, Y370 , Y371, Y372, Y373, Y375,Y377,Y379, Y380,Y382, Y382a, Y383`): print(` Y384, Y387, Y388,Y393, Y394, Y395,Y398, Y398a,Y399,Y399a,Y400, Y401, Y402,Y404, Y410, Y411`): print(`Y360,Y360a, Y361,Y362,Y365,Y365a,Y369,Y371,Y372,Y373,Y375,Y377,Y379, Y380, Y382, Y382a, Y383,Y384,Y387, &388, Y391, Y393,`): print(`Y394,Y395,Y398,Y398a,Y399, Y400, Y401,Y402,Y404,Y410,Y411, Y412, Y415, Y416, Y416a, Y418, Y420, Y421, Y422, Y423, Y424,`): print(`Y426, Y427, Y428, Y428a, Y430, Y431, Y432, Y432a, Y433, Y434, Y435, Y436, Y438, Y439, Y440, Y441, Y442,`): print(`Y433, Y433a, Y444, Y445, Y446, Y448, Y448a, Y449, Y450, Y451, Y452, Y454, Y455, Y456, Y457, Y458, Y459, Y460, Y461, Y463,`): print(`Y464,Y465,Y466,Y467, Y469, Y471, Y472, Y473, Y473a, Y474, Y475, Y476, Y477`): print(`Y479,Y482,Y483,Y484,Y484a,Y486,Y487,Y488,Y489,Y491,Y492,Y493,Y494,Y495,Y496,Y498,Y500,Y501,Y501a,Y502,Y504,Y506,Y507,Y510,`): print(`Y511,Y513,Y514,Y515,Y516,Y517,Y518,Y519,Y519a,Y520`): 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(`Y363,Y364,Y366,Y381, Y389,Y390,Y392,Y405,Y409 `): print(`Mate-in-4-moves Ha3 (too long for my computer), Y302, Y309 `): print(`Y346, Y347, Y351, Y357, Y358`): print(`Mate-in-5-moves Ha11`): end: ezra:=proc() if args=NULL then print(`The Main Procedures are: `): print(` MATE, MATEv, MATEvv, MateInTwo, MateInTwoS,`): print(`For help with a specific procedure, type`): print(`ezra(Procedure_Name);, for example ezra(MATE);`): elif nops([args])=1 and op(1,[args])=BlackLost then print(`BlackLost(POS): Did Black Lose?`): elif nops([args])=1 and op(1,[args])=BlackMoves then print(`BlackMoves(POS): all the legal moves of Black`): elif 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]]);`): elif 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`): elif 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`): elif nops([args])=1 and op(1,[args])=IsStallMate then print(`IsStallMate(POS): Is it a stall-mate?`): elif 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);`): elif 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`): elif 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"`): elif nops([args])=1 and op(1,[args])=MateInTwo then print(`MateInTwo(POS): compact form of displaying the solution for`): print(`Mate in-two-probems. `): elif nops([args])=1 and op(1,[args])=MateInTwoS then print(`MateInTwoS(POS): displays the solutions of`): print(`Mate in-two-probems in standard Chess notation, with threat. `): elif 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);`): elif 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);`): elif 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);`): elif nops([args])=1 and op(1,[args])=PICT then print(`PICT(POS): draws the position in terms of a matrix`): elif 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`): elif 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]);`): elif 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`): elif nops([args])=1 and op(1,[args])=RandGameV then print(`RandGameV(): A random game, Verbose style`): elif 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); `): elif 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);`): elif 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);`): elif 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);`): elif nops([args])=1 and op(1,[args])=Threat2 then print(`Threat2(P): the threat of a two-mover, if it exists`): print(`Try:`): print(`Threat2(AlgToNum(Y477));`): elif nops([args])=1 and op(1,[args])=WhiteLost then print(`WhiteLost(POS): Did White Lose?`): elif nops([args])=1 and op(1,[args])=WhiteMoves then print(`WhiteMoves(POS): all the legal moves of White`): elif nops([args])=1 and op(1,[args])=WinningMove0W then print(`WinningMove0W(POS): Can White Win right away?`): else print(`There is no ezra for`, args[1][1] ): 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, Threat2, 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,wN,wB,wR,wK,wQ, bP,bN,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]:=wN: 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]:=bN: 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: Tar1a:=proc(i): if abs(i)=1 then (``): elif abs(i)=2 then (`N`): elif abs(i)=3 then (`B`): elif abs(i)=4 then (`R`): elif abs(i)=5 then (`Q`): elif abs(i)=6 then (`K`): 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: #Targem1(move1): translates the move move1 to human language #short version Targem1:=proc(move1) cat(Tar1a(move1[1]),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: #MateInTwoNP(POS): compact form of displaying the solution for #Mate in-two-probems. without pictures MateInTwoNP:=proc(POS1) local lu,WM,S,CheckMates, BlackMoves,T,cm,i, BM1,bm1,POS,a,POS2: POS:=AlgToNum(POS1); if MateInk1(POS,1)[1] then print(`Mate-In-One`): RETURN(FAIL): fi: lu:=MateInk1(POS,2): if not lu[1] then print(`Not Mate-In-Two`): RETURN(FAIL): fi: WM:=lu[2][1]: S:=lu[2][2]: CheckMates:={seq(S[i][3][1],i=1..nops(S))}: BlackMoves:={seq(S[i][2],i=1..nops(S))}: for cm in CheckMates do T[cm]:={}: od: for i from 1 to nops(S) do T[S[i][3][1]]:= T[S[i][3][1]] union {S[i][2]}: od: print(`White can win in two moves with the move:`, Targem(WM)): POS2:=ExecMove(POS,WM): print(`Black has`, nops(BlackMoves), `possible legal counter-moves. each of them leading to a checkmate`): for cm in CheckMates do BM1:=T[cm]: BM1:=Tsamek(BM1); if nops(BM1)>1 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: #Threat2(P): the threat of a two-mover, if it exists #Try: #Threat2(AlgToNum(Y477)); Threat2:=proc(P) local i,gu,mu, mu1,T,aluf,si,WM,P1,P2,ku: option remember: if not MateInk1(P,2)[1] then FAIL: else ku:=MateInk1(P,2)[2][2]: gu:=[seq(ku[i][3][1],i=1..nops(ku))]; fi: mu:=convert(gu,set): for mu1 in mu do T[mu1]:=0: od: for i from 1 to nops(gu) do T[gu[i]]:= T[gu[i]]+1: od: aluf:=mu[1]: si:=T[mu[1]]: for i from 2 to nops(mu) do if T[mu[i]]>si then aluf:=mu[i]: si:=T[mu[i]]: fi: od: WM:=MateInk1(P,2)[2][1]: P1:=ExecMove(P,WM): P2:=ExecMove(P1,aluf): if IsCheckMate(P2)[1] then RETURN(aluf): else RETURN(FAIL): fi: end: #MateInTwoST(POS): short form of displaying the solution for #Mate in-two-probems when there is a threat. without pictures MateInTwoST:=proc(POS1) local lu,WM,S,CheckMates, BlackMoves,T,cm,i, BM1,bm1,POS,a,POS2,Thr2: PIC(POS1): print(`--------------------------------------------------------`): print(``):print(``):print(``):print(``):print(``):print(``): print(`Solution:`): POS:=AlgToNum(POS1); Thr2:=Threat2(POS): if Thr2=FAIL then MateInTwoS(POS1): RETURN(): fi: if MateInk1(POS,1)[1] then print(`Mate-In-One`): RETURN(FAIL): fi: lu:=MateInk1(POS,2): if not lu[1] then print(`Not Mate-In-Two`): RETURN(FAIL): fi: WM:=lu[2][1]: S:=lu[2][2]: CheckMates:={seq(S[i][3][1],i=1..nops(S))}: BlackMoves:={seq(S[i][2],i=1..nops(S))}: for cm in CheckMates do T[cm]:={}: od: for i from 1 to nops(S) do T[S[i][3][1]]:= T[S[i][3][1]] union {S[i][2]}: od: print(cat(`1.`,Targem1(WM))): print(``): print(cat(`..1.Threat`,` 2.`,Targem1(Thr2))): print(``): POS2:=ExecMove(POS,WM): for cm in CheckMates do BM1:=T[cm]: BM1:=Tsamek(BM1); for i from 1 to nops(BM1) do bm1:=BM1[i]: for a in bm1[2] do if cm<>Thr2 then print(cat(`..1.`,Tar1a(bm1[1][1]),Tar2(a),` 2.`,Targem1(cm))): fi: od: od: od: end: #MateInTwoS(POS): the abbreviated solution to a Mate In Two problem. Try: #MateInTwoS(E30): MateInTwoS:=proc(POS) local lu,i1,P,Iyum,P1,Mo,P2,mu: P:=AlgToNum(POS): lu:=MateInk1(P,2): if not lu[1] then RETURN(FAIL): fi: lu:=lu[2]: lu:=[lu[1], [seq([lu[2][i1][2],lu[2][i1][3][1]],i1=1..nops(lu[2]) ) ]] : Iyum:={}: P1:=ExecMove(P,lu[1]): for i1 from 1 to nops(lu[2]) do Mo:=lu[2][i1][2]: P2:=ExecMove(P1,Mo): if P2<>FAIL and member(Mo,WhiteMoves(P1)) and IsCheckMate(P2)[1] then Iyum:=Iyum union {Mo}: fi: od: mu:=[[lu[1],Iyum] ]: for i1 from 1 to nops(lu[2]) do if not member(lu[2][i1][2],Iyum) then mu:=[op(mu), lu[2][i1]]: fi: od: mu: if nops(mu[1][2])=0 then if IsCheck(P1) then print(cat(`1.`,Targem1(mu[1][1]), ` ; Check` )): else print(cat(`1.`,Targem1(mu[1][1]), ` ; Zugzwang ` )): fi: elif nops(mu[1][2])=1 then print(cat(`1.`,Targem1(mu[1][1]), ` Threat:`, Targem1(mu[1][2][1]) ) ): else print(cat(`1.`,Targem1(mu[1][1]), ` Threats:`, seq(op([Targem1(mu[1][2][i1]), ` ` ]), i1=1..nops(mu[1][2]) ) ) ): fi: for i1 from 2 to nops(mu) do print(cat(`..1.`, Targem1(mu[i1][1]), ` 2. `, Targem1(mu[i1][2])) ): od: end: