M4: 숫자 타일 규칙·화면·테스트

- 규칙 모듈(packages/games/src/rummikub): 106타일, 선 정하기·분배, 그룹/런 판정과 조커 해석,
  서버 초안(setDraft/undoDraft/resetDraft) + 보존 검사(C1~C3), 확정 검증(받침대 1장 이상,
  첫 등록 점수, 재배치), 시간 초과(그대로면 1장, 올바르면 확정/되돌림, 틀리면 벌칙 장수),
  풀 소진 교착 종료, 점수 계산, 여러 판 매치, 나가기·자리 비움, 숨김 정보 view, secretsOf
- 테스트: 문서 10절 시나리오 전부 + 엔진 randomPlayout 25회 + 시드 1,000개 무작위 대국
  (타일 106장 보존, 매 단계 정보 유출·onTimeout 합법성 검사, 결정성)
- 화면(apps/web/src/games/rummikub): 탭으로 고르고 놓을 곳 누르기(◀ 앞 / ▶ 뒤 / 새 묶음),
  받침대 색깔순·숫자순 정렬, 되돌리기·처음으로, 실시간 묶음 검사(초록/빨강 + 이유),
  첫 등록 진행 막대, 도와줘 힌트, 한 장 가져오기·확정, 색+모양 표시 타일(조커 자체 디자인)
- 등록: GAMES, CATALOG, 화면 레지스트리, 아이콘(곧 나올 게임 목록에서 제거)
- E2E: PC 방장 + 휴대폰 친구가 화면으로 10차례(힌트로 내기, 되돌리기, 가져오기) 진행
- @bg/games 패키지에 './rummikub/rules' 내보내기 추가(화면 청크에 zod가 안 들어가게)

Co-Authored-By: Claude Opus 5.5 <noreply@anthropic.com>
This commit is contained in:
EJClaw
2026-10-05 04:34:59 +09:00
parent 5dd8e6ea07
commit 96e406b2c9
10 changed files with 2775 additions and 1 deletions

View File

@@ -18,6 +18,7 @@ export const CATALOG: CatalogEntry[] = [
{ id: 'baduk', nameKo: '바둑', minPlayers: 2, maxPlayers: 2, minutes: '15~60', level: '어려움', blurb: '집을 더 많이 지은 쪽이 승리', available: true },
{ id: 'seotda', nameKo: '섯다', minPlayers: 2, maxPlayers: 10, minutes: '20~40', level: '보통', blurb: '화투 두 장으로 겨루는 족보 승부 · 놀이용 칩', available: true },
{ id: 'poker', nameKo: '포커', minPlayers: 2, maxPlayers: 10, minutes: '20~60', level: '보통', blurb: '홀덤·7포커·인디언 등 7가지 모드 · 놀이용 칩', available: true },
{ id: 'rummikub', nameKo: '숫자 타일', minPlayers: 2, maxPlayers: 4, minutes: '30~60', level: '보통', blurb: '같은 숫자, 이어지는 숫자로 묶어 먼저 다 내려놓기!', available: true },
];
export const catalogById = (id: string): CatalogEntry | undefined => CATALOG.find((g) => g.id === id);