@pkmn/randoms 0.9.5 → 0.9.7

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.mjs CHANGED
@@ -43,14 +43,16 @@ function sortBy(array, callback) {
43
43
  return array.sort((a, b) => compare(callback(a), callback(b)));
44
44
  }
45
45
  var Multiset = class extends Map {
46
- add(key) {
46
+ get(key) {
47
47
  var _a;
48
- this.set(key, ((_a = this.get(key)) != null ? _a : 0) + 1);
48
+ return (_a = super.get(key)) != null ? _a : 0;
49
+ }
50
+ add(key) {
51
+ this.set(key, this.get(key) + 1);
49
52
  return this;
50
53
  }
51
54
  remove(key) {
52
- var _a;
53
- const newValue = ((_a = this.get(key)) != null ? _a : 0) - 1;
55
+ const newValue = this.get(key) - 1;
54
56
  if (newValue <= 0)
55
57
  return this.delete(key);
56
58
  this.set(key, newValue);
@@ -72,9 +74,6 @@ var MoveCounter = class extends Utils.Multiset {
72
74
  this.damagingMoves = /* @__PURE__ */ new Set();
73
75
  this.setupType = "";
74
76
  }
75
- get(key) {
76
- return super.get(key) || 0;
77
- }
78
77
  };
79
78
  var RECOVERY_MOVES = [
80
79
  "healorder",
@@ -10452,9 +10451,6 @@ var MoveCounter2 = class extends Utils.Multiset {
10452
10451
  this.damagingMoves = /* @__PURE__ */ new Set();
10453
10452
  this.ironFist = 0;
10454
10453
  }
10455
- get(key) {
10456
- return super.get(key) || 0;
10457
- }
10458
10454
  };
10459
10455
  var RECOVERY_MOVES8 = [
10460
10456
  "healorder",
@@ -10671,6 +10667,7 @@ var RandomTeams = class {
10671
10667
  constructor(dex, format, prng) {
10672
10668
  this.randomSets = randomSetsJSON7;
10673
10669
  this.randomDoublesSets = randomDoublesSetsJSON;
10670
+ this.randomBSSFactorySets = {};
10674
10671
  this.dex = dex;
10675
10672
  this.gen = this.dex.gen;
10676
10673
  this.noStab = NO_STAB8;
@@ -13017,6 +13014,239 @@ var RandomTeams = class {
13017
13014
  }
13018
13015
  return team;
13019
13016
  }
13017
+ randomBSSFactorySet(species, teamData) {
13018
+ var _a;
13019
+ const id = toID5(species.name);
13020
+ const setList = this.randomBSSFactorySets[id].sets;
13021
+ const movesMax = {
13022
+ batonpass: 1,
13023
+ stealthrock: 1,
13024
+ toxicspikes: 1,
13025
+ trickroom: 1,
13026
+ auroraveil: 1
13027
+ };
13028
+ const weatherAbilities = ["drizzle", "drought", "snowwarning", "sandstream"];
13029
+ const terrainAbilities = {
13030
+ electricsurge: "electric",
13031
+ psychicsurge: "psychic",
13032
+ grassysurge: "grassy",
13033
+ seedsower: "grassy",
13034
+ mistysurge: "misty"
13035
+ };
13036
+ const terrainItemsRequire = {
13037
+ electricseed: "electric",
13038
+ psychicseed: "psychic",
13039
+ grassyseed: "grassy",
13040
+ mistyseed: "misty"
13041
+ };
13042
+ const maxWantsTera = 2;
13043
+ const effectivePool = [];
13044
+ for (const curSet of setList) {
13045
+ let reject = false;
13046
+ if (curSet.wantsTera && teamData.wantsTeraCount && teamData.wantsTeraCount >= maxWantsTera) {
13047
+ continue;
13048
+ }
13049
+ if (teamData.weather && weatherAbilities.includes(curSet.ability)) {
13050
+ continue;
13051
+ }
13052
+ if (terrainAbilities[curSet.ability]) {
13053
+ if (!teamData.terrain)
13054
+ teamData.terrain = [];
13055
+ teamData.terrain.push(terrainAbilities[curSet.ability]);
13056
+ }
13057
+ for (const item of curSet.item) {
13058
+ if (terrainItemsRequire[item] && !((_a = teamData.terrain) == null ? void 0 : _a.includes(terrainItemsRequire[item]))) {
13059
+ reject = true;
13060
+ break;
13061
+ }
13062
+ }
13063
+ const curSetMoveVariants = [];
13064
+ for (const move of curSet.moves) {
13065
+ const variantIndex = this.random(move.length);
13066
+ const moveId = toID5(move[variantIndex]);
13067
+ if (movesMax[moveId] && teamData.has[moveId] >= movesMax[moveId]) {
13068
+ reject = true;
13069
+ break;
13070
+ }
13071
+ curSetMoveVariants.push(variantIndex);
13072
+ }
13073
+ if (reject)
13074
+ continue;
13075
+ const set = { set: curSet, moveVariants: curSetMoveVariants };
13076
+ effectivePool.push(set);
13077
+ }
13078
+ if (!effectivePool.length) {
13079
+ if (!teamData.forceResult)
13080
+ return null;
13081
+ for (const curSet of setList) {
13082
+ effectivePool.push({ set: curSet });
13083
+ }
13084
+ }
13085
+ let setData = this.sample(effectivePool);
13086
+ const total = effectivePool.reduce((a, b) => a + b.set.weight, 0);
13087
+ const setRand = this.random(total);
13088
+ let cur = 0;
13089
+ for (const set of effectivePool) {
13090
+ cur += set.set.weight;
13091
+ if (cur > setRand) {
13092
+ setData = set;
13093
+ break;
13094
+ }
13095
+ }
13096
+ const moves = [];
13097
+ for (const [i, moveSlot] of setData.set.moves.entries()) {
13098
+ moves.push(setData.moveVariants ? moveSlot[setData.moveVariants[i]] : this.sample(moveSlot));
13099
+ }
13100
+ return {
13101
+ name: setData.set.species || species.baseSpecies,
13102
+ species: setData.set.species,
13103
+ teraType: this.sampleIfArray(setData.set.teraType),
13104
+ gender: setData.set.gender || species.gender || (this.randomChance(1, 2) ? "M" : "F"),
13105
+ item: this.sampleIfArray(setData.set.item) || "",
13106
+ ability: this.sampleIfArray(setData.set.ability),
13107
+ shiny: this.randomChance(1, 1024),
13108
+ level: 50,
13109
+ happiness: 255,
13110
+ evs: { hp: 0, atk: 0, def: 0, spa: 0, spd: 0, spe: 0, ...setData.set.evs },
13111
+ ivs: { hp: 31, atk: 31, def: 31, spa: 31, spd: 31, spe: 31, ...setData.set.ivs },
13112
+ nature: setData.set.nature || "Serious",
13113
+ moves,
13114
+ wantsTera: setData.set.wantsTera
13115
+ };
13116
+ }
13117
+ randomBSSFactoryTeam(side, depth = 0) {
13118
+ var _a;
13119
+ this.enforceNoDirectCustomBanlistChanges();
13120
+ const forceResult = depth >= 4;
13121
+ const pokemon = [];
13122
+ const pokemonPool = Object.keys(this.randomBSSFactorySets);
13123
+ const teamData = {
13124
+ typeCount: {},
13125
+ typeComboCount: {},
13126
+ baseFormes: {},
13127
+ has: {},
13128
+ wantsTeraCount: 0,
13129
+ forceResult,
13130
+ weaknesses: {},
13131
+ resistances: {}
13132
+ };
13133
+ const weatherAbilitiesSet = {
13134
+ drizzle: "raindance",
13135
+ drought: "sunnyday",
13136
+ snowwarning: "hail",
13137
+ sandstream: "sandstorm"
13138
+ };
13139
+ const resistanceAbilities = {
13140
+ waterabsorb: ["Water"],
13141
+ flashfire: ["Fire"],
13142
+ lightningrod: ["Electric"],
13143
+ voltabsorb: ["Electric"],
13144
+ thickfat: ["Ice", "Fire"],
13145
+ levitate: ["Ground"]
13146
+ };
13147
+ const limitFactor = Math.ceil(this.maxTeamSize / 6);
13148
+ const shuffledSpecies = [];
13149
+ for (const speciesName of pokemonPool) {
13150
+ const sortObject = {
13151
+ speciesName,
13152
+ score: Math.pow(this.prng.next(), 1 / this.randomBSSFactorySets[speciesName].weight)
13153
+ };
13154
+ shuffledSpecies.push(sortObject);
13155
+ }
13156
+ shuffledSpecies.sort((a, b) => a.score - b.score);
13157
+ while (shuffledSpecies.length && pokemon.length < this.maxTeamSize) {
13158
+ const species = this.dex.species.get(shuffledSpecies.pop().speciesName);
13159
+ if (!species.exists)
13160
+ continue;
13161
+ if (this.forceMonotype && !species.types.includes(this.forceMonotype))
13162
+ continue;
13163
+ if (teamData.baseFormes[species.baseSpecies])
13164
+ continue;
13165
+ const types = species.types;
13166
+ let skip = false;
13167
+ if (!this.forceMonotype) {
13168
+ for (const type of types) {
13169
+ if (teamData.typeCount[type] >= 2 * limitFactor && this.randomChance(4, 5)) {
13170
+ skip = true;
13171
+ break;
13172
+ }
13173
+ }
13174
+ }
13175
+ if (skip)
13176
+ continue;
13177
+ const set = this.randomBSSFactorySet(species, teamData);
13178
+ if (!set)
13179
+ continue;
13180
+ let typeCombo = types.slice().sort().join();
13181
+ if (set.ability === "Drought" || set.ability === "Drizzle") {
13182
+ typeCombo = set.ability;
13183
+ }
13184
+ if (!this.forceMonotype && teamData.typeComboCount[typeCombo] >= limitFactor)
13185
+ continue;
13186
+ const itemData = this.dex.items.get(set.item);
13187
+ if (teamData.has[itemData.id])
13188
+ continue;
13189
+ pokemon.push(set);
13190
+ for (const type of types) {
13191
+ if (type in teamData.typeCount) {
13192
+ teamData.typeCount[type]++;
13193
+ } else {
13194
+ teamData.typeCount[type] = 1;
13195
+ }
13196
+ }
13197
+ if (typeCombo in teamData.typeComboCount) {
13198
+ teamData.typeComboCount[typeCombo]++;
13199
+ } else {
13200
+ teamData.typeComboCount[typeCombo] = 1;
13201
+ }
13202
+ teamData.baseFormes[species.baseSpecies] = 1;
13203
+ teamData.has[itemData.id] = 1;
13204
+ if (set.wantsTera) {
13205
+ if (!teamData.wantsTeraCount)
13206
+ teamData.wantsTeraCount = 0;
13207
+ teamData.wantsTeraCount++;
13208
+ }
13209
+ const abilityState = this.dex.abilities.get(set.ability);
13210
+ if (abilityState.id in weatherAbilitiesSet) {
13211
+ teamData.weather = weatherAbilitiesSet[abilityState.id];
13212
+ }
13213
+ for (const move of set.moves) {
13214
+ const moveId = toID5(move);
13215
+ if (moveId in teamData.has) {
13216
+ teamData.has[moveId]++;
13217
+ } else {
13218
+ teamData.has[moveId] = 1;
13219
+ }
13220
+ }
13221
+ for (const typeName of this.dex.types.names()) {
13222
+ if (teamData.resistances[typeName] >= 1)
13223
+ continue;
13224
+ if (((_a = resistanceAbilities[abilityState.id]) == null ? void 0 : _a.includes(typeName)) || !this.dex.getImmunity(typeName, types)) {
13225
+ teamData.resistances[typeName] = (teamData.resistances[typeName] || 0) + 1;
13226
+ if (teamData.resistances[typeName] >= 1)
13227
+ teamData.weaknesses[typeName] = 0;
13228
+ continue;
13229
+ }
13230
+ const typeMod = this.dex.getEffectiveness(typeName, types);
13231
+ if (typeMod < 0) {
13232
+ teamData.resistances[typeName] = (teamData.resistances[typeName] || 0) + 1;
13233
+ if (teamData.resistances[typeName] >= 1)
13234
+ teamData.weaknesses[typeName] = 0;
13235
+ } else if (typeMod > 0) {
13236
+ teamData.weaknesses[typeName] = (teamData.weaknesses[typeName] || 0) + 1;
13237
+ }
13238
+ }
13239
+ }
13240
+ if (!teamData.forceResult && pokemon.length < this.maxTeamSize)
13241
+ return this.randomBSSFactoryTeam(side, ++depth);
13242
+ if (!teamData.forceResult && !this.forceMonotype) {
13243
+ for (const type in teamData.weaknesses) {
13244
+ if (teamData.weaknesses[type] >= 3 * limitFactor)
13245
+ return this.randomBSSFactoryTeam(side, ++depth);
13246
+ }
13247
+ }
13248
+ return pokemon;
13249
+ }
13020
13250
  };
13021
13251
 
13022
13252
  // src/index.ts