feat: rng & commands impl & tests
This commit is contained in:
+60
-2
@@ -5,6 +5,64 @@
|
||||
params: string[];
|
||||
}
|
||||
|
||||
// TODO implement this
|
||||
export function parseCommand(input: string): Command {
|
||||
/**
|
||||
* 解析命令行输入字符串为 Command 对象
|
||||
* 支持格式:commandName [params...] [--flags...] [-o value...]
|
||||
*
|
||||
* @example
|
||||
* parseCommand("move meeple1 region1 --force -x 10")
|
||||
* // returns { name: "move", params: ["meeple1", "region1"], flags: { force: true }, options: { x: "10" } }
|
||||
*/
|
||||
export function parseCommand(input: string): Command {
|
||||
const tokens = input.trim().split(/\s+/).filter(Boolean);
|
||||
|
||||
if (tokens.length === 0) {
|
||||
return { name: '', flags: {}, options: {}, params: [] };
|
||||
}
|
||||
|
||||
const name = tokens[0];
|
||||
const params: string[] = [];
|
||||
const flags: Record<string, true> = {};
|
||||
const options: Record<string, string> = {};
|
||||
|
||||
let i = 1;
|
||||
while (i < tokens.length) {
|
||||
const token = tokens[i];
|
||||
|
||||
if (token.startsWith('--') && !/^-?\d+$/.test(token)) {
|
||||
// 长格式标志或选项:--flag 或 --option value
|
||||
const key = token.slice(2);
|
||||
const nextToken = tokens[i + 1];
|
||||
|
||||
// 如果下一个 token 存在且不以 - 开头(或者是负数),则是选项值
|
||||
if (nextToken && (!nextToken.startsWith('-') || /^-\d+$/.test(nextToken))) {
|
||||
options[key] = nextToken;
|
||||
i += 2;
|
||||
} else {
|
||||
// 否则是布尔标志
|
||||
flags[key] = true;
|
||||
i++;
|
||||
}
|
||||
} else if (token.startsWith('-') && token.length > 1 && !/^-?\d+$/.test(token)) {
|
||||
// 短格式标志或选项:-f 或 -o value(但不匹配负数)
|
||||
const key = token.slice(1);
|
||||
const nextToken = tokens[i + 1];
|
||||
|
||||
// 如果下一个 token 存在且不以 - 开头(或者是负数),则是选项值
|
||||
if (nextToken && (!nextToken.startsWith('-') || /^-\d+$/.test(nextToken))) {
|
||||
options[key] = nextToken;
|
||||
i += 2;
|
||||
} else {
|
||||
// 否则是布尔标志
|
||||
flags[key] = true;
|
||||
i++;
|
||||
}
|
||||
} else {
|
||||
// 普通参数(包括负数)
|
||||
params.push(token);
|
||||
i++;
|
||||
}
|
||||
}
|
||||
|
||||
return { name, flags, options, params };
|
||||
}
|
||||
+77
-5
@@ -1,12 +1,84 @@
|
||||
export interface RNG {
|
||||
/** 设置随机数种子 */
|
||||
(seed: number): void;
|
||||
|
||||
/** 获取一个[0,1)随机数 */
|
||||
|
||||
/** 获取一个 [0,1) 随机数 */
|
||||
next(max?: number): number;
|
||||
|
||||
/** 获取一个[0,max)随机整数 */
|
||||
|
||||
/** 获取一个 [0,max) 随机整数 */
|
||||
nextInt(max: number): number;
|
||||
}
|
||||
|
||||
// TODO: create a RNG implementation with the alea library
|
||||
/**
|
||||
* 使用 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;
|
||||
}
|
||||
}
|
||||
|
||||
Reference in New Issue
Block a user