X-Git-Url: https://git.sesse.net/?a=blobdiff_plain;ds=sidebyside;f=www%2Fjs%2Fbook.js;h=5ee769335390fe04463ce1756b5386c161232910;hb=74f1261e4067cbc1b743b329ed2d419aee735cbf;hp=8300be61da3391a1d4c517ab07f2d41c7a7524e1;hpb=b00d64218b75a44b86f2fbc8529765d0cd8cc9d0;p=remoteglot-book diff --git a/www/js/book.js b/www/js/book.js index 8300be6..5ee7693 100644 --- a/www/js/book.js +++ b/www/js/book.js @@ -5,6 +5,11 @@ 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_move = null; +var reverse_dragging_from = null; var entity_map = { "&": "&", @@ -48,11 +53,11 @@ var update = function() { board.position(current_display_fen()); } + $("#board").find('.square-55d63').removeClass('nonuglyhighlight'); if (move_override > 0) { var last_move = history[move_override - 1]; var highlight_from = last_move.from; var highlight_to = last_move.to; - $("#board").find('.square-55d63').removeClass('nonuglyhighlight'); $("#board").find('.square-' + highlight_from).addClass('nonuglyhighlight'); $("#board").find('.square-' + highlight_to).addClass('nonuglyhighlight'); } @@ -92,6 +97,8 @@ var headings = [ [ "Move", TYPE_MOVE ], [ "Games", TYPE_INTEGER ], [ "%", TYPE_RATIO ], + [ "CGames", TYPE_INTEGER ], + [ "Hum", TYPE_RATIO ], [ "Win%", TYPE_RATIO ], [ "WWin", TYPE_INTEGER ], [ "%WW", TYPE_RATIO ], @@ -167,12 +174,18 @@ var show_lines = function(data, game) { var white = parseInt(move['white']); var draw = parseInt(move['draw']); var black = parseInt(move['black']); + var computer = parseInt(move['computer']); line.push(move['move']); // Move. transpose_only.push(move['transpose_only']); var num = white + draw + black; line.push(num); // N. line.push(num / total_num); // %. + line.push(computer); // CGames. + + // Adjust so that the human index is 50% overall. + var exp = Math.log(0.5) / Math.log(data['computer_games'] / data['total_games']); + line.push(1.0 - Math.pow(computer / num, exp)); // Hum. // Win%. var white_win_ratio = (white + 0.5 * draw) / num; @@ -237,10 +250,14 @@ var show_lines = function(data, game) { } } - var move_a = document.createElement("a"); - move_a.href = "javascript:make_move('" + line[j] + "')"; - td.appendChild(move_a); - $(move_a).text(line[j]); + if (line[j] === '1-0' || line[j] === '1/2-1/2' || line[j] === '0-1') { + $(td).text($(td).text() + line[j]); + } else { + var move_a = document.createElement("a"); + move_a.href = "javascript:make_move('" + line[j] + "')"; + td.appendChild(move_a); + $(move_a).text(line[j]); + } } else if (headings[j][1] == TYPE_INTEGER) { add_td(tr, line[j] || 0); } else if (headings[j][1] == TYPE_FLOAT) { @@ -268,6 +285,11 @@ var set_includetransp = function(value) { } window['set_includetransp'] = set_includetransp; +var set_flipboard = function(value) { + board.orientation(value ? 'black' : 'white'); +} +window['set_flipboard'] = set_flipboard; + var make_move = function(move, do_update) { var history = game.history({ verbose: true }); if (move_override < history.length && history[move_override].san == move) { @@ -330,9 +352,124 @@ var onDragStart = function(source, piece, position, orientation) { (pseudogame.turn() === 'b' && piece.search(/^w/) !== -1)) { return false; } + + recommended_move = null; + get_best_dest(pseudogame, source, null, function(src, dest) { + $("#board").find('.square-55d63').removeClass('nonuglyhighlight'); + if (dest !== null) { + var squareEl = $('#board .square-' + dest); + squareEl.addClass('highlight1-32417'); + recommended_move = [src, dest]; + } + }); +} + +var mousedownSquare = function(e) { + reverse_dragging_from = null; + var square = $(this).attr('data-square'); + + var pseudogame = new Chess(current_display_fen()); + if (pseudogame.game_over() === true) { + return; + } + + // If the square is empty, or has a piece of the side not to move, + // we handle it. If not, normal piece dragging will take it. + var position = board.position(); + if (!position.hasOwnProperty(square) || + (pseudogame.turn() === 'w' && position[square].search(/^b/) !== -1) || + (pseudogame.turn() === 'b' && position[square].search(/^w/) !== -1)) { + reverse_dragging_from = square; + get_best_dest(pseudogame, null, square, function(src, dest) { + if (src !== null) { + var squareEl = $('#board .square-' + src); + squareEl.addClass('highlight1-32417'); + squareEl = $('#board .square-' + dest); + squareEl.addClass('highlight1-32417'); + recommended_move = [src, dest]; + } + }); + } else { + recommended_src = null; + } +} + +var mouseupSquare = function(e) { + if (reverse_dragging_from === null) { + return; + } + var source = $(this).attr('data-square'); + var target = reverse_dragging_from; + reverse_dragging_from = null; + if (onDrop(source, target) !== 'snapback') { + onSnapEnd(source, target); + } + $("#board").find('.square-55d63').removeClass('highlight1-32417'); +} + +var get_best_dest = function(game, source, target, cb) { + var moves = game.moves({ verbose: true }); + if (source !== null) { + moves = moves.filter(function(move) { return move.from == source; }); + } + if (target !== null) { + moves = moves.filter(function(move) { return move.to == target; }); + } + if (moves.length == 0) { + cb(null, null); + return; + } + if (moves.length == 1) { + cb(moves[0].from, 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], res[2]); + } + } + }; + 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_move === null) { + return 'snapback'; + } else { + // Accept the move. It will be changed in onSnapEnd. + return; + } + } else { + // Suggestion not asked for. + recommended_move = null; + } + // see if the move is legal var pseudogame = new Chess(current_display_fen()); var move = pseudogame.move({ @@ -346,6 +483,11 @@ var onDrop = function(source, target) { } var onSnapEnd = function(source, target) { + if (source == target && recommended_move !== null) { + source = recommended_move[0]; + target = recommended_move[1]; + } + recommended_move = null; var pseudogame = new Chess(current_display_fen()); var move = pseudogame.move({ from: source, @@ -388,6 +530,8 @@ var init = function() { onDrop: onDrop, onSnapEnd: onSnapEnd }); + $("#board").on('mousedown', '.square-55d63', mousedownSquare); + $("#board").on('mouseup', '.square-55d63', mouseupSquare); window.onpopstate = onpopstate; onpopstate(); @@ -399,8 +543,10 @@ var init = function() { prev_move(); } }); -} + // Seemingly the web worker is not started before we send it a message. + stockfish.postMessage("uci"); +} $(document).ready(init);