구십구: 코리아보드게임즈 공식 규칙으로 맞춤

- 공식 상품 페이지 규칙 설명 이미지 기준: 5장씩, 시작 카드(2명 40·3명 20·4명 이상 0),
  0 카드는 방향 유지/반대 선택, 칩(목숨)은 공식 규칙이 아니라 하우스 룰
- handSize 'auto'(전용 카드 5, 트럼프 3), startTotal 옵션, 카드 종류 'zero'와 dir 액션
- stateVersion 2, 진행 중인 v1 게임은 옛 규칙 그대로 이어서 하도록 migrate
- 특수 카드 장수(±9·±10·0)는 공개 자료가 없어 각 4장 유지

Co-Authored-By: Claude Opus 5.5 <noreply@anthropic.com>
This commit is contained in:
EJClaw
2026-10-06 22:16:32 +09:00
parent d8b8cdd8f3
commit 7da06d1b27
10 changed files with 325 additions and 119 deletions

View File

@@ -12,30 +12,31 @@
- 나무위키 "99(플레잉 카드)"도 2~10명이다.
- 그래서 2~10명으로 한다.
### 확인된 것과 확인되지 않은 것 (오너 확인 필요)
- 확인됨(코리아보드게임즈 매거진 기사, 공식 상품 페이지)
### 확인된 것과 확인되지 않은 것
- 확인됨(코리아보드게임즈 공식 상품 페이지의 상세 이미지에 실린 규칙, 매거진 기사)
- 1~8 카드 각 7장, 10 카드 21장.
- 특수 카드 ±9, ±10, 0, 조커(정확히 2장).
- 자기 차례에 1장을 내고 이전 수에 더한 새 수를 말한다.
- 99를 넘게 만드는 카드는 낼 수 없고, 낼 카드가 1장도 없으면 탈락한다. 혼자 남으면 승리한다.
- ±9·±10은 더하거나 뺄 수 있다. 0은 수 변화 없이 진행 방향을 바꾼다. 조커는 앞 수와 상관없이 60~99 중 원하는 수를 부른다.
- 확인되지 않음(공식 규칙서 원문을 구하지 못함. 아래는 이 문서의 기본값이고 모두 옵션)
- 준비: 가운데에 시작 카드를 놓는다. 시작 카드에는 인원별 시작 숫자가 있다. 2명 40, 3명 20, 4명 이상 0. 카드를 섞어 모두에게 5장씩 나눈다.
- 이미지에서 시작 카드 글씨는 작지만, 4명 예시는 분명히 0에서 시작한다.
- 자기 차례에 1장을 내고 이전 수에 더한 새 수를 말한 뒤, 더미에서 1장을 가져온다.
- 99를 넘게 만드는 카드는 낼 수 없다. 낼 카드가 1장도 없으면 탈락하고, 합계는 그대로 다음 사람에게 넘어가 게임이 이어진다. 혼자 남으면 승리한다.
- ±9·±10은 더하거나 뺄 수 있다. 조커는 앞 수와 상관없이 60~99 중 원하는 수를 부른다.
- 0은 수 변화 없이 지금 합계를 그대로 말한다. 0을 낼 때 진행 방향을 그대로 둘지 반대로 바꿀지 낸 사람이 고른다.
- 공식 규칙에는 칩이나 목숨이 없다. `lives` 옵션은 전통 99의 토큰 3개 규칙을 빌려 온 하우스 룰이다(`kr-product` 기본값은 목숨 없음).
- 확인되지 않음(이 문서의 기본값이고 모두 옵션)
- ±9, ±10, 0 카드의 장수. 기본값은 각 4장(추정)이다.
- 시작 손패 장수. 기본값은 3장(전통 99와 같음)이다.
- 카드를 낸 뒤 1장 보충 여부. 기본값은 보충한다(전통 99와 같음).
- 빼기로 0 미만이 될 때 처리. 기본값은 0 미만이 되는 빼기는 금지다.
- 탈락자가 생긴 뒤 합계를 이어 갈지 초기화할지. 기본값은 이어 간다.
- 칩(목숨) 변형이 공식 규칙서에 있는지. 일부 소개 글에 "칩 3개, 99를 넘기면 1개 잃음" 변형이 언급되지만 원문으로 확인하지 못했다. 전통 99의 토큰 3개 규칙과 같은 구조라 `lives` 옵션으로 둔다.
## 2. 모드와 옵션
| 옵션 키 | 설명 | 선택지 | 기본값 |
|---|---|---|---|
| `mode` | 규칙 | `kr-product` / `classic` | `kr-product` |
| `handSize` | 손패 장수 | 3 / 4 / 5 | 3 |
| `handSize` | 손패 장수 | `auto` / 3 / 4 / 5 | `auto`(`kr-product` 5, `classic` 3) |
| `startTotal` | (`kr-product`) 시작 숫자 | `auto`(시작 카드: 2명 40, 3명 20, 4명 이상 0) / `zero`(항상 0) | `auto` |
| `refill` | 카드를 낸 뒤 1장 보충 | on / off | on |
| `lives` | 목숨(토큰) 수. 0이면 목숨 없이 바로 탈락 | 0 / 1 / 2 / 3 / 5 | `kr-product` 0, `classic` 3 |
| `lives` | 목숨(토큰) 수. 0이면 목숨 없이 바로 탈락. `kr-product`에서는 하우스 룰 | `auto` / 0 / 1 / 2 / 3 / 5 | `auto`(`kr-product` 0, `classic` 3) |
| `onTheBoard` | 목숨을 다 잃은 뒤에도 한 번 더 질 때까지 남음(전통 변형) | on / off | off |
| `afterElimination` | (`lives=0`) 탈락 뒤 합계 처리 | `continue`(그대로 이어 감) / `reset`(0으로, 다시 나눔) | `continue` |
| `afterElimination` | (`lives=0`) 탈락 뒤 합계 처리 | `continue`(그대로 이어 감, 공식) / `reset`(시작 숫자로, 다시 나눔) | `continue` |
| `floorAtZero` | 빼기 결과가 0 미만일 때 | `forbid`(그런 빼기는 못 냄) / `clamp`(0으로 맞춤) | `forbid` |
| `specialCounts` | (`kr-product`) ±9, ±10, 0 각 장수 | 2 / 3 / 4 / 5 / 6 | 4 |
| `jokerRange` | (`kr-product`) 조커로 부를 수 있는 범위 | `60-99`(원작) / `0-99` | `60-99` |
@@ -52,10 +53,11 @@
| 10 | 10 더함 | 21장 |
| ±9 | 9를 더하거나 뺌(낸 사람이 선택) | `specialCounts`(기본 4, 추정) |
| ±10 | 10을 더하거나 뺌 | `specialCounts`(기본 4, 추정) |
| 0 | 수 변화 없음, 진행 방향 반대 | `specialCounts`(기본 4, 추정) |
| 0 | 수 변화 없음. 진행 방향을 그대로 둘지 반대로 바꿀지 낸 사람이 고름 | `specialCounts`(기본 4, 추정) |
| 조커 | 앞 수와 상관없이 60~99 중 원하는 수로 만듦 | 2장 |
- 9 숫자 카드는 없다(±9만 있음).
- 시작 카드 1장(인원별 시작 숫자 표시). 화면에서는 판 가운데 합계로 보여 주므로 카드로 만들지 않는다.
- 목숨을 쓰면(`lives > 0`) 플레이어마다 목숨 토큰을 그만큼 준다. 방 안에서만 쓰는 표시용이다.
`classic` (트럼프 52장, Bicycle 규칙 기준)
@@ -75,8 +77,10 @@
## 4. 준비(셋업)
1. 모드에 맞는 덱을 만들고 시드 RNG로 섞는다.
2. 선 플레이어를 RNG로 정한다. 진행은 시계 방향이다.
3. 각자 `handSize`장을 받는다. 남은 카드는 뽑을 더미가 된다.
4. 합계는 0에서 시작한다.
3. 각자 `handSize`장을 받는다(`auto`면 `kr-product` 5장, `classic` 3장). 남은 카드는 뽑을 더미가 된다.
4. 합계는 시작 숫자에서 시작한다.
- `kr-product`이고 `startTotal = auto`면 시작 카드대로 2명 40, 3명 20, 4명 이상 0.
- `startTotal = zero`이거나 `classic`이면 항상 0.
5. 목숨을 쓰면 각자 `lives`개를 받는다.
## 5. 진행 규칙
@@ -85,10 +89,10 @@
1. **탈락 판정(턴 시작 때 서버 자동)**: 현재 플레이어가 낼 수 있는 카드가 하나도 없으면 바로 "패배 처리"(5.3)를 한다. 패배 처리 결과 탈락하지 않은 경우(목숨이 남음)에는 새 라운드가 시작된다.
2. **카드 내기**: 낼 수 있는 카드 1장을 낸다. ±카드는 더하기/빼기를, A는 1/11을, 조커는 숫자를 함께 고른다. 새 합계가 공개된다.
3. **보충**(`refill = on`): 뽑을 더미에서 1장을 가져온다. 더미가 비었으면 버린 카드를 모두 섞어 새 더미를 만든다(합계는 그대로). 그래도 없으면 보충하지 않는다.
4. 다음 차례로 넘긴다. 0(또는 `classic`의 4)이면 방향을 반대로 바꾼 뒤 넘긴다.
4. 다음 차례로 넘긴다. `classic`의 4이면 방향을 반대로 바꾼 뒤 넘긴다. `kr-product`의 0이면 낸 사람이 고른 대로 방향을 그대로 두거나 반대로 바꾼 뒤 넘긴다.
- 패스는 없다. 낼 수 있는 카드가 있으면 반드시 1장을 내야 한다.
- 2인일 때 방향 반대 카드는 방향만 바뀌고 다음 차례는 여전히 상대다.
- 2인일 때 방향을 바꿔도 다음 차례는 여전히 상대다.
### 5.2 낼 수 있는 카드(합법 조건)
합계를 S, 카드를 낸 뒤 합계를 S'라 할 때 S' ≤ 99여야 한다.
@@ -99,7 +103,7 @@
- 더하기면 S' = S + 값.
- 빼기면 S' = S - 값. `floorAtZero = forbid`이면 S' ≥ 0이어야 하고, `clamp`이면 S' = max(0, S - 값).
- 두 방향 중 하나라도 합법이면 낼 수 있다.
- 0: S' = S. 항상 낼 수 있다.
- 0: S' = S. 항상 낼 수 있다. 방향(`keep` 그대로 / `reverse` 반대)을 함께 고른다.
- 조커: S'를 `jokerRange`(60~99) 안의 아무 정수로 고른다. 항상 낼 수 있다. 현재 합계와 같은 수를 골라도 된다.
`classic`
@@ -113,17 +117,17 @@
- `lives = 0`(`kr-product` 기본)
- 그 플레이어는 탈락한다. 손패는 버린 더미로 간다.
- `afterElimination = continue`면 같은 합계로 다음 사람 차례가 된다(다음 사람도 낼 카드가 없으면 연달아 탈락할 수 있다).
- `reset`이면 합계를 0으로 하고 남은 사람 손패를 모두 거둬 다시 섞어 나눈다. 탈락자의 다음 사람이 시작한다.
- `reset`이면 합계를 시작 숫자(남은 인원 기준, 4절)로 하고 남은 사람 손패를 모두 거둬 다시 섞어 나눈다. 탈락자의 다음 사람이 시작한다.
- `lives > 0`
- 그 플레이어가 목숨 1개를 잃는다. 이번 라운드는 끝난다.
- 목숨이 0이 되면 탈락한다. `onTheBoard = on`이면 목숨 0인 상태로 계속 하고, 그 상태에서 한 번 더 지면 탈락한다.
- 새 라운드: 모든 카드를 거둬 섞고, 남은 사람에게 다시 나누고, 합계 0에서 시작한다. 진 사람이 탈락하지 않았으면 진 사람이 먼저 하고, 탈락했으면 그 다음 사람이 먼저 한다.
- 새 라운드: 모든 카드를 거둬 섞고, 남은 사람에게 다시 나누고, 시작 숫자(남은 인원 기준, 4절)에서 시작한다. 진 사람이 탈락하지 않았으면 진 사람이 먼저 하고, 탈락했으면 그 다음 사람이 먼저 한다.
- 남은 사람이 1명이면 게임이 끝난다.
### 5.4 예시 (`kr-product`, 3인)
### 5.4 예시 (`kr-product`, 3인, 시작 숫자 20에서 진행된 판의 중간. 손패는 짧게 3장만 적음)
- 합계 85에서 A가 10을 내 95가 된다. A가 보충한다.
- B의 손패는 [8, 7, ±9]이다. 8과 7은 99를 넘는다. ±9를 빼기로 내서 86이 된다.
- C의 손패는 [10, 10, 0]이다. 0을 내서 86 그대로이고 방향이 반대가 되어 B 차례가 된다.
- C의 손패는 [10, 10, 0]이다. 0을 내며 방향을 바꾸기로 고른다. 86 그대로이고 방향이 반대가 되어 B 차례가 된다.
- B의 손패는 [8, 7, 6](보충한 6)이다. 8 → 94, 7 → 93, 6 → 92 모두 가능하다. B가 7을 내서 93.
- 방향이 바뀌었으므로 다음은 A다. A의 손패가 [8, 10, 7]이면 101, 103, 100이라 낼 카드가 없다. A는 턴 시작 때 탈락하고 C 차례가 된다.
@@ -134,8 +138,9 @@
- 점수, 칩, 돈은 없다. 목숨 토큰은 이 판에서만 쓰는 표시이고 방 밖으로 이어지지 않는다.
## 7. 지역 룰 / 하우스 룰 (옵션으로 켜고 끄기)
- 목숨(칩) 변형(`lives`, `onTheBoard`): 전통 99의 토큰 3개 규칙이다. 구십구 소개 글 일부에서도 "칩 3개" 변형이 언급된다(원문 미확인).
- 목숨(칩) 변형(`lives`, `onTheBoard`): 전통 99의 토큰 3개 규칙이다. 구십구 공식 규칙에는 없다.
- 손패 장수(`handSize`), 보충 여부(`refill`).
- 시작 숫자를 항상 0으로(`startTotal = zero`).
- 탈락 뒤 합계 처리(`afterElimination`).
- 0 미만 빼기 처리(`floorAtZero`).
- 조커 범위 확장(`jokerRange`, 어린이용 0~99).
@@ -151,7 +156,8 @@
type NNCard =
| { id: string; kind: 'add'; v: number } // kr: 1..8, 10 / classic: 2,3,5,6,7,8, J/Q(10)
| { id: string; kind: 'plusMinus'; v: 9 | 10 } // kr ±9, ±10
| { id: string; kind: 'reverse' } // kr 0 / classic 4
| { id: string; kind: 'reverse' } // classic 4 (항상 방향 반대)
| { id: string; kind: 'zero' } // kr 0 (방향은 낸 사람이 고름)
| { id: string; kind: 'hold' } // classic 9
| { id: string; kind: 'minus'; v: 10 } // classic 10
| { id: string; kind: 'ace' } // classic A (1 또는 aceHigh)
@@ -184,13 +190,14 @@ interface NinetyNineState {
### 8.2 액션
| type | payload | 누가 / 언제 | 검증 조건 |
|---|---|---|---|
| `play` | `{ cardId: string; sign?: '+' \| '-'; aceValue?: 1 \| 10 \| 11; jokerValue?: number }` | `current`, playing | 카드가 손에 있음. ±카드는 `sign` 필수, A는 `aceValue` 필수(1 또는 `aceHigh`), 조커는 `jokerValue` 필수이고 `jokerRange` 안의 정수. 5.2 조건으로 계산한 S' ≤ 99(그리고 `forbid`면 S' ≥ 0) |
| `play` | `{ cardId: string; sign?: '+' \| '-'; aceValue?: 1 \| 10 \| 11; jokerValue?: number; dir?: 'keep' \| 'reverse' }` | `current`, playing | 카드가 손에 있음. ±카드는 `sign` 필수, A는 `aceValue` 필수(1 또는 `aceHigh`), 조커는 `jokerValue` 필수이고 `jokerRange` 안의 정수, `kr-product`의 0은 `dir` 필수(다른 카드에 `dir`이 있으면 거부). 5.2 조건으로 계산한 S' ≤ 99(그리고 `forbid`면 S' ≥ 0) |
- 플레이어가 보내는 액션은 `play` 하나뿐이다. 탈락, 목숨 감소, 라운드 재시작, 보충은 `apply` 안에서 자동으로 처리한다.
- `play`를 적용한 직후 다음 플레이어를 정한다. 그 플레이어에게 합법 수가 없으면 같은 `apply` 안에서 패배 처리를 하고, 다시 다음 사람을 검사한다(반복). 이 과정을 이벤트로 순서대로 남긴다.
- 이렇게 하면 "낼 카드가 없는 사람이 타이머를 기다리는" 상황이 없다.
- 이벤트 예: `cardPlayed{player, face, total}`, `directionChanged`, `cardDrawn{player}`, `reshuffled`, `lifeLost{player, left}`, `eliminated{player}`, `roundStarted{round, starter}`.
- `reason` 예: "99를 넘어서 낼 수 없어요", "0보다 작아져서 뺄 수 없어요", "더하기와 빼기 중 하나를 골라 주세요", "조커는 60부터 99 사이 숫자만 고를 수 있어요".
- 이벤트 예: `cardPlayed{player, face, total, choice?}`(0은 choice가 "방향 그대로"/"방향 바꾸기"), `directionChanged`, `cardDrawn{player}`, `reshuffled`, `lifeLost{player, left}`, `eliminated{player}`, `roundStarted{round, starter, total}`.
- `reason` 예: "99를 넘어서 낼 수 없어요", "0보다 작아져서 뺄 수 없어요", "더하기와 빼기 중 하나를 골라 주세요", "조커는 60부터 99 사이 숫자만 고를 수 있어요", "0 카드는 방향을 그대로 둘지 바꿀지 골라 주세요", "방향은 0 카드를 낼 때만 고를 수 있어요".
- `stateVersion` 2: `handSize = auto`, `startTotal`, `zero` 카드가 생겼다. 진행 중이던 v1 게임은 시작할 때 규칙대로 이어 간다(나눈 손패 장수 그대로, 새 라운드도 0부터, 그 게임의 0 카드는 늘 방향 반대). v1로 끝난 게임은 다시 보기를 할 수 없다.
### 8.3 공개/비공개 정보 (view)
- 모두(관전자 포함): 현재 합계, 방향, 현재 차례, 각자 손패 장수, 목숨, 생존 여부, 탈락 순서, 뽑을 더미 장수, 최근에 낸 카드 몇 장과 그때의 합계 기록.
@@ -209,6 +216,7 @@ interface NinetyNineState {
- `deadline = turnStartedAt + turnSeconds*1000`.
- `onTimeout(state, p)`: 합법인 (카드, 선택값) 조합 중 결과 합계 S'가 가장 작은 것을 고른다.
- 같으면 우선순위: 0/4/9(변화 없음) → 일반 숫자 카드 → ±카드 → K/조커. 그래도 같으면 카드 ID 순.
- `kr-product`의 0은 방향을 그대로 두는 쪽으로 낸다.
- 조커는 `jokerRange` 최소값(60)으로 낸다.
- 이 규칙은 본인 손패와 공개 합계만 쓰므로 정보 유출이 없고 결정적이다.
- 합법 수가 없는 경우는 타이머까지 가지 않고 `apply`에서 이미 처리된다(8.2).
@@ -228,28 +236,31 @@ interface GameResult {
- 모바일 세로 화면
- 가운데: 현재 합계를 아주 크게(예: 72pt) 보여 준다. 99에 가까울수록 색이 초록 → 노랑 → 빨강으로 바뀌는 게이지 링을 두른다.
- 위: 상대 아바타(손패 장수, 목숨 하트, 차례 표시), 진행 방향 화살표.
- 아래: 내 손패 3장을 큰 카드로 보여 준다(최소 72×100px).
- 아래: 내 손패(기본 5장)를 큰 카드로 보여 준다(최소 62×87px).
- 조작
- 카드를 탭하면 "내면 → 81"처럼 결과 합계 미리보기가 카드 위에 뜬다. 한 번 더 탭하면 낸다.
- ±카드를 탭하면 [+9 → 95] [−9 → 77] 두 버튼이 뜬다. 불가능한 쪽은 비활성이다.
- 0을 탭하면 [방향 그대로 → 86] [방향 바꾸기 → 86] 두 버튼이 뜬다.
- 조커를 탭하면 60~99 숫자 다이얼(+/− 버튼과 빠른 선택 60/90/99)이 뜬다.
- 낼 수 없는 카드는 흐리게 하고 "99 초과" 배지를 붙인다.
- 애니메이션: 합계 숫자가 올라가는 카운트 애니메이션, 방향 전환 화살표 회전, 탈락 때 아바타 흑백 처리, 목숨 하트가 깨지는 연출.
- 초보 도움말: "99를 넘기면 안 돼요!" 한 줄 규칙과 특수 카드 표. 어린이 방 추천 설정(조커 0~99, 손패 4장).
- 초보 도움말: "99를 넘기면 안 돼요!" 한 줄 규칙과 특수 카드 표. 어린이 방 추천 설정(조커 0~99, 손패 5장).
- 실시간 감각: 턴이 빨라서 타이머 링을 크게 보여 주고, 내 차례가 되면 진동(모바일 지원 시)으로 알린다.
## 10. 테스트 체크리스트
- [ ] 덱 구성: `kr-product` 기본값 91장(1~8 각 7, 10이 21, ±9/±10/0 각 4, 조커 2). `specialCounts=2`면 85장. `classic` 52장, 7인 이상 `auto`면 104장.
- [ ] 같은 시드면 같은 분배, 같은 선이 나온다.
- [ ] 손패 `auto`: `kr-product` 5장, `classic` 3장. 3/4/5를 고르면 그 장수.
- [ ] 시작 숫자: `kr-product` 2명 40, 3명 20, 4명 이상 0. `startTotal = zero`와 `classic`은 항상 0. 목숨 모드 새 라운드와 `reset`도 남은 인원 기준 시작 숫자로 시작한다.
- [ ] 합계 95에서 손패 [8, 5, 4] (`kr-product`)이면 4만 합법이다. 4를 내서 99가 된다. 다음 사람이 [1, 2, 3]만 있으면 턴 시작 때 바로 탈락한다.
- [ ] ±10: 합계 5에서 빼기는 `forbid`면 거부된다. `clamp`면 0이 된다. 더하기는 15로 허용된다.
- [ ] 조커: 합계 20에서 조커로 99를 고르면 99가 된다. 59는 거부되고(`60-99`), 100도 거부된다.
- [ ] 0 카드: 3인에서 A → B 차례에 B가 0을 내면 방향이 반대가 되어 다음이 A다. 2인에서는 상대 차례 그대로다.
- [ ] 0 카드: 3인에서 A → B 차례에 B가 0을 "방향 바꾸기"로 내면 다음이 A, "방향 그대로"로 내면 다음이 C다. 2인에서는 상대 차례 그대로다. `dir` 없이 내면 거부, 0이 아닌 카드에 `dir`이 있어도 거부된다. `classic`의 4는 고르지 않고 항상 방향이 바뀐다.
- [ ] `classic`: 합계 90에서 K → 99, 그다음 사람은 4/9/10/K만 낼 수 있다. A는 1이어도 100이라 거부된다. 합계 88에서 A를 11로 내면 99로 허용된다.
- [ ] `lives=3`: 진 사람이 목숨 1개를 잃고, 합계 0으로 새 라운드가 시작되며 진 사람이 먼저 한다. 목숨 0이면 탈락하고 다음 사람이 시작한다. `onTheBoard`면 0개에서 한 번 더 져야 탈락한다.
- [ ] `lives=3`: 진 사람이 목숨 1개를 잃고, 시작 숫자로 새 라운드가 시작되며 진 사람이 먼저 한다. 목숨 0이면 탈락하고 다음 사람이 시작한다. `onTheBoard`면 0개에서 한 번 더 져야 탈락한다.
- [ ] 연쇄 탈락(`lives=0`, `continue`): 합계 98에서 다음 두 사람 모두 낼 카드가 없으면 한 번의 `apply` 안에서 두 명이 순서대로 탈락하고, 세 번째 사람 차례가 된다. 이벤트 순서가 맞다.
- [ ] 더미 소진: 보충할 때 더미가 비면 버린 카드가 섞여 보충되고 합계는 그대로다.
- [ ] 시간 초과: 손패 [10, 3, 0], 합계 50이면 자동 행동은 0(결과 50, 가장 작음)을 낸다. 손패 [±9, 3, 0], 합계 50이면 −9(결과 41)를 낸다.
- [ ] 시간 초과: 손패 [10, 3, 0], 합계 50이면 자동 행동은 0(결과 50, 가장 작음)을 방향 그대로로 낸다. 손패 [±9, 3, 0], 합계 50이면 −9(결과 41)를 낸다.
- [ ] 연결 끊김: 끊긴 플레이어 차례가 자동으로 진행되고 게임이 멈추지 않는다.
- [ ] 정보 유출: 관전자와 상대 view에 남의 손패, 보충 카드 내용, 더미 순서가 없다. 탈락자 손패도 공개되지 않는다.
- [ ] 차례가 아닌 `play`, `sign` 없는 ±카드, 범위 밖 `jokerValue`, 중복 패킷이 거부되고 상태가 바뀌지 않는다.
@@ -257,6 +268,7 @@ interface GameResult {
## 11. 참고 자료
- 코리아보드게임즈 매거진 "숫자를 더해나가며 한계에 도전하라!": https://www.koreaboardgames.com/magazine/menuDetail?boardCd=contents&postNo=947 (1~8 각 7장, 10이 21장, ±9·±10·0·조커 효과, 조커 2장 60~99, 99 초과 금지, 낼 카드 없으면 탈락)
- 코리아보드게임즈 상품 페이지 "구십구": https://www.koreaboardgames.com/product/detail?prdCd=PD2024002211B1JR (2~10명, 만 8세+, 5분)
- 상세 이미지(공식 규칙의 근거): https://cdnfile.koreaboardgames.com/_data/attach/202303/28/1df6a23faae2d4fd4415f07ba703309d.jpg (시작 카드 2명 40·3명 20·4명 이상 0, 5장씩 나눔, 내고 1장 가져옴, 낼 카드 없으면 탈락하고 합계는 그대로 다음 사람, 조커 60~99, ±9·±10, 0은 방향 유지 또는 반대 선택. 칩·목숨 없음)
- 나무위키 "99(플레잉 카드)": https://namu.wiki/w/99(플레잉%20카드) (트럼프판 2~10명, 손패 3장, 내고 1장 보충, A 1/10, 4 반대, 9는 0, 10은 −10, J·Q 10, K는 99)
- Bicycle Cards "99 (Ninety Nine)": https://bicyclecards.com/how-to-play/99-ninety-nine (토큰 3개, 손패 3장, A 1/11, 4 반대, 9 패스, 10 −10, K 99, 넘기면 토큰 1개 잃고 라운드 종료)
- Wikipedia "Ninety-nine (addition card game)": https://en.wikipedia.org/wiki/Ninety-nine_(addition_card_game) (토큰 3개, 지역 변형 목록)