LCOV - code coverage report
Current view: top level - simulation/ai/petra - researchManager.js (source / functions) Hit Total Coverage
Test: lcov.info Lines: 0 145 0.0 %
Date: 2023-04-02 12:52:40 Functions: 0 10 0.0 %

          Line data    Source code
       1             : /**
       2             :  * Manage the research
       3             :  */
       4           0 : PETRA.ResearchManager = function(Config)
       5             : {
       6           0 :         this.Config = Config;
       7             : };
       8             : 
       9             : /**
      10             :  * Check if we can go to the next phase
      11             :  */
      12           0 : PETRA.ResearchManager.prototype.checkPhase = function(gameState, queues)
      13             : {
      14           0 :         if (queues.majorTech.hasQueuedUnits())
      15           0 :                 return;
      16             :         // Don't try to phase up if already trying to gather resources for a civil-centre or wonder
      17           0 :         if (queues.civilCentre.hasQueuedUnits() || queues.wonder.hasQueuedUnits())
      18           0 :                 return;
      19             : 
      20           0 :         let currentPhaseIndex = gameState.currentPhase();
      21           0 :         let nextPhaseName = gameState.getPhaseName(currentPhaseIndex+1);
      22           0 :         if (!nextPhaseName)
      23           0 :                 return;
      24             : 
      25             :         let petraRequirements =
      26           0 :                 currentPhaseIndex == 1 && gameState.ai.HQ.getAccountedPopulation(gameState) >= this.Config.Economy.popPhase2 ||
      27             :                 currentPhaseIndex == 2 && gameState.ai.HQ.getAccountedWorkers(gameState) > this.Config.Economy.workPhase3 ||
      28             :                 currentPhaseIndex >= 3 && gameState.ai.HQ.getAccountedWorkers(gameState) > this.Config.Economy.workPhase4;
      29           0 :         if (petraRequirements && gameState.hasResearchers(nextPhaseName, true))
      30             :         {
      31           0 :                 gameState.ai.HQ.phasing = currentPhaseIndex + 1;
      32             :                 // Reset the queue priority in case it was changed during a previous phase update
      33           0 :                 gameState.ai.queueManager.changePriority("majorTech", gameState.ai.Config.priorities.majorTech);
      34           0 :                 queues.majorTech.addPlan(new PETRA.ResearchPlan(gameState, nextPhaseName, true));
      35             :         }
      36             : };
      37             : 
      38           0 : PETRA.ResearchManager.prototype.researchPopulationBonus = function(gameState, queues)
      39             : {
      40           0 :         if (queues.minorTech.hasQueuedUnits())
      41           0 :                 return;
      42             : 
      43           0 :         let techs = gameState.findAvailableTech();
      44           0 :         for (let tech of techs)
      45             :         {
      46           0 :                 if (!tech[1]._template.modifications)
      47           0 :                         continue;
      48             :                 // TODO may-be loop on all modifs and check if the effect if positive ?
      49           0 :                 if (tech[1]._template.modifications[0].value !== "Population/Bonus")
      50           0 :                         continue;
      51           0 :                 queues.minorTech.addPlan(new PETRA.ResearchPlan(gameState, tech[0]));
      52           0 :                 break;
      53             :         }
      54             : };
      55             : 
      56           0 : PETRA.ResearchManager.prototype.researchTradeBonus = function(gameState, queues)
      57             : {
      58           0 :         if (queues.minorTech.hasQueuedUnits())
      59           0 :                 return;
      60             : 
      61           0 :         let techs = gameState.findAvailableTech();
      62           0 :         for (let tech of techs)
      63             :         {
      64           0 :                 if (!tech[1]._template.modifications || !tech[1]._template.affects)
      65           0 :                         continue;
      66           0 :                 if (tech[1]._template.affects.indexOf("Trader") === -1)
      67           0 :                         continue;
      68             :                 // TODO may-be loop on all modifs and check if the effect if positive ?
      69           0 :                 if (tech[1]._template.modifications[0].value !== "UnitMotion/WalkSpeed" &&
      70             :                     tech[1]._template.modifications[0].value !== "Trader/GainMultiplier")
      71           0 :                         continue;
      72           0 :                 queues.minorTech.addPlan(new PETRA.ResearchPlan(gameState, tech[0]));
      73           0 :                 break;
      74             :         }
      75             : };
      76             : 
      77             : /** Techs to be searched for as soon as they are available */
      78           0 : PETRA.ResearchManager.prototype.researchWantedTechs = function(gameState, techs)
      79             : {
      80           0 :         let phase1 = gameState.currentPhase() === 1;
      81           0 :         let available = phase1 ? gameState.ai.queueManager.getAvailableResources(gameState) : null;
      82           0 :         const numWorkers = phase1 ? gameState.getOwnEntitiesByRole(PETRA.Worker.ROLE_WORKER, true).length : 0;
      83           0 :         for (let tech of techs)
      84             :         {
      85           0 :                 if (tech[0].indexOf("unlock_champion") == 0)
      86           0 :                         return { "name": tech[0], "increasePriority": true };
      87           0 :                 if (tech[0] == "traditional_army_sele" || tech[0] == "reformed_army_sele")
      88           0 :                         return { "name": pickRandom(["traditional_army_sele", "reformed_army_sele"]), "increasePriority": true };
      89             : 
      90           0 :                 if (!tech[1]._template.modifications)
      91           0 :                         continue;
      92           0 :                 let template = tech[1]._template;
      93           0 :                 if (phase1)
      94             :                 {
      95           0 :                         let cost = template.cost;
      96           0 :                         let costMax = 0;
      97           0 :                         for (let res in cost)
      98           0 :                                 costMax = Math.max(costMax, Math.max(cost[res]-available[res], 0));
      99           0 :                         if (10*numWorkers < costMax)
     100           0 :                                 continue;
     101             :                 }
     102           0 :                 for (let i in template.modifications)
     103             :                 {
     104           0 :                         if (gameState.ai.HQ.navalMap && template.modifications[i].value === "ResourceGatherer/Rates/food.fish")
     105           0 :                                 return { "name": tech[0], "increasePriority": this.CostSum(template.cost) < 400 };
     106           0 :                         else if (template.modifications[i].value === "ResourceGatherer/Rates/food.fruit")
     107           0 :                                 return { "name": tech[0], "increasePriority": this.CostSum(template.cost) < 400 };
     108           0 :                         else if (template.modifications[i].value === "ResourceGatherer/Rates/food.grain")
     109           0 :                                 return { "name": tech[0], "increasePriority": false };
     110           0 :                         else if (template.modifications[i].value === "ResourceGatherer/Rates/wood.tree")
     111           0 :                                 return { "name": tech[0], "increasePriority": this.CostSum(template.cost) < 400 };
     112           0 :                         else if (template.modifications[i].value.startsWith("ResourceGatherer/Capacities"))
     113           0 :                                 return { "name": tech[0], "increasePriority": false };
     114           0 :                         else if (template.modifications[i].value === "Attack/Ranged/MaxRange")
     115           0 :                                 return { "name": tech[0], "increasePriority": false };
     116             :                 }
     117             :         }
     118           0 :         return null;
     119             : };
     120             : 
     121             : /** Techs to be searched for as soon as they are available, but only after phase 2 */
     122           0 : PETRA.ResearchManager.prototype.researchPreferredTechs = function(gameState, techs)
     123             : {
     124           0 :         let phase2 = gameState.currentPhase() === 2;
     125           0 :         let available = phase2 ? gameState.ai.queueManager.getAvailableResources(gameState) : null;
     126           0 :         const numWorkers = phase2 ? gameState.getOwnEntitiesByRole(PETRA.Worker.ROLE_WORKER, true).length : 0;
     127           0 :         for (let tech of techs)
     128             :         {
     129           0 :                 if (!tech[1]._template.modifications)
     130           0 :                         continue;
     131           0 :                 let template = tech[1]._template;
     132           0 :                 if (phase2)
     133             :                 {
     134           0 :                         let cost = template.cost;
     135           0 :                         let costMax = 0;
     136           0 :                         for (let res in cost)
     137           0 :                                 costMax = Math.max(costMax, Math.max(cost[res]-available[res], 0));
     138           0 :                         if (10*numWorkers < costMax)
     139           0 :                                 continue;
     140             :                 }
     141           0 :                 for (let i in template.modifications)
     142             :                 {
     143           0 :                         if (template.modifications[i].value === "ResourceGatherer/Rates/stone.rock")
     144           0 :                                 return { "name": tech[0], "increasePriority": this.CostSum(template.cost) < 400 };
     145           0 :                         else if (template.modifications[i].value === "ResourceGatherer/Rates/metal.ore")
     146           0 :                                 return { "name": tech[0], "increasePriority": this.CostSum(template.cost) < 400 };
     147           0 :                         else if (template.modifications[i].value === "BuildingAI/DefaultArrowCount")
     148           0 :                                 return { "name": tech[0], "increasePriority": this.CostSum(template.cost) < 400 };
     149           0 :                         else if (template.modifications[i].value === "Health/RegenRate")
     150           0 :                                 return { "name": tech[0], "increasePriority": false };
     151           0 :                         else if (template.modifications[i].value === "Health/IdleRegenRate")
     152           0 :                                 return { "name": tech[0], "increasePriority": false };
     153             :                 }
     154             :         }
     155           0 :         return null;
     156             : };
     157             : 
     158           0 : PETRA.ResearchManager.prototype.update = function(gameState, queues)
     159             : {
     160           0 :         if (queues.minorTech.hasQueuedUnits() || queues.majorTech.hasQueuedUnits())
     161           0 :                 return;
     162             : 
     163           0 :         let techs = gameState.findAvailableTech();
     164             : 
     165           0 :         let techName = this.researchWantedTechs(gameState, techs);
     166           0 :         if (techName)
     167             :         {
     168           0 :                 if (techName.increasePriority)
     169             :                 {
     170           0 :                         gameState.ai.queueManager.changePriority("minorTech", 2*this.Config.priorities.minorTech);
     171           0 :                         let plan = new PETRA.ResearchPlan(gameState, techName.name);
     172           0 :                         plan.queueToReset = "minorTech";
     173           0 :                         queues.minorTech.addPlan(plan);
     174             :                 }
     175             :                 else
     176           0 :                         queues.minorTech.addPlan(new PETRA.ResearchPlan(gameState, techName.name));
     177           0 :                 return;
     178             :         }
     179             : 
     180           0 :         if (gameState.currentPhase() < 2)
     181           0 :                 return;
     182             : 
     183           0 :         techName = this.researchPreferredTechs(gameState, techs);
     184           0 :         if (techName)
     185             :         {
     186           0 :                 if (techName.increasePriority)
     187             :                 {
     188           0 :                         gameState.ai.queueManager.changePriority("minorTech", 2*this.Config.priorities.minorTech);
     189           0 :                         let plan = new PETRA.ResearchPlan(gameState, techName.name);
     190           0 :                         plan.queueToReset = "minorTech";
     191           0 :                         queues.minorTech.addPlan(plan);
     192             :                 }
     193             :                 else
     194           0 :                         queues.minorTech.addPlan(new PETRA.ResearchPlan(gameState, techName.name));
     195           0 :                 return;
     196             :         }
     197             : 
     198           0 :         if (gameState.currentPhase() < 3)
     199           0 :                 return;
     200             : 
     201             :         // remove some techs not yet used by this AI
     202             :         // remove also sharedLos if we have no ally
     203           0 :         for (let i = 0; i < techs.length; ++i)
     204             :         {
     205           0 :                 let template = techs[i][1]._template;
     206           0 :                 if (template.affects && template.affects.length === 1 &&
     207             :                         (template.affects[0] === "Healer" || template.affects[0] === "Outpost" || template.affects[0] === "Wall"))
     208             :                 {
     209           0 :                         techs.splice(i--, 1);
     210           0 :                         continue;
     211             :                 }
     212           0 :                 if (template.modifications && template.modifications.length === 1 &&
     213             :                         this.Config.unusedNoAllyTechs.includes(template.modifications[0].value) &&
     214             :                         !gameState.hasAllies())
     215             :                 {
     216           0 :                         techs.splice(i--, 1);
     217           0 :                         continue;
     218             :                 }
     219             :         }
     220           0 :         if (!techs.length)
     221           0 :                 return;
     222             : 
     223             :         // randomly pick one. No worries about pairs in that case.
     224           0 :         queues.minorTech.addPlan(new PETRA.ResearchPlan(gameState, pickRandom(techs)[0]));
     225             : };
     226             : 
     227           0 : PETRA.ResearchManager.prototype.CostSum = function(cost)
     228             : {
     229           0 :         let costSum = 0;
     230           0 :         for (let res in cost)
     231           0 :                 costSum += cost[res];
     232           0 :         return costSum;
     233             : };
     234             : 
     235           0 : PETRA.ResearchManager.prototype.Serialize = function()
     236             : {
     237           0 :         return {};
     238             : };
     239             : 
     240           0 : PETRA.ResearchManager.prototype.Deserialize = function(data)
     241             : {
     242             : };

Generated by: LCOV version 1.14