1
0
mirror of https://github.com/vcmi/vcmi.git synced 2025-06-29 00:41:38 +02:00

Some preparation towards mantis #1743:

- refactored CRandomGenerator (added util methods, improved method names)
- usages of std::minstd_ran are replaced by CRandomGenerator (not in entire code base, C rand() usages are still not replaced)
- refactored getArtSync method of CArtHandler -> now named pickRandomArtifact
- fixed some compiler warnings
- updated source code URL in VCMI spec
This commit is contained in:
beegee1
2014-03-17 19:51:07 +00:00
parent 1aff899f5b
commit fe1b16a7ec
22 changed files with 6774 additions and 6695 deletions

View File

@ -28,7 +28,6 @@
#include "CStopWatch.h"
#include "mapping/CMapEditManager.h"
DLL_LINKAGE std::minstd_rand ran;
class CGObjectInstance;
#ifdef min
@ -363,7 +362,8 @@ static CGObjectInstance * createObject(Obj id, int subid, int3 pos, PlayerColor
return nobj;
}
CGHeroInstance * CGameState::HeroesPool::pickHeroFor(bool native, PlayerColor player, const CTown *town, std::map<ui32, ConstTransitivePtr<CGHeroInstance> > &available, const CHeroClass *bannedClass /*= nullptr*/) const
CGHeroInstance * CGameState::HeroesPool::pickHeroFor(bool native, PlayerColor player, const CTown *town,
std::map<ui32, ConstTransitivePtr<CGHeroInstance> > &available, CRandomGenerator & rand, const CHeroClass * bannedClass /*= nullptr*/) const
{
CGHeroInstance *ret = nullptr;
@ -388,11 +388,11 @@ CGHeroInstance * CGameState::HeroesPool::pickHeroFor(bool native, PlayerColor pl
if(!pool.size())
{
logGlobal->errorStream() << "Cannot pick native hero for " << player << ". Picking any...";
return pickHeroFor(false, player, town, available);
return pickHeroFor(false, player, town, available, rand);
}
else
{
ret = pool[rand()%pool.size()];
ret = *RandomGeneratorUtil::nextItem(pool, rand);
}
}
else
@ -414,7 +414,7 @@ CGHeroInstance * CGameState::HeroesPool::pickHeroFor(bool native, PlayerColor pl
return nullptr;
}
r = rand()%sum;
r = rand.nextInt(sum - 1);
for (auto & elem : pool)
{
r -= elem->type->heroClass->selectionProbability[town->faction->index];
@ -449,7 +449,7 @@ CGameState::CampaignHeroReplacement::CampaignHeroReplacement(CGHeroInstance * he
}
int CGameState::pickNextHeroType(PlayerColor owner) const
int CGameState::pickNextHeroType(PlayerColor owner)
{
const PlayerSettings &ps = scenarioOps->getIthPlayersSettings(owner);
if(ps.hero >= 0 && !isUsedHero(HeroTypeID(ps.hero))) //we haven't used selected hero
@ -460,7 +460,7 @@ int CGameState::pickNextHeroType(PlayerColor owner) const
return pickUnusedHeroTypeRandomly(owner);
}
int CGameState::pickUnusedHeroTypeRandomly(PlayerColor owner) const
int CGameState::pickUnusedHeroTypeRandomly(PlayerColor owner)
{
//list of available heroes for this faction and others
std::vector<HeroTypeID> factionHeroes, otherHeroes;
@ -475,12 +475,16 @@ int CGameState::pickUnusedHeroTypeRandomly(PlayerColor owner) const
}
// select random hero native to "our" faction
if (!factionHeroes.empty())
return factionHeroes.at(ran() % factionHeroes.size()).getNum();
if(!factionHeroes.empty())
{
return RandomGeneratorUtil::nextItem(factionHeroes, rand)->getNum();
}
logGlobal->warnStream() << "Cannot find free hero of appropriate faction for player " << owner << " - trying to get first available...";
if(!otherHeroes.empty())
return otherHeroes.at(ran() % otherHeroes.size()).getNum();
{
return RandomGeneratorUtil::nextItem(otherHeroes, rand)->getNum();
}
logGlobal->errorStream() << "No free allowed heroes!";
auto notAllowedHeroesButStillBetterThanCrash = getUnusedAllowedHeroes(true);
@ -497,29 +501,29 @@ std::pair<Obj,int> CGameState::pickObject (CGObjectInstance *obj)
switch(obj->ID)
{
case Obj::RANDOM_ART:
return std::make_pair(Obj::ARTIFACT, VLC->arth->getRandomArt (CArtifact::ART_TREASURE | CArtifact::ART_MINOR | CArtifact::ART_MAJOR | CArtifact::ART_RELIC));
return std::make_pair(Obj::ARTIFACT, VLC->arth->pickRandomArtifact(rand, CArtifact::ART_TREASURE | CArtifact::ART_MINOR | CArtifact::ART_MAJOR | CArtifact::ART_RELIC));
case Obj::RANDOM_TREASURE_ART:
return std::make_pair(Obj::ARTIFACT, VLC->arth->getRandomArt (CArtifact::ART_TREASURE));
return std::make_pair(Obj::ARTIFACT, VLC->arth->pickRandomArtifact(rand, CArtifact::ART_TREASURE));
case Obj::RANDOM_MINOR_ART:
return std::make_pair(Obj::ARTIFACT, VLC->arth->getRandomArt (CArtifact::ART_MINOR));
return std::make_pair(Obj::ARTIFACT, VLC->arth->pickRandomArtifact(rand, CArtifact::ART_MINOR));
case Obj::RANDOM_MAJOR_ART:
return std::make_pair(Obj::ARTIFACT, VLC->arth->getRandomArt (CArtifact::ART_MAJOR));
return std::make_pair(Obj::ARTIFACT, VLC->arth->pickRandomArtifact(rand, CArtifact::ART_MAJOR));
case Obj::RANDOM_RELIC_ART:
return std::make_pair(Obj::ARTIFACT, VLC->arth->getRandomArt (CArtifact::ART_RELIC));
return std::make_pair(Obj::ARTIFACT, VLC->arth->pickRandomArtifact(rand, CArtifact::ART_RELIC));
case Obj::RANDOM_HERO:
return std::make_pair(Obj::HERO, pickNextHeroType(obj->tempOwner));
case Obj::RANDOM_MONSTER:
return std::make_pair(Obj::MONSTER, VLC->creh->pickRandomMonster(std::ref(ran)));
return std::make_pair(Obj::MONSTER, VLC->creh->pickRandomMonster(rand));
case Obj::RANDOM_MONSTER_L1:
return std::make_pair(Obj::MONSTER, VLC->creh->pickRandomMonster(std::ref(ran), 1));
return std::make_pair(Obj::MONSTER, VLC->creh->pickRandomMonster(rand, 1));
case Obj::RANDOM_MONSTER_L2:
return std::make_pair(Obj::MONSTER, VLC->creh->pickRandomMonster(std::ref(ran), 2));
return std::make_pair(Obj::MONSTER, VLC->creh->pickRandomMonster(rand, 2));
case Obj::RANDOM_MONSTER_L3:
return std::make_pair(Obj::MONSTER, VLC->creh->pickRandomMonster(std::ref(ran), 3));
return std::make_pair(Obj::MONSTER, VLC->creh->pickRandomMonster(rand, 3));
case Obj::RANDOM_MONSTER_L4:
return std::make_pair(Obj::MONSTER, VLC->creh->pickRandomMonster(std::ref(ran), 4));
return std::make_pair(Obj::MONSTER, VLC->creh->pickRandomMonster(rand, 4));
case Obj::RANDOM_RESOURCE:
return std::make_pair(Obj::RESOURCE,ran()%7); //now it's OH3 style, use %8 for mithril
return std::make_pair(Obj::RESOURCE,rand.nextInt(6)); //now it's OH3 style, use %8 for mithril
case Obj::RANDOM_TOWN:
{
PlayerColor align = PlayerColor((static_cast<CGTownInstance*>(obj))->alignment);
@ -539,18 +543,18 @@ std::pair<Obj,int> CGameState::pickObject (CGObjectInstance *obj)
{
do
{
f = ran()%VLC->townh->factions.size();
f = rand.nextInt(VLC->townh->factions.size() - 1);
}
while (VLC->townh->factions[f]->town == nullptr); // find playable faction
}
return std::make_pair(Obj::TOWN,f);
}
case Obj::RANDOM_MONSTER_L5:
return std::make_pair(Obj::MONSTER, VLC->creh->pickRandomMonster(std::ref(ran), 5));
return std::make_pair(Obj::MONSTER, VLC->creh->pickRandomMonster(rand, 5));
case Obj::RANDOM_MONSTER_L6:
return std::make_pair(Obj::MONSTER, VLC->creh->pickRandomMonster(std::ref(ran), 6));
return std::make_pair(Obj::MONSTER, VLC->creh->pickRandomMonster(rand, 6));
case Obj::RANDOM_MONSTER_L7:
return std::make_pair(Obj::MONSTER, VLC->creh->pickRandomMonster(std::ref(ran), 7));
return std::make_pair(Obj::MONSTER, VLC->creh->pickRandomMonster(rand, 7));
case Obj::RANDOM_DWELLING:
case Obj::RANDOM_DWELLING_LVL:
case Obj::RANDOM_DWELLING_FACTION:
@ -561,7 +565,7 @@ std::pair<Obj,int> CGameState::pickObject (CGObjectInstance *obj)
//if castle alignment available
if (auto info = dynamic_cast<CCreGenAsCastleInfo*>(dwl->info))
{
faction = ran() % VLC->townh->factions.size();
faction = rand.nextInt(VLC->townh->factions.size() - 1);
if (info->asCastle)
{
for(auto & elem : map->objects)
@ -586,11 +590,11 @@ std::pair<Obj,int> CGameState::pickObject (CGObjectInstance *obj)
}
else
{
while((!(info->castles[0]&(1<<faction))))
while(!(info->castles[0]&(1<<faction)))
{
if((faction>7) && (info->castles[1]&(1<<(faction-8))))
break;
faction = ran()%GameConstants::F_NUMBER;
faction = rand.nextInt(GameConstants::F_NUMBER - 1);
}
}
}
@ -601,9 +605,13 @@ std::pair<Obj,int> CGameState::pickObject (CGObjectInstance *obj)
//if level set to range
if (auto info = dynamic_cast<CCreGenLeveledInfo*>(dwl->info))
level = ((info->maxLevel-info->minLevel) ? (ran()%(info->maxLevel-info->minLevel)+info->minLevel) : (info->minLevel));
{
level = rand.nextInt(info->minLevel, info->maxLevel);
}
else // fixed level
{
level = obj->subID;
}
delete dwl->info;
dwl->info = nullptr;
@ -627,9 +635,7 @@ std::pair<Obj,int> CGameState::pickObject (CGObjectInstance *obj)
if (result.first == Obj::NO_OBJ)
{
logGlobal->errorStream() << "Error: failed to find creature for dwelling of "<< int(faction) << " of level " << int(level);
auto iter = VLC->objh->cregens.begin();
std::advance(iter, ran() % VLC->objh->cregens.size() );
result = std::make_pair(Obj::CREATURE_GENERATOR1, iter->first);
result = std::make_pair(Obj::CREATURE_GENERATOR1, RandomGeneratorUtil::nextItem(VLC->objh->cregens, rand)->first);
}
return result;
@ -763,7 +769,7 @@ BattleInfo * CGameState::setupBattle(int3 tile, const CArmedInstance *armies[2],
void CGameState::init(StartInfo * si)
{
logGlobal->infoStream() << "\tUsing random seed: "<< si->seedToBeUsed;
ran.seed((boost::int32_t)si->seedToBeUsed);
rand.setSeed(si->seedToBeUsed);
scenarioOps = CMemorySerializer::deepCopy(*si).release();
initialOpts = CMemorySerializer::deepCopy(*si).release();
si = nullptr;
@ -810,7 +816,7 @@ void CGameState::init(StartInfo * si)
logGlobal->debugStream() << "\tChecking objectives";
map->checkForObjectives(); //needs to be run when all objects are properly placed
int seedAfterInit = ran();
auto seedAfterInit = rand.nextInt();
logGlobal->infoStream() << "Seed after init is " << seedAfterInit << " (before was " << scenarioOps->seedToBeUsed << ")";
if(scenarioOps->seedPostInit > 0)
{
@ -1034,10 +1040,14 @@ void CGameState::initGrailPosition()
if(elem && elem->ID == Obj::HOLE)
allowedPos -= elem->pos;
if(allowedPos.size())
map->grailPos = allowedPos[ran() % allowedPos.size()];
if(!allowedPos.empty())
{
map->grailPos = *RandomGeneratorUtil::nextItem(allowedPos, rand);
}
else
{
logGlobal->warnStream() << "Warning: Grail cannot be placed, no appropriate tile found!";
}
}
}
@ -1048,7 +1058,7 @@ void CGameState::initRandomFactionsForPlayers()
{
if(elem.second.castle==-1)
{
int randomID = ran() % map->players[elem.first.getNum()].allowedFactions.size();
auto randomID = rand.nextInt(map->players[elem.first.getNum()].allowedFactions.size() - 1);
auto iter = map->players[elem.first.getNum()].allowedFactions.begin();
std::advance(iter, randomID);
@ -1177,7 +1187,7 @@ void CGameState::placeCampaignHeroes()
auto unusedHeroTypeIds = getUnusedAllowedHeroes();
if(!unusedHeroTypeIds.empty())
{
heroTypeId = std::next(unusedHeroTypeIds.begin(), ran() % unusedHeroTypeIds.size())->getNum();
heroTypeId = (*RandomGeneratorUtil::nextItem(unusedHeroTypeIds, rand)).getNum();
}
else
{
@ -1680,23 +1690,23 @@ void CGameState::initStartingBonus()
{
//starting bonus
if(scenarioOps->playerInfos[elem.first].bonus==PlayerSettings::RANDOM)
scenarioOps->playerInfos[elem.first].bonus = static_cast<PlayerSettings::Ebonus>(ran()%3);
scenarioOps->playerInfos[elem.first].bonus = static_cast<PlayerSettings::Ebonus>(rand.nextInt(2));
switch(scenarioOps->playerInfos[elem.first].bonus)
{
case PlayerSettings::GOLD:
elem.second.resources[Res::GOLD] += 500 + (ran()%6)*100;
elem.second.resources[Res::GOLD] += rand.nextInt(500, 1000);
break;
case PlayerSettings::RESOURCE:
{
int res = VLC->townh->factions[scenarioOps->playerInfos[elem.first].castle]->town->primaryRes;
if(res == Res::WOOD_AND_ORE)
{
elem.second.resources[Res::WOOD] += 5 + ran()%6;
elem.second.resources[Res::ORE] += 5 + ran()%6;
elem.second.resources[Res::WOOD] += rand.nextInt(5, 10);
elem.second.resources[Res::ORE] += rand.nextInt(5, 10);
}
else
{
elem.second.resources[res] += 3 + ran()%4;
elem.second.resources[res] += rand.nextInt(3, 6);
}
break;
}
@ -1708,7 +1718,7 @@ void CGameState::initStartingBonus()
break;
}
CArtifact *toGive;
toGive = VLC->arth->artifacts[VLC->arth->getRandomArt (CArtifact::ART_TREASURE)];
toGive = VLC->arth->artifacts[VLC->arth->pickRandomArtifact(rand, CArtifact::ART_TREASURE)];
CGHeroInstance *hero = elem.second.heroes[0];
giveHeroArtifact(hero, toGive->id);
@ -1756,9 +1766,13 @@ void CGameState::initTowns()
{
CGTownInstance * vti =(elem);
if(!vti->town)
{
vti->town = VLC->townh->factions[vti->subID]->town;
if (vti->name.length()==0) // if town hasn't name we draw it
vti->name = vti->town->names[ran()%vti->town->names.size()];
}
if(vti->name.empty())
{
vti->name = *RandomGeneratorUtil::nextItem(vti->town->names, rand);
}
//init buildings
if(vstd::contains(vti->builtBuildings, BuildingID::DEFAULT)) //give standard set of buildings
@ -1767,8 +1781,10 @@ void CGameState::initTowns()
vti->builtBuildings.insert(BuildingID::VILLAGE_HALL);
vti->builtBuildings.insert(BuildingID::TAVERN);
vti->builtBuildings.insert(BuildingID::DWELL_FIRST);
if(ran()%2)
if(rand.nextInt(1) == 1)
{
vti->builtBuildings.insert(BuildingID::DWELL_LVL_2);
}
}
//#1444 - remove entries that don't have buildings defined (like some unused extra town hall buildings)
@ -1817,7 +1833,7 @@ void CGameState::initTowns()
ev.buildings.insert(BuildingID::HORDE_2);
}
}
//init spells
//init spells
logGlobal->debugStream() << "\t\tTown init spells";
vti->spells.resize(GameConstants::SPELL_LEVELS);
@ -1826,7 +1842,7 @@ void CGameState::initTowns()
CSpell *s = vti->obligatorySpells[z].toSpell();
vti->spells[s->level-1].push_back(s->id);
vti->possibleSpells -= s->id;
}
}
logGlobal->debugStream() << "\t\tTown init spells2";
while(vti->possibleSpells.size())
{
@ -1839,7 +1855,7 @@ void CGameState::initTowns()
if (total == 0) // remaining spells have 0 probability
break;
int r = ran()%total;
auto r = rand.nextInt(total - 1);
for(ui32 ps=0; ps<vti->possibleSpells.size();ps++)
{
r -= vti->possibleSpells[ps].toSpell()->getProbability(vti->subID);
@ -1858,8 +1874,8 @@ void CGameState::initTowns()
}
vti->possibleSpells.clear();
if(vti->getOwner() != PlayerColor::NEUTRAL)
getPlayer(vti->getOwner())->towns.push_back(vti);
logGlobal->debugStream() << "\t\tTown init spells3";
getPlayer(vti->getOwner())->towns.push_back(vti);
logGlobal->debugStream() << "\t\tTown init spells3";
}
}
@ -1921,7 +1937,7 @@ void CGameState::initVisitingAndGarrisonedHeroes()
}
}
BFieldType CGameState::battleGetBattlefieldType(int3 tile) const
BFieldType CGameState::battleGetBattlefieldType(int3 tile)
{
if(tile==int3() && curB)
tile = curB->tile;
@ -1971,13 +1987,13 @@ BFieldType CGameState::battleGetBattlefieldType(int3 tile) const
switch(t.terType)
{
case ETerrainType::DIRT:
return BFieldType(rand()%3+3);
return BFieldType(rand.nextInt(3, 5));
case ETerrainType::SAND:
return BFieldType::SAND_MESAS; //TODO: coast support
case ETerrainType::GRASS:
return BFieldType(rand()%2+6);
return BFieldType(rand.nextInt(6, 7));
case ETerrainType::SNOW:
return BFieldType(rand()%2+10);
return BFieldType(rand.nextInt(10, 11));
case ETerrainType::SWAMP:
return BFieldType::SWAMP_TREES;
case ETerrainType::ROUGH:
@ -3630,3 +3646,8 @@ std::ostream & operator<<(std::ostream & os, const EVictoryLossCheckResult & vic
os << victoryLossCheckResult.messageToSelf;
return os;
}
CRandomGenerator & CGameState::getRandomGenerator()
{
return rand;
}