Files
hyper 8eff44712f feat(tabletop): add free-interaction layer (layer 3)
Add the interaction half of the sandbox: a held part and dialog stack as
UI state outside the game store, with pure helpers (interactionsFor,
dropPaths, pickPath, partFacings, nextFacing). PartPlacement is now
interactive (pick up, drag to move, click to cycle facing), and a drop on
a path with a stack-dialog interaction opens the deck dialog instead of
moving directly. DialogLayer renders the stack-inspector dialog whose
insert button issues a move. Add the dialog role, Setup.interactions, and
Package.dialogs to @tts/bgm, and declare the deck insert dialog in
games/poker.
2026-08-18 10:20:22 +08:00

163 lines
4.2 KiB
Markdown
Raw Permalink Blame History

This file contains ambiguous Unicode characters
This file contains Unicode characters that might be confused with other characters. If you think that this is intentional, you can safely ignore this warning. Use the Escape button to reveal them.
# Poker
A standard 52-card poker deck, laid out on a table with a draw pile and
community-card slots. Exercises the bgm loader's `$variants` expansion to
generate a full deck from a single part definition.
```yaml role=package
id: poker
title: Poker
designer: Public Domain
players: 9
language: en
include: ['./**/*.yaml']
```
## Parts
A single `card` part expanded into 52 cards by the `$variants` CSV. Each row
picks a cell from the `13×4` face sheet (`cards-13x4.jpg`) — 13 ranks across,
4 suits down. All cards share the same back from the `4×1` back sheet
(`back-4x1.png`).
```yaml role=part.card
face: ./cards-13x4.jpg
back: ./back-4x1.png
size: [63, 88, 0.3]
fillet: 2
$variants: ./cards.csv
```
```csv file=cards.csv
id,rank,suit,faceCrop,backCrop
string,string,string,[number;number;number;number],[number;number;number;number]
2s,2,spades,[0;0;13;4],[0;0;4;1]
3s,3,spades,[1;0;13;4],[0;0;4;1]
4s,4,spades,[2;0;13;4],[0;0;4;1]
5s,5,spades,[3;0;13;4],[0;0;4;1]
6s,6,spades,[4;0;13;4],[0;0;4;1]
7s,7,spades,[5;0;13;4],[0;0;4;1]
8s,8,spades,[6;0;13;4],[0;0;4;1]
9s,9,spades,[7;0;13;4],[0;0;4;1]
10s,10,spades,[8;0;13;4],[0;0;4;1]
js,J,spades,[9;0;13;4],[0;0;4;1]
qs,Q,spades,[10;0;13;4],[0;0;4;1]
ks,K,spades,[11;0;13;4],[0;0;4;1]
as,A,spades,[12;0;13;4],[0;0;4;1]
2h,2,hearts,[0;1;13;4],[0;0;4;1]
3h,3,hearts,[1;1;13;4],[0;0;4;1]
4h,4,hearts,[2;1;13;4],[0;0;4;1]
5h,5,hearts,[3;1;13;4],[0;0;4;1]
6h,6,hearts,[4;1;13;4],[0;0;4;1]
7h,7,hearts,[5;1;13;4],[0;0;4;1]
8h,8,hearts,[6;1;13;4],[0;0;4;1]
9h,9,hearts,[7;1;13;4],[0;0;4;1]
10h,10,hearts,[8;1;13;4],[0;0;4;1]
jh,J,hearts,[9;1;13;4],[0;0;4;1]
qh,Q,hearts,[10;1;13;4],[0;0;4;1]
kh,K,hearts,[11;1;13;4],[0;0;4;1]
ah,A,hearts,[12;1;13;4],[0;0;4;1]
2d,2,diamonds,[0;2;13;4],[0;0;4;1]
3d,3,diamonds,[1;2;13;4],[0;0;4;1]
4d,4,diamonds,[2;2;13;4],[0;0;4;1]
5d,5,diamonds,[3;2;13;4],[0;0;4;1]
6d,6,diamonds,[4;2;13;4],[0;0;4;1]
7d,7,diamonds,[5;2;13;4],[0;0;4;1]
8d,8,diamonds,[6;2;13;4],[0;0;4;1]
9d,9,diamonds,[7;2;13;4],[0;0;4;1]
10d,10,diamonds,[8;2;13;4],[0;0;4;1]
jd,J,diamonds,[9;2;13;4],[0;0;4;1]
qd,Q,diamonds,[10;2;13;4],[0;0;4;1]
kd,K,diamonds,[11;2;13;4],[0;0;4;1]
ad,A,diamonds,[12;2;13;4],[0;0;4;1]
2c,2,clubs,[0;3;13;4],[0;0;4;1]
3c,3,clubs,[1;3;13;4],[0;0;4;1]
4c,4,clubs,[2;3;13;4],[0;0;4;1]
5c,5,clubs,[3;3;13;4],[0;0;4;1]
6c,6,clubs,[4;3;13;4],[0;0;4;1]
7c,7,clubs,[5;3;13;4],[0;0;4;1]
8c,8,clubs,[6;3;13;4],[0;0;4;1]
9c,9,clubs,[7;3;13;4],[0;0;4;1]
10c,10,clubs,[8;3;13;4],[0;0;4;1]
jc,J,clubs,[9;3;13;4],[0;0;4;1]
qc,Q,clubs,[10;3;13;4],[0;0;4;1]
kc,K,clubs,[11;3;13;4],[0;0;4;1]
ac,A,clubs,[12;3;13;4],[0;0;4;1]
```
## Board
A table with a draw pile on the left and five community-card slots across the
middle. The deck pile fans its stacked cards along a curve.
```yaml role=surface.board
id: poker
size: [600, 400]
layout:
- route: /deck
x: -250
y: 0
rotation: 0
stacking:
align: center
zStart: 0
#zEnd: 100
curve: M -50 -200 C 50 -150 450 -150 550 -200
- route: /community/:slot
candidates:
$variants: ./community.csv
```
```csv file=community.csv
slot,x,y,rotation
string,number,number,number
0,-100,0,0
1,-50,0,0
2,0,0,0
3,50,0,0
4,100,0,0
```
## Setup
Deal the whole deck facedown onto the draw pile (`poker:card` expands to every
card of that type, `facing: back`), then flip a flop onto the community slots
and stand a couple of drawn cards on their bottom edge.
```yaml role=setup.game
id: main
setup:
- path: /deck
parts: poker:card
facing: back
- path: /community/0
parts: poker:card#as
- path: /community/1
parts: poker:card#kh
- path: /community/2
parts: poker:card#7d
- path: /community/3
parts: poker:card#jc
facing: standing
- path: /community/4
parts: poker:card#2h
facing: standing
interactions:
- dialog: prompt#insert
on: [/deck]
```
## Dialog
Inserting a card into the middle of the deck is a compound interaction: the
deck is lifted into a stack-inspector dialog with an insertion cursor. The
cursor *is* the index — `move(id, /deck, index)` is discovered by scrolling,
not typed.
```yaml role=dialog.prompt
id: insert
title: Insert into deck
body: Scroll to the insertion point, then insert the held card.
widget: stack
```