Skip to content

feat(s5): difficulty tier system — Easy/Normal/Hard with AI brood modifier and tiebreaks (V22)#149

Merged
LightAxe merged 7 commits into
mainfrom
worktree-s4-uat-fixes
May 26, 2026
Merged

feat(s5): difficulty tier system — Easy/Normal/Hard with AI brood modifier and tiebreaks (V22)#149
LightAxe merged 7 commits into
mainfrom
worktree-s4-uat-fixes

Conversation

@LightAxe
Copy link
Copy Markdown
Owner

Summary

  • Sim version V22: adds WorldState.difficulty ('Easy'|'Normal'|'Hard'), updated from V21 to V22 as LATEST_SIM_VERSION
  • Pre-game difficulty overlay: Phaser modal (matching save-prompt pattern) shown before every new game and restart; retry reuses previous difficulty
  • AI brood modifier: ColonyRecord.eggIntervalNumerator stores per-colony scaling (Easy=5, Normal=4, Hard=3); lifecycle-system applies (interval * numerator) >> 2 — integer-only, no division operator; hard floor at MIN_EGG_INTERVAL_TICKS=100
  • AI tier-array lookup gates: warfooting/invading thresholds, recovery duration, spider hunger cap all switch from NORMAL_TIER_INDEX to tierIndex(world.difficulty) at V22+
  • Timeout tiebreak (MATCH_TIMEOUT_TICKS=24000): both queens survive to tick 24000 → winner by living worker count → Victory/Defeat/MutualDestruction
  • Stalemate tiebreak (STALEMATE_FOOD_THRESHOLD_FP=512): all food piles depleted AND both colonies below threshold → MutualDestruction
  • round_end SimEvent: emitted by checkTiebreaks() for playtrace attribution; deriveRoundEndReason() checks it before queen_death
  • Backward compat: pre-V22 saves load with difficulty='Normal' and eggIntervalNumerator=4 (identity); all V22-gated paths fall back to Normal-tier behaviour for byte-identical replay

Test plan

  • npm run test — 73 files, 2201 tests pass
  • npm run test:coverage — statements 90%, branches 83%, functions 96%, lines 93% (all above 80% gate)
  • npx tsc --noEmit — clean
  • Manual: new game → difficulty overlay appears → choose Hard → F9 snapshot shows difficulty: 'Hard' and AI colony eggIntervalNumerator: 3
  • Manual: continue from save → no difficulty overlay; difficulty loads from save
  • Manual: Hard mode → AI egg interval ~112 ticks vs Normal 150 (visible in F9 snapshot)
  • Manual: retry → same difficulty preserved
  • Manual: run to tick 24000 with both queens alive → tiebreak fires

🤖 Generated with Claude Code

…ifier and tiebreaks (V22)

Adds sim version V22 (SIM_VERSION_V22_DIFFICULTY=22). Player chooses difficulty
before each new game via a pre-game overlay. The AI colony's egg-interval is
scaled by a per-difficulty numerator (Easy=5/4×, Normal=1×, Hard=3/4×) stored
in ColonyRecord.eggIntervalNumerator to avoid player-vs-enemy branching in the
hot path. All four AI tier-array lookups (warfooting/invading thresholds,
recovery duration, spider hunger cap) gate on V22. Two new tiebreak conditions
fire in tick step 18 when both queens are alive: Timeout (tick ≥ 24 000,
winner by worker count) and Stalemate (food depleted + both colonies starving).
Pre-V22 saves load with difficulty='Normal' and replay byte-identically.

Co-Authored-By: Claude Sonnet 4.6 <noreply@anthropic.com>
@LightAxe
Copy link
Copy Markdown
Owner Author

@codex review

Copy link
Copy Markdown

@chatgpt-codex-connector chatgpt-codex-connector Bot left a comment

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

💡 Codex Review

Here are some automated review suggestions for this pull request.

Reviewed commit: 31e26a69c2

ℹ️ About Codex in GitHub

Your team has set up Codex to review pull requests in this repo. Reviews are triggered when you

  • Open a pull request for review
  • Mark a draft as ready
  • Comment "@codex review".

If Codex has suggestions, it will comment; otherwise it will react with 👍.

Codex can also answer questions or update the PR. Try commenting "@codex address that feedback".

Comment thread src/render/game-scene.ts
Comment thread src/sim/game-over.ts Outdated
…d in stalemate

P0: showDifficultySelectThenBoot now sets gamePhase=SavePrompt before opening
the overlay. On a fresh install (no save) gameLoop is not yet initialized;
update()'s line-2 SavePrompt guard prevents it from reaching
this.gameLoop.update(delta) before bootFresh is called.

P1: stalemate tiebreak now uses colonyFoodWithCarried() instead of
colonyFoodTotal(), summing food on living ants (world.ants.foodCarrying) in
addition to colony.foodStored + FoodStorage chambers. Prevents a false
MutualDestruction on the tick the last pile is collected when foragers are
still carrying enough food to recover.

Co-Authored-By: Claude Sonnet 4.6 <noreply@anthropic.com>
@LightAxe
Copy link
Copy Markdown
Owner Author

@codex review

Copy link
Copy Markdown

@chatgpt-codex-connector chatgpt-codex-connector Bot left a comment

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

💡 Codex Review

Here are some automated review suggestions for this pull request.

Reviewed commit: 3a7886c1d2

ℹ️ About Codex in GitHub

Your team has set up Codex to review pull requests in this repo. Reviews are triggered when you

  • Open a pull request for review
  • Mark a draft as ready
  • Comment "@codex review".

If Codex has suggestions, it will comment; otherwise it will react with 👍.

Codex can also answer questions or update the PR. Try commenting "@codex address that feedback".

Comment thread src/render/game-scene.ts
Copy link
Copy Markdown

@chatgpt-codex-connector chatgpt-codex-connector Bot left a comment

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

💡 Codex Review

Here are some automated review suggestions for this pull request.

Reviewed commit: 3a7886c1d2

ℹ️ About Codex in GitHub

Your team has set up Codex to review pull requests in this repo. Reviews are triggered when you

  • Open a pull request for review
  • Mark a draft as ready
  • Comment "@codex review".

If Codex has suggestions, it will comment; otherwise it will react with 👍.

Codex can also answer questions or update the PR. Try commenting "@codex address that feedback".

Comment thread src/sim/game-over.ts Outdated
Comment thread src/render/game-scene.ts
- game-scene: set gamePhase=SavePrompt before difficulty overlay in
  restartGame() to prevent update() ticking stale world during selection
- game-scene: pass currentDifficulty to createScenario in finishBoot()
  so prevState replay envelope encodes the correct difficulty
- game-over: move livingWorkerCount calls inside timeout/stalemate
  branches to avoid O(entityCount) scan on every non-tiebreak tick

Co-Authored-By: Claude Sonnet 4.6 <noreply@anthropic.com>
@LightAxe
Copy link
Copy Markdown
Owner Author

@codex review

Copy link
Copy Markdown

@chatgpt-codex-connector chatgpt-codex-connector Bot left a comment

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

💡 Codex Review

Here are some automated review suggestions for this pull request.

Reviewed commit: fca4eb2673

ℹ️ About Codex in GitHub

Your team has set up Codex to review pull requests in this repo. Reviews are triggered when you

  • Open a pull request for review
  • Mark a draft as ready
  • Comment "@codex review".

If Codex has suggestions, it will comment; otherwise it will react with 👍.

Codex can also answer questions or update the PR. Try commenting "@codex address that feedback".

Comment thread src/sim/game-over.ts Outdated
livingWorkerCount was iterating world.ants.alive and counting all
non-queen live entities, including eggs and larvae (which also have
alive===1). The timeout tiebreak winner is defined as the colony with
more *workers*, so overcounting brood could flip Victory/Defeat.

Fix: iterate colony.workers (the maintained worker bucket) and check
alive[id]===1 — eggs and larvae are never in this bucket.

Test helper addWorker updated to push into colony.workers so the
corrected code path is exercised.

Co-Authored-By: Claude Sonnet 4.6 <noreply@anthropic.com>
@LightAxe
Copy link
Copy Markdown
Owner Author

@codex review

Copy link
Copy Markdown

@chatgpt-codex-connector chatgpt-codex-connector Bot left a comment

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

💡 Codex Review

Here are some automated review suggestions for this pull request.

Reviewed commit: f632da1751

ℹ️ About Codex in GitHub

Your team has set up Codex to review pull requests in this repo. Reviews are triggered when you

  • Open a pull request for review
  • Mark a draft as ready
  • Comment "@codex review".

If Codex has suggestions, it will comment; otherwise it will react with 👍.

Codex can also answer questions or update the PR. Try commenting "@codex address that feedback".

Comment thread src/render/game-scene.ts
The SCEN-06 replay check was calling createScenario(seed) without
difficulty, causing Easy/Hard sessions to diverge from the original run.
Read difficulty from the snapshot's SerializedWorldState field and pass
it through; pre-V22 snapshots default to 'Normal'.

Co-Authored-By: Claude Sonnet 4.6 <noreply@anthropic.com>
@LightAxe
Copy link
Copy Markdown
Owner Author

@codex review

Copy link
Copy Markdown

@chatgpt-codex-connector chatgpt-codex-connector Bot left a comment

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

💡 Codex Review

Here are some automated review suggestions for this pull request.

Reviewed commit: fe6f3422c1

ℹ️ About Codex in GitHub

Your team has set up Codex to review pull requests in this repo. Reviews are triggered when you

  • Open a pull request for review
  • Mark a draft as ready
  • Comment "@codex review".

If Codex has suggestions, it will comment; otherwise it will react with 👍.

Codex can also answer questions or update the PR. Try commenting "@codex address that feedback".

Comment thread scripts/analyze-snapshot.ts
createScenario always starts at LATEST_SIM_VERSION (V22). Without
restoring the snapshot's simVersion, replaying a pre-V22 capture would
have V22-gated paths active (tiebreaks, brood modifier), causing false
SCEN-06 divergence reports on valid historical snapshots.

Fix: assign replay.simVersion from the snapshot immediately after
createScenario. Emit a console.warn when the value is missing or invalid
so replay divergence is visible rather than silent.

Co-Authored-By: Claude Sonnet 4.6 <noreply@anthropic.com>
@LightAxe
Copy link
Copy Markdown
Owner Author

@codex review

Copy link
Copy Markdown

@chatgpt-codex-connector chatgpt-codex-connector Bot left a comment

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

💡 Codex Review

Here are some automated review suggestions for this pull request.

Reviewed commit: e332c45885

ℹ️ About Codex in GitHub

Your team has set up Codex to review pull requests in this repo. Reviews are triggered when you

  • Open a pull request for review
  • Mark a draft as ready
  • Comment "@codex review".

If Codex has suggestions, it will comment; otherwise it will react with 👍.

Codex can also answer questions or update the PR. Try commenting "@codex address that feedback".

Comment thread src/render/ui-scene.ts Outdated
Easy (220–360), Normal (330–470), and Hard (440–580) overlapped by 30px
each. Clicks in the overlap bands routed to the wrong difficulty.

Fix: shift Easy left to x=180 and Hard right to x=480, giving 10px gaps
between all three buttons (180–320 / 330–470 / 480–620), centered in
the 800px canvas.

Co-Authored-By: Claude Sonnet 4.6 <noreply@anthropic.com>
@LightAxe
Copy link
Copy Markdown
Owner Author

@codex review

@chatgpt-codex-connector
Copy link
Copy Markdown

Codex Review: Didn't find any major issues. Swish!

ℹ️ About Codex in GitHub

Your team has set up Codex to review pull requests in this repo. Reviews are triggered when you

  • Open a pull request for review
  • Mark a draft as ready
  • Comment "@codex review".

If Codex has suggestions, it will comment; otherwise it will react with 👍.

Codex can also answer questions or update the PR. Try commenting "@codex address that feedback".

@LightAxe LightAxe merged commit 2961a38 into main May 26, 2026
1 check passed
@LightAxe LightAxe deleted the worktree-s4-uat-fixes branch May 26, 2026 20:21
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment

Labels

None yet

Projects

None yet

Development

Successfully merging this pull request may close these issues.

1 participant