mirror of
https://github.com/glest/glest-source.git
synced 2025-02-24 19:52:25 +01:00
- more AI enhancements, now units that harvest AND attack will be more wise when choosing to attack, (think persian) since they need to harvest more than they need to attack when harvester count is very low.
- AI Units now place higher priority on repairing 'castle' style units when looking for something to repair.
This commit is contained in:
parent
d297a68b36
commit
c979ea1254
@ -202,22 +202,28 @@ int Ai::getCountOfType(const UnitType *ut){
|
|||||||
return count;
|
return count;
|
||||||
}
|
}
|
||||||
|
|
||||||
int Ai::getCountOfClass(UnitClass uc){
|
int Ai::getCountOfClass(UnitClass uc,UnitClass *additionalUnitClassToExcludeFromCount) {
|
||||||
int count= 0;
|
int count= 0;
|
||||||
for(int i=0; i<aiInterface->getMyUnitCount(); ++i){
|
for(int i = 0; i < aiInterface->getMyUnitCount(); ++i) {
|
||||||
if(aiInterface->getMyUnit(i)->getType()->isOfClass(uc)){
|
if(aiInterface->getMyUnit(i)->getType()->isOfClass(uc)) {
|
||||||
|
// Skip unit if it ALSO contains the exclusion unit class type
|
||||||
|
if(additionalUnitClassToExcludeFromCount != NULL) {
|
||||||
|
if(aiInterface->getMyUnit(i)->getType()->isOfClass(*additionalUnitClassToExcludeFromCount)) {
|
||||||
|
continue;
|
||||||
|
}
|
||||||
|
}
|
||||||
++count;
|
++count;
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
return count;
|
return count;
|
||||||
}
|
}
|
||||||
|
|
||||||
float Ai::getRatioOfClass(UnitClass uc){
|
float Ai::getRatioOfClass(UnitClass uc,UnitClass *additionalUnitClassToExcludeFromCount) {
|
||||||
if(aiInterface->getMyUnitCount()==0){
|
if(aiInterface->getMyUnitCount() == 0) {
|
||||||
return 0;
|
return 0;
|
||||||
}
|
}
|
||||||
else{
|
else {
|
||||||
return static_cast<float>(getCountOfClass(uc))/aiInterface->getMyUnitCount();
|
return static_cast<float>(getCountOfClass(uc,additionalUnitClassToExcludeFromCount)) / aiInterface->getMyUnitCount();
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
@ -272,9 +278,9 @@ bool Ai::beingAttacked(Vec2i &pos, Field &field, int radius){
|
|||||||
*/
|
*/
|
||||||
}
|
}
|
||||||
|
|
||||||
bool Ai::isStableBase(){
|
bool Ai::isStableBase() {
|
||||||
|
UnitClass ucWorkerType = ucWorker;
|
||||||
if(getCountOfClass(ucWarrior)>minWarriors){
|
if(getCountOfClass(ucWarrior,&ucWorkerType) > minWarriors) {
|
||||||
aiInterface->printLog(4, "Base is stable\n");
|
aiInterface->printLog(4, "Base is stable\n");
|
||||||
return true;
|
return true;
|
||||||
}
|
}
|
||||||
@ -436,10 +442,13 @@ void Ai::sendScoutPatrol(){
|
|||||||
}
|
}
|
||||||
|
|
||||||
void Ai::massiveAttack(const Vec2i &pos, Field field, bool ultraAttack){
|
void Ai::massiveAttack(const Vec2i &pos, Field field, bool ultraAttack){
|
||||||
|
const int minWorkerAttackersHarvesting = 3;
|
||||||
|
|
||||||
int producerWarriorCount=0;
|
int producerWarriorCount=0;
|
||||||
int maxProducerWarriors=random.randRange(1,11);
|
int maxProducerWarriors=random.randRange(1,11);
|
||||||
int unitCount = aiInterface->getMyUnitCount();
|
int unitCount = aiInterface->getMyUnitCount();
|
||||||
|
|
||||||
|
int attackerWorkersHarvestingCount = 0;
|
||||||
for(int i = 0; i < unitCount; ++i) {
|
for(int i = 0; i < unitCount; ++i) {
|
||||||
bool isWarrior=false;
|
bool isWarrior=false;
|
||||||
const Unit *unit= aiInterface->getMyUnit(i);
|
const Unit *unit= aiInterface->getMyUnit(i);
|
||||||
@ -493,24 +502,51 @@ void Ai::massiveAttack(const Vec2i &pos, Field field, bool ultraAttack){
|
|||||||
//printf("~~~~~~~~ Unit [%s - %d] found enemy [%s - %d] act_forenemy [%p] enemy->getCurrField() = %d\n",unit->getFullName().c_str(),unit->getId(),enemy->getFullName().c_str(),enemy->getId(),act_forenemy,enemy->getCurrField());
|
//printf("~~~~~~~~ Unit [%s - %d] found enemy [%s - %d] act_forenemy [%p] enemy->getCurrField() = %d\n",unit->getFullName().c_str(),unit->getId(),enemy->getFullName().c_str(),enemy->getId(),act_forenemy,enemy->getCurrField());
|
||||||
|
|
||||||
if(act_forenemy != NULL) {
|
if(act_forenemy != NULL) {
|
||||||
//printf("~~~~~~~~ Unit [%s - %d] WILL ATTACK [%s - %d]\n",unit->getFullName().c_str(),unit->getId(),enemy->getFullName().c_str(),enemy->getId());
|
bool shouldAttack = true;
|
||||||
aiInterface->giveCommand(i, act_forenemy, beingAttacked.second->getPos());
|
if(unit->getType()->hasSkillClass(scHarvest)) {
|
||||||
unitSignalledToAttack = true;
|
shouldAttack = (attackerWorkersHarvestingCount > minWorkerAttackersHarvesting);
|
||||||
|
if(shouldAttack == false) {
|
||||||
|
attackerWorkersHarvestingCount++;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
if(shouldAttack) {
|
||||||
|
//printf("~~~~~~~~ Unit [%s - %d] WILL ATTACK [%s - %d]\n",unit->getFullName().c_str(),unit->getId(),enemy->getFullName().c_str(),enemy->getId());
|
||||||
|
aiInterface->giveCommand(i, act_forenemy, beingAttacked.second->getPos());
|
||||||
|
unitSignalledToAttack = true;
|
||||||
|
}
|
||||||
}
|
}
|
||||||
else {
|
else {
|
||||||
const AttackStoppedCommandType *asct_forenemy = unit->getType()->getFirstAttackStoppedCommand(enemy->getCurrField());
|
const AttackStoppedCommandType *asct_forenemy = unit->getType()->getFirstAttackStoppedCommand(enemy->getCurrField());
|
||||||
//printf("~~~~~~~~ Unit [%s - %d] found enemy [%s - %d] asct_forenemy [%p] enemy->getCurrField() = %d\n",unit->getFullName().c_str(),unit->getId(),enemy->getFullName().c_str(),enemy->getId(),asct_forenemy,enemy->getCurrField());
|
//printf("~~~~~~~~ Unit [%s - %d] found enemy [%s - %d] asct_forenemy [%p] enemy->getCurrField() = %d\n",unit->getFullName().c_str(),unit->getId(),enemy->getFullName().c_str(),enemy->getId(),asct_forenemy,enemy->getCurrField());
|
||||||
if(asct_forenemy != NULL) {
|
if(asct_forenemy != NULL) {
|
||||||
//printf("~~~~~~~~ Unit [%s - %d] WILL ATTACK [%s - %d]\n",unit->getFullName().c_str(),unit->getId(),enemy->getFullName().c_str(),enemy->getId());
|
bool shouldAttack = true;
|
||||||
aiInterface->giveCommand(i, asct_forenemy, beingAttacked.second->getCenteredPos());
|
if(unit->getType()->hasSkillClass(scHarvest)) {
|
||||||
unitSignalledToAttack = true;
|
shouldAttack = (attackerWorkersHarvestingCount > minWorkerAttackersHarvesting);
|
||||||
|
if(shouldAttack == false) {
|
||||||
|
attackerWorkersHarvestingCount++;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
if(shouldAttack) {
|
||||||
|
//printf("~~~~~~~~ Unit [%s - %d] WILL ATTACK [%s - %d]\n",unit->getFullName().c_str(),unit->getId(),enemy->getFullName().c_str(),enemy->getId());
|
||||||
|
aiInterface->giveCommand(i, asct_forenemy, beingAttacked.second->getCenteredPos());
|
||||||
|
unitSignalledToAttack = true;
|
||||||
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
if(alreadyAttacking == false && act!=NULL && (ultraAttack || isWarrior) &&
|
if(alreadyAttacking == false && act != NULL && (ultraAttack || isWarrior) &&
|
||||||
unitSignalledToAttack == false) {
|
unitSignalledToAttack == false) {
|
||||||
aiInterface->giveCommand(i, act, pos);
|
bool shouldAttack = true;
|
||||||
|
if(unit->getType()->hasSkillClass(scHarvest)) {
|
||||||
|
shouldAttack = (attackerWorkersHarvestingCount > minWorkerAttackersHarvesting);
|
||||||
|
if(shouldAttack == false) {
|
||||||
|
attackerWorkersHarvestingCount++;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
if(shouldAttack) {
|
||||||
|
aiInterface->giveCommand(i, act, pos);
|
||||||
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@ -158,8 +158,8 @@ public:
|
|||||||
RandomGen* getRandom() {return &random;}
|
RandomGen* getRandom() {return &random;}
|
||||||
int getCountOfType(const UnitType *ut);
|
int getCountOfType(const UnitType *ut);
|
||||||
|
|
||||||
int getCountOfClass(UnitClass uc);
|
int getCountOfClass(UnitClass uc,UnitClass *additionalUnitClassToExcludeFromCount=NULL);
|
||||||
float getRatioOfClass(UnitClass uc);
|
float getRatioOfClass(UnitClass uc,UnitClass *additionalUnitClassToExcludeFromCount=NULL);
|
||||||
|
|
||||||
const ResourceType *getNeededResource(int unitIndex);
|
const ResourceType *getNeededResource(int unitIndex);
|
||||||
bool isStableBase();
|
bool isStableBase();
|
||||||
|
@ -94,8 +94,69 @@ AiRuleRepair::AiRuleRepair(Ai *ai):
|
|||||||
bool AiRuleRepair::test(){
|
bool AiRuleRepair::test(){
|
||||||
AiInterface *aiInterface= ai->getAiInterface();
|
AiInterface *aiInterface= ai->getAiInterface();
|
||||||
|
|
||||||
//look for a damaged unit
|
const int minUnitsRepairingCastle = 7;
|
||||||
for(int i=0; i<aiInterface->getMyUnitCount(); ++i){
|
// look for a damaged unit and give priority to the factions bases
|
||||||
|
// (units that produce workers and store resources)
|
||||||
|
for(int i = 0; i < aiInterface->getMyUnitCount(); ++i) {
|
||||||
|
const Unit *u= aiInterface->getMyUnit(i);
|
||||||
|
//printf("\n\n\n\n!!!!!! Is damaged unit [%d - %s] u->getHpRatio() = %f, hp = %d, mapHp = %d\n",u->getId(),u->getType()->getName().c_str(),u->getHpRatio(),u->getHp(),u->getType()->getTotalMaxHp(u->getTotalUpgrade()));
|
||||||
|
if(u->getHpRatio() < 1.f) {
|
||||||
|
|
||||||
|
bool unitCanProduceWorker = false;
|
||||||
|
for(int j = 0; unitCanProduceWorker == false &&
|
||||||
|
j < u->getType()->getCommandTypeCount(); ++j) {
|
||||||
|
const CommandType *ct= u->getType()->getCommandType(j);
|
||||||
|
|
||||||
|
//if the command is produce
|
||||||
|
if(ct->getClass() == ccProduce || ct->getClass() == ccMorph) {
|
||||||
|
const ProducibleType *pt = ct->getProduced();
|
||||||
|
if(pt != NULL) {
|
||||||
|
const UnitType *ut = dynamic_cast<const UnitType *>(pt);
|
||||||
|
if( ut != NULL && ut->hasCommandClass(ccHarvest) == true &&
|
||||||
|
ut->getStoredResourceCount() > 0) {
|
||||||
|
unitCanProduceWorker = true;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
int candidatedamagedUnitIndex=-1;
|
||||||
|
if(unitCanProduceWorker == true) {
|
||||||
|
int unitCountAlreadyRepairingDamagedUnit = 0;
|
||||||
|
// Now check if any other unit is able to repair this unit
|
||||||
|
for(int i1 = 0; i1 < aiInterface->getMyUnitCount(); ++i1) {
|
||||||
|
const Unit *u1= aiInterface->getMyUnit(i1);
|
||||||
|
const RepairCommandType *rct= static_cast<const RepairCommandType *>(u1->getType()->getFirstCtOfClass(ccRepair));
|
||||||
|
//if(rct) printf("\n\n\n\n^^^^^^^^^^ possible repairer unit [%d - %s] current skill [%d] can reapir damaged unit [%d]\n",u1->getId(),u1->getType()->getName().c_str(),u->getCurrSkill()->getClass(),rct->isRepairableUnitType(u->getType()));
|
||||||
|
|
||||||
|
if(rct != NULL) {
|
||||||
|
if(u1->getCurrSkill()->getClass() == scStop || u1->getCurrSkill()->getClass() == scMove) {
|
||||||
|
if(rct->isRepairableUnitType(u->getType())) {
|
||||||
|
candidatedamagedUnitIndex= i;
|
||||||
|
//return true;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
else if(u1->getCurrSkill()->getClass() == scRepair) {
|
||||||
|
Command *cmd = u1->getCurrCommand();
|
||||||
|
if(cmd != NULL && cmd->getCommandType()->getClass() == ccRepair) {
|
||||||
|
if(cmd->getUnit() != NULL && cmd->getUnit()->getId() == u->getId()) {
|
||||||
|
unitCountAlreadyRepairingDamagedUnit++;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
if(candidatedamagedUnitIndex >= 0 && unitCountAlreadyRepairingDamagedUnit < minUnitsRepairingCastle) {
|
||||||
|
damagedUnitIndex = candidatedamagedUnitIndex;
|
||||||
|
return true;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
// Normal Repair checking
|
||||||
|
for(int i = 0; i < aiInterface->getMyUnitCount(); ++i) {
|
||||||
const Unit *u= aiInterface->getMyUnit(i);
|
const Unit *u= aiInterface->getMyUnit(i);
|
||||||
//printf("\n\n\n\n!!!!!! Is damaged unit [%d - %s] u->getHpRatio() = %f, hp = %d, mapHp = %d\n",u->getId(),u->getType()->getName().c_str(),u->getHpRatio(),u->getHp(),u->getType()->getTotalMaxHp(u->getTotalUpgrade()));
|
//printf("\n\n\n\n!!!!!! Is damaged unit [%d - %s] u->getHpRatio() = %f, hp = %d, mapHp = %d\n",u->getId(),u->getType()->getName().c_str(),u->getHpRatio(),u->getHp(),u->getType()->getTotalMaxHp(u->getTotalUpgrade()));
|
||||||
if(u->getHpRatio() < 1.f) {
|
if(u->getHpRatio() < 1.f) {
|
||||||
@ -191,12 +252,13 @@ AiRuleAddTasks::AiRuleAddTasks(Ai *ai):
|
|||||||
}
|
}
|
||||||
|
|
||||||
bool AiRuleAddTasks::test(){
|
bool AiRuleAddTasks::test(){
|
||||||
return !ai->anyTask() || ai->getCountOfClass(ucWorker)<4;
|
return !ai->anyTask() || ai->getCountOfClass(ucWorker) < 4;
|
||||||
}
|
}
|
||||||
|
|
||||||
void AiRuleAddTasks::execute(){
|
void AiRuleAddTasks::execute(){
|
||||||
int buildingCount= ai->getCountOfClass(ucBuilding);
|
int buildingCount= ai->getCountOfClass(ucBuilding);
|
||||||
int warriorCount= ai->getCountOfClass(ucWarrior);
|
UnitClass ucWorkerType = ucWorker;
|
||||||
|
int warriorCount= ai->getCountOfClass(ucWarrior,&ucWorkerType);
|
||||||
int workerCount= ai->getCountOfClass(ucWorker);
|
int workerCount= ai->getCountOfClass(ucWorker);
|
||||||
int upgradeCount= ai->getAiInterface()->getMyUpgradeCount();
|
int upgradeCount= ai->getAiInterface()->getMyUpgradeCount();
|
||||||
|
|
||||||
@ -632,7 +694,7 @@ void AiRuleProduce::produceSpecific(const ProduceTask *pt){
|
|||||||
if( aiInterface->getMyUnit(bestIndex)->getCommandSize() > 2) {
|
if( aiInterface->getMyUnit(bestIndex)->getCommandSize() > 2) {
|
||||||
// maybe we need another producer of this kind if possible!
|
// maybe we need another producer of this kind if possible!
|
||||||
if(aiInterface->reqsOk(aiInterface->getMyUnit(bestIndex)->getType())) {
|
if(aiInterface->reqsOk(aiInterface->getMyUnit(bestIndex)->getType())) {
|
||||||
if(ai->getCountOfClass(ucBuilding)>5)
|
if(ai->getCountOfClass(ucBuilding) > 5)
|
||||||
ai->addTask(new BuildTask(aiInterface->getMyUnit(bestIndex)->getType()));
|
ai->addTask(new BuildTask(aiInterface->getMyUnit(bestIndex)->getType()));
|
||||||
}
|
}
|
||||||
// need to calculate another producer, maybe its better to produce another warrior with another producer
|
// need to calculate another producer, maybe its better to produce another warrior with another producer
|
||||||
|
Loading…
x
Reference in New Issue
Block a user