X-Git-Url: https://git.auder.net/img/rock_paper_scissors_lizard_spock.gif?a=blobdiff_plain;f=client%2Fsrc%2Fvariants%2FPacosako.js;h=efc8fd38dcedf1468514f1db989e59d5f566c67b;hb=f3f8470750e91ac7b5bf57a4e01c5791c54b65fb;hp=b67d429b6f2b38ce1d10c3fb0c51751680d3793a;hpb=da9e846e41622111a4f877742dc0b35406635b5c;p=vchess.git diff --git a/client/src/variants/Pacosako.js b/client/src/variants/Pacosako.js index b67d429b..efc8fd38 100644 --- a/client/src/variants/Pacosako.js +++ b/client/src/variants/Pacosako.js @@ -43,7 +43,7 @@ export class PacosakoRules extends ChessRules { if (position.length == 0) return false; const rows = position.split("/"); if (rows.length != V.size.x) return false; - let kingSymb = ['k', 'g', 'm', 'u', 'x', '_']; + let kingSymb = ['k', 'g', 'm', 'u', 'x', 'z', '_']; let kings = { 'k': 0, 'K': 0 }; for (let row of rows) { let sumElts = 0; @@ -104,7 +104,7 @@ export class PacosakoRules extends ChessRules { this.kingPos = { w: [-1, -1], b: [-1, -1] }; const fenRows = V.ParseFen(fen).position.split("/"); const startRow = { 'w': V.size.x - 1, 'b': 0 }; - const kingSymb = ['k', 'g', 'm', 'u', 'x', '_']; + const kingSymb = ['k', 'g', 'm', 'u', 'x', 'z', '_']; for (let i = 0; i < fenRows.length; i++) { let k = 0; for (let j = 0; j < fenRows[i].length; j++) { @@ -139,6 +139,8 @@ export class PacosakoRules extends ChessRules { end: ChessRules.SquareToCoords(umove.substr(2)) }); } + // Local stack of positions to avoid redundant moves: + this.repetitions = []; } static IsGoodFen(fen) { @@ -600,10 +602,23 @@ export class PacosakoRules extends ChessRules { // "positions" = array of FENs to detect infinite loops. Example: // r1q1k2r/p1Pb1ppp/5n2/1f1p4/AV5P/P1eDP3/3B1PP1/R3K1NR, // Bxd2 Bxc3 Bxb4 Bxc3 Bxb4 etc. - const newPos = { fen: super.getBaseFen(), piece: released }; - if (positions.some(p => p.piece == newPos.piece && p.fen == newPos.fen)) + const newPos = { + fen: super.getBaseFen(), + piece: released, + from: fromSquare + }; + if ( + positions.some(p => { + return ( + p.piece == newPos.piece && + p.fen == newPos.fen && + p.from == newPos.from + ); + }) + ) { // Start of an infinite loop: exit return false; + } positions.push(newPos); const rank = (color == 'w' ? 0 : 7); const moves = this.getPotentialMovesFrom(fromSquare); @@ -692,10 +707,26 @@ export class PacosakoRules extends ChessRules { getCheckSquares() { return []; } + filterValid(moves) { if (moves.length == 0) return []; const L = this.umoves.length; //at least 1: init from FEN - return moves.filter(m => !this.oppositeMoves(this.umoves[L - 1], m)); + return moves.filter(m => { + if (this.oppositeMoves(this.umoves[L - 1], m)) return false; + if (!m.end.released) return true; + // Check for repetitions: + V.PlayOnBoard(this.board, m); + const newState = { piece: m.end.released, position: this.getBaseFen() }; + const repet = + this.repetitions.some(r => { + return ( + r.piece == newState.piece && + r.position == newState.position + ); + }); + V.UndoOnBoard(this.board, m); + return !repet; + }); } updateCastleFlags(move, piece) { @@ -726,14 +757,23 @@ export class PacosakoRules extends ChessRules { const c = this.turn; const L = this.lastMoveEnd.length; const lm = this.lastMoveEnd[L-1]; - const piece = (!!lm ? lm.p : move.vanish[0].p); + // NOTE: lm.p != V.KING, always. + const piece = + !!lm + ? lm.p : + this.getPiece(move.vanish[0].x, move.vanish[0].y); if (piece == V.KING) this.kingPos[c] = [move.appear[0].x, move.appear[0].y]; this.updateCastleFlags(move, piece); const pawnFirstRank = (c == 'w' ? 6 : 1); - if (move.start.x == pawnFirstRank) - // This move (potentially) turns off a 2-squares pawn flag + if ( + move.start.x == pawnFirstRank && + piece == V.PAWN && + Math.abs(move.end.x - move.start.x) == 2 + ) { + // This move turns off a 2-squares pawn flag this.pawnFlags[c][move.start.y] = false; + } } play(move) { @@ -756,6 +796,15 @@ export class PacosakoRules extends ChessRules { } V.PlayOnBoard(this.board, move); this.umoves.push(this.getUmove(move)); + if (!move.end.released) this.repetitions = []; + else { + this.repetitions.push( + { + piece: move.end.released, + position: this.getBaseFen() + } + ); + } } undo(move) { @@ -768,6 +817,7 @@ export class PacosakoRules extends ChessRules { this.movesCount--; } this.umoves.pop(); + if (!!move.end.releasd) this.repetitions.pop(); this.postUndo(move); } @@ -811,6 +861,7 @@ export class PacosakoRules extends ChessRules { for (let i = mvArray.length - 1; i >= 0; i--) this.undo(mvArray[i]); if (!mv.end.released) return (mvArray.length > 1 ? mvArray : mvArray[0]); } + return null; //never reached } // NOTE: evalPosition() is wrong, but unused since bot plays at random @@ -848,8 +899,13 @@ export class PacosakoRules extends ChessRules { // Add potential promotion indications: const firstLastRank = (c == 'w' ? [7, 0] : [0, 7]); if (move.end.x == firstLastRank[1] && piece == V.PAWN) { - const up = this.getUnionPieces(move.appear[0].c, move.appear[0].p); - notation += "=" + up[c].toUpperCase(); + notation += "="; + if (ChessRules.PIECES.includes(move.appear[0].p)) + notation += move.appear[0].p.toUpperCase(); + else { + const up = this.getUnionPieces(move.appear[0].c, move.appear[0].p); + notation += up[c].toUpperCase(); + } } else if ( move.end.x == firstLastRank[0] &&