/** ** Build new units to reduce the food shortage. */ static bool AiRequestSupply() { // Don't request supply if we're sleeping. When the script starts it may // request a better unit than the one we pick here. If we only have enough // resources for one unit we don't want to build the wrong one. if (AiPlayer->SleepCycles != 0) { /* we still need supply */ return true; } // Count the already made build requests. int counter[UnitTypeMax]; AiGetBuildRequestsCount(AiPlayer, counter); struct cnode cache[16]; memset(cache, 0, sizeof(cache)); // // Check if we can build this? // int j = 0; const int n = AiHelpers.UnitLimit[0].size(); for (int i = 0; i < n; ++i) { CUnitType &type = *AiHelpers.UnitLimit[0][i]; if (counter[type.Slot]) { // Already ordered. #if defined(DEBUG) && defined(DebugRequestSupply) DebugPrint("%d: AiRequestSupply: Supply already build in %s\n" _C_ AiPlayer->Player->Index _C_ type->Name.c_str()); #endif return false; } if (!AiRequestedTypeAllowed(AiPlayer->Player, type)) { continue; } // // Check if resources available. // cache[j].needmask = AiCheckUnitTypeCosts(type); for (int c = 1; c < MaxCosts; ++c) { cache[j].unit_cost += type.Stats[AiPlayer->Player->Index].Costs[c]; } cache[j].unit_cost += type.Supply - 1; cache[j].unit_cost /= type.Supply; cache[j++].type = &type; Assert(j < 16); } if (j > 1) qsort(&cache, j, sizeof (struct cnode), cnode_cmp); if (j) { if (!cache[0].needmask) { CUnitType &type = *cache[0].type; if (AiMakeUnit(type, -1, -1)) { AiBuildQueue newqueue; newqueue.Type = &type; newqueue.Want = 1; newqueue.Made = 1; AiPlayer->UnitTypeBuilt.insert( AiPlayer->UnitTypeBuilt.begin(), newqueue); #if defined( DEBUG) && defined( DebugRequestSupply ) DebugPrint("%d: AiRequestSupply: build Supply in %s\n" _C_ AiPlayer->Player->Index _C_ type->Name.c_str()); #endif return false; } } AiPlayer->NeededMask |= cache[0].needmask; } #if defined( DEBUG) && defined( DebugRequestSupply ) std::string needed(""); for (int i = 1; i < MaxCosts; ++i) { if (cache[0].needmask & (1 << i)) { needed += ":"; switch (i) { case GoldCost: needed += "Gold<"; break; case WoodCost: needed += "Wood<"; break; case OilCost: needed += "Oil<"; break; default: needed += "unknown<"; break; } needed += '0' + i; needed += ">"; } } DebugPrint("%d: AiRequestSupply: needed build %s with %s resource\n" _C_ AiPlayer->Player->Index _C_ cache[0].type->Name.c_str() _C_ needed.c_str()); #endif return true; }
/** ** Check if everything is fine, send new requests to resource manager. */ static void AiCheckUnits() { // Count the already made build requests. int counter[UnitTypeMax]; AiGetBuildRequestsCount(*AiPlayer, counter); // Remove non active units. const int unitCount = AiPlayer->Player->GetUnitCount(); for (int i = 0; i < unitCount; ++i) { const CUnit &unit = AiPlayer->Player->GetUnit(i); if (!unit.Active) { counter[unit.Type->Slot]--; } } const int *unit_types_count = AiPlayer->Player->UnitTypesCount; // Look if some unit-types are missing. int n = AiPlayer->UnitTypeRequests.size(); for (int i = 0; i < n; ++i) { const unsigned int t = AiPlayer->UnitTypeRequests[i].Type->Slot; const int x = AiPlayer->UnitTypeRequests[i].Count; // Add equivalent units int e = unit_types_count[t]; if (t < AiHelpers.Equiv.size()) { for (unsigned int j = 0; j < AiHelpers.Equiv[t].size(); ++j) { e += unit_types_count[AiHelpers.Equiv[t][j]->Slot]; } } const int requested = x - e - counter[t]; if (requested > 0) { // Request it. AiAddUnitTypeRequest(*AiPlayer->UnitTypeRequests[i].Type, requested); counter[t] += requested; } counter[t] -= x; } AiPlayer->Force.CheckUnits(counter); // Look if some upgrade-to are missing. n = AiPlayer->UpgradeToRequests.size(); for (int i = 0; i < n; ++i) { const unsigned int t = AiPlayer->UpgradeToRequests[i]->Slot; const int x = 1; // Add equivalent units int e = unit_types_count[t]; if (t < AiHelpers.Equiv.size()) { for (unsigned int j = 0; j < AiHelpers.Equiv[t].size(); ++j) { e += unit_types_count[AiHelpers.Equiv[t][j]->Slot]; } } const int requested = x - e - counter[t]; if (requested > 0) { // Request it. AiAddUpgradeToRequest(*AiPlayer->UpgradeToRequests[i]); counter[t] += requested; } counter[t] -= x; } // Look if some researches are missing. n = (int)AiPlayer->ResearchRequests.size(); for (int i = 0; i < n; ++i) { if (UpgradeIdAllowed(*AiPlayer->Player, AiPlayer->ResearchRequests[i]->ID) == 'A') { AiAddResearchRequest(AiPlayer->ResearchRequests[i]); } } }
void AiNewDepotRequest(CUnit &worker) { /* DebugPrint("%d: Worker %d report: Resource [%d] too far from depot, returning time [%d].\n" _C_ worker->Player->Index _C_ worker->Slot _C_ worker->CurrentResource _C_ worker->Data.Move.Cycles ); */ Vec2i pos = {-1, -1}; ResourceInfo *resinfo = worker.Type->ResInfo[worker.CurrentResource]; if (resinfo->TerrainHarvester) { pos = worker.CurrentOrder()->Arg1.Resource.Pos; } else { CUnit *mine = worker.CurrentOrder()->Arg1.Resource.Mine; if (mine) { pos = mine->tilePos; } } if (pos.x != -1 && NULL != FindDepositNearLoc(worker.Player, pos.x, pos.y, 10, worker.CurrentResource)) { /* * New Depot has just be finished and worker just return to old depot * (far away) from new Deopt. */ return; } CUnitType *best_type = NULL; int best_cost = 0; //int best_mask = 0; // Count the already made build requests. int counter[UnitTypeMax]; AiGetBuildRequestsCount(worker.Player->Ai, counter); const int n = AiHelpers.Depots[worker.CurrentResource - 1].size(); for (int i = 0; i < n; ++i) { CUnitType &type = *AiHelpers.Depots[worker.CurrentResource - 1][i]; if (counter[type.Slot]) { // Already ordered. return; } if (!AiRequestedTypeAllowed(worker.Player, type)) { continue; } // Check if resources available. //int needmask = AiCheckUnitTypeCosts(type); int cost = 0; for (int c = 1; c < MaxCosts; ++c) { cost += type.Stats[worker.Player->Index].Costs[c]; } if (best_type == NULL || (cost < best_cost)) { best_type = &type; best_cost = cost; //best_mask = needmask; } } if (best_type) { //if(!best_mask) { AiBuildQueue queue; queue.Type = best_type; queue.Want = 1; queue.Made = 0; queue.X = pos.x; queue.Y = pos.y; worker.Player->Ai->UnitTypeBuilt.push_back(queue); DebugPrint("%d: Worker %d report: Requesting new depot near [%d,%d].\n" _C_ worker.Player->Index _C_ worker.Slot _C_ queue.X _C_ queue.Y ); /* } else { AiPlayer->NeededMask |= best_mask; } */ } }
void AiNewDepotRequest(CUnit &worker) { #if 0 DebugPrint("%d: Worker %d report: Resource [%d] too far from depot, returning time [%d].\n" _C_ worker->Player->Index _C_ worker->Slot _C_ worker->CurrentResource _C_ worker->Data.Move.Cycles); #endif Assert(worker.CurrentAction() == UnitActionResource); COrder_Resource &order = *static_cast<COrder_Resource *>(worker.CurrentOrder()); const Vec2i pos = order.GetHarvestLocation(); if (pos.x != -1 && NULL != FindDepositNearLoc(*worker.Player, pos, 10, worker.CurrentResource)) { /* * New Depot has just be finished and worker just return to old depot * (far away) from new Deopt. */ return; } CUnitType *best_type = NULL; int best_cost = 0; //int best_mask = 0; // Count the already made build requests. int counter[UnitTypeMax]; AiGetBuildRequestsCount(*worker.Player->Ai, counter); const int n = AiHelpers.Depots[worker.CurrentResource - 1].size(); for (int i = 0; i < n; ++i) { CUnitType &type = *AiHelpers.Depots[worker.CurrentResource - 1][i]; if (counter[type.Slot]) { // Already ordered. return; } if (!AiRequestedTypeAllowed(*worker.Player, type)) { continue; } // Check if resources available. //int needmask = AiCheckUnitTypeCosts(type); int cost = 0; for (int c = 1; c < MaxCosts; ++c) { cost += type.Stats[worker.Player->Index].Costs[c]; } if (best_type == NULL || (cost < best_cost)) { best_type = &type; best_cost = cost; //best_mask = needmask; } } if (best_type) { //if(!best_mask) { AiBuildQueue queue; queue.Type = best_type; queue.Want = 1; queue.Made = 0; queue.Pos = pos; worker.Player->Ai->UnitTypeBuilt.push_back(queue); DebugPrint("%d: Worker %d report: Requesting new depot near [%d,%d].\n" _C_ worker.Player->Index _C_ UnitNumber(worker) _C_ queue.Pos.x _C_ queue.Pos.y); /* } else { AiPlayer->NeededMask |= best_mask; } */ } }