mirror of
https://github.com/glest/glest-source.git
synced 2025-02-24 11:42:31 +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;
|
||||
}
|
||||
|
||||
int Ai::getCountOfClass(UnitClass uc){
|
||||
int Ai::getCountOfClass(UnitClass uc,UnitClass *additionalUnitClassToExcludeFromCount) {
|
||||
int count= 0;
|
||||
for(int i=0; i<aiInterface->getMyUnitCount(); ++i){
|
||||
if(aiInterface->getMyUnit(i)->getType()->isOfClass(uc)){
|
||||
for(int i = 0; i < aiInterface->getMyUnitCount(); ++i) {
|
||||
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;
|
||||
}
|
||||
}
|
||||
return count;
|
||||
}
|
||||
|
||||
float Ai::getRatioOfClass(UnitClass uc){
|
||||
if(aiInterface->getMyUnitCount()==0){
|
||||
float Ai::getRatioOfClass(UnitClass uc,UnitClass *additionalUnitClassToExcludeFromCount) {
|
||||
if(aiInterface->getMyUnitCount() == 0) {
|
||||
return 0;
|
||||
}
|
||||
else{
|
||||
return static_cast<float>(getCountOfClass(uc))/aiInterface->getMyUnitCount();
|
||||
else {
|
||||
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(){
|
||||
|
||||
if(getCountOfClass(ucWarrior)>minWarriors){
|
||||
bool Ai::isStableBase() {
|
||||
UnitClass ucWorkerType = ucWorker;
|
||||
if(getCountOfClass(ucWarrior,&ucWorkerType) > minWarriors) {
|
||||
aiInterface->printLog(4, "Base is stable\n");
|
||||
return true;
|
||||
}
|
||||
@ -436,10 +442,13 @@ void Ai::sendScoutPatrol(){
|
||||
}
|
||||
|
||||
void Ai::massiveAttack(const Vec2i &pos, Field field, bool ultraAttack){
|
||||
const int minWorkerAttackersHarvesting = 3;
|
||||
|
||||
int producerWarriorCount=0;
|
||||
int maxProducerWarriors=random.randRange(1,11);
|
||||
int unitCount = aiInterface->getMyUnitCount();
|
||||
|
||||
int attackerWorkersHarvestingCount = 0;
|
||||
for(int i = 0; i < unitCount; ++i) {
|
||||
bool isWarrior=false;
|
||||
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());
|
||||
|
||||
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());
|
||||
aiInterface->giveCommand(i, act_forenemy, beingAttacked.second->getPos());
|
||||
unitSignalledToAttack = true;
|
||||
bool shouldAttack = true;
|
||||
if(unit->getType()->hasSkillClass(scHarvest)) {
|
||||
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 {
|
||||
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());
|
||||
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());
|
||||
aiInterface->giveCommand(i, asct_forenemy, beingAttacked.second->getCenteredPos());
|
||||
unitSignalledToAttack = true;
|
||||
bool shouldAttack = true;
|
||||
if(unit->getType()->hasSkillClass(scHarvest)) {
|
||||
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) {
|
||||
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;}
|
||||
int getCountOfType(const UnitType *ut);
|
||||
|
||||
int getCountOfClass(UnitClass uc);
|
||||
float getRatioOfClass(UnitClass uc);
|
||||
int getCountOfClass(UnitClass uc,UnitClass *additionalUnitClassToExcludeFromCount=NULL);
|
||||
float getRatioOfClass(UnitClass uc,UnitClass *additionalUnitClassToExcludeFromCount=NULL);
|
||||
|
||||
const ResourceType *getNeededResource(int unitIndex);
|
||||
bool isStableBase();
|
||||
|
@ -94,8 +94,69 @@ AiRuleRepair::AiRuleRepair(Ai *ai):
|
||||
bool AiRuleRepair::test(){
|
||||
AiInterface *aiInterface= ai->getAiInterface();
|
||||
|
||||
//look for a damaged unit
|
||||
for(int i=0; i<aiInterface->getMyUnitCount(); ++i){
|
||||
const int minUnitsRepairingCastle = 7;
|
||||
// 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);
|
||||
//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) {
|
||||
@ -191,12 +252,13 @@ AiRuleAddTasks::AiRuleAddTasks(Ai *ai):
|
||||
}
|
||||
|
||||
bool AiRuleAddTasks::test(){
|
||||
return !ai->anyTask() || ai->getCountOfClass(ucWorker)<4;
|
||||
return !ai->anyTask() || ai->getCountOfClass(ucWorker) < 4;
|
||||
}
|
||||
|
||||
void AiRuleAddTasks::execute(){
|
||||
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 upgradeCount= ai->getAiInterface()->getMyUpgradeCount();
|
||||
|
||||
@ -632,7 +694,7 @@ void AiRuleProduce::produceSpecific(const ProduceTask *pt){
|
||||
if( aiInterface->getMyUnit(bestIndex)->getCommandSize() > 2) {
|
||||
// maybe we need another producer of this kind if possible!
|
||||
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()));
|
||||
}
|
||||
// need to calculate another producer, maybe its better to produce another warrior with another producer
|
||||
|
Loading…
x
Reference in New Issue
Block a user