A local-first game loop is a pattern that prioritises offchain/offline experience. It is characterised by a core game loop that runs entirely on the player’s machine, unaffected by transaction confirmations onchain or responses from other networked machines unless the player chooses to engage them. The name is borrowed from local-first software. Among Topology’s experiments — an organisation I cofounded — this pattern first appeared in Solve2Mint (March 2022). It also characterises the design pattern of Solve2Mint 2 (July 2022), MuMu (November 2022), and Shoshin (January 2023).
Motivation
In networked games, the distribution of computational workload can skew toward either the server or the client. As edge devices see faster improvements in computing power compared to network speeds, it is advantageous to shift as much processing as possible to these edge devices. This strategy minimises latency and enhances the gaming experience.
Similar choices arise when designing Autonomous Worlds. Onchain applications typically need to wait for a transaction to finalise before rendering the resulting application state and proceeding with the next player transaction. Compared to the more prevalent Web3 game pattern where only token ownership executes onchain, Autonomous Worlds and fully onchain games are moving more computation workload away from the edge, worsening the latency situation. For example, Topology's Isaac experiment (August 2022) struggled with long and unstable block time as part of the game loop.
Many approaches to this problem exist, but none address the fundamental issue of waiting for finality to total-ordering transactions from decentralised consensus. To circumvent the problem, we sought to design a game loop where each player sends exactly one transaction per session, effectively making the game loop agnostic to the rate and variability of transactions and block time. By running the core game loop locally, we can remove block time from the calculus of the gameplay experience and leverage local computing power.
The Pattern
This pattern consists of two components: the “core game loop” and the “meta game loop.” The core game loop constitutes the primary gameplay experience and runs entirely on the player’s local machine. The meta game loop operates asynchronously, facilitating interaction between players without blocking the execution of their core game loops. The core game loop relays information to the meta game loop, which then derives new information based on that sent in by players. When available, this new information is asynchronously transmitted back to players’ machines.
A few possibilities are offered here for what the meta game loop may implement. The simplest one is a scoreboard. In this scenario, the core game loop could implement a puzzle game where the player solves puzzles by trial and error. Once happy with a solution, the player submits it and it is relayed to the meta game loop. The meta game loop grades puzzle solutions based on their effectiveness and organises them, along with player names, in a table sorted by grade. This table is relayed back to each player’s machine. The table could contain the full content of the original submissions, allowing players to study and compare them, or just ranking and grade information.
A more advanced use of the meta game loop is matchmaking. In this scenario, the combination of core and meta game loops together implement an automatic battle game. For example, the core game loop may implement a system for the player to design and test a battle strategy. Once happy with the design, the player submits it, relaying it to the meta game loop. The meta game loop performs matchmaking among player submissions to pitch strategies against one another. Additionally, the meta game loop may implement a rating system, such as Elo or Glicko, for assessing the strengths of either individual submissions or the players behind them. Tables for showing these ratings can be built and transmitted back to player machines.
As a final suggestion, consider implementing two coupled game loops, one multiplayer and one single-player. The multiplayer loop progresses at a slower pace and is implemented in the meta game loop. The single-player runs at local speed and is implemented in the core game loop. For example, the meta game loop may implement a battle royale game among robots designed by players while the corresponding core game loop implements a robot-building station where players design robot behaviours and test them out in different simulated encounters. The core game loop runs as fast as the player needs for the purpose of trial and error. The meta game loop advances the global state of the battle royale arena periodically, such as one game tick every X hours or Y blocks of a blockchain of choice. In the meta game arena, a multi-round fight simulation automatically ensues when two robots encounter each other. Rewards and punishments are applied to the winning and losing robots respectively.
Implementation Example
Taking inspiration from the alchemic logic of Zachtronic's Opus Magnum, MuMu is a more recent experiment by Topology in which players search for solutions to visual programming puzzles. MuMu's core game loop is a web frontend that operates in each player's web browser. It consists of:
- A graphical user interface that allows players to input their solutions and see how well they perform.
- A simulation program that runs the solutions against the puzzle simulator logic and produces performance results.
At their will, players submit their solutions to particular puzzles to MuMu's meta game loop. This pipeline consists of a smart contract on Starknet (testnet) followed by an indexing server that captures the events emitted by the smart contract and persists them in an organised database. MuMu's smart contract implements the same simulation program of the core game loop, executing it on solutions submitted by players. Running identical implementations of the same simulation program across the core and meta game loop ensures that the players can evaluate their solutions effectively before submitting them. The smart contract emits two events:
- A
new_simulation
event, which carries the full description of a solution submitted by a player. - A
end_summary
event, which carries information about the performance of a solution.
MuMu's core game loop is subscribed to changes in the database at the meta game loop's indexing server. These changes are transmitted from meta to core game loop for two purposes:
- Players can view a table of all solutions submitted to a particular puzzle ranked on their performance.
- Players can click on a solution in the table to pull it into the puzzle simulator. This allows them to examine how the solutions submitted by other players work and, hopefully, devise better solutions.
Extensions
This pattern can be extended to use proof-carrying data (PCD): a proof is produced by the player's machine to represent a valid execution of the simulation program on the player's solution. The solution, the claimed performance results (produced locally at the player's machine), and the associated proof is then submitted to the meta game loop. Instead of executing the simulation program on the submitted solution, the meta game loop verifies the proof. A successful verification validates the correctness of the submitted performance results.
This extension helps reduce the computation complexity of the meta game loop, because verifying the proof is usually less computationally expensive than re-executing the simulation program.
Additionally, solution-hiding can be achieved with a zero-knowledge proof. Here, only the proof and the claimed performance results are sent from the player's machine to the meta game loop. On top of the computation cost savings, the raw solution stays strictly on the player's machine. Effectively, the meta game loop is able to produce a ranking on solutions without knowing the solutions themselves.