mirror of
https://github.com/vcmi/vcmi.git
synced 2024-12-24 22:14:36 +02:00
VCAI tweaks (#311)
* Add extra priority support for town capture evaluation * Improve building algorithm * GatherArmy: check free gold instead of total for when hiring heroes
This commit is contained in:
parent
98140aab6b
commit
0cb6515ae8
@ -338,6 +338,7 @@ FuzzyHelper::EvalVisitTile::~EvalVisitTile()
|
|||||||
delete heroStrength;
|
delete heroStrength;
|
||||||
delete turnDistance;
|
delete turnDistance;
|
||||||
delete missionImportance;
|
delete missionImportance;
|
||||||
|
delete estimatedReward;
|
||||||
}
|
}
|
||||||
|
|
||||||
void FuzzyHelper::initVisitTile()
|
void FuzzyHelper::initVisitTile()
|
||||||
@ -348,11 +349,12 @@ void FuzzyHelper::initVisitTile()
|
|||||||
vt.heroStrength = new fl::InputVariable("heroStrength"); //we want to use weakest possible hero
|
vt.heroStrength = new fl::InputVariable("heroStrength"); //we want to use weakest possible hero
|
||||||
vt.turnDistance = new fl::InputVariable("turnDistance"); //we want to use hero who is near
|
vt.turnDistance = new fl::InputVariable("turnDistance"); //we want to use hero who is near
|
||||||
vt.missionImportance = new fl::InputVariable("lockedMissionImportance"); //we may want to preempt hero with low-priority mission
|
vt.missionImportance = new fl::InputVariable("lockedMissionImportance"); //we may want to preempt hero with low-priority mission
|
||||||
|
vt.estimatedReward = new fl::InputVariable("estimatedReward"); //indicate AI that content of the file is important or it is probably bad
|
||||||
vt.value = new fl::OutputVariable("Value");
|
vt.value = new fl::OutputVariable("Value");
|
||||||
vt.value->setMinimum(0);
|
vt.value->setMinimum(0);
|
||||||
vt.value->setMaximum(5);
|
vt.value->setMaximum(5);
|
||||||
|
|
||||||
std::vector<fl::InputVariable*> helper = {vt.strengthRatio, vt.heroStrength, vt.turnDistance, vt.missionImportance};
|
std::vector<fl::InputVariable*> helper = {vt.strengthRatio, vt.heroStrength, vt.turnDistance, vt.missionImportance, vt.estimatedReward};
|
||||||
for (auto val : helper)
|
for (auto val : helper)
|
||||||
{
|
{
|
||||||
vt.engine.addInputVariable(val);
|
vt.engine.addInputVariable(val);
|
||||||
@ -379,6 +381,10 @@ void FuzzyHelper::initVisitTile()
|
|||||||
vt.missionImportance->addTerm(new fl::Ramp("HIGH", 2.5, 5));
|
vt.missionImportance->addTerm(new fl::Ramp("HIGH", 2.5, 5));
|
||||||
vt.missionImportance->setRange(0.0, 5.0);
|
vt.missionImportance->setRange(0.0, 5.0);
|
||||||
|
|
||||||
|
vt.estimatedReward->addTerm(new fl::Ramp("LOW", 2.5, 0));
|
||||||
|
vt.estimatedReward->addTerm(new fl::Ramp("HIGH", 2.5, 5));
|
||||||
|
vt.estimatedReward->setRange(0.0, 5.0);
|
||||||
|
|
||||||
//an issue: in 99% cases this outputs center of mass (2.5) regardless of actual input :/
|
//an issue: in 99% cases this outputs center of mass (2.5) regardless of actual input :/
|
||||||
//should be same as "mission Importance" to keep consistency
|
//should be same as "mission Importance" to keep consistency
|
||||||
vt.value->addTerm(new fl::Ramp("LOW", 2.5, 0));
|
vt.value->addTerm(new fl::Ramp("LOW", 2.5, 0));
|
||||||
@ -405,6 +411,9 @@ void FuzzyHelper::initVisitTile()
|
|||||||
vt.addRule("if turnDistance is SMALL then Value is HIGH");
|
vt.addRule("if turnDistance is SMALL then Value is HIGH");
|
||||||
vt.addRule("if turnDistance is MEDIUM then Value is MEDIUM");
|
vt.addRule("if turnDistance is MEDIUM then Value is MEDIUM");
|
||||||
vt.addRule("if turnDistance is LONG then Value is LOW");
|
vt.addRule("if turnDistance is LONG then Value is LOW");
|
||||||
|
//some goals are more rewarding by definition f.e. capturing town is more important than collecting resource - experimental
|
||||||
|
vt.addRule("if estimatedReward is HIGH then Value is very HIGH");
|
||||||
|
vt.addRule("if estimatedReward is LOW then Value is somewhat LOW");
|
||||||
}
|
}
|
||||||
catch (fl::Exception & fe)
|
catch (fl::Exception & fe)
|
||||||
{
|
{
|
||||||
@ -440,12 +449,22 @@ float FuzzyHelper::evaluate (Goals::VisitTile & g)
|
|||||||
if (danger)
|
if (danger)
|
||||||
strengthRatio = (fl::scalar)g.hero.h->getTotalStrength() / danger;
|
strengthRatio = (fl::scalar)g.hero.h->getTotalStrength() / danger;
|
||||||
|
|
||||||
|
float tilePriority = 0;
|
||||||
|
if(g.objid == -1)
|
||||||
|
vt.estimatedReward->setEnabled(false);
|
||||||
|
else if(g.objid == Obj::TOWN) //TODO: move to getObj eventually and add appropiate logic there
|
||||||
|
{
|
||||||
|
vt.estimatedReward->setEnabled(true);
|
||||||
|
tilePriority = 5;
|
||||||
|
}
|
||||||
|
|
||||||
try
|
try
|
||||||
{
|
{
|
||||||
vt.strengthRatio->setInputValue(strengthRatio);
|
vt.strengthRatio->setInputValue(strengthRatio);
|
||||||
vt.heroStrength->setInputValue((fl::scalar)g.hero->getTotalStrength() / ai->primaryHero()->getTotalStrength());
|
vt.heroStrength->setInputValue((fl::scalar)g.hero->getTotalStrength() / ai->primaryHero()->getTotalStrength());
|
||||||
vt.turnDistance->setInputValue(turns);
|
vt.turnDistance->setInputValue(turns);
|
||||||
vt.missionImportance->setInputValue(missionImportance);
|
vt.missionImportance->setInputValue(missionImportance);
|
||||||
|
vt.estimatedReward->setInputValue(tilePriority);
|
||||||
|
|
||||||
vt.engine.process();
|
vt.engine.process();
|
||||||
//engine.process(VISIT_TILE); //TODO: Process only Visit_Tile
|
//engine.process(VISIT_TILE); //TODO: Process only Visit_Tile
|
||||||
|
@ -49,6 +49,7 @@ class FuzzyHelper
|
|||||||
fl::InputVariable * heroStrength;
|
fl::InputVariable * heroStrength;
|
||||||
fl::InputVariable * turnDistance;
|
fl::InputVariable * turnDistance;
|
||||||
fl::InputVariable * missionImportance;
|
fl::InputVariable * missionImportance;
|
||||||
|
fl::InputVariable * estimatedReward;
|
||||||
fl::OutputVariable * value;
|
fl::OutputVariable * value;
|
||||||
fl::RuleBlock rules;
|
fl::RuleBlock rules;
|
||||||
~EvalVisitTile();
|
~EvalVisitTile();
|
||||||
|
@ -719,10 +719,12 @@ TSubgoal VisitTile::whatToDoToAchieve()
|
|||||||
{
|
{
|
||||||
auto ret = fh->chooseSolution(getAllPossibleSubgoals());
|
auto ret = fh->chooseSolution(getAllPossibleSubgoals());
|
||||||
|
|
||||||
if (ret->hero)
|
if(ret->hero)
|
||||||
{
|
{
|
||||||
if (isSafeToVisit(ret->hero, tile) && ai->isAccessibleForHero(tile, ret->hero))
|
if(isSafeToVisit(ret->hero, tile) && ai->isAccessibleForHero(tile, ret->hero))
|
||||||
{
|
{
|
||||||
|
if(cb->getTile(tile)->topVisitableId().num == Obj::TOWN) //if target is town, fuzzy system will use additional "estimatedReward" variable to increase priority a bit
|
||||||
|
ret->objid = Obj::TOWN; //TODO: move to getObj eventually and add appropiate logic there
|
||||||
ret->setisElementar(true);
|
ret->setisElementar(true);
|
||||||
return ret;
|
return ret;
|
||||||
}
|
}
|
||||||
@ -973,40 +975,44 @@ TGoalVec Conquer::getAllPossibleSubgoals()
|
|||||||
};
|
};
|
||||||
|
|
||||||
std::vector<const CGObjectInstance *> objs;
|
std::vector<const CGObjectInstance *> objs;
|
||||||
for (auto obj : ai->visitableObjs)
|
for(auto obj : ai->visitableObjs)
|
||||||
{
|
{
|
||||||
if (conquerable(obj))
|
if(conquerable(obj))
|
||||||
objs.push_back (obj);
|
objs.push_back (obj);
|
||||||
}
|
}
|
||||||
|
|
||||||
for (auto h : cb->getHeroesInfo())
|
for(auto h : cb->getHeroesInfo())
|
||||||
{
|
{
|
||||||
auto sm = ai->getCachedSectorMap(h);
|
auto sm = ai->getCachedSectorMap(h);
|
||||||
std::vector<const CGObjectInstance *> ourObjs(objs); //copy common objects
|
std::vector<const CGObjectInstance *> ourObjs(objs); //copy common objects
|
||||||
|
|
||||||
for (auto obj : ai->reservedHeroesMap[h]) //add objects reserved by this hero
|
for(auto obj : ai->reservedHeroesMap[h]) //add objects reserved by this hero
|
||||||
{
|
{
|
||||||
if (conquerable(obj))
|
if(conquerable(obj))
|
||||||
ourObjs.push_back(obj);
|
ourObjs.push_back(obj);
|
||||||
}
|
}
|
||||||
for (auto obj : ourObjs)
|
for(auto obj : ourObjs)
|
||||||
{
|
{
|
||||||
int3 dest = obj->visitablePos();
|
int3 dest = obj->visitablePos();
|
||||||
auto t = sm->firstTileToGet(h, dest); //we assume that no more than one tile on the way is guarded
|
auto t = sm->firstTileToGet(h, dest); //we assume that no more than one tile on the way is guarded
|
||||||
if (t.valid()) //we know any path at all
|
if(t.valid()) //we know any path at all
|
||||||
{
|
{
|
||||||
if (ai->isTileNotReserved(h, t)) //no other hero wants to conquer that tile
|
if(ai->isTileNotReserved(h, t)) //no other hero wants to conquer that tile
|
||||||
{
|
{
|
||||||
if (isSafeToVisit(h, dest))
|
if(isSafeToVisit(h, dest))
|
||||||
{
|
{
|
||||||
if (dest != t) //there is something blocking our way
|
if(dest != t) //there is something blocking our way
|
||||||
ret.push_back(sptr(Goals::ClearWayTo(dest, h).setisAbstract(true)));
|
ret.push_back(sptr(Goals::ClearWayTo(dest, h).setisAbstract(true)));
|
||||||
else
|
else
|
||||||
{
|
{
|
||||||
if (obj->ID.num == Obj::HERO) //enemy hero may move to other position
|
if(obj->ID.num == Obj::HERO) //enemy hero may move to other position
|
||||||
ret.push_back(sptr(Goals::VisitHero(obj->id.getNum()).sethero(h).setisAbstract(true)));
|
ret.push_back(sptr(Goals::VisitHero(obj->id.getNum()).sethero(h).setisAbstract(true)));
|
||||||
else //just visit that tile
|
else //just visit that tile
|
||||||
ret.push_back(sptr(Goals::VisitTile(dest).sethero(h).setisAbstract(true)));
|
if(obj->ID.num == Obj::TOWN)
|
||||||
|
//if target is town, fuzzy system will use additional "estimatedReward" variable to increase priority a bit
|
||||||
|
ret.push_back(sptr(Goals::VisitTile(dest).sethero(h).setobjid(obj->ID.num).setisAbstract(true))); //TODO: change to getObj eventually and and move appropiate logic there
|
||||||
|
else
|
||||||
|
ret.push_back(sptr(Goals::VisitTile(dest).sethero(h).setisAbstract(true)));
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
else //we need to get army in order to conquer that place
|
else //we need to get army in order to conquer that place
|
||||||
@ -1124,13 +1130,13 @@ TGoalVec GatherArmy::getAllPossibleSubgoals()
|
|||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
if (ai->canRecruitAnyHero()) //this is not stupid in early phase of game
|
if(ai->canRecruitAnyHero() && ai->freeResources()[Res::GOLD] > GameConstants::HERO_GOLD_COST) //this is not stupid in early phase of game
|
||||||
{
|
{
|
||||||
if (auto t = ai->findTownWithTavern())
|
if(auto t = ai->findTownWithTavern())
|
||||||
{
|
{
|
||||||
for (auto h : cb->getAvailableHeroes(t)) //we assume that all towns have same set of heroes
|
for (auto h : cb->getAvailableHeroes(t)) //we assume that all towns have same set of heroes
|
||||||
{
|
{
|
||||||
if (h && h->getTotalStrength() > 500) //do not buy heroes with single creatures for GatherArmy
|
if(h && h->getTotalStrength() > 500) //do not buy heroes with single creatures for GatherArmy
|
||||||
{
|
{
|
||||||
ret.push_back(sptr(Goals::RecruitHero()));
|
ret.push_back(sptr(Goals::RecruitHero()));
|
||||||
break;
|
break;
|
||||||
|
@ -1352,6 +1352,7 @@ bool VCAI::tryBuildNextStructure(const CGTownInstance * t, std::vector<BuildingI
|
|||||||
//Set of buildings for different goals. Does not include any prerequisites.
|
//Set of buildings for different goals. Does not include any prerequisites.
|
||||||
static const BuildingID essential[] = {BuildingID::TAVERN, BuildingID::TOWN_HALL};
|
static const BuildingID essential[] = {BuildingID::TAVERN, BuildingID::TOWN_HALL};
|
||||||
static const BuildingID goldSource[] = {BuildingID::TOWN_HALL, BuildingID::CITY_HALL, BuildingID::CAPITOL};
|
static const BuildingID goldSource[] = {BuildingID::TOWN_HALL, BuildingID::CITY_HALL, BuildingID::CAPITOL};
|
||||||
|
static const BuildingID capitolRequirements[] = { BuildingID::FORT, BuildingID::CITADEL };
|
||||||
static const BuildingID unitsSource[] = { BuildingID::DWELL_LVL_1, BuildingID::DWELL_LVL_2, BuildingID::DWELL_LVL_3,
|
static const BuildingID unitsSource[] = { BuildingID::DWELL_LVL_1, BuildingID::DWELL_LVL_2, BuildingID::DWELL_LVL_3,
|
||||||
BuildingID::DWELL_LVL_4, BuildingID::DWELL_LVL_5, BuildingID::DWELL_LVL_6, BuildingID::DWELL_LVL_7};
|
BuildingID::DWELL_LVL_4, BuildingID::DWELL_LVL_5, BuildingID::DWELL_LVL_6, BuildingID::DWELL_LVL_7};
|
||||||
static const BuildingID unitsUpgrade[] = { BuildingID::DWELL_LVL_1_UP, BuildingID::DWELL_LVL_2_UP, BuildingID::DWELL_LVL_3_UP,
|
static const BuildingID unitsUpgrade[] = { BuildingID::DWELL_LVL_1_UP, BuildingID::DWELL_LVL_2_UP, BuildingID::DWELL_LVL_3_UP,
|
||||||
@ -1370,55 +1371,64 @@ void VCAI::buildStructure(const CGTownInstance * t)
|
|||||||
//TODO: build resource silo, defences when needed
|
//TODO: build resource silo, defences when needed
|
||||||
//Possible - allow "locking" on specific building (build prerequisites and then building itself)
|
//Possible - allow "locking" on specific building (build prerequisites and then building itself)
|
||||||
|
|
||||||
|
//below algorithm focuses on economy growth at start of the game.
|
||||||
TResources currentRes = cb->getResourceAmount();
|
TResources currentRes = cb->getResourceAmount();
|
||||||
TResources currentIncome = t->dailyIncome();
|
TResources currentIncome = t->dailyIncome();
|
||||||
int townIncome = currentIncome[Res::GOLD];
|
int townIncome = currentIncome[Res::GOLD];
|
||||||
|
|
||||||
if (tryBuildAnyStructure(t, std::vector<BuildingID>(essential, essential + ARRAY_COUNT(essential))))
|
if(tryBuildAnyStructure(t, std::vector<BuildingID>(essential, essential + ARRAY_COUNT(essential))))
|
||||||
return;
|
return;
|
||||||
|
|
||||||
//we're running out of gold - try to build something gold-producing. Multiplier can be tweaked, 6 is minimum due to buildings costs
|
//the more gold the better and less problems later
|
||||||
if (currentRes[Res::GOLD] < townIncome * 6)
|
if(tryBuildNextStructure(t, std::vector<BuildingID>(goldSource, goldSource + ARRAY_COUNT(goldSource))))
|
||||||
if (tryBuildNextStructure(t, std::vector<BuildingID>(goldSource, goldSource + ARRAY_COUNT(goldSource))))
|
return;
|
||||||
|
|
||||||
|
//workaround for mantis #2696 - build fort and citadel - building castle will be handled without bug
|
||||||
|
if(vstd::contains(t->builtBuildings, BuildingID::CITY_HALL) && cb->canBuildStructure(t, BuildingID::CAPITOL) != EBuildingState::HAVE_CAPITAL &&
|
||||||
|
cb->canBuildStructure(t, BuildingID::CAPITOL) != EBuildingState::FORBIDDEN)
|
||||||
|
if(tryBuildNextStructure(t, std::vector<BuildingID>(capitolRequirements, capitolRequirements + ARRAY_COUNT(capitolRequirements))))
|
||||||
return;
|
return;
|
||||||
|
|
||||||
if (cb->getDate(Date::DAY_OF_WEEK) > 6)// last 2 days of week - try to focus on growth
|
if((!vstd::contains(t->builtBuildings, BuildingID::CAPITOL) && cb->canBuildStructure(t, BuildingID::CAPITOL) != EBuildingState::HAVE_CAPITAL && cb->canBuildStructure(t, BuildingID::CAPITOL) != EBuildingState::FORBIDDEN)
|
||||||
|
|| (!vstd::contains(t->builtBuildings, BuildingID::CITY_HALL) && cb->canBuildStructure(t, BuildingID::CAPITOL) == EBuildingState::HAVE_CAPITAL && cb->canBuildStructure(t, BuildingID::CITY_HALL) != EBuildingState::FORBIDDEN)
|
||||||
|
|| (!vstd::contains(t->builtBuildings, BuildingID::TOWN_HALL) && cb->canBuildStructure(t, BuildingID::TOWN_HALL) != EBuildingState::FORBIDDEN))
|
||||||
|
return; //save money for capitol or city hall if capitol unavailable, do not build other things (unless gold source buildings are disabled in map editor)
|
||||||
|
|
||||||
|
if(cb->getDate(Date::DAY_OF_WEEK) > 6)// last 2 days of week - try to focus on growth
|
||||||
{
|
{
|
||||||
if (tryBuildNextStructure(t, std::vector<BuildingID>(unitGrowth, unitGrowth + ARRAY_COUNT(unitGrowth)), 2))
|
if(tryBuildNextStructure(t, std::vector<BuildingID>(unitGrowth, unitGrowth + ARRAY_COUNT(unitGrowth)), 2))
|
||||||
return;
|
return;
|
||||||
}
|
}
|
||||||
|
|
||||||
// first in-game week or second half of any week: try build dwellings
|
// first in-game week or second half of any week: try build dwellings
|
||||||
if (cb->getDate(Date::DAY) < 7 || cb->getDate(Date::DAY_OF_WEEK) > 3)
|
if(cb->getDate(Date::DAY) < 7 || cb->getDate(Date::DAY_OF_WEEK) > 3)
|
||||||
if (tryBuildAnyStructure(t, std::vector<BuildingID>(unitsSource, unitsSource + ARRAY_COUNT(unitsSource)), 8 - cb->getDate(Date::DAY_OF_WEEK)))
|
if(tryBuildAnyStructure(t, std::vector<BuildingID>(unitsSource, unitsSource + ARRAY_COUNT(unitsSource)), 8 - cb->getDate(Date::DAY_OF_WEEK)))
|
||||||
return;
|
return;
|
||||||
|
|
||||||
//try to upgrade dwelling
|
//try to upgrade dwelling
|
||||||
for(int i = 0; i < ARRAY_COUNT(unitsUpgrade); i++)
|
for(int i = 0; i < ARRAY_COUNT(unitsUpgrade); i++)
|
||||||
{
|
{
|
||||||
if (t->hasBuilt(unitsSource[i]) && !t->hasBuilt(unitsUpgrade[i]))
|
if(t->hasBuilt(unitsSource[i]) && !t->hasBuilt(unitsUpgrade[i]))
|
||||||
{
|
{
|
||||||
if (tryBuildStructure(t, unitsUpgrade[i]))
|
if(tryBuildStructure(t, unitsUpgrade[i]))
|
||||||
return;
|
return;
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
//remaining tasks
|
//remaining tasks
|
||||||
if (tryBuildNextStructure(t, std::vector<BuildingID>(goldSource, goldSource + ARRAY_COUNT(goldSource))))
|
if(tryBuildNextStructure(t, std::vector<BuildingID>(spells, spells + ARRAY_COUNT(spells))))
|
||||||
return;
|
return;
|
||||||
if (tryBuildNextStructure(t, std::vector<BuildingID>(spells, spells + ARRAY_COUNT(spells))))
|
if(tryBuildAnyStructure(t, std::vector<BuildingID>(extra, extra + ARRAY_COUNT(extra))))
|
||||||
return;
|
|
||||||
if (tryBuildAnyStructure(t, std::vector<BuildingID>(extra, extra + ARRAY_COUNT(extra))))
|
|
||||||
return;
|
return;
|
||||||
|
|
||||||
//at the end, try to get and build any extra buildings with nonstandard slots (for example HotA 3rd level dwelling)
|
//at the end, try to get and build any extra buildings with nonstandard slots (for example HotA 3rd level dwelling)
|
||||||
std::vector<BuildingID> extraBuildings;
|
std::vector<BuildingID> extraBuildings;
|
||||||
|
|
||||||
for (auto buildingInfo : t->town->buildings)
|
for(auto buildingInfo : t->town->buildings)
|
||||||
if (buildingInfo.first > 43)
|
if(buildingInfo.first > 43)
|
||||||
extraBuildings.push_back(buildingInfo.first);
|
extraBuildings.push_back(buildingInfo.first);
|
||||||
|
|
||||||
if (tryBuildAnyStructure(t, extraBuildings))
|
if(tryBuildAnyStructure(t, extraBuildings))
|
||||||
return;
|
return;
|
||||||
}
|
}
|
||||||
|
|
||||||
@ -2865,7 +2875,13 @@ void VCAI::validateObject(ObjectIdRef obj)
|
|||||||
TResources VCAI::freeResources() const
|
TResources VCAI::freeResources() const
|
||||||
{
|
{
|
||||||
TResources myRes = cb->getResourceAmount();
|
TResources myRes = cb->getResourceAmount();
|
||||||
myRes[Res::GOLD] -= GOLD_RESERVE;
|
auto iterator = cb->getTownsInfo();
|
||||||
|
if(std::none_of(iterator.begin(), iterator.end(), [](const CGTownInstance * x)->bool
|
||||||
|
{
|
||||||
|
return x->builtBuildings.find(BuildingID::CAPITOL) != x->builtBuildings.end();
|
||||||
|
})
|
||||||
|
/*|| std::all_of(iterator.begin(), iterator.end(), [](const CGTownInstance * x) -> bool { return x->forbiddenBuildings.find(BuildingID::CAPITOL) != x->forbiddenBuildings.end(); })*/ )
|
||||||
|
myRes[Res::GOLD] -= GOLD_RESERVE; //what if capitol is blocked from building in all possessed towns (set in map editor)? What about reserve for city hall or something similar in that case?
|
||||||
vstd::amax(myRes[Res::GOLD], 0);
|
vstd::amax(myRes[Res::GOLD], 0);
|
||||||
return myRes;
|
return myRes;
|
||||||
}
|
}
|
||||||
|
@ -866,6 +866,11 @@ void CGHeroInstance::setPropertyDer( ui8 what, ui32 val )
|
|||||||
setStackCount(SlotID(0), val);
|
setStackCount(SlotID(0), val);
|
||||||
}
|
}
|
||||||
|
|
||||||
|
TFaction CGHeroInstance::getFaction() const
|
||||||
|
{
|
||||||
|
return type->heroClass->faction;
|
||||||
|
}
|
||||||
|
|
||||||
double CGHeroInstance::getFightingStrength() const
|
double CGHeroInstance::getFightingStrength() const
|
||||||
{
|
{
|
||||||
return sqrt((1.0 + 0.05*getPrimSkillLevel(PrimarySkill::ATTACK)) * (1.0 + 0.05*getPrimSkillLevel(PrimarySkill::DEFENSE)));
|
return sqrt((1.0 + 0.05*getPrimSkillLevel(PrimarySkill::ATTACK)) * (1.0 + 0.05*getPrimSkillLevel(PrimarySkill::DEFENSE)));
|
||||||
|
@ -147,6 +147,7 @@ public:
|
|||||||
EAlignment::EAlignment getAlignment() const;
|
EAlignment::EAlignment getAlignment() const;
|
||||||
const std::string &getBiography() const;
|
const std::string &getBiography() const;
|
||||||
bool needsLastStack()const override;
|
bool needsLastStack()const override;
|
||||||
|
TFaction getFaction() const;
|
||||||
ui32 getTileCost(const TerrainTile &dest, const TerrainTile &from, const TurnInfo * ti) const; //move cost - applying pathfinding skill, road and terrain modifiers. NOT includes diagonal move penalty, last move levelling
|
ui32 getTileCost(const TerrainTile &dest, const TerrainTile &from, const TurnInfo * ti) const; //move cost - applying pathfinding skill, road and terrain modifiers. NOT includes diagonal move penalty, last move levelling
|
||||||
int getNativeTerrain() const;
|
int getNativeTerrain() const;
|
||||||
ui32 getLowestCreatureSpeed() const;
|
ui32 getLowestCreatureSpeed() const;
|
||||||
|
Loading…
Reference in New Issue
Block a user