1
0
Fork 0

Fixed several AI related problems

This commit is contained in:
Michaël Lemaire 2018-03-02 00:14:09 +01:00
parent ea8771fc75
commit 851c59bac1
9 changed files with 49 additions and 27 deletions

View file

@ -69,7 +69,6 @@ Ships models and actions
Artificial Intelligence
-----------------------
* Fix tendency to use moves for nothing
* Produce interesting "angle" areas
* Evaluate active effects
* Account for luck

View file

@ -27,7 +27,7 @@ module TK.SpaceTac {
* Process AI in a webworker if possible, else do the work in the render thread
*/
async processAuto(feedback: AIFeedback): Promise<void> {
if ((<any>window).Worker) {
if (!this.debug && (<any>window).Worker) {
await this.processInWorker(feedback);
} else {
await this.processHere(feedback);

View file

@ -41,6 +41,13 @@ module TK.SpaceTac {
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
*/
@ -87,7 +94,9 @@ module TK.SpaceTac {
for (let i = 0; i < parts.length; i++) {
let part = parts[i];
if (part.action instanceof EndTurnAction || part.possible) {
return battle.applyOneAction(part.action.id, part.target);
if (!battle.applyOneAction(part.action.id, part.target)) {
return false;
}
} else {
return false;
}

View file

@ -40,7 +40,7 @@ module TK.SpaceTac {
[maneuver, producer] = producer();
}
if (maneuver) {
if (maneuver && maneuver.isPossible()) {
if (producer) {
this.producers.push(producer);
}
@ -113,12 +113,12 @@ module TK.SpaceTac {
let evaluators: EvaluatorHelper[] = [
scaled(TacticalAIHelpers.evaluateTurnCost, 1),
scaled(TacticalAIHelpers.evaluateOverheat, 10),
scaled(TacticalAIHelpers.evaluateEnemyHealth, 500),
scaled(TacticalAIHelpers.evaluateAllyHealth, 800),
scaled(TacticalAIHelpers.evaluateClustering, 3),
scaled(TacticalAIHelpers.evaluatePosition, 1),
scaled(TacticalAIHelpers.evaluateIdling, 1),
scaled(TacticalAIHelpers.evaluateOverheat, 3),
scaled(TacticalAIHelpers.evaluateEnemyHealth, 5),
scaled(TacticalAIHelpers.evaluateAllyHealth, 20),
scaled(TacticalAIHelpers.evaluateClustering, 4),
scaled(TacticalAIHelpers.evaluatePosition, 0.5),
scaled(TacticalAIHelpers.evaluateIdling, 2),
]
let battle = nn(this.ship.getBattle());

View file

@ -120,20 +120,31 @@ module TK.SpaceTac.Specs {
TestTools.setShipModel(ship, 100, 0, 10);
let engine = TestTools.addEngine(ship, 50);
let weapon = TestTools.addWeapon(ship, 10, 2, 100, 10);
let toggle = ship.actions.addCustom(new ToggleAction("test"));
let maneuver = new Maneuver(ship, weapon, Target.newFromLocation(0, 0));
check.equals(TacticalAIHelpers.evaluateIdling(ship, battle, maneuver), 0.5);
check.equals(TacticalAIHelpers.evaluateIdling(ship, battle, maneuver), 0.5, "fire");
maneuver = new Maneuver(ship, engine, Target.newFromLocation(0, 0));
check.equals(TacticalAIHelpers.evaluateIdling(ship, battle, maneuver), 0);
maneuver = new Maneuver(ship, toggle, Target.newFromShip(ship));
check.equals(TacticalAIHelpers.evaluateIdling(ship, battle, maneuver), 0.5, "toggle on");
ship.actions.toggle(toggle, true);
maneuver = new Maneuver(ship, toggle, Target.newFromShip(ship));
check.equals(TacticalAIHelpers.evaluateIdling(ship, battle, maneuver), -0.2, "toggle off");
maneuver = new Maneuver(ship, engine, Target.newFromLocation(0, 48));
check.equals(TacticalAIHelpers.evaluateIdling(ship, battle, maneuver), -0.9, "move only, at full power");
maneuver = new Maneuver(ship, EndTurnAction.SINGLETON, Target.newFromShip(ship));
check.equals(TacticalAIHelpers.evaluateIdling(ship, battle, maneuver), -1);
check.equals(TacticalAIHelpers.evaluateIdling(ship, battle, maneuver), -1, "end turn, at full power");
ship.setValue("power", 2);
maneuver = new Maneuver(ship, engine, Target.newFromLocation(0, 48));
check.equals(TacticalAIHelpers.evaluateIdling(ship, battle, maneuver), -0.1, "move only, at reduced power");
maneuver = new Maneuver(ship, EndTurnAction.SINGLETON, Target.newFromShip(ship));
check.equals(TacticalAIHelpers.evaluateIdling(ship, battle, maneuver), -0.2);
check.equals(TacticalAIHelpers.evaluateIdling(ship, battle, maneuver), -0.2, "end turn, at reduced power");
});
test.case("evaluates damage to enemies", check => {

View file

@ -59,7 +59,7 @@ module TK.SpaceTac {
* Produce a turn end.
*/
static produceEndTurn(ship: Ship, battle: Battle): TacticalProducer {
return isingle(new Maneuver(ship, new EndTurnAction(), Target.newFromShip(ship)));
return isingle(new Maneuver(ship, EndTurnAction.SINGLETON, Target.newFromShip(ship)));
}
/**
@ -142,16 +142,16 @@ module TK.SpaceTac {
* Evaluate doing nothing, between -1 and 1
*/
static evaluateIdling(ship: Ship, battle: Battle, maneuver: Maneuver): number {
let power_capacity = ship.getAttribute("power_capacity") || 1;
if (maneuver.action instanceof EndTurnAction) {
return -ship.getValue("power") / ship.getAttribute("power_capacity");
} else if (maneuver.action instanceof TriggerAction || maneuver.action instanceof ToggleAction) {
// TODO Evaluate if drone is useful
// TODO Check there are "interesting" effects
if (maneuver.effects.length == 0) {
return -1;
} else {
return 0.5;
}
return -ship.getValue("power") / power_capacity;
} else if (maneuver.action instanceof TriggerAction) {
return 0.5;
} else if (maneuver.action instanceof ToggleAction) {
return ship.actions.isToggled(maneuver.action) ? -0.2 : 0.5;
} else if (maneuver.action instanceof MoveAction) {
return -(ship.getValue("power") - maneuver.getPowerUsage()) / power_capacity;
} else {
return 0;
}

View file

@ -33,7 +33,7 @@ module TK.SpaceTac {
let missile = new TriggerAction("Defense Missiles", {
effects: [new DamageEffect(25, 30)],
power: 3,
range: 200, blast: 200,
range: 200, blast: 180,
}, "submunitionmissile");
return [

View file

@ -29,6 +29,9 @@ module TK.SpaceTac.UI {
dialogs_layer!: Phaser.Group
dialogs_opened: UIDialog[] = []
// Verbose debug output
readonly debug = false
// Get the size of display
getWidth(): number {
return this.game.width || 1280;

View file

@ -174,7 +174,7 @@ module TK.SpaceTac.UI {
return;
}
if (this.actual_battle.playAI()) {
if (this.actual_battle.playAI(this.debug)) {
if (this.interacting) {
this.action_bar.setShip(new Ship());
}