X-Git-Url: https://git.auder.net/?a=blobdiff_plain;f=client%2Fsrc%2Fvariants%2FSynchrone.js;h=c8f2be575e97d392f93f8374ca885a59f6c920bd;hb=af34341d92d47d14f396e7f4adb81f2a7e9d9a61;hp=cee27c7528984472eed3c2e4f3a8ed8ca8add5bb;hpb=6b9378a6b88b81f71ce5ad5d332ab6accfe1994b;p=vchess.git diff --git a/client/src/variants/Synchrone.js b/client/src/variants/Synchrone.js index cee27c75..c8f2be57 100644 --- a/client/src/variants/Synchrone.js +++ b/client/src/variants/Synchrone.js @@ -16,12 +16,12 @@ export class SynchroneRules extends ChessRules { // 5) Check whiteMove if ( ( - fenParsed.turn == "w" && + fenParsed.turn == "b" && // NOTE: do not check really JSON stringified move... (!fenParsed.whiteMove || fenParsed.whiteMove == "-") ) || - (fenParsed.turn == "b" && fenParsed.whiteMove != "-") + (fenParsed.turn == "w" && fenParsed.whiteMove != "-") ) { return false; } @@ -106,20 +106,20 @@ export class SynchroneRules extends ChessRules { }); } - // NOTE: lazy unefficient implementation (for now. TODO?) getPossibleMovesFrom([x, y]) { - const moves = this.getAllValidMoves(); - return moves.filter(m => { - return m.start.x == x && m.start.y == y; - }); + let moves = this.filterValid(super.getPotentialMovesFrom([x, y])); + if (!this.underCheck(this.getColor(x, y))) + // Augment with potential recaptures, except if we are under check + Array.prototype.push.apply(moves, this.getRecaptures([x, y])); + return moves; } // Aux function used to find opponent and self captures - getCaptures(x, y, color) { + getCaptures(from, to, color) { const sliderAttack = (xx, yy, allowedSteps) => { - const deltaX = xx - x, + const deltaX = xx - to[0], absDeltaX = Math.abs(deltaX); - const deltaY = yy - y, + const deltaY = yy - to[1], absDeltaY = Math.abs(deltaY); const step = [ deltaX / absDeltaX || 0, deltaY / absDeltaY || 0 ]; if ( @@ -129,61 +129,70 @@ export class SynchroneRules extends ChessRules { ) { return null; } - let sq = [ x + step[0], y + step[1] ]; + let sq = [ to[0] + step[0], to[1] + step[1] ]; while (sq[0] != xx || sq[1] != yy) { // NOTE: no need to check OnBoard in this special case if (this.board[sq[0]][sq[1]] != V.EMPTY) return null; sq[0] += step[0]; sq[1] += step[1]; } - return this.getBasicMove([xx, yy], [x, y]); + return this.getBasicMove([xx, yy], [to[0], to[1]]); }; - // Can I take on the square [x, y] ? + // Can I take on the square 'to' ? // If yes, return the (list of) capturing move(s) + const getTargetedCaptures = ([i, j]) => { + let move = null; + // From [i, j]: + switch (this.getPiece(i, j)) { + case V.PAWN: { + // Pushed pawns move as enemy pawns + const shift = (color == 'w' ? 1 : -1); + if (to[0] + shift == i && Math.abs(to[1] - j) == 1) + move = this.getBasicMove([i, j], to); + break; + } + case V.KNIGHT: { + const deltaX = Math.abs(i - to[0]); + const deltaY = Math.abs(j - to[1]); + if ( + deltaX + deltaY == 3 && + [1, 2].includes(deltaX) && + [1, 2].includes(deltaY) + ) { + move = this.getBasicMove([i, j], to); + } + break; + } + case V.KING: + if (Math.abs(i - to[0]) <= 1 && Math.abs(j - to[1]) <= 1) + move = this.getBasicMove([i, j], to); + break; + case V.ROOK: { + move = sliderAttack(i, j, V.steps[V.ROOK]); + break; + } + case V.BISHOP: { + move = sliderAttack(i, j, V.steps[V.BISHOP]); + break; + } + case V.QUEEN: { + move = sliderAttack(i, j, V.steps[V.ROOK].concat(V.steps[V.BISHOP])); + break; + } + } + return move; + }; let moves = []; - for (let i=0; i<8; i++) { - for (let j=0; j<8; j++) { - if (this.getColor(i, j) == color) { - switch (this.getPiece(i, j)) { - case V.PAWN: { - // Pushed pawns move as enemy pawns - const shift = (color == 'w' ? 1 : -1); - if (x + shift == i && Math.abs(y - j) == 1) - moves.push(this.getBasicMove([i, j], [x, y])); - break; - } - case V.KNIGHT: { - const deltaX = Math.abs(i - x); - const deltaY = Math.abs(j - y); - if ( - deltaX + deltaY == 3 && - [1, 2].includes(deltaX) && - [1, 2].includes(deltaY) - ) { - moves.push(this.getBasicMove([i, j], [x, y])); - } - break; - } - case V.KING: - if (Math.abs(i - x) <= 1 && Math.abs(j - y) <= 1) - moves.push(this.getBasicMove([i, j], [x, y])); - break; - case V.ROOK: { - const mv = sliderAttack(i, j, V.steps[V.ROOK]); - if (!!mv) moves.push(mv); - break; - } - case V.BISHOP: { - const mv = sliderAttack(i, j, V.steps[V.BISHOP]); - if (!!mv) moves.push(mv); - break; - } - case V.QUEEN: { - const mv = sliderAttack( - i, j, V.steps[V.ROOK].concat(V.steps[V.BISHOP])); - if (!!mv) moves.push(mv); - break; - } + if (!!from) { + const theMove = getTargetedCaptures(from); + if (!!theMove) moves.push(theMove); + } + else { + for (let i=0; i<8; i++) { + for (let j=0; j<8; j++) { + if (this.getColor(i, j) == color) { + const newMove = getTargetedCaptures([i, j]); + if (!!newMove) moves.push(newMove); } } } @@ -191,12 +200,10 @@ export class SynchroneRules extends ChessRules { return this.filterValid(moves); } - getAllValidMoves() { - const color = this.turn; - // 0) Generate our possible moves - let myMoves = super.getAllValidMoves(); + getRecaptures(from) { // 1) Generate all opponent's capturing moves let oppCaptureMoves = []; + const color = this.turn; const oppCol = V.GetOppCol(color); for (let i=0; i<8; i++) { for (let j=0; j<8; j++) { @@ -207,7 +214,7 @@ export class SynchroneRules extends ChessRules { ) { Array.prototype.push.apply( oppCaptureMoves, - this.getCaptures(i, j, oppCol) + this.getCaptures(null, [i, j], oppCol) ); } } @@ -215,8 +222,9 @@ export class SynchroneRules extends ChessRules { // 2) Play each opponent's capture, and see if back-captures are possible: // Lookup table to quickly decide if a move is already in list: let moveSet = {}; + let moves = []; oppCaptureMoves.forEach(m => { - // If another opponent capture with same endpoint already processed, skip: + // If another opponent capture with same endpoint already processed, skip const mHash = "m" + m.end.x + m.end.y; if (!moveSet[mHash]) { moveSet[mHash] = true; @@ -227,11 +235,17 @@ export class SynchroneRules extends ChessRules { }; V.PlayOnBoard(this.board, justDisappear); // Can I take on [m.end.x, m.end.y] ? If yes, add to list: - this.getCaptures(m.end.x, m.end.y, color).forEach(cm => myMoves.push(cm)); + this.getCaptures(from, [m.end.x, m.end.y], color) + .forEach(cm => moves.push(cm)); V.UndoOnBoard(this.board, justDisappear); } }); - return myMoves; + return moves; + } + + getAllValidMoves() { + // Return possible moves + potential recaptures + return super.getAllValidMoves().concat(this.getRecaptures()); } filterValid(moves) { @@ -419,16 +433,17 @@ export class SynchroneRules extends ChessRules { } else this.whiteMove = move.whiteMove; } - getCheckSquares(color) { + getCheckSquares() { + const color = this.turn; if (color == 'b') { // kingPos must be reset for appropriate highlighting: var lastMove = JSON.parse(JSON.stringify(this.whiteMove)); this.undo(lastMove); //will erase whiteMove, thus saved above } let res = []; - if (this.underCheck('w')) + if (this.kingPos['w'][0] >= 0 && this.underCheck('w')) res.push(JSON.parse(JSON.stringify(this.kingPos['w']))); - if (this.underCheck('b')) + if (this.kingPos['b'][0] >= 0 && this.underCheck('b')) res.push(JSON.parse(JSON.stringify(this.kingPos['b']))); if (color == 'b') this.play(lastMove); return res;