UNPKG

stockfish

Version:

The Stockfish chess engine in Web Assembly (WASM)

427 lines (391 loc) 15.6 kB
return Stockfish; } if (typeof self !== "undefined" && self.location.hash.split(",")[1] === "worker" || typeof global !== "undefined" && Object.prototype.toString.call(global.process) === "[object process]" && !require("worker_threads").isMainThread) { (function() { /// Insert worker here })(); /// Is it a web worker? } else if (typeof onmessage !== "undefined" && (typeof window === "undefined" || typeof window.document === "undefined") || typeof global !== "undefined" && Object.prototype.toString.call(global.process) === "[object process]") { (function () { var isNode = typeof global !== "undefined" && Object.prototype.toString.call(global.process) === "[object process]"; var mod; var myEngine; var queue = []; var args; var wasmPath; function completer(line) { var completions = [ "compiler", "d", "eval", "exit", "flip", "go ", "isready ", "ponderhit ", "position fen ", "position startpos", "position startpos moves", "quit", "setoption name Clear Hash value true", "setoption name Contempt value ", "setoption name Hash value ", "setoption name Minimum Thinking Time value ", "setoption name Move Overhead value ", "setoption name MultiPV value ", "setoption name Ponder value ", //"setoption name Skill Level Maximum Error value ", //"setoption name Skill Level Probability value ", "setoption name Skill Level value ", "setoption name Slow Mover value ", "setoption name Threads value ", "setoption name UCI_Chess960 value false", "setoption name UCI_Chess960 value true", "setoption name UCI_AnalyseMode value true", "setoption name UCI_AnalyseMode value false", "setoption name UCI_LimitStrength value true", "setoption name UCI_LimitStrength value false", "setoption name UCI_Elo value ", "setoption name UCI_ShowWDL value true", "setoption name UCI_ShowWDL value false", "setoption name Use NNUE value true", "setoption name Use NNUE value false", "setoption name nodestime value ", "setoption name EvalFile value ", "stop", "uci", "ucinewgame" ]; var completionsMid = [ "binc ", "btime ", "confidence ", "depth ", "infinite ", "mate ", "maxdepth ", "maxtime ", "mindepth ", "mintime ", "moves ", /// for position fen ... moves "movestogo ", "movetime ", "ponder ", "searchmoves ", "shallow ", "winc ", "wtime " ]; function filter(c) { return c.indexOf(line) === 0; } /// This looks for completions starting at the very beginning of the line. /// If the user has typed nothing, it will match everything. var hits = completions.filter(filter); if (!hits.length) { /// Just get the last word. line = line.replace(/^.*\s/, ""); if (line) { /// Find completion mid line too. hits = completionsMid.filter(filter); } else { /// If no word has been typed, show all options. hits = completionsMid; } } return [hits, line]; } if (isNode) { ///NOTE: Node.js v14+ needs --experimental-wasm-threads --experimental-wasm-simd /// Was it called directly? if (require.main === module) { wasmPath = require("path").join(__dirname, "stockfish.wasm"); mod = { locateFile: function (path) { if (path.indexOf(".wasm") > -1) { /// Set the path to the wasm binary. return wasmPath; } else { /// Set path to worker (self + the worker hash) return __filename; } }, }; Stockfish = INIT_ENGINE(); Stockfish(mod).then(function (sf) { myEngine = sf; sf.addMessageListener(function (line) { console.log(line); }); if (queue.length) { queue.forEach(function (line) { sf.postMessage(line, true); }); } queue = null; }); require("readline").createInterface({ input: process.stdin, output: process.stdout, completer: completer, historySize: 100, }).on("line", function online(line) { if (line) { if (line === "quit" || line === "exit") { process.exit(); } if (myEngine) { myEngine.postMessage(line, true); } else { queue.push(line); } } }).on("close", function onend() { process.exit(); }).setPrompt(""); /// Is this a node module? } else { module.exports = INIT_ENGINE; } } else { var postMessageToEngine = function (data) { if (myEngine.__IS_NON_NESTED__ || myEngine.__IS_SINGLE_THREADED__) { myEngine.onCustomMessage(data); } else { myEngine.postMessage(data, true); } }; args = self.location.hash.substr(1).split(","); wasmPath = decodeURIComponent(args[0] || "stockfish.wasm"); mod = { locateFile: function (path) { if (path.indexOf(".wasm") > -1) { /// Set the path to the wasm binary. return wasmPath; } else { /// Set path to worker (self + the worker hash) return self.location.origin + self.location.pathname + "#" + wasmPath + ",worker"; } } }; Stockfish = INIT_ENGINE(); Stockfish(mod).then(function onCreate(sf) { myEngine = sf; sf.addMessageListener(function onMessage(line) { postMessage(line); }); if (queue.length) { queue.forEach(function (line) { postMessageToEngine(line); }); } queue = null; }).catch(function (e) { /// Sadly, Web Workers will not trigger the error event when errors occur in promises, so we need to create a new context and throw an error there. setTimeout(function throwError() { throw e; }, 1); }); /// Make sure that this is only added once. if (!onmessage) { onmessage = function (event) { if (myEngine) { postMessageToEngine(event.data); } else { queue.push(event.data); } }; } } }()); } else { ///NOTE: If it's a normal browser, the client can use the engine without polluting the global scope. if (typeof document === "object" && document.currentScript) { document.currentScript._exports = INIT_ENGINE(); } else { Stockfish = INIT_ENGINE(); } } (function (global, undefined) { "use strict"; if (global.setImmediate) { quickTimeout = setImmediate; return; } var nextHandle = 1; // Spec says greater than zero var tasksByHandle = {}; var currentlyRunningATask = false; var doc = global.document; var registerImmediate; function setImmediate(callback) { // Callback can either be a function or a string if (typeof callback !== "function") { callback = new Function("" + callback); } // Copy function arguments var args = new Array(arguments.length - 1); for (var i = 0; i < args.length; i++) { args[i] = arguments[i + 1]; } // Store and register the task var task = { callback: callback, args: args }; tasksByHandle[nextHandle] = task; registerImmediate(nextHandle); return nextHandle++; } function clearImmediate(handle) { delete tasksByHandle[handle]; } function run(task) { var callback = task.callback; var args = task.args; switch (args.length) { case 0: callback(); break; case 1: callback(args[0]); break; case 2: callback(args[0], args[1]); break; case 3: callback(args[0], args[1], args[2]); break; default: callback.apply(undefined, args); break; } } function runIfPresent(handle) { // From the spec: "Wait until any invocations of this algorithm started before this one have completed." // So if we're currently running a task, we'll need to delay this invocation. if (currentlyRunningATask) { // Delay by doing a setTimeout. setImmediate was tried instead, but in Firefox 7 it generated a // "too much recursion" error. setTimeout(runIfPresent, 0, handle); } else { var task = tasksByHandle[handle]; if (task) { currentlyRunningATask = true; try { run(task); } finally { clearImmediate(handle); currentlyRunningATask = false; } } } } function installNextTickImplementation() { registerImmediate = function(handle) { process.nextTick(function () { runIfPresent(handle); }); }; } function canUsePostMessage() { // The test against `importScripts` prevents this implementation from being installed inside a web worker, // where `global.postMessage` means something completely different and can't be used for this purpose. if (global.postMessage && !global.importScripts) { var postMessageIsAsynchronous = true; var oldOnMessage = global.onmessage; global.onmessage = function() { postMessageIsAsynchronous = false; }; global.postMessage("", "*"); global.onmessage = oldOnMessage; return postMessageIsAsynchronous; } } function installPostMessageImplementation() { // Installs an event handler on `global` for the `message` event: see // * https://developer.mozilla.org/en/DOM/window.postMessage // * http://www.whatwg.org/specs/web-apps/current-work/multipage/comms.html#crossDocumentMessages var messagePrefix = "setImmediate$" + Math.random() + "$"; var onGlobalMessage = function(event) { if (event.source === global && typeof event.data === "string" && event.data.indexOf(messagePrefix) === 0) { runIfPresent(+event.data.slice(messagePrefix.length)); } }; if (global.addEventListener) { global.addEventListener("message", onGlobalMessage, false); } else { global.attachEvent("onmessage", onGlobalMessage); } registerImmediate = function(handle) { global.postMessage(messagePrefix + handle, "*"); }; } function installMessageChannelImplementation() { var channel = new MessageChannel(); channel.port1.onmessage = function(event) { var handle = event.data; runIfPresent(handle); }; registerImmediate = function(handle) { channel.port2.postMessage(handle); }; } function installReadyStateChangeImplementation() { var html = doc.documentElement; registerImmediate = function(handle) { // Create a <script> element; its readystatechange event will be fired asynchronously once it is inserted // into the document. Do so, thus queuing up the task. Remember to clean up once it's been called. var script = doc.createElement("script"); script.onreadystatechange = function () { runIfPresent(handle); script.onreadystatechange = null; html.removeChild(script); script = null; }; html.appendChild(script); }; } function installSetTimeoutImplementation() { registerImmediate = function(handle) { setTimeout(runIfPresent, 0, handle); }; } // If supported, we should attach to the prototype of global, since that is where setTimeout et al. live. //var attachTo = Object.getPrototypeOf && Object.getPrototypeOf(global); //attachTo = attachTo && attachTo.setTimeout ? attachTo : global; // Don't get fooled by e.g. browserify environments. if ({}.toString.call(global.process) === "[object process]") { // For Node.js before 0.9 installNextTickImplementation(); } else if (canUsePostMessage()) { // For non-IE10 modern browsers installPostMessageImplementation(); } else if (global.MessageChannel) { // For web workers, where supported installMessageChannelImplementation(); } else if (doc && "onreadystatechange" in doc.createElement("script")) { // For IE 6–8 installReadyStateChangeImplementation(); } else { // For older browsers installSetTimeoutImplementation(); } //attachTo.setImmediate = setImmediate; //attachTo.clearImmediate = clearImmediate; quickTimeout = setImmediate; }(typeof self === "undefined" ? typeof global === "undefined" ? this : global : self)); }());