"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 prng_exports = {}; __export(prng_exports, { PRNG: () => PRNG }); module.exports = __toCommonJS(prng_exports); /** * PRNG * Pokemon Showdown - http://pokemonshowdown.com/ * * This simulates the on-cartridge PRNG used in the real games. * * In addition to potentially allowing us to read replays from in-game, * this also makes it possible to record an "input log" (a seed + * initial teams + move/switch decisions) and "replay" a simulation to * get the same result. * * @license MIT license */ class PRNG { /** Creates a new source of randomness for the given seed. */ constructor(seed = null) { if (!seed) seed = PRNG.generateSeed(); this.initialSeed = seed.slice(); this.seed = seed.slice(); } /** * Getter to the initial seed. * * This should be considered a hack and is only here for backwards compatibility. */ get startingSeed() { return this.initialSeed; } /** * Creates a clone of the current PRNG. * * The new PRNG will have its initial seed set to the seed of the current instance. */ clone() { return new PRNG(this.seed); } /** * Retrieves the next random number in the sequence. * This function has three different results, depending on arguments: * - random() returns a real number in [0, 1), just like Math.random() * - random(n) returns an integer in [0, n) * - random(m, n) returns an integer in [m, n) * m and n are converted to integers via Math.floor. If the result is NaN, they are ignored. */ next(from, to) { this.seed = this.nextFrame(this.seed); let result = (this.seed[0] << 16 >>> 0) + this.seed[1]; if (from) from = Math.floor(from); if (to) to = Math.floor(to); if (from === void 0) { result = result / 4294967296; } else if (!to) { result = Math.floor(result * from / 4294967296); } else { result = Math.floor(result * (to - from) / 4294967296) + from; } return result; } /** * Flip a coin (two-sided die), returning true or false. * * This function returns true with probability `P`, where `P = numerator * / denominator`. This function returns false with probability `1 - P`. * * The numerator must be a non-negative integer (`>= 0`). * * The denominator must be a positive integer (`> 0`). */ randomChance(numerator, denominator) { return this.next(denominator) < numerator; } /** * Return a random item from the given array. * * This function chooses items in the array with equal probability. * * If there are duplicate items in the array, each duplicate is * considered separately. For example, sample(['x', 'x', 'y']) returns * 'x' 67% of the time and 'y' 33% of the time. * * The array must contain at least one item. * * The array must not be sparse. */ sample(items) { if (items.length === 0) { throw new RangeError(`Cannot sample an empty array`); } const index = this.next(items.length); const item = items[index]; if (item === void 0 && !Object.prototype.hasOwnProperty.call(items, index)) { throw new RangeError(`Cannot sample a sparse array`); } return item; } /** * A Fisher-Yates shuffle. This is how the game resolves speed ties. * * At least according to V4 in * https://github.com/smogon/pokemon-showdown/issues/1157#issuecomment-214454873 */ shuffle(items, start = 0, end = items.length) { while (start < end - 1) { const nextIndex = this.next(start, end); if (start !== nextIndex) { [items[start], items[nextIndex]] = [items[nextIndex], items[start]]; } start++; } } /** * Calculates `a * b + c` (with 64-bit 2's complement integers) * * If you've done long multiplication, this is the same thing. */ multiplyAdd(a, b, c) { const out = [0, 0, 0, 0]; let carry = 0; for (let outIndex = 3; outIndex >= 0; outIndex--) { for (let bIndex = outIndex; bIndex < 4; bIndex++) { const aIndex = 3 - (bIndex - outIndex); carry += a[aIndex] * b[bIndex]; } carry += c[outIndex]; out[outIndex] = carry & 65535; carry >>>= 16; } return out; } /** * The RNG is a Linear Congruential Generator (LCG) in the form: `x_{n + 1} = (a x_n + c) % m` * * Where: `x_0` is the seed, `x_n` is the random number after n iterations, * * ```` * a = 0x5D588B656C078965 * c = 0x00269EC3 * m = 2^64 * ```` */ nextFrame(seed, framesToAdvance = 1) { const a = [23896, 35685, 27655, 35173]; const c = [0, 0, 38, 40643]; for (let i = 0; i < framesToAdvance; i++) { seed = this.multiplyAdd(seed, a, c); } return seed; } static generateSeed() { return [ Math.floor(Math.random() * 65536), Math.floor(Math.random() * 65536), Math.floor(Math.random() * 65536), Math.floor(Math.random() * 65536) ]; } } //# sourceMappingURL=prng.js.map