1
0
forked from mirrors/0ad

Fix Athens not researching civ phase. Make the AI adapt automatically to changing the max gatherers on fields.

Fix auto-researched technologies not being properly researched on init.
Fix the tests (amazing!).
GarrisonHolder sends which entities were added or removed (mostly for AI
purposes but could benefit other things).
Streamline AIInterface events.

This was SVN commit r14612.
This commit is contained in:
wraitii
2014-01-18 20:26:52 +00:00
parent 76451a297e
commit 9330975d54
11 changed files with 60 additions and 62 deletions
@@ -622,8 +622,9 @@ m.BaseManager.prototype.checkResourceLevels = function (gameState,queues) {
numFarms += queues.field.countQueuedUnits();
// let's see if we need to push new farms.
var maxGatherers = gameState.getTemplate(gameState.applyCiv("structures/{civ}_field")).maxGatherers();
if (numFd < 2)
if (numFarms < Math.round(this.gatherersByType(gameState, "food").length / 4.6) || numFarms < Math.round(this.workers.length / 15.0))
if (numFarms < Math.round(this.gatherersByType(gameState, "food").length / (maxGatherers*0.9)) || numFarms < Math.round(this.workers.length / (maxGatherers*3))
queues.field.addItem(new m.ConstructionPlan(gameState, "structures/{civ}_field", { "base" : this.ID }));
// TODO: refine count to only count my base.
}
@@ -505,7 +505,7 @@ m.Army.prototype.update = function (gameState)
{
var id = this.entities[i];
var ent = gameState.getEntityById(id);
if (!ent.position) // shouldn't be able to happen but apparently does.
if (!ent || !ent.position()) // shouldn't be able to happen but apparently does.
continue;
if (API3.SquareVectorDistance(ent.position(), this.position) > this.breakawaySize)
{
@@ -157,6 +157,8 @@ m.GameState.prototype.townPhase = function()
m.GameState.prototype.cityPhase = function()
{
if (this.playerData.civ == "athen")
return "phase_city_athen";
return "phase_city_generic";
};
@@ -131,8 +131,12 @@ m.SharedScript.prototype.init = function(state) {
this._entities = {};
for (var id in state.entities)
{
// entropy generator
for (var p = 0; p < id; ++p)
Math.random();
this._entities[id] = new m.Entity(this, state.entities[id]);
}
// entity collection updated on create/destroy event.
this.entities = new m.EntityCollection(this, this._entities);
@@ -3,19 +3,26 @@ function AIInterface() {}
AIInterface.prototype.Schema =
"<a:component type='system'/><empty/>";
AIInterface.prototype.EventNames = [
"Create",
"Destroy",
"Attacked",
"RangeUpdate",
"ConstructionFinished",
"TrainingFinished",
"AIMetadata",
"PlayerDefeated",
"EntityRenamed",
"OwnershipChanged",
"Garrison",
"UnGarrison"
];
AIInterface.prototype.Init = function()
{
this.events = {};
this.events["Create"] = [];
this.events["Destroy"] = [];
this.events["Attacked"] = [];
this.events["RangeUpdate"] = [];
this.events["ConstructionFinished"] = [];
this.events["TrainingFinished"] = [];
this.events["AIMetadata"] = [];
this.events["PlayerDefeated"] = [];
this.events["EntityRenamed"] = [];
this.events["OwnershipChanged"] = [];
for each (var i in this.EventNames)
this.events[i] = [];
this.changedEntities = {};
@@ -34,28 +41,13 @@ AIInterface.prototype.GetNonEntityRepresentation = function()
var state = cmpGuiInterface.GetExtendedSimulationState(-1);
// Add some extra AI-specific data
// add custom events and reset them for the next turn
state.events = {};
state.events["Create"] = this.events["Create"];
state.events["Destroy"] = this.events["Destroy"];
state.events["Attacked"] = this.events["Attacked"];
state.events["RangeUpdate"] = this.events["RangeUpdate"];
state.events["ConstructionFinished"] = this.events["ConstructionFinished"];
state.events["TrainingFinished"] = this.events["TrainingFinished"];
state.events["AIMetadata"] = this.events["AIMetadata"];
state.events["PlayerDefeated"] = this.events["PlayerDefeated"];
state.events["EntityRenamed"] = this.events["EntityRenamed"];
state.events["OwnershipChanged"] = this.events["OwnershipChanged"];
// Reset the event list for the next turn
this.events["Create"] = [];
this.events["Destroy"] = [];
this.events["Attacked"] = [];
this.events["RangeUpdate"] = [];
this.events["ConstructionFinished"] = [];
this.events["TrainingFinished"] = [];
this.events["AIMetadata"] = [];
this.events["PlayerDefeated"] = [];
this.events["EntityRenamed"] = [];
this.events["OwnershipChanged"] = [];
for each (var i in this.EventNames)
{
state.events[i] = this.events[i];
this.events[i] = [];
}
return state;
};
@@ -90,18 +82,8 @@ AIInterface.prototype.GetFullRepresentation = function(flushEvents)
var state = this.GetNonEntityRepresentation();
if (flushEvents)
{
state.events["Create"] = [];
state.events["Destroy"] = [];
state.events["Attacked"] = [];
state.events["RangeUpdate"] = [];
state.events["ConstructionFinished"] = [];
state.events["TrainingFinished"] = [];
state.events["AIMetadata"] = [];
state.events["PlayerDefeated"] = [];
state.events["EntityRenamed"] = [];
state.events["OwnershipChanged"] = [];
}
for each (var i in this.EventNames)
state.events[i] = [];
// Add entity representations
Engine.ProfileStart("proxy representations");
@@ -34,7 +34,8 @@ AIProxy.prototype.Init = function()
{
this.changes = null;
this.needsFullGet = true;
this.owner = -1; // for convenience now and then.
// cache some data across turns
this.owner = -1;
this.cmpAIInterface = Engine.QueryInterface(SYSTEM_ENTITY, IID_AIInterface);
@@ -76,7 +77,7 @@ AIProxy.prototype.NotifyChange = function()
if (!this.changes)
{
this.changes = {};
this.cmpAIInterface.ChangedEntity(this.entity);
this.cmpAIInterface.ChangedEntity(this.entity);
}
};
@@ -134,6 +135,15 @@ AIProxy.prototype.OnGarrisonedUnitsChanged = function(msg)
var cmpGarrisonHolder = Engine.QueryInterface(this.entity, IID_GarrisonHolder);
this.changes.garrisoned = cmpGarrisonHolder.GetEntities();
// Send a message telling a unit garrisoned or ungarrisoned.
// I won't check if the unit is still alive so it'll be up to the AI.
var added = msg.added;
var removed = msg.removed;
for each (var ent in added)
this.cmpAIInterface.PushEvent("Garrison", {"entity" : ent, "holder": this.entity});
for each (var ent in removed)
this.cmpAIInterface.PushEvent("UnGarrison", {"entity" : ent, "holder": this.entity});
};
AIProxy.prototype.OnResourceSupplyChanged = function(msg)
@@ -244,7 +244,7 @@ GarrisonHolder.prototype.PerformGarrison = function(entity)
if (cmpAura && cmpAura.HasGarrisonAura())
cmpAura.ApplyGarrisonBonus(this.entity);
Engine.PostMessage(this.entity, MT_GarrisonedUnitsChanged, {});
Engine.PostMessage(this.entity, MT_GarrisonedUnitsChanged, { "added" : [entity], "removed": [] });
var cmpUnitAI = Engine.QueryInterface(entity, IID_UnitAI);
if (cmpUnitAI && cmpUnitAI.GetAlertRaiser())
@@ -310,7 +310,7 @@ GarrisonHolder.prototype.Eject = function(entity, forced)
cmpNewPosition.JumpTo(pos.x, pos.z);
// TODO: what direction should they face in?
Engine.PostMessage(this.entity, MT_GarrisonedUnitsChanged, {});
Engine.PostMessage(this.entity, MT_GarrisonedUnitsChanged, { "added" : [], "removed": [entity] });
return true;
};
@@ -563,7 +563,7 @@ GarrisonHolder.prototype.OnGlobalOwnershipChanged = function(msg)
if (cmpHealth && cmpHealth.GetHitpoints() == 0)
{
this.entities.splice(entityIndex, 1);
Engine.PostMessage(this.entity, MT_GarrisonedUnitsChanged, {});
Engine.PostMessage(this.entity, MT_GarrisonedUnitsChanged, { "added" : [], "removed": [msg.entity] });
this.UpdateGarrisonFlag();
}
else if(!IsOwnedByMutualAllyOfEntity(this.entity, this.entities[entityIndex]))
@@ -580,7 +580,7 @@ GarrisonHolder.prototype.OnGlobalEntityRenamed = function(msg)
if (entityIndex != -1)
{
this.entities[entityIndex] = msg.newentity;
Engine.PostMessage(this.entity, MT_GarrisonedUnitsChanged, {});
Engine.PostMessage(this.entity, MT_GarrisonedUnitsChanged, { "added" : [msg.newentity], "removed": [msg.entity] });
}
};
@@ -628,7 +628,7 @@ GarrisonHolder.prototype.EjectOrKill = function(entities)
this.entities.splice(entityIndex, 1);
}
Engine.PostMessage(this.entity, MT_GarrisonedUnitsChanged, {});
Engine.PostMessage(this.entity, MT_GarrisonedUnitsChanged, { "added" : [], "removed" : entities });
this.UpdateGarrisonFlag();
};
@@ -49,8 +49,6 @@ TechnologyManager.prototype.Init = function ()
if (this.allTechs[key].autoResearch || this.allTechs[key].top)
this.autoResearchTech[key] = this.allTechs[key];
}
this.UpdateAutoResearch();
};
TechnologyManager.prototype.OnUpdate = function ()
@@ -337,12 +335,12 @@ TechnologyManager.prototype.ResearchTechnology = function (tech)
this.UpdateAutoResearch();
var cmpPlayer = Engine.QueryInterface(this.entity, IID_Player);
if (!cmpPlayer || ! cmpPlayer.GetPlayerID())
if (!cmpPlayer || cmpPlayer.GetPlayerID() === undefined)
return;
var playerID = cmpPlayer.GetPlayerID();
var cmpRangeManager = Engine.QueryInterface(SYSTEM_ENTITY, IID_RangeManager);
var ents = cmpRangeManager.GetEntitiesByPlayer(playerID);
// TODO: Handle technology broadcasting for autoresearch properly (some components might not be initialized currently)
for (var component in modifiedComponents)
{
Engine.PostMessage(SYSTEM_ENTITY, MT_TemplateModification, { "player": playerID, "component": component, "valueNames": modifiedComponents[component]});
@@ -1,6 +1,6 @@
Engine.RegisterInterface("GarrisonHolder");
// Message of the form { } (use GetEntities if you want the current details),
// Message of the form { "added":[], "removed":[] } (and use GetEntities if you want the current details),
// sent to the current entity whenever the garrisoned units change.
Engine.RegisterMessageType("GarrisonedUnitsChanged");
@@ -206,7 +206,6 @@ TS_ASSERT_UNEVAL_EQUALS(cmp.GetSimulationState(), {
entityLimits: {"Foo": 10},
entityCounts: {"Foo": 5},
entityLimitChangers: {"Foo": {}},
techModifications: {},
researchQueued: {},
researchStarted: {},
researchedTechs: {},
@@ -235,7 +234,6 @@ TS_ASSERT_UNEVAL_EQUALS(cmp.GetSimulationState(), {
entityLimits: {"Bar": 20},
entityCounts: {"Bar": 0},
entityLimitChangers: {"Bar": {}},
techModifications: {},
researchQueued: {},
researchStarted: {},
researchedTechs: {},
@@ -271,7 +269,6 @@ TS_ASSERT_UNEVAL_EQUALS(cmp.GetExtendedSimulationState(), {
entityLimits: {"Foo": 10},
entityCounts: {"Foo": 5},
entityLimitChangers: {"Foo": {}},
techModifications: {},
researchQueued: {},
researchStarted: {},
researchedTechs: {},
@@ -316,7 +313,6 @@ TS_ASSERT_UNEVAL_EQUALS(cmp.GetExtendedSimulationState(), {
entityLimits: {"Bar": 20},
entityCounts: {"Bar": 0},
entityLimitChangers: {"Bar": {}},
techModifications: {},
researchQueued: {},
researchStarted: {},
researchedTechs: {},
@@ -54,6 +54,11 @@ function LoadPlayerSettings(settings, newPlayers)
// Add player to player manager
cmpPlayerManager.AddPlayer(entID);
// Properly autoresearch techs on init.
var cmpTechManager = Engine.QueryInterface(entID, IID_TechnologyManager);
if (cmpTechManager !== undefined)
cmpTechManager.UpdateAutoResearch();
}
}