X-Git-Url: https://git.auder.net/?a=blobdiff_plain;f=client%2Fsrc%2Fvariants%2FEightpieces.js;h=a0eed50df110d36fc5045b729dcf5f85fe04c829;hb=68e19a449db7a12e0a168e99cd750d985c983ba1;hp=465fbea924dc55d76c59c32e02b77fc1b83f3a1e;hpb=b0a0468aa6f436f2ad4962492561ef430a3bc15c;p=vchess.git diff --git a/client/src/variants/Eightpieces.js b/client/src/variants/Eightpieces.js index 465fbea9..a0eed50d 100644 --- a/client/src/variants/Eightpieces.js +++ b/client/src/variants/Eightpieces.js @@ -13,6 +13,11 @@ export const VariantRules = class EightpiecesRules extends ChessRules { return "l"; } + static get IMAGE_EXTENSION() { + // Temporarily, for the time SVG pieces are being designed: + return ".png"; + } + // Lancer directions *from white perspective* static get LANCER_DIRS() { return { @@ -41,9 +46,9 @@ export const VariantRules = class EightpiecesRules extends ChessRules { } getPpath(b, color, score, orientation) { - if ([V.JAILER, V.SENTRY].includes(b[1])) return "Eightpieces/" + b; + if ([V.JAILER, V.SENTRY].includes(b[1])) return "Eightpieces/tmp_png/" + b; if (Object.keys(V.LANCER_DIRS).includes(b[1])) { - if (orientation == 'w') return "Eightpieces/" + b; + if (orientation == 'w') return "Eightpieces/tmp_png/" + b; // Find opposite direction for adequate display: let oppDir = ''; switch (b[1]) { @@ -72,9 +77,10 @@ export const VariantRules = class EightpiecesRules extends ChessRules { oppDir = 'f'; break; } - return "Eightpieces/" + b[0] + oppDir; + return "Eightpieces/tmp_png/" + b[0] + oppDir; } - return b; + // TODO: after we have SVG pieces, remove the folder and next prefix: + return "Eightpieces/tmp_png/" + b; } getPPpath(b, orientation) { @@ -284,12 +290,14 @@ export const VariantRules = class EightpiecesRules extends ChessRules { getPotentialMovesFrom([x, y]) { // At subTurn == 2, jailers aren't effective (Jeff K) + const piece = this.getPiece(x, y); + const L = this.sentryPush.length; if (this.subTurn == 1) { const jsq = this.isImmobilized([x, y]); if (!!jsq) { let moves = []; // Special pass move if king: - if (this.getPiece(x, y) == V.KING) { + if (piece == V.KING) { moves.push( new Move({ appear: [], @@ -299,11 +307,26 @@ export const VariantRules = class EightpiecesRules extends ChessRules { }) ); } + else if (piece == V.LANCER && !!this.sentryPush[L-1]) { + // A pushed lancer next to the jailer: reorient + const color = this.getColor(x, y); + const curDir = this.board[x][y].charAt(1); + Object.keys(V.LANCER_DIRS).forEach(k => { + moves.push( + new Move({ + appear: [{ x: x, y: y, c: color, p: k }], + vanish: [{ x: x, y: y, c: color, p: curDir }], + start: { x: x, y: y }, + end: { x: jsq[0], y: jsq[1] } + }) + ); + }); + } return moves; } } let moves = []; - switch (this.getPiece(x, y)) { + switch (piece) { case V.JAILER: moves = this.getPotentialJailerMoves([x, y]); break; @@ -317,12 +340,15 @@ export const VariantRules = class EightpiecesRules extends ChessRules { moves = super.getPotentialMovesFrom([x, y]); break; } - const L = this.sentryPush.length; if (!!this.sentryPush[L-1]) { - // Delete moves walking back on sentry push path + // Delete moves walking back on sentry push path, + // only if not a pawn, and the piece is the pushed one. + const pl = this.sentryPush[L-1].length; + const finalPushedSq = this.sentryPush[L-1][pl-1]; moves = moves.filter(m => { if ( m.vanish[0].p != V.PAWN && + m.start.x == finalPushedSq.x && m.start.y == finalPushedSq.y && this.sentryPush[L-1].some(sq => sq.x == m.end.x && sq.y == m.end.y) ) { return false; @@ -343,8 +369,9 @@ export const VariantRules = class EightpiecesRules extends ChessRules { const color = this.getColor(x, y); let moves = []; const [sizeX, sizeY] = [V.size.x, V.size.y]; - let shiftX = color == "w" ? -1 : 1; + let shiftX = (color == "w" ? -1 : 1); if (this.subTurn == 2) shiftX *= -1; + const firstRank = color == "w" ? sizeX - 1 : 0; const startRank = color == "w" ? sizeX - 2 : 1; const lastRank = color == "w" ? 0 : sizeX - 1; @@ -352,10 +379,9 @@ export const VariantRules = class EightpiecesRules extends ChessRules { if (!V.OnBoard(x + shiftX, y)) return []; const finalPieces = - // No promotions after pushes! - x + shiftX == lastRank && this.subTurn == 1 - ? - Object.keys(V.LANCER_DIRS).concat( + // A push cannot put a pawn on last rank (it goes backward) + x + shiftX == lastRank + ? Object.keys(V.LANCER_DIRS).concat( [V.ROOK, V.KNIGHT, V.BISHOP, V.QUEEN, V.SENTRY, V.JAILER]) : [V.PAWN]; if (this.board[x + shiftX][y] == V.EMPTY) { @@ -369,7 +395,9 @@ export const VariantRules = class EightpiecesRules extends ChessRules { ); } if ( - x == startRank && + // 2-squares jumps forbidden if pawn push + this.subTurn == 1 && + [startRank, firstRank].includes(x) && this.board[x + 2 * shiftX][y] == V.EMPTY ) { // Two squares jump @@ -395,10 +423,11 @@ export const VariantRules = class EightpiecesRules extends ChessRules { } } - // En passant: + // En passant: only on subTurn == 1 const Lep = this.epSquares.length; const epSquare = this.epSquares[Lep - 1]; if ( + this.subTurn == 1 && !!epSquare && epSquare.x == x + shiftX && Math.abs(epSquare.y - y) == 1 @@ -444,6 +473,7 @@ export const VariantRules = class EightpiecesRules extends ChessRules { // Add all lancer possible orientations, similar to pawn promotions. // Except if just after a push: allow all movements from init square then const L = this.sentryPush.length; + const color = this.getColor(x, y); if (!!this.sentryPush[L-1]) { // Maybe I was pushed const pl = this.sentryPush[L-1].length; @@ -454,7 +484,6 @@ export const VariantRules = class EightpiecesRules extends ChessRules { // I was pushed: allow all directions (for this move only), but // do not change direction after moving, *except* if I keep the // same orientation in which I was pushed. - const color = this.getColor(x, y); const curDir = V.LANCER_DIRS[this.board[x][y].charAt(1)]; Object.values(V.LANCER_DIRS).forEach(step => { const dirCode = Object.keys(V.LANCER_DIRS).find(k => { @@ -507,10 +536,15 @@ export const VariantRules = class EightpiecesRules extends ChessRules { V.OnBoard(x + step[0], y + step[1]) && this.board[x + step[0]][y + step[1]] == V.EMPTY ) { + const newDirCode = Object.keys(V.LANCER_DIRS).find(k => { + const codeStep = V.LANCER_DIRS[k]; + return (codeStep[0] == step[0] && codeStep[1] == step[1]); + }); potentialNudges.push( this.getBasicMove( [x, y], - [x + step[0], y + step[1]] + [x + step[0], y + step[1]], + { c: color, p: newDirCode } ) ); } @@ -601,7 +635,7 @@ export const VariantRules = class EightpiecesRules extends ChessRules { i = y; do { if ( - this.isAttacked([x, i], [oppCol]) || + this.isAttacked([x, i], oppCol) || (this.board[x][i] != V.EMPTY && (this.getColor(x, i) != c || ![V.KING, V.ROOK, V.JAILER].includes(this.getPiece(x, i)))) @@ -683,11 +717,7 @@ export const VariantRules = class EightpiecesRules extends ChessRules { this.movesCount >= 2 ? filteredMoves : filteredMoves.filter(m => { - return ( - m.vanish.length <= 1 || - m.appear.length != 1 || - basicFilter(m, oppCol) - ); + return (m.vanish.length <= 1 && basicFilter(m, oppCol)); }) ).concat(movesWithSentryPushes); } @@ -732,9 +762,9 @@ export const VariantRules = class EightpiecesRules extends ChessRules { } play(move) { - if (!this.states) this.states = []; - const stateFen = this.getFen(); - this.states.push(stateFen); +// if (!this.states) this.states = []; +// const stateFen = this.getFen(); +// this.states.push(stateFen); this.prePlay(move); move.flags = JSON.stringify(this.aggregateFlags()); @@ -797,9 +827,9 @@ export const VariantRules = class EightpiecesRules extends ChessRules { } this.postUndo(move); - const stateFen = this.getFen(); - if (stateFen != this.states[this.states.length-1]) debugger; - this.states.pop(); +// const stateFen = this.getFen(); +// if (stateFen != this.states[this.states.length-1]) debugger; +// this.states.pop(); } postUndo(move) { @@ -807,15 +837,15 @@ export const VariantRules = class EightpiecesRules extends ChessRules { this.sentryPush.pop(); } - isAttacked(sq, colors) { + isAttacked(sq, color) { return ( - super.isAttacked(sq, colors) || - this.isAttackedByLancer(sq, colors) || - this.isAttackedBySentry(sq, colors) + super.isAttacked(sq, color) || + this.isAttackedByLancer(sq, color) || + this.isAttackedBySentry(sq, color) ); } - isAttackedBySlideNJump([x, y], colors, piece, steps, oneStep) { + isAttackedBySlideNJump([x, y], color, piece, steps, oneStep) { for (let step of steps) { let rx = x + step[0], ry = y + step[1]; @@ -825,8 +855,8 @@ export const VariantRules = class EightpiecesRules extends ChessRules { } if ( V.OnBoard(rx, ry) && - this.getPiece(rx, ry) === piece && - colors.includes(this.getColor(rx, ry)) && + this.getPiece(rx, ry) == piece && + this.getColor(rx, ry) == color && !this.isImmobilized([rx, ry]) ) { return true; @@ -835,27 +865,25 @@ export const VariantRules = class EightpiecesRules extends ChessRules { return false; } - isAttackedByPawn([x, y], colors) { - for (let c of colors) { - const 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 && - !this.isImmobilized([x + pawnShift, y + i]) - ) { - return true; - } + isAttackedByPawn([x, y], color) { + const pawnShift = (color == "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) == color && + !this.isImmobilized([x + pawnShift, y + i]) + ) { + return true; } } } return false; } - isAttackedByLancer([x, y], colors) { + isAttackedByLancer([x, y], color) { for (let step of V.steps[V.ROOK].concat(V.steps[V.BISHOP])) { // If in this direction there are only enemy pieces and empty squares, // and we meet a lancer: can he reach us? @@ -866,7 +894,7 @@ export const VariantRules = class EightpiecesRules extends ChessRules { V.OnBoard(coord.x, coord.y) && ( this.board[coord.x][coord.y] == V.EMPTY || - colors.includes(this.getColor(coord.x, coord.y)) + this.getColor(coord.x, coord.y) == color ) ) { if ( @@ -890,13 +918,20 @@ export const VariantRules = class EightpiecesRules extends ChessRules { selfAttack([x1, y1], [x2, y2]) { const color = this.getColor(x1, y1); const sliderAttack = (allowedSteps, lancer) => { - const deltaX = x2 - x1; - const deltaY = y2 - y1; - const step = [ deltaX / Math.abs(deltaX), deltaY / Math.abs(deltaY) ]; - if (allowedSteps.every(st => st[0] != step[0] || st[1] != step[1])) + const deltaX = x2 - x1, + absDeltaX = Math.abs(deltaX); + const deltaY = y2 - y1, + absDeltaY = Math.abs(deltaY); + const step = [ deltaX / absDeltaX || 0, deltaY / absDeltaY || 0 ]; + if ( + // Check that the step is a priori valid: + (absDeltaX != absDeltaY && deltaX != 0 && deltaY != 0) || + allowedSteps.every(st => st[0] != step[0] || st[1] != step[1]) + ) { return false; + } let sq = [ x1 + step[0], y1 + step[1] ]; - while (sq[0] != x2 && sq[1] != y2) { + while (sq[0] != x2 || sq[1] != y2) { if ( // NOTE: no need to check OnBoard in this special case (!lancer && this.board[sq[0]][sq[1]] != V.EMPTY) || @@ -941,17 +976,17 @@ export const VariantRules = class EightpiecesRules extends ChessRules { return false; } - isAttackedBySentry([x, y], colors) { + isAttackedBySentry([x, y], color) { // Attacked by sentry means it can self-take our king. // Just check diagonals of enemy sentry(ies), and if it reaches // one of our pieces: can I self-take? - const color = V.GetOppCol(colors[0]); + const myColor = V.GetOppCol(color); let candidates = []; for (let i=0; i