hanabi: purpose-built five-seat table, and layout fitted to a real one #6

Merged
joeyr merged 1 commit from hanabi/table-save into main 2026-08-16 18:32:08 -05:00
Owner

Layout, measured instead of guessed

The first live run put every hand at radius ~10.4 — through the Poker table chip ring and most of the way to the middle, crowding the space the fireworks need. handPull 0.60 → 0.78, slot step 2.6 → 2.45, and the freed middle now holds the fireworks row and discard pile.

!hanabi where dumps the geometry the script is working from, because none of it can be checked outside the client and guessing twice is worse than measuring once. It reported the seat ring at radius 17.4.

A generated five-seat table

saves/Hanabi.json is five hand zones 72° apart, the two scripts, and nothing else — no deck, no cards, nothing draggable. Global spawns every card at deal time, and in a game where seeing your own hand ruins it, fewer loose objects is strictly better.

Generated rather than assembled in the client so the seat geometry agrees with LAYOUT by construction. A hand-placed zone stops agreeing the first time anyone nudges it.

Five seats, not eight, because eight was the crowding: 45° apart leaves 10.7 of arc against a 12.0 five-card hand, so neighbouring hands overlap. At 72° there is 17.1. Hanabi caps at five players, so the extra seats bought nothing.

Seat colours match TTS own fixed colour order, since getSeatedPlayers() returns that order and turn order comes straight from it. Swap in Orange or Teal and play silently hops across the table instead of going around it.

The clearance that matters

Cards land at radius 13.57; the hand zone inner face is at 14.67. They sit 1.09 outside the zone. Inside it, TTS adopts them into the hand and takes over their ordering — and slot order is exactly what a clue refers to, so that would quietly break the one thing the layout exists to protect.

Safety

Save scanned before committing per the root README: no local paths, no credentials, empty nicknames and descriptions, only URL is the Forgejo raw art endpoint. make check-normalized finally has something real to check, and passes.

### Layout, measured instead of guessed The first live run put every hand at radius ~10.4 — through the Poker table chip ring and most of the way to the middle, crowding the space the fireworks need. `handPull` 0.60 → 0.78, slot step 2.6 → 2.45, and the freed middle now holds the fireworks row and discard pile. `!hanabi where` dumps the geometry the script is working from, because none of it can be checked outside the client and guessing twice is worse than measuring once. It reported the seat ring at radius 17.4. ### A generated five-seat table `saves/Hanabi.json` is five hand zones 72° apart, the two scripts, and **nothing else** — no deck, no cards, nothing draggable. Global spawns every card at deal time, and in a game where seeing your own hand ruins it, fewer loose objects is strictly better. Generated rather than assembled in the client so the seat geometry agrees with `LAYOUT` by construction. A hand-placed zone stops agreeing the first time anyone nudges it. **Five seats, not eight**, because eight was the crowding: 45° apart leaves 10.7 of arc against a 12.0 five-card hand, so neighbouring hands overlap. At 72° there is 17.1. Hanabi caps at five players, so the extra seats bought nothing. **Seat colours match TTS own fixed colour order**, since `getSeatedPlayers()` returns that order and turn order comes straight from it. Swap in Orange or Teal and play silently hops across the table instead of going around it. ### The clearance that matters Cards land at radius 13.57; the hand zone inner face is at 14.67. They sit **1.09 outside the zone**. Inside it, TTS adopts them into the hand and takes over their ordering — and slot order is exactly what a clue refers to, so that would quietly break the one thing the layout exists to protect. ### Safety Save scanned before committing per the root README: no local paths, no credentials, empty nicknames and descriptions, only URL is the Forgejo raw art endpoint. `make check-normalized` finally has something real to check, and passes.
hanabi: purpose-built five-seat table, and layout fitted to a real one
All checks were successful
lint / lua (pull_request) Successful in 18s
98f602040a
The first live run put every hand at radius ~10.4: through the stock Poker
table's chip ring and most of the way to the middle, crowding the space the
fireworks need. handPull goes 0.60 -> 0.78, which seats each hand next to its
owner, slot step 2.6 -> 2.45, and the freed middle now holds the fireworks row
and the discard pile instead of them fighting the hands for space.

Those numbers are fitted rather than guessed. `!hanabi where` dumps the geometry
the script is working from -- hand zone transforms and the computed position of
every slot -- because none of it can be checked outside the client, and guessing
twice is worse than measuring once. It reported the seat ring at radius 17.4,
which is what the new constants are relative to.

The table itself is generated, not assembled in the client. saves/Hanabi.json is
five hand zones 72 degrees apart, the two scripts, and nothing else: no deck, no
cards, nothing draggable. Global spawns every card at deal time, and in a game
where seeing your own hand ruins it, fewer loose objects is strictly better.
Generating it also means the seat geometry agrees with LAYOUT by construction,
where a hand-placed zone stops agreeing the first time anyone nudges it.

Five seats rather than the Poker table's eight because eight is what was
crowding the hands: seats 45 degrees apart leave 10.7 of arc and a five-card
hand spans 12.0, so neighbouring hands overlap. At 72 degrees there is 17.1 and
they never touch. Hanabi caps at five players anyway, so the extra three seats
bought nothing.

The seat colours are chosen and ordered to match TTS's own fixed colour order,
because getSeatedPlayers() returns that order and turn order comes straight from
it. Swap in Orange or Teal and play silently starts hopping across the table
instead of going around it.

One clearance is worth stating because it is not obvious: cards land at radius
13.57 and the hand zone's inner face is at 14.67, so they sit 1.09 outside the
zone. Inside it, TTS adopts them into the hand and takes over their ordering --
and slot order is exactly what a clue refers to, so that would quietly break the
one thing the whole layout exists to protect.

Save scanned before committing, per the root README: no local paths, no
credentials, empty nicknames and descriptions, and the only URL is the Forgejo
raw art endpoint. make check-normalized now has something real to check and
passes.

Co-Authored-By: Claude Opus 5 (1M context) <noreply@anthropic.com>
joeyr merged commit f392b617ee into main 2026-08-16 18:32:08 -05:00
Sign in to join this conversation.
No reviewers
No labels
No milestone
No project
No assignees
1 participant
Notifications
Due date
The due date is invalid or out of range. Please use the format "yyyy-mm-dd".

No due date set.

Dependencies

No dependencies set.

Reference
joeyr/tts-games!6
No description provided.