A few bugfixes, slight change in logic for smoother play. Makes Aegis gather with cavalry. Allows it to send chat messages to warn about attacks.
This was SVN commit r13266.
This commit is contained in:
parent
ca40764dc6
commit
9b1b8cc8fd
@ -22,12 +22,23 @@ function handleNotifications()
|
||||
// Handle chat notifications specially
|
||||
if (notification.type == "chat")
|
||||
{
|
||||
addChatMessage({
|
||||
"type": "message",
|
||||
"guid": findGuidForPlayerID(g_PlayerAssignments, notification.player),
|
||||
"text": notification.message
|
||||
});
|
||||
}
|
||||
var guid = findGuidForPlayerID(g_PlayerAssignments, notification.player);
|
||||
if (guid == undefined)
|
||||
{
|
||||
addChatMessage({
|
||||
"type": "message",
|
||||
"guid": -1,
|
||||
"player": notification.player,
|
||||
"text": notification.message
|
||||
});
|
||||
} else {
|
||||
addChatMessage({
|
||||
"type": "message",
|
||||
"guid": findGuidForPlayerID(g_PlayerAssignments, notification.player),
|
||||
"text": notification.message
|
||||
});
|
||||
}
|
||||
}
|
||||
else if (notification.type == "defeat")
|
||||
{
|
||||
addChatMessage({
|
||||
@ -39,7 +50,7 @@ function handleNotifications()
|
||||
// If the diplomacy panel is open refresh it.
|
||||
if (isDiplomacyOpen)
|
||||
openDiplomacy();
|
||||
}
|
||||
}
|
||||
else if (notification.type == "diplomacy")
|
||||
{
|
||||
addChatMessage({
|
||||
@ -52,7 +63,7 @@ function handleNotifications()
|
||||
// If the diplomacy panel is open refresh it.
|
||||
if (isDiplomacyOpen)
|
||||
openDiplomacy();
|
||||
}
|
||||
}
|
||||
else if (notification.type == "quit")
|
||||
{
|
||||
// Used for AI testing
|
||||
@ -274,6 +285,12 @@ function addChatMessage(msg, playerAssignments)
|
||||
// This case is hit for AIs, whose names don't exist in playerAssignments.
|
||||
playerColor = g_Players[msg.player].color.r + " " + g_Players[msg.player].color.g + " " + g_Players[msg.player].color.b;
|
||||
username = escapeText(g_Players[msg.player].name);
|
||||
} else if (msg.type == "message")
|
||||
{
|
||||
// This case is hit for AIs, whose names don't exist in playerAssignments.
|
||||
playerColor = g_Players[msg.player].color.r + " " + g_Players[msg.player].color.g + " " + g_Players[msg.player].color.b;
|
||||
username = escapeText(g_Players[msg.player].name);
|
||||
parseChatCommands(msg, playerAssignments);
|
||||
}
|
||||
else
|
||||
{
|
||||
@ -380,7 +397,11 @@ function parseChatCommands(msg, playerAssignments)
|
||||
if (!msg.text || msg.text[0] != '/')
|
||||
return;
|
||||
|
||||
var sender = playerAssignments[msg.guid].player;
|
||||
var sender;
|
||||
if (playerAssignments[msg.guid])
|
||||
sender = playerAssignments[msg.guid].player;
|
||||
else
|
||||
sender = msg.player;
|
||||
var recurse = false;
|
||||
var split = msg.text.split(/\s/);
|
||||
|
||||
|
@ -227,6 +227,14 @@ BaseAI.prototype.chat = function(message)
|
||||
{
|
||||
Engine.PostCommand({"type": "chat", "message": message});
|
||||
};
|
||||
BaseAI.prototype.chatTeam = function(message)
|
||||
{
|
||||
Engine.PostCommand({"type": "chat", "message": "/team " +message});
|
||||
};
|
||||
BaseAI.prototype.chatEnemies = function(message)
|
||||
{
|
||||
Engine.PostCommand({"type": "chat", "message": "/enemy " +message});
|
||||
};
|
||||
|
||||
BaseAI.prototype.registerUpdatingEntityCollection = function(entCollection)
|
||||
{
|
||||
|
@ -579,10 +579,10 @@ var Entity = Class({
|
||||
// Flees from a unit in the opposite direction.
|
||||
flee: function(unitToFleeFrom) {
|
||||
if (this.position() !== undefined && unitToFleeFrom.position() !== undefined) {
|
||||
var FleeDirection = [unitToFleeFrom.position()[0] - this.position()[0],unitToFleeFrom.position()[1] - this.position()[1]];
|
||||
var FleeDirection = [this.position()[0] - unitToFleeFrom.position()[0],this.position()[1] - unitToFleeFrom.position()[1]];
|
||||
var dist = VectorDistance(unitToFleeFrom.position(), this.position() );
|
||||
FleeDirection[0] = (FleeDirection[0]/dist) * 5;
|
||||
FleeDirection[1] = (FleeDirection[1]/dist) * 5;
|
||||
FleeDirection[0] = (FleeDirection[0]/dist) * 8;
|
||||
FleeDirection[1] = (FleeDirection[1]/dist) * 8;
|
||||
|
||||
Engine.PostCommand({"type": "walk", "entities": [this.id()], "x": this.position()[0] + FleeDirection[0]*5, "z": this.position()[1] + FleeDirection[1]*5, "queued": false});
|
||||
}
|
||||
|
@ -41,9 +41,9 @@ var Filters = {
|
||||
},
|
||||
"dynamicProperties": ['metadata.' + key]};
|
||||
},
|
||||
byHasMetadata: function(key){
|
||||
byHasMetadata: function(player, key){
|
||||
return {"func" : function(ent){
|
||||
return (ent.getMetadata(PlayerID, key) != undefined);
|
||||
return (ent.getMetadata(player, key) != undefined);
|
||||
},
|
||||
"dynamicProperties": ['metadata.' + key]};
|
||||
},
|
||||
|
@ -29,9 +29,19 @@ function SharedScript(settings)
|
||||
|
||||
//Return a simple object (using no classes etc) that will be serialized
|
||||
//into saved games
|
||||
// TODO: that
|
||||
//TODO: that
|
||||
// note: we'll need to serialize much more than that before this can work.
|
||||
SharedScript.prototype.Serialize = function()
|
||||
{
|
||||
// serializing entities without using the class.
|
||||
var entities = [];
|
||||
for (var id in this._entities)
|
||||
{
|
||||
var ent = this._entities[id];
|
||||
entities.push( [ent._template, ent._entity, ent._templateName]);
|
||||
}
|
||||
// serialiazing metadata will be done by each AI on a AI basis and they shall update the shared script with that info on deserialization (using DeserializeMetadata() ).
|
||||
return { "entities" : entities };
|
||||
};
|
||||
|
||||
//Called after the constructor when loading a saved game, with 'data' being
|
||||
@ -39,6 +49,13 @@ SharedScript.prototype.Serialize = function()
|
||||
// TODO: that
|
||||
SharedScript.prototype.Deserialize = function(data)
|
||||
{
|
||||
this._entities = {};
|
||||
for (i in data.entities)
|
||||
{
|
||||
var entData = data.entities[i];
|
||||
|
||||
//this._entities[entData[1].id] = new Entity();
|
||||
}
|
||||
};
|
||||
|
||||
// Components that will be disabled in foundation entity templates.
|
||||
|
@ -67,10 +67,12 @@ aStarPath.prototype.markImpassableArea = function(cx, cy, Distance) {
|
||||
|
||||
|
||||
// sending gamestate creates a map
|
||||
// Not recommended to use minwidth < sampling. I allow minwidth = sampling - 1.
|
||||
// (you run the risk of "jumping" over obstacles or weird behavior.
|
||||
aStarPath.prototype.getPath = function(start, end, Sampling, minWidth, iterationLimit, gamestate)
|
||||
{
|
||||
this.Sampling = Sampling >= 1 ? Sampling : 1;
|
||||
this.minWidth = (minWidth !== undefined && minWidth >= this.Sampling) ? minWidth : this.Sampling;
|
||||
this.minWidth = (minWidth !== undefined && minWidth+1 >= this.Sampling) ? minWidth : this.Sampling;
|
||||
|
||||
if (start[0] < 0 || this.gamePosToMapPos(start)[0] >= this.width || start[1] < 0 || this.gamePosToMapPos(start)[1] >= this.height)
|
||||
return undefined;
|
||||
|
@ -20,7 +20,6 @@ function CityAttack(gameState, militaryManager, uniqueID, targetEnemy, type , ta
|
||||
max = enemyCount[i];
|
||||
}
|
||||
}
|
||||
warn ("target " + this.targetPlayer);
|
||||
if (this.targetPlayer === undefined || this.targetPlayer === -1)
|
||||
{
|
||||
this.failed = true;
|
||||
@ -185,7 +184,9 @@ function CityAttack(gameState, militaryManager, uniqueID, targetEnemy, type , ta
|
||||
else
|
||||
var position = [-1,-1];
|
||||
|
||||
// abort.
|
||||
if (gameState.ai.accessibility.getAccessValue(position) !== gameState.ai.myIndex)
|
||||
var position = [-1,-1];
|
||||
|
||||
var nearestCCArray = CCs.filterNearest(position, 1).toEntityArray();
|
||||
var CCpos = nearestCCArray[0].position();
|
||||
this.rallyPoint = [0,0];
|
||||
@ -217,6 +218,8 @@ function CityAttack(gameState, militaryManager, uniqueID, targetEnemy, type , ta
|
||||
|
||||
// get a good path to an estimated target.
|
||||
this.pathFinder = new aStarPath(gameState,false);
|
||||
this.pathWidth = 8; // a path pretty farm from entities
|
||||
this.pathSampling = 2;
|
||||
this.onBoat = false; // tells us if our units are loaded on boats.
|
||||
this.needsShip = false;
|
||||
|
||||
@ -265,7 +268,7 @@ CityAttack.prototype.setPaused = function(gameState, boolValue){
|
||||
}
|
||||
};
|
||||
CityAttack.prototype.mustStart = function(gameState){
|
||||
if (this.isPaused())
|
||||
if (this.isPaused() || this.path === undefined)
|
||||
return false;
|
||||
var MaxReachedEverywhere = true;
|
||||
for (unitCat in this.unitStat) {
|
||||
@ -284,65 +287,88 @@ CityAttack.prototype.mustStart = function(gameState){
|
||||
CityAttack.prototype.updatePreparation = function(gameState, militaryManager,events) {
|
||||
var self = this;
|
||||
|
||||
if (this.path == undefined || this.target == undefined) {
|
||||
if (this.path == undefined || this.target == undefined || this.path === "toBeContinued") {
|
||||
// find our target
|
||||
var targets = this.targetFinder(gameState, militaryManager);
|
||||
if (targets.length === 0){
|
||||
targets = this.defaultTargetFinder(gameState, militaryManager);
|
||||
}
|
||||
if (targets.length) {
|
||||
debug ("Aiming for " + targets);
|
||||
// picking a target
|
||||
var rand = Math.floor((Math.random()*targets.length));
|
||||
this.targetPos = undefined;
|
||||
var count = 0;
|
||||
while (!this.targetPos){
|
||||
this.target = targets.toEntityArray()[rand];
|
||||
this.targetPos = this.target.position();
|
||||
count++;
|
||||
if (count > 1000){
|
||||
debug("No target with a valid position found");
|
||||
return false;
|
||||
if (this.target == undefined)
|
||||
{
|
||||
var targets = this.targetFinder(gameState, militaryManager);
|
||||
if (targets.length === 0)
|
||||
targets = this.defaultTargetFinder(gameState, militaryManager);
|
||||
|
||||
if (targets.length) {
|
||||
debug ("Aiming for " + targets);
|
||||
// picking a target
|
||||
var maxDist = 1000000;
|
||||
var index = 0;
|
||||
for (i in targets._entities)
|
||||
{
|
||||
var dist = SquareVectorDistance(targets._entities[i].position(), this.rallyPoint);
|
||||
if (dist < maxDist)
|
||||
{
|
||||
maxDist = dist;
|
||||
index = i;
|
||||
}
|
||||
}
|
||||
this.target = targets._entities[index];
|
||||
this.targetPos = this.target.position();
|
||||
}
|
||||
// when we have a target, we path to it.
|
||||
this.path = this.pathFinder.getPath(this.rallyPoint,this.targetPos, 3, 3);//,300000,gameState);
|
||||
|
||||
if (this.path === undefined) {
|
||||
}
|
||||
// when we have a target, we path to it.
|
||||
// I'd like a good high width sampling first.
|
||||
// Thus I will not do everything at once.
|
||||
// It will probably carry over a few turns but that's no issue.
|
||||
if (this.path === undefined)
|
||||
this.path = this.pathFinder.getPath(this.rallyPoint,this.targetPos, this.pathSampling, this.pathWidth,250,gameState);
|
||||
else if (this.path === "toBeContinued")
|
||||
this.path = this.pathFinder.continuePath(gameState);
|
||||
|
||||
if (this.path === undefined) {
|
||||
if (this.pathWidth == 8)
|
||||
{
|
||||
this.pathWidth = 2;
|
||||
delete this.path;
|
||||
} else {
|
||||
delete this.pathFinder;
|
||||
return 3; // no path.
|
||||
} else if (this.path[1] === true) {
|
||||
// okay so we need a ship.
|
||||
// Basically we'll add it as a new class to train compulsorily, and we'll recompute our path.
|
||||
debug ("We need a ship.");
|
||||
if (!gameState.ai.waterMap)
|
||||
{
|
||||
debug ("This is actually a water map.");
|
||||
gameState.ai.waterMap = true;
|
||||
}
|
||||
this.unitStat["TransportShip"] = { "priority" : 1.1, "minSize" : 2, "targetSize" : 2, "batchSize" : 1, "classes" : ["Warship"],
|
||||
"interests" : [ ["strength",1], ["cost",1] ] ,"templates" : [] };
|
||||
if (type === "superSized") {
|
||||
this.unitStat["TransportShip"]["minSize"] = 4;
|
||||
this.unitStat["TransportShip"]["targetSize"] = 4;
|
||||
}
|
||||
var Unit = this.unitStat["TransportShip"];
|
||||
var filter = Filters.and(Filters.byClassesAnd(Unit["classes"]),Filters.and(Filters.byMetadata(PlayerID, "plan",this.name),Filters.byOwner(PlayerID)));
|
||||
this.unit["TransportShip"] = gameState.getOwnEntities().filter(filter);
|
||||
this.unit["TransportShip"].registerUpdates();
|
||||
this.unit["TransportShip"].length;
|
||||
this.buildOrder.push([0, Unit["classes"], this.unit["TransportShip"], Unit, "TransportShip"]);
|
||||
this.needsShip = true;
|
||||
}
|
||||
} else if (this.path === "toBeContinued") {
|
||||
// carry on.
|
||||
} else if (this.path[1] === true && this.pathWidth == 2) {
|
||||
// okay so we need a ship.
|
||||
// Basically we'll add it as a new class to train compulsorily, and we'll recompute our path.
|
||||
if (!gameState.ai.waterMap)
|
||||
{
|
||||
debug ("This is actually a water map.");
|
||||
gameState.ai.waterMap = true;
|
||||
}
|
||||
debug ("We need a ship.");
|
||||
this.unitStat["TransportShip"] = { "priority" : 1.1, "minSize" : 2, "targetSize" : 2, "batchSize" : 1, "classes" : ["Warship"],
|
||||
"interests" : [ ["strength",1], ["cost",1] ] ,"templates" : [] };
|
||||
if (type === "superSized") {
|
||||
this.unitStat["TransportShip"]["minSize"] = 4;
|
||||
this.unitStat["TransportShip"]["targetSize"] = 4;
|
||||
}
|
||||
var Unit = this.unitStat["TransportShip"];
|
||||
var filter = Filters.and(Filters.byClassesAnd(Unit["classes"]),Filters.and(Filters.byMetadata(PlayerID, "plan",this.name),Filters.byOwner(PlayerID)));
|
||||
this.unit["TransportShip"] = gameState.getOwnEntities().filter(filter);
|
||||
this.unit["TransportShip"].registerUpdates();
|
||||
this.unit["TransportShip"].length;
|
||||
this.buildOrder.push([0, Unit["classes"], this.unit["TransportShip"], Unit, "TransportShip"]);
|
||||
this.needsShip = true;
|
||||
this.pathWidth = 3;
|
||||
this.pathSampling = 3;
|
||||
this.path = this.path[0].reverse();
|
||||
delete this.pathFinder;
|
||||
} else if (this.path[1] === true && this.pathWidth == 8) {
|
||||
// retry with a smaller pathwidth:
|
||||
this.pathWidth = 2;
|
||||
delete this.path;
|
||||
} else {
|
||||
this.path = this.path[0].reverse();
|
||||
delete this.pathFinder;
|
||||
} else if (targets.length == 0 ) {
|
||||
gameState.ai.gameFinished = true;
|
||||
debug ("I do not have any target. So I'll just assume I won the game.");
|
||||
return 0;
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
Engine.ProfileStart("Update Preparation");
|
||||
|
||||
// special case: if we're reached max pop, and we can start the plan, start it.
|
||||
@ -737,7 +763,7 @@ CityAttack.prototype.update = function(gameState, militaryManager, events){
|
||||
return undefined; // should spawn an error.
|
||||
|
||||
// basically haven't moved an inch: very likely stuck)
|
||||
if (SquareVectorDistance(this.position, this.position10TurnsAgo) < 10 && this.path.length > 0 && gameState.ai.playedTurn % 20 === 0) {
|
||||
if (SquareVectorDistance(this.position, this.position10TurnsAgo) < 10 && this.path.length > 0 && gameState.ai.playedTurn % 10 === 0) {
|
||||
// check for stuck siege units
|
||||
|
||||
var sieges = this.unitCollection.filter(Filters.byClass("Siege"));
|
||||
@ -753,7 +779,7 @@ CityAttack.prototype.update = function(gameState, militaryManager, events){
|
||||
if (farthestEnt !== -1)
|
||||
farthestEnt.destroy();
|
||||
}
|
||||
if (gameState.ai.playedTurn % 20 === 0)
|
||||
if (gameState.ai.playedTurn % 10 === 0)
|
||||
this.position10TurnsAgo = this.position;
|
||||
|
||||
if (this.lastPosition && SquareVectorDistance(this.position, this.lastPosition) < 20 && this.path.length > 0) {
|
||||
@ -778,11 +804,11 @@ CityAttack.prototype.update = function(gameState, militaryManager, events){
|
||||
}
|
||||
|
||||
// check if our land units are close enough from the next waypoint.
|
||||
if (SquareVectorDistance(this.unitCollection.filter(Filters.not(Filters.byClass("Warship"))).getCentrePosition(), this.targetPos) < 8000 ||
|
||||
SquareVectorDistance(this.unitCollection.filter(Filters.not(Filters.byClass("Warship"))).getCentrePosition(), this.path[0][0]) < 600) {
|
||||
if (SquareVectorDistance(this.unitCollection.filter(Filters.not(Filters.byClass("Warship"))).getCentrePosition(), this.targetPos) < 7500 ||
|
||||
SquareVectorDistance(this.unitCollection.filter(Filters.not(Filters.byClass("Warship"))).getCentrePosition(), this.path[0][0]) < 850) {
|
||||
if (this.unitCollection.filter(Filters.byClass("Siege")).length !== 0
|
||||
&& SquareVectorDistance(this.unitCollection.filter(Filters.not(Filters.byClass("Warship"))).getCentrePosition(), this.targetPos) > 8000
|
||||
&& SquareVectorDistance(this.unitCollection.filter(Filters.byClass("Siege")).getCentrePosition(), this.path[0][0]) > 600)
|
||||
&& SquareVectorDistance(this.unitCollection.filter(Filters.not(Filters.byClass("Warship"))).getCentrePosition(), this.targetPos) > 7500
|
||||
&& SquareVectorDistance(this.unitCollection.filter(Filters.byClass("Siege")).getCentrePosition(), this.path[0][0]) > 850)
|
||||
{
|
||||
} else {
|
||||
// okay so here basically two cases. The first one is "we need a boat at this point".
|
||||
|
@ -439,6 +439,9 @@ Defence.prototype.defendFromEnemies = function(gameState, events, militaryManage
|
||||
if (nonDefenders.length*2.0 < newEnemies.length && this.nbAttackers > 5)
|
||||
gameState.setDefcon(1);
|
||||
|
||||
if (gameState.defcon() > 3)
|
||||
militaryManager.unpauseAllPlans(gameState);
|
||||
|
||||
if ( (nonDefenders.length + this.nbDefenders > newEnemies.length + this.nbAttackers)
|
||||
|| this.nbDefenders + nonDefenders.length < 4)
|
||||
{
|
||||
@ -496,6 +499,8 @@ Defence.prototype.defendFromEnemies = function(gameState, events, militaryManage
|
||||
|
||||
// successfully sorted
|
||||
defs.forEach(function (defender) { //}){
|
||||
if (defender.getMetadata(PlayerID, "plan") != undefined && gameState.defcon() < 3)
|
||||
militaryManager.pausePlan(gameState, defender.getMetadata(PlayerID, "plan"));
|
||||
//debug ("Against " +enemy.id() + " Assigning " + defender.id());
|
||||
if (defender.getMetadata(PlayerID, "role") == "worker" || defender.getMetadata(PlayerID, "role") == "attack")
|
||||
defender.setMetadata(PlayerID, "formerrole", defender.getMetadata(PlayerID, "role"));
|
||||
@ -535,8 +540,10 @@ Defence.prototype.defendFromEnemies = function(gameState, events, militaryManage
|
||||
break;
|
||||
}
|
||||
}
|
||||
if (!garrisoned)
|
||||
if (!garrisoned) {
|
||||
ent.flee(enemy);
|
||||
ent.setMetadata(PlayerID,"fleeing", gameState.getTimeElapsed());
|
||||
}
|
||||
}
|
||||
}
|
||||
});
|
||||
@ -578,6 +585,7 @@ Defence.prototype.MessageProcess = function(gameState,events, militaryManager) {
|
||||
ourUnit.attack(e.msg.attacker);
|
||||
else {
|
||||
ourUnit.flee(attacker);
|
||||
ourUnit.setMetadata(PlayerID,"fleeing", gameState.getTimeElapsed());
|
||||
}
|
||||
}
|
||||
// anyway we'll register the animal as dangerous, and attack it.
|
||||
@ -653,6 +661,7 @@ Defence.prototype.MessageProcess = function(gameState,events, militaryManager) {
|
||||
|
||||
// Right now we'll flee from the attacker.
|
||||
ourUnit.flee(attacker);
|
||||
ourUnit.setMetadata(PlayerID,"fleeing", gameState.getTimeElapsed());
|
||||
} else {
|
||||
// It's a soldier. Right now we'll retaliate
|
||||
// TODO: check for stronger units against this type, check for fleeing options, etc.
|
||||
|
@ -52,24 +52,27 @@ EconomyManager.prototype.init = function(gameState, events){
|
||||
if (ents.length > 0)
|
||||
{
|
||||
gameState.getResourceSupplies("food").forEach( function (ent) {
|
||||
if (SquareVectorDistance(ent.position(), ents[0].position()) < 5000)
|
||||
if (ent.resourceSupplyType().generic === "treasure" && SquareVectorDistance(ent.position(), ents[0].position()) < 5000)
|
||||
availableRess += ent.resourceSupplyMax();
|
||||
});
|
||||
gameState.getResourceSupplies("stone").forEach( function (ent) {
|
||||
if (SquareVectorDistance(ent.position(), ents[0].position()) < 5000)
|
||||
if (ent.resourceSupplyType().generic === "treasure" && SquareVectorDistance(ent.position(), ents[0].position()) < 5000)
|
||||
availableRess += ent.resourceSupplyMax();
|
||||
});
|
||||
gameState.getResourceSupplies("metal").forEach( function (ent) {
|
||||
if (SquareVectorDistance(ent.position(), ents[0].position()) < 5000)
|
||||
if (ent.resourceSupplyType().generic === "treasure" && SquareVectorDistance(ent.position(), ents[0].position()) < 5000)
|
||||
availableRess += ent.resourceSupplyMax();
|
||||
});
|
||||
gameState.getResourceSupplies("wood").forEach( function (ent) {
|
||||
if (SquareVectorDistance(ent.position(), ents[0].position()) < 5000)
|
||||
if (ent.resourceSupplyType().generic === "treasure" && SquareVectorDistance(ent.position(), ents[0].position()) < 5000)
|
||||
availableRess += ent.resourceSupplyMax();
|
||||
});
|
||||
}
|
||||
if (availableRess > 2000)
|
||||
{
|
||||
debug ("Assuming a fast start");
|
||||
this.fastStart = true;
|
||||
}
|
||||
// initialize once all the resource maps.
|
||||
this.updateResourceMaps(gameState, events);
|
||||
this.updateResourceConcentrations(gameState,"food");
|
||||
@ -225,6 +228,10 @@ EconomyManager.prototype.pickMostNeededResources = function(gameState) {
|
||||
// Prefer fewer gatherers (divided by weight)
|
||||
var va = numGatherers[a] / (self.gatherWeights[a]+1);
|
||||
var vb = numGatherers[b] / (self.gatherWeights[b]+1);
|
||||
if (self.gatherWeights[a] === 0)
|
||||
va = 10000;
|
||||
if (self.gatherWeights[b] === 0)
|
||||
vb = 10000;
|
||||
return va-vb;
|
||||
});
|
||||
return types;
|
||||
@ -235,7 +242,7 @@ EconomyManager.prototype.reassignRolelessUnits = function(gameState) {
|
||||
var roleless = gameState.getOwnEntitiesByRole(undefined);
|
||||
|
||||
roleless.forEach(function(ent) {
|
||||
if (ent.hasClass("Worker")){
|
||||
if ((ent.hasClass("Worker") || ent.hasClass("CitizenSoldier")) && !ent.getMetadata(PlayerID, "stoppedHunting")) {
|
||||
ent.setMetadata(PlayerID, "role", "worker");
|
||||
}
|
||||
});
|
||||
@ -292,10 +299,14 @@ EconomyManager.prototype.reassignIdleWorkers = function(gameState) {
|
||||
if (ent.position() === undefined){
|
||||
return;
|
||||
}
|
||||
|
||||
var types = self.pickMostNeededResources(gameState);
|
||||
ent.setMetadata(PlayerID, "subrole", "gatherer");
|
||||
ent.setMetadata(PlayerID, "gather-type", types[0]);
|
||||
if (ent.hasClass("Worker")) {
|
||||
var types = self.pickMostNeededResources(gameState);
|
||||
ent.setMetadata(PlayerID, "subrole", "gatherer");
|
||||
ent.setMetadata(PlayerID, "gather-type", types[0]);
|
||||
} else {
|
||||
ent.setMetadata(PlayerID, "subrole", "hunter");
|
||||
}
|
||||
|
||||
});
|
||||
}
|
||||
};
|
||||
@ -319,7 +330,7 @@ EconomyManager.prototype.assignToFoundations = function(gameState, noRepair) {
|
||||
if (!foundations.length && !damagedBuildings.length){
|
||||
return;
|
||||
}
|
||||
var workers = gameState.getOwnEntitiesByRole("worker");
|
||||
var workers = gameState.getOwnEntitiesByRole("worker").filter(Filters.not(Filters.byClass("Cavalry")));
|
||||
var builderWorkers = this.workersBySubrole(gameState, "builder");
|
||||
|
||||
var addedWorkers = 0;
|
||||
@ -336,7 +347,10 @@ EconomyManager.prototype.assignToFoundations = function(gameState, noRepair) {
|
||||
if (builderWorkers.length + addedWorkers < this.targetNumBuilders*Math.min(4.0,gameState.getTimeElapsed()/60000)) {
|
||||
var nonBuilderWorkers = workers.filter(function(ent) { return (ent.getMetadata(PlayerID, "subrole") !== "builder" && ent.getMetadata(PlayerID, "gather-type") !== "food" && ent.position() !== undefined); });
|
||||
var nearestNonBuilders = null;
|
||||
if (target.hasClass("CivCentre") || (target.hasClass("House") && gameState.getTimeElapsed() < 300000) )
|
||||
// if it's a civ centre, a house in the start of the game, or the first barracks, double the amount of workers.
|
||||
if (target.hasClass("CivCentre") || (target.hasClass("House") && gameState.getTimeElapsed() < 300000)
|
||||
|| (gameState.countEntitiesByType(gameState.applyCiv(gameState.ai.modules.military.bModerate[0])) === 0
|
||||
&& target._templateName == gameState.applyCiv(gameState.ai.modules.military.bModerate[0])))
|
||||
nearestNonBuilders = nonBuilderWorkers.filterNearest(target.position(), this.targetNumBuilders*2.0 - assigned);
|
||||
else
|
||||
nearestNonBuilders = nonBuilderWorkers.filterNearest(target.position(), this.targetNumBuilders - assigned);
|
||||
@ -902,7 +916,7 @@ EconomyManager.prototype.buildTemple = function(gameState, queues){
|
||||
};
|
||||
|
||||
EconomyManager.prototype.buildMarket = function(gameState, queues){
|
||||
if (gameState.getTimeElapsed() > this.marketStartTime && gameState.currentPhase() >= 2 ) {
|
||||
if (this.numWorkers > 50 && gameState.currentPhase() >= 2 ) {
|
||||
if (queues.economicBuilding.countTotalQueuedUnitsWithClass("BarterMarket") === 0 &&
|
||||
gameState.countEntitiesAndQueuedByType(gameState.applyCiv("structures/{civ}_market")) === 0){
|
||||
//only ever build one mill/CC/market at a time
|
||||
@ -985,7 +999,7 @@ EconomyManager.prototype.buildDropsites = function(gameState, queues){
|
||||
};
|
||||
// build more houses if needed.
|
||||
EconomyManager.prototype.buildMoreHouses = function(gameState, queues) {
|
||||
if (gameState.getTimeElapsed() < 25000)
|
||||
if (gameState.getTimeElapsed() < 15000)
|
||||
return;
|
||||
|
||||
// temporary 'remaining population space' based check, need to do
|
||||
@ -996,7 +1010,7 @@ EconomyManager.prototype.buildMoreHouses = function(gameState, queues) {
|
||||
var numConstructing = gameState.countEntitiesByType(gameState.applyCiv("foundation|structures/{civ}_house"));
|
||||
var numPlanned = queues.house.totalLength();
|
||||
|
||||
if (gameState.getTimeElapsed() < 300000 && numConstructing + numPlanned !== 0)
|
||||
if (gameState.getTimeElapsed() < 120000 && numConstructing + numPlanned !== 0)
|
||||
return;
|
||||
var additional = 0;
|
||||
if (gameState.civ() == "gaul" || gameState.civ() == "brit" || gameState.civ() == "iber")
|
||||
@ -1113,6 +1127,7 @@ EconomyManager.prototype.update = function(gameState, queues, events) {
|
||||
Engine.ProfileStop();
|
||||
return;
|
||||
}
|
||||
this.numWorkers = gameState.getOwnEntitiesByRole("worker").filter(Filters.not(Filters.byHasMetadata(PlayerID,"plan"))).length;
|
||||
|
||||
// this function also deals with a few things that are number-of-workers related
|
||||
Engine.ProfileStart("Train workers and build farms, houses. Research techs.");
|
||||
@ -1142,8 +1157,19 @@ EconomyManager.prototype.update = function(gameState, queues, events) {
|
||||
this.femaleRatio = Config.Economy.femaleRatio * 0.9; // might expect a rush and build some CS to counter.
|
||||
else
|
||||
this.femaleRatio = Config.Economy.femaleRatio;
|
||||
|
||||
if (gameState.getTimeElapsed() > 600000 && this.numWorkers < 50)
|
||||
{
|
||||
gameState.ai.queueManager.changePriority("villager", 80);
|
||||
gameState.ai.queueManager.changePriority("citizenSoldier", 70);
|
||||
} else if (gameState.getTimeElapsed() > 600000 && this.numWorkers > 80
|
||||
&& gameState.ai.queueManager.priorities["villager"] == 80)
|
||||
{
|
||||
gameState.ai.queueManager.changePriority("villager", Config.priorities.villager);
|
||||
gameState.ai.queueManager.changePriority("citizenSoldier", Config.priorities.citizenSoldier);
|
||||
}
|
||||
|
||||
if (this.baseNeed["metal"] === 0 && gameState.getTimeElapsed() > 540*1000) {
|
||||
if (this.baseNeed["metal"] === 0 && gameState.currentPhase() !== 1) {
|
||||
this.baseNeed["food"] = 140;
|
||||
this.baseNeed["wood"] = 100;
|
||||
this.baseNeed["stone"] = 50;
|
||||
@ -1190,6 +1216,8 @@ EconomyManager.prototype.update = function(gameState, queues, events) {
|
||||
Engine.ProfileStart("Swap Workers");
|
||||
var gathererGroups = {};
|
||||
gameState.getOwnEntitiesByRole("worker").forEach(function(ent){
|
||||
if (ent.hasClass("Cavalry"))
|
||||
return;
|
||||
var key = uneval(ent.resourceGatherRates());
|
||||
if (!gathererGroups[key]){
|
||||
gathererGroups[key] = {"food": [], "wood": [], "metal": [], "stone": []};
|
||||
|
@ -4,7 +4,7 @@
|
||||
|
||||
var MilitaryAttackManager = function() {
|
||||
|
||||
this.fortressStartTime = Config.Military.fortressStartTime * 1000;
|
||||
this.fortressStartTime = 0;
|
||||
this.fortressLapseTime = Config.Military.fortressLapseTime * 1000;
|
||||
this.defenceBuildingTime = Config.Military.defenceBuildingTime * 1000;
|
||||
this.advancedMilitaryStartTime = Config.Military.advancedMilitaryStartTime * 1000;
|
||||
@ -382,6 +382,9 @@ MilitaryAttackManager.prototype.measureEnemyStrength = function(gameState){
|
||||
|
||||
// Adds towers to the defenceBuilding queue
|
||||
MilitaryAttackManager.prototype.buildDefences = function(gameState, queues){
|
||||
|
||||
var workersNumber = gameState.getOwnEntitiesByRole("worker").filter(Filters.not(Filters.byHasMetadata(PlayerID,"plan"))).length;
|
||||
|
||||
if (gameState.countEntitiesAndQueuedByType(gameState.applyCiv('structures/{civ}_defense_tower'))
|
||||
+ queues.defenceBuilding.totalLength() < gameState.getEntityLimits()["DefenseTower"] && queues.defenceBuilding.totalLength() < 4
|
||||
&& gameState.currentPhase() > 1 && queues.defenceBuilding.totalLength() < 3) {
|
||||
@ -401,16 +404,13 @@ MilitaryAttackManager.prototype.buildDefences = function(gameState, queues){
|
||||
numFortresses += gameState.countEntitiesAndQueuedByType(gameState.applyCiv(this.bFort[i]));
|
||||
}
|
||||
|
||||
if (numFortresses + queues.defenceBuilding.totalLength() < 2 && gameState.currentPhase() > 2)
|
||||
if (queues.defenceBuilding.totalLength() < 1 && gameState.currentPhase() > 2)
|
||||
{
|
||||
if (gameState.getTimeElapsed() > this.fortressStartTime + numFortresses * this.fortressLapseTime){
|
||||
if (gameState.ai.pathsToMe && gameState.ai.pathsToMe.length > 0){
|
||||
var position = gameState.ai.pathsToMe.shift();
|
||||
// TODO: pick a fort randomly from the list.
|
||||
queues.defenceBuilding.addItem(new BuildingConstructionPlan(gameState, this.bFort[0], position));
|
||||
}else{
|
||||
queues.defenceBuilding.addItem(new BuildingConstructionPlan(gameState, this.bFort[0]));
|
||||
}
|
||||
if (workersNumber >= 95 && gameState.getTimeElapsed() > numFortresses * this.fortressLapseTime + this.fortressStartTime)
|
||||
{
|
||||
if (!this.fortressStartTime)
|
||||
this.fortressStartTime = gameState.getTimeElapsed();
|
||||
queues.defenceBuilding.addItem(new BuildingConstructionPlan(gameState, this.bFort[0]));
|
||||
}
|
||||
}
|
||||
};
|
||||
@ -419,24 +419,28 @@ MilitaryAttackManager.prototype.constructTrainingBuildings = function(gameState,
|
||||
// Build more military buildings
|
||||
// TODO: make military building better
|
||||
Engine.ProfileStart("Build buildings");
|
||||
if (gameState.countEntitiesByType(gameState.applyCiv("units/{civ}_support_female_citizen")) > 25 && (gameState.currentPhase() > 1 || gameState.isResearching("phase_town"))) {
|
||||
|
||||
|
||||
var workersNumber = gameState.getOwnEntitiesByRole("worker").filter(Filters.not(Filters.byHasMetadata(PlayerID, "plan"))).length;
|
||||
|
||||
if (workersNumber > 40 && (gameState.currentPhase() > 1 || gameState.isResearching("phase_town"))) {
|
||||
if (gameState.countEntitiesAndQueuedByType(gameState.applyCiv(this.bModerate[0])) + queues.militaryBuilding.totalLength() < 1) {
|
||||
debug ("Trying to build barracks");
|
||||
queues.militaryBuilding.addItem(new BuildingConstructionPlan(gameState, this.bModerate[0]));
|
||||
}
|
||||
}
|
||||
|
||||
if (gameState.countEntitiesAndQueuedByType(gameState.applyCiv(this.bModerate[0])) < 2 && gameState.getTimeElapsed() > 15*60*1000)
|
||||
if (gameState.countEntitiesAndQueuedByType(gameState.applyCiv(this.bModerate[0])) < 2 && workersNumber > 85)
|
||||
if (queues.militaryBuilding.totalLength() < 1)
|
||||
queues.militaryBuilding.addItem(new BuildingConstructionPlan(gameState, this.bModerate[0]));
|
||||
|
||||
if (gameState.countEntitiesAndQueuedByType(gameState.applyCiv(this.bModerate[0])) < 3 && gameState.getTimeElapsed() > 23*60*1000 &&
|
||||
if (gameState.countEntitiesAndQueuedByType(gameState.applyCiv(this.bModerate[0])) < 3 && workersNumber > 125 &&
|
||||
(gameState.civ() == "gaul" || gameState.civ() == "brit" || gameState.civ() == "iber"))
|
||||
if (queues.militaryBuilding.totalLength() < 1)
|
||||
queues.militaryBuilding.addItem(new BuildingConstructionPlan(gameState, this.bModerate[0]));
|
||||
|
||||
//build advanced military buildings
|
||||
if (gameState.getTimeElapsed() > this.advancedMilitaryStartTime && gameState.currentPhase() > 2){
|
||||
if (workersNumber > 75 && gameState.currentPhase() > 2){
|
||||
if (queues.militaryBuilding.totalLength() === 0){
|
||||
var inConst = 0;
|
||||
for (var i in this.bAdvanced)
|
||||
@ -450,7 +454,7 @@ MilitaryAttackManager.prototype.constructTrainingBuildings = function(gameState,
|
||||
}
|
||||
}
|
||||
if (gameState.civ() !== "gaul" && gameState.civ() !== "brit" && gameState.civ() !== "iber" &&
|
||||
gameState.getTimeElapsed() > this.advancedMilitaryStartTime && gameState.currentPhase() > 2 && gameState.getTimeElapsed() > 25*60*1000)
|
||||
workersNumber > 130 && gameState.currentPhase() > 2)
|
||||
{
|
||||
var Const = 0;
|
||||
for (var i in this.bAdvanced)
|
||||
@ -600,19 +604,35 @@ MilitaryAttackManager.prototype.update = function(gameState, queues, events) {
|
||||
debug ("Military Manager: " +attack.getType() +" plan " +attack.getName() +" aborted.");
|
||||
if (updateStep === 3) {
|
||||
this.attackPlansEncounteredWater = true;
|
||||
debug("I dare not wet my feet");
|
||||
debug("No attack path found. Aborting.");
|
||||
}
|
||||
attack.Abort(gameState, this);
|
||||
//this.abortedAttacks.push(attack);
|
||||
|
||||
this.upcomingAttacks[attackType].splice(i--,1);
|
||||
} else if (updateStep === 2) {
|
||||
var chatText = "I am launching an attack against " + gameState.sharedScript.playersData[attack.targetPlayer].name;
|
||||
if (Math.random() < 0.2)
|
||||
chatText = "Attacking " + gameState.sharedScript.playersData[attack.targetPlayer].name;
|
||||
else if (Math.random() < 0.3)
|
||||
chatText = "Starting to attack " + gameState.sharedScript.playersData[attack.targetPlayer].name;
|
||||
else if (Math.random() < 0.3)
|
||||
chatText = "I'm starting an attack against " + gameState.sharedScript.playersData[attack.targetPlayer].name;
|
||||
gameState.ai.chatTeam(chatText);
|
||||
debug ("Military Manager: Starting " +attack.getType() +" plan " +attack.getName());
|
||||
attack.StartAttack(gameState,this);
|
||||
this.startedAttacks[attackType].push(attack);
|
||||
this.upcomingAttacks[attackType].splice(i--,1);
|
||||
}
|
||||
} else {
|
||||
var chatText = "I am launching an attack against " + gameState.sharedScript.playersData[attack.targetPlayer].name;
|
||||
if (Math.random() < 0.2)
|
||||
chatText = "Attacking " + gameState.sharedScript.playersData[attack.targetPlayer].name;
|
||||
else if (Math.random() < 0.3)
|
||||
chatText = "Starting to attack " + gameState.sharedScript.playersData[attack.targetPlayer].name;
|
||||
else if (Math.random() < 0.3)
|
||||
chatText = "I'm starting an attack against " + gameState.sharedScript.playersData[attack.targetPlayer].name;
|
||||
gameState.ai.chatTeam(chatText);
|
||||
debug ("Military Manager: Starting " +attack.getType() +" plan " +attack.getName());
|
||||
this.startedAttacks[attackType].push(attack);
|
||||
this.upcomingAttacks[attackType].splice(i--,1);
|
||||
@ -652,25 +672,30 @@ MilitaryAttackManager.prototype.update = function(gameState, queues, events) {
|
||||
// creating plans after updating because an aborted plan might be reused in that case.
|
||||
if (gameState.countEntitiesByType(gameState.applyCiv(this.bModerate[0])) >= 1 && !this.attackPlansEncounteredWater
|
||||
&& gameState.getTimeElapsed() > this.attackPlansStartTime) {
|
||||
if (this.upcomingAttacks["CityAttack"].length == 0 && (gameState.getTimeElapsed() < 25*60000 || Config.difficulty < 2)) {
|
||||
var Lalala = new CityAttack(gameState, this,this.TotalAttackNumber, -1);
|
||||
if (Lalala.failed)
|
||||
{
|
||||
this.attackPlansEncounteredWater = true; // hack
|
||||
} else {
|
||||
debug ("Military Manager: Creating the plan " +this.TotalAttackNumber);
|
||||
this.TotalAttackNumber++;
|
||||
this.upcomingAttacks["CityAttack"].push(Lalala);
|
||||
}
|
||||
} else if (this.upcomingAttacks["CityAttack"].length == 0 && Config.difficulty !== 0) {
|
||||
var Lalala = new CityAttack(gameState, this,this.TotalAttackNumber, -1, "superSized");
|
||||
if (Lalala.failed)
|
||||
{
|
||||
this.attackPlansEncounteredWater = true; // hack
|
||||
} else {
|
||||
debug ("Military Manager: Creating the super sized plan " +this.TotalAttackNumber);
|
||||
this.TotalAttackNumber++;
|
||||
this.upcomingAttacks["CityAttack"].push(Lalala);
|
||||
if (gameState.countEntitiesByType(gameState.applyCiv("structures/{civ}_dock")) === 0 && gameState.ai.waterMap)
|
||||
{
|
||||
// wait till we get a dock.
|
||||
} else {
|
||||
if (this.upcomingAttacks["CityAttack"].length == 0 && (gameState.getTimeElapsed() < 25*60000 || Config.difficulty < 2)) {
|
||||
var Lalala = new CityAttack(gameState, this,this.TotalAttackNumber, -1);
|
||||
if (Lalala.failed)
|
||||
{
|
||||
this.attackPlansEncounteredWater = true; // hack
|
||||
} else {
|
||||
debug ("Military Manager: Creating the plan " +this.TotalAttackNumber);
|
||||
this.TotalAttackNumber++;
|
||||
this.upcomingAttacks["CityAttack"].push(Lalala);
|
||||
}
|
||||
} else if (this.upcomingAttacks["CityAttack"].length == 0 && Config.difficulty !== 0) {
|
||||
var Lalala = new CityAttack(gameState, this,this.TotalAttackNumber, -1, "superSized");
|
||||
if (Lalala.failed)
|
||||
{
|
||||
this.attackPlansEncounteredWater = true; // hack
|
||||
} else {
|
||||
debug ("Military Manager: Creating the super sized plan " +this.TotalAttackNumber);
|
||||
this.TotalAttackNumber++;
|
||||
this.upcomingAttacks["CityAttack"].push(Lalala);
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
|
@ -115,6 +115,9 @@ BuildingConstructionPlan.prototype.findGoodPosition = function(gameState) {
|
||||
} else if (template.genericName() == "House") {
|
||||
friendlyTiles.addInfluence(x, z, Math.ceil(infl/2.0),infl); // houses are farther away from other buildings but houses
|
||||
friendlyTiles.addInfluence(x, z, Math.ceil(infl/4.0),-infl/2.0); // houses are farther away from other buildings but houses
|
||||
} else if (template.hasClass("GarrisonFortress"))
|
||||
{
|
||||
friendlyTiles.addInfluence(x, z, -infl/3.0, -infl/3.0);
|
||||
} else if (ent.genericName() != "House") // houses have no influence on other buildings
|
||||
{
|
||||
friendlyTiles.addInfluence(x, z, infl);
|
||||
@ -142,15 +145,15 @@ BuildingConstructionPlan.prototype.findGoodPosition = function(gameState) {
|
||||
// also not for fields who can be stacked quite a bit
|
||||
var radius = 0;
|
||||
if (template.genericName() == "Field")
|
||||
radius = Math.ceil(template.obstructionRadius() / cellSize) - 0.7;
|
||||
radius = Math.ceil(template.obstructionRadius() / cellSize) - 0.4;
|
||||
else if (template.buildCategory() === "Dock")
|
||||
radius = 1;//Math.floor(template.obstructionRadius() / cellSize);
|
||||
else if (template.genericName() != "House" && !template.hasClass("DropsiteWood") && !template.hasClass("DropsiteStone") && !template.hasClass("DropsiteMetal"))
|
||||
radius = Math.ceil(template.obstructionRadius() / cellSize + 0.5);
|
||||
else if (gameState.civ() === "iber" || gameState.civ() === "gaul" || gameState.civ() === "brit")
|
||||
radius = Math.ceil(template.obstructionRadius() / cellSize - 0.5);
|
||||
else
|
||||
radius = Math.ceil(template.obstructionRadius() / cellSize);
|
||||
else
|
||||
radius = Math.ceil(template.obstructionRadius() / cellSize + 0.2);
|
||||
|
||||
// further contract cause walls
|
||||
// Note: I'm currently destroying them so that doesn't matter.
|
||||
@ -183,9 +186,6 @@ BuildingConstructionPlan.prototype.findGoodPosition = function(gameState) {
|
||||
// default angle
|
||||
var angle = 3*Math.PI/4;
|
||||
|
||||
if (template.genericName() == "House")
|
||||
angle = Math.PI;
|
||||
|
||||
return {
|
||||
"x" : x,
|
||||
"z" : z,
|
||||
|
@ -67,7 +67,7 @@ QBotAI.prototype.InitShared = function(gameState, sharedScript) {
|
||||
|
||||
// First path has a sampling of 3, which ensures we'll get at least one path even on Acropolis. The others are 6 so might fail.
|
||||
var pos = [this.pathInfo.mkeyPos[0] + 200*Math.cos(this.pathInfo.angle),this.pathInfo.mkeyPos[1] + 200*Math.sin(this.pathInfo.angle)];
|
||||
var path = this.pathFinder.getPath(this.pathInfo.ekeyPos, pos, 3, 3);// uncomment for debug:*/, 300000, gameState);
|
||||
var path = this.pathFinder.getPath(this.pathInfo.ekeyPos, pos, 2, 2);// uncomment for debug:*/, 300000, gameState);
|
||||
|
||||
//Engine.DumpImage("initialPath" + PlayerID + ".png", this.pathFinder.TotorMap.map, this.pathFinder.TotorMap.width,this.pathFinder.TotorMap.height,255);
|
||||
|
||||
@ -173,7 +173,7 @@ QBotAI.prototype.OnUpdate = function(sharedScript) {
|
||||
if (this.pathInfo !== undefined)
|
||||
{
|
||||
var pos = [this.pathInfo.mkeyPos[0] + 200*Math.cos(this.pathInfo.angle),this.pathInfo.mkeyPos[1] + 200*Math.sin(this.pathInfo.angle)];
|
||||
var path = this.pathFinder.getPath(this.pathInfo.ekeyPos, pos, 6, 6);// uncomment for debug:*/, 300000, gameState);
|
||||
var path = this.pathFinder.getPath(this.pathInfo.ekeyPos, pos, 6, 5);// uncomment for debug:*/, 300000, gameState);
|
||||
if (path !== undefined && path[1] !== undefined && path[1] == false) {
|
||||
// path is viable and doesn't require boating.
|
||||
// blackzone the last two waypoints.
|
||||
@ -228,14 +228,25 @@ QBotAI.prototype.OnUpdate = function(sharedScript) {
|
||||
if (this.playedTurn % 80 === 0)
|
||||
{
|
||||
// some debug informations about units.
|
||||
var units = gameState.getOwnEntities().filter(Filters.byClass("Unit"));
|
||||
var units = gameState.getOwnEntities();
|
||||
for (var i in units._entities)
|
||||
{
|
||||
var ent = units._entities[i];
|
||||
debug ("Unit " + ent.id() + " is a " + ent._templateName);
|
||||
debug ("It is a " + uneval(ent.getMetadata(PlayerID, "role")) + ", "+ uneval(ent.getMetadata(PlayerID, "subrole")));
|
||||
if (ent.getMetadata(PlayerID, "plan") != undefined)
|
||||
debug ("it is part of the plan " + uneval(ent.getMetadata(PlayerID, "plan")));
|
||||
if (sharedScript._entityMetadata[PlayerID][ent.id()])
|
||||
{
|
||||
var metadata = sharedScript._entityMetadata[PlayerID][ent.id()];
|
||||
for (j in metadata)
|
||||
{
|
||||
debug ("Metadata " + j);
|
||||
if (typeof(metadata[j]) == "object")
|
||||
warn ("Object");
|
||||
else if (typeof(metadata[j]) == undefined)
|
||||
warn ("Undefined");
|
||||
else
|
||||
warn(metadata[j]);
|
||||
}
|
||||
}
|
||||
}
|
||||
}*/
|
||||
|
||||
|
@ -333,4 +333,16 @@ QueueManager.prototype.removeQueue = function(queueName) {
|
||||
this.queueArrays.sort(function (a,b) { return (self.priorities[b[0]] - self.priorities[a[0]]) });
|
||||
}
|
||||
}
|
||||
QueueManager.prototype.changePriority = function(queueName, newPriority) {
|
||||
var self = this;
|
||||
if (this.queues[queueName] !== undefined)
|
||||
this.priorities[queueName] = newPriority;
|
||||
this.queueArrays = [];
|
||||
for (var p in this.queues) {
|
||||
this.account[p] = 0;
|
||||
this.accounts[p] = new Resources();
|
||||
this.queueArrays.push([p,this.queues[p]]);
|
||||
}
|
||||
this.queueArrays.sort(function (a,b) { return (self.priorities[b[0]] - self.priorities[a[0]]) });
|
||||
}
|
||||
|
||||
|
@ -12,12 +12,14 @@ Worker.prototype.update = function(gameState) {
|
||||
|
||||
|
||||
var subrole = this.ent.getMetadata(PlayerID, "subrole");
|
||||
|
||||
if (!this.ent.position()){
|
||||
|
||||
if (!this.ent.position() || (this.ent.getMetadata(PlayerID,"fleeing") && gameState.getTimeElapsed() - this.ent.getMetadata(PlayerID,"fleeing") < 8000)){
|
||||
// If the worker has no position then no work can be done
|
||||
return;
|
||||
}
|
||||
|
||||
if (this.ent.getMetadata(PlayerID,"fleeing"))
|
||||
this.ent.setMetadata(PlayerID,"fleeing", undefined);
|
||||
|
||||
if (subrole === "gatherer") {
|
||||
if (this.ent.unitAIState().split(".")[1] !== "GATHER" && this.ent.unitAIState().split(".")[1] !== "COMBAT" && this.ent.unitAIState().split(".")[1] !== "RETURNRESOURCE"){
|
||||
// TODO: handle combat for hunting animals
|
||||
@ -92,6 +94,12 @@ Worker.prototype.update = function(gameState) {
|
||||
}
|
||||
this.startApproachingResourceTime = gameState.getTimeElapsed();
|
||||
//Engine.PostCommand({"type": "set-shading-color", "entities": [this.ent.id()], "rgb": [0,10,0]});
|
||||
} else if(subrole === "hunter") {
|
||||
if (!this.ent.resourceCarrying() || this.ent.resourceCarrying().length === 0){
|
||||
Engine.ProfileStart("Start Hunting");
|
||||
this.startHunting(gameState);
|
||||
Engine.ProfileStop();
|
||||
}
|
||||
} else {
|
||||
this.startApproachingResourceTime = gameState.getTimeElapsed();
|
||||
}
|
||||
@ -306,7 +314,10 @@ Worker.prototype.startGathering = function(gameState){
|
||||
//debug ("noposition");
|
||||
return;
|
||||
}
|
||||
|
||||
|
||||
if (supply.isUnhuntable())
|
||||
return;
|
||||
|
||||
if (supply.getMetadata(PlayerID, "inaccessible") === true) {
|
||||
//debug ("inaccessible");
|
||||
return;
|
||||
@ -323,12 +334,6 @@ Worker.prototype.startGathering = function(gameState){
|
||||
//debug ("enemy");
|
||||
return;
|
||||
}
|
||||
|
||||
var territoryOwner = Map.createTerritoryMap(gameState).getOwner(supply.position());
|
||||
if (territoryOwner != PlayerID && territoryOwner != 0) {
|
||||
dist *= 3.0;
|
||||
//return;
|
||||
}
|
||||
|
||||
// quickscope accessbility check.
|
||||
if (!gameState.ai.accessibility.pathAvailable(gameState, ent.position(), supply.position(), true)) {
|
||||
@ -355,6 +360,12 @@ Worker.prototype.startGathering = function(gameState){
|
||||
dist += 4*SquareVectorDistance(supply.position(), nearestDropsite.position());
|
||||
dist /= 5.0;
|
||||
}
|
||||
|
||||
var territoryOwner = Map.createTerritoryMap(gameState).getOwner(supply.position());
|
||||
if (territoryOwner != PlayerID && territoryOwner != 0) {
|
||||
dist *= 3.0;
|
||||
//return;
|
||||
}
|
||||
|
||||
// Go for treasure as a priority
|
||||
if (dist < 40000 && supply.resourceSupplyType().generic == "treasure"){
|
||||
@ -452,6 +463,95 @@ Worker.prototype.returnResources = function(gameState){
|
||||
return true;
|
||||
};
|
||||
|
||||
Worker.prototype.startHunting = function(gameState){
|
||||
var ent = this.ent;
|
||||
|
||||
if (!ent.position() || ent.getMetadata(PlayerID, "stoppedHunting"))
|
||||
return;
|
||||
|
||||
// So here we're doing it basic. We check what we can hunt, we hunt it. No fancies.
|
||||
|
||||
var resources = gameState.getResourceSupplies("food");
|
||||
|
||||
if (resources.length === 0){
|
||||
debug("No food found to hunt!");
|
||||
return;
|
||||
}
|
||||
|
||||
var supplies = [];
|
||||
var nearestSupplyDist = Math.min();
|
||||
var nearestSupply = undefined;
|
||||
|
||||
resources.forEach(function(supply) { //}){
|
||||
if (!supply.position())
|
||||
return;
|
||||
|
||||
if (supply.getMetadata(PlayerID, "inaccessible") === true)
|
||||
return;
|
||||
|
||||
//if (supply.isFull === true)
|
||||
// return;
|
||||
|
||||
if (!supply.hasClass("Animal"))
|
||||
return;
|
||||
|
||||
if (supply.walkSpeed() + 0.5 >= ent.walkSpeed())
|
||||
return;
|
||||
|
||||
// measure the distance to the resource
|
||||
var dist = SquareVectorDistance(supply.position(), ent.position());
|
||||
|
||||
var territoryOwner = Map.createTerritoryMap(gameState).getOwner(supply.position());
|
||||
if (territoryOwner != PlayerID && territoryOwner != 0) {
|
||||
dist *= 3.0;
|
||||
}
|
||||
|
||||
// quickscope accessbility check
|
||||
if (!gameState.ai.accessibility.pathAvailable(gameState, ent.position(), supply.position(), true))
|
||||
return;
|
||||
|
||||
if (dist < nearestSupplyDist) {
|
||||
nearestSupplyDist = dist;
|
||||
nearestSupply = supply;
|
||||
}
|
||||
});
|
||||
|
||||
if (nearestSupply) {
|
||||
var pos = nearestSupply.position();
|
||||
|
||||
var nearestDropsite = 0;
|
||||
var minDropsiteDist = 1000000;
|
||||
// find a fitting dropsites in case we haven't already.
|
||||
gameState.getOwnDropsites("food").forEach(function (dropsite){ //}){
|
||||
if (dropsite.position()){
|
||||
var dist = SquareVectorDistance(pos, dropsite.position());
|
||||
if (dist < minDropsiteDist){
|
||||
minDropsiteDist = dist;
|
||||
nearestDropsite = dropsite;
|
||||
}
|
||||
}
|
||||
});
|
||||
if (!nearestDropsite)
|
||||
{
|
||||
ent.setMetadata(PlayerID, "stoppedHunting", true);
|
||||
ent.setMetadata(PlayerID, "role", undefined);
|
||||
debug ("No dropsite for hunting food");
|
||||
return;
|
||||
}
|
||||
if (minDropsiteDist > 45000) {
|
||||
ent.setMetadata(PlayerID, "stoppedHunting", true);
|
||||
ent.setMetadata(PlayerID, "role", undefined);
|
||||
} else {
|
||||
ent.gather(nearestSupply);
|
||||
ent.setMetadata(PlayerID, "target-foundation", undefined);
|
||||
}
|
||||
} else {
|
||||
ent.setMetadata(PlayerID, "stoppedHunting", true);
|
||||
ent.setMetadata(PlayerID, "role", undefined);
|
||||
debug("No food found for hunting! (2)");
|
||||
}
|
||||
};
|
||||
|
||||
Worker.prototype.getResourceType = function(type){
|
||||
if (!type || !type.generic){
|
||||
return undefined;
|
||||
|
@ -610,6 +610,14 @@ public:
|
||||
if (!m_ScriptInterface.CallFunction(m_Players[i]->m_Obj.get(), "Serialize", scriptData))
|
||||
LOGERROR(L"AI script Serialize call failed");
|
||||
serializer.ScriptVal("data", scriptData);
|
||||
|
||||
}
|
||||
if (m_HasSharedComponent)
|
||||
{
|
||||
CScriptVal sharedData;
|
||||
if (!m_ScriptInterface.CallFunction(m_SharedAIObj.get(), "Serialize", sharedData))
|
||||
LOGERROR(L"AI shared script Serialize call failed");
|
||||
serializer.ScriptVal("sharedData", sharedData);
|
||||
}
|
||||
}
|
||||
|
||||
@ -658,6 +666,13 @@ public:
|
||||
LOGERROR(L"AI script Deserialize call failed");
|
||||
}
|
||||
TryLoadSharedComponent(false);
|
||||
if (m_HasSharedComponent)
|
||||
{
|
||||
CScriptVal sharedData;
|
||||
deserializer.ScriptVal("sharedData", sharedData);
|
||||
if (!m_ScriptInterface.CallFunctionVoid(m_SharedAIObj.get(), "Deserialize", sharedData))
|
||||
LOGERROR(L"AI shared script Deserialize call failed");
|
||||
}
|
||||
}
|
||||
|
||||
int getPlayerSize()
|
||||
|
Loading…
Reference in New Issue
Block a user