Systems/Nuggets Game
44 / 67

06/2021Systems

Nuggets Game

A multiplayer terminal game in C: one server owns the maze and the gold, and streams each player only the sectors their line of sight reveals.

╌╌╌╌

A multiplayer command-line game of nuggets. A single server holds the maze, the gold piles, and every player's position; clients connect over sockets, send keystrokes, and receive the slice of the map their character can currently see. The game ends when the last pile is collected, and the player with the most gold wins.

The server is authoritative: it owns the grid, the set of gold piles and their values, and each connected player's location and purse. A client is a thin terminal that captures movement keystrokes, ships them to the server as short messages over a socket, and redraws whatever display string the server sends back. The two speak a small line-based protocol: a join message and per-keystroke moves upstream, a grid string and a status banner downstream. Every state change, whether a move, a pickup, or a join, happens on the server and fans out to the clients, so no two clients can disagree about where the gold is or who holds it. The client keeps no authoritative state of its own; if its socket drops, the server can drop that player without the rest of the game noticing.

Visibility comes down to a line-of-sight test. Each player sees only what their position reveals, and the maze uncovers gradually as they walk; a wall, once seen, stays drawn, but gold and other players show only while in view. A cell is visible from the player at when the straight segment is not interrupted by a wall. Walking the segment column by column, the row where it crosses column is

and the cell there — or, when is fractional, the pair of cells it falls between — must be open for the sightline to survive:

Algorithm:Visible(q,p,grid)\textsc{Visible}(q, p, grid) — can the player at qq see cell pp?
  1. 1
    input: player cell qq, target cell pp, the maze gridgrid
  2. 2
    for each column xx strictly between qxq_x and pxp_x do
  3. 3
    yqy+(pyqy)(xqx)/(pxqx)y \gets q_y + (p_y - q_y)\,(x - q_x)/(p_x - q_x)
  4. 4
    if yy is an integer then
  5. 5
    if grid[x][y]grid[x][y] is a wall then return false
  6. 6
    else if grid[x][y]grid[x][\lfloor y \rfloor] and grid[x][y]grid[x][\lceil y \rceil] are both walls then return false
  7. 7
    for each row yy strictly between qyq_y and pyp_y, symmetric in xx, do
  8. 8
    if the crossing cell, or the pair it falls between, is wall then return false
  9. 9
    return true
The player (circle) sees the gold (diamond) along the solid sightline, which crosses only open cells. The dashed segment to a second spot passes through a wall cell (filled), so that spot stays hidden until the player moves to a new vantage.

The server runs this test from every player against every cell it might reveal, then sends each client the visible region merged with the walls that player has already discovered. Because the visible set is a function of position, it is recomputed the moment a player moves: the old vantage's sightlines no longer hold, gold that was occluded may come into view, and cells that were open may fall behind a corner. Recomputing per move, rather than caching a fixed field of view, is what lets the map unfold as the player explores and keeps every client's picture of the world honest.

The sightline reduces to a segment-versus-grid intersection — a geometric primitive doing the work of a game mechanic.

Collaborative project with Alphonso Bradham and Zimehr Abbasi.

References

  1. Project repository
  2. Reference notes: Geometric Primitives & Orientation

╌╌ END ╌╌