Skip to content

Commit

Permalink
Random Battles updates
Browse files Browse the repository at this point in the history
  • Loading branch information
AnnikaCodes committed Apr 10, 2021
1 parent 986142a commit 3ca9472
Show file tree
Hide file tree
Showing 7 changed files with 78 additions and 23 deletions.
4 changes: 2 additions & 2 deletions data/formats-data.ts
Expand Up @@ -4380,7 +4380,7 @@ export const FormatsData: {[k: string]: SpeciesFormatsData} = {
tier: "LC",
},
doublade: {
randomBattleMoves: ["ironhead", "sacredsword", "shadowclaw", "shadowsneak", "swordsdance"],
randomBattleMoves: ["closecombat", "ironhead", "shadowclaw", "shadowsneak", "swordsdance"],
randomBattleLevel: 82,
tier: "RU",
doublesTier: "NFE",
Expand Down Expand Up @@ -5394,7 +5394,7 @@ export const FormatsData: {[k: string]: SpeciesFormatsData} = {
},
magearnaoriginal: {
randomBattleMoves: ["agility", "calmmind", "flashcannon", "fleurcannon"],
randomBattleLevel: 74,
randomBattleLevel: 76,
randomDoubleBattleMoves: ["agility", "aurasphere", "dazzlinggleam", "flashcannon", "fleurcannon", "protect", "trick"],
randomDoubleBattleLevel: 72,
tier: "Uber",
Expand Down
4 changes: 2 additions & 2 deletions data/mods/gen6/formats-data.ts
Expand Up @@ -664,7 +664,7 @@ export const FormatsData: {[k: string]: ModdedSpeciesFormatsData} = {
doublesTier: "(DUU)",
},
kangaskhanmega: {
randomBattleMoves: ["crunch", "earthquake", "fakeout", "poweruppunch", "return", "suckerpunch"],
randomBattleMoves: ["crunch", "earthquake", "fakeout", "poweruppunch", "return", "suckerpunch", "seismictoss"],
randomDoubleBattleMoves: ["crunch", "doubleedge", "drainpunch", "earthquake", "fakeout", "poweruppunch", "protect", "return", "suckerpunch"],
tier: "Uber",
doublesTier: "DOU",
Expand Down Expand Up @@ -1223,7 +1223,7 @@ export const FormatsData: {[k: string]: ModdedSpeciesFormatsData} = {
doublesTier: "(DUU)",
},
shuckle: {
randomBattleMoves: ["encore", "infestation", "knockoff", "stealthrock", "stickyweb", "toxic"],
randomBattleMoves: ["encore", "knockoff", "stealthrock", "stickyweb", "toxic"],
randomDoubleBattleMoves: ["encore", "guardsplit", "helpinghand", "knockoff", "powersplit", "stealthrock", "stickyweb", "toxic"],
tier: "RUBL",
doublesTier: "(DUU)",
Expand Down
2 changes: 1 addition & 1 deletion data/mods/gen6/random-teams.ts
Expand Up @@ -289,7 +289,7 @@ export class RandomGen6Teams extends RandomGen7Teams {
case 'lavaplume':
return {cull: hasMove['firepunch'] || hasMove['fireblast'] && (counter.setupType || !!counter.speedsetup)};
case 'airslash': case 'hurricane':
return {cull: hasMove['bravebird']};
return {cull: hasMove['bravebird'] || hasMove[move.id === 'hurricane' ? 'airslash' : 'hurricane']};
case 'shadowball':
return {cull: hasMove['darkpulse'] || (hasMove['hex'] && hasMove['willowisp'])};
case 'shadowclaw':
Expand Down
38 changes: 22 additions & 16 deletions data/random-teams.ts
Expand Up @@ -120,13 +120,16 @@ export class RandomTeams {
if (!counter.Dark) return true;
return hasMove['suckerpunch'] && (movePool.includes('knockoff') || movePool.includes('wickedblow'));
},
Dragon: (movePool, hasMove, hasAbility, hasType, counter) => (
!(counter.setupType === 'Physical' && hasType['Flying']) &&
!counter.Dragon &&
!hasMove['dragonascent'] &&
!hasMove['substitute'] &&
!(hasMove['rest'] && hasMove['sleeptalk'])
),
Dragon: (movePool, hasMove, hasAbility, hasType, counter, species) => {
if (movePool.includes('outrage') && species.baseStats.atk >= 115) return true;
return (
!(counter.setupType === 'Physical' && hasType['Flying']) &&
!counter.Dragon &&
!hasMove['dragonascent'] &&
!hasMove['substitute'] &&
!(hasMove['rest'] && hasMove['sleeptalk'])
);
},
Electric: (movePool, hasMove, hasAbility, hasType, counter) => !counter.Electric || movePool.includes('thunder'),
Fairy: (movePool, hasMove, hasAbility, hasType, counter) => (
!counter.Fairy &&
Expand Down Expand Up @@ -755,6 +758,7 @@ export class RandomTeams {
return {cull: true};
}
if (
(species.id === 'doublade' && movePool.includes('swordsdance')) ||
(species.id === 'entei' && movePool.includes('extremespeed')) ||
(species.id === 'genesectdouse' && movePool.includes('technoblast')) ||
(species.id === 'golisopod' && movePool.includes('leechlife') && movePool.includes('firstimpression'))
Expand Down Expand Up @@ -1043,7 +1047,8 @@ export class RandomTeams {
// Special case for Necrozma-DM, which always wants Dragon Dance
return {cull: hasMove['morningsun']};
case 'psychic':
return {cull: hasMove['psyshock'] && (counter.setupType || isDoubles)};
const alcremieCase = species.id === 'alcremiegmax' && counter.Status < 2;
return {cull: alcremieCase || (hasMove['psyshock'] && (counter.setupType || isDoubles))};
case 'psyshock':
// Special case for Sylveon which only wants Psyshock if it gets a Choice item
const sylveonCase = hasAbility['Pixilate'] && counter.Special < 4;
Expand Down Expand Up @@ -1217,7 +1222,7 @@ export class RandomTeams {
case 'Lightning Rod':
return (species.types.includes('Ground') || (!isNoDynamax && counter.setupType === 'Physical'));
case 'Limber':
return species.types.includes('Electric');
return species.types.includes('Electric') || hasMove['facade'];
case 'Liquid Voice':
return !hasMove['hypervoice'];
case 'Magic Guard':
Expand Down Expand Up @@ -1393,10 +1398,7 @@ export class RandomTeams {
// Ability based logic and miscellaneous logic
if (species.name === 'Wobbuffet' || ['Cheek Pouch', 'Harvest', 'Ripen'].includes(ability)) return 'Sitrus Berry';
if (ability === 'Gluttony') return this.sample(['Aguav', 'Figy', 'Iapapa', 'Mago', 'Wiki']) + ' Berry';
if (
ability === 'Gorilla Tactics' || ability === 'Imposter' ||
(ability === 'Magnet Pull' && hasMove['bodypress'] && !isDoubles)
) return 'Choice Scarf';
if (ability === 'Imposter' || (ability === 'Magnet Pull' && hasMove['bodypress'] && !isDoubles)) return 'Choice Scarf';
if (ability === 'Guts' && (counter.Physical > 2 || isDoubles)) return hasType['Fire'] ? 'Toxic Orb' : 'Flame Orb';
if (ability === 'Magic Guard' && counter.damagingMoves.length > 1) {
return hasMove['counter'] ? 'Focus Sash' : 'Life Orb';
Expand Down Expand Up @@ -1806,9 +1808,13 @@ export class RandomTeams {
);

if (rejectAbility) {
if (ability === abilities[0].name && abilities[1].rating >= 1) {
// Lopunny, and other Facade users, don't want Limber, even if other abilities are poorly rated,
// since paralysis would arguably be good for them.
const limberFacade = hasMove['facade'] && ability === 'Limber';

if (ability === abilities[0].name && (abilities[1].rating >= 1 || limberFacade)) {
ability = abilities[1].name;
} else if (ability === abilities[1].name && abilityNames[2] && abilities[2].rating >= 1) {
} else if (ability === abilities[1].name && abilityNames[2] && (abilities[2].rating >= 1 || limberFacade)) {
ability = abilities[2].name;
} else {
// Default to the highest rated ability if all are rejected
Expand Down Expand Up @@ -2043,7 +2049,7 @@ export class RandomTeams {
break;
case 'Magearna': case 'Toxtricity': case 'Zacian': case 'Zamazenta': case 'Zarude':
case 'Appletun': case 'Blastoise': case 'Butterfree': case 'Copperajah': case 'Grimmsnarl':
case 'Inteleon': case 'Rillaboom': case 'Snorlax': case 'Urshifu': case 'Giratina':
case 'Inteleon': case 'Rillaboom': case 'Snorlax': case 'Urshifu': case 'Giratina': case 'Genesect':
if (this.gen >= 8 && this.randomChance(1, 2)) continue;
break;
}
Expand Down
15 changes: 15 additions & 0 deletions test/random-battles/gen6.js
@@ -0,0 +1,15 @@

/**
* Tests for Gen 7 randomized formats

This comment has been minimized.

Copy link
@DaWoblefet

DaWoblefet Apr 10, 2021

Member

Copy-pasted comment from the other test

This comment has been minimized.

Copy link
@AnnikaCodes

AnnikaCodes Apr 10, 2021

Author Collaborator

Fixed in b4da54c

*/
'use strict';

const {testNotBothMoves} = require('./tools');

describe('[Gen 6] Random Battle', () => {
const options = {format: 'gen6randombattle'};

it('should not select Air Slash and Hurricane together', () => {
testNotBothMoves('swanna', options, 'hurricane', 'airslash');
});
});
19 changes: 18 additions & 1 deletion test/random-battles/gen8.js
Expand Up @@ -3,7 +3,7 @@
*/
'use strict';

const {testSet, testNotBothMoves, testHasSTAB} = require('./tools');
const {testSet, testNotBothMoves, testHasSTAB, testAlwaysHasMove} = require('./tools');
const assert = require('../assert');

describe('[Gen 8] Random Battle', () => {
Expand All @@ -29,6 +29,23 @@ describe('[Gen 8] Random Battle', () => {
}
});
});

it('should not generate 3-attack Alcremie-Gmax', () => {
testSet('alcremiegmax', options, set => assert(
!['psychic', 'dazzlinggleam', 'mysticalfire'].every(move => set.moves.includes(move)),
`Alcremie-Gmax should not get three attacks (got ${set.moves})`
));
});

it('should always give Doublade Swords Dance', () => {
testAlwaysHasMove('doublade', options, 'swordsdance');
});

it('Dragonite and Salamence should always get Outrage', () => {
for (const pkmn of ['dragonite', 'salamence']) {
testAlwaysHasMove(pkmn, options, 'outrage');
}
});
});

describe('[Gen 8] Random Doubles Battle', () => {
Expand Down
19 changes: 18 additions & 1 deletion test/random-battles/tools.js
Expand Up @@ -56,7 +56,23 @@ function testNotBothMoves(pokemon, options, move1, move2) {
testSet(pokemon, options, set => {
assert(
!(set.moves.includes(move1) && set.moves.includes(move2)),
`${pokemon} should not generate both "${move1}" and "${move2}" (generate moveset: ${set.moves})`
`${pokemon} should not generate both "${move1}" and "${move2}" (generated moveset: ${set.moves})`
);
});
}

/**
* Tests that a Pokémon always gets a move.
*
* @param {ID} pokemon the ID of the Pokemon whose set is to be tested
* @param {{format?: string, rounds?: number, isDoubles?: boolean, isLead?: boolean, isDynamax?: boolean}} options
* @param {ID} move
*/
function testAlwaysHasMove(pokemon, options, move) {
testSet(pokemon, options, set => {
assert(
set.moves.includes(move),
`${pokemon} should always generate "${move}" (generated moveset: ${set.moves})`
);
});
}
Expand All @@ -78,6 +94,7 @@ function testTeam(options, test) {
}

exports.testSet = testSet;
exports.testAlwaysHasMove = testAlwaysHasMove;
exports.testNotBothMoves = testNotBothMoves;
exports.testTeam = testTeam;
exports.testHasSTAB = testHasSTAB;

0 comments on commit 3ca9472

Please sign in to comment.