📄 aaiexecute.cpp
字号:
{
if(ai->activeScouts < 2)
{
buildque->insert(buildque->begin(), number, def_id);
return true;
}
else
{
/*// insert after the last builder
for(list<int>::iterator unit = buildque->begin(); unit != buildque->end(); ++unit)
{
if(!bt->IsBuilder(*unit))
{
buildque->insert(unit, number, def_id);
return true;
}
}*/
buildque->insert(buildque->begin(), number, def_id);
return true;
}
}
else if(buildque->size() < cfg->MAX_BUILDQUE_SIZE)
{
if(urgent)
buildque->insert(buildque->begin(), number, def_id);
else
buildque->insert(buildque->end(), number, def_id);
//fprintf(ai->file, "Added %s to buildque with length %i\n", bt->unitList[def_id-1]->humanName.c_str(), buildque->size());
return true;
}
}
//else
// fprintf(ai->file, "Could not find builque for %s\n", bt->unitList[def_id-1]->humanName.c_str());
return false;
}
void AAIExecute::InitBuildques()
{
// determine number of factories first
numOfFactories = 0;
// stationary factories
for(list<int>::iterator cons = bt->units_of_category[STATIONARY_CONSTRUCTOR][ai->side-1].begin(); cons != bt->units_of_category[STATIONARY_CONSTRUCTOR][ai->side-1].end(); ++cons)
{
if(bt->units_static[*cons].unit_type & UNIT_TYPE_FACTORY)
++numOfFactories;
}
// and look for all mobile factories
for(list<int>::iterator cons = bt->units_of_category[MOBILE_CONSTRUCTOR][ai->side-1].begin(); cons != bt->units_of_category[MOBILE_CONSTRUCTOR][ai->side-1].end(); ++cons)
{
if(bt->units_static[*cons].unit_type & UNIT_TYPE_FACTORY)
++numOfFactories;
}
// and add com
for(list<int>::iterator cons = bt->units_of_category[COMMANDER][ai->side-1].begin(); cons != bt->units_of_category[COMMANDER][ai->side-1].end(); ++cons)
{
if(bt->units_static[*cons].unit_type & UNIT_TYPE_FACTORY)
++numOfFactories;
}
// buildques = new list<int>[numOfFactories];
buildques.resize(numOfFactories);
// set up factory buildque identification
// factory_table = new int[numOfFactories];
factory_table.resize(numOfFactories);
int i = 0;
for(list<int>::iterator cons = bt->units_of_category[STATIONARY_CONSTRUCTOR][ai->side-1].begin(); cons != bt->units_of_category[STATIONARY_CONSTRUCTOR][ai->side-1].end(); ++cons)
{
if(bt->units_static[*cons].unit_type & UNIT_TYPE_FACTORY)
{
factory_table[i] = *cons;
++i;
}
}
for(list<int>::iterator cons = bt->units_of_category[MOBILE_CONSTRUCTOR][ai->side-1].begin(); cons != bt->units_of_category[MOBILE_CONSTRUCTOR][ai->side-1].end(); ++cons)
{
if(bt->units_static[*cons].unit_type & UNIT_TYPE_FACTORY)
{
factory_table[i] = *cons;
++i;
}
}
for(list<int>::iterator cons = bt->units_of_category[COMMANDER][ai->side-1].begin(); cons != bt->units_of_category[COMMANDER][ai->side-1].end(); ++cons)
{
if(bt->units_static[*cons].unit_type & UNIT_TYPE_FACTORY)
{
factory_table[i] = *cons;
++i;
}
}
}
float3 AAIExecute::GetRallyPoint(UnitCategory category, int min_dist, int max_dist, int random)
{
AAISector* best_sector = 0;
float best_rating = 0, my_rating;
int combat_cat = bt->GetIDOfAssaultCategory(category);
bool land = true;
bool water = true;
if(!cfg->AIR_ONLY_MOD)
{
if(category == GROUND_ASSAULT)
water = false;
else if(category == SEA_ASSAULT || category == SUBMARINE_ASSAULT)
land = false;
}
// check neighbouring sectors
for(int i = min_dist; i <= max_dist; ++i)
{
for(list<AAISector*>::iterator sector = brain->sectors[i].begin(); sector != brain->sectors[i].end(); sector++)
{
my_rating = 24.0f / ((*sector)->mobile_combat_power[combat_cat] + 4.0f) + 2 * (*sector)->GetMapBorderDist();
if(land)
my_rating += 8 * pow((*sector)->flat_ratio, 2);
if(water)
my_rating += 8 * pow((*sector)->water_ratio, 2);
my_rating += 0.25 * (rand()%random);
my_rating /= sqrt(10.0f + (*sector)->allied_structures);
if(my_rating > best_rating)
{
best_rating = my_rating;
best_sector = *sector;
}
}
}
if(best_sector)
return best_sector->GetCenter();
else
return ZeroVector;
}
float3 AAIExecute::GetRallyPointCloseTo(UnitCategory category, float3 pos, int min_dist, int max_dist)
{
AAISector* best_sector = 0;
float best_rating = 0, my_rating;
float3 center;
int combat_cat = bt->GetIDOfAssaultCategory(category);
bool land = true;
bool water = true;
if(!cfg->AIR_ONLY_MOD)
{
if(category == GROUND_ASSAULT)
water = false;
else if(category == SEA_ASSAULT || category == SUBMARINE_ASSAULT)
land = false;
}
// check neighbouring sectors
for(int i = min_dist; i <= max_dist; i++)
{
for(list<AAISector*>::iterator sector = brain->sectors[i].begin(); sector != brain->sectors[i].end(); sector++)
{
my_rating = 24.0f / ((*sector)->mobile_combat_power[combat_cat] + 4.0f);
if(land)
my_rating += 8 * pow((*sector)->flat_ratio, 2.0f);
if(water)
my_rating += 8 * pow((*sector)->water_ratio, 2.0f);
center = (*sector)->GetCenter();
my_rating /= sqrt( sqrt( pow( pos.x - center.x , 2.0f) + pow( pos.z - center.z , 2.0f) ) );
if(my_rating > best_rating)
{
best_rating = my_rating;
best_sector = *sector;
}
}
}
if(best_sector)
return best_sector->GetCenter();
else
return ZeroVector;
}
// ****************************************************************************************************
// all building functions
// ****************************************************************************************************
bool AAIExecute::BuildExtractor()
{
if(ai->activeFactories < 1 && ai->activeUnits[EXTRACTOR] >= 2)
return true;
AAIConstructor *builder;
AAIMetalSpot *spot = 0;
float3 pos;
int land_mex;
int water_mex;
bool water;
float cost = 0.25f + brain->Affordable() / 6.0f;
float efficiency = 6.0 / (cost + 0.75f);
// check if metal map
if(ai->map->metalMap)
{
// get id of an extractor and look for suitable builder
land_mex = bt->GetMex(ai->side, cost, efficiency, false, false, false);
if(land_mex && bt->units_dynamic[land_mex].buildersAvailable <= 0)
{
bt->BuildBuilderFor(land_mex);
land_mex = bt->GetMex(ai->side, cost, efficiency, false, false, true);
}
builder = ut->FindBuilder(land_mex, true, 10);
if(builder)
{
pos = GetBuildsite(builder->unit_id, land_mex, EXTRACTOR);
if(pos.x != 0)
{
builder->GiveConstructionOrder(land_mex, pos, false);
}
return true;
}
else
{
bt->AddBuilder(land_mex);
return false;
}
}
else // normal map
{
// different behaviour dependent on number of builders (to save time in late game)
if(ut->constructors.size() < 5)
{
// get id of an extractor and look for suitable builder
land_mex = bt->GetMex(ai->side, cost, efficiency, false, false, false);
if(land_mex && bt->units_dynamic[land_mex].buildersAvailable <= 0)
{
bt->BuildBuilderFor(land_mex);
land_mex = bt->GetMex(ai->side, cost, efficiency, false, false, true);
}
water_mex = bt->GetMex(ai->side, cost, efficiency, false, true, false);
if(water_mex && bt->units_dynamic[water_mex].buildersAvailable <= 0)
{
bt->BuildBuilderFor(water_mex);
water_mex = bt->GetMex(ai->side, cost, efficiency, false, true, true);
}
// find metal spot with lowest distance to available builders
spot = FindMetalSpotClosestToBuilder(land_mex, water_mex);
if(spot)
{
// check if land or sea spot
if(cb->GetElevation(spot->pos.x, spot->pos.z) < 0)
{
water = true;
// build the water mex instead of land mex
land_mex = water_mex;
}
else
water = false;
// look for suitable builder
int x = spot->pos.x/map->xSectorSize;
int y = spot->pos.z/map->ySectorSize;
// only allow commander if spot is close to own base
if(map->sector[x][y].distance_to_base <= 0 || (brain->sectors[0].size() < 3 && map->sector[x][y].distance_to_base <= 1) )
builder = ut->FindClosestBuilder(land_mex, spot->pos, true, 10);
else
builder = ut->FindClosestBuilder(land_mex, spot->pos, false, 10);
if(builder)
{
builder->GiveConstructionOrder(land_mex, spot->pos, water);
spot->occupied = true;
}
else
{
bt->AddBuilder(land_mex);
return false;
}
}
else
{
// request metal makers if no spot found (only if spot was not found due to no buidlers available)
builder = ut->FindClosestBuilder(land_mex, brain->base_center, true, 10);
if(!builder)
builder = ut->FindClosestBuilder(water_mex, brain->base_center, true, 10);
if(!builder)
{
if(map->mapType == WATER_MAP && !cfg->AIR_ONLY_MOD)
bt->AddBuilder(water_mex);
else
bt->AddBuilder(land_mex);
return false;
}
else
{
if(ai->activeUnits[METAL_MAKER] < cfg->MAX_METAL_MAKERS && urgency[METAL_MAKER] <= GetMetalUrgency() / 2.0f)
urgency[METAL_MAKER] = GetMetalUrgency() / 2.0f;
}
}
}
else
{
bool land = true, water = true;
// get next free metal spot
AAIMetalSpot *spot = FindMetalSpot(land, water);
if(spot)
{
int x = spot->pos.x/map->xSectorSize;
int y = spot->pos.z/map->ySectorSize;
if(cb->GetElevation(spot->pos.x, spot->pos.z) > 0)
water = false;
else
water = true;
// choose mex dependend on safety
bool armed = false;
//if(map->sector[x][y].lost_units[EXTRACTOR-COMMANDER] > 0.01f || map->sector[x][y].distance_to_base > 2)
if(map->sector[x][y].distance_to_base > 2)
{
cost = 6.0f;
armed = true;
efficiency = 1.0f;
// check mex upgrade
if(ai->futureUnits[EXTRACTOR] < 2)
CheckMexUpgrade();
}
int mex = bt->GetMex(ai->side, cost, efficiency, armed, water, false);
if(mex && bt->units_dynamic[mex].buildersAvailable <= 0)
{
bt->BuildBuilderFor(mex);
mex = bt->GetMex(ai->side, cost, efficiency, armed, water, true);
}
if(mex)
{
if(map->sector[x][y].distance_to_base <= 0 || (brain->sectors[0].size() < 3 && map->sector[x][y].distance_to_base <= 1) )
builder = ut->FindClosestBuilder(mex, brain->base_center, true, 10);
else
builder = ut->FindClosestBuilder(mex, brain->base_center, false, 10);
if(builder)
{
builder->GiveConstructionOrder(mex, spot->pos, water);
spot->occupied = true;
}
}
}
else
{
// check mex upgrade
if(ai->futureUnits[EXTRACTOR] < 2)
CheckMexUpgrade();
// request metal makers if no spot found
if(ai->activeUnits[METAL_MAKER] < cfg->MAX_METAL_MAKERS && urgency[METAL_MAKER] <= GetMetalUrgency() / 2.0f)
urgency[METAL_MAKER] = GetMetalUrgency() / 2.0f;
}
}
}
return true;
}
bool AAIExecute::BuildPowerPlant()
{
if(ai->futureUnits[POWER_PLANT] > 1)
return true;
else if(ai->futureUnits[POWER_PLANT] > 0)
{
// try to assist construction of other power plants first
AAIConstructor *builder;
for(list<AAIBuildTask*>::iterator task = ai->build_tasks.begin(); task != ai->build_tasks.end(); ++task)
{
if((*task)->builder_id >= 0)
builder = ut->units[(*task)->builder_id].cons;
else
builder = 0;
// find the power plant that is already under construction
if(builder && builder->construction_category == POWER_PLANT)
{
// dont build further power plants if already buidling an expensive plant
if(bt->units_static[builder->construction_def_id].cost > bt->avg_cost[POWER_PLANT][ai->side-1])
return true;
// try to assist
if(builder->assistants.size() < cfg->MAX_ASSISTANTS)
{
AAIConstructor *assistant;
if(bt->unitList[builder->construction_def_id-1]->minWaterDepth > 0)
{
if(bt->unitList[builder->construction_def_id-1]->floater)
assistant = ut->FindClosestAssister(builder->build_pos, 5, true, true, true);
else
assistant = ut->FindClosestAssister(builder->build_pos, 5, true, true, false);
}
else
assistant = ut->FindClosestAssister(builder->build_pos, 5, true, false, false);
if(assistant)
{
builder->assistants.insert(assistant->unit_id);
assistant->AssistConstruction(builder->unit_id, (*task)->unit_id);
return true;
}
else
return false;
}
}
}
// power plant construction has not started -> builder is still on its way to constrcution site, wait until starting a new power plant
return false;
}
else if(ai->activeFactories < 1 && ai->activeUnits[POWER_PLANT] >= 2)
return true;
// stop building power plants if already to much available energy
if(cb->GetEnergyIncome() > 1.5f * cb->GetEnergyUsage() + 200.0)
return true;
int ground_plant = 0;
int water_plant = 0;
AAIConstructor *builder;
float3 pos;
float current_energy = cb->GetEnergyIncome();
bool checkWater, checkGround;
float urgency;
float max_power;
float eff;
float energy = cb->GetEnergyIncome()+1;
// check if already one power_plant under construction and energy short
if(ai->futureUnits[POWER_PLANT] > 0 && ai->activeUnits[POWER_PLANT] > 9 && averageEnergySurplus < 100)
{
urgency = 0.4f + GetEnergyUrgency();
max_power = 0.5f;
eff = 2.2f - brain->Affordable() / 4.0f;
}
else
{
max_power = 0.5f + pow((float) ai->activeUnits[POWER_PLANT], 0.8f);
eff = 0.5 + 1.0f / (brain->Affordable() + 0.5f);
urgency = 0.5f + GetEnergyUrgency();
}
// sort sectors according to threat level
learned = 70000.0 / (cb->GetCurrentFrame() + 35000) + 1;
current = 2.5 - learned;
if(ai->activeUnits[POWER_PLANT] >= 2)
brain->sectors[0].sort(suitable_for_power_plant);
// get water and ground plant
ground_plant = bt->GetPowerPlant(ai->side, eff, urgency, max_power, energy, false, false, false);
// currently aai cannot build this building
if(ground_plant && bt->units_dynamic[ground_plant].buildersAvailable <= 0)
{
if( bt->units_dynamic[water_plant].buildersRequested <= 0)
bt->AddBuilder(ground_plant);
ground_plant = bt->GetPowerPlant(ai->side, eff, urgency, max_power, energy, false, false, true);
}
⌨️ 快捷键说明
复制代码
Ctrl + C
搜索代码
Ctrl + F
全屏模式
F11
切换主题
Ctrl + Shift + D
显示快捷键
?
增大字号
Ctrl + =
减小字号
Ctrl + -