Weapons with blast can now target a ship indirectly
This commit is contained in:
parent
ed5d338522
commit
e64e3955b3
|
@ -97,7 +97,7 @@ module TS.SpaceTac {
|
|||
result.total_fire_ap = action.getActionPointsUsage(this.ship, target);
|
||||
result.can_fire = result.total_fire_ap <= ap;
|
||||
result.fire_location = target;
|
||||
result.parts.push({ action: action, target: target, ap: result.total_fire_ap, possible: result.can_fire });
|
||||
result.parts.push({ action: action, target: target, ap: result.total_fire_ap, possible: (!result.need_move || result.can_end_move) && result.can_fire });
|
||||
}
|
||||
} else {
|
||||
result.success = false;
|
||||
|
|
|
@ -106,19 +106,19 @@ module TS.SpaceTac {
|
|||
apply(ship: Ship, target: Target): boolean {
|
||||
let reject = this.checkCannotBeApplied(ship);
|
||||
if (reject == null) {
|
||||
target = this.checkTarget(ship, target);
|
||||
if (!target && this.needs_target) {
|
||||
console.warn("Action rejected - no target selected", ship, this, target);
|
||||
let checked_target = this.checkTarget(ship, target);
|
||||
if (!checked_target && this.needs_target) {
|
||||
console.warn("Action rejected - invalid target", ship, this, target);
|
||||
return false;
|
||||
}
|
||||
|
||||
let cost = this.getActionPointsUsage(ship, target);
|
||||
let cost = this.getActionPointsUsage(ship, checked_target);
|
||||
if (!ship.useActionPoints(cost)) {
|
||||
console.warn("Action rejected - not enough power", ship, this, target);
|
||||
console.warn("Action rejected - not enough power", ship, this, checked_target);
|
||||
return false;
|
||||
}
|
||||
|
||||
this.customApply(ship, target);
|
||||
this.customApply(ship, checked_target);
|
||||
return true;
|
||||
} else {
|
||||
console.warn(`Action rejected - ${reject}`, ship, this, target);
|
||||
|
|
|
@ -43,5 +43,29 @@ module TS.SpaceTac {
|
|||
expect(mock_apply).toHaveBeenCalledTimes(1);
|
||||
expect(mock_apply).toHaveBeenCalledWith(ship2);
|
||||
});
|
||||
|
||||
it("transforms ship target in location target, when the weapon has blast radius", function () {
|
||||
let ship1 = new Ship();
|
||||
ship1.setArenaPosition(50, 10);
|
||||
let ship2 = new Ship();
|
||||
ship2.setArenaPosition(150, 10);
|
||||
let weapon = TestTools.addWeapon(ship1, 1, 0, 100, 30);
|
||||
|
||||
let target = weapon.action.checkTarget(ship1, new Target(150, 10));
|
||||
expect(target).toEqual(new Target(150, 10));
|
||||
|
||||
target = weapon.action.checkTarget(ship1, Target.newFromShip(ship2));
|
||||
expect(target).toEqual(new Target(150, 10));
|
||||
|
||||
ship1.setArenaPosition(30, 10);
|
||||
|
||||
target = weapon.action.checkTarget(ship1, Target.newFromShip(ship2));
|
||||
expect(target).toEqual(new Target(130, 10));
|
||||
|
||||
ship1.setArenaPosition(0, 10);
|
||||
|
||||
target = weapon.action.checkTarget(ship1, Target.newFromShip(ship2));
|
||||
expect(target).toEqual(new Target(100, 10));
|
||||
});
|
||||
});
|
||||
}
|
||||
|
|
|
@ -27,7 +27,9 @@ module TS.SpaceTac {
|
|||
return null;
|
||||
} else {
|
||||
// Check if target is in range
|
||||
if (target.isInRange(ship.arena_x, ship.arena_y, this.equipment.distance)) {
|
||||
if (this.can_target_space) {
|
||||
return this.checkLocationTarget(ship, new Target(target.x, target.y));
|
||||
} else if (target.isInRange(ship.arena_x, ship.arena_y, this.equipment.distance)) {
|
||||
return target;
|
||||
} else {
|
||||
return null;
|
||||
|
|
|
@ -22,7 +22,7 @@ module TS.SpaceTac {
|
|||
remaining_ap = ship.values.power.get();
|
||||
}
|
||||
if (remaining_ap > 0.0001) {
|
||||
return null
|
||||
return null;
|
||||
} else {
|
||||
return "not enough power";
|
||||
}
|
||||
|
|
|
@ -72,9 +72,10 @@ module TS.SpaceTac {
|
|||
let battle = Battle.newQuickRandom();
|
||||
|
||||
while (!battle.ended && battle.turn < 100) {
|
||||
//console.debug(`Turn ${battle.turn} - Ship ${battle.play_order.indexOf(playing)}`);
|
||||
|
||||
let playing = battle.playing_ship;
|
||||
|
||||
// console.debug(`Turn ${battle.turn} - Ship ${battle.play_order.indexOf(playing)} - Player ${battle.fleets.indexOf(playing.fleet)}`);
|
||||
|
||||
let ai = (playing.fleet == battle.fleets[0]) ? this.ai1 : this.ai2;
|
||||
ai.timer = Timer.synchronous;
|
||||
ai.ship = playing;
|
||||
|
@ -118,6 +119,7 @@ module TS.SpaceTac {
|
|||
AIDuel.current = null;
|
||||
button.textContent = "Start !";
|
||||
} else {
|
||||
console.clear();
|
||||
let ai1 = parseInt(element.getElementsByTagName("select").item(0).value);
|
||||
let ai2 = parseInt(element.getElementsByTagName("select").item(1).value);
|
||||
AIDuel.current = new AIDuel(ais[ai1], ais[ai2]);
|
||||
|
|
|
@ -15,22 +15,24 @@ module TS.SpaceTac {
|
|||
move_margin = 0.1;
|
||||
|
||||
protected initWork(): void {
|
||||
this.addWorkItem(() => {
|
||||
var maneuvers = this.listAllManeuvers();
|
||||
var maneuver: BullyManeuver;
|
||||
if (this.ship.getValue("power") > 0) {
|
||||
this.addWorkItem(() => {
|
||||
var maneuvers = this.listAllManeuvers();
|
||||
var maneuver: BullyManeuver;
|
||||
|
||||
if (maneuvers.length > 0) {
|
||||
maneuver = this.pickManeuver(maneuvers);
|
||||
this.applyManeuver(maneuver);
|
||||
if (maneuvers.length > 0) {
|
||||
maneuver = this.pickManeuver(maneuvers);
|
||||
this.applyManeuver(maneuver);
|
||||
|
||||
// Try to make another maneuver
|
||||
this.initWork();
|
||||
} else {
|
||||
// No bullying available, going to fallback move
|
||||
maneuver = this.getFallbackManeuver();
|
||||
this.applyManeuver(maneuver);
|
||||
}
|
||||
});
|
||||
// Try to make another maneuver
|
||||
this.initWork();
|
||||
} else {
|
||||
// No bullying available, going to fallback move
|
||||
maneuver = this.getFallbackManeuver();
|
||||
this.applyManeuver(maneuver);
|
||||
}
|
||||
});
|
||||
}
|
||||
}
|
||||
|
||||
// List all enemy ships that can be a target
|
||||
|
@ -83,8 +85,8 @@ module TS.SpaceTac {
|
|||
// Check if a weapon can be used against an enemy
|
||||
// Returns the BullyManeuver, or null if impossible to fire
|
||||
checkBullyManeuver(enemy: Ship, weapon: Equipment): BullyManeuver | null {
|
||||
var target = weapon.blast ? Target.newFromLocation(enemy.arena_x, enemy.arena_y) : Target.newFromShip(enemy);
|
||||
let maneuver = new BullyManeuver(this.ship, weapon, target, this.move_margin);
|
||||
let maneuver = new BullyManeuver(this.ship, weapon, Target.newFromShip(enemy), this.move_margin);
|
||||
// TODO In case of blast weapon, check that this would be a hit !
|
||||
if (maneuver.simulation.can_fire) {
|
||||
return maneuver;
|
||||
} else {
|
||||
|
|
|
@ -17,7 +17,7 @@ module TS.SpaceTac {
|
|||
// Result of move-fire simulation
|
||||
simulation: MoveFireResult;
|
||||
|
||||
constructor(ship: Ship, equipment: Equipment, target: Target, move_margin = 0) {
|
||||
constructor(ship: Ship, equipment: Equipment, target: Target, move_margin = 0.1) {
|
||||
this.ship = ship;
|
||||
this.equipment = equipment;
|
||||
this.target = target;
|
||||
|
|
|
@ -1,15 +0,0 @@
|
|||
module TS.SpaceTac {
|
||||
// A chain of Maneuver to execute sequentially
|
||||
export class ManeuverSequence {
|
||||
// Concerned ship
|
||||
ship: Ship;
|
||||
|
||||
// Sequence of maneuvers
|
||||
maneuvers: Maneuver[];
|
||||
|
||||
constructor(ship: Ship, maneuvers: Maneuver[]) {
|
||||
this.ship = ship;
|
||||
this.maneuvers = maneuvers;
|
||||
}
|
||||
}
|
||||
}
|
|
@ -23,7 +23,7 @@ module TS.SpaceTac.Specs {
|
|||
|
||||
it("applies the highest evaluated maneuver", function () {
|
||||
let ai = new TacticalAI(new Ship(), Timer.synchronous);
|
||||
ai.evaluators.push(maneuver => maneuver.score);
|
||||
ai.evaluators.push(maneuver => (<FixedManeuver>maneuver).score);
|
||||
ai.producers.push(producer(1, -8, 4));
|
||||
ai.producers.push(producer(3, 7, 0, 6, 1));
|
||||
|
||||
|
|
|
@ -3,7 +3,7 @@
|
|||
module TS.SpaceTac {
|
||||
|
||||
export type TacticalProducer = Iterator<Maneuver>;
|
||||
export type TacticalEvaluator = (Maneuver) => number;
|
||||
export type TacticalEvaluator = (maneuver: Maneuver) => number;
|
||||
|
||||
/**
|
||||
* AI that applies a set of tactical rules
|
||||
|
@ -16,10 +16,13 @@ module TS.SpaceTac {
|
|||
producers: TacticalProducer[] = []
|
||||
evaluators: TacticalEvaluator[] = []
|
||||
|
||||
best: Maneuver | null = null
|
||||
best_score = -Infinity
|
||||
best: Maneuver | null
|
||||
best_score: number
|
||||
|
||||
protected initWork(): void {
|
||||
this.best = null;
|
||||
this.best_score = -Infinity;
|
||||
|
||||
if (this.producers.length == 0) {
|
||||
this.setupDefaultProducers();
|
||||
}
|
||||
|
|
|
@ -125,8 +125,8 @@ module TS.SpaceTac.Specs {
|
|||
TestTools.setShipAP(ship, 10);
|
||||
let weapon = TestTools.addWeapon(ship, 100, 1, 100, 10);
|
||||
|
||||
let maneuver = new Maneuver(ship, weapon, Target.newFromLocation(200, 0));
|
||||
expect(maneuver.simulation.move_location).toEqual(Target.newFromLocation(100, 0));
|
||||
let maneuver = new Maneuver(ship, weapon, Target.newFromLocation(200, 0), 0.5);
|
||||
expect(maneuver.simulation.move_location).toEqual(Target.newFromLocation(100.5, 0));
|
||||
expect(TacticalAIHelpers.evaluateClustering(ship, battle, maneuver)).toEqual(0);
|
||||
|
||||
battle.fleets[1].addShip().setArenaPosition(battle.width, battle.height);
|
||||
|
|
|
@ -88,10 +88,11 @@ module TS.SpaceTac.Specs {
|
|||
|
||||
ship2.setArenaPosition(10, 15);
|
||||
expect(equipment.action.checkShipTarget(ship, Target.newFromShip(ship2))).toEqual(
|
||||
Target.newFromShip(ship2));
|
||||
Target.newFromLocation(10, 15));
|
||||
|
||||
ship2.setArenaPosition(10, 25);
|
||||
expect(equipment.action.checkShipTarget(ship, Target.newFromShip(ship2))).toBeNull();
|
||||
expect(equipment.action.checkShipTarget(ship, Target.newFromShip(ship2))).toEqual(
|
||||
Target.newFromLocation(10, 20));
|
||||
|
||||
// Forbid targetting in space
|
||||
weapon.setRange(10, 10, false);
|
||||
|
|
|
@ -39,7 +39,7 @@ module TS.SpaceTac.Specs {
|
|||
equipment.action.apply(ship, target);
|
||||
checkHP(50, 10, 50, 10, 50, 10);
|
||||
expect(battle.log.events.length).toBe(4);
|
||||
expect(battle.log.events[0]).toEqual(new FireEvent(ship, equipment, target));
|
||||
expect(battle.log.events[0]).toEqual(new FireEvent(ship, equipment, Target.newFromLocation(1, 0)));
|
||||
expect(battle.log.events[1]).toEqual(new DamageEvent(ship, 0, 20));
|
||||
expect(battle.log.events[2]).toEqual(new DamageEvent(enemy1, 0, 20));
|
||||
expect(battle.log.events[3]).toEqual(new DamageEvent(enemy2, 0, 20));
|
||||
|
|
Loading…
Reference in a new issue