block chain moves which are known dead ends

This commit is contained in:
Jesse D. McDonald 2020-04-24 22:07:16 -05:00
parent 612a39e891
commit 2171bb00ee
2 changed files with 69 additions and 8 deletions

View File

@ -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" };

View File

@ -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)) {
continue;
}
} catch (err) {}
if (currentGame.isDeadEnd(from, there)) {
continue;
}
const square = cbSquare(there);
square.addClass('cb-legal')