From: Benjamin Auder Date: Tue, 18 Dec 2018 18:08:14 +0000 (+0100) Subject: Play computer move in webworker to not freeze interface X-Git-Url: https://git.auder.net/%7B%7B%20asset%28%27mixstore/images/common.css?a=commitdiff_plain;h=643479f8d7c3622b57fc49c4f10d9950793ebf4f;p=vchess.git Play computer move in webworker to not freeze interface --- diff --git a/TODO b/TODO deleted file mode 100644 index 4b311b04..00000000 --- a/TODO +++ /dev/null @@ -1,2 +0,0 @@ -global lang cookie, + display (remember in each variant what is shown...) -translations (how ? switch on index page only, then find ideas...) diff --git a/db/create.sql b/db/create.sql index 36bda8aa..033df4be 100644 --- a/db/create.sql +++ b/db/create.sql @@ -21,6 +21,7 @@ insert into Variants values ('Ultima', 'Exotic captures'); create table Problems ( + num integer primary key, added datetime, variant varchar, fen varchar, diff --git a/public/javascripts/components/game.js b/public/javascripts/components/game.js index 186c027c..b242ee27 100644 --- a/public/javascripts/components/game.js +++ b/public/javascripts/components/game.js @@ -22,6 +22,9 @@ Vue.component('my-game', { color: getCookie("color", "lichess"), //lichess, chesscom or chesstempo // sound level: 0 = no sound, 1 = sound only on newgame, 2 = always sound: parseInt(getCookie("sound", "2")), + // Web worker to play computer moves without freezing interface: + compWorker: new Worker('/javascripts/playCompMove.js'), + timeStart: undefined, //time when computer starts thinking }; }, watch: { @@ -146,7 +149,7 @@ Vue.component('my-game', { 'class': { "tooltip": true, "topindicator": true, - "indic-right": true, + "indic-left": true, "settings-btn": !smallScreen, "settings-btn-small": smallScreen, }, @@ -965,6 +968,19 @@ Vue.component('my-game', { this.play(); } }; + // Computer moves web worker logic: + this.compWorker.postMessage(["scripts",variant]); + const self = this; + this.compWorker.onmessage = function(e) { + const compMove = e.data; + // (first move) HACK: small delay to avoid selecting elements + // before they appear on page: + const delay = Math.max(500-(Date.now()-self.timeStart), 0); + setTimeout(() => { + if (self.mode == "computer") //Warning: mode could have changed! + self.play(compMove, "animate") + }, delay); + } }, methods: { toggleShowSolution: function() { @@ -1161,23 +1177,16 @@ Vue.component('my-game', { } else if (mode == "computer") { + this.compWorker.postMessage(["init",this.vr.getFen()]); this.mycolor = Math.random() < 0.5 ? 'w' : 'b'; if (this.mycolor == 'b') - setTimeout(this.playComputerMove, 100); //small delay for drawing board + this.playComputerMove(); } //else: against a (IRL) friend or problem solving: nothing more to do }, playComputerMove: function() { - const timeStart = Date.now(); - // TODO: next call asynchronous (avoid freezing interface while computer "think"). - // This would also allow to remove some artificial setTimeouts - const compMove = this.vr.getComputerMove(); - // (first move) HACK: avoid selecting elements before they appear on page: - const delay = Math.max(250-(Date.now()-timeStart), 0); - setTimeout(() => { - if (this.mode == "computer") //Warning: mode could have changed! - this.play(compMove, "animate") - }, delay); + this.timeStart = Date.now(); + this.compWorker.postMessage(["askmove"]); }, // Get the identifier of a HTML table cell from its numeric coordinates o.x,o.y. getSquareId: function(o) { @@ -1339,6 +1348,11 @@ Vue.component('my-game', { { this.incheck = this.vr.getCheckSquares(move); //is opponent in check? this.vr.play(move, "ingame"); + if (this.mode == "computer") + { + // Send the move to web worker + this.compWorker.postMessage(["newmove",move]); + } } else { @@ -1363,7 +1377,7 @@ Vue.component('my-game', { } } if (this.mode == "computer" && this.vr.turn != this.mycolor) - setTimeout(this.playComputerMove, 250); //small delay for animation + this.playComputerMove(); }, undo: function() { // Navigate after game is over diff --git a/public/javascripts/playCompMove.js b/public/javascripts/playCompMove.js new file mode 100644 index 00000000..fc69ce24 --- /dev/null +++ b/public/javascripts/playCompMove.js @@ -0,0 +1,26 @@ +// For asynchronous computer move search +onmessage = function(e) +{ + switch (e.data[0]) + { + case "scripts": + self.importScripts( + '//cdnjs.cloudflare.com/ajax/libs/underscore.js/1.9.1/underscore-min.js', + '/javascripts/base_rules.js', + '/javascripts/utils/array.js', + '/javascripts/variants/' + e.data[1] + '.js'); + self.V = VariantRules; + break; + case "init": + const fen = e.data[1]; + self.vr = new VariantRules(fen, []); + break; + case "newmove": + self.vr.play(e.data[1]); + break; + case "askmove": + const compMove = self.vr.getComputerMove(); + postMessage(compMove); + break; + } +} diff --git a/public/javascripts/variant.js b/public/javascripts/variant.js index 3aa2f686..e9e956ca 100644 --- a/public/javascripts/variant.js +++ b/public/javascripts/variant.js @@ -1,15 +1,21 @@ new Vue({ el: "#variantPage", data: { - display: "", //do not show anything... + display: getCookie("display-"+variant,""), //default: do not show anything... problem: undefined, //current problem in view }, methods: { toggleDisplay: function(elt) { if (this.display == elt) + { this.display = ""; //hide + setCookie("display-"+variant, ""); + } else + { this.display = elt; //show + setCookie("display-"+variant, elt); + } }, showProblem: function(problemTxt) { this.problem = JSON.parse(problemTxt); diff --git a/public/javascripts/variants/Alice.js b/public/javascripts/variants/Alice.js index 00103a7b..f7d2fa13 100644 --- a/public/javascripts/variants/Alice.js +++ b/public/javascripts/variants/Alice.js @@ -336,3 +336,5 @@ class AliceRules extends ChessRules return notation; } } + +const VariantRules = AliceRules; diff --git a/public/javascripts/variants/Antiking.js b/public/javascripts/variants/Antiking.js index 38cadf22..0d342713 100644 --- a/public/javascripts/variants/Antiking.js +++ b/public/javascripts/variants/Antiking.js @@ -204,3 +204,5 @@ class AntikingRules extends ChessRules " w 1111"; } } + +const VariantRules = AntikingRules; diff --git a/public/javascripts/variants/Atomic.js b/public/javascripts/variants/Atomic.js index e2f8ea33..0275805f 100644 --- a/public/javascripts/variants/Atomic.js +++ b/public/javascripts/variants/Atomic.js @@ -147,3 +147,5 @@ class AtomicRules extends ChessRules return color == "w" ? "0-1" : "1-0"; //checkmate } } + +const VariantRules = AtomicRules; diff --git a/public/javascripts/variants/Checkered.js b/public/javascripts/variants/Checkered.js index 314cd8e4..d73cef41 100644 --- a/public/javascripts/variants/Checkered.js +++ b/public/javascripts/variants/Checkered.js @@ -303,3 +303,5 @@ class CheckeredRules extends ChessRules } } } + +const VariantRules = CheckeredRules; diff --git a/public/javascripts/variants/Chess960.js b/public/javascripts/variants/Chess960.js index 1c8292ce..529ad997 100644 --- a/public/javascripts/variants/Chess960.js +++ b/public/javascripts/variants/Chess960.js @@ -2,3 +2,5 @@ class Chess960Rules extends ChessRules { // Standard rules } + +const VariantRules = Chess960Rules; diff --git a/public/javascripts/variants/Crazyhouse.js b/public/javascripts/variants/Crazyhouse.js index 00452cbd..afebcc35 100644 --- a/public/javascripts/variants/Crazyhouse.js +++ b/public/javascripts/variants/Crazyhouse.js @@ -266,3 +266,5 @@ class CrazyhouseRules extends ChessRules return "@" + V.CoordsToSquare(move.end); } } + +const VariantRules = CrazyhouseRules; diff --git a/public/javascripts/variants/Extinction.js b/public/javascripts/variants/Extinction.js index 49d61b2d..bc061629 100644 --- a/public/javascripts/variants/Extinction.js +++ b/public/javascripts/variants/Extinction.js @@ -135,3 +135,5 @@ class ExtinctionRules extends ChessRules return super.evalPosition(); } } + +const VariantRules = ExtinctionRules; diff --git a/public/javascripts/variants/Grand.js b/public/javascripts/variants/Grand.js index b598f2d2..ec2afd81 100644 --- a/public/javascripts/variants/Grand.js +++ b/public/javascripts/variants/Grand.js @@ -358,3 +358,5 @@ class GrandRules extends ChessRules " w 1111 -"; } } + +const VariantRules = GrandRules; diff --git a/public/javascripts/variants/Loser.js b/public/javascripts/variants/Loser.js index 5f156129..6731d322 100644 --- a/public/javascripts/variants/Loser.js +++ b/public/javascripts/variants/Loser.js @@ -193,3 +193,5 @@ class LoserRules extends ChessRules " w -"; //no en-passant } } + +const VariantRules = LoserRules; diff --git a/public/javascripts/variants/Magnetic.js b/public/javascripts/variants/Magnetic.js index 225489ec..17efeaa9 100644 --- a/public/javascripts/variants/Magnetic.js +++ b/public/javascripts/variants/Magnetic.js @@ -281,3 +281,5 @@ class MagneticRules extends ChessRules return 500; //checkmates evals may be slightly below 1000 } } + +const VariantRules = MagneticRules; diff --git a/public/javascripts/variants/Switching.js b/public/javascripts/variants/Switching.js index ee84e4ca..e53ab692 100644 --- a/public/javascripts/variants/Switching.js +++ b/public/javascripts/variants/Switching.js @@ -137,3 +137,5 @@ class SwitchingRules extends ChessRules return "S" + startSquare + finalSquare; } } + +const VariantRules = SwitchingRules; diff --git a/public/javascripts/variants/Ultima.js b/public/javascripts/variants/Ultima.js index 7f4a7ebe..04d62b7d 100644 --- a/public/javascripts/variants/Ultima.js +++ b/public/javascripts/variants/Ultima.js @@ -1,8 +1,8 @@ class UltimaRules extends ChessRules { - static get HasFlags { return false; } + static get HasFlags() { return false; } - static get HasEnpassant { return false; } + static get HasEnpassant() { return false; } static getPpath(b) { @@ -626,3 +626,5 @@ class UltimaRules extends ChessRules return notation; } } + +const VariantRules = UltimaRules; diff --git a/public/javascripts/variants/Wildebeest.js b/public/javascripts/variants/Wildebeest.js index 4194521e..783eb440 100644 --- a/public/javascripts/variants/Wildebeest.js +++ b/public/javascripts/variants/Wildebeest.js @@ -281,3 +281,5 @@ class WildebeestRules extends ChessRules " w 1111 -"; } } + +const VariantRules = WildebeestRules; diff --git a/public/javascripts/variants/Zen.js b/public/javascripts/variants/Zen.js index da4dd7af..b090a292 100644 --- a/public/javascripts/variants/Zen.js +++ b/public/javascripts/variants/Zen.js @@ -226,3 +226,5 @@ class ZenRules extends ChessRules } } } + +const VariantRules = ZenRules; diff --git a/public/stylesheets/variant.sass b/public/stylesheets/variant.sass index 856f22b6..a0d4f2a2 100644 --- a/public/stylesheets/variant.sass +++ b/public/stylesheets/variant.sass @@ -280,3 +280,6 @@ ul:not(.browser-default) > li #solution-div h3 cursor: pointer + +.newproblem-form, .newproblem-preview + max-width: 90% diff --git a/views/rules/Ultima.pug b/views/rules/Ultima.pug index cf5da24f..8255a5e9 100644 --- a/views/rules/Ultima.pug +++ b/views/rules/Ultima.pug @@ -103,7 +103,7 @@ p. figure.diagram-container .diagram - | fen:2n4k/3r4/5b2/3p4/1m6/3b4/3N4/K7 w d4,d6,d8,a5: + | fen:2n4k/3r4/5b2/3p4/1m6/3b4/3N4/K7 d4,d6,d8,a5: figcaption All marked squares captures are playable from d2. h4 Withdrawer (queen) @@ -114,7 +114,7 @@ p. figure.diagram-container .diagram - | fen:7k/8/8/3Qr3/8/8/8/K7 w a5,b5,c5: + | fen:7k/8/8/3Qr3/8/8/8/K7 a5,b5,c5: figcaption 1.Qa5, 1.Qb5 or 1.Qc5 captures the black rook. h4 Chameleon (bishop) @@ -129,7 +129,7 @@ p ...and these captures can be combined. figure.diagram-container .diagram - | fen:7k/8/8/r3pP2/2n5/8/B7/K7 w a5,c4,e5: + | fen:7k/8/8/r3pP2/2n5/8/B7/K7 a5,c4,e5: figcaption 1.Bd5 captures all marked pieces. p. @@ -150,7 +150,7 @@ p. figure.diagram-container .diagram - | fen:7k/8/8/p4r/4K3/8/8/8 w e5: + | fen:7k/8/8/p4r/4K3/8/8/8 e5: figcaption 1.Ke5 is impossible h3 Credits diff --git a/views/variant.pug b/views/variant.pug index b1caabdb..d3581ae3 100644 --- a/views/variant.pug +++ b/views/variant.pug @@ -32,7 +32,6 @@ block javascripts script(src="/javascripts/base_rules.js") script(src="/javascripts/variants/" + variant + ".js") script. - const VariantRules = #{variant}Rules; const V = VariantRules; //because this variable is often used const variant = "#{variant}"; const problemArray = !{JSON.stringify(problemArray)};