'use strict'; const path = require('path'); const fs = require('fs'); const assert = require('./assert'); const Sim = require('./../dist/sim'); const Dex = Sim.Dex; const cache = new Map(); const formatsCache = new Map(); function capitalize(word) { return word.charAt(0).toUpperCase() + word.slice(1); } /** * The default random number generator seed used if one is not given. */ const DEFAULT_SEED = 'gen5,99176924e1c86af0'; class TestTools { constructor(mod = 'base') { this.currentMod = mod; this.dex = Dex.mod(mod); this.modPrefix = this.dex.isBase ? `[gen9] ` : `[${mod}] `; } mod(mod) { if (cache.has(mod)) return cache.get(mod); if (typeof mod !== 'string') throw new Error("This only supports strings"); if (!Dex.dexes[mod]) throw new Error(`Mod ${mod} does not exist`); const moddedTestTools = new TestTools(mod); cache.set(mod, moddedTestTools); return moddedTestTools; } gen(genNum) { return this.mod('gen' + genNum); } getFormat(options) { if (options.formatid) { const format = Dex.formats.get(options.formatid); if (format.effectType !== 'Format') throw new Error(`Unidentified format: ${options.formatid}`); return format; } const gameType = Dex.toID(options.gameType || 'singles'); const customRules = [ options.pokemon && '-Nonexistent', options.legality && 'Obtainable', !options.preview && '!Team Preview', options.sleepClause && 'Sleep Clause Mod', !options.cancel && '!Cancel Mod', options.endlessBattleClause && 'Endless Battle Clause', options.inverseMod && 'Inverse Mod', options.overflowStatMod && 'Overflow Stat Mod', ].filter(Boolean); const customRulesID = customRules.length ? `@@@${customRules.join(',')}` : ``; let basicFormat = this.currentMod === 'base' && gameType === 'singles' ? 'Anything Goes' : 'Custom Game'; let modPrefix = this.modPrefix; if (this.currentMod === 'gen1stadium') basicFormat = 'OU'; if (gameType === 'multi') { basicFormat = 'randombattle'; modPrefix = `[gen8] `; // Remove when multis support Gen 9 } // Re-integrate to the above if statement when gen 9 ffa randbats is added if (gameType === 'freeforall') basicFormat = ''; const gameTypePrefix = gameType === 'singles' ? '' : capitalize(gameType) + ' '; const formatName = `${modPrefix}${gameTypePrefix}${basicFormat}${customRulesID}`; let format = formatsCache.get(formatName); if (format) return format; format = Dex.formats.get(formatName); if (format.effectType !== 'Format') throw new Error(`Unidentified format: ${formatName}`); formatsCache.set(formatName, format); return format; } /** * Creates a new Battle and returns it. * * @param {Object} [options] * @param {Team[]} [teams] * @returns {Sim.Battle} A battle. */ createBattle(options, teams) { if (Array.isArray(options)) { teams = options; options = {}; } if (!options) options = {}; const format = this.getFormat(options); const battleOptions = { debug: true, forceRandomChance: options.forceRandomChance, format, // If a seed for the pseudo-random number generator is not provided, // a default seed (guaranteed to be the same across test executions) // will be used. seed: options.seed === undefined ? DEFAULT_SEED : (options.seed || undefined), strictChoices: options.strictChoices !== false, }; if (!teams) return new Sim.Battle(battleOptions); for (let i = 0; i < teams.length; i++) { assert(Array.isArray(teams[i]), `Team provided is not an array`); const playerSlot = `p${i + 1}`; battleOptions[playerSlot] = { team: teams[i] }; } return new Sim.Battle(battleOptions); } /** * Saves the log of the given battle as a bare-bones replay file in the `test\replays` directory * You can view the replay by opening the file in any browser or by dragging and dropping the * file into a PS! client window. * * @param {Sim.Battle} battle * @param {string} [fileName] */ saveReplay(battle, fileName) { const battleLog = battle.getDebugLog(); if (!fileName) fileName = 'test-replay'; const filePath = path.resolve(__dirname, `./replays/${fileName}-${Date.now()}.html`); const out = fs.createWriteStream(filePath, { flags: 'a' }); out.on('open', () => { out.write( `\n` + `\n` + `\n` ); out.end(); }); } hasModule(mod) { try { require(mod); return true; } catch { return false; } } } const common = exports = module.exports = new TestTools(); cache.set('base', common); cache.set('gen9', common);