Skip to content

bug: Double undo snapshot pushed when executeAndRecalculate calls Game.move #95

Description

@nodots

Problem

Both Game.move() (line ~959) and Game.executeAndRecalculate() (line ~1395) push pre-move snapshots onto activePlay.undo.frames. Since executeAndRecalculate() calls Game.move() internally (line ~1409), two snapshots are pushed for a single logical move when the move is initiated through executeAndRecalculate.

This means:

  • Calling undoLastInActivePlay() once only pops the inner snapshot — the game state is still post-move
  • Users/robots must call undo twice to revert a single move made through executeAndRecalculate
  • The undo stack grows at 2x the expected rate, wasting memory

Reproduction

  1. Call Game.executeAndRecalculate(game, originId) to make a move
  2. Inspect game.activePlay.undo.frames.length — it has 2 entries instead of 1
  3. Call Game.undoLastInActivePlay(game) — the board state doesn't match the pre-move state

Affected code

  • src/Game/index.tsGame.move() snapshot push (~line 959)
  • src/Game/index.tsGame.executeAndRecalculate() snapshot push (~line 1395)

Implementation Plan

  1. Remove the snapshot push from Game.executeAndRecalculate() (lines ~1394-1407) — let Game.move() be the single source of truth for undo snapshots
  2. Add a unit test that verifies: after calling executeAndRecalculate once, undo.frames.length === 1
  3. Add a test that verifies: calling undoLastInActivePlay after a single executeAndRecalculate move restores the exact pre-move board state
  4. Verify switchDice gating still works correctly with single-snapshot undo stack

Files to modify

  • src/Game/index.ts — remove duplicate snapshot in executeAndRecalculate
  • src/Game/__tests__/undo-stack.test.ts — new test file

Metadata

Metadata

Assignees

No one assigned

    Labels

    No labels
    No labels

    Projects

    No projects

    Milestone

    No milestone

    Relationships

    None yet

    Development

    No branches or pull requests

    Issue actions