namespace TK.SpaceTac { /** * The machinery to apply a turn plan, in order to resolve the current turn */ export class TurnResolution { play_order: Ship[] = [] constructor(readonly battle: Battle, readonly plan: TurnPlan, readonly random = new RandomGenerator()) { } /** * Perform the whole resolution */ resolve(): void { this.throwInitiative(); this.logStart(); this.performActions(ActionCategory.PASSIVE); this.performActions(ActionCategory.MOVE); this.performActions(ActionCategory.ACTIVE); this.logEnd(); } /** * Perform an initiative throw, to obtain an order in which the ships will play */ throwInitiative(): void { const with_thrown = this.battle.ships.list().map(ship => [ship, ship.throwInitiative(this.random)] as [Ship, number]); const sorted_by_thrown = sortedBy(with_thrown, ([_, thrown]) => thrown); this.play_order = sorted_by_thrown.reverse().map(([ship, _]) => ship); } /** * Log a turn start diff */ logStart(): void { this.battle.applyDiffs([new TurnStartDiff(this.play_order)]); } /** * Perform all actions of a given category, for all ships in the initiative order */ performActions(category: ActionCategory): void { this.play_order.forEach(ship => this.performActionsForShip(ship, category)); } /** * Perform all actions of a given category, for one given ship */ performActionsForShip(ship: Ship, category: ActionCategory): void { this.plan.fleets.forEach(fleetplan => { fleetplan.ships.forEach(shipplan => { if (ship.is(shipplan.ship)) { shipplan.actions.forEach(actionplan => { if (actionplan.category === category) { this.battle.applyOneAction(actionplan.action, actionplan.target); } }); } }); }); } /** * Log a turn end diff */ logEnd(): void { this.battle.applyDiffs([new TurnEndDiff()]); } } }