forked from eros/curltastic
Replace REQUIREMENTS.md as source of truth with the pm-board yaml. Drop README friction-scalar lies. Include pending HUD frontend work.
123 lines
5.7 KiB
YAML
123 lines
5.7 KiB
YAML
requirements:
|
|
- id: R1
|
|
title: Mobile 2D overhead curling
|
|
body: Players play curling in a mobile browser from a 2D overhead view.
|
|
- id: R2
|
|
title: Portrait sheet
|
|
body: The sheet is shown in portrait.
|
|
- id: R3
|
|
title: Two teams, unlimited clients
|
|
body: A room has two teams and an unlimited number of clients.
|
|
- id: R4
|
|
title: Team pick per device
|
|
body: Each client picks Team 1 or Team 2 on that device.
|
|
- id: R5
|
|
title: Anyone on turn may throw
|
|
body: Anyone on the team whose turn it is may throw.
|
|
- id: R6
|
|
title: Shareable room link
|
|
body: Players join a room from a shareable link.
|
|
- id: R7
|
|
title: Create room from empty link
|
|
body: If the link has no room, the client creates one and writes that room into the URL.
|
|
- id: R8
|
|
title: Ten ends, eight stones
|
|
body: A match has 10 ends. Each team has 8 stones per end.
|
|
- id: R9
|
|
title: Extra ends until a lead
|
|
body: Extra ends are played while the score is tied after 10 ends. The match ends when one team leads after an end.
|
|
- id: R10
|
|
title: Random hammer
|
|
body: Hammer is random at the start. The team without hammer throws first in the end.
|
|
- id: R11
|
|
title: Hammer after score or blank
|
|
body: The team that scores gives hammer away. A blank end keeps hammer.
|
|
- id: R12
|
|
title: Alternate throws
|
|
body: After a throw, that team has one fewer stone and the other team throws.
|
|
- id: R13
|
|
title: Score when stones are gone
|
|
body: When all throws have completed, the end is scored.
|
|
- id: R14
|
|
title: House only scores
|
|
body: Only stones touching the house can score.
|
|
- id: R15
|
|
title: Count to opponent nearest
|
|
body: The team closest to the tee scores one point for each of its stones nearer than the opponent's nearest stone.
|
|
- id: R16
|
|
title: Blank end is 0-0
|
|
body: If no stone can score, the end is 0-0.
|
|
- id: R17
|
|
title: Shared live state
|
|
body: Every client sees the current end, both scores, hammer, whose turn it is, stones remaining, stone positions, trajectories from all shots, and whether the match is over.
|
|
- id: R18
|
|
title: Winner on match end
|
|
body: When the match ends, both scores are shown with the winning team.
|
|
- id: R19
|
|
title: Hack to broom
|
|
body: A thrown stone starts at the hack and travels toward the broom. The player chooses initial speed and curl.
|
|
- id: R20
|
|
title: Clockwise is thrower's right
|
|
body: Clockwise curl moves the stone to the thrower's right.
|
|
- id: R21
|
|
title: Stone bounce, no line bounce
|
|
body: Stones bounce off other stones. Stones do not bounce back from a sideline or the backline.
|
|
- id: R22
|
|
title: Out of play rules
|
|
body: A stone is out if it touches a sideline. A stone must fully cross the backline to be out. A stone is out if it never fully crosses the hog line.
|
|
- id: R23
|
|
title: Sheet markings
|
|
body: The ice is a curling sheet with a house, hog line, sidelines, and a backline on the 12-foot ring.
|
|
- id: R24
|
|
title: Default house framing
|
|
body: The default view frames the house, sidelines, and backline above the controls.
|
|
- id: R25
|
|
title: Pan to hog
|
|
body: The player can pan up and down the sheet to the hog line.
|
|
- id: R26
|
|
title: Broom anywhere then throw
|
|
body: On turn, the player drags to place the broom anywhere on the sheet, then throws.
|
|
- id: R27
|
|
title: Discrete throw weights
|
|
body: The player sets throw weight on a discrete scale of draw weights 1 through 10, then named takeouts hack, board, control, normal, and peel.
|
|
- id: R28
|
|
title: Curl direction
|
|
body: The player sets curl clockwise or counterclockwise. Clockwise is the default.
|
|
- id: R29
|
|
title: Throw only on turn while still
|
|
body: Throw controls work only on that team's turn and only while stones are not moving.
|
|
- id: R30
|
|
title: Stones, hammer, scoreboard HUD
|
|
body: The HUD shows eight remaining-stone markers per team, a hammer marker, and a scoreboard with each end and a total.
|
|
- id: R31
|
|
title: End overlay
|
|
body: After the stones stop and the end is scored, an end-result overlay appears. The player dismisses it.
|
|
- id: R32
|
|
title: Shared motion, hide out stones
|
|
body: All clients see the same stone motion. A stone that leaves play is hidden when it leaves the sheet.
|
|
- id: R33
|
|
title: Copyable errors
|
|
body: Errors and the final result appear on the page as copyable text, not as a blocking alert.
|
|
- id: R34
|
|
title: No pinch-zoom, remember team
|
|
body: Pinch-zoom is off. The client remembers the last team choice.
|
|
choices:
|
|
- id: C1
|
|
title: Stack
|
|
body: Backend is Rust, Axum, WebSocket, Rapier2D, server-authoritative at 120 Hz. Frontend is TypeScript, Vite, Canvas2D, portrait-first touch.
|
|
- id: C2
|
|
title: Team colours
|
|
body: Team 1 is red. Team 2 is yellow.
|
|
- id: C3
|
|
title: Wire protocol
|
|
body: WebSocket JSON with snake_case tags. game_state carries totals, hammer, turn_team, per-end scoreboard, stones_remaining, and stones. Trajectories sample at 40 Hz from the 120 Hz sim. No room-full limit. No end_scored message.
|
|
- id: C4
|
|
title: Physics how
|
|
body: Ice friction is a server µ(v) table shared by linear and angular damping. Curl uses initial |ω| = 5 rot / 14 s with clockwise to the thrower's right. Stone-stone restitution is 0.9. Sidelines and backline are not colliders; out-of-play is applied after sim. Stone ids are { team, n } with n 1 through 8. Lengths use FEET_TO_METERS = 0.3048.
|
|
- id: C5
|
|
title: Weight mapping
|
|
body: Discrete UI weights map to calibrated open-ice stop speeds in SPEED_TABLE. The server takes velocity and curl, not a local friction scalar.
|
|
- id: C6
|
|
title: Out of scope
|
|
body: No accounts, persistence, anti-cheat, replay log, turn timer, or sweeping.
|