@pkmn/sim 0.5.10 → 0.5.13

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 (83) hide show
  1. package/README.md +5 -0
  2. package/build/config/formats.js +376 -299
  3. package/build/config/formats.js.map +1 -1
  4. package/build/data/abilities.js +9 -9
  5. package/build/data/abilities.js.map +1 -1
  6. package/build/data/aliases.js +3 -0
  7. package/build/data/aliases.js.map +1 -1
  8. package/build/data/conditions.js +8 -12
  9. package/build/data/conditions.js.map +1 -1
  10. package/build/data/formats-data.js +36 -35
  11. package/build/data/formats-data.js.map +1 -1
  12. package/build/data/items.js +1 -1
  13. package/build/data/items.js.map +1 -1
  14. package/build/data/learnsets.js +5 -4
  15. package/build/data/learnsets.js.map +1 -1
  16. package/build/data/mods/gen1/formats-data.js +6 -4
  17. package/build/data/mods/gen1/formats-data.js.map +1 -1
  18. package/build/data/mods/gen1/moves.js +2 -4
  19. package/build/data/mods/gen1/moves.js.map +1 -1
  20. package/build/data/mods/gen3/formats-data.js +2 -2
  21. package/build/data/mods/gen3/formats-data.js.map +1 -1
  22. package/build/data/mods/gen6/formats-data.js +3 -3
  23. package/build/data/mods/gen6/formats-data.js.map +1 -1
  24. package/build/data/mods/gen7/formats-data.js +1 -1
  25. package/build/data/mods/gen7/formats-data.js.map +1 -1
  26. package/build/data/moves.js +14 -12
  27. package/build/data/moves.js.map +1 -1
  28. package/build/data/pokedex.js +2 -2
  29. package/build/data/pokedex.js.map +1 -1
  30. package/build/data/rulesets.js +1 -1
  31. package/build/data/rulesets.js.map +1 -1
  32. package/build/data/tags.js +4 -4
  33. package/build/data/tags.js.map +1 -1
  34. package/build/data/text/moves.js +1 -0
  35. package/build/data/text/moves.js.map +1 -1
  36. package/build/sim/battle-actions.js +0 -6
  37. package/build/sim/battle-actions.js.map +1 -1
  38. package/build/sim/battle-queue.js +1 -3
  39. package/build/sim/battle-queue.js.map +1 -1
  40. package/build/sim/battle.js +13 -11
  41. package/build/sim/battle.js.map +1 -1
  42. package/build/sim/dex-conditions.js +11 -3
  43. package/build/sim/dex-conditions.js.map +1 -1
  44. package/build/sim/dex-data.js +2 -0
  45. package/build/sim/dex-data.js.map +1 -1
  46. package/build/sim/dex-formats.js +1 -0
  47. package/build/sim/dex-formats.js.map +1 -1
  48. package/build/sim/dex-items.js +1 -0
  49. package/build/sim/dex-items.js.map +1 -1
  50. package/build/sim/dex-moves.js +1 -0
  51. package/build/sim/dex-moves.js.map +1 -1
  52. package/build/sim/dex-species.js +1 -0
  53. package/build/sim/dex-species.js.map +1 -1
  54. package/build/sim/team-validator.js +1 -1
  55. package/build/sim/team-validator.js.map +1 -1
  56. package/config/formats.ts +363 -283
  57. package/data/abilities.ts +9 -9
  58. package/data/aliases.ts +3 -0
  59. package/data/conditions.ts +8 -10
  60. package/data/formats-data.ts +36 -35
  61. package/data/items.ts +1 -1
  62. package/data/learnsets.ts +5 -4
  63. package/data/mods/gen1/formats-data.ts +6 -4
  64. package/data/mods/gen1/moves.ts +2 -4
  65. package/data/mods/gen3/formats-data.ts +2 -2
  66. package/data/mods/gen6/formats-data.ts +3 -3
  67. package/data/mods/gen7/formats-data.ts +1 -1
  68. package/data/moves.ts +13 -12
  69. package/data/pokedex.ts +2 -2
  70. package/data/rulesets.ts +1 -1
  71. package/data/tags.ts +4 -4
  72. package/data/text/moves.ts +2 -0
  73. package/package.json +3 -3
  74. package/sim/battle-actions.ts +0 -7
  75. package/sim/battle-queue.ts +1 -3
  76. package/sim/battle.ts +4 -1
  77. package/sim/dex-conditions.ts +10 -3
  78. package/sim/dex-data.ts +2 -0
  79. package/sim/dex-formats.ts +1 -0
  80. package/sim/dex-items.ts +1 -0
  81. package/sim/dex-moves.ts +1 -0
  82. package/sim/dex-species.ts +1 -0
  83. package/sim/team-validator.ts +1 -1
package/data/moves.ts CHANGED
@@ -664,9 +664,9 @@ export const Moves: {[moveid: string]: MoveData} = {
664
664
  return false;
665
665
  }
666
666
 
667
- if (effect.id === 'cutecharm') {
667
+ if (effect.name === 'Cute Charm') {
668
668
  this.add('-start', pokemon, 'Attract', '[from] ability: Cute Charm', '[of] ' + source);
669
- } else if (effect.id === 'destinyknot') {
669
+ } else if (effect.name === 'Destiny Knot') {
670
670
  this.add('-start', pokemon, 'Attract', '[from] item: Destiny Knot', '[of] ' + source);
671
671
  } else {
672
672
  this.add('-start', pokemon, 'Attract');
@@ -4103,7 +4103,7 @@ export const Moves: {[moveid: string]: MoveData} = {
4103
4103
  },
4104
4104
  onFieldStart(field, source, effect) {
4105
4105
  if (effect?.effectType === 'Ability') {
4106
- this.add('-fieldstart', 'move: Electric Terrain', '[from] ability: ' + effect, '[of] ' + source);
4106
+ this.add('-fieldstart', 'move: Electric Terrain', '[from] ability: ' + effect.name, '[of] ' + source);
4107
4107
  } else {
4108
4108
  this.add('-fieldstart', 'move: Electric Terrain');
4109
4109
  }
@@ -7196,7 +7196,7 @@ export const Moves: {[moveid: string]: MoveData} = {
7196
7196
  },
7197
7197
  onFieldStart(field, source, effect) {
7198
7198
  if (effect?.effectType === 'Ability') {
7199
- this.add('-fieldstart', 'move: Grassy Terrain', '[from] ability: ' + effect, '[of] ' + source);
7199
+ this.add('-fieldstart', 'move: Grassy Terrain', '[from] ability: ' + effect.name, '[of] ' + source);
7200
7200
  } else {
7201
7201
  this.add('-fieldstart', 'move: Grassy Terrain');
7202
7202
  }
@@ -11449,7 +11449,7 @@ export const Moves: {[moveid: string]: MoveData} = {
11449
11449
  },
11450
11450
  onFieldStart(field, source, effect) {
11451
11451
  if (effect?.effectType === 'Ability') {
11452
- this.add('-fieldstart', 'move: Misty Terrain', '[from] ability: ' + effect, '[of] ' + source);
11452
+ this.add('-fieldstart', 'move: Misty Terrain', '[from] ability: ' + effect.name, '[of] ' + source);
11453
11453
  } else {
11454
11454
  this.add('-fieldstart', 'move: Misty Terrain');
11455
11455
  }
@@ -13244,7 +13244,7 @@ export const Moves: {[moveid: string]: MoveData} = {
13244
13244
  },
13245
13245
  onFieldStart(field, source, effect) {
13246
13246
  if (effect?.effectType === 'Ability') {
13247
- this.add('-fieldstart', 'move: Psychic Terrain', '[from] ability: ' + effect, '[of] ' + source);
13247
+ this.add('-fieldstart', 'move: Psychic Terrain', '[from] ability: ' + effect.name, '[of] ' + source);
13248
13248
  } else {
13249
13249
  this.add('-fieldstart', 'move: Psychic Terrain');
13250
13250
  }
@@ -14122,17 +14122,18 @@ export const Moves: {[moveid: string]: MoveData} = {
14122
14122
  num: 804,
14123
14123
  accuracy: 100,
14124
14124
  basePower: 70,
14125
+ basePowerCallback(source, target, move) {
14126
+ if (this.field.isTerrain('electricterrain') && target.isGrounded()) {
14127
+ if (!source.isAlly(target)) this.hint(`${move.name}'s BP doubled on grounded target.`);
14128
+ return move.basePower * 2;
14129
+ }
14130
+ return move.basePower;
14131
+ },
14125
14132
  category: "Special",
14126
14133
  name: "Rising Voltage",
14127
14134
  pp: 20,
14128
14135
  priority: 0,
14129
14136
  flags: {protect: 1, mirror: 1},
14130
- onBasePower(basePower, pokemon, target) {
14131
- if (this.field.isTerrain('electricterrain') && target.isGrounded()) {
14132
- this.debug('terrain buff');
14133
- return this.chainModify(2);
14134
- }
14135
- },
14136
14137
  secondary: null,
14137
14138
  target: "normal",
14138
14139
  type: "Electric",
package/data/pokedex.ts CHANGED
@@ -16366,7 +16366,7 @@ export const Pokedex: {[speciesid: string]: SpeciesData} = {
16366
16366
  color: "Green",
16367
16367
  prevo: "Basculin-White-Striped",
16368
16368
  evoType: "other",
16369
- evoCondition: "Receive 294+ recoil from one move without fainting",
16369
+ evoCondition: "Receive 294+ recoil without fainting",
16370
16370
  eggGroups: ["Water 2"],
16371
16371
  otherFormes: ["Basculegion-F"],
16372
16372
  formeOrder: ["Basculegion", "Basculegion-F"],
@@ -16385,7 +16385,7 @@ export const Pokedex: {[speciesid: string]: SpeciesData} = {
16385
16385
  color: "Green",
16386
16386
  prevo: "Basculin-White-Striped",
16387
16387
  evoType: "other",
16388
- evoCondition: "Receive 294+ recoil from one move without fainting",
16388
+ evoCondition: "Receive 294+ recoil without fainting",
16389
16389
  eggGroups: ["Water 2"],
16390
16390
  },
16391
16391
  sneasler: {
package/data/rulesets.ts CHANGED
@@ -671,7 +671,7 @@ export const Rulesets: {[k: string]: FormatData} = {
671
671
  name: 'Gravity Sleep Clause',
672
672
  desc: "Bans sleep moves below 100% accuracy, in conjunction with Gravity or Gigantamax Orbeetle",
673
673
  banlist: [
674
- 'Gravity ++ Grass Whistle', 'Gravity ++ Hypnosis', 'Gravity ++ Lovely Kiss', 'Gravity ++ Sing', 'Gravity ++ Sleep Powder',
674
+ 'Gravity ++ Dark Void', 'Gravity ++ Grass Whistle', 'Gravity ++ Hypnosis', 'Gravity ++ Lovely Kiss', 'Gravity ++ Sing', 'Gravity ++ Sleep Powder',
675
675
  ],
676
676
  onValidateTeam(team) {
677
677
  let hasOrbeetle = false;
package/data/tags.ts CHANGED
@@ -197,10 +197,10 @@ export const Tags: {[id: string]: TagData} = {
197
197
  nduubl: {
198
198
  name: "ND UUBL",
199
199
  speciesFilter: species => [
200
- 'Aerodactyl-Mega', 'Blacephalon', 'Diancie-Mega', 'Gallade-Mega', 'Gardevoir-Mega', 'Gengar', 'Gyarados', 'Gyarados-Mega',
201
- 'Hawlucha', 'Heracross-Mega', 'Hoopa-Unbound', 'Hydreigon', 'Jirachi', 'Latias', 'Latias-Mega', 'Latios', 'Latios-Mega', 'Manaphy',
202
- 'Medicham-Mega', 'Mew', 'Pinsir-Mega', 'Sableye-Mega', 'Slowbro-Mega', 'Slowking-Galar', 'Thundurus', 'Thundurus-Therian', 'Venusaur-Mega',
203
- 'Xurkitree', 'Zapdos-Galar',
200
+ 'Aerodactyl-Mega', 'Alakazam', 'Blacephalon', 'Blaziken', 'Diancie-Mega', 'Gallade-Mega', 'Gardevoir-Mega', 'Gengar', 'Gyarados',
201
+ 'Gyarados-Mega', 'Hawlucha', 'Heracross-Mega', 'Hoopa-Unbound', 'Hydreigon', 'Jirachi', 'Latias', 'Latias-Mega', 'Latios', 'Latios-Mega',
202
+ 'Manaphy', 'Medicham-Mega', 'Mew', 'Pinsir-Mega', 'Sableye-Mega', 'Slowbro-Mega', 'Slowking-Galar', 'Thundurus', 'Thundurus-Therian',
203
+ 'Venusaur-Mega', 'Xurkitree', 'Zapdos-Galar',
204
204
  ].includes(species.name),
205
205
  },
206
206
 
@@ -900,6 +900,8 @@ export const MovesText: {[k: string]: MoveText} = {
900
900
  desc: "Causes the user's types to become the same as the current types of the target.",
901
901
  shortDesc: "User becomes the same type as the target.",
902
902
  },
903
+
904
+ typeChange: " Converted type to [SOURCE]'s!", // gen 1 only
903
905
  },
904
906
  conversion2: {
905
907
  name: "Conversion 2",
package/package.json CHANGED
@@ -1,6 +1,6 @@
1
1
  {
2
2
  "name": "@pkmn/sim",
3
- "version": "0.5.10",
3
+ "version": "0.5.13",
4
4
  "description": "An automatically generated extraction of just the simulator portion of Pokémon Showdown",
5
5
  "homepage": "https://psim.us",
6
6
  "main": "build/sim/index.js",
@@ -27,11 +27,11 @@
27
27
  "sim"
28
28
  ],
29
29
  "dependencies": {
30
- "@pkmn/sets": "^2.0.0",
30
+ "@pkmn/sets": "^3.0.0",
31
31
  "@pkmn/streams": "^1.0.0"
32
32
  },
33
33
  "devDependencies": {
34
- "mocha": "^9.2.1"
34
+ "mocha": "^9.2.2"
35
35
  },
36
36
  "scripts": {
37
37
  "compile": "tsc -p .",
@@ -1779,13 +1779,6 @@ export class BattleActions {
1779
1779
  const speciesid = pokemon.canMegaEvo || pokemon.canUltraBurst;
1780
1780
  if (!speciesid) return false;
1781
1781
 
1782
- // Pokémon affected by Sky Drop cannot mega evolve. Enforce it here for now.
1783
- for (const foeActive of pokemon.foes()) {
1784
- if (foeActive.volatiles['skydrop']?.source === pokemon) {
1785
- return false;
1786
- }
1787
- }
1788
-
1789
1782
  pokemon.formeChange(speciesid, pokemon.getItem(), true);
1790
1783
 
1791
1784
  // Limit one mega evolution
@@ -203,9 +203,7 @@ export class BattleQueue {
203
203
  choice: 'beforeTurnMove', pokemon: action.pokemon, move: action.move, targetLoc: action.targetLoc,
204
204
  }));
205
205
  }
206
- if (action.mega) {
207
- // TODO: Check that the Pokémon is not affected by Sky Drop.
208
- // (This is currently being done in `runMegaEvo`).
206
+ if (action.mega && !action.pokemon.isSkyDropped()) {
209
207
  actions.unshift(...this.resolveAction({
210
208
  choice: 'megaEvo',
211
209
  pokemon: action.pokemon,
package/sim/battle.ts CHANGED
@@ -479,6 +479,7 @@ export class Battle {
479
479
  if (!handler.state.duration) {
480
480
  const endCallArgs = handler.endCallArgs || [handler.effectHolder, effect.id];
481
481
  handler.end.call(...endCallArgs as [any, ...any[]]);
482
+ if (this.ended) return;
482
483
  continue;
483
484
  }
484
485
  }
@@ -1557,8 +1558,9 @@ export class Battle {
1557
1558
  // These are checked before the 100 turn minimum as the battle cannot progress if they are true
1558
1559
  if (this.gen <= 1) {
1559
1560
  const noProgressPossible = this.sides.every(side => {
1560
- const foeAllGhosts = side.foe.pokemon.every(pokemon => pokemon.types.includes('Ghost'));
1561
+ const foeAllGhosts = side.foe.pokemon.every(pokemon => pokemon.fainted || pokemon.types.includes('Ghost'));
1561
1562
  const foeAllTransform = side.foe.pokemon.every(pokemon => (
1563
+ pokemon.fainted ||
1562
1564
  // true if transforming into this pokemon would lead to an endless battle
1563
1565
  // Transform will fail (depleting PP) if used against Ditto in Stadium 1
1564
1566
  (this.dex.currentMod !== 'gen1stadium' || pokemon.species.id !== 'ditto') &&
@@ -1567,6 +1569,7 @@ export class Battle {
1567
1569
  pokemon.moves.every(moveid => moveid === 'transform')
1568
1570
  ));
1569
1571
  return side.pokemon.every(pokemon => (
1572
+ pokemon.fainted ||
1570
1573
  // frozen pokemon can't thaw in gen 1 without outside help
1571
1574
  pokemon.status === 'frz' ||
1572
1575
  // a pokemon can't lose PP if it Transforms into a pokemon with only Transform
@@ -640,6 +640,7 @@ export class Condition extends BasicEffect implements
640
640
 
641
641
  constructor(data: AnyObject) {
642
642
  super(data);
643
+ // eslint-disable-next-line @typescript-eslint/no-this-alias
643
644
  data = this;
644
645
  this.effectType = (['Weather', 'Status'].includes(data.effectType) ? data.effectType : 'Condition');
645
646
  }
@@ -659,7 +660,10 @@ export class DexConditions {
659
660
  if (!name) return EMPTY_CONDITION;
660
661
  if (typeof name !== 'string') return name as Condition;
661
662
 
662
- return this.getByID(name.startsWith('item:') || name.startsWith('ability:') ? name as ID : toID(name));
663
+ const special = name.startsWith('item:') ? `item:${toID(name.slice(5))}` as ID :
664
+ name.startsWith('ability:') ? `ability:${toID(name.slice(8))}` as ID :
665
+ name.startsWith('move:') ? `move:${toID(name.slice(5))}` as ID : undefined;
666
+ return this.getByID(special || toID(name));
663
667
  }
664
668
 
665
669
  getByID(id: ID): Condition {
@@ -671,10 +675,13 @@ export class DexConditions {
671
675
  let found;
672
676
  if (id.startsWith('item:')) {
673
677
  const item = this.dex.items.getByID(id.slice(5) as ID);
674
- condition = {...item, id: 'item:' + item.id as ID} as any as Condition;
678
+ condition = item as any as Condition;
675
679
  } else if (id.startsWith('ability:')) {
676
680
  const ability = this.dex.abilities.getByID(id.slice(8) as ID);
677
- condition = {...ability, id: 'ability:' + ability.id as ID} as any as Condition;
681
+ condition = ability as any as Condition;
682
+ } else if (id.startsWith('move:')) {
683
+ const move = this.dex.moves.getByID(id.slice(5) as ID);
684
+ condition = move as any as Condition;
678
685
  } else if (this.dex.data.Rulesets.hasOwnProperty(id)) {
679
686
  condition = this.dex.formats.get(id) as any as Condition;
680
687
  } else if (this.dex.data.Conditions.hasOwnProperty(id)) {
package/sim/dex-data.ts CHANGED
@@ -117,6 +117,7 @@ export class BasicEffect implements EffectData {
117
117
 
118
118
  constructor(data: AnyObject) {
119
119
  this.exists = true;
120
+ // eslint-disable-next-line @typescript-eslint/no-this-alias
120
121
  Object.assign(this, data);
121
122
 
122
123
  this.name = Utils.getString(data.name).trim();
@@ -148,6 +149,7 @@ export class Nature extends BasicEffect implements Readonly<BasicEffect & Nature
148
149
  readonly minus?: StatIDExceptHP;
149
150
  constructor(data: AnyObject) {
150
151
  super(data);
152
+ // eslint-disable-next-line @typescript-eslint/no-this-alias
151
153
  data = this;
152
154
 
153
155
  this.fullname = `nature: ${this.name}`;
@@ -435,6 +435,7 @@ export class Format extends BasicEffect implements Readonly<BasicEffect> {
435
435
 
436
436
  constructor(data: AnyObject) {
437
437
  super(data);
438
+ // eslint-disable-next-line @typescript-eslint/no-this-alias
438
439
  data = this;
439
440
 
440
441
  this.mod = Utils.getString(data.mod) || 'gen8';
package/sim/dex-items.ts CHANGED
@@ -113,6 +113,7 @@ export class Item extends BasicEffect implements Readonly<BasicEffect> {
113
113
 
114
114
  constructor(data: AnyObject) {
115
115
  super(data);
116
+ // eslint-disable-next-line @typescript-eslint/no-this-alias
116
117
  data = this;
117
118
 
118
119
  this.fullname = `item: ${this.name}`;
package/sim/dex-moves.ts CHANGED
@@ -470,6 +470,7 @@ export class DataMove extends BasicEffect implements Readonly<BasicEffect & Move
470
470
 
471
471
  constructor(data: AnyObject) {
472
472
  super(data);
473
+ // eslint-disable-next-line @typescript-eslint/no-this-alias
473
474
  data = this;
474
475
 
475
476
  this.fullname = `move: ${this.name}`;
@@ -242,6 +242,7 @@ export class Species extends BasicEffect implements Readonly<BasicEffect & Speci
242
242
 
243
243
  constructor(data: AnyObject) {
244
244
  super(data);
245
+ // eslint-disable-next-line @typescript-eslint/no-this-alias
245
246
  data = this;
246
247
 
247
248
  this.fullname = `pokemon: ${data.name}`;
@@ -712,7 +712,7 @@ export class TeamValidator {
712
712
  }
713
713
 
714
714
  let isFromRBYEncounter = false;
715
- if (this.gen === 1 && !this.ruleTable.has('allowtradeback')) {
715
+ if (this.gen === 1 && ruleTable.has('obtainablemisc') && !this.ruleTable.has('allowtradeback')) {
716
716
  let lowestEncounterLevel;
717
717
  for (const encounter of learnsetSpecies.encounters || []) {
718
718
  if (encounter.generation !== 1) continue;