]> git.sesse.net Git - remoteglot-book/blobdiff - www/js/book.js
Embed Stockfish (!) to get square suggestions whenever you pick up a piece.
[remoteglot-book] / www / js / book.js
index ebccd1ef2fdf99eb909134ecf3b1d5adcc6e6487..bc6adfceccca4174daf9ee78d0f274028abc050e 100644 (file)
@@ -5,6 +5,10 @@ var game = new Chess();
 var fens = [];
 var move_override = 0;
 var includetransp = true;
+var stockfish = new Worker('/js/stockfish.js');
+var engine_running = false;
+var engine_replacement_callback = null;
+var recommended_dest = null;
 
 var entity_map = {
        "&": "&",
@@ -338,9 +342,75 @@ var onDragStart = function(source, piece, position, orientation) {
            (pseudogame.turn() === 'b' && piece.search(/^w/) !== -1)) {
                return false;
        }
+
+       recommended_dest = null;
+       get_best_dest(pseudogame, source, function(dest) {
+               $("#board").find('.square-55d63').removeClass('nonuglyhighlight');
+               if (dest !== null) {
+                       var squareEl = $('#board .square-' + dest);
+                       squareEl.addClass('highlight1-32417');
+               }
+               recommended_dest = dest;
+       });
+}
+
+var get_best_dest = function(game, source, cb) {
+       var moves = game.moves({ square: source, verbose: true });
+       if (moves.length == 0) {
+               cb(null);
+               return;
+       }
+       if (moves.length == 1) {
+               cb(moves[0].to);
+               return;
+       }
+
+       // More than one move. Ask the engine to disambiguate.
+       var uci_moves = moves.map(function(m) { return m.from + m.to; });
+       var when_engine_is_ready = function() {
+               engine_running = true;
+               stockfish.onmessage = function(event) {
+                       var res = event.data.match(/^bestmove \S\S(\S\S)/);
+                       if (res !== null) {
+                               engine_running = false;
+                               if (engine_replacement_callback !== null) {
+                                       // We are no longer interested in this query,
+                                       // so just discard it and call this other callback.
+                                       engine_replacement_callback();
+                                       engine_replacement_callback = null;
+                               } else {
+                                       cb(res[1]);
+                               }
+                       }
+               };
+               stockfish.postMessage("position fen " + game.fen());
+               stockfish.postMessage("go depth 6 searchmoves " + uci_moves.join(" "));
+       };
+       if (engine_running) {
+               engine_replacement_callback = when_engine_is_ready;
+       } else {
+               when_engine_is_ready();
+       }
 }
 
 var onDrop = function(source, target) {
+       if (engine_running) {
+               // Snap end before the engine came back.
+               // Discard the result when it does.
+               engine_replacement_callback = function() {};
+       }
+       if (source == target) {
+               if (recommended_dest === null) {
+                       return 'snapback';
+               } else {
+                       // Accept the move. It will be changed in onSnapEnd.
+                       return;
+               }
+       } else {
+               // Suggestion not asked for.
+               recommended_dest = null;
+       }
+
        // see if the move is legal
        var pseudogame = new Chess(current_display_fen());
        var move = pseudogame.move({
@@ -354,6 +424,10 @@ var onDrop = function(source, target) {
 }
 
 var onSnapEnd = function(source, target) {
+       if (source == target && recommended_dest !== null) {
+               target = recommended_dest;
+       }
+       recommended_dest = null;
        var pseudogame = new Chess(current_display_fen());
        var move = pseudogame.move({
                from: source,