Skip to content

Add life total change logging to game log#9845

Open
TytaniumDev wants to merge 5 commits intoCard-Forge:masterfrom
TytaniumDev:log-life-total-changes
Open

Add life total change logging to game log#9845
TytaniumDev wants to merge 5 commits intoCard-Forge:masterfrom
TytaniumDev:log-life-total-changes

Conversation

@TytaniumDev
Copy link

@TytaniumDev TytaniumDev commented Feb 21, 2026

I'm building a tool that uses headless Forge simulations to play commander games and then analyze the logs (more detail in #9844 ). Player life changes are currently not logged, which makes it hard to visualize game states at a high level.

This PR adds life logging. The code was primarily written by Claude but I've verified it and made sure tests were written to validate all the scenarios I could think of.

Summary

  • GameEventPlayerLivesChanged is already fired on every life total change but had no visitor in GameLogFormatter — the event was silently discarded
  • Adds new GameLogEntryType.LIFE enum value, replacing the // Where's life loss? comment that was next to DAMAGE
  • Adds visit(GameEventPlayerLivesChanged) to GameLogFormatter producing log lines like: Life: Ai(1)-Doran Big Butts 40 -> 37
  • Adds localized message key lblLogPlayerLifeChange to all language files (English fallback for non-English locales)
  • Adds 6 targeted tests in GameLogLifeChangeTest

No behavior changes to existing log entries.

Closes #9844

Example game log output

Combat damage → life change

Two Nest Robbers (2/1 haste) attack an opponent at 4 life:

[COMBAT]       p1 assigned Nest Robber (1) and Nest Robber (2) to attack p2.
[COMBAT]       p2 didn't block Nest Robber (1).
               p2 didn't block Nest Robber (2).
[DAMAGE]       Nest Robber (1) deals 2 combat damage to p2.
[DAMAGE]       Nest Robber (2) deals 2 combat damage to p2.
[LIFE]         Life: p2 4 -> 0

Lifegain from spell resolution

AI casts Lightning Helix (3 damage + 3 life) targeting opponent at 3 life:

[STACK_ADD]    p1 cast Lightning Helix targeting [p2]
[DAMAGE]       Lightning Helix (3) deals 3 non-combat damage to p2.
[LIFE]         Life: p2 3 -> 0
[LIFE]         Life: p1 20 -> 23
[STACK_RESOLVE] Lightning Helix (3) - Lightning Helix (3) deals 3 damage to p2. p1 gains 3 life.

Test results

Existing tests (63/63 passing, no regressions)

[INFO] Tests run: 63, Failures: 0, Errors: 0, Skipped: 0
       -- in forge.ai.simulation.GameSimulationTest

Full build with Checkstyle (all 13 modules passing)

[INFO] Reactor Summary for Forge Parent 2.0.11-SNAPSHOT:
[INFO]
[INFO] Forge Parent ....................................... SUCCESS
[INFO] Forge Core ......................................... SUCCESS
[INFO] Forge Game ......................................... SUCCESS
[INFO] Forge AI ........................................... SUCCESS
[INFO] Forge Gui .......................................... SUCCESS
[INFO] Forge Mobile ....................................... SUCCESS
[INFO] Forge Mobile Dev ................................... SUCCESS
[INFO] Forge .............................................. SUCCESS
[INFO] Forge iOS .......................................... SUCCESS
[INFO] Forge LDA .......................................... SUCCESS
[INFO] Adventure Editor ................................... SUCCESS
[INFO] Forge Android ...................................... SUCCESS
[INFO] Forge Installer .................................... SUCCESS
[INFO] BUILD SUCCESS

Build command: mvn -U -B clean install -P windows-linux

Test plan

  • mvn -U -B clean install -P windows-linux passes (includes Checkstyle)
  • Existing GameSimulationTest — all 63 tests pass (no regressions)
  • Game log shows [LIFE] entries after [DAMAGE] entries in combat scenarios
  • Game log shows [LIFE] entries for both damage-caused loss and spell-caused gain (Lightning Helix)
  • Existing log lines (Damage:, Combat:, etc.) are unchanged
  • Life: lines show accurate before/after values matching the game state

🤖 Generated with Claude Code

@TytaniumDev TytaniumDev marked this pull request as draft February 21, 2026 00:31
@TytaniumDev TytaniumDev force-pushed the log-life-total-changes branch from 8111b9d to 634d65f Compare February 21, 2026 03:47
GameEventPlayerLivesChanged is already fired on every life change but
had no visitor in GameLogFormatter, so the event was silently discarded.

- Add GameLogEntryType.LIFE enum value (answers the "Where's life loss?"
  comment that was in the enum)
- Add visit(GameEventPlayerLivesChanged) to GameLogFormatter
- Add lblLogPlayerLifeChange localization key to all language files
- Log format: "Life: PlayerName oldLife -> newLife"
- Add 6 tests in GameLogLifeChangeTest covering loss, gain, format,
  zero-loss no-op, setLife (both directions + no-op), multiple changes

Closes Card-Forge#9844

Co-Authored-By: Claude Opus 4.6 <noreply@anthropic.com>
@TytaniumDev TytaniumDev force-pushed the log-life-total-changes branch from 634d65f to 02fd6cc Compare February 21, 2026 03:54
@TytaniumDev TytaniumDev marked this pull request as ready for review February 21, 2026 03:59
@tool4ever tool4ever added the GUI label Feb 21, 2026
@MostCromulent
Copy link
Contributor

MostCromulent commented Feb 23, 2026

I think this is a good addition, but suspect it doesn't need built-in tests to validate the logging capability as long as we're confident it works? i.e. do other GameLogEntryType values have automated tests associated with them?

@tool4ever
Copy link
Contributor

yea imo AI a bit too overeager: a more generic test for logging would be more valuable

@TytaniumDev
Copy link
Author

@tool4ever @MostCromulent would you like me to remove the test, or condense it somehow? Or should I try to have the AI write a more generic logging test in this PR (seems out of scope)?

@MostCromulent
Copy link
Contributor

I'd suggest just removing the tests from this PR - we're doing some work on logging separately and can think about a more general test there if needed.

Really the proof is in the pudding on this one - either the life events show up in the log or they don't.

claude and others added 2 commits February 25, 2026 23:08
Tests for life total change logging are not needed at this time.
Logging validation will be handled separately as part of
broader logging infrastructure work.

https://claude.ai/code/session_01PXr1guxfuZVQvSYZUwhxk7
…-njYqQ

Remove GameLogLifeChangeTest per reviewer feedback
@TytaniumDev
Copy link
Author

@MostCromulent done!

Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment

Labels

Projects

None yet

Development

Successfully merging this pull request may close these issues.

Add explicit life change logs

4 participants