@pkmn/sim 0.5.16 → 0.5.19

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 (79) hide show
  1. package/build/config/formats.js +97 -114
  2. package/build/config/formats.js.map +1 -1
  3. package/build/data/aliases.js +2 -2
  4. package/build/data/aliases.js.map +1 -1
  5. package/build/data/items.js +1 -3
  6. package/build/data/items.js.map +1 -1
  7. package/build/data/learnsets.js +50 -11
  8. package/build/data/learnsets.js.map +1 -1
  9. package/build/data/mods/gen1/formats-data.js +1 -1
  10. package/build/data/mods/gen1/formats-data.js.map +1 -1
  11. package/build/data/mods/gen1/moves.js +3 -10
  12. package/build/data/mods/gen1/moves.js.map +1 -1
  13. package/build/data/mods/gen3/moves.js +0 -7
  14. package/build/data/mods/gen3/moves.js.map +1 -1
  15. package/build/data/mods/gen3/scripts.js +2 -2
  16. package/build/data/mods/gen3/scripts.js.map +1 -1
  17. package/build/data/mods/gen4/moves.js +1 -1
  18. package/build/data/mods/gen4/moves.js.map +1 -1
  19. package/build/data/mods/gen4/rulesets.js +2 -1
  20. package/build/data/mods/gen4/rulesets.js.map +1 -1
  21. package/build/data/mods/gen5/rulesets.js +2 -1
  22. package/build/data/mods/gen5/rulesets.js.map +1 -1
  23. package/build/data/mods/gen7/formats-data.js +5 -5
  24. package/build/data/mods/gen7/formats-data.js.map +1 -1
  25. package/build/data/mods/gen7/rulesets.js +2 -1
  26. package/build/data/mods/gen7/rulesets.js.map +1 -1
  27. package/build/data/moves.js +57 -78
  28. package/build/data/moves.js.map +1 -1
  29. package/build/data/pokedex.js +10 -3
  30. package/build/data/pokedex.js.map +1 -1
  31. package/build/data/rulesets.js +3 -4
  32. package/build/data/rulesets.js.map +1 -1
  33. package/build/data/text/items.js +1 -0
  34. package/build/data/text/items.js.map +1 -1
  35. package/build/data/text/moves.js +5 -3
  36. package/build/data/text/moves.js.map +1 -1
  37. package/build/sim/battle-actions.js +9 -1
  38. package/build/sim/battle-actions.js.map +1 -1
  39. package/build/sim/battle.js +39 -1
  40. package/build/sim/battle.js.map +1 -1
  41. package/build/sim/dex-conditions.d.ts +1 -0
  42. package/build/sim/dex-conditions.js.map +1 -1
  43. package/build/sim/exported-global-types.d.ts +1 -0
  44. package/build/sim/global-types.d.ts +1 -0
  45. package/build/sim/state.d.ts +1 -1
  46. package/build/sim/state.js +6 -6
  47. package/build/sim/state.js.map +1 -1
  48. package/build/sim/team-validator.js +15 -4
  49. package/build/sim/team-validator.js.map +1 -1
  50. package/build/sim/teams.d.ts +2 -2
  51. package/build/sim/tools/exhaustive-runner.d.ts +9 -0
  52. package/build/sim/tools/exhaustive-runner.js +18 -7
  53. package/build/sim/tools/exhaustive-runner.js.map +1 -1
  54. package/config/formats.ts +100 -117
  55. package/data/aliases.ts +2 -2
  56. package/data/items.ts +1 -3
  57. package/data/learnsets.ts +50 -11
  58. package/data/mods/gen1/formats-data.ts +1 -1
  59. package/data/mods/gen1/moves.ts +3 -10
  60. package/data/mods/gen3/moves.ts +0 -7
  61. package/data/mods/gen3/scripts.ts +3 -3
  62. package/data/mods/gen4/moves.ts +1 -1
  63. package/data/mods/gen4/rulesets.ts +2 -1
  64. package/data/mods/gen5/rulesets.ts +2 -1
  65. package/data/mods/gen7/formats-data.ts +5 -5
  66. package/data/mods/gen7/rulesets.ts +2 -1
  67. package/data/moves.ts +57 -69
  68. package/data/pokedex.ts +10 -3
  69. package/data/rulesets.ts +3 -6
  70. package/data/text/items.ts +2 -0
  71. package/data/text/moves.ts +6 -3
  72. package/package.json +1 -1
  73. package/sim/battle-actions.ts +13 -1
  74. package/sim/battle.ts +38 -1
  75. package/sim/dex-conditions.ts +1 -0
  76. package/sim/exported-global-types.ts +3 -0
  77. package/sim/global-types.ts +3 -0
  78. package/sim/team-validator.ts +16 -4
  79. package/sim/tools/exhaustive-runner.ts +30 -11
@@ -312,6 +312,9 @@ export interface ModdedBattlePokemon {
312
312
  clearBoosts?: (this: Pokemon) => void;
313
313
  calculateStat?: (this: Pokemon, statName: StatIDExceptHP, boost: number, modifier?: number) => number;
314
314
  cureStatus?: (this: Pokemon, silent?: boolean) => boolean;
315
+ formeChange?: (
316
+ this: Pokemon, speciesId: string | Species, source: Effect, isPermanent?: boolean, message?: string
317
+ ) => boolean;
315
318
  getAbility?: (this: Pokemon) => Ability;
316
319
  getActionSpeed?: (this: Pokemon) => number;
317
320
  getItem?: (this: Pokemon) => Item;
@@ -312,6 +312,9 @@ interface ModdedBattlePokemon {
312
312
  clearBoosts?: (this: Pokemon) => void;
313
313
  calculateStat?: (this: Pokemon, statName: StatIDExceptHP, boost: number, modifier?: number) => number;
314
314
  cureStatus?: (this: Pokemon, silent?: boolean) => boolean;
315
+ formeChange?: (
316
+ this: Pokemon, speciesId: string | Species, source: Effect, isPermanent?: boolean, message?: string
317
+ ) => boolean;
315
318
  getAbility?: (this: Pokemon) => Ability;
316
319
  getActionSpeed?: (this: Pokemon) => number;
317
320
  getItem?: (this: Pokemon) => Item;
@@ -543,6 +543,10 @@ export class TeamValidator {
543
543
  tierSpecies = dex.species.get('Kyogre-Primal');
544
544
  } else if (canMegaEvo && species.id === 'rayquaza' && set.moves.map(toID).includes('dragonascent' as ID)) {
545
545
  tierSpecies = dex.species.get('Rayquaza-Mega');
546
+ } else if (item.id === 'rustedsword' && species.id === 'zacian') {
547
+ tierSpecies = dex.species.get('Zacian-Crowned');
548
+ } else if (item.id === 'rustedshield' && species.id === 'zamazenta') {
549
+ tierSpecies = dex.species.get('Zamazenta-Crowned');
546
550
  }
547
551
  }
548
552
 
@@ -1315,10 +1319,10 @@ export class TeamValidator {
1315
1319
  const crowned: {[k: string]: string} = {
1316
1320
  'Zacian-Crowned': 'behemothblade', 'Zamazenta-Crowned': 'behemothbash',
1317
1321
  };
1318
- if (set.species in crowned) {
1319
- const ironHead = set.moves.map(toID).indexOf('ironhead' as ID);
1320
- if (ironHead >= 0) {
1321
- set.moves[ironHead] = crowned[set.species];
1322
+ if (species.name in crowned) {
1323
+ const behemothMove = set.moves.map(toID).indexOf(crowned[species.name] as ID);
1324
+ if (behemothMove >= 0) {
1325
+ set.moves[behemothMove] = 'ironhead';
1322
1326
  }
1323
1327
  }
1324
1328
  return problems;
@@ -1328,6 +1332,14 @@ export class TeamValidator {
1328
1332
  const dex = this.dex;
1329
1333
  const ruleTable = this.ruleTable;
1330
1334
 
1335
+ // https://www.smogon.com/forums/posts/8659168
1336
+ if (
1337
+ (tierSpecies.id === 'zamazentacrowned' && species.id === 'zamazenta') ||
1338
+ (tierSpecies.id === 'zaciancrowned' && species.id === 'zacian')
1339
+ ) {
1340
+ species = tierSpecies;
1341
+ }
1342
+
1331
1343
  setHas['pokemon:' + species.id] = true;
1332
1344
  setHas['basepokemon:' + toID(species.baseSpecies)] = true;
1333
1345
 
@@ -1,4 +1,5 @@
1
1
  import {ObjectReadWriteStream} from '../../lib/streams';
2
+ import {ID} from '../exported-global-types';
2
3
  import {Dex, toID} from '../dex';
3
4
  import {PRNG, PRNGSeed} from '../prng';
4
5
  import {RandomPlayerAI} from './random-player-ai';
@@ -19,10 +20,18 @@ export interface ExhaustiveRunnerOptions {
19
20
  maxGames?: number;
20
21
  maxFailures?: number;
21
22
  dual?: boolean | 'debug';
23
+ possible?: ExhaustiveRunnerPossibilites;
22
24
  runner?: (options: RunnerOptions) => Promise<void>;
23
25
  cmd?: (cycles: number, format: string, seed: string) => string;
24
26
  }
25
27
 
28
+ export interface ExhaustiveRunnerPossibilites {
29
+ pokemon?: ID[];
30
+ items?: ID[];
31
+ abilities?: ID[];
32
+ moves?: ID[];
33
+ }
34
+
26
35
  export class ExhaustiveRunner {
27
36
  static readonly DEFAULT_CYCLES = 1;
28
37
  static readonly MAX_FAILURES = 10;
@@ -46,6 +55,7 @@ export class ExhaustiveRunner {
46
55
  private readonly maxGames?: number;
47
56
  private readonly maxFailures?: number;
48
57
  private readonly dual: boolean | 'debug';
58
+ private readonly possible?: ExhaustiveRunnerPossibilites;
49
59
 
50
60
  private readonly runner: (options: RunnerOptions) => Promise<void>;
51
61
  private readonly cmd: (cycles: number, format: string, seed: string) => string;
@@ -63,6 +73,7 @@ export class ExhaustiveRunner {
63
73
  this.maxFailures = options.maxFailures || ExhaustiveRunner.MAX_FAILURES;
64
74
  this.dual = options.dual || false;
65
75
  this.runner = options.runner || ((o: RunnerOptions) => new Runner(o).run());
76
+ this.possible = options.possible;
66
77
  this.cmd = options.cmd || ((cycles: number, format: string, seed: string) =>
67
78
  `node tools/simulate exhaustive --cycles=${cycles} --format=${format} --seed=${seed}`);
68
79
 
@@ -93,7 +104,7 @@ export class ExhaustiveRunner {
93
104
  error: true,
94
105
  });
95
106
 
96
- if (this.log) this.logProgress(pools);
107
+ if (this.log) this.logProgress(dex, pools);
97
108
  } catch (err) {
98
109
  this.failures++;
99
110
  console.error(
@@ -110,23 +121,31 @@ export class ExhaustiveRunner {
110
121
 
111
122
  private createPools(dex: typeof Dex): Pools {
112
123
  return {
113
- pokemon: new Pool(ExhaustiveRunner.onlyValid(dex.gen, dex.data.Pokedex, p => dex.species.get(p),
114
- (_, p) => (p.name !== 'Pichu-Spiky-eared' && p.name.substr(0, 8) !== 'Pikachu-')), this.prng),
115
- items: new Pool(ExhaustiveRunner.onlyValid(dex.gen, dex.data.Items, i => dex.items.get(i)), this.prng),
116
- abilities: new Pool(ExhaustiveRunner.onlyValid(dex.gen, dex.data.Abilities, a => dex.abilities.get(a)), this.prng),
117
- moves: new Pool(ExhaustiveRunner.onlyValid(dex.gen, dex.data.Moves, m => dex.moves.get(m),
118
- m => (m !== 'struggle' && (m === 'hiddenpower' || m.substr(0, 11) !== 'hiddenpower'))), this.prng),
124
+ pokemon: new Pool(this.possible?.pokemon ??
125
+ ExhaustiveRunner.onlyValid(dex.gen, dex.data.Pokedex, p => dex.species.get(p), (_, p) =>
126
+ (p.name !== 'Pichu-Spiky-eared' && p.name.substr(0, 8) !== 'Pikachu-')), this.prng),
127
+ items: new Pool(this.possible?.items ??
128
+ ExhaustiveRunner.onlyValid(dex.gen, dex.data.Items, i => dex.items.get(i)), this.prng),
129
+ abilities: new Pool(this.possible?.abilities ??
130
+ ExhaustiveRunner.onlyValid(dex.gen, dex.data.Abilities, a => dex.abilities.get(a)), this.prng),
131
+ moves: new Pool(this.possible?.moves ??
132
+ ExhaustiveRunner.onlyValid(dex.gen, dex.data.Moves, m => dex.moves.get(m), m =>
133
+ (m !== 'struggle' && (m === 'hiddenpower' || m.substr(0, 11) !== 'hiddenpower'))), this.prng),
119
134
  };
120
135
  }
121
136
 
122
- private logProgress(p: Pools) {
137
+ private logProgress(dex: typeof Dex, p: Pools) {
123
138
  // `\r` = return to the beginning of the line
124
139
  // `\x1b[k` (`\e[K`) = clear all characters from cursor position to EOL
125
140
  if (this.games) process.stdout.write('\r\x1b[K');
141
+
142
+ const msg = [`[${this.format}] P:${p.pokemon}`];
143
+ if (dex.gen >= 2) msg.push(`I:${p.items}`);
144
+ if (dex.gen >= 3) msg.push(`A:${p.abilities}`);
145
+ msg.push(`M:${p.moves} = ${this.games}`);
146
+
126
147
  // Deliberately don't print a `\n` character so that we can overwrite
127
- process.stdout.write(
128
- `[${this.format}] P:${p.pokemon} I:${p.items} A:${p.abilities} M:${p.moves} = ${this.games}`
129
- );
148
+ process.stdout.write(msg.join(' '));
130
149
  }
131
150
 
132
151
  private static getSignatures(dex: typeof Dex, pools: Pools): Map<string, {item: string, move?: string}[]> {