text: /**
   * This code is an implementation of Alea algorithm; (C) 2010 Johannes Baagøe.
   * Alea is licensed according to the http://en.wikipedia.org/wiki/MIT_License.
   */
  
  const FRAC = 2.3283064365386963e-10; /* 2^-32 */
  
  class RNG {
    constructor() {
      this._seed = 0;
      this._s0 = 0;
      this._s1 = 0;
      this._s2 = 0;
      this._c = 0;
    }
  
    getSeed() {
      return this._seed;
    }
  
    /**
     * Seed the number generator
     */
    setSeed(seed) {
      seed = seed < 1 ? 1 / seed : seed;
  
      this._seed = seed;
      this._s0 = (seed >>> 0) * FRAC;
  
      seed = (seed * 69069 + 1) >>> 0;
      this._s1 = seed * FRAC;
  
      seed = (seed * 69069 + 1) >>> 0;
      this._s2 = seed * FRAC;
  
      this._c = 1;
      return this;
    }
  
    /**
     * @returns Pseudorandom value [0,1), uniformly distributed
     */
    getUniform() {
      let t = 2091639 * this._s0 + this._c * FRAC;
      this._s0 = this._s1;
      this._s1 = this._s2;
      this._c = t | 0;
      this._s2 = t - this._c;
      return this._s2;
    }
  
    /**
     * @param lowerBound The lower end of the range to return a value from, inclusive
     * @param upperBound The upper end of the range to return a value from, inclusive
     * @returns Pseudorandom value [lowerBound, upperBound], using ROT.RNG.getUniform() to distribute the value
     */
    getUniformInt(lowerBound, upperBound) {
      let max = Math.max(lowerBound, upperBound);
      let min = Math.min(lowerBound, upperBound);
      return Math.floor(this.getUniform() * (max - min + 1)) + min;
    }
  
    /**
     * @param mean Mean value
     * @param stddev Standard deviation. ~95% of the absolute values will be lower than 2*stddev.
     * @returns A normally distributed pseudorandom value
     */
    getNormal(mean = 0, stddev = 1) {
      let u, v, r;
      do {
        u = 2 * this.getUniform() - 1;
        v = 2 * this.getUniform() - 1;
        r = u * u + v * v;
      } while (r > 1 || r == 0);
  
      let gauss = u * Math.sqrt((-2 * Math.log(r)) / r);
      return mean + gauss * stddev;
    }
  
    /**
     * @returns Pseudorandom value [1,100] inclusive, uniformly distributed
     */
    getPercentage() {
      return 1 + Math.floor(this.getUniform() * 100);
    }
  
    /**
     * @returns Randomly picked item, null when length=0
     */
    getItem(array) {
      if (!array.length) {
        return null;
      }
      return array[Math.floor(this.getUniform() * array.length)];
    }
  
    /**
     * @returns New array with randomized items
     */
    shuffle(array) {
      let result = [];
      let clone = array.slice();
      while (clone.length) {
        let index = clone.indexOf(this.getItem(clone));
        result.push(clone.splice(index, 1)[0]);
      }
      return result;
    }
  
    /**
     * @param data key=whatever, value=weight (relative probability)
     * @returns whatever
     */
    getWeightedValue(data) {
      let total = 0;
  
      for (let id in data) {
        total += data[id];
      }
      let random = this.getUniform() * total;
  
      let id,
        part = 0;
      for (id in data) {
        part += data[id];
        if (random < part) {
          return id;
        }
      }
  
      // If by some floating-point annoyance we have
      // random >= total, just return the last id.
      return id;
    }
  
    /**
     * Get RNG state. Useful for storing the state and re-setting it via setState.
     * @returns Internal state
     */
    getState() {
      return [this._s0, this._s1, this._s2, this._c];
    }
  
    /**
     * Set a previously retrieved state.
     */
    setState(state) {
      this._s0 = state[0];
      this._s1 = state[1];
      this._s2 = state[2];
      this._c = state[3];
      return this;
    }
  
    /**
     * Returns a cloned RNG
     */
    clone() {
      let clone = new RNG();
      return clone.setState(this.getState());
    }
  }
  
  export default new RNG().setSeed(Date.now());
  