Skip to content

Add optional per-room undo for authoritative game-state rollback #648

Description

@ninthworld

Summary

Add an Undo option that can be enabled when configuring a room. When enabled, any player in the room may undo the most recent game-state transition and return the game to its previous authoritative state.

This must be implemented across both the server and client. The server remains authoritative; clients only request an undo and render the resulting restored state.

Intended behavior

  • Undo is disabled by default and must be explicitly enabled per room.
  • The room configuration and lobby should clearly show whether undo is enabled.
  • When enabled, any player may invoke undo at any time during an active game without requiring approval from the other players.
  • One activation restores the immediately previous authoritative state checkpoint.
  • Players may undo repeatedly while earlier checkpoints remain available.
  • After an undo, any newer state history is discarded. New actions create a new history branch.
  • All connected clients are notified of the rollback and synchronized to the restored state.
  • The game log should record that an undo occurred and identify the player who requested it.
  • The client should disable or hide the control when undo is unavailable, disabled for the room, or no prior checkpoint exists.

State rollback requirements

Undo must restore the complete authoritative game state, not only the visible battlefield. This includes, as applicable:

  • battlefield permanents, tokens, counters, attachments, and tapped state
  • player life totals and other player counters
  • hands and all public or hidden zones
  • library contents and ordering
  • graveyard, exile, command, and other zones
  • stack contents and pending choices
  • active player, turn, phase, step, priority, and pass state
  • mana pools, costs paid, targets, modes, and selections
  • continuous-effect and derived-state inputs
  • random-number-generator state or any other deterministic state needed to resume correctly
  • game-over status when undoing the action that ended a game

A checkpoint should represent a stable, server-accepted game transition rather than a transient client animation frame. The implementation should establish a clear checkpoint boundary so a single undo has predictable behavior.

Server work

  • Add an undo_enabled room/game configuration field and expose it through room creation, room metadata, and game initialization.
  • Maintain a history of restorable authoritative game-state checkpoints when undo is enabled.
  • Add a validated client command for requesting undo.
  • Reject requests when undo is disabled, no prior checkpoint exists, the game is not in an undoable state, or the requester is not a player in the room.
  • Restore the previous checkpoint atomically.
  • Discard checkpoints newer than the restored state.
  • Broadcast an explicit undo/state-restored event and the canonical restored state to every client.
  • Ensure reconnecting clients receive the current restored state rather than stale pre-undo data.
  • Define a reasonable memory strategy for history, such as bounded checkpoints or another representation that avoids unbounded game-state growth. The limit, if any, must be visible to clients so the UI accurately represents availability.

Client work

  • Add an undo-enabled option to room creation/edit configuration.
  • Show the setting in the lobby before the game begins.
  • Add an Undo control to the in-game interface when the room supports it.
  • Clearly indicate when no earlier state is available.
  • Send an undo request rather than attempting local rollback.
  • On success, cancel stale animations, prompts, targeting, selections, and pending local interaction state before rendering the restored canonical state.
  • Show a brief notification such as “PlayerName undid the previous action.”
  • Handle rejection responses without leaving the client in a partially rolled-back state.

Product considerations

Undo can reveal information that players retain after rollback, such as a card drawn from a library or a previously hidden choice. This is acceptable for rooms that deliberately enable the feature, but the room configuration should make clear that undo is intended for casual play, testing, and correcting mistakes rather than competitive integrity.

Acceptance criteria

  • Room creators can enable or disable undo, with disabled as the default.
  • All players can see the room's undo setting before the game starts.
  • In an undo-enabled game, any player can request a rollback without a vote.
  • A successful request restores exactly the previous authoritative checkpoint.
  • Repeated requests can move backward through available history.
  • Newer history is discarded after a rollback and subsequent play continues normally.
  • Hidden zones, library order, stack, priority, turn state, counters, and pending decisions remain server-consistent after rollback.
  • All connected clients update to the same restored state.
  • Reconnecting after an undo produces the restored state.
  • Stale client prompts and animations are cleared after restoration.
  • Undo requests are safely rejected when the feature is disabled or no checkpoint exists.
  • The game log identifies who requested each undo.
  • Undoing a game-ending transition can return the game to active play when a prior checkpoint exists.
  • Server-level tests cover checkpoint creation, rollback, history truncation, rejection cases, and multiplayer synchronization.
  • Client tests cover room configuration, control availability, restored-state handling, and stale interaction cleanup.

Out of scope

  • Voting or approval workflows for undo
  • Per-player undo permissions
  • Selectively undoing only part of an action
  • Redo support
  • Guaranteeing competitive fairness after hidden information has been revealed

Activity

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

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