chore: update tests and imports

This commit is contained in:
2026-04-03 17:56:35 +08:00
parent 65a3d682b6
commit 50c146964d
8 changed files with 474 additions and 11 deletions
+23 -6
View File
@@ -14,12 +14,13 @@ export function createPart<TMeta = {}>(
template: PartTemplate<TMeta>,
id: string
): Part<TMeta> {
return {
regionId: '',
position: [],
...template,
const part: Part<TMeta> = {
id,
} as Part<TMeta>;
regionId: template.regionId ?? '',
position: template.position ?? [],
...template,
};
return part;
}
export function createParts<TMeta = {}>(
@@ -67,7 +68,7 @@ export function mergePartPools<TMeta = {}>(
...pools: PartPool<TMeta>[]
): PartPool<TMeta> {
if (pools.length === 0) {
return createPartPool({} as PartTemplate<TMeta>, 0, 'merged');
return createEmptyPartPool<TMeta>();
}
const allPartsArray = pools.flatMap(p => Object.values(p.parts));
@@ -94,3 +95,19 @@ export function mergePartPools<TMeta = {}>(
},
};
}
function createEmptyPartPool<TMeta>(): PartPool<TMeta> {
return {
parts: {},
template: {} as PartTemplate<TMeta>,
draw() {
return undefined;
},
return(_part: Part<TMeta>) {
// no-op for empty pool
},
remaining() {
return 0;
},
};
}
+19 -1
View File
@@ -1,4 +1,5 @@
import {RNG} from "@/utils/rng";
import {RNG} from '@/utils/rng';
import {Region} from '@/core/region';
export type Part<TMeta = {}> = {
id: string;
@@ -40,3 +41,20 @@ export function getPartAtPosition<TMeta>(parts: Record<string, Part<TMeta>>, reg
const posKey = position.join(',');
return Object.values(parts).find(p => p.regionId === regionId && p.position.join(',') === posKey);
}
/**
* O(1) cell occupancy check using Region.partMap
*/
export function isCellOccupiedByRegion(region: Region, position: number[]): boolean {
return position.join(',') in region.partMap;
}
/**
* O(1) part lookup using Region.partMap and parts Record
*/
export function getPartAtPositionInRegion<TMeta>(region: Region, parts: Record<string, Part<TMeta>>, position: number[]): Part<TMeta> | undefined {
const posKey = position.join(',');
const partId = region.partMap[posKey];
if (!partId) return undefined;
return parts[partId];
}
+1 -1
View File
@@ -8,7 +8,7 @@ export type { IGameContext } from './core/game';
export { createGameContext, createGameCommandRegistry } from './core/game';
export type { Part } from './core/part';
export { flip, flipTo, roll, findPartById, isCellOccupied, getPartAtPosition } from './core/part';
export { flip, flipTo, roll, findPartById, isCellOccupied, getPartAtPosition, isCellOccupiedByRegion, getPartAtPositionInRegion } from './core/part';
export type { PartTemplate, PartPool } from './core/part-factory';
export { createPart, createParts, createPartPool, mergePartPools } from './core/part-factory';
+9 -1
View File
@@ -1,4 +1,12 @@
import {createGameCommandRegistry, Part, MutableSignal, createRegion, createPart, isCellOccupied as isCellOccupiedUtil, getPartAtPosition} from '@/index';
import {
createGameCommandRegistry,
Part,
MutableSignal,
createRegion,
createPart,
isCellOccupied as isCellOccupiedUtil,
getPartAtPosition,
} from '@/index';
const BOARD_SIZE = 6;
const MAX_PIECES_PER_PLAYER = 8;
+1 -1
View File
@@ -1,4 +1,4 @@
import {Signal, signal, SignalOptions} from "@preact/signals-core";
import {Signal, signal, SignalOptions} from '@preact/signals-core';
import {create} from 'mutative';
export class MutableSignal<T> extends Signal<T> {