refactors

This commit is contained in:
Kim Ravn Hansen
2025-10-21 23:55:52 +02:00
parent bebd4ce944
commit 9de5140e47
6 changed files with 69 additions and 50 deletions

View File

@@ -17,13 +17,22 @@ import { Player } from "./player.js";
/** @typedef {import("./item.js").ItemBlueprint} ItemBlueprint */ /** @typedef {import("./item.js").ItemBlueprint} ItemBlueprint */
export class Game { export class Game {
_counter = 1_000_000; #counter = 1_000_000;
get counter() {
return this.#counter;
}
/** @type {Map<string,ItemBlueprint>} List of all item blueprints in the game */ /** @type {Map<string,ItemBlueprint>} List of all item blueprints in the game */
_itemBlueprints = new Map(); #itemBlueprints = new Map();
get itemBlueprints() {
return this.#itemBlueprints;
}
/** @type {Map<string,Location>} The list of locations in the game */ /** @type {Map<string,Location>} The list of locations in the game */
_locations = new Map(); #locations = new Map();
get locations() {
return this.#locations;
}
/** /**
* The characters in the game. * The characters in the game.
@@ -31,34 +40,40 @@ export class Game {
* @protected * @protected
* @type {Map<string,Character>} * @type {Map<string,Character>}
*/ */
_characters = new Map(); #characters = new Map();
get characters() {
return this.#characters;
}
/* /*
* @protected * @protected
* @type {Map<string,Player>} Map of users in the game username->Player * @type {Map<string,Player>} Map of users in the game username->Player
*/ */
_players = new Map(); #players = new Map();
get players() {
return this.#players;
}
/** @protected @type {Xorshift32} */ /** @protected @type {Xorshift32} */
_random; #random;
/** @type {Xorshift32} */ /** @type {Xorshift32} */
get random() { get random() {
return this._random; return this.#random;
} }
/** @param {number} rngSeed Seed number used for randomization */ /** @param {number} rngSeed Seed number used for randomization */
constructor() { constructor(rngSeed) {
this.rngSeed = Date.now(); this.seedRNG(rngSeed);
} }
set rngSeed(rngSeed) { seedRNG(rngSeed) {
this._random = new Xorshift32(rngSeed); this.#random = new Xorshift32(rngSeed);
} }
getPlayerByUsername(username) { getPlayerByUsername(username) {
console.log("GETTING PLAYER: `%s`", 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. * @returns {Player|null} Returns the player if username wasn't already taken, or null otherwise.
*/ */
createPlayer(username, passwordHash = undefined, salt = undefined) { createPlayer(username, passwordHash = undefined, salt = undefined) {
if (this._players.has(username)) { if (this.#players.has(username)) {
return false; return false;
} }
@@ -81,7 +96,7 @@ export class Game {
typeof salt === "string" && salt.length > 0 ? salt : miniUid(), typeof salt === "string" && salt.length > 0 ? salt : miniUid(),
); );
this._players.set(username, player); this.#players.set(username, player);
return player; return player;
} }
@@ -99,7 +114,7 @@ export class Game {
throw new Error("Invalid blueprintId!"); throw new Error("Invalid blueprintId!");
} }
const existing = this._itemBlueprints.get(blueprintId); const existing = this.#itemBlueprints.get(blueprintId);
if (existing) { if (existing) {
console.warn("we tried to create the same item blueprint more than once", blueprintId, attributes); 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); const result = new ItemBlueprint(attributes);
this._itemBlueprints.set(blueprintId, result); this.#itemBlueprints.set(blueprintId, result);
return result; return result;
} }
@@ -123,6 +138,6 @@ export class Game {
if (!isIdSane(blueprintId)) { if (!isIdSane(blueprintId)) {
throw new Error(`blueprintId >>${blueprintId}<< is not a valid id`); throw new Error(`blueprintId >>${blueprintId}<< is not a valid id`);
} }
return this._itemBlueprints.get(blueprintId); return this.#itemBlueprints.get(blueprintId);
} }
} }

View File

@@ -1,4 +1,5 @@
import { Config } from "../config.js";
import { Game } from "./game.js"; import { Game } from "./game.js";
/** @constant @readonly @type {Game} Global instance of Game */ /** @constant @readonly @type {Game} Global instance of Game */
export const gGame = new Game(); export const gGame = new Game(Config.rngSeed);

View File

@@ -9,28 +9,28 @@
* or magical portals to distant locations. * or magical portals to distant locations.
*/ */
export class Location { export class Location {
/** @protected @type {string} */ /** @type {string} */
_id; #id;
get id() { get id() {
return this._id; return this.#id;
} }
/** @protected @type {string} */ /** @type {string} */
_name; #name;
get name() { get name() {
return this._name; return this.#name;
} }
/** @protected @type {string} */ /** @type {string} */
_description; #description;
get description() { get description() {
return this._description; return this.#description;
} }
/** @protected @type {Map<string,Portal>} */ /** @type {Map<string,Portal>} */
_portals = new Map(); #portals = new Map();
get portals() { get portals() {
return this._portals; return this.#portals;
} }
/** /**
@@ -39,8 +39,8 @@ export class Location {
* @param {string} description * @param {string} description
*/ */
constructor(id, name, description) { constructor(id, name, description) {
this._id = id; this.#id = id;
this._name = name; this.#name = name;
this._description = description; this.#description = description;
} }
} }

View File

@@ -81,7 +81,7 @@ export class CharacterSeeder {
c.name = c.name =
gGame.random.oneOf("sir ", "madam ", "mister ", "miss ", "", "", "") + // prefix gGame.random.oneOf("sir ", "madam ", "mister ", "miss ", "", "", "") + // prefix
"random " + // name "random " + // name
gGame.random.get().toString(); // suffix gGame.random.next().toString(); // suffix
c.awareness = roll.d6() + 2; c.awareness = roll.d6() + 2;
c.grit = roll.d6() + 2; c.grit = roll.d6() + 2;

View File

@@ -3,16 +3,16 @@
* using the xorshift32 method. * using the xorshift32 method.
*/ */
export class Xorshift32 { export class Xorshift32 {
/* @type {number} */
initialSeed;
/** /**
* State holds a single uint32. * State holds a single uint32.
* It's useful for staying within modulo 2**32. * It's useful for staying within modulo 2**32.
* *
* @type {Uint32Array} * @type {Uint32Array}
*/ */
state; #state;
get state() {
return this.#state;
}
/** @param {number} seed */ /** @param {number} seed */
constructor(seed) { constructor(seed) {
@@ -21,41 +21,44 @@ export class Xorshift32 {
seed = Math.floor(Math.random() * (maxInt32 - 1)) + 1; seed = Math.floor(Math.random() * (maxInt32 - 1)) + 1;
} }
seed = seed | 0; seed = seed | 0;
this.state = Uint32Array.of(seed); this.#state = Uint32Array.of(seed);
} }
/** @protected Shuffle the internal state. */ /** @protected Shuffle the internal state. */
shuffle() { shuffle() {
this.state[0] ^= this.state[0] << 13; this.#state[0] ^= this.#state[0] << 13;
this.state[0] ^= this.state[0] >>> 17; this.#state[0] ^= this.#state[0] >>> 17;
this.state[0] ^= this.state[0] << 5; this.#state[0] ^= this.#state[0] << 5;
// We could also do something like this: // We could also do something like this:
// x ^= x << 13; // x ^= x << 13;
// x ^= x >> 17; // x ^= x >>> 17;
// x ^= x << 5; // x ^= x << 5;
// return x; // return x;
// But we'd have to xor the x with 2^32 after every op, // And even though bitwise operations coerce numbers
// we get that "for free" by using the uint32array // 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. * Get a random number and shuffle the internal state.
* @returns {number} a pseudo-random positive integer. * @returns {number} a pseudo-random positive integer.
*/ */
get() { next() {
this.shuffle(); this.shuffle();
return this.state[0]; return this.#state[0];
} }
/** @param {number} x @returns {number} a positive integer lower than x */ /** @param {number} x @returns {number} a positive integer lower than x */
lowerThan(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 */ /** @param {number} x @returns {number} a positive integer lower than or equal to x */
lowerThanOrEqual(x) { lowerThanOrEqual(x) {
return this.get() % (x + 1); return this.next() % (x + 1);
} }
/** /**