# Tag — one game of chasey across the whole world

## overview.md
```yaml
id: tag
title: Tag — one game of chasey across the whole world
area: client
summary: Playground tag as a core mechanic: opt in on your account, one player is it everywhere at once, run up beside another tag player and they're it — a white glove over the it's head, green over everyone playing, a line under the health bar saying who is it, a 20 s no-butcher-back, a random new it when the it player vanishes, and a per-Area switch for places where the game does not continue.
repo: land-of-lor (game/ — director, world, client; tools/hub-ui; builder/; site/)
depends_on: ["mini-games","world-map-and-portals","connection-and-sync"]
parked: false
standing: Live and signed off 2026-09-11; the family's play is the test now.
```

## Where this stands (2026-09-13)

Signed off by Kris on 2026-09-11 ("that is excellent") — the line in the sand at APK v30.
The six pieces from his voice prompt were built in order that day: the opt-in, the director's
game, the Area's sensor, the glove and the heart, Areas without tag, the verifier and the deploy
(`docs/handoff/tag.md`). Ideas held, not started: a tag-only Area, sounds for the tag and the
pick, a wider "who is online" list on the account page.
No open issues. Past task files (to 2026-09-13): `workshop/historic-docs/epics/tag/tasks/`.

## What this is

Kris, by voice, 2026-09-11 — one prompt, planned in full before a line was written (the plan
is the six tasks here). His words, lightly ordered:

> My kids Willow and Rah have been playing it lots already, and what we love to play in it
> already is **tag** — we just manually run up to each other and go "you're it". The girls love
> that so much that I want to make it completely core. And architecturally it should be very
> **decoupled** from everything else.

> It's **opt-in**, on the accounts page — when they create their account, a final question:
> do you want to play tag with everyone? And if you're logged in and go to the account page,
> we now have our first account setting: a toggle that makes that really clear, and under it
> how many people are playing tag now.

> The icon is a **hand — really a big white mitten**. Make a 3D object of it, shown as a still.
> Everyone playing tag has a green one above their head, about half the size of their head.
> The person who is it has a larger white one. Under the health bar the white glove, and next
> to it "you are it", or the name of who is. Tap the glove and it says how many are playing.

> If you're it and you're in a cell adjacent to another player, that player becomes it. And
> you **can't get the butcher back** for twenty seconds. If someone goes offline, "such and
> such is offline", then "choosing a new player to be it", then randomly pick one — they get a
> message, "you've been selected to be it in tag". One game for all players across the whole
> world, across portals — with a flag on Areas that says whether the tag game continues there.
> And keep a log somewhere of who tagged whom, when.

> Also, unrelated: the health bar has a little diamond on it — change that to a **heart**.

## Vocabulary

- **It** — the one player, anywhere in the world, holding the white glove. Alone, you are it.
- **The butcher** — the previous it, who cannot be tagged back for 20 s after passing it on.
- **Playing (now)** — online, opted in, and standing in an Area where the game continues.
  The count under the toggle and behind the glove.
- **The tag lands** — every Area whose "Tag continues here" is Yes: all of them, unless an
  author says otherwise in the editor.

## The rules, as built

- Opt-in is **off by default** — a true opt-in. Every account starts out not playing and
  turns it on from the account page. *(2026-09-12: the sign-up's last question is gone —
  Kris: "off by default and an explicit enable via the Accounts page"; `platform-sign-in`.
  The account page is now the one place, for email and platform accounts alike.)*
- The it player's body on a cell **beside** another tag player's (diagonals included, same
  layer) passes it. The butcher is locked out for 20 s; from 5 s in, while the two stand
  beside each other, both see "Can't get the butcher back for N s". A fresh it **catches their
  breath** for 2 s before they can tag — so three players standing together do not pass it
  round twenty times a second with nobody able to react.
- **Doors out of the tag lands** (Kris's call, plan review): the it player is **refused** while
  somebody else is playing — "You're it! Tag someone before you leave the tag lands." Anyone
  else playing is asked first: "Going through to X takes you out of the tag game. Go anyway?"
  Inside a no-tag Area, a tag player is not playing (their strip says "Tag can't follow you
  here"); back out through a door, they are.
- **When the it player goes away**: 60 s unbound everywhere (Kris's call: match the moment the
  body starts to fade for everyone) or an opt-out at once → "Name is offline" / "Name is no
  longer playing tag" for 8 s → "Choosing a new player to be it" for 6 s → one of those
  playing, at random, who is told "You've been selected to be it in tag". A return during the
  beats cancels them. Nobody to choose → nobody is it until somebody plays.
- A deploy's restart keeps who is it, and does not call anyone offline until the Areas have
  reported and two minutes have passed.
- The log: `tag_events` — `tagged`, `became_it`, `selected`, `it_gone` — one row per event,
  by account id. No UI; `psql` reads it.

## The two ways of being gone

Tag's offline rule hooks into what the game already does when a player's connection goes, so
here is that, in one place (Kris asked for it, 2026-09-11). "Online" means a game socket is
bound to your body in some Area.

| What | When | What everyone sees |
|---|---|---|
| The client notices a stall | 6 s without a frame | "Reconnecting…", and it re-joins for up to 15 s |
| **Away** | the socket is gone — at once on a clean close, after **90 s of silence** for a phone that simply vanished | the body stands where it was, no longer blocking a cell; **it starts to fade at 60 s** and is gone from the wire at 80 s; it is back the instant its player is |
| **Gone from the Area** | nobody bound: at once on a deliberate leave, after a 60 s grace on a drop | the Area shuts down; the body lives in the saved state; where you reopen is the last Area within ten minutes (or always, where "comes back where they were" is on), else home |
| The director's own socket | pinged every 30 s, cut after a missed one | nothing — the game socket is what a player feels |

**Tag's offline rule**: the it player is *gone* when no Area has reported them bound for
**60 s** (`TAG_OFFLINE_MS`, env-overridable) — the same moment their body starts to fade, so
what the kids see agrees with the game. Worst case for a vanished phone: 90 s of silence plus
60 s. Until the Area notices the silence, that body still counts, can still be tagged, and can
still tag. The count of "people playing now" reads presence with a 15 s grace, so a walk
through a door never moves it.

## Decisions taken without asking (assumptions)

- The sign-up question is its own last screen, after the character, with the mitten beside it.
- The it player alone at a no-tag door is asked like anyone (there is no game to abandon).
- Tag rides the **game channel**, never the director socket: an old client's director poller
  keeps every unknown frame for ever, and the director's public listener also serves sockets
  that never signed in. No protocol bump — every change is additive.
- Only a client that plays tag draws any of it; everyone else's game is exactly as it was.

## Non-goals (for now)

Teams, scores, a leaderboard, tag across several servers, a tag-only Area, sounds.

## Where it lives

`game/director/src/tag.ts` (the game), `game/world/tag_rules.gd` + `area_server.gd` (the
sensor and the mirror), `game/world/client/` (`humanoid_node.gd` the gloves, `ui/hud.gd` the
strip and the heart, `client_main.gd` the countdown and the door, `ui/account_flow.gd` the
question and the setting), `tools/hub-ui/editor.js` (the Area flag). The handoff is
`docs/handoff/tag.md`; the game's own notes are in `game/README.md`, "Tag".

## deliverables (1)

- #26 — Tag — one game of chasey across the whole world (2026-09-11) — /deliverables/26