X-Git-Url: https://git.auder.net/?a=blobdiff_plain;f=public%2Fjavascripts%2Fbase_rules.js;h=f466624d653ebc5ec50e46036c7c3785ecb4b82d;hb=a37076f1ac8f4c19d9b34a60cbe89df86b88fa0b;hp=ec5f9372f826e15ea1f0b4848e001f67101c03fb;hpb=0f51ef985c094530a63d242dddf514e66d23959b;p=vchess.git diff --git a/public/javascripts/base_rules.js b/public/javascripts/base_rules.js index ec5f9372..f466624d 100644 --- a/public/javascripts/base_rules.js +++ b/public/javascripts/base_rules.js @@ -171,7 +171,6 @@ class ChessRules 'r': [ [-1,0],[1,0],[0,-1],[0,1] ], 'n': [ [-1,-2],[-1,2],[1,-2],[1,2],[-2,-1],[-2,1],[2,-1],[2,1] ], 'b': [ [-1,-1],[-1,1],[1,-1],[1,1] ], - 'q': [ [-1,0],[1,0],[0,-1],[0,1],[-1,-1],[-1,1],[1,-1],[1,1] ] }; } @@ -379,14 +378,17 @@ class ChessRules // What are the queen moves from square x,y ? getPotentialQueenMoves(sq) { - return this.getSlideNJumpMoves(sq, VariantRules.steps[VariantRules.QUEEN]); + const V = VariantRules; + return this.getSlideNJumpMoves(sq, V.steps[V.ROOK].concat(V.steps[V.BISHOP])); } // What are the king moves from square x,y ? getPotentialKingMoves(sq) { + const V = VariantRules; // Initialize with normal moves - let moves = this.getSlideNJumpMoves(sq, VariantRules.steps[VariantRules.QUEEN], "oneStep"); + let moves = this.getSlideNJumpMoves(sq, + V.steps[V.ROOK].concat(V.steps[V.BISHOP]), "oneStep"); return moves.concat(this.getCastleMoves(sq)); } @@ -479,8 +481,7 @@ class ChessRules { if (moves.length == 0) return []; - let color = this.turn; - return moves.filter(m => { return !this.underCheck(m, color); }); + return moves.filter(m => { return !this.underCheck(m); }); } // Search for all valid moves considering current turn (for engine and game end) @@ -587,15 +588,17 @@ class ChessRules // Is square x,y attacked by queens of color c ? isAttackedByQueen(sq, colors) { - return this.isAttackedBySlideNJump(sq, colors, - VariantRules.QUEEN, VariantRules.steps[VariantRules.QUEEN]); + const V = VariantRules; + return this.isAttackedBySlideNJump(sq, colors, V.QUEEN, + V.steps[V.ROOK].concat(V.steps[V.BISHOP])); } // Is square x,y attacked by king of color c ? isAttackedByKing(sq, colors) { - return this.isAttackedBySlideNJump(sq, colors, - VariantRules.KING, VariantRules.steps[VariantRules.QUEEN], "oneStep"); + const V = VariantRules; + return this.isAttackedBySlideNJump(sq, colors, V.KING, + V.steps[V.ROOK].concat(V.steps[V.BISHOP]), "oneStep"); } // Generic method for non-pawn pieces ("sliding or jumping"): is x,y attacked by piece != color ? @@ -699,6 +702,10 @@ class ChessRules play(move, ingame) { + // DEBUG: +// if (!this.states) this.states = []; +// if (!ingame) this.states.push(JSON.stringify(this.board)); + if (!!ingame) move.notation = this.getNotation(move); @@ -716,6 +723,11 @@ class ChessRules this.moves.pop(); this.unupdateVariables(move); this.parseFlags(JSON.parse(move.flags)); + + // DEBUG: +// let state = this.states.pop(); +// if (JSON.stringify(this.board) != state) +// debugger; } ////////////// @@ -777,18 +789,28 @@ class ChessRules }; } + static get INFINITY() { + return 9999; //"checkmate" (unreachable eval) + } + + static get THRESHOLD_MATE() { + // At this value or above, the game is over + return VariantRules.INFINITY; + } + // Assumption: at least one legal move - getComputerMove() + getComputerMove(moves1) //moves1 might be precomputed (Magnetic chess) { + const maxeval = VariantRules.INFINITY; const color = this.turn; + if (!moves1) + moves1 = this.getAllValidMoves(); // Rank moves using a min-max at depth 2 - let moves1 = this.getAllValidMoves(); - for (let i=0; i { return (color=="w" ? 1 : -1) * (b.eval - a.eval); }); - // TODO: show current analyzed move for depth 3, allow stopping eval (return moves1[0]) - for (let i=0; i { return (color=="w" ? 1 : -1) * (b.eval - a.eval); }); } - moves1.sort( (a,b) => { return (color=="w" ? 1 : -1) * (b.eval - a.eval); }); let candidates = [0]; //indices of candidates moves for (let j=1; j { return [this.getNotation(m), m.eval]; })); return moves1[_.sample(candidates, 1)]; } alphabeta(depth, alpha, beta) { + const maxeval = VariantRules.INFINITY; const color = this.turn; if (!this.atLeastOneMove()) { switch (this.checkGameEnd()) { case "1/2": return 0; - default: return color=="w" ? -1000 : 1000; + default: return color=="w" ? -maxeval : maxeval; } } if (depth == 0) return this.evalPosition(); const moves = this.getAllValidMoves(); - let v = color=="w" ? -1000 : 1000; + let v = color=="w" ? -maxeval : maxeval; if (color == "w") { for (let i=0; i