1
0
Fork 0

AI: avoid damage to allies

This commit is contained in:
Michaël Lemaire 2017-05-18 01:17:07 +02:00
parent 84e56ffc7d
commit b9eaea41d0
4 changed files with 36 additions and 16 deletions

1
TODO
View file

@ -44,7 +44,6 @@
* AI: do not always move first, they are defenders
* AI: add combination of random small move and actual maneuver, as producer
* AI: evaluate drone area effects
* AI: avoid damaging allies
* AI: produce random blast shots
* AI: consider overheat/cooldown
* AI: new duel page with producers/evaluators tweaking

View file

@ -82,15 +82,23 @@ module TS.SpaceTac {
/**
* Return an iterator over all ships engaged in the battle
*/
iships(): Iterator<Ship> {
return ichainit(imap(iarray(this.fleets), fleet => iarray(fleet.ships)));
iships(alive_only = false): Iterator<Ship> {
let result = ichainit(imap(iarray(this.fleets), fleet => iarray(fleet.ships)));
return alive_only ? ifilter(result, ship => ship.alive) : result;
}
/**
* Return an iterator over ships allies of (or owned by) a player
*/
iallies(player: Player, alive_only = false): Iterator<Ship> {
return ifilter(this.iships(alive_only), ship => ship.getPlayer() === player);
}
/**
* Return an iterator over ships enemy of a player
*/
ienemies(player: Player, alive_only = false): Iterator<Ship> {
return ifilter(this.iships(), ship => ship.getPlayer() != player && (ship.alive || !alive_only));
return ifilter(this.iships(alive_only), ship => ship.getPlayer() !== player);
}
// Check if a player is able to play

View file

@ -104,6 +104,7 @@ module TS.SpaceTac {
let evaluators = [
scaled(TacticalAIHelpers.evaluateTurnCost, 3),
scaled(TacticalAIHelpers.evaluateDamageToEnemy, 20),
scaled(TacticalAIHelpers.evaluateDamageToAllies, 30),
scaled(TacticalAIHelpers.evaluateClustering, 8),
scaled(TacticalAIHelpers.evaluatePosition, 1),
scaled(TacticalAIHelpers.evaluateIdling, 5),

View file

@ -103,35 +103,47 @@ module TS.SpaceTac {
}
/**
* Evaluate the damage done to the enemy, between -1 and 1
* Evaluate the damage done to a set of ships, between -1 and 1
*/
static evaluateDamageToEnemy(ship: Ship, battle: Battle, maneuver: Maneuver): number {
static evaluateDamage(ship: Ship, battle: Battle, maneuver: Maneuver, others: Ship[]): number {
let action = maneuver.action;
if (action instanceof FireWeaponAction) {
let enemies = imaterialize(battle.ienemies(ship.getPlayer(), true));
if (enemies.length == 0) {
return 0;
}
let damage = 0;
let dead = 0;
let effects = action.getEffects(ship, maneuver.target);
effects.forEach(([ship, effect]) => {
if (effect instanceof DamageEffect && contains(enemies, ship)) {
let [shield, hull] = effect.getEffectiveDamage(ship);
effects.forEach(([other, effect]) => {
if (effect instanceof DamageEffect && contains(others, other)) {
let [shield, hull] = effect.getEffectiveDamage(other);
damage += shield + hull;
if (hull == ship.getValue("hull")) {
if (hull == other.getValue("hull")) {
dead += 1
}
}
});
let hp = sum(enemies.map(enemy => enemy.getValue("hull") + enemy.getValue("shield")));
let result = (damage ? 0.2 : 0) + 0.3 * (damage / hp) + (dead ? 0.2 : 0) + 0.3 * (dead / enemies.length);
let hp = sum(others.map(other => other.getValue("hull") + other.getValue("shield")));
let result = (damage ? 0.2 : 0) + 0.3 * (damage / hp) + (dead ? 0.2 : 0) + 0.3 * (dead / others.length);
return result;
} else {
return 0;
}
}
/**
* Evaluate the damage done to the enemy, between -1 and 1
*/
static evaluateDamageToEnemy(ship: Ship, battle: Battle, maneuver: Maneuver): number {
let enemies = imaterialize(battle.ienemies(ship.getPlayer(), true));
return TacticalAIHelpers.evaluateDamage(ship, battle, maneuver, enemies);
}
/**
* Evaluate the damage done to allied ships, between -1 and 1
*/
static evaluateDamageToAllies(ship: Ship, battle: Battle, maneuver: Maneuver): number {
let allies = imaterialize(battle.iallies(ship.getPlayer(), true));
return -TacticalAIHelpers.evaluateDamage(ship, battle, maneuver, allies);
}
/**
* Evaluate the clustering of ships, between -1 and 1
*/