@pkmn/sim 0.4.19 → 0.4.23

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 (88) hide show
  1. package/build/config/formats.js +752 -743
  2. package/build/config/formats.js.map +1 -1
  3. package/build/data/aliases.js +4 -4
  4. package/build/data/aliases.js.map +1 -1
  5. package/build/data/conditions.js +4 -1
  6. package/build/data/conditions.js.map +1 -1
  7. package/build/data/formats-data.js +27 -27
  8. package/build/data/formats-data.js.map +1 -1
  9. package/build/data/learnsets.js +10 -10
  10. package/build/data/learnsets.js.map +1 -1
  11. package/build/data/mods/gen1/moves.js +1 -1
  12. package/build/data/mods/gen1/moves.js.map +1 -1
  13. package/build/data/mods/gen1/scripts.js +18 -22
  14. package/build/data/mods/gen1/scripts.js.map +1 -1
  15. package/build/data/mods/gen2/scripts.js +16 -23
  16. package/build/data/mods/gen2/scripts.js.map +1 -1
  17. package/build/data/mods/gen3/moves.js +2 -1
  18. package/build/data/mods/gen3/moves.js.map +1 -1
  19. package/build/data/mods/gen4/conditions.js +6 -0
  20. package/build/data/mods/gen4/conditions.js.map +1 -1
  21. package/build/data/mods/gen4/moves.js +2 -1
  22. package/build/data/mods/gen4/moves.js.map +1 -1
  23. package/build/data/mods/gen4/scripts.js +2 -1
  24. package/build/data/mods/gen4/scripts.js.map +1 -1
  25. package/build/data/mods/gen6/conditions.js +4 -1
  26. package/build/data/mods/gen6/conditions.js.map +1 -1
  27. package/build/data/mods/gen7/formats-data.js +2 -2
  28. package/build/data/mods/gen7/formats-data.js.map +1 -1
  29. package/build/data/mods/gen7/moves.js +8 -0
  30. package/build/data/mods/gen7/moves.js.map +1 -1
  31. package/build/data/moves.js +26 -14
  32. package/build/data/moves.js.map +1 -1
  33. package/build/data/rulesets.js +258 -16
  34. package/build/data/rulesets.js.map +1 -1
  35. package/build/data/tags.js +3 -3
  36. package/build/data/tags.js.map +1 -1
  37. package/build/lib/streams.d.ts +1 -199
  38. package/build/lib/streams.js +11 -772
  39. package/build/lib/streams.js.map +1 -1
  40. package/build/sim/battle-actions.d.ts +1 -1
  41. package/build/sim/battle-actions.js +18 -42
  42. package/build/sim/battle-actions.js.map +1 -1
  43. package/build/sim/battle.d.ts +1 -0
  44. package/build/sim/battle.js +5 -0
  45. package/build/sim/battle.js.map +1 -1
  46. package/build/sim/dex-moves.d.ts +31 -11
  47. package/build/sim/dex-moves.js +4 -3
  48. package/build/sim/dex-moves.js.map +1 -1
  49. package/build/sim/dex-species.js +11 -1
  50. package/build/sim/dex-species.js.map +1 -1
  51. package/build/sim/exported-global-types.d.ts +4 -0
  52. package/build/sim/global-types.d.ts +4 -0
  53. package/build/sim/pokemon.js +1 -1
  54. package/build/sim/pokemon.js.map +1 -1
  55. package/build/sim/side.js +2 -2
  56. package/build/sim/side.js.map +1 -1
  57. package/build/sim/team-validator.d.ts +4 -0
  58. package/build/sim/team-validator.js +37 -11
  59. package/build/sim/team-validator.js.map +1 -1
  60. package/config/formats.ts +649 -630
  61. package/data/aliases.ts +4 -4
  62. package/data/conditions.ts +4 -1
  63. package/data/formats-data.ts +27 -27
  64. package/data/learnsets.ts +10 -10
  65. package/data/mods/gen1/moves.ts +1 -1
  66. package/data/mods/gen1/scripts.ts +23 -19
  67. package/data/mods/gen2/scripts.ts +20 -19
  68. package/data/mods/gen3/moves.ts +2 -1
  69. package/data/mods/gen4/conditions.ts +6 -0
  70. package/data/mods/gen4/moves.ts +2 -1
  71. package/data/mods/gen4/scripts.ts +1 -1
  72. package/data/mods/gen6/conditions.ts +4 -1
  73. package/data/mods/gen7/formats-data.ts +2 -2
  74. package/data/mods/gen7/moves.ts +8 -0
  75. package/data/moves.ts +23 -14
  76. package/data/rulesets.ts +235 -16
  77. package/data/tags.ts +3 -3
  78. package/lib/streams.ts +1 -874
  79. package/package.json +4 -3
  80. package/sim/battle-actions.ts +19 -40
  81. package/sim/battle.ts +6 -0
  82. package/sim/dex-moves.ts +35 -13
  83. package/sim/dex-species.ts +10 -1
  84. package/sim/exported-global-types.ts +4 -0
  85. package/sim/global-types.ts +4 -0
  86. package/sim/pokemon.ts +1 -1
  87. package/sim/side.ts +2 -2
  88. package/sim/team-validator.ts +41 -10
@@ -52,6 +52,12 @@ exports.Formats = [
52
52
  rated: false,
53
53
  ruleset: ['Obtainable', 'Species Clause', 'HP Percentage Mod', 'Cancel Mod', 'Sleep Clause Mod'],
54
54
  },
55
+ {
56
+ name: "[Gen 8] Random Battle (Blitz)",
57
+ mod: 'gen8',
58
+ team: 'random',
59
+ ruleset: ['[Gen 8] Random Battle', 'Blitz'],
60
+ },
55
61
  {
56
62
  name: "[Gen 8] Multi Random Battle",
57
63
  mod: 'gen8',
@@ -219,9 +225,9 @@ exports.Formats = [
219
225
  ruleset: ['[Gen 8] LC'],
220
226
  banlist: [
221
227
  // LC OU
222
- 'Abra', 'Archen', 'Carvanha', 'Dewpider', 'Diglett-Base', 'Dwebble', 'Ferroseed', 'Foongus', 'Frillish', 'Grookey',
223
- 'Koffing', 'Larvesta', 'Magnemite', 'Mareanie', 'Mienfoo', 'Mudbray', 'Munchlax', 'Natu', 'Onix', 'Pawniard', 'Ponyta',
224
- 'Ponyta-Galar', 'Porygon', 'Slowpoke', 'Spritzee', 'Staryu', 'Timburr', 'Trapinch', 'Tyrunt', 'Vulpix',
228
+ 'Abra', 'Archen', 'Carvanha', 'Diglett-Base', 'Dwebble', 'Ferroseed', 'Foongus', 'Frillish', 'Grookey', 'Koffing',
229
+ 'Larvesta', 'Magnemite', 'Mareanie', 'Mienfoo', 'Mudbray', 'Munchlax', 'Natu', 'Onix', 'Pawniard', 'Ponyta',
230
+ 'Ponyta-Galar', 'Porygon', 'Slowpoke-Base', 'Spritzee', 'Staryu', 'Timburr', 'Trapinch', 'Tyrunt', 'Vulpix',
225
231
  // LC UUBL
226
232
  'Farfetch\u2019d-Galar', 'Scorbunny', 'Shellder', 'Wingull',
227
233
  ],
@@ -237,10 +243,21 @@ exports.Formats = [
237
243
  ruleset: ['[Gen 8] OU', '+CAP'],
238
244
  banlist: ['Crucibellite'],
239
245
  },
246
+ {
247
+ name: "[Gen 8] CAP LC",
248
+ threads: [
249
+ `&bullet; <a href="https://www.smogon.com/forums/threads/3691918/">CAP LC Metagame Discussion</a>`,
250
+ `&bullet; <a href="https://www.smogon.com/forums/posts/8997714/">CAP LC Sample Teams</a>`,
251
+ `&bullet; <a href="https://www.smogon.com/forums/posts/8997713/">CAP LC Viability Rankings</a>`,
252
+ ],
253
+ mod: 'gen8',
254
+ searchShow: false,
255
+ ruleset: ['[Gen 8] LC', '+CAP'],
256
+ },
240
257
  {
241
258
  name: "[Gen 8] Battle Stadium Singles",
242
259
  mod: 'gen8',
243
- ruleset: ['Flat Rules', '!! Adjust Level = 50', 'Min Source Gen = 8', 'Limit One Restricted', 'Dynamax Clause'],
260
+ ruleset: ['Flat Rules', '!! Adjust Level = 50', 'Min Source Gen = 8', 'Limit One Restricted'],
244
261
  restricted: ['Restricted Legendary'],
245
262
  },
246
263
  {
@@ -318,15 +335,10 @@ exports.Formats = [
318
335
  banlist: ['Corsola-Galar', 'Cutiefly', 'Ponyta-Base', 'Scyther', 'Sneasel', 'Swirlix', 'Tangela', 'Vulpix', 'Vulpix-Alola'],
319
336
  },
320
337
  {
321
- name: "[Gen 8] VGC 2021 Series 10",
322
- threads: [
323
- `&bullet; <a href="https://www.smogon.com/forums/threads/3677186/">VGC 2021 Series 10 Metagame Discussion</a>`,
324
- `&bullet; <a href="https://www.smogon.com/forums/threads/3689153/">VGC 2021 Series 10 Sample Teams</a>`,
325
- `&bullet; <a href="https://www.smogon.com/forums/threads/3688166/">VGC 2021 Series 10 Viability Rankings</a>`,
326
- ],
338
+ name: "[Gen 8] VGC 2021 Series 11",
327
339
  mod: 'gen8',
328
340
  gameType: 'doubles',
329
- ruleset: ['Flat Rules', '!! Adjust Level = 50', 'Min Source Gen = 8', 'VGC Timer', 'Limit One Restricted', 'Dynamax Clause'],
341
+ ruleset: ['Flat Rules', '!! Adjust Level = 50', 'Min Source Gen = 8', 'VGC Timer', 'Limit One Restricted'],
330
342
  restricted: ['Restricted Legendary'],
331
343
  },
332
344
  {
@@ -343,30 +355,6 @@ exports.Formats = [
343
355
  searchShow: false,
344
356
  ruleset: ['Flat Rules', '!! Adjust Level = 50', 'Min Source Gen = 8', 'VGC Timer'],
345
357
  },
346
- {
347
- name: "[Gen 8] Spooky Cup 2021",
348
- mod: 'gen8',
349
- gameType: 'doubles',
350
- ruleset: ['Flat Rules', '!! Adjust Level = 50', 'Min Source Gen = 8'],
351
- onValidateSet(set) {
352
- const spookyMonsList = [
353
- 'Vileplume', 'Tentacruel', 'Gengar', 'Marowak', 'Weezing', 'Mr. Mime', 'Pinsir', 'Ditto', 'Omastar', 'Kabutops', 'Aerodactyl',
354
- 'Noctowl', 'Crobat', 'Espeon', 'Umbreon', 'Wobbuffet', 'Shiftry', 'Shedinja', 'Exploud', 'Sableye', 'Mawile', 'Sharpedo',
355
- 'Lunatone', 'Crawdaunt', 'Baltoy', 'Claydol', 'Absol', 'Glalie', 'Drifblim', 'Skuntank', 'Spiritomb', 'Drapion', 'Toxicroak',
356
- 'Abomasnow', 'Weavile', 'Tangrowth', 'Electivire', 'Magmortar', 'Dusknoir', 'Froslass', 'Rotom', 'Liepard', 'Gigalith',
357
- 'Swoobat', 'Scolipede', 'Basculin', 'Krookodile', 'Sigilyph', 'Cofagrigus', 'Garbodor', 'Zoroark', 'Gothitelle', 'Jellicent',
358
- 'Galvantula', 'Beheeyem', 'Chandelure', 'Golurk', 'Bisharp', 'Mandibuzz', 'Hydreigon', 'Volcarona', 'Pangoro', 'Meowstic',
359
- 'Aegislash', 'Slurpuff', 'Malamar', 'Trevenant', 'Gourgeist', 'Noivern', 'Decidueye', 'Incineroar', 'Toxapex', 'Araquanid',
360
- 'Shiinotic', 'Salazzle', 'Bewear', 'Golisopod', 'Palossand', 'Silvally', 'Mimikyu', 'Dhelmise', 'Nihilego', 'Xurkitree',
361
- 'Guzzlord', 'Poipole', 'Naganadel', 'Blacephalon', 'Corviknight', 'Orbeetle', 'Thievul', 'Coalossal', 'Centiskorch', 'Grapploct',
362
- 'Polteageist', 'Hatterene', 'Grimmsnarl', 'Obstagoon', 'Cursola', 'Mr. Rime', 'Runerigus', 'Dracovish', 'Dragapult', 'Spectrier',
363
- ];
364
- const species = this.dex.species.get(set.species);
365
- if (!spookyMonsList.includes(species.baseSpecies) && species.id !== 'lycanrocmidnight') {
366
- return [`${species.name} is banned for not looking spooky enough.`];
367
- }
368
- },
369
- },
370
358
  {
371
359
  name: "[Gen 8] 2v2 Doubles",
372
360
  desc: `Double battle where you bring four Pok&eacute;mon to Team Preview and choose only two.`,
@@ -484,11 +472,10 @@ exports.Formats = [
484
472
  ],
485
473
  // Used to distinguish UU from below UU in the client
486
474
  restricted: [
487
- 'Absol-Mega', 'Aegislash', 'Aggron-Mega', 'Altaria-Mega', 'Amoonguss', 'Beedrill-Mega', 'Bisharp', 'Breloom', 'Buzzwole', 'Celesteela',
488
- 'Chesnaught', 'Crobat', 'Donphan', 'Dragonite', 'Hippowdon', 'Honchkrow', 'Hoopa-Unbound', 'Infernape', 'Jirachi', 'Keldeo', 'Krookodile',
489
- 'Mamoswine', 'Mandibuzz', 'Manectric-Mega', 'Melmetal', 'Mew', 'Mienshao', 'Moltres-Base', 'Nihilego', 'Porygon2', 'Regieleki', 'Ribombee',
490
- 'Rotom-Heat', 'Rotom-Wash', 'Sableye-Mega', 'Scizor', 'Shuckle', 'Skarmory', 'Slowking', 'Slowking-Galar', 'Staraptor', 'Swampert', 'Tangrowth',
491
- 'Umbreon', 'Urshifu-Rapid-Strike',
475
+ 'Absol-Mega', 'Aegislash', 'Alomomola', 'Altaria-Mega', 'Amoonguss', 'Beedrill-Mega', 'Bisharp', 'Breloom', 'Celesteela',
476
+ 'Donphan', 'Dragonite', 'Hippowdon', 'Infernape', 'Keldeo', 'Krookodile', 'Mandibuzz', 'Manectric-Mega', 'Melmetal', 'Mew',
477
+ 'Moltres-Base', 'Porygon2', 'Regieleki', 'Rotom-Heat', 'Rotom-Wash', 'Scizor', 'Skarmory', 'Slowking', 'Slowking-Galar',
478
+ 'Swampert-Base', 'Tangrowth', 'Umbreon', 'Urshifu-Rapid-Strike',
492
479
  ],
493
480
  },
494
481
  {
@@ -504,8 +491,8 @@ exports.Formats = [
504
491
  'Arceus', 'Blastoise-Mega', 'Blaziken', 'Calyrex-Ice', 'Calyrex-Shadow', 'Darkrai', 'Deoxys-Base', 'Deoxys-Attack', 'Dialga', 'Dracovish', 'Dragapult',
505
492
  'Eternatus', 'Genesect', 'Gengar-Mega', 'Giratina', 'Giratina-Origin', 'Groudon', 'Ho-Oh', 'Hoopa-Unbound', 'Kangaskhan-Mega', 'Kartana', 'Kyogre',
506
493
  'Kyurem-Black', 'Kyurem-White', 'Lucario-Mega', 'Lugia', 'Lunala', 'Magearna', 'Marshadow', 'Mawile-Mega', 'Medicham-Mega', 'Metagross-Mega', 'Mewtwo',
507
- 'Naganadel', 'Necrozma-Dawn-Wings', 'Necrozma-Dusk-Mane', 'Palkia', 'Pheromosa', 'Rayquaza', 'Reshiram', 'Salamence-Mega', 'Shaymin-Sky', 'Solgaleo',
508
- 'Spectrier', 'Urshifu-Base', 'Xerneas', 'Yveltal', 'Zacian', 'Zacian-Crowned', 'Zamazenta', 'Zamazenta-Crowned', 'Zekrom', 'Zygarde-Base',
494
+ 'Moltres-Galar', 'Naganadel', 'Necrozma-Dawn-Wings', 'Necrozma-Dusk-Mane', 'Palkia', 'Pheromosa', 'Rayquaza', 'Reshiram', 'Salamence-Mega', 'Shaymin-Sky',
495
+ 'Solgaleo', 'Spectrier', 'Urshifu-Base', 'Xerneas', 'Yveltal', 'Zacian', 'Zacian-Crowned', 'Zamazenta', 'Zamazenta-Crowned', 'Zekrom', 'Zygarde-Base',
509
496
  'Battle Bond', 'Moody', 'Power Construct', 'Shadow Tag',
510
497
  'Bright Powder', 'Damp Rock', 'Focus Band', 'King\'s Rock', 'Lax Incense', 'Quick Claw', 'Smooth Rock', 'Terrain Extender', 'Baton Pass',
511
498
  ],
@@ -529,6 +516,7 @@ exports.Formats = [
529
516
  `&bullet; <a href="https://www.smogon.com/forums/threads/3674163/">Fusion Evolution UU</a>`,
530
517
  ],
531
518
  mod: "fusionevolutionuu",
519
+ searchShow: false,
532
520
  ruleset: ['Standard NatDex', 'OHKO Clause', 'Evasion Moves Clause', 'Species Clause', 'Dynamax Clause', 'Sleep Clause Mod', 'Z-Move Clause', 'Data Mod', 'Mega Data Mod'],
533
521
  banlist: [
534
522
  'All Pokemon', 'Lopunnite', 'Tapu Lop-Mega', 'Red Orb', 'Grousle-Primal',
@@ -570,343 +558,137 @@ exports.Formats = [
570
558
  column: 2,
571
559
  },
572
560
  {
573
- name: "[Gen 8] Inheritance",
574
- desc: `Pok&eacute;mon may use the ability and moves of another, as long as they forfeit their own learnset.`,
561
+ name: "[Gen 8] Sketchmons",
562
+ desc: `Pok&eacute;mon can learn one of any move they don't normally learn, barring the few that are banned.`,
575
563
  threads: [
576
- `&bullet; <a href="https://www.smogon.com/forums/threads/3656811/">Inheritance</a>`,
564
+ `&bullet; <a href="https://www.smogon.com/forums/threads/3680298/">Sketchmons</a>`,
577
565
  ],
578
566
  mod: 'gen8',
579
- // searchShow: false,
580
- ruleset: ['Standard', '2 Ability Clause', 'Dynamax Clause'],
567
+ ruleset: ['Standard', 'Dynamax Clause', 'Sketchmons Move Legality'],
581
568
  banlist: [
582
- 'Blacephalon', 'Blaziken', 'Butterfree', 'Calyrex-Ice', 'Calyrex-Shadow', 'Chansey', 'Combusken', 'Cresselia', 'Darmanitan-Galar', 'Dialga', 'Dracovish',
583
- 'Eternatus', 'Giratina', 'Giratina-Origin', 'Groudon', 'Ho-Oh', 'Kartana', 'Kyogre', 'Kyurem-Black', 'Kyurem-White', 'Landorus-Base', 'Lugia', 'Lunala',
584
- 'Magearna', 'Marshadow', 'Melmetal', 'Mewtwo', 'Natu', 'Necrozma-Dawn-Wings', 'Necrozma-Dusk-Mane', 'Palkia', 'Pheromosa', 'Rayquaza', 'Regieleki',
585
- 'Regigigas', 'Reshiram', 'Sableye', 'Shedinja', 'Solgaleo', 'Spectrier', 'Tapu Koko', 'Toxtricity', 'Torkoal', 'Urshifu-Base', 'Xatu', 'Xerneas', 'Yveltal',
586
- 'Zacian', 'Zacian-Crowned', 'Zamazenta', 'Zamazenta-Crowned', 'Zeraora', 'Zekrom', 'Arena Trap', 'Contrary', 'Drizzle', 'Huge Power', 'Imposter', 'Innards Out',
587
- 'Libero', 'Moody', 'Power Construct', 'Pure Power', 'Quick Draw', 'Shadow Tag', 'Sheer Force', 'Simple', 'Unaware', 'Unburden', 'Water Bubble', 'King\'s Rock',
588
- 'Quick Claw', 'Baton Pass', 'Bolt Beak', 'Fishious Rend', 'Shell Smash', 'Thousand Arrows',
569
+ 'Calyrex-Ice', 'Calyrex-Shadow', 'Cinderace', 'Darmanitan-Galar', 'Dialga', 'Dracovish', 'Dragapult', 'Eternatus', 'Genesect',
570
+ 'Giratina', 'Giratina-Origin', 'Groudon', 'Hawlucha', 'Ho-Oh', 'Kartana', 'Kyogre', 'Kyurem-Black', 'Kyurem-White', 'Landorus-Base',
571
+ 'Lugia', 'Lunala', 'Marshadow', 'Mewtwo', 'Naganadel', 'Necrozma-Dawn-Wings', 'Necrozma-Dusk-Mane', 'Palkia', 'Pheromosa',
572
+ 'Porygon-Z', 'Rayquaza', 'Regieleki', 'Reshiram', 'Rillaboom', 'Shedinja', 'Solgaleo', 'Spectrier', 'Swoobat', 'Tapu Bulu',
573
+ 'Urshifu-Base', 'Xerneas', 'Yveltal', 'Zacian', 'Zacian-Crowned', 'Zamazenta', 'Zamazenta-Crowned', 'Zekrom', 'Zeraora', 'Zygarde-Base',
574
+ 'Arena Trap', 'Moody', 'Power Construct', 'Sand Rush', 'Shadow Tag', 'King\'s Rock', 'Baton Pass',
589
575
  ],
590
- getEvoFamily(speciesid) {
591
- let species = Dex.species.get(speciesid);
592
- while (species.prevo) {
593
- species = Dex.species.get(species.prevo);
594
- }
595
- return species.id;
596
- },
597
- validateSet(set, teamHas) {
598
- const unreleased = (pokemon) => pokemon.tier === "Unreleased" && pokemon.isNonstandard === "Unobtainable";
599
- if (!teamHas.abilityMap) {
600
- teamHas.abilityMap = Object.create(null);
601
- for (const pokemon of Dex.species.all()) {
602
- if (pokemon.isNonstandard || unreleased(pokemon))
603
- continue;
604
- if (pokemon.requiredAbility || pokemon.requiredItem || pokemon.requiredMove)
605
- continue;
606
- if (this.ruleTable.isBannedSpecies(pokemon))
607
- continue;
608
- for (const key of Object.values(pokemon.abilities)) {
609
- const abilityId = this.dex.toID(key);
610
- if (abilityId in teamHas.abilityMap) {
611
- teamHas.abilityMap[abilityId][pokemon.evos ? 'push' : 'unshift'](pokemon.id);
612
- }
613
- else {
614
- teamHas.abilityMap[abilityId] = [pokemon.id];
615
- }
616
- }
576
+ restricted: [
577
+ 'Acupressure', 'Astral Barrage', 'Belly Drum', 'Bolt Beak', 'Clangorous Soul', 'Double Iron Bash', 'Electrify', 'Extreme Speed',
578
+ 'Fishious Rend', 'Geomancy', 'Glacial Lance', 'Lovely Kiss', 'No Retreat', 'Oblivion Wing', 'Octolock', 'Quiver Dance', 'Secret Sword',
579
+ 'Shell Smash', 'Shift Gear', 'Sleep Powder', 'Spore', 'Thousand Arrows', 'Transform', 'V-create', 'Wicked Blow',
580
+ ],
581
+ },
582
+ {
583
+ name: "[Gen 8] AAA Doubles",
584
+ desc: `Pok&eacute;mon have access to almost any ability, in a doubles setting.`,
585
+ threads: [
586
+ `&bullet; <a href="https://www.smogon.com/forums/posts/8299984">AAA Doubles</a>`,
587
+ ],
588
+ mod: 'gen8',
589
+ gameType: 'doubles',
590
+ ruleset: ['[Gen 8] Doubles OU', 'Sleep Clause Mod', '2 Ability Clause', '!Obtainable Abilities'],
591
+ banlist: [
592
+ 'Kyurem-Black', 'Regigigas', 'Shedinja', 'Urshifu-Rapid-Strike', 'Zygarde-Base', 'Anger Point', 'Arena Trap', 'Comatose', 'Contrary',
593
+ 'Desolate Land', 'Fluffy', 'Fur Coat', 'Gorilla Tactics', 'Huge Power', 'Ice Scales', 'Illusion', 'Imposter', 'Innards Out', 'Intrepid Sword',
594
+ 'Libero', 'Moody', 'Neutralizing Gas', 'Parental Bond', 'Prankster', 'Primordial Sea', 'Protean', 'Pure Power', 'Rattled', 'Serene Grace',
595
+ 'Simple', 'Soul-Heart', 'Stakeout', 'Steam Engine', 'Speed Boost', 'Water Bubble', 'Water Compaction', 'Wonder Guard', 'King\'s Rock',
596
+ 'Weakness Policy', 'Beat Up', 'Stored Power',
597
+ ],
598
+ },
599
+ // Other Metagames
600
+ ///////////////////////////////////////////////////////////////////
601
+ {
602
+ section: "Other Metagames",
603
+ column: 2,
604
+ },
605
+ {
606
+ name: "[Gen 8] Balanced Hackmons",
607
+ desc: `Anything that can be hacked in-game and is usable in local battles is allowed.`,
608
+ threads: [
609
+ `&bullet; <a href="https://www.smogon.com/forums/threads/3656408/">Balanced Hackmons</a>`,
610
+ `&bullet; <a href="https://www.smogon.com/forums/threads/3659817/">BH Resources</a>`,
611
+ ],
612
+ mod: 'gen8',
613
+ ruleset: ['-Nonexistent', 'OHKO Clause', 'Evasion Moves Clause', 'Forme Clause', 'Team Preview', 'HP Percentage Mod', 'Cancel Mod', 'Dynamax Clause', 'Sleep Moves Clause', 'Endless Battle Clause'],
614
+ banlist: [
615
+ 'Calyrex-Shadow', 'Cramorant-Gorging', 'Darmanitan-Galar-Zen', 'Eternatus-Eternamax', 'Shedinja', 'Zacian-Crowned',
616
+ 'Arena Trap', 'Contrary', 'Gorilla Tactics', 'Huge Power', 'Illusion', 'Innards Out', 'Intrepid Sword', 'Libero',
617
+ 'Magnet Pull', 'Moody', 'Neutralizing Gas', 'Parental Bond', 'Protean', 'Pure Power', 'Shadow Tag', 'Stakeout',
618
+ 'Water Bubble', 'Wonder Guard', 'Comatose + Sleep Talk', 'Rusted Sword', 'Court Change', 'Bolt Beak', 'Double Iron Bash',
619
+ 'Octolock', 'Shell Smash',
620
+ ],
621
+ onChangeSet(set) {
622
+ const item = this.dex.toID(set.item);
623
+ if (set.species === 'Zacian' && item === 'rustedsword') {
624
+ set.species = 'Zacian-Crowned';
625
+ set.ability = 'Intrepid Sword';
626
+ const ironHead = set.moves.indexOf('ironhead');
627
+ if (ironHead >= 0) {
628
+ set.moves[ironHead] = 'behemothblade';
617
629
  }
618
630
  }
619
- const problem = this.validateForme(set);
620
- if (problem.length)
621
- return problem;
622
- const species = this.dex.species.get(set.species);
623
- if (!species.exists || species.num < 1)
624
- return [`The Pok\u00e9mon "${set.species}" does not exist.`];
625
- if (species.isNonstandard || unreleased(species)) {
626
- return [`${species.name} is not obtainable in Generation ${this.dex.gen}.`];
627
- }
628
- const name = set.name;
629
- if (this.ruleTable.isBannedSpecies(species)) {
630
- return this.validateSet(set, teamHas);
631
+ if (set.species === 'Zamazenta' && item === 'rustedshield') {
632
+ set.species = 'Zamazenta-Crowned';
633
+ set.ability = 'Dauntless Shield';
634
+ const ironHead = set.moves.indexOf('ironhead');
635
+ if (ironHead >= 0) {
636
+ set.moves[ironHead] = 'behemothbash';
637
+ }
631
638
  }
632
- const ability = this.dex.abilities.get(set.ability);
633
- if (!ability.exists || ability.isNonstandard)
634
- return [`${name} needs to have a valid ability.`];
635
- const pokemonWithAbility = teamHas.abilityMap[ability.id];
636
- if (!pokemonWithAbility)
637
- return [`${ability.name} is not available on a legal Pok\u00e9mon.`];
638
- this.format.debug = true;
639
- if (!teamHas.abilitySources)
640
- teamHas.abilitySources = Object.create(null);
641
- const validSources = teamHas.abilitySources[this.dex.toID(set.species)] = []; // Evolution families
642
- let canonicalSource = ''; // Specific for the basic implementation of Donor Clause (see onValidateTeam).
643
- for (const donor of pokemonWithAbility) {
644
- const donorSpecies = this.dex.species.get(donor);
645
- let format = this.format;
646
- if (!format.getEvoFamily)
647
- format = this.dex.formats.get('gen8inheritance');
648
- const evoFamily = format.getEvoFamily(donorSpecies.id);
649
- if (validSources.includes(evoFamily))
639
+ },
640
+ },
641
+ {
642
+ name: "[Gen 8] Mix and Mega",
643
+ desc: `Mega evolve any Pok&eacute;mon with any mega stone and no limit. Boosts based on mega evolution from gen 7.`,
644
+ threads: [
645
+ `&bullet; <a href="https://www.smogon.com/forums/threads/3656469/">Mix and Mega</a>`,
646
+ `&bullet; <a href="https://www.smogon.com/forums/threads/3659028/">M&amp;M Resources</a>`,
647
+ ],
648
+ mod: 'mixandmega',
649
+ ruleset: ['Obtainable', 'Species Clause', 'Nickname Clause', 'OHKO Clause', 'Evasion Moves Clause', 'Team Preview', 'HP Percentage Mod', 'Cancel Mod', 'Overflow Stat Mod', 'Dynamax Clause', 'Sleep Clause Mod', 'Endless Battle Clause'],
650
+ banlist: [
651
+ 'Calyrex-Shadow', 'Kyogre', 'Zacian',
652
+ 'Beedrillite', 'Blazikenite', 'Gengarite', 'Kangaskhanite', 'Mawilite', 'Medichamite', 'Pidgeotite',
653
+ 'Moody', 'Shadow Tag', 'Baton Pass', 'Electrify',
654
+ ],
655
+ restricted: [
656
+ 'Calyrex-Ice', 'Dialga', 'Eternatus', 'Gengar', 'Giratina', 'Groudon', 'Ho-Oh', 'Kyurem-Black', 'Kyurem-White',
657
+ 'Lugia', 'Lunala', 'Marshadow', 'Melmetal', 'Mewtwo', 'Naganadel', 'Necrozma-Dawn-Wings', 'Necrozma-Dusk-Mane',
658
+ 'Palkia', 'Rayquaza', 'Regigigas', 'Reshiram', 'Urshifu-Base', 'Xerneas', 'Yveltal', 'Zekrom', 'Zygarde-Complete',
659
+ ],
660
+ onValidateTeam(team) {
661
+ const itemTable = new Set();
662
+ for (const set of team) {
663
+ const item = this.dex.items.get(set.item);
664
+ if (!item.megaStone)
650
665
  continue;
651
- set.species = donorSpecies.name;
652
- set.name = donorSpecies.baseSpecies;
653
- const problems = this.validateSet(set, teamHas) || [];
654
- if (!problems.length) {
655
- validSources.push(evoFamily);
656
- canonicalSource = donorSpecies.name;
666
+ const species = this.dex.species.get(set.species);
667
+ if (species.isNonstandard)
668
+ return [`${species.baseSpecies} does not exist in gen 8.`];
669
+ if (this.ruleTable.isRestrictedSpecies(species) || this.toID(set.ability) === 'powerconstruct') {
670
+ return [`${species.name} is not allowed to hold ${item.name}.`];
657
671
  }
658
- // Specific for the basic implementation of Donor Clause (see onValidateTeam).
659
- if (validSources.length > 1)
660
- break;
672
+ if (itemTable.has(item.id)) {
673
+ return [`You are limited to one of each mega stone.`, `(You have more than one ${item.name})`];
674
+ }
675
+ itemTable.add(item.id);
661
676
  }
662
- this.format.debug = false;
663
- set.name = name;
664
- set.species = species.name;
665
- if (!validSources.length) {
666
- if (pokemonWithAbility.length > 1)
667
- return [`${name}'s set is illegal.`];
668
- return [`${name} has an illegal set with an ability from ${this.dex.species.get(pokemonWithAbility[0]).name}.`];
677
+ },
678
+ onBegin() {
679
+ for (const pokemon of this.getAllPokemon()) {
680
+ pokemon.m.originalSpecies = pokemon.baseSpecies.name;
669
681
  }
670
- // Protocol: Include the data of the donor species in the `ability` data slot.
671
- // Afterwards, we are going to reset the name to what the user intended.
672
- set.ability = `${set.ability}0${canonicalSource}`;
673
- return null;
674
682
  },
675
- onValidateTeam(team, f, teamHas) {
676
- if (this.format.ruleTable?.has('2abilityclause')) {
677
- const abilityTable = new Map();
678
- const base = {
679
- airlock: 'cloudnine',
680
- battlearmor: 'shellarmor',
681
- clearbody: 'whitesmoke',
682
- dazzling: 'queenlymajesty',
683
- emergencyexit: 'wimpout',
684
- filter: 'solidrock',
685
- gooey: 'tanglinghair',
686
- insomnia: 'vitalspirit',
687
- ironbarbs: 'roughskin',
688
- libero: 'protean',
689
- minus: 'plus',
690
- moxie: 'chillingneigh',
691
- powerofalchemy: 'receiver',
692
- propellertail: 'stalwart',
693
- teravolt: 'moldbreaker',
694
- turboblaze: 'moldbreaker',
695
- };
696
- for (const set of team) {
697
- let ability = this.toID(set.ability.split('0')[0]);
698
- if (!ability)
699
- continue;
700
- if (ability in base)
701
- ability = base[ability];
702
- if ((abilityTable.get(ability) || 0) >= 2) {
703
- return [
704
- `You are limited to two of each ability by 2 Ability Clause.`,
705
- `(You have more than two ${this.dex.abilities.get(ability).name} variants)`,
706
- ];
707
- }
708
- abilityTable.set(ability, (abilityTable.get(ability) || 0) + 1);
709
- }
710
- }
711
- // Donor Clause
712
- const evoFamilyLists = [];
713
- for (const set of team) {
714
- const abilitySources = teamHas.abilitySources?.[this.dex.toID(set.species)];
715
- if (!abilitySources)
716
- continue;
717
- let format = this.format;
718
- if (!format.getEvoFamily)
719
- format = this.dex.formats.get('gen8inheritance');
720
- evoFamilyLists.push(abilitySources.map(format.getEvoFamily));
721
- }
722
- // Checking actual full incompatibility would require expensive algebra.
723
- // Instead, we only check the trivial case of multiple Pokémon only legal for exactly one family. FIXME?
724
- const requiredFamilies = Object.create(null);
725
- for (const evoFamilies of evoFamilyLists) {
726
- if (evoFamilies.length !== 1)
727
- continue;
728
- const [familyId] = evoFamilies;
729
- if (!(familyId in requiredFamilies))
730
- requiredFamilies[familyId] = 1;
731
- requiredFamilies[familyId]++;
732
- if (requiredFamilies[familyId] > 2) {
733
- return [
734
- `You are limited to up to two inheritances from each evolution family by the Donor Clause.`,
735
- `(You inherit more than twice from ${this.dex.species.get(familyId).name}).`,
736
- ];
737
- }
738
- }
739
- },
740
- onBegin() {
741
- for (const pokemon of this.getAllPokemon()) {
742
- if (pokemon.baseAbility.includes('0')) {
743
- const donor = pokemon.baseAbility.split('0')[1];
744
- pokemon.m.donor = this.toID(donor);
745
- pokemon.baseAbility = this.toID(pokemon.baseAbility.split('0')[0]);
746
- pokemon.ability = pokemon.baseAbility;
747
- }
748
- }
749
- },
750
- onSwitchIn(pokemon) {
751
- if (!pokemon.m.donor)
752
- return;
753
- const donorTemplate = this.dex.species.get(pokemon.m.donor);
754
- if (!donorTemplate.exists)
755
- return;
756
- // Place volatiles on the Pokémon to show the donor details.
757
- this.add('-start', pokemon, donorTemplate.name, '[silent]');
758
- },
759
- },
760
- {
761
- name: "[Gen 8] Godly Gift",
762
- desc: `Each Pok&eacute;mon receives one base stat from a God (AG/Uber Pok&eacute;mon) depending on its position in the team. If there is no Uber Pok&eacute;mon, it uses the Pok&eacute;mon in the first slot.`,
763
- threads: [
764
- `&bullet; <a href="https://www.smogon.com/forums/threads/3660461/">Godly Gift</a>`,
765
- ],
766
- mod: 'gen8',
767
- // searchShow: false,
768
- ruleset: ['Standard', 'Dynamax Clause'],
769
- banlist: [
770
- 'Blissey', 'Calyrex-Shadow', 'Chansey', 'Marowak-Alola', 'Melmetal', 'Toxapex', 'Zacian', 'Zacian-Crowned',
771
- 'Uber > 1', 'AG ++ Uber > 1', 'Arena Trap', 'Huge Power', 'Moody', 'Pure Power', 'Shadow Tag', 'Baton Pass',
772
- ],
773
- onValidateTeam(team) {
774
- const gods = new Set();
775
- for (const set of team) {
776
- let species = this.dex.species.get(set.species);
777
- if (typeof species.battleOnly === 'string')
778
- species = this.dex.species.get(species.battleOnly);
779
- if (['ag', 'uber'].includes(this.toID(species.tier)) || this.toID(set.ability) === 'powerconstruct') {
780
- gods.add(species.name);
781
- }
782
- }
783
- if (gods.size > 1) {
784
- return [`You have too many Gods.`, `(${Array.from(gods).join(', ')} are Gods.)`];
785
- }
786
- },
787
- onModifySpeciesPriority: 3,
788
- onModifySpecies(species, target, source) {
789
- if (source || !target?.side)
790
- return;
791
- const god = target.side.team.find(set => {
792
- let godSpecies = this.dex.species.get(set.species);
793
- const validator = this.dex.formats.getRuleTable(this.dex.formats.get(`gen${this.gen}ou`));
794
- if (this.toID(set.ability) === 'powerconstruct') {
795
- return true;
796
- }
797
- if (set.item) {
798
- const item = this.dex.items.get(set.item);
799
- if (item.megaEvolves === set.species)
800
- godSpecies = this.dex.species.get(item.megaStone);
801
- }
802
- const isBanned = validator.isBannedSpecies(godSpecies);
803
- return isBanned;
804
- }) || target.side.team[0];
805
- const stat = Dex.stats.ids()[target.side.team.indexOf(target.set)];
806
- const newSpecies = this.dex.deepClone(species);
807
- let godSpecies = this.dex.species.get(god.species);
808
- if (godSpecies.forme === 'Crowned') {
809
- godSpecies = this.dex.species.get(godSpecies.changesFrom || godSpecies.baseSpecies);
810
- }
811
- newSpecies.bst -= newSpecies.baseStats[stat];
812
- newSpecies.baseStats[stat] = godSpecies.baseStats[stat];
813
- newSpecies.bst += newSpecies.baseStats[stat];
814
- return newSpecies;
815
- },
816
- },
817
- // Other Metagames
818
- ///////////////////////////////////////////////////////////////////
819
- {
820
- section: "Other Metagames",
821
- column: 2,
822
- },
823
- {
824
- name: "[Gen 8] Balanced Hackmons",
825
- desc: `Anything that can be hacked in-game and is usable in local battles is allowed.`,
826
- threads: [
827
- `&bullet; <a href="https://www.smogon.com/forums/threads/3656408/">Balanced Hackmons</a>`,
828
- `&bullet; <a href="https://www.smogon.com/forums/threads/3659817/">BH Resources</a>`,
829
- ],
830
- mod: 'gen8',
831
- ruleset: ['-Nonexistent', 'OHKO Clause', 'Evasion Moves Clause', 'Forme Clause', 'Team Preview', 'HP Percentage Mod', 'Cancel Mod', 'Dynamax Clause', 'Sleep Clause Mod', 'Endless Battle Clause'],
832
- banlist: [
833
- 'Calyrex-Shadow', 'Cramorant-Gorging', 'Darmanitan-Galar-Zen', 'Eternatus-Eternamax', 'Shedinja', 'Zacian-Crowned',
834
- 'Arena Trap', 'Contrary', 'Gorilla Tactics', 'Huge Power', 'Illusion', 'Innards Out', 'Intrepid Sword', 'Libero',
835
- 'Magnet Pull', 'Moody', 'Neutralizing Gas', 'Parental Bond', 'Protean', 'Pure Power', 'Shadow Tag', 'Stakeout',
836
- 'Water Bubble', 'Wonder Guard', 'Comatose + Sleep Talk', 'Rusted Sword', 'Court Change', 'Bolt Beak', 'Double Iron Bash',
837
- 'Octolock', 'Shell Smash',
838
- ],
839
- onChangeSet(set) {
840
- const item = this.dex.toID(set.item);
841
- if (set.species === 'Zacian' && item === 'rustedsword') {
842
- set.species = 'Zacian-Crowned';
843
- set.ability = 'Intrepid Sword';
844
- const ironHead = set.moves.indexOf('ironhead');
845
- if (ironHead >= 0) {
846
- set.moves[ironHead] = 'behemothblade';
847
- }
848
- }
849
- if (set.species === 'Zamazenta' && item === 'rustedshield') {
850
- set.species = 'Zamazenta-Crowned';
851
- set.ability = 'Dauntless Shield';
852
- const ironHead = set.moves.indexOf('ironhead');
853
- if (ironHead >= 0) {
854
- set.moves[ironHead] = 'behemothbash';
855
- }
856
- }
857
- },
858
- },
859
- {
860
- name: "[Gen 8] Mix and Mega",
861
- desc: `Mega evolve any Pok&eacute;mon with any mega stone and no limit. Boosts based on mega evolution from gen 7.`,
862
- threads: [
863
- `&bullet; <a href="https://www.smogon.com/forums/threads/3656469/">Mix and Mega</a>`,
864
- `&bullet; <a href="https://www.smogon.com/forums/threads/3659028/">M&amp;M Resources</a>`,
865
- ],
866
- mod: 'mixandmega',
867
- ruleset: ['Obtainable', 'Species Clause', 'Nickname Clause', 'OHKO Clause', 'Evasion Moves Clause', 'Team Preview', 'HP Percentage Mod', 'Cancel Mod', 'Overflow Stat Mod', 'Dynamax Clause', 'Sleep Clause Mod', 'Endless Battle Clause'],
868
- banlist: [
869
- 'Calyrex-Shadow', 'Kyogre', 'Zacian',
870
- 'Beedrillite', 'Blazikenite', 'Gengarite', 'Kangaskhanite', 'Mawilite', 'Medichamite', 'Pidgeotite',
871
- 'Moody', 'Shadow Tag', 'Baton Pass', 'Electrify',
872
- ],
873
- restricted: [
874
- 'Calyrex-Ice', 'Dialga', 'Eternatus', 'Gengar', 'Giratina', 'Groudon', 'Ho-Oh', 'Kyurem-Black', 'Kyurem-White',
875
- 'Lugia', 'Lunala', 'Marshadow', 'Melmetal', 'Mewtwo', 'Naganadel', 'Necrozma-Dawn-Wings', 'Necrozma-Dusk-Mane',
876
- 'Palkia', 'Rayquaza', 'Regigigas', 'Reshiram', 'Urshifu-Base', 'Xerneas', 'Yveltal', 'Zekrom', 'Zygarde-Complete',
877
- ],
878
- onValidateTeam(team) {
879
- const itemTable = new Set();
880
- for (const set of team) {
881
- const item = this.dex.items.get(set.item);
882
- if (!item?.megaStone)
883
- continue;
884
- const species = this.dex.species.get(set.species);
885
- if (species.isNonstandard)
886
- return [`${species.baseSpecies} does not exist in gen 8.`];
887
- if (this.ruleTable.isRestrictedSpecies(species) || this.toID(set.ability) === 'powerconstruct') {
888
- return [`${species.name} is not allowed to hold ${item.name}.`];
889
- }
890
- if (itemTable.has(item.id)) {
891
- return [`You are limited to one of each mega stone.`, `(You have more than one ${item.name})`];
892
- }
893
- itemTable.add(item.id);
894
- }
895
- },
896
- onBegin() {
897
- for (const pokemon of this.getAllPokemon()) {
898
- pokemon.m.originalSpecies = pokemon.baseSpecies.name;
899
- }
900
- },
901
- onSwitchIn(pokemon) {
902
- // @ts-ignore
903
- const oMegaSpecies = this.dex.species.get(pokemon.species.originalMega);
904
- if (oMegaSpecies.exists && pokemon.m.originalSpecies !== oMegaSpecies.baseSpecies) {
905
- // Place volatiles on the Pokémon to show its mega-evolved condition and details
906
- this.add('-start', pokemon, oMegaSpecies.requiredItem || oMegaSpecies.requiredMove, '[silent]');
907
- const oSpecies = this.dex.species.get(pokemon.m.originalSpecies);
908
- if (oSpecies.types.length !== pokemon.species.types.length || oSpecies.types[1] !== pokemon.species.types[1]) {
909
- this.add('-start', pokemon, 'typechange', pokemon.species.types.join('/'), '[silent]');
683
+ onSwitchIn(pokemon) {
684
+ // @ts-ignore
685
+ const oMegaSpecies = this.dex.species.get(pokemon.species.originalMega);
686
+ if (oMegaSpecies.exists && pokemon.m.originalSpecies !== oMegaSpecies.baseSpecies) {
687
+ // Place volatiles on the Pokémon to show its mega-evolved condition and details
688
+ this.add('-start', pokemon, oMegaSpecies.requiredItem || oMegaSpecies.requiredMove, '[silent]');
689
+ const oSpecies = this.dex.species.get(pokemon.m.originalSpecies);
690
+ if (oSpecies.types.length !== pokemon.species.types.length || oSpecies.types[1] !== pokemon.species.types[1]) {
691
+ this.add('-start', pokemon, 'typechange', pokemon.species.types.join('/'), '[silent]');
910
692
  }
911
693
  }
912
694
  },
@@ -931,7 +713,7 @@ exports.Formats = [
931
713
  'Archeops', 'Buzzwole', 'Calyrex-Ice', 'Calyrex-Shadow', 'Dialga', 'Dracovish', 'Dragapult', 'Dragonite', 'Eternatus', 'Gengar', 'Giratina', 'Giratina-Origin',
932
714
  'Groudon', 'Ho-Oh', 'Kartana', 'Keldeo', 'Kyogre', 'Kyurem', 'Kyurem-Black', 'Kyurem-White', 'Lugia', 'Lunala', 'Magearna', 'Marshadow', 'Melmetal', 'Mewtwo',
933
715
  'Naganadel', 'Necrozma-Dawn-Wings', 'Necrozma-Dusk-Mane', 'Noivern', 'Palkia', 'Pheromosa', 'Rayquaza', 'Regigigas', 'Reshiram', 'Shedinja', 'Solgaleo', 'Spectrier',
934
- 'Urshifu-Base', 'Urshifu-Rapid-Strike', 'Victini', 'Xerneas', 'Yveltal', 'Zacian', 'Zacian-Crowned', 'Zamazenta-Base', 'Zekrom', 'Zeraora', 'Zygarde-Base',
716
+ 'Urshifu-Base', 'Urshifu-Rapid-Strike', 'Victini', 'Weavile', 'Xerneas', 'Yveltal', 'Zacian', 'Zacian-Crowned', 'Zamazenta-Base', 'Zekrom', 'Zeraora', 'Zygarde-Base',
935
717
  'Arena Trap', 'Comatose', 'Contrary', 'Fluffy', 'Fur Coat', 'Gorilla Tactics', 'Huge Power', 'Ice Scales', 'Illusion', 'Imposter', 'Innards Out', 'Intrepid Sword',
936
718
  'Libero', 'Magnet Pull', 'Moody', 'Neutralizing Gas', 'Parental Bond', 'Poison Heal', 'Power Construct', 'Protean', 'Pure Power', 'Shadow Tag', 'Simple', 'Stakeout',
937
719
  'Speed Boost', 'Water Bubble', 'Wonder Guard', 'King\'s Rock', 'Baton Pass',
@@ -955,11 +737,12 @@ exports.Formats = [
955
737
  mod: 'gen8',
956
738
  ruleset: ['Standard', 'STABmons Move Legality', 'Dynamax Clause', 'Sleep Moves Clause'],
957
739
  banlist: [
958
- 'Calyrex-Ice', 'Calyrex-Shadow', 'Darmanitan-Galar', 'Dialga', 'Dracovish', 'Dragapult', 'Eternatus', 'Genesect', 'Giratina', 'Giratina-Origin',
959
- 'Groudon', 'Ho-Oh', 'Kartana', 'Kyogre', 'Kyurem-Black', 'Kyurem-White', 'Landorus', 'Landorus-Therian', 'Lugia', 'Lunala', 'Marshadow', 'Mewtwo',
960
- 'Naganadel', 'Necrozma-Dawn-Wings', 'Necrozma-Dusk-Mane', 'Palkia', 'Pheromosa', 'Porygon-Z', 'Rayquaza', 'Reshiram', 'Silvally', 'Solgaleo',
961
- 'Spectrier', 'Tapu Koko', 'Thundurus-Base', 'Urshifu-Base', 'Xerneas', 'Yveltal', 'Zacian', 'Zacian-Crowned', 'Zamazenta', 'Zamazenta-Crowned',
962
- 'Zapdos-Galar', 'Zekrom', 'Zygarde-Base', 'Arena Trap', 'Magnet Pull', 'Moody', 'Power Construct', 'Shadow Tag', 'King\'s Rock', 'Baton Pass',
740
+ 'Calyrex-Ice', 'Calyrex-Shadow', 'Darmanitan-Galar', 'Dialga', 'Dracovish', 'Dragapult', 'Eternatus', 'Genesect', 'Garchomp', 'Giratina',
741
+ 'Giratina-Origin', 'Groudon', 'Ho-Oh', 'Kartana', 'Kyogre', 'Kyurem-Black', 'Kyurem-White', 'Landorus', 'Landorus-Therian', 'Lugia', 'Lunala',
742
+ 'Marshadow', 'Mewtwo', 'Naganadel', 'Necrozma-Dawn-Wings', 'Necrozma-Dusk-Mane', 'Palkia', 'Pheromosa', 'Porygon-Z', 'Rayquaza', 'Reshiram',
743
+ 'Silvally', 'Solgaleo', 'Spectrier', 'Tapu Bulu', 'Tapu Koko', 'Thundurus-Base', 'Urshifu-Base', 'Xerneas', 'Yveltal', 'Zacian', 'Zacian-Crowned',
744
+ 'Zamazenta', 'Zamazenta-Crowned', 'Zapdos-Galar', 'Zekrom', 'Zygarde-Base', 'Arena Trap', 'Magnet Pull', 'Moody', 'Power Construct', 'Shadow Tag',
745
+ 'King\'s Rock', 'Baton Pass',
963
746
  ],
964
747
  restricted: [
965
748
  'Acupressure', 'Astral Barrage', 'Belly Drum', 'Bolt Beak', 'Clangorous Soul', 'Double Iron Bash', 'Electrify', 'Extreme Speed', 'Fishious Rend',
@@ -995,25 +778,61 @@ exports.Formats = [
995
778
  'Kyurem-White', 'Lugia', 'Lunala', 'Magearna', 'Marshadow', 'Mewtwo', 'Necrozma-Dawn-Wings', 'Necrozma-Dusk-Mane', 'Palkia', 'Rayquaza',
996
779
  'Reshiram', 'Solgaleo', 'Urshifu-Base', 'Xerneas', 'Yveltal', 'Zacian', 'Zacian-Crowned', 'Zamazenta', 'Zamazenta-Crowned', 'Zekrom',
997
780
  'Zygarde-Complete', 'Moody', 'Power Construct', 'Shadow Tag', 'Acupressure', 'Aromatic Mist', 'Baton Pass', 'Coaching', 'Court Change',
998
- 'Decorate', 'Flatter', 'Floral Healing', 'Follow Me', 'Heal Pulse', 'Rage Powder', 'Swagger',
781
+ 'Decorate', 'Final Gambit', 'Flatter', 'Floral Healing', 'Flower Shield', 'Follow Me', 'Heal Pulse', 'Rage Powder', 'Swagger',
999
782
  ],
1000
783
  },
1001
784
  {
1002
- name: "[Gen 8] Bonus Type",
1003
- desc: `Pok&eacute;mon can be nicknamed the name of a type to have that type added onto their current ones.`,
785
+ section: "BD/SP",
786
+ column: 2,
787
+ },
788
+ {
789
+ name: "[Gen 8 BDSP] Random Battle",
790
+ desc: `Randomized teams of level-balanced Pok&eacute;mon with sets that are generated to be competitively viable.`,
791
+ mod: 'gen8bdsp',
792
+ team: 'random',
793
+ searchShow: false,
794
+ challengeShow: false,
795
+ tournamentShow: false,
796
+ ruleset: ['[Gen 8] Random Battle'],
797
+ },
798
+ {
799
+ name: "[Gen 8 BDSP] OU",
1004
800
  threads: [
1005
- `&bullet; <a href="https://www.smogon.com/forums/threads/3683173/">Bonus Type</a>`,
801
+ `&bullet; <a href="https://www.smogon.com/forums/threads/3693629/">BDSP OU Metagame Discussion</a>`,
802
+ `&bullet; <a href="https://www.smogon.com/forums/threads/3693620/">BDSP OU Viability List</a>`,
1006
803
  ],
1007
- mod: 'gen8',
804
+ mod: 'gen8bdsp',
805
+ ruleset: ['Standard'],
806
+ banlist: ['Uber', 'Arena Trap', 'Drizzle', 'Moody', 'Shadow Tag', 'King\'s Rock', 'Razor Fang', 'Baton Pass'],
807
+ },
808
+ {
809
+ name: "[Gen 8 BDSP] Doubles OU",
810
+ mod: 'gen8bdsp',
811
+ gameType: 'doubles',
1008
812
  searchShow: false,
1009
- ruleset: ['Standard', 'Dynamax Clause', 'Bonus Type Rule', '!Nickname Clause'],
1010
- banlist: [
1011
- 'Calyrex-Ice', 'Calyrex-Shadow', 'Darmanitan-Galar', 'Dialga', 'Dracovish', 'Dragapult', 'Dragonite', 'Eternatus', 'Genesect',
1012
- 'Giratina', 'Giratina-Origin', 'Groudon', 'Ho-Oh', 'Kartana', 'Kyogre', 'Kyurem-Black', 'Kyurem-White', 'Landorus-Base', 'Lugia',
1013
- 'Lunala', 'Magearna', 'Marshadow', 'Mewtwo', 'Naganadel', 'Necrozma-Dawn-Wings', 'Necrozma-Dusk-Mane', 'Palkia', 'Pheromosa',
1014
- 'Rayquaza', 'Reshiram', 'Shedinja', 'Solgaleo', 'Spectrier', 'Urshifu-Base', 'Xerneas', 'Yveltal', 'Zacian', 'Zacian-Crowned',
1015
- 'Zamazenta', 'Zamazenta-Crowned', 'Zekrom', 'Zygarde-Base', 'Arena Trap', 'Moody', 'Power Construct', 'Shadow Tag', 'Baton Pass',
813
+ ruleset: ['Standard Doubles'],
814
+ banlist: ['DUber'],
815
+ },
816
+ {
817
+ name: "[Gen 8 BDSP] Battle Festival Doubles",
818
+ mod: 'gen8bdsp',
819
+ gameType: 'doubles',
820
+ // VGC Timer is temporary
821
+ ruleset: ['Flat Rules', '!! Adjust Level = 50', 'Min Source Gen = 8', 'VGC Timer'],
822
+ },
823
+ {
824
+ name: "[Gen 8 BDSP] Pure Hackmons",
825
+ desc: `Anything that can be hacked in-game and is usable in local battles is allowed.`,
826
+ threads: [
827
+ `&bullet; <a href="https://www.smogon.com/forums/threads/3656851/">Pure Hackmons</a>`,
1016
828
  ],
829
+ mod: 'gen8bdsp',
830
+ searchShow: false,
831
+ ruleset: ['-Nonexistent', 'Team Preview', 'HP Percentage Mod', 'Cancel Mod', 'Endless Battle Clause'],
832
+ },
833
+ {
834
+ section: "Challengeable OMs",
835
+ column: 2,
1017
836
  },
1018
837
  {
1019
838
  name: "[Gen 8] Camomons",
@@ -1025,10 +844,10 @@ exports.Formats = [
1025
844
  searchShow: false,
1026
845
  ruleset: ['Obtainable', 'Species Clause', 'Nickname Clause', 'OHKO Clause', 'Evasion Moves Clause', 'Team Preview', 'HP Percentage Mod', 'Cancel Mod', 'Dynamax Clause', 'Sleep Clause Mod', 'Endless Battle Clause'],
1027
846
  banlist: [
1028
- 'Calyrex-Ice', 'Calyrex-Shadow', 'Darmanitan-Galar', 'Dialga', 'Dracovish', 'Dragonite', 'Eternatus', 'Genesect', 'Giratina', 'Giratina-Origin',
1029
- 'Groudon', 'Ho-Oh', 'Hydreigon', 'Kartana', 'Kyogre', 'Kyurem', 'Kyurem-Black', 'Kyurem-White', 'Landorus-Base', 'Latias', 'Latios', 'Lugia',
1030
- 'Lunala', 'Marshadow', 'Mewtwo', 'Necrozma-Dawn-Wings', 'Necrozma-Dusk-Mane', 'Palkia', 'Rayquaza', 'Reshiram', 'Shedinja', 'Slowking-Galar',
1031
- 'Solgaleo', 'Xerneas', 'Yveltal', 'Zacian', 'Zacian-Crowned', 'Zamazenta', 'Zamazenta-Crowned', 'Zekrom', 'Zeraora', 'Zygarde-Base',
847
+ 'Calyrex-Ice', 'Calyrex-Shadow', 'Darmanitan-Galar', 'Dialga', 'Dracovish', 'Dragonite', 'Eternatus', 'Genesect', 'Giratina', 'Giratina-Origin', 'Groudon',
848
+ 'Ho-Oh', 'Hydreigon', 'Kartana', 'Kyogre', 'Kyurem', 'Kyurem-Black', 'Kyurem-White', 'Landorus-Base', 'Latias', 'Latios', 'Lugia', 'Lunala', 'Marshadow',
849
+ 'Mewtwo', 'Naganadel', 'Necrozma-Dawn-Wings', 'Necrozma-Dusk-Mane', 'Palkia', 'Pheromosa', 'Rayquaza', 'Reshiram', 'Shedinja', 'Slowking-Galar', 'Solgaleo',
850
+ 'Tornadus-Therian', 'Xerneas', 'Yveltal', 'Zacian', 'Zacian-Crowned', 'Zamazenta', 'Zamazenta-Crowned', 'Zekrom', 'Zeraora', 'Zygarde-Base',
1032
851
  'Arena Trap', 'Moody', 'Power Construct', 'Shadow Tag', 'Baton Pass',
1033
852
  ],
1034
853
  onModifySpeciesPriority: 2,
@@ -1048,168 +867,454 @@ exports.Formats = [
1048
867
  },
1049
868
  },
1050
869
  {
1051
- name: "[Gen 8] Cross Evolution",
1052
- desc: `Give a Pok&eacute;mon a Pok&eacute;mon name of the next evolution stage as a nickname to inherit stat changes, typing, abilities, and up to 2 moves from the next stage Pok&eacute;mon.`,
870
+ name: "[Gen 8] Godly Gift",
871
+ desc: `Each Pok&eacute;mon receives one base stat from a God (AG/Uber Pok&eacute;mon) depending on its position in the team. If there is no Uber Pok&eacute;mon, it uses the Pok&eacute;mon in the first slot.`,
1053
872
  threads: [
1054
- `&bullet; <a href="https://www.smogon.com/forums/threads/3657562/">Cross Evolution</a>`,
873
+ `&bullet; <a href="https://www.smogon.com/forums/threads/3660461/">Godly Gift</a>`,
1055
874
  ],
1056
875
  mod: 'gen8',
1057
876
  searchShow: false,
1058
- ruleset: ['Standard', 'Overflow Stat Mod', 'Dynamax Clause'],
1059
- banlist: ['Corsola-Galar', 'Sneasel', 'Type: Null', 'Arena Trap', 'Ice Scales', 'Moody', 'King\'s Rock', 'Baton Pass'],
1060
- restricted: ['Chansey', 'Lunala', 'Shedinja', 'Solgaleo', 'Gorilla Tactics', 'Huge Power', 'Pure Power', 'Shadow Tag'],
877
+ ruleset: ['Standard', 'Dynamax Clause'],
878
+ banlist: [
879
+ 'Blissey', 'Calyrex-Shadow', 'Chansey', 'Hawlucha', 'Marowak-Alola', 'Melmetal', 'Pikachu', 'Toxapex', 'Zacian', 'Zacian-Crowned',
880
+ 'Uber > 1', 'AG ++ Uber > 1', 'Arena Trap', 'Huge Power', 'Moody', 'Pure Power', 'Shadow Tag', 'Baton Pass',
881
+ ],
1061
882
  onValidateTeam(team) {
1062
- const names = new Set();
883
+ const gods = new Set();
1063
884
  for (const set of team) {
1064
- const name = set.name;
1065
- if (names.has(this.dex.toID(name))) {
1066
- return [
1067
- `Your Pok\u00e9mon must have different nicknames.`,
1068
- `(You have more than one Pok\u00e9mon named '${name}')`,
1069
- ];
885
+ let species = this.dex.species.get(set.species);
886
+ if (typeof species.battleOnly === 'string')
887
+ species = this.dex.species.get(species.battleOnly);
888
+ if (['ag', 'uber'].includes(this.toID(species.tier)) || this.toID(set.ability) === 'powerconstruct') {
889
+ gods.add(species.name);
1070
890
  }
1071
- names.add(this.dex.toID(name));
1072
891
  }
1073
- if (!names.size) {
1074
- return [
1075
- `${this.format.name} works using nicknames; your team has 0 nicknamed Pok\u00e9mon.`,
1076
- `(If this was intentional, add a nickname to one Pok\u00e9mon that isn't the name of a Pok\u00e9mon species.)`,
1077
- ];
892
+ if (gods.size > 1) {
893
+ return [`You have too many Gods.`, `(${Array.from(gods).join(', ')} are Gods.)`];
1078
894
  }
1079
895
  },
1080
- checkCanLearn(move, species, lsetData, set) {
1081
- // @ts-ignore
1082
- if (!set.sp?.exists || !set.crossSpecies?.exists) {
1083
- return this.checkCanLearn(move, species, lsetData, set);
896
+ onModifySpeciesPriority: 3,
897
+ onModifySpecies(species, target, source) {
898
+ if (source || !target?.side)
899
+ return;
900
+ const god = target.side.team.find(set => {
901
+ let godSpecies = this.dex.species.get(set.species);
902
+ const validator = this.dex.formats.getRuleTable(this.dex.formats.get(`gen${this.gen}ou`));
903
+ if (this.toID(set.ability) === 'powerconstruct') {
904
+ return true;
905
+ }
906
+ if (set.item) {
907
+ const item = this.dex.items.get(set.item);
908
+ if (item.megaEvolves === set.species)
909
+ godSpecies = this.dex.species.get(item.megaStone);
910
+ }
911
+ const isBanned = validator.isBannedSpecies(godSpecies);
912
+ return isBanned;
913
+ }) || target.side.team[0];
914
+ const stat = Dex.stats.ids()[target.side.team.indexOf(target.set)];
915
+ const newSpecies = this.dex.deepClone(species);
916
+ let godSpecies = this.dex.species.get(god.species);
917
+ if (godSpecies.forme === 'Crowned') {
918
+ godSpecies = this.dex.species.get(godSpecies.changesFrom || godSpecies.baseSpecies);
1084
919
  }
1085
- // @ts-ignore
1086
- const problem = this.checkCanLearn(move, set.sp);
1087
- if (!problem)
1088
- return null;
1089
- // @ts-ignore
1090
- if (!set.crossMovesLeft)
1091
- return problem;
1092
- // @ts-ignore
1093
- if (this.checkCanLearn(move, set.crossSpecies))
1094
- return problem;
1095
- // @ts-ignore
1096
- set.crossMovesLeft--;
1097
- return null;
920
+ newSpecies.bst -= newSpecies.baseStats[stat];
921
+ newSpecies.baseStats[stat] = godSpecies.baseStats[stat];
922
+ newSpecies.bst += newSpecies.baseStats[stat];
923
+ return newSpecies;
924
+ },
925
+ },
926
+ {
927
+ name: "[Gen 8] Inheritance",
928
+ desc: `Pok&eacute;mon may use the ability and moves of another, as long as they forfeit their own learnset.`,
929
+ threads: [
930
+ `&bullet; <a href="https://www.smogon.com/forums/threads/3656811/">Inheritance</a>`,
931
+ ],
932
+ mod: 'gen8',
933
+ searchShow: false,
934
+ ruleset: ['Standard', '2 Ability Clause', 'Dynamax Clause'],
935
+ banlist: [
936
+ 'Blacephalon', 'Blaziken', 'Butterfree', 'Calyrex-Ice', 'Calyrex-Shadow', 'Chansey', 'Combusken', 'Cresselia', 'Darmanitan-Galar', 'Dialga', 'Dracovish',
937
+ 'Eternatus', 'Giratina', 'Giratina-Origin', 'Groudon', 'Ho-Oh', 'Kartana', 'Kyogre', 'Kyurem-Black', 'Kyurem-White', 'Landorus-Base', 'Lugia', 'Lunala',
938
+ 'Magearna', 'Marshadow', 'Melmetal', 'Mewtwo', 'Natu', 'Necrozma-Dawn-Wings', 'Necrozma-Dusk-Mane', 'Palkia', 'Pheromosa', 'Rayquaza', 'Regieleki',
939
+ 'Regigigas', 'Reshiram', 'Sableye', 'Shedinja', 'Solgaleo', 'Spectrier', 'Tapu Koko', 'Toxtricity', 'Torkoal', 'Urshifu-Base', 'Xatu', 'Xerneas', 'Yveltal',
940
+ 'Zacian', 'Zacian-Crowned', 'Zamazenta', 'Zamazenta-Crowned', 'Zeraora', 'Zekrom', 'Arena Trap', 'Contrary', 'Drizzle', 'Huge Power', 'Imposter', 'Innards Out',
941
+ 'Libero', 'Moody', 'Power Construct', 'Pure Power', 'Quick Draw', 'Shadow Tag', 'Sheer Force', 'Simple', 'Unaware', 'Unburden', 'Water Bubble', 'King\'s Rock',
942
+ 'Quick Claw', 'Baton Pass', 'Bolt Beak', 'Fishious Rend', 'Shell Smash', 'Thousand Arrows',
943
+ ],
944
+ getEvoFamily(speciesid) {
945
+ let species = Dex.species.get(speciesid);
946
+ while (species.prevo) {
947
+ species = Dex.species.get(species.prevo);
948
+ }
949
+ return species.id;
1098
950
  },
1099
951
  validateSet(set, teamHas) {
1100
- const crossSpecies = this.dex.species.get(set.name);
1101
- const onChangeSet = this.dex.formats.get('Pokemon').onChangeSet;
1102
- let problems = onChangeSet?.call(this, set, this.format) || null;
1103
- if (Array.isArray(problems) && problems.length)
1104
- return problems;
1105
- const crossNonstandard = !this.ruleTable.has('standardnatdex') && crossSpecies.isNonstandard === 'Past';
1106
- const crossIsCap = !this.ruleTable.has('+pokemontag:cap') && crossSpecies.isNonstandard === 'CAP';
1107
- if (!crossSpecies.exists || crossNonstandard || crossIsCap)
1108
- return this.validateSet(set, teamHas);
1109
- const species = this.dex.species.get(set.species);
1110
- const check = this.checkSpecies(set, species, species, {});
1111
- if (check)
1112
- return [check];
1113
- const nonstandard = !this.ruleTable.has('standardnatdex') && species.isNonstandard === 'Past';
1114
- const isCap = !this.ruleTable.has('+pokemontag:cap') && species.isNonstandard === 'CAP';
1115
- if (!species.exists || nonstandard || isCap || species === crossSpecies)
1116
- return this.validateSet(set, teamHas);
1117
- if (!species.nfe)
1118
- return [`${species.name} cannot cross evolve because it doesn't evolve.`];
1119
- const crossIsUnreleased = (crossSpecies.tier === "Unreleased" && crossSpecies.isNonstandard === "Unobtainable");
1120
- if (crossSpecies.battleOnly || crossIsUnreleased || !crossSpecies.prevo) {
1121
- return [`${species.name} cannot cross evolve into ${crossSpecies.name} because it isn't an evolution.`];
952
+ const unreleased = (pokemon) => pokemon.tier === "Unreleased" && pokemon.isNonstandard === "Unobtainable";
953
+ if (!teamHas.abilityMap) {
954
+ teamHas.abilityMap = Object.create(null);
955
+ for (const pokemon of Dex.species.all()) {
956
+ if (pokemon.isNonstandard || unreleased(pokemon))
957
+ continue;
958
+ if (pokemon.requiredAbility || pokemon.requiredItem || pokemon.requiredMove)
959
+ continue;
960
+ if (this.ruleTable.isBannedSpecies(pokemon))
961
+ continue;
962
+ for (const key of Object.values(pokemon.abilities)) {
963
+ const abilityId = this.dex.toID(key);
964
+ if (abilityId in teamHas.abilityMap) {
965
+ teamHas.abilityMap[abilityId][pokemon.evos ? 'push' : 'unshift'](pokemon.id);
966
+ }
967
+ else {
968
+ teamHas.abilityMap[abilityId] = [pokemon.id];
969
+ }
970
+ }
971
+ }
1122
972
  }
1123
- if (this.ruleTable.isRestrictedSpecies(crossSpecies)) {
1124
- return [`${species.name} cannot cross evolve into ${crossSpecies.name} because it is banned.`];
973
+ const problem = this.validateForme(set);
974
+ if (problem.length)
975
+ return problem;
976
+ const species = this.dex.species.get(set.species);
977
+ if (!species.exists || species.num < 1)
978
+ return [`The Pok\u00e9mon "${set.species}" does not exist.`];
979
+ if (species.isNonstandard || unreleased(species)) {
980
+ return [`${species.name} is not obtainable in Generation ${this.dex.gen}.`];
1125
981
  }
1126
- const crossPrevoSpecies = this.dex.species.get(crossSpecies.prevo);
1127
- if (!crossPrevoSpecies.prevo !== !species.prevo) {
1128
- return [
1129
- `${species.name} cannot cross evolve into ${crossSpecies.name} because they are not consecutive evolution stages.`,
1130
- ];
982
+ const name = set.name;
983
+ if (this.ruleTable.isBannedSpecies(species)) {
984
+ return this.validateSet(set, teamHas);
1131
985
  }
1132
986
  const ability = this.dex.abilities.get(set.ability);
1133
- if (!this.ruleTable.isRestricted(`ability:${ability.id}`) || Object.values(species.abilities).includes(ability.name)) {
1134
- set.species = crossSpecies.name;
987
+ if (!ability.exists || ability.isNonstandard)
988
+ return [`${name} needs to have a valid ability.`];
989
+ const pokemonWithAbility = teamHas.abilityMap[ability.id];
990
+ if (!pokemonWithAbility)
991
+ return [`${ability.name} is not available on a legal Pok\u00e9mon.`];
992
+ this.format.debug = true;
993
+ if (!teamHas.abilitySources)
994
+ teamHas.abilitySources = Object.create(null);
995
+ const validSources = teamHas.abilitySources[this.dex.toID(set.species)] = []; // Evolution families
996
+ let canonicalSource = ''; // Specific for the basic implementation of Donor Clause (see onValidateTeam).
997
+ for (const donor of pokemonWithAbility) {
998
+ const donorSpecies = this.dex.species.get(donor);
999
+ let format = this.format;
1000
+ if (!format.getEvoFamily)
1001
+ format = this.dex.formats.get('gen8inheritance');
1002
+ const evoFamily = format.getEvoFamily(donorSpecies.id);
1003
+ if (validSources.includes(evoFamily))
1004
+ continue;
1005
+ set.species = donorSpecies.name;
1006
+ set.name = donorSpecies.baseSpecies;
1007
+ const problems = this.validateSet(set, teamHas) || [];
1008
+ if (!problems.length) {
1009
+ validSources.push(evoFamily);
1010
+ canonicalSource = donorSpecies.name;
1011
+ }
1012
+ // Specific for the basic implementation of Donor Clause (see onValidateTeam).
1013
+ if (validSources.length > 1)
1014
+ break;
1135
1015
  }
1136
- // @ts-ignore
1137
- set.sp = species;
1138
- // @ts-ignore
1139
- set.crossSpecies = crossSpecies;
1140
- // @ts-ignore
1141
- set.crossMovesLeft = 2;
1142
- problems = this.validateSet(set, teamHas);
1143
- set.name = crossSpecies.name;
1016
+ this.format.debug = false;
1017
+ set.name = name;
1144
1018
  set.species = species.name;
1145
- return problems;
1019
+ if (!validSources.length) {
1020
+ if (pokemonWithAbility.length > 1)
1021
+ return [`${name}'s set is illegal.`];
1022
+ return [`${name} has an illegal set with an ability from ${this.dex.species.get(pokemonWithAbility[0]).name}.`];
1023
+ }
1024
+ // Protocol: Include the data of the donor species in the `ability` data slot.
1025
+ // Afterwards, we are going to reset the name to what the user intended.
1026
+ set.ability = `${set.ability}0${canonicalSource}`;
1027
+ return null;
1146
1028
  },
1147
- onModifySpecies(species, target, source, effect) {
1148
- if (!target)
1149
- return; // chat
1150
- if (effect && ['imposter', 'transform'].includes(effect.id))
1151
- return;
1152
- if (target.set.name === target.set.species)
1153
- return;
1154
- const crossSpecies = this.dex.species.get(target.set.name);
1155
- if (!crossSpecies.exists)
1156
- return;
1157
- if (species.battleOnly || !species.nfe)
1029
+ onValidateTeam(team, f, teamHas) {
1030
+ if (this.ruleTable.has('2abilityclause')) {
1031
+ const abilityTable = new Map();
1032
+ const base = {
1033
+ airlock: 'cloudnine',
1034
+ battlearmor: 'shellarmor',
1035
+ clearbody: 'whitesmoke',
1036
+ dazzling: 'queenlymajesty',
1037
+ emergencyexit: 'wimpout',
1038
+ filter: 'solidrock',
1039
+ gooey: 'tanglinghair',
1040
+ insomnia: 'vitalspirit',
1041
+ ironbarbs: 'roughskin',
1042
+ libero: 'protean',
1043
+ minus: 'plus',
1044
+ moxie: 'chillingneigh',
1045
+ powerofalchemy: 'receiver',
1046
+ propellertail: 'stalwart',
1047
+ teravolt: 'moldbreaker',
1048
+ turboblaze: 'moldbreaker',
1049
+ };
1050
+ for (const set of team) {
1051
+ let ability = this.toID(set.ability.split('0')[0]);
1052
+ if (!ability)
1053
+ continue;
1054
+ if (ability in base)
1055
+ ability = base[ability];
1056
+ if ((abilityTable.get(ability) || 0) >= 2) {
1057
+ return [
1058
+ `You are limited to two of each ability by 2 Ability Clause.`,
1059
+ `(You have more than two ${this.dex.abilities.get(ability).name} variants)`,
1060
+ ];
1061
+ }
1062
+ abilityTable.set(ability, (abilityTable.get(ability) || 0) + 1);
1063
+ }
1064
+ }
1065
+ // Donor Clause
1066
+ const evoFamilyLists = [];
1067
+ for (const set of team) {
1068
+ const abilitySources = teamHas.abilitySources?.[this.dex.toID(set.species)];
1069
+ if (!abilitySources)
1070
+ continue;
1071
+ let format = this.format;
1072
+ if (!format.getEvoFamily)
1073
+ format = this.dex.formats.get('gen8inheritance');
1074
+ evoFamilyLists.push(abilitySources.map(format.getEvoFamily));
1075
+ }
1076
+ // Checking actual full incompatibility would require expensive algebra.
1077
+ // Instead, we only check the trivial case of multiple Pokémon only legal for exactly one family. FIXME?
1078
+ const requiredFamilies = Object.create(null);
1079
+ for (const evoFamilies of evoFamilyLists) {
1080
+ if (evoFamilies.length !== 1)
1081
+ continue;
1082
+ const [familyId] = evoFamilies;
1083
+ if (!(familyId in requiredFamilies))
1084
+ requiredFamilies[familyId] = 1;
1085
+ requiredFamilies[familyId]++;
1086
+ if (requiredFamilies[familyId] > 2) {
1087
+ return [
1088
+ `You are limited to up to two inheritances from each evolution family by the Donor Clause.`,
1089
+ `(You inherit more than twice from ${this.dex.species.get(familyId).name}).`,
1090
+ ];
1091
+ }
1092
+ }
1093
+ },
1094
+ onBegin() {
1095
+ for (const pokemon of this.getAllPokemon()) {
1096
+ if (pokemon.baseAbility.includes('0')) {
1097
+ const donor = pokemon.baseAbility.split('0')[1];
1098
+ pokemon.m.donor = this.toID(donor);
1099
+ pokemon.baseAbility = this.toID(pokemon.baseAbility.split('0')[0]);
1100
+ pokemon.ability = pokemon.baseAbility;
1101
+ }
1102
+ }
1103
+ },
1104
+ onSwitchIn(pokemon) {
1105
+ if (!pokemon.m.donor)
1158
1106
  return;
1159
- const crossIsUnreleased = (crossSpecies.tier === "Unreleased" && crossSpecies.isNonstandard === "Unobtainable");
1160
- if (crossSpecies.battleOnly || crossIsUnreleased || !crossSpecies.prevo)
1107
+ const donorTemplate = this.dex.species.get(pokemon.m.donor);
1108
+ if (!donorTemplate.exists)
1161
1109
  return;
1162
- const crossPrevoSpecies = this.dex.species.get(crossSpecies.prevo);
1163
- if (!crossPrevoSpecies.prevo !== !species.prevo)
1110
+ // Place volatiles on the Pokémon to show the donor details.
1111
+ this.add('-start', pokemon, donorTemplate.name, '[silent]');
1112
+ },
1113
+ },
1114
+ {
1115
+ name: "[Gen 8] Multibility",
1116
+ desc: `Run a second ability at the cost of giving up a Pok&eacute;mon's item slot.`,
1117
+ threads: [
1118
+ `&bullet; <a href="https://www.smogon.com/forums/threads/3688892/">Multibility</a>`,
1119
+ ],
1120
+ mod: 'gen8',
1121
+ searchShow: false,
1122
+ ruleset: ['Standard', 'Dynamax Clause', '2 Ability Clause', 'Sleep Moves Clause', '!Sleep Clause Mod'],
1123
+ banlist: [
1124
+ 'Calyrex-Ice', 'Calyrex-Shadow', 'Cinderace', 'Darmanitan-Galar', 'Dialga', 'Dracovish', 'Dragonite', 'Eternatus',
1125
+ 'Genesect', 'Giratina', 'Giratina-Origin', 'Groudon', 'Ho-Oh', 'Kartana', 'Kyogre', 'Kyurem-Black', 'Kyurem-White',
1126
+ 'Lugia', 'Lunala', 'Magearna', 'Marshadow', 'Melmetal', 'Mewtwo', 'Naganadel', 'Necrozma-Dawn-Wings', 'Necrozma-Dusk-Mane',
1127
+ 'Palkia', 'Pheromosa', 'Rayquaza', 'Reshiram', 'Shedinja', 'Solgaleo', 'Spectrier', 'Urshifu-Base', 'Xerneas',
1128
+ 'Yveltal', 'Zacian', 'Zacian-Crowned', 'Zamazenta', 'Zamazenta-Crowned', 'Zekrom', 'Zygarde-Base', 'Arena Trap',
1129
+ 'Chlorophyll', 'Magnet Pull', 'Moody', 'Power Construct', 'Sand Rush', 'Shadow Tag', 'Slush Rush', 'Swift Swim',
1130
+ 'Stench', 'Trace', 'King\'s Rock', 'Baton Pass',
1131
+ ],
1132
+ restricted: [
1133
+ 'Comatose', 'Contrary', 'Fluffy', 'Fur Coat', 'Huge Power', 'Ice Scales', 'Illusion', 'Imposter', 'Innards Out',
1134
+ 'Intrepid Sword', 'Libero', 'Neutralizing Gas', 'Parental Bond', 'Protean', 'Pure Power', 'Simple', 'Speed Boost',
1135
+ 'Stakeout', 'Tinted Lens', 'Unaware', 'Water Bubble', 'Wonder Guard',
1136
+ 'Emergency Exit + Regenerator', 'Wimp Out + Regenerator',
1137
+ ],
1138
+ validateSet(set, teamHas) {
1139
+ const ability = this.dex.abilities.get(set.ability);
1140
+ const item = this.dex.abilities.get(set.item);
1141
+ if (!item.exists)
1142
+ return this.validateSet(set, teamHas);
1143
+ const problems = [];
1144
+ if (item.isNonstandard && !this.ruleTable.has(`+ability:${item.id}`)) {
1145
+ problems.push(`${item.name} is banned.`);
1146
+ }
1147
+ if (ability.id === item.id) {
1148
+ problems.push(`${set.species} has ${ability.name} as an ability and as an item.`);
1149
+ }
1150
+ if (this.ruleTable.isRestricted(`ability:${item.id}`) || this.ruleTable.isBanned(`ability:${item.id}`)) {
1151
+ problems.push(`${set.species}'s second ability (${item.name}) can only be used as an ability.`);
1152
+ }
1153
+ if ((ability.id === 'regenerator' && ['emergencyexit', 'wimpout'].includes(item.id)) ||
1154
+ (item.id === 'regenerator' && ['emergencyexit', 'wimpout'].includes(ability.id))) {
1155
+ problems.push(`${ability.name} and ${item.name} are banned together.`);
1156
+ }
1157
+ const itemStr = set.item;
1158
+ set.item = '';
1159
+ const problem = this.validateSet(set, teamHas);
1160
+ if (problem?.length)
1161
+ problems.push(...problem);
1162
+ set.item = itemStr;
1163
+ return problems;
1164
+ },
1165
+ onValidateTeam(team) {
1166
+ if (!this.ruleTable.has('2abilityclause'))
1164
1167
  return;
1165
- const mixedSpecies = this.dex.deepClone(species);
1166
- mixedSpecies.baseSpecies = mixedSpecies.name = `${species.name}-${crossSpecies.name}`;
1167
- mixedSpecies.weightkg =
1168
- Math.max(0.1, +(species.weightkg + crossSpecies.weightkg - crossPrevoSpecies.weightkg)).toFixed(1);
1169
- mixedSpecies.nfe = false;
1170
- mixedSpecies.evos = [];
1171
- mixedSpecies.eggGroups = crossSpecies.eggGroups;
1172
- mixedSpecies.abilities = crossSpecies.abilities;
1173
- mixedSpecies.bst = 0;
1174
- let i;
1175
- for (i in species.baseStats) {
1176
- const statChange = crossSpecies.baseStats[i] - crossPrevoSpecies.baseStats[i];
1177
- mixedSpecies.baseStats[i] = this.clampIntRange(species.baseStats[i] + statChange, 1, 255);
1178
- mixedSpecies.bst += mixedSpecies.baseStats[i];
1168
+ const abilityTable = new Map();
1169
+ const base = {
1170
+ airlock: 'cloudnine',
1171
+ battlearmor: 'shellarmor',
1172
+ clearbody: 'whitesmoke',
1173
+ dazzling: 'queenlymajesty',
1174
+ emergencyexit: 'wimpout',
1175
+ filter: 'solidrock',
1176
+ gooey: 'tanglinghair',
1177
+ insomnia: 'vitalspirit',
1178
+ ironbarbs: 'roughskin',
1179
+ libero: 'protean',
1180
+ minus: 'plus',
1181
+ moxie: 'chillingneigh',
1182
+ powerofalchemy: 'receiver',
1183
+ propellertail: 'stalwart',
1184
+ teravolt: 'moldbreaker',
1185
+ turboblaze: 'moldbreaker',
1186
+ };
1187
+ const abilities = [];
1188
+ for (const set of team) {
1189
+ abilities.push([set.ability, set.item].map((abil) => {
1190
+ const id = this.toID(abil);
1191
+ return base[id] || id;
1192
+ }));
1179
1193
  }
1180
- if (crossSpecies.types[0] !== crossPrevoSpecies.types[0])
1181
- mixedSpecies.types[0] = crossSpecies.types[0];
1182
- if (crossSpecies.types[1] !== crossPrevoSpecies.types[1]) {
1183
- mixedSpecies.types[1] = crossSpecies.types[1] || crossSpecies.types[0];
1194
+ for (const [abilityid, itemid] of abilities) {
1195
+ const ability = this.dex.abilities.get(abilityid);
1196
+ const item = this.dex.abilities.get(itemid);
1197
+ if (ability.exists)
1198
+ abilityTable.set(ability.id, (abilityTable.get(ability.id) || 0) + 1);
1199
+ if (item.exists)
1200
+ abilityTable.set(item.id, (abilityTable.get(item.id) || 0) + 1);
1201
+ }
1202
+ for (const [abilityid, size] of abilityTable) {
1203
+ if (size > 2) {
1204
+ return [
1205
+ `You are limited to two of each ability by 2 Ability Clause.`,
1206
+ `(You have more than two ${this.dex.abilities.get(abilityid).name} variants)`,
1207
+ ];
1208
+ }
1184
1209
  }
1185
- if (mixedSpecies.types[0] === mixedSpecies.types[1])
1186
- mixedSpecies.types = [mixedSpecies.types[0]];
1187
- return mixedSpecies;
1188
1210
  },
1189
- onBegin() {
1190
- for (const pokemon of this.getAllPokemon()) {
1191
- pokemon.baseSpecies = pokemon.species;
1211
+ onSwitchOut(pokemon) {
1212
+ const item = this.dex.abilities.get(pokemon.item);
1213
+ if (item.exists) {
1214
+ this.singleEvent('End', item, pokemon.itemState, pokemon);
1215
+ }
1216
+ },
1217
+ onFaint(pokemon) {
1218
+ const item = this.dex.abilities.get(pokemon.item);
1219
+ if (item.exists) {
1220
+ this.singleEvent('End', item, pokemon.itemState, pokemon);
1192
1221
  }
1193
1222
  },
1194
- },
1195
- {
1196
- name: "[Gen 8] Inverse",
1197
- desc: `The type chart is inverted. Normal is super effective against Ghost, and vice versa, etc.`,
1198
- threads: [
1199
- `&bullet; <a href="https://www.smogon.com/forums/threads/3666858/">Inverse</a>`,
1200
- ],
1201
- mod: 'gen8',
1202
- searchShow: false,
1203
- ruleset: ['Standard', 'Dynamax Clause', 'Inverse Mod'],
1204
- banlist: [
1205
- 'Calyrex-Ice', 'Calyrex-Shadow', 'Cinderace', 'Darmanitan-Galar', 'Dialga', 'Diggersby', 'Dracovish',
1206
- 'Dracozolt', 'Eternatus', 'Genesect', 'Giratina', 'Giratina-Origin', 'Groudon', 'Ho-Oh', 'Kartana',
1207
- 'Kyogre', 'Kyurem-Black', 'Kyurem-White', 'Landorus-Base', 'Lugia', 'Lunala', 'Marshadow', 'Mewtwo',
1208
- 'Naganadel', 'Necrozma-Dawn-Wings', 'Necrozma-Dusk-Mane', 'Palkia', 'Pheromosa', 'Porygon-Z', 'Rayquaza',
1209
- 'Regidrago', 'Regieleki', 'Reshiram', 'Rillaboom', 'Solgaleo', 'Spectrier', 'Urshifu-Base', 'Xerneas',
1210
- 'Yveltal', 'Zacian', 'Zacian-Crowned', 'Zamazenta-Base', 'Zekrom', 'Arena Trap', 'Moody', 'Power Construct',
1211
- 'Shadow Tag', 'King\'s Rock', 'Baton Pass',
1212
- ],
1223
+ field: {
1224
+ suppressingWeather() {
1225
+ for (const pokemon of this.battle.getAllActive()) {
1226
+ const item = this.battle.dex.abilities.get(pokemon.item);
1227
+ if (pokemon && !pokemon.ignoringAbility() &&
1228
+ (pokemon.getAbility().suppressWeather || (item.exists && item.suppressWeather))) {
1229
+ return true;
1230
+ }
1231
+ }
1232
+ return false;
1233
+ },
1234
+ },
1235
+ pokemon: {
1236
+ getItem() {
1237
+ const ability = this.battle.dex.abilities.get(this.item);
1238
+ if (!ability.exists)
1239
+ return Object.getPrototypeOf(this).getItem.call(this);
1240
+ return { ...ability, ignoreKlutz: true, onTakeItem: false };
1241
+ },
1242
+ hasItem(item) {
1243
+ const ownItem = this.item;
1244
+ if (this.battle.dex.abilities.get(ownItem).exists)
1245
+ return false;
1246
+ if (this.ignoringItem())
1247
+ return false;
1248
+ if (!Array.isArray(item))
1249
+ return ownItem === this.battle.toID(item);
1250
+ return item.map(this.battle.toID).includes(ownItem);
1251
+ },
1252
+ hasAbility(ability) {
1253
+ if (this.ignoringAbility())
1254
+ return false;
1255
+ if (Array.isArray(ability))
1256
+ return ability.some(abil => this.hasAbility(abil));
1257
+ const abilityid = this.battle.toID(ability);
1258
+ const item = this.battle.dex.abilities.get(this.item);
1259
+ return this.ability === abilityid || (item.exists && item.id === abilityid);
1260
+ },
1261
+ ignoringAbility() {
1262
+ // Check if any active pokemon have the ability Neutralizing Gas
1263
+ let neutralizinggas = false;
1264
+ for (const pokemon of this.battle.getAllActive()) {
1265
+ // can't use hasAbility because it would lead to infinite recursion
1266
+ if ((pokemon.ability === 'neutralizinggas' || pokemon.item === 'neutralizinggas') &&
1267
+ !pokemon.volatiles['gastroacid'] && !pokemon.abilityState.ending) {
1268
+ neutralizinggas = true;
1269
+ break;
1270
+ }
1271
+ }
1272
+ return !!((this.battle.gen >= 5 && !this.isActive) ||
1273
+ ((this.volatiles['gastroacid'] || (neutralizinggas && this.ability !== 'neutralizinggas' &&
1274
+ this.item !== 'neutralizinggas')) && !this.getAbility().isPermanent));
1275
+ },
1276
+ ignoringItem() {
1277
+ let nGas = false;
1278
+ for (const pokemon of this.battle.getAllActive()) {
1279
+ // can't use hasAbility because it would lead to infinite recursion
1280
+ if (((pokemon.ability === 'neutralizinggas' && !pokemon.abilityState.ending) ||
1281
+ (pokemon.item === 'neutralizinggas' && !pokemon.itemState.ending)) &&
1282
+ !pokemon.volatiles['gastroacid'] && !pokemon.abilityState.ending) {
1283
+ nGas = true;
1284
+ break;
1285
+ }
1286
+ }
1287
+ const item = this.battle.dex.abilities.get(this.item);
1288
+ return !!((this.battle.gen >= 5 && !this.isActive) ||
1289
+ (this.hasAbility('klutz') && !this.getItem().ignoreKlutz) ||
1290
+ this.volatiles['embargo'] || this.battle.field.pseudoWeather['magicroom'] ||
1291
+ (item.exists && item.id !== 'neutralizinggas' && (nGas || this.volatiles['gastroacid'])));
1292
+ },
1293
+ takeItem(source) {
1294
+ if (!this.isActive)
1295
+ return false;
1296
+ if (!this.item)
1297
+ return false;
1298
+ if (this.battle.dex.abilities.get(this.item).exists)
1299
+ return false;
1300
+ if (!source)
1301
+ source = this;
1302
+ if (this.battle.gen === 4) {
1303
+ if (this.battle.toID(this.ability) === 'multitype')
1304
+ return false;
1305
+ if (source && this.battle.toID(source.ability) === 'multitype')
1306
+ return false;
1307
+ }
1308
+ const item = this.getItem();
1309
+ if (this.battle.runEvent('TakeItem', this, source, null, item)) {
1310
+ this.item = '';
1311
+ this.itemState = { id: '', target: this };
1312
+ this.pendingStaleness = undefined;
1313
+ return item;
1314
+ }
1315
+ return false;
1316
+ },
1317
+ },
1213
1318
  },
1214
1319
  {
1215
1320
  name: "[Gen 8] Nature Swap",
@@ -1266,16 +1371,6 @@ exports.Formats = [
1266
1371
  },
1267
1372
  },
1268
1373
  },
1269
- {
1270
- name: "[Gen 8] Pure Hackmons",
1271
- desc: `Anything that can be hacked in-game and is usable in local battles is allowed.`,
1272
- threads: [
1273
- `&bullet; <a href="https://www.smogon.com/forums/threads/3656851/">Pure Hackmons</a>`,
1274
- ],
1275
- mod: 'gen8',
1276
- searchShow: false,
1277
- ruleset: ['-Nonexistent', 'Team Preview', 'HP Percentage Mod', 'Cancel Mod', 'Endless Battle Clause'],
1278
- },
1279
1374
  {
1280
1375
  name: "[Gen 8] Shared Power",
1281
1376
  desc: `Once a Pok&eacute;mon switches in, its ability is shared with the rest of the team.`,
@@ -1340,29 +1435,6 @@ exports.Formats = [
1340
1435
  }
1341
1436
  },
1342
1437
  },
1343
- {
1344
- name: "[Gen 8] Sketchmons",
1345
- desc: `Pok&eacute;mon can learn one of any move they don't normally learn, barring the few that are banned.`,
1346
- threads: [
1347
- `&bullet; <a href="https://www.smogon.com/forums/threads/3680298/">Sketchmons</a>`,
1348
- ],
1349
- mod: 'gen8',
1350
- searchShow: false,
1351
- ruleset: ['Standard', 'Dynamax Clause', 'Sketchmons Move Legality'],
1352
- banlist: [
1353
- 'Calyrex-Ice', 'Calyrex-Shadow', 'Cinderace', 'Darmanitan-Galar', 'Dialga', 'Dracovish', 'Dragapult', 'Eternatus', 'Genesect',
1354
- 'Giratina', 'Giratina-Origin', 'Groudon', 'Ho-Oh', 'Kartana', 'Kyogre', 'Kyurem-Black', 'Kyurem-White', 'Landorus-Base', 'Lugia',
1355
- 'Lunala', 'Marshadow', 'Mewtwo', 'Naganadel', 'Necrozma-Dawn-Wings', 'Necrozma-Dusk-Mane', 'Palkia', 'Pheromosa', 'Porygon-Z',
1356
- 'Rayquaza', 'Regieleki', 'Reshiram', 'Rillaboom', 'Shedinja', 'Solgaleo', 'Spectrier', 'Swoobat', 'Urshifu-Base', 'Xerneas',
1357
- 'Yveltal', 'Zacian', 'Zacian-Crowned', 'Zamazenta', 'Zamazenta-Crowned', 'Zekrom', 'Zeraora', 'Zygarde-Base', 'Arena Trap',
1358
- 'Moody', 'Power Construct', 'Shadow Tag', 'King\'s Rock', 'Baton Pass',
1359
- ],
1360
- restricted: [
1361
- 'Acupressure', 'Astral Barrage', 'Belly Drum', 'Bolt Beak', 'Clangorous Soul', 'Double Iron Bash', 'Electrify', 'Extreme Speed',
1362
- 'Fishious Rend', 'Geomancy', 'Glacial Lance', 'Lovely Kiss', 'No Retreat', 'Oblivion Wing', 'Octolock', 'Quiver Dance', 'Secret Sword',
1363
- 'Shell Smash', 'Shift Gear', 'Sleep Powder', 'Spore', 'Thousand Arrows', 'Transform', 'V-create', 'Wicked Blow',
1364
- ],
1365
- },
1366
1438
  {
1367
1439
  name: "[Gen 8] The Loser's Game",
1368
1440
  desc: `The first player to lose all of their Pok&eacute;mon wins.`,
@@ -1485,54 +1557,6 @@ exports.Formats = [
1485
1557
  },
1486
1558
  },
1487
1559
  },
1488
- {
1489
- name: "[Gen 8] Tier Shift",
1490
- desc: `Pok&eacute;mon below OU get their stats, excluding HP, boosted. UU/RUBL get +10, RU/NUBL get +20, NU/PUBL get +30, and PU or lower get +40.`,
1491
- threads: [
1492
- `&bullet; <a href="https://www.smogon.com/forums/threads/3662165/">Tier Shift</a>`,
1493
- ],
1494
- mod: 'gen8',
1495
- searchShow: false,
1496
- ruleset: ['[Gen 8] OU', 'Overflow Stat Mod'],
1497
- banlist: ['Damp Rock', 'Eviolite', 'Heat Rock'],
1498
- unbanlist: ['Zamazenta-Crowned'],
1499
- onModifySpecies(species, target, source, effect) {
1500
- if (!species.baseStats)
1501
- return;
1502
- const boosts = {
1503
- uu: 10,
1504
- rubl: 10,
1505
- ru: 20,
1506
- nubl: 20,
1507
- nu: 30,
1508
- publ: 30,
1509
- pu: 40,
1510
- nfe: 40,
1511
- lc: 40,
1512
- };
1513
- let tier = this.toID(species.tier);
1514
- if (!(tier in boosts))
1515
- return;
1516
- // Non-Pokemon bans in lower tiers
1517
- if (target) {
1518
- if (target.set.item === 'lightclay')
1519
- return;
1520
- if (['drizzle', 'drought', 'snowwarning'].includes(target.set.ability) && boosts[tier] > 20)
1521
- tier = 'nubl';
1522
- }
1523
- const pokemon = this.dex.deepClone(species);
1524
- pokemon.bst = pokemon.baseStats['hp'];
1525
- const boost = boosts[tier];
1526
- let statName;
1527
- for (statName in pokemon.baseStats) {
1528
- if (statName === 'hp')
1529
- continue;
1530
- pokemon.baseStats[statName] = this.clampIntRange(pokemon.baseStats[statName] + boost, 1, 255);
1531
- pokemon.bst += pokemon.baseStats[statName];
1532
- }
1533
- return pokemon;
1534
- },
1535
- },
1536
1560
  {
1537
1561
  name: "[Gen 8] Trademarked",
1538
1562
  desc: `Sacrifice your Pok&eacute;mon's ability for a status move that activates on switch-in.`,
@@ -1550,9 +1574,10 @@ exports.Formats = [
1550
1574
  'Arena Trap', 'Moody', 'Power Construct', 'Shadow Tag', 'Baton Pass',
1551
1575
  ],
1552
1576
  restricted: [
1553
- 'Baneful Bunker', 'Block', 'Copycat', 'Corrosive Gas', 'Detect', 'Destiny Bond', 'Disable', 'Encore', 'Fairy Lock', 'Ingrain', 'Instruct',
1554
- 'King\'s Shield', 'Mat Block', 'Mean Look', 'move:Metronome', 'Obstruct', 'Octolock', 'Nature Power', 'Parting Shot', 'Psycho Shift',
1555
- 'Protect', 'Roar', 'Skill Swap', 'Sleep Talk', 'Spiky Shield', 'Substitute', 'Teleport', 'Whirlwind', 'Wish', 'Yawn',
1577
+ 'Baneful Bunker', 'Block', 'Copycat', 'Corrosive Gas', 'Detect', 'Destiny Bond', 'Disable', 'Encore', 'Fairy Lock', 'Hypnosis', 'Ingrain',
1578
+ 'Instruct', 'Lovely Kiss', 'King\'s Shield', 'Mat Block', 'Mean Look', 'move:Metronome', 'Obstruct', 'Octolock', 'Nature Power', 'Parting Shot',
1579
+ 'Psycho Shift', 'Protect', 'Roar', 'Sing', 'Skill Swap', 'Sleep Powder', 'Sleep Talk', 'Spiky Shield', 'Spore', 'Substitute', 'Teleport',
1580
+ 'Whirlwind', 'Wish', 'Yawn',
1556
1581
  ],
1557
1582
  onValidateTeam(team, format, teamHas) {
1558
1583
  const problems = [];
@@ -1566,18 +1591,33 @@ exports.Formats = [
1566
1591
  validateSet(set, teamHas) {
1567
1592
  const dex = this.dex;
1568
1593
  const ability = dex.moves.get(set.ability);
1569
- // Prevent stack overflow
1570
- const overflowAbilityNames = ['Assist', 'Entrainment', 'Skill Swap'];
1571
- if (overflowAbilityNames.includes(ability.name) || ability.category !== 'Status' || ability.status === 'slp' ||
1572
- this.ruleTable.isRestricted(`move:${ability.id}`) || set.moves.map(this.toID).includes(ability.id)) {
1594
+ if (!ability.exists) { // Not even a real move
1573
1595
  return this.validateSet(set, teamHas);
1574
1596
  }
1597
+ // Absolute trademark bans
1598
+ if (ability.category !== 'Status') {
1599
+ return [`${ability.name} is not a status move, and cannot be used as a trademark.`];
1600
+ }
1575
1601
  if (ability.forceSwitch || ability.selfSwitch) {
1576
1602
  return [
1577
1603
  `Force-switching and self-switching moves are banned from being used as trademarks.`,
1578
1604
  `(${ability.name} is a ${ability.forceSwitch ? 'force' : 'self'}-switching move.)`,
1579
1605
  ];
1580
1606
  }
1607
+ const irrevokablyRestricted = [
1608
+ 'Assist', 'Copycat', 'Metronome', 'Mirror Move', 'Sleep Talk',
1609
+ 'Skill Swap', // Self-propagates indefinitely
1610
+ ];
1611
+ if (irrevokablyRestricted.includes(ability.name)) {
1612
+ return [`${ability.name} cannot safely function as a trademark.`];
1613
+ }
1614
+ // Contingent trademark bans
1615
+ if (this.ruleTable.isRestricted(`move:${ability.id}`)) {
1616
+ return [`${ability.name} is restricted from being used as a trademark.`];
1617
+ }
1618
+ if (set.moves.map(this.toID).includes(ability.id)) {
1619
+ return [`${set.name} may not use ${ability.name} as both a trademark and one of its moves simultaneously.`];
1620
+ }
1581
1621
  const customRules = this.format.customRules || [];
1582
1622
  if (!customRules.includes('!obtainableabilities'))
1583
1623
  customRules.push('!obtainableabilities');
@@ -1617,72 +1657,6 @@ exports.Formats = [
1617
1657
  },
1618
1658
  },
1619
1659
  },
1620
- {
1621
- name: "[Gen 8] STABmons Mix and Mega",
1622
- desc: `Pok&eacute;mon can use any move of their typing, in addition to the moves they can normally learn. Mega evolve any Pok&eacute;mon with any mega stone and no limit. Boosts based on mega evolution from gen 7.`,
1623
- threads: [
1624
- `&bullet; <a href="https://www.smogon.com/forums/posts/8299984/">STABmons Mix and Mega</a>`,
1625
- ],
1626
- mod: 'mixandmega',
1627
- searchShow: false,
1628
- ruleset: ['Standard', 'Dynamax Clause', 'Overflow Stat Mod', 'STABmons Move Legality'],
1629
- banlist: [
1630
- 'Calyrex-Shadow', 'Kyogre', 'Zacian', 'Zacian-Crowned', 'Moody', 'Shadow Tag', 'Beedrillite', 'Blazikenite', 'Gengarite',
1631
- 'Kangaskhanite', 'Mawilite', 'Medichamite', 'Pidgeotite', 'Baton Pass', 'Electrify', 'King\'s Rock',
1632
- ],
1633
- restricted: [
1634
- 'Calyrex-Ice', 'Dialga', 'Dragapult', 'Dragonite', 'Eternatus', 'Genesect', 'Gengar', 'Giratina', 'Giratina-Origin',
1635
- 'Groudon', 'Ho-Oh', 'Kartana', 'Keldeo', 'Kyurem-Black', 'Kyurem-White', 'Landorus-Therian', 'Lugia', 'Lunala',
1636
- 'Marshadow', 'Melmetal', 'Mewtwo', 'Naganadel', 'Necrozma-Dawn-Wings', 'Necrozma-Dusk-Mane', 'Palkia', 'Rayquaza',
1637
- 'Regigigas', 'Reshiram', 'Spectrier', 'Tapu Koko', 'Urshifu', 'Urshifu-Rapid-Strike', 'Xerneas', 'Yveltal', 'Zekrom',
1638
- 'Zygarde-Base', 'Zygarde-Complete',
1639
- 'Acupressure', 'Astral Barrage', 'Belly Drum', 'Bolt Beak', 'Boomburst', 'Clangorous Soul', 'Double Iron Bash',
1640
- 'Extreme Speed', 'Fishious Rend', 'Geomancy', 'Glacial Lance', 'Lovely Kiss', 'Precipice Blades', 'Shell Smash',
1641
- 'Shift Gear', 'Sleep Powder', 'Spore', 'Thousand Arrows', 'Transform', 'V-create', 'Wicked Blow',
1642
- ],
1643
- onValidateTeam(team) {
1644
- const itemTable = new Set();
1645
- for (const set of team) {
1646
- const item = this.dex.items.get(set.item);
1647
- if (!item?.megaStone)
1648
- continue;
1649
- const species = this.dex.species.get(set.species);
1650
- if (species.isNonstandard)
1651
- return [`${species.baseSpecies} does not exist in gen 8.`];
1652
- if (this.ruleTable.isRestrictedSpecies(species) || this.toID(set.ability) === 'powerconstruct') {
1653
- return [`${species.name} is not allowed to hold ${item.name}.`];
1654
- }
1655
- if (itemTable.has(item.id)) {
1656
- return [`You are limited to one of each mega stone.`, `(You have more than one ${item.name})`];
1657
- }
1658
- itemTable.add(item.id);
1659
- }
1660
- },
1661
- onBegin() {
1662
- for (const pokemon of this.getAllPokemon()) {
1663
- pokemon.m.originalSpecies = pokemon.baseSpecies.name;
1664
- }
1665
- },
1666
- onSwitchIn(pokemon) {
1667
- // @ts-ignore
1668
- const oMegaSpecies = this.dex.species.get(pokemon.species.originalMega);
1669
- if (oMegaSpecies.exists && pokemon.m.originalSpecies !== oMegaSpecies.baseSpecies) {
1670
- // Place volatiles on the Pokémon to show its mega-evolved condition and details
1671
- this.add('-start', pokemon, oMegaSpecies.requiredItem || oMegaSpecies.requiredMove, '[silent]');
1672
- const oSpecies = this.dex.species.get(pokemon.m.originalSpecies);
1673
- if (oSpecies.types.length !== pokemon.species.types.length || oSpecies.types[1] !== pokemon.species.types[1]) {
1674
- this.add('-start', pokemon, 'typechange', pokemon.species.types.join('/'), '[silent]');
1675
- }
1676
- }
1677
- },
1678
- onSwitchOut(pokemon) {
1679
- // @ts-ignore
1680
- const oMegaSpecies = this.dex.species.get(pokemon.species.originalMega);
1681
- if (oMegaSpecies.exists && pokemon.m.originalSpecies !== oMegaSpecies.baseSpecies) {
1682
- this.add('-end', pokemon, oMegaSpecies.requiredItem || oMegaSpecies.requiredMove, '[silent]');
1683
- }
1684
- },
1685
- },
1686
1660
  // Randomized Metas
1687
1661
  ///////////////////////////////////////////////////////////////////
1688
1662
  {
@@ -1699,6 +1673,7 @@ exports.Formats = [
1699
1673
  name: "[Gen 8] Random Battle (No Dmax)",
1700
1674
  mod: 'gen8',
1701
1675
  team: 'random',
1676
+ searchShow: false,
1702
1677
  ruleset: ['[Gen 8] Random Battle', 'Dynamax Clause'],
1703
1678
  },
1704
1679
  {
@@ -1841,6 +1816,13 @@ exports.Formats = [
1841
1816
  team: 'randomFactory',
1842
1817
  ruleset: ['Obtainable', 'Sleep Clause Mod', 'Team Preview', 'HP Percentage Mod', 'Cancel Mod', 'Mega Rayquaza Clause'],
1843
1818
  },
1819
+ {
1820
+ name: "[Gen 7] Monotype Battle Factory",
1821
+ desc: `Randomized teams of Pok&eacute;mon with competitively-viable sets that all share a type.`,
1822
+ mod: 'gen7',
1823
+ team: 'randomFactory',
1824
+ ruleset: ['[Gen 7] Battle Factory', 'Same Type Clause'],
1825
+ },
1844
1826
  {
1845
1827
  name: "[Gen 7] BSS Factory",
1846
1828
  desc: `Randomized 3v3 Singles featuring Pok&eacute;mon and movesets popular in Battle Spot Singles.`,
@@ -1946,38 +1928,37 @@ exports.Formats = [
1946
1928
  column: 3,
1947
1929
  },
1948
1930
  {
1949
- name: "[Gen 4] Ubers",
1931
+ name: "[Gen 6] Ubers",
1950
1932
  threads: [
1951
- `&bullet; <a href="https://www.smogon.com/forums/posts/8286279/">DPP Ubers</a>`,
1933
+ `&bullet; <a href="https://www.smogon.com/forums/posts/8286277/">ORAS Ubers</a>`,
1952
1934
  ],
1953
- mod: 'gen4',
1935
+ mod: 'gen6',
1954
1936
  // searchShow: false,
1955
- ruleset: ['Standard'],
1956
- banlist: ['AG'],
1937
+ ruleset: ['Standard', 'Swagger Clause', 'Mega Rayquaza Clause'],
1957
1938
  },
1958
1939
  {
1959
- name: "[Gen 3] 1v1",
1960
- desc: `Bring three Pok&eacute;mon to Team Preview and choose one to battle.`,
1940
+ name: "[Gen 4] UU",
1961
1941
  threads: [
1962
- `&bullet; <a href="https://www.smogon.com/forums/posts/8031456/">ADV 1v1</a>`,
1942
+ `&bullet; <a href="https://www.smogon.com/forums/threads/3532624/">DPP UU Metagame Discussion</a>`,
1943
+ `&bullet; <a href="https://www.smogon.com/forums/threads/3503638/">DPP UU Viability Rankings</a>`,
1963
1944
  ],
1964
- mod: 'gen3',
1945
+ mod: 'gen4',
1965
1946
  // searchShow: false,
1966
- ruleset: [
1967
- 'Picked Team Size = 1', 'Max Team Size = 3',
1968
- '[Gen 3] OU', 'Accuracy Moves Clause', 'Sleep Moves Clause', 'Team Preview',
1969
- ],
1970
- banlist: ['Clefable', 'Slaking', 'Snorlax', 'Suicune', 'Destiny Bond', 'Explosion', 'Ingrain', 'Perish Song', 'Self-Destruct', 'Bright Powder', 'Focus Band', 'King\'s Rock', 'Lax Incense', 'Quick Claw'],
1947
+ ruleset: ['[Gen 4] OU'],
1948
+ banlist: ['OU', 'UUBL'],
1949
+ unbanlist: ['Arena Trap'],
1971
1950
  },
1972
1951
  {
1973
- name: "[Gen 1] Tradebacks OU",
1974
- desc: `RBY OU with movepool additions from the Time Capsule.`,
1952
+ name: "[Gen 3] Doubles OU",
1975
1953
  threads: [
1976
- `&bullet; <a href="https://www.smogon.com/articles/rby-tradebacks-ou">RBY Tradebacks OU</a>`,
1954
+ `&bullet; <a href="https://www.smogon.com/forums/threads/3666831/">ADV Doubles OU</a>`,
1977
1955
  ],
1978
- mod: 'gen1',
1956
+ mod: 'gen3',
1979
1957
  // searchShow: false,
1980
- ruleset: ['[Gen 1] OU', 'Allow Tradeback'],
1958
+ gameType: 'doubles',
1959
+ ruleset: ['Standard', '!Sleep Clause Mod', '!Switch Priority Clause Mod'],
1960
+ banlist: ['Uber'],
1961
+ unbanlist: ['Deoxys-Speed', 'Wobbuffet', 'Wynaut'],
1981
1962
  },
1982
1963
  // Past Gens OU
1983
1964
  ///////////////////////////////////////////////////////////////////
@@ -2015,7 +1996,7 @@ exports.Formats = [
2015
1996
  ],
2016
1997
  mod: 'gen5',
2017
1998
  ruleset: ['Standard', 'Evasion Abilities Clause', 'Baton Pass Clause', 'Sleep Moves Clause', 'Swagger Clause'],
2018
- banlist: ['Uber', 'Arena Trap', 'Drizzle ++ Swift Swim', 'Drought ++ Chlorophyll', 'Sand Rush', 'Shadow Tag', 'King\'s Rock', 'Razor Fang', 'Soul Dew'],
1999
+ banlist: ['Uber', 'Arena Trap', 'Drizzle ++ Swift Swim', 'Drought ++ Chlorophyll', 'Sand Rush', 'Shadow Tag', 'King\'s Rock', 'Razor Fang', 'Soul Dew', 'Assist'],
2019
2000
  },
2020
2001
  {
2021
2002
  name: "[Gen 4] OU",
@@ -2434,7 +2415,7 @@ exports.Formats = [
2434
2415
  `&bullet; <a href="https://www.smogon.com/forums/threads/3591794/">VGC 2017 Viability Rankings</a>`,
2435
2416
  `&bullet; <a href="https://www.smogon.com/forums/threads/3590391/">VGC 2017 Sample Teams</a>`,
2436
2417
  ],
2437
- mod: 'vgc17',
2418
+ mod: 'gen7sm',
2438
2419
  gameType: 'doubles',
2439
2420
  searchShow: false,
2440
2421
  timer: {
@@ -2446,7 +2427,7 @@ exports.Formats = [
2446
2427
  timeoutAutoChoose: true,
2447
2428
  dcTimerBank: false,
2448
2429
  },
2449
- ruleset: ['Flat Rules', 'Alola Pokedex', '!! Adjust Level = 50', 'Min Source Gen = 7'],
2430
+ ruleset: ['Flat Rules', 'Old Alola Pokedex', '!! Adjust Level = 50', 'Min Source Gen = 7'],
2450
2431
  banlist: ['Mega', 'Custap Berry', 'Enigma Berry', 'Jaboca Berry', 'Micle Berry', 'Rowap Berry'],
2451
2432
  },
2452
2433
  {
@@ -2478,15 +2459,6 @@ exports.Formats = [
2478
2459
  section: "OR/AS Singles",
2479
2460
  column: 4,
2480
2461
  },
2481
- {
2482
- name: "[Gen 6] Ubers",
2483
- threads: [
2484
- `&bullet; <a href="https://www.smogon.com/forums/posts/8286277/">ORAS Ubers</a>`,
2485
- ],
2486
- mod: 'gen6',
2487
- searchShow: false,
2488
- ruleset: ['Standard', 'Swagger Clause', 'Mega Rayquaza Clause'],
2489
- },
2490
2462
  {
2491
2463
  name: "[Gen 6] UU",
2492
2464
  threads: [
@@ -2555,11 +2527,12 @@ exports.Formats = [
2555
2527
  searchShow: false,
2556
2528
  ruleset: ['Standard', 'Swagger Clause', 'Same Type Clause'],
2557
2529
  banlist: [
2558
- 'Aegislash', 'Altaria-Mega', 'Arceus', 'Blaziken', 'Charizard-Mega-X', 'Darkrai', 'Deoxys-Base', 'Deoxys-Attack', 'Dialga',
2559
- 'Genesect', 'Gengar-Mega', 'Giratina', 'Giratina-Origin', 'Greninja', 'Groudon', 'Ho-Oh', 'Hoopa-Unbound', 'Kangaskhan-Mega',
2560
- 'Kyogre', 'Kyurem-White', 'Lucario-Mega', 'Lugia', 'Mawile-Mega', 'Medicham-Mega', 'Metagross-Mega', 'Mewtwo', 'Palkia', 'Rayquaza',
2561
- 'Reshiram', 'Sableye-Mega', 'Salamence-Mega', 'Shaymin-Sky', 'Slowbro-Mega', 'Talonflame', 'Xerneas', 'Yveltal', 'Zekrom',
2562
- 'Shadow Tag', 'Damp Rock', 'Smooth Rock', 'Soul Dew', 'Baton Pass',
2530
+ 'Aegislash', 'Altaria-Mega', 'Arceus', 'Blaziken', 'Darkrai', 'Deoxys-Base', 'Deoxys-Attack', 'Dialga', 'Genesect', 'Gengar-Mega',
2531
+ 'Giratina', 'Giratina-Origin', 'Greninja', 'Groudon', 'Ho-Oh', 'Hoopa-Unbound', 'Kangaskhan-Mega', 'Kyogre', 'Kyurem-White',
2532
+ 'Lucario-Mega', 'Lugia', 'Mawile-Mega', 'Medicham-Mega', 'Metagross-Mega', 'Mewtwo', 'Palkia', 'Rayquaza', 'Reshiram', 'Sableye-Mega',
2533
+ 'Salamence-Mega', 'Shaymin-Sky', 'Slowbro-Mega', 'Talonflame', 'Xerneas', 'Yveltal', 'Zekrom',
2534
+ 'Shadow Tag', 'Bright Powder', 'Damp Rock', 'Focus Band', 'King\'s Rock', 'Lax Incense', 'Quick Claw', 'Razor Fang', 'Smooth Rock',
2535
+ 'Soul Dew', 'Baton Pass',
2563
2536
  ],
2564
2537
  },
2565
2538
  {
@@ -2656,16 +2629,17 @@ exports.Formats = [
2656
2629
  banlist: ['Soul Dew'],
2657
2630
  },
2658
2631
  {
2659
- name: "[Gen 6] Battle Spot Doubles",
2632
+ name: "[Gen 6] VGC 2015",
2660
2633
  threads: [
2634
+ `&bullet; <a href="https://www.smogon.com/forums/threads/3524352/">VGC 2015 Rules</a>`,
2661
2635
  `&bullet; <a href="https://www.smogon.com/forums/threads/3560820/">ORAS Battle Spot Doubles Discussion</a>`,
2662
- `&bullet; <a href="https://www.smogon.com/forums/threads/3560824/">ORAS BSD Viability Rankings</a>`,
2636
+ `&bullet; <a href="https://www.smogon.com/forums/threads/3530547/">VGC 2015 Viability Rankings</a>`,
2663
2637
  ],
2664
2638
  mod: 'gen6',
2665
2639
  gameType: 'doubles',
2666
2640
  searchShow: false,
2667
2641
  ruleset: ['Flat Rules', 'Min Source Gen = 6'],
2668
- banlist: ['Soul Dew'],
2642
+ banlist: ['Soul Dew', 'Articuno + Snow Cloak', 'Zapdos + Static', 'Moltres + Flame Body', 'Dragonite + Barrier'],
2669
2643
  },
2670
2644
  {
2671
2645
  name: "[Gen 6] VGC 2014",
@@ -2678,6 +2652,18 @@ exports.Formats = [
2678
2652
  searchShow: false,
2679
2653
  ruleset: ['Flat Rules', 'Kalos Pokedex', 'Min Source Gen = 6'],
2680
2654
  },
2655
+ {
2656
+ name: "[Gen 6] Battle Spot Doubles",
2657
+ threads: [
2658
+ `&bullet; <a href="https://www.smogon.com/forums/threads/3560820/">ORAS Battle Spot Doubles Discussion</a>`,
2659
+ `&bullet; <a href="https://www.smogon.com/forums/threads/3560824/">ORAS BSD Viability Rankings</a>`,
2660
+ ],
2661
+ mod: 'gen6',
2662
+ gameType: 'doubles',
2663
+ searchShow: false,
2664
+ ruleset: ['Flat Rules', 'Min Source Gen = 6'],
2665
+ banlist: ['Soul Dew'],
2666
+ },
2681
2667
  {
2682
2668
  name: "[Gen 6] Doubles Custom Game",
2683
2669
  mod: 'gen6',
@@ -2732,8 +2718,8 @@ exports.Formats = [
2732
2718
  ],
2733
2719
  mod: 'gen5',
2734
2720
  searchShow: false,
2735
- ruleset: ['Standard', 'Evasion Abilities Clause', 'Baton Pass Clause', 'Swagger Clause', 'Sleep Clause Mod'],
2736
- banlist: ['Uber', 'OU', 'UUBL', 'Arena Trap', 'Drought', 'Sand Stream', 'Snow Warning'],
2721
+ ruleset: ['Standard', 'Evasion Abilities Clause', 'Swagger Clause', 'Sleep Clause Mod'],
2722
+ banlist: ['Uber', 'OU', 'UUBL', 'Arena Trap', 'Drought', 'Sand Stream', 'Snow Warning', 'Prankster + Assist', 'Prankster + Copycat', 'Baton Pass'],
2737
2723
  },
2738
2724
  {
2739
2725
  name: "[Gen 5] RU",
@@ -2743,8 +2729,9 @@ exports.Formats = [
2743
2729
  ],
2744
2730
  mod: 'gen5',
2745
2731
  searchShow: false,
2746
- ruleset: ['[Gen 5] UU', '!Sleep Clause Mod', 'Sleep Moves Clause'],
2732
+ ruleset: ['[Gen 5] UU', 'Baton Pass Clause', '!Sleep Clause Mod', 'Sleep Moves Clause'],
2747
2733
  banlist: ['UU', 'RUBL', 'Shadow Tag', 'Shell Smash + Baton Pass'],
2734
+ unbanlist: ['Prankster + Assist', 'Prankster + Copycat', 'Baton Pass'],
2748
2735
  },
2749
2736
  {
2750
2737
  name: "[Gen 5] NU",
@@ -2754,8 +2741,8 @@ exports.Formats = [
2754
2741
  ],
2755
2742
  mod: 'gen5',
2756
2743
  searchShow: false,
2757
- ruleset: ['[Gen 5] RU', '!Sleep Moves Clause', 'Sleep Clause Mod', '+Shadow Tag'],
2758
- banlist: ['RU', 'NUBL', 'Prankster + Assist'],
2744
+ ruleset: ['[Gen 5] RU', '!Sleep Moves Clause', 'Sleep Clause Mod'],
2745
+ banlist: ['RU', 'NUBL', 'Assist', 'Copycat'],
2759
2746
  },
2760
2747
  {
2761
2748
  name: "[Gen 5] PU",
@@ -2765,7 +2752,7 @@ exports.Formats = [
2765
2752
  mod: 'gen5',
2766
2753
  searchShow: false,
2767
2754
  ruleset: ['[Gen 5] NU', 'Sleep Moves Clause'],
2768
- banlist: ['NU', 'Combusken', 'Gothorita', 'Linoone', 'Riolu', 'Rotom-Frost', 'Throh', 'Vigoroth'],
2755
+ banlist: ['NU', 'Combusken', 'Gothorita', 'Linoone', 'Riolu', 'Rotom-Frost', 'Simipour', 'Throh', 'Vigoroth'],
2769
2756
  },
2770
2757
  {
2771
2758
  name: "[Gen 5] LC",
@@ -2842,7 +2829,7 @@ exports.Formats = [
2842
2829
  banlist: ['DUber', 'Soul Dew', 'Dark Void', 'Gravity'],
2843
2830
  },
2844
2831
  {
2845
- name: "[Gen 5] GBU Doubles",
2832
+ name: "[Gen 5] VGC 2013",
2846
2833
  mod: 'gen5',
2847
2834
  gameType: 'doubles',
2848
2835
  searchShow: false,
@@ -2892,16 +2879,14 @@ exports.Formats = [
2892
2879
  column: 5,
2893
2880
  },
2894
2881
  {
2895
- name: "[Gen 4] UU",
2882
+ name: "[Gen 4] Ubers",
2896
2883
  threads: [
2897
- `&bullet; <a href="https://www.smogon.com/forums/threads/3532624/">DPP UU Metagame Discussion</a>`,
2898
- `&bullet; <a href="https://www.smogon.com/forums/threads/3503638/">DPP UU Viability Rankings</a>`,
2884
+ `&bullet; <a href="https://www.smogon.com/forums/posts/8286279/">DPP Ubers</a>`,
2899
2885
  ],
2900
2886
  mod: 'gen4',
2901
2887
  searchShow: false,
2902
- ruleset: ['[Gen 4] OU'],
2903
- banlist: ['OU', 'UUBL'],
2904
- unbanlist: ['Arena Trap'],
2888
+ ruleset: ['Standard'],
2889
+ banlist: ['AG'],
2905
2890
  },
2906
2891
  {
2907
2892
  name: "[Gen 4] NU",
@@ -2957,7 +2942,7 @@ exports.Formats = [
2957
2942
  'Picked Team Size = 1', 'Max Team Size = 3',
2958
2943
  '[Gen 4] OU', 'Accuracy Moves Clause', 'Sleep Moves Clause', 'Team Preview',
2959
2944
  ],
2960
- banlist: ['Latias', 'Porygon-Z', 'Snorlax', 'Togekiss', 'Focus Sash', 'Destiny Bond', 'Explosion', 'Perish Song', 'Self-Destruct'],
2945
+ banlist: ['Latias', 'Machamp', 'Porygon-Z', 'Snorlax', 'Togekiss', 'Focus Sash', 'Destiny Bond', 'Explosion', 'Perish Song', 'Self-Destruct'],
2961
2946
  unbanlist: ['Wobbuffet', 'Wynaut', 'Sand Veil'],
2962
2947
  },
2963
2948
  {
@@ -3057,6 +3042,20 @@ exports.Formats = [
3057
3042
  banlist: ['UU'],
3058
3043
  unbanlist: ['Baton Pass'],
3059
3044
  },
3045
+ {
3046
+ name: "[Gen 3] 1v1",
3047
+ desc: `Bring three Pok&eacute;mon to Team Preview and choose one to battle.`,
3048
+ threads: [
3049
+ `&bullet; <a href="https://www.smogon.com/forums/posts/8031456/">ADV 1v1</a>`,
3050
+ ],
3051
+ mod: 'gen3',
3052
+ searchShow: false,
3053
+ ruleset: [
3054
+ 'Picked Team Size = 1', 'Max Team Size = 3',
3055
+ '[Gen 3] OU', 'Accuracy Moves Clause', 'Sleep Moves Clause', 'Team Preview',
3056
+ ],
3057
+ banlist: ['Clefable', 'Slaking', 'Snorlax', 'Suicune', 'Destiny Bond', 'Explosion', 'Ingrain', 'Perish Song', 'Self-Destruct', 'Bright Powder', 'Focus Band', 'King\'s Rock', 'Lax Incense', 'Quick Claw'],
3058
+ },
3060
3059
  {
3061
3060
  name: "[Gen 3] Custom Game",
3062
3061
  mod: 'gen3',
@@ -3107,7 +3106,7 @@ exports.Formats = [
3107
3106
  'Picked Team Size = 1', 'Max Team Size = 3',
3108
3107
  '[Gen 2] OU', 'Accuracy Moves Clause', 'Sleep Moves Clause', 'Team Preview',
3109
3108
  ],
3110
- banlist: ['Clefable', 'Snorlax', 'Zapdos', 'Berserk Gene', 'Bright Powder', 'Focus Band', 'King\'s Rock', 'Quick Claw', 'Destiny Bond', 'Explosion', 'Present', 'Self-Destruct'],
3109
+ banlist: ['Clefable', 'Snorlax', 'Zapdos', 'Berserk Gene', 'Bright Powder', 'Focus Band', 'King\'s Rock', 'Quick Claw', 'Destiny Bond', 'Explosion', 'Perish Song', 'Present', 'Self-Destruct'],
3111
3110
  },
3112
3111
  {
3113
3112
  name: "[Gen 2] Nintendo Cup 2000",
@@ -3171,19 +3170,6 @@ exports.Formats = [
3171
3170
  ruleset: ['[Gen 1] UU'],
3172
3171
  banlist: ['UU', 'NUBL'],
3173
3172
  },
3174
- {
3175
- name: "[Gen 1] Stadium OU",
3176
- threads: [
3177
- `&bullet; <a href="https://www.smogon.com/forums/threads/3685877/">Stadium OU Viability Rankings</a>`,
3178
- ],
3179
- mod: 'gen1stadium',
3180
- searchShow: false,
3181
- ruleset: ['Standard', 'Team Preview'],
3182
- banlist: ['Uber',
3183
- 'Nidoking + Fury Attack + Thrash', 'Exeggutor + Poison Powder + Stomp', 'Exeggutor + Sleep Powder + Stomp',
3184
- 'Exeggutor + Stun Spore + Stomp', 'Jolteon + Focus Energy + Thunder Shock', 'Flareon + Focus Energy + Ember',
3185
- ],
3186
- },
3187
3173
  {
3188
3174
  name: "[Gen 1] Japanese OU",
3189
3175
  desc: `Generation 1 with Japanese battle mechanics.`,
@@ -3205,6 +3191,29 @@ exports.Formats = [
3205
3191
  ],
3206
3192
  banlist: ['Uber'],
3207
3193
  },
3194
+ {
3195
+ name: "[Gen 1] Stadium OU",
3196
+ threads: [
3197
+ `&bullet; <a href="https://www.smogon.com/forums/threads/3685877/">Stadium OU Viability Rankings</a>`,
3198
+ ],
3199
+ mod: 'gen1stadium',
3200
+ searchShow: false,
3201
+ ruleset: ['Standard', 'Team Preview'],
3202
+ banlist: ['Uber',
3203
+ 'Nidoking + Fury Attack + Thrash', 'Exeggutor + Poison Powder + Stomp', 'Exeggutor + Sleep Powder + Stomp',
3204
+ 'Exeggutor + Stun Spore + Stomp', 'Jolteon + Focus Energy + Thunder Shock', 'Flareon + Focus Energy + Ember',
3205
+ ],
3206
+ },
3207
+ {
3208
+ name: "[Gen 1] Tradebacks OU",
3209
+ desc: `RBY OU with movepool additions from the Time Capsule.`,
3210
+ threads: [
3211
+ `&bullet; <a href="https://www.smogon.com/articles/rby-tradebacks-ou">RBY Tradebacks OU</a>`,
3212
+ ],
3213
+ mod: 'gen1',
3214
+ searchShow: false,
3215
+ ruleset: ['[Gen 1] OU', 'Allow Tradeback'],
3216
+ },
3208
3217
  {
3209
3218
  name: "[Gen 1] Custom Game",
3210
3219
  mod: 'gen1',