@pkmn/randoms 0.6.4 → 0.7.1
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/build/index.d.ts +5 -3
- package/build/index.js +8036 -33
- package/build/index.js.map +1 -1
- package/build/index.mjs +8039 -0
- package/build/index.mjs.map +1 -0
- package/package.json +8 -9
- package/build/gen1.d.ts +0 -43
- package/build/gen1.js +0 -447
- package/build/gen1.js.map +0 -1
- package/build/gen2.d.ts +0 -13
- package/build/gen2.js +0 -289
- package/build/gen2.js.map +0 -1
- package/build/gen3.d.ts +0 -17
- package/build/gen3.js +0 -621
- package/build/gen3.js.map +0 -1
- package/build/gen4.d.ts +0 -16
- package/build/gen4.js +0 -724
- package/build/gen4.js.map +0 -1
- package/build/gen5.d.ts +0 -16
- package/build/gen5.js +0 -842
- package/build/gen5.js.map +0 -1
- package/build/gen6.d.ts +0 -23
- package/build/gen6.js +0 -1216
- package/build/gen6.js.map +0 -1
- package/build/gen7.d.ts +0 -43
- package/build/gen7.js +0 -2022
- package/build/gen7.js.map +0 -1
- package/build/gen8.d.ts +0 -154
- package/build/gen8.js +0 -2921
- package/build/gen8.js.map +0 -1
- package/build/utils.d.ts +0 -43
- package/build/utils.js +0 -70
- package/build/utils.js.map +0 -1
- package/src/gen1.ts +0 -493
- package/src/gen2.ts +0 -323
- package/src/gen3.ts +0 -688
- package/src/gen4.ts +0 -858
- package/src/gen5.ts +0 -916
- package/src/gen6.ts +0 -1357
- package/src/gen7.ts +0 -2194
- package/src/gen8.ts +0 -3122
- package/src/global.d.ts +0 -6
- package/src/index.ts +0 -46
- package/src/utils.ts +0 -78
package/src/gen2.ts
DELETED
|
@@ -1,323 +0,0 @@
|
|
|
1
|
-
import {MoveCounter} from './gen8';
|
|
2
|
-
import {RandomGen3Teams} from './gen3';
|
|
3
|
-
import {
|
|
4
|
-
Format,
|
|
5
|
-
ModdedDex,
|
|
6
|
-
Move,
|
|
7
|
-
PRNG,
|
|
8
|
-
PRNGSeed,
|
|
9
|
-
RandomTeamsTypes,
|
|
10
|
-
Species,
|
|
11
|
-
} from '@pkmn/sim';
|
|
12
|
-
|
|
13
|
-
export class RandomGen2Teams extends RandomGen3Teams {
|
|
14
|
-
constructor(dex: ModdedDex, format: Format, prng: PRNG | PRNGSeed | null) {
|
|
15
|
-
super(dex, format, prng);
|
|
16
|
-
this.moveEnforcementCheckers = {
|
|
17
|
-
Electric: (movePool, moves, abilities, types, counter) => !counter.get('Electric'),
|
|
18
|
-
Fire: (movePool, moves, abilities, types, counter) => !counter.get('Fire'),
|
|
19
|
-
Ground: (movePool, moves, abilities, types, counter) => !counter.get('Ground'),
|
|
20
|
-
Ice: (movePool, moves, abilities, types, counter) => !counter.get('Ice'),
|
|
21
|
-
Normal: (movePool, moves, abilities, types, counter) => !counter.get('Normal') && counter.setupType === 'Physical',
|
|
22
|
-
Psychic: (movePool, moves, abilities, types, counter) => !counter.get('Psychic') && types.has('Grass'),
|
|
23
|
-
Rock: (movePool, moves, abilities, types, counter, species) => !counter.get('Rock') && species.baseStats.atk > 60,
|
|
24
|
-
Water: (movePool, moves, abilities, types, counter) => !counter.get('Water'),
|
|
25
|
-
};
|
|
26
|
-
}
|
|
27
|
-
|
|
28
|
-
shouldCullMove(
|
|
29
|
-
move: Move,
|
|
30
|
-
types: Set<string>,
|
|
31
|
-
moves: Set<string>,
|
|
32
|
-
abilities = {},
|
|
33
|
-
counter: MoveCounter,
|
|
34
|
-
movePool: string[],
|
|
35
|
-
teamDetails: RandomTeamsTypes.TeamDetails,
|
|
36
|
-
): {cull: boolean, isSetup?: boolean} {
|
|
37
|
-
const restTalk = moves.has('rest') && moves.has('sleeptalk');
|
|
38
|
-
|
|
39
|
-
switch (move.id) {
|
|
40
|
-
// Set up once and only if we have the moves for it
|
|
41
|
-
case 'bellydrum': case 'curse': case 'meditate': case 'screech': case 'swordsdance':
|
|
42
|
-
return {
|
|
43
|
-
cull: (
|
|
44
|
-
(counter.setupType !== 'Physical' || counter.get('physicalsetup') > 1) ||
|
|
45
|
-
(!counter.get('Physical') || counter.damagingMoves.size < 2 && !moves.has('batonpass') && !moves.has('sleeptalk'))
|
|
46
|
-
),
|
|
47
|
-
isSetup: true,
|
|
48
|
-
};
|
|
49
|
-
|
|
50
|
-
// Not very useful without their supporting moves
|
|
51
|
-
case 'batonpass':
|
|
52
|
-
return {cull: !counter.setupType && !counter.get('speedsetup') && !moves.has('meanlook')};
|
|
53
|
-
case 'meanlook':
|
|
54
|
-
return {cull: movePool.includes('perishsong')};
|
|
55
|
-
case 'nightmare':
|
|
56
|
-
return {cull: !moves.has('lovelykiss') && !moves.has('sleeppowder')};
|
|
57
|
-
case 'swagger':
|
|
58
|
-
return {cull: !moves.has('substitute')};
|
|
59
|
-
|
|
60
|
-
// Bad after setup
|
|
61
|
-
case 'charm': case 'counter':
|
|
62
|
-
return {cull: !!counter.setupType};
|
|
63
|
-
case 'haze':
|
|
64
|
-
return {cull: !!counter.setupType || restTalk};
|
|
65
|
-
case 'reflect': case 'lightscreen':
|
|
66
|
-
return {cull: !!counter.setupType || moves.has('rest')};
|
|
67
|
-
|
|
68
|
-
// Ineffective to have both
|
|
69
|
-
case 'doubleedge':
|
|
70
|
-
return {cull: moves.has('bodyslam') || moves.has('return')};
|
|
71
|
-
case 'explosion': case 'selfdestruct':
|
|
72
|
-
return {cull: moves.has('softboiled') || restTalk};
|
|
73
|
-
case 'extremespeed':
|
|
74
|
-
return {cull: moves.has('bodyslam') || restTalk};
|
|
75
|
-
case 'hyperbeam':
|
|
76
|
-
return {cull: moves.has('rockslide')};
|
|
77
|
-
case 'quickattack':
|
|
78
|
-
return {cull: moves.has('rest')};
|
|
79
|
-
case 'rapidspin':
|
|
80
|
-
return {cull: !!teamDetails.rapidSpin || moves.has('sleeptalk')};
|
|
81
|
-
case 'return':
|
|
82
|
-
return {cull: moves.has('bodyslam')};
|
|
83
|
-
case 'surf':
|
|
84
|
-
return {cull: moves.has('hydropump')};
|
|
85
|
-
case 'thunder':
|
|
86
|
-
return {cull: moves.has('thunderbolt')};
|
|
87
|
-
case 'gigadrain':
|
|
88
|
-
return {cull: moves.has('razorleaf') || moves.has('swordsdance') && movePool.includes('sludgebomb')};
|
|
89
|
-
case 'icebeam':
|
|
90
|
-
return {cull: moves.has('dragonbreath')};
|
|
91
|
-
case 'seismictoss':
|
|
92
|
-
return {cull: moves.has('rest') || moves.has('sleeptalk')};
|
|
93
|
-
case 'destinybond':
|
|
94
|
-
return {cull: moves.has('explosion')};
|
|
95
|
-
case 'pursuit':
|
|
96
|
-
return {cull: moves.has('crunch') && moves.has('solarbeam')};
|
|
97
|
-
case 'thief':
|
|
98
|
-
return {cull: moves.has('rest') || moves.has('substitute')};
|
|
99
|
-
case 'irontail':
|
|
100
|
-
return {cull: types.has('Ground') && movePool.includes('earthquake')};
|
|
101
|
-
|
|
102
|
-
// Status and illegal move rejections
|
|
103
|
-
case 'confuseray': case 'roar': case 'whirlwind':
|
|
104
|
-
return {cull: restTalk};
|
|
105
|
-
case 'encore':
|
|
106
|
-
return {cull: moves.has('bodyslam') || moves.has('surf') || restTalk};
|
|
107
|
-
case 'lovelykiss':
|
|
108
|
-
return {cull: ['healbell', 'moonlight', 'morningsun'].some(m => moves.has(m)) || restTalk};
|
|
109
|
-
case 'sleeptalk':
|
|
110
|
-
return {cull: moves.has('curse') && counter.get('stab') >= 2};
|
|
111
|
-
case 'softboiled':
|
|
112
|
-
return {cull: movePool.includes('swordsdance')};
|
|
113
|
-
case 'spikes':
|
|
114
|
-
return {cull: !!teamDetails.spikes || types.has('Ice') && moves.has('rapidspin')};
|
|
115
|
-
case 'substitute':
|
|
116
|
-
return {cull: moves.has('agility') || moves.has('rest')};
|
|
117
|
-
case 'synthesis':
|
|
118
|
-
return {cull: moves.has('explosion')};
|
|
119
|
-
case 'thunderwave':
|
|
120
|
-
return {cull: moves.has('thunder') || moves.has('toxic')};
|
|
121
|
-
}
|
|
122
|
-
|
|
123
|
-
return {cull: false};
|
|
124
|
-
}
|
|
125
|
-
|
|
126
|
-
getItem(
|
|
127
|
-
ability: string,
|
|
128
|
-
types: Set<string>,
|
|
129
|
-
moves: Set<string>,
|
|
130
|
-
counter: MoveCounter,
|
|
131
|
-
species: Species,
|
|
132
|
-
) {
|
|
133
|
-
// First, the high-priority items
|
|
134
|
-
if (species.name === 'Ditto') return this.sample(['Metal Powder', 'Quick Claw']);
|
|
135
|
-
if (species.name === 'Farfetch\u2019d') return 'Stick';
|
|
136
|
-
if (species.name === 'Marowak') return 'Thick Club';
|
|
137
|
-
if (species.name === 'Pikachu') return 'Light Ball';
|
|
138
|
-
if (species.name === 'Unown') return 'Twisted Spoon';
|
|
139
|
-
if (moves.has('thief')) return '';
|
|
140
|
-
|
|
141
|
-
// Medium priority
|
|
142
|
-
if (moves.has('rest') && !moves.has('sleeptalk')) return 'Mint Berry';
|
|
143
|
-
if (
|
|
144
|
-
(moves.has('bellydrum') || moves.has('swordsdance')) &&
|
|
145
|
-
species.baseStats.spe >= 60 && !types.has('Ground') &&
|
|
146
|
-
!moves.has('sleeptalk') && !moves.has('substitute') &&
|
|
147
|
-
this.randomChance(1, 2)
|
|
148
|
-
) {
|
|
149
|
-
return 'Miracle Berry';
|
|
150
|
-
}
|
|
151
|
-
|
|
152
|
-
// Default to Leftovers
|
|
153
|
-
return 'Leftovers';
|
|
154
|
-
}
|
|
155
|
-
|
|
156
|
-
randomSet(species: string | Species, teamDetails: RandomTeamsTypes.TeamDetails = {}): RandomTeamsTypes.RandomSet {
|
|
157
|
-
species = this.dex.species.get(species);
|
|
158
|
-
|
|
159
|
-
const movePool = (species.randomBattleMoves || Object.keys(this.dex.species.getLearnset(species.id)!)).slice();
|
|
160
|
-
const rejectedPool: string[] = [];
|
|
161
|
-
const moves = new Set<string>();
|
|
162
|
-
|
|
163
|
-
let ivs = {hp: 30, atk: 30, def: 30, spa: 30, spd: 30, spe: 30};
|
|
164
|
-
let availableHP = 0;
|
|
165
|
-
for (const setMoveid of movePool) {
|
|
166
|
-
if (setMoveid.startsWith('hiddenpower')) availableHP++;
|
|
167
|
-
}
|
|
168
|
-
|
|
169
|
-
const types = new Set(species.types);
|
|
170
|
-
|
|
171
|
-
let counter;
|
|
172
|
-
// We use a special variable to track Hidden Power
|
|
173
|
-
// so that we can check for all Hidden Powers at once
|
|
174
|
-
let hasHiddenPower = false;
|
|
175
|
-
|
|
176
|
-
do {
|
|
177
|
-
// Choose next 4 moves from learnset/viable moves and add them to moves list:
|
|
178
|
-
while (moves.size < this.maxMoveCount && movePool.length) {
|
|
179
|
-
const moveid = this.sampleNoReplace(movePool);
|
|
180
|
-
if (moveid.startsWith('hiddenpower')) {
|
|
181
|
-
availableHP--;
|
|
182
|
-
if (hasHiddenPower) continue;
|
|
183
|
-
hasHiddenPower = true;
|
|
184
|
-
}
|
|
185
|
-
moves.add(moveid);
|
|
186
|
-
}
|
|
187
|
-
while (moves.size < this.maxMoveCount && rejectedPool.length) {
|
|
188
|
-
const moveid = this.sampleNoReplace(rejectedPool);
|
|
189
|
-
if (moveid.startsWith('hiddenpower')) {
|
|
190
|
-
if (hasHiddenPower) continue;
|
|
191
|
-
hasHiddenPower = true;
|
|
192
|
-
}
|
|
193
|
-
moves.add(moveid);
|
|
194
|
-
}
|
|
195
|
-
|
|
196
|
-
counter = this.queryMoves(moves, species.types, new Set(), movePool);
|
|
197
|
-
|
|
198
|
-
// Iterate through the moves again, this time to cull them:
|
|
199
|
-
for (const moveid of moves) {
|
|
200
|
-
const move = this.dex.moves.get(moveid);
|
|
201
|
-
let {cull, isSetup} = this.shouldCullMove(move, types, moves, {}, counter, movePool, teamDetails);
|
|
202
|
-
|
|
203
|
-
// This move doesn't satisfy our setup requirements:
|
|
204
|
-
if (counter.setupType === 'Physical' && move.category === 'Special' && !counter.get('Physical')) {
|
|
205
|
-
cull = true;
|
|
206
|
-
}
|
|
207
|
-
|
|
208
|
-
|
|
209
|
-
// Reject Status, non-STAB, or low basepower moves
|
|
210
|
-
const moveIsRejectable = (
|
|
211
|
-
(move.category !== 'Status' || !move.flags.heal) &&
|
|
212
|
-
// These moves cannot be rejected in favor of a forced move
|
|
213
|
-
!['batonpass', 'sleeptalk', 'spikes', 'sunnyday'].includes(move.id) &&
|
|
214
|
-
(move.category === 'Status' || !types.has(move.type) || (move.basePower && move.basePower < 40))
|
|
215
|
-
);
|
|
216
|
-
|
|
217
|
-
if (!cull && !isSetup && moveIsRejectable && (counter.setupType || !move.stallingMove)) {
|
|
218
|
-
// There may be more important moves that this Pokemon needs
|
|
219
|
-
if (
|
|
220
|
-
// Pokemon should usually have at least one STAB move
|
|
221
|
-
(
|
|
222
|
-
!counter.get('stab') &&
|
|
223
|
-
!counter.get('damage') &&
|
|
224
|
-
!types.has('Ghost') &&
|
|
225
|
-
counter.get('physicalpool') + counter.get('specialpool') > 0
|
|
226
|
-
) || (movePool.includes('megahorn') || (movePool.includes('softboiled') && moves.has('present'))) ||
|
|
227
|
-
// Rest + Sleep Talk should be selected together
|
|
228
|
-
((moves.has('rest') && movePool.includes('sleeptalk')) || (moves.has('sleeptalk') && movePool.includes('rest'))) ||
|
|
229
|
-
// Sunny Day + Solar Beam should be selected together
|
|
230
|
-
(moves.has('sunnyday') && movePool.includes('solarbeam') ||
|
|
231
|
-
(moves.has('solarbeam') && movePool.includes('sunnyday'))) ||
|
|
232
|
-
['milkdrink', 'recover', 'spore'].some(m => movePool.includes(m))
|
|
233
|
-
) {
|
|
234
|
-
cull = true;
|
|
235
|
-
} else {
|
|
236
|
-
// Pokemon should have moves that benefit their typing
|
|
237
|
-
for (const type of types) {
|
|
238
|
-
if (this.moveEnforcementCheckers[type]?.(movePool, moves, new Set(), types, counter, species, teamDetails)) cull = true;
|
|
239
|
-
}
|
|
240
|
-
}
|
|
241
|
-
}
|
|
242
|
-
|
|
243
|
-
// Remove rejected moves from the move list
|
|
244
|
-
if (
|
|
245
|
-
cull &&
|
|
246
|
-
(movePool.length - availableHP || availableHP && (move.id === 'hiddenpower' || !hasHiddenPower))
|
|
247
|
-
) {
|
|
248
|
-
if (move.category !== 'Status' && !move.damage && (move.id !== 'hiddenpower' || !availableHP)) {
|
|
249
|
-
rejectedPool.push(moveid);
|
|
250
|
-
}
|
|
251
|
-
moves.delete(moveid);
|
|
252
|
-
if (moveid.startsWith('hiddenpower')) hasHiddenPower = false;
|
|
253
|
-
break;
|
|
254
|
-
}
|
|
255
|
-
|
|
256
|
-
if (cull && rejectedPool.length) {
|
|
257
|
-
moves.delete(moveid);
|
|
258
|
-
if (moveid.startsWith('hiddenpower')) hasHiddenPower = false;
|
|
259
|
-
break;
|
|
260
|
-
}
|
|
261
|
-
}
|
|
262
|
-
} while (moves.size < this.maxMoveCount && (movePool.length || rejectedPool.length));
|
|
263
|
-
|
|
264
|
-
// Adjust IVs for Hidden Power
|
|
265
|
-
for (const setMoveid of moves) {
|
|
266
|
-
if (!setMoveid.startsWith('hiddenpower')) continue;
|
|
267
|
-
const hpType = setMoveid.substr(11, setMoveid.length);
|
|
268
|
-
|
|
269
|
-
const hpIVs: {[k: string]: Partial<typeof ivs>} = {
|
|
270
|
-
dragon: {def: 28},
|
|
271
|
-
ice: {def: 26},
|
|
272
|
-
psychic: {def: 24},
|
|
273
|
-
electric: {atk: 28},
|
|
274
|
-
grass: {atk: 28, def: 28},
|
|
275
|
-
water: {atk: 28, def: 26},
|
|
276
|
-
fire: {atk: 28, def: 24},
|
|
277
|
-
steel: {atk: 26},
|
|
278
|
-
ghost: {atk: 26, def: 28},
|
|
279
|
-
bug: {atk: 26, def: 26},
|
|
280
|
-
rock: {atk: 26, def: 24},
|
|
281
|
-
ground: {atk: 24},
|
|
282
|
-
poison: {atk: 24, def: 28},
|
|
283
|
-
flying: {atk: 24, def: 26},
|
|
284
|
-
fighting: {atk: 24, def: 24},
|
|
285
|
-
};
|
|
286
|
-
if (hpIVs[hpType]) {
|
|
287
|
-
ivs = {...ivs, ...hpIVs[hpType]};
|
|
288
|
-
}
|
|
289
|
-
|
|
290
|
-
if (ivs.atk === 28 || ivs.atk === 24) ivs.hp = 14;
|
|
291
|
-
if (ivs.def === 28 || ivs.def === 24) ivs.hp -= 8;
|
|
292
|
-
}
|
|
293
|
-
|
|
294
|
-
const levelScale: {[k: string]: number} = {
|
|
295
|
-
NU: 73,
|
|
296
|
-
NUBL: 71,
|
|
297
|
-
UU: 69,
|
|
298
|
-
UUBL: 67,
|
|
299
|
-
OU: 65,
|
|
300
|
-
Uber: 61,
|
|
301
|
-
};
|
|
302
|
-
const customScale: {[k: string]: number} = {
|
|
303
|
-
Ditto: 83, Unown: 87, Wobbuffet: 83,
|
|
304
|
-
};
|
|
305
|
-
const level = this.adjustLevel || customScale[species.name] || levelScale[species.tier] || 80;
|
|
306
|
-
|
|
307
|
-
return {
|
|
308
|
-
name: species.name,
|
|
309
|
-
species: species.name,
|
|
310
|
-
moves: Array.from(moves),
|
|
311
|
-
ability: 'No Ability',
|
|
312
|
-
evs: {hp: 255, atk: 255, def: 255, spa: 255, spd: 255, spe: 255},
|
|
313
|
-
ivs,
|
|
314
|
-
item: this.getItem('None', types, moves, counter, species),
|
|
315
|
-
level,
|
|
316
|
-
// No shiny chance because Gen 2 shinies have bad IVs
|
|
317
|
-
shiny: false,
|
|
318
|
-
gender: species.gender ? species.gender : 'M',
|
|
319
|
-
};
|
|
320
|
-
}
|
|
321
|
-
}
|
|
322
|
-
|
|
323
|
-
export default RandomGen2Teams;
|