1
0
Fork 0
spacetac/src/core/ai/Maneuver.ts

108 lines
3.6 KiB
TypeScript
Raw Normal View History

module TS.SpaceTac {
/**
* Ship maneuver for an artifical intelligence
*
* A maneuver is like a human player action, choosing an action and using it
*/
2015-03-12 00:00:00 +00:00
export class Maneuver {
// Concerned ship
2017-05-18 21:10:16 +00:00
ship: Ship
// Reference to battle
battle: Battle
// Action to use
2017-05-18 21:10:16 +00:00
action: BaseAction
2017-05-18 21:10:16 +00:00
// Target for the action
target: Target
// Result of move-fire simulation
2017-05-18 21:10:16 +00:00
simulation: MoveFireResult
// List of guessed effects of this maneuver
effects: [Ship, BaseEffect][]
constructor(ship: Ship, action: BaseAction, target: Target, move_margin = 0.1) {
this.ship = ship;
2017-05-18 21:10:16 +00:00
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);
2017-05-18 21:10:16 +00:00
this.effects = this.guessEffects();
}
jasmineToString() {
return `Use ${this.action.code} on ${this.target.jasmineToString()}`;
}
2017-05-18 23:19:05 +00:00
/**
* 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);
}
/**
* Apply the maneuver in current battle
*/
apply(): void {
if (this.simulation.success) {
2017-03-07 22:16:47 +00:00
this.simulation.parts.filter(part => part.possible).forEach(part => {
if (!part.action.apply(this.ship, part.target)) {
console.error("AI cannot apply maneuver", this, part);
}
});
}
}
/**
* 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;
}
2017-05-18 21:10:16 +00:00
/**
* Guess what will be the effects applied on any ship by this maneuver
*/
guessEffects(): [Ship, BaseEffect][] {
let result: [Ship, BaseEffect][] = [];
// Effects of weapon
2017-05-18 21:10:16 +00:00
if (this.action instanceof FireWeaponAction) {
result = result.concat(this.action.getEffects(this.ship, this.target));
} else if (this.action instanceof DeployDroneAction) {
let ships = this.battle.collectShipsInCircle(this.target, this.action.effect_radius, true);
this.action.effects.forEach(effect => {
result = result.concat(ships.map(ship => <[Ship, BaseEffect]>[ship, effect]));
});
}
// Area effects on final location
let location = this.getFinalLocation();
let effects = this.battle.drones.forEach(drone => {
if (Target.newFromLocation(location.x, location.y).isInRange(drone.x, drone.y, drone.radius)) {
result = result.concat(drone.effects.map(effect => <[Ship, BaseEffect]>[this.ship, effect]));
}
});
2017-05-18 21:10:16 +00:00
return result;
}
}
}