Ok, so I finally made a semi-functional AI. It won once. ;-)
Semi-nice things it does:
* Builds 4 harvesters at first. Will only switch to rebuilding harvesters if they drop to 2. Even so, that might be a bit high for the last tutorial scenario.
* Then builds 2 or 3 Hunters.
* Then builds up to 3 elites.
* The hunters will stay near the mothership until an Elite is in service.
* If an enemy comes in sight of the mothership, all the Hunters will move to attack it unless they are currently attacking something.
Things that would help to add:
* The mothership doesn’t seem to be able to do much else while it is building, so it probably shouldn’t start building until it has enough resources to fully build whatever it’s about to try to build. Yes it may slow down production, but at least it won’t get paralyzed in build mode.
* The mothership should detect when its harvesters are dead, and if so, go searching itself. Actually, the first point above should take care of that, since it’s default is to wander around (though it never does thanks to the build mandate).
* The fighting ships shouldn’t just wander randomly when on the attack. It’s not even a good search method, and there is strength in numbers. They should move in groups of at least 2, and plot longer courses over the map looking for targets, and/or call in others when they find an enemy.
* The harvesters also should at least not get stuck ramming into map edges or each other.
* The harvesters should run away from armed enemies, and let any bored hunters know when they see unarmed enemies.
// Mothership
var _droneController = {
onSpawn ()
{
Game.mothership.harvesterCount = 0;
Game.mothership.hunterCount = 0;
Game.mothership.eliteCount = 0;
Game.mothership.attackerX = null;
Game.mothership.attackerY = null;
},
// this function will be called on every timestep
onTick () {
// Scan for enemy drones:
this.attacking = false;
var drones = this.drone.dronesInSight;
var i = 0;
Game.mothership.attackerX = null;
Game.mothership.attackerY = null;
for( i; i < drones.length; i++ )
{
if (drones[i].isEnemy)
{
Game.mothership.attackerX = drones[i].position.x;
Game.mothership.attackerY = drones[i].position.y;
if( this.drone.isInMissileRange( drones[i] ) )
{
this.attacking = true;
this.drone.fireMissilesAt( drones[i] );
}
}
}
if (Math.random() < 0.01) {
// Random wandering:
var x = Math.random() * 1800 – 900;
var y = Math.random() * 1800 – 900;
this.drone.moveTo(x, y);
}
if (!this.attacking && !this.drone.isConstructing) {
if (Game.mothership.harvesterCount < 3)
{
this.drone.buildDrone(‘Harvester1’, {storageModules: 2});
}
else if (Game.mothership.hunterCount < 2)
{
this.drone.buildDrone(‘Hunter1’, {missileBatteries: 2});
}
else if (Game.mothership.eliteCount < 3)
{
this.drone.buildDrone(‘Elite1’, {missileBatteries: 2, shieldGenerators: 2});
}
}
},
};
// Harvester.js
var _droneController = {
onTick: function() {
if (!this.harvesting && Math.random() < 0.05) {
var direction = 2 * Math.PI * Math.random();
this.drone.moveInDirection(direction);
}
},
onMineralEntersVision: function(mineral) {
if (!this.harvesting) {
this.harvesting = true;
this.drone.moveTo(mineral);
}
},
onArrivesAtMineral: function(mineral) {
this.drone.harvest(mineral);
this.drone.moveTo(Game.mothership);
},
onArrivesAtDrone: function(drone) {
if (drone == Game.mothership)
{
this.drone.giveMineralsTo(drone);
this.harvesting = false;
}
},
onSpawn: function()
{
Game.mothership.harvesterCount = Game.mothership.harvesterCount +1;
// alert(“Now at ” + Game.mothership.harvesterCount + ” harvesters.”)
},
onDeath: function()
{
Game.mothership.harvesterCount—;
}
};
Hunter:
var _droneController = {
onTick: function() {
// Scan for enemy drones:
this.attacking = false;
var drones = this.drone.dronesInSight;
var i = 0;
for( i; i < drones.length; i++ )
{
if( this.drone.isInMissileRange( drones[i] ) && drones[i].isEnemy )
{
this.attacking = true;
this.drone.fireMissilesAt( drones[i] );
}
}
if (!this.attacking && Game.mothership.attackerX !== null)
{
// Defend the mothership!
this.drone.moveTo(Game.mothership.attackerX, Game.mothership.attackerY);
}
else if (!this.attacking && Math.random() < 0.05) {
// If we have no Elites, stay near mothership:
if (Game.mothership.eliteCount < 1)
{
var x = Game.mothership.position.x;
var y = Game.mothership.position.y;
if (Math.random() > 0.67)
{
x += 300;
y -= 300;
}
else if (Math.random() > 0.5)
{
x -= 400;
}
else
{
y += 400;
}
this.drone.moveTo(x, y);
}
else
{
var direction = 2 * Math.PI * Math.random();
this.drone.moveInDirection(direction);
}
}
},
onSpawn: function()
{
Game.mothership.hunterCount++;
},
onDeath: function()
{
Game.mothership.hunterCount—;
}
};
// Elite:
var _droneController = {
onTick: function() {
// Scan for enemy drones:
this.attacking = false;
var drones = this.drone.dronesInSight;
var i = 0;
for( i; i < drones.length; i++ )
{
if( this.drone.isInMissileRange( drones[i] ) && drones[i].isEnemy )
{
this.attacking = true;
this.drone.fireMissilesAt( drones[i] );
}
}
if (!this.attacking && Math.random() < 0.05) {
var direction = 2 * Math.PI * Math.random();
this.drone.moveInDirection(direction);
}
},
onSpawn: function()
{
Game.mothership.eliteCount++;
},
onDeath: function()
{
Game.mothership.eliteCount—;
}
};