X-Git-Url: https://git.auder.net/?a=blobdiff_plain;f=variants%2FCheckered%2Fclass.js;h=f73ed0ea27e7d120c57b1a6ba51cc23db76ac2d0;hb=f57232cdb4ea7c7b5fab1c7ef23c26714d26501e;hp=9d9bf24260179c7dc2bbba4cc93ec501040db871;hpb=5006aaca31fa5fa36cb82784d13f6d28d754c90c;p=xogo.git diff --git a/variants/Checkered/class.js b/variants/Checkered/class.js index 9d9bf24..f73ed0e 100644 --- a/variants/Checkered/class.js +++ b/variants/Checkered/class.js @@ -12,7 +12,7 @@ export default class CheckeredRules extends ChessRules { label: "Allow switching", variable: "withswitch", type: "checkbox", - defaut: false + defaut: true } ], styles: [ @@ -28,7 +28,13 @@ export default class CheckeredRules extends ChessRules { }; } - static board2fen(b) { + static GetColorClass(c) { + if (c == 'c') + return "checkered"; + return C.GetColorClass(c); + } + + board2fen(b) { const checkered_codes = { p: "s", q: "t", @@ -41,7 +47,7 @@ export default class CheckeredRules extends ChessRules { return super.board2fen(b); } - static fen2board(f) { + fen2board(f) { // Tolerate upper-case versions of checkered pieces (why not?) const checkered_pieces = { s: "p", @@ -60,11 +66,20 @@ export default class CheckeredRules extends ChessRules { return super.fen2board(f); } + genRandInitBaseFen() { + let res = super.genRandInitBaseFen(); + res.o.flags += "1".repeat(16); //pawns flags + return res; + } + getPartFen(o) { - let parts = super.getPartFen(o); - parts["cmove"] = this.getCmoveFen(); - parts["stage"] = this.getStageFen(); - return parts; + return Object.assign( + { + "cmove": o.init ? "-" : this.getCmoveFen(), + "stage": o.init ? "1" : this.getStageFen() + }, + super.getPartFen(o) + ); } getCmoveFen() { @@ -82,9 +97,10 @@ export default class CheckeredRules extends ChessRules { getFlagsFen() { let fen = super.getFlagsFen(); // Add pawns flags - for (let c of ["w", "b"]) + for (let c of ["w", "b"]) { for (let i = 0; i < 8; i++) fen += (this.pawnFlags[c][i] ? "1" : "0"); + } return fen; } @@ -92,26 +108,44 @@ export default class CheckeredRules extends ChessRules { return super.getPawnShift(color == 'c' ? this.turn : color); } + getOppCols(color) { + if (this.stage == 1) + return super.getOppCols(color).concat(['c']); + // Stage 2: depends if color is w+b or checkered + if (color == this.sideCheckered) + return ['w', 'b']; + return ['c']; + } + pieces(color, x, y) { let baseRes = super.pieces(color, x, y); - if ( - this.getPiece(x, y) == 'p' && - this.stage == 2 && - this.getColor(x, y) == 'c' - ) { + if (this.getPiece(x, y) == 'p' && color == 'c') { + const pawnShift = this.getPawnShift(this.turn); //cannot trust color + const initRank = ( + (this.stage == 2 && [1, 6].includes(x)) || + (this.stage == 1 && + ((x == 1 && this.turn == 'b') || (x == 6 && this.turn == 'w')) + ) + ); // Checkered pawns on stage 2 are bidirectional - const initRank = ((color == 'w' && x >= 6) || (color == 'b' && x <= 1)); + let moveSteps = [[pawnShift, 0]], + attackSteps = [[pawnShift, 1], [pawnShift, -1]]; + if (this.stage == 2) { + moveSteps.push([-pawnShift, 0]); + Array.prototype.push.apply(attackSteps, + [[-pawnShift, 1], [-pawnShift, -1]]); + } baseRes['p'] = { "class": "pawn", moves: [ { - steps: [[1, 0], [-1, 0]], + steps: moveSteps, range: (initRank ? 2 : 1) } ], attack: [ { - steps: [[1, 1], [1, -1], [-1, 1], [-1, -1]], + steps: attackSteps, range: 1 } ] @@ -157,15 +191,6 @@ export default class CheckeredRules extends ChessRules { } } - aggregateFlags() { - return [this.castleFlags, this.pawnFlags]; - } - - disaggregateFlags(flags) { - this.castleFlags = flags[0]; - this.pawnFlags = flags[1]; - } - getEpSquare(moveOrSquare) { // At stage 2, all pawns can be captured en-passant if ( @@ -202,27 +227,26 @@ export default class CheckeredRules extends ChessRules { } postProcessPotentialMoves(moves) { + moves = super.postProcessPotentialMoves(moves); if (this.stage == 2 || moves.length == 0) return moves; const color = this.turn; // Apply "checkerization" of standard moves const lastRank = (color == "w" ? 0 : 7); const [x, y] = [moves[0].start.x, moves[0].start.y]; - let moves = []; const piece = this.getPiece(x, y); // King is treated differently: it never turn checkered - if (piece == 'k') { + if (piece == 'k' && this.stage == 1) { // If at least one checkered piece, allow switching: if ( this.options["withswitch"] && this.board.some(b => b.some(cell => cell[0] == 'c')) ) { - const oppCol = C.GetOppCol(color); - const oppKingPos = this.searchKingPos(oppCol)[0]; + const oppKingPos = this.searchKingPos(C.GetOppTurn(this.turn))[0]; moves.push( new Move({ start: { x: x, y: y }, - end: { x: oppKingPos[0], y: oppKingPos[1] }, + end: {x: oppKingPos[0], y: oppKingPos[1]}, appear: [], vanish: [] }) @@ -233,7 +257,7 @@ export default class CheckeredRules extends ChessRules { if (piece == 'p') { // Filter out forbidden pawn moves moves = moves.filter(m => { - if (m.vanish[0].p == 'p') { + if (m.vanish.length > 0 && m.vanish[0].p == 'p') { if ( Math.abs(m.end.x - m.start.x) == 2 && !this.pawnFlags[this.turn][m.start.y] @@ -241,7 +265,7 @@ export default class CheckeredRules extends ChessRules { return false; //forbidden 2-squares jumps } if ( - this.board[m.end.x][m.end.y] == V.EMPTY && + this.board[m.end.x][m.end.y] == "" && m.vanish.length == 2 && this.getColor(m.start.x, m.start.y) == "c" ) { @@ -253,7 +277,7 @@ export default class CheckeredRules extends ChessRules { } let extraMoves = []; moves.forEach(m => { - if (m.vanish.length == 2 && m.appear.length == 1) + if (m.vanish.length == 2 && m.appear.length == 1) { // A capture occured m.appear[0].c = "c"; if ( @@ -271,7 +295,7 @@ export default class CheckeredRules extends ChessRules { return moves.concat(extraMoves); } - canIplay(side, [x, y]) { + canIplay(x, y) { if (this.stage == 2) { const color = this.getColor(x, y); return ( @@ -280,7 +304,10 @@ export default class CheckeredRules extends ChessRules { : ['w', 'b'].includes(color) ); } - return side == this.turn && [side, "c"].includes(this.getColor(x, y)); + return ( + this.playerColor == this.turn && + [this.turn, "c"].includes(this.getColor(x, y)) + ); } // Does m2 un-do m1 ? (to disallow undoing checkered moves) @@ -299,36 +326,42 @@ export default class CheckeredRules extends ChessRules { filterValid(moves) { const color = this.turn; - if (stage == 2 && this.sideCheckered == color) + if (this.stage == 2 && this.sideCheckered == color) // Checkered cannot be under check (no king) return moves; let kingPos = super.searchKingPos(color); - const oppCol = C.GetOppCol(color); if (this.stage == 2) // Must consider both kings (attacked by checkered side) - kingPos = [kingPos, super.searchKingPos(oppCol)]; - return moves.filter(m => { + kingPos.push(super.searchKingPos(C.GetOppTurn(this.turn))[0]); + const oppCols = this.getOppCols(color); + const filteredMoves = moves.filter(m => { + if (m.vanish.length == 0 && m.appear.length == 0) + return true; //switch move this.playOnBoard(m); + if (m.vanish[0].p == 'k') + kingPos[0] = [m.appear[0].x, m.appear[0].y]; let res = true; - if (stage == 1) + if (this.stage == 1) res = !this.oppositeMoves(this.cmove, m); if (res && m.appear.length > 0) - // NOTE: oppCol might be inaccurate; fixed in underCheck() - res = !this.underCheck(kingPos, oppCol); + res = !this.underCheck(kingPos, oppCols); + if (m.vanish[0].p == 'k') + kingPos[0] = [m.vanish[0].x, m.vanish[0].y]; this.undoOnBoard(m); return res; }); + return filteredMoves; } atLeastOneMove(color) { - const oppCol = C.GetOppCol(color); + const myCols = [color, 'c']; for (let i = 0; i < this.size.x; i++) { for (let j = 0; j < this.size.y; j++) { const colIJ = this.getColor(i, j); if ( this.board[i][j] != "" && ( - (this.stage == 1 && colIJ != oppCol) || + (this.stage == 1 && myCols.includes(colIJ)) || (this.stage == 2 && ( (this.sideCheckered == color && colIJ == 'c') || @@ -346,12 +379,15 @@ export default class CheckeredRules extends ChessRules { return false; } - underCheck(square_s, oppCol) { - if (this.stage == 1) - return super.underAttack(square_s, [oppCol, 'c']); - if (oppCol != this.sideCheckered) + underCheck(square_s, oppCols) { + if (this.stage == 2 && this.turn == this.sideCheckered) return false; //checkered pieces is me, I'm not under check - return super.underAttack(square_s, 'c'); + // Artificial turn change required, because canTake uses turn info. + // canTake is called from underCheck --> ... --> findDestSquares + this.turn = C.GetOppTurn(this.turn); + const res = square_s.some(sq => super.underAttack(sq, oppCols)); + this.turn = C.GetOppTurn(this.turn); + return res; } prePlay(move) { @@ -359,7 +395,7 @@ export default class CheckeredRules extends ChessRules { super.prePlay(move); if ( [1, 6].includes(move.start.x) && - move.vanish[0].p == V.PAWN && + move.vanish[0].p == 'p' && Math.abs(move.end.x - move.start.x) == 2 ) { // This move turns off a 2-squares pawn flag @@ -372,6 +408,8 @@ export default class CheckeredRules extends ChessRules { if (move.appear.length == 0 && move.vanish.length == 0) { this.stage = 2; this.sideCheckered = this.turn; + if (this.playerColor != this.turn) + super.displayMessage(null, "Autonomous checkered!", "info-text", 2000); } else super.postPlay(move); @@ -389,11 +427,11 @@ export default class CheckeredRules extends ChessRules { if (this.atLeastOneMove(color)) return "*"; // Artifically change turn, for checkered pawns - const oppCol = C.GetOppCol(color); - this.turn = oppCol; + const oppTurn = C.GetOppTurn(color); + this.turn = oppTurn; const kingPos = super.searchKingPos(color)[0]; let res = "1/2"; - if (super.underAttack(kingPos, [oppCol, 'c'])) + if (super.underAttack(kingPos, [oppTurn, 'c'])) res = (color == "w" ? "0-1" : "1-0"); this.turn = color; return res; @@ -410,9 +448,9 @@ export default class CheckeredRules extends ChessRules { } if (this.atLeastOneMove(color)) return "*"; - let res = super.underAttack(super.searchKingPos(color)[0], 'c'); + let res = super.underAttack(super.searchKingPos(color)[0], ['c']); if (!res) - res = super.underAttack(super.searchKingPos(oppCol)[0], 'c'); + res = super.underAttack(super.searchKingPos(oppCol)[0], ['c']); if (res) return (color == 'w' ? "0-1" : "1-0"); return "1/2";