"use strict"; var __create = Object.create; var __defProp = Object.defineProperty; var __getOwnPropDesc = Object.getOwnPropertyDescriptor; var __getOwnPropNames = Object.getOwnPropertyNames; var __getProtoOf = Object.getPrototypeOf; var __hasOwnProp = Object.prototype.hasOwnProperty; var __export = (target, all) => { for (var name in all) __defProp(target, name, { get: all[name], enumerable: true }); }; var __copyProps = (to, from, except, desc) => { if (from && typeof from === "object" || typeof from === "function") { for (let key of __getOwnPropNames(from)) if (!__hasOwnProp.call(to, key) && key !== except) __defProp(to, key, { get: () => from[key], enumerable: !(desc = __getOwnPropDesc(from, key)) || desc.enumerable }); } return to; }; var __toESM = (mod, isNodeMode, target) => (target = mod != null ? __create(__getProtoOf(mod)) : {}, __copyProps( // If the importer is in node compatibility mode or this is not an ESM // file that has been converted to a CommonJS file using a Babel- // compatible transform (i.e. "__esModule" has not been set), then set // "default" to the CommonJS "module.exports" for node compatibility. isNodeMode || !mod || !mod.__esModule ? __defProp(target, "default", { value: mod, enumerable: true }) : target, mod )); var __toCommonJS = (mod) => __copyProps(__defProp({}, "__esModule", { value: true }), mod); var runner_exports = {}; __export(runner_exports, { Runner: () => Runner }); module.exports = __toCommonJS(runner_exports); var import_assert = require("assert"); var fs = __toESM(require("fs")); var import__ = require(".."); var import_battle = require("../battle"); var BattleStreams = __toESM(require("../battle-stream")); var import_state = require("../state"); var import_prng = require("../prng"); var import_random_player_ai = require("./random-player-ai"); /** * Battle Simulator runner. * Pokemon Showdown - http://pokemonshowdown.com/ * * @license MIT */ const _Runner = class { constructor(options) { this.format = options.format; this.prng = import_prng.PRNG.get(options.prng); this.p1options = { ..._Runner.AI_OPTIONS, ...options.p1options }; this.p2options = { ..._Runner.AI_OPTIONS, ...options.p2options }; this.p3options = { ..._Runner.AI_OPTIONS, ...options.p3options }; this.p4options = { ..._Runner.AI_OPTIONS, ...options.p4options }; this.input = !!options.input; this.output = !!options.output; this.error = !!options.error; this.dual = options.dual || false; } async run() { const battleStream = this.dual ? new DualStream(this.input, this.dual === "debug") : new RawBattleStream(this.input); const game = this.runGame(this.format, battleStream); if (!this.error) return game; return game.catch((err) => { console.log(` ${battleStream.rawInputLog.join("\n")} `); throw err; }); } async runGame(format, battleStream) { const streams = BattleStreams.getPlayerStreams(battleStream); const spec = { formatid: format, seed: this.prng.getSeed() }; const is4P = import__.Dex.formats.get(format).playerCount > 2; const p1spec = this.getPlayerSpec("Bot 1", this.p1options); const p2spec = this.getPlayerSpec("Bot 2", this.p2options); let p3spec, p4spec; if (is4P) { p3spec = this.getPlayerSpec("Bot 3", this.p3options); p4spec = this.getPlayerSpec("Bot 4", this.p4options); } const p1 = this.p1options.createAI( streams.p1, { seed: this.newSeed(), ...this.p1options } ); const p2 = this.p2options.createAI( streams.p2, { seed: this.newSeed(), ...this.p2options } ); let p3, p4; if (is4P) { p3 = this.p4options.createAI( streams.p3, { seed: this.newSeed(), ...this.p3options } ); p4 = this.p4options.createAI( streams.p4, { seed: this.newSeed(), ...this.p4options } ); } void p1.start(); void p2.start(); if (is4P) { void p3.start(); void p4.start(); } let initMessage = `>start ${JSON.stringify(spec)} >player p1 ${JSON.stringify(p1spec)} >player p2 ${JSON.stringify(p2spec)}`; if (is4P) { initMessage += ` >player p3 ${JSON.stringify(p3spec)} >player p4 ${JSON.stringify(p4spec)}`; } void streams.omniscient.write(initMessage); for await (const chunk of streams.omniscient) { if (this.output) console.log(chunk); } return streams.omniscient.writeEnd(); } // Same as PRNG#generatedSeed, only deterministic. // NOTE: advances this.prng's seed by 4. newSeed() { return [ this.prng.random(2 ** 16), this.prng.random(2 ** 16), this.prng.random(2 ** 16), this.prng.random(2 ** 16) ].join(","); } getPlayerSpec(name, options) { if (options.team) return { name, team: options.team }; return { name, seed: this.newSeed() }; } }; let Runner = _Runner; Runner.AI_OPTIONS = { createAI: (s, o) => new import_random_player_ai.RandomPlayerAI(s, o), move: 0.7, mega: 0.6 }; class RawBattleStream extends BattleStreams.BattleStream { constructor(input) { super(); this.input = !!input; this.rawInputLog = []; } _write(message) { if (this.input) console.log(message); this.rawInputLog.push(message); super._write(message); } } class DualStream { constructor(input, debug) { this.debug = debug; this.control = new RawBattleStream(input); this.test = new RawBattleStream(false); } get rawInputLog() { const control = this.control.rawInputLog; const test = this.test.rawInputLog; import_assert.strict.deepEqual(test, control); return control; } async read() { const control = await this.control.read(); const test = await this.test.read(); if (!this.debug) import_assert.strict.equal(import_state.State.normalizeLog(test), import_state.State.normalizeLog(control)); return control; } write(message) { this.control._write(message); this.test._write(message); this.compare(); } writeEnd() { this.compare(true); this.control._writeEnd(); this.test._writeEnd(); } compare(end) { if (!this.control.battle || !this.test.battle) return; const control = this.control.battle.toJSON(); const test = this.test.battle.toJSON(); try { import_assert.strict.deepEqual(import_state.State.normalize(test), import_state.State.normalize(control)); } catch (err) { if (this.debug) { fs.writeFileSync("logs/control.json", JSON.stringify(control, null, 2)); fs.writeFileSync("logs/test.json", JSON.stringify(test, null, 2)); } throw new Error(err.message); } if (end) return; const send = this.test.battle.send; this.test.battle = import_battle.Battle.fromJSON(test); this.test.battle.restart(send); } } //# sourceMappingURL=runner.js.map