구십구: 코리아보드게임즈 공식 규칙으로 맞춤
- 공식 상품 페이지 규칙 설명 이미지 기준: 5장씩, 시작 카드(2명 40·3명 20·4명 이상 0), 0 카드는 방향 유지/반대 선택, 칩(목숨)은 공식 규칙이 아니라 하우스 룰 - handSize 'auto'(전용 카드 5, 트럼프 3), startTotal 옵션, 카드 종류 'zero'와 dir 액션 - stateVersion 2, 진행 중인 v1 게임은 옛 규칙 그대로 이어서 하도록 migrate - 특수 카드 장수(±9·±10·0)는 공개 자료가 없어 각 4장 유지 Co-Authored-By: Claude Opus 5.5 <noreply@anthropic.com>
This commit is contained in:
@@ -1,12 +1,19 @@
|
||||
/** 구십구 [?] "지금 할 수 있는 것" (docs/07 §5). Pure: only reads the client view. */
|
||||
import type { NinetyNineView } from '@bg/games/ninety-nine';
|
||||
import type { NNOptions, NinetyNineView } from '@bg/games/ninety-nine';
|
||||
import type { PublicUser } from '@bg/shared/lite';
|
||||
|
||||
/** Same as the engine's: `auto` deals 5 with the dedicated cards, 3 with trump cards. */
|
||||
export const resolvedHandSize = (o: Pick<NNOptions, 'mode' | 'handSize'>): number => (o.handSize === 'auto' ? (o.mode === 'classic' ? 3 : 5) : o.handSize);
|
||||
/** Same as the engine's: the start card shows 40 for 2 players, 20 for 3, 0 for 4 or more. */
|
||||
export const resolvedStartTotal = (o: Pick<NNOptions, 'mode' | 'startTotal'>, players: number): number =>
|
||||
o.mode === 'kr-product' && o.startTotal === 'auto' ? (players <= 2 ? 40 : players === 3 ? 20 : 0) : 0;
|
||||
|
||||
const nm = (players: Record<string, PublicUser>, id: string | null | undefined) => `${(id && players[id]?.nickname) || '다른 사람'}님`;
|
||||
|
||||
/** What happens to someone who has no card to play (option dependent). */
|
||||
function loseText(v: NinetyNineView): string {
|
||||
return v.livesStart > 0 ? '목숨 1개를 잃고 합계 0부터 새 판을 해요' : '바로 탈락해요';
|
||||
if (v.livesStart === 0) return '바로 탈락해요';
|
||||
return `목숨 1개를 잃고 합계 ${resolvedStartTotal(v.options, v.seats.filter((s) => s.alive).length)}부터 새 판을 해요`;
|
||||
}
|
||||
|
||||
export function helpNow(v: NinetyNineView, me: string | null, players: Record<string, PublicUser>): string {
|
||||
@@ -44,6 +51,7 @@ export function helpNow(v: NinetyNineView, me: string | null, players: Record<st
|
||||
if (legal.some((c) => c.kind === 'ace')) lines.push('A는 누른 뒤 더할 값을 골라요.');
|
||||
if (legal.some((c) => c.kind === 'joker')) lines.push(`조커는 합계를 ${v.jokerRange.min}~${v.jokerRange.max} 중 원하는 수로 만들어요. 수를 고르고 [조커 내기]를 눌러요.`);
|
||||
const face = (k: string) => legal.find((c) => c.kind === k)?.face.label;
|
||||
if (face('zero')) lines.push(`${face('zero')} 카드는 합계를 그대로 둬요. 누른 뒤 [방향 그대로]와 [방향 바꾸기] 중 하나를 골라요.`);
|
||||
if (face('reverse')) lines.push(`${face('reverse')} 카드는 합계를 그대로 두고 진행 방향만 바꿔요.`);
|
||||
if (face('hold')) lines.push(`${face('hold')} 카드는 합계를 그대로 두고 다음 사람에게 넘겨요.`);
|
||||
if (face('to99')) lines.push(`${face('to99')} 카드는 합계를 바로 99로 만들어요.`);
|
||||
|
||||
Reference in New Issue
Block a user