diff --git a/AI/VCAI/VCAI.cpp b/AI/VCAI/VCAI.cpp index 2c4c98c00..5edea5f1a 100644 --- a/AI/VCAI/VCAI.cpp +++ b/AI/VCAI/VCAI.cpp @@ -1408,24 +1408,6 @@ bool VCAI::isGoodForVisit(const CGObjectInstance *obj, HeroPtr h, SectorMap &sm) return false; } -std::vector VCAI::getPossibleDestinations(HeroPtr h) -{ - validateVisitableObjs(); - std::vector possibleDestinations; - auto sm = getCachedSectorMap(h); - for(const CGObjectInstance *obj : visitableObjs) - { - if (isGoodForVisit(obj, h, *sm)) - { - possibleDestinations.push_back(obj); - } - } - - boost::sort(possibleDestinations, CDistanceSorter(h.get())); - - return possibleDestinations; -} - bool VCAI::isTileNotReserved(const CGHeroInstance * h, int3 t) { if (t.valid()) @@ -1468,20 +1450,41 @@ void VCAI::wander(HeroPtr h) while (h->movement) { validateVisitableObjs(); - std::vector dests, tmp; + std::vector dests; auto sm = getCachedSectorMap(h); - range::copy(reservedHeroesMap[h], std::back_inserter(tmp)); //also visit our reserved objects - but they are not prioritized to avoid running back and forth - for (auto obj : tmp) + //also visit our reserved objects - but they are not prioritized to avoid running back and forth + vstd::copy_if(reservedHeroesMap[h], std::back_inserter(dests), [&](ObjectIdRef obj) -> bool { int3 pos = sm->firstTileToGet(h, obj->visitablePos()); - if (pos.valid()) - if (isAccessibleForHero (pos, h)) //even nearby objects could be blocked by other heroes :( - dests.push_back(obj); //can't use lambda for member function :( + if(pos.valid() && isAccessibleForHero(pos, h)) //even nearby objects could be blocked by other heroes :( + return true; + + return false; + }); + + int pass = 0; + while(!dests.size() && pass < 3) + { + if(pass < 2) // optimization - first check objects in current sector; then in sectors around + { + auto objs = sm->getNearbyObjs(h, pass); + vstd::copy_if(objs, std::back_inserter(dests), [&](ObjectIdRef obj) -> bool + { + return isGoodForVisit(obj, h, *sm); + }); + } + else // we only check full objects list if for some reason there are no objects in closest sectors + { + vstd::copy_if(visitableObjs, std::back_inserter(dests), [&](ObjectIdRef obj) -> bool + { + return isGoodForVisit(obj, h, *sm); + }); + } + pass++; } - range::copy(getPossibleDestinations(h), std::back_inserter(dests)); vstd::erase_if(dests, [&](ObjectIdRef obj) -> bool { return !isSafeToVisit(h, sm->firstTileToGet(h, obj->visitablePos())); @@ -1691,9 +1694,6 @@ void VCAI::clearPathsInfo() void VCAI::validateVisitableObjs() { - std::vector hlp; - retreiveVisitableObjs(hlp, true); - std::string errorMsg; auto shouldBeErased = [&](const CGObjectInstance *obj) -> bool { @@ -1701,15 +1701,6 @@ void VCAI::validateVisitableObjs() return !cb->getObj(obj->id, false); // no verbose output needed as we check object visibility else return true; - - //why would we have our local logic for object checks? use cb! - - //if(!vstd::contains(hlp, obj)) - //{ - // logAi->errorStream() << helperObjInfo[obj].name << " at " << helperObjInfo[obj].pos << errorMsg; - // return true; - //} - //return false; }; //errorMsg is captured by ref so lambda will take the new text @@ -1764,7 +1755,7 @@ std::vector VCAI::getFlaggedObjects() const std::vector ret; for(const CGObjectInstance *obj : visitableObjs) { - if(obj->tempOwner == ai->playerID) + if(obj->tempOwner == playerID) ret.push_back(obj); } return ret; @@ -3070,10 +3061,7 @@ void SectorMap::exploreNewSector(crint3 pos, int num, CCallback * cbp) if(t->visitable) { auto obj = t->visitableObjects.front(); - if (vstd::contains(ai->knownSubterraneanGates, obj)) - { - s.subterraneanGates.push_back (obj); - } + s.visitableObjs.push_back(obj); } } } @@ -3463,3 +3451,19 @@ TerrainTile* SectorMap::getTile(crint3 pos) const //still we cached this array to avoid any checks return visibleTiles->operator[](pos.x)[pos.y][pos.z]; } + +std::vector SectorMap::getNearbyObjs(HeroPtr h, bool sectorsAround) +{ + const Sector *heroSector = &infoOnSectors[retreiveTile(h->visitablePos())]; + if(sectorsAround) + { + std::vector ret; + for(auto embarkPoint : heroSector->embarkmentPoints) + { + const Sector *embarkSector = &infoOnSectors[retreiveTile(embarkPoint)]; + range::copy(embarkSector->visitableObjs, std::back_inserter(ret)); + } + return ret; + } + return heroSector->visitableObjs; +} diff --git a/AI/VCAI/VCAI.h b/AI/VCAI/VCAI.h index d68b15c77..b35662d2a 100644 --- a/AI/VCAI/VCAI.h +++ b/AI/VCAI/VCAI.h @@ -79,7 +79,7 @@ struct SectorMap int id; std::vector tiles; std::vector embarkmentPoints; //tiles of other sectors onto which we can (dis)embark - std::vector subterraneanGates; + std::vector visitableObjs; bool water; //all tiles of sector are land or water Sector() { @@ -106,6 +106,7 @@ struct SectorMap bool markIfBlocked(ui8 &sec, crint3 pos); unsigned char &retreiveTile(crint3 pos); TerrainTile* getTile(crint3 pos) const; + std::vector getNearbyObjs(HeroPtr h, bool sectorsAround); void makeParentBFS(crint3 source); @@ -259,7 +260,6 @@ public: void recruitHero(const CGTownInstance * t, bool throwing = false); bool isGoodForVisit(const CGObjectInstance *obj, HeroPtr h, SectorMap &sm); - std::vector getPossibleDestinations(HeroPtr h); void buildStructure(const CGTownInstance * t); //void recruitCreatures(const CGTownInstance * t); void recruitCreatures(const CGDwelling * d, const CArmedInstance * recruiter); diff --git a/lib/CGameInterface.cpp b/lib/CGameInterface.cpp index 2f73d6782..8d301b394 100644 --- a/lib/CGameInterface.cpp +++ b/lib/CGameInterface.cpp @@ -36,8 +36,8 @@ extern "C" DLL_EXPORT void BattleAI_GetNewBattleAI(std::shared_ptr std::shared_ptr createAny(const boost::filesystem::path& libpath, const std::string& methodName) { - typedef void(*TGetAIFun)(std::shared_ptr&); - typedef void(*TGetNameFun)(char*); + typedef void(*TGetAIFun)(std::shared_ptr&); + typedef void(*TGetNameFun)(char*); char temp[150]; @@ -105,7 +105,7 @@ std::shared_ptr createAny(const boost::filesystem::path& libpath, const st std::shared_ptr ret; getAI(ret); if(!ret) - logGlobal->errorStream() << "Cannot get AI!"; + logGlobal->error("Cannot get AI!"); return ret; } diff --git a/lib/CGameState.cpp b/lib/CGameState.cpp index a5583f048..40b9ce11e 100644 --- a/lib/CGameState.cpp +++ b/lib/CGameState.cpp @@ -490,12 +490,12 @@ int CGameState::pickUnusedHeroTypeRandomly(PlayerColor owner) return RandomGeneratorUtil::nextItem(otherHeroes, rand)->getNum(); } - logGlobal->errorStream() << "No free allowed heroes!"; + logGlobal->error("No free allowed heroes!"); auto notAllowedHeroesButStillBetterThanCrash = getUnusedAllowedHeroes(true); if(notAllowedHeroesButStillBetterThanCrash.size()) return notAllowedHeroesButStillBetterThanCrash.begin()->getNum(); - logGlobal->errorStream() << "No free heroes at all!"; + logGlobal->error("No free heroes at all!"); assert(0); //current code can't handle this situation return -1; // no available heroes at all } @@ -769,13 +769,13 @@ void CGameState::init(StartInfo * si) return; } VLC->arth->initAllowedArtifactsList(map->allowedArtifact); - logGlobal->infoStream() << "Map loaded!"; + logGlobal->info("Map loaded!"); checkMapChecksum(); day = 0; - logGlobal->debugStream() << "Initialization:"; + logGlobal->debug("Initialization:"); initPlayerStates(); placeCampaignHeroes(); @@ -792,7 +792,7 @@ void CGameState::init(StartInfo * si) initVisitingAndGarrisonedHeroes(); initFogOfWar(); - logGlobal->debugStream() << "\tChecking objectives"; + logGlobal->debug("\tChecking objectives"); map->checkForObjectives(); //needs to be run when all objects are properly placed auto seedAfterInit = rand.nextInt(); @@ -812,7 +812,7 @@ void CGameState::initNewGame() { if(scenarioOps->createRandomMap()) { - logGlobal->infoStream() << "Create random map."; + logGlobal->info("Create random map."); CStopWatch sw; // Gen map @@ -874,7 +874,7 @@ void CGameState::initDuel() { logGlobal->infoStream() << "Loading duel settings from JSON file: " << scenarioOps->mapname; dp = DuelParameters::fromJSON(scenarioOps->mapname); - logGlobal->infoStream() << "JSON file has been successfully read!"; + logGlobal->info("JSON file has been successfully read!"); } else { @@ -974,7 +974,7 @@ void CGameState::checkMapChecksum() logGlobal->infoStream() << "\tServer checksum for " << scenarioOps->mapname <<": "<< scenarioOps->mapfileChecksum; if(map->checksum != scenarioOps->mapfileChecksum) { - logGlobal->errorStream() << "Wrong map checksum!!!"; + logGlobal->error("Wrong map checksum!!!"); throw std::runtime_error("Wrong checksum"); } } @@ -986,7 +986,7 @@ void CGameState::checkMapChecksum() void CGameState::initGrailPosition() { - logGlobal->debugStream() << "\tPicking grail position"; + logGlobal->debug("\tPicking grail position"); //pick grail location if(map->grailPos.x < 0 || map->grailRadius) //grail not set or set within a radius around some place { @@ -1025,14 +1025,14 @@ void CGameState::initGrailPosition() } else { - logGlobal->warnStream() << "Warning: Grail cannot be placed, no appropriate tile found!"; + logGlobal->warn("Grail cannot be placed, no appropriate tile found!"); } } } void CGameState::initRandomFactionsForPlayers() { - logGlobal->debugStream() << "\tPicking random factions for players"; + logGlobal->debug("\tPicking random factions for players"); for(auto & elem : scenarioOps->playerInfos) { if(elem.second.castle==-1) @@ -1048,7 +1048,7 @@ void CGameState::initRandomFactionsForPlayers() void CGameState::randomizeMapObjects() { - logGlobal->debugStream() << "\tRandomizing objects"; + logGlobal->debug("\tRandomizing objects"); for(CGObjectInstance *obj : map->objects) { if(!obj) continue; @@ -1072,7 +1072,7 @@ void CGameState::randomizeMapObjects() void CGameState::initPlayerStates() { - logGlobal->debugStream() << "\tCreating player entries in gs"; + logGlobal->debug("\tCreating player entries in gs"); for(auto & elem : scenarioOps->playerInfos) { std::pair ins(elem.first,PlayerState()); @@ -1114,10 +1114,10 @@ void CGameState::placeCampaignHeroes() if(!crossoverHeroes.heroesFromAnyPreviousScenarios.empty()) { - logGlobal->debugStream() << "\tGenerate list of hero placeholders"; + logGlobal->debug("\tGenerate list of hero placeholders"); auto campaignHeroReplacements = generateCampaignHeroesToReplace(crossoverHeroes); - logGlobal->debugStream() << "\tPrepare crossover heroes"; + logGlobal->debug("\tPrepare crossover heroes"); prepareCrossoverHeroes(campaignHeroReplacements, scenarioOps->campState->getCurrentScenario().travelOptions); // remove same heroes on the map which will be added through crossover heroes @@ -1137,7 +1137,7 @@ void CGameState::placeCampaignHeroes() } } - logGlobal->debugStream() << "\tReplace placeholders with heroes"; + logGlobal->debug("\tReplace placeholders with heroes"); replaceHeroesPlaceholders(campaignHeroReplacements); // remove hero placeholders on map @@ -1169,7 +1169,7 @@ void CGameState::placeCampaignHeroes() } else { - logGlobal->errorStream() << "No free hero type ID found to replace prison."; + logGlobal->error("No free hero type ID found to replace prison."); assert(0); } } @@ -1365,7 +1365,7 @@ void CGameState::prepareCrossoverHeroes(std::vectordebugStream() << "\tGiving starting hero"; + logGlobal->debug("\tGiving starting hero"); for(auto & playerSettingPair : scenarioOps->playerInfos) { @@ -1393,7 +1393,7 @@ void CGameState::placeStartingHeroes() void CGameState::initStartingResources() { - logGlobal->debugStream() << "\tSetting up resources"; + logGlobal->debug("\tSetting up resources"); const JsonNode config(ResourceID("config/startres.json")); const JsonVector &vector = config["difficulty"].Vector(); const JsonNode &level = vector[scenarioOps->difficulty]; @@ -1465,7 +1465,7 @@ void CGameState::initHeroes() { if (hero->getOwner() == PlayerColor::UNFLAGGABLE) { - logGlobal->warnStream() << "Warning - hero with uninitialized owner!"; + logGlobal->warn("Hero with uninitialized owner!"); continue; } @@ -1539,7 +1539,7 @@ void CGameState::initHeroes() } } if(maxB < 0) - logGlobal->warnStream() << "Warning - cannot give bonus to hero cause there are no heroes!"; + logGlobal->warn("Cannot give bonus to hero cause there are no heroes!"); else giveCampaignBonusToHero(heroes[maxB]); } @@ -1617,7 +1617,7 @@ void CGameState::giveCampaignBonusToHero(CGHeroInstance * hero) void CGameState::initFogOfWar() { - logGlobal->debugStream() << "\tFog of war"; //FIXME: should be initialized after all bonuses are set + logGlobal->debug("\tFog of war"); //FIXME: should be initialized after all bonuses are set for(auto & elem : teams) { elem.second.fogOfWarMap.resize(map->width); @@ -1649,7 +1649,7 @@ void CGameState::initFogOfWar() void CGameState::initStartingBonus() { - logGlobal->debugStream() << "\tStarting bonuses"; + logGlobal->debug("\tStarting bonuses"); for(auto & elem : players) { //starting bonus @@ -1679,7 +1679,7 @@ void CGameState::initStartingBonus() { if(!elem.second.heroes.size()) { - logGlobal->debugStream() << "Cannot give starting artifact - no heroes!"; + logGlobal->error("Cannot give starting artifact - no heroes!"); break; } CArtifact *toGive; @@ -1695,7 +1695,7 @@ void CGameState::initStartingBonus() void CGameState::initTowns() { - logGlobal->debugStream() << "\tTowns"; + logGlobal->debug("\tTowns"); //campaign bonuses for towns if (scenarioOps->mode == StartInfo::CAMPAIGN) @@ -1846,7 +1846,7 @@ void CGameState::initTowns() void CGameState::initMapObjects() { - logGlobal->debugStream() << "\tObject initialization"; + logGlobal->debug("\tObject initialization"); // objCaller->preInit(); for(CGObjectInstance *obj : map->objects) { diff --git a/lib/CGeneralTextHandler.cpp b/lib/CGeneralTextHandler.cpp index 03465d888..196ce5208 100644 --- a/lib/CGeneralTextHandler.cpp +++ b/lib/CGeneralTextHandler.cpp @@ -132,7 +132,7 @@ void Unicode::trimRight(std::string & text, const size_t amount/* =1 */) return; //todo: more efficient algorithm for(int i = 0; i< amount; i++){ - auto b = text.begin(); + auto b = text.begin(); auto e = text.end(); size_t lastLen = 0; size_t len = 0; @@ -141,14 +141,14 @@ void Unicode::trimRight(std::string & text, const size_t amount/* =1 */) size_t n = getCharacterSize(*b); if(!isValidCharacter(&(*b),e-b)) - { - logGlobal->errorStream() << "Invalid UTF8 sequence"; + { + logGlobal->error("Invalid UTF8 sequence"); break;//invalid sequence will be trimmed } len += n; b += n; - } + } text.resize(lastLen); } @@ -217,13 +217,13 @@ std::string CLegacyConfigParser::extractQuotedString() char * begin = curr; while (curr < end && *curr != '\t' && *curr != '\r' && *curr != '\"')//find end of string or next quoted part start - curr++; - + curr++; + ret += std::string(begin, curr); - + if(curr>=end || *curr != '\"') return ret; - } + } else // end of string return ret; } diff --git a/lib/CHeroHandler.cpp b/lib/CHeroHandler.cpp index 76d4da3cb..3cf76d536 100644 --- a/lib/CHeroHandler.cpp +++ b/lib/CHeroHandler.cpp @@ -80,7 +80,7 @@ std::vector CObstacleInfo::getBlocked(BattleHex hex) const toBlock += BattleHex::LEFT; if(!toBlock.isValid()) - logGlobal->errorStream() << "Misplaced obstacle!"; + logGlobal->error("Misplaced obstacle!"); else ret.push_back(toBlock); } @@ -577,7 +577,7 @@ ui64 CHeroHandler::reqExp (ui32 level) const } else { - logGlobal->warnStream() << "A hero has reached unsupported amount of experience"; + logGlobal->warn("A hero has reached unsupported amount of experience"); return expPerLevel[expPerLevel.size()-1]; } } diff --git a/lib/Connection.cpp b/lib/Connection.cpp index 9e2f3e3a0..2a491885a 100644 --- a/lib/Connection.cpp +++ b/lib/Connection.cpp @@ -113,11 +113,11 @@ CConnection::CConnection(std::string host, std::string port, std::string Name) //we shouldn't be here - error handling connerror1: - logNetwork->errorStream() << "Something went wrong... checking for error info"; + logNetwork->error("Something went wrong... checking for error info"); if(error) logNetwork->errorStream() << error; else - logNetwork->errorStream() << "No error info. "; + logNetwork->error("No error info."); delete io_service; //delete socket; throw std::runtime_error("Can't establish connection :("); diff --git a/test/CMapEditManagerTest.cpp b/test/CMapEditManagerTest.cpp index b1e2fd735..a60fad8bd 100644 --- a/test/CMapEditManagerTest.cpp +++ b/test/CMapEditManagerTest.cpp @@ -23,7 +23,7 @@ BOOST_AUTO_TEST_CASE(CMapEditManager_DrawTerrain_Type) { - logGlobal->infoStream() << "CMapEditManager_DrawTerrain_Type start"; + logGlobal->info("CMapEditManager_DrawTerrain_Type start"); try { auto map = make_unique(); @@ -103,21 +103,22 @@ BOOST_AUTO_TEST_CASE(CMapEditManager_DrawTerrain_Type) } catch(const std::exception & e) { - logGlobal->errorStream() << "CMapEditManager_DrawTerrain_Type crash" << "\n" << e.what(); + logGlobal->error("CMapEditManager_DrawTerrain_Type crash"); + logGlobal->error(e.what()); throw; } - logGlobal->infoStream() << "CMapEditManager_DrawTerrain_Type finish"; + logGlobal->info("CMapEditManager_DrawTerrain_Type finish"); } BOOST_AUTO_TEST_CASE(CMapEditManager_DrawTerrain_View) { - logGlobal->infoStream() << "CMapEditManager_DrawTerrain_View start"; + logGlobal->info("CMapEditManager_DrawTerrain_View start"); try { // Load maps and json config const auto originalMap = CMapService::loadMap("test/TerrainViewTest"); auto map = CMapService::loadMap("test/TerrainViewTest"); - logGlobal->infoStream() << "Loaded test map successfully."; + logGlobal->info("Loaded test map successfully."); // Validate edit manager auto editManager = map->getEditManager(); @@ -163,14 +164,16 @@ BOOST_AUTO_TEST_CASE(CMapEditManager_DrawTerrain_View) } } BOOST_CHECK(isInRange); - if(!isInRange) logGlobal->errorStream() << "No or invalid pattern found for current position."; + if(!isInRange) + logGlobal->error("No or invalid pattern found for current position."); } } } catch(const std::exception & e) { - logGlobal->infoStream() << "CMapEditManager_DrawTerrain_View crash"<< "\n" << e.what(); + logGlobal->info("CMapEditManager_DrawTerrain_View crash"); + logGlobal->info(e.what()); throw; } - logGlobal->infoStream() << "CMapEditManager_DrawTerrain_View finish"; + logGlobal->info("CMapEditManager_DrawTerrain_View finish"); } diff --git a/test/CMapFormatTest.cpp b/test/CMapFormatTest.cpp index 9e4ace40d..2fa859b86 100644 --- a/test/CMapFormatTest.cpp +++ b/test/CMapFormatTest.cpp @@ -78,7 +78,8 @@ BOOST_AUTO_TEST_CASE(CMapFormatVCMI_Simple) tmp.flush(); tmp.close(); - logGlobal->infoStream() << "Test map has been saved to " << path; + logGlobal->info("Test map has been saved to:"); + logGlobal->info(path.string()); } BOOST_TEST_CHECKPOINT("CMapFormatVCMI_Simple saved"); diff --git a/test/CVcmiTestConfig.cpp b/test/CVcmiTestConfig.cpp index 96a36ddfd..7497bbc64 100644 --- a/test/CVcmiTestConfig.cpp +++ b/test/CVcmiTestConfig.cpp @@ -31,7 +31,7 @@ CVcmiTestConfig::CVcmiTestConfig() settings.init(); logConfig.configure(); loadDLLClasses(); - logGlobal->infoStream() << "Initialized global test setup."; + logGlobal->info("Initialized global test setup."); const std::string TEST_DATA_DIR = "test/";