X-Git-Url: https://git.auder.net/?a=blobdiff_plain;f=client%2Fsrc%2Fvariants%2FCrazyhouse.js;h=eabdd49343d155b5645942a2ecc15061123c5cf4;hb=4313762da3237b04f204e121a20cab3ba7bb5dd2;hp=d7d82b8c48d36e78f34592c024c1f0cad9bc642b;hpb=78d64531113d4b5045ff588dd43f301a332ebae8;p=vchess.git diff --git a/client/src/variants/Crazyhouse.js b/client/src/variants/Crazyhouse.js index d7d82b8c..eabdd493 100644 --- a/client/src/variants/Crazyhouse.js +++ b/client/src/variants/Crazyhouse.js @@ -1,41 +1,53 @@ import { ChessRules, PiPo, Move } from "@/base_rules"; import { ArrayFun } from "@/utils/array"; -export const VariantRules = class CrazyhouseRules extends ChessRules { +export class CrazyhouseRules extends ChessRules { + + static get PawnSpecs() { + return Object.assign( + {}, + ChessRules.PawnSpecs, + // Change names to know that this goes back to pawn after capture: + { promotions: ['u', 'o', 'c', 't'] } + ); + } + + static get PIECES() { + return ChessRules.PIECES.concat(['u', 'o', 'c', 't']); + } + + getPpath(b) { + const prefix = (ChessRules.PIECES.includes(b[1]) ? "" : "Crazyhouse/"); + return prefix + b; + } + static IsGoodFen(fen) { if (!ChessRules.IsGoodFen(fen)) return false; const fenParsed = V.ParseFen(fen); // 5) Check reserves if (!fenParsed.reserve || !fenParsed.reserve.match(/^[0-9]{10,10}$/)) return false; - // 6) Check promoted array - if (!fenParsed.promoted) return false; - if (fenParsed.promoted == "-") return true; //no promoted piece on board - const squares = fenParsed.promoted.split(","); - for (let square of squares) { - const c = V.SquareToCoords(square); - if (c.y < 0 || c.y > V.size.y || isNaN(c.x) || c.x < 0 || c.x > V.size.x) - return false; - } return true; } static ParseFen(fen) { const fenParts = fen.split(" "); - return Object.assign(ChessRules.ParseFen(fen), { - reserve: fenParts[5], - promoted: fenParts[6] - }); + return Object.assign( + ChessRules.ParseFen(fen), + { reserve: fenParts[5] } + ); } - static GenRandInitFen() { - return ChessRules.GenRandInitFen() + " 0000000000 -"; + static GenRandInitFen(options) { + return ChessRules.GenRandInitFen(options) + " 0000000000 -"; } getFen() { - return ( - super.getFen() + " " + this.getReserveFen() + " " + this.getPromotedFen() - ); + return super.getFen() + " " + this.getReserveFen(); + } + + getFenForRepeat() { + return super.getFenForRepeat() + "_" + this.getReserveFen(); } getReserveFen() { @@ -51,46 +63,27 @@ export const VariantRules = class CrazyhouseRules extends ChessRules { return counts.join(""); } - getPromotedFen() { - let res = ""; - for (let i = 0; i < V.size.x; i++) { - for (let j = 0; j < V.size.y; j++) { - if (this.promoted[i][j]) res += V.CoordsToSquare({ x: i, y: j }); - } - } - if (res.length > 0) res = res.slice(0, -1); - //remove last comma - else res = "-"; - return res; - } - setOtherVariables(fen) { super.setOtherVariables(fen); const fenParsed = V.ParseFen(fen); // Also init reserves (used by the interface to show landable pieces) + const reserve = fenParsed.reserve.split("").map(x => parseInt(x, 10)); this.reserve = { w: { - [V.PAWN]: parseInt(fenParsed.reserve[0]), - [V.ROOK]: parseInt(fenParsed.reserve[1]), - [V.KNIGHT]: parseInt(fenParsed.reserve[2]), - [V.BISHOP]: parseInt(fenParsed.reserve[3]), - [V.QUEEN]: parseInt(fenParsed.reserve[4]) + [V.PAWN]: reserve[0], + [V.ROOK]: reserve[1], + [V.KNIGHT]: reserve[2], + [V.BISHOP]: reserve[3], + [V.QUEEN]: reserve[4] }, b: { - [V.PAWN]: parseInt(fenParsed.reserve[5]), - [V.ROOK]: parseInt(fenParsed.reserve[6]), - [V.KNIGHT]: parseInt(fenParsed.reserve[7]), - [V.BISHOP]: parseInt(fenParsed.reserve[8]), - [V.QUEEN]: parseInt(fenParsed.reserve[9]) + [V.PAWN]: reserve[5], + [V.ROOK]: reserve[6], + [V.KNIGHT]: reserve[7], + [V.BISHOP]: reserve[8], + [V.QUEEN]: reserve[9] } }; - this.promoted = ArrayFun.init(V.size.x, V.size.y, false); - if (fenParsed.promoted != "-") { - for (let square of fenParsed.promoted.split(",")) { - const [x, y] = V.SquareToCoords(square); - this.promoted[x][y] = true; - } - } } getColor(i, j) { @@ -98,15 +91,36 @@ export const VariantRules = class CrazyhouseRules extends ChessRules { return this.board[i][j].charAt(0); } + // Pieces types after pawn promotion + static get PromotionMap() { + return { + u: 'r', + o: 'n', + c: 'b', + t: 'q' + }; + } + getPiece(i, j) { if (i >= V.size.x) return V.RESERVE_PIECES[j]; - return this.board[i][j].charAt(1); + const p = this.board[i][j].charAt(1); + if (ChessRules.PIECES.includes(p)) return p; + // Pawn promotion: + return V.PromotionMap[p]; } // Used by the interface: - getReservePpath(color, index) { + getReservePpath(index, color) { return color + V.RESERVE_PIECES[index]; } +// // Version if some day I have pieces with numbers printed on it: +// getReservePpath(index, color) { +// return ( +// "Crazyhouse/" + +// color + V.RESERVE_PIECES[index] + +// "_" + this.vr.reserve[playingColor][V.RESERVE_PIECES[i]] +// ); +// } // Ordering on reserve pieces static get RESERVE_PIECES() { @@ -143,72 +157,68 @@ export const VariantRules = class CrazyhouseRules extends ChessRules { } getPotentialMovesFrom([x, y]) { - if (x >= V.size.x) { + if (x >= V.size.x) // Reserves, outside of board: x == sizeX(+1) return this.getReserveMoves([x, y]); - } // Standard moves return super.getPotentialMovesFrom([x, y]); } getAllValidMoves() { - let moves = super.getAllValidMoves(); + let moves = super.getAllPotentialMoves(); const color = this.turn; - for (let i = 0; i < V.RESERVE_PIECES.length; i++) + for (let i = 0; i < V.RESERVE_PIECES.length; i++) { moves = moves.concat( this.getReserveMoves([V.size.x + (color == "w" ? 0 : 1), i]) ); + } return this.filterValid(moves); } atLeastOneMove() { - if (!super.atLeastOneMove()) { - // Search one reserve move - for (let i = 0; i < V.RESERVE_PIECES.length; i++) { - let moves = this.filterValid( - this.getReserveMoves([V.size.x + (this.turn == "w" ? 0 : 1), i]) - ); - if (moves.length > 0) return true; - } - return false; + if (super.atLeastOneMove()) return true; + // Search one reserve move + for (let i = 0; i < V.RESERVE_PIECES.length; i++) { + const moves = this.filterValid( + this.getReserveMoves([V.size.x + (this.turn == "w" ? 0 : 1), i]) + ); + if (moves.length > 0) return true; } - return true; + return false; } - updateVariables(move) { - super.updateVariables(move); - if (move.vanish.length == 2 && move.appear.length == 2) return; //skip castle + postPlay(move) { + super.postPlay(move); + // Skip castle: + if (move.vanish.length == 2 && move.appear.length == 2) return; const color = move.appear[0].c; if (move.vanish.length == 0) { this.reserve[color][move.appear[0].p]--; return; } - move.movePromoted = this.promoted[move.start.x][move.start.y]; - move.capturePromoted = this.promoted[move.end.x][move.end.y]; - this.promoted[move.start.x][move.start.y] = false; - this.promoted[move.end.x][move.end.y] = - move.movePromoted || - (move.vanish[0].p == V.PAWN && move.appear[0].p != V.PAWN); - if (move.capturePromoted) this.reserve[color][V.PAWN]++; - else if (move.vanish.length == 2) this.reserve[color][move.vanish[1].p]++; - } - - unupdateVariables(move) { - super.unupdateVariables(move); + if (move.vanish.length == 2) { + if (V.PawnSpecs.promotions.includes(move.vanish[1].p)) + this.reserve[color][V.PAWN]++; + else this.reserve[color][move.vanish[1].p]++; + } + } + + postUndo(move) { + super.postUndo(move); if (move.vanish.length == 2 && move.appear.length == 2) return; const color = this.turn; if (move.vanish.length == 0) { this.reserve[color][move.appear[0].p]++; return; } - if (move.movePromoted) this.promoted[move.start.x][move.start.y] = true; - this.promoted[move.end.x][move.end.y] = move.capturePromoted; - if (move.capturePromoted) this.reserve[color][V.PAWN]--; - else if (move.vanish.length == 2) this.reserve[color][move.vanish[1].p]--; + if (move.vanish.length == 2) { + if (V.PawnSpecs.promotions.includes(move.vanish[1].p)) + this.reserve[color][V.PAWN]--; + else this.reserve[color][move.vanish[1].p]--; + } } static get SEARCH_DEPTH() { - // High branching factor return 2; } @@ -226,8 +236,14 @@ export const VariantRules = class CrazyhouseRules extends ChessRules { getNotation(move) { if (move.vanish.length > 0) return super.getNotation(move); // Rebirth: - const piece = - move.appear[0].p != V.PAWN ? move.appear[0].p.toUpperCase() : ""; - return piece + "@" + V.CoordsToSquare(move.end); + let piece = move.appear[0].p; + let prefix = ""; + const endNotation = "@" + V.CoordsToSquare(move.end); + if (piece != V.PAWN) { + if (ChessRules.PIECES.includes(piece)) prefix = piece.toUpperCase(); + else piece = V.PromotionMap[piece].toUpperCase(); + } + return prefix + endNotation; } + };