X-Git-Url: https://git.auder.net/?a=blobdiff_plain;f=client%2Fsrc%2Fbase_rules.js;h=33b0fc9022f6f4a585af32d3d3f534c36f6139e8;hb=6b7b2cf720e6255e4da0dc34fee363c456346a58;hp=d2b8a7fd98e1dab4d6531d6522687afd1fd37b7a;hpb=f35b9960e1c527fc400ebac85321bd4712459da3;p=vchess.git diff --git a/client/src/base_rules.js b/client/src/base_rules.js index d2b8a7fd..33b0fc90 100644 --- a/client/src/base_rules.js +++ b/client/src/base_rules.js @@ -197,13 +197,10 @@ export const ChessRules = class ChessRules { const move = moveOrSquare; const s = move.start, e = move.end; - // NOTE: next conditions are first for Atomic, and last for Checkered if ( - move.appear.length > 0 && Math.abs(s.x - e.x) == 2 && s.y == e.y && - move.appear[0].p == V.PAWN && - ["w", "b"].includes(move.appear[0].c) + move.appear[0].p == V.PAWN ) { return { x: (s.x + e.x) / 2, @@ -319,16 +316,24 @@ export const ChessRules = class ChessRules { // Return current fen (game state) getFen() { return ( - this.getBaseFen() + - " " + - this.getTurnFen() + - " " + + this.getBaseFen() + " " + + this.getTurnFen() + " " + this.movesCount + (V.HasFlags ? " " + this.getFlagsFen() : "") + (V.HasEnpassant ? " " + this.getEnpassantFen() : "") ); } + getFenForRepeat() { + // Omit movesCount, only variable allowed to differ + return ( + this.getBaseFen() + "_" + + this.getTurnFen() + + (V.HasFlags ? "_" + this.getFlagsFen() : "") + + (V.HasEnpassant ? "_" + this.getEnpassantFen() : "") + ); + } + // Position part of the FEN string getBaseFen() { let position = ""; @@ -423,6 +428,7 @@ export const ChessRules = class ChessRules { this.INIT_COL_ROOK = { w: [-1, -1], b: [-1, -1] }; this.kingPos = { w: [-1, -1], b: [-1, -1] }; //squares of white and black king const fenRows = V.ParseFen(fen).position.split("/"); + const startRow = { 'w': V.size.x - 1, 'b': 0 }; for (let i = 0; i < fenRows.length; i++) { let k = 0; //column index on board for (let j = 0; j < fenRows[i].length; j++) { @@ -436,12 +442,16 @@ export const ChessRules = class ChessRules { this.INIT_COL_KING["w"] = k; break; case "r": - if (this.INIT_COL_ROOK["b"][0] < 0) this.INIT_COL_ROOK["b"][0] = k; - else this.INIT_COL_ROOK["b"][1] = k; + if (i == startRow['b']) { + if (this.INIT_COL_ROOK["b"][0] < 0) this.INIT_COL_ROOK["b"][0] = k; + else this.INIT_COL_ROOK["b"][1] = k; + } break; case "R": - if (this.INIT_COL_ROOK["w"][0] < 0) this.INIT_COL_ROOK["w"][0] = k; - else this.INIT_COL_ROOK["w"][1] = k; + if (i == startRow['w']) { + if (this.INIT_COL_ROOK["w"][0] < 0) this.INIT_COL_ROOK["w"][0] = k; + else this.INIT_COL_ROOK["w"][1] = k; + } break; default: { const num = parseInt(fenRows[i].charAt(j)); @@ -636,7 +646,6 @@ export const ChessRules = class ChessRules { const firstRank = color == "w" ? sizeX - 1 : 0; const startRank = color == "w" ? sizeX - 2 : 1; const lastRank = color == "w" ? 0 : sizeX - 1; - const pawnColor = this.getColor(x, y); //can be different for checkered // NOTE: next condition is generally true (no pawn on last rank) if (x + shiftX >= 0 && x + shiftX < sizeX) { @@ -649,7 +658,7 @@ export const ChessRules = class ChessRules { for (let piece of finalPieces) { moves.push( this.getBasicMove([x, y], [x + shiftX, y], { - c: pawnColor, + c: color, p: piece }) ); @@ -674,7 +683,7 @@ export const ChessRules = class ChessRules { for (let piece of finalPieces) { moves.push( this.getBasicMove([x, y], [x + shiftX, y + shiftY], { - c: pawnColor, + c: color, p: piece }) ); @@ -992,7 +1001,7 @@ export const ChessRules = class ChessRules { // After move is played, update variables + flags updateVariables(move) { let piece = undefined; - // TODO: update variables before move is played, and just use this.turn ? + // TODO: update variables before move is played, and just use this.turn? // (doesn't work in general, think MarseilleChess) let c = undefined; if (move.vanish.length >= 1) { @@ -1049,7 +1058,7 @@ export const ChessRules = class ChessRules { play(move) { // DEBUG: // if (!this.states) this.states = []; -// const stateFen = this.getBaseFen() + this.getTurnFen() + this.getFlagsFen(); +// const stateFen = this.getBaseFen() + this.getTurnFen();// + this.getFlagsFen(); // this.states.push(stateFen); if (V.HasFlags) move.flags = JSON.stringify(this.aggregateFlags()); //save flags (for undo) @@ -1069,7 +1078,7 @@ export const ChessRules = class ChessRules { this.unupdateVariables(move); // DEBUG: -// const stateFen = this.getBaseFen() + this.getTurnFen() + this.getFlagsFen(); +// const stateFen = this.getBaseFen() + this.getTurnFen();// + this.getFlagsFen(); // if (stateFen != this.states[this.states.length-1]) debugger; // this.states.pop(); } @@ -1124,16 +1133,18 @@ export const ChessRules = class ChessRules { getComputerMove() { const maxeval = V.INFINITY; const color = this.turn; - // Some variants may show a bigger moves list to the human (Switching), - // thus the argument "computer" below (which is generally ignored) let moves1 = this.getAllValidMoves(); if (moves1.length == 0) // TODO: this situation should not happen return null; - // Rank moves using a min-max at depth 2 + // Rank moves using a min-max at depth 2 (if search_depth >= 2!) for (let i = 0; i < moves1.length; i++) { + if (V.SEARCH_DEPTH == 1) { + moves1[i].eval = this.evalPosition(); + continue; + } // Initial self evaluation is very low: "I'm checkmated" moves1[i].eval = (color == "w" ? -1 : 1) * maxeval; this.play(moves1[i]); @@ -1181,19 +1192,9 @@ export const ChessRules = class ChessRules { }); // console.log(moves1.map(m => { return [this.getNotation(m), m.eval]; })); - let candidates = [0]; //indices of candidates moves - for (let j = 1; j < moves1.length && moves1[j].eval == moves1[0].eval; j++) - candidates.push(j); - let currentBest = moves1[candidates[randInt(candidates.length)]]; - // Skip depth 3+ if we found a checkmate (or if we are checkmated in 1...) if (V.SEARCH_DEPTH >= 3 && Math.abs(moves1[0].eval) < V.THRESHOLD_MATE) { - // From here, depth >= 3: may take a while, so we control time - const timeStart = Date.now(); for (let i = 0; i < moves1.length; i++) { - if (Date.now() - timeStart >= 5000) - //more than 5 seconds - return currentBest; //depth 2 at least this.play(moves1[i]); // 0.1 * oldEval : heuristic to avoid some bad moves (not all...) moves1[i].eval = @@ -1204,10 +1205,9 @@ export const ChessRules = class ChessRules { moves1.sort((a, b) => { return (color == "w" ? 1 : -1) * (b.eval - a.eval); }); - } else return currentBest; -// console.log(moves1.map(m => { return [this.getNotation(m), m.eval]; })); + } - candidates = [0]; + let candidates = [0]; for (let j = 1; j < moves1.length && moves1[j].eval == moves1[0].eval; j++) candidates.push(j); return moves1[candidates[randInt(candidates.length)]];