Files
drinkmarble/app/game/cell-event.ts
kimyu 347dfc1f4a 게임·입장 UX와 물리/고지 개선을 반영한다.
비행기(세계여행) 칸 선택 이동, 주사위 무게감, 설정 패널·주사위 초기화,
개인정보 고지·파비콘·탭 제목을 정리하고 런타임 로그는 추적에서 제외한다.

Co-authored-by: Cursor <cursoragent@cursor.com>
2026-09-21 12:50:22 +09:00

88 lines
2.3 KiB
TypeScript

import type { Chessman } from './chessman';
export type PlaneCell = {
id: number;
x: number;
y: number;
/** UI에 보이는 이름 */
type: string;
/** 효과가 있을 때만 설정. 없으면 착지 시 아무 일도 없음 */
eventId?: string | null;
/** 칸 이미지 (없으면 텍스트만) */
imageSrc?: string | null;
/** false면 게임 판에서 이름(텍스트)만 숨김 */
contentVisible?: boolean;
};
export type TurnContext = {
chessman: Chessman;
board: PlaneCell[];
roll: number;
landIndex: number;
};
export type TurnResult = {
message: string;
/** 비행기 등: 즉시 이동할 칸 */
teleportTo?: number;
/** 비행기: 도착 칸을 플레이어가 직접 고름 */
chooseDestination?: boolean;
};
export interface CellEvent {
readonly id: string;
apply(ctx: TurnContext): TurnResult;
}
/** 무인도: 최대 3턴 대기, 주사위 6이면 즉시 탈출 가능 */
export class IslandEvent implements CellEvent {
readonly id = 'island';
apply(ctx: TurnContext): TurnResult {
ctx.chessman.enterIsland(3, 6);
return { message: '무인도! 3턴 대기 (6이면 탈출)' };
}
}
/** 역방향: 진행 방향을 반대로 */
export class ReverseEvent implements CellEvent {
readonly id = 'reverse';
apply(ctx: TurnContext): TurnResult {
const dir = ctx.chessman.reverseDirection();
return {
message: dir === 1 ? '역방향! 다시 시계방향' : '역방향! 반시계로 진행',
};
}
}
/** 비행기: 원하는 칸을 고른 뒤 그곳으로 이동 */
export class AirplaneEvent implements CellEvent {
readonly id = 'airplane';
apply(_ctx: TurnContext): TurnResult {
return {
message: '원하는 곳을 클릭해주세요',
chooseDestination: true,
};
}
}
export const CELL_EVENTS: Record<string, CellEvent> = {
island: new IslandEvent(),
reverse: new ReverseEvent(),
airplane: new AirplaneEvent(),
};
export function getCellEvent(eventId: string | null | undefined): CellEvent | null {
if (!eventId) return null;
return CELL_EVENTS[eventId] ?? null;
}
export function applyLandEvent(ctx: TurnContext): TurnResult | null {
const cell = ctx.board[ctx.landIndex];
const event = getCellEvent(cell?.eventId);
if (!event) return null;
return event.apply(ctx);
}