@pkmn/randoms 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.
- package/build/gen1.js +42 -71
- package/build/gen1.js.map +1 -1
- package/build/gen2.js +2 -2
- package/build/gen2.js.map +1 -1
- package/build/gen3.js +1 -1
- package/build/gen3.js.map +1 -1
- package/build/gen4.js +1 -1
- package/build/gen4.js.map +1 -1
- package/build/gen5.js +1 -1
- package/build/gen5.js.map +1 -1
- package/build/gen6.d.ts +7 -3
- package/build/gen6.js +2 -2
- package/build/gen6.js.map +1 -1
- package/build/gen7.d.ts +23 -2
- package/build/gen7.js +16 -11
- package/build/gen7.js.map +1 -1
- package/build/gen8.js +92 -65
- package/build/gen8.js.map +1 -1
- package/package.json +2 -2
- package/src/gen1.ts +44 -73
- package/src/gen2.ts +2 -2
- package/src/gen3.ts +1 -1
- package/src/gen4.ts +1 -1
- package/src/gen5.ts +1 -1
- package/src/gen6.ts +4 -4
- package/src/gen7.ts +30 -11
- package/src/gen8.ts +91 -66
package/src/gen8.ts
CHANGED
|
@@ -194,7 +194,7 @@ export class RandomTeams {
|
|
|
194
194
|
),
|
|
195
195
|
Poison: (movePool, moves, abilities, types, counter) => {
|
|
196
196
|
if (counter.get('Poison')) return false;
|
|
197
|
-
return types.has('Ground') || types.has('Psychic') || !!counter.setupType || movePool.includes('gunkshot');
|
|
197
|
+
return types.has('Ground') || types.has('Psychic') || types.has('Grass') || !!counter.setupType || movePool.includes('gunkshot');
|
|
198
198
|
},
|
|
199
199
|
Psychic: (movePool, moves, abilities, types, counter) => {
|
|
200
200
|
if (counter.get('Psychic')) return false;
|
|
@@ -209,7 +209,7 @@ export class RandomTeams {
|
|
|
209
209
|
},
|
|
210
210
|
Water: (movePool, moves, abilities, types, counter, species) => {
|
|
211
211
|
if (!counter.get('Water') && !moves.has('hypervoice')) return true;
|
|
212
|
-
if (
|
|
212
|
+
if (['hypervoice', 'liquidation', 'surgingstrikes'].some(m => movePool.includes(m))) return true;
|
|
213
213
|
return abilities.has('Huge Power') && movePool.includes('aquajet');
|
|
214
214
|
},
|
|
215
215
|
};
|
|
@@ -307,8 +307,8 @@ export class RandomTeams {
|
|
|
307
307
|
const dex = this.dex;
|
|
308
308
|
const team = [];
|
|
309
309
|
|
|
310
|
-
const natures =
|
|
311
|
-
const items =
|
|
310
|
+
const natures = this.dex.natures.all();
|
|
311
|
+
const items = this.dex.items.all();
|
|
312
312
|
|
|
313
313
|
const randomN = this.randomNPokemon(this.maxTeamSize, this.forceMonotype);
|
|
314
314
|
|
|
@@ -320,8 +320,8 @@ export class RandomTeams {
|
|
|
320
320
|
let item = '';
|
|
321
321
|
if (this.gen >= 2) {
|
|
322
322
|
do {
|
|
323
|
-
item = this.sample(items);
|
|
324
|
-
} while (this.dex.items.get(item).gen > this.gen || this.dex.
|
|
323
|
+
item = this.sample(items).name;
|
|
324
|
+
} while (this.dex.items.get(item).gen > this.gen || this.dex.items.get(item).isNonstandard);
|
|
325
325
|
}
|
|
326
326
|
|
|
327
327
|
// Make sure forme is legal
|
|
@@ -342,8 +342,8 @@ export class RandomTeams {
|
|
|
342
342
|
let itemData = this.dex.items.get(item);
|
|
343
343
|
if (itemData.forcedForme && forme === this.dex.species.get(itemData.forcedForme).baseSpecies) {
|
|
344
344
|
do {
|
|
345
|
-
|
|
346
|
-
|
|
345
|
+
itemData = this.sample(items);
|
|
346
|
+
item = itemData.name;
|
|
347
347
|
} while (
|
|
348
348
|
itemData.gen > this.gen ||
|
|
349
349
|
itemData.isNonstandard ||
|
|
@@ -353,27 +353,28 @@ export class RandomTeams {
|
|
|
353
353
|
|
|
354
354
|
// Random legal ability
|
|
355
355
|
const abilities = Object.values(species.abilities).filter(a => this.dex.abilities.get(a).gen <= this.gen);
|
|
356
|
-
const ability: string = this.gen <= 2 ? '
|
|
356
|
+
const ability: string = this.gen <= 2 ? 'No Ability' : this.sample(abilities);
|
|
357
357
|
|
|
358
358
|
// Four random unique moves from the movepool
|
|
359
359
|
let pool = ['struggle'];
|
|
360
360
|
if (forme === 'Smeargle') {
|
|
361
|
-
pool =
|
|
362
|
-
|
|
363
|
-
|
|
364
|
-
|
|
361
|
+
pool = this.dex.moves
|
|
362
|
+
.all()
|
|
363
|
+
.filter(move => !(move.isNonstandard || move.isZ || move.isMax || move.realMove))
|
|
364
|
+
.map(m => m.id);
|
|
365
365
|
} else {
|
|
366
366
|
const formes = ['gastrodoneast', 'pumpkaboosuper', 'zygarde10'];
|
|
367
|
-
let learnset = this.dex.
|
|
368
|
-
|
|
369
|
-
this.dex.
|
|
367
|
+
let learnset = this.dex.species.getLearnset(species.id);
|
|
368
|
+
if (formes.includes(species.id) || !learnset) {
|
|
369
|
+
learnset = this.dex.species.getLearnset(this.dex.species.get(species.baseSpecies).id);
|
|
370
|
+
}
|
|
370
371
|
if (learnset) {
|
|
371
372
|
pool = Object.keys(learnset).filter(
|
|
372
373
|
moveid => learnset![moveid].find(learned => learned.startsWith(String(this.gen)))
|
|
373
374
|
);
|
|
374
375
|
}
|
|
375
376
|
if (species.changesFrom) {
|
|
376
|
-
learnset = this.dex.
|
|
377
|
+
learnset = this.dex.species.getLearnset(toID(species.changesFrom));
|
|
377
378
|
const basePool = Object.keys(learnset!).filter(
|
|
378
379
|
moveid => learnset![moveid].find(learned => learned.startsWith(String(this.gen)))
|
|
379
380
|
);
|
|
@@ -405,7 +406,7 @@ export class RandomTeams {
|
|
|
405
406
|
};
|
|
406
407
|
|
|
407
408
|
// Random nature
|
|
408
|
-
const nature = this.sample(natures);
|
|
409
|
+
const nature = this.sample(natures).name;
|
|
409
410
|
|
|
410
411
|
// Level balance--calculate directly from stats rather than using some silly lookup table
|
|
411
412
|
const mbstmin = 1307; // Sunkern has the lowest modified base stat total, and that total is 807
|
|
@@ -447,15 +448,15 @@ export class RandomTeams {
|
|
|
447
448
|
name: species.baseSpecies,
|
|
448
449
|
species: species.name,
|
|
449
450
|
gender: species.gender,
|
|
450
|
-
item
|
|
451
|
-
ability
|
|
452
|
-
moves
|
|
453
|
-
evs
|
|
454
|
-
ivs
|
|
455
|
-
nature
|
|
451
|
+
item,
|
|
452
|
+
ability,
|
|
453
|
+
moves,
|
|
454
|
+
evs,
|
|
455
|
+
ivs,
|
|
456
|
+
nature,
|
|
456
457
|
level,
|
|
457
|
-
happiness
|
|
458
|
-
shiny
|
|
458
|
+
happiness,
|
|
459
|
+
shiny,
|
|
459
460
|
});
|
|
460
461
|
}
|
|
461
462
|
|
|
@@ -474,14 +475,11 @@ export class RandomTeams {
|
|
|
474
475
|
}
|
|
475
476
|
|
|
476
477
|
const pool: number[] = [];
|
|
477
|
-
for (const
|
|
478
|
-
if (
|
|
479
|
-
|
|
480
|
-
|
|
481
|
-
|
|
482
|
-
if (requiredType && !this.dex.data.Pokedex[id].types.includes(requiredType)) continue;
|
|
483
|
-
if (minSourceGen && (this.dex.data.Pokedex[id].gen || 8) < minSourceGen) continue;
|
|
484
|
-
const num = this.dex.data.Pokedex[id].num;
|
|
478
|
+
for (const species of this.dex.species.all()) {
|
|
479
|
+
if (species.isNonstandard && species.isNonstandard !== 'Unobtainable') continue;
|
|
480
|
+
if (requiredType && !species.types.includes(requiredType)) continue;
|
|
481
|
+
if (minSourceGen && species.gen < minSourceGen) continue;
|
|
482
|
+
const num = species.num;
|
|
485
483
|
if (num <= 0 || pool.includes(num)) continue;
|
|
486
484
|
if (num > last) break;
|
|
487
485
|
pool.push(num);
|
|
@@ -494,9 +492,8 @@ export class RandomTeams {
|
|
|
494
492
|
}
|
|
495
493
|
|
|
496
494
|
const formes: string[][] = [];
|
|
497
|
-
for (const
|
|
498
|
-
if (!(
|
|
499
|
-
const species = this.dex.species.get(id);
|
|
495
|
+
for (const species of this.dex.species.all()) {
|
|
496
|
+
if (!(species.num in hasDexNumber)) continue;
|
|
500
497
|
if (species.gen <= this.gen && (!species.isNonstandard || species.isNonstandard === 'Unobtainable')) {
|
|
501
498
|
if (!formes[hasDexNumber[species.num]]) formes[hasDexNumber[species.num]] = [];
|
|
502
499
|
formes[hasDexNumber[species.num]].push(species.name);
|
|
@@ -516,10 +513,10 @@ export class RandomTeams {
|
|
|
516
513
|
randomHCTeam(): PokemonSet[] {
|
|
517
514
|
const team = [];
|
|
518
515
|
|
|
519
|
-
const itemPool =
|
|
520
|
-
const abilityPool =
|
|
521
|
-
const movePool =
|
|
522
|
-
const naturePool =
|
|
516
|
+
const itemPool = [...this.dex.items.all()];
|
|
517
|
+
const abilityPool = [...this.dex.abilities.all()];
|
|
518
|
+
const movePool = [...this.dex.moves.all()];
|
|
519
|
+
const naturePool = this.dex.natures.all();
|
|
523
520
|
|
|
524
521
|
const randomN = this.randomNPokemon(this.maxTeamSize, this.forceMonotype);
|
|
525
522
|
|
|
@@ -529,27 +526,30 @@ export class RandomTeams {
|
|
|
529
526
|
|
|
530
527
|
// Random unique item
|
|
531
528
|
let item = '';
|
|
529
|
+
let itemData;
|
|
532
530
|
if (this.gen >= 2) {
|
|
533
531
|
do {
|
|
534
|
-
|
|
535
|
-
|
|
532
|
+
itemData = this.sampleNoReplace(itemPool);
|
|
533
|
+
item = itemData.name;
|
|
534
|
+
} while (itemData.gen > this.gen || itemData.isNonstandard);
|
|
536
535
|
}
|
|
537
536
|
|
|
538
537
|
// Random unique ability
|
|
539
|
-
let ability = '
|
|
538
|
+
let ability = 'No Ability';
|
|
539
|
+
let abilityData;
|
|
540
540
|
if (this.gen >= 3) {
|
|
541
541
|
do {
|
|
542
|
-
|
|
543
|
-
|
|
542
|
+
abilityData = this.sampleNoReplace(abilityPool);
|
|
543
|
+
ability = abilityData.name;
|
|
544
|
+
} while (abilityData.gen > this.gen || abilityData.isNonstandard);
|
|
544
545
|
}
|
|
545
546
|
|
|
546
547
|
// Random unique moves
|
|
547
548
|
const m = [];
|
|
548
549
|
do {
|
|
549
|
-
const
|
|
550
|
-
const move = this.dex.moves.get(moveid);
|
|
550
|
+
const move = this.sampleNoReplace(movePool);
|
|
551
551
|
if (move.gen <= this.gen && !move.isNonstandard && !move.name.startsWith('Hidden Power ')) {
|
|
552
|
-
m.push(
|
|
552
|
+
m.push(move.id);
|
|
553
553
|
}
|
|
554
554
|
} while (m.length < 4);
|
|
555
555
|
|
|
@@ -580,7 +580,7 @@ export class RandomTeams {
|
|
|
580
580
|
};
|
|
581
581
|
|
|
582
582
|
// Random nature
|
|
583
|
-
const nature = this.sample(naturePool);
|
|
583
|
+
const nature = this.sample(naturePool).name;
|
|
584
584
|
|
|
585
585
|
// Level balance
|
|
586
586
|
const mbstmin = 1307;
|
|
@@ -613,15 +613,15 @@ export class RandomTeams {
|
|
|
613
613
|
name: species.baseSpecies,
|
|
614
614
|
species: species.name,
|
|
615
615
|
gender: species.gender,
|
|
616
|
-
item
|
|
617
|
-
ability
|
|
616
|
+
item,
|
|
617
|
+
ability,
|
|
618
618
|
moves: m,
|
|
619
|
-
evs
|
|
620
|
-
ivs
|
|
621
|
-
nature
|
|
619
|
+
evs,
|
|
620
|
+
ivs,
|
|
621
|
+
nature,
|
|
622
622
|
level,
|
|
623
|
-
happiness
|
|
624
|
-
shiny
|
|
623
|
+
happiness,
|
|
624
|
+
shiny,
|
|
625
625
|
});
|
|
626
626
|
}
|
|
627
627
|
|
|
@@ -1243,8 +1243,8 @@ export class RandomTeams {
|
|
|
1243
1243
|
return (moves.has('rapidspin') || species.nfe || isDoubles);
|
|
1244
1244
|
case 'Blaze':
|
|
1245
1245
|
return (isDoubles && abilities.has('Solar Power')) || (!isDoubles && !isNoDynamax && species.id === 'charizard');
|
|
1246
|
-
case 'Bulletproof': case 'Overcoat':
|
|
1247
|
-
|
|
1246
|
+
// case 'Bulletproof': case 'Overcoat':
|
|
1247
|
+
// return !!counter.setupType;
|
|
1248
1248
|
case 'Chlorophyll':
|
|
1249
1249
|
return (species.baseStats.spe > 100 || !counter.get('Fire') && !moves.has('sunnyday') && !teamDetails.sun);
|
|
1250
1250
|
case 'Cloud Nine':
|
|
@@ -1731,7 +1731,7 @@ export class RandomTeams {
|
|
|
1731
1731
|
(isDoubles && species.randomDoubleBattleMoves) ||
|
|
1732
1732
|
(isNoDynamax && species.randomBattleNoDynamaxMoves) ||
|
|
1733
1733
|
species.randomBattleMoves;
|
|
1734
|
-
const movePool = (randMoves || Object.keys(this.dex.
|
|
1734
|
+
const movePool = (randMoves || Object.keys(this.dex.species.getLearnset(species.id)!)).slice();
|
|
1735
1735
|
if (this.format.gameType === 'multi' || this.format.gameType === 'freeforall') {
|
|
1736
1736
|
// Random Multi Battle uses doubles move pools, but Ally Switch fails in multi battles
|
|
1737
1737
|
// Random Free-For-All also uses doubles move pools, for now
|
|
@@ -1967,8 +1967,10 @@ export class RandomTeams {
|
|
|
1967
1967
|
}
|
|
1968
1968
|
|
|
1969
1969
|
let level: number;
|
|
1970
|
+
// doubles levelling
|
|
1970
1971
|
if (isDoubles && species.randomDoubleBattleLevel) {
|
|
1971
1972
|
level = species.randomDoubleBattleLevel;
|
|
1973
|
+
// No Dmax levelling
|
|
1972
1974
|
} else if (isNoDynamax) {
|
|
1973
1975
|
const tier = species.name.endsWith('-Gmax') ? this.dex.species.get(species.changesFrom).tier : species.tier;
|
|
1974
1976
|
const tierScale: {[k: string]: number} = {
|
|
@@ -1994,19 +1996,38 @@ export class RandomTeams {
|
|
|
1994
1996
|
decidueye: 87, noivern: 85, magnezone: 82, slowking: 81,
|
|
1995
1997
|
};
|
|
1996
1998
|
level = customScale[species.id] || tierScale[tier];
|
|
1999
|
+
// BDSP tier levelling
|
|
2000
|
+
} else if (this.dex.currentMod === 'gen8bdsp') {
|
|
2001
|
+
const tierScale: {[k: string]: number} = {
|
|
2002
|
+
Uber: 76,
|
|
2003
|
+
OU: 80,
|
|
2004
|
+
UUBL: 81,
|
|
2005
|
+
UU: 82,
|
|
2006
|
+
RUBL: 83,
|
|
2007
|
+
RU: 84,
|
|
2008
|
+
NUBL: 85,
|
|
2009
|
+
NU: 86,
|
|
2010
|
+
PUBL: 87,
|
|
2011
|
+
PU: 88, "(PU)": 88, NFE: 88,
|
|
2012
|
+
};
|
|
2013
|
+
// to override tier scaling if needed
|
|
2014
|
+
const customScale: {[k: string]: number} = {};
|
|
2015
|
+
|
|
2016
|
+
level = customScale[species.id] || tierScale[species.tier];
|
|
2017
|
+
// Arbitrary levelling base on data files (typically winrate-influenced)
|
|
1997
2018
|
} else if (species.randomBattleLevel) {
|
|
1998
2019
|
level = species.randomBattleLevel;
|
|
2020
|
+
// Default to level 80
|
|
1999
2021
|
} else {
|
|
2000
2022
|
level = 80;
|
|
2001
2023
|
}
|
|
2002
2024
|
|
|
2003
|
-
|
|
2004
2025
|
// Prepare optimal HP
|
|
2005
2026
|
const srImmunity = ability === 'Magic Guard' || item === 'Heavy-Duty Boots';
|
|
2006
2027
|
const srWeakness = srImmunity ? 0 : this.dex.getEffectiveness('Rock', species);
|
|
2007
2028
|
while (evs.hp > 1) {
|
|
2008
2029
|
const hp = Math.floor(Math.floor(2 * species.baseStats.hp + ivs.hp + Math.floor(evs.hp / 4) + 100) * level / 100 + 10);
|
|
2009
|
-
const multipleOfFourNecessary = (moves.has('substitute') && (
|
|
2030
|
+
const multipleOfFourNecessary = (moves.has('substitute') && !['Leftovers', 'Black Sludge'].includes(item) && (
|
|
2010
2031
|
item === 'Sitrus Berry' ||
|
|
2011
2032
|
item === 'Salac Berry' ||
|
|
2012
2033
|
ability === 'Power Construct'
|
|
@@ -2030,7 +2051,12 @@ export class RandomTeams {
|
|
|
2030
2051
|
if (moves.has('shellsidearm') && item === 'Choice Specs') evs.atk -= 8;
|
|
2031
2052
|
|
|
2032
2053
|
// Minimize confusion damage
|
|
2033
|
-
|
|
2054
|
+
const noAttackStatMoves = [...moves].every(m => {
|
|
2055
|
+
const move = this.dex.moves.get(m);
|
|
2056
|
+
if (move.damageCallback || move.damage) return false;
|
|
2057
|
+
return move.category !== 'Physical' || move.id === 'bodypress';
|
|
2058
|
+
});
|
|
2059
|
+
if (noAttackStatMoves && !moves.has('transform') && (!moves.has('shellsidearm') || !counter.get('Status'))) {
|
|
2034
2060
|
evs.atk = 0;
|
|
2035
2061
|
ivs.atk = 0;
|
|
2036
2062
|
}
|
|
@@ -2065,8 +2091,7 @@ export class RandomTeams {
|
|
|
2065
2091
|
) {
|
|
2066
2092
|
const exclude = pokemonToExclude.map(p => toID(p.species));
|
|
2067
2093
|
const pokemonPool = [];
|
|
2068
|
-
for (
|
|
2069
|
-
let species = this.dex.species.get(id);
|
|
2094
|
+
for (let species of this.dex.species.all()) {
|
|
2070
2095
|
if (species.gen > this.gen || exclude.includes(species.id)) continue;
|
|
2071
2096
|
if (isMonotype) {
|
|
2072
2097
|
if (!species.types.includes(type)) continue;
|
|
@@ -2075,7 +2100,7 @@ export class RandomTeams {
|
|
|
2075
2100
|
if (!species.types.includes(type)) continue;
|
|
2076
2101
|
}
|
|
2077
2102
|
}
|
|
2078
|
-
pokemonPool.push(id);
|
|
2103
|
+
pokemonPool.push(species.id);
|
|
2079
2104
|
}
|
|
2080
2105
|
return pokemonPool;
|
|
2081
2106
|
}
|