{ "version": 3, "sources": ["../../../../sim/tools/random-player-ai.ts"], "sourcesContent": ["/**\r\n * Example random player AI.\r\n *\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 {BattlePlayer} from '../battle-stream';\r\nimport {PRNG, PRNGSeed} from '../prng';\r\n\r\nexport class RandomPlayerAI extends BattlePlayer {\r\n\tprotected readonly move: number;\r\n\tprotected readonly mega: number;\r\n\tprotected readonly prng: PRNG;\r\n\r\n\tconstructor(\r\n\t\tplayerStream: ObjectReadWriteStream,\r\n\t\toptions: {move?: number, mega?: number, seed?: PRNG | PRNGSeed | null } = {},\r\n\t\tdebug = false\r\n\t) {\r\n\t\tsuper(playerStream, debug);\r\n\t\tthis.move = options.move || 1.0;\r\n\t\tthis.mega = options.mega || 0;\r\n\t\tthis.prng = options.seed && !Array.isArray(options.seed) ? options.seed : new PRNG(options.seed);\r\n\t}\r\n\r\n\treceiveError(error: Error) {\r\n\t\t// If we made an unavailable choice we will receive a followup request to\r\n\t\t// allow us the opportunity to correct our decision.\r\n\t\tif (error.message.startsWith('[Unavailable choice]')) return;\r\n\t\tthrow error;\r\n\t}\r\n\r\n\treceiveRequest(request: AnyObject) {\r\n\t\tif (request.wait) {\r\n\t\t\t// wait request\r\n\t\t\t// do nothing\r\n\t\t} else if (request.forceSwitch) {\r\n\t\t\t// switch request\r\n\t\t\tconst pokemon = request.side.pokemon;\r\n\t\t\tconst chosen: number[] = [];\r\n\t\t\tconst choices = request.forceSwitch.map((mustSwitch: AnyObject, i: number) => {\r\n\t\t\t\tif (!mustSwitch) return `pass`;\r\n\r\n\t\t\t\tconst canSwitch = range(1, 6).filter(j => (\r\n\t\t\t\t\tpokemon[j - 1] &&\r\n\t\t\t\t\t// not active\r\n\t\t\t\t\tj > request.forceSwitch.length &&\r\n\t\t\t\t\t// not chosen for a simultaneous switch\r\n\t\t\t\t\t!chosen.includes(j) &&\r\n\t\t\t\t\t// not fainted or fainted and using Revival Blessing\r\n\t\t\t\t\t!!(+!!pokemon[i].reviving ^ +!pokemon[j - 1].condition.endsWith(` fnt`))\r\n\t\t\t\t));\r\n\r\n\t\t\t\tif (!canSwitch.length) return `pass`;\r\n\t\t\t\tconst target = this.chooseSwitch(\r\n\t\t\t\t\trequest.active,\r\n\t\t\t\t\tcanSwitch.map(slot => ({slot, pokemon: pokemon[slot - 1]}))\r\n\t\t\t\t);\r\n\t\t\t\tchosen.push(target);\r\n\t\t\t\treturn `switch ${target}`;\r\n\t\t\t});\r\n\r\n\t\t\tthis.choose(choices.join(`, `));\r\n\t\t} else if (request.active) {\r\n\t\t\t// move request\r\n\t\t\tlet [canMegaEvo, canUltraBurst, canZMove, canDynamax, canTerastallize] = [true, true, true, true, true];\r\n\t\t\tconst pokemon = request.side.pokemon;\r\n\t\t\tconst chosen: number[] = [];\r\n\t\t\tconst choices = request.active.map((active: AnyObject, i: number) => {\r\n\t\t\t\tif (pokemon[i].condition.endsWith(` fnt`) || pokemon[i].commanding) return `pass`;\r\n\r\n\t\t\t\tcanMegaEvo = canMegaEvo && active.canMegaEvo;\r\n\t\t\t\tcanUltraBurst = canUltraBurst && active.canUltraBurst;\r\n\t\t\t\tcanZMove = canZMove && !!active.canZMove;\r\n\t\t\t\tcanDynamax = canDynamax && !!active.canDynamax;\r\n\t\t\t\tcanTerastallize = canTerastallize && !!active.canTerastallize;\r\n\r\n\t\t\t\t// Determine whether we should change form if we do end up switching\r\n\t\t\t\tconst change = (canMegaEvo || canUltraBurst || canDynamax) && this.prng.next() < this.mega;\r\n\t\t\t\t// If we've already dynamaxed or if we're planning on potentially dynamaxing\r\n\t\t\t\t// we need to use the maxMoves instead of our regular moves\r\n\r\n\t\t\t\tconst useMaxMoves = (!active.canDynamax && active.maxMoves) || (change && canDynamax);\r\n\t\t\t\tconst possibleMoves = useMaxMoves ? active.maxMoves.maxMoves : active.moves;\r\n\r\n\t\t\t\tlet canMove = range(1, possibleMoves.length).filter(j => (\r\n\t\t\t\t\t// not disabled\r\n\t\t\t\t\t!possibleMoves[j - 1].disabled\r\n\t\t\t\t\t// NOTE: we don't actually check for whether we have PP or not because the\r\n\t\t\t\t\t// simulator will mark the move as disabled if there is zero PP and there are\r\n\t\t\t\t\t// situations where we actually need to use a move with 0 PP (Gen 1 Wrap).\r\n\t\t\t\t)).map(j => ({\r\n\t\t\t\t\tslot: j,\r\n\t\t\t\t\tmove: possibleMoves[j - 1].move,\r\n\t\t\t\t\ttarget: possibleMoves[j - 1].target,\r\n\t\t\t\t\tzMove: false,\r\n\t\t\t\t}));\r\n\t\t\t\tif (canZMove) {\r\n\t\t\t\t\tcanMove.push(...range(1, active.canZMove.length)\r\n\t\t\t\t\t\t.filter(j => active.canZMove[j - 1])\r\n\t\t\t\t\t\t.map(j => ({\r\n\t\t\t\t\t\t\tslot: j,\r\n\t\t\t\t\t\t\tmove: active.canZMove[j - 1].move,\r\n\t\t\t\t\t\t\ttarget: active.canZMove[j - 1].target,\r\n\t\t\t\t\t\t\tzMove: true,\r\n\t\t\t\t\t\t})));\r\n\t\t\t\t}\r\n\r\n\t\t\t\t// Filter out adjacentAlly moves if we have no allies left, unless they're our\r\n\t\t\t\t// only possible move options.\r\n\t\t\t\tconst hasAlly = pokemon.length > 1 && !pokemon[i ^ 1].condition.endsWith(` fnt`);\r\n\t\t\t\tconst filtered = canMove.filter(m => m.target !== `adjacentAlly` || hasAlly);\r\n\t\t\t\tcanMove = filtered.length ? filtered : canMove;\r\n\r\n\t\t\t\tconst moves = canMove.map(m => {\r\n\t\t\t\t\tlet move = `move ${m.slot}`;\r\n\t\t\t\t\t// NOTE: We don't generate all possible targeting combinations.\r\n\t\t\t\t\tif (request.active.length > 1) {\r\n\t\t\t\t\t\tif ([`normal`, `any`, `adjacentFoe`].includes(m.target)) {\r\n\t\t\t\t\t\t\tmove += ` ${1 + Math.floor(this.prng.next() * 2)}`;\r\n\t\t\t\t\t\t}\r\n\t\t\t\t\t\tif (m.target === `adjacentAlly`) {\r\n\t\t\t\t\t\t\tmove += ` -${(i ^ 1) + 1}`;\r\n\t\t\t\t\t\t}\r\n\t\t\t\t\t\tif (m.target === `adjacentAllyOrSelf`) {\r\n\t\t\t\t\t\t\tif (hasAlly) {\r\n\t\t\t\t\t\t\t\tmove += ` -${1 + Math.floor(this.prng.next() * 2)}`;\r\n\t\t\t\t\t\t\t} else {\r\n\t\t\t\t\t\t\t\tmove += ` -${i + 1}`;\r\n\t\t\t\t\t\t\t}\r\n\t\t\t\t\t\t}\r\n\t\t\t\t\t}\r\n\t\t\t\t\tif (m.zMove) move += ` zmove`;\r\n\t\t\t\t\treturn {choice: move, move: m};\r\n\t\t\t\t});\r\n\r\n\t\t\t\tconst canSwitch = range(1, 6).filter(j => (\r\n\t\t\t\t\tpokemon[j - 1] &&\r\n\t\t\t\t\t// not active\r\n\t\t\t\t\t!pokemon[j - 1].active &&\r\n\t\t\t\t\t// not chosen for a simultaneous switch\r\n\t\t\t\t\t!chosen.includes(j) &&\r\n\t\t\t\t\t// not fainted\r\n\t\t\t\t\t!pokemon[j - 1].condition.endsWith(` fnt`)\r\n\t\t\t\t));\r\n\t\t\t\tconst switches = active.trapped ? [] : canSwitch;\r\n\r\n\t\t\t\tif (switches.length && (!moves.length || this.prng.next() > this.move)) {\r\n\t\t\t\t\tconst target = this.chooseSwitch(\r\n\t\t\t\t\t\tactive,\r\n\t\t\t\t\t\tcanSwitch.map(slot => ({slot, pokemon: pokemon[slot - 1]}))\r\n\t\t\t\t\t);\r\n\t\t\t\t\tchosen.push(target);\r\n\t\t\t\t\treturn `switch ${target}`;\r\n\t\t\t\t} else if (moves.length) {\r\n\t\t\t\t\tconst move = this.chooseMove(active, moves);\r\n\t\t\t\t\tif (move.endsWith(` zmove`)) {\r\n\t\t\t\t\t\tcanZMove = false;\r\n\t\t\t\t\t\treturn move;\r\n\t\t\t\t\t} else if (change) {\r\n\t\t\t\t\t\tif (canTerastallize) {\r\n\t\t\t\t\t\t\tcanTerastallize = false;\r\n\t\t\t\t\t\t\treturn `${move} terastallize`;\r\n\t\t\t\t\t\t} else if (canDynamax) {\r\n\t\t\t\t\t\t\tcanDynamax = false;\r\n\t\t\t\t\t\t\treturn `${move} dynamax`;\r\n\t\t\t\t\t\t} else if (canMegaEvo) {\r\n\t\t\t\t\t\t\tcanMegaEvo = false;\r\n\t\t\t\t\t\t\treturn `${move} mega`;\r\n\t\t\t\t\t\t} else {\r\n\t\t\t\t\t\t\tcanUltraBurst = false;\r\n\t\t\t\t\t\t\treturn `${move} ultra`;\r\n\t\t\t\t\t\t}\r\n\t\t\t\t\t} else {\r\n\t\t\t\t\t\treturn move;\r\n\t\t\t\t\t}\r\n\t\t\t\t} else {\r\n\t\t\t\t\tthrow new Error(`${this.constructor.name} unable to make choice ${i}. request='${request}',` +\r\n\t\t\t\t\t\t` chosen='${chosen}', (mega=${canMegaEvo}, ultra=${canUltraBurst}, zmove=${canZMove},` +\r\n\t\t\t\t\t\t` dynamax='${canDynamax}', terastallize=${canTerastallize})`);\r\n\t\t\t\t}\r\n\t\t\t});\r\n\t\t\tthis.choose(choices.join(`, `));\r\n\t\t} else {\r\n\t\t\t// team preview?\r\n\t\t\tthis.choose(this.chooseTeamPreview(request.side.pokemon));\r\n\t\t}\r\n\t}\r\n\r\n\tprotected chooseTeamPreview(team: AnyObject[]): string {\r\n\t\treturn `default`;\r\n\t}\r\n\r\n\tprotected chooseMove(active: AnyObject, moves: {choice: string, move: AnyObject}[]): string {\r\n\t\treturn this.prng.sample(moves).choice;\r\n\t}\r\n\r\n\tprotected chooseSwitch(active: AnyObject | undefined, switches: {slot: number, pokemon: AnyObject}[]): number {\r\n\t\treturn this.prng.sample(switches).slot;\r\n\t}\r\n}\r\n\r\n// Creates an array of numbers progressing from start up to and including end\r\nfunction range(start: number, end?: number, step = 1) {\r\n\tif (end === undefined) {\r\n\t\tend = start;\r\n\t\tstart = 0;\r\n\t}\r\n\tconst result = [];\r\n\tfor (; start <= end; start += step) {\r\n\t\tresult.push(start);\r\n\t}\r\n\treturn result;\r\n}\r\n"], "mappings": "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", "names": [] }