X-Git-Url: https://git.auder.net/?a=blobdiff_plain;f=client%2Fsrc%2Fvariants%2FBaroque.js;h=7abb77d47776add03ef39119de8ee56651b9e4c9;hb=4313762da3237b04f204e121a20cab3ba7bb5dd2;hp=246f51110dcdc2b6c54f56d8d4f44401882cf2be;hpb=f35b9960e1c527fc400ebac85321bd4712459da3;p=vchess.git diff --git a/client/src/variants/Baroque.js b/client/src/variants/Baroque.js index 246f5111..7abb77d4 100644 --- a/client/src/variants/Baroque.js +++ b/client/src/variants/Baroque.js @@ -1,8 +1,9 @@ import { ChessRules, PiPo, Move } from "@/base_rules"; import { ArrayFun } from "@/utils/array"; -import { randInt } from "@/utils/alea"; +import { shuffle } from "@/utils/alea"; + +export class BaroqueRules extends ChessRules { -export const VariantRules = class BaroqueRules extends ChessRules { static get HasFlags() { return false; } @@ -38,7 +39,7 @@ export const VariantRules = class BaroqueRules extends ChessRules { this.kingPos["w"] = [i, k]; break; default: { - const num = parseInt(position[i].charAt(j)); + const num = parseInt(position[i].charAt(j), 10); if (!isNaN(num)) k += num - 1; } } @@ -87,7 +88,8 @@ export const VariantRules = class BaroqueRules extends ChessRules { } return true; //immobilizer isn't neutralized } - // Chameleons can't be immobilized twice, because there is only one immobilizer + // Chameleons can't be immobilized twice, + // because there is only one immobilizer if (oppPiece == V.BISHOP && piece == V.IMMOBILIZER) return true; } } @@ -105,23 +107,11 @@ export const VariantRules = class BaroqueRules extends ChessRules { } } - getSlideNJumpMoves([x, y], steps, oneStep) { - const piece = this.getPiece(x, y); - let moves = []; - outerLoop: for (let step of steps) { - let i = 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]; - j += step[1]; - } - // Only king can take on occupied square: - if (piece == V.KING && V.OnBoard(i, j) && this.canTake([x, y], [i, j])) - moves.push(this.getBasicMove([x, y], [i, j])); - } - return moves; + canTake([x1, y1], [x2, y2]) { + return ( + this.getPiece(x1, y1) == V.KING && + this.getColor(x1, y1) != this.getColor(x2, y2) + ); } // Modify capturing moves among listed pawn moves @@ -130,7 +120,9 @@ export const VariantRules = class BaroqueRules extends ChessRules { const color = this.turn; const oppCol = V.GetOppCol(color); moves.forEach(m => { - if (!!byChameleon && m.start.x != m.end.x && m.start.y != m.end.y) return; //chameleon not moving as pawn + if (!!byChameleon && m.start.x != m.end.x && m.start.y != m.end.y) + // Chameleon not moving as pawn + return; // Try capturing in every direction for (let step of steps) { const sq2 = [m.end.x + 2 * step[0], m.end.y + 2 * step[1]]; @@ -224,10 +216,11 @@ export const VariantRules = class BaroqueRules extends ChessRules { ) { continue; } - // last(thing), cur(thing) : stop if "cur" is our color, or beyond board limits, - // or if "last" isn't empty and cur neither. Otherwise, if cur is empty then - // add move until cur square; if cur is occupied then stop if !!byChameleon and - // the square not occupied by a leaper. + // last(thing), cur(thing) : stop if "cur" is our color, + // or beyond board limits, or if "last" isn't empty and cur neither. + // Otherwise, if cur is empty then add move until cur square; + // if cur is occupied then stop if !!byChameleon and the square not + // occupied by a leaper. let last = [i, j]; let cur = [i + step[0], j + step[1]]; let vanished = [new PiPo({ x: x, y: y, c: color, p: piece })]; @@ -289,12 +282,7 @@ export const VariantRules = class BaroqueRules extends ChessRules { mergedMoves[key].vanish.push(m.vanish[i]); } }); - // Finally return an array - moves = []; - Object.keys(mergedMoves).forEach(k => { - moves.push(mergedMoves[k]); - }); - return moves; + return Object.values(mergedMoves); } addQueenCaptures(moves, byChameleon) { @@ -352,17 +340,9 @@ export const VariantRules = class BaroqueRules extends ChessRules { return super.getPotentialQueenMoves(sq); } - getPotentialKingMoves(sq) { - return this.getSlideNJumpMoves( - sq, - V.steps[V.ROOK].concat(V.steps[V.BISHOP]), - "oneStep" - ); - } - // isAttacked() is OK because the immobilizer doesn't take - isAttackedByPawn([x, y], colors) { + isAttackedByPawn([x, y], color) { // Square (x,y) must be surroundable by two enemy pieces, // and one of them at least should be a pawn (moving). const dirs = [ @@ -375,12 +355,17 @@ export const VariantRules = class BaroqueRules extends ChessRules { const [i2, j2] = [x + dir[0], y + dir[1]]; //"after" if (V.OnBoard(i1, j1) && V.OnBoard(i2, j2)) { if ( - (this.board[i1][j1] != V.EMPTY && - colors.includes(this.getColor(i1, j1)) && - this.board[i2][j2] == V.EMPTY) || - (this.board[i2][j2] != V.EMPTY && - colors.includes(this.getColor(i2, j2)) && - this.board[i1][j1] == V.EMPTY) + ( + this.board[i1][j1] != V.EMPTY && + this.getColor(i1, j1) == color && + this.board[i2][j2] == V.EMPTY + ) + || + ( + this.board[i2][j2] != V.EMPTY && + this.getColor(i2, j2) == color && + this.board[i1][j1] == V.EMPTY + ) ) { // Search a movable enemy pawn landing on the empty square for (let step of steps) { @@ -392,7 +377,7 @@ export const VariantRules = class BaroqueRules extends ChessRules { } if ( V.OnBoard(i3, j3) && - colors.includes(this.getColor(i3, j3)) && + this.getColor(i3, j3) == color && this.getPiece(i3, j3) == V.PAWN && !this.isImmobilized([i3, j3]) ) { @@ -405,31 +390,33 @@ export const VariantRules = class BaroqueRules extends ChessRules { return false; } - isAttackedByRook([x, y], colors) { + isAttackedByRook([x, y], color) { // King must be on same column or row, // and a rook should be able to reach a capturing square - // colors contains only one element, giving the oppCol and thus king position - const sameRow = x == this.kingPos[colors[0]][0]; - const sameColumn = y == this.kingPos[colors[0]][1]; + const sameRow = x == this.kingPos[color][0]; + const sameColumn = y == this.kingPos[color][1]; if (sameRow || sameColumn) { // Look for the enemy rook (maximum 1) 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 && - colors.includes(this.getColor(i, j)) && + this.getColor(i, j) == color && this.getPiece(i, j) == V.ROOK ) { - if (this.isImmobilized([i, j])) return false; //because only one rook - // Can it reach a capturing square? - // Easy but quite suboptimal way (TODO): generate all moves (turn is OK) + if (this.isImmobilized([i, j])) + // Because only one rook: + return false; + // Can it reach a capturing square? Easy but quite suboptimal way + // (TODO: generate all moves (turn is OK)) const moves = this.getPotentialMovesFrom([i, j]); for (let move of moves) { if ( (sameRow && move.end.y == y) || (sameColumn && move.end.x == x) - ) + ) { return true; + } } } } @@ -438,7 +425,7 @@ export const VariantRules = class BaroqueRules extends ChessRules { return false; } - isAttackedByKnight([x, y], colors) { + isAttackedByKnight([x, y], color) { // Square (x,y) must be on same line as a knight, // and there must be empty square(s) behind. const steps = V.steps[V.ROOK].concat(V.steps[V.BISHOP]); @@ -453,15 +440,17 @@ export const VariantRules = class BaroqueRules extends ChessRules { j -= step[1]; } if (V.OnBoard(i, j)) { - if (colors.includes(this.getColor(i, j))) { + if (this.getColor(i, j) == color) { if ( this.getPiece(i, j) == V.KNIGHT && !this.isImmobilized([i, j]) - ) + ) { return true; + } continue outerLoop; } - // [else] Our color, could be captured *if there was an empty space* + // [else] Our color, + // could be captured *if there was an empty space* if (this.board[i + step[0]][j + step[1]] != V.EMPTY) continue outerLoop; i -= step[0]; @@ -473,7 +462,7 @@ export const VariantRules = class BaroqueRules extends ChessRules { return false; } - isAttackedByBishop([x, y], colors) { + isAttackedByBishop([x, y], color) { // We cheat a little here: since this function is used exclusively for // the king, it's enough to check the immediate surrounding of the square. const adjacentSteps = V.steps[V.ROOK].concat(V.steps[V.BISHOP]); @@ -482,16 +471,17 @@ export const VariantRules = class BaroqueRules extends ChessRules { if ( V.OnBoard(i, j) && this.board[i][j] != V.EMPTY && - colors.includes(this.getColor(i, j)) && - this.getPiece(i, j) == V.BISHOP + this.getColor(i, j) == color && + this.getPiece(i, j) == V.BISHOP && + !this.isImmobilized([i, j]) ) { - return true; //bishops are never immobilized + return true; } } return false; } - isAttackedByQueen([x, y], colors) { + isAttackedByQueen([x, y], color) { // Square (x,y) must be adjacent to a queen, and the queen must have // some free space in the opposite direction from (x,y) const adjacentSteps = V.steps[V.ROOK].concat(V.steps[V.BISHOP]); @@ -501,7 +491,7 @@ export const VariantRules = class BaroqueRules extends ChessRules { const sq1 = [x + step[0], y + step[1]]; if ( this.board[sq1[0]][sq1[1]] != V.EMPTY && - colors.includes(this.getColor(sq1[0], sq1[1])) && + this.getColor(sq1[0], sq1[1]) == color && this.getPiece(sq1[0], sq1[1]) == V.QUEEN && !this.isImmobilized(sq1) ) { @@ -512,7 +502,7 @@ export const VariantRules = class BaroqueRules extends ChessRules { return false; } - isAttackedByKing([x, y], colors) { + isAttackedByKing([x, y], color) { const steps = V.steps[V.ROOK].concat(V.steps[V.BISHOP]); for (let step of steps) { let rx = x + step[0], @@ -520,7 +510,7 @@ export const VariantRules = class BaroqueRules extends ChessRules { if ( V.OnBoard(rx, ry) && this.getPiece(rx, ry) === V.KING && - colors.includes(this.getColor(rx, ry)) && + this.getColor(rx, ry) == color && !this.isImmobilized([rx, ry]) ) { return true; @@ -529,75 +519,23 @@ export const VariantRules = class BaroqueRules extends ChessRules { return false; } - static get VALUES() { - return { - p: 1, - r: 2, - n: 5, - b: 3, - q: 3, - m: 5, - k: 1000 - }; - } - - static get SEARCH_DEPTH() { - return 2; - } - - static GenRandInitFen(randomness) { - if (randomness == 0) + static GenRandInitFen(options) { + if (options.randomness == 0) // Deterministic: - return "rnbqkbnrm/pppppppp/8/8/8/8/PPPPPPPP/MNBKQBNR w 0"; + return "rnbkqbnm/pppppppp/8/8/8/8/PPPPPPPP/MNBQKBNR w 0"; let pieces = { w: new Array(8), b: new Array(8) }; // Shuffle pieces on first and last rank for (let c of ["w", "b"]) { - if (c == 'b' && randomness == 1) { + if (c == 'b' && options.randomness == 1) { pieces['b'] = pieces['w']; break; } - let positions = ArrayFun.range(8); // Get random squares for every piece, totally freely - - let randIndex = randInt(8); - const bishop1Pos = positions[randIndex]; - positions.splice(randIndex, 1); - - randIndex = randInt(7); - const bishop2Pos = positions[randIndex]; - positions.splice(randIndex, 1); - - randIndex = randInt(6); - const knight1Pos = positions[randIndex]; - positions.splice(randIndex, 1); - - randIndex = randInt(5); - const knight2Pos = positions[randIndex]; - positions.splice(randIndex, 1); - - randIndex = randInt(4); - const queenPos = positions[randIndex]; - positions.splice(randIndex, 1); - - randIndex = randInt(3); - const kingPos = positions[randIndex]; - positions.splice(randIndex, 1); - - randIndex = randInt(2); - const rookPos = positions[randIndex]; - positions.splice(randIndex, 1); - const immobilizerPos = positions[0]; - - pieces[c][bishop1Pos] = "b"; - pieces[c][bishop2Pos] = "b"; - pieces[c][knight1Pos] = "n"; - pieces[c][knight2Pos] = "n"; - pieces[c][queenPos] = "q"; - pieces[c][kingPos] = "k"; - pieces[c][rookPos] = "r"; - pieces[c][immobilizerPos] = "m"; + let positions = shuffle(ArrayFun.range(8)); + const composition = ['r', 'n', 'b', 'q', 'k', 'b', 'n', 'm']; + for (let i = 0; i < 8; i++) pieces[c][positions[i]] = composition[i]; } return ( pieces["b"].join("") + @@ -607,6 +545,22 @@ export const VariantRules = class BaroqueRules extends ChessRules { ); } + static get VALUES() { + return { + p: 1, + r: 2, + n: 5, + b: 3, + q: 3, + m: 5, + k: 1000 + }; + } + + static get SEARCH_DEPTH() { + return 2; + } + getNotation(move) { const initialSquare = V.CoordsToSquare(move.start); const finalSquare = V.CoordsToSquare(move.end); @@ -621,4 +575,5 @@ export const VariantRules = class BaroqueRules extends ChessRules { if (move.vanish.length > 1 && move.appear[0].p != V.KING) notation += "X"; return notation; } + };