Problem
_on_tick() in scripts/main.gd (line 1360) is the game's main loop. It orchestrates:
maybe_fire_event() — random events
_clean_stale_reservations() — reservation cleanup
apply_food_upkeep() — food deduction for extra workers
- Per-worker:
choose_task() → step_worker() (which calls do_build, gather, haul, etc.)
GoalProgression.process_tick() — goal completion/rotation
GoalReward.tick_rewards() — reward expiration/trickle
persist() — save state
render_all() — full UI refresh
None of the existing tests exercise this path:
tests/test_e2e.gd simulates ticks by incrementing counters manually and testing state persistence — it does NOT instantiate a Control and run _on_tick() with a real timer
- Individual module tests (
test_food_upkeep.gd, test_goal_progression.gd, etc.) test components in isolation
A regression in the tick orchestration (e.g., ordering bug, missing call, double-fire) would not be caught.
Fix
Create tests/test_tick_integration.gd that:
- Instantiates the main scene (or a test double with the same script)
- Sets up a minimal valid game state (a few tiles, one worker, one resource)
- Runs N ticks by calling
_on_tick() directly (or via the timer signal)
- Asserts the expected state transitions:
- Worker moves toward a resource
- Resource is gathered
- Food upkeep fires at the right interval
- Events can fire
- State is persisted (dirty flag cleared)
- Test edge cases: starvation, no available tasks, build completion
This will likely require some refactoring of _on_tick() to be testable without a full scene tree — at minimum, extracting the tick logic into a callable that doesn't depend on render_all().
Acceptance criteria
Problem
_on_tick()inscripts/main.gd(line 1360) is the game's main loop. It orchestrates:maybe_fire_event()— random events_clean_stale_reservations()— reservation cleanupapply_food_upkeep()— food deduction for extra workerschoose_task()→step_worker()(which callsdo_build, gather, haul, etc.)GoalProgression.process_tick()— goal completion/rotationGoalReward.tick_rewards()— reward expiration/tricklepersist()— save staterender_all()— full UI refreshNone of the existing tests exercise this path:
tests/test_e2e.gdsimulates ticks by incrementing counters manually and testing state persistence — it does NOT instantiate aControland run_on_tick()with a real timertest_food_upkeep.gd,test_goal_progression.gd, etc.) test components in isolationA regression in the tick orchestration (e.g., ordering bug, missing call, double-fire) would not be caught.
Fix
Create
tests/test_tick_integration.gdthat:_on_tick()directly (or via the timer signal)This will likely require some refactoring of
_on_tick()to be testable without a full scene tree — at minimum, extracting the tick logic into a callable that doesn't depend onrender_all().Acceptance criteria
tests/test_tick_integration.gdexists and runs in headless moderender_all)test_runner.gd