compw00tergame designer
2026-06-20 2026-06-20-compw00ter-hero-builder-design.md

compw00ter — Hero Builder (Design Spec)

Date: 2026-06-20 Status: Awaiting review Scope of this spec: The backend Hero Builder admin tool — the first buildable piece. The wider game design is captured below as context, but is not built in this phase.


1. Game vision (context, not built yet)

compw00ter is a web-based multiplayer game for an annual 10-friend LAN party. Two modes are planned; we build co-op first, PvP brawler is deferred.

Co-op mode — Keep The LAN Alive: Ten friends vs. entropy. Players don't fight each other — they fight everything threatening to end the LAN party. Goal: survive as long as possible. Score = party uptime.

Decisions locked during brainstorming:

  • Genre: real-time, turn-less scramble (cooldown-driven), not strict turns.
  • Tech (split): the Hero Builder is a PHP web app served by the existing Apache (no new port). The game engine is a separate Node.js + WebSocket server on port 6767, played over the LAN. They share one SQLite database file: PHP writes hero content, Node reads it at match time.
  • Core threat: an Incident Queue with limited slots (~6–8). Incidents have a type (Tech / Social / Supply / Chaos), a size (small / big), and a countdown.
    • Small fire: one matching hero ability clears it.
    • Big fire: several heroes must hit it together before its timer expires.
  • Lose condition: queue overflow. Expired incidents lock in and clog their slot; when a new incident has no free slot, the party collapses.
  • Bosses: named social forces that target players, not just the board. E.g. The Wife (removes a player until rescued), The Martin (pulls several players out; +morale, −beer). A rescue/cover path exists so removal isn't always permanent.
  • Heroes (the soul): each hero has a superpower and a self-destruct. To get stronger you indulge (beer / edibles / energy drink) for buffs, but indulging pushes you into a state (Drunk / High / Wired / Tilted). When a hero hits their trigger state, their game-ruining trait fires. e.g. b0n1 goes High → spawns a Malware (Chaos) incident.
  • Light resources: Beer/Supplies (spent indulging, drained by bosses) and Morale (soft modifier).
  • Screens: own-screen-only — each player sees the shared board + their own hero panel on their own device.

The heroes are the content everything depends on, so the Hero Builder is built first.


2. Hero Builder — what we build now

A PHP web application, served by the existing Apache under the site web root (like booking/, racecloud/), to create, edit, and delete heroes and their abilities/traits, plus the shared game vocabularies they reference. Data persists in a SQLite database file. The eventual Node game engine reads the same SQLite file — the database is the contract between the PHP builder and the Node runtime.

2.1 Goals

  • Author a roster of heroes, each with several abilities and several traits.
  • Edit the shared vocabularies (incident types, vice states, vices→states) since the design is still fluid.
  • Fast, friendly, single-page admin UI usable on a laptop.
  • Clean data model the future game runtime can consume directly.

2.2 Non-goals (this phase)

  • The game loop / real-time WebSocket runtime.
  • PvP brawler mode.
  • Authentication beyond a simple optional shared token (this is a local/LAN admin tool).
  • Player accounts, matchmaking, lobbies.

3. Data model (SQLite)

heroes
  id            TEXT PRIMARY KEY        -- slug, e.g. "b0n1"
  name          TEXT NOT NULL
  tagline       TEXT                    -- short flavour/bio
  based_on      TEXT                    -- which real friend
  color         TEXT                    -- hex theme colour
  created_at    TEXT
  updated_at    TEXT

abilities
  id            INTEGER PRIMARY KEY
  hero_id       TEXT NOT NULL REFERENCES heroes(id) ON DELETE CASCADE
  name          TEXT NOT NULL
  description   TEXT
  counters_type TEXT      -- references incident_types.name
  target        TEXT      -- 'small' | 'big' | 'boss' | 'any'
  power         INTEGER   -- effect magnitude (clear / cut timer / contribute X)
  cooldown      INTEGER   -- seconds
  boosted_while_indulging INTEGER  -- 0/1
  sort_order    INTEGER

traits
  id            INTEGER PRIMARY KEY
  hero_id       TEXT NOT NULL REFERENCES heroes(id) ON DELETE CASCADE
  name          TEXT NOT NULL
  description   TEXT
  trigger_state TEXT      -- references vice_states.name
  effect        TEXT      -- what bad thing happens (free text in v1)
  severity      TEXT      -- 'minor' | 'major' | 'catastrophic'
  sort_order    INTEGER

-- Editable vocabularies
incident_types  (id INTEGER PK, name TEXT UNIQUE, sort_order INTEGER)
vice_states     (id INTEGER PK, name TEXT UNIQUE, sort_order INTEGER)
vices           (id INTEGER PK, name TEXT UNIQUE, state TEXT, sort_order INTEGER)  -- state -> vice_states.name

Seeded defaults:

  • incident_types: Tech, Social, Supply, Chaos
  • vice_states: Drunk, High, Wired, Tilted
  • vices: Beer→Drunk, Edibles→High, Energy Drink→Wired

Seed heroes (starter examples, fully editable):

  • Eradicus — ability Fix The Internet (counters Tech, target any, power high, cooldown ~30s); trait Perfectionist Meltdown (trigger Tilted → briefly freezes own abilities, severity major).
  • b0n1 — ability Quick Patch (counters Tech, target small, cooldown ~20s); trait Malware Drop (trigger High → spawns a Malware/Chaos incident, severity catastrophic).

These exist so the tool opens with working examples; the user edits/replaces them.


4. Architecture

The repo splits into a PHP builder (built now) and a Node engine (built later), sharing one SQLite file.

compw00ter/                         -- served by Apache at https://.../compw00ter/
  index.php                       -- hero list / dashboard
  hero_edit.php                   -- create/edit one hero (identity + abilities + traits)
  hero_save.php                   -- POST handler: validate + persist (then redirect)
  hero_delete.php                 -- POST handler: delete (cascade)
  vocab.php                       -- edit incident types / vice states / vices
  classes/
    Database.php                  -- PDO SQLite connection (singleton), WAL mode
    HeroRepository.php            -- CRUD for heroes + nested abilities/traits
    VocabRepository.php           -- CRUD for the editable vocabularies
  includes/
    config.php                    -- DB path, app constants
    bootstrap.php                 -- session start, CSRF helpers, autoload
    header.php / footer.php       -- shared XHTML layout (project palette)
  sql/
    schema.sql                    -- table definitions
    seed.sql                      -- vocab defaults + Eradicus & b0n1 seeds
  assets/
    style.css                     -- styling (project palette)
    builder.js                    -- progressive enhancement: inline add/remove rows
  data/                           -- NOT web-accessible (.htaccess deny)
    compw00ter.db                   -- shared SQLite file (created on first run)
    .htaccess                     -- Require all denied
  engine/                         -- Node game engine (LATER, not this phase)
    package.json, server.js ...   -- WebSocket runtime on port 6767, reads ../data/compw00ter.db
  docs/superpowers/specs/...
  • Vanilla PHP 8.4, PDO SQLite, prepared statements throughout — matches the house style of the other apps here (booking/, racecloud/).
  • The SQLite file lives in data/ with an .htaccess deny so it is never web-downloadable.
  • WAL journal mode on the DB so the PHP builder and the Node engine can read/write concurrently without lock contention.
  • The Node engine (built in a later phase) lives in engine/ with its own package.json and reads the same DB via better-sqlite3 (already verified to compile here).

4.1 Request flow (no JS required)

Form-POST, server-render, redirect — works fully without JavaScript (progressive enhancement, per house style):

  • index.php — list heroes; links to edit; “New Hero”.
  • hero_edit.php?id=… — renders the hero form. Abilities and traits are repeatable fieldset rows.
  • hero_save.php — CSRF-checked POST; validates; upserts hero + replaces its abilities/traits inside one transaction; redirects back.
  • hero_delete.php — CSRF-checked POST; cascade delete; redirect.
  • vocab.php — edit incident types / vice states / vices (POST + redirect).

builder.js only enhances: add/remove ability & trait rows client-side without a round-trip. With JS off, an "Add row" submit re-renders the form with one more empty row.

4.2 Validation & security

  • All state-changing actions are POST with a CSRF token (session-based).
  • Prepared statements for every query; output escaped with htmlspecialchars (XSS).
  • Server-side validation: hero name required; ability counters_type must be a known incident type; trait trigger_state must be a known vice state; numeric fields coerced/bounded.
  • Builder is unauthenticated for local/LAN admin use in v1 (noted in Open Questions); the data/ deny rule is the key protection.

4.3 UI

  • Dashboard: hero cards/list + “New Hero”; link to Vocabularies.
  • Hero editor: identity fields; an Abilities section (repeatable rows: name, description, counters-type, target, power, cooldown, indulge-boost); a Traits section (repeatable rows: name, description, trigger-state, effect, severity); Save / Delete.
  • Dropdowns for counters_type, target, trigger_state, severity are populated live from the vocabularies.
  • XHTML 1.1 Strict, accessible labels, project palette (warm orange #FF7F4F, nice blue #4A9FCC).

5. How to run

  • Builder: nothing to start — it's PHP served by the existing Apache at https://playground.crisprain.co.uk/compw00ter/. First load creates data/compw00ter.db from schema.sql + seed.sql. (If the first load throws "could not find driver", reload web PHP once: sudo systemctl reload php8.4-fpm apache2.)
  • Engine (later): cd engine && npm install && node server.js → WebSocket runtime on port 6767, reading the shared DB.

6. Open questions / deferred

  • Auth: ship unauthenticated for local use now; optional shared-token later.
  • Trait effect is free text in v1; may become structured once the game runtime defines concrete effect types.
  • Ability power semantics will be pinned down precisely when the incident engine is built.