From 462947f0a6c5f33033bbee5d42d38149be6d51cb Mon Sep 17 00:00:00 2001 From: Benjamin Auder <benjamin.auder@somewhere> Date: Fri, 1 Jul 2022 15:37:44 +0200 Subject: [PATCH] Animate castle moves + better Apocalypse draft --- TODO | 2 - base_rules.js | 19 +++++++++ variants/Apocalypse/class.js | 83 +++++++++++++++++++----------------- 3 files changed, 63 insertions(+), 41 deletions(-) diff --git a/TODO b/TODO index c2ab9af..1e4eda3 100644 --- a/TODO +++ b/TODO @@ -1,5 +1,3 @@ -Animate castle by both movements (and generalize? match vanishes with appears?) - add variants : Dark Racing Kings ? Checkered-Teleport ? diff --git a/base_rules.js b/base_rules.js index beac0bb..ebf8f1e 100644 --- a/base_rules.js +++ b/base_rules.js @@ -2583,12 +2583,31 @@ export default class ChessRules { this.animateFading(arr, () => targetObj.increment()); } } + targetObj.target += + this.tryAnimateCastle(move, () => targetObj.increment()); targetObj.target += this.customAnimate(move, segments, () => targetObj.increment()); if (targetObj.target == 0) callback(); } + tryAnimateCastle(move, cb) { + if ( + this.hasCastle && + move.vanish.length == 2 && + move.appear.length == 2 && + this.isKing(0, 0, move.vanish[0].p) && + this.isKing(0, 0, move.appear[0].p) + ) { + const start = {x: move.vanish[1].x, y: move.vanish[1].y}, + end = {x: move.appear[1].x, y: move.appear[1].y}; + const segments = [ [[start.x, start.y], [end.x, end.y]] ]; + this.animateMoving(start, end, null, segments, cb); + return 1; + } + return 0; + } + // Potential other animations (e.g. for Suction variant) customAnimate(move, segments, cb) { return 0; //nb of targets diff --git a/variants/Apocalypse/class.js b/variants/Apocalypse/class.js index e91cf81..c0cd8ee 100644 --- a/variants/Apocalypse/class.js +++ b/variants/Apocalypse/class.js @@ -1,4 +1,5 @@ import ChessRules from "/base_rules.js"; +import {ArrayFun} from "/utils/array.js"; export class ApocalypseRules extends ChessRules { @@ -14,6 +15,13 @@ export class ApocalypseRules extends ChessRules { return {x: 5, y: 5}; } + setOtherVariables(fenParsed) { + super.setOtherVariables(fenParsed); + this.whiteMove = fenParsed.whiteMove != "-" + ? JSON.parse(fenParsed.whiteMove) + : null; + } + genRandInitBaseFen() { return { fen: "npppn/p3p/5/P3P/NPPPN w 0", @@ -28,46 +36,21 @@ export class ApocalypseRules extends ChessRules { } getFlagsFen() { - return ( - this.penaltyFlags['w'].toString() + this.penaltyFlags['b'].toString() - ); - } - - setOtherVariables(fen) { - const parsedFen = V.ParseFen(fen); - this.setFlags(parsedFen.flags); - // Also init whiteMove - this.whiteMove = - parsedFen.whiteMove != "-" - ? JSON.parse(parsedFen.whiteMove) - : null; + return Object.values(this.penaltyFlags).join(""); } setFlags(fenflags) { - this.penaltyFlags = { - 'w': parseInt(fenflags[0], 10), - 'b': parseInt(fenflags[1], 10) - }; + this.penaltyFlags = ArrayFun.toObject( + ['w', 'b'], [0, 1].map(i => parseInt(fenflags.charAt(i), 10))); } - // TODO: could be a stack of 2 (pawn promote + relocation) getWhitemoveFen() { - if (!this.whiteMove) return "-"; - return JSON.stringify({ - start: this.whiteMove.start, - end: this.whiteMove.end, - appear: this.whiteMove.appear, - vanish: this.whiteMove.vanish - }); + return !this.whiteMove ? "-" : JSON.stringify(this.whiteMove); } - // allow pawns to move diagonally and capture vertically --> only purpose illegal - // allow capture self --> same purpose - // ---> MARK such moves : move.illegal = true - - // simpler: allow all moves, including "capturing nothing" - // flag every pawn capture as "illegal" (potentially) - + // Allow pawns to move diagonally and capture vertically, + // because some of these moves might be valid a posteriori. + // They will be flagged as 'illegal' in a first time, however. pieces(color, x, y) { const pawnShift = (color == "w" ? -1 : 1); return { @@ -84,6 +67,8 @@ export class ApocalypseRules extends ChessRules { }; } + // Allow self-captures, because they might be valid + // if opponent takes on the same square (luck...) canTake() { return true; } @@ -132,6 +117,9 @@ export class ApocalypseRules extends ChessRules { return moves; } + +//TODO: from here + // White and black (partial) moves were played: merge // + animate both at the same time ! resolveSynchroneMove(move) { @@ -139,7 +127,7 @@ export class ApocalypseRules extends ChessRules { } play(move) { - // Do not play on board (would reveal the move...) + if (this.subTurn...) //TODO: detect (mark?) if pawn move arriving on last rank (=> subTurn++) this.turn = V.GetOppCol(this.turn); this.movesCount++; this.postPlay(move); @@ -156,21 +144,38 @@ export class ApocalypseRules extends ChessRules { } else { // A full turn just ended: - const smove = this.resolveSynchroneMove(move); + const [wMove, bMove] = this.resolveSynchroneMove(move); V.PlayOnBoard(this.board, smove); //----> ici : animate both ! this.whiteMove = null; } } - atLeastOneLegalMove(...) { - // TODO +//until here + + + atLeastOneLegalMove(color) { + for (let i=0; i<this.size.x; i++) { + for (let j=0; j<this.size.y; j++) { + if ( + this.board[i][j] != "" && + this.getColor(i, j) == color && + this.getPotentialMoves([i, j]).some(m => !m.illegal) + ) { + return true; + } + } + } + return false; } getCurrentScore() { - if (this.turn == 'b') - // Turn (white + black) not over yet. Could be stalemate if black cannot move (legally) - // TODO: check. If so, return "1/2". + if (this.turn == 'b') { + // Turn (white + black) not over yet. + // Could be stalemate if black cannot move (legally): + if (!this.atLeastOneLegalMove('b')) + return "1/2"; return "*"; + } // Count footmen: if a side has none, it loses let fmCount = { 'w': 0, 'b': 0 }; for (let i=0; i<5; i++) { -- 2.44.0