X-Git-Url: https://git.auder.net/?a=blobdiff_plain;f=client%2Fsrc%2Fvariants%2FChakart.js;h=1d12e42ec6e65b455fec6d1596e8e21475c9e74f;hb=e50a802531b99829c533f22ecd21e359e7e1e049;hp=53af2c464b58156c8e1bd689d520d764049db7fa;hpb=77fc0c65efaa226730bb8dc2323c22810e5d4fc0;p=vchess.git diff --git a/client/src/variants/Chakart.js b/client/src/variants/Chakart.js index 53af2c46..1d12e42e 100644 --- a/client/src/variants/Chakart.js +++ b/client/src/variants/Chakart.js @@ -114,6 +114,7 @@ export class ChakartRules extends ChessRules { } getPPpath(m) { + if (!!m.promoteInto) return m.promoteInto; let piece = m.appear[0].p; if (Object.keys(V.IMMOBILIZE_DECODE).includes(piece)) piece = V.IMMOBILIZE_DECODE[piece]; @@ -147,14 +148,14 @@ export class ChakartRules extends ChessRules { if (['K', 'k', 'L', 'l'].includes(row[i])) kings[row[i]]++; if (V.PIECES.includes(row[i].toLowerCase())) sumElts++; else { - const num = parseInt(row[i]); + const num = parseInt(row[i], 10); if (isNaN(num)) return false; sumElts += num; } } if (sumElts != V.size.y) return false; } - if (kings['k'] + kings['l'] != 1 || kings['K'] + kings['L'] != 1) + if (kings['k'] + kings['l'] == 0 || kings['K'] + kings['L'] == 0) return false; return true; } @@ -209,24 +210,25 @@ export class ChakartRules extends ChessRules { setOtherVariables(fen) { super.setOtherVariables(fen); - const fenParsed = V.ParseFen(fen); // Initialize captured pieces' counts from FEN + const captured = + V.ParseFen(fen).captured.split("").map(x => parseInt(x, 10)); this.captured = { w: { - [V.ROOK]: parseInt(fenParsed.captured[0]), - [V.KNIGHT]: parseInt(fenParsed.captured[1]), - [V.BISHOP]: parseInt(fenParsed.captured[2]), - [V.QUEEN]: parseInt(fenParsed.captured[3]), - [V.KING]: parseInt(fenParsed.captured[4]), - [V.PAWN]: parseInt(fenParsed.captured[5]), + [V.PAWN]: captured[0], + [V.ROOK]: captured[1], + [V.KNIGHT]: captured[2], + [V.BISHOP]: captured[3], + [V.QUEEN]: captured[4], + [V.KING]: captured[5] }, b: { - [V.ROOK]: parseInt(fenParsed.captured[6]), - [V.KNIGHT]: parseInt(fenParsed.captured[7]), - [V.BISHOP]: parseInt(fenParsed.captured[8]), - [V.QUEEN]: parseInt(fenParsed.captured[9]), - [V.KING]: parseInt(fenParsed.captured[10]), - [V.PAWN]: parseInt(fenParsed.captured[11]), + [V.PAWN]: captured[6], + [V.ROOK]: captured[7], + [V.KNIGHT]: captured[8], + [V.BISHOP]: captured[9], + [V.QUEEN]: captured[10], + [V.KING]: captured[11] } }; this.firstMove = []; @@ -268,7 +270,11 @@ export class ChakartRules extends ChessRules { const end = (color == 'b' && p == V.PAWN ? 7 : 8); for (let i = start; i < end; i++) { for (let j = 0; j < V.size.y; j++) { - if (this.board[i][j] == V.EMPTY || this.getColor(i, j) == 'a') { + if ( + this.board[i][j] == V.EMPTY || + this.getColor(i, j) == 'a' || + this.getPiece(i, j) == V.INVISIBLE_QUEEN + ) { let m = this.getBasicMove({ p: p, x: i, y: j}); m.start = { x: x, y: y }; moves.push(m); @@ -315,7 +321,6 @@ export class ChakartRules extends ChessRules { const L = this.firstMove.length; const fm = this.firstMove[L-1]; switch (fm.end.effect) { - // case 0: a click is required (banana or bomb) case "kingboo": // Exchange position with any piece, // except pawns if arriving on last rank. @@ -365,11 +370,12 @@ export class ChakartRules extends ChessRules { // Helper for getBasicMove() getRandomSquare([x, y], steps) { + const color = this.turn; const validSteps = steps.filter(s => { const [i, j] = [x + s[0], y + s[1]]; return ( V.OnBoard(i, j) && - (this.board[i][j] == V.EMPTY || this.getColor(i, j) == 'a') + (this.board[i][j] == V.EMPTY || this.getColor(i, j) != color) ); }); if (validSteps.length == 0) @@ -386,16 +392,19 @@ export class ChakartRules extends ChessRules { if (piece == V.PAWN) { const forward = (color == 'w' ? -1 : 1); return ( - this.board[x + forward][y] != oppCol || + V.OnBoard(x + forward, y) && ( - V.OnBoard(x + forward, y + 1) && - this.board[x + forward][y + 1] != V.EMPTY && - this.getColor[x + forward, y + 1] == oppCol - ) || - ( - V.OnBoard(x + forward, y - 1) && - this.board[x + forward][y - 1] != V.EMPTY && - this.getColor[x + forward, y - 1] == oppCol + this.board[x + forward][y] != oppCol || + ( + V.OnBoard(x + forward, y + 1) && + this.board[x + forward][y + 1] != V.EMPTY && + this.getColor[x + forward, y + 1] == oppCol + ) || + ( + V.OnBoard(x + forward, y - 1) && + this.board[x + forward][y - 1] != V.EMPTY && + this.getColor[x + forward, y - 1] == oppCol + ) ) ); } @@ -421,7 +430,7 @@ export class ChakartRules extends ChessRules { getBasicMove_aux(psq1, sq2, tr, initMove) { const [x1, y1] = [psq1.x, psq1.y]; const color1 = this.turn; - const piece1 = psq1.p || this.getPiece(x1, y1); + const piece1 = (!!tr ? tr.p : (psq1.p || this.getPiece(x1, y1))); const oppCol = V.GetOppCol(color1); if (!sq2) { let move = { @@ -458,6 +467,7 @@ export class ChakartRules extends ChessRules { const [x2, y2] = [sq2[0], sq2[1]]; // The move starts normally, on board: let move = super.getBasicMove([x1, y1], [x2, y2], tr); + if (!!tr) move.promoteInto = tr.c + tr.p; //in case of (chomped...) const L = this.firstMove.length; if ( [V.PAWN, V.KNIGHT].includes(piece1) && @@ -819,6 +829,7 @@ export class ChakartRules extends ChessRules { // start is wrong for Toadette moves --> it's fixed later move.start = { x: psq1.x, y: psq1.y }; move.end = !!sq2 ? { x: sq2[0], y: sq2[1] } : { x: psq1.x, y: psq1.y }; + if (!!tr) move.promoteInto = moves[0].promoteInto; let lm = moves[moves.length-1]; if (this.subTurn == 1 && !!lm.end.effect) move.end.effect = lm.end.effect; @@ -1194,37 +1205,42 @@ export class ChakartRules extends ChessRules { } else if (move.appear[0].p == V.INVISIBLE_QUEEN) this.powerFlags[move.appear[0].c][V.QUEEN] = false; - if (move.turn[1] == 2) return; + if (this.subTurn == 2) return; if ( + move.turn[1] == 1 && move.appear.length == 0 || !(Object.keys(V.IMMOBILIZE_DECODE).includes(move.appear[0].p)) ) { // Look for an immobilized piece of my color: it can now move - // Also make opponent invisible queen visible again, if any - const oppCol = V.GetOppCol(color); for (let i=0; i<8; i++) { for (let j=0; j<8; j++) { if (this.board[i][j] != V.EMPTY) { - const colIJ = this.getColor(i, j); const piece = this.getPiece(i, j); if ( - colIJ == color && + this.getColor(i, j) == color && Object.keys(V.IMMOBILIZE_DECODE).includes(piece) ) { this.board[i][j] = color + V.IMMOBILIZE_DECODE[piece]; move.wasImmobilized = [i, j]; } - else if ( - colIJ == oppCol && - piece == V.INVISIBLE_QUEEN - ) { - this.board[i][j] = oppCol + V.QUEEN; - move.wasInvisible = [i, j]; - } } } } } + // Also make opponent invisible queen visible again, if any + const oppCol = V.GetOppCol(color); + for (let i=0; i<8; i++) { + for (let j=0; j<8; j++) { + if ( + this.board[i][j] != V.EMPTY && + this.getColor(i, j) == oppCol && + this.getPiece(i, j) == V.INVISIBLE_QUEEN + ) { + this.board[i][j] = oppCol + V.QUEEN; + move.wasInvisible = [i, j]; + } + } + } } undo(move) { @@ -1305,10 +1321,45 @@ export class ChakartRules extends ChessRules { return moves; } + static get VALUES() { + return Object.assign( + {}, + ChessRules.VALUES, + { + s: 1, + u: 5, + o: 3, + c: 3, + t: 9, + l: 1000, + e: 0, + d: 0, + w: 0, + m: 0 + } + ); + } + + static get SEARCH_DEPTH() { + return 1; + } + getComputerMove() { - // Random mover: const moves = this.getAllValidMoves(); - let move1 = moves[randInt(moves.length)]; + // Split into "normal" and "random" moves: + // (Next splitting condition is OK because cannot take self object + // without a banana or bomb on the way). + const deterministicMoves = moves.filter(m => { + return m.vanish.every(a => a.c != 'a' || a.p == V.MUSHROOM); + }); + const randomMoves = moves.filter(m => { + return m.vanish.some(a => a.c == 'a' && a.p != V.MUSHROOM); + }); + if (Math.random() < deterministicMoves.length / randomMoves.length) + // Play a deterministic one: capture king or material if possible + return super.getComputerMove(deterministicMoves); + // Play a random effect move, at random: + let move1 = randomMoves[randInt(randomMoves.length)]; this.play(move1); let move2 = undefined; if (this.subTurn == 2) { @@ -1351,14 +1402,19 @@ export class ChakartRules extends ChessRules { ) ); } - if ( - move.appear.length == 1 && - move.vanish.length == 1 && - move.appear[0].c == 'a' && - move.vanish[0].c == 'a' - ) { - // Bonus replacement: - return move.appear[0].p.toUpperCase() + "@" + finalSquare; + if (move.appear.length == 1 && move.vanish.length == 1) { + const moveStart = move.appear[0].p.toUpperCase() + "@"; + if (move.appear[0].c == 'a' && move.vanish[0].c == 'a') + // Bonus replacement: + return moveStart + finalSquare; + if ( + move.vanish[0].p == V.INVISIBLE_QUEEN && + move.appear[0].x == move.vanish[0].x && + move.appear[0].y == move.vanish[0].y + ) { + // Toadette takes invisible queen + return moveStart + "Q" + finalSquare; + } } if ( move.appear.length == 2 &&