module TK.SpaceTac { /** * Ship maneuver for an artifical intelligence * * A maneuver is like a human player action, choosing an action and using it */ export class Maneuver { // Concerned ship ship: Ship // Reference to battle battle: Battle // Action to use action: BaseAction // Target for the action target: Target // Result of move-fire simulation simulation: MoveFireResult // List of guessed effects of this maneuver effects: BaseBattleDiff[] constructor(ship: Ship, action: BaseAction, target: Target, move_margin = 1) { this.ship = ship; this.battle = nn(ship.getBattle()); this.action = action; this.target = target; let simulator = new MoveFireSimulator(this.ship); this.simulation = simulator.simulateAction(this.action, this.target, move_margin); this.effects = flatten(this.simulation.parts.map(part => part.action.getDiffs(this.ship, this.battle, part.target) )); } jasmineToString() { return `Use ${this.action.code} on ${this.target.jasmineToString()}`; } /** * Returns true if the maneuver has at least one part doable */ isPossible(): boolean { return any(this.simulation.parts, part => part.possible); } /** * Returns true if the maneuver cannot be fully done this turn */ isIncomplete(): boolean { return (this.simulation.need_move && !this.simulation.can_end_move) || (this.simulation.need_fire && !this.simulation.can_fire); } /** * Returns true if another maneuver could be done next on the same ship */ mayContinue(): boolean { return this.ship.playing && !this.isIncomplete() && !(this.action instanceof EndTurnAction); } /** * Get the location of the ship after the action */ getFinalLocation(): { x: number, y: number } { if (this.simulation.need_move) { return this.simulation.move_location; } else { return { x: this.ship.arena_x, y: this.ship.arena_y }; } } /** * Get the total power usage of this maneuver */ getPowerUsage(): number { return this.simulation.total_move_ap + this.simulation.total_fire_ap; } /** * Standard feedback for this maneuver. It will apply it on the battle state. */ apply(battle: Battle): boolean { if (!this.ship.is(battle.playing_ship)) { console.error("Maneuver was not produced for the playing ship", this, battle); return false; } else if (!this.simulation.success) { return false; } else { let parts = this.simulation.parts; for (let i = 0; i < parts.length; i++) { let part = parts[i]; if (part.action instanceof EndTurnAction || part.possible) { if (!battle.applyOneAction(part.action.id, part.target)) { return false; } } else { return false; } } return this.mayContinue(); } } } }