From 095cf9e49190566feb95a5d3b5400d5d42144b62 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Micha=C3=ABl=20Lemaire?= Date: Fri, 6 Apr 2018 00:27:26 +0200 Subject: [PATCH] Replaced AI duel page with a node.js multi-process simulator --- TODO.md | 3 +- out/ai.html | 110 ----- out/sim.js | 68 +++ package-lock.json | 952 +++++++++++++++++++++++++++++++++++++++++- package.json | 5 +- src/MainUI.ts | 17 + src/core/ai/AIDuel.ts | 144 ------- tsconfig.json | 5 +- 8 files changed, 1041 insertions(+), 263 deletions(-) delete mode 100644 out/ai.html create mode 100644 out/sim.js delete mode 100644 src/core/ai/AIDuel.ts diff --git a/TODO.md b/TODO.md index 81cc7df..4991334 100644 --- a/TODO.md +++ b/TODO.md @@ -72,11 +72,11 @@ Ships models and actions * Add a reflect damage effect * Add untargettable effect (can only be targetted with area effects) * Add damage modifier (to change the options of incoming damage or outgoing damage) -* Add a balance testing page, using AI battles with or without an upgrade, to help in balancing Artificial Intelligence ----------------------- +* Account for overheated engines * If web worker is not responsive, or produces only errors, it should be disabled for the session * Produce interesting "angle" areas * Evaluate active effects @@ -85,7 +85,6 @@ Artificial Intelligence * Use a first batch of producers, and only if no "good" move has been found, go on with some infinite producers * Abandon fight if the AI judges there is no hope of victory * Add combination of random small move and actual maneuver, as producer -* New duel page with producers/evaluators tweaking * Use tree techniques to account for potential future moves * Prototype of evolving AI diff --git a/out/ai.html b/out/ai.html deleted file mode 100644 index 32aad32..0000000 --- a/out/ai.html +++ /dev/null @@ -1,110 +0,0 @@ - - - - - - SpaceTac - AI Duel - - - - - - - - -
-

SpaceTac - AI Duel

- - - - - - - - - - - - - - - - - - - - -
- - versus - -
- -
WinDrawWin
-
- - - - - \ No newline at end of file diff --git a/out/sim.js b/out/sim.js new file mode 100644 index 0000000..fa053da --- /dev/null +++ b/out/sim.js @@ -0,0 +1,68 @@ +const Pool = require('process-pool').default; + +const pool = new Pool({ processLimit: 8 }); +const work = pool.prepare(function () { + const App = require("./build").TK.SpaceTac; + + async function doOneBattle(i) { + let ai1 = new App.TacticalAI(); + let ai2 = new App.TacticalAI(); + + // Prepare battle + let battle = App.Battle.newQuickRandom(true, 1, 2 + i % 4); + battle.fleets.forEach((fleet, findex) => { + fleet.ships.forEach((ship, sindex) => { + ship.name = `F${findex + 1}S${sindex + 1} (${ship.model.name})`; + }); + }); + + // Run battle + while (!battle.ended && battle.cycle < 100) { + let playing = battle.playing_ship; + if (playing) { + let ai = (playing.fleet == battle.fleets[0]) ? ai1 : ai2; + ai.ship = playing; + await ai.play(); + } + } + + // Collect results + if (battle.outcome && battle.outcome.winner) { + let results = {}; + battle.fleets.forEach(fleet => { + fleet.ships.forEach(ship => { + let name = `Level ${ship.level.get()} ${ship.model.name}`; + results[name] = (results[name] || 0) + (ship.fleet === battle.outcome.winner ? 1 : 0); + }); + }); + return results; + } else { + return {}; + } + } + + return (i) => doOneBattle(i); +}); + +let played = {}; +let winned = {}; +let works = Array.from({ length: 1000 }, (v, i) => i).map(i => { + return work(i).then(result => { + Object.keys(result).forEach(model => { + if (result[model]) { + winned[model] = (winned[model] || 0) + 1; + } + played[model] = (played[model] || 0) + 1; + }); + + console.warn("------------------------------------------------"); + console.warn(`--- Results after battle ${i}`); + Object.keys(played).sort().forEach(model => { + let factor = (winned[model] || 0) / played[model]; + console.warn(`${model} ${Math.round(factor * 100)}%`); + }); + console.warn("------------------------------------------------"); + }); +}); + +Promise.all(works).then(() => process.exit(0)); diff --git a/package-lock.json b/package-lock.json index 65e94eb..775a43e 100644 --- a/package-lock.json +++ b/package-lock.json @@ -115,8 +115,7 @@ "amdefine": { "version": "1.0.1", "resolved": "https://registry.npmjs.org/amdefine/-/amdefine-1.0.1.tgz", - "integrity": "sha1-SlKCrBZHKek2Gbz9OtFR+BfOkfU=", - "dev": true + "integrity": "sha1-SlKCrBZHKek2Gbz9OtFR+BfOkfU=" }, "amqplib": { "version": "0.5.2", @@ -1019,6 +1018,7 @@ "requires": { "anymatch": "1.3.2", "async-each": "1.0.1", + "fsevents": "1.1.3", "glob-parent": "2.0.0", "inherits": "2.0.3", "is-binary-path": "1.0.1", @@ -2213,6 +2213,910 @@ "integrity": "sha1-FQStJSMVjKpA20onh8sBQRmU6k8=", "dev": true }, + "fsevents": { + "version": "1.1.3", + "resolved": "https://registry.npmjs.org/fsevents/-/fsevents-1.1.3.tgz", + "integrity": "sha512-WIr7iDkdmdbxu/Gh6eKEZJL6KPE74/5MEsf2whTOFNxbIoIixogroLdKYqB6FDav4Wavh/lZdzzd3b2KxIXC5Q==", + "dev": true, + "optional": true, + "requires": { + "nan": "2.10.0", + "node-pre-gyp": "0.6.39" + }, + "dependencies": { + "abbrev": { + "version": "1.1.0", + "bundled": true, + "dev": true, + "optional": true + }, + "ajv": { + "version": "4.11.8", + "bundled": true, + "dev": true, + "optional": true, + "requires": { + "co": "4.6.0", + "json-stable-stringify": "1.0.1" + } + }, + "ansi-regex": { + "version": "2.1.1", + "bundled": true, + "dev": true + }, + "aproba": { + "version": "1.1.1", + "bundled": true, + "dev": true, + "optional": true + }, + "are-we-there-yet": { + "version": "1.1.4", + "bundled": true, + "dev": true, + "optional": true, + "requires": { + "delegates": "1.0.0", + "readable-stream": "2.2.9" + } + }, + "asn1": { + "version": "0.2.3", + "bundled": true, + "dev": true, + "optional": true + }, + "assert-plus": { + "version": "0.2.0", + "bundled": true, + "dev": true, + "optional": true + }, + "asynckit": { + "version": "0.4.0", + "bundled": true, + "dev": true, + "optional": true + }, + "aws-sign2": { + "version": "0.6.0", + "bundled": true, + "dev": true, + "optional": true + }, + "aws4": { + "version": "1.6.0", + "bundled": true, + "dev": true, + "optional": true + }, + "balanced-match": { + "version": "0.4.2", + "bundled": true, + "dev": true + }, + "bcrypt-pbkdf": { + "version": "1.0.1", + "bundled": true, + "dev": true, + "optional": true, + "requires": { + "tweetnacl": "0.14.5" + } + }, + "block-stream": { + "version": "0.0.9", + "bundled": true, + "dev": true, + "requires": { + "inherits": "2.0.3" + } + }, + "boom": { + "version": "2.10.1", + "bundled": true, + "dev": true, + "requires": { + "hoek": "2.16.3" + } + }, + "brace-expansion": { + "version": "1.1.7", + "bundled": true, + "dev": true, + "requires": { + "balanced-match": "0.4.2", + "concat-map": "0.0.1" + } + }, + "buffer-shims": { + "version": "1.0.0", + "bundled": true, + "dev": true + }, + "caseless": { + "version": "0.12.0", + "bundled": true, + "dev": true, + "optional": true + }, + "co": { + "version": "4.6.0", + "bundled": true, + "dev": true, + "optional": true + }, + "code-point-at": { + "version": "1.1.0", + "bundled": true, + "dev": true + }, + "combined-stream": { + "version": "1.0.5", + "bundled": true, + "dev": true, + "requires": { + "delayed-stream": "1.0.0" + } + }, + "concat-map": { + "version": "0.0.1", + "bundled": true, + "dev": true + }, + "console-control-strings": { + "version": "1.1.0", + "bundled": true, + "dev": true + }, + "core-util-is": { + "version": "1.0.2", + "bundled": true, + "dev": true + }, + "cryptiles": { + "version": "2.0.5", + "bundled": true, + "dev": true, + "requires": { + "boom": "2.10.1" + } + }, + "dashdash": { + "version": "1.14.1", + "bundled": true, + "dev": true, + "optional": true, + "requires": { + "assert-plus": "1.0.0" + }, + "dependencies": { + "assert-plus": { + "version": "1.0.0", + "bundled": true, + "dev": true, + "optional": true + } + } + }, + "debug": { + "version": "2.6.8", + "bundled": true, + "dev": true, + "optional": true, + "requires": { + "ms": "2.0.0" + } + }, + "deep-extend": { + "version": "0.4.2", + "bundled": true, + "dev": true, + "optional": true + }, + "delayed-stream": { + "version": "1.0.0", + "bundled": true, + "dev": true + }, + "delegates": { + "version": "1.0.0", + "bundled": true, + "dev": true, + "optional": true + }, + "detect-libc": { + "version": "1.0.2", + "bundled": true, + "dev": true, + "optional": true + }, + "ecc-jsbn": { + "version": "0.1.1", + "bundled": true, + "dev": true, + "optional": true, + "requires": { + "jsbn": "0.1.1" + } + }, + "extend": { + "version": "3.0.1", + "bundled": true, + "dev": true, + "optional": true + }, + "extsprintf": { + "version": "1.0.2", + "bundled": true, + "dev": true + }, + "forever-agent": { + "version": "0.6.1", + "bundled": true, + "dev": true, + "optional": true + }, + "form-data": { + "version": "2.1.4", + "bundled": true, + "dev": true, + "optional": true, + "requires": { + "asynckit": "0.4.0", + "combined-stream": "1.0.5", + "mime-types": "2.1.15" + } + }, + "fs.realpath": { + "version": "1.0.0", + "bundled": true, + "dev": true + }, + "fstream": { + "version": "1.0.11", + "bundled": true, + "dev": true, + "requires": { + "graceful-fs": "4.1.11", + "inherits": "2.0.3", + "mkdirp": "0.5.1", + "rimraf": "2.6.1" + } + }, + "fstream-ignore": { + "version": "1.0.5", + "bundled": true, + "dev": true, + "optional": true, + "requires": { + "fstream": "1.0.11", + "inherits": "2.0.3", + "minimatch": "3.0.4" + } + }, + "gauge": { + "version": "2.7.4", + "bundled": true, + "dev": true, + "optional": true, + "requires": { + "aproba": "1.1.1", + "console-control-strings": "1.1.0", + "has-unicode": "2.0.1", + "object-assign": "4.1.1", + "signal-exit": "3.0.2", + "string-width": "1.0.2", + "strip-ansi": "3.0.1", + "wide-align": "1.1.2" + } + }, + "getpass": { + "version": "0.1.7", + "bundled": true, + "dev": true, + "optional": true, + "requires": { + "assert-plus": "1.0.0" + }, + "dependencies": { + "assert-plus": { + "version": "1.0.0", + "bundled": true, + "dev": true, + "optional": true + } + } + }, + "glob": { + "version": "7.1.2", + "bundled": true, + "dev": true, + "requires": { + "fs.realpath": "1.0.0", + "inflight": "1.0.6", + "inherits": "2.0.3", + "minimatch": "3.0.4", + "once": "1.4.0", + "path-is-absolute": "1.0.1" + } + }, + "graceful-fs": { + "version": "4.1.11", + "bundled": true, + "dev": true + }, + "har-schema": { + "version": "1.0.5", + "bundled": true, + "dev": true, + "optional": true + }, + "har-validator": { + "version": "4.2.1", + "bundled": true, + "dev": true, + "optional": true, + "requires": { + "ajv": "4.11.8", + "har-schema": "1.0.5" + } + }, + "has-unicode": { + "version": "2.0.1", + "bundled": true, + "dev": true, + "optional": true + }, + "hawk": { + "version": "3.1.3", + "bundled": true, + "dev": true, + "requires": { + "boom": "2.10.1", + "cryptiles": "2.0.5", + "hoek": "2.16.3", + "sntp": "1.0.9" + } + }, + "hoek": { + "version": "2.16.3", + "bundled": true, + "dev": true + }, + "http-signature": { + "version": "1.1.1", + "bundled": true, + "dev": true, + "optional": true, + "requires": { + "assert-plus": "0.2.0", + "jsprim": "1.4.0", + "sshpk": "1.13.0" + } + }, + "inflight": { + "version": "1.0.6", + "bundled": true, + "dev": true, + "requires": { + "once": "1.4.0", + "wrappy": "1.0.2" + } + }, + "inherits": { + "version": "2.0.3", + "bundled": true, + "dev": true + }, + "ini": { + "version": "1.3.4", + "bundled": true, + "dev": true, + "optional": true + }, + "is-fullwidth-code-point": { + "version": "1.0.0", + "bundled": true, + "dev": true, + "requires": { + "number-is-nan": "1.0.1" + } + }, + "is-typedarray": { + "version": "1.0.0", + "bundled": true, + "dev": true, + "optional": true + }, + "isarray": { + "version": "1.0.0", + "bundled": true, + "dev": true + }, + "isstream": { + "version": "0.1.2", + "bundled": true, + "dev": true, + "optional": true + }, + "jodid25519": { + "version": "1.0.2", + "bundled": true, + "dev": true, + "optional": true, + "requires": { + "jsbn": "0.1.1" + } + }, + "jsbn": { + "version": "0.1.1", + "bundled": true, + "dev": true, + "optional": true + }, + "json-schema": { + "version": "0.2.3", + "bundled": true, + "dev": true, + "optional": true + }, + "json-stable-stringify": { + "version": "1.0.1", + "bundled": true, + "dev": true, + "optional": true, + "requires": { + "jsonify": "0.0.0" + } + }, + "json-stringify-safe": { + "version": "5.0.1", + "bundled": true, + "dev": true, + "optional": true + }, + "jsonify": { + "version": "0.0.0", + "bundled": true, + "dev": true, + "optional": true + }, + "jsprim": { + "version": "1.4.0", + "bundled": true, + "dev": true, + "optional": true, + "requires": { + "assert-plus": "1.0.0", + "extsprintf": "1.0.2", + "json-schema": "0.2.3", + "verror": "1.3.6" + }, + "dependencies": { + "assert-plus": { + "version": "1.0.0", + "bundled": true, + "dev": true, + "optional": true + } + } + }, + "mime-db": { + "version": "1.27.0", + "bundled": true, + "dev": true + }, + "mime-types": { + "version": "2.1.15", + "bundled": true, + "dev": true, + "requires": { + "mime-db": "1.27.0" + } + }, + "minimatch": { + "version": "3.0.4", + "bundled": true, + "dev": true, + "requires": { + "brace-expansion": "1.1.7" + } + }, + "minimist": { + "version": "0.0.8", + "bundled": true, + "dev": true + }, + "mkdirp": { + "version": "0.5.1", + "bundled": true, + "dev": true, + "requires": { + "minimist": "0.0.8" + } + }, + "ms": { + "version": "2.0.0", + "bundled": true, + "dev": true, + "optional": true + }, + "node-pre-gyp": { + "version": "0.6.39", + "bundled": true, + "dev": true, + "optional": true, + "requires": { + "detect-libc": "1.0.2", + "hawk": "3.1.3", + "mkdirp": "0.5.1", + "nopt": "4.0.1", + "npmlog": "4.1.0", + "rc": "1.2.1", + "request": "2.81.0", + "rimraf": "2.6.1", + "semver": "5.3.0", + "tar": "2.2.1", + "tar-pack": "3.4.0" + } + }, + "nopt": { + "version": "4.0.1", + "bundled": true, + "dev": true, + "optional": true, + "requires": { + "abbrev": "1.1.0", + "osenv": "0.1.4" + } + }, + "npmlog": { + "version": "4.1.0", + "bundled": true, + "dev": true, + "optional": true, + "requires": { + "are-we-there-yet": "1.1.4", + "console-control-strings": "1.1.0", + "gauge": "2.7.4", + "set-blocking": "2.0.0" + } + }, + "number-is-nan": { + "version": "1.0.1", + "bundled": true, + "dev": true + }, + "oauth-sign": { + "version": "0.8.2", + "bundled": true, + "dev": true, + "optional": true + }, + "object-assign": { + "version": "4.1.1", + "bundled": true, + "dev": true, + "optional": true + }, + "once": { + "version": "1.4.0", + "bundled": true, + "dev": true, + "requires": { + "wrappy": "1.0.2" + } + }, + "os-homedir": { + "version": "1.0.2", + "bundled": true, + "dev": true, + "optional": true + }, + "os-tmpdir": { + "version": "1.0.2", + "bundled": true, + "dev": true, + "optional": true + }, + "osenv": { + "version": "0.1.4", + "bundled": true, + "dev": true, + "optional": true, + "requires": { + "os-homedir": "1.0.2", + "os-tmpdir": "1.0.2" + } + }, + "path-is-absolute": { + "version": "1.0.1", + "bundled": true, + "dev": true + }, + "performance-now": { + "version": "0.2.0", + "bundled": true, + "dev": true, + "optional": true + }, + "process-nextick-args": { + "version": "1.0.7", + "bundled": true, + "dev": true + }, + "punycode": { + "version": "1.4.1", + "bundled": true, + "dev": true, + "optional": true + }, + "qs": { + "version": "6.4.0", + "bundled": true, + "dev": true, + "optional": true + }, + "rc": { + "version": "1.2.1", + "bundled": true, + "dev": true, + "optional": true, + "requires": { + "deep-extend": "0.4.2", + "ini": "1.3.4", + "minimist": "1.2.0", + "strip-json-comments": "2.0.1" + }, + "dependencies": { + "minimist": { + "version": "1.2.0", + "bundled": true, + "dev": true, + "optional": true + } + } + }, + "readable-stream": { + "version": "2.2.9", + "bundled": true, + "dev": true, + "requires": { + "buffer-shims": "1.0.0", + "core-util-is": "1.0.2", + "inherits": "2.0.3", + "isarray": "1.0.0", + "process-nextick-args": "1.0.7", + "string_decoder": "1.0.1", + "util-deprecate": "1.0.2" + } + }, + "request": { + "version": "2.81.0", + "bundled": true, + "dev": true, + "optional": true, + "requires": { + "aws-sign2": "0.6.0", + "aws4": "1.6.0", + "caseless": "0.12.0", + "combined-stream": "1.0.5", + "extend": "3.0.1", + "forever-agent": "0.6.1", + "form-data": "2.1.4", + "har-validator": "4.2.1", + "hawk": "3.1.3", + "http-signature": "1.1.1", + "is-typedarray": "1.0.0", + "isstream": "0.1.2", + "json-stringify-safe": "5.0.1", + "mime-types": "2.1.15", + "oauth-sign": "0.8.2", + "performance-now": "0.2.0", + "qs": "6.4.0", + "safe-buffer": "5.0.1", + "stringstream": "0.0.5", + "tough-cookie": "2.3.2", + "tunnel-agent": "0.6.0", + "uuid": "3.0.1" + } + }, + "rimraf": { + "version": "2.6.1", + "bundled": true, + "dev": true, + "requires": { + "glob": "7.1.2" + } + }, + "safe-buffer": { + "version": "5.0.1", + "bundled": true, + "dev": true + }, + "semver": { + "version": "5.3.0", + "bundled": true, + "dev": true, + "optional": true + }, + "set-blocking": { + "version": "2.0.0", + "bundled": true, + "dev": true, + "optional": true + }, + "signal-exit": { + "version": "3.0.2", + "bundled": true, + "dev": true, + "optional": true + }, + "sntp": { + "version": "1.0.9", + "bundled": true, + "dev": true, + "requires": { + "hoek": "2.16.3" + } + }, + "sshpk": { + "version": "1.13.0", + "bundled": true, + "dev": true, + "optional": true, + "requires": { + "asn1": "0.2.3", + "assert-plus": "1.0.0", + "bcrypt-pbkdf": "1.0.1", + "dashdash": "1.14.1", + "ecc-jsbn": "0.1.1", + "getpass": "0.1.7", + "jodid25519": "1.0.2", + "jsbn": "0.1.1", + "tweetnacl": "0.14.5" + }, + "dependencies": { + "assert-plus": { + "version": "1.0.0", + "bundled": true, + "dev": true, + "optional": true + } + } + }, + "string-width": { + "version": "1.0.2", + "bundled": true, + "dev": true, + "requires": { + "code-point-at": "1.1.0", + "is-fullwidth-code-point": "1.0.0", + "strip-ansi": "3.0.1" + } + }, + "string_decoder": { + "version": "1.0.1", + "bundled": true, + "dev": true, + "requires": { + "safe-buffer": "5.0.1" + } + }, + "stringstream": { + "version": "0.0.5", + "bundled": true, + "dev": true, + "optional": true + }, + "strip-ansi": { + "version": "3.0.1", + "bundled": true, + "dev": true, + "requires": { + "ansi-regex": "2.1.1" + } + }, + "strip-json-comments": { + "version": "2.0.1", + "bundled": true, + "dev": true, + "optional": true + }, + "tar": { + "version": "2.2.1", + "bundled": true, + "dev": true, + "requires": { + "block-stream": "0.0.9", + "fstream": "1.0.11", + "inherits": "2.0.3" + } + }, + "tar-pack": { + "version": "3.4.0", + "bundled": true, + "dev": true, + "optional": true, + "requires": { + "debug": "2.6.8", + "fstream": "1.0.11", + "fstream-ignore": "1.0.5", + "once": "1.4.0", + "readable-stream": "2.2.9", + "rimraf": "2.6.1", + "tar": "2.2.1", + "uid-number": "0.0.6" + } + }, + "tough-cookie": { + "version": "2.3.2", + "bundled": true, + "dev": true, + "optional": true, + "requires": { + "punycode": "1.4.1" + } + }, + "tunnel-agent": { + "version": "0.6.0", + "bundled": true, + "dev": true, + "optional": true, + "requires": { + "safe-buffer": "5.0.1" + } + }, + "tweetnacl": { + "version": "0.14.5", + "bundled": true, + "dev": true, + "optional": true + }, + "uid-number": { + "version": "0.0.6", + "bundled": true, + "dev": true, + "optional": true + }, + "util-deprecate": { + "version": "1.0.2", + "bundled": true, + "dev": true + }, + "uuid": { + "version": "3.0.1", + "bundled": true, + "dev": true, + "optional": true + }, + "verror": { + "version": "1.3.6", + "bundled": true, + "dev": true, + "optional": true, + "requires": { + "extsprintf": "1.0.2" + } + }, + "wide-align": { + "version": "1.1.2", + "bundled": true, + "dev": true, + "optional": true, + "requires": { + "string-width": "1.0.2" + } + }, + "wrappy": { + "version": "1.0.2", + "bundled": true, + "dev": true + } + } + }, "ftp": { "version": "0.3.10", "resolved": "https://registry.npmjs.org/ftp/-/ftp-0.3.10.tgz", @@ -2461,6 +3365,7 @@ "anymatch": "2.0.0", "async-each": "1.0.1", "braces": "2.3.1", + "fsevents": "1.1.3", "glob-parent": "3.1.0", "inherits": "2.0.3", "is-binary-path": "1.0.1", @@ -4500,6 +5405,13 @@ "integrity": "sha1-QCj3d4sXcIpImTCm5SrDvKDaQdA=", "dev": true }, + "nan": { + "version": "2.10.0", + "resolved": "https://registry.npmjs.org/nan/-/nan-2.10.0.tgz", + "integrity": "sha512-bAdJv7fBLhWC+/Bls0Oza+mvTaNQtP+1RyhhhvD95pgUJz6XM5IzgmxOkItJ9tkoCiplvAnXI1tNmmUD/eScyA==", + "dev": true, + "optional": true + }, "nanomatch": { "version": "1.2.9", "resolved": "https://registry.npmjs.org/nanomatch/-/nanomatch-1.2.9.tgz", @@ -5270,6 +6182,37 @@ "integrity": "sha512-MtEC1TqN0EU5nephaJ4rAtThHtC86dNN9qCuEhtshvpVBkAW5ZO7BASN9REnF9eoXGcRub+pFuKEpOHE+HbEMw==", "dev": true }, + "process-pool": { + "version": "0.3.5", + "resolved": "https://registry.npmjs.org/process-pool/-/process-pool-0.3.5.tgz", + "integrity": "sha1-lrQKexzd2SRhu9Ygx2arCO1L7zc=", + "requires": { + "bluebird": "2.11.0", + "lodash": "3.10.1", + "rewire": "2.5.2", + "source-map": "0.4.4" + }, + "dependencies": { + "bluebird": { + "version": "2.11.0", + "resolved": "https://registry.npmjs.org/bluebird/-/bluebird-2.11.0.tgz", + "integrity": "sha1-U0uQM8AiyVecVro7Plpcqvu2UOE=" + }, + "lodash": { + "version": "3.10.1", + "resolved": "https://registry.npmjs.org/lodash/-/lodash-3.10.1.tgz", + "integrity": "sha1-W/Rejkm6QYnhfUgnid/RW9FAt7Y=" + }, + "source-map": { + "version": "0.4.4", + "resolved": "https://registry.npmjs.org/source-map/-/source-map-0.4.4.tgz", + "integrity": "sha1-66T12pwNyZneaAMti092FzZSA2s=", + "requires": { + "amdefine": "1.0.1" + } + } + } + }, "progress": { "version": "1.1.8", "resolved": "https://registry.npmjs.org/progress/-/progress-1.1.8.tgz", @@ -5738,6 +6681,11 @@ "integrity": "sha512-TTlYpa+OL+vMMNG24xSlQGEJ3B/RzEfUlLct7b5G/ytav+wPrplCpVMFuwzXbkecJrb6IYo1iFb0S9v37754mg==", "dev": true }, + "rewire": { + "version": "2.5.2", + "resolved": "https://registry.npmjs.org/rewire/-/rewire-2.5.2.tgz", + "integrity": "sha1-ZCfee3/u+n02QBUH62SlOFvFjcc=" + }, "right-align": { "version": "0.1.3", "resolved": "https://registry.npmjs.org/right-align/-/right-align-0.1.3.tgz", diff --git a/package.json b/package.json index 77810ba..1523551 100644 --- a/package.json +++ b/package.json @@ -39,6 +39,7 @@ "dependencies": { "jasmine-core": "^3.1.0", "parse": "^1.11.0", - "phaser": "2.6.2" + "phaser": "2.6.2", + "process-pool": "^0.3.5" } -} \ No newline at end of file +} diff --git a/src/MainUI.ts b/src/MainUI.ts index 62c7b40..26537bc 100644 --- a/src/MainUI.ts +++ b/src/MainUI.ts @@ -1,9 +1,26 @@ /// if (typeof window != "undefined") { + // If jasmine is not present, ignore describe (window).describe = (window).describe || function () { }; } +declare var global: any; +if (typeof global != "undefined") { + // In node, does not extend Phaser classes + var handler = { + get(target: any, name: any) { + return function () { } + } + } + global.Phaser = new Proxy({}, handler); +} + +declare var module: any; +if (typeof module != "undefined") { + module.exports = { TK }; +} + module TK.SpaceTac { // Router between game views export class MainUI extends Phaser.Game { diff --git a/src/core/ai/AIDuel.ts b/src/core/ai/AIDuel.ts deleted file mode 100644 index f4a1d82..0000000 --- a/src/core/ai/AIDuel.ts +++ /dev/null @@ -1,144 +0,0 @@ -module TK.SpaceTac { - /** - * Duel between two AIs, over multiple battles - */ - export class AIDuel { - static current: AIDuel | null = null - - ai1: AbstractAI - ai2: AbstractAI - win1 = 0 - win2 = 0 - draw = 0 - scheduled = null - stopped = false - onupdate: Function | null = null - - constructor(ai1: AbstractAI, ai2: AbstractAI) { - this.ai1 = ai1; - this.ai2 = ai2; - } - - /** - * Start the duel - */ - start(onupdate: Function | null = null) { - if (!this.scheduled) { - this.stopped = false; - this.scheduled = Timer.global.schedule(100, () => this.next()); - this.onupdate = onupdate; - } - } - - /** - * Stop the duel - */ - stop() { - this.stopped = true; - if (this.scheduled) { - Timer.global.cancel(this.scheduled); - this.scheduled = null; - } - } - - /** - * Update the result of a single battle - */ - update(winner: number) { - if (winner >= 0) { - if (winner == 0) { - this.win1 += 1; - console.log(` => Player 1 wins (${this.ai1})`); - } else { - this.win2 += 1; - console.log(` => Player 2 wins (${this.ai2})`); - } - } else { - this.draw += 1; - console.log(" => draw"); - } - - if (this.onupdate) { - this.onupdate(); - } - } - - /** - * Perform the next battle - */ - async next() { - console.log(`${this.ai1.name} vs ${this.ai2.name} ...`); - - // Prepare battle - let battle = Battle.newQuickRandom(); - battle.fleets.forEach((fleet, findex) => { - fleet.ships.forEach((ship, sindex) => { - ship.name = `F${findex + 1}S${sindex + 1} (${ship.model.name})`; - }); - }); - - // Run battle - while (!battle.ended && battle.cycle < 100) { - if (this.stopped) { - return; - } - - let playing = battle.playing_ship; - if (playing) { - let ai = (playing.fleet == battle.fleets[0]) ? this.ai1 : this.ai2; - ai.ship = playing; - await ai.play(); - } - } - - // Update results, and go on to next battle - if (battle.outcome && !battle.outcome.draw && battle.outcome.winner) { - this.update(battle.fleets.indexOf(battle.outcome.winner)); - } else { - this.update(-1); - } - this.scheduled = Timer.global.schedule(50, () => this.next()); - } - - /** - * Setup the duel HTML page - */ - static setup(element: HTMLElement) { - let fakeship = new Ship(); - let ais = [new TacticalAI(fakeship), new AbstractAI(fakeship)]; - ais.forEach((ai, idx) => { - let selects = element.getElementsByTagName("select"); - for (let i = 0; i < selects.length; i++) { - let option = document.createElement("option"); - option.setAttribute("value", idx.toString()); - option.textContent = ai.name; - selects[i].appendChild(option); - } - ai.name += `${idx + 1}`; - ai.timer = new Timer(); - ai.timer.schedule = (delay, callback) => Timer.global.schedule(1, callback); - }); - - let button = element.getElementsByTagName("button").item(0); - button.onclick = () => { - if (AIDuel.current) { - AIDuel.current.stop(); - AIDuel.current = null; - button.textContent = "Start !"; - } else { - console.clear(); - let ai1 = parseInt(element.getElementsByTagName("select").item(0).value); - let ai2 = parseInt(element.getElementsByTagName("select").item(1).value); - let duel = new AIDuel(ais[ai1], ais[ai2]); - AIDuel.current = duel; - duel.start(() => { - element.getElementsByClassName("win1").item(0).textContent = duel.win1.toString(); - element.getElementsByClassName("win2").item(0).textContent = duel.win2.toString(); - element.getElementsByClassName("draw").item(0).textContent = duel.draw.toString(); - }); - button.textContent = "Stop !"; - } - } - } - } -} diff --git a/tsconfig.json b/tsconfig.json index b265a5f..5a2418c 100644 --- a/tsconfig.json +++ b/tsconfig.json @@ -11,10 +11,9 @@ "sourceMap": true, "lib": [ "dom", - "es2015.promise", - "es5" + "es6" ], - "target": "es5" + "target": "es6" }, "include": [ "src/**/*.ts"