# 요트 다이스 (`yacht`) > 마일스톤: M4 · 인원: 최소 1 ~ 최대 8명 · 예상 시간: 1인당 약 5~8분(4명 약 20~30분) · 난이도: 쉬움 ## 1. 개요 - 주사위 5개를 한 차례에 최대 3번 굴리며(원하는 주사위는 고정), 12개 족보 칸 중 하나에 점수를 기록한다. 12라운드 후 총점이 가장 높은 사람이 이긴다. - 한국에서는 닌텐도 스위치 "세계의 아소비 대전 51"(영문 Clubhouse Games: 51 Worldwide Games)에 수록된 "요트"로 크게 알려졌고, 인터넷 방송과 웹 게임으로 "요트 다이스"라는 이름이 널리 쓰인다. 이 문서의 기본 규칙은 그 버전을 따른다. 미국식 상용 변형(야찌 방식 13칸)은 옵션으로 둔다. - 인원 근거: 요트는 전통적으로 인원 제한이 없는 주사위 게임이며 혼자서 점수 도전도 가능하다(최소 1명). 상한은 원작에 없으므로 점수표 가독성과 대기 시간을 고려해 8명으로 정한다. ## 2. 모드와 옵션 | 옵션 키 | 설명 | 선택지 | 기본값 | |---|---|---|---| | `scoring` | 점수 규칙 | `yacht51`(12칸, 51 수록판), `yahtzee`(13칸, 미국식 변형) | `yacht51` | | `fullHouseAllowsYacht` | `yacht51`에서 5개가 모두 같은 눈을 풀하우스로 인정할지 | `true`, `false` | `true` | | `yahtzeeJoker` | `yahtzee`에서 추가 요트(5개 같은 눈) 처리 | `forced`(공식 강제 조커), `free`(자유 선택 조커) | `forced` | | `turnSeconds` | 한 차례 제한 시간 | 30, 60, 90, `null` | 60 | | `showPreview` | 아직 안 채운 칸에 "지금 넣으면 몇 점"을 미리 표시 | `true`, `false` | `true` | ## 3. 구성물 - 육면체 주사위 5개(공용). - 플레이어별 점수표(아래 6장 칸 구성). ## 4. 준비(셋업) 1. 좌석 순서를 RNG로 섞어 차례 순서를 정한다(방장이 "입장 순서 유지"를 선택하면 섞지 않음 — UI 설정, 엔진 옵션 아님. 기본은 섞음). 2. 모든 칸 비움, 라운드 1, 첫 플레이어 차례, `rollsUsed = 0`, 고정(hold) 없음. ## 5. 진행 규칙 - 게임은 칸 수만큼의 라운드(`yacht51` 12라운드, `yahtzee` 13라운드)로 진행된다. 한 라운드에 모든 플레이어가 차례 순서대로 한 번씩 차례를 가진다. - 한 차례: 1. 첫 굴림: 주사위 5개를 모두 굴린다(`ROLL`). 첫 굴림 전에는 고정할 수 없고 점수를 기록할 수 없다. 2. 두 번째·세 번째 굴림(선택): 원하는 주사위를 고정(`SET_HOLD`)하고 나머지만 다시 굴린다. 고정은 굴림마다 자유롭게 바꿀 수 있다(이전에 고정한 주사위를 풀어서 다시 굴려도 됨). 5개 모두 고정한 상태로는 굴릴 수 없다. 3. 기록: 1~3번 굴린 뒤 언제든 비어 있는 칸 하나를 골라 현재 주사위 5개로 점수를 기록한다(`SCORE`). 조건을 만족하지 않는 칸에 넣으면 0점. 3번 굴린 뒤에는 반드시 기록해야 한다. 4. 기록하면 차례가 끝나고 다음 사람으로 넘어간다. - 한 번 기록한 칸은 바꿀 수 없다. 모든 칸이 차면 그 플레이어는 끝. ## 6. 승패와 점수 계산 ### 6.1 `yacht51` (기본, 12칸) | 칸 | 조건 | 점수 | 최대 | |---|---|---|---| | 에이스(1) | 없음 | 눈 1인 주사위 눈의 합 | 5 | | 듀스(2) | 없음 | 눈 2인 주사위 눈의 합 | 10 | | 트레이(3) | 없음 | 눈 3의 합 | 15 | | 포(4) | 없음 | 눈 4의 합 | 20 | | 파이브(5) | 없음 | 눈 5의 합 | 25 | | 식스(6) | 없음 | 눈 6의 합 | 30 | | 상단 보너스 | 위 6칸 합계가 63 이상 | 35 (자동) | 35 | | 초이스 | 없음 | 주사위 5개 눈의 합 | 30 | | 포 카인드 | 같은 눈이 4개 이상 | 주사위 5개 눈의 합 | 30 | | 풀 하우스 | 같은 눈 3개 + 다른 같은 눈 2개 (`fullHouseAllowsYacht=true`면 5개 모두 같은 눈도 인정) | 주사위 5개 눈의 합 | 30 (인정 안 하면 28) | | 스몰 스트레이트 | 연속된 4개 눈 포함(1-2-3-4, 2-3-4-5, 3-4-5-6) | 15 | 15 | | 라지 스트레이트 | 연속된 5개 눈(1-2-3-4-5, 2-3-4-5-6) | 30 | 30 | | 요트 | 5개 모두 같은 눈 | 50 | 50 | - 총점 = 상단 6칸 합 + 상단 보너스 + 하단 6칸 합. 이론상 최대 325점(풀하우스에 요트 인정 시), 323점(불인정 시). - 상단 보너스는 63점(각 눈 3개씩 = 3+6+9+12+15+18) 기준이며, 상단 칸이 다 차기 전이라도 63에 도달하는 순간 확정 표시해도 된다(점수는 동일). - 라지 스트레이트는 스몰 스트레이트 조건도 만족한다(스몰 칸에 넣으면 15점). - 요트는 포 카인드 조건도 만족한다(포 카인드 칸에 넣으면 5개 합). 예시: 주사위 [6,6,6,6,2] - 식스 24, 듀스 2, 초이스 26, 포 카인드 26, 풀 하우스 0, 스트레이트 0, 요트 0. 예시: [3,3,5,5,5] → 풀 하우스 21, 초이스 21, 트레이 6, 파이브 15. 예시: [4,4,4,4,4] → 요트 50, 포 카인드 20, 풀 하우스 20(`true`일 때) 또는 0, 포 20. ### 6.2 `yahtzee` (옵션, 13칸) | 칸 | 조건 | 점수 | |---|---|---| | 1~6 | 없음 | 해당 눈의 합 | | 상단 보너스 | 상단 합 63 이상 | 35 | | 쓰리 카인드 | 같은 눈 3개 이상 | 5개 합 | | 포 카인드 | 같은 눈 4개 이상 | 5개 합 | | 풀 하우스 | 3개 + 2개(서로 다른 눈) | 25 | | 스몰 스트레이트 | 연속 4개 포함 | 30 | | 라지 스트레이트 | 연속 5개 | 40 | | 요트(5개 같은 눈) | 5개 모두 같음 | 50 | | 찬스 | 없음 | 5개 합 | - 요트 보너스: 요트 칸에 이미 50점이 기록된 상태에서 다시 5개 같은 눈이 나와 어딘가에 기록하면 +100(횟수 제한 없음). 요트 칸이 0점이면 보너스 없음. - 조커 규칙(요트 칸이 이미 채워진 상태(50 또는 0)에서 5개 같은 눈을 기록할 때): - `forced`(공식): (1) 그 눈에 해당하는 상단 칸이 비어 있으면 반드시 거기에 기록. (2) 상단 칸이 이미 차 있으면 비어 있는 하단 칸 아무 곳에나 기록할 수 있고, 이때 풀 하우스 25, 스몰 30, 라지 40을 조건 무관하게 인정(쓰리/포 카인드·찬스는 5개 합). (3) 하단도 모두 차 있으면 비어 있는 상단 칸 하나에 0점. - `free`: 아무 빈 칸이나 고를 수 있다. 단 조커(풀 하우스·스트레이트 고정 점수 인정)는 해당 눈의 상단 칸이 이미 차 있을 때만 적용. - 총점 = 상단 합 + 보너스 35 + 하단 합 + 요트 보너스 합계. ### 6.3 순위와 동점 - 총점 높은 순. 동점이면 공동 순위(1등 동점이면 공동 우승). 원작에 별도 동점 규칙이 없으므로 추가 판정은 하지 않는다. - 혼자 하는 경우 결과는 "총점"과 "개인 최고 기록 대비"만 표시(기록 저장은 SQLite에 선택적으로). ## 7. 지역 룰 / 하우스 룰 (옵션으로 켜고 끄기) - 풀 하우스에 요트 인정 여부(`fullHouseAllowsYacht`): 51 수록판 설명 기준으로 기본 인정. 전통 요트 규칙(풀 하우스는 서로 다른 두 눈)을 원하면 끈다. - 전통 요트 규칙의 포 카인드는 "같은 4개의 합"만 세는 경우가 있다(최대 24점). 수요가 있으면 `fourKindScore: 'allFive' | 'fourOnly'` 옵션으로 추가할 수 있다(현재 범위 밖). - 야찌 방식 13칸과 조커 규칙: `scoring = yahtzee`, `yahtzeeJoker`. ## 8. 엔진 설계 ### 8.1 상태(State) ```ts type Category = | 'ones' | 'twos' | 'threes' | 'fours' | 'fives' | 'sixes' | 'choice' | 'threeKind' | 'fourKind' | 'fullHouse' | 'smallStraight' | 'largeStraight' | 'yacht'; // yacht51 사용 칸: threeKind 제외 12칸 / yahtzee 사용 칸: 13칸 (choice = 찬스) interface YachtState { options: YachtOptions; rng: RngState; order: PlayerId[]; // 차례 순서 current: number; // order 인덱스 round: number; // 1부터 totalRounds: 12 | 13; dice: [number, number, number, number, number] | null; // 첫 굴림 전 null held: [boolean, boolean, boolean, boolean, boolean]; rollsUsed: 0 | 1 | 2 | 3; sheets: Record>; yahtzeeBonus: number; // yahtzee 모드 요트 보너스 누적(100 단위) }>; left: PlayerId[]; // 기권·퇴장한 사람(남은 칸은 0점 처리) phase: 'playing' | 'finished'; turnSeq: number; deadlineAt: number | null; } ``` ### 8.2 액션 | type | payload | 누가 / 언제 | 검증 조건 | |---|---|---|---| | `ROLL` | 없음 | 현재 차례 사람, `rollsUsed < 3` | `rollsUsed = 0`이면 고정 무시(모두 굴림). 그 외 고정 안 된 주사위가 1개 이상. 위반: "이번 차례에는 더 굴릴 수 없어요." / "굴릴 주사위를 하나 이상 풀어 주세요." | | `SET_HOLD` | `{ held: boolean[5] }` | 현재 차례 사람, `1 ≤ rollsUsed < 3` | 길이 5. `rollsUsed = 3`이면 의미 없으므로 거부. (실시간으로 다른 사람 화면에도 고정 상태가 보이도록 별도 액션) | | `SCORE` | `{ category: Category }` | 현재 차례 사람, `rollsUsed ≥ 1` | 현재 모드에서 쓰는 칸이고 비어 있음. `yahtzee` + `forced` 조커 상황이면 6.2의 강제 순서를 만족하는 칸만 허용("이 요트는 ○ 칸에 먼저 넣어야 해요."). | | `CONCEDE` | 없음 | 참가자 누구나 | 남은 칸 모두 0점 확정, 차례 순서에서 제외 | - 점수 계산은 순수 함수 `scoreFor(dice, category, sheet, options) → { points, joker, yahtzeeBonus }`로 분리해 클라이언트 미리보기와 서버가 같은 코드를 공유한다. - 이벤트: `rolled{dice,held}`, `holdChanged`, `scored{player,category,points,bonus}`, `upperBonus{player}`, `turnChanged`, `roundChanged`, `gameOver`. ### 8.3 공개/비공개 정보 (view) - 숨겨진 정보 없음. 모든 참가자·관전자에게 같은 View: 주사위, 고정 상태, 남은 굴림 수, 모든 점수표, 현재 차례, 남은 시간. - 현재 차례 사람(및 `showPreview=true`면 모두)에게 `preview: Partial>`(빈 칸에 지금 넣을 때 점수)를 넣는다. - `rng` 상태는 View에 넣지 않는다. ### 8.4 랜덤 요소 (시드 RNG 사용 지점) - 셋업: 차례 순서 섞기(Fisher–Yates). - `ROLL`: 고정되지 않은 주사위마다 `1 + floor(rng() * 6)`, 인덱스 0→4 순서로 호출(리플레이 일관성). ### 8.5 타이머·시간 초과·연결 끊김 시 자동 행동 - `deadline`: 차례 시작 시 `now + turnSeconds`(차례 전체에 대한 시간, 굴릴 때마다 초기화하지 않음). - `onTimeout`: - `rollsUsed = 0` → `ROLL` (그 다음 즉시 다시 onTimeout이 호출되어 기록). - `rollsUsed ≥ 1` → `SCORE`: 허용된 빈 칸 중 점수가 가장 높은 칸. 동점이면 6.1/6.2 표의 위쪽 칸 우선. 모든 칸이 0점이면 희생 순서 `ones → yacht → largeStraight → smallStraight → fullHouse → fourKind → threeKind → twos → threes → fours → fives → sixes → choice` 중 첫 빈 칸. - 끊긴 사람: 차례가 오면 10초 유예 후 위 자동 행동. 3번 연속 자동이면 "자리 비움" 표시. ### 8.6 종료 조건과 결과(GameResult) - 마지막 라운드의 마지막 사람이 기록하면 종료(기권자는 건너뜀). 모든 사람이 기권하면 즉시 종료. ```ts interface YachtResult { ranking: { rank: number; player: PlayerId; total: number; upper: number; upperBonus: number; lower: number; yahtzeeBonus: number }[]; winners: PlayerId[]; sheets: Record>>; summary: string; // 예: "민수 승리! 245점 (요트 1회)" } ``` ## 9. UI/UX - 모바일 세로: 위에 주사위 5개(각 64px 이상, 고정된 주사위는 아래로 내려가며 자물쇠 표시), 그 아래 큰 "굴리기 (남은 2번)" 버튼, 아래 절반은 점수표. 점수표는 내 열을 크게, 다른 사람은 가로 스크롤 열 또는 탭. - 조작: 주사위를 누르면 고정/해제. 점수표의 빈 칸에 미리보기 점수가 회색으로 보이고, 누르면 "식스에 24점 기록할까요?" 확인 후 기록(실수 방지, 설정에서 끌 수 있음). - 하이라이트: 조건을 만족하는 칸은 초록색, 0점이 되는 칸은 흐리게. 상단 보너스 진행률("63까지 12점 남음") 막대. - 애니메이션: 주사위 굴림 0.6초(서버 결과 수신 후 재생). 요트 달성 시 큰 축하 효과. - 초보자 도움말: "규칙 보기"에 칸별 조건과 예시 그림. 힌트 옵션: 추천 고정(간단한 휴리스틱: 가장 많은 같은 눈 유지)을 연하게 표시. - 다른 사람 차례에도 주사위와 고정 상태가 실시간으로 보인다(관전 재미). ## 10. 테스트 체크리스트 - [ ] `yacht51` 점수: [6,6,6,6,2] 각 칸 값이 6.1 예시와 일치. [3,3,5,5,5] 풀 하우스 21. [1,2,3,4,6] 스몰 15, 라지 0. [2,3,4,5,6] 스몰 15, 라지 30. - [ ] `fullHouseAllowsYacht`: [4,4,4,4,4] 풀 하우스 = 20(true) / 0(false). - [ ] 상단 보너스: 상단 합 62 → 0, 63 → 35. - [ ] 첫 굴림 전 `SCORE`, `SET_HOLD` 거부. 3번 굴린 뒤 `ROLL` 거부. 5개 모두 고정 후 `ROLL` 거부. - [ ] 고정 해제 후 재굴림: 2번째에 고정한 주사위를 3번째에 풀면 그 주사위도 굴려진다. - [ ] 이미 채운 칸 `SCORE` 거부. 조건 불충족 칸은 0점 기록 허용. - [ ] `yahtzee` 요트 보너스: 요트 50 기록 후 두 번째 요트 → +100. 요트 칸 0점이면 보너스 0. - [ ] `forced` 조커: 요트 칸 채움 + [5,5,5,5,5] + 파이브 칸 비어 있음 → 파이브 이외 `SCORE` 거부. 파이브 차 있음 → 라지 스트레이트 40 인정. 하단 모두 차 있음 → 빈 상단 칸 0점만 허용. - [ ] 12라운드 × 3명 진행 후 자동 종료, 동점자는 같은 rank. - [ ] 시간 초과: 굴리지 않은 상태 → 자동 굴림 후 최고 점수 칸 기록. 모든 칸 0점 → 희생 순서대로 기록. - [ ] 연결 끊김 사용자 차례가 유예 후 자동 진행되고, 다른 사람 진행이 막히지 않음. - [ ] 기권: 남은 칸 0점, 이후 차례에서 제외, 결과에 포함. - [ ] 정보 유출: View에 `rng` 없음. 같은 시드·액션 열 리플레이 시 같은 주사위. - [ ] 1인 플레이: 12라운드 연속 진행, 결과 정상. ## 11. 참고 자료 - 나무위키 "요트(주사위)": https://namu.wiki/w/요트(주사위) (51 수록판 칸별 점수, 최대 325점, 전통 규칙과의 차이) - 나무위키 "세계 게임전집 51": https://namu.wiki/w/51%20Worldwide%20Games - Wikipedia "Yacht (dice game)": https://en.wikipedia.org/wiki/Yacht_(dice_game) - Wikipedia "Yahtzee"(13칸 점수, 요트 보너스 100, 강제/자유 조커 규칙): https://en.wikipedia.org/wiki/Yahtzee ## 12. 메모 (상표·법적 주의 등) - "Yahtzee"(야찌)는 Hasbro의 등록 상표다. 화면·옵션 이름에 쓰지 말고 "13칸 변형", "미국식 규칙" 등으로 표기한다. "요트(Yacht)"는 오래된 공용 게임 이름이라 사용 가능하다. - "세계의 아소비 대전 51", "Clubhouse Games"는 닌텐도 상표이므로 화면에 "○○ 규칙"처럼 쓰지 않고 내부 문서에서만 출처로 언급한다. 표시 이름 후보: "요트 다이스", "주사위 요트". - 돈·포인트를 걸지 않는다. 점수는 게임 안 점수일 뿐이다.