From 9330975d54fa383f8fa3276eb39e00bcd552e63e Mon Sep 17 00:00:00 2001 From: wraitii Date: Sat, 18 Jan 2014 20:26:52 +0000 Subject: [PATCH] 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. --- .../simulation/ai/aegis/base-manager.js | 3 +- .../simulation/ai/aegis/defence-helper.js | 2 +- .../simulation/ai/common-api/gamestate.js | 2 + .../public/simulation/ai/common-api/shared.js | 6 +- .../simulation/components/AIInterface.js | 68 +++++++------------ .../public/simulation/components/AIProxy.js | 14 +++- .../simulation/components/GarrisonHolder.js | 10 +-- .../components/TechnologyManager.js | 6 +- .../components/interfaces/GarrisonHolder.js | 2 +- .../components/tests/test_GuiInterface.js | 4 -- .../mods/public/simulation/helpers/Player.js | 5 ++ 11 files changed, 60 insertions(+), 62 deletions(-) diff --git a/binaries/data/mods/public/simulation/ai/aegis/base-manager.js b/binaries/data/mods/public/simulation/ai/aegis/base-manager.js index 0a814ba874..4cc3e7f34c 100644 --- a/binaries/data/mods/public/simulation/ai/aegis/base-manager.js +++ b/binaries/data/mods/public/simulation/ai/aegis/base-manager.js @@ -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. } diff --git a/binaries/data/mods/public/simulation/ai/aegis/defence-helper.js b/binaries/data/mods/public/simulation/ai/aegis/defence-helper.js index bbb7f8b970..043c5c43a6 100755 --- a/binaries/data/mods/public/simulation/ai/aegis/defence-helper.js +++ b/binaries/data/mods/public/simulation/ai/aegis/defence-helper.js @@ -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) { diff --git a/binaries/data/mods/public/simulation/ai/common-api/gamestate.js b/binaries/data/mods/public/simulation/ai/common-api/gamestate.js index 9cbacacf0e..3db569cb32 100644 --- a/binaries/data/mods/public/simulation/ai/common-api/gamestate.js +++ b/binaries/data/mods/public/simulation/ai/common-api/gamestate.js @@ -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"; }; diff --git a/binaries/data/mods/public/simulation/ai/common-api/shared.js b/binaries/data/mods/public/simulation/ai/common-api/shared.js index b4dc583de5..a01afef289 100644 --- a/binaries/data/mods/public/simulation/ai/common-api/shared.js +++ b/binaries/data/mods/public/simulation/ai/common-api/shared.js @@ -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); diff --git a/binaries/data/mods/public/simulation/components/AIInterface.js b/binaries/data/mods/public/simulation/components/AIInterface.js index f7ba2f1a61..a6d9fb0775 100644 --- a/binaries/data/mods/public/simulation/components/AIInterface.js +++ b/binaries/data/mods/public/simulation/components/AIInterface.js @@ -3,19 +3,26 @@ function AIInterface() {} AIInterface.prototype.Schema = ""; +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"); diff --git a/binaries/data/mods/public/simulation/components/AIProxy.js b/binaries/data/mods/public/simulation/components/AIProxy.js index a00f7b9fac..aca09bc928 100644 --- a/binaries/data/mods/public/simulation/components/AIProxy.js +++ b/binaries/data/mods/public/simulation/components/AIProxy.js @@ -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) diff --git a/binaries/data/mods/public/simulation/components/GarrisonHolder.js b/binaries/data/mods/public/simulation/components/GarrisonHolder.js index a30c76545c..5dfd56dce9 100644 --- a/binaries/data/mods/public/simulation/components/GarrisonHolder.js +++ b/binaries/data/mods/public/simulation/components/GarrisonHolder.js @@ -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(); }; diff --git a/binaries/data/mods/public/simulation/components/TechnologyManager.js b/binaries/data/mods/public/simulation/components/TechnologyManager.js index b24b816353..0cddba8e4c 100644 --- a/binaries/data/mods/public/simulation/components/TechnologyManager.js +++ b/binaries/data/mods/public/simulation/components/TechnologyManager.js @@ -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]}); diff --git a/binaries/data/mods/public/simulation/components/interfaces/GarrisonHolder.js b/binaries/data/mods/public/simulation/components/interfaces/GarrisonHolder.js index 480c88a539..c2017f8ff3 100644 --- a/binaries/data/mods/public/simulation/components/interfaces/GarrisonHolder.js +++ b/binaries/data/mods/public/simulation/components/interfaces/GarrisonHolder.js @@ -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"); diff --git a/binaries/data/mods/public/simulation/components/tests/test_GuiInterface.js b/binaries/data/mods/public/simulation/components/tests/test_GuiInterface.js index 60ae42e0be..3fd0fc3125 100644 --- a/binaries/data/mods/public/simulation/components/tests/test_GuiInterface.js +++ b/binaries/data/mods/public/simulation/components/tests/test_GuiInterface.js @@ -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: {}, diff --git a/binaries/data/mods/public/simulation/helpers/Player.js b/binaries/data/mods/public/simulation/helpers/Player.js index 6dc73b176d..b679178c76 100644 --- a/binaries/data/mods/public/simulation/helpers/Player.js +++ b/binaries/data/mods/public/simulation/helpers/Player.js @@ -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(); } }