Files
joke-app/docs/games/marble.md
EJClaw f4d63e1544 docs: 온라인 보드게임 사이트 계획서 (공통 14편 + 게임 26종)
- 개요, 조사(BGA·한국 인기 보드게임·UI/UX), 아키텍처, 실시간 프로토콜,
  안정성·보안, 계정, 로비·방, UI/UX, 데이터 모델, 게임 엔진, 테스트,
  배포·운영, 로드맵(M0~M9), 사용자 결정 항목
- 게임별 규칙·엔진 설계·UI·테스트 체크리스트 26종

Co-Authored-By: Claude Opus 5.5 <noreply@anthropic.com>
2026-10-04 04:18:29 +09:00

351 lines
28 KiB
Markdown
Raw 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.
# 세계 여행 땅따먹기 (`marble`)
> 마일스톤: M6 · 인원: 최소 2 ~ 최대 4명 · 예상 시간: 약 30~50분(기본 20라운드 제한) · 난이도: 쉬움~보통
## 1. 개요
- 주사위 2개를 굴려 세계 도시 40칸 판을 돌며 땅을 사고 건물을 지어, 남이 내 땅에 오면 통행료를 받는 "주사위 땅따먹기" 게임. 상대를 모두 파산시키거나, 제한 라운드가 끝났을 때 총자산이 가장 많은 사람이 이긴다.
- 한국에서는 1982년 출시된 "부루마불"(씨앗사)과 모바일 게임 "모두의마블"(넷마블)로 세대를 가리지 않고 알려진 장르다. 이 문서는 두 게임의 공통 뼈대(무인도, 사회복지기금, 우주여행, 카드 칸, 더블 규칙, 파산)를 따르되, 판·도시 배치·가격·카드는 모두 자체 설계했다. 모두의마블식 요소(인수, 랜드마크, 독점 승리)는 옵션으로 둔다.
- 인원 근거: 부루마불 기본 2~4명. 모두의마블도 개인전 최대 4명.
## 2. 모드와 옵션
| 옵션 키 | 설명 | 선택지 | 기본값 |
|---|---|---|---|
| `startMoney` | 시작 자금(만) | 200, 300, 500 | 300 |
| `salary` | 출발 칸을 지나거나 도착할 때 받는 월급(만) | 10, 20, 30 | 20 |
| `maxRounds` | 라운드 제한(0 = 무제한, 파산으로만 종료) | 0, 15, 20, 30 | 20 |
| `buildOnPurchase` | 땅을 산 그 방문에서 별장까지 바로 지을 수 있는지 | `true`, `false` | `false` |
| `islandTurns` | 무인도에서 최대 쉬는 차례 수 | 1, 2, 3 | 3 |
| `islandFee` | 무인도 탈출 비용을 내고 바로 나갈 수 있는지(만, 0 = 불가) | 0, 10, 20 | 0 |
| `takeover` | 인수: 남의 도시에 도착해 통행료를 낸 뒤 2배 값에 강제 매입(모두의마블식) | `true`, `false` | `false` |
| `landmark` | 호텔 다음 단계 랜드마크(인수 불가, 통행료 최고) | `true`, `false` | `false` |
| `monopolyWin` | 독점 즉시 승리(트리플·라인·관광지) | `true`, `false` | `false` |
| `trade` | 플레이어 간 도시·돈 교환 | `true`, `false` | `false` |
| `turnSeconds` | 결정 1회당 제한 시간 | 15, 30, 60, `null` | 30 |
- 돈은 방 안에서만 쓰는 가상 화폐이며 단위는 "만"으로 표시한다. 게임이 끝나면 사라지고 계정에 저장·이월·교환되지 않는다.
## 3. 구성물
- 판 40칸(아래 표), 주사위 2개, 말 4개, 땅 문서(도시 24 + 관광지 4), 건물(별장·빌딩·호텔·랜드마크), 행운카드 20장, 은행(무제한 돈), 사회복지기금 적립금.
### 3.1 판 배치(시계 방향 0→39)
| 칸 | 이름 | 종류 | | 칸 | 이름 | 종류 |
|---|---|---|---|---|---|---|
| 0 | 출발 | 모서리 | | 20 | 사회복지기금 받는 곳 | 모서리 |
| 1 | 타이베이 | 도시 A | | 21 | 부에노스아이레스 | 도시 E |
| 2 | 행운카드 | 카드 | | 22 | 행운카드 | 카드 |
| 3 | 마닐라 | 도시 A | | 23 | 상파울루 | 도시 E |
| 4 | 하노이 | 도시 A | | 24 | 시드니 | 도시 E |
| 5 | 제주도 | 관광지 | | 25 | 우주센터 | 관광지 |
| 6 | 방콕 | 도시 B | | 26 | 리스본 | 도시 F |
| 7 | 행운카드 | 카드 | | 27 | 마드리드 | 도시 F |
| 8 | 싱가포르 | 도시 B | | 28 | 행운카드 | 카드 |
| 9 | 카이로 | 도시 B | | 29 | 파리 | 도시 F |
| 10 | 무인도 | 모서리 | | 30 | 우주여행 | 모서리 |
| 11 | 이스탄불 | 도시 C | | 31 | 런던 | 도시 G |
| 12 | 행운카드 | 카드 | | 32 | 밴쿠버 | 도시 G |
| 13 | 아테네 | 도시 C | | 33 | 행운카드 | 카드 |
| 14 | 로마 | 도시 C | | 34 | 샌프란시스코 | 도시 G |
| 15 | 경주 | 관광지 | | 35 | 부산 | 관광지 |
| 16 | 코펜하겐 | 도시 D | | 36 | 뉴욕 | 도시 H |
| 17 | 행운카드 | 카드 | | 37 | 도쿄 | 도시 H |
| 18 | 스톡홀름 | 도시 D | | 38 | 사회복지기금 내는 곳 | 특수 |
| 19 | 베를린 | 도시 D | | 39 | 서울 | 도시 H |
- 합계: 도시 24(8그룹 × 3), 관광지 4, 행운카드 7, 모서리 4, 사회복지기금 내는 곳 1 = 40.
- "라인"(독점 판정용): 1번 줄 1~9, 2번 줄 11~19, 3번 줄 21~29, 4번 줄 31~39(각 줄 도시 6곳, 관광지 제외).
### 3.2 도시 가격표(단위: 만)
- 건설비는 단계마다 따로 내는 금액(별장 = 땅값 × 0.5, 빌딩 × 1.0, 호텔 × 1.5, 랜드마크 × 2.0, 반올림).
- 통행료 = 땅값 × [땅만 0.2(최소 1), 별장 0.6, 빌딩 1.5, 호텔 2.5, 랜드마크 4.0], 반올림.
- `*` 랜드마크 열은 `landmark=true`일 때만 사용.
| 칸 | 도시 | 그룹 | 땅값 | 별장 | 빌딩 | 호텔 | 랜드마크* | 통행료: 땅 | 별장 | 빌딩 | 호텔 | 랜드마크* |
|---|---|---|---|---|---|---|---|---|---|---|---|---|
| 1 | 타이베이 | A | 6 | 3 | 6 | 9 | 12 | 1 | 4 | 9 | 15 | 24 |
| 3 | 마닐라 | A | 6 | 3 | 6 | 9 | 12 | 1 | 4 | 9 | 15 | 24 |
| 4 | 하노이 | A | 8 | 4 | 8 | 12 | 16 | 2 | 5 | 12 | 20 | 32 |
| 6 | 방콕 | B | 10 | 5 | 10 | 15 | 20 | 2 | 6 | 15 | 25 | 40 |
| 8 | 싱가포르 | B | 10 | 5 | 10 | 15 | 20 | 2 | 6 | 15 | 25 | 40 |
| 9 | 카이로 | B | 12 | 6 | 12 | 18 | 24 | 2 | 7 | 18 | 30 | 48 |
| 11 | 이스탄불 | C | 14 | 7 | 14 | 21 | 28 | 3 | 8 | 21 | 35 | 56 |
| 13 | 아테네 | C | 14 | 7 | 14 | 21 | 28 | 3 | 8 | 21 | 35 | 56 |
| 14 | 로마 | C | 16 | 8 | 16 | 24 | 32 | 3 | 10 | 24 | 40 | 64 |
| 16 | 코펜하겐 | D | 18 | 9 | 18 | 27 | 36 | 4 | 11 | 27 | 45 | 72 |
| 18 | 스톡홀름 | D | 18 | 9 | 18 | 27 | 36 | 4 | 11 | 27 | 45 | 72 |
| 19 | 베를린 | D | 20 | 10 | 20 | 30 | 40 | 4 | 12 | 30 | 50 | 80 |
| 21 | 부에노스아이레스 | E | 22 | 11 | 22 | 33 | 44 | 4 | 13 | 33 | 55 | 88 |
| 23 | 상파울루 | E | 22 | 11 | 22 | 33 | 44 | 4 | 13 | 33 | 55 | 88 |
| 24 | 시드니 | E | 24 | 12 | 24 | 36 | 48 | 5 | 14 | 36 | 60 | 96 |
| 26 | 리스본 | F | 26 | 13 | 26 | 39 | 52 | 5 | 16 | 39 | 65 | 104 |
| 27 | 마드리드 | F | 26 | 13 | 26 | 39 | 52 | 5 | 16 | 39 | 65 | 104 |
| 29 | 파리 | F | 28 | 14 | 28 | 42 | 56 | 6 | 17 | 42 | 70 | 112 |
| 31 | 런던 | G | 30 | 15 | 30 | 45 | 60 | 6 | 18 | 45 | 75 | 120 |
| 32 | 밴쿠버 | G | 30 | 15 | 30 | 45 | 60 | 6 | 18 | 45 | 75 | 120 |
| 34 | 샌프란시스코 | G | 32 | 16 | 32 | 48 | 64 | 6 | 19 | 48 | 80 | 128 |
| 36 | 뉴욕 | H | 35 | 18 | 35 | 53 | 70 | 7 | 21 | 53 | 88 | 140 |
| 37 | 도쿄 | H | 35 | 18 | 35 | 53 | 70 | 7 | 21 | 53 | 88 | 140 |
| 39 | 서울 | H | 40 | 20 | 40 | 60 | 80 | 8 | 24 | 60 | 100 | 160 |
### 3.3 관광지(건물 없음)
| 칸 | 이름 | 땅값 | 통행료 | 비고 |
|---|---|---|---|---|
| 5 | 제주도 | 20 | 10 | |
| 15 | 경주 | 20 | 10 | |
| 25 | 우주센터 | 30 | 15 | 우주여행 탑승료(20)도 소유자가 받음 |
| 35 | 부산 | 25 | 12 | |
- 같은 사람이 관광지를 여러 곳 가지면 각 관광지 통행료가 2배(2곳 이상 소유 시). 인수 불가.
### 3.4 고정 금액
| 항목 | 금액(만) |
|---|---|
| 월급(출발 통과·도착) | `salary`(기본 20) |
| 사회복지기금 납부(38번 칸) | 15 |
| 우주여행 탑승료 | 20(우주센터를 다른 사람이 가지고 있을 때만 그 사람에게) |
| 무인도 탈출비 | `islandFee`(기본 0 = 불가) |
| 건물 매각가 | 그 단계에 낸 건설비(또는 땅값)의 50%, 내림 |
### 3.5 행운카드 20장(자체 설계, 각 1장)
| ID | 이름 | 효과 |
|---|---|---|
| L01 | 복권 당첨 | 은행에서 20 받기 |
| L02 | 장학금 | 은행에서 10 받기 |
| L03 | 주식 배당 | 은행에서 15 받기 |
| L04 | 생일 축하 | 다른 플레이어 모두에게서 각 5 받기 |
| L05 | 예금 이자 | 은행에서 10 받기 |
| L06 | 과속 벌금 | 5를 사회복지기금에 적립 |
| L07 | 병원비 | 은행에 10 내기 |
| L08 | 이웃 돕기 성금 | 10을 사회복지기금에 적립 |
| L09 | 건물 수리비 | 내 건물마다 별장 3, 빌딩 6, 호텔 10, 랜드마크 15를 은행에 내기(도시 하나의 건물 단계마다 해당 금액을 합산: 호텔까지 지은 도시는 별장+빌딩+호텔 = 19) |
| L10 | 폭풍 경보 | 무인도로 바로 이동(출발을 지나도 월급 없음, 더블 연속 끊김) |
| L11 | 무인도 탈출권 | 보관. 무인도에서 사용하면 즉시 탈출. 쓰면 카드 더미 맨 아래로 |
| L12 | 통행료 면제권 | 보관. 다음에 다른 플레이어에게 통행료를 낼 때 자동 사용(1회). 쓰면 맨 아래로 |
| L13 | 출발지로 | 출발(0)로 이동, 월급 받기 |
| L14 | 우주 초대장 | 우주여행(30)으로 앞으로 이동(출발을 지나면 월급). 도착 효과 적용 |
| L15 | 서울 관광 | 서울(39)로 앞으로 이동(출발을 지나면 월급). 도착 효과 적용 |
| L16 | 뒤로 3칸 | 뒤로 3칸 이동(월급 없음). 도착 효과 적용 |
| L17 | 기부 천사 | 사회복지기금 받는 곳(20)으로 앞으로 이동(출발 지나면 월급), 적립금 받기 |
| L18 | 관광 안내 | 앞으로 가장 가까운 관광지로 이동(출발 지나면 월급). 도착 효과 적용 |
| L19 | 여행 경비 | 다른 플레이어 모두에게 각 5 주기 |
| L20 | 재산세 | 내가 가진 땅(도시·관광지) 1곳당 2를 은행에 내기 |
- 이동 카드로 도착한 칸이 행운카드 칸이면 다시 카드를 뽑는다(연쇄 가능, 이론상 무한 반복 방지를 위해 한 차례에 카드 5장 이상이면 이후 카드 칸 효과 무시).
- 사용한 카드는 더미 맨 아래로. 보관 카드(L11, L12)는 사용할 때까지 그 플레이어 앞에 두고, 사용 후 맨 아래로. 파산하면 보관 카드도 맨 아래로.
## 4. 준비(셋업)
1. 차례 순서 RNG로 섞기(원작: 주사위로 결정).
2. 모두 출발(0) 칸, 현금 `startMoney`.
3. 행운카드 20장 섞어 비공개 더미.
4. 사회복지기금 적립금 0. 모든 땅 은행 소유(주인 없음).
5. 라운드 1.
## 5. 진행 규칙
### 5.1 차례
1. (무인도에 있으면 5.4, 우주여행 대기 중이면 5.5 먼저)
2. `ROLL`: 주사위 2개 굴려 합만큼 시계 방향 이동. 출발(0)을 지나거나 도착하면 월급.
3. 도착 칸 처리(5.2).
4. 더블(두 주사위 같은 눈)이면 도착 처리 후 한 번 더 `ROLL`. 같은 차례에 3번째 더블이 나오면 이동하지 않고 즉시 무인도로 가며 차례 끝(월급 없음).
- 더블로 이동했어도 무인도로 가게 되거나(카드 L10 포함), 우주여행 칸에 도착하면 추가 굴림은 사라진다.
5. 차례 종료.
### 5.2 도착 칸 처리
- 주인 없는 도시/관광지: `BUY`(땅값 지불) 또는 `PASS`. 현금이 부족하면 살 수 없다(돈을 만들기 위해 팔고 사는 것은 불가). 경매 없음.
- `buildOnPurchase=true`이면 산 직후 별장 1단계까지 바로 지을 수 있다.
- 내 도시: 다음 단계 건물 1개를 지을 수 있다(`BUILD`) 또는 `PASS`. 순서는 별장 → 빌딩 → 호텔 → (랜드마크). 한 방문에 1단계만. 땅을 산 그 방문에는 짓지 못한다(옵션 예외).
- 남의 도시/관광지: 통행료를 그 주인에게 낸다(3.2/3.3 표). 통행료 면제권이 있으면 자동 사용. 주인이 무인도에 있어도 받는다. 이후 `takeover=true`이고 랜드마크가 아닌 도시면 인수 선택(5.7).
- 행운카드: 맨 위 카드를 뽑아 즉시 적용(3.5).
- 사회복지기금 내는 곳(38): 15를 적립금에 넣는다.
- 사회복지기금 받는 곳(20): 적립금 전부를 받는다(0이면 아무 일 없음).
- 무인도(10): 무인도에 갇힘(5.4). 단순히 지나가면 아무 일 없음.
- 우주여행(30): 다음 차례에 우주여행(5.5). 이번 차례 종료(더블 추가 굴림 소멸).
- 출발(0)에 정확히 도착: 월급(지나갈 때와 같은 1회분).
### 5.3 지불과 파산
- 반드시 내야 하는 돈(통행료, 카드 지출, 기금 납부, 우주여행 탑승료)이 현금보다 많으면 "빚 갚기" 단계(무인도 탈출비·구매·건설·인수처럼 스스로 고르는 지출은 현금이 충분할 때만 가능하므로 빚이 생기지 않는다):
- 먼저 서버가 최대 확보 가능액 = 현금 + 모든 건물·땅 매각가 합을 계산한다. 이것이 빚보다 작으면 즉시 파산.
- 그렇지 않으면 그 플레이어가 `SELL`로 건물(맨 위 단계부터 1단계씩) 또는 땅(건물 전부 포함)을 은행에 팔아 현금이 빚 이상이 될 때까지 반복. 매각가 = 그 단계에 냈던 금액의 50%(내림). 다 모이면 자동 지불.
- 파산: 가진 모든 건물·땅을 매각가로 은행에 팔아 생긴 현금 전부를 채권자(다른 플레이어, 은행, 기금 중 빚을 진 상대)에게 준다. 땅은 은행 소유(건물 없음)로 돌아간다. 파산한 사람은 탈락(관전으로 전환).
- 여러 사람에게 내야 하는 카드(L19)는 좌석 순으로 1명씩 별도의 빚으로 처리한다. 도중에 파산하면 그때의 채권자가 남은 돈을 받고 나머지 사람은 받지 못한다.
- 은행 돈은 무한. 은행에 돈이 모자라는 일은 없다.
### 5.4 무인도
- 무인도에 들어가면 `islandLeft = islandTurns`(기본 3). 더블 연속은 끊긴다.
- 무인도에 있는 내 차례에 다음 중 하나:
- `ROLL`: 더블이면 즉시 탈출해 그 합만큼 이동(이번 더블로는 추가 굴림 없음). 더블이 아니면 이동하지 않고 `islandLeft -= 1`, 차례 끝. `islandLeft`가 0이 되면 다음 차례부터 일반 진행.
- `USE_ESCAPE_CARD`(L11 보유 시) 또는 `PAY_ISLAND_FEE`(`islandFee > 0`이고 현금 충분): 즉시 탈출 후 같은 차례에 일반 `ROLL`(더블 규칙 정상 적용).
- 무인도에 있어도 땅 주인으로서 통행료는 받는다. 교환(옵션)도 가능.
### 5.5 우주여행
- 우주여행 칸에 도착한 다음 내 차례에는 주사위를 굴리지 않고 `SPACE_TRAVEL { dest }`로 판의 아무 칸(30번 제외)이나 골라 시계 방향으로 이동한다.
- 탑승료: 우주센터(25)가 다른 플레이어 소유면 그 사람에게 20. 은행 소유거나 내 것이면 무료.
- 이동 경로가 출발(0)을 지나거나 0에 도착하면 월급.
- 도착 칸 효과를 적용(구매·통행료·카드 등). 이 차례는 더블이 없으므로 추가 굴림 없음.
### 5.6 라운드와 종료
- 라운드: 생존한 모든 플레이어가 한 차례씩 마치면 1라운드. 선(차례 순서 첫 사람)이 파산하면 다음 생존자가 라운드 기준이 된다.
- 종료: (1) 생존자 1명, (2) `maxRounds` 라운드가 끝남, (3) `monopolyWin=true`이고 누군가 독점 달성(즉시).
### 5.7 모두의마블식 옵션
- 인수(`takeover`): 남의 도시(관광지·랜드마크 제외)에서 통행료를 낸 뒤, 인수가 = 2 × (그 도시의 땅값 + 지어진 건물의 건설비 합)을 그 주인에게 내고 소유권(건물 포함)을 가져올 수 있다. 주인은 거부할 수 없다. 인수한 방문에는 추가 건설 불가. 현금이 부족하면 인수 불가(빚 갚기로 만들 수 없음).
- 랜드마크(`landmark`): 호텔이 있는 내 도시에 다음 방문 때 지을 수 있는 5번째 단계. 인수 불가.
- 독점 승리(`monopolyWin`): 차례 중 어느 시점이든 아래를 만족하면 즉시 승리.
- 트리플 독점: 도시 그룹(A~H) 3개를 각각 3곳 모두 소유.
- 라인 독점: 한 줄(3.1의 라인)의 도시 6곳 모두 소유.
- 관광지 독점: 관광지 4곳 모두 소유.
### 5.8 교환(옵션, 기본 꺼짐)
- `trade=true`일 때, 내 차례에 주사위를 굴리기 전(또는 무인도·우주여행 선택 전)에 1명에게 제안할 수 있다: 주는 것(내 땅들 + 현금) ↔ 받는 것(상대 땅들 + 현금). 건물이 있는 땅은 건물째로 넘어간다.
- 제안을 받은 사람은 `TRADE_RESPOND { accept }`. 제한 시간 안에 응답이 없으면 거절. 한 차례에 제안은 최대 2번. 현금은 제안 시점과 수락 시점 모두 보유액 이내여야 한다.
### 5.9 예시
- A가 서울(39, B 소유, 호텔)에 도착 → 통행료 100. A 현금 70, 확보 가능액 = 70 + 매각가 합 50 = 120 ≥ 100 → 빚 갚기 단계. A가 리스본 빌딩(건설비 26 → 매각 13)과 별장(13 → 6), 리스본 땅(26 → 13)을 팔아 현금 102 → 자동으로 100 지불, 현금 2.
- B가 37(도쿄)에서 더블 4-4 → 8칸 이동, 출발(0)을 지나 5(제주도) 도착, 월급 20 받고 제주도 구매 여부 결정 → 더블이므로 다시 굴림.
- C가 우주여행 칸 도착 → 다음 차례 `SPACE_TRAVEL { dest: 39 }`, 우주센터 주인 D에게 20, 30→39 이동(출발 안 지남, 월급 없음), 서울 처리.
## 6. 승패와 점수 계산
- 파산으로 생존자 1명 → 그 사람 1위. 탈락 순서의 역순으로 순위(먼저 파산한 사람이 꼴찌).
- 라운드 제한 종료 → 총자산 = 현금 + Σ(소유 땅의 땅값 + 지어진 건물 건설비 합, 정가 100%). 총자산 많은 순. 동점이면 현금 많은 순, 그래도 같으면 공동 순위. 파산자는 생존자보다 아래.
- 독점 승리 → 달성자 1위, 나머지는 총자산 순.
- 예: 현금 120, 서울(땅 40 + 별장 20 + 빌딩 40), 제주도(20) → 총자산 = 120 + 100 + 20 = 240.
## 7. 지역 룰 / 하우스 룰 (옵션으로 켜고 끄기)
- 이미 옵션화: 시작 자금, 월급, 라운드 제한, 구매 즉시 건설, 무인도 쉬는 차례 수와 탈출비, 인수, 랜드마크, 독점 승리, 교환.
- 지원하지 않는 변형(문서화만): 경매, 대출, 같은 그룹 독점 시 통행료 2배(모노폴리식), 모두의마블의 올림픽·세계여행 비용 변형·통행료 배수 증가, 팀전. 요구가 있으면 옵션으로 추가.
- 원작 부루마불은 한 도시에 별장 최대 2채·빌딩·호텔을 자유롭게 섞어 짓지만, 우리 판은 어린이도 이해하기 쉽게 "한 단계씩 올리는" 방식으로 단순화했다.
## 8. 엔진 설계
### 8.1 상태(State)
```ts
type Pos = number; // 0..39
type Level = 0 | 1 | 2 | 3 | 4; // 0 땅만, 1 별장, 2 빌딩, 3 호텔, 4 랜드마크
type Creditor = { kind: 'player'; id: PlayerId } | { kind: 'bank' } | { kind: 'fund' };
interface MarbleState {
options: MarbleOptions;
rng: RngState;
order: PlayerId[];
current: number;
round: number;
phase:
| 'turnStart' // 굴리기(또는 무인도/우주여행 선택, 교환 제안)
| 'decide' // 구매/건설/인수 결정
| 'debt' // 빚 갚기(매각)
| 'tradeResponse' // 교환 응답 대기
| 'finished';
players: Record<PlayerId, {
pos: Pos; cash: number; alive: boolean; bankruptAtRound: number | null;
islandLeft: number; // 0이면 무인도 아님
spacePending: boolean;
heldCards: ('L11' | 'L12')[];
}>;
owners: Record<Pos, { owner: PlayerId; level: Level } | undefined>; // 도시·관광지만
fund: number;
deck: string[]; // 비공개, 0번 = 맨 위
doublesThisTurn: number;
cardsThisTurn: number;
decision: null | {
pos: Pos;
canBuy: boolean; canBuild: Level | null; canTakeover: number | null; // 인수가
boughtThisVisit: boolean;
};
debt: null | { amount: number; to: Creditor; then: 'continueTurn' | 'nextCreditor'; queue: { amount: number; to: Creditor }[] };
pendingTrade: null | { from: PlayerId; to: PlayerId; give: { lands: Pos[]; cash: number }; take: { lands: Pos[]; cash: number } };
tradesThisTurn: number;
extraRoll: boolean; // 더블로 한 번 더
lastRoll: [number, number] | null;
turnSeq: number;
deadlineAt: number | null;
}
```
### 8.2 액션
| type | payload | 누가 / 언제 | 검증 조건 |
|---|---|---|---|
| `ROLL` | 없음 | 현재 차례, `turnStart` | 우주여행 대기 아님. 무인도면 무인도 굴림으로 처리 |
| `PAY_ISLAND_FEE` | 없음 | 현재 차례, `turnStart`, `islandLeft > 0` | `islandFee > 0`, 현금 ≥ 탈출비 |
| `USE_ESCAPE_CARD` | 없음 | 위와 같음 | L11 보유 |
| `SPACE_TRAVEL` | `{ dest: Pos }` | 현재 차례, `turnStart`, `spacePending` | `dest ≠ 30`, 0..39. 탑승료는 빚 규칙 적용 |
| `BUY` | 없음 | 현재 차례, `decide`, `canBuy` | 현금 ≥ 땅값. 위반: "돈이 부족해요." |
| `BUILD` | `{ level }` | 현재 차례, `decide` | `level = 현재 단계 + 1`, 랜드마크는 옵션 켜짐, 이번 방문 미건설, 구매 직후면 `buildOnPurchase`이고 `level=1`만, 현금 ≥ 건설비 |
| `TAKEOVER` | 없음 | 현재 차례, `decide`, `canTakeover` | 옵션 켜짐, 통행료 지불 완료, 랜드마크·관광지 아님, 현금 ≥ 인수가 |
| `PASS` | 없음 | 현재 차례, `decide` | 항상 가능 |
| `SELL` | `{ pos; what: 'top' \| 'all' }` | 빚진 사람, `debt` | 내 땅. `top`은 건물 단계 ≥ 1 |
| `PROPOSE_TRADE` | `{ to; give; take }` | 현재 차례, `turnStart`, `trade=true` | 상대 생존, 땅 소유 확인, 현금 ≤ 보유, 이번 차례 2회 미만, 빈 제안 아님 |
| `TRADE_RESPOND` | `{ accept: boolean }` | 제안받은 사람, `tradeResponse` | `pendingTrade.to`와 일치. 수락 시 소유·현금 재검증 |
| `CONCEDE` | 없음 | 참가자 | 파산과 같은 처리(채권자 은행). 생존자 1명이면 종료 |
- 처리 흐름(apply 내부, 자동 연쇄): 굴림 → 이동(월급) → 칸 효과 → 필요 시 `decide`/`debt` 단계 → 결정 후 독점 판정 → `extraRoll`이면 `turnStart`로, 아니면 다음 차례.
- 이벤트: `rolled{dice,double}`, `moved{from,to,passedStart}`, `salary`, `bought`, `built`, `tollPaid{from,to,amount,waived}`, `takeover`, `cardDrawn{cardId}`, `fundPaid`, `fundReceived`, `toIsland`, `islandRoll`, `escaped`, `spaceTravel`, `sold`, `bankrupt{player,creditor,amount}`, `tradeProposed`, `tradeResolved`, `roundEnd`, `monopoly`, `gameOver`.
### 8.3 공개/비공개 정보 (view)
- 공개(모두·관전자 동일): 말 위치, 모든 현금, 땅 소유와 건물 단계, 적립금, 보관 카드 종류, 무인도·우주여행 상태, 라운드, 주사위, 뽑힌 카드(뽑는 순간 공개), 교환 제안 내용.
- 비공개: 행운카드 더미 순서(남은 장 수만 공개), `rng`.
- 현재 결정 중인 사람에게 `decision`의 선택지와 비용 미리보기, 빚 갚기 중이면 매각 후보와 매각가.
### 8.4 랜덤 요소 (시드 RNG 사용 지점)
- 셋업: 차례 순서, 행운카드 더미 섞기.
- `ROLL`(무인도 굴림 포함): 주사위 2개 `1 + floor(rng()*6)` 순서대로.
- 더미는 맨 아래로 돌려 넣으므로 다시 섞지 않는다.
### 8.5 타이머·시간 초과·연결 끊김 시 자동 행동
- `deadline`: 결정이 필요할 때마다 `now + turnSeconds`. 교환 응답은 20초 고정.
- `onTimeout`(결정적):
- `turnStart`: 무인도면 `ROLL`(돈 쓰지 않음). 우주여행이면 `SPACE_TRAVEL { dest: 0 }`(출발, 월급). 그 외 `ROLL`.
- `decide`: `PASS`(자리 비운 사람의 돈을 마음대로 쓰지 않음).
- `debt`: 매각가가 작은 것부터 자동 `SELL top`, 건물이 없으면 땅값 작은 땅부터 `SELL all`(동률이면 칸 번호 작은 것).
- `tradeResponse`: 거절.
- 끊긴 사람: 5초 유예 후 위 규칙. 2라운드 연속 자리 비움이면 방장에게 "강퇴/계속" 선택 제공(강퇴 = `CONCEDE`).
### 8.6 종료 조건과 결과(GameResult)
```ts
interface MarbleResult {
reason: 'lastSurvivor' | 'roundLimit' | 'monopoly';
monopolyType?: 'triple' | 'line' | 'tour';
ranking: { rank: number; player: PlayerId; totalAssets: number; cash: number; lands: number; bankruptAtRound: number | null }[];
winners: PlayerId[];
summary: string; // 예: "20라운드 종료! 수진 총자산 812만으로 승리"
}
```
## 9. UI/UX
- 모바일 세로: 정사각형 판을 화면 폭에 맞춰 위에 배치(칸이 작으므로 칸을 누르면 큰 정보 카드 팝업: 주인, 건물, 통행료표). 판 가운데 빈 공간에 주사위와 큰 "굴리기" 버튼, 적립금 표시. 판 아래에 플레이어 카드(현금, 땅 수, 색) 가로 4칸.
- 결정 화면: 하단 시트로 "타이베이를 6만에 살까요?" + 큰 "사기"/"안 사기" 버튼, 남은 현금 미리보기.
- 하이라이트: 이동 경로 칸이 차례로 빛나며 말이 이동. 내 땅은 내 색 테두리, 건물 아이콘(별장 집 1채 → 빌딩 → 호텔 → 랜드마크 탑).
- 우주여행: 판의 칸들이 모두 선택 가능 상태로 빛나고, 칸을 누르면 "여기로 가면: 월급 받음/통행료 ○○" 미리보기.
- 빚 갚기: "○○만이 모자라요" 진행 막대와 매각 후보 목록(매각가 표시), 다 모이면 자동 지불.
- 애니메이션: 주사위 굴림, 돈이 오가는 숫자 팝업(+20, −100), 파산 시 땅 색이 회색으로.
- 초보자 도움말: 칸 종류별 설명, "더블이면 한 번 더, 3번 연속이면 무인도" 안내. 힌트 옵션: "이 땅을 사면 남은 돈 ○○" 경고(현금이 50 미만이 되면 주황색).
## 10. 테스트 체크리스트
- [ ] 판 데이터: 40칸 구성(도시 24, 관광지 4, 카드 7, 특수 5), 가격표 스냅샷 일치.
- [ ] 월급: 37에서 5칸 → 2 도착, 월급 1회. 0에 정확히 도착해도 1회. 뒤로 3칸 카드로 0을 거꾸로 지나면 월급 없음.
- [ ] 더블: 더블 → 처리 후 재굴림. 3번째 더블 → 이동 없이 무인도, 월급 없음.
- [ ] 더블로 우주여행 도착 → 추가 굴림 소멸, 다음 차례 `SPACE_TRAVEL`만 허용(`ROLL` 거부).
- [ ] 무인도: `islandTurns=3`, 비더블 3번 → 4번째 차례 일반 진행. 무인도 더블 → 탈출·이동, 추가 굴림 없음. 탈출권 사용 → 같은 차례 일반 굴림, 더블이면 재굴림.
- [ ] 건설: 구매한 방문에 `BUILD` 거부(`buildOnPurchase=false`). 다음 방문 별장만 허용, 빌딩 건너뛰기 거부. 한 방문 2단계 거부.
- [ ] 통행료: 표 값 그대로. 면제권 자동 사용 후 카드 맨 아래로. 관광지 2곳 소유 시 통행료 2배.
- [ ] 빚 갚기: 5.9 예시 재현. 확보 가능액 < 빚이면 즉시 파산, 채권자가 매각 후 현금 전부 받음, 땅은 은행으로.
- [ ] L19(여행 경비) 중 파산: 좌석 순 앞사람만 받고 이후 사람은 못 받음.
- [ ] 사회복지기금: 38 도착 15 적립, L06/L08 적립, 20 도착 시 전액 수령 후 0.
- [ ] 우주여행: 우주센터 타인 소유 시 탑승료 20, 30→5 이동 시 출발 통과 월급.
- [ ] 인수(옵션): 통행료 지불 후 인수가 = 2 × 투자액, 랜드마크·관광지 거부. 옵션 꺼짐 시 액션 거부.
- [ ] 독점 승리(옵션): 관광지 4곳 소유 순간 즉시 종료.
- [ ] 라운드 제한 20: 20라운드 마지막 사람 차례 후 총자산 순위, 동점 시 현금 비교.
- [ ] 교환(옵션): 제안 후 상대 미응답 20초 → 거절. 수락 시점에 현금 부족하면 실패 처리.
- [ ] 시간 초과: `decide`는 항상 `PASS`(돈을 쓰지 않음), `debt`는 싼 것부터 자동 매각.
- [ ] 연결 끊김: 끊긴 사람의 차례가 자동 진행되고 통행료는 정상 수령.
- [ ] 정보 유출: View·이벤트에 카드 더미 순서와 `rng` 없음. 카드는 뽑힌 뒤에만 ID 공개.
- [ ] 리플레이 결정성: 같은 시드·액션 열로 같은 최종 자산.
## 11. 참고 자료
- 나무위키 "부루마불": https://namu.wiki/w/부루마불 (무인도 3턴·더블 탈출, 사회복지기금 납부/수령, 우주여행 탑승료, 황금열쇠, 별장·빌딩·호텔, 더블 3번 무인도, 파산)
- 나무위키 "모두의마블 for kakao/규칙": https://namu.wiki/w/모두의마블%20for%20kakao/규칙 (인수 2배, 랜드마크 인수 불가, 트리플·라인·관광지 독점, 턴 제한)
- Wikipedia "Monopoly (game)"(원형 장르, 파산·매각 규칙 참고): https://en.wikipedia.org/wiki/Monopoly_(game)
## 12. 메모 (상표·법적 주의 등)
- "부루마불"은 씨앗사, "모두의마블"은 넷마블, "Monopoly"는 Hasbro의 상표다. 화면·광고에 쓰지 말고 표시 이름은 자체 명칭(후보: "세계 여행 땅따먹기", "주사위 부자 여행", "지구 한 바퀴")으로 한다. "황금열쇠"라는 카드 이름도 부루마불을 강하게 연상시키므로 "행운카드"로 쓴다.
- 판 배치·가격·카드는 모두 자체 설계이며 원작의 수치·카드 문구를 옮기지 않았다. 도시 이름은 실제 지명이라 자유롭게 쓸 수 있다. 원작의 우주선 이름(콜롬비아호 등) 대신 "우주센터"를 쓴다.
- 사행성 주의: 돈은 방 안에서만 쓰는 가상 화폐로 저장·이월·환전이 없다. 실제 돈·상품 연동 금지. 규칙 보기에 명시한다.