{ "version": 3, "sources": ["../../../../sim/tools/exhaustive-runner.ts"], "sourcesContent": ["/**\r\n * Battle Simulator exhaustive runner.\r\n * Pokemon Showdown - http://pokemonshowdown.com/\r\n *\r\n * @license MIT\r\n */\r\n\r\nimport {ObjectReadWriteStream} from '../../lib/streams';\r\nimport {Dex, toID} from '../dex';\r\nimport {PRNG, PRNGSeed} from '../prng';\r\nimport {RandomPlayerAI} from './random-player-ai';\r\nimport {AIOptions, Runner} from './runner';\r\n\r\ninterface Pools {\r\n\tpokemon: Pool;\r\n\titems: Pool;\r\n\tabilities: Pool;\r\n\tmoves: Pool;\r\n}\r\n\r\nexport interface ExhaustiveRunnerOptions {\r\n\tformat: string;\r\n\tcycles?: number;\r\n\tprng?: PRNG | PRNGSeed | null;\r\n\tlog?: boolean;\r\n\tmaxGames?: number;\r\n\tmaxFailures?: number;\r\n\tdual?: boolean | 'debug';\r\n}\r\n\r\nexport class ExhaustiveRunner {\r\n\tstatic readonly DEFAULT_CYCLES = 1;\r\n\tstatic readonly MAX_FAILURES = 10;\r\n\r\n\t// TODO: Add triple battles once supported by the AI.\r\n\tstatic readonly FORMATS = [\r\n\t\t'gen9customgame', 'gen9doublescustomgame',\r\n\t\t'gen8customgame', 'gen8doublescustomgame',\r\n\t\t'gen7customgame', 'gen7doublescustomgame',\r\n\t\t'gen6customgame', 'gen6doublescustomgame',\r\n\t\t'gen5customgame', 'gen5doublescustomgame',\r\n\t\t'gen4customgame', 'gen4doublescustomgame',\r\n\t\t'gen3customgame', 'gen3doublescustomgame',\r\n\t\t'gen2customgame',\r\n\t\t'gen1customgame',\r\n\t];\r\n\r\n\tprivate readonly format: string;\r\n\tprivate readonly cycles: number;\r\n\tprivate readonly prng: PRNG;\r\n\tprivate readonly log: boolean;\r\n\tprivate readonly maxGames?: number;\r\n\tprivate readonly maxFailures?: number;\r\n\tprivate readonly dual: boolean | 'debug';\r\n\r\n\tprivate failures: number;\r\n\tprivate games: number;\r\n\r\n\tconstructor(options: ExhaustiveRunnerOptions) {\r\n\t\tthis.format = options.format;\r\n\t\tthis.cycles = options.cycles || ExhaustiveRunner.DEFAULT_CYCLES;\r\n\t\tthis.prng = (options.prng && !Array.isArray(options.prng)) ?\r\n\t\t\toptions.prng : new PRNG(options.prng);\r\n\t\tthis.log = !!options.log;\r\n\t\tthis.maxGames = options.maxGames;\r\n\t\tthis.maxFailures = options.maxFailures || ExhaustiveRunner.MAX_FAILURES;\r\n\t\tthis.dual = options.dual || false;\r\n\r\n\t\tthis.failures = 0;\r\n\t\tthis.games = 0;\r\n\t}\r\n\r\n\tasync run() {\r\n\t\tconst dex = Dex.forFormat(this.format);\r\n\t\tdex.loadData(); // FIXME: This is required for `dex.gen` to be set properly...\r\n\r\n\t\tconst seed = this.prng.seed;\r\n\t\tconst pools = this.createPools(dex);\r\n\t\tconst createAI = (s: ObjectReadWriteStream, o: AIOptions) => new CoordinatedPlayerAI(s, o, pools);\r\n\t\tconst generator = new TeamGenerator(dex, this.prng, pools, ExhaustiveRunner.getSignatures(dex, pools));\r\n\r\n\t\tdo {\r\n\t\t\tthis.games++;\r\n\t\t\ttry {\r\n\t\t\t\tconst is4P = dex.formats.get(this.format).gameType === 'multi';\r\n\t\t\t\t// We run these sequentially instead of async so that the team generator\r\n\t\t\t\t// and the AI can coordinate usage properly.\r\n\t\t\t\tawait new Runner({\r\n\t\t\t\t\tprng: this.prng,\r\n\t\t\t\t\tp1options: {team: generator.generate(), createAI},\r\n\t\t\t\t\tp2options: {team: generator.generate(), createAI},\r\n\t\t\t\t\tp3options: is4P ? {team: generator.generate(), createAI} : undefined,\r\n\t\t\t\t\tp4options: is4P ? {team: generator.generate(), createAI} : undefined,\r\n\t\t\t\t\tformat: this.format,\r\n\t\t\t\t\tdual: this.dual,\r\n\t\t\t\t\terror: true,\r\n\t\t\t\t}).run();\r\n\r\n\t\t\t\tif (this.log) this.logProgress(pools);\r\n\t\t\t} catch (err) {\r\n\t\t\t\tthis.failures++;\r\n\t\t\t\tconsole.error(\r\n\t\t\t\t\t`\\n\\nRun \\`node tools/simulate exhaustive --cycles=${this.cycles} ` +\r\n\t\t\t\t\t\t`--format=${this.format} --seed=${seed.join()}\\`:\\n`,\r\n\t\t\t\t\terr\r\n\t\t\t\t);\r\n\t\t\t}\r\n\t\t} while ((!this.maxGames || this.games < this.maxGames) &&\r\n\t\t\t\t\t(!this.maxFailures || this.failures < this.maxFailures) &&\r\n\t\t\t\t\tgenerator.exhausted < this.cycles);\r\n\r\n\t\treturn this.failures;\r\n\t}\r\n\r\n\tprivate createPools(dex: typeof Dex): Pools {\r\n\t\treturn {\r\n\t\t\tpokemon: new Pool(ExhaustiveRunner.onlyValid(dex.gen, dex.data.Pokedex, p => dex.species.get(p),\r\n\t\t\t\t(_, p) => (p.name !== 'Pichu-Spiky-eared' && p.name.substr(0, 8) !== 'Pikachu-')), this.prng),\r\n\t\t\titems: new Pool(ExhaustiveRunner.onlyValid(dex.gen, dex.data.Items, i => dex.items.get(i)), this.prng),\r\n\t\t\tabilities: new Pool(ExhaustiveRunner.onlyValid(dex.gen, dex.data.Abilities, a => dex.abilities.get(a)), this.prng),\r\n\t\t\tmoves: new Pool(ExhaustiveRunner.onlyValid(dex.gen, dex.data.Moves, m => dex.moves.get(m),\r\n\t\t\t\tm => (m !== 'struggle' && (m === 'hiddenpower' || m.substr(0, 11) !== 'hiddenpower'))), this.prng),\r\n\t\t};\r\n\t}\r\n\r\n\tprivate logProgress(p: Pools) {\r\n\t\t// `\\r` = return to the beginning of the line\r\n\t\t// `\\x1b[k` (`\\e[K`) = clear all characters from cursor position to EOL\r\n\t\tif (this.games) process.stdout.write('\\r\\x1b[K');\r\n\t\t// Deliberately don't print a `\\n` character so that we can overwrite\r\n\t\tprocess.stdout.write(\r\n\t\t\t`[${this.format}] P:${p.pokemon} I:${p.items} A:${p.abilities} M:${p.moves} = ${this.games}`\r\n\t\t);\r\n\t}\r\n\r\n\tprivate static getSignatures(dex: typeof Dex, pools: Pools): Map {\r\n\t\tconst signatures = new Map();\r\n\t\tfor (const id of pools.items.possible) {\r\n\t\t\tconst item = dex.data.Items[id];\r\n\t\t\tif (item.megaEvolves) {\r\n\t\t\t\tconst pokemon = toID(item.megaEvolves);\r\n\t\t\t\tconst combo = {item: id};\r\n\t\t\t\tlet combos = signatures.get(pokemon);\r\n\t\t\t\tif (!combos) {\r\n\t\t\t\t\tcombos = [];\r\n\t\t\t\t\tsignatures.set(pokemon, combos);\r\n\t\t\t\t}\r\n\t\t\t\tcombos.push(combo);\r\n\t\t\t} else if (item.itemUser) {\r\n\t\t\t\tfor (const user of item.itemUser) {\r\n\t\t\t\t\tconst pokemon = toID(user);\r\n\t\t\t\t\tconst combo: {item: string, move?: string} = {item: id};\r\n\t\t\t\t\tif (item.zMoveFrom) combo.move = toID(item.zMoveFrom);\r\n\t\t\t\t\tlet combos = signatures.get(pokemon);\r\n\t\t\t\t\tif (!combos) {\r\n\t\t\t\t\t\tcombos = [];\r\n\t\t\t\t\t\tsignatures.set(pokemon, combos);\r\n\t\t\t\t\t}\r\n\t\t\t\t\tcombos.push(combo);\r\n\t\t\t\t}\r\n\t\t\t}\r\n\t\t}\r\n\t\treturn signatures;\r\n\t}\r\n\r\n\tprivate static onlyValid(\r\n\t\tgen: number, obj: {[key: string]: T}, getter: (k: string) => AnyObject,\r\n\t\tadditional?: (k: string, v: AnyObject) => boolean, nonStandard?: boolean\r\n\t) {\r\n\t\treturn Object.keys(obj).filter(k => {\r\n\t\t\tconst v = getter(k);\r\n\t\t\treturn v.gen <= gen &&\r\n\t\t\t\t(!v.isNonstandard || !!nonStandard) &&\r\n\t\t\t\t(!additional || additional(k, v));\r\n\t\t});\r\n\t}\r\n}\r\n\r\n// Generates random teams of pokemon suitable for use in custom games (ie. without team\r\n// validation). Coordinates with the CoordinatedPlayerAI below through Pools to ensure as\r\n// many different options as possible get exercised in battle.\r\nclass TeamGenerator {\r\n\t// By default, the TeamGenerator generates sets completely at random which unforunately means\r\n\t// certain signature combinations (eg. Mega Stone/Z Moves which only work for specific Pokemon)\r\n\t// are unlikely to be chosen. To combat this, we keep a mapping of these combinations and some\r\n\t// fraction of the time when we are generating sets for these particular Pokemon we give them\r\n\t// the combinations they need to exercise the simulator more thoroughly.\r\n\tstatic readonly COMBO = 0.5;\r\n\r\n\tprivate readonly dex: typeof Dex;\r\n\tprivate readonly prng: PRNG;\r\n\tprivate readonly pools: Pools;\r\n\tprivate readonly signatures: Map;\r\n\tprivate readonly natures: readonly string[];\r\n\r\n\tconstructor(\r\n\t\tdex: typeof Dex, prng: PRNG | PRNGSeed | null, pools: Pools,\r\n\t\tsignatures: Map\r\n\t) {\r\n\t\tthis.dex = dex;\r\n\t\tthis.prng = prng && !Array.isArray(prng) ? prng : new PRNG(prng);\r\n\t\tthis.pools = pools;\r\n\t\tthis.signatures = signatures;\r\n\r\n\t\tthis.natures = Object.keys(this.dex.data.Natures);\r\n\t}\r\n\r\n\tget exhausted() {\r\n\t\tconst exhausted = [this.pools.pokemon.exhausted, this.pools.moves.exhausted];\r\n\t\tif (this.dex.gen >= 2) exhausted.push(this.pools.items.exhausted);\r\n\t\tif (this.dex.gen >= 3) exhausted.push(this.pools.abilities.exhausted);\r\n\t\treturn Math.min.apply(null, exhausted);\r\n\t}\r\n\r\n\tgenerate() {\r\n\t\tconst team: PokemonSet[] = [];\r\n\t\tfor (const pokemon of this.pools.pokemon.next(6)) {\r\n\t\t\tconst species = this.dex.species.get(pokemon);\r\n\t\t\tconst randomEVs = () => this.prng.next(253);\r\n\t\t\tconst randomIVs = () => this.prng.next(32);\r\n\r\n\t\t\tlet item;\r\n\t\t\tconst moves = [];\r\n\t\t\tconst combos = this.signatures.get(species.id);\r\n\t\t\tif (combos && this.prng.next() > TeamGenerator.COMBO) {\r\n\t\t\t\tconst combo = this.prng.sample(combos);\r\n\t\t\t\titem = combo.item;\r\n\t\t\t\tif (combo.move) moves.push(combo.move);\r\n\t\t\t} else {\r\n\t\t\t\titem = this.dex.gen >= 2 ? this.pools.items.next() : '';\r\n\t\t\t}\r\n\r\n\t\t\tteam.push({\r\n\t\t\t\tname: species.baseSpecies,\r\n\t\t\t\tspecies: species.name,\r\n\t\t\t\tgender: species.gender,\r\n\t\t\t\titem,\r\n\t\t\t\tability: this.dex.gen >= 3 ? this.pools.abilities.next() : 'None',\r\n\t\t\t\tmoves: moves.concat(...this.pools.moves.next(4 - moves.length)),\r\n\t\t\t\tevs: {\r\n\t\t\t\t\thp: randomEVs(),\r\n\t\t\t\t\tatk: randomEVs(),\r\n\t\t\t\t\tdef: randomEVs(),\r\n\t\t\t\t\tspa: randomEVs(),\r\n\t\t\t\t\tspd: randomEVs(),\r\n\t\t\t\t\tspe: randomEVs(),\r\n\t\t\t\t},\r\n\t\t\t\tivs: {\r\n\t\t\t\t\thp: randomIVs(),\r\n\t\t\t\t\tatk: randomIVs(),\r\n\t\t\t\t\tdef: randomIVs(),\r\n\t\t\t\t\tspa: randomIVs(),\r\n\t\t\t\t\tspd: randomIVs(),\r\n\t\t\t\t\tspe: randomIVs(),\r\n\t\t\t\t},\r\n\t\t\t\tnature: this.prng.sample(this.natures),\r\n\t\t\t\tlevel: this.prng.next(50, 100),\r\n\t\t\t\thappiness: this.prng.next(256),\r\n\t\t\t\tshiny: this.prng.randomChance(1, 1024),\r\n\t\t\t});\r\n\t\t}\r\n\t\treturn team;\r\n\t}\r\n}\r\n\r\nclass Pool {\r\n\treadonly possible: string[];\r\n\r\n\tprivate readonly prng: PRNG;\r\n\r\n\tprivate unused: Set;\r\n\tprivate filled: Set | undefined;\r\n\tprivate filler: string[] | undefined;\r\n\tprivate iter: (Iterator & {done?: boolean}) | undefined;\r\n\r\n\texhausted: number;\r\n\r\n\tconstructor(possible: string[], prng: PRNG) {\r\n\t\tthis.possible = possible;\r\n\t\tthis.prng = prng;\r\n\t\tthis.exhausted = 0;\r\n\t\tthis.unused = new Set();\r\n\t}\r\n\r\n\ttoString() {\r\n\t\treturn `${this.exhausted} (${this.unused.size}/${this.possible.length})`;\r\n\t}\r\n\r\n\tprivate reset() {\r\n\t\tif (this.filled) this.exhausted++;\r\n\r\n\t\tthis.iter = undefined;\r\n\t\tthis.unused = new Set(this.shuffle(this.possible));\r\n\t\tif (this.possible.length && this.filled) {\r\n\t\t\tfor (const used of this.filled) {\r\n\t\t\t\tthis.unused.delete(used);\r\n\t\t\t}\r\n\t\t\tthis.filled = new Set();\r\n\t\t\tif (!this.unused.size) this.reset();\r\n\t\t} else {\r\n\t\t\tthis.filled = new Set();\r\n\t\t}\r\n\t\tthis.filler = this.possible.slice();\r\n\t\t// POST: this.unused.size === this.possible.length\r\n\t\t// POST: this.filler.length > 0\r\n\t\t// POST: this.filled.size === 0\r\n\t\t// POST: this.iter === undefined\r\n\t}\r\n\r\n\tprivate shuffle(arr: T[]): T[] {\r\n\t\tfor (let i = arr.length - 1; i > 0; i--) {\r\n\t\t\tconst j = Math.floor(this.prng.next() * (i + 1));\r\n\t\t\t[arr[i], arr[j]] = [arr[j], arr[i]];\r\n\t\t}\r\n\t\treturn arr;\r\n\t}\r\n\r\n\twasUsed(k: string) {\r\n\t\t// NOTE: We are intentionally clearing our iterator even though `unused`\r\n\t\t// hasn't been modified, see explanation below.\r\n\t\tthis.iter = undefined;\r\n\t\treturn !this.unused.has(k);\r\n\t}\r\n\r\n\tmarkUsed(k: string) {\r\n\t\tthis.iter = undefined;\r\n\t\tthis.unused.delete(k);\r\n\t}\r\n\r\n\tnext(): string;\r\n\tnext(num: number): string[];\r\n\tnext(num?: number): string | string[] {\r\n\t\tif (!num) return this.choose();\r\n\t\tconst chosen = [];\r\n\t\tfor (let i = 0; i < num; i++) {\r\n\t\t\tchosen.push(this.choose());\r\n\t\t}\r\n\t\treturn chosen;\r\n\t}\r\n\r\n\t// Returns the next option in our set of unused options which were shuffled\r\n\t// before insertion so as to come out in random order. The iterator is\r\n\t// reset when the pools are manipulated by the CombinedPlayerAI (`markUsed`\r\n\t// as it mutates the set, but also `wasUsed` because resetting the\r\n\t// iterator isn't so much 'marking it as invalid' as 'signalling that we\r\n\t// should move the unused options to the top again').\r\n\t//\r\n\t// As the pool of options dwindles, we run into scenarios where `choose`\r\n\t// will keep returning the same options. This helps ensure they get used,\r\n\t// but having a game with every Pokemon having the same move or ability etc\r\n\t// is less realistic, so instead we 'fill' out the remaining choices during a\r\n\t// generator round (ie. until our iterator gets invalidated during gameplay).\r\n\t//\r\n\t// The 'filler' choices are tracked in `filled` to later subtract from the next\r\n\t// exhaustion cycle of this pool, but in theory we could be so unlucky that\r\n\t// we loop through our fillers multiple times while dealing with a few stubborn\r\n\t// remaining options in `unused`, therefore undercounting our `exhausted` total,\r\n\t// but this is considered to be unlikely enough that we don't care (and\r\n\t// `exhausted` is a lower bound anyway).\r\n\tprivate choose() {\r\n\t\tif (!this.unused.size) this.reset();\r\n\r\n\t\tif (this.iter) {\r\n\t\t\tif (!this.iter.done) {\r\n\t\t\t\tconst next = this.iter.next();\r\n\t\t\t\tthis.iter.done = next.done;\r\n\t\t\t\tif (!next.done) return next.value;\r\n\t\t\t}\r\n\t\t\treturn this.fill();\r\n\t\t}\r\n\r\n\t\tthis.iter = this.unused.values();\r\n\t\tconst next = this.iter.next();\r\n\t\tthis.iter.done = next.done;\r\n\t\t// this.iter.next() must have a value (!this.iter.done) because this.unused.size > 0\r\n\t\t// after this.reset(), and the only places that mutate this.unused clear this.iter.\r\n\t\treturn next.value;\r\n\t}\r\n\r\n\tprivate fill() {\r\n\t\tlet length = this.filler!.length;\r\n\t\tif (!length) {\r\n\t\t\tthis.filler = this.possible.slice();\r\n\t\t\tlength = this.filler.length;\r\n\t\t}\r\n\t\tconst index = this.prng.next(length);\r\n\t\tconst element = this.filler![index];\r\n\t\tthis.filler![index] = this.filler![length - 1];\r\n\t\tthis.filler!.pop();\r\n\t\tthis.filled!.add(element);\r\n\t\treturn element;\r\n\t}\r\n}\r\n\r\n// Random AI which shares Pools with the TeamGenerator to coordinate creating battle simulations\r\n// that test out as many different Pokemon/Species/Items/Moves as possible. The logic is still\r\n// random, so it's not going to optimally use as many new effects as would be possible, but it\r\n// should exhaust its pools much faster than the naive RandomPlayerAI alone.\r\n//\r\n// NOTE: We're tracking 'usage' when we make the choice and not what actually gets used in Battle.\r\n// These can differ in edge cases and so its possible we report that we've 'used' every option\r\n// when we haven't (for example, we may switch in a Pokemon with an ability, but we're not\r\n// guaranteeing the ability activates, etc).\r\nclass CoordinatedPlayerAI extends RandomPlayerAI {\r\n\tprivate readonly pools: Pools;\r\n\r\n\tconstructor(playerStream: ObjectReadWriteStream, options: AIOptions, pools: Pools) {\r\n\t\tsuper(playerStream, options);\r\n\t\tthis.pools = pools;\r\n\t}\r\n\r\n\tprotected chooseTeamPreview(team: AnyObject[]): string {\r\n\t\treturn `team ${this.choosePokemon(team.map((p, i) => ({slot: i + 1, pokemon: p}))) || 1}`;\r\n\t}\r\n\r\n\tprotected chooseMove(active: AnyObject, moves: {choice: string, move: AnyObject}[]): string {\r\n\t\tthis.markUsedIfGmax(active);\r\n\t\t// Prefer to use a move which hasn't been used yet.\r\n\t\tfor (const {choice, move} of moves) {\r\n\t\t\tconst id = this.fixMove(move);\r\n\t\t\tif (!this.pools.moves.wasUsed(id)) {\r\n\t\t\t\tthis.pools.moves.markUsed(id);\r\n\t\t\t\treturn choice;\r\n\t\t\t}\r\n\t\t}\r\n\t\treturn super.chooseMove(active, moves);\r\n\t}\r\n\r\n\tprotected chooseSwitch(active: AnyObject | undefined, switches: {slot: number, pokemon: AnyObject}[]): number {\r\n\t\tthis.markUsedIfGmax(active);\r\n\t\treturn this.choosePokemon(switches) || super.chooseSwitch(active, switches);\r\n\t}\r\n\r\n\tprivate choosePokemon(choices: {slot: number, pokemon: AnyObject}[]) {\r\n\t\t// Prefer to choose a Pokemon that has a species/ability/item/move we haven't seen yet.\r\n\t\tfor (const {slot, pokemon} of choices) {\r\n\t\t\tconst species = toID(pokemon.details.split(',')[0]);\r\n\t\t\tif (!this.pools.pokemon.wasUsed(species) ||\r\n\t\t\t\t\t!this.pools.abilities.wasUsed(pokemon.baseAbility) ||\r\n\t\t\t\t\t!this.pools.items.wasUsed(pokemon.item) ||\r\n\t\t\t\t\tpokemon.moves.some((m: AnyObject) => !this.pools.moves.wasUsed(this.fixMove(m)))) {\r\n\t\t\t\tthis.pools.pokemon.markUsed(species);\r\n\t\t\t\tthis.pools.abilities.markUsed(pokemon.baseAbility);\r\n\t\t\t\tthis.pools.items.markUsed(pokemon.item);\r\n\t\t\t\treturn slot;\r\n\t\t\t}\r\n\t\t}\r\n\t}\r\n\r\n\t// The move options provided by the simulator have been converted from the name\r\n\t// which we're tracking, so we need to convert them back.\r\n\tprivate fixMove(m: AnyObject) {\r\n\t\tconst id = toID(m.move);\r\n\t\tif (id.startsWith('return')) return 'return';\r\n\t\tif (id.startsWith('frustration')) return 'frustration';\r\n\t\tif (id.startsWith('hiddenpower')) return 'hiddenpower';\r\n\t\treturn id;\r\n\t}\r\n\r\n\t// Gigantamax Pokemon need to be special cased for tracking because the current\r\n\t// tracking only works if you can switch in a Pokemon.\r\n\tprivate markUsedIfGmax(active: AnyObject | undefined) {\r\n\t\tif (active && !active.canDynamax && active.maxMoves && active.maxMoves.gigantamax) {\r\n\t\t\tthis.pools.pokemon.markUsed(toID(active.maxMoves.gigantamax));\r\n\t\t}\r\n\t}\r\n}\r\n"], "mappings": "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", "names": ["next"] }