r/programming

Designing a Movement Transaction System for a Sokoban Game

Brief

The Movement Transaction System for Lights Out (r/programming post 2026-08-06; full blog 2026-07-26) moves movement and rule evaluation to server transactions (delta, entity list, flags) that progress through Queued, Issued, Committed, or Aborted. Clients receive interpolation metadata (duration, acceleration/linear) and animate per-frame while the server’s validate_transaction enforces rules. The author says this centralization simplifies code and improves feel; no community responses were provided.

Why it matters

The Movement Transaction System for the multiplayer 2D grid game Lights Out (post dated 2026-08-06) bundles all server-side movement + rule evaluation into transactions that contain a movement delta, an affected-entities list, and flags; transactions move through Queued → Issued → Committed → Aborted states.

Key details

  • Clients receive transaction events from the server with interpolation parameters (duration and flags such as acceleration vs linear); client-side prediction/visual interpolation runs per-frame until commit/abort, while server-side validate_transaction centralizes all gameplay-rule checks (blog post 2026-07-26).
  • The author reports concrete benefits: simplified gameplay code, a single validate_transaction function replacing dispersed rules, and smoother visuals (e.g., continuous fireball movement). No community comments or rebuttals were included in the provided r/programming post, so peer feedback isn’t available here.
Source evidence

Context
My multiplayer game Lights Out is based on a 2D grid. Entities can only ever be in exactly one grid tile. This makes the rule evaluation really simple and understandable. However, it doesn't really feel nice to play (which you know if you've ever played any of the PuzzleScript games). At the same time, the more content is in the game, the more complex and arbitrary the game rules become.
I therefore introduced the Movement Transaction System into the code base to deal with this. This includes two sides: - The gameplay code on server side deals with transactions. This bundles all movement code (including rule evaluation) into a single system. - The visualization & prediction code on client side deals with visual interpolation for moves (introducing some juice into the gameplay feel), based on the transactions managed by the server.
The Transaction
A single transaction includes the movement delta, a list of entities that it has affected and some flags. A transaction then undergoes several stages: - Queued: Gameplay code has requested an entity to move - Issued: The visual interpolation for the transaction has started in the client, but the entities have not been moved from a gameplay perspective - Committed: The entities have now been moved onto their new tiles, the visual interpolation is finishing - Aborted: The transaction couldn't be committed as it would've violated gameplay rules. Visual interpolation is reversed.
The Visual Interpolation
Whenever a transaction is issued on server-side, the server tells the clients to start a visual interpolation based on the transaction. This information includes the desired duration of the interpolation, as well as some flags (like whether to use acceleration or do a linear interpolation). The client then updates the visual interpolation every frame, until the transaction is either aborted or the target position has been reached.
Simplifying Gameplay Code
This new system has made the gameplay code much simpler. I can now easily query whether an entity currently has a live transaction to know whether the visual interpolation is still in progress. This enables seamless, continuous movement across the world (e.g. for fireballs moving at linear speed).
This also guarantees that the visual position of an entity is always close enough to its gameplay (physical) position so that players aren't confused about the rule evaluation.
Finally, the gameplay rules are now implemented in a single function called validate_transaction, instead of being spread out across all the different entities like it was before.
Summary
The transaction system made the gameplay code much simpler and easier to reason about, while also improving the game feel and robustness.
You can find the full blog most, including more details and sample code, over on https://lightsout.afterthought.games/blog/2026-07-26-19-00

Link: https://lightsout.afterthought.games/blog/2026-07-26-19-00

Subreddit: r/programming