X-Git-Url: https://git.auder.net/?p=vchess.git;a=blobdiff_plain;f=client%2Fsrc%2Fvariants%2FDark.js;h=c0bfb09ca049876cd4dc25ee5dd3fd7c4aaa3b36;hp=bc14cfa32565bf42af67c707c46c3e3d73fe23c0;hb=dac395887d96e2d642b209c6db6aaacc3ffacb34;hpb=5fde3a01497262862afc4cb4c9457d4e0ad69a4a diff --git a/client/src/variants/Dark.js b/client/src/variants/Dark.js index bc14cfa3..c0bfb09c 100644 --- a/client/src/variants/Dark.js +++ b/client/src/variants/Dark.js @@ -4,295 +4,295 @@ import { randInt } from "@/utils/alea"; export const VariantRules = class DarkRules extends ChessRules { - // Standard rules, in the shadow - setOtherVariables(fen) - { - super.setOtherVariables(fen); - const [sizeX,sizeY] = [V.size.x,V.size.y]; - this.enlightened = { - "w": ArrayFun.init(sizeX,sizeY), - "b": ArrayFun.init(sizeX,sizeY) - }; - // Setup enlightened: squares reachable by each side - // (TODO: one side would be enough ?) - this.updateEnlightened(); - } + // Standard rules, in the shadow + setOtherVariables(fen) + { + super.setOtherVariables(fen); + const [sizeX,sizeY] = [V.size.x,V.size.y]; + this.enlightened = { + "w": ArrayFun.init(sizeX,sizeY), + "b": ArrayFun.init(sizeX,sizeY) + }; + // Setup enlightened: squares reachable by each side + // (TODO: one side would be enough ?) + this.updateEnlightened(); + } - updateEnlightened() - { - for (let i=0; i= 2 && move.vanish[1].p == V.KING) - { - // We took opponent king ! (because if castle vanish[1] is a rook) - this.kingPos[this.turn] = [-1,-1]; - } + updateVariables(move) + { + super.updateVariables(move); + if (move.vanish.length >= 2 && move.vanish[1].p == V.KING) + { + // We took opponent king ! (because if castle vanish[1] is a rook) + this.kingPos[this.turn] = [-1,-1]; + } - // Update lights for both colors: - this.updateEnlightened(); - } + // Update lights for both colors: + this.updateEnlightened(); + } - unupdateVariables(move) - { - super.unupdateVariables(move); - const c = move.vanish[0].c; - const oppCol = V.GetOppCol(c); - if (this.kingPos[oppCol][0] < 0) - { - // Last move took opponent's king - for (let psq of move.vanish) - { - if (psq.p == 'k') - { - this.kingPos[oppCol] = [psq.x, psq.y]; - break; - } - } - } + unupdateVariables(move) + { + super.unupdateVariables(move); + const c = move.vanish[0].c; + const oppCol = V.GetOppCol(c); + if (this.kingPos[oppCol][0] < 0) + { + // Last move took opponent's king + for (let psq of move.vanish) + { + if (psq.p == 'k') + { + this.kingPos[oppCol] = [psq.x, psq.y]; + break; + } + } + } - // Update lights for both colors: - this.updateEnlightened(); - } + // Update lights for both colors: + this.updateEnlightened(); + } getCurrentScore() { - const color = this.turn; - const kp = this.kingPos[color]; - if (kp[0] < 0) //king disappeared - return (color == "w" ? "0-1" : "1-0"); + const color = this.turn; + const kp = this.kingPos[color]; + if (kp[0] < 0) //king disappeared + return (color == "w" ? "0-1" : "1-0"); if (this.atLeastOneMove()) // game not over return "*"; return "1/2"; //no moves but kings still there (seems impossible) - } + } - static get THRESHOLD_MATE() - { - return 500; //checkmates evals may be slightly below 1000 - } + static get THRESHOLD_MATE() + { + return 500; //checkmates evals may be slightly below 1000 + } - // In this special situation, we just look 1 half move ahead - getComputerMove() - { - const maxeval = V.INFINITY; - const color = this.turn; - const oppCol = V.GetOppCol(color); - const pawnShift = (color == "w" ? -1 : 1); + // In this special situation, we just look 1 half move ahead + getComputerMove() + { + const maxeval = V.INFINITY; + const color = this.turn; + const oppCol = V.GetOppCol(color); + const pawnShift = (color == "w" ? -1 : 1); - // Do not cheat: the current enlightment is all we can see - const myLight = JSON.parse(JSON.stringify(this.enlightened[color])); + // Do not cheat: the current enlightment is all we can see + const myLight = JSON.parse(JSON.stringify(this.enlightened[color])); - // Can a slider on (i,j) apparently take my king? - // NOTE: inaccurate because assume yes if some squares are shadowed - const sliderTake = ([i,j], piece) => { - const kp = this.kingPos[color]; - let step = undefined; - if (piece == V.BISHOP) - { - if (Math.abs(kp[0] - i) == Math.abs(kp[1] - j)) - { - step = - [ - (i-kp[0]) / Math.abs(i-kp[0]), - (j-kp[1]) / Math.abs(j-kp[1]) - ]; - } - } - else if (piece == V.ROOK) - { - if (kp[0] == i) - step = [0, (j-kp[1]) / Math.abs(j-kp[1])]; - else if (kp[1] == j) - step = [(i-kp[0]) / Math.abs(i-kp[0]), 0]; - } - if (!step) - return false; - // Check for obstacles - let obstacle = false; - for ( + // Can a slider on (i,j) apparently take my king? + // NOTE: inaccurate because assume yes if some squares are shadowed + const sliderTake = ([i,j], piece) => { + const kp = this.kingPos[color]; + let step = undefined; + if (piece == V.BISHOP) + { + if (Math.abs(kp[0] - i) == Math.abs(kp[1] - j)) + { + step = + [ + (i-kp[0]) / Math.abs(i-kp[0]), + (j-kp[1]) / Math.abs(j-kp[1]) + ]; + } + } + else if (piece == V.ROOK) + { + if (kp[0] == i) + step = [0, (j-kp[1]) / Math.abs(j-kp[1])]; + else if (kp[1] == j) + step = [(i-kp[0]) / Math.abs(i-kp[0]), 0]; + } + if (!step) + return false; + // Check for obstacles + let obstacle = false; + for ( let x=kp[0]+step[0], y=kp[1]+step[1]; - x != i && y != j; - x += step[0], y += step[1]) + x != i && y != j; + x += step[0], y += step[1]) { - if (myLight[x][y] && this.board[x][y] != V.EMPTY) - { - obstacle = true; - break; - } - } - if (!obstacle) - return true; - return false; - }; + if (myLight[x][y] && this.board[x][y] != V.EMPTY) + { + obstacle = true; + break; + } + } + if (!obstacle) + return true; + return false; + }; - // Do I see something which can take my king ? - const kingThreats = () => { - const kp = this.kingPos[color]; - for (let i=0; i { + const kp = this.kingPos[color]; + for (let i=0; i= 0 && kingThreats()) - { - // We didn't take opponent king, and our king will be captured: bad - move.eval = -maxeval; - } - this.undo(move); + let moves = this.getAllValidMoves(); + for (let move of moves) + { + this.play(move); + if (this.kingPos[oppCol][0] >= 0 && kingThreats()) + { + // We didn't take opponent king, and our king will be captured: bad + move.eval = -maxeval; + } + this.undo(move); if (!!move.eval) - continue; + continue; - move.eval = 0; //a priori... + move.eval = 0; //a priori... - // Can I take something ? If yes, do it if it seems good... - if (move.vanish.length == 2 && move.vanish[1].c != color) //avoid castle - { - const myPieceVal = V.VALUES[move.appear[0].p]; - const hisPieceVal = V.VALUES[move.vanish[1].p]; - if (myPieceVal <= hisPieceVal) - move.eval = hisPieceVal - myPieceVal + 2; //favor captures - else - { - // Taking a pawn with minor piece, - // or minor piece or pawn with a rook, - // or anything but a queen with a queen, - // or anything with a king. - // ==> Do it at random, although - // this is clearly inferior to what a human can deduce... - move.eval = (Math.random() < 0.5 ? 1 : -1); - } - } - } + // Can I take something ? If yes, do it if it seems good... + if (move.vanish.length == 2 && move.vanish[1].c != color) //avoid castle + { + const myPieceVal = V.VALUES[move.appear[0].p]; + const hisPieceVal = V.VALUES[move.vanish[1].p]; + if (myPieceVal <= hisPieceVal) + move.eval = hisPieceVal - myPieceVal + 2; //favor captures + else + { + // Taking a pawn with minor piece, + // or minor piece or pawn with a rook, + // or anything but a queen with a queen, + // or anything with a king. + // ==> Do it at random, although + // this is clearly inferior to what a human can deduce... + move.eval = (Math.random() < 0.5 ? 1 : -1); + } + } + } - // TODO: also need to implement the case when an opponent piece (in light) - // is threatening something - maybe not the king, but e.g. pawn takes rook. + // TODO: also need to implement the case when an opponent piece (in light) + // is threatening something - maybe not the king, but e.g. pawn takes rook. - moves.sort((a,b) => b.eval - a.eval); - let candidates = [0]; - for (let j=1; j b.eval - a.eval); + let candidates = [0]; + for (let j=1; j