diff --git a/source/glest_game/ai/ai.cpp b/source/glest_game/ai/ai.cpp index 87f006e0..f647b892 100644 --- a/source/glest_game/ai/ai.cpp +++ b/source/glest_game/ai/ai.cpp @@ -14,6 +14,7 @@ #include "ai_rule.h" #include "unit_type.h" #include "unit.h" +#include "map.h" #include "leak_dumper.h" using namespace Shared::Graphics; @@ -122,6 +123,7 @@ void Ai::init(AiInterface *aiInterface, int useStartLocation) { aiRules.push_back(new AiRuleWorkerHarvest(this)); aiRules.push_back(new AiRuleRefreshHarvester(this)); aiRules.push_back(new AiRuleScoutPatrol(this)); + aiRules.push_back(new AiRuleUnBlock(this)); aiRules.push_back(new AiRuleReturnBase(this)); aiRules.push_back(new AiRuleMassiveAttack(this)); aiRules.push_back(new AiRuleAddTasks(this)); @@ -525,4 +527,152 @@ void Ai::harvest(int unitIndex) { } } +bool Ai::haveBlockedUnits() { + int unitCount = aiInterface->getMyUnitCount(); + Map *map = aiInterface->getMap(); + //If there is no close store + for(int j=0; j < unitCount; ++j) { + const Unit *u= aiInterface->getMyUnit(j); + const UnitType *ut= u->getType(); + + // If this building is a store + if(u->isAlive() && ut->isMobile() && u->getPath() != NULL && (u->getPath()->isBlocked() || u->getPath()->getBlockCount())) { + Vec2i unitPos = u->getPos(); + + //printf("#1 AI found blocked unit [%d - %s]\n",u->getId(),u->getFullName().c_str()); + + int failureCount = 0; + int cellCount = 0; + + for(int i = -1; i <= 1; ++i) { + for(int j = -1; j <= 1; ++j) { + Vec2i pos = unitPos + Vec2i(i, j); + if(map->isInside(pos) && map->isInsideSurface(map->toSurfCoords(pos))) { + if(pos != unitPos) { + bool canUnitMoveToCell = map->aproxCanMove(u, unitPos, pos); + if(canUnitMoveToCell == false) { + failureCount++; + } + cellCount++; + } + } + } + } + bool unitImmediatelyBlocked = (failureCount == cellCount); + //printf("#1 unitImmediatelyBlocked = %d, failureCount = %d, cellCount = %d\n",unitImmediatelyBlocked,failureCount,cellCount); + + if(unitImmediatelyBlocked) { + //printf("#1 AI unit IS BLOCKED [%d - %s]\n",u->getId(),u->getFullName().c_str()); + return true; + } + } + } + + return false; +} + +bool Ai::getAdjacentUnits(std::map > &signalAdjacentUnits, const Unit *unit) { + bool result = false; + Map *map = aiInterface->getMap(); + Vec2i unitPos = unit->getPos(); + for(int i = -1; i <= 1; ++i) { + for(int j = -1; j <= 1; ++j) { + Vec2i pos = unitPos + Vec2i(i, j); + if(map->isInside(pos) && map->isInsideSurface(map->toSurfCoords(pos))) { + if(pos != unitPos) { + Unit *adjacentUnit = map->getCell(pos)->getUnit(unit->getCurrField()); + if(adjacentUnit != NULL && adjacentUnit->getFactionIndex() == unit->getFactionIndex()) { + if(adjacentUnit->getType()->isMobile() && adjacentUnit->getPath() != NULL) { + //signalAdjacentUnits.push_back(adjacentUnit); + float dist = unitPos.dist(adjacentUnit->getPos()); + + std::map >::iterator iterFind1 = signalAdjacentUnits.find(dist); + if(iterFind1 == signalAdjacentUnits.end()) { + signalAdjacentUnits[dist][adjacentUnit->getId()] = adjacentUnit; + + getAdjacentUnits(signalAdjacentUnits, adjacentUnit); + result = true; + } + else { + std::map::iterator iterFind2 = iterFind1->second.find(adjacentUnit->getId()); + if(iterFind2 == iterFind1->second.end()) { + signalAdjacentUnits[dist][adjacentUnit->getId()] = adjacentUnit; + getAdjacentUnits(signalAdjacentUnits, adjacentUnit); + result = true; + } + } + } + } + } + } + } + } + return result; +} + +void Ai::unblockUnits() { + int unitCount = aiInterface->getMyUnitCount(); + Map *map = aiInterface->getMap(); + // Find blocked units and move surrounding units out of the way + std::map > signalAdjacentUnits; + for(int idx=0; idx < unitCount; ++idx) { + const Unit *u= aiInterface->getMyUnit(idx); + const UnitType *ut= u->getType(); + + // If this building is a store + if(u->isAlive() && ut->isMobile() && u->getPath() != NULL && (u->getPath()->isBlocked() || u->getPath()->getBlockCount())) { + Vec2i unitPos = u->getPos(); + + //printf("#2 AI found blocked unit [%d - %s]\n",u->getId(),u->getFullName().c_str()); + + int failureCount = 0; + int cellCount = 0; + + for(int i = -1; i <= 1; ++i) { + for(int j = -1; j <= 1; ++j) { + Vec2i pos = unitPos + Vec2i(i, j); + if(map->isInside(pos) && map->isInsideSurface(map->toSurfCoords(pos))) { + if(pos != unitPos) { + bool canUnitMoveToCell = map->aproxCanMove(u, unitPos, pos); + if(canUnitMoveToCell == false) { + failureCount++; + getAdjacentUnits(signalAdjacentUnits, u); + } + cellCount++; + } + } + } + } + //bool unitImmediatelyBlocked = (failureCount == cellCount); + //printf("#2 unitImmediatelyBlocked = %d, failureCount = %d, cellCount = %d, signalAdjacentUnits.size() = %d\n",unitImmediatelyBlocked,failureCount,cellCount,signalAdjacentUnits.size()); + } + } + + if(signalAdjacentUnits.size() > 0) { + //printf("#2 AI units ARE BLOCKED about to unblock\n"); + + for(std::map >::reverse_iterator iterMap = signalAdjacentUnits.rbegin(); + iterMap != signalAdjacentUnits.rend(); iterMap++) { + + for(std::map::iterator iterMap2 = iterMap->second.begin(); + iterMap2 != iterMap->second.end(); iterMap2++) { + int idx = iterMap2->first; + const Unit *adjacentUnit = iterMap2->second; + + for(int moveAttempt = 1; moveAttempt <= villageRadius; ++moveAttempt) { + Vec2i pos= Vec2i( + random.randRange(-villageRadius*2, villageRadius*2), random.randRange(-villageRadius*2, villageRadius*2)) + + adjacentUnit->getPos(); + + bool canUnitMoveToCell = map->aproxCanMove(adjacentUnit, adjacentUnit->getPos(), pos); + if(canUnitMoveToCell == true) { + const CommandType *ct = adjacentUnit->getType()->getFirstCtOfClass(ccMove); + CommandResult r = aiInterface->giveCommand(adjacentUnit,ct, pos); + } + } + } + } + } +} + }}//end namespace diff --git a/source/glest_game/ai/ai.h b/source/glest_game/ai/ai.h index d7b85e96..d3e1a486 100644 --- a/source/glest_game/ai/ai.h +++ b/source/glest_game/ai/ai.h @@ -145,6 +145,8 @@ private: Positions expansionPositions; RandomGen random; + bool getAdjacentUnits(std::map > &signalAdjacentUnits, const Unit *unit); + public: int minWarriors; ~Ai(); @@ -183,6 +185,8 @@ public: void massiveAttack(const Vec2i &pos, Field field, bool ultraAttack= false); void returnBase(int unitIndex); void harvest(int unitIndex); + bool haveBlockedUnits(); + void unblockUnits(); }; }}//end namespace diff --git a/source/glest_game/ai/ai_interface.cpp b/source/glest_game/ai/ai_interface.cpp index b90087d4..1c6d8e45 100644 --- a/source/glest_game/ai/ai_interface.cpp +++ b/source/glest_game/ai/ai_interface.cpp @@ -132,7 +132,7 @@ CommandResult AiInterface::giveCommand(int unitIndex, CommandClass commandClass, } } -CommandResult AiInterface::giveCommand(Unit *unit, const CommandType *commandType, const Vec2i &pos) { +CommandResult AiInterface::giveCommand(const Unit *unit, const CommandType *commandType, const Vec2i &pos) { assert(this->gameSettings != NULL); if(unit == NULL) { @@ -172,7 +172,9 @@ CommandResult AiInterface::giveCommand(Unit *unit, const CommandType *commandTyp else { SystemFlags::OutputDebug(SystemFlags::debugSystem,"In [%s::%s Line: %d]\n",__FILE__,__FUNCTION__,__LINE__); - CommandResult result = unit->giveCommand(new Command(commandType, pos)); + Faction *faction = world->getFaction(unit->getFactionIndex()); + Unit *unitToCommand = faction->findUnit(unit->getId()); + CommandResult result = unitToCommand->giveCommand(new Command(commandType, pos)); SystemFlags::OutputDebug(SystemFlags::debugSystem,"In [%s::%s Line: %d]\n",__FILE__,__FUNCTION__,__LINE__); return result; @@ -613,5 +615,9 @@ const Unit *AiInterface::getFirstOnSightEnemyUnit(Vec2i &pos, Field &field, int return NULL; } +Map * AiInterface::getMap() { + Map *map= world->getMap(); + return map; +} }}//end namespace diff --git a/source/glest_game/ai/ai_interface.h b/source/glest_game/ai/ai_interface.h index 0d96201c..511d4e39 100644 --- a/source/glest_game/ai/ai_interface.h +++ b/source/glest_game/ai/ai_interface.h @@ -68,7 +68,7 @@ public: CommandResult giveCommand(int unitIndex, const CommandType *commandType, const Vec2i &pos, const UnitType* unitType); CommandResult giveCommand(int unitIndex, const CommandType *commandType, const Vec2i &pos); CommandResult giveCommand(int unitIndex, const CommandType *commandType, Unit *u= NULL); - CommandResult giveCommand(Unit *unit, const CommandType *commandType, const Vec2i &pos); + CommandResult giveCommand(const Unit *unit, const CommandType *commandType, const Vec2i &pos); //get data const ControlType getControlType(); @@ -94,6 +94,7 @@ public: bool checkCosts(const ProducibleType *pt); bool isFreeCells(const Vec2i &pos, int size, Field field); const Unit *getFirstOnSightEnemyUnit(Vec2i &pos, Field &field, int radius); + Map * getMap(); private: string getLogFilename() const {return "ai"+intToStr(factionIndex)+".log";} diff --git a/source/glest_game/ai/ai_rule.cpp b/source/glest_game/ai/ai_rule.cpp index 1155b719..c4384a27 100644 --- a/source/glest_game/ai/ai_rule.cpp +++ b/source/glest_game/ai/ai_rule.cpp @@ -1156,4 +1156,23 @@ void AiRuleExpand::execute(){ ai->addPriorityTask(new BuildTask(storeType, expandPos)); } + +// ======================================== +// class AiRuleUnBlock +// ======================================== + +AiRuleUnBlock::AiRuleUnBlock(Ai *ai): + AiRule(ai) +{ + +} + +bool AiRuleUnBlock::test() { + return ai->haveBlockedUnits(); +} + +void AiRuleUnBlock::execute(){ + ai->unblockUnits(); +} + }}//end namespace diff --git a/source/glest_game/ai/ai_rule.h b/source/glest_game/ai/ai_rule.h index 4935b252..37458a6a 100644 --- a/source/glest_game/ai/ai_rule.h +++ b/source/glest_game/ai/ai_rule.h @@ -310,6 +310,21 @@ public: virtual void execute(); }; +// ===================================================== +// class AiRuleUnBlock +// ===================================================== + +class AiRuleUnBlock: public AiRule{ +public: + AiRuleUnBlock(Ai *ai); + + virtual int getTestInterval() const {return 3000;} + virtual string getName() const {return "Blocked Units => Move surrounding units";} + + virtual bool test(); + virtual void execute(); +}; + }}//end namespace #endif diff --git a/source/glest_game/ai/path_finder.cpp b/source/glest_game/ai/path_finder.cpp index f061c5c3..dca8b7b3 100644 --- a/source/glest_game/ai/path_finder.cpp +++ b/source/glest_game/ai/path_finder.cpp @@ -526,6 +526,63 @@ TravelState PathFinder::aStar(Unit *unit, const Vec2i &targetPos, bool inBailout if(SystemFlags::getSystemSettingType(SystemFlags::debugPerformance).enabled == true && chrono.getMillis() > 4) SystemFlags::OutputDebug(SystemFlags::debugPerformance,"In [%s::%s Line: %d] took msecs: %lld\n",__FILE__,__FUNCTION__,__LINE__,chrono.getMillis()); + // First check if unit currently blocked + if(inBailout == false && unitPos != finalPos) { + int failureCount = 0; + int cellCount = 0; + + for(int i = -1; i <= 1; ++i) { + for(int j = -1; j <= 1; ++j) { + Vec2i pos = unitPos + Vec2i(i, j); + if(pos != unitPos) { + bool canUnitMoveToCell = map->aproxCanMove(unit, unitPos, pos); + if(canUnitMoveToCell == false) { + failureCount++; + } + cellCount++; + } + } + } + nodeLimitReached = (failureCount == cellCount); + pathFound = !nodeLimitReached; + + if(SystemFlags::getSystemSettingType(SystemFlags::debugPerformance).enabled == true && chrono.getMillis() > 1) SystemFlags::OutputDebug(SystemFlags::debugPerformance,"In [%s::%s Line: %d] **Check if dest blocked, distance for unit [%d - %s] from [%s] to [%s] is %.2f took msecs: %lld nodeLimitReached = %d, failureCount = %d\n",__FILE__,__FUNCTION__,__LINE__,unit->getId(),unit->getFullName().c_str(), unitPos.getString().c_str(), finalPos.getString().c_str(), dist,(long long int)chrono.getMillis(),nodeLimitReached,failureCount); + if(showConsoleDebugInfo && nodeLimitReached) { + //if(showConsoleDebugInfo) { + printf("**Check if src blocked [%d - %d], unit [%d - %s] from [%s] to [%s] distance %.2f took msecs: %lld nodeLimitReached = %d, failureCount = %d [%d]\n", + nodeLimitReached, inBailout, unit->getId(),unit->getFullName().c_str(), unitPos.getString().c_str(), finalPos.getString().c_str(), dist,(long long int)chrono.getMillis(),nodeLimitReached,failureCount,cellCount); + } + + if(nodeLimitReached == false) { + // First check if final destination blocked + failureCount = 0; + cellCount = 0; + + for(int i = -1; i <= 1; ++i) { + for(int j = -1; j <= 1; ++j) { + Vec2i pos = finalPos + Vec2i(i, j); + if(pos != finalPos) { + bool canUnitMoveToCell = map->aproxCanMove(unit, pos, finalPos); + if(canUnitMoveToCell == false) { + failureCount++; + } + cellCount++; + } + } + } + nodeLimitReached = (failureCount == cellCount); + pathFound = !nodeLimitReached; + + if(SystemFlags::getSystemSettingType(SystemFlags::debugPerformance).enabled == true && chrono.getMillis() > 1) SystemFlags::OutputDebug(SystemFlags::debugPerformance,"In [%s::%s Line: %d] **Check if dest blocked, distance for unit [%d - %s] from [%s] to [%s] is %.2f took msecs: %lld nodeLimitReached = %d, failureCount = %d\n",__FILE__,__FUNCTION__,__LINE__,unit->getId(),unit->getFullName().c_str(), unitPos.getString().c_str(), finalPos.getString().c_str(), dist,(long long int)chrono.getMillis(),nodeLimitReached,failureCount); + if(showConsoleDebugInfo && nodeLimitReached) { + //if(showConsoleDebugInfo) { + printf("**Check if dest blocked [%d - %d], unit [%d - %s] from [%s] to [%s] distance %.2f took msecs: %lld nodeLimitReached = %d, failureCount = %d [%d]\n", + nodeLimitReached, inBailout, unit->getId(),unit->getFullName().c_str(), unitPos.getString().c_str(), finalPos.getString().c_str(), dist,(long long int)chrono.getMillis(),nodeLimitReached,failureCount,cellCount); + } + } + } + // + int whileLoopCount = 0; while(nodeLimitReached == false) { whileLoopCount++; @@ -614,7 +671,7 @@ TravelState PathFinder::aStar(Unit *unit, const Vec2i &targetPos, bool inBailout if(SystemFlags::getSystemSettingType(SystemFlags::debugPerformance).enabled == true && chrono.getMillis() > 1) SystemFlags::OutputDebug(SystemFlags::debugPerformance,"In [%s::%s Line: %d] took msecs: %lld nodeLimitReached = %d whileLoopCount = %d nodePoolCount = %d\n",__FILE__,__FUNCTION__,__LINE__,chrono.getMillis(),nodeLimitReached,whileLoopCount,nodePoolCount); if(showConsoleDebugInfo && chrono.getMillis() > 2) { - printf("Distance for unit [%d - %s] to destination is %.2f took msecs: %lld nodeLimitReached = %d whileLoopCount = %d nodePoolCount = %d\n",unit->getId(),unit->getFullName().c_str(), dist,(long long int)chrono.getMillis(),nodeLimitReached,whileLoopCount,nodePoolCount); + printf("Distance for unit [%d - %s] from [%s] to [%s] is %.2f took msecs: %lld nodeLimitReached = %d whileLoopCount = %d nodePoolCount = %d\n",unit->getId(),unit->getFullName().c_str(), unitPos.getString().c_str(), finalPos.getString().c_str(), dist,(long long int)chrono.getMillis(),nodeLimitReached,whileLoopCount,nodePoolCount); } Node *lastNode= node; diff --git a/source/glest_game/game/game.cpp b/source/glest_game/game/game.cpp index ece7b570..1f70a68d 100644 --- a/source/glest_game/game/game.cpp +++ b/source/glest_game/game/game.cpp @@ -1701,7 +1701,7 @@ void Game::render2d(){ str+= "Render FPS: " + intToStr(lastRenderFps) + "[" + intToStr(avgRenderFps) + "]\n"; str+= "Update FPS: " + intToStr(lastUpdateFps) + "[" + intToStr(avgUpdateFps) + "]\n"; str+= "GameCamera pos: " + floatToStr(gameCamera.getPos().x)+","+floatToStr(gameCamera.getPos().y)+","+floatToStr(gameCamera.getPos().z)+"\n"; - str+= "Cached surfacedata: " + intToStr(renderer.getCachedSurfaceDataSize()); + str+= "Cached surfacedata: " + intToStr(renderer.getCachedSurfaceDataSize())+"\n"; str+= "Time: " + floatToStr(world.getTimeFlow()->getTime(),2)+"\n"; if(SystemFlags::getThreadedLoggerRunning() == true) { str+= "Log buffer count: " + intToStr(SystemFlags::getLogEntryBufferCount())+"\n"; diff --git a/source/glest_game/menu/menu_state_connected_game.cpp b/source/glest_game/menu/menu_state_connected_game.cpp index 7a535aed..7ccd1ed9 100644 --- a/source/glest_game/menu/menu_state_connected_game.cpp +++ b/source/glest_game/menu/menu_state_connected_game.cpp @@ -889,6 +889,8 @@ void MenuStateConnectedGame::update() { string file = Map::getMapPath(gameSettings->getMap(),"",false); checksum.addFile(file); int32 mapCRC = checksum.getSum(); + // Test data synch + //mapCRC++; safeMutexFTPProgress.ReleaseLock(); bool dataSynchMismatch = ((mapCRC != 0 && mapCRC != gameSettings->getMapCRC()) ||