pokemon-showdown/test/common.js
Guangcong Luo 801af59b98 Fix remaining build errors
- Centiskorch was misspelled in formats-data, causing a crash in the
  egg validator

- A few validation errors were due to Gen 6 not inheriting from Gen 7,
  Gen 7 not having a scripts file, and Gen 8 having a gen of 7

- Intimidate (Gen 7) wasn't inheriting from Intimidate (Gen 8), giving
  it no name, causing a few validation errors

  (Technically not a build error, but I also added Keen Eye to the list
  of Intimidate immunities, as reported by SadisticMystic.)

- A lot of tests relied on Teleport always failing; these have been
  switched to Gen 7 or swapped Teleport for Celebrate

- Inverse Mod suddenly stopped working; its implementation was a huge
  hack and I can't figure out what went wrong, so I've switched it to
	using the same system the other mod tests use. It's still a huge
	hack, but I don't have the free time to fix it right now.
2019-11-16 06:08:48 +13:00

136 lines
3.9 KiB
JavaScript

'use strict';
const assert = require('assert');
const Dex = require('./../.sim-dist/dex').Dex;
const Sim = require('./../.sim-dist');
const cache = new Map();
const RULE_FLAGS = {
pokemon: 1,
legality: 2,
preview: 4,
sleepClause: 8,
cancel: 16,
endlessBattleClause: 32,
inverseMod: 64,
};
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 = [0x09917, 0x06924, 0x0e1c8, 0x06af0];
class TestTools {
constructor(options) {
if (!options) options = {};
const mod = options.mod || 'base';
this.baseFormat = options.baseFormat || {effectType: 'Format', mod: mod};
this.dex = Dex.mod(mod);
this.modPrefix = this.baseFormat.name ? `[${this.baseFormat.name}]` : '';
if (!this.modPrefix && !this.dex.isBase) {
this.modPrefix = (/^gen\d$/.test(mod) ? `[Gen ${this.dex.gen}]` : `[${mod}]`);
}
// Handle caches
this.formats = new Map([['singles', new Map()], ['doubles', new Map()], ['triples', new Map()]]);
cache.set(this.baseFormat.id || mod, this);
}
mod(mod) {
if (typeof mod !== 'string') throw new Error("This only supports strings");
if (cache.has(mod)) return cache.get(mod);
if (Dex.dexes[mod]) return new TestTools({mod: mod});
const baseFormat = Dex.getFormat(mod);
if (baseFormat.effectType === 'Format') return new TestTools({mod: baseFormat.mod, baseFormat});
throw new Error(`Mod ${mod} does not exist`);
}
gen(genNum) {
return this.mod('gen' + genNum);
}
getFormat(options) {
let mask = 0;
for (let property in options) {
if (property === 'gameType' || !options[property]) continue;
mask |= RULE_FLAGS[property];
}
const gameType = Dex.getId(options.gameType || 'singles');
if (this.formats.get(gameType).has(mask)) return this.formats.get(gameType).get(mask);
const gameTypePrefix = gameType === 'singles' ? '' : capitalize(gameType);
const formatName = [this.modPrefix, gameTypePrefix, "Custom Game", '' + mask].filter(part => part).join(" ");
const formatId = Dex.getId(formatName);
const format = Object.assign(Object.assign({}, this.baseFormat), {
id: formatId,
name: formatName,
mask: mask,
gameType: options.gameType || 'singles',
isCustomGameFormat: true,
rated: false,
});
if (!format.ruleset) format.ruleset = [];
if (!format.banlist) format.banlist = [];
if (options.pokemon) format.ruleset.push('-Nonexistent');
if (options.legality) format.ruleset.push('Obtainable');
if (options.preview) format.ruleset.push('Team Preview');
if (options.sleepClause) format.ruleset.push('Sleep Clause Mod');
if (options.cancel) format.ruleset.push('Cancel Mod');
if (options.endlessBattleClause) format.ruleset.push('Endless Battle Clause');
if (options.inverseMod) format.ruleset.push('Inverse Mod');
this.dex.installFormat(formatId, 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 = {
formatid: format.id,
// 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 || DEFAULT_SEED,
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);
}
}
const common = exports = module.exports = new TestTools();
cache.set('base', common);
cache.set('gen8', common);