Skip to content

ajuggler/midnight-games

Folders and files

NameName
Last commit message
Last commit date

Latest commit

 

History

33 Commits
 
 
 
 
 
 
 
 
 
 
 
 

Repository files navigation

Midnight Games

This repository is an ongoing project exploring how games built on Midnight can model real-world human interactions in which selective disclosure and zero-knowledge proofs play an important role. Midnight is described in its developer documentation as a privacy-first blockchain focused on selective disclosure, zero-knowledge proofs, and confidential data handling.

Our first project is Counterfeit Compass, described below.

Possible directions for future development include:

  • hidden-alliance games
  • anti-coercion governance games
  • credential-and-bluff games

Counterfeit Compass

Counterfeit Compass is a two-player game of incomplete information in which bluffing is possible, but risky: a challenged claim must be backed by a ZK proof, and verification failure is fatal.

Both players start with zero charge, which increases or decreases as they take turns moving on a 5×5 board according to precise rules.

Objective: the first player to reach a charge of 5 wins.

Runtime modes

There are currently two ways to run the game:

Backend mode (default)

Uses a trusted Express referee.

  1. Install dependencies: npm --prefix frontend install npm --prefix backend install
  2. In one terminal, rebuild the frontend on changes: npm --prefix backend run dev:frontend
  3. In another terminal, launch the backend: npm --prefix backend run dev
  4. Open http://localhost:3000.

Midnight mode

This serves the same React app, but expects the trust-critical game flow to come from a Midnight contract/client adapter instead of the backend referee.

  1. Install dependencies: npm --prefix frontend install npm --prefix backend install
  2. Set the required frontend environment variables before building: VITE_GAME_MODE=midnight VITE_MIDNIGHT_STAKE=<stake> VITE_MIDNIGHT_PAYOUT_ADDRESS=<payout-address>
  3. Wire the generated Midnight bindings/adapter into frontend/src/midnight/contract.ts.
  4. In one terminal, rebuild the frontend on changes with the Midnight env vars set: VITE_GAME_MODE=midnight VITE_MIDNIGHT_STAKE=<stake> VITE_MIDNIGHT_PAYOUT_ADDRESS=<payout-address> npm --prefix backend run dev:frontend
  5. In another terminal, launch the backend as a static-file host: COMPASS_GAME_MODE=midnight npm --prefix backend run dev
  6. Open http://localhost:3000.

About Midnight client layer

This repository has a small Midnight client layer under frontend/src/midnight. It is responsible for:

  • keeping each player's private board, salts, and local Merkle-tree mirror in browser-local storage;
  • preparing witnesses for Compact circuits;
  • mapping contract ledger state into the UI state used by the React app;
  • replacing the "trusted" backend routes with Midnight transaction/query wrappers when Midnight mode is enabled.

Game description and setup

Both players begin with the same initial field of directions (N, E, S, and W) on a 5×5 square grid.

board showing default directions

A marker on each player's grid indicates that player's current position.

Setup:

  • both players start at the center;
  • both players start with charge 0;
  • both players begin from the same initial grid and may modify up to 3 cells.

The game starts after both players confirm their modified cells. Each grid remains fixed for the duration of the game. Each player can see only their own grid.

Example: each player has chosen a grid of directions (modified directions shown in blue):

two boards with modified directions

Position and dominant direction

A player's position determines a dominant direction, defined as the most frequent direction among the arrows immediately above, to the right, below, and to the left of the player's current position.

If there is a tie among these four arrows, the dominant direction is the direction of the arrow at the player's current position.

The dominant direction of one player determines the movement of the other player, as explained below.

Movement and charge

Charge changes as players move across the grid.

  1. Players take turns moving, and each move consists of exactly one square up, right, down, or left; that is, one of N, E, S, or W.

  2. The player whose turn it is to move, say Player A, requests a reading of the dominant direction associated with Player B's current position, as defined above. This reading determines the direction in which Player A must move.

    Note that Player B is not required to tell the truth about the dominant direction at their current position.

  3. After moving, Player A's charge may increase or decrease as follows. Let M denote Player A's direction of movement, and let D denote the direction of the arrow on the destination square.

    Player A's charge:

    • increases by 2 if D coincides with M;
    • increases by 1 if D is 90 degrees clockwise from M;
    • decreases by 1 if D is opposite to M;
    • remains unchanged if D is 90 degrees counterclockwise from M.

As stated above, the first player to reach a charge of 5 wins.

  1. Before Player A makes the move indicated by Player B's reading, Player A may challenge Player B's reading. In that case, Player B must submit a ZK proof attesting that the reading is correct. If verification of Player B's proof:

    • fails, or no proof is submitted, then Player A wins the game;
    • succeeds, then Player A loses 3 units of charge.
  2. Movement at the board edges follows the Pac-Man (or toroidal) convention: if a player is at the top edge of the board, then moving up (N) places the player at the bottom of the same column, and similarly for the other three edges.

    The same convention is used to determine the dominant direction. For example, if a player is at the top edge, then the arrow "above" is the arrow at the bottom of the same column.

About

Exploring privacy solutions through games.

Resources

Stars

Watchers

Forks

Releases

No releases published

Packages

 
 
 

Contributors

Languages