]> git.sesse.net Git - remoteglot/blobdiff - www/js/chess.js
chess.js: Much faster disambiguation.
[remoteglot] / www / js / chess.js
index 569d7c8b7f4ca2de2eb5dac2de130076b51e137a..9a2d383047dc167bebb571e4e4b515601cbd6589 100644 (file)
@@ -242,7 +242,7 @@ var Chess = function(fen) {
     var i, flag;
     if (white_frc_columns !== null) {
       for (i = 0; i < white_frc_columns.length; ++i) {
-        var sq = SQUARES.a1 + (white_frc_columns[0].charCodeAt(0) - "A".charCodeAt(0));
+        var sq = SQUARES.a1 + (white_frc_columns[i].charCodeAt(0) - "A".charCodeAt(0));
         flag = sq < kings[WHITE] ? BITS.QSIDE_CASTLE : BITS.KSIDE_CASTLE;
         castling.w |= flag;
         rooks[WHITE].push({square: sq, flag: flag});
@@ -270,7 +270,7 @@ var Chess = function(fen) {
     var black_frc_columns = tokens[2].match(/[a-h]/g);
     if (black_frc_columns !== null) {
       for (i = 0; i < black_frc_columns.length; ++i) {
-        var sq = SQUARES.a1 + (black_frc_columns[0].charCodeAt(0) - "A".charCodeAt(0));
+        var sq = SQUARES.a8 + (black_frc_columns[i].charCodeAt(0) - "a".charCodeAt(0));
         flag = sq < kings[BLACK] ? BITS.QSIDE_CASTLE : BITS.KSIDE_CASTLE;
         castling.b |= flag;
         rooks[BLACK].push({square: sq, flag: flag});
@@ -708,6 +708,10 @@ var Chess = function(fen) {
       }
     }
 
+    return possibly_filter_moves(moves, us, legal);
+  }
+
+  function possibly_filter_moves(moves, us, legal) {
     /* return all pseudo-legal moves (this includes moves that allow the king
      * to be captured)
      */
@@ -968,11 +972,12 @@ var Chess = function(fen) {
   function make_move(move) {
     var us = turn;
     var them = swap_color(us);
-    var old_to = board[move.to];
     push(move);
 
     board[move.to] = board[move.from];
-    board[move.from] = null;
+    if (move.from != move.to) {
+      board[move.from] = null;
+    }
 
     /* if ep capture, remove the captured pawn */
     if (move.flags & BITS.EP_CAPTURE) {
@@ -996,14 +1001,14 @@ var Chess = function(fen) {
       if (move.flags & BITS.KSIDE_CASTLE) {
         var castling_to = move.to - 1;
         var castling_from = move.rook_sq;
-        board[castling_to] = old_to===null ? board[castling_from] : old_to;
-        if(castling_from !== move.to)
+        board[castling_to] = {type: ROOK, color: us};
+        if(castling_from !== move.to && castling_from !== castling_to)
           board[castling_from] = null;
       } else if (move.flags & BITS.QSIDE_CASTLE) {
         var castling_to = move.to + 1;
         var castling_from = move.rook_sq;
-        board[castling_to] = old_to===null ? board[castling_from] : old_to;
-        if(castling_from !== move.to)
+        board[castling_to] = {type: ROOK, color: us};
+        if(castling_from !== move.to && castling_from !== castling_to)
           board[castling_from] = null;
       }
 
@@ -1074,11 +1079,11 @@ var Chess = function(fen) {
     var us = turn;
     var them = swap_color(turn);
 
-    var old_from = board[move.from];
-
-    board[move.from] = board[move.to];
-    board[move.from].type = move.piece;  // to undo any promotions
-    board[move.to] = null;
+    if (move.from != move.to) {
+      board[move.from] = board[move.to];
+      board[move.from].type = move.piece;  // to undo any promotions
+      board[move.to] = null;
+    }
 
     if (move.flags & BITS.CAPTURE) {
       board[move.to] = {type: move.captured, color: them};
@@ -1103,8 +1108,8 @@ var Chess = function(fen) {
         castling_from = move.to + 1;
       }
 
-      board[castling_to] = old_from===null ? board[castling_from] : old_from;
-      if(castling_from !== move.from)
+      board[castling_to] = {type: ROOK, color: us};
+      if(castling_from !== move.from && castling_from !== castling_to)
         board[castling_from] = null;
     }
 
@@ -1113,12 +1118,17 @@ var Chess = function(fen) {
 
   /* this function is used to uniquely identify ambiguous moves */
   function get_disambiguator(move, sloppy) {
-    var moves = generate_moves({legal: !sloppy});
-
     var from = move.from;
     var to = move.to;
     var piece = move.piece;
 
+    if (piece === 'p' || piece === 'k') {
+       // Pawn or king moves are never ambiguous.
+       return '';
+    }
+
+    let moves = find_attacking_moves(move.to, piece, move.color, sloppy);
+
     var ambiguities = 0;
     var same_rank = 0;
     var same_file = 0;
@@ -1166,6 +1176,41 @@ var Chess = function(fen) {
     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) {
+    let moves = [];
+
+    function add_move(board, moves, from, to, flags, rook_sq) {
+      moves.push(build_move(board, from, to, flags, undefined, rook_sq));
+    }
+    for (let offset of PIECE_OFFSETS[piece]) {
+      var square = to;
+
+      while (true) {
+        square += offset;
+        if (square & 0x88) break;
+
+        if (board[square] != null) {
+          if (board[square].color !== us) break;
+          if (board[to] == null) {
+            add_move(board, moves, square, to, BITS.NORMAL);
+          } else {
+            add_move(board, moves, square, to, BITS.CAPTURE);
+          }
+          break;
+        }
+
+        /* break if knight */
+        if (piece === 'n') break;
+      }
+    }
+
+    return possibly_filter_moves(moves, us, !sloppy);
+  }
+
   function ascii() {
     var s = '   +------------------------+\n';
     for (var i = SQUARES.a8; i <= SQUARES.h1; i++) {