@pkmn/sim 0.5.23 → 0.5.26

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 (74) hide show
  1. package/LICENSE +1 -1
  2. package/build/config/formats.js +323 -197
  3. package/build/config/formats.js.map +1 -1
  4. package/build/data/aliases.js +7 -3
  5. package/build/data/aliases.js.map +1 -1
  6. package/build/data/formats-data.js +823 -20
  7. package/build/data/formats-data.js.map +1 -1
  8. package/build/data/learnsets.js +64 -39
  9. package/build/data/learnsets.js.map +1 -1
  10. package/build/data/mods/gen1/formats-data.js +0 -5
  11. package/build/data/mods/gen1/formats-data.js.map +1 -1
  12. package/build/data/mods/gen1/moves.js +54 -22
  13. package/build/data/mods/gen1/moves.js.map +1 -1
  14. package/build/data/mods/gen2/moves.js +0 -5
  15. package/build/data/mods/gen2/moves.js.map +1 -1
  16. package/build/data/mods/gen2/rulesets.js +7 -1
  17. package/build/data/mods/gen2/rulesets.js.map +1 -1
  18. package/build/data/mods/gen3/rulesets.js +1 -1
  19. package/build/data/mods/gen3/rulesets.js.map +1 -1
  20. package/build/data/mods/gen4/rulesets.js +1 -1
  21. package/build/data/mods/gen4/rulesets.js.map +1 -1
  22. package/build/data/mods/gen5/rulesets.js +1 -1
  23. package/build/data/mods/gen5/rulesets.js.map +1 -1
  24. package/build/data/mods/gen6/formats-data.js +14 -14
  25. package/build/data/mods/gen6/formats-data.js.map +1 -1
  26. package/build/data/mods/gen7/pokedex.js +4 -5
  27. package/build/data/mods/gen7/pokedex.js.map +1 -1
  28. package/build/data/mods/gen7/rulesets.js +1 -1
  29. package/build/data/mods/gen7/rulesets.js.map +1 -1
  30. package/build/data/pokedex.js +8 -8
  31. package/build/data/pokedex.js.map +1 -1
  32. package/build/data/rulesets.js +125 -3
  33. package/build/data/rulesets.js.map +1 -1
  34. package/build/data/tags.js +26 -9
  35. package/build/data/tags.js.map +1 -1
  36. package/build/lib/utils.d.ts +4 -0
  37. package/build/lib/utils.js +20 -1
  38. package/build/lib/utils.js.map +1 -1
  39. package/build/sim/battle.d.ts +1 -1
  40. package/build/sim/battle.js.map +1 -1
  41. package/build/sim/dex-conditions.d.ts +1 -0
  42. package/build/sim/dex-conditions.js.map +1 -1
  43. package/build/sim/dex-species.d.ts +5 -0
  44. package/build/sim/dex-species.js +11 -3
  45. package/build/sim/dex-species.js.map +1 -1
  46. package/build/sim/exported-global-types.d.ts +2 -0
  47. package/build/sim/global-types.d.ts +2 -0
  48. package/build/sim/team-validator.js +14 -3
  49. package/build/sim/team-validator.js.map +1 -1
  50. package/config/formats.ts +328 -199
  51. package/data/aliases.ts +7 -3
  52. package/data/formats-data.ts +823 -20
  53. package/data/learnsets.ts +64 -39
  54. package/data/mods/gen1/formats-data.ts +0 -5
  55. package/data/mods/gen1/moves.ts +54 -23
  56. package/data/mods/gen2/moves.ts +0 -5
  57. package/data/mods/gen2/rulesets.ts +8 -1
  58. package/data/mods/gen3/rulesets.ts +1 -1
  59. package/data/mods/gen4/rulesets.ts +1 -1
  60. package/data/mods/gen5/rulesets.ts +1 -1
  61. package/data/mods/gen6/formats-data.ts +14 -14
  62. package/data/mods/gen7/pokedex.ts +4 -5
  63. package/data/mods/gen7/rulesets.ts +1 -1
  64. package/data/pokedex.ts +8 -8
  65. package/data/rulesets.ts +121 -3
  66. package/data/tags.ts +27 -9
  67. package/lib/utils.ts +16 -0
  68. package/package.json +2 -2
  69. package/sim/battle.ts +1 -1
  70. package/sim/dex-conditions.ts +1 -0
  71. package/sim/dex-species.ts +15 -3
  72. package/sim/exported-global-types.ts +2 -0
  73. package/sim/global-types.ts +2 -0
  74. package/sim/team-validator.ts +15 -3
@@ -24,7 +24,7 @@ export const FormatsData: {[k: string]: ModdedSpeciesFormatsData} = {
24
24
  tier: "NFE",
25
25
  },
26
26
  charizard: {
27
- randomBattleMoves: ["acrobatics", "airslash", "earthquake", "fireblast", "flareblitz", "roost", "swordsdance", "willowisp"],
27
+ randomBattleMoves: ["airslash", "earthquake", "fireblast", "roost", "willowisp"],
28
28
  randomDoubleBattleMoves: ["airslash", "dragonpulse", "fireblast", "heatwave", "overheat", "protect", "roost", "tailwind"],
29
29
  tier: "NU",
30
30
  doublesTier: "(DUU)",
@@ -54,7 +54,7 @@ export const FormatsData: {[k: string]: ModdedSpeciesFormatsData} = {
54
54
  doublesTier: "(DUU)",
55
55
  },
56
56
  blastoisemega: {
57
- randomBattleMoves: ["aurasphere", "darkpulse", "dragontail", "hydropump", "icebeam", "rapidspin", "scald"],
57
+ randomBattleMoves: ["aurasphere", "darkpulse", "hydropump", "icebeam", "rapidspin", "scald"],
58
58
  randomDoubleBattleMoves: ["aurasphere", "darkpulse", "fakeout", "followme", "hydropump", "icebeam", "icywind", "muddywater", "protect", "scald"],
59
59
  tier: "UU",
60
60
  doublesTier: "DUU",
@@ -686,7 +686,7 @@ export const FormatsData: {[k: string]: ModdedSpeciesFormatsData} = {
686
686
  tier: "LC",
687
687
  },
688
688
  seaking: {
689
- randomBattleMoves: ["drillrun", "icebeam", "knockoff", "megahorn", "scald", "waterfall"],
689
+ randomBattleMoves: ["drillrun", "icebeam", "knockoff", "megahorn", "raindance", "waterfall"],
690
690
  randomDoubleBattleMoves: ["drillrun", "icebeam", "icywind", "knockoff", "megahorn", "protect", "surf", "waterfall"],
691
691
  tier: "(PU)",
692
692
  doublesTier: "(DUU)",
@@ -1693,7 +1693,7 @@ export const FormatsData: {[k: string]: ModdedSpeciesFormatsData} = {
1693
1693
  tier: "NFE",
1694
1694
  },
1695
1695
  aggron: {
1696
- randomBattleMoves: ["aquatail", "autotomize", "earthquake", "headsmash", "heavyslam", "lowkick", "stealthrock"],
1696
+ randomBattleMoves: ["aquatail", "autotomize", "earthquake", "headsmash", "heavyslam", "stealthrock"],
1697
1697
  randomDoubleBattleMoves: ["aquatail", "earthquake", "headsmash", "heavyslam", "lowkick", "protect", "rockslide", "stealthrock"],
1698
1698
  tier: "NU",
1699
1699
  doublesTier: "(DUU)",
@@ -1819,7 +1819,7 @@ export const FormatsData: {[k: string]: ModdedSpeciesFormatsData} = {
1819
1819
  doublesTier: "DUU",
1820
1820
  },
1821
1821
  torkoal: {
1822
- randomBattleMoves: ["earthpower", "fireblast", "hiddenpowergrass", "lavaplume", "rapidspin", "shellsmash", "stealthrock", "yawn"],
1822
+ randomBattleMoves: ["earthpower", "lavaplume", "rapidspin", "stealthrock", "yawn"],
1823
1823
  randomDoubleBattleMoves: ["earthpower", "fireblast", "heatwave", "hiddenpowergrass", "protect", "shellsmash", "willowisp"],
1824
1824
  tier: "PU",
1825
1825
  doublesTier: "(DUU)",
@@ -1846,7 +1846,7 @@ export const FormatsData: {[k: string]: ModdedSpeciesFormatsData} = {
1846
1846
  tier: "NFE",
1847
1847
  },
1848
1848
  flygon: {
1849
- randomBattleMoves: ["defog", "earthquake", "fireblast", "firepunch", "outrage", "roost", "stoneedge", "uturn"],
1849
+ randomBattleMoves: ["defog", "earthquake", "fireblast", "outrage", "roost", "stoneedge", "uturn"],
1850
1850
  randomDoubleBattleMoves: ["dragonclaw", "earthquake", "feint", "fireblast", "firepunch", "protect", "rockslide", "tailwind", "uturn"],
1851
1851
  tier: "RU",
1852
1852
  doublesTier: "(DUU)",
@@ -1855,7 +1855,7 @@ export const FormatsData: {[k: string]: ModdedSpeciesFormatsData} = {
1855
1855
  tier: "LC",
1856
1856
  },
1857
1857
  cacturne: {
1858
- randomBattleMoves: ["darkpulse", "drainpunch", "focusblast", "gigadrain", "seedbomb", "spikes", "suckerpunch", "swordsdance"],
1858
+ randomBattleMoves: ["darkpulse", "drainpunch", "focusblast", "seedbomb", "spikes", "suckerpunch", "swordsdance"],
1859
1859
  randomDoubleBattleMoves: ["drainpunch", "seedbomb", "spikyshield", "substitute", "suckerpunch", "swordsdance"],
1860
1860
  tier: "PU",
1861
1861
  doublesTier: "(DUU)",
@@ -1882,7 +1882,7 @@ export const FormatsData: {[k: string]: ModdedSpeciesFormatsData} = {
1882
1882
  doublesTier: "(DUU)",
1883
1883
  },
1884
1884
  seviper: {
1885
- randomBattleMoves: ["coil", "darkpulse", "earthquake", "flamethrower", "gigadrain", "poisonjab", "sludgewave", "suckerpunch", "switcheroo"],
1885
+ randomBattleMoves: ["darkpulse", "earthquake", "flamethrower", "gigadrain", "poisonjab", "sludgewave", "suckerpunch", "switcheroo"],
1886
1886
  randomDoubleBattleMoves: ["aquatail", "earthquake", "flamethrower", "gigadrain", "glare", "poisonjab", "protect", "sludgebomb", "suckerpunch"],
1887
1887
  tier: "(PU)",
1888
1888
  doublesTier: "(DUU)",
@@ -2021,7 +2021,7 @@ export const FormatsData: {[k: string]: ModdedSpeciesFormatsData} = {
2021
2021
  doublesTier: "(DUU)",
2022
2022
  },
2023
2023
  absolmega: {
2024
- randomBattleMoves: ["fireblast", "icebeam", "knockoff", "playrough", "pursuit", "suckerpunch", "superpower", "swordsdance"],
2024
+ randomBattleMoves: ["icebeam", "knockoff", "playrough", "pursuit", "suckerpunch", "superpower", "swordsdance"],
2025
2025
  randomDoubleBattleMoves: ["fireblast", "knockoff", "playrough", "protect", "suckerpunch", "superpower", "swordsdance"],
2026
2026
  tier: "UU",
2027
2027
  doublesTier: "(DUU)",
@@ -2147,7 +2147,7 @@ export const FormatsData: {[k: string]: ModdedSpeciesFormatsData} = {
2147
2147
  doublesTier: "(DUU)",
2148
2148
  },
2149
2149
  latiasmega: {
2150
- randomBattleMoves: ["calmmind", "dracometeor", "dragonpulse", "hiddenpowerfire", "psyshock", "roost", "substitute", "surf"],
2150
+ randomBattleMoves: ["calmmind", "dracometeor", "hiddenpowerfire", "psyshock", "roost", "substitute", "surf"],
2151
2151
  randomDoubleBattleMoves: ["dragonpulse", "healpulse", "helpinghand", "lightscreen", "protect", "psychic", "reflect", "tailwind"],
2152
2152
  tier: "(OU)",
2153
2153
  doublesTier: "(DUU)",
@@ -3392,7 +3392,7 @@ export const FormatsData: {[k: string]: ModdedSpeciesFormatsData} = {
3392
3392
  tier: "NFE",
3393
3393
  },
3394
3394
  hydreigon: {
3395
- randomBattleMoves: ["darkpulse", "dracometeor", "dragonpulse", "earthpower", "fireblast", "flashcannon", "roost", "superpower", "uturn"],
3395
+ randomBattleMoves: ["darkpulse", "dracometeor", "fireblast", "flashcannon", "roost", "superpower", "uturn"],
3396
3396
  randomDoubleBattleMoves: ["darkpulse", "dracometeor", "dragonpulse", "earthpower", "fireblast", "flashcannon", "protect", "roost", "superpower", "tailwind", "uturn"],
3397
3397
  tier: "UU",
3398
3398
  doublesTier: "DOU",
@@ -3401,7 +3401,7 @@ export const FormatsData: {[k: string]: ModdedSpeciesFormatsData} = {
3401
3401
  tier: "LC",
3402
3402
  },
3403
3403
  volcarona: {
3404
- randomBattleMoves: ["bugbuzz", "fierydance", "fireblast", "gigadrain", "hiddenpowerground", "hiddenpowerice", "quiverdance", "roost"],
3404
+ randomBattleMoves: ["bugbuzz", "fierydance", "fireblast", "gigadrain", "hiddenpowerice", "quiverdance", "roost"],
3405
3405
  randomDoubleBattleMoves: ["bugbuzz", "fierydance", "fireblast", "gigadrain", "heatwave", "hiddenpowerice", "protect", "quiverdance", "ragepowder", "roost", "tailwind", "willowisp"],
3406
3406
  tier: "UUBL",
3407
3407
  doublesTier: "DUU",
@@ -3449,7 +3449,7 @@ export const FormatsData: {[k: string]: ModdedSpeciesFormatsData} = {
3449
3449
  doublesTier: "(DUU)",
3450
3450
  },
3451
3451
  reshiram: {
3452
- randomBattleMoves: ["blueflare", "dracometeor", "dragonpulse", "flamecharge", "roost", "stoneedge", "toxic"],
3452
+ randomBattleMoves: ["blueflare", "dracometeor", "earthpower", "roost", "stoneedge", "toxic"],
3453
3453
  randomDoubleBattleMoves: ["blueflare", "dracometeor", "dragonpulse", "flamecharge", "heatwave", "protect", "roost", "tailwind"],
3454
3454
  tier: "Uber",
3455
3455
  doublesTier: "DUber",
@@ -3805,7 +3805,7 @@ export const FormatsData: {[k: string]: ModdedSpeciesFormatsData} = {
3805
3805
  doublesTier: "DUU",
3806
3806
  },
3807
3807
  klefki: {
3808
- randomBattleMoves: ["foulplay", "lightscreen", "magnetrise", "playrough", "reflect", "spikes", "thunderwave", "toxic"],
3808
+ randomBattleMoves: ["foulplay", "lightscreen", "playrough", "reflect", "spikes", "thunderwave", "toxic"],
3809
3809
  randomDoubleBattleMoves: ["dazzlinggleam", "flashcannon", "lightscreen", "playrough", "protect", "reflect", "safeguard", "substitute", "thunderwave"],
3810
3810
  tier: "UU",
3811
3811
  doublesTier: "(DUU)",
@@ -165,13 +165,12 @@ export const Pokedex: {[k: string]: ModdedSpeciesData} = {
165
165
  inherit: true,
166
166
  baseStats: {hp: 90, atk: 85, def: 80, spa: 105, spd: 80, spe: 110},
167
167
  },
168
- justyke: {
168
+ mumbao: {
169
169
  inherit: true,
170
- abilities: {0: "Levitate", 1: "Bulletproof", H: "Justified"},
170
+ unreleasedHidden: true,
171
171
  },
172
- equilibra: {
172
+ jumbao: {
173
173
  inherit: true,
174
- baseStats: {hp: 102, atk: 50, def: 96, spa: 133, spd: 118, spe: 60},
175
- abilities: {0: "Levitate", 1: "Bulletproof", H: "Justified"},
174
+ unreleasedHidden: true,
176
175
  },
177
176
  };
@@ -1,7 +1,7 @@
1
1
  export const Rulesets: {[k: string]: ModdedFormatData} = {
2
2
  standard: {
3
3
  inherit: true,
4
- ruleset: ['Obtainable', 'Team Preview', 'Sleep Clause Mod', 'Species Clause', 'Nickname Clause', 'OHKO Clause', 'Moody Clause', 'Evasion Moves Clause', 'Endless Battle Clause', 'HP Percentage Mod', 'Cancel Mod'],
4
+ ruleset: ['Obtainable', 'Team Preview', 'Sleep Clause Mod', 'Species Clause', 'Nickname Clause', 'OHKO Clause', 'Moody Clause', 'Evasion Items Clause', 'Evasion Moves Clause', 'Endless Battle Clause', 'HP Percentage Mod', 'Cancel Mod'],
5
5
  },
6
6
  standarddoubles: {
7
7
  inherit: true,
package/data/pokedex.ts CHANGED
@@ -16536,7 +16536,7 @@ export const Pokedex: {[speciesid: string]: SpeciesData} = {
16536
16536
  num: -6,
16537
16537
  name: "Pyroak",
16538
16538
  types: ["Fire", "Grass"],
16539
- baseStats: {hp: 120, atk: 70, def: 105, spa: 75, spd: 90, spe: 60},
16539
+ baseStats: {hp: 120, atk: 70, def: 105, spa: 70, spd: 65, spe: 60},
16540
16540
  abilities: {0: "Rock Head", 1: "Battle Armor", H: "Contrary"},
16541
16541
  heightm: 2.1,
16542
16542
  weightkg: 168,
@@ -17065,9 +17065,9 @@ export const Pokedex: {[speciesid: string]: SpeciesData} = {
17065
17065
  name: "Mumbao",
17066
17066
  types: ["Grass", "Fairy"],
17067
17067
  baseStats: {hp: 55, atk: 30, def: 64, spa: 87, spd: 73, spe: 66},
17068
- abilities: {0: "Solar Power", 1: "Trace", H: "Overcoat"},
17068
+ abilities: {0: "Trace", 1: "Overcoat", H: "Solar Power"},
17069
17069
  heightm: 1,
17070
- weightkg: 250,
17070
+ weightkg: 83,
17071
17071
  color: "Brown",
17072
17072
  evos: ["Jumbao"],
17073
17073
  eggGroups: ["Grass"],
@@ -17078,9 +17078,9 @@ export const Pokedex: {[speciesid: string]: SpeciesData} = {
17078
17078
  name: "Jumbao",
17079
17079
  types: ["Grass", "Fairy"],
17080
17080
  baseStats: {hp: 92, atk: 63, def: 97, spa: 124, spd: 104, spe: 96},
17081
- abilities: {0: "Drought", 1: "Trace", H: "Overcoat"},
17081
+ abilities: {0: "Trace", 1: "Overcoat", H: "Drought"},
17082
17082
  heightm: 2.4,
17083
- weightkg: 600,
17083
+ weightkg: 200,
17084
17084
  color: "Brown",
17085
17085
  prevo: "Mumbao",
17086
17086
  evoType: "levelFriendship",
@@ -17229,7 +17229,7 @@ export const Pokedex: {[speciesid: string]: SpeciesData} = {
17229
17229
  types: ["Steel", "Ground"],
17230
17230
  gender: "N",
17231
17231
  baseStats: {hp: 72, atk: 70, def: 56, spa: 83, spd: 68, spe: 30},
17232
- abilities: {0: "Levitate", 1: "Stalwart", H: "Justified"},
17232
+ abilities: {0: "Levitate", 1: "Bulletproof", H: "Justified"},
17233
17233
  heightm: 0.4,
17234
17234
  weightkg: 36.5,
17235
17235
  color: "Brown",
@@ -17242,8 +17242,8 @@ export const Pokedex: {[speciesid: string]: SpeciesData} = {
17242
17242
  name: "Equilibra",
17243
17243
  types: ["Steel", "Ground"],
17244
17244
  gender: "N",
17245
- baseStats: {hp: 102, atk: 50, def: 96, spa: 121, spd: 118, spe: 60},
17246
- abilities: {0: "Levitate", 1: "Stalwart", H: "Justified"},
17245
+ baseStats: {hp: 102, atk: 50, def: 96, spa: 133, spd: 118, spe: 60},
17246
+ abilities: {0: "Levitate", 1: "Bulletproof", H: "Justified"},
17247
17247
  heightm: 0.8,
17248
17248
  weightkg: 51.3,
17249
17249
  color: "Brown",
package/data/rulesets.ts CHANGED
@@ -14,7 +14,7 @@ export const Rulesets: {[k: string]: FormatData} = {
14
14
  name: 'Standard',
15
15
  desc: "The standard ruleset for all offical Smogon singles tiers (Ubers, OU, etc.)",
16
16
  ruleset: [
17
- 'Obtainable', 'Team Preview', 'Sleep Clause Mod', 'Species Clause', 'Nickname Clause', 'OHKO Clause', 'Evasion Moves Clause', 'Endless Battle Clause', 'HP Percentage Mod', 'Cancel Mod',
17
+ 'Obtainable', 'Team Preview', 'Sleep Clause Mod', 'Species Clause', 'Nickname Clause', 'OHKO Clause', 'Evasion Items Clause', 'Evasion Moves Clause', 'Endless Battle Clause', 'HP Percentage Mod', 'Cancel Mod',
18
18
  ],
19
19
  },
20
20
  standardnext: {
@@ -71,6 +71,14 @@ export const Rulesets: {[k: string]: FormatData} = {
71
71
  'Obtainable', 'Team Preview', 'Species Clause', 'Nickname Clause', 'OHKO Clause', 'Evasion Moves Clause', 'Gravity Sleep Clause', 'Endless Battle Clause', 'HP Percentage Mod', 'Cancel Mod',
72
72
  ],
73
73
  },
74
+ standardoms: {
75
+ effectType: 'ValidatorRule',
76
+ name: 'Standard OMs',
77
+ desc: "The standard ruleset for all Smogon OMs (Almost Any Ability, STABmons, etc.)",
78
+ ruleset: [
79
+ 'Obtainable', 'Team Preview', 'Species Clause', 'Nickname Clause', 'OHKO Clause', 'Evasion Moves Clause', 'Endless Battle Clause', 'Dynamax Clause', 'HP Percentage Mod', 'Cancel Mod', 'Overflow Stat Mod',
80
+ ],
81
+ },
74
82
  standardnatdex: {
75
83
  effectType: 'ValidatorRule',
76
84
  name: 'Standard NatDex',
@@ -643,6 +651,15 @@ export const Rulesets: {[k: string]: FormatData} = {
643
651
  return problems;
644
652
  },
645
653
  },
654
+ evasionclause: {
655
+ effectType: 'ValidatorRule',
656
+ name: 'Evasion Clause',
657
+ desc: "Bans abilities, items, and moves that boost Evasion",
658
+ ruleset: ['Evasion Abilities Clause', 'Evasion Items Clause', 'Evasion Moves Clause'],
659
+ onBegin() {
660
+ this.add('rule', 'Evasion Clause: Evasion abilities, items, and moves are banned');
661
+ },
662
+ },
646
663
  evasionabilitiesclause: {
647
664
  effectType: 'ValidatorRule',
648
665
  name: 'Evasion Abilities Clause',
@@ -652,6 +669,15 @@ export const Rulesets: {[k: string]: FormatData} = {
652
669
  this.add('rule', 'Evasion Abilities Clause: Evasion abilities are banned');
653
670
  },
654
671
  },
672
+ evasionitemsclause: {
673
+ effectType: 'ValidatorRule',
674
+ name: 'Evasion Items Clause',
675
+ desc: "Bans moves that lower the accuracy of moves used against the user",
676
+ banlist: ['Bright Powder', 'Lax Incense'],
677
+ onBegin() {
678
+ this.add('rule', 'Evasion Items Clause: Evasion items are banned');
679
+ },
680
+ },
655
681
  evasionmovesclause: {
656
682
  effectType: 'ValidatorRule',
657
683
  name: 'Evasion Moves Clause',
@@ -968,7 +994,7 @@ export const Rulesets: {[k: string]: FormatData} = {
968
994
  if (status.id === 'slp') {
969
995
  for (const pokemon of target.side.pokemon) {
970
996
  if (pokemon.hp && pokemon.status === 'slp') {
971
- this.add('-message', "Sleep Clause activated. (In Stadium, Sleep Clause activates if any of the opponent's Pokemon are asleep, even if self-inflicted from Rest)");
997
+ this.add('-message', "Sleep Clause activated. (In Nintendo formats, Sleep Clause activates if any of the opponent's Pokemon are asleep, even if self-inflicted from Rest)");
972
998
  return false;
973
999
  }
974
1000
  }
@@ -1409,6 +1435,7 @@ export const Rulesets: {[k: string]: FormatData} = {
1409
1435
  name: 'Team Type Preview',
1410
1436
  desc: "Allows each player to see the Pokémon on their opponent's team and those Pokémon's types before they choose their lead Pokémon",
1411
1437
  onTeamPreview() {
1438
+ this.add('clearpoke');
1412
1439
  for (const side of this.sides) {
1413
1440
  for (const pokemon of side.pokemon) {
1414
1441
  const details = pokemon.details.replace(', shiny', '')
@@ -1870,7 +1897,6 @@ export const Rulesets: {[k: string]: FormatData} = {
1870
1897
  effectType: "Rule",
1871
1898
  name: "Re-Evolution Mod",
1872
1899
  desc: "Pokémon gain the stat changes they would gain from evolving again.",
1873
- ruleset: ['Overflow Stat Mod'],
1874
1900
  onBegin() {
1875
1901
  this.add('rule', 'Re-Evolution Mod: Pok\u00e9mon gain the boosts they would gain from evolving again');
1876
1902
  },
@@ -1979,4 +2005,96 @@ export const Rulesets: {[k: string]: FormatData} = {
1979
2005
  }
1980
2006
  },
1981
2007
  },
2008
+ categoryswapmod: {
2009
+ effectType: 'Rule',
2010
+ name: 'Category Swap Mod',
2011
+ desc: `All physical moves become special, and all special moves become physical.`,
2012
+ onBegin() {
2013
+ this.add('rule', 'Category Swap Mod: All physical moves become special, and vice versa');
2014
+ },
2015
+ onModifyMove(move, pokemon, target) {
2016
+ if (move.category === "Status") return;
2017
+
2018
+ if (move.category === "Physical") {
2019
+ move.category = "Special";
2020
+ } else if (move.category === "Special") {
2021
+ move.category = "Physical";
2022
+ }
2023
+
2024
+ switch (move.id) {
2025
+ case 'doomdesire': {
2026
+ move.onTry = function (source, subtarget) {
2027
+ if (!subtarget.side.addSlotCondition(subtarget, 'futuremove')) return false;
2028
+ Object.assign(subtarget.side.slotConditions[subtarget.position]['futuremove'], {
2029
+ move: 'doomdesire',
2030
+ source: source,
2031
+ moveData: {
2032
+ id: 'doomdesire',
2033
+ name: "Doom Desire",
2034
+ accuracy: 100,
2035
+ basePower: 140,
2036
+ category: "Physical",
2037
+ priority: 0,
2038
+ flags: {},
2039
+ effectType: 'Move',
2040
+ isFutureMove: true,
2041
+ type: 'Steel',
2042
+ },
2043
+ });
2044
+ this.add('-start', source, 'Doom Desire');
2045
+ return this.NOT_FAIL;
2046
+ };
2047
+ break;
2048
+ }
2049
+ case 'futuresight': {
2050
+ move.onTry = function (source, subtarget) {
2051
+ if (!subtarget.side.addSlotCondition(subtarget, 'futuremove')) return false;
2052
+ Object.assign(subtarget.side.slotConditions[subtarget.position]['futuremove'], {
2053
+ duration: 3,
2054
+ move: 'futuresight',
2055
+ source: source,
2056
+ moveData: {
2057
+ id: 'futuresight',
2058
+ name: "Future Sight",
2059
+ accuracy: 100,
2060
+ basePower: 120,
2061
+ category: "Physical",
2062
+ priority: 0,
2063
+ flags: {},
2064
+ ignoreImmunity: false,
2065
+ effectType: 'Move',
2066
+ isFutureMove: true,
2067
+ type: 'Psychic',
2068
+ },
2069
+ });
2070
+ this.add('-start', source, 'move: Future Sight');
2071
+ return this.NOT_FAIL;
2072
+ };
2073
+ break;
2074
+ }
2075
+ // Moves with dynamic categories will always be physical if not special-cased
2076
+ case 'lightthatburnsthesky':
2077
+ case 'photongeyser': {
2078
+ move.category = 'Special';
2079
+ if (pokemon.getStat('atk', false, true) > pokemon.getStat('spa', false, true)) move.category = 'Physical';
2080
+ break;
2081
+ }
2082
+ case 'shellsidearm': {
2083
+ if (!target) return;
2084
+ move.category = 'Special';
2085
+ const atk = pokemon.getStat('atk', false, true);
2086
+ const spa = pokemon.getStat('spa', false, true);
2087
+ const def = target.getStat('def', false, true);
2088
+ const spd = target.getStat('spd', false, true);
2089
+ const physical = Math.floor(Math.floor(Math.floor(Math.floor(2 * pokemon.level / 5 + 2) * 90 * atk) / def) / 50);
2090
+ const special = Math.floor(Math.floor(Math.floor(Math.floor(2 * pokemon.level / 5 + 2) * 90 * spa) / spd) / 50);
2091
+ if (physical > special || (physical === special && this.random(2) === 0)) {
2092
+ move.category = 'Physical';
2093
+ move.flags.contact = 1;
2094
+ }
2095
+ break;
2096
+ }
2097
+ }
2098
+ },
2099
+ },
1982
2100
  };
package/data/tags.ts CHANGED
@@ -194,15 +194,6 @@ export const Tags: {[id: string]: TagData} = {
194
194
  name: "AG",
195
195
  speciesFilter: species => species.tier === 'AG',
196
196
  },
197
- nduubl: {
198
- name: "ND UUBL",
199
- speciesFilter: species => [
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',
202
- 'Latios-Mega', 'Manaphy', 'Medicham-Mega', 'Melmetal', 'Mew', 'Moltres-Galar', 'Pinsir-Mega', 'Sableye-Mega', 'Slowbro-Mega',
203
- 'Slowking-Galar', 'Thundurus', 'Venusaur-Mega', 'Xurkitree', 'Zapdos-Galar',
204
- ].includes(species.name),
205
- },
206
197
 
207
198
  // Doubles tiers
208
199
  // -------------
@@ -227,6 +218,33 @@ export const Tags: {[id: string]: TagData} = {
227
218
  speciesFilter: species => species.doublesTier === '(DUU)',
228
219
  },
229
220
 
221
+ // Nat Dex tiers
222
+ // -------------
223
+ nduber: {
224
+ name: "ND Uber",
225
+ speciesFilter: species => species.natDexTier === 'Uber' || species.natDexTier === '(Uber)',
226
+ },
227
+ ndou: {
228
+ name: "ND OU",
229
+ speciesFilter: species => species.natDexTier === 'OU' || species.natDexTier === '(OU)',
230
+ },
231
+ nduubl: {
232
+ name: "ND UUBL",
233
+ speciesFilter: species => species.natDexTier === 'UUBL',
234
+ },
235
+ nduu: {
236
+ name: "ND UU",
237
+ speciesFilter: species => species.natDexTier === 'UU',
238
+ },
239
+ ndrubl: {
240
+ name: "ND RUBL",
241
+ speciesFilter: species => species.natDexTier === 'RUBL',
242
+ },
243
+ ndru: {
244
+ name: "ND RU",
245
+ speciesFilter: species => species.natDexTier === 'RU',
246
+ },
247
+
230
248
  // Legality tags
231
249
  past: {
232
250
  name: "Past",
package/lib/utils.ts CHANGED
@@ -63,6 +63,22 @@ export function stripHTML(htmlContent: string) {
63
63
  return htmlContent.replace(/<[^>]*>/g, '');
64
64
  }
65
65
 
66
+ /**
67
+ * Maps numbers to their ordinal string.
68
+ */
69
+ export function formatOrder(place: number) {
70
+ // anything between 10 and 20 should always end with -th
71
+ let remainder = place % 100;
72
+ if (remainder >= 10 && remainder <= 20) return place + 'th';
73
+
74
+ // follow standard rules with -st, -nd, -rd, and -th
75
+ remainder = place % 10;
76
+ if (remainder === 1) return place + 'st';
77
+ if (remainder === 2) return place + 'nd';
78
+ if (remainder === 3) return place + 'rd';
79
+ return place + 'th';
80
+ }
81
+
66
82
  /**
67
83
  * Visualizes eval output in a slightly more readable form
68
84
  */
package/package.json CHANGED
@@ -1,6 +1,6 @@
1
1
  {
2
2
  "name": "@pkmn/sim",
3
- "version": "0.5.23",
3
+ "version": "0.5.26",
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,7 +27,7 @@
27
27
  "sim"
28
28
  ],
29
29
  "dependencies": {
30
- "@pkmn/sets": "^3.1.0",
30
+ "@pkmn/sets": "^3.1.1",
31
31
  "@pkmn/streams": "^1.0.0"
32
32
  },
33
33
  "devDependencies": {
package/sim/battle.ts CHANGED
@@ -399,7 +399,7 @@ export class Battle {
399
399
  }
400
400
 
401
401
  /** Sort a list, resolving speed ties the way the games do. */
402
- speedSort<T>(list: T[], comparator: (a: T, b: T) => number = this.comparePriority) {
402
+ speedSort<T extends AnyObject>(list: T[], comparator: (a: T, b: T) => number = this.comparePriority) {
403
403
  if (list.length < 2) return;
404
404
  let sorted = 0;
405
405
  // This is a Selection Sort - not the fastest sort in general, but
@@ -473,6 +473,7 @@ export interface EventMethods {
473
473
  onModifyPriorityPriority?: number;
474
474
  onModifySpAPriority?: number;
475
475
  onModifySpDPriority?: number;
476
+ onModifySpePriority?: number;
476
477
  onModifyTypePriority?: number;
477
478
  onModifyWeightPriority?: number;
478
479
  onRedirectTargetPriority?: number;
@@ -42,6 +42,7 @@ export interface SpeciesFormatsData {
42
42
  exclusiveMoves?: readonly string[];
43
43
  gmaxUnreleased?: boolean;
44
44
  isNonstandard?: Nonstandard | null;
45
+ natDexTier?: TierTypes.Singles | TierTypes.Other;
45
46
  randomBattleMoves?: readonly string[];
46
47
  randomBattleLevel?: number;
47
48
  randomDoubleBattleMoves?: readonly string[];
@@ -231,6 +232,10 @@ export class Species extends BasicEffect implements Readonly<BasicEffect & Speci
231
232
  * Doubles Tier. The Pokemon's location in the Smogon doubles tier system.
232
233
  */
233
234
  readonly doublesTier: TierTypes.Doubles | TierTypes.Other;
235
+ /**
236
+ * National Dex Tier. The Pokemon's location in the Smogon National Dex tier system.
237
+ */
238
+ readonly natDexTier: TierTypes.Singles | TierTypes.Other;
234
239
  declare readonly randomBattleMoves?: readonly ID[];
235
240
  declare readonly randomBattleLevel?: number;
236
241
  declare readonly randomDoubleBattleMoves?: readonly ID[];
@@ -261,6 +266,7 @@ export class Species extends BasicEffect implements Readonly<BasicEffect & Speci
261
266
  this.prevo = data.prevo || '';
262
267
  this.tier = data.tier || '';
263
268
  this.doublesTier = data.doublesTier || '';
269
+ this.natDexTier = data.natDexTier || '';
264
270
  this.evos = data.evos || [];
265
271
  this.evoType = data.evoType || undefined;
266
272
  this.evoMove = data.evoMove || undefined;
@@ -451,16 +457,19 @@ export class DexSpecies {
451
457
  if (!(key in species)) (species as any)[key] = baseSpeciesStatuses[key];
452
458
  }
453
459
  }
454
- if (!species.tier && !species.doublesTier && species.baseSpecies !== species.name) {
460
+ if (!species.tier && !species.doublesTier && !species.natDexTier && species.baseSpecies !== species.name) {
455
461
  if (species.baseSpecies === 'Mimikyu') {
456
462
  species.tier = this.dex.data.FormatsData[toID(species.baseSpecies)].tier || 'Illegal';
457
463
  species.doublesTier = this.dex.data.FormatsData[toID(species.baseSpecies)].doublesTier || 'Illegal';
464
+ species.natDexTier = this.dex.data.FormatsData[toID(species.baseSpecies)].natDexTier || 'Illegal';
458
465
  } else if (species.id.endsWith('totem')) {
459
466
  species.tier = this.dex.data.FormatsData[species.id.slice(0, -5)].tier || 'Illegal';
460
467
  species.doublesTier = this.dex.data.FormatsData[species.id.slice(0, -5)].doublesTier || 'Illegal';
468
+ species.natDexTier = this.dex.data.FormatsData[species.id.slice(0, -5)].natDexTier || 'Illegal';
461
469
  } else if (species.battleOnly) {
462
470
  species.tier = this.dex.data.FormatsData[toID(species.battleOnly)].tier || 'Illegal';
463
471
  species.doublesTier = this.dex.data.FormatsData[toID(species.battleOnly)].doublesTier || 'Illegal';
472
+ species.natDexTier = this.dex.data.FormatsData[toID(species.battleOnly)].natDexTier || 'Illegal';
464
473
  } else {
465
474
  const baseFormatsData = this.dex.data.FormatsData[toID(species.baseSpecies)];
466
475
  if (!baseFormatsData) {
@@ -468,13 +477,16 @@ export class DexSpecies {
468
477
  }
469
478
  species.tier = baseFormatsData.tier || 'Illegal';
470
479
  species.doublesTier = baseFormatsData.doublesTier || 'Illegal';
480
+ species.natDexTier = baseFormatsData.natDexTier || 'Illegal';
471
481
  }
472
482
  }
473
483
  if (!species.tier) species.tier = 'Illegal';
474
484
  if (!species.doublesTier) species.doublesTier = species.tier as any;
485
+ if (!species.natDexTier) species.natDexTier = species.tier;
475
486
  if (species.gen > this.dex.gen) {
476
487
  species.tier = 'Illegal';
477
488
  species.doublesTier = 'Illegal';
489
+ species.natDexTier = 'Illegal';
478
490
  species.isNonstandard = 'Future';
479
491
  }
480
492
  if (this.dex.currentMod === 'gen7letsgo' && !species.isNonstandard) {
@@ -490,7 +502,7 @@ export class DexSpecies {
490
502
  if (species.gen > 4 || (species.num < 1 && species.isNonstandard !== 'CAP') ||
491
503
  species.id === 'pichuspikyeared') {
492
504
  species.isNonstandard = 'Future';
493
- species.tier = species.doublesTier = 'Illegal';
505
+ species.tier = species.doublesTier = species.natDexTier = 'Illegal';
494
506
  }
495
507
  }
496
508
  species.nfe = species.evos.some(evo => {
@@ -505,7 +517,7 @@ export class DexSpecies {
505
517
  } else {
506
518
  species = new Species({
507
519
  id, name: id,
508
- exists: false, tier: 'Illegal', doublesTier: 'Illegal', isNonstandard: 'Custom',
520
+ exists: false, tier: 'Illegal', doublesTier: 'Illegal', natDexTier: 'Illegal', isNonstandard: 'Custom',
509
521
  });
510
522
  }
511
523
  (species as any).kind = 'Species';
@@ -312,6 +312,7 @@ export interface ModdedBattlePokemon {
312
312
  clearBoosts?: (this: Pokemon) => void;
313
313
  calculateStat?: (this: Pokemon, statName: StatIDExceptHP, boost: number, modifier?: number) => number;
314
314
  cureStatus?: (this: Pokemon, silent?: boolean) => boolean;
315
+ eatItem?: (this: Pokemon, force?: boolean, source?: Pokemon, sourceEffect?: Effect) => boolean;
315
316
  formeChange?: (
316
317
  this: Pokemon, speciesId: string | Species, source: Effect, isPermanent?: boolean, message?: string
317
318
  ) => boolean;
@@ -344,6 +345,7 @@ export interface ModdedBattlePokemon {
344
345
  ) => boolean;
345
346
  takeItem?: (this: Pokemon, source: Pokemon | undefined) => boolean | Item;
346
347
  transformInto?: (this: Pokemon, pokemon: Pokemon, effect: Effect | null) => boolean;
348
+ useItem?: (this: Pokemon, source?: Pokemon, sourceEffect?: Effect) => boolean;
347
349
  ignoringAbility?: (this: Pokemon) => boolean;
348
350
  ignoringItem?: (this: Pokemon) => boolean;
349
351
 
@@ -312,6 +312,7 @@ interface ModdedBattlePokemon {
312
312
  clearBoosts?: (this: Pokemon) => void;
313
313
  calculateStat?: (this: Pokemon, statName: StatIDExceptHP, boost: number, modifier?: number) => number;
314
314
  cureStatus?: (this: Pokemon, silent?: boolean) => boolean;
315
+ eatItem?: (this: Pokemon, force?: boolean, source?: Pokemon, sourceEffect?: Effect) => boolean;
315
316
  formeChange?: (
316
317
  this: Pokemon, speciesId: string | Species, source: Effect, isPermanent?: boolean, message?: string
317
318
  ) => boolean;
@@ -344,6 +345,7 @@ interface ModdedBattlePokemon {
344
345
  ) => boolean;
345
346
  takeItem?: (this: Pokemon, source: Pokemon | undefined) => boolean | Item;
346
347
  transformInto?: (this: Pokemon, pokemon: Pokemon, effect: Effect | null) => boolean;
348
+ useItem?: (this: Pokemon, source?: Pokemon, sourceEffect?: Effect) => boolean;
347
349
  ignoringAbility?: (this: Pokemon) => boolean;
348
350
  ignoringItem?: (this: Pokemon) => boolean;
349
351
 
@@ -733,9 +733,16 @@ export class TeamValidator {
733
733
  isFromRBYEncounter = true;
734
734
  }
735
735
  }
736
- if (!isFromRBYEncounter && ruleTable.has('obtainablemisc') && set.level < (species.evoLevel || 0)) {
736
+ if (!isFromRBYEncounter && ruleTable.has('obtainablemisc')) {
737
737
  // FIXME: Event pokemon given at a level under what it normally can be attained at gives a false positive
738
- problems.push(`${name} must be at least level ${species.evoLevel} to be evolved.`);
738
+ let evoSpecies = species;
739
+ while (evoSpecies.prevo) {
740
+ if (set.level < (evoSpecies.evoLevel || 0)) {
741
+ problems.push(`${name} must be at least level ${evoSpecies.evoLevel} to be evolved.`);
742
+ break;
743
+ }
744
+ evoSpecies = dex.species.get(evoSpecies.prevo);
745
+ }
739
746
  }
740
747
 
741
748
  if (ruleTable.has('obtainablemoves') && species.id === 'keldeo' && set.moves.includes('secretsword') &&
@@ -1366,6 +1373,11 @@ export class TeamValidator {
1366
1373
  const doublesTierTag = 'pokemontag:' + toID(doublesTier);
1367
1374
  setHas[doublesTierTag] = true;
1368
1375
 
1376
+ const ndTier = tierSpecies.natDexTier === '(PU)' ? 'ZU' :
1377
+ tierSpecies.natDexTier === '(NU)' ? 'PU' : tierSpecies.natDexTier;
1378
+ const ndTierTag = 'pokemontag:nd' + toID(ndTier);
1379
+ setHas[ndTierTag] = true;
1380
+
1369
1381
  // Only pokemon that can gigantamax should have the Gmax flag
1370
1382
  if (!tierSpecies.canGigantamax && set.gigantamax) {
1371
1383
  return `${tierSpecies.name} cannot Gigantamax but is flagged as being able to.`;
@@ -2206,7 +2218,7 @@ export class TeamValidator {
2206
2218
  // different learnsets. To prevent a leak, we make them show up as their
2207
2219
  // base forme, but hardcode their learnsets into Rockruff-Dusk and
2208
2220
  // Greninja-Ash
2209
- if ((species.baseSpecies === 'Gastrodon' || species.baseSpecies === 'Pumpkaboo') && species.forme) {
2221
+ if (['Gastrodon', 'Pumpkaboo', 'Sinistea'].includes(species.baseSpecies) && species.forme) {
2210
2222
  return this.dex.species.get(species.baseSpecies);
2211
2223
  } else if (species.name === 'Lycanroc-Dusk') {
2212
2224
  return this.dex.species.get('Rockruff-Dusk');