k: [-17, -16, -15, 1, 17, 16, 15, -1]
};
- var ATTACKS = [
- 20, 0, 0, 0, 0, 0, 0, 24, 0, 0, 0, 0, 0, 0,20, 0,
- 0,20, 0, 0, 0, 0, 0, 24, 0, 0, 0, 0, 0,20, 0, 0,
- 0, 0,20, 0, 0, 0, 0, 24, 0, 0, 0, 0,20, 0, 0, 0,
- 0, 0, 0,20, 0, 0, 0, 24, 0, 0, 0,20, 0, 0, 0, 0,
- 0, 0, 0, 0,20, 0, 0, 24, 0, 0,20, 0, 0, 0, 0, 0,
- 0, 0, 0, 0, 0,20, 2, 24, 2,20, 0, 0, 0, 0, 0, 0,
- 0, 0, 0, 0, 0, 2,53, 56, 53, 2, 0, 0, 0, 0, 0, 0,
- 24,24,24,24,24,24,56, 0, 56,24,24,24,24,24,24, 0,
- 0, 0, 0, 0, 0, 2,53, 56, 53, 2, 0, 0, 0, 0, 0, 0,
- 0, 0, 0, 0, 0,20, 2, 24, 2,20, 0, 0, 0, 0, 0, 0,
- 0, 0, 0, 0,20, 0, 0, 24, 0, 0,20, 0, 0, 0, 0, 0,
- 0, 0, 0,20, 0, 0, 0, 24, 0, 0, 0,20, 0, 0, 0, 0,
- 0, 0,20, 0, 0, 0, 0, 24, 0, 0, 0, 0,20, 0, 0, 0,
- 0,20, 0, 0, 0, 0, 0, 24, 0, 0, 0, 0, 0,20, 0, 0,
- 20, 0, 0, 0, 0, 0, 0, 24, 0, 0, 0, 0, 0, 0,20
- ];
-
- var RAYS = [
- 17, 0, 0, 0, 0, 0, 0, 16, 0, 0, 0, 0, 0, 0, 15, 0,
- 0, 17, 0, 0, 0, 0, 0, 16, 0, 0, 0, 0, 0, 15, 0, 0,
- 0, 0, 17, 0, 0, 0, 0, 16, 0, 0, 0, 0, 15, 0, 0, 0,
- 0, 0, 0, 17, 0, 0, 0, 16, 0, 0, 0, 15, 0, 0, 0, 0,
- 0, 0, 0, 0, 17, 0, 0, 16, 0, 0, 15, 0, 0, 0, 0, 0,
- 0, 0, 0, 0, 0, 17, 0, 16, 0, 15, 0, 0, 0, 0, 0, 0,
- 0, 0, 0, 0, 0, 0, 17, 16, 15, 0, 0, 0, 0, 0, 0, 0,
- 1, 1, 1, 1, 1, 1, 1, 0, -1, -1, -1,-1, -1, -1, -1, 0,
- 0, 0, 0, 0, 0, 0,-15,-16,-17, 0, 0, 0, 0, 0, 0, 0,
- 0, 0, 0, 0, 0,-15, 0,-16, 0,-17, 0, 0, 0, 0, 0, 0,
- 0, 0, 0, 0,-15, 0, 0,-16, 0, 0,-17, 0, 0, 0, 0, 0,
- 0, 0, 0,-15, 0, 0, 0,-16, 0, 0, 0,-17, 0, 0, 0, 0,
- 0, 0,-15, 0, 0, 0, 0,-16, 0, 0, 0, 0,-17, 0, 0, 0,
- 0,-15, 0, 0, 0, 0, 0,-16, 0, 0, 0, 0, 0,-17, 0, 0,
- -15, 0, 0, 0, 0, 0, 0,-16, 0, 0, 0, 0, 0, 0,-17
- ];
-
- var SHIFTS = { p: 0, n: 1, b: 2, r: 3, q: 4, k: 5 };
-
var FLAGS = {
NORMAL: 'n',
CAPTURE: 'c',
}
function attacked(color, square) {
- for (var i = SQUARES.a8; i <= SQUARES.h1; i++) {
- /* did we run off the end of the board */
- if (i & 0x88) { i += 7; continue; }
+ // Check for attacks by the king.
+ if (Math.abs(rank(kings[color]) - rank(square)) <= 1 &&
+ Math.abs(file(kings[color]) - file(square)) <= 1) {
+ return true;
+ }
- /* if empty square or wrong color */
- if (board[i] == null || board[i].color !== color) continue;
+ // Check for attacks by knights.
+ for (const offset of PIECE_OFFSETS[KNIGHT]) {
+ let knight_sq = square + offset;
+ if (knight_sq & 0x88) continue;
- var piece = board[i];
- var difference = i - square;
- var index = difference + 119;
+ if (board[knight_sq] != null &&
+ board[knight_sq].type === KNIGHT &&
+ board[knight_sq].color === color) {
+ return true;
+ }
+ }
- if (ATTACKS[index] & (1 << SHIFTS[piece.type])) {
- if (piece.type === PAWN) {
- if (difference > 0) {
- if (piece.color === WHITE) return true;
- } else {
- if (piece.color === BLACK) return true;
+ // Check for attacks by pawns.
+ const p1sq = square - PAWN_OFFSETS[color][2];
+ const p2sq = square - PAWN_OFFSETS[color][3];
+ if (!(p1sq & 0x88) &&
+ board[p1sq] != null &&
+ board[p1sq].type === PAWN &&
+ board[p1sq].color === color) {
+ return true;
+ }
+ if (!(p2sq & 0x88) &&
+ board[p2sq] != null &&
+ board[p2sq].type === PAWN &&
+ board[p2sq].color === color) {
+ return true;
+ }
+
+ // Check for attacks by rooks (where queens count as rooks).
+ for (const offset of PIECE_OFFSETS[ROOK]) {
+ let rook_sq = square;
+ while (true) {
+ rook_sq += offset;
+ if (rook_sq & 0x88) break;
+
+ if (board[rook_sq] != null) {
+ if ((board[rook_sq].type === ROOK || board[rook_sq].type === QUEEN) &&
+ board[rook_sq].color === color) {
+ return true;
}
- continue;
+ break;
}
+ }
+ }
- /* if the piece is a knight or a king */
- if (piece.type === 'n' || piece.type === 'k') return true;
-
- var offset = RAYS[index];
- var j = i + offset;
+ // And similarly for attacks by bishops (where queens count as bishops).
+ for (const offset of PIECE_OFFSETS[BISHOP]) {
+ let bishop_sq = square;
+ while (true) {
+ bishop_sq += offset;
+ if (bishop_sq & 0x88) break;
- var blocked = false;
- while (j !== square) {
- if (board[j] != null) { blocked = true; break; }
- j += offset;
+ if (board[bishop_sq] != null) {
+ if ((board[bishop_sq].type === BISHOP || board[bishop_sq].type === QUEEN) &&
+ board[bishop_sq].color === color) {
+ return true;
+ }
+ break;
}
-
- if (!blocked) return true;
}
}
return '';
}
- let moves = find_attacking_moves(move.to, piece, move.color, sloppy);
+ let moves = find_attacking_moves(move.to, piece, move.color);
+ if (moves.length <= 1) {
+ // There can be no ambiguity, so don't bother checking legality
+ // (we assume the move has already been found legal).
+ return '';
+ }
+
+ moves = possibly_filter_moves(moves, move.color, !sloppy);
var ambiguities = 0;
var same_rank = 0;
return '';
}
- // Find all moves featuring the given piece attacking the given square
- // (using symmetry of all non-pawn-or-castle moves, we simply generate
- // moves backwards). Does not support kings or pawns. Assumes there's
- // not already a piece of our own color on the destination square.
- function find_attacking_moves(to, piece, us, sloppy) {
+ // Find all pseudolegal moves featuring the given piece attacking
+ // the given square (using symmetry of all non-pawn-or-castle moves,
+ // we simply generate // moves backwards). Does not support kings
+ // or pawns. Assumes there's // not already a piece of our own color
+ // on the destination square.
+ function find_attacking_moves(to, piece, us) {
let moves = [];
function add_move(board, moves, from, to, flags, rook_sq) {
}
}
- return possibly_filter_moves(moves, us, !sloppy);
+ return moves;
}
function ascii() {