89 lines
2.3 KiB
TypeScript
89 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;
|
|
};
|
|
|
|
export type TurnContext = {
|
|
chessman: Chessman;
|
|
board: PlaneCell[];
|
|
roll: number;
|
|
landIndex: number;
|
|
};
|
|
|
|
export type TurnResult = {
|
|
message: string;
|
|
/** 비행기 등: 즉시 이동할 칸 */
|
|
teleportTo?: number;
|
|
};
|
|
|
|
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';
|
|
|
|
constructor(private readonly targetIndex: number) {}
|
|
|
|
apply(ctx: TurnContext): TurnResult {
|
|
const target =
|
|
((this.targetIndex % ctx.board.length) + ctx.board.length) % ctx.board.length;
|
|
ctx.chessman.teleport(target);
|
|
const dest = ctx.board[target];
|
|
return {
|
|
message: `비행기! → ${dest?.type ?? target}`,
|
|
teleportTo: target,
|
|
};
|
|
}
|
|
}
|
|
|
|
export const CELL_EVENTS: Record<string, CellEvent> = {
|
|
island: new IslandEvent(),
|
|
reverse: new ReverseEvent(),
|
|
// 기본 도착지는 시작(0). 판 생성 시 덮어쓸 수 있다.
|
|
airplane: new AirplaneEvent(0),
|
|
};
|
|
|
|
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);
|
|
}
|