From 6c29c905dace2bf32230ae8673e277ddcaf92e1e Mon Sep 17 00:00:00 2001 From: dot-Comfey <84290266+dot-Comfey@users.noreply.github.com> Date: Thu, 26 Sep 2024 18:22:11 -0700 Subject: [PATCH] Fix prevo/evo move incompatibilities (#10574) --- server/chat-plugins/datasearch.ts | 2 +- sim/team-validator.ts | 53 ++++++++++++++++++++++++++++--- test/sim/team-validator/misc.js | 7 ++++ 3 files changed, 57 insertions(+), 5 deletions(-) diff --git a/server/chat-plugins/datasearch.ts b/server/chat-plugins/datasearch.ts index 0943c891e720..8df72eab453f 100644 --- a/server/chat-plugins/datasearch.ts +++ b/server/chat-plugins/datasearch.ts @@ -1116,7 +1116,6 @@ function runDexsearch(target: string, cmd: string, canAll: boolean, message: str if (nationalSearch && !ruleTable.has('standardnatdex')) additionalRules.push('standardnatdex'); if (nationalSearch && ruleTable.valueRules.has('minsourcegen')) additionalRules.push('!!minsourcegen=3'); validator = TeamValidator.get(`${format}${additionalRules.length ? `@@@${additionalRules.join(',')}` : ''}`); - pokemonSource = validator.allSources(); } for (const alts of searches) { if (alts.skip) continue; @@ -1282,6 +1281,7 @@ function runDexsearch(target: string, cmd: string, canAll: boolean, message: str if (matched) continue; for (const move of altsMoves) { + pokemonSource = validator?.allSources(); if (validator && !validator.checkCanLearn(move, dex[mon], pokemonSource) === alts.moves[move.id]) { matched = true; break; diff --git a/sim/team-validator.ts b/sim/team-validator.ts index 2afdfdec0693..ab243fa24021 100644 --- a/sim/team-validator.ts +++ b/sim/team-validator.ts @@ -106,6 +106,11 @@ export class PokemonSources { * For event-only Pokemon that do not have a minimum source gen identified by its moves */ eventOnlyMinSourceGen?: number; + /** + * A list of movepools, identified by gen and species, which moves can be pulled from. + * Used to deal with compatibility issues for prevo/evo-exclusive moves + */ + learnsetDomain?: string[] | null; /** * Some Pokemon evolve by having a move in their learnset (like Piloswine * with Ancient Power). These can only carry three other moves from their @@ -265,6 +270,13 @@ export class PokemonSources { this.pomegEggMoves.push(...other.pomegEggMoves); } } + if (other.learnsetDomain) { + if (!this.learnsetDomain) { + this.learnsetDomain = other.learnsetDomain; + } else { + this.learnsetDomain.filter(source => other.learnsetDomain?.includes(source)); + } + } if (this.possiblyLimitedEggMoves && !this.sourcesBefore) { const eggSources = this.sources.filter(source => source.charAt(1) === 'E'); let minEggGen = parseInt(eggSources[0]); @@ -2421,6 +2433,7 @@ export class TeamValidator { const format = this.format; const ruleTable = this.ruleTable; const level = set.level || 100; + const canLearnSpecies: ID[] = []; let cantLearnReason = null; @@ -2429,6 +2442,7 @@ export class TeamValidator { let blockedHM = false; let babyOnly = ''; + let minLearnGen = dex.gen; // This is a pretty complicated algorithm @@ -2512,6 +2526,12 @@ export class TeamValidator { // teach it, and transfer it to the current gen.) const learnedGen = parseInt(learned.charAt(0)); + if (setSources.learnsetDomain && !setSources.learnsetDomain.includes(learnedGen + species.id)) { + if (!cantLearnReason) { + cantLearnReason = `is incompatible with ${(setSources.restrictiveMoves || []).join(', ')}.`; + } + continue; + } if (learnedGen < this.minSourceGen) { if (!cantLearnReason) { cantLearnReason = `can't be transferred from Gen ${learnedGen} to ${this.minSourceGen}.`; @@ -2527,9 +2547,6 @@ export class TeamValidator { if (formeCantInherit && (learned.charAt(1) !== 'E' || learnedGen < 9)) continue; - // redundant - if (learnedGen <= moveSources.sourcesBefore) continue; - if ( baseSpecies.evoRegion === 'Alola' && checkingPrevo && learnedGen >= 8 && (dex.gen < 9 || learned.charAt(1) !== 'E') @@ -2612,7 +2629,7 @@ export class TeamValidator { setSources.babyOnly = babyOnly; } } - if (!moveSources.moveEvoCarryCount) return null; + if (!moveSources.moveEvoCarryCount && !setSources.babyOnly) return null; } // past-gen level-up, TM, or tutor moves: // available as long as the source gen was or was before this gen @@ -2673,6 +2690,8 @@ export class TeamValidator { } moveSources.add(learned); } + if (!canLearnSpecies.includes(species.id)) canLearnSpecies.push(species.id); + minLearnGen = Math.min(minLearnGen, learnedGen); } if (ruleTable.has('mimicglitch') && species.gen < 5) { // include the Mimic Glitch when checking this mon's learnset @@ -2758,6 +2777,32 @@ export class TeamValidator { } } + let nextSpecies; + nextSpecies = baseSpecies; + let speciesCount = 0; + if (!tradebackEligible) { + while (nextSpecies) { + for (let gen = nextSpecies.gen; gen <= dex.gen; gen++) { + /** + * Case 1: The species can learn the move - allow moves of the species from all gens + * Case 2: Both prevo and evo can learn the move - same as case 1 + * Case 3: Prevo-only move - allow moves of the species from the min gen and later + * Case 4: Evo-only move - allow moves of the species from the max gen and before + */ + if (canLearnSpecies.includes(nextSpecies.id) || + (0 < speciesCount && speciesCount < canLearnSpecies.length) || + (speciesCount === 0 && gen >= minLearnGen) || + (speciesCount === canLearnSpecies.length && gen <= moveSources.sourcesBefore) + ) { + if (!moveSources.learnsetDomain) moveSources.learnsetDomain = []; + moveSources.learnsetDomain.push(gen + nextSpecies.id); + } + } + if (canLearnSpecies.includes(nextSpecies.id)) speciesCount++; + nextSpecies = dex.species.learnsetParent(nextSpecies); + } + } + // Now that we have our list of possible sources, intersect it with the current list if (!moveSources.size()) { if (cantLearnReason) return `'s move ${move.name} ${cantLearnReason}`; diff --git a/test/sim/team-validator/misc.js b/test/sim/team-validator/misc.js index fc86a05a7fec..3b5fcb641460 100644 --- a/test/sim/team-validator/misc.js +++ b/test/sim/team-validator/misc.js @@ -200,4 +200,11 @@ describe('Team Validator', function () { ]; assert.false.legalTeam(team, 'gen8ou'); }); + + it('should disallow certain combinations of prevo/evo-exclusive moves', function () { + const team = [ + {species: 'slowking', ability: 'oblivious', moves: ['counter', 'slackoff'], evs: {hp: 1}}, + ]; + assert.false.legalTeam(team, 'gen7ou'); + }); });