1
0
Fork 0

Weapons with blast can now target a ship indirectly

This commit is contained in:
Michaël Lemaire 2017-03-09 00:18:40 +01:00
parent ed5d338522
commit e64e3955b3
14 changed files with 71 additions and 52 deletions

View file

@ -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;

View file

@ -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);

View file

@ -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));
});
});
}

View file

@ -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;

View file

@ -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";
}

View file

@ -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]);

View file

@ -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 {

View file

@ -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;

View file

@ -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;
}
}
}

View file

@ -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));

View file

@ -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();
}

View file

@ -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);

View file

@ -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);

View file

@ -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));