X-Git-Url: https://git.auder.net/?a=blobdiff_plain;f=client%2Fsrc%2Fvariants%2FFootball.js;h=d63cfee3ac33d84dda458bb5679e2eb918096208;hb=2cfc3b918bf2c6581199f9ca72b61112c35fdb15;hp=a6630584c059073ddad55672f40c6ce303f4b865;hpb=5c50b18ebe03fd485ab1e5301a37bec8b14a0ff8;p=vchess.git diff --git a/client/src/variants/Football.js b/client/src/variants/Football.js index a6630584..d63cfee3 100644 --- a/client/src/variants/Football.js +++ b/client/src/variants/Football.js @@ -108,7 +108,6 @@ export class FootballRules extends ChessRules { if (randomness == 0) return "rnbq1knbr/9/9/9/4a4/9/9/9/RNBQ1KNBR w 0"; - // TODO: following is mostly copy-paste from Suicide variant let pieces = { w: new Array(8), b: new Array(8) }; for (let c of ["w", "b"]) { if (c == 'b' && randomness == 1) { @@ -119,12 +118,16 @@ export class FootballRules extends ChessRules { // Get random squares for every piece, totally freely let positions = shuffle(ArrayFun.range(8)); const composition = ['b', 'b', 'r', 'r', 'n', 'n', 'k', 'q']; - const rem2 = positions[0] % 2; - if (rem2 == positions[1] % 2) { - // Fix bishops (on different colors) + // Fix bishops (on different colors) + const realOddity = + (pos) => { return (pos <= 3 ? pos % 2 : (pos + 1) % 2); }; + const rem2 = realOddity(positions[0]); + if (rem2 == realOddity(positions[1])) { for (let i=2; i<8; i++) { - if (positions[i] % 2 != rem2) + if (realOddity(positions[i]) != rem2) { [positions[1], positions[i]] = [positions[i], positions[1]]; + break; + } } } for (let i = 0; i < 8; i++) pieces[c][positions[i]] = composition[i]; @@ -188,36 +191,98 @@ export class FootballRules extends ChessRules { let [i, j] = [bp[0] + step[0], bp[1] + step[1]]; const horizontalStepOnGoalRow = ([0, 8].includes(bp[0]) && step.some(s => s == 0)); - if (emptySquare(i, j) && (!horizontalStepOnGoalRow || j != 4)) { + if ( + emptySquare(i, j) && + (this.movesCount >= 2 || j != 4 || ![0, 8].includes(i)) && + (!horizontalStepOnGoalRow || j != 4) + ) { moves.push(super.getBasicMove(bp, [i, j])); if (!oneStep) { do { i += step[0]; j += step[1]; if (!emptySquare(i, j)) break; - if (!horizontalStepOnGoalRow || j != 4) + if ( + (this.movesCount >= 2 || j != 4 || ![0, 8].includes(i)) && + (!horizontalStepOnGoalRow || j != 4) + ) { moves.push(super.getBasicMove(bp, [i, j])); + } + } while (true); + } + } + // Try the other direction (TODO: experimental) + [i, j] = [bp[0] - 2*step[0], bp[1] - 2*step[1]]; + if ( + emptySquare(i, j) && + (this.movesCount >= 2 || j != 4 || ![0, 8].includes(i)) && + (!horizontalStepOnGoalRow || j != 4) + ) { + moves.push(super.getBasicMove(bp, [i, j])); + if (!oneStep) { + do { + i -= step[0]; + j -= step[1]; + if (!emptySquare(i, j)) break; + if ( + (this.movesCount >= 2 || j != 4 || ![0, 8].includes(i)) && + (!horizontalStepOnGoalRow || j != 4) + ) { + moves.push(super.getBasicMove(bp, [i, j])); + } } while (true); } } } const kickedFrom = x + "-" + y; - moves.forEach(m => m.by = kickedFrom) + moves.forEach(m => m.start.by = kickedFrom) return moves; } getPotentialMovesFrom([x, y], computer) { - if (V.PIECES.includes(this.getPiece(x, y))) { + const piece = this.getPiece(x, y); + if (V.PIECES.includes(piece)) { if (this.subTurn > 1) return []; - return ( - super.getPotentialMovesFrom([x, y]) - .filter(m => m.end.y != 4 || ![0, 8].includes(m.end.x)) - ); + const moves = super.getPotentialMovesFrom([x, y]) + .filter(m => m.end.y != 4 || ![0, 8].includes(m.end.x)); + // If bishop stuck in a corner: allow to jump over the next obstacle + if (moves.length == 0 && piece == V.BISHOP) { + if ( + x == 0 && y == 0 && + this.board[1][1] != V.EMPTY && + this.board[2][2] == V.EMPTY + ) { + return [super.getBasicMove([x, y], [2, 2])]; + } + if ( + x == 0 && y == 8 && + this.board[1][7] != V.EMPTY && + this.board[2][6] == V.EMPTY + ) { + return [super.getBasicMove([x, y], [2, 6])]; + } + if ( + x == 8 && y == 0 && + this.board[7][1] != V.EMPTY && + this.board[6][2] == V.EMPTY + ) { + return [super.getBasicMove([x, y], [6, 2])]; + } + if ( + x == 8 && y == 8 && + this.board[7][7] != V.EMPTY && + this.board[6][6] == V.EMPTY + ) { + return [super.getBasicMove([x, y], [6, 6])]; + } + } + return moves; } // Kicking the ball: look for adjacent pieces. const steps = V.steps[V.ROOK].concat(V.steps[V.BISHOP]); const c = this.turn; let moves = []; + let kicks = {}; for (let s of steps) { const [i, j] = [x + s[0], y + s[1]]; if ( @@ -225,15 +290,24 @@ export class FootballRules extends ChessRules { this.board[i][j] != V.EMPTY && this.getColor(i, j) == c ) { - Array.prototype.push.apply(moves, this.tryKickFrom([i, j])); + const kmoves = this.tryKickFrom([i, j]); + kmoves.forEach(km => { + const key = V.CoordsToSquare(km.start) + V.CoordsToSquare(km.end); + if (!kicks[km]) { + moves.push(km); + kicks[km] = true; + } + }); } } - // And, always add the "end" move. For computer, keep only one - outerLoop: for (let i=0; i < V.size.x; i++) { - for (let j=0; j < V.size.y; j++) { - if (this.board[i][j] != V.EMPTY && this.getColor(i, j) == c) { - moves.push(super.getBasicMove([x, y], [i, j])); - if (!!computer) break outerLoop; + if (Object.keys(kicks).length > 0) { + // And, always add the "end" move. For computer, keep only one + outerLoop: for (let i=0; i < V.size.x; i++) { + for (let j=0; j < V.size.y; j++) { + if (this.board[i][j] != V.EMPTY && this.getColor(i, j) == c) { + moves.push(super.getBasicMove([x, y], [i, j])); + if (!!computer) break outerLoop; + } } } } @@ -282,7 +356,7 @@ export class FootballRules extends ChessRules { filterValid(moves) { const L = this.kickedBy.length; const kb = this.kickedBy[L-1]; - return moves.filter(m => !m.by || !kb[m.by]); + return moves.filter(m => !m.start.by || !kb[m.start.by]); } getCheckSquares() { @@ -329,9 +403,9 @@ export class FootballRules extends ChessRules { } else { this.subTurn++; - if (!!move.by) { + if (!!move.start.by) { const L = this.kickedBy.length; - this.kickedBy[L-1][move.by] = true; + this.kickedBy[L-1][move.start.by] = true; } } } @@ -345,9 +419,9 @@ export class FootballRules extends ChessRules { } else { this.subTurn--; - if (!!move.by) { + if (!!move.start.by) { const L = this.kickedBy.length; - delete this.kickedBy[L-1][move.by]; + delete this.kickedBy[L-1][move.start.by]; } } if (!passesOver) {