X-Git-Url: https://git.auder.net/?a=blobdiff_plain;f=public%2Fjavascripts%2Fvariants%2FDark.js;h=f1bd6c0d5c7b9423118a21ce5f4a544945093ba0;hb=69f3d8014e594ef949792d04d97b8286e9c2c268;hp=9cf50513f5ce06b3e2d97ef2cd091a648fa77d16;hpb=375ecdd1387e729f85ed114e82253469e4849869;p=vchess.git diff --git a/public/javascripts/variants/Dark.js b/public/javascripts/variants/Dark.js index 9cf50513..f1bd6c0d 100644 --- a/public/javascripts/variants/Dark.js +++ b/public/javascripts/variants/Dark.js @@ -1,25 +1,75 @@ -class Chess960Rules extends ChessRules +class DarkRules extends ChessRules { // Standard rules, in the shadow setOtherVariables(fen) { super.setOtherVariables(fen); - const [sizeX,sizeY] = {V.size.x,V.size.y}; + const [sizeX,sizeY] = [V.size.x,V.size.y]; this.enlightened = { - "w": doubleArray(sizeX,sizeY,false), - "b": doubleArray(sizeX,sizeY,false) + "w": doubleArray(sizeX,sizeY), + "b": doubleArray(sizeX,sizeY) }; - setup enlightened: squares reachable by each side (TODO: one side would be enough) + // Setup enlightened: squares reachable by each side + // (TODO: one side would be enough ?) + this.updateEnlightened(); } - isEnlightened(x, y, color) + updateEnlightened() { - //TODO: artificlaly change turn + const pawnShift = {"w":-1, "b":1}; + // Initialize with pieces positions (which are seen) + for (let i=0; i but isEnlightened() should have its variable updated - // --> in fact an array is enough (no need for a function) - // recomputed after every play/undo (although there are no undo here for now) + updateVariables(move) + { + super.updateVariables(move); + if (move.vanish.length >= 2 && move.vanish[1].p == V.KING) + { + // We took opponent king ! + this.kingPos[this.turn] = [-1,-1]; + } + + // Update moves for both colors: + this.updateEnlightened(); + } + + unupdateVariables(move) + { + super.unupdateVariables(move); + const c = move.vanish[0].c; + const oppCol = this.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 moves for both colors: + this.updateEnlightened(); + } checkGameEnd() { @@ -62,6 +134,150 @@ class Chess960Rules extends ChessRules { 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 = this.getOppCol(color); + const pawnShift = (color == "w" ? -1 : 1); + const kp = this.kingPos[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) => { + 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]) + { + 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 = () => { + 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); + if (!!move.eval) + continue; + + 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); + } + } + } + + // 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