卫戍协议:盟约 web remake — initial import

Online co-op browser remake of Arknights' Stronghold Protocol: Alliance
(client-simulated combat, official waves/bonds/items/strategies, 3D board,
facing wheel, operator loadout, official emotes, deployment scripts).
This commit is contained in:
sganggs committed 2026-09-29 16:21:31 +08:00
commit 01a44cd288
408 files changed
+308986

No files matched your search

+56
View File
@@ -0,0 +1,56 @@
// server/sim/rng.js — seeded PRNG (mulberry32) + helpers. The ONLY source of randomness in the sim.
/**
* Create a deterministic PRNG. Returns a function producing floats in [0, 1) with helper methods.
* @param {number} seed uint32 (any number is coerced)
*/
export function createRng(seed = 1) {
let s = (Number(seed) >>> 0) || 0x9e3779b9;
const next = () => {
s = (s + 0x6d2b79f5) >>> 0;
let t = s;
t = Math.imul(t ^ (t >>> 15), t | 1);
t ^= t + Math.imul(t ^ (t >>> 7), t | 61);
return ((t ^ (t >>> 14)) >>> 0) / 4294967296;
};
const rng = () => next();
/** integer in [0, n) */
rng.int = (n) => Math.floor(next() * Math.max(0, n));
/** float in [a, b) */
rng.range = (a, b) => a + next() * (b - a);
/** true with probability p */
rng.chance = (p) => next() < p;
/** random element (undefined for empty) */
rng.pick = (arr) => (arr && arr.length ? arr[Math.floor(next() * arr.length)] : undefined);
/** in-place Fisher–Yates shuffle, returns arr */
rng.shuffle = (arr) => {
for (let i = arr.length - 1; i > 0; i--) {
const j = Math.floor(next() * (i + 1));
const tmp = arr[i]; arr[i] = arr[j]; arr[j] = tmp;
}
return arr;
};
/** weighted pick: items with weightFn(item) */
rng.weighted = (arr, weightFn) => {
let total = 0;
for (const x of arr) total += Math.max(0, weightFn(x));
if (total <= 0) return undefined;
let r = next() * total;
for (const x of arr) { r -= Math.max(0, weightFn(x)); if (r < 0) return x; }
return arr[arr.length - 1];
};
/** current internal state (for debugging / hashing) */
rng.state = () => s;
return rng;
}
/** Derive a child seed deterministically (e.g. per field). */
export function deriveSeed(seed, salt) {
let h = (Number(seed) >>> 0) ^ 0x85ebca6b;
const str = String(salt);
for (let i = 0; i < str.length; i++) {
h = Math.imul(h ^ str.charCodeAt(i), 0x9e3779b1);
h ^= h >>> 13;
}
return h >>> 0;
}