Use Sunsetter for local crazyhouse analysis

pull/2184/head
Niklas Fiekas 2016-08-16 15:49:29 +02:00
parent aabd656191
commit 1732078da7
7 changed files with 136 additions and 6 deletions

3
.gitmodules vendored
View File

@ -31,3 +31,6 @@
[submodule "public/vendor/stockfish.js"]
path = public/vendor/stockfish.js
url = https://github.com/niklasf/stockfish.js
[submodule "public/vendor/Sunsetter"]
path = public/vendor/Sunsetter
url = https://github.com/niklasf/Sunsetter.git

1
public/vendor/Sunsetter vendored 160000

@ -0,0 +1 @@
Subproject commit 3d0122e11268a11edb9c95916f8a3fc062b8ce5c

View File

@ -1,6 +1,8 @@
var m = require('mithril');
var makePool = require('./cevalPool');
var dict = require('./cevalDict');
var stockfishWorker = require('./stockfishWorker');
var sunsetterWorker = require('./sunsetterWorker');
module.exports = function(possible, variant, emit) {
@ -12,12 +14,12 @@ module.exports = function(possible, variant, emit) {
var allowed = m.prop(true);
var enabled = m.prop(possible() && allowed() && lichess.storage.get(storageKey) === '1');
var started = false;
var engine = variant.key !== 'crazyhouse' ? stockfishWorker : sunsetterWorker;
var pool = makePool({
path: '/assets/vendor/stockfish.js/stockfish.js', // Can't CDN because same-origin policy
minDepth: minDepth,
maxDepth: maxDepth,
variant: variant
}, nbWorkers);
}, engine, nbWorkers);
var onEmit = function(res) {
curDepth = res.eval.depth;

View File

@ -1,7 +1,6 @@
var m = require('mithril');
var makeWorker = require('./cevalWorker');
module.exports = function(opts, nb) {
module.exports = function(opts, makeWorker, nb) {
var workers = [];
var token = -1;

View File

@ -56,7 +56,7 @@ module.exports = function(opts, name) {
var reboot = function() {
if (instance) instance.terminate();
instance = new Worker(opts.path);
instance = new Worker('/assets/vendor/stockfish.js/stockfish.js');
busy = false;
stopping = false;
var uciVariant = variantMap[opts.variant.key];

View File

@ -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');
}
};
};

View File

@ -387,7 +387,7 @@ module.exports = function(opts) {
});
}.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() {
return (util.synthetic(this.data) || !game.playable(this.data)) &&
cevalVariants.indexOf(this.data.game.variant.key) !== -1;