"use strict";
var __defProp = Object.defineProperty;
var __getOwnPropDesc = Object.getOwnPropertyDescriptor;
var __getOwnPropNames = Object.getOwnPropertyNames;
var __hasOwnProp = Object.prototype.hasOwnProperty;
var __export = (target, all) => {
  for (var name in all)
    __defProp(target, name, { get: all[name], enumerable: true });
};
var __copyProps = (to, from, except, desc) => {
  if (from && typeof from === "object" || typeof from === "function") {
    for (let key of __getOwnPropNames(from))
      if (!__hasOwnProp.call(to, key) && key !== except)
        __defProp(to, key, { get: () => from[key], enumerable: !(desc = __getOwnPropDesc(from, key)) || desc.enumerable });
  }
  return to;
};
var __toCommonJS = (mod) => __copyProps(__defProp({}, "__esModule", { value: true }), mod);
var randombattles_exports = {};
__export(randombattles_exports, {
  commands: () => commands
});
module.exports = __toCommonJS(randombattles_exports);
var import_lib = require("../../../lib");
var import_random_teams = require("../../../data/mods/ssb/random-teams");
function getHTMLCriteriaDescription(criteria) {
  const format = (list) => list.map((m) => import_lib.Utils.html`<strong>${m.name}</strong>`);
  const parts = [];
  const { moves, ability, item, nature, teraType } = criteria;
  if (moves.mustHave.length) {
    parts.push(`had the move${Chat.plural(moves.mustHave)} ${Chat.toListString(format(moves.mustHave))}`);
  }
  if (moves.mustNotHave.length) {
    parts.push(`did not have the move${Chat.plural(moves.mustNotHave)} ${Chat.toListString(format(moves.mustNotHave), "or")}`);
  }
  if (ability.mustHave) {
    parts.push(import_lib.Utils.html`had the ability <strong>${ability.mustHave.name}</strong>`);
  }
  if (ability.mustNotHave.length) {
    parts.push(`did not have the ${Chat.plural(ability.mustNotHave, "abilities", "ability")} ${Chat.toListString(format(ability.mustNotHave), "or")}`);
  }
  if (item.mustHave) {
    parts.push(import_lib.Utils.html`had the item <strong>${item.mustHave.name}</strong>`);
  }
  if (item.mustNotHave.length) {
    parts.push(`did not have the item${Chat.plural(item.mustNotHave)} ${Chat.toListString(format(item.mustNotHave), "or")}`);
  }
  if (nature.mustHave) {
    parts.push(import_lib.Utils.html`had the nature <strong>${nature.mustHave.name}</strong>`);
  }
  if (nature.mustNotHave.length) {
    parts.push(`did not have the nature${Chat.plural(nature.mustNotHave)} ${Chat.toListString(format(nature.mustNotHave), "or")}`);
  }
  if (teraType.mustHave) {
    parts.push(import_lib.Utils.html`had the Tera Type <strong>${teraType.mustHave.name}</strong>`);
  }
  if (teraType.mustNotHave.length) {
    parts.push(`did not have the Tera Type${Chat.plural(teraType.mustNotHave)} ${Chat.toListString(format(teraType.mustNotHave), "or")}`);
  }
  return Chat.toListString(parts, "and");
}
function setProbability(species, format, criteria, rounds = 700) {
  const results = { rounds, matches: 0 };
  const generator = Teams.getGenerator(format);
  for (let i = 0; i < rounds; i++) {
    const set = generator.randomSet(
      species,
      {},
      false,
      format.gameType !== "singles",
      format.ruleTable?.has("dynamaxclause")
    );
    if (criteria.item.mustHave && set.item !== criteria.item.mustHave.name)
      continue;
    if (criteria.item.mustNotHave.some((item) => item.name === set.item))
      continue;
    if (criteria.ability.mustHave && set.ability !== criteria.ability.mustHave.name)
      continue;
    if (criteria.ability.mustNotHave.some((ability) => ability.name === set.ability))
      continue;
    if (criteria.nature.mustHave && set.nature !== criteria.nature.mustHave.name)
      continue;
    if (criteria.nature.mustNotHave.some((nature) => nature.name === set.nature))
      continue;
    if (criteria.teraType.mustHave && set.teraType !== criteria.teraType.mustHave.name)
      continue;
    if (criteria.teraType.mustNotHave.some((type) => type.name === set.teraType))
      continue;
    const setHasMove = (move) => {
      const id = move.id === "hiddenpower" ? `${move.id}${toID(move.type)}` : move.id;
      return set.moves.includes(id);
    };
    if (!criteria.moves.mustHave.every(setHasMove))
      continue;
    if (criteria.moves.mustNotHave.some(setHasMove))
      continue;
    results.matches++;
  }
  return results;
}
const GEN_NAMES = {
  gen1: "[Gen 1]",
  gen2: "[Gen 2]",
  gen3: "[Gen 3]",
  gen4: "[Gen 4]",
  gen5: "[Gen 5]",
  gen6: "[Gen 6]",
  gen7: "[Gen 7]"
};
const STAT_NAMES = {
  hp: "HP",
  atk: "Atk",
  def: "Def",
  spa: "SpA",
  spd: "SpD",
  spe: "Spe"
};
const TIERS = {
  uber: "Uber",
  ubers: "Uber",
  ou: "OU",
  uu: "UU",
  ru: "RU",
  nu: "NU",
  pu: "PU",
  mono: "Mono",
  monotype: "Mono",
  lc: "LC",
  littlecup: "LC"
};
function formatAbility(ability) {
  ability = Dex.abilities.get(ability);
  return `<a href="https://${Config.routes.dex}/abilities/${ability.id}" target="_blank" class="subtle" style="white-space:nowrap">${ability.name}</a>`;
}
function formatNature(n) {
  const nature = Dex.natures.get(n);
  return nature.name;
}
function formatMove(move) {
  move = Dex.moves.get(move);
  return `<a href="https://${Config.routes.dex}/moves/${move.id}" target="_blank" class="subtle" style="white-space:nowrap">${move.name}</a>`;
}
function formatItem(item) {
  if (typeof item === "string" && item === "No Item") {
    return `No Item`;
  } else {
    item = Dex.items.get(item);
    return `<a href="https://${Config.routes.dex}/items/${item.id}" target="_blank" class="subtle" style="white-space:nowrap">${item.name}</a>`;
  }
}
function getSets(species, format = "gen9randombattle") {
  const dex = Dex.forFormat(format);
  species = dex.species.get(species);
  const setsFile = JSON.parse(
    (0, import_lib.FS)(`data/${dex.isBase ? "" : `mods/${dex.currentMod}/`}random-sets.json`).readIfExistsSync() || "{}"
  );
  const sets = setsFile[species.id]?.sets;
  if (!sets?.length)
    return null;
  return sets;
}
function getData(species, format) {
  const dex = Dex.forFormat(format);
  species = dex.species.get(species);
  const dataFile = JSON.parse(
    (0, import_lib.FS)(`data/mods/${dex.currentMod}/random-data.json`).readIfExistsSync() || "{}"
  );
  const data = dataFile[species.id];
  if (!data)
    return null;
  return data;
}
function getRBYMoves(species) {
  species = Dex.mod(`gen1`).species.get(species);
  const data = getData(species, "gen1randombattle");
  if (!data)
    return false;
  let buf = ``;
  if (data.moves) {
    buf += `<br/><b>Randomized moves</b>: `;
    buf += data.moves.map(formatMove).sort().join(", ");
  }
  if (data.comboMoves) {
    buf += `<br/><b>Combo moves</b>: `;
    buf += data.comboMoves.map(formatMove).sort().join(", ");
  }
  if (data.exclusiveMoves) {
    buf += `<br/><b>Exclusive moves</b>: `;
    buf += data.exclusiveMoves.map(formatMove).sort().join(", ");
  }
  if (data.essentialMove) {
    buf += `<br/><b>Essential move</b>: `;
    buf += formatMove(data.essentialMove);
  }
  if (!data.moves && !data.comboMoves && !data.exclusiveMoves && !data.essentialMove) {
    return false;
  }
  return buf;
}
function getLetsGoMoves(species) {
  species = Dex.species.get(species);
  const data = getData(species, "gen7letsgorandombattle");
  if (!data)
    return false;
  const isLetsGoLegal = (species.num <= 151 || ["Meltan", "Melmetal"].includes(species.name)) && (!species.forme || ["Alola", "Mega", "Mega-X", "Mega-Y", "Starter"].includes(species.forme));
  if (!isLetsGoLegal)
    return false;
  if (!data.moves?.length)
    return false;
  return data.moves.map(formatMove).sort().join(`, `);
}
function battleFactorySets(species, tier, gen = "gen8", isBSS = false) {
  species = Dex.species.get(species);
  if (typeof species.battleOnly === "string") {
    species = Dex.species.get(species.battleOnly);
  }
  gen = toID(gen);
  const genNum = parseInt(gen[3]);
  if (isNaN(genNum) || genNum < 6 || isBSS && genNum < 7)
    return null;
  const statsFile = JSON.parse(
    (0, import_lib.FS)(`data${gen === "gen9" ? "/" : `/mods/${gen}`}/${isBSS ? `bss-` : ``}factory-sets.json`).readIfExistsSync() || "{}"
  );
  if (!Object.keys(statsFile).length)
    return null;
  let buf = ``;
  if (!isBSS) {
    if (!tier)
      return { e: `Please provide a valid tier.` };
    if (!(toID(tier) in TIERS))
      return { e: `That tier isn't supported.` };
    if (!(TIERS[toID(tier)] in statsFile)) {
      return { e: `${TIERS[toID(tier)]} is not included in [Gen ${genNum}] Battle Factory.` };
    }
    const t = statsFile[TIERS[toID(tier)]];
    if (!(species.id in t)) {
      const formatName = Dex.formats.get(`${gen}battlefactory`).name;
      return { e: `${species.name} doesn't have any sets in ${TIERS[toID(tier)]} for ${formatName}.` };
    }
    const setObj = t[species.id];
    buf += `<span style="color:#999999;">Sets for ${species.name} in${genNum === 8 ? `` : ` ${GEN_NAMES[gen]}`} ${TIERS[toID(tier)]}:</span><br />`;
    for (const [i, set] of setObj.sets.entries()) {
      buf += `<details><summary>Set ${i + 1}</summary>`;
      buf += `<ul style="list-style-type:none;">`;
      buf += `<li>${set.species}${set.gender ? ` (${set.gender})` : ``} @ ${Array.isArray(set.item) ? set.item.map(formatItem).join(" / ") : formatItem(set.item)}</li>`;
      buf += `<li>Ability: ${Array.isArray(set.ability) ? set.ability.map(formatAbility).join(" / ") : formatAbility(set.ability)}</li>`;
      if (TIERS[toID(tier)] === "LC" && !set.level)
        buf += `<li>Level: 5</li>`;
      if (set.level && set.level < 100)
        buf += `<li>Level: ${set.level}</li>`;
      if (set.shiny)
        buf += `<li>Shiny: Yes</li>`;
      if (set.happiness)
        buf += `<li>Happiness: ${set.happiness}</li>`;
      if (set.evs) {
        buf += `<li>EVs: `;
        const evs = [];
        let ev;
        for (ev in set.evs) {
          if (set.evs[ev] === 0)
            continue;
          evs.push(`${set.evs[ev]} ${STAT_NAMES[ev]}`);
        }
        buf += `${evs.join(" / ")}</li>`;
      }
      buf += `<li>${Array.isArray(set.nature) ? set.nature.map(formatNature).join(" / ") : formatNature(set.nature)} Nature</li>`;
      if (set.ivs) {
        buf += `<li>IVs: `;
        const ivs = [];
        let iv;
        for (iv in set.ivs) {
          if (set.ivs[iv] === 31)
            continue;
          ivs.push(`${set.ivs[iv]} ${STAT_NAMES[iv]}`);
        }
        buf += `${ivs.join(" / ")}</li>`;
      }
      for (const moveid of set.moves) {
        buf += `<li>- ${Array.isArray(moveid) ? moveid.map(formatMove).join(" / ") : formatMove(moveid)}</li>`;
      }
      buf += `</ul></details>`;
    }
  } else {
    const format = Dex.formats.get(`${gen}bssfactory`);
    if (!(species.id in statsFile))
      return { e: `${species.name} doesn't have any sets in ${format.name}.` };
    const setObj = statsFile[species.id];
    buf += `<span style="color:#999999;">Sets for ${species.name} in ${format.name}:</span><br />`;
    for (const [i, set] of setObj.sets.entries()) {
      buf += `<details><summary>Set ${i + 1}</summary>`;
      buf += `<ul style="list-style-type:none;padding-left:0;">`;
      buf += `<li>${set.species}${set.gender ? ` (${set.gender})` : ``} @ ${Array.isArray(set.item) ? set.item.map(formatItem).join(" / ") : formatItem(set.item)}</li>`;
      buf += `<li>Ability: ${Array.isArray(set.ability) ? set.ability.map(formatAbility).join(" / ") : formatAbility(set.ability)}</li>`;
      if (!set.level)
        buf += `<li>Level: 50</li>`;
      if (set.level && set.level < 50)
        buf += `<li>Level: ${set.level}</li>`;
      if (set.shiny)
        buf += `<li>Shiny: Yes</li>`;
      if (set.happiness)
        buf += `<li>Happiness: ${set.happiness}</li>`;
      if (set.evs) {
        buf += `<li>EVs: `;
        const evs = [];
        let ev;
        for (ev in set.evs) {
          if (set.evs[ev] === 0)
            continue;
          evs.push(`${set.evs[ev]} ${STAT_NAMES[ev]}`);
        }
        buf += `${evs.join(" / ")}</li>`;
      }
      buf += `<li>${Array.isArray(set.nature) ? set.nature.map(formatNature).join(" / ") : formatNature(set.nature)} Nature</li>`;
      if (set.ivs) {
        buf += `<li>IVs: `;
        const ivs = [];
        let iv;
        for (iv in set.ivs) {
          if (set.ivs[iv] === 31)
            continue;
          ivs.push(`${set.ivs[iv]} ${STAT_NAMES[iv]}`);
        }
        buf += `${ivs.join(" / ")}</li>`;
      }
      for (const moveid of set.moves) {
        buf += `<li>- ${Array.isArray(moveid) ? moveid.map(formatMove).join(" / ") : formatMove(moveid)}</li>`;
      }
      buf += `</ul></details>`;
    }
  }
  return buf;
}
function CAP1v1Sets(species) {
  species = Dex.species.get(species);
  const statsFile = JSON.parse(
    (0, import_lib.FS)(`data/mods/gen8/cap-1v1-sets.json`).readIfExistsSync() || "{}"
  );
  if (!Object.keys(statsFile).length)
    return null;
  if (species.isNonstandard !== "CAP") {
    return {
      e: `[Gen 8] CAP 1v1 only allows Pok\xE9mon created by the Create-A-Pok\xE9mon Project.`,
      parse: `/cap`
    };
  }
  if (species.isNonstandard === "CAP" && !(species.name in statsFile)) {
    return { e: `${species.name} doesn't have any sets in [Gen 8] CAP 1v1.` };
  }
  let buf = `<span style="color:#999999;">Sets for ${species.name} in [Gen 8] CAP 1v1:</span><br />`;
  for (const [i, set] of statsFile[species.name].entries()) {
    buf += `<details><summary>Set ${i + 1}</summary>`;
    buf += `<ul style="list-style-type:none;">`;
    buf += `<li>${set.species || species.name}${set.gender ? ` (${set.gender})` : ``} @ ${Array.isArray(set.item) ? set.item.map(formatItem).join(" / ") : formatItem(set.item)}</li>`;
    buf += `<li>Ability: ${Array.isArray(set.ability) ? set.ability.map(formatAbility).join(" / ") : formatAbility(set.ability)}</li>`;
    if (set.level && set.level < 100)
      buf += `<li>Level: ${set.level}</li>`;
    if (set.shiny)
      buf += `<li>Shiny: Yes</li>`;
    if (set.happiness)
      buf += `<li>Happiness: ${set.happiness}</li>`;
    if (set.evs) {
      buf += `<li>EVs: `;
      const evs = [];
      let ev;
      for (ev in set.evs) {
        if (set.evs[ev] === 0)
          continue;
        evs.push(`${set.evs[ev]} ${STAT_NAMES[ev]}`);
      }
      buf += `${evs.join(" / ")}</li>`;
    }
    buf += `<li>${Array.isArray(set.nature) ? set.nature.map(formatNature).join(" / ") : formatNature(set.nature)} Nature</li>`;
    if (set.ivs) {
      buf += `<li>IVs: `;
      const ivs = [];
      let iv;
      for (iv in set.ivs) {
        if (set.ivs[iv] === 31)
          continue;
        ivs.push(`${set.ivs[iv]} ${STAT_NAMES[iv]}`);
      }
      buf += `${ivs.join(" / ")}</li>`;
    }
    for (const moveid of set.moves) {
      buf += `<li>- ${Array.isArray(moveid) ? moveid.map(formatMove).join(" / ") : formatMove(moveid)}</li>`;
    }
    buf += `</ul></details>`;
  }
  return buf;
}
function generateSSBSet(set, dex, baseDex) {
  if (set.skip) {
    const baseSet = toID(Object.values(import_random_teams.ssbSets[set.skip]).join());
    const skipSet = toID(Object.values(set).join()).slice(0, -toID(set.skip).length);
    if (baseSet === skipSet)
      return ``;
  }
  let buf = ``;
  buf += `<details><summary>Set</summary>`;
  buf += `<ul style="list-style-type:none;"><li>${set.species}${set.gender !== "" ? ` (${set.gender})` : ``} @ ${Array.isArray(set.item) ? set.item.map((x) => dex.items.get(x).name).join(" / ") : dex.items.get(set.item).name}</li>`;
  buf += `<li>Ability: ${Array.isArray(set.ability) ? set.ability.map((x) => dex.abilities.get(x).name).join(" / ") : dex.abilities.get(set.ability).name}</li>`;
  if (set.shiny)
    buf += `<li>Shiny: ${typeof set.shiny === "number" ? `Sometimes` : `Yes`}</li>`;
  if (set.evs) {
    const evs = [];
    let ev;
    for (ev in set.evs) {
      if (set.evs[ev] === 0)
        continue;
      evs.push(`${set.evs[ev]} ${STAT_NAMES[ev]}`);
    }
    buf += `<li>EVs: ${evs.join(" / ")}</li>`;
  }
  if (set.nature) {
    buf += `<li>${Array.isArray(set.nature) ? set.nature.join(" / ") : formatNature(set.nature)} Nature</li>`;
  }
  if (set.ivs) {
    const ivs = [];
    let iv;
    for (iv in set.ivs) {
      if (set.ivs[iv] === 31)
        continue;
      ivs.push(`${set.ivs[iv]} ${STAT_NAMES[iv]}`);
    }
    buf += `<li>IVs: ${ivs.join(" / ")}</li>`;
  }
  for (const moveid of set.moves) {
    buf += `<li>- ${Array.isArray(moveid) ? moveid.map((x) => dex.moves.get(x).name).join(" / ") : dex.moves.get(moveid).name}</li>`;
  }
  const italicize = !baseDex.moves.get(set.signatureMove).exists;
  buf += `<li>- ${italicize ? `<i>` : ``}${dex.moves.get(set.signatureMove).name}${italicize ? `</i>` : ``}</li>`;
  buf += `</ul>`;
  buf += `</details>`;
  return buf;
}
function generateSSBMoveInfo(sigMove, dex) {
  let buf = ``;
  if (sigMove.shortDesc || sigMove.desc) {
    buf += `<hr />`;
    buf += Chat.getDataMoveHTML(sigMove);
    const details = {
      Priority: String(sigMove.priority),
      Gen: String(sigMove.gen) || "CAP"
    };
    if (sigMove.isNonstandard === "Past" && dex.gen >= 8)
      details["&#10007; Past Gens Only"] = "";
    if (sigMove.secondary || sigMove.secondaries)
      details["&#10003; Secondary effect"] = "";
    if (sigMove.flags["contact"])
      details["&#10003; Contact"] = "";
    if (sigMove.flags["sound"])
      details["&#10003; Sound"] = "";
    if (sigMove.flags["bullet"])
      details["&#10003; Bullet"] = "";
    if (sigMove.flags["pulse"])
      details["&#10003; Pulse"] = "";
    if (!sigMove.flags["protect"] && !/(ally|self)/i.test(sigMove.target))
      details["&#10003; Bypasses Protect"] = "";
    if (sigMove.flags["bypasssub"])
      details["&#10003; Bypasses Substitutes"] = "";
    if (sigMove.flags["defrost"])
      details["&#10003; Thaws user"] = "";
    if (sigMove.flags["bite"])
      details["&#10003; Bite"] = "";
    if (sigMove.flags["punch"])
      details["&#10003; Punch"] = "";
    if (sigMove.flags["powder"])
      details["&#10003; Powder"] = "";
    if (sigMove.flags["reflectable"])
      details["&#10003; Bounceable"] = "";
    if (sigMove.flags["charge"])
      details["&#10003; Two-turn move"] = "";
    if (sigMove.flags["recharge"])
      details["&#10003; Has recharge turn"] = "";
    if (sigMove.flags["gravity"])
      details["&#10007; Suppressed by Gravity"] = "";
    if (sigMove.flags["dance"])
      details["&#10003; Dance move"] = "";
    if (sigMove.zMove?.basePower) {
      details["Z-Power"] = String(sigMove.zMove.basePower);
    } else if (sigMove.zMove?.effect) {
      const zEffects = {
        clearnegativeboost: "Restores negative stat stages to 0",
        crit2: "Crit ratio +2",
        heal: "Restores HP 100%",
        curse: "Restores HP 100% if user is Ghost type, otherwise Attack +1",
        redirect: "Redirects opposing attacks to user",
        healreplacement: "Restores replacement's HP 100%"
      };
      details["Z-Effect"] = zEffects[sigMove.zMove.effect];
    } else if (sigMove.zMove?.boost) {
      details["Z-Effect"] = "";
      const boost = sigMove.zMove.boost;
      for (const h in boost) {
        details["Z-Effect"] += ` ${Dex.stats.mediumNames[h]} +${boost[h]}`;
      }
    } else if (sigMove.isZ && typeof sigMove.isZ === "string") {
      details["&#10003; Z-Move"] = "";
      const zCrystal = dex.items.get(sigMove.isZ);
      details["Z-Crystal"] = zCrystal.name;
      if (zCrystal.itemUser) {
        details["User"] = zCrystal.itemUser.join(", ");
        details["Required Move"] = dex.items.get(sigMove.isZ).zMoveFrom;
      }
    } else {
      details["Z-Effect"] = "None";
    }
    const targetTypes = {
      normal: "One Adjacent Pok\xE9mon",
      self: "User",
      adjacentAlly: "One Ally",
      adjacentAllyOrSelf: "User or Ally",
      adjacentFoe: "One Adjacent Opposing Pok\xE9mon",
      allAdjacentFoes: "All Adjacent Opponents",
      foeSide: "Opposing Side",
      allySide: "User's Side",
      allyTeam: "User's Side",
      allAdjacent: "All Adjacent Pok\xE9mon",
      any: "Any Pok\xE9mon",
      all: "All Pok\xE9mon",
      scripted: "Chosen Automatically",
      randomNormal: "Random Adjacent Opposing Pok\xE9mon",
      allies: "User and Allies"
    };
    details["Target"] = targetTypes[sigMove.target] || "Unknown";
    if (sigMove.isNonstandard === "Unobtainable") {
      details[`Unobtainable in Gen ${dex.gen}`] = "";
    }
    buf += `<font size="1">${Object.entries(details).map(([detail, value]) => value === "" ? detail : `<font color="#686868">${detail}:</font> ${value}`).join("&nbsp;|&ThickSpace;")}</font>`;
    if (sigMove.desc && sigMove.desc !== sigMove.shortDesc) {
      buf += `<details><summary><strong>In-Depth Description</strong></summary>${sigMove.desc}</details>`;
    }
  }
  return buf;
}
function generateSSBItemInfo(set, dex, baseDex) {
  let buf = ``;
  if (!Array.isArray(set.item)) {
    const baseItem = baseDex.items.get(set.item);
    const sigItem = dex.items.get(set.item);
    if (!baseItem.exists || (baseItem.desc || baseItem.shortDesc) !== (sigItem.desc || sigItem.shortDesc)) {
      buf += `<hr />`;
      buf += Chat.getDataItemHTML(sigItem);
      const details = {
        Gen: String(sigItem.gen)
      };
      if (dex.gen >= 4) {
        if (sigItem.fling) {
          details["Fling Base Power"] = String(sigItem.fling.basePower);
          if (sigItem.fling.status)
            details["Fling Effect"] = sigItem.fling.status;
          if (sigItem.fling.volatileStatus)
            details["Fling Effect"] = sigItem.fling.volatileStatus;
          if (sigItem.isBerry)
            details["Fling Effect"] = "Activates the Berry's effect on the target.";
          if (sigItem.id === "whiteherb")
            details["Fling Effect"] = "Restores the target's negative stat stages to 0.";
          if (sigItem.id === "mentalherb") {
            const flingEffect = "Removes the effects of Attract, Disable, Encore, Heal Block, Taunt, and Torment from the target.";
            details["Fling Effect"] = flingEffect;
          }
        } else {
          details["Fling"] = "This item cannot be used with Fling.";
        }
      }
      if (sigItem.naturalGift && dex.gen >= 3) {
        details["Natural Gift Type"] = sigItem.naturalGift.type;
        details["Natural Gift Base Power"] = String(sigItem.naturalGift.basePower);
      }
      if (sigItem.isNonstandard && sigItem.isNonstandard !== "Custom") {
        details[`Unobtainable in Gen ${dex.gen}`] = "";
      }
      buf += `<font size="1">${Object.entries(details).map(([detail, value]) => value === "" ? detail : `<font color="#686868">${detail}:</font> ${value}`).join("&nbsp;|&ThickSpace;")}</font>`;
    }
  }
  return buf;
}
function generateSSBAbilityInfo(set, dex, baseDex) {
  let buf = ``;
  if (!Array.isArray(set.ability) && !baseDex.abilities.get(set.ability).exists) {
    const sigAbil = Dex.deepClone(dex.abilities.get(set.ability));
    if (!sigAbil.desc && !sigAbil.shortDesc) {
      sigAbil.desc = `This ability doesn't have a description. Try contacting the SSB dev team.`;
    }
    buf += `<hr />`;
    buf += Chat.getDataAbilityHTML(sigAbil);
    const details = {
      Gen: String(sigAbil.gen) || "CAP"
    };
    buf += `<font size="1">${Object.entries(details).map(([detail, value]) => value === "" ? detail : `<font color="#686868">${detail}:</font> ${value}`).join("&nbsp;|&ThickSpace;")}</font>`;
    if (sigAbil.desc && sigAbil.shortDesc && sigAbil.desc !== sigAbil.shortDesc) {
      buf += `<details><summary><strong>In-Depth Description</strong></summary>${sigAbil.desc}</details>`;
    }
  }
  return buf;
}
function generateSSBPokemonInfo(species, dex, baseDex) {
  let buf = ``;
  const origSpecies = baseDex.species.get(species);
  const newSpecies = dex.species.get(species);
  if (newSpecies.types.join("/") !== origSpecies.types.join("/") || Object.values(newSpecies.abilities).join("/") !== Object.values(origSpecies.abilities).join("/") || Object.values(newSpecies.baseStats).join("/") !== Object.values(origSpecies.baseStats).join("/")) {
    buf += `<hr />`;
    buf += Chat.getDataPokemonHTML(newSpecies, dex.gen, "SSB");
    let weighthit = 20;
    if (newSpecies.weighthg >= 2e3) {
      weighthit = 120;
    } else if (newSpecies.weighthg >= 1e3) {
      weighthit = 100;
    } else if (newSpecies.weighthg >= 500) {
      weighthit = 80;
    } else if (newSpecies.weighthg >= 250) {
      weighthit = 60;
    } else if (newSpecies.weighthg >= 100) {
      weighthit = 40;
    }
    const details = {
      "Dex#": String(newSpecies.num),
      Gen: String(newSpecies.gen) || "CAP",
      Height: `${newSpecies.heightm} m`
    };
    details["Weight"] = `${newSpecies.weighthg / 10} kg <em>(${weighthit} BP)</em>`;
    if (newSpecies.color && dex.gen >= 5)
      details["Dex Colour"] = newSpecies.color;
    if (newSpecies.eggGroups && dex.gen >= 2)
      details["Egg Group(s)"] = newSpecies.eggGroups.join(", ");
    const evos = [];
    for (const evoName of newSpecies.evos) {
      const evo = dex.species.get(evoName);
      if (evo.gen <= dex.gen) {
        const condition = evo.evoCondition ? ` ${evo.evoCondition}` : ``;
        switch (evo.evoType) {
          case "levelExtra":
            evos.push(`${evo.name} (level-up${condition})`);
            break;
          case "levelFriendship":
            evos.push(`${evo.name} (level-up with high Friendship${condition})`);
            break;
          case "levelHold":
            evos.push(`${evo.name} (level-up holding ${evo.evoItem}${condition})`);
            break;
          case "useItem":
            evos.push(`${evo.name} (${evo.evoItem})`);
            break;
          case "levelMove":
            evos.push(`${evo.name} (level-up with ${evo.evoMove}${condition})`);
            break;
          case "other":
            evos.push(`${evo.name} (${evo.evoCondition})`);
            break;
          case "trade":
            evos.push(`${evo.name} (trade${evo.evoItem ? ` holding ${evo.evoItem}` : condition})`);
            break;
          default:
            evos.push(`${evo.name} (${evo.evoLevel}${condition})`);
        }
      }
    }
    if (!evos.length) {
      details[`<font color="#686868">Does Not Evolve</font>`] = "";
    } else {
      details["Evolution"] = evos.join(", ");
    }
    buf += `<font size="1">${Object.entries(details).map(([detail, value]) => value === "" ? detail : `<font color="#686868">${detail}:</font> ${value}`).join("&nbsp;|&ThickSpace;")}</font>`;
  }
  return buf;
}
function generateSSBInnateInfo(name, dex, baseDex) {
  let buf = ``;
  let effect = dex.conditions.get(name + "user");
  let longDesc = ``;
  const baseAbility = Dex.deepClone(baseDex.abilities.get("noability"));
  if (effect.exists && effect.innateName && (effect.desc || effect.shortDesc)) {
    baseAbility.name = effect.innateName;
    if (effect.desc)
      baseAbility.desc = effect.desc;
    if (effect.shortDesc)
      baseAbility.shortDesc = effect.shortDesc;
    buf += `<hr />Innate Ability:<br />${Chat.getDataAbilityHTML(baseAbility)}`;
    if (effect.desc && effect.shortDesc && effect.desc !== effect.shortDesc) {
      longDesc = effect.desc;
    }
  } else {
    effect = dex.conditions.get(name);
    if (effect.exists && effect.innateName && (effect.desc || effect.shortDesc)) {
      baseAbility.name = effect.innateName;
      if (effect.desc)
        baseAbility.desc = effect.desc;
      if (effect.shortDesc)
        baseAbility.shortDesc = effect.shortDesc;
      buf += `<hr />Innate Ability:<br />${Chat.getDataAbilityHTML(baseAbility)}`;
      if (effect.desc && effect.shortDesc && effect.desc !== effect.shortDesc) {
        longDesc = effect.desc;
      }
    }
  }
  if (buf) {
    const details = { Gen: "8" };
    buf += `<font size="1">${Object.entries(details).map(([detail, value]) => value === "" ? detail : `<font color="#686868">${detail}:</font> ${value}`).join("&nbsp;|&ThickSpace;")}</font>`;
  }
  if (longDesc) {
    buf += `<details><summary><strong>In-Depth Description</strong></summary>${longDesc}</details>`;
  }
  return buf;
}
function SSBSets(target) {
  const baseDex = Dex;
  const dex = Dex.forFormat("gen8superstaffbros4");
  if (!Object.keys(import_random_teams.ssbSets).map(toID).includes(toID(target))) {
    return { e: `Error: ${target.trim()} doesn't have a [Gen 8] Super Staff Bros 4 set.` };
  }
  let displayName = "";
  const names = [];
  for (const member in import_random_teams.ssbSets) {
    if (toID(member).startsWith(toID(target)))
      names.push(member);
    if (toID(member) === toID(target))
      displayName = member;
  }
  let buf = "";
  for (const name of names) {
    if (buf)
      buf += `<hr>`;
    const set = import_random_teams.ssbSets[name];
    const mutatedSpecies = dex.species.get(set.species);
    if (!set.skip) {
      buf += import_lib.Utils.html`<h1><psicon pokemon="${mutatedSpecies.id}">${displayName === "yuki" ? name : displayName}</h1>`;
    } else {
      buf += `<details><summary><psicon pokemon="${set.species}"><strong>${name.split("-").slice(1).join("-") + " forme"}</strong></summary>`;
    }
    buf += generateSSBSet(set, dex, baseDex);
    const item = dex.items.get(set.item);
    if (!set.skip || set.signatureMove !== import_random_teams.ssbSets[set.skip].signatureMove) {
      const sigMove = baseDex.moves.get(set.signatureMove).exists && !Array.isArray(set.item) && typeof item.zMove === "string" ? dex.moves.get(item.zMove) : dex.moves.get(set.signatureMove);
      buf += generateSSBMoveInfo(sigMove, dex);
      if (sigMove.id === "blackbird")
        buf += generateSSBMoveInfo(dex.moves.get("gaelstrom"), dex);
    }
    buf += generateSSBItemInfo(set, dex, baseDex);
    buf += generateSSBAbilityInfo(set, dex, baseDex);
    buf += generateSSBInnateInfo(name, dex, baseDex);
    buf += generateSSBPokemonInfo(set.species, dex, baseDex);
    if (!Array.isArray(set.item) && item.megaStone) {
      buf += generateSSBPokemonInfo(item.megaStone, dex, baseDex);
    } else if (["Aggron", "Rayquaza"].includes(set.species)) {
      buf += generateSSBPokemonInfo(`${set.species}-Mega`, dex, baseDex);
    } else if (set.species === "Charizard") {
      buf += generateSSBPokemonInfo("Charizard-Mega-X", dex, baseDex);
    }
    if (set.skip)
      buf += `</details>`;
  }
  return buf;
}
const commands = {
  randbats: "randombattles",
  randombattles(target, room, user) {
    if (!this.runBroadcast())
      return;
    const battle = room?.battle;
    if (battle) {
      if (battle.format.includes("nodmax"))
        return this.parse(`/randombattlenodmax ${target}`);
      if (battle.format.includes("doubles") || battle.gameType === "freeforall") {
        return this.parse(`/randomdoublesbattle ${target}`);
      }
    }
    const args = target.split(",");
    if (!args[0])
      return this.parse(`/help randombattles`);
    const { dex } = this.splitFormat(target, true);
    const isLetsGo = dex.currentMod === "gen7letsgo";
    const species = dex.species.get(args[0]);
    if (!species.exists) {
      return this.errorReply(`Error: Pok\xE9mon '${args[0].trim()}' does not exist.`);
    }
    const extraFormatModifier = isLetsGo ? "letsgo" : dex.currentMod === "gen8bdsp" ? "bdsp" : "";
    let formatName = dex.formats.get(`gen${dex.gen}${extraFormatModifier}randombattle`).name;
    const movesets = [];
    let setCount = 0;
    if (dex.gen === 1) {
      const rbyMoves = getRBYMoves(species);
      if (!rbyMoves) {
        return this.errorReply(`Error: ${species.name} has no Random Battle data in ${GEN_NAMES[toID(args[1])]}`);
      }
      movesets.push(`<span style="color:#999999;">Moves for ${species.name} in ${formatName}:</span>${rbyMoves}`);
      setCount = 1;
    } else if (isLetsGo) {
      formatName = `[Gen 7 Let's Go] Random Battle`;
      const lgpeMoves = getLetsGoMoves(species);
      if (!lgpeMoves) {
        return this.errorReply(`Error: ${species.name} has no Random Battle data in [Gen 7 Let's Go]`);
      }
      movesets.push(`<span style="color:#999999;">Moves for ${species.name} in ${formatName}:</span><br />${lgpeMoves}`);
      setCount = 1;
    } else {
      const setsToCheck = [species];
      if (dex.gen > 7)
        setsToCheck.push(dex.species.get(`${args[0]}gmax`));
      if (species.otherFormes)
        setsToCheck.push(...species.otherFormes.map((pkmn) => dex.species.get(pkmn)));
      if (dex.gen >= 9) {
        for (const pokemon of setsToCheck) {
          const sets = getSets(pokemon);
          if (!sets)
            continue;
          let buf2 = `<span style="color:#999999;">Moves for ${pokemon.name} in ${formatName}:</span><br/>`;
          for (const set of sets) {
            buf2 += `<details><summary>${set.role}</summary><b>Tera Type${Chat.plural(set.teraTypes)}</b>: ${set.teraTypes.join(", ")}<br/><b>Moves</b>: ${set.movepool.sort().map(formatMove).join(", ")}</details>`;
            setCount++;
          }
          movesets.push(buf2);
        }
      } else {
        for (const pokemon of setsToCheck) {
          const data = getData(pokemon, formatName);
          if (!data)
            continue;
          if (!data.moves || pokemon.isNonstandard === "Future")
            continue;
          const randomMoves = data.moves.slice();
          const m = randomMoves.sort().map(formatMove);
          movesets.push(
            `<details><summary><span style="color:#999999;">Moves for ${pokemon.name} in ${formatName}:<span style="color:#999999;"></summary>${m.join(`, `)}</details>`
          );
          setCount++;
        }
      }
    }
    if (!movesets.length) {
      return this.errorReply(`Error: ${species.name} has no Random Battle data in ${formatName}`);
    }
    let buf = movesets.join("<hr/>");
    if (setCount <= 2) {
      buf = buf.replace(/<details>/g, "<details open>");
    }
    this.sendReplyBox(buf);
  },
  randombattleshelp: [
    `/randombattles OR /randbats [pokemon], [gen] - Displays a Pok\xE9mon's Random Battle Moves. Defaults to Gen 9. If used in a battle, defaults to the gen of that battle.`
  ],
  randdubs: "randomdoublesbattle",
  randomdoublesbattle(target, room, user) {
    if (!this.runBroadcast())
      return;
    const args = target.split(",");
    if (!args[0])
      return this.parse(`/help randomdoublesbattle`);
    const { dex } = this.splitFormat(target, true);
    if (dex.gen < 4)
      return this.parse(`/help randomdoublesbattle`);
    const species = dex.species.get(args[0]);
    const formatName = dex.gen > 6 ? dex.formats.get(`gen${dex.gen}randomdoublesbattle`).name : dex.gen === 6 ? "[Gen 6] Random Doubles Battle" : dex.gen === 5 ? "[Gen 5] Random Doubles Battle" : "[Gen 4] Random Doubles Battle";
    if (!species.exists) {
      return this.errorReply(`Error: Pok\xE9mon '${args[0].trim()}' does not exist.`);
    }
    const setsToCheck = [species];
    if (dex.gen > 7)
      setsToCheck.push(dex.species.get(`${args[0]}gmax`));
    if (species.otherFormes)
      setsToCheck.push(...species.otherFormes.map((pkmn) => dex.species.get(pkmn)));
    const movesets = [];
    for (const pokemon of setsToCheck) {
      const data = getData(pokemon, formatName);
      if (!data)
        continue;
      if (!data.doublesMoves)
        continue;
      const moves = [...data.doublesMoves];
      const m = moves.sort().map(formatMove);
      movesets.push(`<span style="color:#999999;">Doubles moves for ${pokemon.name} in ${formatName}:</span><br />${m.join(`, `)}`);
    }
    this.sendReplyBox(movesets.join("<hr />"));
  },
  randomdoublesbattlehelp: [
    `/randomdoublesbattle OR /randdubs [pokemon], [gen] - Displays a Pok\xE9mon's Random Doubles Battle Moves. Supports Gens 4-8. Defaults to Gen 8. If used in a battle, defaults to that gen.`
  ],
  randsnodmax: "randombattlenodmax",
  randombattlenodmax(target, room, user) {
    if (!this.runBroadcast())
      return;
    if (!target)
      return this.parse(`/help randombattlenodmax`);
    const dex = Dex.forFormat("gen8randombattlenodmax");
    let species = dex.species.get(target);
    if (!species.exists) {
      throw new Chat.ErrorMessage(`Error: Pok\xE9mon '${target.trim()}' does not exist.`);
    }
    const data = getData(species, "gen8randombattle");
    let randomMoves = data ? data.noDynamaxMoves || data.moves : null;
    if (!randomMoves) {
      const gmaxSpecies = dex.species.get(`${target}gmax`);
      const gmaxData = getData(gmaxSpecies, "gen8randombattle");
      if (!gmaxSpecies.exists || !gmaxData || !gmaxData.moves) {
        return this.errorReply(`Error: No move data found for ${species.name} in [Gen 8] Random Battle (No Dmax).`);
      }
      species = gmaxSpecies;
      randomMoves = gmaxData.noDynamaxMoves || gmaxData.moves;
    }
    const m = [...randomMoves].sort().map(formatMove);
    this.sendReplyBox(`<span style="color:#999999;">Moves for ${species.name} in [Gen 8] Random Battle (No Dmax):</span><br />${m.join(`, `)}`);
  },
  randombattlenodmaxhelp: [
    `/randombattlenodmax OR /randsnodmax [pokemon] - Displays a Pok\xE9mon's Random Battle (No Dmax) moves.`
  ],
  bssfactory: "battlefactory",
  battlefactory(target, room, user, connection, cmd) {
    if (!this.runBroadcast())
      return;
    const isBSS = cmd === "bssfactory";
    if (isBSS) {
      const args = target.split(",");
      if (!args[0])
        return this.parse(`/help battlefactory`);
      const species = Dex.species.get(args[0]);
      if (!species.exists) {
        return this.errorReply(`Error: Pok\xE9mon '${args[0].trim()}' not found.`);
      }
      let mod = "gen8";
      if (args[1] && toID(args[1]) in Dex.dexes && Dex.dexes[toID(args[1])].gen >= 7)
        mod = toID(args[1]);
      const bssSets = battleFactorySets(species, null, mod, true);
      if (!bssSets)
        return this.parse(`/help battlefactory`);
      if (typeof bssSets !== "string") {
        return this.errorReply(`Error: ${bssSets.e}`);
      }
      return this.sendReplyBox(bssSets);
    } else {
      const args = target.split(",");
      if (!args[0])
        return this.parse(`/help battlefactory`);
      const species = Dex.species.get(args[0]);
      if (!species.exists) {
        return this.errorReply(`Error: Pok\xE9mon '${args[0].trim()}' not found.`);
      }
      let tier = "";
      if (args[1] && toID(args[1]) in TIERS) {
        tier = TIERS[toID(args[1])];
      } else {
        tier = "ou";
      }
      const mod = args[2] || "gen8";
      let bfSets;
      if (species.name === "Necrozma-Ultra") {
        bfSets = battleFactorySets(Dex.species.get("necrozma-dawnwings"), tier, mod);
        if (typeof bfSets === "string") {
          bfSets += battleFactorySets(Dex.species.get("necrozma-duskmane"), tier, mod);
        }
      } else if (species.name === "Zygarde-Complete") {
        bfSets = battleFactorySets(Dex.species.get("zygarde"), tier, mod);
        if (typeof bfSets === "string") {
          bfSets += battleFactorySets(Dex.species.get("zygarde-10"), tier, mod);
        }
      } else {
        bfSets = battleFactorySets(species, tier, mod);
      }
      if (!bfSets)
        return this.parse(`/help battlefactory`);
      if (typeof bfSets !== "string") {
        return this.errorReply(`Error: ${bfSets.e}`);
      }
      return this.sendReplyBox(bfSets);
    }
  },
  battlefactoryhelp: [
    `/battlefactory [pokemon], [tier], [gen] - Displays a Pok\xE9mon's Battle Factory sets. Supports Gens 6-7. Defaults to Gen 7. If no tier is provided, defaults to OU.`,
    `- Supported tiers: OU, Ubers, UU, RU, NU, PU, Monotype (Gen 7 only), LC (Gen 7 only)`,
    `/bssfactory [pokemon], [gen] - Displays a Pok\xE9mon's BSS Factory sets. Supports Gen 7. Defaults to Gen 7.`
  ],
  cap1v1(target, room, user) {
    if (!this.runBroadcast())
      return;
    if (!target)
      return this.parse(`/help cap1v1`);
    const species = Dex.species.get(target);
    if (!species.exists)
      return this.errorReply(`Error: Pok\xE9mon '${target.trim()}' not found.`);
    const cap1v1Set = CAP1v1Sets(species);
    if (!cap1v1Set)
      return this.parse(`/help cap1v1`);
    if (typeof cap1v1Set !== "string") {
      this.errorReply(`Error: ${cap1v1Set.e}`);
      if (cap1v1Set.parse)
        this.parse(cap1v1Set.parse);
      return;
    }
    return this.sendReplyBox(cap1v1Set);
  },
  cap1v1help: [
    `/cap1v1 [pokemon] - Displays a Pok\xE9mon's CAP 1v1 sets.`
  ],
  ssb(target, room, user) {
    if (!this.runBroadcast())
      return;
    if (!target)
      return this.parse(`/help ssb`);
    const set = SSBSets(target);
    if (typeof set !== "string") {
      throw new Chat.ErrorMessage(set.e);
    }
    return this.sendReplyBox(set);
  },
  ssbhelp: [
    `/ssb [staff member] - Displays a staff member's Super Staff Bros. set and custom features.`
  ],
  setodds: "randombattlesetprobabilities",
  randbatsodds: "randombattlesetprobabilities",
  randbatsprobabilities: "randombattlesetprobabilities",
  randombattlesetprobabilities(target, room, user) {
    const randbatsRoom = Rooms.get("randombattles");
    if (!(randbatsRoom && randbatsRoom.auth.has(user.id))) {
      this.checkCan("lock");
    }
    if (!target)
      return this.parse(`/help randombattlesetprobabilities`);
    this.runBroadcast();
    const args = target.split(",");
    if (args.length < 2)
      return this.parse(`/help randombattlesetprobabilities`);
    let format = Dex.formats.get("gen9randombattle");
    let formatOrSpecies = args.shift();
    const possibleFormat = Dex.formats.get(formatOrSpecies);
    if (possibleFormat.exists) {
      if (!possibleFormat.team) {
        throw new Chat.ErrorMessage(`${possibleFormat.name} does not have randomly-generated teams.`);
      }
      format = possibleFormat;
      formatOrSpecies = args.shift();
    }
    const dex = Dex.forFormat(format);
    const species = dex.species.get(formatOrSpecies);
    if (!species.exists) {
      throw new Chat.ErrorMessage(`Species ${species.name} does not exist in the specified format.`);
    }
    let setExists;
    if (dex.gen >= 9) {
      setExists = !!getSets(species);
    } else {
      const data = getData(species, format);
      if (!data) {
        setExists = false;
      } else if (format.gameType === "doubles" || format.gameType === "freeforall") {
        setExists = !!data.doublesMoves;
      } else {
        setExists = !!data.moves;
      }
    }
    if (!setExists) {
      throw new Chat.ErrorMessage(`${species.name} does not have random battle moves in ${format.name}.`);
    }
    const criteria = {
      moves: { mustHave: [], mustNotHave: [] },
      item: { mustNotHave: [] },
      ability: { mustNotHave: [] },
      nature: { mustNotHave: [] },
      teraType: { mustNotHave: [] }
    };
    if (args.length < 1) {
      this.errorReply(`You must specify at least one condition.`);
      return this.parse(`/help randombattlesetprobabilities`);
    }
    for (const arg of args) {
      let [key, value] = arg.split("=");
      key = toID(key);
      if (!value || !key) {
        this.errorReply(`Invalid condition format: ${arg}`);
        return this.parse(`/help randombattlesetprobabilities`);
      }
      switch (key) {
        case "moves":
          for (const rawMove of value.split("&")) {
            const move = dex.moves.get(rawMove);
            if (!move.exists) {
              throw new Chat.ErrorMessage(`"${rawMove}" is not a move in the specified format.`);
            }
            const isNegation = rawMove.trim().startsWith("!");
            if (isNegation) {
              criteria.moves.mustNotHave.push(move);
            } else {
              criteria.moves.mustHave.push(move);
            }
          }
          break;
        case "item":
          const item = dex.items.get(value);
          if (!item.exists) {
            throw new Chat.ErrorMessage(`"${value}" is not an item in the specified format.`);
          }
          const itemNegation = value.trim().startsWith("!");
          if (itemNegation) {
            criteria.item.mustNotHave.push(item);
          } else {
            if (criteria.item.mustHave) {
              throw new Chat.ErrorMessage(`Impossible situation: two items (${criteria.item.mustHave.name} and ${item.name}) are required.`);
            }
            criteria.item.mustHave = item;
          }
          break;
        case "ability":
          const ability = dex.abilities.get(value);
          if (!ability.exists) {
            throw new Chat.ErrorMessage(`"${value}" is not an ability in the specified format.`);
          }
          const abilityNegation = value.trim().startsWith("!");
          if (abilityNegation) {
            criteria.ability.mustNotHave.push(ability);
          } else {
            if (criteria.ability.mustHave) {
              throw new Chat.ErrorMessage(`Impossible situation: two abilities (${criteria.ability.mustHave.name} and ${ability.name}) are required.`);
            }
            criteria.ability.mustHave = ability;
          }
          break;
        case "nature":
          const nature = dex.natures.get(value);
          if (!nature.exists) {
            throw new Chat.ErrorMessage(`"${value}" is not a nature in the specified format.`);
          }
          const natureNegation = value.trim().startsWith("!");
          if (natureNegation) {
            criteria.nature.mustNotHave.push(nature);
          } else {
            if (criteria.nature.mustHave) {
              throw new Chat.ErrorMessage(`Impossible situation: two natures (${criteria.nature.mustHave.name} and ${nature.name}) are required.`);
            }
            criteria.nature.mustHave = nature;
          }
          break;
        case "tera":
        case "teratype":
          if (dex.gen < 9)
            throw new Chat.ErrorMessage("Tera Types do not exist in the specified format.");
          const type = dex.types.get(value);
          if (!type.exists) {
            throw new Chat.ErrorMessage(`"${value}" is not a type in the specified format.`);
          }
          const typeNegation = value.trim().startsWith("!");
          if (typeNegation) {
            criteria.teraType.mustNotHave.push(type);
          } else {
            if (criteria.teraType.mustHave) {
              throw new Chat.ErrorMessage(`Impossible situation: two Tera Types (${criteria.teraType.mustHave.name} and ${type.name}) are required.`);
            }
            criteria.teraType.mustHave = type;
          }
          break;
        default:
          throw new Chat.ErrorMessage(`Invalid criterion: ${key}`);
      }
    }
    const results = setProbability(species, format, criteria);
    const percentage = Math.round(results.matches / results.rounds * 100);
    return this.sendReplyBox(
      import_lib.Utils.html`Generated ${results.rounds} sets for <strong>${species.name}</strong> in ${format.name}:<br />` + `Approximately <strong>${percentage}%</strong> (${results.matches} sets) ${getHTMLCriteriaDescription(criteria)}.`
    );
  },
  randombattlesetprobabilitieshelp() {
    return this.sendReplyBox(
      `<code>/randombattlesetprobabilities [optional format], [species], [conditions]</code>: Gives the probability of a set matching the conditions appearing for the given species.<br /><code>[conditions]</code> is a comma-separated list of conditions of the form <code>[component]=[matching value]</code>, where <code>[component]</code> can be any of the following: <ul><li><code>moves</code>: matches all generated sets that contain every move specified. <code>[matching value]</code> should be a list of moves separated with <code>&amp;</code>.<li><code>item</code>: matches all generated sets that have the specified item. <code>[matching value]</code> should be an item name.<li><code>ability</code>: matches all generated sets with the specified ability. <code>[matching value]</code> should be an ability name.<li><code>nature</code>: matches all generated sets with the specified nature. <code>[matching value]</code> should be a nature name.<li><code>tera</code>: matches all generated sets with the specified Tera Type. <code>[matching value]</code> should be a type. Gen 9 only.</ul>The given probability is for a set that matches EVERY provided condition. Conditions can be negated by prefixing the <code>[matching value]</code> with <code>!</code>.<br />Requires: % @ # & (globally or in the Random Battles room)`
    );
  },
  genteam: "generateteam",
  generateteam(target, room, user) {
    if (!Rooms.get("randombattles")?.auth.has(user.id))
      this.checkCan("lock");
    this.runBroadcast(true);
    if (!target)
      return this.parse("/help generateteam");
    const format = Dex.formats.get(target);
    if (!format.exists)
      throw new Chat.ErrorMessage(`"${target}" is not a recognized format.`);
    if (!format.team)
      throw new Chat.ErrorMessage(`"${format.name}" requires you to bring your own team.`);
    const team = Teams.getGenerator(format).getTeam();
    const dex = Dex.forFormat(format);
    const teamHTML = team.map((set) => {
      set.moves = set.moves.map((m) => dex.moves.get(m).name);
      set.item = dex.items.get(set.item).name;
      return `<details><summary>${set.name}</summary>${import_lib.Utils.escapeHTML(Teams.exportSet(set))}<br /></details>`;
    }).join("");
    return this.sendReplyBox(`<strong>Team for ${format.name}</strong>:` + teamHTML);
  },
  generateteamhelp: [`/genteam [format] - Generates a team for the given format. Requires: % @ & or Random Battles room auth`]
};
//# sourceMappingURL=index.js.map
