1
0
Fork 0

Replaced AI duel page with a node.js multi-process simulator

This commit is contained in:
Michaël Lemaire 2018-04-06 00:27:26 +02:00
parent 4838c74236
commit 095cf9e491
8 changed files with 1041 additions and 263 deletions

View File

@ -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

View File

@ -1,110 +0,0 @@
<!DOCTYPE HTML>
<html lang="en">
<head>
<meta charset="utf-8" />
<title>SpaceTac - AI Duel</title>
<style>
* {
margin: 0;
font-family: 'SpaceTac';
}
@font-face {
font-family: 'SpaceTac';
src: url('fonts/daggersquare.regular.otf');
}
body {
background-color: #111;
color: #eee;
}
h1 {
margin-bottom: 38px;
font-size: 30px;
}
#duel {
width: 50vw;
margin-top: 30vh;
margin-left: auto;
margin-right: auto;
text-align: center;
}
button,
select {
font-size: 26px;
border: none;
border-radius: 6px;
background-color: #ddd;
cursor: pointer;
}
td {
padding: 12px;
width: 16vw;
text-align: center;
font-size: 26px;
border-radius: 5px;
}
td:nth-child(1) {
background-color: #611;
}
td:nth-child(3) {
background-color: #148;
}
td[colspan] {
background-color: inherit;
}
</style>
</head>
<body>
<script src="vendor/phaser/phaser.min.js"></script>
<script src="build.js"></script>
<div id="duel">
<h1>SpaceTac - AI Duel</h1>
<table>
<tr>
<td>
<select></select>
</td>
<td>versus</td>
<td>
<select></select>
</td>
</tr>
<tr>
<td colspan="3">
<button>Start !</button>
</td>
</tr>
<tr>
<td>Win</td>
<td>Draw</td>
<td>Win</td>
</tr>
<tr>
<td class="win1"></td>
<td class="draw"></td>
<td class="win2"></td>
</tr>
</table>
</div>
<script>
window.onload = function () {
TK.SpaceTac.AIDuel.setup(document.getElementById("duel"));
};
</script>
</body>
</html>

68
out/sim.js Normal file
View File

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

952
package-lock.json generated
View File

@ -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",

View File

@ -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"
}
}
}

View File

@ -1,9 +1,26 @@
/// <reference path="lib/phaser.d.ts"/>
if (typeof window != "undefined") {
// If jasmine is not present, ignore describe
(<any>window).describe = (<any>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 {

View File

@ -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 !";
}
}
}
}
}

View File

@ -11,10 +11,9 @@
"sourceMap": true,
"lib": [
"dom",
"es2015.promise",
"es5"
"es6"
],
"target": "es5"
"target": "es6"
},
"include": [
"src/**/*.ts"