mirror of
				https://github.com/vcmi/vcmi.git
				synced 2025-10-31 00:07:39 +02:00 
			
		
		
		
	Remove usage of std::function from CRandomGenerator
This commit is contained in:
		| @@ -24,20 +24,17 @@ class HypotheticBattle; | ||||
| class RNGStub : public vstd::RNG | ||||
| { | ||||
| public: | ||||
| 	vstd::TRandI64 getInt64Range(int64_t lower, int64_t upper) override | ||||
| 	int nextInt(int lower, int upper) override | ||||
| 	{ | ||||
| 		return [=]()->int64_t | ||||
| 		{ | ||||
| 			return (lower + upper)/2; | ||||
| 		}; | ||||
| 		return (lower + upper) / 2; | ||||
| 	} | ||||
|  | ||||
| 	vstd::TRand getDoubleRange(double lower, double upper) override | ||||
| 	int64_t nextInt64(int64_t lower, int64_t upper) override | ||||
| 	{ | ||||
| 		return [=]()->double | ||||
| 		{ | ||||
| 			return (lower + upper)/2; | ||||
| 		}; | ||||
| 		return (lower + upper) / 2; | ||||
| 	} | ||||
| 	double nextDouble(double lower, double upper) override | ||||
| 	{ | ||||
| 		return (lower + upper) / 2; | ||||
| 	} | ||||
| }; | ||||
|  | ||||
|   | ||||
| @@ -15,18 +15,14 @@ VCMI_LIB_NAMESPACE_BEGIN | ||||
| namespace vstd | ||||
| { | ||||
|  | ||||
| using TRandI64 = std::function<int64_t()>; | ||||
| using TRand = std::function<double()>; | ||||
|  | ||||
| class DLL_LINKAGE RNG | ||||
| { | ||||
| public: | ||||
|  | ||||
| 	virtual ~RNG() = default; | ||||
|  | ||||
| 	virtual TRandI64 getInt64Range(int64_t lower, int64_t upper) = 0; | ||||
|  | ||||
| 	virtual TRand getDoubleRange(double lower, double upper) = 0; | ||||
| 	virtual int nextInt(int lower, int upper) = 0; | ||||
| 	virtual int64_t nextInt64(int64_t lower, int64_t upper) = 0; | ||||
| 	virtual double nextDouble(double lower, double upper) = 0; | ||||
| }; | ||||
|  | ||||
| } | ||||
| @@ -39,7 +35,7 @@ namespace RandomGeneratorUtil | ||||
| 		if(container.empty()) | ||||
| 			throw std::runtime_error("Unable to select random item from empty container!"); | ||||
|  | ||||
| 		return std::next(container.begin(), rand.getInt64Range(0, container.size() - 1)()); | ||||
| 		return std::next(container.begin(), rand.nextInt64(0, container.size() - 1)); | ||||
| 	} | ||||
|  | ||||
| 	template<typename Container> | ||||
| @@ -48,7 +44,7 @@ namespace RandomGeneratorUtil | ||||
| 		if(container.empty()) | ||||
| 			throw std::runtime_error("Unable to select random item from empty container!"); | ||||
|  | ||||
| 		return std::next(container.begin(), rand.getInt64Range(0, container.size() - 1)()); | ||||
| 		return std::next(container.begin(), rand.nextInt64(0, container.size() - 1)); | ||||
| 	} | ||||
|  | ||||
| 	template<typename Container> | ||||
| @@ -59,7 +55,7 @@ namespace RandomGeneratorUtil | ||||
| 		int64_t totalWeight = std::accumulate(container.begin(), container.end(), 0); | ||||
| 		assert(totalWeight > 0); | ||||
|  | ||||
| 		int64_t roll = rand.getInt64Range(0, totalWeight - 1)(); | ||||
| 		int64_t roll = rand.nextInt64(0, totalWeight - 1); | ||||
|  | ||||
| 		for (size_t i = 0; i < container.size(); ++i) | ||||
| 		{ | ||||
| @@ -77,7 +73,7 @@ namespace RandomGeneratorUtil | ||||
|  | ||||
| 		for(int64_t i = n-1; i>0; --i) | ||||
| 		{ | ||||
| 			std::swap(container.begin()[i],container.begin()[rand.getInt64Range(0, i)()]); | ||||
| 			std::swap(container.begin()[i],container.begin()[rand.nextInt64(0, i)]); | ||||
| 		} | ||||
| 	} | ||||
| } | ||||
|   | ||||
| @@ -35,28 +35,17 @@ void CRandomGenerator::resetSeed() | ||||
| 	setSeed(static_cast<int>(threadIdHash * std::time(nullptr))); | ||||
| } | ||||
|  | ||||
| TRandI CRandomGenerator::getIntRange(int lower, int upper) | ||||
| { | ||||
| 	if (lower <= upper) | ||||
| 		return std::bind(TIntDist(lower, upper), std::ref(rand)); | ||||
| 	throw std::runtime_error("Invalid range provided: " + std::to_string(lower) + " ... " + std::to_string(upper)); | ||||
| } | ||||
|  | ||||
| vstd::TRandI64 CRandomGenerator::getInt64Range(int64_t lower, int64_t upper) | ||||
| { | ||||
| 	if(lower <= upper) | ||||
| 		return std::bind(TInt64Dist(lower, upper), std::ref(rand)); | ||||
| 	throw std::runtime_error("Invalid range provided: " + std::to_string(lower) + " ... " + std::to_string(upper)); | ||||
| } | ||||
|  | ||||
| int CRandomGenerator::nextInt(int upper) | ||||
| { | ||||
| 	return getIntRange(0, upper)(); | ||||
| 	return nextInt(0, upper); | ||||
| } | ||||
|  | ||||
| int CRandomGenerator::nextInt(int lower, int upper) | ||||
| { | ||||
| 	return getIntRange(lower, upper)(); | ||||
| 	if (lower > upper) | ||||
| 		throw std::runtime_error("Invalid range provided: " + std::to_string(lower) + " ... " + std::to_string(upper)); | ||||
|  | ||||
| 	return TIntDist(lower, upper)(rand); | ||||
| } | ||||
|  | ||||
| int CRandomGenerator::nextInt() | ||||
| @@ -64,28 +53,31 @@ int CRandomGenerator::nextInt() | ||||
| 	return TIntDist()(rand); | ||||
| } | ||||
|  | ||||
| vstd::TRand CRandomGenerator::getDoubleRange(double lower, double upper) | ||||
| int64_t CRandomGenerator::nextInt64(int64_t lower, int64_t upper) | ||||
| { | ||||
| 	if(lower <= upper) | ||||
| 		return std::bind(TRealDist(lower, upper), std::ref(rand)); | ||||
| 	throw std::runtime_error("Invalid range provided: " + std::to_string(lower) + " ... " + std::to_string(upper)); | ||||
| 	if (lower > upper) | ||||
| 		throw std::runtime_error("Invalid range provided: " + std::to_string(lower) + " ... " + std::to_string(upper)); | ||||
|  | ||||
| 	return TInt64Dist(lower, upper)(rand); | ||||
| } | ||||
|  | ||||
| double CRandomGenerator::nextDouble(double upper) | ||||
| { | ||||
| 	return getDoubleRange(0, upper)(); | ||||
| 	return nextDouble(0, upper); | ||||
| } | ||||
|  | ||||
| double CRandomGenerator::nextDouble(double lower, double upper) | ||||
| { | ||||
| 	return getDoubleRange(lower, upper)(); | ||||
| 	if(lower > upper) | ||||
| 		throw std::runtime_error("Invalid range provided: " + std::to_string(lower) + " ... " + std::to_string(upper)); | ||||
|  | ||||
| 	return TRealDist(lower, upper)(rand); | ||||
| } | ||||
|  | ||||
| double CRandomGenerator::nextDouble() | ||||
| { | ||||
| 	return TRealDist()(rand); | ||||
| } | ||||
| //double CRandomGenerator::nextDouble() | ||||
| //{ | ||||
| //	return TRealDist()(rand); | ||||
| //} | ||||
|  | ||||
| CRandomGenerator & CRandomGenerator::getDefault() | ||||
| { | ||||
|   | ||||
| @@ -15,6 +15,7 @@ | ||||
|  | ||||
| VCMI_LIB_NAMESPACE_BEGIN | ||||
|  | ||||
|  | ||||
| /// Generator to use for all randomization in game | ||||
| /// minstd_rand is selected due to following reasons: | ||||
| /// 1. Its randomization quality is below mt_19937 however this is unlikely to be noticeable in game | ||||
| @@ -23,12 +24,11 @@ using TGenerator = std::minstd_rand; | ||||
| using TIntDist = std::uniform_int_distribution<int>; | ||||
| using TInt64Dist = std::uniform_int_distribution<int64_t>; | ||||
| using TRealDist = std::uniform_real_distribution<double>; | ||||
| using TRandI = std::function<int()>; | ||||
|  | ||||
| /// 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. An instance of this RNG is not thread safe. | ||||
| class DLL_LINKAGE CRandomGenerator : public vstd::RNG, boost::noncopyable, public Serializeable | ||||
| class DLL_LINKAGE CRandomGenerator final : public vstd::RNG, boost::noncopyable, public Serializeable | ||||
| { | ||||
| public: | ||||
| 	/// Seeds the generator by default with the product of the current time in milliseconds and the | ||||
| @@ -44,37 +44,23 @@ public: | ||||
| 	/// current thread ID. | ||||
| 	void resetSeed(); | ||||
|  | ||||
| 	/// Generate several integer numbers within the same range. | ||||
| 	/// e.g.: auto a = gen.getIntRange(0,10); a(); a(); a(); | ||||
| 	/// requires: lower <= upper | ||||
| 	TRandI getIntRange(int lower, int upper); | ||||
|  | ||||
| 	vstd::TRandI64 getInt64Range(int64_t lower, int64_t upper) override; | ||||
|  | ||||
| 	/// Generates an integer between 0 and upper. | ||||
| 	/// requires: 0 <= upper | ||||
| 	int nextInt(int upper); | ||||
|  | ||||
| 	/// requires: lower <= upper | ||||
| 	int nextInt(int lower, int upper); | ||||
| 	int nextInt(int lower, int upper) override; | ||||
| 	int64_t nextInt64(int64_t lower, int64_t upper) override; | ||||
|  | ||||
| 	/// Generates an integer between 0 and the maximum value it can hold. | ||||
| 	int nextInt(); | ||||
|  | ||||
| 	/// Generate several double/real numbers within the same range. | ||||
| 	/// e.g.: auto a = gen.getDoubleRange(4.5,10.2); a(); a(); a(); | ||||
| 	/// requires: lower <= upper | ||||
| 	vstd::TRand getDoubleRange(double lower, double upper) override; | ||||
|  | ||||
| 	/// Generates a double between 0 and upper. | ||||
| 	/// requires: 0 <= upper | ||||
| 	double nextDouble(double upper); | ||||
|  | ||||
| 	/// requires: lower <= upper | ||||
| 	double nextDouble(double lower, double upper); | ||||
|  | ||||
| 	/// Generates a double between 0.0 and 1.0. | ||||
| 	double nextDouble(); | ||||
| 	double nextDouble(double lower, double upper) override; | ||||
|  | ||||
| 	/// Gets a globally accessible RNG which will be constructed once per thread. For the | ||||
| 	/// seed a combination of the thread ID and current time in milliseconds will be used. | ||||
|   | ||||
| @@ -212,11 +212,9 @@ void CStack::prepareAttacked(BattleStackAttacked & bsa, vstd::RNG & rand, const | ||||
|  | ||||
| 			auto resurrectedAdd = static_cast<int32_t>(baseAmount - (resurrectedCount / resurrectFactor)); | ||||
|  | ||||
| 			auto rangeGen = rand.getInt64Range(0, 99); | ||||
|  | ||||
| 			for(int32_t i = 0; i < resurrectedAdd; i++) | ||||
| 			{ | ||||
| 				if(resurrectValue > rangeGen()) | ||||
| 				if(resurrectValue > rand.nextInt(0, 99)) | ||||
| 					resurrectedCount += 1; | ||||
| 			} | ||||
|  | ||||
|   | ||||
| @@ -662,10 +662,9 @@ int64_t BattleInfo::getActualDamage(const DamageRange & damage, int32_t attacker | ||||
| 		int64_t sum = 0; | ||||
|  | ||||
| 		auto howManyToAv = std::min<int32_t>(10, attackerCount); | ||||
| 		auto rangeGen = rng.getInt64Range(damage.min, damage.max); | ||||
|  | ||||
| 		for(int32_t g = 0; g < howManyToAv; ++g) | ||||
| 			sum += rangeGen(); | ||||
| 			sum += rng.nextInt64(damage.min, damage.max); | ||||
|  | ||||
| 		return sum / howManyToAv; | ||||
| 	} | ||||
|   | ||||
| @@ -63,7 +63,7 @@ VCMI_LIB_NAMESPACE_BEGIN | ||||
| 		{ | ||||
| 			const auto & vector = value.Vector(); | ||||
|  | ||||
| 			size_t index= rng.getIntRange(0, vector.size()-1)(); | ||||
| 			size_t index= rng.nextInt64(0, vector.size()-1); | ||||
| 			return loadValue(vector[index], rng, variables, 0); | ||||
| 		} | ||||
| 		if(value.isStruct()) | ||||
| @@ -72,7 +72,7 @@ VCMI_LIB_NAMESPACE_BEGIN | ||||
| 				return loadValue(value["amount"], rng, variables, defaultValue); | ||||
| 			si32 min = loadValue(value["min"], rng, variables, 0); | ||||
| 			si32 max = loadValue(value["max"], rng, variables, 0); | ||||
| 			return rng.getIntRange(min, max)(); | ||||
| 			return rng.nextInt64(min, max); | ||||
| 		} | ||||
| 		return defaultValue; | ||||
| 	} | ||||
|   | ||||
| @@ -298,7 +298,7 @@ void Rewardable::Info::configureRewards( | ||||
| 			{ | ||||
| 				const JsonNode & preset = object.getPresetVariable("dice", diceID); | ||||
| 				if (preset.isNull()) | ||||
| 					object.initVariable("dice", diceID, rng.getIntRange(0, 99)()); | ||||
| 					object.initVariable("dice", diceID, rng.nextInt(0, 99)); | ||||
| 				else | ||||
| 					object.initVariable("dice", diceID, preset.Integer()); | ||||
|  | ||||
|   | ||||
| @@ -444,7 +444,7 @@ void ConnectionsPlacer::collectNeighbourZones() | ||||
| bool ConnectionsPlacer::shouldGenerateRoad(const rmg::ZoneConnection& connection) const | ||||
| { | ||||
| 	return connection.getRoadOption() == rmg::ERoadOption::ROAD_TRUE || | ||||
| 		(connection.getRoadOption() == rmg::ERoadOption::ROAD_RANDOM && zone.getRand().nextDouble() >= 0.5f); | ||||
| 		(connection.getRoadOption() == rmg::ERoadOption::ROAD_RANDOM && zone.getRand().nextDouble(0, 1) >= 0.5f); | ||||
| } | ||||
|  | ||||
| void ConnectionsPlacer::createBorder() | ||||
|   | ||||
| @@ -187,7 +187,7 @@ ESpellCastResult SummonBoatMechanics::applyAdventureEffects(SpellCastEnvironment | ||||
| 	const auto schoolLevel = parameters.caster->getSpellSchoolLevel(owner); | ||||
|  | ||||
| 	//check if spell works at all | ||||
| 	if(env->getRNG()->getInt64Range(0, 99)() >= owner->getLevelPower(schoolLevel)) //power is % chance of success | ||||
| 	if(env->getRNG()->nextInt(0, 99) >= owner->getLevelPower(schoolLevel)) //power is % chance of success | ||||
| 	{ | ||||
| 		InfoWindow iw; | ||||
| 		iw.player = parameters.caster->getCasterOwner(); | ||||
| @@ -280,7 +280,7 @@ ESpellCastResult ScuttleBoatMechanics::applyAdventureEffects(SpellCastEnvironmen | ||||
| { | ||||
| 	const auto schoolLevel = parameters.caster->getSpellSchoolLevel(owner); | ||||
| 	//check if spell works at all | ||||
| 	if(env->getRNG()->getInt64Range(0, 99)() >= owner->getLevelPower(schoolLevel)) //power is % chance of success | ||||
| 	if(env->getRNG()->nextInt(0, 99) >= owner->getLevelPower(schoolLevel)) //power is % chance of success | ||||
| 	{ | ||||
| 		InfoWindow iw; | ||||
| 		iw.player = parameters.caster->getCasterOwner(); | ||||
|   | ||||
| @@ -377,15 +377,13 @@ void BattleSpellMechanics::beforeCast(BattleSpellCast & sc, vstd::RNG & rng, con | ||||
|  | ||||
| 	std::vector <const battle::Unit *> resisted; | ||||
|  | ||||
| 	auto rangeGen = rng.getInt64Range(0, 99); | ||||
|  | ||||
| 	auto filterResisted = [&, this](const battle::Unit * unit) -> bool | ||||
| 	{ | ||||
| 		if(isNegativeSpell() && isMagicalEffect()) | ||||
| 		{ | ||||
| 			//magic resistance | ||||
| 			const int prob = std::min(unit->magicResistance(), 100); //probability of resistance in % | ||||
| 			if(rangeGen() < prob) | ||||
| 			if(rng.nextInt(0, 99) < prob) | ||||
| 				return true; | ||||
| 		} | ||||
| 		return false; | ||||
|   | ||||
| @@ -268,11 +268,9 @@ void BattleCast::cast(ServerCallback * server, Target target) | ||||
| 		const std::string magicMirrorCacheStr = "type_MAGIC_MIRROR"; | ||||
| 		static const auto magicMirrorSelector = Selector::type()(BonusType::MAGIC_MIRROR); | ||||
|  | ||||
| 		auto rangeGen = server->getRNG()->getInt64Range(0, 99); | ||||
|  | ||||
| 		const int mirrorChance = mainTarget->valOfBonuses(magicMirrorSelector, magicMirrorCacheStr); | ||||
|  | ||||
| 		if(rangeGen() < mirrorChance) | ||||
| 		if(server->getRNG()->nextInt(0, 99) < mirrorChance) | ||||
| 		{ | ||||
| 			auto mirrorTargets = cb->battleGetUnitsIf([this](const battle::Unit * unit) | ||||
| 			{ | ||||
|   | ||||
| @@ -118,7 +118,7 @@ void Catapult::applyTargeted(ServerCallback * server, const Mechanics * m, const | ||||
| 		auto actualTarget = EWallPart::INVALID; | ||||
|  | ||||
| 		if ( m->battle()->isWallPartAttackable(desiredTarget) && | ||||
| 				server->getRNG()->getInt64Range(0, 99)() < getCatapultHitChance(desiredTarget)) | ||||
| 				server->getRNG()->nextInt(0, 99) < getCatapultHitChance(desiredTarget)) | ||||
| 		{ | ||||
| 			actualTarget = desiredTarget; | ||||
| 		} | ||||
| @@ -172,7 +172,7 @@ int Catapult::getRandomDamage (ServerCallback * server) const | ||||
| { | ||||
| 	std::array<int, 3> damageChances = { noDmg, hit, crit }; //dmgChance[i] - chance for doing i dmg when hit is successful | ||||
| 	int totalChance = std::accumulate(damageChances.begin(), damageChances.end(), 0); | ||||
| 	int damageRandom = server->getRNG()->getInt64Range(0, totalChance - 1)(); | ||||
| 	int damageRandom = server->getRNG()->nextInt(0, totalChance - 1); | ||||
| 	int dealtDamage = 0; | ||||
|  | ||||
| 	//calculating dealt damage | ||||
|   | ||||
| @@ -1341,7 +1341,7 @@ void BattleActionProcessor::handleAfterAttackCasting(const CBattleInfoCallback & | ||||
| 		double chanceToTrigger = attacker->valOfBonuses(BonusType::TRANSMUTATION) / 100.0f; | ||||
| 		vstd::amin(chanceToTrigger, 1); //cap at 100% | ||||
|  | ||||
| 		if(gameHandler->getRandomGenerator().getDoubleRange(0, 1)() > chanceToTrigger) | ||||
| 		if(gameHandler->getRandomGenerator().nextDouble(0, 1) > chanceToTrigger) | ||||
| 			return; | ||||
|  | ||||
| 		int bonusAdditionalInfo = attacker->getBonus(Selector::type()(BonusType::TRANSMUTATION))->additionalInfo[0]; | ||||
| @@ -1405,7 +1405,7 @@ void BattleActionProcessor::handleAfterAttackCasting(const CBattleInfoCallback & | ||||
|  | ||||
| 		vstd::amin(chanceToTrigger, 1); //cap trigger chance at 100% | ||||
|  | ||||
| 		if(gameHandler->getRandomGenerator().getDoubleRange(0, 1)() > chanceToTrigger) | ||||
| 		if(gameHandler->getRandomGenerator().nextDouble(0, 1) > chanceToTrigger) | ||||
| 			return; | ||||
|  | ||||
| 		BattleStackAttacked bsa; | ||||
|   | ||||
| @@ -18,8 +18,9 @@ namespace vstd | ||||
| class RNGMock : public RNG | ||||
| { | ||||
| public: | ||||
| 	MOCK_METHOD2(getInt64Range, TRandI64(int64_t, int64_t)); | ||||
| 	MOCK_METHOD2(getDoubleRange, TRand(double, double)); | ||||
| 	MOCK_METHOD2(nextInt, int(int lower, int upper)); | ||||
| 	MOCK_METHOD2(nextInt64, int64_t(int64_t lower, int64_t upper)); | ||||
| 	MOCK_METHOD2(nextDouble, double(double lower, double upper)); | ||||
| }; | ||||
|  | ||||
| } | ||||
|   | ||||
| @@ -101,27 +101,21 @@ void EffectFixture::setUp() | ||||
| 	ON_CALL(serverMock, apply(Matcher<CatapultAttack *>(_))).WillByDefault(Invoke(battleFake.get(),  &battle::BattleFake::accept<CatapultAttack>)); | ||||
| } | ||||
|  | ||||
| static vstd::TRandI64 getInt64RangeDef(int64_t lower, int64_t upper) | ||||
| static int64_t getInt64Range(int64_t lower, int64_t upper) | ||||
| { | ||||
| 	return [=]()->int64_t | ||||
| 	{ | ||||
| 		return (lower + upper)/2; | ||||
| 	}; | ||||
| 	return (lower + upper)/2; | ||||
| } | ||||
|  | ||||
| static vstd::TRand getDoubleRangeDef(double lower, double upper) | ||||
| static double getDoubleRange(double lower, double upper) | ||||
| { | ||||
| 	return [=]()->double | ||||
| 	{ | ||||
| 		return (lower + upper)/2; | ||||
| 	}; | ||||
| 	return (lower + upper)/2; | ||||
| } | ||||
|  | ||||
| void EffectFixture::setupDefaultRNG() | ||||
| { | ||||
| 	EXPECT_CALL(serverMock, getRNG()).Times(AtLeast(0)); | ||||
| 	EXPECT_CALL(rngMock, getInt64Range(_,_)).WillRepeatedly(Invoke(&getInt64RangeDef)); | ||||
| 	EXPECT_CALL(rngMock, getDoubleRange(_,_)).WillRepeatedly(Invoke(&getDoubleRangeDef)); | ||||
| 	EXPECT_CALL(rngMock, nextInt64(_,_)).WillRepeatedly(Invoke(&getInt64Range)); | ||||
| 	EXPECT_CALL(rngMock, nextDouble(_,_)).WillRepeatedly(Invoke(&getDoubleRange)); | ||||
| } | ||||
|  | ||||
| } | ||||
|   | ||||
		Reference in New Issue
	
	Block a user