Files
joke-app/docs/games/cockroach-poker.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

12 KiB
Raw Permalink Blame History

바퀴벌레 포커 (cockroach-poker)

마일스톤: M7 · 인원: 최소 2 ~ 최대 6명 · 예상 시간: 약 15~20분 · 난이도: 쉬움

1. 개요

  • 해충 카드를 뒤집어 건네며 "이건 쥐야"라고 말하면, 받은 사람이 진실/거짓을 맞히거나 몰래 보고 다른 사람에게 떠넘기는 블러핑 게임. 같은 해충 4장을 앞에 모으는 사람이 진다(패배자 1명을 정하는 게임).
  • 한국에서는 보드게임 카페 입문용 파티 게임으로 인기가 높고, 규칙이 단순해 어린이·어른이 함께 하기 좋다.
  • 인원 근거: 원작(Drei Magier Spiele, 2004, 자크 젤리거) 박스 표기 2~6인. 2인은 원작의 별도 2인 규칙을 따른다.

2. 모드와 옵션

옵션 키 설명 선택지 기본값
loseCount 같은 종류가 몇 장 쌓이면 패배 3 / 4 / 5 3~6인 4, 2인 5(원작)
turnSeconds 카드 건네기/판단 제한 시간 15 / 30 / 60 30
showSeenBy 현재 카드를 이미 본 사람 표시 on 고정 on
claimHistory 이번 라운드의 주장 이력(누가 무엇이라 했는지) 표시 on / off on
quickChat 정해진 문구 버튼("정말이야!", "의심스러운데?") on / off on

3. 구성물

  • 카드 64장: 해충 8종 × 8장.
종류 키 표시 이름
cockroach 바퀴벌레
bat 박쥐
fly 파리
toad 두꺼비
rat 쥐
scorpion 전갈
spider 거미
stinkbug 노린재

어린이 대상 서비스이므로 그림은 귀여운 캐릭터풍 자체 제작 아트를 쓴다(원작 아트 사용 금지).

4. 준비(셋업)

  1. 64장을 RNG로 섞는다.
  2. 2인: 섞은 뒤 10장을 보지 않고 제거(공개하지 않음). 남은 54장을 27장씩.
  3. 3~6인: 전부 나눈다. 좌석 순(첫 플레이어부터)으로 1장씩 돌려 나누므로 앞 좌석이 1장 더 받을 수 있다.
인원 손패 장수
2 27, 27 (10장 제거)
3 22, 21, 21
4 16 × 4
5 13, 13, 13, 13, 12
6 11, 11, 11, 11, 10, 10
  1. 첫 플레이어는 RNG로 정하고, 좌석은 그 사람부터 시작하게 배치한다(첫 플레이어가 가장 많이 받음).
  2. 각자 앞의 "앞마당"(공개 카드 영역)은 비어 있다.

5. 진행 규칙

5.1 라운드 시작

  • 라운드 시작 플레이어(시작자)가 손패 1장을 골라 뒷면으로 다른 플레이어 1명에게 건네며 해충 종류 1개를 주장한다. 주장은 진실이어도 거짓이어도 된다.
  • 시작자의 손패가 0장이면 그 즉시 시작자가 진다(6장).

5.2 카드를 받은 사람의 선택

받은 사람(수신자)은 둘 중 하나를 고른다.

  1. 판정: "진실이다" 또는 "거짓이다"라고 말하고 카드를 공개한다.
    • 맞히면: 카드를 건넨 사람(직전 전달자)이 그 카드를 자기 앞마당에 공개해 놓는다.
    • 틀리면: 수신자가 자기 앞마당에 놓는다.
  2. 떠넘기기: 카드를 몰래 확인한 뒤, 이 카드를 아직 보지 않은 다른 플레이어에게 건네며 다시 주장한다(같은 주장이든 다른 주장이든 자유).
    • "본 사람" = 원래 건넨 시작자 + 이 카드를 본 모든 수신자. 이 사람들에게는 건넬 수 없다.
    • 건넬 수 있는 사람이 없으면(나머지 전원이 이미 봄) 떠넘기기 불가, 반드시 판정.
    • 손패가 0장인 사람에게도 건넬 수 있다(손패와 무관).
  • 2인 규칙: 떠넘기기 없음. 항상 판정.

5.3 라운드 종료와 다음 시작자

  • 앞마당에 카드를 받은 사람이 다음 라운드 시작자.
  • 판정 대상은 언제나 가장 마지막 주장이다.

5.4 예시(4인 A·B·C·D)

  1. A가 실제 "거미"를 B에게 건네며 "파리"라고 주장.
  2. B가 몰래 보고(거미) C에게 "거미"라고 주장(진실). 본 사람 = {A, B}.
  3. C가 "거짓이다" 판정 → 공개하니 거미 → 주장은 진실이었으므로 C가 틀림 → C의 앞마당에 거미. C가 다음 시작자.
  4. 만약 C가 떠넘기기를 골랐다면 보고 나서 D에게만 건넬 수 있다. D는 떠넘길 사람이 없으므로 반드시 판정.

6. 승패와 점수 계산

  • 패배 조건(먼저 성립하는 즉시 종료):
    1. 어떤 플레이어의 앞마당에 같은 종류가 loseCount장(기본 4, 2인 5) 모였다.
    2. 라운드 시작자가 되어야 하는데 손패가 0장이다.
  • 패배자 1명, 나머지 전원 공동 승리.
  • 순위(방 기록용 보조 표시): 패배자 꼴찌. 나머지는 "앞마당 최다 동일 종류 장수"가 적은 순 → 앞마당 총 장수가 적은 순 → 그래도 같으면 공동 순위.
  • 점수: 승리자 각 1점, 패배자 0점.

7. 지역 룰 / 하우스 룰 (옵션으로 켜고 끄기)

옵션 내용 기본값
loseCount=3 짧은 게임(어린이 모드 추천) off
eightKindsRule 앞마당에 8종을 모두 1장 이상 모아도 패배(일부 하우스 룰) off
twoPlayerPass 2인에서도 수신자가 보고 되돌려 줄 수 있음(원작에 없음) off

8. 엔진 설계

8.1 상태(State)

type Kind = 'cockroach' | 'bat' | 'fly' | 'toad' | 'rat' | 'scorpion' | 'spider' | 'stinkbug';
interface Card { id: number; kind: Kind }   // id 0..63

interface CockroachState {
  options: CockroachOptions;
  rng: RngState;
  order: PlayerId[];                         // 좌석
  hands: Record<PlayerId, number[]>;
  fronts: Record<PlayerId, number[]>;        // 공개 앞마당
  removed: number[];                         // 2인 제거 10장(비공개)
  round: {
    starter: PlayerId;
    card: number | null;                     // 건네는 중인 카드
    holder: PlayerId | null;                 // 현재 수신자(판단할 사람). null이면 시작자가 고르는 중
    lastPasser: PlayerId | null;
    claim: Kind | null;                      // 마지막 주장
    seen: PlayerId[];                        // 이 카드를 본 사람
    claims: { from: PlayerId; to: PlayerId; claim: Kind }[];
    deadline: number;
  };
  loser: PlayerId | null;
  lossReason: 'four' | 'emptyHand' | null;
  lastReveal?: { card: number; claim: Kind; call: 'true' | 'false'; caller: PlayerId; correct: boolean; takenBy: PlayerId };
}

8.2 액션

type payload 누가 / 언제 검증 조건
offer { cardId; to; claim } 시작자, card == null 손패에 있음, to != 본인, claim이 8종 중 하나
call { call: 'true' | 'false' } 현재 holder, 아직 peek 안 함 —
peek {} 현재 holder, 아직 안 봄 2인이 아님(twoPlayerPass 제외), 떠넘길 대상(seen에 없고 본인 아닌 사람)이 1명 이상. 이후 holder는 seen에 추가되고 view로 카드 내용을 받으며 call 불가
pass { to; claim } peek 완료한 holder to가 seen에 없고 본인 아님, claim이 8종 중 하나

클라이언트는 서버가 카드 내용을 보내기 전에는 카드를 알 수 없으므로 "보기"와 "넘기기"를 두 액션으로 나눈다. 원작에서 "보고 나면 반드시 넘겨야 한다"는 규칙을 그대로 강제한다(peek 후 call 거부, 사유 "카드를 이미 봤으니 다른 사람에게 넘겨야 해요").

8.3 공개/비공개 정보 (view)

  • 모두: 좌석, 각자 손패 장수, 모든 앞마당, 시작자, 현재 holder, 현재 주장, 주장 이력, seen 목록, 공개된 판정 결과.
  • 본인: 자기 손패 내용. 건네는 중인 카드 내용은 seen에 있는 사람(시작자와 peek한 사람)에게만.
  • 비공개: 다른 사람 손패, 건네는 중인 카드(미확인자·관전자), 2인 제거 카드(진행 중 비공개, 게임 종료 후 전체 손패와 함께 공개).
  • 관전자: 공개 정보만.

8.4 랜덤 요소 (시드 RNG 사용 지점)

덱 셔플, 2인 제거 카드(셔플 결과의 앞 10장), 첫 시작자, 시간 초과 시 무작위 선택.

8.5 타이머·시간 초과·연결 끊김 시 자동 행동

  • activePlayers: card 없으면 시작자, 있으면 holder.
  • onTimeout:
    • 시작자 → RNG로 손패 1장, 다음 좌석 플레이어에게, 주장은 RNG 종류.
    • holder(미확인) → call 중 RNG(true/false).
    • holder(peek 완료) → seen에 없는 첫 좌석 플레이어에게 "실제 종류"로 pass.
  • 연결이 90초 이상 끊긴 플레이어는 차례가 오면 즉시 onTimeout 처리. 수신 대상으로는 계속 지정 가능(지정 시 바로 자동 판정).

8.6 종료 조건과 결과(GameResult)

interface CockroachResult {
  loser: PlayerId;
  reason: 'four' | 'emptyHand';
  losingKind?: Kind;
  ranking: PlayerId[][];       // 공동 순위 그룹, 마지막 그룹 = [loser]
  fronts: Record<PlayerId, Record<Kind, number>>;
  summary: string;             // 예: "민수님 앞에 쥐 4장! 민수님 패배, 나머지 모두 승리"
}

9. UI/UX

  • 모바일 세로: 상단 상대 플레이어 카드(아바타 + 손패 장수 + 앞마당 종류별 개수 배지, 3장째부터 노란색 경고, 위험 종류는 빨간색). 가운데 "건네지는 카드" 애니메이션과 말풍선 주장("이건 쥐야!"). 하단 내 손패(종류별 묶음 + 개수 배지, 탭으로 선택).
  • 건네기 흐름: 카드 선택 → 받을 사람 탭(건넬 수 없는 사람은 회색) → 8종 그림 버튼 중 주장 선택(그림 + 글자, 각 64px 이상) → 확인.
  • 판정 화면: 큰 버튼 두 개 "진짜!"(초록), "거짓말!"(빨강) + "몰래 보고 넘기기"(파랑, 넘길 사람이 없으면 비활성 + 이유).
  • 공개 애니메이션: 카드 뒤집기 후 "맞혔어요!/틀렸어요!"와 앞마당으로 날아가는 연출.
  • 초보자 도움말: "같은 벌레 4장 모이면 져요", 위험 경고 툴팁.

10. 테스트 체크리스트

  • 인원별 손패 장수가 4장 표와 일치, 2인은 10장 제거 후 27장씩, 카드 총합 보존.
  • 판정 정답(진실 주장에 "진실") → 전달자 앞마당, 오답 → 수신자 앞마당, 받은 사람이 다음 시작자.
  • 떠넘기기 시 seen에 있는 사람(시작자 포함)에게 pass 거부.
  • 나머지 전원이 본 상태의 holder는 peek 거부, call만 가능.
  • peek 후 call 거부.
  • 2인: peek 거부, 같은 종류 5장에서 패배(4장에서는 계속).
  • 같은 종류 4장 도달 즉시 종료(다른 종류 4장은 무관).
  • 다음 시작자의 손패가 0장 → 즉시 패배(reason emptyHand).
  • 손패 0장인 사람에게 카드 건네기 허용, 그가 떠넘기기/판정 정상 동작.
  • 시간 초과: 시작자 무응답 → 자동 offer, holder 무응답 → 자동 call, peek 후 무응답 → 자동 pass.
  • 비공개 누출 검사: 미확인 holder·관전자·다른 플레이어 view에 건네는 카드의 kind가 없는지, 다른 사람 손패 내용이 없는지, 2인 제거 카드가 진행 중에 없는지.
  • 같은 시드 + 액션 로그 재생 시 동일 결과.

11. 참고 자료

12. 메모 (상표·법적 주의 등)

  • "Cockroach Poker / Kakerlakenpoker / 바퀴벌레 포커"는 Drei Magier Spiele(현 Schmidt Spiele)의 제품명이다. 규칙은 보호 대상이 아니지만 이름과 아트는 사용하지 않는다. 표시 이름 후보: "벌레 떠넘기기", "거짓말 벌레", "벌레 블러핑".
  • 이름에 "포커"가 들어가지만 칩·베팅이 전혀 없는 게임이므로 도박 관련 이슈 없음. 다만 표시 이름에서 "포커"를 빼는 편이 어린이 서비스 인상에 좋다.
  • 벌레 그림을 싫어하는 이용자를 위해 "동물 테마" 스킨(종류 키는 동일, 그림만 교체) 검토.