{
  "$schema": "https://pointcast.xyz/for-agents",
  "generatedAt": "2026-10-22T18:42:09.096Z",
  "name": "Kelp",
  "status": "playable browser game",
  "human": "https://pointcast.xyz/kelp",
  "image": "https://pointcast.xyz/images/kelp/og.png",
  "intent": "A snake game with 1980s innocence: a kelp strand grows across a portrait grid by eating plankton, the frame is the wall, each stage stands a new rock pattern, and the game keeps a mood with the player.",
  "direction": "Brief by Michael Hoydich, 2026-10-22: 80s innocence, the joy of the compute and flow, mood-state symbiosis, mobile and full screen, audio-visual multimedia, Atari and Commodore inspired, rendered modern. Thread 2 of 5 after Breakwater; siblings are Tideline, Soft Landing, Crosswalk and Driftwood.",
  "credits": {
    "director": "Michael Hoydich",
    "build": "Claude Code, 2026-10-22",
    "note": "Original code, art, and synthesized sound. No ROMs, no emulation, no copyrighted sprites or recordings. Machine names are referenced as tributes. The pixel font, palettes and mood model are shared with Breakwater."
  },
  "game": {
    "genre": "snake / nibbler",
    "field": {
      "width": 288,
      "height": 396,
      "columns": 24,
      "rows": 32,
      "haven": {
        "c0": 9,
        "c1": 14,
        "r0": 18,
        "r1": 29
      }
    },
    "strand": {
      "startLength": 4,
      "growthPerPlankton": 1,
      "growthPerGolden": 2,
      "turnQueue": 2
    },
    "scoring": {
      "plankton": "10 x stage number, x1.5 at FLOW, x2 at RUSH",
      "golden": "3x a plankton, only in RUSH, times out",
      "stageClear": "the strand reaches the target length"
    },
    "targets": [
      {
        "stage": 1,
        "length": 12
      },
      {
        "stage": 2,
        "length": 16
      },
      {
        "stage": 3,
        "length": 20
      },
      {
        "stage": 4,
        "length": 24
      },
      {
        "stage": 5,
        "length": 28
      },
      {
        "stage": 6,
        "length": 32
      },
      {
        "stage": 7,
        "length": 36
      },
      {
        "stage": 8,
        "length": 40
      }
    ],
    "stages": [
      "open",
      "posts",
      "bars",
      "nameplate",
      "reef",
      "gates",
      "counter"
    ],
    "stagesNote": "Patterns cycle. The nameplate spells the chosen machine and the counter spells the stage number, both from the 3x5 pixel font at three cells per pixel, with a doorway cut through any enclosed loop. The mood density thins a pattern; it never adds rocks.",
    "tick": {
      "baseSeconds": 0.17,
      "minimumSeconds": 0.07,
      "rule": "Faster each stage, multiplied by the mood speed, 30% faster for a short boost after a golden plankton."
    },
    "lives": 3,
    "extraLifeEveryStages": 3,
    "collision": "The frame, a rock or the strand itself costs a life and the next strand starts over at the start length on the same stage. On CALM there are no lives; a collision only trims the strand.",
    "localBestScore": true
  },
  "moodSymbiosis": {
    "labels": [
      "DAWN",
      "FLOW",
      "RUSH",
      "DRIFT"
    ],
    "mapping": {
      "paddle": "each plankton eaten in an unbroken run",
      "brick": "each plankton",
      "loss": "a collision",
      "wave": "a stage clear"
    },
    "meaning": {
      "DAWN": "warming up: cool palette, slow major arpeggio, the strand bands hold still",
      "FLOW": "an unbroken run: bright palette, the bands cycle, plankton worth half again as much",
      "RUSH": "high energy: hot palette, raster bars, faster ticks, golden plankton worth triple that speeds you up",
      "DRIFT": "after collisions: softened palette, slower ticks, thinner rocks next stage, a shorter strand on the next life"
    },
    "playerSide": {
      "dial": [
        {
          "id": "calm",
          "label": "CALM",
          "baseline": 0.22,
          "cap": 0.62,
          "noLives": true
        },
        {
          "id": "play",
          "label": "PLAY",
          "baseline": 0.45,
          "cap": 1,
          "noLives": false
        },
        {
          "id": "rush",
          "label": "RUSH",
          "baseline": 0.66,
          "cap": 1,
          "noLives": false
        }
      ],
      "note": "The dial sets the baseline the game relaxes toward. Plankton push energy up, collisions pull calm down, time restores it."
    },
    "gameSide": [
      "tick rate",
      "plankton value",
      "obstacle density",
      "start length",
      "music tempo and scale",
      "palette temperature and band cycling",
      "particle density",
      "raster bars",
      "golden plankton"
    ],
    "memory": "The session mood tape and the last energy are kept in this browser under kelp:v1 and the next session starts most of the way back. After a game, the current label is written to the sitewide pc:mood key (chill, flow, hype, quiet) so the town carries it."
  },
  "machines": [
    {
      "id": "xl",
      "name": "ATARI 800XL",
      "year": 1983,
      "soundChip": "POKEY",
      "prompt": "READY",
      "field": "#2545a8",
      "border": "#000000",
      "text": "#a9b9f5",
      "bands": {
        "red": "#d84a3a",
        "orange": "#e7893a",
        "green": "#67b24a",
        "yellow": "#efd25a"
      },
      "raster": [
        "#d84a3a",
        "#e7893a",
        "#efd25a",
        "#67b24a",
        "#3aa0c8",
        "#6b5ad8",
        "#b85ab0"
      ]
    },
    {
      "id": "c64",
      "name": "COMMODORE 64",
      "year": 1982,
      "soundChip": "SID",
      "prompt": "READY.",
      "field": "#3e31a2",
      "border": "#7c70da",
      "text": "#7c70da",
      "bands": {
        "red": "#c46c71",
        "orange": "#dd8855",
        "green": "#a9ff9f",
        "yellow": "#edf171"
      },
      "raster": [
        "#813338",
        "#c46c71",
        "#edf171",
        "#a9ff9f",
        "#75cec8",
        "#7c70da",
        "#8e3c97"
      ]
    }
  ],
  "audio": {
    "engine": "Web Audio API, synthesized at runtime, started by the first tap or key",
    "voices": "Square and triangle oscillators with short envelopes. The C64 mode adds a resonant low-pass sweep in the SID spirit; the 800XL mode keeps raw squares with a noise burst, in the POKEY spirit.",
    "music": "A slow eighth-note swell over a four-chord loop, two bars per chord. Tempo and scale follow the mood: major at DAWN, lydian-bright at FLOW, minor at RUSH, sparse at DRIFT.",
    "sfx": "Each plankton plays one short note that climbs a pentatonic scale with the strand's length, an octave every five plankton. A low thud on collision. Golden plankton, stage clear and extra life are separate cues.",
    "haptics": "short vibration on plankton and collisions where supported"
  },
  "controls": {
    "touch": "Swipe anywhere on the field to turn; keep the finger down and swipe again to turn again. Tap to start, to skip the boot, and to resume.",
    "keyboard": "Arrows or W A S D turn (the first one starts the swim), Space starts, P pauses, F toggles full screen, M toggles sound, C toggles the CRT overlay, 1 and 2 switch machines, 3 cycles the dial.",
    "fullscreen": "The FULL button uses the Fullscreen API on the stage element. iOS Safari lacks it for pages, so the stage fills the viewport instead.",
    "mobile": "Portrait first, 100dvh stage, touch-action none on the field, pauses when the tab is hidden."
  },
  "accessibility": [
    "CRT scanlines can be switched off",
    "reduced-motion preference stops band cycling and raster movement and lowers particles",
    "a polite live region announces stage, life and collision events",
    "no sound is required to play"
  ],
  "caveats": [
    "Scores, settings and the mood tape are browser-local only.",
    "The machine palettes are tributes chosen to read on modern displays, not chip-accurate output.",
    "The boot screens are affectionate tributes with PointCast wording, not copies of the original ROM text."
  ],
  "links": {
    "human": "https://pointcast.xyz/kelp",
    "json": "https://pointcast.xyz/kelp.json",
    "research": "https://github.com/mhoydich/pointcast/blob/main/docs/notes/2026-10-22-kelp-notes.md",
    "breakwater": "https://pointcast.xyz/breakwater",
    "games": "https://pointcast.xyz/games/",
    "play": "https://pointcast.xyz/play",
    "pointcast": "https://pointcast.xyz/"
  }
}