- more AI fixes.

#1: AI does not try to harvest resources that the unit cannot yet harvest (could be an upgrade required)

#2: AI no longer tries to expand near resources that they are not yet able to harvest. (found using RealtimeFreaks test mod and map). This makes for a more aggresive CPU in scenarios where there are additional resource types since they expand much more quickly.
This commit is contained in:
Mark Vejvoda 2010-10-02 01:11:59 +00:00
parent 468340403f
commit 02e0a1302f
7 changed files with 61 additions and 42 deletions

View File

@ -200,9 +200,9 @@ const ResourceType *Ai::getNeededResource(int unitIndex) {
// Now MAKE SURE the unit has a harvest command for this resource
// AND that the resource is within eye-sight to avoid units
// standing around doing nothing.
const HarvestCommandType *hct= aiInterface->getMyUnit(unitIndex)->getType()->getFirstHarvestCommand(rt);
const HarvestCommandType *hct= aiInterface->getMyUnit(unitIndex)->getType()->getFirstHarvestCommand(rt,aiInterface->getMyUnit(unitIndex)->getFaction());
Vec2i resPos;
if(hct != NULL && aiInterface->getNearestSightedResource(rt, aiInterface->getHomeLocation(), resPos)) {
if(hct != NULL && aiInterface->getNearestSightedResource(rt, aiInterface->getHomeLocation(), resPos, false)) {
amount= r->getAmount();
neededResource= rt;
}
@ -486,9 +486,9 @@ void Ai::harvest(int unitIndex) {
const ResourceType *rt= getNeededResource(unitIndex);
if(rt != NULL) {
const HarvestCommandType *hct= aiInterface->getMyUnit(unitIndex)->getType()->getFirstHarvestCommand(rt);
const HarvestCommandType *hct= aiInterface->getMyUnit(unitIndex)->getType()->getFirstHarvestCommand(rt,aiInterface->getMyUnit(unitIndex)->getFaction());
Vec2i resPos;
if(hct != NULL && aiInterface->getNearestSightedResource(rt, aiInterface->getHomeLocation(), resPos)) {
if(hct != NULL && aiInterface->getNearestSightedResource(rt, aiInterface->getHomeLocation(), resPos, false)) {
resPos= resPos+Vec2i(random.randRange(-2, 2), random.randRange(-2, 2));
aiInterface->giveCommand(unitIndex, hct, resPos);
//aiInterface->printLog(4, "Order harvest pos:" + intToStr(resPos.x)+", "+intToStr(resPos.y)+": "+rrToStr(r)+"\n");

View File

@ -371,29 +371,45 @@ const TechTree *AiInterface::getTechTree(){
return world->getTechTree();
}
bool AiInterface::getNearestSightedResource(const ResourceType *rt, const Vec2i &pos, Vec2i &resultPos){
float tmpDist;
bool AiInterface::getNearestSightedResource(const ResourceType *rt, const Vec2i &pos,
Vec2i &resultPos, bool usableResourceTypeOnly) {
float tmpDist=0;
float nearestDist= infinity;
bool anyResource= false;
const Map *map= world->getMap();
bool canUseResourceType = (usableResourceTypeOnly == false);
if(usableResourceTypeOnly == true) {
// can any unit harvest this resource yet?
for(int i = 0; i < getMyUnitCount(); ++i) {
const Unit *unit = getMyUnit(i);
const HarvestCommandType *hct= unit->getType()->getFirstHarvestCommand(rt,unit->getFaction());
if(hct != NULL) {
canUseResourceType = true;
break;
}
}
}
for(int i=0; i<map->getW(); ++i){
for(int j=0; j<map->getH(); ++j){
Vec2i surfPos= Map::toSurfCoords(Vec2i(i, j));
//if explored cell
if(map->getSurfaceCell(surfPos)->isExplored(teamIndex)){
Resource *r= map->getSurfaceCell(surfPos)->getResource();
if(canUseResourceType == true) {
const Map *map= world->getMap();
for(int i=0; i<map->getW(); ++i){
for(int j=0; j<map->getH(); ++j){
Vec2i surfPos= Map::toSurfCoords(Vec2i(i, j));
//if resource cell
if(r!=NULL && r->getType()==rt){
tmpDist= pos.dist(Vec2i(i, j));
if(tmpDist<nearestDist){
anyResource= true;
nearestDist= tmpDist;
resultPos= Vec2i(i, j);
//if explored cell
if(map->getSurfaceCell(surfPos)->isExplored(teamIndex)){
Resource *r= map->getSurfaceCell(surfPos)->getResource();
//if resource cell
if(r != NULL && r->getType() == rt) {
tmpDist= pos.dist(Vec2i(i, j));
if(tmpDist < nearestDist) {
anyResource= true;
nearestDist= tmpDist;
resultPos= Vec2i(i, j);
}
}
}
}

View File

@ -30,7 +30,7 @@ namespace Glest{ namespace Game{
/// The AI will interact with the game through this interface
// =====================================================
class AiInterface{
class AiInterface {
private:
World *world;
Commander *commander;
@ -80,7 +80,7 @@ public:
const Unit *getOnSightUnit(int unitIndex);
const FactionType *getMyFactionType();
const TechTree *getTechTree();
bool getNearestSightedResource(const ResourceType *rt, const Vec2i &pos, Vec2i &resultPos);
bool getNearestSightedResource(const ResourceType *rt, const Vec2i &pos, Vec2i &resultPos, bool usableResourceTypeOnly);
bool isAlly(const Unit *unit) const;
bool isAlly(int factionIndex) const;
bool reqsOk(const RequirableType *rt);

View File

@ -1089,42 +1089,38 @@ AiRuleExpand::AiRuleExpand(Ai *ai):
storeType= NULL;
}
bool AiRuleExpand::test(){
bool AiRuleExpand::test() {
AiInterface *aiInterface = ai->getAiInterface();
for(int i= 0; i<aiInterface->getTechTree()->getResourceTypeCount(); ++i){
const ResourceType *rt = aiInterface->getTechTree()->getResourceType(i);
if(rt->getClass()==rcTech){
if(rt->getClass() == rcTech){
// If any resource sighted
if(aiInterface->getNearestSightedResource(rt, aiInterface->getHomeLocation(), expandPos)){
if(aiInterface->getNearestSightedResource(rt, aiInterface->getHomeLocation(), expandPos, true)) {
int minDistance= INT_MAX;
storeType= NULL;
//If there is no close store
for(int j=0; j<aiInterface->getMyUnitCount(); ++j){
for(int j=0; j < aiInterface->getMyUnitCount(); ++j) {
const Unit *u= aiInterface->getMyUnit(j);
const UnitType *ut= aiInterface->getMyUnit(j)->getType();
// If this building is a store
if(ut->getStore(rt)>0){
if(ut->getStore(rt) > 0) {
storeType = ut;
int distance= static_cast<int> (u->getPos().dist(expandPos));
if(distance < minDistance){
if(distance < minDistance) {
minDistance = distance;
}
}
}
if(minDistance>expandDistance)
{
if(minDistance > expandDistance) {
return true;
}
}
else{
else {
// send patrol to look for resource
ai->sendScoutPatrol();
}

View File

@ -930,7 +930,7 @@ const CommandType *Unit::computeCommandType(const Vec2i &pos, const Unit *target
//check harvest command
Resource *resource= sc->getResource();
if(resource!=NULL){
commandType= type->getFirstHarvestCommand(resource->getType());
commandType= type->getFirstHarvestCommand(resource->getType(),this->getFaction());
}
}

View File

@ -24,6 +24,7 @@
#include "renderer.h"
#include "game_util.h"
#include "unit_particle_type.h"
#include "faction.h"
#include "leak_dumper.h"
using namespace Shared::Xml;
@ -434,11 +435,16 @@ const SkillType *UnitType::getFirstStOfClass(SkillClass skillClass) const{
return firstSkillTypeOfClass[skillClass];
}
const HarvestCommandType *UnitType::getFirstHarvestCommand(const ResourceType *resourceType) const{
for(int i=0; i<commandTypes.size(); ++i) {
if(commandTypes[i]->getClass()== ccHarvest){
const HarvestCommandType *hct= static_cast<const HarvestCommandType*>(commandTypes[i]);
if(hct->canHarvest(resourceType)){
const HarvestCommandType *UnitType::getFirstHarvestCommand(const ResourceType *resourceType, const Faction *faction) const {
for(int i = 0; i < commandTypes.size(); ++i) {
if(commandTypes[i]->getClass() == ccHarvest) {
const HarvestCommandType *hct = static_cast<const HarvestCommandType*>(commandTypes[i]);
if (faction->reqsOk(hct) == false) {
continue;
}
if(hct->canHarvest(resourceType)) {
return hct;
}
}

View File

@ -31,6 +31,7 @@ class UnitParticleSystemType;
class ResourceType;
class TechTree;
class FactionType;
class Faction;
// ===============================
@ -172,7 +173,7 @@ public:
const SkillType *getSkillType(const string &skillName, SkillClass skillClass) const;
const SkillType *getFirstStOfClass(SkillClass skillClass) const;
const CommandType *getFirstCtOfClass(CommandClass commandClass) const;
const HarvestCommandType *getFirstHarvestCommand(const ResourceType *resourceType) const;
const HarvestCommandType *getFirstHarvestCommand(const ResourceType *resourceType,const Faction *faction) const;
const AttackCommandType *getFirstAttackCommand(Field field) const;
const RepairCommandType *getFirstRepairCommand(const UnitType *repaired) const;