@pkmn/sim 0.7.47 → 0.7.48

This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
Files changed (38) hide show
  1. package/build/cjs/config/formats.js +98 -56
  2. package/build/cjs/config/formats.js.map +1 -1
  3. package/build/cjs/data/abilities.js +4 -1
  4. package/build/cjs/data/abilities.js.map +1 -1
  5. package/build/cjs/data/aliases.js +1 -1
  6. package/build/cjs/data/formats-data.js +36 -23
  7. package/build/cjs/data/formats-data.js.map +1 -1
  8. package/build/cjs/data/learnsets.js +157 -4
  9. package/build/cjs/data/learnsets.js.map +1 -1
  10. package/build/cjs/data/legality.js +260 -50
  11. package/build/cjs/data/legality.js.map +1 -1
  12. package/build/cjs/data/mods/gen4/moves.js +3 -3
  13. package/build/cjs/data/mods/gen4/moves.js.map +1 -1
  14. package/build/cjs/data/pokedex.js +39 -3
  15. package/build/cjs/data/pokedex.js.map +1 -1
  16. package/build/cjs/sim/team-validator.js +100 -23
  17. package/build/cjs/sim/team-validator.js.map +1 -1
  18. package/build/esm/config/formats.mjs +98 -56
  19. package/build/esm/config/formats.mjs.map +1 -1
  20. package/build/esm/data/abilities.mjs +4 -1
  21. package/build/esm/data/abilities.mjs.map +1 -1
  22. package/build/esm/data/aliases.mjs +1 -1
  23. package/build/esm/data/formats-data.mjs +36 -23
  24. package/build/esm/data/formats-data.mjs.map +1 -1
  25. package/build/esm/data/learnsets.mjs +157 -4
  26. package/build/esm/data/learnsets.mjs.map +1 -1
  27. package/build/esm/data/legality.mjs +260 -50
  28. package/build/esm/data/legality.mjs.map +1 -1
  29. package/build/esm/data/mods/gen4/moves.mjs +3 -3
  30. package/build/esm/data/mods/gen4/moves.mjs.map +1 -1
  31. package/build/esm/data/pokedex.mjs +39 -3
  32. package/build/esm/data/pokedex.mjs.map +1 -1
  33. package/build/esm/sim/team-validator.mjs +100 -23
  34. package/build/esm/sim/team-validator.mjs.map +1 -1
  35. package/build/types/sim/exported-global-types.d.ts +14 -1
  36. package/build/types/sim/global-types.d.ts +14 -1
  37. package/build/types/sim/team-validator.d.ts +16 -0
  38. package/package.json +1 -1
@@ -45,6 +45,9 @@ export class PokemonSources {
45
45
  add(source, limitedEggMove) {
46
46
  if (this.sources[this.sources.length - 1] !== source)
47
47
  this.sources.push(source);
48
+ if (limitedEggMove && source.substr(0, 3) === '1ET') {
49
+ this.possiblyLimitedEggMoves = [limitedEggMove];
50
+ }
48
51
  if (limitedEggMove && this.limitedEggMoves !== null) {
49
52
  this.limitedEggMoves = [limitedEggMove];
50
53
  }
@@ -79,6 +82,24 @@ export class PokemonSources {
79
82
  return max;
80
83
  }
81
84
  intersectWith(other) {
85
+ if (this.pomegEventEgg && other.pomegEggMoves) {
86
+ const newSources = [];
87
+ for (const source of other.sources) {
88
+ newSources.push(source.substr(0, 2) === '3E' ? this.pomegEventEgg : source);
89
+ }
90
+ other.sources = newSources;
91
+ }
92
+ else if (other.pomegEventEgg && this.pomegEventEgg !== null) {
93
+ const newSources = [];
94
+ for (const source of this.sources) {
95
+ newSources.push(source.substr(0, 2) === '3E' ? other.pomegEventEgg : source);
96
+ }
97
+ this.sources = newSources;
98
+ this.pomegEventEgg = other.pomegEventEgg;
99
+ }
100
+ else if (!other.pomegEggMoves && !other.sourcesBefore) {
101
+ this.pomegEventEgg = null;
102
+ }
82
103
  if (other.sourcesBefore || this.sourcesBefore) {
83
104
  // having sourcesBefore is the equivalent of having everything before that gen
84
105
  // in sources, so we fill the other array in preparation for intersection
@@ -128,6 +149,37 @@ export class PokemonSources {
128
149
  this.limitedEggMoves.push(...other.limitedEggMoves);
129
150
  }
130
151
  }
152
+ if (other.possiblyLimitedEggMoves) {
153
+ if (!this.possiblyLimitedEggMoves) {
154
+ this.possiblyLimitedEggMoves = other.possiblyLimitedEggMoves;
155
+ }
156
+ else {
157
+ this.possiblyLimitedEggMoves.push(...other.possiblyLimitedEggMoves);
158
+ }
159
+ }
160
+ if (other.pomegEggMoves) {
161
+ if (!this.pomegEggMoves) {
162
+ this.pomegEggMoves = other.pomegEggMoves;
163
+ }
164
+ else {
165
+ this.pomegEggMoves.push(...other.pomegEggMoves);
166
+ }
167
+ }
168
+ let eggTradebackLegal = false;
169
+ for (const source of this.sources) {
170
+ if (source.substr(0, 3) === '1ET') {
171
+ eggTradebackLegal = true;
172
+ break;
173
+ }
174
+ }
175
+ if (!eggTradebackLegal && this.possiblyLimitedEggMoves) {
176
+ for (const eggMove of this.possiblyLimitedEggMoves) {
177
+ if (!this.limitedEggMoves)
178
+ this.limitedEggMoves = [];
179
+ if (!this.limitedEggMoves.includes(eggMove))
180
+ this.limitedEggMoves.push(eggMove);
181
+ }
182
+ }
131
183
  this.moveEvoCarryCount += other.moveEvoCarryCount;
132
184
  this.dreamWorldMoveCount += other.dreamWorldMoveCount;
133
185
  if (other.sourcesAfter > this.sourcesAfter)
@@ -640,20 +692,23 @@ export class TeamValidator {
640
692
  evoSpecies = dex.species.get(evoSpecies.prevo);
641
693
  }
642
694
  }
643
- const moveProblems = this.validateMoves(outOfBattleSpecies, set.moves, setSources, set, name, moveLegalityWhitelist);
695
+ let moveProblems;
644
696
  if (ruleTable.has('obtainablemoves')) {
697
+ moveProblems = this.validateMoves(outOfBattleSpecies, set.moves, setSources, set, name, moveLegalityWhitelist);
645
698
  problems.push(...moveProblems);
646
699
  }
647
700
  let eventOnlyData;
648
701
  if (!setSources.sourcesBefore && setSources.sources.length) {
649
- let legal = false;
702
+ const legalSources = [];
650
703
  for (const source of setSources.sources) {
651
704
  if (this.validateSource(set, source, setSources, outOfBattleSpecies))
652
705
  continue;
653
- legal = true;
654
- break;
706
+ legalSources.push(source);
655
707
  }
656
- if (!legal) {
708
+ if (legalSources.length) {
709
+ setSources.sources = legalSources;
710
+ }
711
+ else {
657
712
  let nonEggSource = null;
658
713
  for (const source of setSources.sources) {
659
714
  if (source.charAt(1) !== 'E') {
@@ -730,15 +785,6 @@ export class TeamValidator {
730
785
  }
731
786
  }
732
787
  }
733
- // Attempt move validation again after verifying Pokemon GO origin
734
- if (setSources.isFromPokemonGo) {
735
- setSources.restrictiveMoves = [];
736
- setSources.sources = ['8V'];
737
- setSources.sourcesBefore = 0;
738
- if (!moveProblems.length && ruleTable.has('obtainablemoves')) {
739
- problems.push(...this.validateMoves(outOfBattleSpecies, set.moves, setSources, set, name, moveLegalityWhitelist));
740
- }
741
- }
742
788
  // Hardcoded forced validation for Pokemon GO
743
789
  const pokemonGoOnlySpecies = ['meltan', 'melmetal', 'gimmighoulroaming'];
744
790
  if (ruleTable.has('obtainablemisc') && (pokemonGoOnlySpecies.includes(species.id))) {
@@ -753,6 +799,15 @@ export class TeamValidator {
753
799
  if (ruleTable.isBanned('nonexistent')) {
754
800
  problems.push(...this.validateStats(set, species, setSources, pokemonGoProblems));
755
801
  }
802
+ // Attempt move validation again after verifying Pokemon GO origin
803
+ if (ruleTable.has('obtainablemoves') && setSources.isFromPokemonGo) {
804
+ setSources.restrictiveMoves = [];
805
+ setSources.sources = ['8V'];
806
+ setSources.sourcesBefore = 0;
807
+ if (moveProblems && !moveProblems.length) {
808
+ problems.push(...this.validateMoves(outOfBattleSpecies, set.moves, setSources, set, name, moveLegalityWhitelist));
809
+ }
810
+ }
756
811
  if (ruleTable.has('obtainablemoves')) {
757
812
  if (species.id === 'keldeo' && set.moves.includes('secretsword') && this.minSourceGen > 5 && dex.gen <= 7) {
758
813
  problems.push(`${name} has Secret Sword, which is only compatible with Keldeo-Ordinary obtained from Gen 5.`);
@@ -818,7 +873,8 @@ export class TeamValidator {
818
873
  if (nameSpecies.baseSpecies === species.baseSpecies) {
819
874
  set.name = species.baseSpecies;
820
875
  }
821
- else if (nameSpecies.name !== species.name && nameSpecies.name !== species.baseSpecies) {
876
+ else if (nameSpecies.name !== species.name &&
877
+ nameSpecies.name !== species.baseSpecies && ruleTable.has('nicknameclause')) {
822
878
  // nickname species doesn't match actual species
823
879
  // Nickname Clause
824
880
  problems.push(`${name} must not be nicknamed a different Pokémon species than what it actually is.`);
@@ -1145,16 +1201,18 @@ export class TeamValidator {
1145
1201
  const fathers = [];
1146
1202
  // Gen 6+ don't have egg move incompatibilities
1147
1203
  // (except for certain cases with baby Pokemon not handled here)
1148
- if (!getAll && eggGen >= 6)
1204
+ if (!getAll && eggGen >= 6 && species.gender !== 'F')
1149
1205
  return true;
1150
- const eggMoves = setSources.limitedEggMoves;
1206
+ let eggMoves = setSources.limitedEggMoves;
1207
+ if (eggGen === 3)
1208
+ eggMoves = eggMoves?.filter(eggMove => !setSources.pomegEggMoves?.includes(eggMove));
1151
1209
  // must have 2 or more egg moves to have egg move incompatibilities
1152
1210
  if (!eggMoves) {
1153
1211
  // happens often in gen 1-6 LC if your only egg moves are level-up moves,
1154
1212
  // which aren't limited and so aren't in `limitedEggMoves`
1155
1213
  return getAll ? ['*'] : true;
1156
1214
  }
1157
- if (!getAll && eggMoves.length <= 1)
1215
+ if (!getAll && eggMoves.length <= 1 && species.gender !== 'F')
1158
1216
  return true;
1159
1217
  // gen 1 eggs come from gen 2 breeding
1160
1218
  const dex = this.dex.gen === 1 ? this.dex.mod('gen2') : this.dex;
@@ -1245,6 +1303,8 @@ export class TeamValidator {
1245
1303
  learnset = this.dex.species.getLearnset(curSpecies.id);
1246
1304
  if (learnset && learnset[move]) {
1247
1305
  for (const moveSource of learnset[move]) {
1306
+ if (eggGen > 8 && parseInt(moveSource.charAt(0)) <= 8)
1307
+ continue;
1248
1308
  if (parseInt(moveSource.charAt(0)) > eggGen)
1249
1309
  continue;
1250
1310
  const canLearnFromSmeargle = moveSource.charAt(1) === 'E' && canBreedWithSmeargle;
@@ -2196,7 +2256,8 @@ export class TeamValidator {
2196
2256
  // redundant
2197
2257
  if (learnedGen <= moveSources.sourcesBefore)
2198
2258
  continue;
2199
- if (baseSpecies.evoRegion === 'Alola' && checkingPrevo && learnedGen >= 8) {
2259
+ if (baseSpecies.evoRegion === 'Alola' && checkingPrevo && learnedGen >= 8 &&
2260
+ (dex.gen < 9 || learned.charAt(1) !== 'E')) {
2200
2261
  cantLearnReason = `is from a ${species.name} that can't be transferred to USUM to evolve into ${baseSpecies.name}.`;
2201
2262
  continue;
2202
2263
  }
@@ -2233,6 +2294,7 @@ export class TeamValidator {
2233
2294
  }
2234
2295
  else if (level >= 5 && learnedGen === 3 && species.canHatch) {
2235
2296
  // Pomeg Glitch
2297
+ learned = learnedGen + 'Epomeg';
2236
2298
  }
2237
2299
  else if ((!species.gender || species.gender === 'F') &&
2238
2300
  learnedGen >= 2 && species.canHatch && !setSources.isFromPokemonGo) {
@@ -2247,7 +2309,8 @@ export class TeamValidator {
2247
2309
  }
2248
2310
  }
2249
2311
  // Gen 8+ egg moves can be taught to any pokemon from any source
2250
- if (learnedGen >= 8 && learned.charAt(1) === 'E' || 'LMTR'.includes(learned.charAt(1))) {
2312
+ if (learnedGen >= 8 && learned.charAt(1) === 'E' && learned.slice(1) !== 'Eany' &&
2313
+ learned.slice(1) !== 'Epomeg' || 'LMTR'.includes(learned.charAt(1))) {
2251
2314
  if (learnedGen === dex.gen && learned.charAt(1) !== 'R') {
2252
2315
  // current-gen level-up, TM or tutor moves:
2253
2316
  // always available
@@ -2276,7 +2339,17 @@ export class TeamValidator {
2276
2339
  // only if hatched from an egg
2277
2340
  let limitedEggMove = undefined;
2278
2341
  if (learned.slice(1) === 'Eany') {
2279
- limitedEggMove = null;
2342
+ if (species.gender === 'F') {
2343
+ limitedEggMove = move.id;
2344
+ }
2345
+ else {
2346
+ limitedEggMove = null;
2347
+ }
2348
+ }
2349
+ else if (learned.slice(1) === 'Epomeg') {
2350
+ // Pomeg glitched moves have to be from an egg but since they aren't true egg moves,
2351
+ // there should be no breeding restrictions
2352
+ moveSources.pomegEggMoves = [move.id];
2280
2353
  }
2281
2354
  else if (learnedGen < 6) {
2282
2355
  limitedEggMove = move.id;
@@ -2284,7 +2357,7 @@ export class TeamValidator {
2284
2357
  learned = learnedGen + 'E' + (species.prevo ? species.id : '');
2285
2358
  if (tradebackEligible && learnedGen === 2 && move.gen <= 1) {
2286
2359
  // can tradeback
2287
- moveSources.add('1ET' + learned.slice(2));
2360
+ moveSources.add('1ET' + learned.slice(2), limitedEggMove);
2288
2361
  }
2289
2362
  moveSources.add(learned, limitedEggMove);
2290
2363
  }
@@ -2298,6 +2371,10 @@ export class TeamValidator {
2298
2371
  moveSources.add('1ST' + learned.slice(2) + ' ' + species.id);
2299
2372
  }
2300
2373
  moveSources.add(learned + ' ' + species.id);
2374
+ const eventLearnset = dex.species.getLearnsetData(species.id);
2375
+ if (eventLearnset.eventData?.[parseInt(learned.charAt(2))].emeraldEventEgg && learnedGen === 3) {
2376
+ moveSources.pomegEventEgg = learned + ' ' + species.id;
2377
+ }
2301
2378
  }
2302
2379
  else if (learned.charAt(1) === 'D') {
2303
2380
  // DW moves:
@@ -2424,7 +2501,7 @@ export class TeamValidator {
2424
2501
  // different learnsets. To prevent a leak, we make them show up as their
2425
2502
  // base forme, but hardcode their learnsets into Rockruff-Dusk and
2426
2503
  // Greninja-Ash
2427
- if (['Gastrodon', 'Pumpkaboo', 'Sinistea'].includes(species.baseSpecies) && species.forme) {
2504
+ if (['Gastrodon', 'Pumpkaboo', 'Sinistea', 'Tatsugiri'].includes(species.baseSpecies) && species.forme) {
2428
2505
  return this.dex.species.get(species.baseSpecies);
2429
2506
  }
2430
2507
  else if (species.name === 'Lycanroc-Dusk') {