From 19489f3bf92a655fa3ae4291773a3f8060f0b939 Mon Sep 17 00:00:00 2001 From: "Steinar H. Gunderson" Date: Mon, 15 Dec 2014 23:11:09 +0100 Subject: [PATCH] Stop replaying the game every move; Chess.js is so slow, it eventually takes hundreds of milliseconds. --- www/js/book.js | 96 ++++++++++++++++++++++++++------------------------ 1 file changed, 49 insertions(+), 47 deletions(-) diff --git a/www/js/book.js b/www/js/book.js index 36a9a26..5998058 100644 --- a/www/js/book.js +++ b/www/js/book.js @@ -1,7 +1,8 @@ (function() { var board = null; -var history = []; +var game = new Chess(); +var fens = []; var move_override = 0; var includetransp = true; @@ -19,40 +20,36 @@ function escape_html(string) { }); } -var get_game = function(skip_last_move) { - var moves_to_drop = 0; - if (skip_last_move === true) { - moves_to_drop = 1; - } - - var game = new Chess(); - for (var i = 0; i < move_override - moves_to_drop; ++i) { - game.move(history[i]); +var current_display_fen = function() { + if (move_override == 0) { + return 'rnbqkbnr/pppppppp/8/8/8/8/PPPPPPPP/RNBQKBNR w KQkq - 0 1'; + } else { + return fens[move_override - 1]; } - return game; } var update = function() { var text = ""; + var history = game.history({ verbose: true }); for (var i = 0; i < history.length; ++i) { if (i % 2 == 0) { text += (i/2 + 1) + ". "; } if (i + 1 == move_override) { - text += '' + history[i] + ''; + text += '' + history[i].san + ''; } else { - text += '' + history[i] + ''; + text += '' + history[i].san + ''; } text += " "; } $('#gamehistory').html(text); - var game = get_game(); - board.position(game.fen()); + if (board.fen() != current_display_fen()) { + board.position(current_display_fen()); + } - var all_moves = game.history({ verbose: true }); - if (all_moves.length > 0) { - var last_move = all_moves.pop(); + 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'); @@ -64,8 +61,7 @@ var update = function() { } var fetch_analysis = function() { - var game = get_game(); - var fen = game.fen(); + var fen = current_display_fen(); $.ajax({ url: "/opening-stats.pl?fen=" + encodeURIComponent(fen) + ";includetransp=" + (includetransp ? 1 : 0) @@ -174,7 +170,7 @@ var show_lines = function(data, game) { // Win%. var white_win_ratio = (white + 0.5 * draw) / num; - var win_ratio = (game.turn() == 'w') ? white_win_ratio : 1.0 - white_win_ratio; + var win_ratio = (i % 2 == 0) ? white_win_ratio : 1.0 - white_win_ratio; line.push(win_ratio); line.push(white); // WWin. @@ -194,7 +190,7 @@ var show_lines = function(data, game) { var win_elo = -400.0 * Math.log(1.0 / white_win_ratio - 1.0) / Math.LN10; win_elo -= (move['white_avg_elo'] - move['black_avg_elo']); white_win_ratio = 1.0 / (1.0 + Math.pow(10, win_elo / -400.0)); - win_ratio = (game.turn() == 'w') ? white_win_ratio : 1.0 - white_win_ratio; + win_ratio = (i % 2 == 0) ? white_win_ratio : 1.0 - white_win_ratio; line.push(win_ratio); } else { line.push(null); @@ -259,13 +255,23 @@ var set_includetransp = function(value) { window['set_includetransp'] = set_includetransp; var make_move = function(move) { - if (move_override < history.length && history[move_override] == move) { + var history = game.history({ verbose: true }); + if (move_override < history.length && history[move_override].san == move) { // User effectively only moved forward in history. ++move_override; } else { - history.length = move_override; - history.push(move); - move_override = history.length; + var moves = game.history(); + // Truncate the history if needed. + if (move_override < moves.length) { + game = new Chess(); + for (var i = 0; i < move_override; ++i) { + game.move(moves[i]); + } + fens.length = move_override; + } + game.move(move); + fens.push(game.fen()); + ++move_override; } update(); } @@ -280,7 +286,7 @@ var prev_move = function() { window['prev_move'] = prev_move; var next_move = function() { - if (move_override < history.length) { + if (move_override < game.history().length) { ++move_override; update(); } @@ -295,18 +301,18 @@ window['set_move'] = set_move; // almost all of this stuff comes from the chessboard.js example page var onDragStart = function(source, piece, position, orientation) { - var game = get_game(); - if (game.game_over() === true || - (game.turn() === 'w' && piece.search(/^b/) !== -1) || - (game.turn() === 'b' && piece.search(/^w/) !== -1)) { + var pseudogame = new Chess(current_display_fen()); + if (pseudogame.game_over() === true || + (pseudogame.turn() === 'w' && piece.search(/^b/) !== -1) || + (pseudogame.turn() === 'b' && piece.search(/^w/) !== -1)) { return false; } } var onDrop = function(source, target) { // see if the move is legal - var game = get_game(); - var move = game.move({ + var pseudogame = new Chess(current_display_fen()); + var move = pseudogame.move({ from: source, to: target, promotion: 'q' // NOTE: always promote to a queen for example simplicity @@ -314,22 +320,18 @@ var onDrop = function(source, target) { // illegal move if (move === null) return 'snapback'; +} - var new_history = game.history({ verbose: true }); - history = []; - for (var i = 0; i < new_history.length; ++i) { - history.push(new_history[i].san); - } - move_override = history.length; -}; +var onSnapEnd = function(source, target) { + var pseudogame = new Chess(current_display_fen()); + var move = pseudogame.move({ + from: source, + to: target, + promotion: 'q' // NOTE: always promote to a queen for example simplicity + }); -// update the board position after the piece snap -// for castling, en passant, pawn promotion -var onSnapEnd = function() { - var game = get_game(); - board.position(game.fen()); - update(); -}; + make_move(pseudogame.history({ verbose: true }).pop().san); +} var init = function() { // Create board. -- 2.39.2