Spaces:
Running
Running
File size: 4,703 Bytes
5c2ed06 |
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 24 25 26 27 28 29 30 31 32 33 34 35 36 37 38 39 40 41 42 43 44 45 46 47 48 49 50 51 52 53 54 55 56 57 58 59 60 61 62 63 64 65 66 67 68 69 70 71 72 73 74 75 76 77 78 79 80 81 82 83 84 85 86 87 88 89 90 91 92 93 94 95 96 97 98 99 100 101 102 103 104 105 106 107 108 109 110 111 112 113 114 115 116 117 118 119 120 121 122 123 124 125 126 127 128 129 130 131 132 133 134 135 136 137 138 139 140 141 142 143 144 145 146 147 148 149 150 151 152 153 154 155 156 157 158 |
'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(
`<!DOCTYPE html>\n` +
`<script type="text/plain" class="battle-log-data">${battleLog}</script>\n` +
`<script src="https://play.pokemonshowdown.com/js/replay-embed.js"></script>\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);
|