X-Git-Url: https://git.auder.net/?a=blobdiff_plain;f=client%2Fsrc%2Fvariants%2FChakart.js;h=45230a14f4f354fa92aeae022d954531b318fa8b;hb=596e24d030f94682a31df74799c13eb792a63cdf;hp=9a026630eeb5b2b6e567f2c83b20bc94fd4d40b0;hpb=00eef1ca12534a43cb8e2e12155a46c00353eac2;p=vchess.git diff --git a/client/src/variants/Chakart.js b/client/src/variants/Chakart.js index 9a026630..45230a14 100644 --- a/client/src/variants/Chakart.js +++ b/client/src/variants/Chakart.js @@ -12,6 +12,10 @@ export class ChakartRules extends ChessRules { return false; } + static get HasEnpassant() { + return false; + } + static get CorrConfirm() { // Because of bonus effects return false; @@ -33,13 +37,10 @@ export class ChakartRules extends ChessRules { const deltaX = Math.abs(fm.appear[0].x - x); const deltaY = Math.abs(fm.appear[0].y - y); return ( - (deltaX == 0 && deltaY == 0) || + (this.board[x][y] == V.EMPTY || this.getColor(x, y) == 'a') && ( - this.board[x][y] == V.EMPTY && - ( - (fm.vanish[0].p == V.ROOK && deltaX == 1 && deltaY == 1) || - (fm.vanish[0].p == V.BISHOP && deltaX + deltaY == 1) - ) + (fm.vanish[0].p == V.ROOK && deltaX == 1 && deltaY == 1) || + (fm.vanish[0].p == V.BISHOP && deltaX + deltaY == 1) ) ); } @@ -123,10 +124,17 @@ export class ChakartRules extends ChessRules { const fenParts = fen.split(" "); return Object.assign( ChessRules.ParseFen(fen), - { captured: fenParts[5] } + { captured: fenParts[4] } ); } + static IsGoodFen(fen) { + if (!ChessRules.IsGoodFen(fen)) return false; + const captured = V.ParseFen(fen).captured; + if (!captured || !captured.match(/^[0-9]{12,12}$/)) return false; + return true; + } + // King can be l or L (immobilized) --> similar to Alice variant static IsGoodPosition(position) { if (position.length == 0) return false; @@ -187,11 +195,11 @@ export class ChakartRules extends ChessRules { } getCapturedFen() { - let counts = [...Array(10).fill(0)]; + let counts = [...Array(12).fill(0)]; let i = 0; - for (let p of [V.ROOK, V.KNIGHT, V.BISHOP, V.QUEEN, V.PAWN]) { + for (let p of V.RESERVE_PIECES) { counts[i] = this.captured["w"][p]; - counts[5 + i] = this.captured["b"][p]; + counts[6 + i] = this.captured["b"][p]; i++; } return counts.join(""); @@ -209,14 +217,16 @@ export class ChakartRules extends ChessRules { [V.KNIGHT]: parseInt(fenParsed.captured[1]), [V.BISHOP]: parseInt(fenParsed.captured[2]), [V.QUEEN]: parseInt(fenParsed.captured[3]), - [V.PAWN]: parseInt(fenParsed.captured[4]), + [V.KING]: parseInt(fenParsed.captured[4]), + [V.PAWN]: parseInt(fenParsed.captured[5]), }, b: { - [V.ROOK]: parseInt(fenParsed.captured[5]), - [V.KNIGHT]: parseInt(fenParsed.captured[6]), - [V.BISHOP]: parseInt(fenParsed.captured[7]), - [V.QUEEN]: parseInt(fenParsed.captured[8]), - [V.PAWN]: parseInt(fenParsed.captured[9]), + [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]), } }; this.firstMove = []; @@ -231,12 +241,22 @@ export class ChakartRules extends ChessRules { return fen; } + getColor(i, j) { + if (i >= V.size.x) return i == V.size.x ? "w" : "b"; + return this.board[i][j].charAt(0); + } + + getPiece(i, j) { + if (i >= V.size.x) return V.RESERVE_PIECES[j]; + return this.board[i][j].charAt(1); + } + getReservePpath(index, color) { return color + V.RESERVE_PIECES[index]; } static get RESERVE_PIECES() { - return [V.PAWN, V.ROOK, V.KNIGHT, V.BISHOP, V.QUEEN]; + return [V.PAWN, V.ROOK, V.KNIGHT, V.BISHOP, V.QUEEN, V.KING]; } getReserveMoves([x, y]) { @@ -248,16 +268,8 @@ 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++) { - // TODO: allow also to drop on bonus square? - // No effect if mushroom, but normal (recursive) effect otherwise. - // - //Koopa --> shift() - // - //Egg: no effect on subTurn == 2 => OK - //Juste bootstrap banan or bomb effect => getBasicMove otherwise - // - // - if (this.board[i][j] == V.EMPTY) { + const colIJ = this.getColor(i, j); + if (this.board[i][j] == V.EMPTY || colIJ == 'a') { let mv = new Move({ appear: [ new PiPo({ @@ -271,6 +283,34 @@ export class ChakartRules extends ChessRules { start: { x: x, y: y }, //a bit artificial... end: { x: i, y: j } }); + if (colIJ == 'a') { + const pieceIJ = this.getPiece(i, j); + mv.vanish.push( + new PiPo({ + x: i, + y: j, + c: colIJ, + p: pieceIJ + }) + ); + if ([V.BANANA, V.BOMB].includes(pieceIJ)) { + // Apply first effect, remove bonus from board, and then + // relay to getBasicMove. Finally merge mv.appear/vanish and + // put back the bonus on the board: + const bSteps = V.steps[pieceIJ == V.BANANA ? V.ROOK : V.BISHOP]; + const sqEffect = this.getRandomSquare([i, j], bSteps); + if (sqEffect[0] != i || sqEffect[1] != j) { + this.board[i][j] = color + p; + const bMove = + this.getBasicMove([i, j], [sqEffect[0], sqEffect[1]]); + this.board[i][j] = 'a' + pieceIJ; + mv.appear[0].x = bMove.appear[0].x; + mv.appear[0].y = bMove.appear[0].y; + for (let k = 1; k < bMove.vanish.length; k++) + mv.vanish.push(bMove.vanish[k]); + } + } + } moves.push(mv); } } @@ -379,17 +419,52 @@ export class ChakartRules extends ChessRules { return [x + step[0], y + step[1]]; } + canMove([x, y], piece) { + const color = this.getColor(x, y); + const oppCol = V.GetOppCol(color); + piece = piece || this.getPiece(x, y); + if (piece == V.PAWN) { + const forward = (color == 'w' ? -1 : 1); + return ( + 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 + ) + ); + } + // Checking one step is enough: + const steps = + [V.KING, V.QUEEN].includes(piece) + ? V.steps[V.ROOK].concat(V.steps[V.BISHOP]) + : V.steps[piece]; + if (!Array.isArray(steps)) debugger; + for (let step of steps) { + const [i, j] = [x + step[0], y + step[1]]; + if ( + V.OnBoard(i, j) && + (this.board[i][j] == V.EMPTY || this.getColor(i, j) != color) + ) { + return true; + } + } + return false; + } + getBasicMove([x1, y1], [x2, y2], tr) { // Apply mushroom, bomb or banana effect (hidden to the player). // Determine egg effect, too, and apply its first part if possible. let move = super.getBasicMove([x1, y1], [x2, y2], tr); const color1 = this.getColor(x1, y1); - const color2 = this.getColor(x2, y2); const piece1 = this.getPiece(x1, y1); - const piece2 = this.getPiece(x2, y2); const oppCol = V.GetOppCol(color1); if ([V.PAWN, V.KNIGHT].includes(piece1)) { - //&& (color2 != 'a' || !([V.BANANA, V.BOMB].includes(piece2))) switch (piece1) { case V.PAWN: { const twoSquaresMove = (Math.abs(x2 - x1) == 2); @@ -463,11 +538,19 @@ export class ChakartRules extends ChessRules { this.board[moveTo[0]][moveTo[1]] != V.EMPTY && this.getColor(moveTo[0], moveTo[1]) == 'a' ) { + move.vanish.push( + new PiPo({ + x: moveTo[0], + y: moveTo[1], + c: 'a', + p: this.getPiece(moveTo[0], moveTo[1]) + }) + ); // Artificially change direction, before applying new effects: x1 = x; y1 = y; x2 = moveTo[0]; - x2 = moveTo[1]; + y2 = moveTo[1]; switch (this.getPiece(moveTo[0], moveTo[1])) { case V.BANANA: applyBeffect(V.steps[V.ROOK]); @@ -490,25 +573,28 @@ export class ChakartRules extends ChessRules { const oppLastRank = (color == 'w' ? 7 : 0); 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) == color - ) { + if (this.board[i][j] != V.EMPTY && this.getColor(i, j) == color) { const piece = this.getPiece(i, j); if (piece != V.KING && (piece != V.PAWN || i != oppLastRank)) pieces.push({ x: i, y: j, p: piece }); } } } + // Special case of the current piece (temporarily off board): + if (color == color1) + pieces.push({ x: move.appear[0].x, y: move.appear[0].y, p: piece1 }); const cp = pieces[randInt(pieces.length)]; - move.vanish.push( - new PiPo({ - x: cp.x, - y: cp.y, - c: color, - p: cp.p - }) - ); + if (move.appear[0].x != cp.x || move.appear[0].y != cp.y) { + move.vanish.push( + new PiPo({ + x: cp.x, + y: cp.y, + c: color, + p: cp.p + }) + ); + } + else move.appear.pop(); move.appear.push( new PiPo({ x: cp.x, @@ -536,10 +622,13 @@ export class ChakartRules extends ChessRules { canPlayAgain = true; } else { - move.end.effect = "toadette"; - this.play(move); - canPlayAgain = this.getPotentialMovesFrom([x2, y2]).length > 0; - this.undo(move); + move.end.effect = "daisy"; + this.board[move.start.x][move.start.y] = saveCurrent; + V.PlayOnBoard(this.board, move); + const square = [move.appear[0].x, move.appear[0].y]; + canPlayAgain = this.canMove(square, piece1); + V.UndoOnBoard(this.board, move); + this.board[move.start.x][move.start.y] = V.EMPTY; delete move.end["effect"]; } if (canPlayAgain) effects.push("daisy"); @@ -549,7 +638,7 @@ export class ChakartRules extends ChessRules { return ( cell[0] == oppCol && cell[1] != V.KING && - (cell[1] != V.PAWN || i != lastRank[oppCol]) + (cell[1] != V.PAWN || i != lastRank[color1]) ); }) ) @@ -557,12 +646,16 @@ export class ChakartRules extends ChessRules { effects.push("luigi"); } if ( + ( + piece1 != V.KING && + (piece1 != V.PAWN || move.appear[0].x != lastRank[oppCol]) + ) || this.board.some((b,i) => b.some(cell => { return ( cell[0] == color1 && cell[1] != V.KING && - (cell[1] != V.PAWN || i != lastRank[color1]) + (cell[1] != V.PAWN || i != lastRank[oppCol]) ); }) ) @@ -650,44 +743,52 @@ export class ChakartRules extends ChessRules { this.getColor(next[0], next[1]) != 'a' ) { const afterNext = [next[0] + step[0], next[1] + step[1]]; - if ( - V.OnBoard(afterNext[0], afterNext[1]) && - ( + if (V.OnBoard(afterNext[0], afterNext[1])) { + const afterColor = this.getColor(afterNext[0], afterNext[1]) + if ( this.board[afterNext[0]][afterNext[1]] == V.EMPTY || - this.getColor(afterNext[0], afterNext[1]) == 'a' - ) - ) { - move.appear[0].x = afterNext[0]; - move.appear[0].y = afterNext[1]; - if (this.board[afterNext[0]][afterNext[1]] != V.EMPTY) { - const object = this.getPiece(afterNext[0], afterNext[1]); - move.vanish.push( - new PiPo({ - x: afterNext[0], - y: afterNext[0], - c: 'a', - p: object - }) - ); - switch (object) { - case V.BANANA: - applyBeffect(V.steps[V.ROOK]); - break; - case V.BOMB: - applyBeffect(V.steps[V.BISHOP]); - break; - case V.EGG: - applyEggEffect(); - break; - case V.MUSHROOM: - applyMushroomEffect(); - break; + afterColor != color1 + ) { + move.appear[0].x = afterNext[0]; + move.appear[0].y = afterNext[1]; + if (this.board[afterNext[0]][afterNext[1]] != V.EMPTY) { + // The "object" could also be an opponent's piece + const object = this.getPiece(afterNext[0], afterNext[1]); + move.vanish.push( + new PiPo({ + x: afterNext[0], + y: afterNext[1], + c: afterColor, + p: object + }) + ); + switch (object) { + case V.BANANA: + applyBeffect(V.steps[V.ROOK]); + break; + case V.BOMB: + applyBeffect(V.steps[V.BISHOP]); + break; + case V.EGG: + applyEggEffect(); + break; + case V.MUSHROOM: + applyMushroomEffect(); + break; + } } } } } } }; + const color2 = this.getColor(x2, y2); + const piece2 = this.getPiece(x2, y2); + // In case of (bonus effects might go through initial square): + // TODO: push the idea further, objects left initially should alter the + // trajectory or move as well (mushroom or egg). + const saveCurrent = this.board[move.start.x][move.start.y]; + this.board[move.start.x][move.start.y] = V.EMPTY; if (color2 == 'a') { switch (piece2) { case V.BANANA: @@ -700,57 +801,63 @@ export class ChakartRules extends ChessRules { applyMushroomEffect(); break; case V.EGG: - if (this.subTurn == 1) { + if (this.subTurn == 1) // No egg effect at subTurn 2 - if ([V.ROOK, V.BISHOP].includes(piece1)) { - // Drop a bomb or banana at random, because even if bonus is - // "play again" nothing can be done after next move. - const steps = V.steps[piece1 == V.ROOK ? V.BISHOP : V.ROOK]; - const object = (piece1 == V.ROOK ? V.BANANA : V.BOMB); - const dropOn = this.getRandomSquare([x2, y2], steps); - move.appear.push( - new PiPo({ - x: dropOn[0], - y: dropOn[1], - c: 'a', - p: object - }) - ); - } applyEggEffect(); - } break; } } if ( this.subTurn == 1 && - (color2 != 'a' || piece2 != V.EGG) && + move.appear.length > 0 && [V.ROOK, V.BISHOP].includes(piece1) ) { - move.end.effect = 0; + const finalSquare = [move.appear[0].x, move.appear[0].y]; + if ( + color2 != 'a' || + this.getColor(finalSquare[0], finalSquare[1]) != 'a' || + this.getPiece(finalSquare[0], finalSquare[1]) != V.EGG + ) { + const validSteps = + V.steps[piece1 == V.ROOK ? V.BISHOP : V.ROOK].filter(s => { + const [i, j] = [finalSquare[0] + s[0], finalSquare[1] + s[1]]; + return ( + V.OnBoard(i, j) && + (this.board[i][j] == V.EMPTY || this.getColor(i, j) == 'a') + ); + }); + if (validSteps.length >= 2) move.end.effect = 0; + else if (validSteps.length == 1) { + const [x, y] = [ + finalSquare[0] + validSteps[0][0], + finalSquare[1] + validSteps[0][1] + ]; + move.appear.push( + new PiPo({ + x: x, + y: y, + c: 'a', + p: (piece1 == V.ROOK ? V.BANANA : V.BOMB) + }) + ); + if (this.board[x][y] != V.EMPTY) { + move.vanish.push( + new PiPo({ x: x, y: y, c: 'a', p: this.getPiece(x, y) })); + } + } + } } - return move; - } - - getEnpassantCaptures([x, y], shiftX) { - const Lep = this.epSquares.length; - const epSquare = this.epSquares[Lep - 1]; //always at least one element - let enpassantMove = null; + this.board[move.start.x][move.start.y] = saveCurrent; if ( - !!epSquare && - epSquare.x == x + shiftX && - Math.abs(epSquare.y - y) == 1 + move.appear.length == 2 && + move.appear[0].x == move.appear[1].x && + move.appear[0].y == move.appear[1].y ) { - // Not using this.getBasicMove() because the mushroom has no effect - enpassantMove = super.getBasicMove([x, y], [epSquare.x, epSquare.y]); - enpassantMove.vanish.push({ - x: x, - y: epSquare.y, - p: V.PAWN, - c: this.getColor(x, epSquare.y) - }); + // Arrive on bonus left initially: + move.appear.pop(); } - return !!enpassantMove ? [enpassantMove] : []; + return move; + // TODO: if loopback to initial square, simplify move. } getPotentialPawnMoves([x, y]) { @@ -780,15 +887,11 @@ export class ChakartRules extends ChessRules { y + shiftY >= 0 && y + shiftY < sizeY && this.board[x + shiftX][y + shiftY] != V.EMPTY && - this.getColor(x + shiftX, y + shiftY) == oppCol + ['a', oppCol].includes(this.getColor(x + shiftX, y + shiftY)) ) { this.addPawnMoves([x, y], [x + shiftX, y + shiftY], moves); } } - Array.prototype.push.apply( - moves, - this.getEnpassantCaptures([x, y], shiftX) - ); return moves; } @@ -798,7 +901,12 @@ export class ChakartRules extends ChessRules { let invisibleMoves = []; if (this.powerFlags[this.turn][V.QUEEN]) { normalMoves.forEach(m => { - if (m.vanish.length == 1) { + if ( + m.appear.length == 1 && + m.vanish.length == 1 && + // Only simple non-capturing moves: + m.vanish[0].c != 'a' + ) { let im = JSON.parse(JSON.stringify(m)); im.appear[0].p = V.INVISIBLE_QUEEN; im.end.noHighlight = true; @@ -815,9 +923,16 @@ export class ChakartRules extends ChessRules { // If flag allows it, add 'remote shell captures' if (this.powerFlags[this.turn][V.KING]) { V.steps[V.ROOK].concat(V.steps[V.BISHOP]).forEach(step => { + const [nextX, nextY] = [x + step[0], y + step[1]]; if ( - V.OnBoard(x + step[0], y + step[1]) && - this.board[x + step[0]][y + step[1]] == V.EMPTY + V.OnBoard(nextX, nextY) && + ( + this.board[nextX][nextY] == V.EMPTY || + ( + this.getColor(nextX, nextY) == 'a' && + [V.EGG, V.MUSHROOM].includes(this.getPiece(nextX, nextY)) + ) + ) ) { let [i, j] = [x + 2 * step[0], y + 2 * step[1]]; while ( @@ -965,24 +1080,20 @@ export class ChakartRules extends ChessRules { } doClick(square) { - if (isNaN(square[0])) return null; - if (this.subTurn == 1) return null; const L = this.firstMove.length; - const fm = this.firstMove[L-1]; - if (fm.end.effect != 0) return null; + const fm = (L > 0 ? this.firstMove[L-1] : null); + if ( + isNaN(square[0]) || + this.subTurn == 1 || + !([0, "daisy"].includes(fm.end.effect)) + ) { + return null; + } const [x, y] = [square[0], square[1]]; const deltaX = Math.abs(fm.appear[0].x - x); const deltaY = Math.abs(fm.appear[0].y - y); - if (deltaX == 0 && deltaY == 0) { - // Empty move: - return { - start: { x: -1, y: -1 }, - end: { x: -1, y: -1 }, - appear: [], - vanish: [] - }; - } if ( + fm.end.effect == 0 && (this.board[x][y] == V.EMPTY || this.getColor(x, y) == 'a') && ( (fm.vanish[0].p == V.ROOK && deltaX == 1 && deltaY == 1) || @@ -1008,12 +1119,28 @@ export class ChakartRules extends ChessRules { } return m; } + else if ( + fm.end.effect == "daisy" && + deltaX == 0 && deltaY == 0 && + !this.canMove([x, y]) + ) { + // No possible move: return empty move + return { + start: { x: -1, y: -1 }, + end: { x: -1, y: -1 }, + appear: [], + vanish: [] + }; + } return null; } play(move) { +// if (!this.states) this.states = []; +// const stateFen = this.getFen(); +// this.states.push(stateFen); + move.flags = JSON.stringify(this.aggregateFlags()); - this.epSquares.push(this.getEpSquare(move)); V.PlayOnBoard(this.board, move); move.turn = [this.turn, this.subTurn]; if ([0, "kingboo", "toadette", "daisy"].includes(move.end.effect)) { @@ -1031,6 +1158,7 @@ export class ChakartRules extends ChessRules { postPlay(move) { if (move.end.effect == "toadette") this.reserve = this.captured; else this.reserve = undefined; + const color = move.turn[0]; if (move.vanish.length == 2 && move.vanish[1].c != 'a') // Capture: update this.captured this.captured[move.vanish[1].c][move.vanish[1].p]++; @@ -1039,57 +1167,42 @@ export class ChakartRules extends ChessRules { // A piece is back on board this.captured[move.appear[0].c][move.appear[0].p]--; } - - - - -// TODO: simplify and fix this - - - - if (this.subTurn == 1) { - // Update flags: - if ( - this.board[move.start.x][move.start.y] != V.EMPTY && - this.getPiece(move.start.x, move.start.y) == V.KING && - ( - Math.abs(move.end.x - move.start.x) >= 2 || - Math.abs(move.end.y - move.start.y) >= 2 - ) - ) { - const myColor = this.getColor(move.start.x, move.start.y); - this.powerFlags[myColor][V.KING] = false; - } - else if ( - move.vanish[0].p == V.QUEEN && - this.getPiece(move.end.x, move.end.y) == V.INVISIBLE_QUEEN - ) { - this.powerFlags[move.vanish[0].c][V.QUEEN] = false; - } - const color = move.vanish[0].c; + if (move.appear.length == 0) { + // Three cases: king "shell capture", Chomp or Koopa + if (this.getPiece(move.start.x, move.start.y) == V.KING) + // King remote capture: + this.powerFlags[color][V.KING] = false; + else if (move.end.effect == "chomp") + this.captured[color][move.vanish[0].p]++; + } + 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 ( + 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); - if (!(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 - 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 && - 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]; - } + 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 && + 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]; } } } @@ -1098,7 +1211,6 @@ export class ChakartRules extends ChessRules { } undo(move) { - this.epSquares.pop(); this.disaggregateFlags(JSON.parse(move.flags)); V.UndoOnBoard(this.board, move); if ([0, "kingboo", "toadette", "daisy"].includes(move.end.effect)) @@ -1107,6 +1219,10 @@ export class ChakartRules extends ChessRules { this.turn = move.turn[0]; this.subTurn = move.turn[1]; this.postUndo(move); + +// const stateFen = this.getFen(); +// if (stateFen != this.states[this.states.length-1]) debugger; +// this.states.pop(); } postUndo(move) { @@ -1117,8 +1233,7 @@ export class ChakartRules extends ChessRules { } if (!!move.wasInvisible) { const [i, j] = move.wasInvisible; - this.board[i][j] = - this.getColor(i, j) + V.INVISIBLE_QUEEN; + this.board[i][j] = this.getColor(i, j) + V.INVISIBLE_QUEEN; } if (move.vanish.length == 2 && move.vanish[1].c != 'a') this.captured[move.vanish[1].c][move.vanish[1].p]--; @@ -1127,6 +1242,8 @@ export class ChakartRules extends ChessRules { // A piece was back on board this.captured[move.appear[0].c][move.appear[0].p]++; } + else if (move.appear.length == 0 && move.end.effect == "chomp") + this.captured[move.vanish[0].c][move.vanish[0].p]--; if (move.vanish.length == 0) this.reserve = this.captured; else this.reserve = undefined; } @@ -1157,8 +1274,8 @@ export class ChakartRules extends ChessRules { static GenRandInitFen(randomness) { return ( SuicideRules.GenRandInitFen(randomness).slice(0, -1) + - // Add Peach + Mario flags, re-add en-passant + capture counts - "1111 - 0000000000" + // Add Peach + Mario flags + capture counts + "1111 000000000000" ); } @@ -1175,14 +1292,15 @@ export class ChakartRules extends ChessRules { if (this.subTurn == 2) { const moves2 = this.getAllValidMoves(); move2 = moves2[randInt(moves2.length)]; -console.log(move2); - } this.undo(move1); if (!move2) return move1; return [move1, move2]; } + // TODO: king chomped, king koopa: notation is incomplete. + // Also, king boo effect should be better written like "e4Sg1". + // Toadette placements on bonus square are badly written as well. getNotation(move) { if (move.vanish.length == 0) { if (move.appear.length == 0) return "-"; @@ -1198,14 +1316,27 @@ console.log(move2); return "Q??"; } const finalSquare = V.CoordsToSquare(move.end); - const piece = move.vanish[0].p; + let piece = undefined; if (move.appear.length == 0) { - // Koopa or Chomp + piece = this.getPiece(move.start.x, move.start.y); + if (piece == V.KING) return "Kx" + finalSquare; + // Koopa or Chomp: return ( piece.toUpperCase() + "x" + finalSquare + "*" + (move.end.effect == "koopa" ? "K" : "C") ); } + else if ( + move.appear.length == 1 && + move.vanish.length == 1 && + move.appear[0].c == 'a' && + move.vanish[0].c == 'a' + ) { + // Bonus replacement: + piece = move.appear[0].p.toUpperCase(); + return piece + "@" + finalSquare; + } + piece = move.vanish[0].p; let notation = undefined; if (piece == V.PAWN) { // Pawn move @@ -1247,21 +1378,6 @@ console.log(move2); break; } } - else if (move.vanish.length >= 2 && move.vanish[1].c == 'a') { - let symbol = ""; - switch (move.vanish[1].p) { - case V.MUSHROOM: - symbol = 'M'; - break; - case V.BANANA: - symbol = 'B'; - break; - case V.BOMB: - symbol = 'X'; - break; - } - notation.replace('x', 'x' + symbol); - } return notation; } };