- bugfix AI, no longer try to build a farm type unit if the faction does not have a unit that is able to build it yet

- new optional feature added to tell each faction some basic info regarding which units should take priority when building,producing and morphing
This commit is contained in:
Mark Vejvoda 2011-10-04 06:49:44 +00:00
parent 22e28c323f
commit 8729c32b68
5 changed files with 220 additions and 17 deletions

View File

@ -536,11 +536,14 @@ bool AiRuleBuildOneFarm::test(){
const Resource *r= producedType->getCost(k);
//find a food producer in the farm produced units
if(r->getAmount()<0 && r->getType()->getClass()==rcConsumable && ai->getCountOfType(ut)==0){
farm= ut;
if(r->getAmount() < 0 && r->getType()->getClass() == rcConsumable && ai->getCountOfType(ut) == 0) {
if(aiInterface->reqsOk(ct) && aiInterface->getMyFaction()->canCreateUnit(ut, true, true, true) == true) {
farm= ut;
//printf("AiRuleBuildOneFarm returning true, RULE Name[%s] ut [%s] producedType [%s]\n",this->getName().c_str(),ut->getName().c_str(),producedType->getName().c_str());
if(ai->outputAIBehaviourToConsole()) printf("AiRuleBuildOneFarm returning true, RULE Name[%s]\n",this->getName().c_str());
return true;
if(ai->outputAIBehaviourToConsole()) printf("AiRuleBuildOneFarm returning true, RULE Name[%s]\n",this->getName().c_str());
return true;
}
}
}
}
@ -652,21 +655,67 @@ void AiRuleProduce::execute(){
}
}
void AiRuleProduce::produceGeneric(const ProduceTask *pt){
void AiRuleProduce::produceGeneric(const ProduceTask *pt) {
typedef vector<const UnitType*> UnitTypes;
UnitTypes ableUnits;
AiInterface *aiInterface= ai->getAiInterface();
if(pt->getResourceType() != NULL) {
if(aiInterface->getMyFactionType()->getAIBehaviorUnits(aibcResourceProducerUnits).size() > 0) {
const std::vector<FactionType::PairPUnitTypeInt> &unitList = aiInterface->getMyFactionType()->getAIBehaviorUnits(aibcResourceProducerUnits);
for(unsigned int i = 0; i < unitList.size(); ++i) {
const FactionType::PairPUnitTypeInt &priorityUnit = unitList[i];
if(ai->getCountOfType(priorityUnit.first) < priorityUnit.second &&
aiInterface->getMyFaction()->canCreateUnit(priorityUnit.first, false, true, true) == true) {
//if(ai->getRandom()->randRange(0, 1)==0) {
ai->addTask(new ProduceTask(priorityUnit.first));
return;
//}
}
}
}
}
else if(pt->getUnitClass() == ucWorker) {
if(aiInterface->getMyFactionType()->getAIBehaviorUnits(aibcWorkerUnits).size() > 0) {
const std::vector<FactionType::PairPUnitTypeInt> &unitList = aiInterface->getMyFactionType()->getAIBehaviorUnits(aibcWorkerUnits);
for(unsigned int i = 0; i < unitList.size(); ++i) {
const FactionType::PairPUnitTypeInt &priorityUnit = unitList[i];
if(ai->getCountOfType(priorityUnit.first) < priorityUnit.second &&
aiInterface->getMyFaction()->canCreateUnit(priorityUnit.first, false, true, true) == true) {
//if(ai->getRandom()->randRange(0, 1)==0) {
ai->addTask(new ProduceTask(priorityUnit.first));
return;
//}
}
}
}
}
else if(pt->getUnitClass() == ucWarrior) {
if(aiInterface->getMyFactionType()->getAIBehaviorUnits(aibcWarriorUnits).size() > 0) {
const std::vector<FactionType::PairPUnitTypeInt> &unitList = aiInterface->getMyFactionType()->getAIBehaviorUnits(aibcWarriorUnits);
for(unsigned int i = 0; i < unitList.size(); ++i) {
const FactionType::PairPUnitTypeInt &priorityUnit = unitList[i];
if(ai->getCountOfType(priorityUnit.first) < priorityUnit.second &&
aiInterface->getMyFaction()->canCreateUnit(priorityUnit.first, false, true, true) == true) {
//if(ai->getRandom()->randRange(0, 1)==0) {
ai->addTask(new ProduceTask(priorityUnit.first));
return;
//}
}
}
}
}
//for each unit, produce it if possible
for(int i=0; i<aiInterface->getMyUnitCount(); ++i){
for(int i = 0; i < aiInterface->getMyUnitCount(); ++i) {
//for each command
const UnitType *ut= aiInterface->getMyUnit(i)->getType();
for(int j=0; j<ut->getCommandTypeCount(); ++j){
for(int j = 0; j < ut->getCommandTypeCount(); ++j) {
const CommandType *ct= ut->getCommandType(j);
//if the command is produce
if(ct->getClass()==ccProduce || ct->getClass()==ccMorph){
if(ct->getClass() == ccProduce || ct->getClass()==ccMorph) {
const UnitType *producedUnit= static_cast<const UnitType*>(ct->getProduced());
bool produceIt= false;
@ -674,19 +723,19 @@ void AiRuleProduce::produceGeneric(const ProduceTask *pt){
if(ai->outputAIBehaviourToConsole()) printf("produceGeneric [%p] Testing AI RULE Name[%s]\n",pt->getResourceType(), this->getName().c_str());
//if the unit produces the resource
if(pt->getResourceType()!=NULL){
if(pt->getResourceType() != NULL) {
const Resource *r= producedUnit->getCost(pt->getResourceType());
if(r != NULL) {
if(ai->outputAIBehaviourToConsole()) printf("produceGeneric r = [%s][%d] Testing AI RULE Name[%s]\n",r->getDescription().c_str(),r->getAmount(), this->getName().c_str());
}
if(r!=NULL && r->getAmount()<0){
if(r != NULL && r->getAmount() < 0) {
produceIt= true;
}
}
else{
else {
//if the unit is from the right class
if(ai->outputAIBehaviourToConsole()) printf("produceGeneric right class = [%d] Testing AI RULE Name[%s]\n",producedUnit->isOfClass(pt->getUnitClass()), this->getName().c_str());
@ -697,7 +746,7 @@ void AiRuleProduce::produceGeneric(const ProduceTask *pt){
}
}
if(produceIt){
if(produceIt) {
//if the unit is not already on the list
if(find(ableUnits.begin(), ableUnits.end(), producedUnit)==ableUnits.end()){
ableUnits.push_back(producedUnit);
@ -708,13 +757,13 @@ void AiRuleProduce::produceGeneric(const ProduceTask *pt){
}
//add specific produce task
if(!ableUnits.empty()){
if(ableUnits.empty() == false) {
if(ai->outputAIBehaviourToConsole()) printf("produceGeneric !ableUnits.empty(), ableUnits.size() = [%d] Testing AI RULE Name[%s]\n",(int)ableUnits.size(), this->getName().c_str());
//priority for non produced units
for(unsigned int i=0; i<ableUnits.size(); ++i){
if(ai->getCountOfType(ableUnits[i])==0){
for(unsigned int i=0; i < ableUnits.size(); ++i) {
if(ai->getCountOfType(ableUnits[i]) == 0) {
if(ai->getRandom()->randRange(0, 1)==0){
ai->addTask(new ProduceTask(ableUnits[i]));
return;
@ -1023,13 +1072,44 @@ void AiRuleBuild::execute() {
}
}
void AiRuleBuild::buildGeneric(const BuildTask *bt){
void AiRuleBuild::buildGeneric(const BuildTask *bt) {
//find buildings that can be built
AiInterface *aiInterface= ai->getAiInterface();
typedef vector<const UnitType*> UnitTypes;
UnitTypes buildings;
if(bt->getResourceType() != NULL) {
if(aiInterface->getMyFactionType()->getAIBehaviorUnits(aibcResourceProducerUnits).size() > 0) {
const std::vector<FactionType::PairPUnitTypeInt> &unitList = aiInterface->getMyFactionType()->getAIBehaviorUnits(aibcResourceProducerUnits);
for(unsigned int i = 0; i < unitList.size(); ++i) {
const FactionType::PairPUnitTypeInt &priorityUnit = unitList[i];
if(ai->getCountOfType(priorityUnit.first) < priorityUnit.second &&
aiInterface->getMyFaction()->canCreateUnit(priorityUnit.first, true, false, false) == true) {
//if(ai->getRandom()->randRange(0, 1)==0) {
ai->addTask(new BuildTask(priorityUnit.first));
return;
//}
}
}
}
}
else {
if(aiInterface->getMyFactionType()->getAIBehaviorUnits(aibcBuildingUnits).size() > 0) {
const std::vector<FactionType::PairPUnitTypeInt> &unitList = aiInterface->getMyFactionType()->getAIBehaviorUnits(aibcBuildingUnits);
for(unsigned int i = 0; i < unitList.size(); ++i) {
const FactionType::PairPUnitTypeInt &priorityUnit = unitList[i];
if(ai->getCountOfType(priorityUnit.first) < priorityUnit.second &&
aiInterface->getMyFaction()->canCreateUnit(priorityUnit.first, true, false, false) == true) {
//if(ai->getRandom()->randRange(0, 1)==0) {
ai->addTask(new BuildTask(priorityUnit.first));
return;
//}
}
}
}
}
//for each unit
for(int i=0; i<aiInterface->getMyUnitCount(); ++i){

View File

@ -1588,6 +1588,62 @@ void Faction::setSwitchTeamVote(SwitchTeamVote &vote) {
switchTeamVotes[vote.factionIndex] = vote;
}
bool Faction::canCreateUnit(const UnitType *ut, bool checkBuild, bool checkProduce, bool checkMorph) const {
// Now check that at least 1 other unit can produce, build or morph this unit
bool foundUnit = false;
for(int l = 0; l < this->getUnitCount() && foundUnit == false; ++l) {
const UnitType *unitType2 = this->getUnit(l)->getType();
for(int j = 0; j < unitType2->getCommandTypeCount() && foundUnit == false; ++j) {
const CommandType *cmdType = unitType2->getCommandType(j);
if(cmdType != NULL) {
// Check if this is a produce command
if(checkProduce == true && cmdType->getClass() == ccProduce) {
const ProduceCommandType *produce = dynamic_cast<const ProduceCommandType *>(cmdType);
if(produce != NULL) {
const UnitType *produceUnit = produce->getProducedUnit();
if( produceUnit != NULL &&
ut->getId() != unitType2->getId() &&
ut->getName() == produceUnit->getName()) {
foundUnit = true;
break;
}
}
}
// Check if this is a build command
else if(checkBuild == true && cmdType->getClass() == ccBuild) {
const BuildCommandType *build = dynamic_cast<const BuildCommandType *>(cmdType);
for(int k = 0; k < build->getBuildingCount() && foundUnit == false; ++k) {
const UnitType *buildUnit = build->getBuilding(k);
if( buildUnit != NULL &&
ut->getId() != unitType2->getId() &&
ut->getName() == buildUnit->getName()) {
foundUnit = true;
break;
}
}
}
// Check if this is a morph command
else if(checkMorph == true && cmdType->getClass() == ccMorph) {
const MorphCommandType *morph = dynamic_cast<const MorphCommandType *>(cmdType);
const UnitType *morphUnit = morph->getMorphUnit();
if( morphUnit != NULL &&
ut->getId() != unitType2->getId() &&
ut->getName() == morphUnit->getName()) {
foundUnit = true;
break;
}
}
}
}
}
return foundUnit;
}
std::string Faction::toString() const {
std::string result = "";

View File

@ -248,6 +248,8 @@ public:
void sortUnitsByCommandGroups();
bool canCreateUnit(const UnitType *ut, bool checkBuild, bool checkProduce, bool checkMorph) const;
std::string toString() const;
private:

View File

@ -163,10 +163,63 @@ void FactionType::load(const string &dir, const TechTree *techTree, Checksum* ch
music->open(musicNode->getAttribute("path")->getRestrictedValue(currentPath));
loadedFileList[musicNode->getAttribute("path")->getRestrictedValue(currentPath)].push_back(make_pair(path,musicNode->getAttribute("path")->getRestrictedValue()));
}
//read ai behavior
if(factionNode->hasChild("ai-behavior") == true) {
const XmlNode *aiNode= factionNode->getChild("ai-behavior");
if(aiNode->hasChild("worker-units") == true) {
const XmlNode *aiNodeUnits= aiNode->getChild("worker-units");
for(int i = 0; i < aiNodeUnits->getChildCount(); ++i) {
const XmlNode *unitNode= aiNodeUnits->getChild("unit", i);
string name= unitNode->getAttribute("name")->getRestrictedValue();
int minimum= unitNode->getAttribute("minimum")->getIntValue();
mapAIBehaviorUnitCategories[aibcWorkerUnits].push_back(PairPUnitTypeInt(getUnitType(name), minimum));
}
}
if(aiNode->hasChild("warrior-units") == true) {
const XmlNode *aiNodeUnits= aiNode->getChild("warrior-units");
for(int i = 0; i < aiNodeUnits->getChildCount(); ++i) {
const XmlNode *unitNode= aiNodeUnits->getChild("unit", i);
string name= unitNode->getAttribute("name")->getRestrictedValue();
int minimum= unitNode->getAttribute("minimum")->getIntValue();
mapAIBehaviorUnitCategories[aibcWarriorUnits].push_back(PairPUnitTypeInt(getUnitType(name), minimum));
}
}
if(aiNode->hasChild("resource-producer-units") == true) {
const XmlNode *aiNodeUnits= aiNode->getChild("resource-producer-units");
for(int i = 0; i < aiNodeUnits->getChildCount(); ++i) {
const XmlNode *unitNode= aiNodeUnits->getChild("unit", i);
string name= unitNode->getAttribute("name")->getRestrictedValue();
int minimum= unitNode->getAttribute("minimum")->getIntValue();
mapAIBehaviorUnitCategories[aibcResourceProducerUnits].push_back(PairPUnitTypeInt(getUnitType(name), minimum));
}
}
if(aiNode->hasChild("building-units") == true) {
const XmlNode *aiNodeUnits= aiNode->getChild("building-units");
for(int i = 0; i < aiNodeUnits->getChildCount(); ++i) {
const XmlNode *unitNode= aiNodeUnits->getChild("unit", i);
string name= unitNode->getAttribute("name")->getRestrictedValue();
int minimum= unitNode->getAttribute("minimum")->getIntValue();
mapAIBehaviorUnitCategories[aibcBuildingUnits].push_back(PairPUnitTypeInt(getUnitType(name), minimum));
}
}
}
}
if(SystemFlags::getSystemSettingType(SystemFlags::debugSystem).enabled) SystemFlags::OutputDebug(SystemFlags::debugSystem,"In [%s::%s Line: %d]\n",__FILE__,__FUNCTION__,__LINE__);
}
const std::vector<FactionType::PairPUnitTypeInt> FactionType::getAIBehaviorUnits(AIBehaviorUnitCategory category) const {
std::map<AIBehaviorUnitCategory, std::vector<PairPUnitTypeInt> >::const_iterator iterFind = mapAIBehaviorUnitCategories.find(category);
if(iterFind != mapAIBehaviorUnitCategories.end()) {
return iterFind->second;
}
return std::vector<FactionType::PairPUnitTypeInt>();
}
FactionType::~FactionType(){
delete music;
music = NULL;

View File

@ -27,8 +27,16 @@ namespace Glest{ namespace Game{
/// Each of the possible factions the user can select
// =====================================================
enum AIBehaviorUnitCategory {
aibcWorkerUnits,
aibcWarriorUnits,
aibcResourceProducerUnits,
aibcBuildingUnits
};
class FactionType {
private:
public:
typedef pair<const UnitType*, int> PairPUnitTypeInt;
typedef vector<UnitType> UnitTypes;
typedef vector<UpgradeType> UpgradeTypes;
@ -44,6 +52,8 @@ private:
StrSound *music;
FactionPersonalityType personalityType;
std::map<AIBehaviorUnitCategory, std::vector<PairPUnitTypeInt> > mapAIBehaviorUnitCategories;
public:
//init
FactionType();
@ -51,6 +61,8 @@ public:
Checksum *techtreeChecksum, std::map<string,vector<pair<string, string> > > &loadedFileList);
~FactionType();
const std::vector<FactionType::PairPUnitTypeInt> getAIBehaviorUnits(AIBehaviorUnitCategory category) const;
//get
int getUnitTypeCount() const {return unitTypes.size();}
int getUpgradeTypeCount() const {return upgradeTypes.size();}