Use Sunsetter for local crazyhouse analysis
parent
aabd656191
commit
1732078da7
|
@ -31,3 +31,6 @@
|
||||||
[submodule "public/vendor/stockfish.js"]
|
[submodule "public/vendor/stockfish.js"]
|
||||||
path = public/vendor/stockfish.js
|
path = public/vendor/stockfish.js
|
||||||
url = https://github.com/niklasf/stockfish.js
|
url = https://github.com/niklasf/stockfish.js
|
||||||
|
[submodule "public/vendor/Sunsetter"]
|
||||||
|
path = public/vendor/Sunsetter
|
||||||
|
url = https://github.com/niklasf/Sunsetter.git
|
||||||
|
|
|
@ -0,0 +1 @@
|
||||||
|
Subproject commit 3d0122e11268a11edb9c95916f8a3fc062b8ce5c
|
|
@ -1,6 +1,8 @@
|
||||||
var m = require('mithril');
|
var m = require('mithril');
|
||||||
var makePool = require('./cevalPool');
|
var makePool = require('./cevalPool');
|
||||||
var dict = require('./cevalDict');
|
var dict = require('./cevalDict');
|
||||||
|
var stockfishWorker = require('./stockfishWorker');
|
||||||
|
var sunsetterWorker = require('./sunsetterWorker');
|
||||||
|
|
||||||
module.exports = function(possible, variant, emit) {
|
module.exports = function(possible, variant, emit) {
|
||||||
|
|
||||||
|
@ -12,12 +14,12 @@ module.exports = function(possible, variant, emit) {
|
||||||
var allowed = m.prop(true);
|
var allowed = m.prop(true);
|
||||||
var enabled = m.prop(possible() && allowed() && lichess.storage.get(storageKey) === '1');
|
var enabled = m.prop(possible() && allowed() && lichess.storage.get(storageKey) === '1');
|
||||||
var started = false;
|
var started = false;
|
||||||
|
var engine = variant.key !== 'crazyhouse' ? stockfishWorker : sunsetterWorker;
|
||||||
var pool = makePool({
|
var pool = makePool({
|
||||||
path: '/assets/vendor/stockfish.js/stockfish.js', // Can't CDN because same-origin policy
|
|
||||||
minDepth: minDepth,
|
minDepth: minDepth,
|
||||||
maxDepth: maxDepth,
|
maxDepth: maxDepth,
|
||||||
variant: variant
|
variant: variant
|
||||||
}, nbWorkers);
|
}, engine, nbWorkers);
|
||||||
|
|
||||||
var onEmit = function(res) {
|
var onEmit = function(res) {
|
||||||
curDepth = res.eval.depth;
|
curDepth = res.eval.depth;
|
||||||
|
|
|
@ -1,7 +1,6 @@
|
||||||
var m = require('mithril');
|
var m = require('mithril');
|
||||||
var makeWorker = require('./cevalWorker');
|
|
||||||
|
|
||||||
module.exports = function(opts, nb) {
|
module.exports = function(opts, makeWorker, nb) {
|
||||||
|
|
||||||
var workers = [];
|
var workers = [];
|
||||||
var token = -1;
|
var token = -1;
|
||||||
|
|
|
@ -56,7 +56,7 @@ module.exports = function(opts, name) {
|
||||||
|
|
||||||
var reboot = function() {
|
var reboot = function() {
|
||||||
if (instance) instance.terminate();
|
if (instance) instance.terminate();
|
||||||
instance = new Worker(opts.path);
|
instance = new Worker('/assets/vendor/stockfish.js/stockfish.js');
|
||||||
busy = false;
|
busy = false;
|
||||||
stopping = false;
|
stopping = false;
|
||||||
var uciVariant = variantMap[opts.variant.key];
|
var uciVariant = variantMap[opts.variant.key];
|
|
@ -0,0 +1,125 @@
|
||||||
|
var m = require('mithril');
|
||||||
|
|
||||||
|
module.exports = function(opts, name) {
|
||||||
|
|
||||||
|
var instance = null;
|
||||||
|
var busy = false;
|
||||||
|
var stopping = false;
|
||||||
|
|
||||||
|
// Sunsetter always plays only moves right away. Count the number of played
|
||||||
|
// moves to show the correct mate in #n.
|
||||||
|
var onlyMoves = 0;
|
||||||
|
var best;
|
||||||
|
|
||||||
|
var send = function(text) {
|
||||||
|
instance.postMessage(text);
|
||||||
|
};
|
||||||
|
|
||||||
|
var processOutput = function(text, work) {
|
||||||
|
if (text === 'tellics stopped') {
|
||||||
|
busy = false;
|
||||||
|
stopping = false;
|
||||||
|
onlyMoves = 0;
|
||||||
|
best = undefined;
|
||||||
|
return;
|
||||||
|
}
|
||||||
|
if (stopping) return;
|
||||||
|
|
||||||
|
if (text.indexOf('move ') == 0) {
|
||||||
|
onlyMoves++;
|
||||||
|
best = text.split(' ')[1];
|
||||||
|
send('analyze');
|
||||||
|
return;
|
||||||
|
}
|
||||||
|
|
||||||
|
var depth, cp, mate;
|
||||||
|
|
||||||
|
var matches = text.match(/(\d+)\s+([-+]?\d+)\s+(\d+)\s+(\d+)\s+([a-h1-8=@PNBRQK]+).*/);
|
||||||
|
if (matches) {
|
||||||
|
depth = parseInt(matches[1], 10);
|
||||||
|
cp = parseInt(matches[2], 10);
|
||||||
|
if (!onlyMoves) best = matches[5];
|
||||||
|
} else {
|
||||||
|
matches = text.match(/Found move:\s+([a-h1-8=@PNBRQK]+)\s+([-+]?\d+)\s.*/);
|
||||||
|
if (matches) {
|
||||||
|
depth = opts.maxDepth;
|
||||||
|
cp = parseInt(matches[2], 10);
|
||||||
|
if (!onlyMoves) best = matches[1];
|
||||||
|
stopping = true;
|
||||||
|
send('force');
|
||||||
|
send('tellics stopped');
|
||||||
|
} else {
|
||||||
|
return;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
if (!onlyMoves && depth < opts.minDepth) return;
|
||||||
|
|
||||||
|
if ((work.ply + onlyMoves) % 2 == 1) {
|
||||||
|
if (cp) cp = -cp;
|
||||||
|
if (mate) mate = -mate;
|
||||||
|
}
|
||||||
|
|
||||||
|
// transform mate scores
|
||||||
|
if (cp > 20000) {
|
||||||
|
mate = Math.floor((30000 - cp) / 10);
|
||||||
|
cp = undefined;
|
||||||
|
} else if (cp < -20000) {
|
||||||
|
mate = Math.floor((-30000 - cp) / 10);
|
||||||
|
cp = undefined;
|
||||||
|
}
|
||||||
|
|
||||||
|
if (mate) {
|
||||||
|
if (mate > 0) mate += onlyMoves;
|
||||||
|
else mate -= onlyMoves;
|
||||||
|
}
|
||||||
|
|
||||||
|
work.emit({
|
||||||
|
work: work,
|
||||||
|
eval: {
|
||||||
|
depth: depth,
|
||||||
|
cp: cp,
|
||||||
|
mate: mate,
|
||||||
|
best: best
|
||||||
|
},
|
||||||
|
name: name
|
||||||
|
});
|
||||||
|
};
|
||||||
|
|
||||||
|
var reboot = function() {
|
||||||
|
if (instance) instance.terminate();
|
||||||
|
instance = new Worker('/assets/vendor/Sunsetter/sunsetter.js');
|
||||||
|
busy = false;
|
||||||
|
stopping = false;
|
||||||
|
onlyMoves = 0;
|
||||||
|
send('xboard');
|
||||||
|
};
|
||||||
|
|
||||||
|
reboot();
|
||||||
|
|
||||||
|
return {
|
||||||
|
start: function(work) {
|
||||||
|
if (busy) reboot();
|
||||||
|
busy = true;
|
||||||
|
send('variant ' + opts.variant.key);
|
||||||
|
send('setboard ' + work.position);
|
||||||
|
send('force');
|
||||||
|
for (var i = 0; i < work.moves.length; i++) {
|
||||||
|
send(work.moves[i]);
|
||||||
|
}
|
||||||
|
send('analyze');
|
||||||
|
send('go');
|
||||||
|
instance.onmessage = function(msg) {
|
||||||
|
processOutput(msg.data, work);
|
||||||
|
};
|
||||||
|
},
|
||||||
|
stop: function() {
|
||||||
|
if (!busy) return;
|
||||||
|
stopping = true;
|
||||||
|
onlyMoves = 0;
|
||||||
|
best = undefined;
|
||||||
|
send('exit');
|
||||||
|
send('tellics stopped');
|
||||||
|
}
|
||||||
|
};
|
||||||
|
};
|
|
@ -387,7 +387,7 @@ module.exports = function(opts) {
|
||||||
});
|
});
|
||||||
}.bind(this);
|
}.bind(this);
|
||||||
|
|
||||||
var cevalVariants = ['standard', 'fromPosition', 'chess960', 'kingOfTheHill', 'threeCheck', 'horde', 'racingKings', 'atomic'];
|
var cevalVariants = ['standard', 'fromPosition', 'chess960', 'kingOfTheHill', 'threeCheck', 'horde', 'racingKings', 'atomic', 'crazyhouse'];
|
||||||
var cevalPossible = function() {
|
var cevalPossible = function() {
|
||||||
return (util.synthetic(this.data) || !game.playable(this.data)) &&
|
return (util.synthetic(this.data) || !game.playable(this.data)) &&
|
||||||
cevalVariants.indexOf(this.data.game.variant.key) !== -1;
|
cevalVariants.indexOf(this.data.game.variant.key) !== -1;
|
||||||
|
|
Loading…
Reference in New Issue