diff --git a/src/scripts/game/ai/AIManeuver.ts b/src/scripts/game/ai/AIManeuver.ts new file mode 100644 index 0000000..0b478eb --- /dev/null +++ b/src/scripts/game/ai/AIManeuver.ts @@ -0,0 +1,27 @@ +module SpaceTac.Game.AI { + "use strict"; + + // Ship maneuver for an artifical intelligence + // A maneuver is like a human player action, choosing an equipment and using it + export class AIManeuver { + // Concerned ship + ship: Ship; + + // Equipment to use + equipment: Equipment; + + // Target for the action; + target: Target; + + constructor(ship: Ship, equipment: Equipment, target: Target) { + this.ship = ship; + this.equipment = equipment; + this.target = target; + } + + // Apply the maneuver in current battle + apply(): void { + this.equipment.action.apply(this.ship.getBattle(), this.ship, this.target); + } + } +} diff --git a/src/scripts/game/ai/BullyAI.ts b/src/scripts/game/ai/BullyAI.ts index 1d034f4..5acc58a 100644 --- a/src/scripts/game/ai/BullyAI.ts +++ b/src/scripts/game/ai/BullyAI.ts @@ -2,23 +2,23 @@ module SpaceTac.Game.AI { "use strict"; - export class BullyMove { - // Position to move to, before firing - move_to: Target; + // Combination of a move action and a fire action + export class BullyManeuver { + // Move action to position the ship before firing + move: AIManeuver; - // Engine used to move - engine: Equipment; + // Fire action + fire: AIManeuver; - // Weapon to use - weapon: Equipment; - - // Ship to target - target: Ship; + constructor(move: AIManeuver = null, fire: AIManeuver = null) { + this.move = move; + this.fire = fire; + } // Get a sorting score, by distance to another point // Nearest means higher score getScoreByDistance(point: Target): number { - return -point.getDistanceTo(Target.newFromShip(this.target)); + return -point.getDistanceTo(this.fire.target); } } @@ -35,13 +35,13 @@ module SpaceTac.Game.AI { protected initWork(): void { this.addWorkItem(() => { - var moves = this.listAllMoves(); + var maneuvers = this.listAllManeuvers(); - if (moves.length > 0) { - var move = this.pickMove(moves); - this.applyMove(move); + if (maneuvers.length > 0) { + var maneuver = this.pickManeuver(maneuvers); + this.applyManeuver(maneuver); - // Try to make another move + // Try to make another maneuver this.initWork(); } }); @@ -65,18 +65,18 @@ module SpaceTac.Game.AI { return this.ship.listEquipment(SlotType.Weapon); } - // List all available "moves" for the playing ship - listAllMoves(): BullyMove[] { - var result: BullyMove[] = []; + // List all available maneuvers for the playing ship + listAllManeuvers(): BullyManeuver[] { + var result: BullyManeuver[] = []; var enemies = this.listAllEnemies(); var weapons = this.listAllWeapons(); enemies.forEach((ship: Ship) => { weapons.forEach((weapon: Equipment) => { - var move = this.checkBullyMove(ship, weapon); - if (move) { - result.push(move); + var maneuver = this.checkBullyManeuver(ship, weapon); + if (maneuver) { + result.push(maneuver); } }); }); @@ -85,8 +85,8 @@ module SpaceTac.Game.AI { } // Check if a weapon can be used against an enemy - // Returns the BullyMove, or null if impossible to fire - checkBullyMove(enemy: Ship, weapon: Equipment): BullyMove { + // Returns the BullyManeuver, or null if impossible to fire + checkBullyManeuver(enemy: Ship, weapon: Equipment): BullyManeuver { // Check if enemy in range var target = Target.newFromShip(enemy); var distance = target.getDistanceTo(Target.newFromShip(this.ship)); @@ -121,40 +121,40 @@ module SpaceTac.Game.AI { // Not enough AP to fire return null; } else { - var result = new BullyMove(); - result.move_to = move; - result.engine = engine; - result.target = enemy; - result.weapon = weapon; + var result = new BullyManeuver(); + if (move) { + result.move = new AIManeuver(this.ship, engine, move); + } + result.fire = new AIManeuver(this.ship, weapon, target); return result; } } - // Pick a move from a list of available ones + // Pick a maneuver from a list of available ones // By default, it chooses the nearest enemy - pickMove(available: BullyMove[]): BullyMove { + pickManeuver(available: BullyManeuver[]): BullyManeuver { if (available.length === 0) { return null; } // Sort by descending score - available.sort((m1: BullyMove, m2: BullyMove): number => { + available.sort((m1: BullyManeuver, m2: BullyManeuver): number => { var point = Target.newFromShip(this.ship); return m1.getScoreByDistance(point) < m2.getScoreByDistance(point) ? 1 : -1; }); return available[0]; } - // Effectively apply the chosen move - applyMove(move: BullyMove): void { - if (move.move_to) { + // Effectively apply the chosen maneuver + applyManeuver(maneuver: BullyManeuver): void { + if (maneuver.move) { this.addWorkItem(() => { - move.engine.action.apply(this.battle, this.ship, move.move_to); + maneuver.move.apply(); }, 500); } this.addWorkItem(() => { - move.weapon.action.apply(this.fleet.battle, this.ship, Target.newFromShip(move.target)); + maneuver.fire.apply(); }, 1500); this.addWorkItem(null, 1500); diff --git a/src/scripts/game/ai/specs/BullyAI.spec.ts b/src/scripts/game/ai/specs/BullyAI.spec.ts index ce5a4ed..081d856 100644 --- a/src/scripts/game/ai/specs/BullyAI.spec.ts +++ b/src/scripts/game/ai/specs/BullyAI.spec.ts @@ -63,10 +63,10 @@ module SpaceTac.Game.AI.Specs { ship.arena_y = 0; enemy.arena_x = 3; enemy.arena_y = 0; - var result = ai.checkBullyMove(enemy, weapon); - expect(result.move_to).toBeNull(); - expect(result.target).toBe(enemy); - expect(result.weapon).toBe(weapon); + var result = ai.checkBullyManeuver(enemy, weapon); + expect(result.move).toBeNull(); + expect(result.fire.target).toEqual(Target.newFromShip(enemy)); + expect(result.fire.equipment).toBe(weapon); // enemy out of range, but moving can bring it in range ship.ap_current.set(8); @@ -74,10 +74,10 @@ module SpaceTac.Game.AI.Specs { ship.arena_y = 0; enemy.arena_x = 6; enemy.arena_y = 0; - result = ai.checkBullyMove(enemy, weapon); - expect(result.move_to).toEqual(Target.newFromLocation(3, 0)); - expect(result.target).toBe(enemy); - expect(result.weapon).toBe(weapon); + result = ai.checkBullyManeuver(enemy, weapon); + expect(result.move.target).toEqual(Target.newFromLocation(3, 0)); + expect(result.fire.target).toEqual(Target.newFromShip(enemy)); + expect(result.fire.equipment).toBe(weapon); // enemy out of range, but moving can bring it in range, except for the safety margin ai.move_margin = 0.1; @@ -86,7 +86,7 @@ module SpaceTac.Game.AI.Specs { ship.arena_y = 0; enemy.arena_x = 6; enemy.arena_y = 0; - result = ai.checkBullyMove(enemy, weapon); + result = ai.checkBullyManeuver(enemy, weapon); expect(result).toBeNull(); ai.move_margin = 0; @@ -96,7 +96,7 @@ module SpaceTac.Game.AI.Specs { ship.arena_y = 0; enemy.arena_x = 30; enemy.arena_y = 0; - result = ai.checkBullyMove(enemy, weapon); + result = ai.checkBullyManeuver(enemy, weapon); expect(result).toBeNull(); // enemy in range but not enough AP to fire @@ -105,7 +105,7 @@ module SpaceTac.Game.AI.Specs { ship.arena_y = 0; enemy.arena_x = 3; enemy.arena_y = 0; - result = ai.checkBullyMove(enemy, weapon); + result = ai.checkBullyManeuver(enemy, weapon); expect(result).toBeNull(); // can move in range of enemy, but not enough AP to fire @@ -114,7 +114,7 @@ module SpaceTac.Game.AI.Specs { ship.arena_y = 0; enemy.arena_x = 6; enemy.arena_y = 0; - result = ai.checkBullyMove(enemy, weapon); + result = ai.checkBullyManeuver(enemy, weapon); expect(result).toBeNull(); // no engine, can't move @@ -124,7 +124,7 @@ module SpaceTac.Game.AI.Specs { ship.arena_y = 0; enemy.arena_x = 6; enemy.arena_y = 0; - result = ai.checkBullyMove(enemy, weapon); + result = ai.checkBullyManeuver(enemy, weapon); expect(result).toBeNull(); }); @@ -144,7 +144,7 @@ module SpaceTac.Game.AI.Specs { var ai = new BullyAI(ship1.fleet); ai.ship = ship1; - var result = ai.listAllMoves(); + var result = ai.listAllManeuvers(); expect(result.length).toBe(0); var weapon1 = new Equipment(SlotType.Weapon); @@ -159,7 +159,7 @@ module SpaceTac.Game.AI.Specs { ai.ship.ap_current.setMaximal(10); ai.ship.ap_current.set(8); - result = ai.listAllMoves(); + result = ai.listAllManeuvers(); expect(result.length).toBe(3); }); @@ -196,12 +196,12 @@ module SpaceTac.Game.AI.Specs { ship2.hull.set(15); ship2.shield.set(10); - var move = ai.checkBullyMove(ship2, weapon); + var move = ai.checkBullyManeuver(ship2, weapon); expect(move).not.toBeNull(); battle.playing_ship = ai.ship; battle.log.clear(); - ai.applyMove(move); + ai.applyManeuver(move); expect(battle.log.events.length).toBe(7);