block chain moves which are known dead ends
This commit is contained in:
parent
612a39e891
commit
2171bb00ee
|
|
@ -757,6 +757,72 @@ class Game {
|
|||
return recordCheck(this, false);
|
||||
}
|
||||
|
||||
isDeadEnd(from, to) {
|
||||
const side = this._player;
|
||||
const sim = new Game(this);
|
||||
sim.dropHistory();
|
||||
|
||||
try {
|
||||
sim.move(from, to);
|
||||
} catch (err) {
|
||||
/* illegal moves are automatic dead ends */
|
||||
return true;
|
||||
}
|
||||
|
||||
if (!sim._board.phantom) {
|
||||
/* moves that leave the player in check are also dead ends */
|
||||
/* otherwise this is a legal non-chain move, so not a dead end */
|
||||
return sim.isInCheck(side);
|
||||
}
|
||||
|
||||
const seen = new Set();
|
||||
let queue = [sim];
|
||||
let counter = 0;
|
||||
|
||||
while (queue.length > 0) {
|
||||
const game = queue[0];
|
||||
queue = queue.slice(1);
|
||||
|
||||
seen.add(game._board.toString());
|
||||
|
||||
/* look for another piece that can reach the king or continue the chain */
|
||||
for (const toNext of game.legalMoves(side, PHANTOM, true)) {
|
||||
if (counter >= 300) {
|
||||
/* this is taking too long */
|
||||
const newMoves = game._moves.length - this._moves.length;
|
||||
console.log(`stopped looking for dead end after ${counter} moves (max length was ${newMoves})`);
|
||||
return undefined;
|
||||
}
|
||||
|
||||
++counter;
|
||||
|
||||
const game2 = new Game(game);
|
||||
try {
|
||||
game2.move(PHANTOM, toNext);
|
||||
} catch (err) {
|
||||
/* internal error */
|
||||
console.log('isDeadEnd:', err);
|
||||
continue;
|
||||
}
|
||||
|
||||
if (!game2._board.phantom) {
|
||||
/* skip moves that would leave the player in check */
|
||||
if (!game2.isInCheck(side)) {
|
||||
/* it's a legal non-chain move, so not a dead end */
|
||||
return false;
|
||||
}
|
||||
}
|
||||
else if (!seen.has(game2._board.toString())) {
|
||||
/* we haven't seen this exact board state before */
|
||||
queue.push(game2);
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
/* an exhaustive search didn't uncover any legal ways to end the chain */
|
||||
return true;
|
||||
}
|
||||
|
||||
move(from, to, meta) {
|
||||
if (this._status !== PLAYING) {
|
||||
throw { message: "can't move, game is already over" };
|
||||
|
|
|
|||
|
|
@ -147,14 +147,9 @@ $(function (){
|
|||
const from = piece.data('location');
|
||||
const legals = currentGame.legalMoves(side, from);
|
||||
for (const there of legals) {
|
||||
try {
|
||||
const preview = new PS.Game(currentGame);
|
||||
preview.dropHistory();
|
||||
preview.move(from, there);
|
||||
if (preview.isInCheck(side)) {
|
||||
if (currentGame.isDeadEnd(from, there)) {
|
||||
continue;
|
||||
}
|
||||
} catch (err) {}
|
||||
|
||||
const square = cbSquare(there);
|
||||
square.addClass('cb-legal')
|
||||
|
|
|
|||
Loading…
Reference in New Issue