diff --git a/src/engine/__tests__/determinism.test.ts b/src/engine/__tests__/determinism.test.ts new file mode 100644 index 0000000..70cce04 --- /dev/null +++ b/src/engine/__tests__/determinism.test.ts @@ -0,0 +1,44 @@ +import { describe, expect, it } from 'vitest'; +import { buildContent } from '../../content/schema'; +import { createGameState, startAction, tickGame } from '../game'; +import { advance, createTickLoop, TICK_MS } from '../tickLoop'; + +function testContent() { + return buildContent({ + resources: [{ id: 'gold', name: 'Gold', startAmount: 0 }], + actions: [ + { + id: 'forage', + name: 'Forage', + durationMs: 300, + yields: { resourceId: 'gold', amount: 1 }, + }, + ], + }); +} + +function simulate(elapsedMs: number, chunkMs: number) { + const content = testContent(); + const state = createGameState(content); + startAction(state, content, 'forage'); + + const loop = createTickLoop({ tickMs: TICK_MS, startNow: 0 }); + let now = 0; + while (now < elapsedMs) { + const next = Math.min(now + chunkMs, elapsedMs); + advance(loop, next, () => { + tickGame(state, content, TICK_MS); + }); + now = next; + } + return { tickCount: loop.tickCount, gold: state.resources.gold }; +} + +describe('determinism integration', () => { + it('produces identical tick counts and game state regardless of advance chunking', () => { + const whole = simulate(5000, 5000); + const chunked = simulate(5000, 37); + expect(chunked.tickCount).toBe(whole.tickCount); + expect(chunked.gold).toBe(whole.gold); + }); +});