@pkmn/randoms 0.4.25 → 0.5.3

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.
package/src/gen7.ts CHANGED
@@ -9,7 +9,9 @@ import {
9
9
  PRNGSeed,
10
10
  PlayerOptions,
11
11
  RandomTeamsTypes,
12
+ SparseStatsTable,
12
13
  Species,
14
+ StatID,
13
15
  StatsTable,
14
16
  toID,
15
17
  } from '@pkmn/sim';
@@ -27,6 +29,19 @@ interface BattleFactorySet {
27
29
  evs?: Partial<StatsTable>;
28
30
  ivs?: Partial<StatsTable>;
29
31
  }
32
+
33
+ const ZeroAttackHPIVs: {[k: string]: SparseStatsTable} = {
34
+ grass: {hp: 30, spa: 30},
35
+ fire: {spa: 30, spe: 30},
36
+ ice: {def: 30},
37
+ ground: {spa: 30, spd: 30},
38
+ fighting: {def: 30, spa: 30, spd: 30, spe: 30},
39
+ electric: {def: 30, spe: 30},
40
+ psychic: {spe: 30},
41
+ flying: {spa: 30, spd: 30, spe: 30},
42
+ rock: {def: 30, spd: 30, spe: 30},
43
+ };
44
+
30
45
  export class RandomGen7Teams extends RandomTeams {
31
46
  constructor(dex: ModdedDex, format: Format, prng: PRNG | PRNGSeed | null) {
32
47
  super(dex, format, prng);
@@ -1423,6 +1438,20 @@ export class RandomGen7Teams extends RandomTeams {
1423
1438
  ivs.spe = 0;
1424
1439
  }
1425
1440
 
1441
+ // Fix IVs for non-Bottle Cap-able sets
1442
+ if (hasHiddenPower && level < 100) {
1443
+ let hpType;
1444
+ for (const move of moves) {
1445
+ if (move.startsWith('hiddenpower')) hpType = move.substr(11);
1446
+ }
1447
+ if (!hpType) throw new Error(`hasHiddenPower is true, but no Hidden Power move was found.`);
1448
+ const HPivs = ivs.atk === 0 ? ZeroAttackHPIVs[hpType] : this.dex.types.get(hpType).HPivs;
1449
+ let iv: StatID;
1450
+ for (iv in HPivs) {
1451
+ ivs[iv] = HPivs[iv]!;
1452
+ }
1453
+ }
1454
+
1426
1455
  return {
1427
1456
  name: species.baseSpecies,
1428
1457
  species: forme,
package/src/gen8.ts CHANGED
@@ -934,7 +934,8 @@ export class RandomTeams {
934
934
  !!counter.setupType ||
935
935
  !!counter.get('speedsetup') ||
936
936
  !!teamDetails.stealthRock ||
937
- ['rest', 'substitute', 'trickroom', 'teleport'].some(m => moves.has(m)),
937
+ ['rest', 'substitute', 'trickroom', 'teleport'].some(m => moves.has(m)) ||
938
+ (species.id === 'palossand' && movePool.includes('shoreup')),
938
939
  };
939
940
  case 'stickyweb':
940
941
  return {cull: counter.setupType === 'Special' || !!teamDetails.stickyWeb};
@@ -1231,7 +1232,7 @@ export class RandomTeams {
1231
1232
  isNoDynamax: boolean
1232
1233
  ): boolean {
1233
1234
  if ([
1234
- 'Flare Boost', 'Hydration', 'Ice Body', 'Innards Out', 'Insomnia', 'Misty Surge',
1235
+ 'Flare Boost', 'Hydration', 'Ice Body', 'Immunity', 'Innards Out', 'Insomnia', 'Misty Surge',
1235
1236
  'Quick Feet', 'Rain Dish', 'Snow Cloak', 'Steadfast', 'Steam Engine',
1236
1237
  ].includes(ability)) return true;
1237
1238
 
@@ -1650,7 +1651,6 @@ export class RandomTeams {
1650
1651
  !counter.get('drain') && !counter.get('recoil') && !counter.get('recovery') &&
1651
1652
  ((defensiveStatTotal <= 250 && counter.get('hazards')) || defensiveStatTotal <= 210)
1652
1653
  ) return 'Focus Sash';
1653
- if (!isDoubles && ability === 'Water Bubble') return 'Mystic Water';
1654
1654
  if (
1655
1655
  moves.has('clangoroussoul') ||
1656
1656
  // We manually check for speed-boosting moves, rather than using `counter.get('speedsetup')`,
@@ -1874,6 +1874,20 @@ export class RandomTeams {
1874
1874
  }
1875
1875
  } while (moves.size < 4 && (movePool.length || rejectedPool.length));
1876
1876
 
1877
+ // for BD/SP only
1878
+ if (hasHiddenPower) {
1879
+ let hpType;
1880
+ for (const move of moves) {
1881
+ if (move.startsWith('hiddenpower')) hpType = move.substr(11);
1882
+ }
1883
+ if (!hpType) throw new Error(`hasHiddenPower is true, but no Hidden Power move was found.`);
1884
+ const HPivs = this.dex.types.get(hpType).HPivs;
1885
+ let iv: StatID;
1886
+ for (iv in HPivs) {
1887
+ ivs[iv] = HPivs[iv]!;
1888
+ }
1889
+ }
1890
+
1877
1891
  const abilityData = Array.from(abilities).map(a => this.dex.abilities.get(a));
1878
1892
  Utils.sortBy(abilityData, abil => -abil.rating);
1879
1893
 
@@ -1982,7 +1996,7 @@ export class RandomTeams {
1982
1996
  // No Dmax levelling
1983
1997
  } else if (isNoDynamax) {
1984
1998
  const tier = species.name.endsWith('-Gmax') ? this.dex.species.get(species.changesFrom).tier : species.tier;
1985
- const tierScale: {[k: string]: number} = {
1999
+ const tierScale: Partial<Record<Species['tier'], number>> = {
1986
2000
  Uber: 76,
1987
2001
  OU: 80,
1988
2002
  UUBL: 81,
@@ -2004,11 +2018,24 @@ export class RandomTeams {
2004
2018
  delibird: 100, vespiquen: 96, pikachu: 92, shedinja: 92, solrock: 90, arctozolt: 88, reuniclus: 87,
2005
2019
  decidueye: 87, noivern: 85, magnezone: 82, slowking: 81,
2006
2020
  };
2007
- level = customScale[species.id] || tierScale[tier];
2021
+ level = customScale[species.id] || tierScale[tier] || 80;
2008
2022
  // BDSP tier levelling
2009
2023
  } else if (this.dex.currentMod === 'gen8bdsp') {
2010
- // TODO: figure out BDSP levelling based on the in-room poll
2011
- level = 80;
2024
+ const tierScale: Partial<Record<Species['tier'], number>> = {
2025
+ Uber: 76, Unreleased: 76,
2026
+ OU: 80,
2027
+ UUBL: 81,
2028
+ UU: 82,
2029
+ RUBL: 83,
2030
+ RU: 84,
2031
+ NUBL: 85,
2032
+ NU: 86,
2033
+ PUBL: 87,
2034
+ PU: 88, "(PU)": 88, NFE: 88,
2035
+ };
2036
+ const customScale: {[k: string]: number} = {};
2037
+
2038
+ level = customScale[species.id] || tierScale[species.tier] || 80;
2012
2039
  // Arbitrary levelling base on data files (typically winrate-influenced)
2013
2040
  } else if (species.randomBattleLevel) {
2014
2041
  level = species.randomBattleLevel;