From 5345fe9f07ca4f2950562e0e65a664261a5935e4 Mon Sep 17 00:00:00 2001 From: livid washed <115855253+livid-washed@users.noreply.github.com> Date: Fri, 28 Jun 2024 14:32:21 +1000 Subject: [PATCH] Improve and simplify Random Battles tests (#10366) --- data/random-battles/gen3/sets.json | 9 +- data/random-battles/gen9baby/sets.json | 13 +- test/random-battles/all-gens.js | 154 ++++++++++++++++++----- test/random-battles/gen2.js | 92 -------------- test/random-battles/gen3.js | 86 ------------- test/random-battles/gen4.js | 111 ---------------- test/random-battles/gen5.js | 106 +--------------- test/random-battles/gen6.js | 124 +----------------- test/random-battles/gen7.js | 152 +--------------------- test/random-battles/gen9.js | 167 ------------------------- 10 files changed, 138 insertions(+), 876 deletions(-) delete mode 100644 test/random-battles/gen2.js delete mode 100644 test/random-battles/gen3.js delete mode 100644 test/random-battles/gen4.js diff --git a/data/random-battles/gen3/sets.json b/data/random-battles/gen3/sets.json index 9bda7d118982..5a009282a9a1 100644 --- a/data/random-battles/gen3/sets.json +++ b/data/random-battles/gen3/sets.json @@ -1156,12 +1156,12 @@ "sets": [ { "role": "Bulky Attacker", - "movepool": ["encore", "hiddenpowergrass", "hypnosis", "icebeam", "rest", "surf", "toxic"], + "movepool": ["hiddenpowergrass", "hypnosis", "icebeam", "rest", "surf", "toxic"], "preferredTypes": ["Ice"] }, { "role": "Staller", - "movepool": ["encore", "icebeam", "protect", "surf", "toxic"] + "movepool": ["icebeam", "protect", "surf", "toxic"] }, { "role": "Bulky Support", @@ -2687,11 +2687,6 @@ "movepool": ["dragondance", "earthquake", "hiddenpowerflying", "overheat", "rockslide"], "preferredTypes": ["Ground"] }, - { - "role": "Bulky Setup", - "movepool": ["earthquake", "extremespeed", "hiddenpowerflying", "rockslide", "swordsdance"], - "preferredTypes": ["Ground"] - }, { "role": "Wallbreaker", "movepool": ["earthquake", "extremespeed", "hiddenpowerflying", "overheat", "rockslide"], diff --git a/data/random-battles/gen9baby/sets.json b/data/random-battles/gen9baby/sets.json index 18244141cff0..aa0bdf25a9cb 100644 --- a/data/random-battles/gen9baby/sets.json +++ b/data/random-battles/gen9baby/sets.json @@ -229,7 +229,7 @@ }, { "role": "Fast Support", - "movepool": ["Leaf Storm", "Giga Drain", "Stomping Tantrum", "Super Fang", "Thief"], + "movepool": ["Giga Drain", "Leaf Storm", "Stomping Tantrum", "Super Fang", "Thief"], "teraTypes": ["Poison", "Water"] } ] @@ -436,11 +436,6 @@ "role": "Bulky Setup", "movepool": ["Bulk Up", "Drain Punch", "Earthquake", "Gunk Shot", "Knock Off", "Sucker Punch"], "teraTypes": ["Dark", "Fighting", "Ground"] - }, - { - "role": "Fast Attacker", - "movepool": ["Close Combat", "Earthquake", "Gunk Shot", "Knock Off", "Swords Dance"], - "teraTypes": ["Dark"] } ] }, @@ -1004,7 +999,7 @@ "sets": [ { "role": "Bulky Attacker", - "movepool": ["Dynamic Punch", "Earthquake", "Poltergeist", "Stealth Rock", "Stone Edge"], + "movepool": ["Dynamic Punch", "Earthquake", "Poltergeist", "Rock Tomb", "Stealth Rock"], "teraTypes": ["Fighting"] } ] @@ -1534,7 +1529,7 @@ }, { "role": "Bulky Support", - "movepool": ["Iron Head", "Knock Off", "Play Rough", "Stealth Rock", "Thunder Wave", "U-turn"], + "movepool": ["Iron Head", "Knock Off", "Play Rough", "Stealth Rock", "U-turn"], "teraTypes": ["Fairy", "Water"] } ] @@ -1549,7 +1544,7 @@ }, { "role": "Fast Support", - "movepool": ["High Jump Kick", "Fake Out", "Knock Off", "U-turn"], + "movepool": ["Fake Out", "High Jump Kick", "Knock Off", "U-turn"], "teraTypes": ["Dark", "Steel"] }, { diff --git a/test/random-battles/all-gens.js b/test/random-battles/all-gens.js index 6d053026e4b0..5286ef42ad17 100644 --- a/test/random-battles/all-gens.js +++ b/test/random-battles/all-gens.js @@ -113,44 +113,142 @@ describe('value rule support (slow)', () => { } }); -describe("New set format", () => { - const files = ['../../data/random-battles/gen9/sets.json', '../../data/random-battles/gen9/doubles-sets.json']; - for (const filename of files) { - it(`${filename} should have valid set data`, () => { - const setsJSON = require(filename); - let validRoles = []; - if (filename === '../../data/random-battles/gen9/sets.json') { - validRoles = ["Fast Attacker", "Setup Sweeper", "Wallbreaker", "Tera Blast user", - "Bulky Attacker", "Bulky Setup", "Fast Bulky Setup", "Bulky Support", "Fast Support", "AV Pivot"]; - } else { - validRoles = ["Doubles Fast Attacker", "Doubles Setup Sweeper", "Doubles Wallbreaker", "Tera Blast user", - "Doubles Bulky Attacker", "Doubles Bulky Setup", "Offensive Protect", "Bulky Protect", "Doubles Support", "Choice Item user"]; - } +describe("New set format (slow)", () => { + // formatInfo lists filenames and roles for each format + const formatInfo = { + "gen2randombattle": { + filename: "gen2/sets", + roles: ["Fast Attacker", "Setup Sweeper", "Bulky Attacker", "Bulky Setup", "Bulky Support", "Generalist", "Thief user"], + }, + "gen3randombattle": { + filename: "gen3/sets", + roles: ["Fast Attacker", "Setup Sweeper", "Wallbreaker", "Bulky Attacker", "Bulky Setup", "Staller", "Bulky Support", "Generalist", "Berry Sweeper"], + }, + "gen4randombattle": { + filename: "gen4/sets", + roles: ["Fast Attacker", "Setup Sweeper", "Wallbreaker", "Bulky Attacker", "Bulky Setup", "Staller", "Bulky Support", "Fast Support", "Spinner"], + }, + "gen5randombattle": { + filename: "gen5/sets", + roles: ["Fast Attacker", "Setup Sweeper", "Wallbreaker", "Bulky Attacker", "Bulky Setup", "Staller", "Bulky Support", "Fast Support", "Spinner"], + }, + "gen6randombattle": { + filename: "gen6/sets", + roles: ["Fast Attacker", "Setup Sweeper", "Wallbreaker", "Bulky Attacker", "Bulky Setup", "Staller", "Bulky Support", "Fast Support", "AV Pivot"], + }, + "gen7randombattle": { + filename: "gen7/sets", + roles: ["Fast Attacker", "Setup Sweeper", "Wallbreaker", "Z-Move user", "Bulky Attacker", "Bulky Setup", "Staller", "Bulky Support", "Fast Support", "AV Pivot"], + }, + "gen9randombattle": { + filename: "gen9/sets", + roles: ["Fast Attacker", "Setup Sweeper", "Wallbreaker", "Tera Blast user", "Bulky Attacker", "Bulky Setup", "Fast Bulky Setup", "Bulky Support", "Fast Support", "AV Pivot"], + }, + "gen9randomdoublesbattle": { + filename: "gen9/doubles-sets", + roles: ["Doubles Fast Attacker", "Doubles Setup Sweeper", "Doubles Wallbreaker", "Tera Blast user", "Doubles Bulky Attacker", "Doubles Bulky Setup", "Offensive Protect", "Bulky Protect", "Doubles Support", "Choice Item user"], + }, + "gen9babyrandombattle": { + filename: "gen9baby/sets", + roles: ["Fast Attacker", "Setup Sweeper", "Wallbreaker", "Tera Blast user", "Bulky Attacker", "Bulky Setup", "Bulky Support", "Fast Support"], + }, + }; + for (const format of Object.keys(formatInfo)) { + const filename = formatInfo[format].filename; + const setsJSON = require(`../../dist/data/random-battles/${filename}.json`); + const mod = filename.split('/')[0]; + const genNum = parseInt(mod[3]); + const rounds = 100; + const dex = Dex.forFormat(format); + it(`${filename}.json should have valid set data`, () => { + const validRoles = formatInfo[format].roles; for (const [id, sets] of Object.entries(setsJSON)) { const species = Dex.species.get(id); - assert(species.exists, `Misspelled species ID: ${id}`); + assert(species.exists, `In ${format}, misspelled species ID: ${id}`); assert(Array.isArray(sets.sets)); for (const set of sets.sets) { - assert(validRoles.includes(set.role), `Set for ${species.name} has invalid role: ${set.role}`); - assert.equal(set.role === "Tera Blast user", set.movepool.includes("Tera Blast"), - `Set for ${species.name} has inconsistent Tera Blast user status`); + assert(validRoles.includes(set.role), `In ${format}, set for ${species.name} has invalid role: ${set.role}`); for (const move of set.movepool) { const dexMove = Dex.moves.get(move); - assert(dexMove.exists, `${species.name} has invalid move: ${move}`); - assert.equal(move, dexMove.name, `${species.name} has misformatted move: ${move}`); - assert(validateLearnset(dexMove, {species}, 'anythinggoes', 'gen9'), `${species.name} can't learn ${move}`); + assert(dexMove.exists, `In ${format}, ${species.name} has invalid move: ${move}`); + // Old gens have moves in id form, currently. + if (genNum === 9) { + assert.equal(move, dexMove.name, `In ${format}, ${species.name} has misformatted move: ${move}`); + } else { + assert(move === dexMove.id || move.startsWith('hiddenpower'), `In ${format}, ${species.name} has misformatted move: ${move}`); + } + assert(validateLearnset(dexMove, {species}, 'ubers', `gen${genNum}`), `In ${format}, ${species.name} can't learn ${move}`); } for (let i = 0; i < set.movepool.length - 1; i++) { - assert(set.movepool[i + 1] > set.movepool[i], `${species} movepool should be sorted alphabetically`); + assert(set.movepool[i + 1] > set.movepool[i], `In ${format}, ${species.name} movepool should be sorted alphabetically`); + } + if (set.teraTypes) { + for (const type of set.teraTypes) { + const dexType = Dex.types.get(type); + assert(dexType.exists, `In ${format}, ${species.name} has invalid Tera Type: ${type}`); + assert.equal(type, dexType.name, `In ${format}, ${species.name} has misformatted Tera Type: ${type}`); + } + for (let i = 0; i < set.teraTypes.length - 1; i++) { + assert(set.teraTypes[i + 1] > set.teraTypes[i], `In ${format}, ${species.name} teraTypes should be sorted alphabetically`); + } } - for (const type of set.teraTypes) { - const dexType = Dex.types.get(type); - assert(dexType.exists, `${species.name} has invalid Tera Type: ${type}`); - assert.equal(type, dexType.name, `${species.name} has misformatted Tera Type: ${type}`); + if (set.preferredTypes) { + for (const type of set.preferredTypes) { + const dexType = Dex.types.get(type); + assert(dexType.exists, `In ${format}, ${species.name} has invalid Preferred Type: ${type}`); + assert.equal(type, dexType.name, `In ${format}, ${species.name} has misformatted Preferred Type: ${type}`); + } + for (let i = 0; i < set.preferredTypes.length - 1; i++) { + assert(set.preferredTypes[i + 1] > set.preferredTypes[i], `In ${format}, ${species.name} preferredTypes should be sorted alphabetically`); + } } - for (let i = 0; i < set.teraTypes.length - 1; i++) { - assert(set.teraTypes[i + 1] > set.teraTypes[i], `${species} teraTypes should be sorted alphabetically`); + } + } + }); + it('all Pokemon should have 4 moves, except for Ditto and Unown', function () { + testTeam({format, rounds}, team => { + for (const pokemon of team) assert(pokemon.name === 'Ditto' || pokemon.name === 'Unown' || pokemon.moves.length === 4, `In ${format}, ${pokemon.name} can generate with ${pokemon.moves.length} moves`); + }); + }); + it('all moves on all sets should exist and be obtainable', function () { + const generator = Teams.getGenerator(format); + for (const pokemon of Object.keys(setsJSON)) { + const species = dex.species.get(pokemon); + assert(species.exists, `In ${format}, Pokemon ${species} does not exist`); + const sets = setsJSON[pokemon]["sets"]; + const types = species.types; + const abilities = new Set(Object.values(species.abilities)); + if (species.unreleasedHidden) abilities.delete(species.abilities.H); + for (const set of sets) { + assert(set.movepool.every(m => dex.moves.get(m).exists), `In ${format}, for Pokemon ${species}, one of ${set.movepool} does not exist.`); + const role = set.role; + const moves = new Set(set.movepool.map(m => (m.startsWith('hiddenpower') ? m : dex.moves.get(m).id))); + const specialTypes = genNum === 9 ? set.teraTypes : set.preferredTypes; + // Go through all possible teamDetails combinations, if necessary + for (let j = 0; j < rounds; j++) { + // In Gens 2-3, if a set has multiple preferred types, we enforce moves of all the types. + const specialType = specialTypes ? (genNum > 3 ? specialTypes[j % specialTypes.length] : specialTypes.join()) : ''; + // Generate a moveset for each combination of relevant teamDetails. Spikes is relevant for Gen 2. + for (let i = 0; i < 16; i++) { + const rapidSpin = i % 2; + const stealthRock = Math.floor(i / 2) % 2; + const stickyWeb = Math.floor(i / 4) % 2; + const spikes = Math.floor(i / 8) % 2; + const teamDetails = {rapidSpin, stealthRock, stickyWeb, spikes}; + // randomMoveset() deletes moves from the movepool, so recreate it every time + const movePool = set.movepool.map(m => (m.startsWith('hiddenpower') ? m : dex.moves.get(m).id)); + let moveSet; + if (genNum === 9) { + moveSet = generator.randomMoveset(types, abilities, teamDetails, species, false, format.includes('doubles'), movePool, specialType, role); + } else { + moveSet = generator.randomMoveset(types, abilities, teamDetails, species, false, movePool, specialType, role); + } + for (const move of moveSet) moves.delete(move); + if (!moves.size) break; + } + if (!moves.size) break; } + assert.false(moves.size, `In ${format}, the following moves on ${species.name} are unused: ${[...moves].join(', ')}`); } } }); @@ -183,7 +281,7 @@ describe('Battle Factory and BSS Factory data should be valid (slow)', () => { this.timeout(0); const setsJSON = require(`../../dist/data/random-battles/${filename}.json`); const mod = filename.split('/')[0] || 'gen' + Dex.gen; - const genNum = isNaN(mod[3]) ? Dex.gen : mod[3]; + const genNum = isNaN(mod[3]) ? Dex.gen : parseInt(mod[3]); for (const type in setsJSON) { const typeTable = filename.includes('bss-factory-sets') ? setsJSON : setsJSON[type]; diff --git a/test/random-battles/gen2.js b/test/random-battles/gen2.js deleted file mode 100644 index e52a895a460f..000000000000 --- a/test/random-battles/gen2.js +++ /dev/null @@ -1,92 +0,0 @@ -/** - * Tests for Gen 2 randomized formats - */ -'use strict'; - -const assert = require('../assert'); -const {testTeam, validateLearnset} = require('./tools'); - -describe('[Gen 2] Random Battle (slow)', () => { - const options = {format: 'gen2randombattle'}; - const setsJSON = require(`../../dist/data/random-battles/gen2/sets.json`); - const dex = Dex.forFormat(options.format); - - describe("New set format", () => { - const filename = '../../data/random-battles/gen2/sets.json'; - it(`${filename} should have valid set data`, () => { - const setsJSON = require(filename); - const validRoles = [ - "Fast Attacker", "Setup Sweeper", "Bulky Attacker", "Bulky Setup", "Bulky Support", "Generalist", "Thief user", - ]; - for (const [id, sets] of Object.entries(setsJSON)) { - const species = Dex.species.get(id); - assert(species.exists, `Misspelled species ID: ${id}`); - assert(Array.isArray(sets.sets)); - for (const set of sets.sets) { - assert(validRoles.includes(set.role), `Set for ${species.name} has invalid role: ${set.role}`); - for (const move of set.movepool) { - const dexMove = Dex.moves.get(move); - assert(dexMove.exists, `${species.name} has invalid move: ${move}`); - assert(move === dexMove.id || move.startsWith('hiddenpower'), `${species.name} has misformatted move: ${move}`); - assert(validateLearnset(dexMove, {species}, 'ubers', 'gen2'), `${species.name} can't learn ${move}`); - } - for (let i = 0; i < set.movepool.length - 1; i++) { - assert(set.movepool[i + 1] > set.movepool[i], `${species} movepool should be sorted alphabetically`); - } - if (set.preferredTypes) { - for (const type of set.preferredTypes) { - const dexType = Dex.types.get(type); - assert(dexType.exists, `${species.name} has invalid Preferred Type: ${type}`); - assert.equal(type, dexType.name, `${species.name} has misformatted Preferred Type: ${type}`); - } - for (let i = 0; i < set.preferredTypes.length - 1; i++) { - assert(set.preferredTypes[i + 1] > set.preferredTypes[i], `${species} preferredTypes should be sorted alphabetically`); - } - } - } - } - }); - }); - - it('all Pokemon should have 4 moves, except for Ditto and Unown', function () { - // This test takes more than 2000ms - testTeam({...options, rounds: 100}, team => { - for (const pokemon of team) assert(pokemon.name === 'Ditto' || pokemon.name === 'Unown' || pokemon.moves.length === 4); - }); - }); - - it('all moves on all sets should be obtainable', function () { - const generator = Teams.getGenerator(options.format); - const rounds = 100; - for (const pokemon of Object.keys(setsJSON)) { - const species = dex.species.get(pokemon); - const sets = setsJSON[pokemon]["sets"]; - const types = species.types; - const abilities = new Set(Object.values(species.abilities)); - if (species.unreleasedHidden) abilities.delete(species.abilities.H); - for (const set of sets) { - const role = set.role; - const moves = new Set(Array.from(set.movepool)); - const preferredTypes = set.preferredTypes; - let teamDetails = {}; - // Go through all possible teamDetails combinations, if necessary - for (let j = 0; j < rounds; j++) { - const preferredType = preferredTypes ? preferredTypes[j % preferredTypes.length] : ''; - // Generate a moveset for each combination of relevant teamDetails - for (let i = 0; i < 4; i++) { - const rapidSpin = i % 2; - const spikes = Math.floor(i / 2) % 2; - teamDetails = {rapidSpin, spikes}; - // randomMoveset() deletes moves from the movepool, so recreate it every time - const movePool = Array.from(set.movepool); - const moveSet = generator.randomMoveset(types, abilities, teamDetails, species, false, movePool, preferredType, role); - for (const move of moveSet) moves.delete(move); - if (!moves.size) break; - } - if (!moves.size) break; - } - assert(!moves.size, species); - } - } - }); -}); diff --git a/test/random-battles/gen3.js b/test/random-battles/gen3.js deleted file mode 100644 index 9d5709340cd5..000000000000 --- a/test/random-battles/gen3.js +++ /dev/null @@ -1,86 +0,0 @@ -/** - * Tests for Gen 3 randomized formats - */ -'use strict'; - -const assert = require('../assert'); -const {testTeam, validateLearnset} = require('./tools'); - -describe('[Gen 3] Random Battle (slow)', () => { - const options = {format: 'gen3randombattle'}; - const setsJSON = require(`../../dist/data/random-battles/gen3/sets.json`); - const dex = Dex.forFormat(options.format); - - describe("New set format", () => { - const filename = '../../data/random-battles/gen3/sets.json'; - it(`${filename} should have valid set data`, () => { - const setsJSON = require(filename); - const validRoles = [ - "Fast Attacker", "Setup Sweeper", "Wallbreaker", "Bulky Attacker", - "Bulky Setup", "Staller", "Bulky Support", "Generalist", "Berry Sweeper", - ]; - for (const [id, sets] of Object.entries(setsJSON)) { - const species = Dex.species.get(id); - assert(species.exists, `Misspelled species ID: ${id}`); - assert(Array.isArray(sets.sets)); - for (const set of sets.sets) { - assert(validRoles.includes(set.role), `Set for ${species.name} has invalid role: ${set.role}`); - for (const move of set.movepool) { - const dexMove = Dex.moves.get(move); - assert(dexMove.exists, `${species.name} has invalid move: ${move}`); - assert(move === dexMove.id || move.startsWith('hiddenpower'), `${species.name} has misformatted move: ${move}`); - assert(validateLearnset(dexMove, {species}, 'anythinggoes', 'gen3'), `${species.name} can't learn ${move}`); - } - for (let i = 0; i < set.movepool.length - 1; i++) { - assert(set.movepool[i + 1] > set.movepool[i], `${species} movepool should be sorted alphabetically`); - } - if (set.preferredTypes) { - for (const type of set.preferredTypes) { - const dexType = Dex.types.get(type); - assert(dexType.exists, `${species.name} has invalid Preferred Type: ${type}`); - assert.equal(type, dexType.name, `${species.name} has misformatted Preferred Type: ${type}`); - } - for (let i = 0; i < set.preferredTypes.length - 1; i++) { - assert(set.preferredTypes[i + 1] > set.preferredTypes[i], `${species} preferredTypes should be sorted alphabetically`); - } - } - } - } - }); - }); - - it('all Pokemon should have 4 moves, except for Ditto and Unown', function () { - // This test takes more than 2000ms - testTeam({...options, rounds: 100}, team => { - for (const pokemon of team) assert(pokemon.name === 'Ditto' || pokemon.name === 'Unown' || pokemon.moves.length === 4); - }); - }); - - it('all moves on all sets should be obtainable', function () { - const generator = Teams.getGenerator(options.format); - const rounds = 100; - for (const pokemon of Object.keys(setsJSON)) { - const species = dex.species.get(pokemon); - const sets = setsJSON[pokemon]["sets"]; - const types = species.types; - const abilities = new Set(Object.values(species.abilities)); - if (species.unreleasedHidden) abilities.delete(species.abilities.H); - for (const set of sets) { - const role = set.role; - const moves = new Set(Array.from(set.movepool)); - const preferredTypes = set.preferredTypes; - // Go through all possible teamDetails combinations, if necessary - for (let j = 0; j < rounds; j++) { - // Generate a moveset - // randomMoveset() deletes moves from the movepool, so recreate it every time - const preferredType = preferredTypes ? preferredTypes.join() : ''; - const movePool = Array.from(set.movepool); - const moveSet = generator.randomMoveset(types, abilities, {}, species, false, movePool, preferredType, role); - for (const move of moveSet) moves.delete(move); - if (!moves.size) break; - } - assert(!moves.size, species); - } - } - }); -}); diff --git a/test/random-battles/gen4.js b/test/random-battles/gen4.js deleted file mode 100644 index 3cdbd444bc13..000000000000 --- a/test/random-battles/gen4.js +++ /dev/null @@ -1,111 +0,0 @@ -/** - * Tests for Gen 4 randomized formats - */ -'use strict'; - -const assert = require('../assert'); -const {testTeam, testSet, testHiddenPower, validateLearnset} = require('./tools'); - -describe('[Gen 4] Random Battle (slow)', () => { - const options = {format: 'gen4randombattle'}; - const setsJSON = require(`../../dist/data/random-battles/gen4/sets.json`); - const dex = Dex.forFormat(options.format); - - describe("New set format", () => { - const filename = '../../data/random-battles/gen4/sets.json'; - it(`${filename} should have valid set data`, () => { - const setsJSON = require(filename); - const validRoles = [ - "Fast Attacker", "Setup Sweeper", "Wallbreaker", "Bulky Attacker", - "Bulky Setup", "Staller", "Bulky Support", "Fast Support", "Spinner", - ]; - for (const [id, sets] of Object.entries(setsJSON)) { - const species = Dex.species.get(id); - assert(species.exists, `Misspelled species ID: ${id}`); - assert(Array.isArray(sets.sets)); - for (const set of sets.sets) { - assert(validRoles.includes(set.role), `Set for ${species.name} has invalid role: ${set.role}`); - for (const move of set.movepool) { - const dexMove = Dex.moves.get(move); - assert(dexMove.exists, `${species.name} has invalid move: ${move}`); - assert(move === dexMove.id || move.startsWith('hiddenpower'), `${species.name} has misformatted move: ${move}`); - assert(validateLearnset(dexMove, {species}, 'anythinggoes', 'gen4'), `${species.name} can't learn ${move}`); - } - for (let i = 0; i < set.movepool.length - 1; i++) { - assert(set.movepool[i + 1] > set.movepool[i], `${species} movepool should be sorted alphabetically`); - } - if (set.preferredTypes) { - for (const type of set.preferredTypes) { - const dexType = Dex.types.get(type); - assert(dexType.exists, `${species.name} has invalid Preferred Type: ${type}`); - assert.equal(type, dexType.name, `${species.name} has misformatted Preferred Type: ${type}`); - } - for (let i = 0; i < set.preferredTypes.length - 1; i++) { - assert(set.preferredTypes[i + 1] > set.preferredTypes[i], `${species} preferredTypes should be sorted alphabetically`); - } - } - } - } - }); - }); - - it('all Pokemon should have 4 moves, except for Ditto and Unown', function () { - // This test takes more than 2000ms - testTeam({...options, rounds: 100}, team => { - for (const pokemon of team) assert(pokemon.name === 'Ditto' || pokemon.name === 'Unown' || pokemon.moves.length === 4); - }); - }); - - it('all moves on all sets should be obtainable', function () { - const generator = Teams.getGenerator(options.format); - const rounds = 100; - for (const pokemon of Object.keys(setsJSON)) { - const species = dex.species.get(pokemon); - const sets = setsJSON[pokemon]["sets"]; - const types = species.types; - const abilities = new Set(Object.values(species.abilities)); - if (species.unreleasedHidden) abilities.delete(species.abilities.H); - for (const set of sets) { - const role = set.role; - const moves = new Set(Array.from(set.movepool)); - const preferredTypes = set.preferredTypes; - let teamDetails = {}; - // Go through all possible teamDetails combinations, if necessary - for (let j = 0; j < rounds; j++) { - // Generate a moveset as the lead, teamDetails is always empty for this - const preferredType = preferredTypes ? preferredTypes[j % preferredTypes.length] : ''; - const movePool = Array.from(set.movepool); - const moveSet = generator.randomMoveset(types, abilities, {}, species, true, movePool, preferredType, role); - for (const move of moveSet) moves.delete(move); - if (!moves.size) break; - // Generate a moveset for each combination of relevant teamDetails - for (let i = 0; i < 4; i++) { - const rapidSpin = i % 2; - const stealthRock = Math.floor(i / 2) % 2; - teamDetails = {rapidSpin, stealthRock}; - // randomMoveset() deletes moves from the movepool, so recreate it every time - const movePool = Array.from(set.movepool); - const moveSet = generator.randomMoveset(types, abilities, teamDetails, species, false, movePool, preferredType, role); - for (const move of moveSet) moves.delete(move); - if (!moves.size) break; - } - if (!moves.size) break; - } - assert(!moves.size, species); - } - } - }); - - it('should not generate Shaymin-Sky without Air Slash', () => { - testSet('shayminsky', options, set => assert(set.moves.includes('airslash'), `got ${set.moves}`)); - }); - - it('should prevent double Hidden Power', () => testHiddenPower('magnezone', options)); - - it('should give Yanmega Speed Boost if it has Protect', () => { - testSet('yanmega', options, set => { - if (set.ability !== 'Speed Boost') return; - assert(set.moves.includes('protect'), `got ${set.moves}`); - }); - }); -}); diff --git a/test/random-battles/gen5.js b/test/random-battles/gen5.js index 1e13d531bf2f..8d501077a9ec 100644 --- a/test/random-battles/gen5.js +++ b/test/random-battles/gen5.js @@ -4,110 +4,10 @@ 'use strict'; const assert = require('../assert'); -const {testTeam, testSet, testHiddenPower, testAlwaysHasMove, validateLearnset} = require('./tools'); +const {testSet} = require('./tools'); describe('[Gen 5] Random Battle (slow)', () => { const options = {format: 'gen5randombattle'}; - const setsJSON = require(`../../dist/data/random-battles/gen5/sets.json`); - const dex = Dex.forFormat(options.format); - - describe("New set format", () => { - const filename = '../../data/random-battles/gen5/sets.json'; - it(`${filename} should have valid set data`, () => { - const setsJSON = require(filename); - const validRoles = [ - "Fast Attacker", "Setup Sweeper", "Wallbreaker", "Bulky Attacker", - "Bulky Setup", "Staller", "Bulky Support", "Fast Support", "Spinner", - ]; - for (const [id, sets] of Object.entries(setsJSON)) { - const species = Dex.species.get(id); - assert(species.exists, `Misspelled species ID: ${id}`); - assert(Array.isArray(sets.sets)); - for (const set of sets.sets) { - assert(validRoles.includes(set.role), `Set for ${species.name} has invalid role: ${set.role}`); - for (const move of set.movepool) { - const dexMove = Dex.moves.get(move); - assert(dexMove.exists, `${species.name} has invalid move: ${move}`); - assert(move === dexMove.id || move.startsWith('hiddenpower'), `${species.name} has misformatted move: ${move}`); - assert(validateLearnset(dexMove, {species}, 'anythinggoes', 'gen5'), `${species.name} can't learn ${move}`); - } - for (let i = 0; i < set.movepool.length - 1; i++) { - assert(set.movepool[i + 1] > set.movepool[i], `${species} movepool should be sorted alphabetically`); - } - if (set.preferredTypes) { - for (const type of set.preferredTypes) { - const dexType = Dex.types.get(type); - assert(dexType.exists, `${species.name} has invalid Preferred Type: ${type}`); - assert.equal(type, dexType.name, `${species.name} has misformatted Preferred Type: ${type}`); - } - for (let i = 0; i < set.preferredTypes.length - 1; i++) { - assert(set.preferredTypes[i + 1] > set.preferredTypes[i], `${species} preferredTypes should be sorted alphabetically`); - } - } - } - } - }); - }); - - it('all Pokemon should have 4 moves, except for Ditto and Unown', function () { - // This test takes more than 2000ms - testTeam({...options, rounds: 100}, team => { - for (const pokemon of team) assert(pokemon.name === 'Ditto' || pokemon.name === 'Unown' || pokemon.moves.length === 4); - }); - }); - - it('all moves on all sets should be obtainable', function () { - const generator = Teams.getGenerator(options.format); - const rounds = 100; - for (const pokemon of Object.keys(setsJSON)) { - const species = dex.species.get(pokemon); - const sets = setsJSON[pokemon]["sets"]; - const types = species.types; - const abilities = new Set(Object.values(species.abilities)); - if (species.unreleasedHidden) abilities.delete(species.abilities.H); - for (const set of sets) { - const role = set.role; - const moves = new Set(Array.from(set.movepool)); - const preferredTypes = set.preferredTypes; - let teamDetails = {}; - // Go through all possible teamDetails combinations, if necessary - for (let j = 0; j < rounds; j++) { - // Generate a moveset as the lead, teamDetails is always empty for this - const preferredType = preferredTypes ? preferredTypes[j % preferredTypes.length] : ''; - const movePool = Array.from(set.movepool); - const moveSet = generator.randomMoveset(types, abilities, {}, species, true, movePool, preferredType, role); - for (const move of moveSet) moves.delete(move); - if (!moves.size) break; - // Generate a moveset for each combination of relevant teamDetails - for (let i = 0; i < 4; i++) { - const rapidSpin = i % 2; - const stealthRock = Math.floor(i / 2) % 2; - teamDetails = {rapidSpin, stealthRock}; - // randomMoveset() deletes moves from the movepool, so recreate it every time - const movePool = Array.from(set.movepool); - const moveSet = generator.randomMoveset(types, abilities, teamDetails, species, false, movePool, preferredType, role); - for (const move of moveSet) moves.delete(move); - if (!moves.size) break; - } - if (!moves.size) break; - } - assert(!moves.size, species); - } - } - }); - - it('should prevent double Hidden Power', () => { - testHiddenPower('ampharos', options); - testHiddenPower('venusaur', options); - }); - - it('should give Venusaur four moves', () => { - testSet( - 'venusaur', - {format: 'gen5randombattle', rounds: 1, seed: [2201, 2201, 2201, 2201]}, - set => assert.equal(set.moves.length, 4, `got ${JSON.stringify(set.moves)}`) - ); - }); it('should prevent unreleased HAs from being used', () => { testSet('chandelure', options, set => assert.notEqual(set.ability, 'Shadow Tag')); @@ -116,8 +16,4 @@ describe('[Gen 5] Random Battle (slow)', () => { it('should not give Ursaring Eviolite', () => { testSet('ursaring', options, set => assert.notEqual(set.item, 'Eviolite')); }); - - it('should always give Watchog Return', () => { - testAlwaysHasMove('watchog', options, 'return'); - }); }); diff --git a/test/random-battles/gen6.js b/test/random-battles/gen6.js index 66b0e8f74aab..e5b1fb8853d1 100644 --- a/test/random-battles/gen6.js +++ b/test/random-battles/gen6.js @@ -4,98 +4,10 @@ 'use strict'; const assert = require('../assert'); -const {testTeam, testNotBothMoves, testSet, testHiddenPower, testAlwaysHasMove, validateLearnset} = require('./tools'); +const {testSet} = require('./tools'); describe('[Gen 6] Random Battle (slow)', () => { const options = {format: 'gen6randombattle'}; - const setsJSON = require(`../../dist/data/random-battles/gen6/sets.json`); - const dex = Dex.forFormat(options.format); - - describe("New set format", () => { - const filename = '../../data/random-battles/gen6/sets.json'; - it(`${filename} should have valid set data`, () => { - const setsJSON = require(filename); - const validRoles = [ - "Fast Attacker", "Setup Sweeper", "Wallbreaker", "Bulky Attacker", - "Bulky Setup", "Staller", "Bulky Support", "Fast Support", "AV Pivot", - ]; - for (const [id, sets] of Object.entries(setsJSON)) { - const species = Dex.species.get(id); - assert(species.exists, `Misspelled species ID: ${id}`); - assert(Array.isArray(sets.sets)); - for (const set of sets.sets) { - assert(validRoles.includes(set.role), `Set for ${species.name} has invalid role: ${set.role}`); - for (const move of set.movepool) { - const dexMove = Dex.moves.get(move); - assert(dexMove.exists, `${species.name} has invalid move: ${move}`); - assert(move === dexMove.id || move.startsWith('hiddenpower'), `${species.name} has misformatted move: ${move}`); - assert(validateLearnset(dexMove, {species}, 'anythinggoes', 'gen6'), `${species.name} can't learn ${move}`); - } - for (let i = 0; i < set.movepool.length - 1; i++) { - assert(set.movepool[i + 1] > set.movepool[i], `${species} movepool should be sorted alphabetically`); - } - if (set.preferredTypes) { - for (const type of set.preferredTypes) { - const dexType = Dex.types.get(type); - assert(dexType.exists, `${species.name} has invalid Preferred Type: ${type}`); - assert.equal(type, dexType.name, `${species.name} has misformatted Preferred Type: ${type}`); - } - for (let i = 0; i < set.preferredTypes.length - 1; i++) { - assert(set.preferredTypes[i + 1] > set.preferredTypes[i], `${species} preferredTypes should be sorted alphabetically`); - } - } - } - } - }); - }); - - it('all Pokemon should have 4 moves, except for Ditto and Unown', function () { - // This test takes more than 2000ms - testTeam({...options, rounds: 100}, team => { - for (const pokemon of team) assert(pokemon.name === 'Ditto' || pokemon.name === 'Unown' || pokemon.moves.length === 4); - }); - }); - - it('all moves on all sets should be obtainable', function () { - const generator = Teams.getGenerator(options.format); - const rounds = 100; - for (const pokemon of Object.keys(setsJSON)) { - const species = dex.species.get(pokemon); - const sets = setsJSON[pokemon]["sets"]; - const types = species.types; - const abilities = new Set(Object.values(species.abilities)); - if (species.unreleasedHidden) abilities.delete(species.abilities.H); - for (const set of sets) { - const role = set.role; - const moves = new Set(Array.from(set.movepool)); - const preferredTypes = set.preferredTypes; - let teamDetails = {}; - // Go through all possible teamDetails combinations, if necessary - for (let j = 0; j < rounds; j++) { - // Generate a moveset as the lead, teamDetails is always empty for this - const preferredType = preferredTypes ? preferredTypes[j % preferredTypes.length] : ''; - const movePool = Array.from(set.movepool); - const moveSet = generator.randomMoveset(types, abilities, {}, species, true, movePool, preferredType, role); - for (const move of moveSet) moves.delete(move); - if (!moves.size) break; - // Generate a moveset for each combination of relevant teamDetails - for (let i = 0; i < 8; i++) { - const defog = i % 2; - const stealthRock = Math.floor(i / 2) % 2; - const stickyWeb = Math.floor(i / 4) % 2; - teamDetails = {defog, stealthRock, stickyWeb}; - // randomMoveset() deletes moves from the movepool, so recreate it every time - const movePool = Array.from(set.movepool); - const moveSet = generator.randomMoveset(types, abilities, teamDetails, species, false, movePool, preferredType, role); - for (const move of moveSet) moves.delete(move); - if (!moves.size) break; - } - if (!moves.size) break; - } - assert(!moves.size, species); - } - } - }); it('should not give mega evolution abilities to base formes', () => { testSet('manectricmega', {rounds: 1, ...options}, set => { @@ -103,40 +15,10 @@ describe('[Gen 6] Random Battle (slow)', () => { }); }); - it('should not select Air Slash and Hurricane together', () => { - testNotBothMoves('swanna', options, 'hurricane', 'airslash'); - }); - - it('should enforce STAB properly', () => { - testAlwaysHasMove('hariyama', options, 'closecombat'); - testAlwaysHasMove('rapidash', options, 'flareblitz'); - }); - - it('should give Drifblim only one Ghost-type attack', () => { - testSet('drifblim', options, set => { - assert.equal(set.moves.filter(m => { - const move = Dex.moves.get(m); - return move.type === 'Ghost' && move.category !== 'Status'; - }).length, 1, `got ${JSON.stringify(set.moves)}`); - }); - }); - - it('should prevent double Hidden Power', () => testHiddenPower('thundurustherian', options)); - - it('should always give Mega Glalie Return', () => testAlwaysHasMove('glaliemega', options, 'return')); - it('should not give Ursaring Eviolite', () => { testSet('ursaring', options, set => assert.notEqual(set.item, 'Eviolite')); }); - it('should always give Quagsire Unaware', () => { - testSet('quagsire', options, set => assert.equal(set.ability, 'Unaware')); - }); - - it('should always give Quagsire Recover', () => { - testAlwaysHasMove('quagsire', options, 'recover'); - }); - it('should not give Raikou Volt Absorb', () => { testSet('raikou', options, set => assert.notEqual(set.ability, 'Volt Absorb')); }); @@ -148,8 +30,4 @@ describe('[Gen 6] Random Battle (slow)', () => { it('should not give Entei Flash Fire', () => { testSet('entei', options, set => assert.notEqual(set.ability, 'Flash Fire')); }); - - it('should only give Charizard one of Air Slash and Acrobatics', () => { - testNotBothMoves('charizard', options, 'airslash', 'acrobatics'); - }); }); diff --git a/test/random-battles/gen7.js b/test/random-battles/gen7.js index 5e14129487de..e7bbc7f112b8 100644 --- a/test/random-battles/gen7.js +++ b/test/random-battles/gen7.js @@ -4,162 +4,18 @@ 'use strict'; const assert = require('../assert'); -const {testTeam, testNotBothMoves, testSet, testHiddenPower, testAlwaysHasMove, validateLearnset} = require('./tools'); +const {testSet} = require('./tools'); describe('[Gen 7] Random Battle (slow)', () => { const options = {format: 'gen7randombattle'}; - const setsJSON = require(`../../dist/data/random-battles/gen7/sets.json`); - const dex = Dex.forFormat(options.format); - describe("New set format", () => { - const filename = '../../data/random-battles/gen7/sets.json'; - it(`${filename} should have valid set data`, () => { - const setsJSON = require(filename); - const validRoles = [ - "Fast Attacker", "Setup Sweeper", "Wallbreaker", "Z-Move user", "Bulky Attacker", - "Bulky Setup", "Staller", "Bulky Support", "Fast Support", "AV Pivot", - ]; - for (const [id, sets] of Object.entries(setsJSON)) { - const species = Dex.species.get(id); - assert(species.exists, `Misspelled species ID: ${id}`); - assert(Array.isArray(sets.sets)); - for (const set of sets.sets) { - assert(validRoles.includes(set.role), `Set for ${species.name} has invalid role: ${set.role}`); - for (const move of set.movepool) { - const dexMove = Dex.moves.get(move); - assert(dexMove.exists, `${species.name} has invalid move: ${move}`); - assert(move === dexMove.id || move.startsWith('hiddenpower'), `${species.name} has misformatted move: ${move}`); - assert(validateLearnset(dexMove, {species}, 'anythinggoes', 'gen7'), `${species.name} can't learn ${move}`); - } - for (let i = 0; i < set.movepool.length - 1; i++) { - assert(set.movepool[i + 1] > set.movepool[i], `${species} movepool should be sorted alphabetically`); - } - if (set.preferredTypes) { - for (const type of set.preferredTypes) { - const dexType = Dex.types.get(type); - assert(dexType.exists, `${species.name} has invalid Preferred Type: ${type}`); - assert.equal(type, dexType.name, `${species.name} has misformatted Preferred Type: ${type}`); - } - for (let i = 0; i < set.preferredTypes.length - 1; i++) { - assert(set.preferredTypes[i + 1] > set.preferredTypes[i], `${species} preferredTypes should be sorted alphabetically`); - } - } - } - } + it('should not give mega evolution abilities to base formes', () => { + testSet('manectricmega', {rounds: 1, ...options}, set => { + assert(set.ability !== 'Intimidate', 'Mega Manectric should not have Intimidate before it mega evolves'); }); }); - it('all Pokemon should have 4 moves, except for Ditto and Unown', function () { - // This test takes more than 2000ms - testTeam({...options, rounds: 100}, team => { - for (const pokemon of team) assert(pokemon.name === 'Ditto' || pokemon.name === 'Unown' || pokemon.moves.length === 4); - }); - }); - - it('all moves on all sets should be obtainable', function () { - const generator = Teams.getGenerator(options.format); - const rounds = 100; - for (const pokemon of Object.keys(setsJSON)) { - const species = dex.species.get(pokemon); - const sets = setsJSON[pokemon]["sets"]; - const types = species.types; - const abilities = new Set(Object.values(species.abilities)); - if (species.unreleasedHidden) abilities.delete(species.abilities.H); - for (const set of sets) { - const role = set.role; - const moves = new Set(Array.from(set.movepool)); - const preferredTypes = set.preferredTypes; - let teamDetails = {}; - // Go through all possible teamDetails combinations, if necessary - for (let j = 0; j < rounds; j++) { - // Generate a moveset as the lead, teamDetails is always empty for this - const preferredType = preferredTypes ? preferredTypes[j % preferredTypes.length] : ''; - const movePool = Array.from(set.movepool); - const moveSet = generator.randomMoveset(types, abilities, {}, species, true, movePool, preferredType, role); - for (const move of moveSet) moves.delete(move); - if (!moves.size) break; - // Generate a moveset for each combination of relevant teamDetails - for (let i = 0; i < 8; i++) { - const defog = i % 2; - const stealthRock = Math.floor(i / 2) % 2; - const stickyWeb = Math.floor(i / 4) % 2; - teamDetails = {defog, stealthRock, stickyWeb}; - // randomMoveset() deletes moves from the movepool, so recreate it every time - const movePool = Array.from(set.movepool); - const moveSet = generator.randomMoveset(types, abilities, teamDetails, species, false, movePool, preferredType, role); - for (const move of moveSet) moves.delete(move); - if (!moves.size) break; - } - if (!moves.size) break; - } - assert(!moves.size, species); - } - } - }); - - it('should not generate Calm Mind + Yawn', () => { - testNotBothMoves('chimecho', options, 'calmmind', 'yawn'); - }); - - it('should give Azumarill Aqua Jet', () => { - testSet('azumarill', options, set => { - assert(set.moves.includes('aquajet'), `Azumarill: got ${set.moves}`); - }); - }); - - it('should give Typhlosion Eruption', () => { - testSet('typhlosion', options, set => { - assert(set.moves.includes('eruption'), `Typhlosion: got ${set.moves}`); - }); - }); - - it('should not generate Dragon Tail as the only STAB move', () => { - // Mono-Dragon Pokémon chosen as test dummies for simplicity - testSet('druddigon', options, set => { - if (set.moves.includes('dragontail')) { - assert(set.moves.includes('outrage'), `Druddigon: got ${set.moves}`); - } - }); - - testSet('goodra', options, set => { - if (set.moves.includes('dragontail')) { - assert(set.moves.includes('dracometeor') || set.moves.includes('dragonpulse'), `Goodra: got ${set.moves}`); - } - }); - }); - - it('should not generate Swords Dance + Ice Beam', () => { - testNotBothMoves('arceusground', options, 'swordsdance', 'icebeam'); - }); - - it('should prevent double Hidden Power', () => testHiddenPower('thundurustherian', options)); - - it('should never give Xerneas Assault Vest', () => { - testSet('xerneas', options, set => assert.notEqual(set.item, 'Assault Vest')); - }); - - it('should always give Gastrodon Recover', () => { - testAlwaysHasMove('gastrodon', options, 'recover'); - }); - - it('should never give Poliwrath both Rain Dance and Rest', () => { - testNotBothMoves('poliwrath', options, 'raindance', 'rest'); - }); - it('should not give Ursaring Eviolite', () => { testSet('ursaring', options, set => assert.notEqual(set.item, 'Eviolite')); }); - - it('should always give Mega Glalie Return', () => testAlwaysHasMove('glaliemega', options, 'return')); - - it('should not give Zebstrika Thunderbolt and Wild Charge', () => { - testNotBothMoves('zebstrika', options, 'thunderbolt', 'wildcharge'); - }); - - it('should always give Mega Diancie Moonblast if it has Calm Mind', () => { - testSet('dianciemega', options, set => { - if (!set.moves.includes('calmmind')) return; - assert(set.moves.includes('moonblast'), `Diancie: got ${set.moves}`); - }); - }); }); diff --git a/test/random-battles/gen9.js b/test/random-battles/gen9.js index 74c4260c3c7a..fd7f4a5f8b67 100644 --- a/test/random-battles/gen9.js +++ b/test/random-battles/gen9.js @@ -5,125 +5,14 @@ const {testTeam, testAlwaysHasMove} = require('./tools'); const assert = require('../assert'); -const Teams = require('./../../dist/sim/teams').Teams; -const Dex = require('./../../dist/sim/dex').Dex; describe('[Gen 9] Random Battle (slow)', () => { const options = {format: 'gen9randombattle'}; - const setsJSON = require(`../../dist/data/random-battles/gen9/sets.json`); - const dex = Dex.forFormat(options.format); - - it('all Pokemon should have 4 moves, except for Ditto', function () { - // This test takes more than 2000ms - testTeam({...options, rounds: 100}, team => { - for (const pokemon of team) assert(pokemon.name === 'Ditto' || pokemon.moves.length === 4); - }); - }); - - it('all moves on all sets should exist and be obtainable', function () { - const generator = Teams.getGenerator(options.format); - const rounds = 100; - for (const pokemon of Object.keys(setsJSON)) { - const species = dex.species.get(pokemon); - assert(species.exists, `Pokemon ${species} does not exist`); - const sets = setsJSON[pokemon]["sets"]; - const types = species.types; - const abilities = new Set(Object.values(species.abilities)); - if (species.unreleasedHidden) abilities.delete(species.abilities.H); - for (const set of sets) { - assert(set.movepool.every(m => dex.moves.get(m).exists), `One of ${set.movepool} does not exist.`); - const role = set.role; - const moves = new Set(set.movepool.map(m => dex.moves.get(m).id)); - const teraTypes = set.teraTypes; - let teamDetails = {}; - // Go through all possible teamDetails combinations, if necessary - for (let j = 0; j < rounds; j++) { - // Generate a moveset as the lead, teamDetails is always empty for this - const teraType = teraTypes[j % teraTypes.length]; - const movePool = set.movepool.map(m => dex.moves.get(m).id); - const moveSet = generator.randomMoveset(types, abilities, {}, species, true, false, movePool, teraType, role); - for (const move of moveSet) moves.delete(move); - if (!moves.size) break; - // Generate a moveset for each combination of relevant teamDetails - for (let i = 0; i < 8; i++) { - const defog = i % 2; - const stealthRock = Math.floor(i / 2) % 2; - const stickyWeb = Math.floor(i / 4) % 2; - teamDetails = {defog, stealthRock, stickyWeb}; - // randomMoveset() deletes moves from the movepool, so recreate it every time - const movePool = set.movepool.map(m => dex.moves.get(m).id); - const moveSet = generator.randomMoveset(types, abilities, teamDetails, species, false, false, movePool, teraType, role); - for (const move of moveSet) moves.delete(move); - if (!moves.size) break; - } - if (!moves.size) break; - } - assert.false(moves.size, `The following moves on ${species.name} are unused: ${[...moves].join(', ')}`); - } - } - }); - it("should always give Iron Bundle Freeze-Dry", () => { testAlwaysHasMove('ironbundle', options, 'freezedry'); }); }); -describe('[Gen 9] Baby Random Battle (slow)', () => { - const options = {format: 'gen9babyrandombattle'}; - const setsJSON = require(`../../dist/data/random-battles/gen9baby/sets.json`); - const dex = Dex.forFormat(options.format); - - it('all Pokemon should have 4 moves', function () { - // This test takes more than 2000ms - testTeam({...options, rounds: 100}, team => { - for (const pokemon of team) assert(pokemon.moves.length === 4); - }); - }); - - it('all moves on all sets should exist and be obtainable', function () { - const generator = Teams.getGenerator(options.format); - const rounds = 100; - for (const pokemon of Object.keys(setsJSON)) { - const species = dex.species.get(pokemon); - assert(species.exists, `Pokemon ${species} does not exist`); - const sets = setsJSON[pokemon]["sets"]; - const types = species.types; - const abilities = new Set(Object.values(species.abilities)); - if (species.unreleasedHidden) abilities.delete(species.abilities.H); - for (const set of sets) { - assert(set.movepool.every(m => dex.moves.get(m).exists), `One of ${set.movepool} does not exist.`); - const role = set.role; - const moves = new Set(set.movepool.map(m => dex.moves.get(m).id)); - const teraTypes = set.teraTypes; - let teamDetails = {}; - // Go through all possible teamDetails combinations, if necessary - for (let j = 0; j < rounds; j++) { - // Generate a moveset as the lead, teamDetails is always empty for this - const teraType = teraTypes[j % teraTypes.length]; - const movePool = set.movepool.map(m => dex.moves.get(m).id); - const moveSet = generator.randomMoveset(types, abilities, {}, species, true, false, movePool, teraType, role); - for (const move of moveSet) moves.delete(move); - if (!moves.size) break; - // Generate a moveset for each combination of relevant teamDetails - for (let i = 0; i < 8; i++) { - const defog = i % 2; - const stealthRock = Math.floor(i / 2) % 2; - const stickyWeb = Math.floor(i / 4) % 2; - teamDetails = {defog, stealthRock, stickyWeb}; - // randomMoveset() deletes moves from the movepool, so recreate it every time - const movePool = set.movepool.map(m => dex.moves.get(m).id); - const moveSet = generator.randomMoveset(types, abilities, teamDetails, species, false, false, movePool, teraType, role); - for (const move of moveSet) moves.delete(move); - if (!moves.size) break; - } - if (!moves.size) break; - } - assert.false(moves.size, `The following moves on ${species.name} are unused: ${[...moves].join(', ')}`); - } - } - }); -}); - describe('[Gen 9] Monotype Random Battle (slow)', () => { const options = {format: 'gen9monotyperandombattle'}; @@ -133,59 +22,3 @@ describe('[Gen 9] Monotype Random Battle (slow)', () => { }); }); }); - -describe('[Gen 9] Random Doubles Battle (slow)', () => { - const options = {format: 'gen9randomdoublesbattle'}; - const setsJSON = require(`../../dist/data/random-battles/gen9/doubles-sets.json`); - const dex = Dex.forFormat(options.format); - - it('all Pokemon should have 4 moves, except for Ditto', function () { - // This test takes more than 2000ms - testTeam({...options, rounds: 100}, team => { - for (const pokemon of team) assert(pokemon.name === 'Ditto' || pokemon.moves.length === 4); - }); - }); - - it('all moves on all sets should exist and be obtainable', function () { - const generator = Teams.getGenerator(options.format); - const rounds = 100; - for (const pokemon of Object.keys(setsJSON)) { - const species = dex.species.get(pokemon); - assert(species.exists, `Pokemon ${species} does not exist`); - const sets = setsJSON[pokemon]["sets"]; - const types = species.types; - const abilities = new Set(Object.values(species.abilities)); - if (species.unreleasedHidden) abilities.delete(species.abilities.H); - for (const set of sets) { - assert(set.movepool.every(m => dex.moves.get(m).exists), `One of ${set.movepool} does not exist.`); - const role = set.role; - const moves = new Set(set.movepool.map(m => dex.moves.get(m).id)); - const teraTypes = set.teraTypes; - let teamDetails = {}; - // Go through all possible teamDetails combinations, if necessary - for (let j = 0; j < rounds; j++) { - // Generate a moveset as the lead, teamDetails is always empty for this - const teraType = teraTypes[j % teraTypes.length]; - const movePool = set.movepool.map(m => dex.moves.get(m).id); - const moveSet = generator.randomMoveset(types, abilities, {}, species, true, true, movePool, teraType, role); - for (const move of moveSet) moves.delete(move); - if (!moves.size) break; - // Generate a moveset for each combination of relevant teamDetails - for (let i = 0; i < 8; i++) { - const defog = i % 2; - const stealthRock = Math.floor(i / 2) % 2; - const stickyWeb = Math.floor(i / 4) % 2; - teamDetails = {defog, stealthRock, stickyWeb}; - // randomMoveset() deletes moves from the movepool, so recreate it every time - const movePool = set.movepool.map(m => dex.moves.get(m).id); - const moveSet = generator.randomMoveset(types, abilities, teamDetails, species, false, true, movePool, teraType, role); - for (const move of moveSet) moves.delete(move); - if (!moves.size) break; - } - if (!moves.size) break; - } - assert(!moves.size); - } - } - }); -});