mirror of
https://github.com/vcmi/vcmi.git
synced 2024-12-24 22:14:36 +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:
parent
1aff899f5b
commit
fe1b16a7ec
@ -1873,8 +1873,6 @@ std::vector<HeroPtr> VCAI::getUnblockedHeroes() const
|
||||
|
||||
bool VCAI::canAct (HeroPtr h) const
|
||||
{
|
||||
bool digsTile = false;
|
||||
|
||||
auto mission = lockedHeroes.find(h);
|
||||
if (mission != lockedHeroes.end())
|
||||
{
|
||||
|
@ -5963,7 +5963,7 @@ void MoraleLuckBox::set(const IBonusBearer *node)
|
||||
else
|
||||
{
|
||||
//it's a creature window
|
||||
if (morale && node->hasBonusOfType (Bonus::UNDEAD) ||
|
||||
if ((morale && node->hasBonusOfType(Bonus::UNDEAD)) ||
|
||||
node->hasBonusOfType(Bonus::BLOCK_MORALE) || node->hasBonusOfType(Bonus::NON_LIVING))
|
||||
{
|
||||
text += CGI->generaltexth->arraytxt[113]; //unaffected by morale
|
||||
|
@ -1,4 +1,14 @@
|
||||
#include "StdInc.h"
|
||||
/*
|
||||
* BattleState.cpp, part of VCMI engine
|
||||
*
|
||||
* Authors: listed in file AUTHORS in main folder
|
||||
*
|
||||
* License: GNU General Public License v2.0 or later
|
||||
* Full text of license available in license.txt file, in main folder
|
||||
*
|
||||
*/
|
||||
|
||||
#include "StdInc.h"
|
||||
#include "BattleState.h"
|
||||
|
||||
#include <numeric>
|
||||
@ -11,18 +21,7 @@
|
||||
#include "NetPacks.h"
|
||||
#include "JsonNode.h"
|
||||
#include "filesystem/Filesystem.h"
|
||||
|
||||
|
||||
/*
|
||||
* BattleState.h, part of VCMI engine
|
||||
*
|
||||
* Authors: listed in file AUTHORS in main folder
|
||||
*
|
||||
* License: GNU General Public License v2.0 or later
|
||||
* Full text of license available in license.txt file, in main folder
|
||||
*
|
||||
*/
|
||||
extern std::minstd_rand ran;
|
||||
#include "CRandomGenerator.h"
|
||||
|
||||
const CStack * BattleInfo::getNextStack() const
|
||||
{
|
||||
@ -1133,7 +1132,7 @@ std::pair<int,int> CStack::countKilledByAttack(int damageReceived) const
|
||||
return std::make_pair(killedCount, newRemainingHP);
|
||||
}
|
||||
|
||||
void CStack::prepareAttacked(BattleStackAttacked &bsa, boost::optional<int> customCount /*= boost::none*/) const
|
||||
void CStack::prepareAttacked(BattleStackAttacked &bsa, CRandomGenerator & rand, boost::optional<int> customCount /*= boost::none*/) const
|
||||
{
|
||||
auto afterAttack = countKilledByAttack(bsa.damageAmount);
|
||||
|
||||
@ -1158,17 +1157,25 @@ void CStack::prepareAttacked(BattleStackAttacked &bsa, boost::optional<int> cust
|
||||
int resurrectFactor = valOfBonuses(Bonus::REBIRTH);
|
||||
if(resurrectFactor > 0 && casts) //there must be casts left
|
||||
{
|
||||
int resurrectedCount = base->count * resurrectFactor / 100;
|
||||
if (resurrectedCount)
|
||||
resurrectedCount += ((base->count * resurrectFactor / 100.0 - resurrectedCount) > ran()%100 / 100.0) ? 1 : 0; //last stack has proportional chance to rebirth
|
||||
else //only one unit
|
||||
resurrectedCount += ((base->count * resurrectFactor / 100.0) > ran()%100 / 100.0) ? 1 : 0;
|
||||
int resurrectedStackCount = base->count * resurrectFactor / 100;
|
||||
|
||||
// last stack has proportional chance to rebirth
|
||||
auto diff = base->count * resurrectFactor / 100.0 - resurrectedStackCount;
|
||||
if (diff > rand.nextDouble(0, 0.99))
|
||||
{
|
||||
resurrectedStackCount += 1;
|
||||
}
|
||||
|
||||
if(hasBonusOfType(Bonus::REBIRTH, 1))
|
||||
vstd::amax (resurrectedCount, 1); //resurrect at least one Sacred Phoenix
|
||||
if (resurrectedCount)
|
||||
{
|
||||
// resurrect at least one Sacred Phoenix
|
||||
vstd::amax(resurrectedStackCount, 1);
|
||||
}
|
||||
|
||||
if(resurrectedStackCount > 0)
|
||||
{
|
||||
bsa.flags |= BattleStackAttacked::REBIRTH;
|
||||
bsa.newAmount = resurrectedCount; //risky?
|
||||
bsa.newAmount = resurrectedStackCount; //risky?
|
||||
bsa.newHP = MaxHealth(); //resore full health
|
||||
}
|
||||
}
|
||||
|
@ -27,7 +27,7 @@ class CArmedInstance;
|
||||
class CGTownInstance;
|
||||
class CStackInstance;
|
||||
struct BattleStackAttacked;
|
||||
|
||||
class CRandomGenerator;
|
||||
|
||||
|
||||
//only for use in BattleInfo
|
||||
@ -222,7 +222,7 @@ public:
|
||||
std::vector<BattleHex> getSurroundingHexes(BattleHex attackerPos = BattleHex::INVALID) const; // get six or 8 surrounding hexes depending on creature size
|
||||
|
||||
std::pair<int,int> countKilledByAttack(int damageReceived) const; //returns pair<killed count, new left HP>
|
||||
void prepareAttacked(BattleStackAttacked &bsa, boost::optional<int> customCount = boost::none) const; //requires bsa.damageAmout filled
|
||||
void prepareAttacked(BattleStackAttacked &bsa, CRandomGenerator & rand, boost::optional<int> customCount = boost::none) const; //requires bsa.damageAmout filled
|
||||
|
||||
template <typename Handler> void serialize(Handler &h, const int version)
|
||||
{
|
||||
|
@ -1,3 +1,13 @@
|
||||
/*
|
||||
* CArtHandler.cpp, part of VCMI engine
|
||||
*
|
||||
* Authors: listed in file AUTHORS in main folder
|
||||
*
|
||||
* License: GNU General Public License v2.0 or later
|
||||
* Full text of license available in license.txt file, in main folder
|
||||
*
|
||||
*/
|
||||
|
||||
#include "StdInc.h"
|
||||
#include "CArtHandler.h"
|
||||
|
||||
@ -9,20 +19,10 @@
|
||||
#include "CObjectHandler.h"
|
||||
#include "NetPacksBase.h"
|
||||
#include "GameConstants.h"
|
||||
#include "CRandomGenerator.h"
|
||||
|
||||
using namespace boost::assign;
|
||||
|
||||
/*
|
||||
* CArtHandler.cpp, part of VCMI engine
|
||||
*
|
||||
* Authors: listed in file AUTHORS in main folder
|
||||
*
|
||||
* License: GNU General Public License v2.0 or later
|
||||
* Full text of license available in license.txt file, in main folder
|
||||
*
|
||||
*/
|
||||
|
||||
extern std::minstd_rand ran;
|
||||
// Note: list must match entries in ArtTraits.txt
|
||||
#define ART_POS_LIST \
|
||||
ART_POS(SPELLBOOK) \
|
||||
@ -422,11 +422,7 @@ CreatureID CArtHandler::machineIDToCreature(ArtifactID id)
|
||||
return CreatureID::NONE; //this artifact is not a creature
|
||||
}
|
||||
|
||||
ArtifactID CArtHandler::getRandomArt(int flags)
|
||||
{
|
||||
return getArtSync(ran(), flags, true);
|
||||
}
|
||||
ArtifactID CArtHandler::getArtSync (ui32 rand, int flags, bool erasePicked)
|
||||
ArtifactID CArtHandler::pickRandomArtifact(CRandomGenerator & rand, int flags)
|
||||
{
|
||||
auto getAllowedArts = [&](std::vector<ConstTransitivePtr<CArtifact> > &out, std::vector<CArtifact*> *arts, CArtifact::EartClass flag)
|
||||
{
|
||||
@ -466,8 +462,7 @@ ArtifactID CArtHandler::getArtSync (ui32 rand, int flags, bool erasePicked)
|
||||
|
||||
std::vector<ConstTransitivePtr<CArtifact> > out;
|
||||
getAllowed(out);
|
||||
ArtifactID artID = out[rand % out.size()]->id;
|
||||
if(erasePicked)
|
||||
ArtifactID artID = (*RandomGeneratorUtil::nextItem(out, rand))->id;
|
||||
erasePickedArt(artID);
|
||||
return artID;
|
||||
}
|
||||
|
@ -24,6 +24,7 @@ class CGHeroInstance;
|
||||
struct ArtifactLocation;
|
||||
class CArtifactSet;
|
||||
class CArtifactInstance;
|
||||
class CRandomGenerator;
|
||||
|
||||
#define ART_BEARER_LIST \
|
||||
ART_BEARER(HERO)\
|
||||
@ -188,18 +189,6 @@ public:
|
||||
|
||||
class DLL_LINKAGE CArtHandler : public IHandlerBase //handles artifacts
|
||||
{
|
||||
CArtifact * loadFromJson(const JsonNode & node);
|
||||
|
||||
void addSlot(CArtifact * art, const std::string & slotID);
|
||||
void loadSlots(CArtifact * art, const JsonNode & node);
|
||||
void loadClass(CArtifact * art, const JsonNode & node);
|
||||
void loadType(CArtifact * art, const JsonNode & node);
|
||||
void loadComponents(CArtifact * art, const JsonNode & node);
|
||||
void loadGrowingArt(CGrowingArtifact * art, const JsonNode & node);
|
||||
|
||||
void giveArtBonus(ArtifactID aid, Bonus::BonusType type, int val, int subtype = -1, Bonus::ValueType valType = Bonus::BASE_NUMBER, shared_ptr<ILimiter> limiter = shared_ptr<ILimiter>(), int additionalinfo = 0);
|
||||
void giveArtBonus(ArtifactID aid, Bonus::BonusType type, int val, int subtype, shared_ptr<IPropagator> propagator, int additionalinfo = 0);
|
||||
void giveArtBonus(ArtifactID aid, Bonus *bonus);
|
||||
public:
|
||||
std::vector<CArtifact*> treasures, minors, majors, relics; //tmp vectors!!! do not touch if you don't know what you are doing!!!
|
||||
|
||||
@ -213,9 +202,9 @@ public:
|
||||
void fillList(std::vector<CArtifact*> &listToBeFilled, CArtifact::EartClass artifactClass); //fills given empty list with allowed artifacts of gibven class. No side effects
|
||||
|
||||
boost::optional<std::vector<CArtifact*>&> listFromClass(CArtifact::EartClass artifactClass);
|
||||
void erasePickedArt(ArtifactID id);
|
||||
ArtifactID getRandomArt (int flags);
|
||||
ArtifactID getArtSync (ui32 rand, int flags, bool erasePicked = false);
|
||||
|
||||
/// Gets a artifact ID randomly and removes the selected artifact from this handler.
|
||||
ArtifactID pickRandomArtifact(CRandomGenerator & rand, int flags);
|
||||
bool legalArtifact(ArtifactID id);
|
||||
void getAllowedArts(std::vector<ConstTransitivePtr<CArtifact> > &out, std::vector<CArtifact*> *arts, int flag);
|
||||
void getAllowed(std::vector<ConstTransitivePtr<CArtifact> > &out, int flags);
|
||||
@ -245,6 +234,22 @@ public:
|
||||
& growingArtifacts;
|
||||
//if(!h.saving) sortArts();
|
||||
}
|
||||
|
||||
private:
|
||||
CArtifact * loadFromJson(const JsonNode & node);
|
||||
|
||||
void addSlot(CArtifact * art, const std::string & slotID);
|
||||
void loadSlots(CArtifact * art, const JsonNode & node);
|
||||
void loadClass(CArtifact * art, const JsonNode & node);
|
||||
void loadType(CArtifact * art, const JsonNode & node);
|
||||
void loadComponents(CArtifact * art, const JsonNode & node);
|
||||
void loadGrowingArt(CGrowingArtifact * art, const JsonNode & node);
|
||||
|
||||
void giveArtBonus(ArtifactID aid, Bonus::BonusType type, int val, int subtype = -1, Bonus::ValueType valType = Bonus::BASE_NUMBER, shared_ptr<ILimiter> limiter = shared_ptr<ILimiter>(), int additionalinfo = 0);
|
||||
void giveArtBonus(ArtifactID aid, Bonus::BonusType type, int val, int subtype, shared_ptr<IPropagator> propagator, int additionalinfo = 0);
|
||||
void giveArtBonus(ArtifactID aid, Bonus *bonus);
|
||||
|
||||
void erasePickedArt(ArtifactID id);
|
||||
};
|
||||
|
||||
struct DLL_LINKAGE ArtSlotInfo
|
||||
|
@ -1052,7 +1052,7 @@ std::pair<ui32, ui32> CBattleInfoCallback::battleEstimateDamage(const BattleAtta
|
||||
{
|
||||
BattleStackAttacked bsa;
|
||||
bsa.damageAmount = ret.*pairElems[i];
|
||||
bai.defender->prepareAttacked(bsa, bai.defenderCount);
|
||||
bai.defender->prepareAttacked(bsa, gs->getRandomGenerator(), bai.defenderCount);
|
||||
|
||||
auto retaliationAttack = bai.reverse();
|
||||
retaliationAttack.attackerCount = bsa.newAmount;
|
||||
|
@ -1054,14 +1054,14 @@ CCreatureHandler::~CCreatureHandler()
|
||||
creature.dellNull();
|
||||
}
|
||||
|
||||
CreatureID CCreatureHandler::pickRandomMonster(const std::function<int()> &randGen, int tier) const
|
||||
CreatureID CCreatureHandler::pickRandomMonster(CRandomGenerator & rand, int tier) const
|
||||
{
|
||||
int r = 0;
|
||||
if(tier == -1) //pick any allowed creature
|
||||
{
|
||||
do
|
||||
{
|
||||
r = vstd::pickRandomElementOf(creatures, randGen)->idNumber;
|
||||
r = (*RandomGeneratorUtil::nextItem(creatures, rand))->idNumber;
|
||||
} while (VLC->creh->creatures[r] && VLC->creh->creatures[r]->special); // find first "not special" creature
|
||||
}
|
||||
else
|
||||
@ -1082,7 +1082,7 @@ CreatureID CCreatureHandler::pickRandomMonster(const std::function<int()> &randG
|
||||
return CreatureID::NONE;
|
||||
}
|
||||
|
||||
return vstd::pickRandomElementOf(allowed, randGen);
|
||||
return *RandomGeneratorUtil::nextItem(allowed, rand);
|
||||
}
|
||||
assert (r >= 0); //should always be, but it crashed
|
||||
return CreatureID(r);
|
||||
|
@ -7,6 +7,7 @@
|
||||
#include "GameConstants.h"
|
||||
#include "JsonNode.h"
|
||||
#include "IHandlerBase.h"
|
||||
#include "CRandomGenerator.h"
|
||||
|
||||
/*
|
||||
* CCreatureHandler.h, part of VCMI engine
|
||||
@ -186,7 +187,7 @@ public:
|
||||
std::vector <std::pair <Bonus*, std::pair <ui8, ui8> > > skillRequirements; // first - Bonus, second - which two skills are needed to use it
|
||||
|
||||
void deserializationFix();
|
||||
CreatureID pickRandomMonster(const std::function<int()> &randGen = nullptr, int tier = -1) const; //tier <1 - CREATURES_PER_TOWN> or -1 for any
|
||||
CreatureID pickRandomMonster(CRandomGenerator & rand, int tier = -1) const; //tier <1 - CREATURES_PER_TOWN> or -1 for any
|
||||
void addBonusForTier(int tier, Bonus *b); //tier must be <1-7>
|
||||
void addBonusForAllCreatures(Bonus *b);
|
||||
|
||||
|
@ -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;
|
||||
@ -476,11 +476,15 @@ int CGameState::pickUnusedHeroTypeRandomly(PlayerColor owner) const
|
||||
|
||||
// select random hero native to "our" faction
|
||||
if(!factionHeroes.empty())
|
||||
return factionHeroes.at(ran() % factionHeroes.size()).getNum();
|
||||
{
|
||||
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,12 +1040,16 @@ 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!";
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
void CGameState::initRandomFactionsForPlayers()
|
||||
{
|
||||
@ -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,9 +1781,11 @@ 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)
|
||||
vstd::erase_if(vti->builtBuildings, [vti](BuildingID bid){
|
||||
@ -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);
|
||||
@ -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;
|
||||
}
|
||||
|
@ -16,7 +16,7 @@
|
||||
#include "int3.h"
|
||||
#include "CObjectHandler.h"
|
||||
#include "IGameCallback.h"
|
||||
|
||||
#include "CRandomGenerator.h"
|
||||
|
||||
/*
|
||||
* CGameState.h, part of VCMI engine
|
||||
@ -399,7 +399,8 @@ public:
|
||||
std::map<ui32, ConstTransitivePtr<CGHeroInstance> > heroesPool; //[subID] - heroes available to buy; nullptr if not available
|
||||
std::map<ui32,ui8> pavailable; // [subid] -> which players can recruit hero (binary flags)
|
||||
|
||||
CGHeroInstance * pickHeroFor(bool native, PlayerColor player, const CTown *town, std::map<ui32, ConstTransitivePtr<CGHeroInstance> > &available, const CHeroClass *bannedClass = nullptr) const;
|
||||
CGHeroInstance * pickHeroFor(bool native, PlayerColor player, const CTown *town,
|
||||
std::map<ui32, ConstTransitivePtr<CGHeroInstance> > &available, CRandomGenerator & rand, const CHeroClass *bannedClass = nullptr) const;
|
||||
|
||||
template <typename Handler> void serialize(Handler &h, const int version)
|
||||
{
|
||||
@ -426,7 +427,7 @@ public:
|
||||
void giveHeroArtifact(CGHeroInstance *h, ArtifactID aid);
|
||||
|
||||
void apply(CPack *pack);
|
||||
BFieldType battleGetBattlefieldType(int3 tile) const;
|
||||
BFieldType battleGetBattlefieldType(int3 tile);
|
||||
UpgradeInfo getUpgradeInfo(const CStackInstance &stack);
|
||||
PlayerRelations::PlayerRelations getPlayerRelations(PlayerColor color1, PlayerColor color2);
|
||||
bool checkForVisitableDir(const int3 & src, const int3 & dst) const; //check if src tile is visitable from dst tile
|
||||
@ -453,6 +454,9 @@ public:
|
||||
int getMovementCost(const CGHeroInstance *h, const int3 &src, const int3 &dest, int remainingMovePoints=-1, bool checkLast=true);
|
||||
int getDate(Date::EDateType mode=Date::DAY) const; //mode=0 - total days in game, mode=1 - day of week, mode=2 - current week, mode=3 - current month
|
||||
|
||||
// ----- getters, setters -----
|
||||
CRandomGenerator & getRandomGenerator();
|
||||
|
||||
template <typename Handler> void serialize(Handler &h, const int version)
|
||||
{
|
||||
h & scenarioOps & initialOpts & currentPlayer & day & map & players & teams & hpool & globalEffects;
|
||||
@ -519,8 +523,11 @@ private:
|
||||
bool isUsedHero(HeroTypeID hid) const; //looks in heroes and prisons
|
||||
std::set<HeroTypeID> getUnusedAllowedHeroes(bool alsoIncludeNotAllowed = false) const;
|
||||
std::pair<Obj,int> pickObject(CGObjectInstance *obj); //chooses type of object to be randomized, returns <type, subtype>
|
||||
int pickUnusedHeroTypeRandomly(PlayerColor owner) const; // picks a unused hero type randomly
|
||||
int pickNextHeroType(PlayerColor owner) const; // picks next free hero type of the H3 hero init sequence -> chosen starting hero, then unused hero type randomly
|
||||
int pickUnusedHeroTypeRandomly(PlayerColor owner); // picks a unused hero type randomly
|
||||
int pickNextHeroType(PlayerColor owner); // picks next free hero type of the H3 hero init sequence -> chosen starting hero, then unused hero type randomly
|
||||
|
||||
// ---- data -----
|
||||
CRandomGenerator rand;
|
||||
|
||||
friend class CCallback;
|
||||
friend class CClient;
|
||||
|
@ -36,7 +36,6 @@ using namespace boost::assign;
|
||||
std::map<Obj, std::map<int, std::vector<ObjectInstanceID> > > CGTeleport::objs;
|
||||
std::vector<std::pair<ObjectInstanceID, ObjectInstanceID> > CGTeleport::gates;
|
||||
IGameCallback * IObjectInterface::cb = nullptr;
|
||||
extern std::minstd_rand ran;
|
||||
std::map <PlayerColor, std::set <ui8> > CGKeys::playerKeyMap;
|
||||
std::map <si32, std::vector<ObjectInstanceID> > CGMagi::eyelist;
|
||||
ui8 CGObelisk::obeliskCount; //how many obelisks are on map
|
||||
@ -798,7 +797,7 @@ void CGHeroInstance::initArmy(IArmyDescriptor *dst /*= nullptr*/)
|
||||
dst = this;
|
||||
|
||||
int howManyStacks = 0; //how many stacks will hero receives <1 - 3>
|
||||
int pom = ran()%100;
|
||||
int pom = cb->gameState()->getRandomGenerator().nextInt(99);
|
||||
int warMachinesGiven = 0;
|
||||
|
||||
if(pom < 9)
|
||||
@ -814,8 +813,7 @@ void CGHeroInstance::initArmy(IArmyDescriptor *dst /*= nullptr*/)
|
||||
{
|
||||
auto & stack = type->initialArmy[stackNo];
|
||||
|
||||
int range = stack.maxAmount - stack.minAmount;
|
||||
int count = ran()%(range+1) + stack.minAmount;
|
||||
int count = cb->gameState()->getRandomGenerator().nextInt(stack.minAmount, stack.maxAmount);
|
||||
|
||||
if(stack.creature >= CreatureID::CATAPULT &&
|
||||
stack.creature <= CreatureID::ARROW_TOWERS) //war machine
|
||||
@ -1465,7 +1463,7 @@ CStackBasicDescriptor CGHeroInstance::calculateNecromancy (const BattleResult &b
|
||||
void CGHeroInstance::showNecromancyDialog(const CStackBasicDescriptor &raisedStack) const
|
||||
{
|
||||
InfoWindow iw;
|
||||
iw.soundID = soundBase::pickup01 + ran() % 7;
|
||||
iw.soundID = soundBase::pickup01 + cb->gameState()->getRandomGenerator().nextInt(6);
|
||||
iw.player = tempOwner;
|
||||
iw.components.push_back(Component(raisedStack));
|
||||
|
||||
@ -1553,7 +1551,7 @@ EAlignment::EAlignment CGHeroInstance::getAlignment() const
|
||||
|
||||
void CGHeroInstance::initExp()
|
||||
{
|
||||
exp=40+ (ran()) % 50;
|
||||
exp = cb->gameState()->getRandomGenerator().nextInt(40, 89);
|
||||
level = 1;
|
||||
}
|
||||
|
||||
@ -1894,7 +1892,7 @@ void CGDwelling::newTurn() const
|
||||
|
||||
if(ID == Obj::REFUGEE_CAMP) //if it's a refugee camp, we need to pick an available creature
|
||||
{
|
||||
cb->setObjProperty(id, ObjProperty::AVAILABLE_CREATURE, VLC->creh->pickRandomMonster());
|
||||
cb->setObjProperty(id, ObjProperty::AVAILABLE_CREATURE, VLC->creh->pickRandomMonster(cb->gameState()->getRandomGenerator()));
|
||||
}
|
||||
|
||||
bool change = false;
|
||||
@ -2774,7 +2772,7 @@ void CGVisitableOPH::initObj()
|
||||
{
|
||||
if(ID==Obj::TREE_OF_KNOWLEDGE)
|
||||
{
|
||||
switch (ran() % 3)
|
||||
switch (cb->gameState()->getRandomGenerator().nextInt(2))
|
||||
{
|
||||
case 1:
|
||||
treePrice[Res::GOLD] = 2000;
|
||||
@ -3292,13 +3290,13 @@ void CGCreature::initObj()
|
||||
character = -4;
|
||||
break;
|
||||
case 1:
|
||||
character = 1 + ran()%7;
|
||||
character = cb->gameState()->getRandomGenerator().nextInt(1, 7);
|
||||
break;
|
||||
case 2:
|
||||
character = 1 + ran()%10;
|
||||
character = cb->gameState()->getRandomGenerator().nextInt(1, 10);
|
||||
break;
|
||||
case 3:
|
||||
character = 4 + ran()%7;
|
||||
character = cb->gameState()->getRandomGenerator().nextInt(4, 10);
|
||||
break;
|
||||
case 4:
|
||||
character = 10;
|
||||
@ -3308,14 +3306,11 @@ void CGCreature::initObj()
|
||||
stacks[SlotID(0)]->setType(CreatureID(subID));
|
||||
TQuantity &amount = stacks[SlotID(0)]->count;
|
||||
CCreature &c = *VLC->creh->creatures[subID];
|
||||
if(!amount)
|
||||
if(amount == 0)
|
||||
{
|
||||
if(c.ammMax == c.ammMin)
|
||||
amount = c.ammMax;
|
||||
else
|
||||
amount = c.ammMin + (ran() % (c.ammMax - c.ammMin));
|
||||
amount = cb->gameState()->getRandomGenerator().nextInt(c.ammMin, c.ammMax);
|
||||
|
||||
if(!amount) //armies with 0 creatures are illegal
|
||||
if(amount == 0) //armies with 0 creatures are illegal
|
||||
{
|
||||
logGlobal->warnStream() << "Problem: stack " << nodeName() << " cannot have 0 creatures. Check properties of " << c.nodeName();
|
||||
amount = 1;
|
||||
@ -3666,7 +3661,7 @@ void CGMine::initObj()
|
||||
if(subID >= 7) //Abandoned Mine
|
||||
{
|
||||
//set guardians
|
||||
int howManyTroglodytes = 100 + ran()%100;
|
||||
int howManyTroglodytes = cb->gameState()->getRandomGenerator().nextInt(100, 199);
|
||||
auto troglodytes = new CStackInstance(CreatureID::TROGLODYTES, howManyTroglodytes);
|
||||
putStack(SlotID(0), troglodytes);
|
||||
|
||||
@ -3676,8 +3671,8 @@ void CGMine::initObj()
|
||||
if(tempOwner.getNum() & 1<<i) //NOTE: reuse of tempOwner
|
||||
possibleResources.push_back(static_cast<Res::ERes>(i));
|
||||
|
||||
assert(possibleResources.size());
|
||||
producedResource = possibleResources[ran()%possibleResources.size()];
|
||||
assert(!possibleResources.empty());
|
||||
producedResource = *RandomGeneratorUtil::nextItem(possibleResources, cb->gameState()->getRandomGenerator());
|
||||
tempOwner = PlayerColor::NEUTRAL;
|
||||
hoverName = VLC->generaltexth->mines[7].first + "\n" + VLC->generaltexth->allTexts[202] + " " + troglodytes->getQuantityTXT(false) + " " + troglodytes->type->namePl;
|
||||
}
|
||||
@ -3761,13 +3756,13 @@ void CGResource::initObj()
|
||||
switch(subID)
|
||||
{
|
||||
case 6:
|
||||
amount = 500 + (ran()%6)*100;
|
||||
amount = cb->gameState()->getRandomGenerator().nextInt(500, 1000);
|
||||
break;
|
||||
case 0: case 2:
|
||||
amount = 6 + (ran()%5);
|
||||
amount = cb->gameState()->getRandomGenerator().nextInt(6, 10);
|
||||
break;
|
||||
default:
|
||||
amount = 3 + (ran()%3);
|
||||
amount = cb->gameState()->getRandomGenerator().nextInt(3, 5);
|
||||
break;
|
||||
}
|
||||
}
|
||||
@ -4171,12 +4166,12 @@ void CGPickable::initObj()
|
||||
switch(ID)
|
||||
{
|
||||
case Obj::CAMPFIRE:
|
||||
val2 = (ran()%3) + 4; //4 - 6
|
||||
val2 = cb->gameState()->getRandomGenerator().nextInt(4, 6);
|
||||
val1 = val2 * 100;
|
||||
type = ran()%6; //given resource
|
||||
type = cb->gameState()->getRandomGenerator().nextInt(5); // given resource
|
||||
break;
|
||||
case Obj::FLOTSAM:
|
||||
switch(type = ran()%4)
|
||||
switch(type = cb->gameState()->getRandomGenerator().nextInt(3))
|
||||
{
|
||||
case 0:
|
||||
val1 = val2 = 0;
|
||||
@ -4197,7 +4192,7 @@ void CGPickable::initObj()
|
||||
break;
|
||||
case Obj::SEA_CHEST:
|
||||
{
|
||||
int hlp = ran()%100;
|
||||
int hlp = cb->gameState()->getRandomGenerator().nextInt(99);
|
||||
if(hlp < 20)
|
||||
{
|
||||
val1 = 0;
|
||||
@ -4211,31 +4206,31 @@ void CGPickable::initObj()
|
||||
else
|
||||
{
|
||||
val1 = 1000;
|
||||
val2 = cb->getRandomArt (CArtifact::ART_TREASURE);
|
||||
val2 = VLC->arth->pickRandomArtifact(cb->gameState()->getRandomGenerator(), CArtifact::ART_TREASURE);
|
||||
type = 1;
|
||||
}
|
||||
}
|
||||
break;
|
||||
case Obj::SHIPWRECK_SURVIVOR:
|
||||
{
|
||||
int hlp = ran()%100;
|
||||
int hlp = cb->gameState()->getRandomGenerator().nextInt(99);
|
||||
if(hlp < 55)
|
||||
val1 = cb->getRandomArt (CArtifact::ART_TREASURE);
|
||||
val1 = VLC->arth->pickRandomArtifact(cb->gameState()->getRandomGenerator(), CArtifact::ART_TREASURE);
|
||||
else if(hlp < 75)
|
||||
val1 = cb->getRandomArt (CArtifact::ART_MINOR);
|
||||
val1 = VLC->arth->pickRandomArtifact(cb->gameState()->getRandomGenerator(), CArtifact::ART_MINOR);
|
||||
else if(hlp < 95)
|
||||
val1 = cb->getRandomArt (CArtifact::ART_MAJOR);
|
||||
val1 = VLC->arth->pickRandomArtifact(cb->gameState()->getRandomGenerator(), CArtifact::ART_MAJOR);
|
||||
else
|
||||
val1 = cb->getRandomArt (CArtifact::ART_RELIC);
|
||||
val1 = VLC->arth->pickRandomArtifact(cb->gameState()->getRandomGenerator(), CArtifact::ART_RELIC);
|
||||
}
|
||||
break;
|
||||
case Obj::TREASURE_CHEST:
|
||||
{
|
||||
int hlp = ran()%100;
|
||||
int hlp = cb->gameState()->getRandomGenerator().nextInt(99);
|
||||
if(hlp >= 95)
|
||||
{
|
||||
type = 1;
|
||||
val1 = cb->getRandomArt (CArtifact::ART_TREASURE);
|
||||
val1 = VLC->arth->pickRandomArtifact(cb->gameState()->getRandomGenerator(), CArtifact::ART_TREASURE);
|
||||
return;
|
||||
}
|
||||
else if (hlp >= 65)
|
||||
@ -4733,8 +4728,8 @@ void CGSeerHut::setObjToKill()
|
||||
|
||||
void CGSeerHut::init()
|
||||
{
|
||||
seerName = VLC->generaltexth->seerNames[ran()%VLC->generaltexth->seerNames.size()];
|
||||
quest->textOption = ran() % 3;
|
||||
seerName = *RandomGeneratorUtil::nextItem(VLC->generaltexth->seerNames, cb->gameState()->getRandomGenerator());
|
||||
quest->textOption = cb->gameState()->getRandomGenerator().nextInt(2);
|
||||
}
|
||||
|
||||
void CGSeerHut::initObj()
|
||||
@ -5058,7 +5053,7 @@ void CGSeerHut::blockingDialogAnswered(const CGHeroInstance *hero, ui32 answer)
|
||||
void CGQuestGuard::init()
|
||||
{
|
||||
blockVisit = true;
|
||||
quest->textOption = (ran() % 3) + 3; //3-5
|
||||
quest->textOption = cb->gameState()->getRandomGenerator().nextInt(3, 5);
|
||||
}
|
||||
void CGQuestGuard::completeQuest(const CGHeroInstance *h) const
|
||||
{
|
||||
@ -5066,7 +5061,7 @@ void CGQuestGuard::completeQuest(const CGHeroInstance *h) const
|
||||
}
|
||||
void CGWitchHut::initObj()
|
||||
{
|
||||
ability = allowedAbilities[ran()%allowedAbilities.size()];
|
||||
ability = *RandomGeneratorUtil::nextItem(allowedAbilities, cb->gameState()->getRandomGenerator());
|
||||
}
|
||||
|
||||
void CGWitchHut::onHeroVisit( const CGHeroInstance * h ) const
|
||||
@ -5862,13 +5857,13 @@ void CGShrine::initObj()
|
||||
std::vector<SpellID> possibilities;
|
||||
cb->getAllowedSpells (possibilities, level);
|
||||
|
||||
if(!possibilities.size())
|
||||
if(possibilities.empty())
|
||||
{
|
||||
logGlobal->errorStream() << "Error: cannot init shrine, no allowed spells!";
|
||||
return;
|
||||
}
|
||||
|
||||
spell = possibilities[ran() % possibilities.size()];
|
||||
spell = *RandomGeneratorUtil::nextItem(possibilities, cb->gameState()->getRandomGenerator());
|
||||
}
|
||||
}
|
||||
|
||||
@ -5889,8 +5884,10 @@ const std::string & CGShrine::getHoverText() const
|
||||
void CGSignBottle::initObj()
|
||||
{
|
||||
//if no text is set than we pick random from the predefined ones
|
||||
if(!message.size())
|
||||
message = VLC->generaltexth->randsign[ran()%VLC->generaltexth->randsign.size()];
|
||||
if(message.empty())
|
||||
{
|
||||
message = *RandomGeneratorUtil::nextItem(VLC->generaltexth->randsign, cb->gameState()->getRandomGenerator());
|
||||
}
|
||||
|
||||
if(ID == Obj::OCEAN_BOTTLE)
|
||||
{
|
||||
@ -5930,10 +5927,9 @@ void CGScholar::onHeroVisit( const CGHeroInstance * h ) const
|
||||
))) //hero doesn't have a spellbook or already knows the spell or doesn't have Wisdom
|
||||
{
|
||||
type = PRIM_SKILL;
|
||||
bid = ran() % GameConstants::PRIMARY_SKILLS;
|
||||
bid = cb->gameState()->getRandomGenerator().nextInt(GameConstants::PRIMARY_SKILLS - 1);
|
||||
}
|
||||
|
||||
|
||||
InfoWindow iw;
|
||||
iw.soundID = soundBase::gazebo;
|
||||
iw.player = h->getOwner();
|
||||
@ -5971,20 +5967,20 @@ void CGScholar::initObj()
|
||||
blockVisit = true;
|
||||
if(bonusType == RANDOM)
|
||||
{
|
||||
bonusType = static_cast<EBonusType>(ran()%3);
|
||||
bonusType = static_cast<EBonusType>(cb->gameState()->getRandomGenerator().nextInt(2));
|
||||
switch(bonusType)
|
||||
{
|
||||
case PRIM_SKILL:
|
||||
bonusID = ran() % GameConstants::PRIMARY_SKILLS;
|
||||
bonusID = cb->gameState()->getRandomGenerator().nextInt(GameConstants::PRIMARY_SKILLS -1);
|
||||
break;
|
||||
case SECONDARY_SKILL:
|
||||
bonusID = ran() % GameConstants::SKILL_QUANTITY;
|
||||
bonusID = cb->gameState()->getRandomGenerator().nextInt(GameConstants::SKILL_QUANTITY -1);
|
||||
break;
|
||||
case SPELL:
|
||||
std::vector<SpellID> possibilities;
|
||||
for (int i = 1; i < 6; ++i)
|
||||
cb->getAllowedSpells (possibilities, i);
|
||||
bonusID = possibilities[ran() % possibilities.size()];
|
||||
bonusID = *RandomGeneratorUtil::nextItem(possibilities, cb->gameState()->getRandomGenerator());
|
||||
break;
|
||||
}
|
||||
}
|
||||
@ -6124,11 +6120,11 @@ void CGOnceVisitable::initObj()
|
||||
case Obj::CORPSE:
|
||||
{
|
||||
blockVisit = true;
|
||||
int hlp = ran()%100;
|
||||
int hlp = cb->gameState()->getRandomGenerator().nextInt(99);
|
||||
if(hlp < 20)
|
||||
{
|
||||
artOrRes = 1;
|
||||
bonusType = cb->getRandomArt (CArtifact::ART_TREASURE | CArtifact::ART_MINOR | CArtifact::ART_MAJOR);
|
||||
bonusType = VLC->arth->pickRandomArtifact(cb->gameState()->getRandomGenerator(), CArtifact::ART_TREASURE | CArtifact::ART_MINOR | CArtifact::ART_MAJOR);
|
||||
}
|
||||
else
|
||||
{
|
||||
@ -6140,8 +6136,8 @@ void CGOnceVisitable::initObj()
|
||||
case Obj::LEAN_TO:
|
||||
{
|
||||
artOrRes = 2;
|
||||
bonusType = ran()%6; //any basic resource without gold
|
||||
bonusVal = ran()%4 + 1;
|
||||
bonusType = cb->gameState()->getRandomGenerator().nextInt(5); //any basic resource without gold
|
||||
bonusVal = cb->gameState()->getRandomGenerator().nextInt(1, 4);
|
||||
}
|
||||
break;
|
||||
|
||||
@ -6149,21 +6145,21 @@ void CGOnceVisitable::initObj()
|
||||
{
|
||||
artOrRes = 1;
|
||||
|
||||
int hlp = ran()%100;
|
||||
int hlp = cb->gameState()->getRandomGenerator().nextInt(99);
|
||||
if(hlp < 30)
|
||||
bonusType = cb->getRandomArt (CArtifact::ART_TREASURE);
|
||||
bonusType = VLC->arth->pickRandomArtifact(cb->gameState()->getRandomGenerator(), CArtifact::ART_TREASURE);
|
||||
else if(hlp < 80)
|
||||
bonusType = cb->getRandomArt (CArtifact::ART_MINOR);
|
||||
bonusType = VLC->arth->pickRandomArtifact(cb->gameState()->getRandomGenerator(), CArtifact::ART_MINOR);
|
||||
else if(hlp < 95)
|
||||
bonusType = cb->getRandomArt (CArtifact::ART_MAJOR);
|
||||
bonusType = VLC->arth->pickRandomArtifact(cb->gameState()->getRandomGenerator(), CArtifact::ART_MAJOR);
|
||||
else
|
||||
bonusType = cb->getRandomArt (CArtifact::ART_RELIC);
|
||||
bonusType = VLC->arth->pickRandomArtifact(cb->gameState()->getRandomGenerator(), CArtifact::ART_RELIC);
|
||||
}
|
||||
break;
|
||||
|
||||
case Obj::WAGON:
|
||||
{
|
||||
int hlp = ran()%100;
|
||||
int hlp = cb->gameState()->getRandomGenerator().nextInt(99);
|
||||
|
||||
if(hlp < 10)
|
||||
{
|
||||
@ -6172,13 +6168,13 @@ void CGOnceVisitable::initObj()
|
||||
else if(hlp < 50) //minor or treasure art
|
||||
{
|
||||
artOrRes = 1;
|
||||
bonusType = cb->getRandomArt (CArtifact::ART_TREASURE | CArtifact::ART_MINOR);
|
||||
bonusType = VLC->arth->pickRandomArtifact(cb->gameState()->getRandomGenerator(), CArtifact::ART_TREASURE | CArtifact::ART_MINOR);
|
||||
}
|
||||
else //2 - 5 of non-gold resource
|
||||
{
|
||||
artOrRes = 2;
|
||||
bonusType = ran()%6;
|
||||
bonusVal = ran()%4 + 2;
|
||||
bonusType = cb->gameState()->getRandomGenerator().nextInt(5);
|
||||
bonusVal = cb->gameState()->getRandomGenerator().nextInt(2, 5);
|
||||
}
|
||||
}
|
||||
break;
|
||||
@ -6250,7 +6246,7 @@ void CBank::reset(ui16 var1) //prevents desync
|
||||
|
||||
void CBank::initialize() const
|
||||
{
|
||||
cb->setObjProperty (id, ObjProperty::BANK_RESET, ran()); //synchronous reset
|
||||
cb->setObjProperty(id, ObjProperty::BANK_RESET, cb->gameState()->getRandomGenerator().nextInt()); //synchronous reset
|
||||
|
||||
for (ui8 i = 0; i <= 3; i++)
|
||||
{
|
||||
@ -6266,12 +6262,12 @@ void CBank::initialize() const
|
||||
default: assert(0); continue;
|
||||
}
|
||||
|
||||
int artID = cb->getArtSync(ran(), artClass, true);
|
||||
int artID = VLC->arth->pickRandomArtifact(cb->gameState()->getRandomGenerator(), artClass);
|
||||
cb->setObjProperty(id, ObjProperty::BANK_ADD_ARTIFACT, artID);
|
||||
}
|
||||
}
|
||||
|
||||
cb->setObjProperty (id, ObjProperty::BANK_INIT_ARMY, ran()); //get army
|
||||
cb->setObjProperty(id, ObjProperty::BANK_INIT_ARMY, cb->gameState()->getRandomGenerator().nextInt()); //get army
|
||||
}
|
||||
void CBank::setPropertyDer (ui8 what, ui32 val)
|
||||
/// random values are passed as arguments and processed identically on all clients
|
||||
@ -6578,13 +6574,13 @@ void CGPyramid::initObj()
|
||||
if (available.size())
|
||||
{
|
||||
bc = VLC->objh->banksInfo[21].front(); //TODO: remove hardcoded value?
|
||||
spell = (available[ran()%available.size()]);
|
||||
spell = *RandomGeneratorUtil::nextItem(available, cb->gameState()->getRandomGenerator());
|
||||
}
|
||||
else
|
||||
{
|
||||
logGlobal->errorStream() <<"No spells available for Pyramid! Object set to empty.";
|
||||
}
|
||||
setPropertyDer (ObjProperty::BANK_INIT_ARMY,ran()); //set guards at game start
|
||||
setPropertyDer(ObjProperty::BANK_INIT_ARMY, cb->gameState()->getRandomGenerator().nextInt()); //set guards at game start
|
||||
}
|
||||
const std::string & CGPyramid::getHoverText() const
|
||||
{
|
||||
@ -7557,20 +7553,26 @@ void CGBlackMarket::newTurn() const
|
||||
void CGUniversity::initObj()
|
||||
{
|
||||
std::vector<int> toChoose;
|
||||
for (int i=0; i<GameConstants::SKILL_QUANTITY; i++)
|
||||
for(int i = 0; i < GameConstants::SKILL_QUANTITY; ++i)
|
||||
{
|
||||
if(cb->isAllowed(2, i))
|
||||
{
|
||||
toChoose.push_back(i);
|
||||
}
|
||||
}
|
||||
if(toChoose.size() < 4)
|
||||
{
|
||||
logGlobal->warnStream()<<"Warning: less then 4 available skills was found by University initializer!";
|
||||
return;
|
||||
}
|
||||
|
||||
for (int i=0; i<4; i++)//get 4 skills
|
||||
// get 4 skills
|
||||
for(int i = 0; i < 4; ++i)
|
||||
{
|
||||
int skillPos = ran()%toChoose.size();
|
||||
skills.push_back(toChoose[skillPos]);//move it to selected
|
||||
toChoose.erase(toChoose.begin()+skillPos);//remove from list
|
||||
// move randomly one skill to selected and remove from list
|
||||
auto it = RandomGeneratorUtil::nextItem(toChoose, cb->gameState()->getRandomGenerator());
|
||||
skills.push_back(*it);
|
||||
toChoose.erase(it);
|
||||
}
|
||||
}
|
||||
|
||||
|
@ -20,44 +20,92 @@ typedef std::function<double()> TRand;
|
||||
/// The random generator randomly generates integers and real numbers("doubles") between
|
||||
/// a given range. This is a header only class and mainly a wrapper for
|
||||
/// convenient usage of the standard random API.
|
||||
class CRandomGenerator
|
||||
class CRandomGenerator : boost::noncopyable
|
||||
{
|
||||
public:
|
||||
/// Seeds the generator with the current time by default.
|
||||
CRandomGenerator()
|
||||
{
|
||||
gen.seed((unsigned long)std::time(nullptr));
|
||||
rand.seed(static_cast<unsigned long>(std::time(nullptr)));
|
||||
}
|
||||
|
||||
void seed(int value)
|
||||
void setSeed(int seed)
|
||||
{
|
||||
gen.seed(value);
|
||||
rand.seed(seed);
|
||||
}
|
||||
|
||||
/// Generate several integer numbers within the same range.
|
||||
/// e.g.: auto a = gen.getRangeI(0,10); a(); a(); a();
|
||||
TRandI getRangeI(int lower, int upper)
|
||||
/// e.g.: auto a = gen.getIntRange(0,10); a(); a(); a();
|
||||
/// requires: lower <= upper
|
||||
TRandI getIntRange(int lower, int upper)
|
||||
{
|
||||
return boost::bind(TIntDist(lower, upper), boost::ref(gen));
|
||||
return boost::bind(TIntDist(lower, upper), boost::ref(rand));
|
||||
}
|
||||
|
||||
int getInteger(int lower, int upper)
|
||||
/// Generates an integer between 0 and upper.
|
||||
/// requires: 0 <= upper
|
||||
int nextInt(int upper)
|
||||
{
|
||||
return getRangeI(lower, upper)();
|
||||
return getIntRange(0, upper)();
|
||||
}
|
||||
|
||||
/// requires: lower <= upper
|
||||
int nextInt(int lower, int upper)
|
||||
{
|
||||
return getIntRange(lower, upper)();
|
||||
}
|
||||
|
||||
/// Generates an integer between 0 and the maximum value it can hold.
|
||||
int nextInt()
|
||||
{
|
||||
return TIntDist()(rand);
|
||||
}
|
||||
|
||||
/// Generate several double/real numbers within the same range.
|
||||
/// e.g.: auto a = gen.getRangeI(0,10); a(); a(); a();
|
||||
TRand getRange(double lower, double upper)
|
||||
/// e.g.: auto a = gen.getDoubleRange(4.5,10.2); a(); a(); a();
|
||||
/// requires: lower <= upper
|
||||
TRand getDoubleRange(double lower, double upper)
|
||||
{
|
||||
return boost::bind(TRealDist(lower, upper), boost::ref(gen));
|
||||
return boost::bind(TRealDist(lower, upper), boost::ref(rand));
|
||||
}
|
||||
|
||||
double getDouble(double lower, double upper)
|
||||
/// Generates a double between 0 and upper.
|
||||
/// requires: 0 <= upper
|
||||
double nextDouble(double upper)
|
||||
{
|
||||
return getRange(lower, upper)();
|
||||
return getDoubleRange(0, upper)();
|
||||
}
|
||||
|
||||
/// requires: lower <= upper
|
||||
double nextDouble(double lower, double upper)
|
||||
{
|
||||
return getDoubleRange(lower, upper)();
|
||||
}
|
||||
|
||||
/// Generates a double between 0.0 and 1.0.
|
||||
double nextDouble()
|
||||
{
|
||||
return TRealDist()(rand);
|
||||
}
|
||||
|
||||
private:
|
||||
TGenerator gen;
|
||||
TGenerator rand;
|
||||
};
|
||||
|
||||
namespace RandomGeneratorUtil
|
||||
{
|
||||
/// Gets an iterator to an element of a nonempty container randomly. Undefined behaviour if container is empty.
|
||||
template<typename Container>
|
||||
auto nextItem(const Container & container, CRandomGenerator & rand) -> decltype(std::begin(container))
|
||||
{
|
||||
assert(!container.empty());
|
||||
return std::next(container.begin(), rand.nextInt(container.size() - 1));
|
||||
}
|
||||
|
||||
template<typename Container>
|
||||
auto nextItem(Container & container, CRandomGenerator & rand) -> decltype(std::begin(container))
|
||||
{
|
||||
assert(!container.empty());
|
||||
return std::next(container.begin(), rand.nextInt(container.size() - 1));
|
||||
}
|
||||
}
|
||||
|
@ -1,3 +1,13 @@
|
||||
/*
|
||||
* IGameCallback.cpp, part of VCMI engine
|
||||
*
|
||||
* Authors: listed in file AUTHORS in main folder
|
||||
*
|
||||
* License: GNU General Public License v2.0 or later
|
||||
* Full text of license available in license.txt file, in main folder
|
||||
*
|
||||
*/
|
||||
|
||||
#include "StdInc.h"
|
||||
#include "IGameCallback.h"
|
||||
|
||||
@ -20,24 +30,12 @@
|
||||
|
||||
#include "Connection.h"
|
||||
|
||||
/*
|
||||
* IGameCallback.cpp, part of VCMI engine
|
||||
*
|
||||
* Authors: listed in file AUTHORS in main folder
|
||||
*
|
||||
* License: GNU General Public License v2.0 or later
|
||||
* Full text of license available in license.txt file, in main folder
|
||||
*
|
||||
*/
|
||||
|
||||
//TODO make clean
|
||||
#define ERROR_SILENT_RET_VAL_IF(cond, txt, retVal) do {if(cond){return retVal;}} while(0)
|
||||
#define ERROR_VERBOSE_OR_NOT_RET_VAL_IF(cond, verbose, txt, retVal) do {if(cond){if(verbose)logGlobal->errorStream() << BOOST_CURRENT_FUNCTION << ": " << txt; return retVal;}} while(0)
|
||||
#define ERROR_RET_IF(cond, txt) do {if(cond){logGlobal->errorStream() << BOOST_CURRENT_FUNCTION << ": " << txt; return;}} while(0)
|
||||
#define ERROR_RET_VAL_IF(cond, txt, retVal) do {if(cond){logGlobal->errorStream() << BOOST_CURRENT_FUNCTION << ": " << txt; return retVal;}} while(0)
|
||||
|
||||
extern std::minstd_rand ran;
|
||||
|
||||
CGameState * CPrivilagedInfoCallback::gameState ()
|
||||
{
|
||||
return gs;
|
||||
@ -182,21 +180,11 @@ bool CGameInfoCallback::isAllowed( int type, int id )
|
||||
void CPrivilagedInfoCallback::pickAllowedArtsSet(std::vector<const CArtifact*> &out)
|
||||
{
|
||||
for (int j = 0; j < 3 ; j++)
|
||||
out.push_back(VLC->arth->artifacts[getRandomArt(CArtifact::ART_TREASURE)]);
|
||||
out.push_back(VLC->arth->artifacts[VLC->arth->pickRandomArtifact(gameState()->getRandomGenerator(), CArtifact::ART_TREASURE)]);
|
||||
for (int j = 0; j < 3 ; j++)
|
||||
out.push_back(VLC->arth->artifacts[getRandomArt(CArtifact::ART_MINOR)]);
|
||||
out.push_back(VLC->arth->artifacts[VLC->arth->pickRandomArtifact(gameState()->getRandomGenerator(), CArtifact::ART_MINOR)]);
|
||||
|
||||
out.push_back(VLC->arth->artifacts[getRandomArt(CArtifact::ART_MAJOR)]);
|
||||
}
|
||||
|
||||
ArtifactID CPrivilagedInfoCallback::getRandomArt (int flags)
|
||||
{
|
||||
return VLC->arth->getRandomArt(flags);
|
||||
}
|
||||
|
||||
ArtifactID CPrivilagedInfoCallback::getArtSync (ui32 rand, int flags, bool erasePicked)
|
||||
{
|
||||
return VLC->arth->getArtSync (rand, flags, erasePicked);
|
||||
out.push_back(VLC->arth->artifacts[VLC->arth->pickRandomArtifact(gameState()->getRandomGenerator(), CArtifact::ART_MAJOR)]);
|
||||
}
|
||||
|
||||
void CPrivilagedInfoCallback::getAllowedSpells(std::vector<SpellID> &out, ui16 level)
|
||||
|
@ -171,8 +171,6 @@ public:
|
||||
void getFreeTiles (std::vector<int3> &tiles) const; //used for random spawns
|
||||
void getTilesInRange(std::unordered_set<int3, ShashInt3> &tiles, int3 pos, int radious, boost::optional<PlayerColor> player = boost::optional<PlayerColor>(), int mode=0) const; //mode 1 - only unrevealed tiles; mode 0 - all, mode -1 - only unrevealed
|
||||
void getAllTiles (std::unordered_set<int3, ShashInt3> &tiles, boost::optional<PlayerColor> player = boost::optional<PlayerColor>(), int level=-1, int surface=0) const; //returns all tiles on given level (-1 - both levels, otherwise number of level); surface: 0 - land and water, 1 - only land, 2 - only water
|
||||
ArtifactID getRandomArt (int flags);
|
||||
ArtifactID getArtSync (ui32 rand, int flags, bool erasePicked); //synchronous
|
||||
void pickAllowedArtsSet(std::vector<const CArtifact*> &out); //gives 3 treasures, 3 minors, 1 major -> used by Black Market and Artifact Merchant
|
||||
void getAllowedSpells(std::vector<SpellID> &out, ui16 level);
|
||||
|
||||
|
@ -598,7 +598,7 @@ void CDrawTerrainOperation::updateTerrainViews()
|
||||
auto & tile = map->getTile(pos);
|
||||
if(!pattern.diffImages)
|
||||
{
|
||||
tile.terView = gen->getInteger(mapping.first, mapping.second);
|
||||
tile.terView = gen->nextInt(mapping.first, mapping.second);
|
||||
tile.extTileFlags = valRslt.flip;
|
||||
}
|
||||
else
|
||||
@ -606,7 +606,7 @@ void CDrawTerrainOperation::updateTerrainViews()
|
||||
const int framesPerRot = (mapping.second - mapping.first + 1) / pattern.rotationTypesCount;
|
||||
int flip = (pattern.rotationTypesCount == 2 && valRslt.flip == 2) ? 1 : valRslt.flip;
|
||||
int firstFrame = mapping.first + flip * framesPerRot;
|
||||
tile.terView = gen->getInteger(firstFrame, firstFrame + framesPerRot - 1);
|
||||
tile.terView = gen->nextInt(firstFrame, firstFrame + framesPerRot - 1);
|
||||
tile.extTileFlags = 0;
|
||||
}
|
||||
}
|
||||
|
@ -177,15 +177,15 @@ const std::map<std::string, CRmgTemplate *> & CMapGenOptions::getAvailableTempla
|
||||
|
||||
void CMapGenOptions::finalize()
|
||||
{
|
||||
CRandomGenerator gen;
|
||||
finalize(gen);
|
||||
CRandomGenerator rand;
|
||||
finalize(rand);
|
||||
}
|
||||
|
||||
void CMapGenOptions::finalize(CRandomGenerator & gen)
|
||||
void CMapGenOptions::finalize(CRandomGenerator & rand)
|
||||
{
|
||||
if(!mapTemplate)
|
||||
{
|
||||
mapTemplate = getPossibleTemplate(gen);
|
||||
mapTemplate = getPossibleTemplate(rand);
|
||||
assert(mapTemplate);
|
||||
}
|
||||
|
||||
@ -194,22 +194,22 @@ void CMapGenOptions::finalize(CRandomGenerator & gen)
|
||||
auto possiblePlayers = mapTemplate->getPlayers().getNumbers();
|
||||
possiblePlayers.erase(possiblePlayers.begin(), possiblePlayers.lower_bound(countHumanPlayers()));
|
||||
assert(!possiblePlayers.empty());
|
||||
playerCount = *std::next(possiblePlayers.begin(), gen.getInteger(0, possiblePlayers.size() - 1));
|
||||
playerCount = *RandomGeneratorUtil::nextItem(possiblePlayers, rand);
|
||||
updatePlayers();
|
||||
}
|
||||
if(teamCount == RANDOM_SIZE)
|
||||
{
|
||||
teamCount = gen.getInteger(0, playerCount - 1);
|
||||
teamCount = rand.nextInt(playerCount - 1);
|
||||
}
|
||||
if(compOnlyPlayerCount == RANDOM_SIZE)
|
||||
{
|
||||
auto possiblePlayers = mapTemplate->getCpuPlayers().getNumbers();
|
||||
compOnlyPlayerCount = *std::next(possiblePlayers.begin(), gen.getInteger(0, possiblePlayers.size() - 1));
|
||||
compOnlyPlayerCount = *RandomGeneratorUtil::nextItem(possiblePlayers, rand);
|
||||
updateCompOnlyPlayers();
|
||||
}
|
||||
if(compOnlyTeamCount == RANDOM_SIZE)
|
||||
{
|
||||
compOnlyTeamCount = gen.getInteger(0, std::max(compOnlyPlayerCount - 1, 0));
|
||||
compOnlyTeamCount = rand.nextInt(std::max(compOnlyPlayerCount - 1, 0));
|
||||
}
|
||||
|
||||
// 1 team isn't allowed
|
||||
@ -220,11 +220,11 @@ void CMapGenOptions::finalize(CRandomGenerator & gen)
|
||||
|
||||
if(waterContent == EWaterContent::RANDOM)
|
||||
{
|
||||
waterContent = static_cast<EWaterContent::EWaterContent>(gen.getInteger(0, 2));
|
||||
waterContent = static_cast<EWaterContent::EWaterContent>(rand.nextInt(2));
|
||||
}
|
||||
if(monsterStrength == EMonsterStrength::RANDOM)
|
||||
{
|
||||
monsterStrength = static_cast<EMonsterStrength::EMonsterStrength>(gen.getInteger(0, 2));
|
||||
monsterStrength = static_cast<EMonsterStrength::EMonsterStrength>(rand.nextInt(2));
|
||||
}
|
||||
}
|
||||
|
||||
@ -313,7 +313,7 @@ bool CMapGenOptions::checkOptions() const
|
||||
}
|
||||
}
|
||||
|
||||
const CRmgTemplate * CMapGenOptions::getPossibleTemplate(CRandomGenerator & gen) const
|
||||
const CRmgTemplate * CMapGenOptions::getPossibleTemplate(CRandomGenerator & rand) const
|
||||
{
|
||||
// Find potential templates
|
||||
const auto & tpls = getAvailableTemplates();
|
||||
@ -363,7 +363,7 @@ const CRmgTemplate * CMapGenOptions::getPossibleTemplate(CRandomGenerator & gen)
|
||||
}
|
||||
else
|
||||
{
|
||||
return *std::next(potentialTpls.begin(), gen.getInteger(0, potentialTpls.size() - 1));
|
||||
return *RandomGeneratorUtil::nextItem(potentialTpls, rand);
|
||||
}
|
||||
}
|
||||
|
||||
|
@ -143,7 +143,7 @@ public:
|
||||
/// a random number generator by keeping the options in a valid state. Check options should return true, otherwise
|
||||
/// this function fails.
|
||||
void finalize();
|
||||
void finalize(CRandomGenerator & gen);
|
||||
void finalize(CRandomGenerator & rand);
|
||||
|
||||
/// Returns false if there is no template available which fits to the currently selected options.
|
||||
bool checkOptions() const;
|
||||
@ -156,7 +156,7 @@ private:
|
||||
PlayerColor getNextPlayerColor() const;
|
||||
void updateCompOnlyPlayers();
|
||||
void updatePlayers();
|
||||
const CRmgTemplate * getPossibleTemplate(CRandomGenerator & gen) const;
|
||||
const CRmgTemplate * getPossibleTemplate(CRandomGenerator & rand) const;
|
||||
|
||||
si32 width, height;
|
||||
bool hasTwoLevels;
|
||||
|
@ -35,9 +35,9 @@ CMapGenerator::~CMapGenerator()
|
||||
std::unique_ptr<CMap> CMapGenerator::generate(CMapGenOptions * mapGenOptions, int randomSeed /*= std::time(nullptr)*/)
|
||||
{
|
||||
this->randomSeed = randomSeed;
|
||||
gen.seed(this->randomSeed);
|
||||
rand.setSeed(this->randomSeed);
|
||||
this->mapGenOptions = mapGenOptions;
|
||||
this->mapGenOptions->finalize(gen);
|
||||
this->mapGenOptions->finalize(rand);
|
||||
|
||||
map = make_unique<CMap>();
|
||||
editManager = map->getEditManager();
|
||||
@ -125,7 +125,8 @@ void CMapGenerator::addPlayerInfo()
|
||||
{
|
||||
player.canHumanPlay = true;
|
||||
}
|
||||
auto itTeam = std::next(teamNumbers[j].begin(), gen.getInteger(0, teamNumbers[j].size() - 1));
|
||||
|
||||
auto itTeam = RandomGeneratorUtil::nextItem(teamNumbers[j], rand);
|
||||
player.team = TeamID(*itTeam);
|
||||
teamNumbers[j].erase(itTeam);
|
||||
map->players[pSettings.getColor().getNum()] = player;
|
||||
@ -138,9 +139,9 @@ void CMapGenerator::addPlayerInfo()
|
||||
void CMapGenerator::genTerrain()
|
||||
{
|
||||
map->initTerrain();
|
||||
editManager->clearTerrain(&gen);
|
||||
editManager->clearTerrain(&rand);
|
||||
editManager->getTerrainSelection().selectRange(MapRect(int3(4, 4, 0), 24, 30));
|
||||
editManager->drawTerrain(ETerrainType::GRASS, &gen);
|
||||
editManager->drawTerrain(ETerrainType::GRASS, &rand);
|
||||
}
|
||||
|
||||
void CMapGenerator::genTowns()
|
||||
@ -158,7 +159,11 @@ void CMapGenerator::genTowns()
|
||||
auto town = new CGTownInstance();
|
||||
town->ID = Obj::TOWN;
|
||||
int townId = mapGenOptions->getPlayersSettings().find(PlayerColor(i))->second.getStartingTown();
|
||||
if(townId == CMapGenOptions::CPlayerSettings::RANDOM_TOWN) townId = gen.getInteger(0, 8); // Default towns
|
||||
if(townId == CMapGenOptions::CPlayerSettings::RANDOM_TOWN)
|
||||
{
|
||||
// select default towns
|
||||
townId = rand.nextInt(8);
|
||||
}
|
||||
town->subID = townId;
|
||||
town->tempOwner = owner;
|
||||
town->appearance = VLC->dobjinfo->pickCandidates(town->ID, town->subID, map->getTile(townPos[side]).terType).front();
|
||||
|
@ -36,7 +36,7 @@ private:
|
||||
|
||||
CMapGenOptions * mapGenOptions;
|
||||
std::unique_ptr<CMap> map;
|
||||
CRandomGenerator gen;
|
||||
CRandomGenerator rand;
|
||||
int randomSeed;
|
||||
CMapEditManager * editManager;
|
||||
};
|
||||
|
@ -7,7 +7,7 @@ Group: Amusements/Games
|
||||
|
||||
# The source for this package was pulled from upstream's vcs. Use the
|
||||
# following commands to generate the tarball:
|
||||
# svn export -r HEAD https://vcmi.svn.sourceforge.net/svnroot/vcmi/tags/0.95 vcmi-0.9.5-1
|
||||
# svn export -r HEAD https://svn.code.sf.net/p/vcmi/code/tags/0.95 vcmi-0.9.5-1
|
||||
# tar -cJf vcmi-0.9.5-1.tar.xz vcmi-0.9.5-1
|
||||
Source: vcmi-0.9.5-1.tar.xz
|
||||
|
||||
|
@ -824,7 +824,7 @@ void CGameHandler::applyBattleEffects(BattleAttack &bat, const CStack *att, cons
|
||||
bsa.attackerID = att->ID;
|
||||
bsa.stackAttacked = def->ID;
|
||||
bsa.damageAmount = gs->curB->calculateDmg(att, def, gs->curB->battleGetOwner(att), gs->curB->battleGetOwner(def), bat.shot(), distance, bat.lucky(), bat.unlucky(), bat.deathBlow(), bat.ballistaDoubleDmg());
|
||||
def->prepareAttacked(bsa); //calculate casualties
|
||||
def->prepareAttacked(bsa, gameState()->getRandomGenerator()); //calculate casualties
|
||||
|
||||
//life drain handling
|
||||
if (att->hasBonusOfType(Bonus::LIFE_DRAIN) && def->isLiving())
|
||||
@ -858,7 +858,7 @@ void CGameHandler::applyBattleEffects(BattleAttack &bat, const CStack *att, cons
|
||||
bsa2.effect = 11;
|
||||
|
||||
bsa2.damageAmount = (bsa.damageAmount * def->valOfBonuses(Bonus::FIRE_SHIELD)) / 100; //TODO: scale with attack/defense
|
||||
att->prepareAttacked(bsa2);
|
||||
att->prepareAttacked(bsa2, gameState()->getRandomGenerator());
|
||||
bat.bsa.push_back(bsa2);
|
||||
}
|
||||
}
|
||||
@ -1079,9 +1079,10 @@ CGameHandler::~CGameHandler(void)
|
||||
|
||||
void CGameHandler::init(StartInfo *si)
|
||||
{
|
||||
//extern DLL_LINKAGE std::minstd_rand ran;
|
||||
if(!si->seedToBeUsed)
|
||||
if(si->seedToBeUsed == 0)
|
||||
{
|
||||
si->seedToBeUsed = std::time(nullptr);
|
||||
}
|
||||
|
||||
gs = new CGameState();
|
||||
logGlobal->infoStream() << "Gamestate created!";
|
||||
@ -1089,8 +1090,10 @@ void CGameHandler::init(StartInfo *si)
|
||||
logGlobal->infoStream() << "Gamestate initialized!";
|
||||
|
||||
for(auto & elem : gs->players)
|
||||
{
|
||||
states.addPlayer(elem.first);
|
||||
}
|
||||
}
|
||||
|
||||
static bool evntCmp(const CMapEvent &a, const CMapEvent &b)
|
||||
{
|
||||
@ -1187,7 +1190,7 @@ void CGameHandler::newTurn()
|
||||
n.specialWeek = NewTurn::DOUBLE_GROWTH;
|
||||
if (VLC->modh->settings.ALL_CREATURES_GET_DOUBLE_MONTHS)
|
||||
{
|
||||
std::pair<int, CreatureID> newMonster(54, VLC->creh->pickRandomMonster([]{ return rand(); }));
|
||||
std::pair<int, CreatureID> newMonster(54, VLC->creh->pickRandomMonster(gs->getRandomGenerator()));
|
||||
n.creatureid = newMonster.second;
|
||||
}
|
||||
else if(VLC->creh->doubledCreatures.size())
|
||||
@ -1209,7 +1212,7 @@ void CGameHandler::newTurn()
|
||||
if (monthType < 25)
|
||||
{
|
||||
n.specialWeek = NewTurn::BONUS_GROWTH; //+5
|
||||
std::pair<int, CreatureID> newMonster(54, VLC->creh->pickRandomMonster([]{ return rand(); }));
|
||||
std::pair<int, CreatureID> newMonster(54, VLC->creh->pickRandomMonster(gs->getRandomGenerator()));
|
||||
//TODO do not pick neutrals
|
||||
n.creatureid = newMonster.second;
|
||||
}
|
||||
@ -1238,7 +1241,8 @@ void CGameHandler::newTurn()
|
||||
CHeroClass *banned = nullptr;
|
||||
for (int j = 0; j < GameConstants::AVAILABLE_HEROES_PER_PLAYER; j++)
|
||||
{
|
||||
if(CGHeroInstance *h = gs->hpool.pickHeroFor(j == 0, elem.first, getNativeTown(elem.first), pool, banned)) //first hero - native if possible, second hero -> any other class
|
||||
//first hero - native if possible, second hero -> any other class
|
||||
if(CGHeroInstance *h = gs->hpool.pickHeroFor(j == 0, elem.first, getNativeTown(elem.first), pool, gs->getRandomGenerator(), banned))
|
||||
{
|
||||
sah.hid[j] = h->subID;
|
||||
h->initArmy(&sah.army[j]);
|
||||
@ -3213,7 +3217,7 @@ bool CGameHandler::hireHero(const CGObjectInstance *obj, ui8 hid, PlayerColor pl
|
||||
const CGHeroInstance *theOtherHero = p->availableHeroes.at(!hid);
|
||||
const CGHeroInstance *newHero = nullptr;
|
||||
if (theOtherHero) //on XXL maps all heroes can be imprisoned :(
|
||||
newHero = gs->hpool.pickHeroFor(false, player, getNativeTown(player), pool, theOtherHero->type->heroClass);
|
||||
newHero = gs->hpool.pickHeroFor(false, player, getNativeTown(player), pool, gs->getRandomGenerator(), theOtherHero->type->heroClass);
|
||||
|
||||
SetAvailableHeroes sah;
|
||||
sah.player = player;
|
||||
@ -4120,7 +4124,7 @@ void CGameHandler::handleSpellCasting( SpellID spellID, int spellLvl, BattleHex
|
||||
bsa.attackerID = stack->ID;
|
||||
else
|
||||
bsa.attackerID = -1;
|
||||
(attackedCre)->prepareAttacked(bsa);
|
||||
(attackedCre)->prepareAttacked(bsa, gs->getRandomGenerator());
|
||||
si.stacks.push_back(bsa);
|
||||
|
||||
if (spellID == SpellID::CHAIN_LIGHTNING)
|
||||
@ -4419,7 +4423,7 @@ void CGameHandler::handleSpellCasting( SpellID spellID, int spellLvl, BattleHex
|
||||
bsa.damageAmount = usedSpellPower * (attackedCre)->valOfBonuses(Bonus::STACK_HEALTH);
|
||||
bsa.stackAttacked = (attackedCre)->ID;
|
||||
bsa.attackerID = -1;
|
||||
(attackedCre)->prepareAttacked(bsa);
|
||||
(attackedCre)->prepareAttacked(bsa, gameState()->getRandomGenerator());
|
||||
si.stacks.push_back(bsa);
|
||||
}
|
||||
}
|
||||
@ -4434,7 +4438,7 @@ void CGameHandler::handleSpellCasting( SpellID spellID, int spellLvl, BattleHex
|
||||
bsa.damageAmount = usedSpellPower; //damage times the number of attackers
|
||||
bsa.stackAttacked = (attackedCre)->ID;
|
||||
bsa.attackerID = -1;
|
||||
(attackedCre)->prepareAttacked(bsa);
|
||||
(attackedCre)->prepareAttacked(bsa, gameState()->getRandomGenerator());
|
||||
si.stacks.push_back(bsa);
|
||||
}
|
||||
}
|
||||
@ -4751,7 +4755,7 @@ void CGameHandler::handleDamageFromObstacle(const CObstacleInstance &obstacle, c
|
||||
bsa.damageAmount = damage;
|
||||
bsa.stackAttacked = curStack->ID;
|
||||
bsa.attackerID = -1;
|
||||
curStack->prepareAttacked(bsa);
|
||||
curStack->prepareAttacked(bsa, gameState()->getRandomGenerator());
|
||||
|
||||
StacksInjured si;
|
||||
si.stacks.push_back(bsa);
|
||||
|
Loading…
Reference in New Issue
Block a user