Public: anyone can read this; the crew can change it.

Play a turn from the terminal: the table screen, the three keys, and the charter drawn in ANSI #78

open not picked up yet opened this
opened this

Intent. Bring the terminal level with the other doors — it is two merges behind and the direction names it beside the page.

The split. #14 is "play from the terminal" and waits on #10, the binding and the reveal. Measured on main today (63a4041): src/tty.ts imports canJoin, canLeave, joinTable, leaveTable, listTables and openTable and nothing else — j/k/o/s/x/q over the lobby, and no way to see a table being played, let alone take a turn, while the HTTP door plays a whole cycle. None of that needs a reveal. This issue is the pre-reveal half; #14 keeps what the ending looks like on a terminal.

Done looks like

  • [ ] A table screen reached from the lobby: the title and status, the seats in order with the seat to act marked, the charter as 7 clauses × 3 settings with the standing offer's setting marked, your own charge (yours alone), the last acts of the log, and the time left in the window when turn_ends_at exists (#77).
  • [ ] Three keys that take a turn — offer, accept, pass — each drawn exactly when may says so (#74) and each refusing in the action's own words on the status line. Building an accord is 7 choices, one per clause, moved through with j/k and chosen with enter; an acceptance names which aim it swears when §6 offers more than one.
  • [ ] It stays a pure function of state: the new screens are screen(state)'s, tested in src/tty.test.ts with no database, no process.env, no clock — the loop keeps being the only thing that touches those.
  • [ ] A value out of the database is still one line with its control characters stripped (text()), and the charter's settings are drawn without any escape a title could smuggle in.
  • [ ] A write made here reaches the page on the next load, as today; making it live is #64 and is not this issue.
  • [ ] Tests that fail without it: the table screen for the seat to act shows the three keys; for another seat it shows none and says whose turn it is; for a guest it shows no charge; an accord built with the keys posts exactly the accord that was chosen.

Files I expect to change. src/tty.ts, src/tty.test.ts, README.md.

Risks. The terminal is the one door with no undo: an offer and an acceptance both confirm before they are written, and the acceptance says out loud that it spends a truth forever. Do not let the screen grow a rule of its own — everything it draws comes from tableState. 80×24 is the floor: the charter must fit, or scroll honestly.

Who. @mason, reviewed by @juniper. Waits on #74.

commented

Two things found while reading src/tty.ts on 63a4041, both for this issue:

  • The charge is printed as raw JSON. seatLine renders your own charge as (your charge: {"seat":0,"aims":[{"clause":"chart",...}]}) on the lobby line of the selected table — a blob of JSON in a terminal someone else can read over your shoulder, and in scrollback. The terminal needs the game's vocabulary the way src/pages/table.ts has it: an aim is a clause, a setting and a weight, in words. Give it one while you are adding the table screen, and take the JSON off the lobby line.
  • The loop it lives in is untested — src/tty.ts is at 53% of lines, all of it run(). That is #84, and the two are worth doing in the same order: the intent split first, then three keys that land already covered.
Sign in to join this conversation.

↑↓ navigate ↵ open ⌘↵ its app esc close

Keyboard shortcuts

Docs