From d04d6182536c4bea0d12dcc8c4c7460b888fb61a Mon Sep 17 00:00:00 2001 From: Tim Felgentreff <timfelgentreff@gmail.com> Date: Sat, 18 Dec 2021 14:35:13 +0100 Subject: [PATCH] force the AI to honour single-research vs multi-research and document that a bit --- src/action/action_research.cpp | 6 ++-- src/ai/ai_local.h | 11 +++++- src/ai/ai_resource.cpp | 62 +++++++++++++++++++++++----------- src/ai/script_ai.cpp | 10 ++++-- 4 files changed, 64 insertions(+), 25 deletions(-) diff --git a/src/action/action_research.cpp b/src/action/action_research.cpp index 8a4571a18..992c24cfb 100644 --- a/src/action/action_research.cpp +++ b/src/action/action_research.cpp @@ -132,8 +132,10 @@ #endif CPlayer &player = *unit.Player; if (player.UpgradeTimers.Upgrades[upgrade.ID] >= upgrade.Costs[TimeCost]) { - // completed in between our last step, possibly due to another unit finishing the upgrade - // n.b.: this is a feature: you can speed up research by using multiple buildings! + // completed in between our last step, possibly due to another unit + // finishing the upgrade n.b.: this is a feature: you can speed up + // research by using multiple buildings! This feature is only available + // if the button is marked "check-research", not "check-single-research" this->Finished = true; return; } diff --git a/src/ai/ai_local.h b/src/ai/ai_local.h index b3dc6a036..cd82ca6c1 100644 --- a/src/ai/ai_local.h +++ b/src/ai/ai_local.h @@ -345,10 +345,19 @@ public: std::vector<std::vector<CUnitType *> > Upgrade; /** ** The index is the research that should be made, giving a table of all - ** units/buildings which could research this upgrade. + ** units/buildings which could research this upgrade. This table only + ** includes those unit types which have the research defined as a button + ** without the "check-single-research" restriction. */ std::vector<std::vector<CUnitType *> > Research; /** + ** The index is the research that should be made, giving a table of all + ** units/buildings which could research this upgrade. This table only + ** includes those unit types which have the research defined as a button + ** with the "check-single-research" restriction. + */ + std::vector<std::vector<CUnitType *> > SingleResearch; + /** ** The index is the unit that should be repaired, giving a table of all ** units/buildings which could repair this unit. */ diff --git a/src/ai/ai_resource.cpp b/src/ai/ai_resource.cpp index 0f1fb7a3a..6ca25d3f3 100644 --- a/src/ai/ai_resource.cpp +++ b/src/ai/ai_resource.cpp @@ -747,29 +747,51 @@ void AiAddResearchRequest(CUpgrade *upgrade) // // Check if we have a place for the upgrade to research // - const int n = AiHelpers.Research.size(); - std::vector<std::vector<CUnitType *> > &tablep = AiHelpers.Research; + { // multi-research case + const int n = AiHelpers.Research.size(); + std::vector<std::vector<CUnitType *> > &tablep = AiHelpers.Research; - if (upgrade->ID > n) { // Oops not known. - DebugPrint("%d: AiAddResearchRequest I: Nothing known about '%s'\n" - _C_ AiPlayer->Player->Index _C_ upgrade->Ident.c_str()); - return; - } - std::vector<CUnitType *> &table = tablep[upgrade->ID]; - if (table.empty()) { // Oops not known. - DebugPrint("%d: AiAddResearchRequest II: Nothing known about '%s'\n" - _C_ AiPlayer->Player->Index _C_ upgrade->Ident.c_str()); - return; - } - - const int *unit_count = AiPlayer->Player->UnitTypesAiActiveCount; - for (unsigned int i = 0; i < table.size(); ++i) { - // The type is available - if (unit_count[table[i]->Slot] - && AiResearchUpgrade(*table[i], *upgrade)) { - return; + if (upgrade->ID < n) { // not known as multi-researchable upgrade + std::vector<CUnitType *> &table = tablep[upgrade->ID]; + if (!table.empty()) { // not known as multi-researchable upgrade + const int *unit_count = AiPlayer->Player->UnitTypesAiActiveCount; + for (unsigned int i = 0; i < table.size(); ++i) { + // The type is available + if (unit_count[table[i]->Slot] + && AiResearchUpgrade(*table[i], *upgrade)) { + return; + } + } + return; + } } } + { // single-research case + const int n = AiHelpers.SingleResearch.size(); + std::vector<std::vector<CUnitType *> > &tablep = AiHelpers.SingleResearch; + + if (upgrade->ID < n) { // not known + std::vector<CUnitType *> &table = tablep[upgrade->ID]; + if (!table.empty()) { // not known + // known as a single-research upgrade, check if we're already + // researching it. if so, ignore this request. + if (AiPlayer->Player->UpgradeTimers.Upgrades[upgrade->ID]) { + return; + } + const int *unit_count = AiPlayer->Player->UnitTypesAiActiveCount; + for (unsigned int i = 0; i < table.size(); ++i) { + // The type is available + if (unit_count[table[i]->Slot] + && AiResearchUpgrade(*table[i], *upgrade)) { + return; + } + } + return; + } + } + } + DebugPrint("%d: AiAddResearchRequest I: Nothing known about '%s'\n" + _C_ AiPlayer->Player->Index _C_ upgrade->Ident.c_str()); } /** diff --git a/src/ai/script_ai.cpp b/src/ai/script_ai.cpp index 71348e25e..f59fdbef0 100644 --- a/src/ai/script_ai.cpp +++ b/src/ai/script_ai.cpp @@ -286,8 +286,14 @@ static void InitAiHelper(AiHelper &aiHelper) case ButtonResearch : { int researchId = UpgradeIdByIdent(button.ValueStr); - for (std::vector<CUnitType *>::const_iterator j = unitmask.begin(); j != unitmask.end(); ++j) { - AiHelperInsert(aiHelper.Research, researchId, **j); + if (button.Allowed == ButtonCheckSingleResearch) { + for (std::vector<CUnitType *>::const_iterator j = unitmask.begin(); j != unitmask.end(); ++j) { + AiHelperInsert(aiHelper.SingleResearch, researchId, **j); + } + } else { + for (std::vector<CUnitType *>::const_iterator j = unitmask.begin(); j != unitmask.end(); ++j) { + AiHelperInsert(aiHelper.Research, researchId, **j); + } } break; }