boardgame-core/src/utils/rng.ts

85 lines
2.1 KiB
TypeScript
Raw Normal View History

2026-04-01 13:36:16 +08:00
export interface RNG {
/** 设置随机数种子 */
(seed: number): void;
2026-04-01 17:34:21 +08:00
/** 获取一个 [0,1) 随机数 */
2026-04-01 13:36:16 +08:00
next(max?: number): number;
2026-04-01 17:34:21 +08:00
/** 获取一个 [0,max) 随机整数 */
2026-04-01 13:36:16 +08:00
nextInt(max: number): number;
}
2026-04-01 17:34:21 +08:00
/**
* 使 mulberry32
* 32 PRNG
*/
export function createRNG(seed?: number): RNG {
let currentSeed: number = seed ?? 1;
function rng(seed: number): void {
currentSeed = seed;
}
rng.next = function(max?: number): number {
let t = (currentSeed += 0x6d2b79f5);
t = Math.imul(t ^ (t >>> 15), t | 1);
t ^= t + Math.imul(t ^ (t >>> 7), t | 61);
const result = ((t ^ (t >>> 14)) >>> 0) / 4294967296;
return max !== undefined ? result * max : result;
};
rng.nextInt = function(max: number): number {
return Math.floor(rng.next(max));
};
(rng as any).setSeed = function(seed: number): void {
currentSeed = seed;
};
(rng as any).getSeed = function(): number {
return currentSeed;
};
return rng;
}
/** Mulberry32RNG 类实现(用于类型兼容) */
export class Mulberry32RNG {
private seed: number = 1;
constructor(seed?: number) {
if (seed !== undefined) {
this.seed = seed;
}
}
/** 设置随机数种子 */
call(seed: number): void {
this.seed = seed;
}
/** 获取一个 [0,1) 随机数 */
next(max?: number): number {
let t = (this.seed += 0x6d2b79f5);
t = Math.imul(t ^ (t >>> 15), t | 1);
t ^= t + Math.imul(t ^ (t >>> 7), t | 61);
const result = ((t ^ (t >>> 14)) >>> 0) / 4294967296;
return max !== undefined ? result * max : result;
}
/** 获取一个 [0,max) 随机整数 */
nextInt(max: number): number {
return Math.floor(this.next(max));
}
/** 重新设置种子 */
setSeed(seed: number): void {
this.seed = seed;
}
/** 获取当前种子 */
getSeed(): number {
return this.seed;
}
}