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