- 개요, 조사(BGA·한국 인기 보드게임·UI/UX), 아키텍처, 실시간 프로토콜,
안정성·보안, 계정, 로비·방, UI/UX, 데이터 모델, 게임 엔진, 테스트,
배포·운영, 로드맵(M0~M9), 사용자 결정 항목
- 게임별 규칙·엔진 설계·UI·테스트 체크리스트 26종
Co-Authored-By: Claude Opus 5.5 <noreply@anthropic.com>
마일스톤: M7 · 인원: 최소 4 ~ 최대 8명 · 예상 시간: 한 라운드 약 10분 (기본 3라운드 약 30분) · 난이도: 쉬움
1. 개요
신분 계급이 있는 버리기형 카드 게임이다. 숫자가 낮을수록 좋은 카드다. 앞사람과 같은 장수를 더 낮은 숫자로 내고, 손패를 먼저 다 털수록 다음 라운드에서 높은 신분이 된다. 높은 신분은 세금으로 낮은 신분의 좋은 카드를 받는다.
원작은 리처드 가필드의 "The Great Dalmuti"(1995)다. 한국에서는 "위대한 달무티"로 학교와 모임 파티 게임으로 많이 알려졌다. 같은 계열 민속 게임으로 "대통령(President)", "대부호(大富豪)"가 있다.
인원 근거: 원작 박스 기준 48명. 나무위키도 48명(57명 권장)이다. 23명이나 9명 이상은 비공식이라 지원하지 않는다.
2. 모드와 옵션
옵션 키
설명
선택지
기본값
rounds
라운드 수
1 / 3 / 5 / 7
3
scoring
최종 순위 방식
rank-points(라운드별 순위 점수 합) / last-round(마지막 라운드 순위)
rank-points
firstRanking
첫 라운드 신분 정하기
draw(카드 뽑기, 원작) / random
draw
revolution
혁명 규칙 사용
on / off
on
jesterTaxable
세금 낼 때 광대도 "좋은 카드"로 내야 하나
on / off
off
passLocksOut
한 번 패스하면 그 트릭에서 다시 못 냄(하우스 룰)
on / off(원작)
off
removeHighCards
9~12 카드를 빼고 하기(손패가 많을 때, 나무위키 언급)
on / off
off
turnSeconds
턴 제한 시간
15 / 20 / 30 / 45
20
3. 구성물
숫자 카드 78장: 숫자 n인 카드가 n장이다(1이 1장, 2가 2장, …, 12가 12장).
광대(Jester) 2장. 단독으로 내면 13이고, 다른 카드와 함께 내면 그 숫자로 변한다(와일드).
합계 80장. removeHighCards = on이면 9~12(42장)를 빼고 38장으로 한다.
카드 이름(원작 계급 이름, 화면 표시용)
숫자
이름
장수
1
달무티
1
2
대주교
2
3
시종장
3
4
남작부인
4
5
수녀원장
5
6
기사
6
7
재봉사
7
8
석공
8
9
요리사
9
10
양치기
10
11
광부
11
12
농노
12
13(광대)
광대
2
플레이어 신분(라운드 순위)
1위: 대달무티
2위: 소달무티
3위 ~ N-2위: 평민
N-1위: 소농노
N위: 대농노
4인이면 평민이 없다.
4. 준비(셋업)
첫 라운드 신분(firstRanking = draw): 섞은 덱에서 각자 1장씩 뽑는다. 숫자가 낮을수록 높은 신분이고, 광대는 13으로 본다. 같은 숫자끼리는 그 사람들만 다시 뽑아 순서를 정한다. 엔진은 RNG로 같은 절차를 시뮬레이션하고 결과를 애니메이션으로 보여 준다.
자리와 순서: 신분 순서대로 시계 방향으로 앉는다(대달무티 → 소달무티 → 평민들 → 소농노 → 대농노 → 다시 대달무티). 턴 순서도 이 순서다.
분배: 덱을 섞어 대달무티부터 신분 순서대로 1장씩 전부 나눠 준다. 나누어떨어지지 않으면 앞 신분이 1장씩 더 받는다.
인원
손패(80장)
4
20 × 4
5
16 × 5
6
14, 14, 13, 13, 13, 13
7
12, 12, 12, 11, 11, 11, 11
8
10 × 8
혁명 확인 단계(revolution = on): 모든 플레이어가 손패를 확인하고 "확인"을 누른다. 광대 2장을 모두 가진 사람에게만 "혁명 선언" 버튼이 함께 보인다. 모든 사람이 같은 단계를 거치므로 단계가 생긴 것만으로 광대 소유자가 드러나지 않는다.
혁명: 광대 2장을 가진 사람(대농노 제외)이 선언하면 광대 2장을 공개한다. 이번 라운드는 세금을 걷지 않고, 신분은 그대로다.
대혁명: 대농노가 광대 2장을 가지고 선언하면 신분 순서가 완전히 뒤집힌다. 대농노가 대달무티, 대달무티가 대농노가 되고 평민 순서도 뒤집힌다. 자리와 턴 순서도 뒤집히고 세금은 없다.
선언은 선택이다. 선언하지 않으면 평소대로 세금을 걷는다.
세금(혁명이 없을 때)
대농노는 손패에서 가장 좋은(숫자가 가장 낮은) 카드 2장을 대달무티에게 준다. 소농노는 가장 좋은 카드 1장을 소달무티에게 준다. 선택권이 없으므로 서버가 자동으로 옮긴다.
jesterTaxable = off(기본)이면 광대는 "가장 좋은 카드" 계산에서 빼고 숫자 카드 중 가장 낮은 것을 준다. 같은 숫자가 여럿이면 어느 것을 줘도 같으므로 카드 ID 순으로 정한다.
받은 대달무티는 아무 카드 2장(방금 받은 카드 포함 가능), 소달무티는 아무 카드 1장을 골라 돌려준다. 두 사람은 동시에 고른다.
4인이면 소달무티 ↔ 소농노, 대달무티 ↔ 대농노만 있다.
첫 트릭은 대달무티가 시작한다(대혁명이면 새 대달무티).
5. 진행 규칙
5.1 트릭 진행
선(리드): 트릭을 시작하는 사람은 같은 숫자 카드를 원하는 장수(1장 이상)만큼 낸다. 광대를 섞어도 된다.
따라 내기: 다음 사람부터 순서대로, 바로 앞에 나온 묶음과 같은 장수이면서 숫자가 더 낮은(더 좋은) 묶음을 내거나 패스한다.
예: 9 세 장이 나왔으면 1~8 중 같은 숫자 세 장만 낼 수 있다(1은 1장뿐이라 광대를 섞어야 3장이 된다).
광대
광대만 내면 1장당 13이다. 광대 1장은 13 한 장, 광대 2장은 13 두 장이다.
숫자 카드와 함께 내면 그 숫자로 간주한다. 예: 4 + 광대 = 4 두 장, 1 + 광대 = 1 두 장(원작에 1과 광대를 같이 내는 것을 막는 문구가 없다).
한 묶음에 숫자 카드가 섞일 때 숫자 카드는 모두 같은 숫자여야 한다.
패스: 낼 수 있어도 언제든 패스할 수 있다. 원작 기본(passLocksOut = off)에서는 패스해도 같은 트릭에서 차례가 다시 오면 낼 수 있다.
트릭 종료: 마지막으로 낸 사람을 뺀, 아직 카드가 있는 나머지 모두가 연속으로 패스하면 트릭이 끝난다. 바닥 카드를 치우고 마지막으로 낸 사람이 새 트릭을 시작한다.
마지막으로 낸 사람이 그 묶음으로 손패를 다 털었으면, 턴 순서상 그 사람의 다음이면서 아직 카드가 있는 사람이 새 트릭을 시작한다.
passLocksOut = on이면 패스한 사람은 그 트릭의 나머지 차례가 자동으로 건너뛰어진다. 트릭 종료 조건은 같다.
5.2 손패를 다 턴 경우와 라운드 종료
손패를 모두 낸 순서대로 다음 라운드 신분이 정해진다. 처음 턴 사람이 다음 대달무티, 두 번째가 소달무티, …
카드가 남은 사람이 1명이 되면 라운드가 끝나고 그 사람이 다음 대농노다. 그 사람의 남은 카드는 따로 내지 않는다.
다음 라운드는 새 신분으로 자리를 다시 잡고 4번 셋업 3단계(분배)부터 반복한다.
5.3 예시(5인)
대달무티 A가 7 두 장을 낸다. B는 5 두 장, C는 패스, D는 2 + 광대(2 두 장), E는 패스, A는 패스(1은 1장뿐이고 광대가 없음), B는 패스, C는 패스.
D를 뺀 모두가 연속으로 패스했으므로 트릭이 끝나고 D가 새 트릭을 시작한다.
6. 승패와 점수 계산
원작에는 정해진 승리 조건이 없다(합의할 때까지 계속). 이 사이트에서는 rounds만큼 하고 끝낸다.
rank-points(기본): 각 라운드에서 순위 r(1~N)인 사람이 N - r점을 받는다(1위 N-1점, 꼴찌 0점).
예(5인): 1위 4, 2위 3, 3위 2, 4위 1, 5위 0점.
최종 순위는 총점이 높은 순이고, 같으면 마지막 라운드 순위가 높은 사람이 앞선다.
last-round: 마지막 라운드 순위가 최종 순위다.
점수는 방 안 결과 표시용이다. 칩이나 돈이 아니다.
7. 지역 룰 / 하우스 룰 (옵션으로 켜고 끄기)
혁명 끄기(revolution).
세금에 광대 포함(jesterTaxable). 일부 모임은 광대도 좋은 카드로 내야 한다고 한다.
한 번 패스하면 트릭에서 빠짐(passLocksOut). 대부호/대통령 계열에서 흔한 규칙이다.
9~12 빼기(removeHighCards). 인원이 적어 손패가 많을 때 쓴다.
지원하지 않는 변형(문서화만): 혁명 시 숫자 강약 반전(대부호식 "혁명"), 8 끊기, 같은 숫자 연속 금지(시바리), 낙오(도시락) 규칙.
8. 엔진 설계
8.1 상태(State)
interfaceDCard{id: string;n: number}// 1..12, 광대는 13
typePlay={cardIds: string[];count: number;rank: number};// rank: 광대 섞이면 숫자 카드의 숫자, 광대만이면 13
interfaceDalmutiState{options: DalmutiOptions;rng: RngState;players: PlayerId[];// 참가자(불변)
order: PlayerId[];// 이번 라운드 신분 순서 = 턴 순서. [0]=대달무티
round: number;// 1부터
hands: Record<PlayerId,DCard[]>;// 비공개
phase:|{kind:'firstRankDraw';draws: Record<PlayerId,number[]>}// 연출용, 즉시 다음 단계
|{kind:'revolutionCheck';confirmed: Record<PlayerId,boolean>}|{kind:'taxReturn';owed: Record<PlayerId,{to:PlayerId;count:number;done:boolean}>}|{kind:'playing'}|{kind:'roundOver'}|{kind:'finished'};revolution:'none'|'revolution'|'great';taxLog:{from:PlayerId;to: PlayerId;cardIds: string[]}[];// 당사자만 열람
trick:{leader: PlayerId;// 이 트릭을 시작한 사람
top:(Play&{by: PlayerId})|null;// 바닥 맨 위 묶음
passesSinceTop: PlayerId[];// top 이후 패스한 사람
lockedOut: PlayerId[];// passLocksOut용
pile: Play[];// 이 트릭에 나온 묶음(공개)
};current: PlayerId;finishOrder: PlayerId[];// 이번 라운드 나간 순서
roundResults:{order: PlayerId[];revolution: string}[];totals: Record<PlayerId,number>;turnStartedAt: number;seq: number;}
8.2 액션
type
payload
누가 / 언제
검증 조건
confirmHand
{ declareRevolution?: boolean }
모든 플레이어, phase=revolutionCheck
한 번만. declareRevolution=true는 광대 2장을 모두 가진 사람만(아니면 "광대 2장이 있어야 혁명할 수 있어요")
returnTax
{ cardIds: string[] }
대달무티(2장), 소달무티(1장), phase=taxReturn
자기 손에 있는 카드이고 장수가 정확함
play
{ cardIds: string[] }
current, phase=playing
카드가 자기 손에 있음. 숫자 카드(광대 제외)는 모두 같은 숫자. 리드면 1장 이상. 따라 내기면 장수 = top.count이고 rank < top.rank. passLocksOut on이면 lockedOut이 아님
pass
{}
current, phase=playing
리드가 아닐 때만(리드는 반드시 내야 함)
revolutionCheck는 모두가 확인하면 끝난다.
선언자가 있으면 혁명 또는 대혁명을 적용하고 playing으로 간다.
없으면 세금을 자동으로 옮기고 taxReturn으로 간다. 두 사람이 모두 돌려주면 playing.
play 처리: 묶음의 rank를 정하고 top을 바꾼 뒤 passesSinceTop = []. 손패가 0이 되면 finishOrder에 넣는다. 남은 사람이 1명이면 roundOver.
다음 차례 계산: 턴 순서에서 다음 사람 중 카드가 있는(그리고 lockedOut이 아닌) 사람.
트릭 종료 판정: (카드가 남은 사람 중 top.by가 아닌 모두)가 passesSinceTop에 있으면 종료한다. top.by가 이미 나간 경우에는 카드가 남은 모두가 패스하면 종료한다.
roundOver 처리: 점수를 반영한다. 라운드가 남았으면 order = finishOrder + [남은 1명]으로 새 라운드 분배를 하고 revolutionCheck로 간다. 다 했으면 finished.
reason 예: "앞사람과 같은 장수(3장)로 내야 해요", "더 낮은 숫자만 낼 수 있어요", "같은 숫자끼리만 낼 수 있어요", "새로 시작할 때는 패스할 수 없어요".
8.3 공개/비공개 정보 (view)
모두(관전자 포함)
신분 순서, 각자 손패 장수, 현재 트릭의 모든 묶음(누가 무엇을 냈는지), 현재 차례, 패스 표시, 나간 순서.
라운드와 총점, 혁명 여부. 혁명이 선언되면 선언자와 "광대 2장"이 공개된다.
본인만: 자기 손패.
세금: 주고받은 카드 내용은 준 사람과 받은 사람에게만 보인다. 다른 사람과 관전자는 "대농노 → 대달무티 2장" 같은 장수만 받는다.
revolutionCheck: 각자에게 canDeclareRevolution이 본인 view에만 있다. 다른 사람은 확인 완료 여부만 본다.
절대 보내지 않는 것: 남의 손패, 덱 섞인 순서, RNG 상태.
8.4 랜덤 요소 (시드 RNG 사용 지점)
첫 라운드 신분 뽑기(동점 재뽑기 포함).
매 라운드 덱 섞기.
그 외 없음(세금 자동 선택은 숫자 → 카드 ID 순으로 결정적).
8.5 타이머·시간 초과·연결 끊김 시 자동 행동
마감: revolutionCheck 20초, taxReturn 30초, 플레이 turnSeconds.
onTimeout
revolutionCheck: confirmHand { declareRevolution: false }. 자동으로 혁명을 선언하지 않는다.
taxReturn: 숫자가 가장 큰(가장 나쁜) 숫자 카드부터 필요한 장수만큼 돌려준다(광대 제외).
playing 리드: 광대를 빼고 가장 큰 숫자 카드를 그 숫자 전부 낸다. 광대만 남았으면 광대를 모두 낸다.
playing 따라 내기: pass.
연결이 끊겨도 탈락시키지 않는다. 위 자동 행동으로 라운드가 끝까지 진행된다. 연속 3턴 타임아웃이면 서버가 마감을 5초로 줄인다.
8.6 종료 조건과 결과(GameResult)
round == rounds의 라운드가 끝나면 종료한다.
interfaceGameResult{ranking:{player: PlayerId;rank: number;total: number;roundRanks: number[]}[];winner: PlayerId[];summary: string;// "3라운드 동안 지수 님이 가장 높은 신분을 지켰어요!"
}
9. UI/UX
모바일 세로 화면
위: 신분 순서대로 상대를 원형으로 배치한다. 각자 왕관/모자 아이콘(신분), 손패 장수, 패스 말풍선을 표시한다.
가운데: 현재 트릭 바닥 묶음(마지막 묶음을 크게, 이전 묶음은 겹쳐서 작게). "지금 기준: 5 × 2장"을 큰 글자로 보여 준다.
아래: 내 손패를 숫자별로 묶어서 보여 준다(같은 숫자 겹치기 + 장수 배지). 탭 영역은 48px 이상이다.
조작
숫자 묶음을 탭하면 필요한 장수만큼 자동으로 선택된다(따라 내기일 때 기준 장수만큼). +/-로 장수를 조절한다. 광대는 "광대 섞기" 토글로 추가한다.
"내기"와 "패스" 큰 버튼을 둔다.
낼 수 있는 숫자 묶음만 밝게 표시하고, 나머지는 흐리게 한다. 광대를 섞어야만 낼 수 있는 묶음은 "광대 필요" 표시를 붙인다.
세금 화면: 받은 카드를 강조하고 "돌려줄 카드 2장을 고르세요"를 안내한다. 기본 추천은 가장 큰 숫자 카드다.
혁명 확인 화면: 모두에게 "손패 확인" 버튼이 있고, 광대 2장 보유자에게만 "혁명!" 버튼이 추가로 보인다.
애니메이션: 신분 바뀔 때 자리 이동, 대혁명 때 자리가 뒤집히는 연출, 세금 카드 이동.
초보 도움말: "숫자가 낮을수록 강해요", "앞사람과 같은 장수로만 낼 수 있어요"를 상단 고정 팁으로 둔다(끌 수 있음). "규칙 보기"에 카드 장수 표와 신분 그림을 넣는다.
10. 테스트 체크리스트
덱: 80장(숫자 n이 n장, 광대 2장). 6인 분배가 14, 14, 13, 13, 13, 13이고, 앞 신분이 더 받는다.
첫 신분 뽑기: 같은 시드면 같은 결과다. 동점자 재뽑기 후 순서가 확정된다.
세금: 대농노 손패 [광대, 광대, 3, 3, 7…]이고 jesterTaxable=off이면 3, 3이 대달무티에게 간다. on이면 광대 2장이 간다.
세금 돌려주기: 대달무티가 방금 받은 카드를 돌려줄 수 있다. 장수가 틀리면 거부된다.
혁명: 평민이 광대 2장으로 선언하면 세금 없이 신분 그대로 시작한다. 대농노가 선언하면 순서가 완전히 뒤집히고 새 대달무티가 첫 트릭을 시작한다.
혁명 정보 유출: 광대 2장 보유자가 있든 없든 revolutionCheck 단계가 똑같이 생긴다. 다른 사람 view에 canDeclareRevolution이 없다.
따라 내기: 9×3 위에 8×2는 거부(장수 다름), 9×3은 거부(같은 숫자), 4 + 4 + 광대는 허용, 광대×2 + 1은 허용(1×3).
광대 단독: 바닥 12×1 위에 광대 1장은 거부된다(13은 12보다 나쁨). 리드로 광대 1장은 허용(13×1)되고, 그 위에 아무 숫자 1장이 허용된다.
트릭 종료: 마지막으로 낸 사람을 뺀 전원이 패스하면 그 사람이 리드한다. 마지막 묶음으로 손패를 턴 경우 다음 사람이 리드한다.
passLocksOut=off: 패스한 사람이 차례가 다시 오면 낼 수 있다. on이면 차례가 건너뛰어진다.
라운드 종료: 1명만 남으면 끝나고 그 사람이 대농노가 된다. 다음 라운드 순서 = 나간 순서.
점수: 5인 3라운드에서 순위 점수 합과 동점 처리(마지막 라운드 순위)가 맞다.
시간 초과: 리드 시간 초과 때 가장 큰 숫자 묶음을 전부 낸다. 따라 내기 시간 초과는 패스다. 세금 돌려주기 시간 초과는 가장 큰 숫자 카드다.
정보 유출: 관전자와 다른 플레이어 view에 남의 손패와 세금 카드 내용이 없다(장수만 있음).
차례가 아닌 play, 손에 없는 카드, 중복 패킷은 거부되고 상태가 바뀌지 않는다.
11. 참고 자료
나무위키 "달무티": https://namu.wiki/w/달무티 (80장 구성, 계급 이름, 신분 뽑기, 세금, 혁명·대혁명, 광대 13/와일드, 1+광대 허용, 9~12 빼기)