diff --git a/models/game.js b/models/game.js index 94f1350..dfb4ca5 100755 --- a/models/game.js +++ b/models/game.js @@ -17,13 +17,22 @@ import { Player } from "./player.js"; /** @typedef {import("./item.js").ItemBlueprint} ItemBlueprint */ export class Game { - _counter = 1_000_000; + #counter = 1_000_000; + get counter() { + return this.#counter; + } /** @type {Map} List of all item blueprints in the game */ - _itemBlueprints = new Map(); + #itemBlueprints = new Map(); + get itemBlueprints() { + return this.#itemBlueprints; + } /** @type {Map} The list of locations in the game */ - _locations = new Map(); + #locations = new Map(); + get locations() { + return this.#locations; + } /** * The characters in the game. @@ -31,34 +40,40 @@ export class Game { * @protected * @type {Map} */ - _characters = new Map(); + #characters = new Map(); + get characters() { + return this.#characters; + } /* * @protected * @type {Map} Map of users in the game username->Player */ - _players = new Map(); + #players = new Map(); + get players() { + return this.#players; + } /** @protected @type {Xorshift32} */ - _random; + #random; /** @type {Xorshift32} */ get random() { - return this._random; + return this.#random; } /** @param {number} rngSeed Seed number used for randomization */ - constructor() { - this.rngSeed = Date.now(); + constructor(rngSeed) { + this.seedRNG(rngSeed); } - set rngSeed(rngSeed) { - this._random = new Xorshift32(rngSeed); + seedRNG(rngSeed) { + this.#random = new Xorshift32(rngSeed); } getPlayerByUsername(username) { console.log("GETTING PLAYER: `%s`", username); - return this._players.get(username); + return this.#players.get(username); } /** @@ -71,7 +86,7 @@ export class Game { * @returns {Player|null} Returns the player if username wasn't already taken, or null otherwise. */ createPlayer(username, passwordHash = undefined, salt = undefined) { - if (this._players.has(username)) { + if (this.#players.has(username)) { return false; } @@ -81,7 +96,7 @@ export class Game { typeof salt === "string" && salt.length > 0 ? salt : miniUid(), ); - this._players.set(username, player); + this.#players.set(username, player); return player; } @@ -99,7 +114,7 @@ export class Game { throw new Error("Invalid blueprintId!"); } - const existing = this._itemBlueprints.get(blueprintId); + const existing = this.#itemBlueprints.get(blueprintId); if (existing) { console.warn("we tried to create the same item blueprint more than once", blueprintId, attributes); @@ -110,7 +125,7 @@ export class Game { const result = new ItemBlueprint(attributes); - this._itemBlueprints.set(blueprintId, result); + this.#itemBlueprints.set(blueprintId, result); return result; } @@ -123,6 +138,6 @@ export class Game { if (!isIdSane(blueprintId)) { throw new Error(`blueprintId >>${blueprintId}<< is not a valid id`); } - return this._itemBlueprints.get(blueprintId); + return this.#itemBlueprints.get(blueprintId); } } diff --git a/models/globals.js b/models/globals.js index 32961e8..c6a3790 100755 --- a/models/globals.js +++ b/models/globals.js @@ -1,4 +1,5 @@ +import { Config } from "../config.js"; import { Game } from "./game.js"; /** @constant @readonly @type {Game} Global instance of Game */ -export const gGame = new Game(); +export const gGame = new Game(Config.rngSeed); diff --git a/models/location.js b/models/location.js index 6ee982d..b911628 100755 --- a/models/location.js +++ b/models/location.js @@ -9,28 +9,28 @@ * or magical portals to distant locations. */ export class Location { - /** @protected @type {string} */ - _id; + /** @type {string} */ + #id; get id() { - return this._id; + return this.#id; } - /** @protected @type {string} */ - _name; + /** @type {string} */ + #name; get name() { - return this._name; + return this.#name; } - /** @protected @type {string} */ - _description; + /** @type {string} */ + #description; get description() { - return this._description; + return this.#description; } - /** @protected @type {Map} */ - _portals = new Map(); + /** @type {Map} */ + #portals = new Map(); get portals() { - return this._portals; + return this.#portals; } /** @@ -39,8 +39,8 @@ export class Location { * @param {string} description */ constructor(id, name, description) { - this._id = id; - this._name = name; - this._description = description; + this.#id = id; + this.#name = name; + this.#description = description; } } diff --git a/resources/js_recipes/recipe - xorshift32.js b/resources/js_recipes/recipe - xorshift32.js index f4b4f38..ac44a7c 100755 --- a/resources/js_recipes/recipe - xorshift32.js +++ b/resources/js_recipes/recipe - xorshift32.js @@ -1,4 +1,4 @@ - const [XSgetSeed, XSgetNext, XSrand] = (() => { +const [XSgetSeed, XSgetNext, XSrand] = (() => { const m = 2 ** 32; const XSgetSeed = () => Math.floor(Math.random() * (m - 1)) + 1; const s = Uint32Array.of(XSgetSeed()); diff --git a/seeders/characerSeeder.js b/seeders/characerSeeder.js index 7320952..346b89c 100755 --- a/seeders/characerSeeder.js +++ b/seeders/characerSeeder.js @@ -81,7 +81,7 @@ export class CharacterSeeder { c.name = gGame.random.oneOf("sir ", "madam ", "mister ", "miss ", "", "", "") + // prefix "random " + // name - gGame.random.get().toString(); // suffix + gGame.random.next().toString(); // suffix c.awareness = roll.d6() + 2; c.grit = roll.d6() + 2; diff --git a/utils/random.js b/utils/random.js index 8b67fc0..29fa0fe 100755 --- a/utils/random.js +++ b/utils/random.js @@ -3,16 +3,16 @@ * using the xorshift32 method. */ export class Xorshift32 { - /* @type {number} */ - initialSeed; - /** * State holds a single uint32. * It's useful for staying within modulo 2**32. * * @type {Uint32Array} */ - state; + #state; + get state() { + return this.#state; + } /** @param {number} seed */ constructor(seed) { @@ -21,41 +21,44 @@ export class Xorshift32 { seed = Math.floor(Math.random() * (maxInt32 - 1)) + 1; } seed = seed | 0; - this.state = Uint32Array.of(seed); + this.#state = Uint32Array.of(seed); } /** @protected Shuffle the internal state. */ shuffle() { - this.state[0] ^= this.state[0] << 13; - this.state[0] ^= this.state[0] >>> 17; - this.state[0] ^= this.state[0] << 5; + this.#state[0] ^= this.#state[0] << 13; + this.#state[0] ^= this.#state[0] >>> 17; + this.#state[0] ^= this.#state[0] << 5; // We could also do something like this: // x ^= x << 13; - // x ^= x >> 17; + // x ^= x >>> 17; // x ^= x << 5; // return x; - // But we'd have to xor the x with 2^32 after every op, - // we get that "for free" by using the uint32array + // And even though bitwise operations coerce numbers + // into int32 (except >>> which converts into uint32). + // But using Uint32Array ensures the number stays + // uint32 all the way through, thus avoiding the pitfalls + // of potentially dipping into negative number territory } /** * Get a random number and shuffle the internal state. * @returns {number} a pseudo-random positive integer. */ - get() { + next() { this.shuffle(); - return this.state[0]; + return this.#state[0]; } /** @param {number} x @returns {number} a positive integer lower than x */ lowerThan(x) { - return this.get() % x; + return this.next() % x; } /** @param {number} x @returns {number} a positive integer lower than or equal to x */ lowerThanOrEqual(x) { - return this.get() % (x + 1); + return this.next() % (x + 1); } /**