X-Git-Url: https://git.auder.net/?p=vchess.git;a=blobdiff_plain;f=client%2Fsrc%2Fvariants%2FCircular.js;h=4db5a52aa1e5ff40091d4a639e6b4b80dfef8fa1;hp=a5a5d6448148086a7f15d9471174e2918ed2050b;hb=71ef1664983cd58db3c3bbfdf6cb7c362474e9a5;hpb=e3e2cc443054cfb273b28b3ba46f559117c5ceae diff --git a/client/src/variants/Circular.js b/client/src/variants/Circular.js index a5a5d644..4db5a52a 100644 --- a/client/src/variants/Circular.js +++ b/client/src/variants/Circular.js @@ -3,20 +3,36 @@ import { ArrayFun } from "@/utils/array"; import { randInt, shuffle } from "@/utils/alea"; export const VariantRules = class CircularRules extends ChessRules { - static get HasFlags() { + static get HasEnpassant() { return false; } - static get HasEnpassant() { + static get CanFlip() { return false; } - // TODO: CanFlip --> also for racing kings (answer is false) + setFlags(fenflags) { + this.pawnFlags = { + w: [...Array(8).fill(true)], //pawns can move 2 squares? + b: [...Array(8).fill(true)] + }; + for (let c of ["w", "b"]) { + for (let i = 0; i < 8; i++) + this.pawnFlags[c][i] = fenflags.charAt((c == "w" ? 0 : 8) + i) == "1"; + } + } + + aggregateFlags() { + return this.pawnFlags; + } + + disaggregateFlags(flags) { + this.pawnFlags = flags; + } - // TODO: shuffle on 1st and 5th ranks static GenRandInitFen() { let pieces = { w: new Array(8), b: new Array(8) }; - // Shuffle pieces on first and last rank + // Shuffle pieces on first and fifth rank for (let c of ["w", "b"]) { let positions = ArrayFun.range(8); @@ -60,23 +76,32 @@ export const VariantRules = class CircularRules extends ChessRules { pieces[c][rook2Pos] = "r"; } return ( + "8/8/pppppppp/" + pieces["b"].join("") + - "/pppppppp/8/8/8/8/PPPPPPPP/" + + "/8/8/PPPPPPPP/" + pieces["w"].join("").toUpperCase() + - " w 0" + // 16 flags: can pawns advance 2 squares? + " w 0 1111111111111111" ); } - // TODO: adapt this for a circular board + // Output basically x % 8 (circular board) + static ComputeX(x) { + let res = x % V.size.x; + if (res < 0) + res += V.size.x; + return res; + } + getSlideNJumpMoves([x, y], steps, oneStep) { let moves = []; outerLoop: for (let step of steps) { - let i = x + step[0]; + let i = V.ComputeX(x + step[0]); let j = y + step[1]; while (V.OnBoard(i, j) && this.board[i][j] == V.EMPTY) { moves.push(this.getBasicMove([x, y], [i, j])); if (oneStep !== undefined) continue outerLoop; - i += step[0]; + i = V.ComputeX(i + step[0]); j += step[1]; } if (V.OnBoard(i, j) && this.canTake([x, y], [i, j])) @@ -85,66 +110,42 @@ export const VariantRules = class CircularRules extends ChessRules { return moves; } - // TODO: adapt: all pawns go in thz same direction! getPotentialPawnMoves([x, y]) { const color = this.turn; let moves = []; const [sizeX, sizeY] = [V.size.x, V.size.y]; - const shiftX = color == "w" ? -1 : 1; - const firstRank = color == "w" ? sizeX - 1 : 0; - const startRank = color == "w" ? sizeX - 2 : 1; - const lastRank = color == "w" ? 0 : sizeX - 1; - const pawnColor = this.getColor(x, y); //can be different for checkered - - // NOTE: next condition is generally true (no pawn on last rank) - if (x + shiftX >= 0 && x + shiftX < sizeX) { - const finalPieces = - x + shiftX == lastRank - ? [V.ROOK, V.KNIGHT, V.BISHOP, V.QUEEN] - : [V.PAWN]; - // One square forward - if (this.board[x + shiftX][y] == V.EMPTY) { - for (let piece of finalPieces) { - moves.push( - this.getBasicMove([x, y], [x + shiftX, y], { - c: pawnColor, - p: piece - }) - ); - } - // Next condition because pawns on 1st rank can generally jump - if ( - [startRank, firstRank].includes(x) && - this.board[x + 2 * shiftX][y] == V.EMPTY - ) { - // Two squares jump - moves.push(this.getBasicMove([x, y], [x + 2 * shiftX, y])); - } + // All pawns go in the same direction! + const shiftX = -1; + const startRank = color == "w" ? sizeX - 2 : 2; + + // One square forward + const nextRow = V.ComputeX(x + shiftX); + if (this.board[nextRow][y] == V.EMPTY) { + moves.push(this.getBasicMove([x, y], [nextRow, y])); + if ( + x == startRank && + this.pawnFlags[color][y] && + this.board[x + 2 * shiftX][y] == V.EMPTY + ) { + // Two squares jump + moves.push(this.getBasicMove([x, y], [x + 2 * shiftX, y])); } - // Captures - for (let shiftY of [-1, 1]) { - if ( - y + shiftY >= 0 && - y + shiftY < sizeY && - this.board[x + shiftX][y + shiftY] != V.EMPTY && - this.canTake([x, y], [x + shiftX, y + shiftY]) - ) { - for (let piece of finalPieces) { - moves.push( - this.getBasicMove([x, y], [x + shiftX, y + shiftY], { - c: pawnColor, - p: piece - }) - ); - } - } + } + // Captures + for (let shiftY of [-1, 1]) { + if ( + y + shiftY >= 0 && + y + shiftY < sizeY && + this.board[nextRow][y + shiftY] != V.EMPTY && + this.canTake([x, y], [nextRow, y + shiftY]) + ) { + moves.push(this.getBasicMove([x, y], [nextRow, y + shiftY])); } } return moves; } - // What are the king moves from square x,y ? getPotentialKingMoves(sq) { return this.getSlideNJumpMoves( sq, @@ -153,33 +154,45 @@ export const VariantRules = class CircularRules extends ChessRules { ); } - // TODO: check boundaries here as well + filterValid(moves) { + const filteredMoves = super.filterValid(moves); + // If at least one full move made, everything is allowed: + if (this.movesCount >= 2) + return filteredMoves; + // Else, forbid check: + const oppCol = V.GetOppCol(this.turn); + return filteredMoves.filter(m => { + this.play(m); + const res = !this.underCheck(oppCol); + this.undo(m); + return res; + }); + } + isAttackedByPawn([x, y], colors) { for (let c of colors) { - let pawnShift = c == "w" ? 1 : -1; - if (x + pawnShift >= 0 && x + pawnShift < V.size.x) { - for (let i of [-1, 1]) { - if ( - y + i >= 0 && - y + i < V.size.y && - this.getPiece(x + pawnShift, y + i) == V.PAWN && - this.getColor(x + pawnShift, y + i) == c - ) { - return true; - } + let pawnShift = 1; + const attackerRow = V.ComputeX(x + pawnShift); + for (let i of [-1, 1]) { + if ( + y + i >= 0 && + y + i < V.size.y && + this.getPiece(attackerRow, y + i) == V.PAWN && + this.getColor(attackerRow, y + i) == c + ) { + return true; } } } return false; } - // TODO: adapt this function isAttackedBySlideNJump([x, y], colors, piece, steps, oneStep) { for (let step of steps) { - let rx = x + step[0], + let rx = V.ComputeX(x + step[0]), ry = y + step[1]; while (V.OnBoard(rx, ry) && this.board[rx][ry] == V.EMPTY && !oneStep) { - rx += step[0]; + rx = V.ComputeX(rx + step[0]); ry += step[1]; } if ( @@ -192,4 +205,37 @@ export const VariantRules = class CircularRules extends ChessRules { } return false; } + + getFlagsFen() { + // Return pawns flags + let flags = ""; + for (let c of ["w", "b"]) { + for (let i = 0; i < 8; i++) flags += this.pawnFlags[c][i] ? "1" : "0"; + } + return flags; + } + + updateVariables(move) { + const c = move.vanish[0].c; + const secondRank = {"w":6, "b":2}; + // Update king position + flags + if (move.vanish[0].p == V.KING && move.appear.length > 0) { + this.kingPos[c][0] = move.appear[0].x; + this.kingPos[c][1] = move.appear[0].y; + } + else if (move.vanish[0].p == V.PAWN && secondRank[c] == move.start.x) + // This move turns off a 2-squares pawn flag + this.pawnFlags[c][move.start.y] = false; + } + + static get VALUES() { + return { + p: 1, + r: 5, + n: 3, + b: 4, + q: 10, + k: 1000 + }; + } };