1
0
mirror of https://github.com/vcmi/vcmi.git synced 2025-11-27 22:49:25 +02:00

Bring back cbc in CAdventureAI and rename the rest to cc

This commit is contained in:
Mircea TheHonestCTO
2025-08-16 20:17:18 +02:00
parent 6eb7bb2ca5
commit bf3d5627e0
46 changed files with 319 additions and 317 deletions

View File

@@ -40,7 +40,7 @@ namespace NK2AI
{
//one thread may be turn of AI and another will be handling a side effect for AI2
thread_local CCallback * cbcTl = nullptr;
thread_local CCallback * ccTl = nullptr;
thread_local AIGateway * aiGwTl = nullptr;
//helper RAII to manage global ai/cb ptrs
@@ -49,17 +49,17 @@ struct SetGlobalState
SetGlobalState(AIGateway * gateway)
{
assert(!aiGwTl);
assert(!cbcTl);
assert(!ccTl);
aiGwTl = gateway;
cbcTl = gateway->cbc.get();
ccTl = gateway->cc.get();
}
~SetGlobalState()
{
//TODO: how to handle rm? shouldn't be called after ai is destroyed, hopefully
//TODO: to ensure that, make rm unique_ptr
aiGwTl = nullptr;
cbcTl = nullptr;
ccTl = nullptr;
}
};
@@ -97,7 +97,7 @@ void AIGateway::heroMoved(const TryMoveHero & details, bool verbose)
LOG_TRACE(logAi);
NET_EVENT_HANDLER;
auto hero = cbc->getHero(details.id);
auto hero = cc->getHero(details.id);
if(!hero)
validateObject(details.id); //enemy hero may have left visible area
@@ -107,8 +107,8 @@ void AIGateway::heroMoved(const TryMoveHero & details, bool verbose)
const int3 from = hero ? hero->convertToVisitablePos(details.start) : (details.start - int3(0,1,0));
const int3 to = hero ? hero->convertToVisitablePos(details.end) : (details.end - int3(0,1,0));
const CGObjectInstance * o1 = vstd::frontOrNull(cbc->getVisitableObjs(from, verbose));
const CGObjectInstance * o2 = vstd::frontOrNull(cbc->getVisitableObjs(to, verbose));
const CGObjectInstance * o1 = vstd::frontOrNull(cc->getVisitableObjs(from, verbose));
const CGObjectInstance * o2 = vstd::frontOrNull(cc->getVisitableObjs(to, verbose));
if(details.result == TryMoveHero::TELEPORTATION)
{
@@ -116,7 +116,7 @@ void AIGateway::heroMoved(const TryMoveHero & details, bool verbose)
auto t2 = dynamic_cast<const CGTeleport *>(o2);
if(t1 && t2)
{
if(cbc->isTeleportChannelBidirectional(t1->channel))
if(cc->isTeleportChannelBidirectional(t1->channel))
{
if(o1->ID == Obj::SUBTERRANEAN_GATE && o1->ID == o2->ID) // We need to only add subterranean gates in knownSubterraneanGates. Used for features not yet ported to use teleport channels
{
@@ -134,7 +134,7 @@ void AIGateway::heroMoved(const TryMoveHero & details, bool verbose)
{
auto boat = dynamic_cast<const CGBoat *>(o1);
if(boat)
memorizeVisitableObj(boat, nullkiller->memory, nullkiller->dangerHitMap, playerID, cbc);
memorizeVisitableObj(boat, nullkiller->memory, nullkiller->dangerHitMap, playerID, cc);
}
}
@@ -214,7 +214,7 @@ void AIGateway::gameOver(PlayerColor player, const EVictoryLossCheckResult & vic
if(victoryLossCheckResult.victory())
{
logAi->debug("AIGateway: Player %d (%s) won. I won! Incredible!", player, player.toString());
logAi->debug("Turn nr %d", cbc->getDate());
logAi->debug("Turn nr %d", cc->getDate());
}
else
{
@@ -274,7 +274,7 @@ void AIGateway::tileHidden(const FowTilesType & pos)
LOG_TRACE(logAi);
NET_EVENT_HANDLER;
nullkiller->memory->removeInvisibleObjects(cbc.get());
nullkiller->memory->removeInvisibleObjects(cc.get());
}
void AIGateway::tileRevealed(const FowTilesType & pos)
@@ -283,8 +283,8 @@ void AIGateway::tileRevealed(const FowTilesType & pos)
NET_EVENT_HANDLER;
for(int3 tile : pos)
{
for(const CGObjectInstance * obj : cbc->getVisitableObjs(tile))
memorizeVisitableObj(obj, nullkiller->memory, nullkiller->dangerHitMap, playerID, cbc);
for(const CGObjectInstance * obj : cc->getVisitableObjs(tile))
memorizeVisitableObj(obj, nullkiller->memory, nullkiller->dangerHitMap, playerID, cc);
}
if (nullkiller->settings->isUpdateHitmapOnTileReveal() && !pos.empty())
@@ -296,8 +296,8 @@ void AIGateway::heroExchangeStarted(ObjectInstanceID hero1, ObjectInstanceID her
LOG_TRACE(logAi);
NET_EVENT_HANDLER;
auto firstHero = cbc->getHero(hero1);
auto secondHero = cbc->getHero(hero2);
auto firstHero = cc->getHero(hero1);
auto secondHero = cc->getHero(hero2);
status.addQuery(query, boost::str(boost::format("Exchange between heroes %s (%d) and %s (%d)") % firstHero->getNameTranslated() % firstHero->tempOwner % secondHero->getNameTranslated() % secondHero->tempOwner));
@@ -306,7 +306,7 @@ void AIGateway::heroExchangeStarted(ObjectInstanceID hero1, ObjectInstanceID her
auto transferFrom2to1 = [this](const CGHeroInstance * h1, const CGHeroInstance * h2) -> void
{
this->pickBestCreatures(h1, h2);
pickBestArtifacts(cbc, h1, h2);
pickBestArtifacts(cc, h1, h2);
};
//Do not attempt army or artifacts exchange if we visited ally player
@@ -370,7 +370,7 @@ void AIGateway::newObject(const CGObjectInstance * obj)
NET_EVENT_HANDLER;
nullkiller->invalidatePathfinderData();
if(obj->isVisitable())
memorizeVisitableObj(obj, nullkiller->memory, nullkiller->dangerHitMap, playerID, cbc);
memorizeVisitableObj(obj, nullkiller->memory, nullkiller->dangerHitMap, playerID, cc);
}
//to prevent AI from accessing objects that got deleted while they became invisible (Cover of Darkness, enemy hero moved etc.) below code allows AI to know deletion of objects out of sight
@@ -393,10 +393,10 @@ void AIGateway::objectRemoved(const CGObjectInstance * obj, const PlayerColor &
if(obj->ID == Obj::HERO && obj->tempOwner == playerID)
{
lostHero(cbc->getHero(obj->id)); //we can promote, since objectRemoved is called just before actual deletion
lostHero(cc->getHero(obj->id)); //we can promote, since objectRemoved is called just before actual deletion
}
if(obj->ID == Obj::HERO && cbc->getPlayerRelations(obj->tempOwner, playerID) == PlayerRelations::ENEMIES)
if(obj->ID == Obj::HERO && cc->getPlayerRelations(obj->tempOwner, playerID) == PlayerRelations::ENEMIES)
nullkiller->dangerHitMap->resetHitmap();
if(obj->ID == Obj::TOWN)
@@ -500,8 +500,8 @@ void AIGateway::objectPropertyChanged(const SetObjectProperty * sop)
NET_EVENT_HANDLER;
if(sop->what == ObjProperty::OWNER)
{
auto relations = cbc->getPlayerRelations(playerID, sop->identifier.as<PlayerColor>());
auto obj = cbc->getObj(sop->id, false);
auto relations = cc->getPlayerRelations(playerID, sop->identifier.as<PlayerColor>());
auto obj = cc->getObj(sop->id, false);
if(!nullkiller) // crash protection
return;
@@ -565,7 +565,7 @@ std::optional<BattleAction> AIGateway::makeSurrenderRetreatDecision(const Battle
double fightRatio = ourStrength / (double)battleState.getEnemyStrength();
// if we have no towns - things are already bad, so retreat is not an option.
if(cbc->getTownsInfo().size() && ourStrength < nullkiller->settings->getRetreatThresholdAbsolute() && fightRatio < nullkiller->settings->getRetreatThresholdRelative() && battleState.canFlee)
if(cc->getTownsInfo().size() && ourStrength < nullkiller->settings->getRetreatThresholdAbsolute() && fightRatio < nullkiller->settings->getRetreatThresholdRelative() && battleState.canFlee)
{
return BattleAction::makeRetreat(battleState.ourSide);
}
@@ -574,19 +574,20 @@ std::optional<BattleAction> AIGateway::makeSurrenderRetreatDecision(const Battle
}
void AIGateway::initGameInterface(std::shared_ptr<Environment> env, std::shared_ptr<CCallback> CB)
void AIGateway::initGameInterface(std::shared_ptr<Environment> env, std::shared_ptr<CCallback> callback)
{
LOG_TRACE(logAi);
cbc = CB;
cbc = callback;
cc = callback;
this->env = env;
NET_EVENT_HANDLER;
playerID = *cbc->getPlayerID();
cbc->waitTillRealize = true;
playerID = *cc->getPlayerID();
cc->waitTillRealize = true;
nullkiller->init(CB, this);
nullkiller->init(callback, this);
memorizeVisitableObjs(nullkiller->memory, nullkiller->dangerHitMap, playerID, cbc);
memorizeVisitableObjs(nullkiller->memory, nullkiller->dangerHitMap, playerID, cc);
}
void AIGateway::yourTurn(QueryID queryID)
@@ -656,7 +657,7 @@ void AIGateway::showBlockingDialog(const std::string & text, const std::vector<C
{
//yes&no -> always answer yes, we are a brave AI :)
bool answer = true;
auto objects = cbc->getVisitableObjs(target);
auto objects = cc->getVisitableObjs(target);
if(hero.validAndSet() && target.isValid() && objects.size())
{
@@ -676,9 +677,9 @@ void AIGateway::showBlockingDialog(const std::string & text, const std::vector<C
logAi->trace("Query hook: %s(%s) by %s danger ratio %f", target.toString(), topObj->getObjectName(), hero.name(), ratio);
if(cbc->getObj(goalObjectID, false))
if(cc->getObj(goalObjectID, false))
{
logAi->trace("AI expected %s", cbc->getObj(goalObjectID, false)->getObjectName());
logAi->trace("AI expected %s", cc->getObj(goalObjectID, false)->getObjectName());
}
if(objType == Obj::BORDERGUARD || objType == Obj::QUEST_GUARD)
@@ -753,7 +754,7 @@ void AIGateway::showTeleportDialog(const CGHeroInstance * hero, TeleportChannelI
{
// TODO: Implement checking if visiting that teleport will uncovert any FoW
// So far this is the best option to handle decision about probing
auto obj = cbc->getObj(exit.first, false);
auto obj = cc->getObj(exit.first, false);
if(obj == nullptr && !vstd::contains(teleportChannelProbingList, exit.first))
{
if(exit.first != destinationTeleport)
@@ -781,7 +782,7 @@ void AIGateway::showGarrisonDialog(const CArmedInstance * up, const CGHeroInstan
//you can't request action from action-response thread
executeActionAsync("showGarrisonDialog", [this, up, down, removableUnits, queryID]()
{
if(removableUnits && up->tempOwner == down->tempOwner && nullkiller->settings->isGarrisonTroopsUsageAllowed() && !cbc->getStartInfo()->restrictedGarrisonsForAI())
if(removableUnits && up->tempOwner == down->tempOwner && nullkiller->settings->isGarrisonTroopsUsageAllowed() && !cc->getStartInfo()->restrictedGarrisonsForAI())
{
pickBestCreatures(down, up);
}
@@ -811,7 +812,7 @@ bool AIGateway::makePossibleUpgrades(const CArmedInstance * obj)
UpgradeInfo upgradeInfo(s->getId());
do
{
cbc->fillUpgradeInfo(obj, SlotID(i), upgradeInfo);
cc->fillUpgradeInfo(obj, SlotID(i), upgradeInfo);
if(upgradeInfo.hasUpgrades())
{
@@ -826,7 +827,7 @@ bool AIGateway::makePossibleUpgrades(const CArmedInstance * obj)
if(newValue > oldValue && nullkiller->getFreeResources().canAfford(upgradeInfo.getUpgradeCostsFor(upgID) * s->getCount()))
{
cbc->upgradeCreature(obj, SlotID(i), upgID);
cc->upgradeCreature(obj, SlotID(i), upgID);
upgraded = true;
logAi->debug("Upgraded %d %s to %s", s->getCount(), upgradeInfo.oldID.toCreature()->getNamePluralTranslated(),
upgradeInfo.getUpgrade().toCreature()->getNamePluralTranslated());
@@ -846,21 +847,21 @@ void AIGateway::makeTurn()
{
MAKING_TURN;
auto day = cbc->getDate(Date::DAY);
auto day = cc->getDate(Date::DAY);
logAi->info("Player %d (%s) starting turn, day %d", playerID, playerID.toString(), day);
std::shared_lock gsLock(CGameState::mutex);
cheatMapReveal(nullkiller);
memorizeVisitableObjs(nullkiller->memory, nullkiller->dangerHitMap, playerID, cbc);
memorizeRevisitableObjs(nullkiller->memory, playerID, cbc);
memorizeVisitableObjs(nullkiller->memory, nullkiller->dangerHitMap, playerID, cc);
memorizeRevisitableObjs(nullkiller->memory, playerID, cc);
try
{
nullkiller->makeTurn();
// for debug purpose
for (const auto *h : cbc->getHeroesInfo())
for (const auto *h : cc->getHeroesInfo())
{
if (h->movementPointsRemaining())
logAi->info("Hero %s has %d MP left", h->getNameTranslated(), h->movementPointsRemaining());
@@ -905,7 +906,7 @@ void AIGateway::performObjectInteraction(const CGObjectInstance * obj, HeroPtr h
&& nullkiller->getFreeGold() >= GameConstants::SPELLBOOK_GOLD_COST)
{
if(h->getVisitedTown()->hasBuilt(BuildingID::MAGES_GUILD_1))
cbc->buyArtifact(h.get(), ArtifactID::SPELLBOOK);
cc->buyArtifact(h.get(), ArtifactID::SPELLBOOK);
}
}
break;
@@ -930,14 +931,14 @@ void AIGateway::pickBestCreatures(const CArmedInstance * destinationArmy, const
const CArmedInstance * armies[] = {destinationArmy, source};
auto bestArmy = nullkiller->armyManager->getBestArmy(destinationArmy, destinationArmy, source, cbc->getTile(source->visitablePos())->getTerrainID());
auto bestArmy = nullkiller->armyManager->getBestArmy(destinationArmy, destinationArmy, source, cc->getTile(source->visitablePos())->getTerrainID());
for(auto army : armies)
{
// move first stack at first slot if empty to avoid can not take away last creature
if(!army->hasStackAtSlot(SlotID(0)) && army->stacksCount() > 0)
{
cbc->mergeOrSwapStacks(
cc->mergeOrSwapStacks(
army,
army,
SlotID(0),
@@ -958,12 +959,12 @@ void AIGateway::pickBestCreatures(const CArmedInstance * destinationArmy, const
if(targetSlot.validSlot())
{
// remove unwanted creatures
cbc->mergeOrSwapStacks(destinationArmy, source, i, targetSlot);
cc->mergeOrSwapStacks(destinationArmy, source, i, targetSlot);
}
else if(destinationArmy->getStack(i).getPower() < destinationArmy->getArmyStrength() / 100)
{
// dismiss creatures if the amount is small
cbc->dismissCreature(destinationArmy, i);
cc->dismissCreature(destinationArmy, i);
}
}
@@ -984,7 +985,7 @@ void AIGateway::pickBestCreatures(const CArmedInstance * destinationArmy, const
&& source->stacksCount() == 1
&& (!destinationArmy->hasStackAtSlot(i) || destinationArmy->getCreature(i) == targetCreature))
{
auto weakest = nullkiller->armyManager->getBestUnitForScout(bestArmy, cbc->getTile(source->visitablePos())->getTerrainID());
auto weakest = nullkiller->armyManager->getBestUnitForScout(bestArmy, cc->getTile(source->visitablePos())->getTerrainID());
if(weakest->creature == targetCreature)
{
@@ -992,7 +993,7 @@ void AIGateway::pickBestCreatures(const CArmedInstance * destinationArmy, const
break;
// move all except 1 of weakest creature from source to destination
cbc->splitStack(
cc->splitStack(
source,
destinationArmy,
j,
@@ -1004,7 +1005,7 @@ void AIGateway::pickBestCreatures(const CArmedInstance * destinationArmy, const
else
{
// Source last stack is not weakest. Move 1 of weakest creature from destination to source
cbc->splitStack(
cc->splitStack(
destinationArmy,
source,
destinationArmy->getSlotFor(weakest->creature),
@@ -1013,7 +1014,7 @@ void AIGateway::pickBestCreatures(const CArmedInstance * destinationArmy, const
}
}
cbc->mergeOrSwapStacks(armyPtr, destinationArmy, j, i);
cc->mergeOrSwapStacks(armyPtr, destinationArmy, j, i);
}
}
}
@@ -1044,7 +1045,7 @@ void AIGateway::recruitCreatures(const CGDwelling * d, const CArmedInstance * re
if(duplicatingSlot != stack.first)
{
cbc->mergeStacks(recruiter, recruiter, stack.first, duplicatingSlot);
cc->mergeStacks(recruiter, recruiter, stack.first, duplicatingSlot);
break;
}
}
@@ -1055,9 +1056,9 @@ void AIGateway::recruitCreatures(const CGDwelling * d, const CArmedInstance * re
}
}
vstd::amin(count, cbc->getResourceAmount() / creID.toCreature()->getFullRecruitCost());
vstd::amin(count, cc->getResourceAmount() / creID.toCreature()->getFullRecruitCost());
if(count > 0)
cbc->recruitCreatures(d, recruiter, creID, count, i);
cc->recruitCreatures(d, recruiter, creID, count, i);
}
}
@@ -1066,7 +1067,7 @@ void AIGateway::battleStart(const BattleID & battleID, const CCreatureSet * army
NET_EVENT_HANDLER;
assert(!playerID.isValidPlayer() || status.getBattle() == UPCOMING_BATTLE);
status.setBattle(ONGOING_BATTLE);
const CGObjectInstance * presumedEnemy = vstd::backOrNull(cbc->getVisitableObjs(tile)); //may be nullptr in some very are cases -> eg. visited monolith and fighting with an enemy at the FoW covered exit
const CGObjectInstance * presumedEnemy = vstd::backOrNull(cc->getVisitableObjs(tile)); //may be nullptr in some very are cases -> eg. visited monolith and fighting with an enemy at the FoW covered exit
battlename = boost::str(boost::format("Starting battle of %s attacking %s at %s") % (hero1 ? hero1->getNameTranslated() : "a army") % (presumedEnemy ? presumedEnemy->getObjectName() : "unknown enemy") % tile.toString());
CAdventureAI::battleStart(battleID, army1, army2, tile, hero1, hero2, side, replayAllowed);
}
@@ -1076,14 +1077,14 @@ void AIGateway::battleEnd(const BattleID & battleID, const BattleResult * br, Qu
NET_EVENT_HANDLER;
assert(status.getBattle() == ONGOING_BATTLE);
status.setBattle(ENDING_BATTLE);
bool won = br->winner == cbc->getBattle(battleID)->battleGetMySide();
bool won = br->winner == cc->getBattle(battleID)->battleGetMySide();
logAi->debug("Player %d (%s): I %s the %s!", playerID, playerID.toString(), (won ? "won" : "lost"), battlename);
battlename.clear();
CAdventureAI::battleEnd(battleID, br, queryID);
// gosolo
if(queryID != QueryID::NONE && cbc->getPlayerState(playerID)->isHuman())
if(queryID != QueryID::NONE && cc->getPlayerState(playerID)->isHuman())
{
status.addQuery(queryID, "Confirm battle query");
@@ -1115,7 +1116,7 @@ bool AIGateway::moveHeroToTile(int3 dst, HeroPtr h)
{
if(h->isGarrisoned() && h->getVisitedTown())
{
cbc->swapGarrisonHero(h->getVisitedTown());
cc->swapGarrisonHero(h->getVisitedTown());
moveCreaturesToHero(h->getVisitedTown());
}
@@ -1141,7 +1142,7 @@ bool AIGateway::moveHeroToTile(int3 dst, HeroPtr h)
{
//FIXME: this assertion fails also if AI moves onto defeated guarded object
//assert(cb->getVisitableObjs(dst).size() > 1); //there's no point in revisiting tile where there is no visitable object
cbc->moveHero(*h, h->convertFromVisitablePos(dst), false);
cc->moveHero(*h, h->convertFromVisitablePos(dst), false);
afterMovementCheck(); // TODO: is it feasible to hero get killed there if game work properly?
// If revisiting, teleport probing is never done, and so the entries into the list would remain unused and uncleared
teleportChannelProbingList.clear();
@@ -1161,9 +1162,9 @@ bool AIGateway::moveHeroToTile(int3 dst, HeroPtr h)
auto getObj = [&](int3 coord, bool ignoreHero)
{
auto tile = cbc->getTile(coord, false);
auto tile = cc->getTile(coord, false);
assert(tile);
return cbc->getObj(tile->topVisitableObj(ignoreHero), false);
return cc->getObj(tile->topVisitableObj(ignoreHero), false);
};
auto isTeleportAction = [&](EPathNodeAction action) -> bool
@@ -1194,12 +1195,12 @@ bool AIGateway::moveHeroToTile(int3 dst, HeroPtr h)
auto doMovement = [&](int3 dst, bool transit)
{
cbc->moveHero(*h, h->convertFromVisitablePos(dst), transit);
cc->moveHero(*h, h->convertFromVisitablePos(dst), transit);
};
auto doTeleportMovement = [&](ObjectInstanceID exitId, int3 exitPos)
{
if(cbc->getObj(exitId) && cbc->getObj(exitId)->ID == Obj::WHIRLPOOL)
if(cc->getObj(exitId) && cc->getObj(exitId)->ID == Obj::WHIRLPOOL)
{
nullkiller->armyFormation->rearrangeArmyForWhirlpool(*h);
}
@@ -1207,7 +1208,7 @@ bool AIGateway::moveHeroToTile(int3 dst, HeroPtr h)
destinationTeleport = exitId;
if(exitPos.isValid())
destinationTeleportPos = exitPos;
cbc->moveHero(*h, h->pos, false);
cc->moveHero(*h, h->pos, false);
destinationTeleport = ObjectInstanceID();
destinationTeleportPos = int3(-1);
afterMovementCheck();
@@ -1311,7 +1312,7 @@ bool AIGateway::moveHeroToTile(int3 dst, HeroPtr h)
}
if(h)
{
if(auto visitedObject = vstd::frontOrNull(cbc->getVisitableObjs(h->visitablePos()))) //we stand on something interesting
if(auto visitedObject = vstd::frontOrNull(cc->getVisitableObjs(h->visitablePos()))) //we stand on something interesting
{
if(visitedObject != *h)
{
@@ -1338,7 +1339,7 @@ void AIGateway::buildStructure(const CGTownInstance * t, BuildingID building)
{
auto name = t->getTown()->buildings.at(building)->getNameTranslated();
logAi->debug("Player %d will build %s in town of %s at %s", aiGwTl->playerID, name, t->getNameTranslated(), t->anchorPos().toString());
cbc->buildBuilding(t, building); //just do this;
cc->buildBuilding(t, building); //just do this;
}
void AIGateway::tryRealize(Goals::DigAtTile & g)
@@ -1346,7 +1347,7 @@ void AIGateway::tryRealize(Goals::DigAtTile & g)
assert(g.hero->visitablePos() == g.tile); //surely we want to crash here?
if(g.hero->diggingStatus() == EDiggingStatus::CAN_DIG)
{
cbc->dig(g.hero);
cc->dig(g.hero);
}
else
{
@@ -1356,15 +1357,15 @@ void AIGateway::tryRealize(Goals::DigAtTile & g)
void AIGateway::tryRealize(Goals::Trade & g) //trade
{
if(cbc->getResourceAmount(GameResID(g.resID)) >= g.value) //goal is already fulfilled. Why we need this check, anyway?
if(cc->getResourceAmount(GameResID(g.resID)) >= g.value) //goal is already fulfilled. Why we need this check, anyway?
throw goalFulfilledException(sptr(g));
int acquiredResources = 0;
if(const CGObjectInstance * obj = cbc->getObj(ObjectInstanceID(g.objid), false))
if(const CGObjectInstance * obj = cc->getObj(ObjectInstanceID(g.objid), false))
{
if(const auto * m = dynamic_cast<const IMarket*>(obj))
{
auto freeRes = cbc->getResourceAmount(); //trade only resources which are not reserved
auto freeRes = cc->getResourceAmount(); //trade only resources which are not reserved
for(auto it = ResourceSet::nziterator(freeRes); it.valid(); it++)
{
auto res = it->resType;
@@ -1378,11 +1379,11 @@ void AIGateway::tryRealize(Goals::Trade & g) //trade
//TODO trade only as much as needed
if (toGive) //don't try to sell 0 resources
{
cbc->trade(m->getObjInstanceID(), EMarketMode::RESOURCE_RESOURCE, res, GameResID(g.resID), toGive);
cc->trade(m->getObjInstanceID(), EMarketMode::RESOURCE_RESOURCE, res, GameResID(g.resID), toGive);
acquiredResources = static_cast<int>(toGet * (it->resVal / toGive));
logAi->debug("Traded %d of %s for %d of %s at %s", toGive, res, acquiredResources, g.resID, obj->getObjectName());
}
if (cbc->getResourceAmount(GameResID(g.resID)))
if (cc->getResourceAmount(GameResID(g.resID)))
throw goalFulfilledException(sptr(g)); //we traded all we needed
}
@@ -1407,9 +1408,9 @@ void AIGateway::endTurn()
logAi->error("Not having turn at the end of turn???");
}
logAi->debug("Resources at the end of turn: %s", cbc->getResourceAmount().toString());
logAi->debug("Resources at the end of turn: %s", cc->getResourceAmount().toString());
if(cbc->getPlayerStatus(playerID) != EPlayerStatus::INGAME)
if(cc->getPlayerStatus(playerID) != EPlayerStatus::INGAME)
{
logAi->info("Ending turn is not needed because we already lost");
return;
@@ -1417,7 +1418,7 @@ void AIGateway::endTurn()
do
{
cbc->endTurn();
cc->endTurn();
}
while(status.haveTurn()); //for some reasons, our request may fail -> stop requesting end of turn only after we've received a confirmation that it's over
@@ -1468,7 +1469,7 @@ void AIGateway::answerQuery(QueryID queryID, int selection)
logAi->debug("I'll answer the query %d giving the choice %d", queryID, selection);
if(queryID != QueryID(-1))
{
cbc->selectionMade(selection, queryID);
cc->selectionMade(selection, queryID);
}
else
{
@@ -1679,11 +1680,11 @@ void AIGateway::invalidatePaths()
void AIGateway::cheatMapReveal(const std::unique_ptr<Nullkiller> & nullkiller)
{
if(nullkiller->cbc->getDate(Date::DAY) == 1) // No need to execute every day, only the first time
if(nullkiller->cc->getDate(Date::DAY) == 1) // No need to execute every day, only the first time
{
if(nullkiller->isOpenMap())
{
nullkiller->cbc->sendMessage("vcmieagles");
nullkiller->cc->sendMessage("vcmieagles");
}
}
}
@@ -1691,14 +1692,14 @@ void AIGateway::cheatMapReveal(const std::unique_ptr<Nullkiller> & nullkiller)
void AIGateway::memorizeVisitableObjs(const std::unique_ptr<AIMemory> & memory,
const std::unique_ptr<DangerHitMapAnalyzer> & dangerHitMap,
const PlayerColor & playerID,
const std::shared_ptr<CCallback> & cbc)
const std::shared_ptr<CCallback> & cc)
{
foreach_tile_pos([&](const int3 & pos)
{
// TODO: Inspect what not visible means when using verbose true
for(const CGObjectInstance * obj : cbc->getVisitableObjs(pos, false))
for(const CGObjectInstance * obj : cc->getVisitableObjs(pos, false))
{
memorizeVisitableObj(obj, memory, dangerHitMap, playerID, cbc);
memorizeVisitableObj(obj, memory, dangerHitMap, playerID, cc);
}
});
}
@@ -1707,22 +1708,22 @@ void AIGateway::memorizeVisitableObj(const CGObjectInstance * obj,
const std::unique_ptr<AIMemory> & memory,
const std::unique_ptr<DangerHitMapAnalyzer> & dangerHitMap,
const PlayerColor & playerID,
const std::shared_ptr<CCallback> & cbc)
const std::shared_ptr<CCallback> & cc)
{
if(obj->ID == Obj::EVENT)
return;
memory->addVisitableObject(obj);
if(obj->ID == Obj::HERO && cbc->getPlayerRelations(obj->tempOwner, playerID) == PlayerRelations::ENEMIES)
if(obj->ID == Obj::HERO && cc->getPlayerRelations(obj->tempOwner, playerID) == PlayerRelations::ENEMIES)
{
dangerHitMap->resetHitmap();
}
}
void AIGateway::memorizeRevisitableObjs(const std::unique_ptr<AIMemory> & memory, const PlayerColor & playerID, const std::shared_ptr<CCallback> & cbc)
void AIGateway::memorizeRevisitableObjs(const std::unique_ptr<AIMemory> & memory, const PlayerColor & playerID, const std::shared_ptr<CCallback> & cc)
{
if(cbc->getDate(Date::DAY_OF_WEEK) == 1)
if(cc->getDate(Date::DAY_OF_WEEK) == 1)
{
for(const CGObjectInstance * obj : memory->visitableObjs)
{
@@ -1734,9 +1735,9 @@ void AIGateway::memorizeRevisitableObjs(const std::unique_ptr<AIMemory> & memory
}
}
void AIGateway::pickBestArtifacts(const std::shared_ptr<CCallback> & cbc, const CGHeroInstance * h, const CGHeroInstance * other)
void AIGateway::pickBestArtifacts(const std::shared_ptr<CCallback> & cc, const CGHeroInstance * h, const CGHeroInstance * other)
{
auto equipBest = [cbc](const CGHeroInstance * h, const CGHeroInstance * otherh, bool giveStuffToFirstHero) -> void
auto equipBest = [cc](const CGHeroInstance * h, const CGHeroInstance * otherh, bool giveStuffToFirstHero) -> void
{
bool changeMade = false;
std::set<std::pair<ArtifactInstanceID, ArtifactInstanceID> > swappedSet;
@@ -1783,7 +1784,7 @@ void AIGateway::pickBestArtifacts(const std::shared_ptr<CCallback> & cbc, const
if(location.slot == ArtifactPosition::MACH4) // don't attempt to move catapult
continue;
auto artHolder = cbc->getHero(location.artHolder);
auto artHolder = cc->getHero(location.artHolder);
auto s = artHolder->getSlot(location.slot);
if(!s || s->locked) //we can't move locks
continue;
@@ -1798,7 +1799,7 @@ void AIGateway::pickBestArtifacts(const std::shared_ptr<CCallback> & cbc, const
if(target->isPositionFree(slot) && artifact->canBePutAt(target, slot, true)) //combined artifacts are not always allowed to move
{
ArtifactLocation destLocation(target->id, slot);
cbc->swapArtifacts(location, destLocation); //just put into empty slot
cc->swapArtifacts(location, destLocation); //just put into empty slot
emptySlotFound = true;
changeMade = true;
break;
@@ -1839,12 +1840,12 @@ void AIGateway::pickBestArtifacts(const std::shared_ptr<CCallback> & cbc, const
ArtifactLocation destLocation(target->id, slot);
ArtifactLocation backpack(artHolder->id, ArtifactPosition::BACKPACK_START);
cbc->swapArtifacts(destLocation, backpack);
cbc->swapArtifacts(location, destLocation);
cc->swapArtifacts(destLocation, backpack);
cc->swapArtifacts(location, destLocation);
}
else
{
cbc->swapArtifacts(location, ArtifactLocation(target->id, target->getArtPos(otherSlot->getArt())));
cc->swapArtifacts(location, ArtifactLocation(target->id, target->getArtPos(otherSlot->getArt())));
}
changeMade = true;

View File

@@ -74,7 +74,8 @@ public:
AIStatus status;
std::string battlename;
std::shared_ptr<CCallback> cbc;
/// Same instance as in cbc. cbc is used to keep CAdventureAI simpler without unnecessary class requirements
std::shared_ptr<CCallback> cc;
std::unique_ptr<AsyncRunner> asyncTasks;
ObjectInstanceID selectedObject;
@@ -90,7 +91,7 @@ public:
std::string getBattleAIName() const override;
void initGameInterface(std::shared_ptr<Environment> env, std::shared_ptr<CCallback> CB) override;
void initGameInterface(std::shared_ptr<Environment> env, std::shared_ptr<CCallback> callback) override;
void yourTurn(QueryID queryID) override;
void heroGotLevel(const CGHeroInstance * hero, PrimarySkill pskill, std::vector<SecondarySkill> & skills, QueryID queryID) override; //pskill is gained primary skill, interface has to choose one of given skills and call callback with selection id
@@ -183,12 +184,12 @@ public:
static void cheatMapReveal(const std::unique_ptr<Nullkiller>& nullkiller);
static void memorizeVisitableObj(const CGObjectInstance* obj, const std::unique_ptr<AIMemory>& memory, const std::unique_ptr<DangerHitMapAnalyzer>&
dangerHitMap, const PlayerColor& playerID, const std::shared_ptr<CCallback>& cbc);
dangerHitMap, const PlayerColor& playerID, const std::shared_ptr<CCallback>& cc);
static void memorizeVisitableObjs(const std::unique_ptr<AIMemory>& memory, const std::unique_ptr<DangerHitMapAnalyzer>& dangerHitMap, const PlayerColor&
playerID, const std::shared_ptr<CCallback>& cbc);
static void memorizeRevisitableObjs(const std::unique_ptr<AIMemory>& memory, const PlayerColor& playerID, const std::shared_ptr<CCallback>& cbc);
playerID, const std::shared_ptr<CCallback>& cc);
static void memorizeRevisitableObjs(const std::unique_ptr<AIMemory>& memory, const PlayerColor& playerID, const std::shared_ptr<CCallback>& cc);
static void pickBestArtifacts(const std::shared_ptr<CCallback> & cbc, const CGHeroInstance * h, const CGHeroInstance * other = nullptr);
static void pickBestArtifacts(const std::shared_ptr<CCallback> & cc, const CGHeroInstance * h, const CGHeroInstance * other = nullptr);
};
}

View File

@@ -30,17 +30,17 @@ namespace NK2AI
const CGObjectInstance * ObjectIdRef::operator->() const
{
return cbcTl->getObj(id, false);
return ccTl->getObj(id, false);
}
ObjectIdRef::operator const CGObjectInstance *() const
{
return cbcTl->getObj(id, false);
return ccTl->getObj(id, false);
}
ObjectIdRef::operator bool() const
{
return cbcTl->getObj(id, false);
return ccTl->getObj(id, false);
}
ObjectIdRef::ObjectIdRef(ObjectInstanceID _id)
@@ -101,7 +101,7 @@ std::string HeroPtr::name() const
const CGHeroInstance * HeroPtr::get(bool doWeExpectNull) const
{
return get(cbcTl, doWeExpectNull);
return get(ccTl, doWeExpectNull);
}
const CGHeroInstance * HeroPtr::get(const CPlayerSpecificInfoCallback * cb, bool doWeExpectNull) const
@@ -203,7 +203,7 @@ bool canBeEmbarkmentPoint(const TerrainTile * t, bool fromWater)
}
else if(!fromWater) // do not try to board when in water sector
{
if(t->visitableObjects.size() == 1 && cbcTl->getObjInstance(t->topVisitableObj())->ID == Obj::BOAT)
if(t->visitableObjects.size() == 1 && ccTl->getObjInstance(t->topVisitableObj())->ID == Obj::BOAT)
return true;
}
return false;
@@ -211,7 +211,7 @@ bool canBeEmbarkmentPoint(const TerrainTile * t, bool fromWater)
bool isObjectPassable(const Nullkiller * aiNk, const CGObjectInstance * obj)
{
return isObjectPassable(obj, aiNk->playerID, aiNk->cbc->getPlayerRelations(obj->tempOwner, aiNk->playerID));
return isObjectPassable(obj, aiNk->playerID, aiNk->cc->getPlayerRelations(obj->tempOwner, aiNk->playerID));
}
// Pathfinder internal helper
@@ -234,7 +234,7 @@ bool isObjectPassable(const CGObjectInstance * obj, PlayerColor playerColor, Pla
bool isBlockVisitObj(const int3 & pos)
{
if(auto obj = cbcTl->getTopObj(pos))
if(auto obj = ccTl->getTopObj(pos))
{
if(obj->isBlockedVisitable()) //we can't stand on that object
return true;
@@ -646,7 +646,7 @@ int getDuplicatingSlots(const CArmedInstance * army)
// todo: move to obj manager
bool shouldVisit(const Nullkiller * aiNk, const CGHeroInstance * h, const CGObjectInstance * obj)
{
auto relations = aiNk->cbc->getPlayerRelations(obj->tempOwner, h->tempOwner);
auto relations = aiNk->cc->getPlayerRelations(obj->tempOwner, h->tempOwner);
switch(obj->ID)
{
@@ -656,7 +656,7 @@ bool shouldVisit(const Nullkiller * aiNk, const CGHeroInstance * h, const CGObje
case Obj::BORDER_GATE:
{
for(auto q : aiNk->cbc->getMyQuests())
for(auto q : aiNk->cc->getMyQuests())
{
if(q.obj == obj->id)
{
@@ -669,11 +669,11 @@ bool shouldVisit(const Nullkiller * aiNk, const CGHeroInstance * h, const CGObje
return (dynamic_cast<const CGKeys *>(obj))->wasMyColorVisited(aiNk->playerID);
case Obj::SEER_HUT:
{
for(auto q : aiNk->cbc->getMyQuests())
for(auto q : aiNk->cc->getMyQuests())
{
if(q.obj == obj->id)
{
if(q.getQuest(aiNk->cbc.get())->checkQuest(h))
if(q.getQuest(aiNk->cc.get())->checkQuest(h))
return true; //we completed the quest
else
return false; //we can't complete this quest
@@ -698,7 +698,7 @@ bool shouldVisit(const Nullkiller * aiNk, const CGHeroInstance * h, const CGObje
{
if(level.first
&& (h->getSlotFor(CreatureID(c)) != SlotID() || duplicatingSlotsCount > 0)
&& aiNk->cbc->getResourceAmount().canAfford(c.toCreature()->getFullRecruitCost()))
&& aiNk->cc->getResourceAmount().canAfford(c.toCreature()->getFullRecruitCost()))
{
return true;
}

View File

@@ -62,7 +62,7 @@ const int WOOD_ORE_MINE_PRODUCTION = 2;
const int RESOURCE_MINE_PRODUCTION = 1;
const int ACTUAL_RESOURCE_COUNT = 7;
extern thread_local CCallback * cbcTl;
extern thread_local CCallback * ccTl;
enum HeroRole
{
@@ -148,7 +148,7 @@ void foreach_tile_pos(const Func & foo)
{
// some micro-optimizations since this function gets called a LOT
// callback pointer is thread-specific and slow to retrieve -> read map size only once
int3 mapSize = cbcTl->getMapSize();
int3 mapSize = ccTl->getMapSize();
for(int z = 0; z < mapSize.z; z++)
{
for(int x = 0; x < mapSize.x; x++)
@@ -180,7 +180,7 @@ void foreach_tile_pos(TCallback * cbp, const Func & foo) // avoid costly retriev
template<class Func>
void foreach_neighbour(const int3 & pos, const Func & foo)
{
CCallback * cbp = cbcTl; // avoid costly retrieval of thread-specific pointer
CCallback * cbp = ccTl; // avoid costly retrieval of thread-specific pointer
for(const int3 & dir : int3::getDirs())
{
const int3 n = pos + dir;

View File

@@ -77,7 +77,7 @@ std::vector<SlotInfo> ArmyManager::toSlotInfo(std::vector<creInfo> army) const
uint64_t ArmyManager::howManyReinforcementsCanGet(const CGHeroInstance * hero, const CCreatureSet * source) const
{
return howManyReinforcementsCanGet(hero, hero, source, aiNk->cbc->getTile(hero->visitablePos())->getTerrainID());
return howManyReinforcementsCanGet(hero, hero, source, aiNk->cc->getTile(hero->visitablePos())->getTerrainID());
}
std::vector<SlotInfo> ArmyManager::getSortedSlots(const CCreatureSet * target, const CCreatureSet * source) const

View File

@@ -42,12 +42,12 @@ void BuildAnalyzer::update()
{
logAi->trace("Start BuildAnalyzer::update");
reset();
const auto towns = aiNk->cbc->getTownsInfo();
const auto towns = aiNk->cc->getTownsInfo();
float economyDevelopmentCost = 0;
for(const CGTownInstance * town : towns)
{
if(town->built >= cbcTl->getSettings().getInteger(EGameSettings::TOWNS_BUILDINGS_PER_TURN_CAP))
if(town->built >= ccTl->getSettings().getInteger(EGameSettings::TOWNS_BUILDINGS_PER_TURN_CAP))
continue; // Not much point in trying anything - can't built in this town anymore today
#if NKAI_TRACE_LEVEL >= 1
@@ -57,8 +57,8 @@ void BuildAnalyzer::update()
developmentInfos.push_back(TownDevelopmentInfo(town));
TownDevelopmentInfo & tdi = developmentInfos.back();
updateCreatureBuildings(tdi, aiNk->armyManager, aiNk->cbc);
updateOtherBuildings(tdi, aiNk->armyManager, aiNk->cbc);
updateCreatureBuildings(tdi, aiNk->armyManager, aiNk->cc);
updateOtherBuildings(tdi, aiNk->armyManager, aiNk->cc);
requiredResources += tdi.requiredResources;
totalDevelopmentCost += tdi.townDevelopmentCost;
@@ -83,7 +83,7 @@ void BuildAnalyzer::update()
return val1 > val2;
});
dailyIncome = calculateDailyIncome(aiNk->cbc->getMyObjects(), aiNk->cbc->getTownsInfo());
dailyIncome = calculateDailyIncome(aiNk->cc->getMyObjects(), aiNk->cc->getTownsInfo());
goldPressure = calculateGoldPressure(aiNk->getLockedResources()[EGameResID::GOLD],
static_cast<float>(armyCost[EGameResID::GOLD]),
economyDevelopmentCost,

View File

@@ -70,8 +70,8 @@ void DangerHitMapAnalyzer::updateHitMap()
hitMapUpToDate = true;
auto start = std::chrono::high_resolution_clock::now();
auto cb = aiNk->cbc.get();
auto mapSize = aiNk->cbc->getMapSize();
auto cb = aiNk->cc.get();
auto mapSize = aiNk->cc->getMapSize();
if(hitMap.shape()[0] != mapSize.x || hitMap.shape()[1] != mapSize.y || hitMap.shape()[2] != mapSize.z)
hitMap.resize(boost::extents[mapSize.x][mapSize.y][mapSize.z]);
@@ -114,7 +114,7 @@ void DangerHitMapAnalyzer::updateHitMap()
if(!pair.first.isValidPlayer())
continue;
if(aiNk->cbc->getPlayerRelations(aiNk->playerID, pair.first) != PlayerRelations::ENEMIES)
if(aiNk->cc->getPlayerRelations(aiNk->playerID, pair.first) != PlayerRelations::ENEMIES)
continue;
PathfinderSettings ps;
@@ -203,8 +203,8 @@ void DangerHitMapAnalyzer::calculateTileOwners()
tileOwnersUpToDate = true;
auto cb = aiNk->cbc.get();
auto mapSize = aiNk->cbc->getMapSize();
auto cb = aiNk->cc.get();
auto mapSize = aiNk->cc->getMapSize();
if(hitMap.shape()[0] != mapSize.x || hitMap.shape()[1] != mapSize.y || hitMap.shape()[2] != mapSize.z)
hitMap.resize(boost::extents[mapSize.x][mapSize.y][mapSize.z]);

View File

@@ -290,7 +290,7 @@ const CGHeroInstance * HeroManager::findHeroWithGrail() const
const CGHeroInstance * HeroManager::findWeakHeroToDismiss(uint64_t armyLimit, const CGTownInstance* townToSpare) const
{
const CGHeroInstance * weakestHero = nullptr;
auto myHeroes = aiNk->cbc->getHeroesInfo();
auto myHeroes = aiNk->cc->getHeroesInfo();
for(auto existingHero : myHeroes)
{

View File

@@ -69,12 +69,12 @@ std::vector<const CGObjectInstance *> ObjectCluster::getObjects(const CPlayerSpe
std::vector<const CGObjectInstance *> ObjectClusterizer::getNearbyObjects() const
{
return nearObjects.getObjects(aiNk->cbc.get());
return nearObjects.getObjects(aiNk->cc.get());
}
std::vector<const CGObjectInstance *> ObjectClusterizer::getFarObjects() const
{
return farObjects.getObjects(aiNk->cbc.get());
return farObjects.getObjects(aiNk->cc.get());
}
std::vector<std::shared_ptr<ObjectCluster>> ObjectClusterizer::getLockedClusters() const
@@ -95,14 +95,14 @@ std::optional<const CGObjectInstance *> ObjectClusterizer::getBlocker(const AIPa
if(node.layer == EPathfindingLayer::LAND || node.layer == EPathfindingLayer::SAIL)
{
auto guardPos = aiNk->cbc->getGuardingCreaturePosition(node.coord);
auto guardPos = aiNk->cc->getGuardingCreaturePosition(node.coord);
if (aiNk->cbc->isVisible(node.coord))
blockers = aiNk->cbc->getVisitableObjs(node.coord);
if (aiNk->cc->isVisible(node.coord))
blockers = aiNk->cc->getVisitableObjs(node.coord);
if(guardPos.isValid() && aiNk->cbc->isVisible(guardPos))
if(guardPos.isValid() && aiNk->cc->isVisible(guardPos))
{
auto guard = aiNk->cbc->getTopObj(aiNk->cbc->getGuardingCreaturePosition(node.coord));
auto guard = aiNk->cc->getTopObj(aiNk->cc->getGuardingCreaturePosition(node.coord));
if(guard)
{
@@ -190,7 +190,7 @@ void ObjectClusterizer::validateObjects()
{
for(auto & pair : cluster.objects)
{
if(!aiNk->cbc->getObj(pair.first, false))
if(!aiNk->cc->getObj(pair.first, false))
toRemove.push_back(pair.first);
}
};
@@ -200,7 +200,7 @@ void ObjectClusterizer::validateObjects()
for(auto & pair : blockedObjects)
{
if(!aiNk->cbc->getObj(pair.first, false) || pair.second->objects.empty())
if(!aiNk->cc->getObj(pair.first, false) || pair.second->objects.empty())
toRemove.push_back(pair.first);
else
scanRemovedObjects(*pair.second);
@@ -248,7 +248,7 @@ bool ObjectClusterizer::shouldVisitObject(const CGObjectInstance * obj) const
return false;
}
auto playerRelations = aiNk->cbc->getPlayerRelations(aiNk->playerID, obj->tempOwner);
auto playerRelations = aiNk->cc->getPlayerRelations(aiNk->playerID, obj->tempOwner);
if(playerRelations != PlayerRelations::ENEMIES && !isWeeklyRevisitable(aiNk->playerID, obj))
{
@@ -258,12 +258,12 @@ bool ObjectClusterizer::shouldVisitObject(const CGObjectInstance * obj) const
//it may be hero visiting this obj
//we don't try visiting object on which allied or owned hero stands
// -> it will just trigger exchange windows and AI will be confused that obj behind doesn't get visited
const CGObjectInstance * topObj = aiNk->cbc->getTopObj(pos);
const CGObjectInstance * topObj = aiNk->cc->getTopObj(pos);
if(!topObj)
return false; // partly visible obj but its visitable pos is not visible.
if(topObj->ID == Obj::HERO && aiNk->cbc->getPlayerRelations(aiNk->playerID, topObj->tempOwner) != PlayerRelations::ENEMIES)
if(topObj->ID == Obj::HERO && aiNk->cc->getPlayerRelations(aiNk->playerID, topObj->tempOwner) != PlayerRelations::ENEMIES)
return false;
else
return true; //all of the following is met
@@ -310,7 +310,7 @@ void ObjectClusterizer::clusterize()
{
for(auto id : invalidated)
{
auto obj = cbcTl->getObj(id, false);
auto obj = ccTl->getObj(id, false);
if(obj)
{
@@ -338,7 +338,7 @@ void ObjectClusterizer::clusterize()
tbb::blocked_range<size_t> r(0, objs.size());
#endif
auto priorityEvaluator = aiNk->priorityEvaluators->acquire();
auto heroes = aiNk->cbc->getHeroesInfo();
auto heroes = aiNk->cc->getHeroesInfo();
std::vector<AIPath> pathCache;
for(int i = r.begin(); i != r.end(); i++)
@@ -354,12 +354,12 @@ void ObjectClusterizer::clusterize()
for(auto pair : blockedObjects)
{
auto blocker = cbcTl->getObj(pair.first);
auto blocker = ccTl->getObj(pair.first);
logAi->trace("Cluster %s %s count: %i", blocker->getObjectName(), blocker->visitablePos().toString(), pair.second->objects.size());
#if NKAI_TRACE_LEVEL >= 1
for(auto obj : pair.second->getObjects(aiNk->cbc.get()))
for(auto obj : pair.second->getObjects(aiNk->cc.get()))
{
logAi->trace("Object %s %s", obj->getObjectName(), obj->visitablePos().toString());
}

View File

@@ -28,7 +28,7 @@ Goals::TGoalVec BuyArmyBehavior::decompose(const Nullkiller * aiNk) const
{
Goals::TGoalVec tasks;
auto heroes = cbcTl->getHeroesInfo();
auto heroes = ccTl->getHeroesInfo();
if(heroes.empty())
{
@@ -37,11 +37,11 @@ Goals::TGoalVec BuyArmyBehavior::decompose(const Nullkiller * aiNk) const
aiNk->dangerHitMap->updateHitMap();
for(auto town : cbcTl->getTownsInfo())
for(auto town : ccTl->getTownsInfo())
{
uint8_t closestThreat = aiNk->dangerHitMap->getTileThreat(town->visitablePos()).fastestDanger.turn;
if (closestThreat >=2 && aiNk->buildAnalyzer->isGoldPressureOverMax() && !town->hasBuilt(BuildingID::CITY_HALL) && cbcTl->canBuildStructure(town, BuildingID::CITY_HALL) != EBuildingState::FORBIDDEN)
if (closestThreat >=2 && aiNk->buildAnalyzer->isGoldPressureOverMax() && !town->hasBuilt(BuildingID::CITY_HALL) && ccTl->canBuildStructure(town, BuildingID::CITY_HALL) != EBuildingState::FORBIDDEN)
{
return tasks;
}

View File

@@ -41,7 +41,7 @@ Goals::TGoalVec ClusterBehavior::decompose(const Nullkiller * aiNk) const
Goals::TGoalVec ClusterBehavior::decomposeCluster(const Nullkiller * aiNk, std::shared_ptr<ObjectCluster> cluster) const
{
auto center = cluster->calculateCenter(aiNk->cbc.get());
auto center = cluster->calculateCenter(aiNk->cc.get());
auto paths = aiNk->pathfinder->getPathInfo(center->visitablePos(), aiNk->isObjectGraphAllowed());
auto blockerPos = cluster->blocker->visitablePos();
@@ -83,7 +83,7 @@ Goals::TGoalVec ClusterBehavior::decomposeCluster(const Nullkiller * aiNk, std::
{
clonedPath.nodes.insert(clonedPath.nodes.begin(), *node);
if(node->coord == blockerPos || aiNk->cbc->getGuardingCreaturePosition(node->coord) == blockerPos)
if(node->coord == blockerPos || aiNk->cc->getGuardingCreaturePosition(node->coord) == blockerPos)
break;
}

View File

@@ -38,7 +38,7 @@ Goals::TGoalVec DefenceBehavior::decompose(const Nullkiller * aiNk) const
{
Goals::TGoalVec tasks;
for(auto town : aiNk->cbc->getTownsInfo())
for(auto town : aiNk->cc->getTownsInfo())
{
evaluateDefence(tasks, town, aiNk);
}
@@ -48,7 +48,7 @@ Goals::TGoalVec DefenceBehavior::decompose(const Nullkiller * aiNk) const
bool isThreatUnderControl(const CGTownInstance * town, const HitMapInfo & threat, const Nullkiller * aiNk, const std::vector<AIPath> & paths)
{
int dayOfWeek = aiNk->cbc->getDate(Date::DAY_OF_WEEK);
int dayOfWeek = aiNk->cc->getDate(Date::DAY_OF_WEEK);
for(const AIPath & path : paths)
{
@@ -121,7 +121,7 @@ bool handleGarrisonHeroFromPreviousTurn(const CGTownInstance * town, Goals::TGoa
if(!town->getVisitingHero())
{
if(aiNk->cbc->getHeroCount(aiNk->playerID, false) < GameConstants::MAX_HEROES_PER_PLAYER)
if(aiNk->cc->getHeroCount(aiNk->playerID, false) < GameConstants::MAX_HEROES_PER_PLAYER)
{
logAi->trace(
"Extracting hero %s from garrison of town %s",
@@ -429,9 +429,9 @@ void DefenceBehavior::evaluateRecruitingHero(Goals::TGoalVec & tasks, const HitM
return;
if(town->hasBuilt(BuildingID::TAVERN)
&& aiNk->cbc->getResourceAmount(EGameResID::GOLD) > GameConstants::HERO_GOLD_COST)
&& aiNk->cc->getResourceAmount(EGameResID::GOLD) > GameConstants::HERO_GOLD_COST)
{
auto heroesInTavern = aiNk->cbc->getAvailableHeroes(town);
auto heroesInTavern = aiNk->cc->getAvailableHeroes(town);
for(auto hero : heroesInTavern)
{
@@ -453,7 +453,7 @@ void DefenceBehavior::evaluateRecruitingHero(Goals::TGoalVec & tasks, const HitM
if (heroAlreadyHiredInOtherTown)
continue;
auto myHeroes = aiNk->cbc->getHeroesInfo();
auto myHeroes = aiNk->cc->getHeroesInfo();
#if NKAI_TRACE_LEVEL >= 1
logAi->trace("Hero %s can be recruited to defend %s", hero->getObjectName(), town->getObjectName());

View File

@@ -51,11 +51,11 @@ Goals::TGoalVec ExplorationBehavior::decompose(const Nullkiller * aiNk) const
case Obj::WHIRLPOOL:
{
auto tObj = dynamic_cast<const CGTeleport*>(obj);
for (auto exit : cbcTl->getTeleportChannelExits(tObj->channel))
for (auto exit : ccTl->getTeleportChannelExits(tObj->channel))
{
if (exit != tObj->id)
{
if (!cbcTl->isVisible(cbcTl->getObjInstance(exit)))
if (!ccTl->isVisible(ccTl->getObjInstance(exit)))
tasks.push_back(sptr(Composition().addNext(ExplorationPoint(obj->visitablePos(), 50)).addNext(CaptureObject(obj))));
}
}
@@ -63,7 +63,7 @@ Goals::TGoalVec ExplorationBehavior::decompose(const Nullkiller * aiNk) const
}
}
auto heroes = aiNk->cbc->getHeroesInfo();
auto heroes = aiNk->cc->getHeroesInfo();
for(const CGHeroInstance * hero : heroes)
{

View File

@@ -34,7 +34,7 @@ Goals::TGoalVec GatherArmyBehavior::decompose(const Nullkiller * aiNk) const
{
Goals::TGoalVec tasks;
auto heroes = aiNk->cbc->getHeroesInfo();
auto heroes = aiNk->cc->getHeroesInfo();
if(heroes.empty())
{
@@ -49,7 +49,7 @@ Goals::TGoalVec GatherArmyBehavior::decompose(const Nullkiller * aiNk) const
}
}
auto towns = aiNk->cbc->getTownsInfo();
auto towns = aiNk->cc->getTownsInfo();
for(const CGTownInstance * town : towns)
{
@@ -314,7 +314,7 @@ Goals::TGoalVec GatherArmyBehavior::upgradeArmy(const Nullkiller * aiNk, const C
&& aiNk->heroManager->canRecruitHero(upgrader)
&& path.turn() < aiNk->settings->getScoutHeroTurnDistanceLimit())
{
for(auto hero : cbcTl->getAvailableHeroes(upgrader))
for(auto hero : ccTl->getAvailableHeroes(upgrader))
{
auto scoutReinforcement = aiNk->armyManager->howManyReinforcementsCanGet(hero, upgrader);

View File

@@ -27,7 +27,7 @@ std::string RecruitHeroBehavior::toString() const
Goals::TGoalVec RecruitHeroBehavior::decompose(const Nullkiller * aiNk) const
{
Goals::TGoalVec tasks;
auto towns = aiNk->cbc->getTownsInfo();
auto towns = aiNk->cc->getTownsInfo();
auto ourHeroes = aiNk->heroManager->getHeroRoles();
auto minScoreToHireMain = std::numeric_limits<float>::max();
@@ -78,7 +78,7 @@ Goals::TGoalVec RecruitHeroBehavior::decompose(const Nullkiller * aiNk) const
}
if(aiNk->heroManager->canRecruitHero(town))
{
auto availableHeroes = aiNk->cbc->getAvailableHeroes(town);
auto availableHeroes = aiNk->cc->getAvailableHeroes(town);
for (auto obj : aiNk->objectClusterizer->getNearbyObjects())
{
@@ -128,8 +128,8 @@ Goals::TGoalVec RecruitHeroBehavior::decompose(const Nullkiller * aiNk) const
}
if (bestHeroToHire && bestTownToHireFrom)
{
if (aiNk->cbc->getHeroesInfo().size() == 0
|| treasureSourcesCount > aiNk->cbc->getHeroesInfo().size() * 5
if (aiNk->cc->getHeroesInfo().size() == 0
|| treasureSourcesCount > aiNk->cc->getHeroesInfo().size() * 5
|| (bestHeroToHire->getArmyCost() > GameConstants::HERO_GOLD_COST / 2.0 && (bestClosestThreat < 1 || !aiNk->buildAnalyzer->isGoldPressureOverMax()))
|| (aiNk->getFreeResources()[EGameResID::GOLD] > 10000 && !aiNk->buildAnalyzer->isGoldPressureOverMax() && haveCapitol)
|| (aiNk->getFreeResources()[EGameResID::GOLD] > 30000 && !aiNk->buildAnalyzer->isGoldPressureOverMax()))

View File

@@ -97,21 +97,21 @@ bool needToRecruitHero(const Nullkiller * aiNk, const CGTownInstance * startupTo
}
}
auto basicCount = cbcTl->getTownsInfo().size() + 2;
auto basicCount = ccTl->getTownsInfo().size() + 2;
auto boost = std::min(
(int)std::floor(std::pow(1 + (cbcTl->getMapSize().x / 50), 2)),
(int)std::floor(std::pow(1 + (ccTl->getMapSize().x / 50), 2)),
treasureSourcesCount / 2);
logAi->trace("Treasure sources found %d", treasureSourcesCount);
logAi->trace("Startup allows %d+%d heroes", basicCount, boost);
return cbcTl->getHeroCount(aiNk->playerID, true) < basicCount + boost;
return ccTl->getHeroCount(aiNk->playerID, true) < basicCount + boost;
}
Goals::TGoalVec StartupBehavior::decompose(const Nullkiller * aiNk) const
{
Goals::TGoalVec tasks;
auto towns = aiNk->cbc->getTownsInfo();
auto towns = aiNk->cc->getTownsInfo();
if(!towns.size())
return tasks;
@@ -135,7 +135,7 @@ Goals::TGoalVec StartupBehavior::decompose(const Nullkiller * aiNk) const
}
if(!startupTown->hasBuilt(BuildingID::TAVERN)
&& aiNk->cbc->canBuildStructure(startupTown, BuildingID::TAVERN) == EBuildingState::ALLOWED)
&& aiNk->cc->canBuildStructure(startupTown, BuildingID::TAVERN) == EBuildingState::ALLOWED)
{
tasks.push_back(Goals::sptr(Goals::BuildThis(BuildingID::TAVERN, startupTown).setpriority(100)));

View File

@@ -30,7 +30,7 @@ std::string StayAtTownBehavior::toString() const
Goals::TGoalVec StayAtTownBehavior::decompose(const Nullkiller * aiNk) const
{
Goals::TGoalVec tasks;
auto towns = aiNk->cbc->getTownsInfo();
auto towns = aiNk->cc->getTownsInfo();
if(!towns.size())
return tasks;

View File

@@ -146,8 +146,8 @@ bool isEquivalentGoals(TSubgoal goal1, TSubgoal goal2)
if(goal1->goalType == Goals::CAPTURE_OBJECT && goal2->goalType == Goals::CAPTURE_OBJECT)
{
auto o1 = cbcTl->getObj(ObjectInstanceID(goal1->objid));
auto o2 = cbcTl->getObj(ObjectInstanceID(goal2->objid));
auto o1 = ccTl->getObj(ObjectInstanceID(goal1->objid));
auto o2 = ccTl->getObj(ObjectInstanceID(goal2->objid));
return o1->ID == Obj::SHIPYARD && o1->ID == o2->ID;
}

View File

@@ -21,7 +21,7 @@ namespace NK2AI
ui64 FuzzyHelper::evaluateDanger(const int3 & tile, const CGHeroInstance * visitor, bool checkGuards)
{
auto cb = aiNk->cbc.get();
auto cb = aiNk->cc.get();
const TerrainTile * t = cb->getTile(tile, false);
if(!t) //we can know about guard but can't check its tile (the edge of fow)
return 190000000; //MUCH
@@ -109,7 +109,7 @@ ui64 FuzzyHelper::evaluateDanger(const int3 & tile, const CGHeroInstance * visit
ui64 FuzzyHelper::evaluateDanger(const CGObjectInstance * obj)
{
auto cb = aiNk->cbc.get();
auto cb = aiNk->cc.get();
if(obj->tempOwner.isValidPlayer() && cb->getPlayerRelations(obj->tempOwner, aiNk->playerID) != PlayerRelations::ENEMIES) //owned or allied objects don't pose any threat
return 0;

View File

@@ -68,7 +68,7 @@ bool canUseOpenMap(std::shared_ptr<CCallback> cb, PlayerColor playerID)
void Nullkiller::init(std::shared_ptr<CCallback> cb, AIGateway * aiGw)
{
this->cbc = cb;
this->cc = cb;
this->aiGw = aiGw;
this->playerID = aiGw->playerID;
@@ -264,7 +264,7 @@ void Nullkiller::updateState(bool partialUpdate)
if(!partialUpdate && pathfinderInvalidated)
{
memory->removeInvisibleObjects(cbc.get());
memory->removeInvisibleObjects(cc.get());
dangerHitMap->updateHitMap();
dangerHitMap->calculateTileOwners();
@@ -276,7 +276,7 @@ void Nullkiller::updateState(bool partialUpdate)
std::map<const CGHeroInstance *, HeroRole> activeHeroes;
for(auto hero : cbc->getHeroesInfo())
for(auto hero : cc->getHeroesInfo())
{
if(getHeroLockedReason(hero) == HeroLockedReason::DEFENCE)
continue;
@@ -368,7 +368,7 @@ void Nullkiller::makeTurn()
Goals::TGoalVec tasks;
tracePlayerStatus(true);
for(int i = 1; i <= settings->getMaxPass() && cbc->getPlayerStatus(playerID) == EPlayerStatus::INGAME; i++)
for(int i = 1; i <= settings->getMaxPass() && cc->getPlayerStatus(playerID) == EPlayerStatus::INGAME; i++)
{
updateState();
@@ -407,7 +407,7 @@ void Nullkiller::makeTurn()
bool hasAnySuccess = false;
for(const auto& selectedTask : selectedTasks)
{
if(cbc->getPlayerStatus(playerID) != EPlayerStatus::INGAME)
if(cc->getPlayerStatus(playerID) != EPlayerStatus::INGAME)
return;
if(!areAffectedObjectsPresent(selectedTask))
@@ -437,7 +437,7 @@ void Nullkiller::makeTurn()
if((settings->isUseFuzzy() && selectedTask->priority < MIN_PRIORITY) || (!settings->isUseFuzzy() && selectedTask->priority <= 0))
{
auto heroes = cbc->getHeroesInfo();
auto heroes = cc->getHeroesInfo();
const auto hasMp = vstd::contains_if(heroes, [](const CGHeroInstance * h) -> bool
{
return h->movementPointsRemaining() > 100;
@@ -481,8 +481,8 @@ void Nullkiller::makeTurn()
return;
}
for (const auto *heroInfo : cbc->getHeroesInfo())
AIGateway::pickBestArtifacts(cbc, heroInfo);
for (const auto *heroInfo : cc->getHeroesInfo())
AIGateway::pickBestArtifacts(cc, heroInfo);
if(i == settings->getMaxPass())
{
@@ -494,7 +494,7 @@ void Nullkiller::makeTurn()
bool Nullkiller::makeTurnHelperPriorityPass(Goals::TGoalVec & tempResults, int passIndex)
{
Goals::TTask bestPrioPassTask = taskptr(Goals::Invalid());
for(int i = 1; i <= settings->getMaxPriorityPass() && cbc->getPlayerStatus(playerID) == EPlayerStatus::INGAME; i++)
for(int i = 1; i <= settings->getMaxPriorityPass() && cc->getPlayerStatus(playerID) == EPlayerStatus::INGAME; i++)
{
tempResults.clear();
@@ -534,7 +534,7 @@ bool Nullkiller::areAffectedObjectsPresent(Goals::TTask task) const
for(auto oid : affectedObjs)
{
if(!cbc->getObj(oid, false))
if(!cc->getObj(oid, false))
return false;
}
@@ -581,7 +581,7 @@ bool Nullkiller::executeTask(Goals::TTask task)
TResources Nullkiller::getFreeResources() const
{
auto freeRes = cbc->getResourceAmount() - lockedResources;
auto freeRes = cc->getResourceAmount() - lockedResources;
freeRes.positive();
@@ -598,7 +598,7 @@ bool Nullkiller::handleTrading()
bool haveTraded = false;
bool shouldTryToTrade = true;
ObjectInstanceID marketId;
for (auto town : cbc->getTownsInfo())
for (auto town : cc->getTownsInfo())
{
if (town->hasBuiltSomeTradeBuilding())
{
@@ -607,7 +607,7 @@ bool Nullkiller::handleTrading()
}
if (!marketId.hasValue())
return false;
if (const CGObjectInstance* obj = cbc->getObj(marketId, false))
if (const CGObjectInstance* obj = cc->getObj(marketId, false))
{
if (const auto* m = dynamic_cast<const IMarket*>(obj))
{
@@ -617,7 +617,7 @@ bool Nullkiller::handleTrading()
buildAnalyzer->update();
TResources required = buildAnalyzer->getTotalResourcesRequired();
TResources income = buildAnalyzer->getDailyIncome();
TResources available = cbc->getResourceAmount();
TResources available = cc->getResourceAmount();
#if NKAI_TRACE_LEVEL >= 2
logAi->debug("Available %s", available.toString());
logAi->debug("Required %s", required.toString());
@@ -678,7 +678,7 @@ bool Nullkiller::handleTrading()
//TODO trade only as much as needed
if (toGive && toGive <= available[mostExpendable]) //don't try to sell 0 resources
{
cbc->trade(m->getObjInstanceID(), EMarketMode::RESOURCE_RESOURCE, GameResID(mostExpendable), GameResID(mostWanted), toGive);
cc->trade(m->getObjInstanceID(), EMarketMode::RESOURCE_RESOURCE, GameResID(mostExpendable), GameResID(mostWanted), toGive);
#if NKAI_TRACE_LEVEL >= 2
logAi->info("Traded %d of %s for %d of %s at %s", toGive, mostExpendable, toGet, mostWanted, obj->getObjectName());
#endif
@@ -706,17 +706,17 @@ void Nullkiller::tracePlayerStatus(bool beginning) const
#if NKAI_TRACE_LEVEL >= 1
float totalHeroesStrength = 0;
int totalTownsLevel = 0;
for (const auto *heroInfo : cbc->getHeroesInfo())
for (const auto *heroInfo : cc->getHeroesInfo())
{
totalHeroesStrength += heroInfo->getTotalStrength();
}
for (const auto *townInfo : cbc->getTownsInfo())
for (const auto *townInfo : cc->getTownsInfo())
{
totalTownsLevel += townInfo->getTownLevel();
}
const auto *firstWord = beginning ? "Beginning:" : "End:";
logAi->info("%s totalHeroesStrength: %f, totalTownsLevel: %d, resources: %s", firstWord, totalHeroesStrength, totalTownsLevel, cbc->getResourceAmount().toString());
logAi->info("%s totalHeroesStrength: %f, totalTownsLevel: %d, resources: %s", firstWord, totalHeroesStrength, totalTownsLevel, cc->getResourceAmount().toString());
#endif
}

View File

@@ -107,7 +107,7 @@ public:
std::unique_ptr<Settings> settings;
/// Same value as AIGateway->playerID
PlayerColor playerID;
std::shared_ptr<CCallback> cbc;
std::shared_ptr<CCallback> cc;
std::mutex aiStateMutex;
mutable ThreadInterruption makingTurnInterrupption;

View File

@@ -227,7 +227,7 @@ uint64_t RewardEvaluator::getArmyReward(
{
const float enemyArmyEliminationRewardRatio = 0.5f;
auto relations = aiNk->cbc->getPlayerRelations(target->tempOwner, aiNk->playerID);
auto relations = aiNk->cc->getPlayerRelations(target->tempOwner, aiNk->playerID);
if(!target)
return 0;
@@ -235,12 +235,12 @@ uint64_t RewardEvaluator::getArmyReward(
switch(target->ID)
{
case Obj::HILL_FORT:
return aiNk->armyManager->calculateCreaturesUpgrade(army, target, aiNk->cbc->getResourceAmount()).upgradeValue;
return aiNk->armyManager->calculateCreaturesUpgrade(army, target, aiNk->cc->getResourceAmount()).upgradeValue;
case Obj::CREATURE_GENERATOR1:
case Obj::CREATURE_GENERATOR2:
case Obj::CREATURE_GENERATOR3:
case Obj::CREATURE_GENERATOR4:
return getDwellingArmyValue(aiNk->cbc.get(), target, checkGold);
return getDwellingArmyValue(aiNk->cc.get(), target, checkGold);
case Obj::SPELL_SCROLL:
return evaluateSpellScrollArmyValue(dynamic_cast<const CGArtifact *>(target)->getArtifactInstance()->getScrollSpellID());
case Obj::ARTIFACT:
@@ -296,7 +296,7 @@ uint64_t RewardEvaluator::getArmyGrowth(
if(!target)
return 0;
auto relations = aiNk->cbc->getPlayerRelations(target->tempOwner, hero->tempOwner);
auto relations = aiNk->cc->getPlayerRelations(target->tempOwner, hero->tempOwner);
if(relations != PlayerRelations::ENEMIES)
return 0;
@@ -308,7 +308,7 @@ uint64_t RewardEvaluator::getArmyGrowth(
auto town = dynamic_cast<const CGTownInstance *>(target);
auto fortLevel = town->fortLevel();
auto neutral = !town->getOwner().isValidPlayer();
auto booster = isAnotherAi(town, *aiNk->cbc) || neutral ? 1 : 2;
auto booster = isAnotherAi(town, *aiNk->cc) || neutral ? 1 : 2;
if(fortLevel < CGTownInstance::CITADEL)
return town->hasFort() ? booster * 500 : 0;
@@ -320,7 +320,7 @@ uint64_t RewardEvaluator::getArmyGrowth(
case Obj::CREATURE_GENERATOR2:
case Obj::CREATURE_GENERATOR3:
case Obj::CREATURE_GENERATOR4:
return getDwellingArmyGrowth(aiNk->cbc.get(), target, hero->getOwner());
return getDwellingArmyGrowth(aiNk->cc.get(), target, hero->getOwner());
case Obj::ARTIFACT:
// it is not supported now because hero will not sit in town on 7th day but later parts of legion may be counted as army growth as well.
return 0;
@@ -343,7 +343,7 @@ int RewardEvaluator::getGoldCost(const CGObjectInstance * target, const CGHeroIn
switch(target->ID)
{
case Obj::HILL_FORT:
return aiNk->armyManager->calculateCreaturesUpgrade(army, target, aiNk->cbc->getResourceAmount()).upgradeCost[EGameResID::GOLD];
return aiNk->armyManager->calculateCreaturesUpgrade(army, target, aiNk->cc->getResourceAmount()).upgradeCost[EGameResID::GOLD];
case Obj::SCHOOL_OF_MAGIC:
case Obj::SCHOOL_OF_WAR:
return 1000;
@@ -499,7 +499,7 @@ float RewardEvaluator::getStrategicalValue(const CGObjectInstance * target, cons
}
auto fortLevel = town->fortLevel();
auto booster = isAnotherAi(town, *aiNk->cbc) ? 0.4f : 1.0f;
auto booster = isAnotherAi(town, *aiNk->cc) ? 0.4f : 1.0f;
if(town->hasCapitol())
return booster * 1.5;
@@ -511,7 +511,7 @@ float RewardEvaluator::getStrategicalValue(const CGObjectInstance * target, cons
}
case Obj::HERO:
return aiNk->cbc->getPlayerRelations(target->tempOwner, aiNk->playerID) == PlayerRelations::ENEMIES
return aiNk->cc->getPlayerRelations(target->tempOwner, aiNk->playerID) == PlayerRelations::ENEMIES
? getEnemyHeroStrategicalValue(dynamic_cast<const CGHeroInstance *>(target))
: 0;
@@ -575,7 +575,7 @@ float RewardEvaluator::getConquestValue(const CGObjectInstance* target) const
}
case Obj::HERO:
return aiNk->cbc->getPlayerRelations(target->tempOwner, aiNk->playerID) == PlayerRelations::ENEMIES
return aiNk->cc->getPlayerRelations(target->tempOwner, aiNk->playerID) == PlayerRelations::ENEMIES
? getEnemyHeroStrategicalValue(dynamic_cast<const CGHeroInstance*>(target))
: 0;
@@ -595,7 +595,7 @@ float RewardEvaluator::evaluateWitchHutSkillScore(const CGObjectInstance * hut,
return role == HeroRole::SCOUT ? 2 : 0;
if(hero->getSecSkillLevel(skill) != MasteryLevel::NONE
|| static_cast<int>(hero->secSkills.size()) >= cbcTl->getSettings().getInteger(EGameSettings::HEROES_SKILL_PER_HERO))
|| static_cast<int>(hero->secSkills.size()) >= ccTl->getSettings().getInteger(EGameSettings::HEROES_SKILL_PER_HERO))
return 0;
auto score = aiNk->heroManager->evaluateSecSkill(skill, hero);
@@ -639,7 +639,7 @@ float RewardEvaluator::getSkillReward(const CGObjectInstance * target, const CGH
//Can contains experience, spells, or skills (only on custom maps)
return 2.5f;
case Obj::HERO:
return aiNk->cbc->getPlayerRelations(target->tempOwner, aiNk->playerID) == PlayerRelations::ENEMIES
return aiNk->cc->getPlayerRelations(target->tempOwner, aiNk->playerID) == PlayerRelations::ENEMIES
? enemyHeroEliminationSkillRewardRatio * dynamic_cast<const CGHeroInstance *>(target)->level
: 0;
@@ -719,7 +719,7 @@ int32_t RewardEvaluator::getGoldReward(const CGObjectInstance * target, const CG
if(!target)
return 0;
auto relations = aiNk->cbc->getPlayerRelations(target->tempOwner, hero->tempOwner);
auto relations = aiNk->cc->getPlayerRelations(target->tempOwner, hero->tempOwner);
const int dailyIncomeMultiplier = 5;
const float enemyArmyEliminationGoldRewardRatio = 0.2f;
@@ -737,7 +737,7 @@ int32_t RewardEvaluator::getGoldReward(const CGObjectInstance * target, const CG
case Obj::WATER_WHEEL:
return 1000;
case Obj::TOWN:
return dailyIncomeMultiplier * estimateTownIncome(aiNk->cbc.get(), target, hero);
return dailyIncomeMultiplier * estimateTownIncome(aiNk->cc.get(), target, hero);
case Obj::MINE:
case Obj::ABANDONED_MINE:
{
@@ -824,7 +824,7 @@ public:
int tilesDiscovered = task->value;
evaluationContext.addNonCriticalStrategicalValue(0.03f * tilesDiscovered);
for (auto obj : evaluationContext.evaluator.aiNk->cbc->getVisitableObjs(task->tile))
for (auto obj : evaluationContext.evaluator.aiNk->cc->getVisitableObjs(task->tile))
{
switch (obj->ID.num)
{
@@ -839,7 +839,7 @@ public:
break;
}
}
if(evaluationContext.evaluator.aiNk->cbc->getTile(task->tile)->roadType != RoadId::NO_ROAD)
if(evaluationContext.evaluator.aiNk->cc->getTile(task->tile)->roadType != RoadId::NO_ROAD)
evaluationContext.explorePriority = 1;
if (evaluationContext.explorePriority == 0)
evaluationContext.explorePriority = 3;
@@ -910,7 +910,7 @@ public:
if(defendTown.getTurn() > 0 && defendTown.isCounterAttack())
{
auto ourSpeed = defendTown.hero->movementPointsLimit(true);
auto enemySpeed = threat.hero.get(evaluationContext.evaluator.aiNk->cbc.get())->movementPointsLimit(true);
auto enemySpeed = threat.hero.get(evaluationContext.evaluator.aiNk->cc.get())->movementPointsLimit(true);
if(enemySpeed > ourSpeed) multiplier *= 0.7f;
}
@@ -986,7 +986,7 @@ public:
bool checkGold = evaluationContext.danger == 0;
auto army = path.heroArmy;
const CGObjectInstance * target = aiNk->cbc->getObj((ObjectInstanceID)task->objid, false);
const CGObjectInstance * target = aiNk->cc->getObj((ObjectInstanceID)task->objid, false);
auto heroRole = evaluationContext.evaluator.aiNk->heroManager->getHeroRole(hero);
if(heroRole == HeroRole::MAIN)
@@ -1038,7 +1038,7 @@ public:
evaluationContext.conquestValue += evaluationContext.evaluator.getConquestValue(target);
if (target->ID == Obj::HERO)
evaluationContext.isHero = true;
if (target->getOwner().isValidPlayer() && aiNk->cbc->getPlayerRelations(aiNk->playerID, target->getOwner()) == PlayerRelations::ENEMIES)
if (target->getOwner().isValidPlayer() && aiNk->cc->getPlayerRelations(aiNk->playerID, target->getOwner()) == PlayerRelations::ENEMIES)
evaluationContext.isEnemy = true;
if (target->ID == Obj::TOWN)
evaluationContext.defenseValue = dynamic_cast<const CGTownInstance*>(target)->fortLevel();
@@ -1081,7 +1081,7 @@ public:
for(auto & objInfo : objects)
{
auto target = evaluationContext.evaluator.aiNk->cbc->getObj(objInfo.first);
auto target = evaluationContext.evaluator.aiNk->cc->getObj(objInfo.first);
bool checkGold = objInfo.second.danger == 0;
auto army = hero;
@@ -1118,7 +1118,7 @@ public:
logAi->trace("buildEvaluationContext ExchangeSwapTownHeroesContextBuilder %s affected objects: %d", swapCommand.toString(), swapCommand.getAffectedObjects().size());
for (auto obj : swapCommand.getAffectedObjects())
{
logAi->trace("affected object: %s", evaluationContext.evaluator.aiNk->cbc->getObj(obj)->getObjectName());
logAi->trace("affected object: %s", evaluationContext.evaluator.aiNk->cc->getObj(obj)->getObjectName());
}
if (garrisonHero)
logAi->debug("with %s and %d", garrisonHero->getNameTranslated(), int(swapCommand.getLockingReason()));
@@ -1184,13 +1184,13 @@ public:
bool alreadyOwn = false;
int highestMageGuildPossible = BuildingID::MAGES_GUILD_3;
for (auto town : evaluationContext.evaluator.aiNk->cbc->getTownsInfo())
for (auto town : evaluationContext.evaluator.aiNk->cc->getTownsInfo())
{
if (town->hasBuilt(bi.id))
alreadyOwn = true;
if (evaluationContext.evaluator.aiNk->cbc->canBuildStructure(town, BuildingID::MAGES_GUILD_5) != EBuildingState::FORBIDDEN)
if (evaluationContext.evaluator.aiNk->cc->canBuildStructure(town, BuildingID::MAGES_GUILD_5) != EBuildingState::FORBIDDEN)
highestMageGuildPossible = BuildingID::MAGES_GUILD_5;
else if (evaluationContext.evaluator.aiNk->cbc->canBuildStructure(town, BuildingID::MAGES_GUILD_4) != EBuildingState::FORBIDDEN)
else if (evaluationContext.evaluator.aiNk->cc->canBuildStructure(town, BuildingID::MAGES_GUILD_4) != EBuildingState::FORBIDDEN)
highestMageGuildPossible = BuildingID::MAGES_GUILD_4;
}
@@ -1231,9 +1231,9 @@ public:
else if(bi.id >= BuildingID::MAGES_GUILD_1 && bi.id <= BuildingID::MAGES_GUILD_5)
{
evaluationContext.skillReward += 2 * bi.id.getMagesGuildLevel();
if (!alreadyOwn && evaluationContext.evaluator.aiNk->cbc->canBuildStructure(buildThis.town, highestMageGuildPossible) != EBuildingState::FORBIDDEN)
if (!alreadyOwn && evaluationContext.evaluator.aiNk->cc->canBuildStructure(buildThis.town, highestMageGuildPossible) != EBuildingState::FORBIDDEN)
{
for (auto hero : evaluationContext.evaluator.aiNk->cbc->getHeroesInfo())
for (auto hero : evaluationContext.evaluator.aiNk->cc->getHeroesInfo())
{
if(hero->getPrimSkillLevel(PrimarySkill::SPELL_POWER) + hero->getPrimSkillLevel(PrimarySkill::KNOWLEDGE) > hero->getPrimSkillLevel(PrimarySkill::ATTACK) + hero->getPrimSkillLevel(PrimarySkill::DEFENSE)
&& hero->manaLimit() > 30)
@@ -1242,7 +1242,7 @@ public:
}
}
int sameTownBonus = 0;
for (auto town : evaluationContext.evaluator.aiNk->cbc->getTownsInfo())
for (auto town : evaluationContext.evaluator.aiNk->cc->getTownsInfo())
{
if (buildThis.town->getFaction() == town->getFaction())
sameTownBonus += town->getTownLevel();
@@ -1382,14 +1382,14 @@ float PriorityEvaluator::evaluate(Goals::TSubgoal task, int priorityTier)
#endif
return 0;
}
const bool amIInDanger = aiNk->cbc->getTownsInfo().empty();
const bool amIInDanger = aiNk->cc->getTownsInfo().empty();
// Shouldn't it default to 0 instead of 1.0 in the end?
const float maxWillingToLose = amIInDanger ? 1 : aiNk->settings->getMaxArmyLossTarget() * evaluationContext.powerRatio > 0 ? aiNk->settings->getMaxArmyLossTarget() * evaluationContext.powerRatio : 1.0;
float dangerThreshold = 1;
dangerThreshold *= evaluationContext.powerRatio > 0 ? evaluationContext.powerRatio : 1.0;
bool arriveNextWeek = false;
if (aiNk->cbc->getDate(Date::DAY_OF_WEEK) + evaluationContext.turn > 7 && priorityTier < PriorityTier::FAR_KILL)
if (aiNk->cc->getDate(Date::DAY_OF_WEEK) + evaluationContext.turn > 7 && priorityTier < PriorityTier::FAR_KILL)
arriveNextWeek = true;
#if NKAI_TRACE_LEVEL >= 2
@@ -1435,7 +1435,7 @@ float PriorityEvaluator::evaluate(Goals::TSubgoal task, int priorityTier)
return 0;
if(evaluationContext.conquestValue > 0)
score = evaluationContext.armyInvolvement;
if (vstd::isAlmostZero(score) || (evaluationContext.enemyHeroDangerRatio > dangerThreshold && (evaluationContext.turn > 0 || evaluationContext.isExchange) && !aiNk->cbc->getTownsInfo().empty()))
if (vstd::isAlmostZero(score) || (evaluationContext.enemyHeroDangerRatio > dangerThreshold && (evaluationContext.turn > 0 || evaluationContext.isExchange) && !aiNk->cc->getTownsInfo().empty()))
return 0;
if (maxWillingToLose - evaluationContext.armyLossRatio < 0)
return 0;
@@ -1485,7 +1485,7 @@ float PriorityEvaluator::evaluate(Goals::TSubgoal task, int priorityTier)
return 0;
if (evaluationContext.conquestValue > 0)
score = evaluationContext.armyInvolvement;
if (vstd::isAlmostZero(score) || (evaluationContext.enemyHeroDangerRatio > dangerThreshold && (evaluationContext.turn > 0 || evaluationContext.isExchange) && !aiNk->cbc->getTownsInfo().empty()))
if (vstd::isAlmostZero(score) || (evaluationContext.enemyHeroDangerRatio > dangerThreshold && (evaluationContext.turn > 0 || evaluationContext.isExchange) && !aiNk->cc->getTownsInfo().empty()))
return 0;
if (maxWillingToLose - evaluationContext.armyLossRatio < 0)
return 0;
@@ -1607,7 +1607,7 @@ float PriorityEvaluator::evaluate(Goals::TSubgoal task, int priorityTier)
if (!evaluationContext.isTradeBuilding && aiNk->getFreeResources()[EGameResID::WOOD] - evaluationContext.buildingCost[EGameResID::WOOD] < 5 && aiNk->buildAnalyzer->getDailyIncome()[EGameResID::WOOD] < 1)
{
logAi->trace("Should make sure to build market-place instead of %s", task->toString());
for (auto town : aiNk->cbc->getTownsInfo())
for (auto town : aiNk->cc->getTownsInfo())
{
if (!town->hasBuiltSomeTradeBuilding())
return 0;

View File

@@ -47,7 +47,7 @@ std::string AbstractGoal::toString() const
break;
case TRADE:
{
auto obj = cbcTl->getObjInstance(ObjectInstanceID(objid));
auto obj = ccTl->getObjInstance(ObjectInstanceID(objid));
if (obj)
desc = (boost::format("TRADE %d of %s at %s") % value % GameConstants::RESOURCE_NAMES[resID] % obj->getObjectName()).str();
}

View File

@@ -49,7 +49,7 @@ void AdventureSpellCast::accept(AIGateway * aiGw)
if(town->getVisitingHero() && town->tempOwner == aiGw->playerID && !town->getUpperArmy()->stacksCount())
{
aiGw->cbc->swapGarrisonHero(town);
aiGw->cc->swapGarrisonHero(town);
}
if(town->getVisitingHero())
@@ -57,12 +57,12 @@ void AdventureSpellCast::accept(AIGateway * aiGw)
}
if (hero->isGarrisoned())
aiGw->cbc->swapGarrisonHero(hero->getVisitedTown());
aiGw->cc->swapGarrisonHero(hero->getVisitedTown());
auto wait = cbcTl->waitTillRealize;
auto wait = ccTl->waitTillRealize;
cbcTl->waitTillRealize = true;
cbcTl->castSpell(hero, spellID, tile);
ccTl->waitTillRealize = true;
ccTl->castSpell(hero, spellID, tile);
if(town && townPortalEffect)
{
@@ -70,7 +70,7 @@ void AdventureSpellCast::accept(AIGateway * aiGw)
aiGw->moveHeroToTile(town->visitablePos(), hero);
}
cbcTl->waitTillRealize = wait;
ccTl->waitTillRealize = wait;
throw goalFulfilledException(sptr(*this));
}

View File

@@ -45,12 +45,12 @@ void BuildBoat::accept(AIGateway * aiGw)
TResources boatCost;
shipyard->getBoatCost(boatCost);
if(!cbcTl->getResourceAmount().canAfford(boatCost))
if(!ccTl->getResourceAmount().canAfford(boatCost))
{
throw cannotFulfillGoalException("Can not afford boat");
}
if(cbcTl->getPlayerRelations(aiGw->playerID, shipyard->getObject()->getOwner()) == PlayerRelations::ENEMIES)
if(ccTl->getPlayerRelations(aiGw->playerID, shipyard->getObject()->getOwner()) == PlayerRelations::ENEMIES)
{
throw cannotFulfillGoalException("Can not build boat in enemy shipyard");
}
@@ -65,7 +65,7 @@ void BuildBoat::accept(AIGateway * aiGw)
shipyard->getObject()->visitablePos().toString(),
shipyard->bestLocation().toString());
cbcTl->buildBoat(shipyard);
ccTl->buildBoat(shipyard);
throw goalFulfilledException(sptr(*this));
}

View File

@@ -52,11 +52,11 @@ void BuildThis::accept(AIGateway * aiGw)
if(town)
{
if(cbcTl->canBuildStructure(town, b) == EBuildingState::ALLOWED)
if(ccTl->canBuildStructure(town, b) == EBuildingState::ALLOWED)
{
logAi->debug("Player %d will build %s in town of %s at %s",
aiGw->playerID, town->getTown()->buildings.at(b)->getNameTranslated(), town->getNameTranslated(), town->anchorPos().toString());
cbcTl->buildBuilding(town, b);
ccTl->buildBuilding(town, b);
return;
}

View File

@@ -48,7 +48,7 @@ void BuyArmy::accept(AIGateway * aiGw)
for(int i = 0; valueBought < value && i < armyToBuy.size(); i++)
{
auto res = cbcTl->getResourceAmount();
auto res = ccTl->getResourceAmount();
auto & ci = armyToBuy[i];
if(objid != CreatureID::NONE && ci.creID.getNum() != objid)
@@ -81,12 +81,12 @@ void BuyArmy::accept(AIGateway * aiGw)
}
if (lowestValueSlot.validSlot())
{
cbcTl->dismissCreature(town->getUpperArmy(), lowestValueSlot);
ccTl->dismissCreature(town->getUpperArmy(), lowestValueSlot);
}
}
if (town->getUpperArmy()->stacksCount() < GameConstants::ARMY_SIZE || town->getUpperArmy()->getSlotFor(ci.creID).validSlot()) //It is possible we don't scrap despite we wanted to due to not scrapping stacks that fit our faction
{
cbcTl->recruitCreatures(town, town->getUpperArmy(), ci.creID, ci.count, ci.level);
ccTl->recruitCreatures(town, town->getUpperArmy(), ci.creID, ci.count, ci.level);
}
valueBought += ci.count * ci.creID.toCreature()->getAIValue();
}

View File

@@ -37,7 +37,7 @@ std::string CaptureObject::toString() const
TGoalVec CaptureObject::decompose(const Nullkiller * aiNk) const
{
return CaptureObjectsBehavior(aiNk->cbc->getObj(ObjectInstanceID(objid))).decompose(aiNk);
return CaptureObjectsBehavior(aiNk->cc->getObj(ObjectInstanceID(objid))).decompose(aiNk);
}
}

View File

@@ -22,7 +22,7 @@ using namespace Goals;
bool isKeyMaster(const QuestInfo & q)
{
auto object = q.getObject(cbcTl);
auto object = q.getObject(ccTl);
return object && (object->ID == Obj::BORDER_GATE || object->ID == Obj::BORDERGUARD);
}
@@ -39,7 +39,7 @@ TGoalVec CompleteQuest::decompose(const Nullkiller * ai) const
}
logAi->debug("Trying to realize quest: %s", questToString());
auto quest = q.getQuest(cbcTl);
auto quest = q.getQuest(ccTl);
if(!quest->mission.artifacts.empty())
return missionArt(ai);
@@ -70,52 +70,52 @@ bool CompleteQuest::operator==(const CompleteQuest & other) const
{
if(isKeyMaster(q))
{
return isKeyMaster(other.q) && q.getObject(cbcTl)->subID == other.q.getObject(cbcTl)->subID;
return isKeyMaster(other.q) && q.getObject(ccTl)->subID == other.q.getObject(ccTl)->subID;
}
else if(isKeyMaster(other.q))
{
return false;
}
return q.getQuest(cbcTl) == other.q.getQuest(cbcTl);
return q.getQuest(ccTl) == other.q.getQuest(ccTl);
}
uint64_t CompleteQuest::getHash() const
{
if(isKeyMaster(q))
{
return q.getObject(cbcTl)->subID;
return q.getObject(ccTl)->subID;
}
return q.getObject(cbcTl)->id.getNum();
return q.getObject(ccTl)->id.getNum();
}
std::string CompleteQuest::questToString() const
{
if(isKeyMaster(q))
{
return "find " + LIBRARY->generaltexth->tentColors[q.getObject(cbcTl)->subID] + " keymaster tent";
return "find " + LIBRARY->generaltexth->tentColors[q.getObject(ccTl)->subID] + " keymaster tent";
}
if(q.getQuest(cbcTl)->questName == CQuest::missionName(EQuestMission::NONE))
if(q.getQuest(ccTl)->questName == CQuest::missionName(EQuestMission::NONE))
return "inactive quest";
MetaString ms;
q.getQuest(cbcTl)->getRolloverText(cbcTl, ms, false);
q.getQuest(ccTl)->getRolloverText(ccTl, ms, false);
return ms.toString();
}
TGoalVec CompleteQuest::tryCompleteQuest(const Nullkiller * aiNk) const
{
auto paths = aiNk->pathfinder->getPathInfo(q.getObject(cbcTl)->visitablePos());
auto paths = aiNk->pathfinder->getPathInfo(q.getObject(ccTl)->visitablePos());
vstd::erase_if(paths, [&](const AIPath & path) -> bool
{
return !q.getQuest(cbcTl)->checkQuest(path.targetHero);
return !q.getQuest(ccTl)->checkQuest(path.targetHero);
});
return CaptureObjectsBehavior::getVisitGoals(paths, aiNk, q.getObject(cbcTl));
return CaptureObjectsBehavior::getVisitGoals(paths, aiNk, q.getObject(ccTl));
}
TGoalVec CompleteQuest::missionArt(const Nullkiller * ai) const
@@ -127,7 +127,7 @@ TGoalVec CompleteQuest::missionArt(const Nullkiller * ai) const
CaptureObjectsBehavior findArts;
for(auto art : q.getQuest(cbcTl)->mission.artifacts)
for(auto art : q.getQuest(ccTl)->mission.artifacts)
{
solutions.push_back(sptr(CaptureObjectsBehavior().ofType(Obj::ARTIFACT, art.getNum())));
}
@@ -150,14 +150,14 @@ TGoalVec CompleteQuest::missionHero(const Nullkiller * ai) const
TGoalVec CompleteQuest::missionArmy(const Nullkiller * aiNk) const
{
auto paths = aiNk->pathfinder->getPathInfo(q.getObject(cbcTl)->visitablePos());
auto paths = aiNk->pathfinder->getPathInfo(q.getObject(ccTl)->visitablePos());
vstd::erase_if(paths, [&](const AIPath & path) -> bool
{
return !CQuest::checkMissionArmy(q.getQuest(cbcTl), path.heroArmy);
return !CQuest::checkMissionArmy(q.getQuest(ccTl), path.heroArmy);
});
return CaptureObjectsBehavior::getVisitGoals(paths, aiNk, q.getObject(cbcTl));
return CaptureObjectsBehavior::getVisitGoals(paths, aiNk, q.getObject(ccTl));
}
TGoalVec CompleteQuest::missionIncreasePrimaryStat(const Nullkiller * ai) const
@@ -172,13 +172,13 @@ TGoalVec CompleteQuest::missionLevel(const Nullkiller * ai) const
TGoalVec CompleteQuest::missionKeymaster(const Nullkiller * ai) const
{
if(isObjectPassable(ai, q.getObject(cbcTl)))
if(isObjectPassable(ai, q.getObject(ccTl)))
{
return CaptureObjectsBehavior(q.getObject(cbcTl)).decompose(ai);
return CaptureObjectsBehavior(q.getObject(ccTl)).decompose(ai);
}
else
{
return CaptureObjectsBehavior().ofType(Obj::KEYMASTER, q.getObject(cbcTl)->subID).decompose(ai);
return CaptureObjectsBehavior().ofType(Obj::KEYMASTER, q.getObject(ccTl)->subID).decompose(ai);
}
}
@@ -190,12 +190,12 @@ TGoalVec CompleteQuest::missionResources(const Nullkiller * ai) const
TGoalVec CompleteQuest::missionDestroyObj(const Nullkiller * aiNk) const
{
auto obj = aiNk->cbc->getObj(q.getQuest(cbcTl)->killTarget);
auto obj = aiNk->cc->getObj(q.getQuest(ccTl)->killTarget);
if(!obj)
return CaptureObjectsBehavior(q.getObject(cbcTl)).decompose(aiNk);
return CaptureObjectsBehavior(q.getObject(ccTl)).decompose(aiNk);
auto relations = aiNk->cbc->getPlayerRelations(aiNk->playerID, obj->tempOwner);
auto relations = aiNk->cc->getPlayerRelations(aiNk->playerID, obj->tempOwner);
//if(relations == PlayerRelations::SAME_PLAYER)
//{

View File

@@ -26,7 +26,7 @@ void DismissHero::accept(AIGateway * aiGw)
if(!hero)
throw cannotFulfillGoalException("Invalid hero!");
cbcTl->dismissHero(hero);
ccTl->dismissHero(hero);
throw goalFulfilledException(sptr(*this));
}

View File

@@ -65,7 +65,7 @@ void ExchangeSwapTownHeroes::accept(AIGateway * aiGw)
if(!currentGarrisonHero)
throw cannotFulfillGoalException("Invalid configuration. There is no hero in town garrison.");
cbcTl->swapGarrisonHero(town);
ccTl->swapGarrisonHero(town);
if(currentGarrisonHero != town->getVisitingHero())
{
@@ -81,7 +81,7 @@ void ExchangeSwapTownHeroes::accept(AIGateway * aiGw)
}
if(town->getVisitingHero() && town->getVisitingHero() != getGarrisonHero())
cbcTl->swapGarrisonHero(town);
ccTl->swapGarrisonHero(town);
aiGw->makePossibleUpgrades(town);
aiGw->moveHeroToTile(town->visitablePos(), getGarrisonHero());
@@ -94,12 +94,12 @@ void ExchangeSwapTownHeroes::accept(AIGateway * aiGw)
{
while (upperArmy->stacksCount() != 0)
{
cbcTl->dismissCreature(upperArmy, upperArmy->Slots().begin()->first);
ccTl->dismissCreature(upperArmy, upperArmy->Slots().begin()->first);
}
}
}
cbcTl->swapGarrisonHero(town);
ccTl->swapGarrisonHero(town);
if(lockingReason != HeroLockedReason::NOT_LOCKED)
{

View File

@@ -88,11 +88,11 @@ void ExecuteHeroChain::accept(AIGateway * aiGw)
aiGw->nullkiller->setTargetObject(objid);
aiGw->nullkiller->objectClusterizer->reset();
auto targetObject = aiGw->cbc->getObj(static_cast<ObjectInstanceID>(objid), false);
auto targetObject = aiGw->cc->getObj(static_cast<ObjectInstanceID>(objid), false);
if(chainPath.turn() == 0 && targetObject && targetObject->ID == Obj::TOWN)
{
auto relations = aiGw->cbc->getPlayerRelations(aiGw->playerID, targetObject->getOwner());
auto relations = aiGw->cc->getPlayerRelations(aiGw->playerID, targetObject->getOwner());
if(relations == PlayerRelations::ENEMIES)
{
@@ -200,7 +200,7 @@ void ExecuteHeroChain::accept(AIGateway * aiGw)
auto findWhirlpool = [&aiGw](const int3 & pos) -> ObjectInstanceID
{
auto objs = aiGw->cbc->getVisitableObjs(pos);
auto objs = aiGw->cc->getVisitableObjs(pos);
auto whirlpool = std::find_if(objs.begin(), objs.end(), [](const CGObjectInstance * o)->bool
{
return o->ID == Obj::WHIRLPOOL;
@@ -296,7 +296,7 @@ std::string ExecuteHeroChain::toString() const
bool ExecuteHeroChain::moveHeroToTile(AIGateway * aiGw, const CGHeroInstance * hero, const int3 & tile)
{
if(tile == hero->visitablePos() && aiGw->cbc->getVisitableObjs(hero->visitablePos()).size() < 2)
if(tile == hero->visitablePos() && aiGw->cc->getVisitableObjs(hero->visitablePos()).size() < 2)
{
logAi->warn("Why do I want to move hero %s to tile %s? Already standing on that tile! ", hero->getNameTranslated(), tile.toString());

View File

@@ -28,7 +28,7 @@ void ExploreNeighbourTile::accept(AIGateway * aiGw)
{
ExplorationHelper h(hero, aiGw->nullkiller.get(), true);
for(int i = 0; i < tilesToExplore && aiGw->cbc->getObj(hero->id, false) && hero->movementPointsRemaining() > 0; i++)
for(int i = 0; i < tilesToExplore && aiGw->cc->getObj(hero->id, false) && hero->movementPointsRemaining() > 0; i++)
{
int3 pos = hero->visitablePos();
float value = 0;

View File

@@ -38,7 +38,7 @@ void RecruitHero::accept(AIGateway * aiGw)
logAi->debug("Trying to recruit a hero in %s at %s", t->getNameTranslated(), t->visitablePos().toString());
auto heroes = cbcTl->getAvailableHeroes(t);
auto heroes = ccTl->getAvailableHeroes(t);
if(!heroes.size())
{
@@ -61,13 +61,13 @@ void RecruitHero::accept(AIGateway * aiGw)
if(t->getVisitingHero())
{
cbcTl->swapGarrisonHero(t);
ccTl->swapGarrisonHero(t);
}
if(t->getVisitingHero())
throw cannotFulfillGoalException("Town " + t->nodeName() + " is occupied. Cannot recruit hero!");
cbcTl->recruitHero(t, heroToHire);
ccTl->recruitHero(t, heroToHire);
{
std::unique_lock lockGuard(aiGw->nullkiller->aiStateMutex);

View File

@@ -25,9 +25,9 @@ namespace NK2AI
using namespace Goals;
ExplorationHelper::ExplorationHelper(const CGHeroInstance * hero, const Nullkiller * aiNk, bool useCPathfinderAccessibility)
:aiNk(aiNk), cbc(aiNk->cbc.get()), hero(hero), useCPathfinderAccessibility(useCPathfinderAccessibility)
:aiNk(aiNk), cc(aiNk->cc.get()), hero(hero), useCPathfinderAccessibility(useCPathfinderAccessibility)
{
ts = cbc->getPlayerTeam(aiNk->playerID);
ts = cc->getPlayerTeam(aiNk->playerID);
sightRadius = hero->getSightRadius();
bestGoal = sptr(Goals::Invalid());
bestValue = 0;
@@ -55,7 +55,7 @@ bool ExplorationHelper::scanSector(int scanRadius)
{
for(tile.y = ourPos.y - scanRadius; tile.y <= ourPos.y + scanRadius; tile.y++)
{
if(cbc->isInTheMap(tile) && slice[tile.x][tile.y])
if(cc->isInTheMap(tile) && slice[tile.x][tile.y])
{
scanTile(tile);
}
@@ -67,7 +67,7 @@ bool ExplorationHelper::scanSector(int scanRadius)
bool ExplorationHelper::scanMap()
{
int3 mapSize = cbc->getMapSize();
int3 mapSize = cc->getMapSize();
int perimeter = 2 * sightRadius * (mapSize.x + mapSize.y);
std::vector<int3> edgeTiles;
@@ -79,7 +79,7 @@ bool ExplorationHelper::scanMap()
{
bool hasInvisibleNeighbor = false;
foreach_neighbour(cbc, pos, [&](CCallback * cbp, int3 neighbour)
foreach_neighbour(cc, pos, [&](CCallback * cbp, int3 neighbour)
{
if(!ts->fogOfWarMap[neighbour.z][neighbour.x][neighbour.y])
{
@@ -120,7 +120,7 @@ bool ExplorationHelper::scanMap()
for(const int3 & tile : tilesToExploreFrom)
{
foreach_neighbour(cbc, tile, [&](CCallback * cbp, int3 neighbour)
foreach_neighbour(cc, tile, [&](CCallback * cbp, int3 neighbour)
{
if(potentialTiles[neighbour.z][neighbour.x][neighbour.y])
{
@@ -143,7 +143,7 @@ bool ExplorationHelper::scanMap()
void ExplorationHelper::scanTile(const int3 & tile)
{
if(tile == ourPos
|| !aiNk->cbc->getTile(tile, false)
|| !aiNk->cc->getTile(tile, false)
|| !aiNk->pathfinder->isTileAccessible(hero, tile)) //shouldn't happen, but it does
return;
@@ -152,7 +152,7 @@ void ExplorationHelper::scanTile(const int3 & tile)
return;
auto paths = aiNk->pathfinder->getPathInfo(tile);
auto waysToVisit = CaptureObjectsBehavior::getVisitGoals(paths, aiNk, aiNk->cbc->getTopObj(tile));
auto waysToVisit = CaptureObjectsBehavior::getVisitGoals(paths, aiNk, aiNk->cc->getTopObj(tile));
for(int i = 0; i != paths.size(); i++)
{
@@ -166,7 +166,7 @@ void ExplorationHelper::scanTile(const int3 & tile)
if(ourValue > bestValue) //avoid costly checks of tiles that don't reveal much
{
auto obj = cbc->getTopObj(tile);
auto obj = cc->getTopObj(tile);
// picking up resources does not yield any exploration at all.
// if it blocks the way to some explorable tile AIPathfinder will take care of it
@@ -197,7 +197,7 @@ int ExplorationHelper::howManyTilesWillBeDiscovered(const int3 & pos) const
{
for(npos.y = pos.y - sightRadius; npos.y <= pos.y + sightRadius; npos.y++)
{
if(cbc->isInTheMap(npos)
if(cc->isInTheMap(npos)
&& pos.dist2d(npos) - 0.5 < sightRadius
&& !slice[npos.x][npos.y])
{
@@ -220,7 +220,7 @@ bool ExplorationHelper::hasReachableNeighbor(const int3 & pos) const
for(const int3 & dir : int3::getDirs())
{
int3 tile = pos + dir;
if(cbc->isInTheMap(tile))
if(cc->isInTheMap(tile))
{
auto isAccessible = useCPathfinderAccessibility
? aiNk->getPathsInfo(hero)->getPathInfo(tile)->reachable()

View File

@@ -28,7 +28,7 @@ private:
int3 bestTile;
int bestTilesDiscovered;
const Nullkiller * aiNk;
CCallback * cbc;
CCallback * cc;
const TeamState * ts;
int3 ourPos;
bool allowDeadEndCancellation;

View File

@@ -103,7 +103,7 @@ int AINodeStorage::getBucketSize() const
}
AINodeStorage::AINodeStorage(const Nullkiller * aiNk, const int3 & Sizes)
: sizes(Sizes), aiNk(aiNk), cbc(aiNk->cbc.get()), nodes(Sizes, aiNk->settings->getPathfinderBucketSize() * aiNk->settings->getPathfinderBucketsCount())
: sizes(Sizes), aiNk(aiNk), cc(aiNk->cc.get()), nodes(Sizes, aiNk->settings->getPathfinderBucketSize() * aiNk->settings->getPathfinderBucketsCount())
{
accessibility = std::make_unique<boost::multi_array<EPathAccessibility, 4>>(
boost::extents[sizes.z][sizes.x][sizes.y][EPathfindingLayer::NUM_LAYERS]);
@@ -1162,11 +1162,11 @@ void AINodeStorage::calculateTownPortal(
const std::vector<CGPathNode *> & initialNodes,
TVector & output)
{
auto towns = cbc->getTownsInfo(false);
auto towns = cc->getTownsInfo(false);
vstd::erase_if(towns, [&](const CGTownInstance * t) -> bool
{
return cbc->getPlayerRelations(actor->hero->tempOwner, t->tempOwner) == PlayerRelations::ENEMIES;
return cc->getPlayerRelations(actor->hero->tempOwner, t->tempOwner) == PlayerRelations::ENEMIES;
});
if(!towns.size())
@@ -1457,7 +1457,7 @@ void AINodeStorage::calculateChainInfo(std::vector<AIPath> & paths, const int3 &
}
int fortLevel = 0;
auto visitableObjects = cbc->getVisitableObjs(pos);
auto visitableObjects = cc->getVisitableObjs(pos);
for (auto obj : visitableObjects)
{
if (objWithID<Obj::TOWN>(obj))

View File

@@ -165,7 +165,7 @@ private:
std::unique_ptr<boost::multi_array<EPathAccessibility, 4>> accessibility;
const CPlayerSpecificInfoCallback * cbc;
const CPlayerSpecificInfoCallback * cc;
const Nullkiller * aiNk;
AISharedStorage nodes;
std::vector<std::shared_ptr<ChainActor>> actors;

View File

@@ -29,7 +29,7 @@ namespace AIPathfinding
Goals::TSubgoal BuildBoatAction::decompose(const Nullkiller * aiNk, const CGHeroInstance * hero) const
{
if(cbc->getPlayerRelations(aiNk->playerID, shipyard->getObject()->getOwner()) == PlayerRelations::ENEMIES)
if(cpsic->getPlayerRelations(aiNk->playerID, shipyard->getObject()->getOwner()) == PlayerRelations::ENEMIES)
{
return Goals::sptr(Goals::CaptureObject(targetObject()));
}
@@ -39,7 +39,7 @@ namespace AIPathfinding
bool BuildBoatAction::canAct(const Nullkiller * ai, const CGHeroInstance * hero, const TResources & reservedResources) const
{
if(cbc->getPlayerRelations(hero->tempOwner, shipyard->getObject()->getOwner()) == PlayerRelations::ENEMIES)
if(cpsic->getPlayerRelations(hero->tempOwner, shipyard->getObject()->getOwner()) == PlayerRelations::ENEMIES)
{
#if NKAI_TRACE_LEVEL > 1
logAi->trace("Can not build a boat. Shipyard is enemy.");
@@ -51,7 +51,7 @@ namespace AIPathfinding
shipyard->getBoatCost(boatCost);
if(!cbc->getResourceAmount().canAfford(reservedResources + boatCost))
if(!cpsic->getResourceAmount().canAfford(reservedResources + boatCost))
{
#if NKAI_TRACE_LEVEL > 1
logAi->trace("Can not build a boat. Not enough resources.");
@@ -87,7 +87,7 @@ namespace AIPathfinding
std::shared_ptr<SpecialAction> BuildBoatActionFactory::create(const Nullkiller * aiNk)
{
return std::make_shared<BuildBoatAction>(aiNk->cbc.get(), dynamic_cast<const IShipyard * >(aiNk->cbc->getObj(shipyard)));
return std::make_shared<BuildBoatAction>(aiNk->cc.get(), dynamic_cast<const IShipyard * >(aiNk->cc->getObj(shipyard)));
}
void SummonBoatAction::execute(AIGateway * aiGw, const CGHeroInstance * hero) const

View File

@@ -54,11 +54,11 @@ namespace AIPathfinding
{
private:
const IShipyard * shipyard;
const CPlayerSpecificInfoCallback * cbc;
const CPlayerSpecificInfoCallback * cpsic;
public:
BuildBoatAction(const CPlayerSpecificInfoCallback * cbc, const IShipyard * shipyard)
: cbc(cbc), shipyard(shipyard)
BuildBoatAction(const CPlayerSpecificInfoCallback * cpsic, const IShipyard * shipyard)
: cpsic(cpsic), shipyard(shipyard)
{
}

View File

@@ -31,8 +31,8 @@ namespace AIPathfinding
bool QuestAction::canAct(const Nullkiller * aiNk, const CGHeroInstance * hero) const
{
auto object = questInfo.getObject(aiNk->cbc.get());
auto quest = questInfo.getQuest(aiNk->cbc.get());
auto object = questInfo.getObject(aiNk->cc.get());
auto quest = questInfo.getQuest(aiNk->cc.get());
if(object->ID == Obj::BORDER_GATE || object->ID == Obj::BORDERGUARD)
{
return dynamic_cast<const IQuestObject *>(object)->checkQuest(hero);
@@ -52,7 +52,7 @@ namespace AIPathfinding
void QuestAction::execute(AIGateway * aiGw, const CGHeroInstance * hero) const
{
aiGw->moveHeroToTile(questInfo.getObject(aiGw->cbc.get())->visitablePos(), hero);
aiGw->moveHeroToTile(questInfo.getObject(aiGw->cc.get())->visitablePos(), hero);
}
std::string QuestAction::toString() const

View File

@@ -260,7 +260,7 @@ ExchangeResult HeroExchangeMap::tryExchangeNoLock(const ChainActor * other)
if(actor->allowSpellCast || other->allowSpellCast)
return result;
TResources resources = aiNk->cbc->getResourceAmount();
TResources resources = aiNk->cc->getResourceAmount();
if(!resources.canAfford(actor->armyCost + other->armyCost))
{
@@ -367,7 +367,7 @@ HeroExchangeArmy * HeroExchangeMap::tryUpgrade(
if(upgrader->ID == Obj::TOWN)
{
auto buyArmy = aiNk->armyManager->getArmyAvailableToBuy(target, aiNk->cbc->getTown(upgrader->id), resources);
auto buyArmy = aiNk->armyManager->getArmyAvailableToBuy(target, aiNk->cc->getTown(upgrader->id), resources);
for(auto & creatureToBuy : buyArmy)
{
@@ -394,7 +394,7 @@ HeroExchangeArmy * HeroExchangeMap::tryUpgrade(
HeroExchangeArmy * HeroExchangeMap::pickBestCreatures(const CCreatureSet * army1, const CCreatureSet * army2) const
{
auto * target = new HeroExchangeArmy();
auto bestArmy = aiNk->armyManager->getBestArmy(actor->hero, army1, army2, aiNk->cbc->getTile(actor->hero->visitablePos())->getTerrainID());
auto bestArmy = aiNk->armyManager->getBestArmy(actor->hero, army1, army2, aiNk->cc->getTile(actor->hero->visitablePos())->getTerrainID());
for(auto & slotInfo : bestArmy)
{

View File

@@ -122,7 +122,7 @@ void GraphPaths::calculatePaths(const CGHeroInstance * targetHero, const Nullkil
if(targetGraphNode.objID.hasValue())
{
targetNode.obj = aiNk->cbc->getObj(targetGraphNode.objID, false);
targetNode.obj = aiNk->cc->getObj(targetGraphNode.objID, false);
if(targetNode.obj && targetNode.obj->ID == Obj::HERO)
return;

View File

@@ -86,7 +86,7 @@ void ObjectGraph::removeObject(const CGObjectInstance * obj)
{
vstd::erase_if(nodes[obj->visitablePos()].connections, [&](const std::pair<int3, ObjectLink> & link) -> bool
{
auto tile = cbcTl->getTile(link.first, false);
auto tile = ccTl->getTile(link.first, false);
return tile && tile->isWater();
});

View File

@@ -35,7 +35,7 @@ void ObjectGraphCalculator::setGraphObjects()
}
}
for(auto town : aiNk->cbc->getTownsInfo())
for(auto town : aiNk->cc->getTownsInfo())
{
addObjectActor(town);
}
@@ -47,7 +47,7 @@ void ObjectGraphCalculator::calculateConnections()
std::vector<AIPath> pathCache;
foreach_tile_pos(aiNk->cbc.get(), [this, &pathCache](const CPlayerSpecificInfoCallback * cb, const int3 & pos)
foreach_tile_pos(aiNk->cc.get(), [this, &pathCache](const CPlayerSpecificInfoCallback * cb, const int3 & pos)
{
calculateConnections(pos, pathCache);
});
@@ -65,7 +65,7 @@ float ObjectGraphCalculator::getNeighborConnectionsCost(const int3 & pos, std::v
}
foreach_neighbour(
aiNk->cbc.get(),
aiNk->cc.get(),
pos,
[this, &neighborCost, &pathCache](const CPlayerSpecificInfoCallback * cb, const int3 & neighbor)
{
@@ -91,12 +91,12 @@ void ObjectGraphCalculator::addMinimalDistanceJunctions()
{
tbb::concurrent_unordered_set<int3, std::hash<int3>> junctions;
pforeachTilePaths(aiNk->cbc->getMapSize(), aiNk, [this, &junctions](const int3 & pos, std::vector<AIPath> & paths)
pforeachTilePaths(aiNk->cc->getMapSize(), aiNk, [this, &junctions](const int3 & pos, std::vector<AIPath> & paths)
{
if(target->hasNodeAt(pos))
return;
if(aiNk->cbc->getGuardingCreaturePosition(pos).isValid())
if(aiNk->cc->getGuardingCreaturePosition(pos).isValid())
return;
ConnectionCostInfo currentCost = getConnectionsCost(paths);
@@ -134,7 +134,7 @@ void ObjectGraphCalculator::calculateConnections(const int3 & pos, std::vector<A
if(target->hasNodeAt(pos))
{
foreach_neighbour(
aiNk->cbc.get(),
aiNk->cc.get(),
pos,
[this, &pos, &pathCache](const CPlayerSpecificInfoCallback * cb, const int3 & neighbor)
{
@@ -152,7 +152,7 @@ void ObjectGraphCalculator::calculateConnections(const int3 & pos, std::vector<A
}
});
auto obj = aiNk->cbc->getTopObj(pos);
auto obj = aiNk->cc->getTopObj(pos);
if((obj && obj->ID == Obj::BOAT) || target->isVirtualBoat(pos))
{
@@ -185,7 +185,7 @@ void ObjectGraphCalculator::calculateConnections(const int3 & pos, std::vector<A
return;
}
auto guardPos = aiNk->cbc->getGuardingCreaturePosition(pos);
auto guardPos = aiNk->cc->getGuardingCreaturePosition(pos);
aiNk->pathfinder->calculatePathInfo(pathCache, pos);
@@ -205,12 +205,12 @@ void ObjectGraphCalculator::calculateConnections(const int3 & pos, std::vector<A
auto obj1 = actorObjectMap[path1.targetHero];
auto obj2 = actorObjectMap[path2.targetHero];
auto tile1 = cbcTl->getTile(pos1);
auto tile2 = cbcTl->getTile(pos2);
auto tile1 = ccTl->getTile(pos1);
auto tile2 = ccTl->getTile(pos2);
if(tile2->isWater() && !tile1->isWater())
{
if(!cbcTl->getTile(pos)->isWater())
if(!ccTl->getTile(pos)->isWater())
continue;
auto startingObjIsBoat = (obj1 && obj1->ID == Obj::BOAT) || target->isVirtualBoat(pos1);
@@ -295,7 +295,7 @@ void ObjectGraphCalculator::addObjectActor(const CGObjectInstance * obj)
objectActor->pos = objectActor->convertFromVisitablePos(visitablePos);
objectActor->initObj(randomizer);
if(cbcTl->getTile(visitablePos)->isWater())
if(ccTl->getTile(visitablePos)->isWater())
{
objectActor->setBoat(temporaryBoats.emplace_back(std::make_unique<CGBoat>(objectActor->cb)).get());
}
@@ -332,7 +332,7 @@ void ObjectGraphCalculator::addJunctionActor(const int3 & visitablePos, bool isV
objectActor->pos = objectActor->convertFromVisitablePos(visitablePos);
objectActor->initObj(randomizer);
if(isVirtualBoat || aiNk->cbc->getTile(visitablePos)->isWater())
if(isVirtualBoat || aiNk->cc->getTile(visitablePos)->isWater())
{
objectActor->setBoat(temporaryBoats.emplace_back(std::make_unique<CGBoat>(objectActor->cb)).get());
}

View File

@@ -49,7 +49,7 @@ namespace AIPathfinding
return;
// when actor represents moster graph node, we need to let him escape monster
if(cbcTl->getGuardingCreaturePosition(source.coord) == actor->initialPosition)
if(ccTl->getGuardingCreaturePosition(source.coord) == actor->initialPosition)
return;
}