Files
glitch_automata_lab/backend/admin/src/caInitialConditionGenerators.ts
T

94 lines
2.6 KiB
TypeScript
Raw Normal View History

2026-07-01 12:10:12 +02:00
import { numericGridSize, seededRandom } from './caRuntime.js'
import type { CaClass, JsonObject, SceneParams } from './types.js'
export interface InitialConditionResult {
type: 'cells'
cells: number[][]
generator: {
kind: string
} & JsonObject
}
export interface InitialConditionRuntimeInput {
settings: SceneParams
caClass: CaClass
params: JsonObject
}
export interface InitialConditionRuntime {
id: string
label: string
generate: (input: InitialConditionRuntimeInput) => InitialConditionResult
}
const initialConditionRuntimes = new Map<string, InitialConditionRuntime>()
function clampDensity(value: unknown) {
return Math.max(0, Math.min(1, typeof value === 'number' ? value : 0.28))
}
function randomSoup({ settings, caClass, params }: InitialConditionRuntimeInput): InitialConditionResult {
const density = clampDensity(params.density)
const seed = typeof params.seed === 'string' ? params.seed : 'studio-seed'
const random = seededRandom(seed)
const [width, height, depth] = numericGridSize(settings.simulation?.grid, caClass.dimensions)
const cells: number[][] = []
for (let z = 0; z < depth; z += 1) {
for (let y = 0; y < height; y += 1) {
for (let x = 0; x < width; x += 1) {
if (random() < density) cells.push([x, y, z])
}
}
}
return {
type: 'cells',
cells,
generator: {
kind: 'random-soup',
density,
seed
}
}
}
export function registerInitialConditionRuntime(
runtime: InitialConditionRuntime,
options: { replace?: boolean } = {}
) {
if (!runtime.id.trim()) throw new Error('Initial condition runtime id is required')
if (initialConditionRuntimes.has(runtime.id) && !options.replace) {
throw new Error(`Initial condition runtime already registered: ${runtime.id}`)
}
initialConditionRuntimes.set(runtime.id, runtime)
}
export function listInitialConditionRuntimes() {
return [...initialConditionRuntimes.values()]
}
export function getInitialConditionRuntime(runtimeId: string) {
return initialConditionRuntimes.get(runtimeId) ?? null
}
export function generateInitialCondition(runtimeId: string, input: InitialConditionRuntimeInput) {
const runtime = getInitialConditionRuntime(runtimeId)
if (!runtime) throw new Error(`Initial condition runtime unavailable: ${runtimeId}`)
const result = runtime.generate(input)
if (result.type !== 'cells' || !Array.isArray(result.cells)) {
throw new Error(`Initial condition runtime returned an invalid result: ${runtimeId}`)
}
return result
}
registerInitialConditionRuntime(
{
id: 'random-soup',
label: 'Random soup',
generate: randomSoup
},
{ replace: true }
)