sources » HouseClass » GenerateAIBuildPlan
/*
* This generates the basic AI base building plan for the future. It does not deal with base rebuilding, defenses, walls
* Invoked when:
* * receives a building with ConstructionYard=yes or a vehicle which deploys into that**
* * a player disconnects from an MP game and an AI takes over (when does that happen?!)
* * a map action #30 "Toggle Auto Base Building" fires**
*
* ** only if the house doesn't have a base plan yet
*/
void HouseClass::GenerateAIBuildPlan() {
unsigned int idxSide = this->Country->Side; // 0 - allied
// Base stores BaseNodes , each BaseNode represents a building it will build
// in SP maps, houses can fill this in the house's ini section
this->Base->Nodes.Clear();
// simply returns the index of this country in [Countries], so this is a bitfield with just n'th bit set
unsigned int ownerBits = 1 << this->Country->ParentCountry->FindIndexOfName();
DynamicVectorClass<BuildingTypeClass *> vec_CanBuildTypes;
DynamicVectorClass<bool> vec_Booleans;
foreach(vec_BuildingTypes as Bld) {
if(!(ownerBits & Bld->Owner)
|| (Bld->AIBasePlanningSide != this->Country->Side && Bld->AIBasePlanningSide != -1)
|| !Bld->AIBuildThis
|| Bld->TechLevel > this->TechLevel
|| Bld->RequiredHouses != -1 && !(Bld->RequiredHouses & ownerBits)
|| Bld->ForbiddenHouses != -1 && (Bld->ForbiddenHouses & ownerBits)
) {
continue;
}
if(!GameSettings->Superweapons && Bld->Superweapon != -1) {
if(!Rules->BuildTech.Contains(Bld) && !vec_SuperWeaponTypes[Bld->Superweapon]->Type->DisableableFromShell) {
continue;
}
}
vec_CanBuildTypes.Append(Bld);
vec_Booleans.Append(0);
}
DynamicVectorClass<BuildingTypeClass *> vec_PlanToBuildTypes;
BuildingTypeClass *obj = this->FindFirstBuildableEntry(Rules->BuildConst);
int idxOf = vec_CanBuildTypes.FindIndexOf(obj);
if(idxOf != -1) {
vec_Booleans[idxOf] = 1;
vec_PlanToBuildTypes.Append(obj);
}
obj = this->FindFirstBuildableEntry(Rules->BuildPower);
idxOf = vec_CanBuildTypes.FindIndexOf(obj);
if(idxOf != -1) {
vec_Booleans[idxOf] = 1;
vec_PlanToBuildTypes.Append(obj);
}
obj = this->FindFirstBuildableEntry(Rules->BuildBarracks);
idxOf = vec_CanBuildTypes.FindIndexOf(obj);
if(idxOf != -1) {
BuildingTypeClass *tmp = vec_CanBuildTypes[0];
vec_CanBuildTypes[0] = obj;
vec_CanBuildTypes[idxOf] = tmp;
vec_Booleans[idxOf] = vec_Booleans[0];
vec_Booleans[0] = 0;
}
obj = this->FindFirstBuildableEntry(Rules->BuildWeapons);
idxOf = vec_CanBuildTypes.FindIndexOf(obj);
if(idxOf != -1) {
BuildingTypeClass *tmp = vec_CanBuildTypes[1];
vec_CanBuildTypes[1] = obj;
vec_CanBuildTypes[idxOf] = tmp;
vec_Booleans[idxOf] = vec_Booleans[1];
vec_Booleans[1] = 0;
}
int remainingTypes = vec_CanBuildTypes.Length - 1;
while(remainingTypes > 0) {
int idxGAPLUG = -1;
bool foundSomething = 0;
for(int j = 0; j < vec_CanBuildTypes.Length; ++j) {
if(vec_Booleans[j]) {
continue;
}
BuildingTypeClass *curType = vec_CanBuildTypes[j];
if("GAPLUG".equals(curType->ID)) {
idxGAPLUG = i;
} else {
if(this->CanBuildItemGivenThesePrereqs(curType, vec_PlanToBuildTypes)) {
vec_Booleans[j] = 1;
vec_PlanToBuildTypes.Append(curType);
foundSomething = 1;
--remainingTypes;
}
}
}
if(!foundSomething && idxGAPLUG != -1) {
vec_PlanToBuildTypes.Append(vec_CanBuildTypes[idxGAPLUG]);
vec_Booleans[idxGAPLUG] = 1;
--remainingTypes;
}
}
UnitTypeClass *harv = NULL;
foreach(Rules->HarvesterUnit as curHarv) {
if(curHarv->Owner & houseBits) {
harv = curHarv;
break;
}
}
int countExtraRefineries;
if(harv) {
countExtraRefineries = Rules->AIExtraRefineries[this->AIDifficulty];
} else {
countExtraRefineries = Rules->AISlaveMinerNumber[this->AIDifficulty];
}
BuildingTypeClass *ref = this->FindFirstBuildableEntry(Rules->BuildRefinery);
if(vec_PlanToBuildTypes.FindIndexOf(ref) != -1) {
while(countExtraRefineries--) {
int idxRand = RandomRanged(0, vec_PlanToBuildTypes.Length - 1);
vec_PlanToBuildTypes.InsertAtPosition(idxRand, ref);
}
}
DynamicVectorClass<BuildingTypeClass *> vec_FinalTypes;
vec_FinalTypes.Append(vec_PlanToBuildTypes[0]);
vec_FinalTypes.Append(vec_PlanToBuildTypes[1]);
vec_FinalTypes.Append(vec_PlanToBuildTypes[2]);
for(int j = 3; j < vec_PlanToBuildTypes.Length; ++j) {
vec_FinalTypes.Append(vec_PlanToBuildTypes[j]);
}
int countBaseDefenses = 0;
switch(this->Country->Side) {
case 0:
countBaseDefenses = Rules->AlliedBaseDefenseCounts[this->AIDifficulty];
break;
case 1:
countBaseDefenses = Rules->SovietBaseDefenseCounts[this->AIDifficulty];
break;
case 2:
countBaseDefenses = Rules->ThirdBaseDefenseCounts[this->AIDifficulty];
break;
}
for(int j = 0; j < countBaseDefenses; ++j) {
int idxRand = RandomRanged(3, vec_FinalTypes.Length - 1);
vec_FinalTypes.InsertAtPosition(idxRand, -1); // special case hack, stands for buildings from PrerequisitePower
}
for(int k = 0; k < vec_FinalTypes.Length; ++k) {
BuildingTypeClass *curType = vec_FinalTypes[k];
/*
struct BaseNode {
int BuildingTypeIndex;
CoordStruct Position;
bool unknown1;
int unknown2;
}
*/
BaseNode *newNode = new BaseNode();
newNode->unknown1 = 0;
newNode->unknown2 = 0;
if((signed int)curType >= 0 || (signed int)curType < -4) {
newNode->BuildingTypeIndex = curType->IndexInArray;
newNode->Position = {0, 0};
this->Base->Nodes.Append(newNode);
} else {
BaseNode *newNode = new BaseNode();
newNode->BuildingTypeIndex = curType;
newNode->Position = {0, 0};
this->Base->Nodes.Append(newNode);
}
}
}