import type { BattleServices } from '../combat/BattleServices'; import type { Cell } from '../battlefield/Cell'; import type { DeployResult, DeployRule } from './DeployTypes'; import { BattlePhase } from '../core/BattlePhase'; /** 仅允许 PREP 阶段部署(连续模式放宽) */ export class PrepPhaseOnlyRule implements DeployRule { check(services: BattleServices, _playerId: number, _unitDefId: string, cells: Cell[]): DeployResult { if (services.phase !== BattlePhase.PREP && !services.isContinuousFlow) { return { ok: false, reason: 'not_prep_phase' }; } return { ok: true, cells }; } } /** 格子必须在玩家部署区域内 */ export class InPlayerRegionRule implements DeployRule { check(services: BattleServices, playerId: number, _unitDefId: string, cells: Cell[]): DeployResult { const player = services.players[playerId]; if (!player) return { ok: false, reason: 'invalid_player' }; for (const c of cells) { if (!player.region.contains(c)) return { ok: false, reason: 'out_of_region' }; } return { ok: true, cells }; } } /** 格子必须未被 ECS 占用(合成格由 DeploySync 在部署前同步 buildable) */ export class CellEmptyRule implements DeployRule { check(services: BattleServices, _playerId: number, _unitDefId: string, cells: Cell[]): DeployResult { for (const c of cells) { const s = services.grid.getCell(c); if (!s) return { ok: false, reason: 'out_of_bounds' }; if (s.occupant != null) return { ok: false, reason: 'cell_occupied' }; } return { ok: true, cells }; } } /** 玩家金币必须足够 */ export class EnoughGoldRule implements DeployRule { check(services: BattleServices, playerId: number, unitDefId: string, _cells: Cell[]): DeployResult { const def = services.config.getUnit(unitDefId); const cost = def?.deploy?.cost ?? 0; const player = services.players[playerId]; if (!player || player.gold < cost) return { ok: false, reason: 'not_enough_gold' }; return { ok: true }; } } /** 占地形状必须在地图范围内 */ export class ShapeInBoundsRule implements DeployRule { check(services: BattleServices, _playerId: number, _unitDefId: string, cells: Cell[]): DeployResult { for (const c of cells) { if (!services.grid.inBounds(c)) return { ok: false, reason: 'out_of_bounds' }; } return { ok: true, cells }; } } /** @returns 默认部署规则链 */ export function createDefaultDeployRules(): DeployRule[] { return [ new PrepPhaseOnlyRule(), new ShapeInBoundsRule(), new InPlayerRegionRule(), new CellEmptyRule(), ]; } export type { DeployRule };