1
0
mirror of https://github.com/vcmi/vcmi.git synced 2025-06-15 00:05:02 +02:00

Refactoring: only use RNGs explicitly to avoid bug prone code in future

Now server-side code should always use CRandomGenerator::getDefault which is serialized in GH.
CGameState::getRandomGenerator should be only used from GS code and CPackForClient-based applyGs.
This commit is contained in:
Arseniy Shestakov
2016-09-09 20:30:36 +03:00
parent 70abae9b51
commit c8faca8f39
28 changed files with 225 additions and 219 deletions

View File

@ -201,7 +201,7 @@ void CGCreature::onHeroVisit( const CGHeroInstance * h ) const
}
void CGCreature::initObj()
void CGCreature::initObj(CRandomGenerator & rand)
{
blockVisit = true;
switch(character)
@ -210,13 +210,13 @@ void CGCreature::initObj()
character = -4;
break;
case 1:
character = cb->gameState()->getRandomGenerator().nextInt(1, 7);
character = rand.nextInt(1, 7);
break;
case 2:
character = cb->gameState()->getRandomGenerator().nextInt(1, 10);
character = rand.nextInt(1, 10);
break;
case 3:
character = cb->gameState()->getRandomGenerator().nextInt(4, 10);
character = rand.nextInt(4, 10);
break;
case 4:
character = 10;
@ -228,7 +228,7 @@ void CGCreature::initObj()
CCreature &c = *VLC->creh->creatures[subID];
if(amount == 0)
{
amount = cb->gameState()->getRandomGenerator().nextInt(c.ammMin, c.ammMax);
amount = rand.nextInt(c.ammMin, c.ammMax);
if(amount == 0) //armies with 0 creatures are illegal
{
@ -241,7 +241,7 @@ void CGCreature::initObj()
refusedJoining = false;
}
void CGCreature::newTurn() const
void CGCreature::newTurn(CRandomGenerator & rand) const
{//Works only for stacks of single type of size up to 2 millions
if (!notGrowingTeam)
{
@ -434,7 +434,7 @@ void CGCreature::fight( const CGHeroInstance *h ) const
const auto & upgrades = getStack(slotID).type->upgrades;
if(!upgrades.empty())
{
auto it = RandomGeneratorUtil::nextItem(upgrades, cb->getRandomGenerator());
auto it = RandomGeneratorUtil::nextItem(upgrades, CRandomGenerator::getDefault());
cb->changeStackType(StackLocation(this, slotID), VLC->creh->creatures[*it]);
}
}
@ -676,7 +676,7 @@ void CGMine::onHeroVisit( const CGHeroInstance * h ) const
}
void CGMine::newTurn() const
void CGMine::newTurn(CRandomGenerator & rand) const
{
if(cb->getDate() == 1)
return;
@ -687,12 +687,12 @@ void CGMine::newTurn() const
cb->giveResource(tempOwner, producedResource, producedQuantity);
}
void CGMine::initObj()
void CGMine::initObj(CRandomGenerator & rand)
{
if(isAbandoned())
{
//set guardians
int howManyTroglodytes = cb->gameState()->getRandomGenerator().nextInt(100, 199);
int howManyTroglodytes = rand.nextInt(100, 199);
auto troglodytes = new CStackInstance(CreatureID::TROGLODYTES, howManyTroglodytes);
putStack(SlotID(0), troglodytes);
@ -703,7 +703,7 @@ void CGMine::initObj()
possibleResources.push_back(static_cast<Res::ERes>(i));
assert(!possibleResources.empty());
producedResource = *RandomGeneratorUtil::nextItem(possibleResources, cb->gameState()->getRandomGenerator());
producedResource = *RandomGeneratorUtil::nextItem(possibleResources, rand);
tempOwner = PlayerColor::NEUTRAL;
}
else
@ -859,7 +859,7 @@ CGResource::CGResource()
amount = 0;
}
void CGResource::initObj()
void CGResource::initObj(CRandomGenerator & rand)
{
blockVisit = true;
@ -868,13 +868,13 @@ void CGResource::initObj()
switch(subID)
{
case 6:
amount = cb->gameState()->getRandomGenerator().nextInt(500, 1000);
amount = rand.nextInt(500, 1000);
break;
case 0: case 2:
amount = cb->gameState()->getRandomGenerator().nextInt(6, 10);
amount = rand.nextInt(6, 10);
break;
default:
amount = cb->gameState()->getRandomGenerator().nextInt(3, 5);
amount = rand.nextInt(3, 5);
break;
}
}
@ -987,7 +987,7 @@ ObjectInstanceID CGTeleport::getRandomExit(const CGHeroInstance * h) const
{
auto passableExits = getPassableExits(cb->gameState(), h, getAllExits(true));
if(passableExits.size())
return *RandomGeneratorUtil::nextItem(passableExits, cb->getRandomGenerator());
return *RandomGeneratorUtil::nextItem(passableExits, CRandomGenerator::getDefault());
return ObjectInstanceID();
}
@ -1119,7 +1119,7 @@ void CGMonolith::teleportDialogAnswered(const CGHeroInstance *hero, ui32 answer,
cb->moveHero(hero->id, dPos, true);
}
void CGMonolith::initObj()
void CGMonolith::initObj(CRandomGenerator & rand)
{
std::vector<Obj> IDs;
IDs.push_back(ID);
@ -1164,7 +1164,7 @@ void CGSubterraneanGate::onHeroVisit( const CGHeroInstance * h ) const
cb->showTeleportDialog(&td);
}
void CGSubterraneanGate::initObj()
void CGSubterraneanGate::initObj(CRandomGenerator & rand)
{
type = BOTH;
}
@ -1283,7 +1283,7 @@ void CGWhirlpool::teleportDialogAnswered(const CGHeroInstance *hero, ui32 answer
{
auto obj = cb->getObj(getRandomExit(hero));
std::set<int3> tiles = obj->getBlockedPos();
dPos = CGHeroInstance::convertPosition(*RandomGeneratorUtil::nextItem(tiles, cb->getRandomGenerator()), true);
dPos = CGHeroInstance::convertPosition(*RandomGeneratorUtil::nextItem(tiles, CRandomGenerator::getDefault()), true);
}
cb->moveHero(hero->id, dPos, true);
@ -1299,7 +1299,7 @@ bool CGWhirlpool::isProtected(const CGHeroInstance * h)
return false;
}
void CGArtifact::initObj()
void CGArtifact::initObj(CRandomGenerator & rand)
{
blockVisit = true;
if(ID == Obj::ARTIFACT)
@ -1441,14 +1441,14 @@ void CGArtifact::serializeJsonOptions(JsonSerializeFormat& handler)
}
}
void CGWitchHut::initObj()
void CGWitchHut::initObj(CRandomGenerator & rand)
{
if (allowedAbilities.empty()) //this can happen for RMG. regular maps load abilities from map file
{
for (int i = 0; i < GameConstants::SKILL_QUANTITY; i++)
allowedAbilities.push_back(i);
}
ability = *RandomGeneratorUtil::nextItem(allowedAbilities, cb->gameState()->getRandomGenerator());
ability = *RandomGeneratorUtil::nextItem(allowedAbilities, rand);
}
void CGWitchHut::onHeroVisit( const CGHeroInstance * h ) const
@ -1627,7 +1627,7 @@ void CGShrine::onHeroVisit( const CGHeroInstance * h ) const
cb->showInfoDialog(&iw);
}
void CGShrine::initObj()
void CGShrine::initObj(CRandomGenerator & rand)
{
if(spell == SpellID::NONE) //spell not set
{
@ -1641,7 +1641,7 @@ void CGShrine::initObj()
return;
}
spell = *RandomGeneratorUtil::nextItem(possibilities, cb->gameState()->getRandomGenerator());
spell = *RandomGeneratorUtil::nextItem(possibilities, rand);
}
}
@ -1669,12 +1669,12 @@ void CGShrine::serializeJsonOptions(JsonSerializeFormat& handler)
handler.serializeId("spell", &CSpellHandler::decodeSpell, &CSpellHandler::encodeSpell, SpellID(SpellID::NONE), spell);
}
void CGSignBottle::initObj()
void CGSignBottle::initObj(CRandomGenerator & rand)
{
//if no text is set than we pick random from the predefined ones
if(message.empty())
{
message = *RandomGeneratorUtil::nextItem(VLC->generaltexth->randsign, cb->gameState()->getRandomGenerator());
message = *RandomGeneratorUtil::nextItem(VLC->generaltexth->randsign, rand);
}
if(ID == Obj::OCEAN_BOTTLE)
@ -1714,7 +1714,7 @@ 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 = cb->getRandomGenerator().nextInt(GameConstants::PRIMARY_SKILLS - 1);
bid = CRandomGenerator::getDefault().nextInt(GameConstants::PRIMARY_SKILLS - 1);
}
InfoWindow iw;
@ -1749,25 +1749,25 @@ void CGScholar::onHeroVisit( const CGHeroInstance * h ) const
cb->removeObject(this);
}
void CGScholar::initObj()
void CGScholar::initObj(CRandomGenerator & rand)
{
blockVisit = true;
if(bonusType == RANDOM)
{
bonusType = static_cast<EBonusType>(cb->gameState()->getRandomGenerator().nextInt(2));
bonusType = static_cast<EBonusType>(rand.nextInt(2));
switch(bonusType)
{
case PRIM_SKILL:
bonusID = cb->gameState()->getRandomGenerator().nextInt(GameConstants::PRIMARY_SKILLS -1);
bonusID = rand.nextInt(GameConstants::PRIMARY_SKILLS -1);
break;
case SECONDARY_SKILL:
bonusID = cb->gameState()->getRandomGenerator().nextInt(GameConstants::SKILL_QUANTITY -1);
bonusID = rand.nextInt(GameConstants::SKILL_QUANTITY -1);
break;
case SPELL:
std::vector<SpellID> possibilities;
for (int i = 1; i < 6; ++i)
cb->getAllowedSpells (possibilities, i);
bonusID = *RandomGeneratorUtil::nextItem(possibilities, cb->gameState()->getRandomGenerator());
bonusID = *RandomGeneratorUtil::nextItem(possibilities, rand);
break;
}
}
@ -1874,7 +1874,7 @@ void CGMagi::reset()
eyelist.clear();
}
void CGMagi::initObj()
void CGMagi::initObj(CRandomGenerator & rand)
{
if (ID == Obj::EYE_OF_MAGI)
{
@ -1920,12 +1920,12 @@ void CGMagi::onHeroVisit(const CGHeroInstance * h) const
}
}
void CGBoat::initObj()
void CGBoat::initObj(CRandomGenerator & rand)
{
hero = nullptr;
}
void CGSirens::initObj()
void CGSirens::initObj(CRandomGenerator & rand)
{
blockVisit = true;
}
@ -2111,7 +2111,7 @@ void CGObelisk::onHeroVisit( const CGHeroInstance * h ) const
}
void CGObelisk::initObj()
void CGObelisk::initObj(CRandomGenerator & rand)
{
obeliskCount++;
}
@ -2172,7 +2172,7 @@ void CGLighthouse::onHeroVisit( const CGHeroInstance * h ) const
}
}
void CGLighthouse::initObj()
void CGLighthouse::initObj(CRandomGenerator & rand)
{
if(tempOwner < PlayerColor::PLAYER_LIMIT)
{