[Scummvm-git-logs] scummvm master -> 2851bd0faf3996a637d17838762d0cfc4b2662fd

OMGPizzaGuy noreply at scummvm.org
Mon Jan 9 03:40:40 UTC 2023


This automated email contains information about 1 new commit which have been
pushed to the 'scummvm' repo located at https://github.com/scummvm/scummvm .

Summary:
2851bd0faf ULTIMA8: Cleanup use of random number generation


Commit: 2851bd0faf3996a637d17838762d0cfc4b2662fd
    https://github.com/scummvm/scummvm/commit/2851bd0faf3996a637d17838762d0cfc4b2662fd
Author: Matthew Jimenez (matthew.jimenez at outlook.com)
Date: 2023-01-08T21:40:11-06:00

Commit Message:
ULTIMA8: Cleanup use of random number generation
This change may address #12182 & improves consistency and prossibly performance around RNG

Changed paths:
    engines/ultima/ultima8/graphics/cycle_process.cpp
    engines/ultima/ultima8/gumps/container_gump.cpp
    engines/ultima/ultima8/gumps/game_map_gump.cpp
    engines/ultima/ultima8/gumps/weasel_gump.cpp
    engines/ultima/ultima8/kernel/kernel.cpp
    engines/ultima/ultima8/kernel/kernel.h
    engines/ultima/ultima8/ultima8.h
    engines/ultima/ultima8/usecode/uc_machine.cpp
    engines/ultima/ultima8/world/actors/actor.cpp
    engines/ultima/ultima8/world/actors/actor_anim_process.cpp
    engines/ultima/ultima8/world/actors/actor_bark_notify_process.cpp
    engines/ultima/ultima8/world/actors/attack_process.cpp
    engines/ultima/ultima8/world/actors/combat_process.cpp
    engines/ultima/ultima8/world/actors/cru_pathfinder_process.cpp
    engines/ultima/ultima8/world/actors/grant_peace_process.cpp
    engines/ultima/ultima8/world/actors/guard_process.cpp
    engines/ultima/ultima8/world/actors/loiter_process.cpp
    engines/ultima/ultima8/world/actors/main_actor.cpp
    engines/ultima/ultima8/world/actors/npc_dat.cpp
    engines/ultima/ultima8/world/actors/rolling_thunder_process.cpp
    engines/ultima/ultima8/world/actors/surrender_process.cpp
    engines/ultima/ultima8/world/actors/u8_avatar_mover_process.cpp
    engines/ultima/ultima8/world/bobo_boomer_process.cpp
    engines/ultima/ultima8/world/camera_process.cpp
    engines/ultima/ultima8/world/damage_info.cpp
    engines/ultima/ultima8/world/fire_type.cpp
    engines/ultima/ultima8/world/fireball_process.cpp
    engines/ultima/ultima8/world/gravity_process.cpp
    engines/ultima/ultima8/world/item.cpp
    engines/ultima/ultima8/world/super_sprite_process.cpp


diff --git a/engines/ultima/ultima8/graphics/cycle_process.cpp b/engines/ultima/ultima8/graphics/cycle_process.cpp
index e3e4a828532..c11f06b148d 100644
--- a/engines/ultima/ultima8/graphics/cycle_process.cpp
+++ b/engines/ultima/ultima8/graphics/cycle_process.cpp
@@ -20,7 +20,7 @@
  */
 
 #include "ultima/ultima8/graphics/cycle_process.h"
-#include "ultima/ultima8/kernel/kernel.h"
+#include "ultima/ultima8/ultima8.h"
 
 namespace Ultima {
 namespace Ultima8 {
@@ -106,14 +106,16 @@ void CycleProcess::run() {
 	// move color 1 -> color 7
 	copyColor(paldata + 3 * 7, tmpcol);
 
+	Common::RandomSource &rs = Ultima8Engine::get_instance()->getRandomSource();
+
 	// Step 2: Cycle 7 other colors 8~14 by increasing their value
 	// until they hit max, then reset.
 	for (int i = 0; i < 7; i++) {
 		bool wrapped = cycleColor(_cycleColData[i], CYCLE_COL_FLAGS[i]);
 		if (CYCLE_RANDOMIZE[i] && wrapped) {
-			_cycleColData[i][0] += (getRandom() % 10);
-			_cycleColData[i][1] += (getRandom() % 10);
-			_cycleColData[i][2] += (getRandom() % 10);
+			_cycleColData[i][0] += rs.getRandomNumber(9);
+			_cycleColData[i][1] += rs.getRandomNumber(9);
+			_cycleColData[i][2] += rs.getRandomNumber(9);
 		}
 		uint8 *dstptr = paldata + (i + 8) * 3;
 		copyColor(dstptr, _cycleColData[i]);
diff --git a/engines/ultima/ultima8/gumps/container_gump.cpp b/engines/ultima/ultima8/gumps/container_gump.cpp
index a21e6e19df1..1c04d7f11c6 100644
--- a/engines/ultima/ultima8/gumps/container_gump.cpp
+++ b/engines/ultima/ultima8/gumps/container_gump.cpp
@@ -90,8 +90,9 @@ void ContainerGump::getItemCoords(Item *item, int32 &itemx, int32 &itemy) {
 		// randomize position
 		// TODO: maybe try to put it somewhere where it doesn't overlap others?
 
-		itemx = getRandom() % _itemArea.width();
-		itemy = getRandom() % _itemArea.height();
+		Common::RandomSource &rs = Ultima8Engine::get_instance()->getRandomSource();
+		itemx = rs.getRandomNumber(_itemArea.width() - 1);
+		itemy = rs.getRandomNumber(_itemArea.height() - 1);
 
 		item->setGumpLocation(itemx, itemy);
 	}
diff --git a/engines/ultima/ultima8/gumps/game_map_gump.cpp b/engines/ultima/ultima8/gumps/game_map_gump.cpp
index 643f65841ed..f0e4bbc3a2c 100644
--- a/engines/ultima/ultima8/gumps/game_map_gump.cpp
+++ b/engines/ultima/ultima8/gumps/game_map_gump.cpp
@@ -500,9 +500,12 @@ void GameMapGump::DropItem(Item *item, int mx, int my) {
 		tx = _draggingPos[0];
 		ty = _draggingPos[1];
 		int inaccuracy = 4 * (30 - avatar->getDex());
-		if (inaccuracy < 20) inaccuracy = 20; // just in case dex > 25
-		tx += (getRandom() % inaccuracy) - (getRandom() % inaccuracy);
-		ty += (getRandom() % inaccuracy) - (getRandom() % inaccuracy);
+		if (inaccuracy < 20)
+			inaccuracy = 20; // just in case dex > 25
+
+		Common::RandomSource &rs = Ultima8Engine::get_instance()->getRandomSource();
+		tx += rs.getRandomNumberRngSigned(-inaccuracy, inaccuracy);
+		ty += rs.getRandomNumberRngSigned(-inaccuracy, inaccuracy);
 		MissileTracker t(item, tx, ty, _draggingPos[2],
 		                 speed, 4);
 		t.launchItem();
diff --git a/engines/ultima/ultima8/gumps/weasel_gump.cpp b/engines/ultima/ultima8/gumps/weasel_gump.cpp
index 9684f3fa5b6..1ce8f7fdc49 100644
--- a/engines/ultima/ultima8/gumps/weasel_gump.cpp
+++ b/engines/ultima/ultima8/gumps/weasel_gump.cpp
@@ -92,7 +92,8 @@ static void _closeIfExists(Gump *gump) {
 }
 
 static const char *_getRandomMovie(const char **movies, int nmovies) {
-	int offset = Ultima8Engine::get_instance()->getRandomNumber(nmovies - 1);
+	Common::RandomSource &rs = Ultima8Engine::get_instance()->getRandomSource();
+	int offset = rs.getRandomNumber(nmovies - 1);
 	return movies[offset];
 }
 }
diff --git a/engines/ultima/ultima8/kernel/kernel.cpp b/engines/ultima/ultima8/kernel/kernel.cpp
index 61db9cc0335..387337e43e0 100644
--- a/engines/ultima/ultima8/kernel/kernel.cpp
+++ b/engines/ultima/ultima8/kernel/kernel.cpp
@@ -493,11 +493,5 @@ uint32 Kernel::I_resetRef(const uint8 *args, unsigned int /*argsize*/) {
 	return 0;
 }
 
-const uint U8_RAND_MAX = 0x7fffffff;
-
-uint getRandom() {
-	return Ultima8Engine::get_instance()->getRandomNumber(U8_RAND_MAX);
-}
-
 } // End of namespace Ultima8
 } // End of namespace Ultima
diff --git a/engines/ultima/ultima8/kernel/kernel.h b/engines/ultima/ultima8/kernel/kernel.h
index 2650fa9f9ba..7de322e5b89 100644
--- a/engines/ultima/ultima8/kernel/kernel.h
+++ b/engines/ultima/ultima8/kernel/kernel.h
@@ -164,11 +164,6 @@ private:
 	static Kernel *_kernel;
 };
 
-
-extern const uint U8_RAND_MAX;
-extern uint getRandom();
-
-
 } // End of namespace Ultima8
 } // End of namespace Ultima
 
diff --git a/engines/ultima/ultima8/ultima8.h b/engines/ultima/ultima8/ultima8.h
index 3061ffae0da..4fda211c363 100644
--- a/engines/ultima/ultima8/ultima8.h
+++ b/engines/ultima/ultima8/ultima8.h
@@ -299,10 +299,9 @@ public:
 		return _avatarMoverProcess;
 	}
 
-	/**
-	 * Get a random number
-	 */
-	uint getRandomNumber(uint maxVal) { return _randomSource.getRandomNumber(maxVal); }
+	Common::RandomSource &getRandomSource() {
+		return _randomSource;
+	}
 
 	/**
 	 * Notifies the engine that the sound settings may have changed
diff --git a/engines/ultima/ultima8/usecode/uc_machine.cpp b/engines/ultima/ultima8/usecode/uc_machine.cpp
index 85a8efcb4b9..aafdaf9f8a7 100644
--- a/engines/ultima/ultima8/usecode/uc_machine.cpp
+++ b/engines/ultima/ultima8/usecode/uc_machine.cpp
@@ -2404,8 +2404,8 @@ uint32 UCMachine::I_urandom(const uint8 *args, unsigned int /*argsize*/) {
 	if (num <= 1) return 0;
 
 	// return random integer between 0 (incl.) to num (excl.)
-
-	return (getRandom() % num);
+	Common::RandomSource &rs = Ultima8Engine::get_instance()->getRandomSource();
+	return rs.getRandomNumber(num - 1);
 }
 
 uint32 UCMachine::I_rndRange(const uint8 *args, unsigned int /*argsize*/) {
@@ -2416,7 +2416,8 @@ uint32 UCMachine::I_rndRange(const uint8 *args, unsigned int /*argsize*/) {
 	if (hi <= lo)
 		return lo;
 
-	return (lo + (getRandom() % (hi - lo + 1)));
+	Common::RandomSource &rs = Ultima8Engine::get_instance()->getRandomSource();
+	return rs.getRandomNumberRng(lo, hi);
 }
 
 } // End of namespace Ultima8
diff --git a/engines/ultima/ultima8/world/actors/actor.cpp b/engines/ultima/ultima8/world/actors/actor.cpp
index 22547606171..0778a846468 100644
--- a/engines/ultima/ultima8/world/actors/actor.cpp
+++ b/engines/ultima/ultima8/world/actors/actor.cpp
@@ -137,18 +137,19 @@ bool Actor::loadMonsterStatsU8() {
 	if (!mi)
 		return false;
 
+	Common::RandomSource &rs = Ultima8Engine::get_instance()->getRandomSource();
 	uint16 hp;
 	if (mi->_maxHp <= mi->_minHp)
 		hp = mi->_minHp;
 	else
-		hp = mi->_minHp + getRandom() % (mi->_maxHp - mi->_minHp);
+		hp = rs.getRandomNumberRng(mi->_minHp, mi->_maxHp);
 	setHP(hp);
 
 	uint16 dex;
 	if (mi->_maxDex <= mi->_minDex)
 		dex = mi->_minDex;
 	else
-		dex = mi->_minDex + getRandom() % (mi->_maxDex - mi->_minDex);
+		dex = rs.getRandomNumberRng(mi->_minDex, mi->_maxDex);
 	setDex(dex);
 
 	uint8 new_alignment = mi->_alignment;
@@ -166,6 +167,7 @@ bool Actor::giveTreasure() {
 	if (!mi)
 		return false;
 
+	Common::RandomSource &rs = Ultima8Engine::get_instance()->getRandomSource();
 	const Std::vector<TreasureInfo> &treasure = mi->_treasure;
 
 	for (unsigned int i = 0; i < treasure.size(); ++i) {
@@ -181,7 +183,7 @@ bool Actor::giveTreasure() {
 
 		// check chance
 		if (ti._chance < 0.999 &&
-		        (static_cast<double>(getRandom()) / U8_RAND_MAX) > ti._chance) {
+		        rs.getRandomNumber(1000) > ti._chance * 1000) {
 			continue;
 		}
 
@@ -190,7 +192,7 @@ bool Actor::giveTreasure() {
 		if (ti._minCount >= ti._maxCount)
 			count = ti._minCount;
 		else
-			count = ti._minCount + (getRandom() % (ti._maxCount - ti._minCount));
+			count = rs.getRandomNumberRng(ti._minCount, ti._maxCount);
 
 		if (!ti._special.empty()) {
 			if (ti._special == "weapon") {
@@ -203,7 +205,7 @@ bool Actor::giveTreasure() {
 					int chance = si->_weaponInfo->_treasureChance;
 					if (!chance) continue;
 
-					int r = getRandom() % 100;
+					int r = rs.getRandomNumber(99);
 
 					debugC(kDebugActor, "weapon (%u) chance: %d/%d", s, r, chance);
 
@@ -227,13 +229,13 @@ bool Actor::giveTreasure() {
 				int frameNum;
 				uint16 qualityNum;
 
-				if (getRandom() % 10 < 8) {
+				if (rs.getRandomNumber(9) < 8) {
 					// wand
-					if (getRandom() % 10 < 4) {
+					if (rs.getRandomNumber(9) < 4) {
 						// charged
 						frameNum = 0;
-						qualityNum = 3 + (getRandom() % 4) + // charges
-						          ((1 + (getRandom() % 4)) << 8); // spell
+						qualityNum = rs.getRandomNumberRng(3, 6) + // charges
+									 (rs.getRandomNumberRng(1, 4) << 8);  // spell
 					} else {
 						frameNum = 15;
 						qualityNum = 0;
@@ -246,13 +248,13 @@ bool Actor::giveTreasure() {
 					item->randomGumpLocation();
 				}
 
-				if (getRandom() % 10 < 6) {
+				if (rs.getRandomNumber(9) < 6) {
 					// rod
-					if (getRandom() % 10 < 2) {
+					if (rs.getRandomNumber(9) < 2) {
 						// charged
 						frameNum = 3;
-						qualityNum = 3 + (getRandom() % 4) + // charges
-						          ((1 + (getRandom() % 7)) << 8); // spell
+						qualityNum = rs.getRandomNumberRng(3, 6) + // charges
+									 (rs.getRandomNumberRng(1, 7) << 8); // spell
 					} else {
 						frameNum = 16;
 						qualityNum = 0;
@@ -265,15 +267,15 @@ bool Actor::giveTreasure() {
 					item->randomGumpLocation();
 				}
 
-				if (getRandom() % 10 < 5) {
+				if (rs.getRandomNumber(9) < 5) {
 					// symbol
-					if (getRandom() % 10 < 5) {
+					if (rs.getRandomNumber(9) < 5) {
 						// charged
 						frameNum = 12;
-						uint8 spell = 1 + (getRandom() % 11);
+						uint8 spell = rs.getRandomNumberRng(1, 11);
 						qualityNum = spell << 8;
 						if (spell < 4) {
-							qualityNum += 3 + (getRandom() % 4);
+							qualityNum += rs.getRandomNumberRng(3, 6);
 						} else {
 							// symbol can only have one charge of anything
 							// other than ignite/extinguish
@@ -291,13 +293,13 @@ bool Actor::giveTreasure() {
 					item->randomGumpLocation();
 				}
 
-				if (getRandom() % 10 < 2) {
+				if (rs.getRandomNumber(9) < 2) {
 					// demon talisman
-					if (getRandom() % 10 < 2) {
+					if (rs.getRandomNumber(9) < 2) {
 						// charged
 						frameNum = 9;
-						qualityNum = 1 + (getRandom() % 2) +  // charges
-						          ((10 + (getRandom() % 2)) << 8); // spell
+						qualityNum = rs.getRandomNumberRng(1, 2) +  // charges
+									 (rs.getRandomNumberRng(10, 11) << 8); // spell
 					} else {
 						frameNum = 18;
 						qualityNum = 0;
@@ -350,11 +352,11 @@ bool Actor::giveTreasure() {
 		// we need to produce a number of items
 		for (int j = 0; (int)j < count; ++j) {
 			// pick shape
-			int n = getRandom() % ti._shapes.size();
+			int n = rs.getRandomNumber(ti._shapes.size() - 1);
 			uint32 shapeNum = ti._shapes[n];
 
 			// pick frame
-			n = getRandom() % ti._frames.size();
+			n = rs.getRandomNumber(ti._frames.size() - 1);
 			uint32 frameNum = ti._frames[n];
 
 			const ShapeInfo *si = GameData::get_instance()->getMainShapes()->
@@ -759,7 +761,8 @@ uint16 Actor::setActivityCru(int activity) {
 		|| hasActorFlags(ACT_WEAPONREADY) || activity == 0)
 		return 0;
 
-	if ((World::get_instance()->getGameDifficulty() == 4) && (getRandom() % 2 == 0)) {
+	Common::RandomSource &rs = Ultima8Engine::get_instance()->getRandomSource();
+	if ((World::get_instance()->getGameDifficulty() == 4) && rs.getRandomBit()) {
 		if (activity == 5)
 			activity = 0xa;
 		if (activity == 9)
@@ -875,12 +878,13 @@ int Actor::getDamageAmount() const {
 	const ShapeInfo *si = getShapeInfo();
 	if (si->_monsterInfo) {
 
-		int min = static_cast<int>(si->_monsterInfo->_minDmg);
-		int max = static_cast<int>(si->_monsterInfo->_maxDmg);
+		uint min = si->_monsterInfo->_minDmg;
+		uint max = si->_monsterInfo->_maxDmg;
 
-		int damage = (getRandom() % (max - min + 1)) + min;
+		Common::RandomSource &rs = Ultima8Engine::get_instance()->getRandomSource();
+		uint damage = rs.getRandomNumberRng(min, max);
 
-		return damage;
+		return static_cast<int>(damage);
 	} else {
 		return 1;
 	}
@@ -1038,11 +1042,12 @@ void Actor::receiveHitCru(uint16 other, Direction dir, int damage, uint16 damage
 				kernel->killProcesses(_objId, PathfinderProcess::PATHFINDER_PROC_TYPE, true);
 				doAnim(static_cast<Animation::Sequence>(0x37), dir_current);
 			} else if (shape == 0x4e6 || shape == 0x338 || shape == 0x385 || shape == 899) {
-				if (!(getRandom() % 3)) {
+				Common::RandomSource &rs = Ultima8Engine::get_instance()->getRandomSource();
+				if (rs.getRandomNumber(2)) {
 					// Randomly stun the NPC for these damage types.
 					// CHECK ME: is this time accurate?
 					Process *attack = kernel->findProcess(_objId, AttackProcess::ATTACK_PROC_TYPE);
-					uint stun = ((getRandom() % 10) + 8) * 60;
+					uint stun = rs.getRandomNumberRng(8, 17) * 60;
 					if (attack && stun) {
 						Process *delay = new DelayProcess(stun);
 						kernel->addProcess(delay);
@@ -1054,7 +1059,7 @@ void Actor::receiveHitCru(uint16 other, Direction dir, int damage, uint16 damage
 	}
 }
 
-#define RAND_ELEM(array) (array[getRandom() % ARRAYSIZE(array)])
+#define RAND_ELEM(array) (array[rs.getRandomNumber(ARRAYSIZE(array) - 1)])
 
 void Actor::tookHitCru() {
 	AudioProcess *audio = AudioProcess::get_instance();
@@ -1063,9 +1068,10 @@ void Actor::tookHitCru() {
 	if (!audio)
 		return;
 
+	Common::RandomSource &rs = Ultima8Engine::get_instance()->getRandomSource();
 	if (lastanim == Animation::lookLeftCru || lastanim == Animation::lookRightCru) {
 		if (canSeeControlledActor(true)) {
-			if (getRandom() % 4)
+			if (rs.getRandomNumber(3) != 0)
 				setActivity(5);
 			else
 				setActivity(10);
@@ -1090,7 +1096,7 @@ void Actor::tookHitCru() {
 					return;
 			}
 
-			audio->playSFX(sounds[getRandom() % nsounds], 0x80, _objId, 1);
+			audio->playSFX(sounds[rs.getRandomNumber(nsounds - 1)], 0x80, _objId, 1);
 		}
 	} else if (GAME_IS_REGRET) {
 		switch (getShape()) {
@@ -1116,7 +1122,7 @@ void Actor::tookHitCru() {
 					return;
 			}
 
-			audio->playSFX(sounds[getRandom() % nsounds], 0x80, _objId, 1);
+			audio->playSFX(sounds[rs.getRandomNumber(nsounds - 1)], 0x80, _objId, 1);
 			return;
 		}
 		case 0x385:
@@ -1196,6 +1202,7 @@ void Actor::receiveHitU8(uint16 other, Direction dir, int damage, uint16 damage_
 		debugC(kDebugActor, "Damage: %d", damage);
 	}
 
+	Common::RandomSource &rs = Ultima8Engine::get_instance()->getRandomSource();
 	if (damage >= 4 && _objId == 1 && attacker) {
 		// play blood sprite
 		int start = 0, end = 12;
@@ -1206,7 +1213,7 @@ void Actor::receiveHitU8(uint16 other, Direction dir, int damage, uint16 damage_
 
 		int32 xv, yv, zv;
 		getLocation(xv, yv, zv);
-		zv += (getRandom() % 24);
+		zv += rs.getRandomNumber(23);
 		Process *sp = new SpriteProcess(620, start, end, 1, 1, xv, yv, zv);
 		Kernel::get_instance()->addProcess(sp);
 	}
@@ -1259,9 +1266,9 @@ void Actor::receiveHitU8(uint16 other, Direction dir, int damage, uint16 damage_
 
 		int sfx;
 		if (damage)
-			sfx = 50 + (getRandom() % 2); // constants!
+			sfx = rs.getRandomNumberRng(50, 51); // constants!
 		else
-			sfx = 20 + (getRandom() % 3); // constants!
+			sfx = rs.getRandomNumberRng(20, 22); // constants!
 		AudioProcess *audioproc = AudioProcess::get_instance();
 		if (audioproc) audioproc->playSFX(sfx, 0x60, _objId, 0);
 		return;
@@ -1339,6 +1346,7 @@ ProcId Actor::dieU8(uint16 damageType) {
 		destroyContents();
 	giveTreasure();
 
+	Common::RandomSource &rs = Ultima8Engine::get_instance()->getRandomSource();
 	const ShapeInfo *shapeinfo = getShapeInfo();
 	const MonsterInfo *mi = nullptr;
 	if (shapeinfo) mi = shapeinfo->_monsterInfo;
@@ -1348,7 +1356,7 @@ ProcId Actor::dieU8(uint16 damageType) {
 
 		debugC(kDebugActor, "Actor::die: scheduling resurrection");
 
-		int timeout = ((getRandom() % 25) + 5) * 30; // 5-30 seconds
+		int timeout = rs.getRandomNumberRng(5, 30) * 30; // 5-30 seconds
 
 		Process *resproc = new ResurrectionProcess(this);
 		Kernel::get_instance()->addProcess(resproc);
@@ -1376,19 +1384,19 @@ ProcId Actor::dieU8(uint16 damageType) {
 
 		for (int i = 0; i < count; ++i) {
 			Item *piece = ItemFactory::createItem(mi->_explode,
-												  getRandom() % framecount,
+												  rs.getRandomNumber(framecount - 1),
 												  0, // qual
 												  Item::FLG_FAST_ONLY, //flags,
 												  0, // npcnum
 												  0, // mapnum
 												  0, true // ext. flags, _objId
 												 );
-			piece->move(_x - 128 + 32 * (getRandom() % 6),
-						_y - 128 + 32 * (getRandom() % 6),
-						_z + getRandom() % 8); // move to near actor's position
-			piece->hurl(-25 + (getRandom() % 50),
-						-25 + (getRandom() % 50),
-						10 + (getRandom() % 10),
+			piece->move(_x + 32 * rs.getRandomNumberRngSigned(-4, 4),
+						_y + 32 * rs.getRandomNumberRngSigned(-4, 4),
+						_z + rs.getRandomNumber(7)); // move to near actor's position
+			piece->hurl(rs.getRandomNumberRngSigned(-25, 25),
+						rs.getRandomNumberRngSigned(-25, 25),
+						rs.getRandomNumberRngSigned(10, 20),
 						4); // (wrong?) CONSTANTS!
 		}
 	}
@@ -1445,19 +1453,20 @@ ProcId Actor::dieCru(uint16 damageType, uint16 damagePts, Direction srcDir) {
 					setShape(0x576);
 					setToStartOfAnim(Animation::walk);
 
-					int num_random_steps = getRandom() % 9;
+					Common::RandomSource &rs = Ultima8Engine::get_instance()->getRandomSource();
+					int num_random_steps = rs.getRandomNumber(8);
 					// switch to an 8-dir value
 					if (rundir % 2)
 						rundir = static_cast<Direction>((rundir + 1) % 16);
 
 					for (int i = 0; i < num_random_steps; i++) {
-						rundir = Direction_TurnByDelta(rundir, (int)(getRandom() % 3) - 1, dirmode_8dirs);
+						rundir = Direction_TurnByDelta(rundir, rs.getRandomNumberRngSigned(-1, 1), dirmode_8dirs);
 						lastanim = doAnimAfter(Animation::walk, rundir, lastanim);
 					}
 
 					lastanim = doAnimAfter(Animation::fallBackwardsCru, dir_current, lastanim);
 
-					int num_random_falls = (getRandom() % 3) + 1;
+					int num_random_falls = rs.getRandomNumberRng(1, 3);
 					for (int i = 0; i < num_random_falls; i++) {
 						lastanim = doAnimAfter(Animation::fallForwardsCru, dir_current, lastanim);
 					}
@@ -1553,11 +1562,12 @@ ProcId Actor::dieCru(uint16 damageType, uint16 damagePts, Direction srcDir) {
 			fall_random_dir = true;
 		}
 
+		Common::RandomSource &rs = Ultima8Engine::get_instance()->getRandomSource();
 		if (!hasAnim(Animation::fallForwardsCru)) {
 			lastanim = doAnimAfter(Animation::fallBackwardsCru, dir_current, lastanim);
 		} else {
 			if (fall_random_dir) {
-				fall_backwards = (getRandom() % 2) == 0;
+				fall_backwards = rs.getRandomBit() == 0;
 			}
 			if (fall_backwards) {
 				lastanim = doAnimAfter(Animation::fallBackwardsCru, dir_current, lastanim);
@@ -1572,12 +1582,12 @@ ProcId Actor::dieCru(uint16 damageType, uint16 damagePts, Direction srcDir) {
 			static const uint16 MALE_DEATH_SFX[] = { 0x88, 0x8C, 0x8F };
 			static const uint16 FEMALE_DEATH_SFX[] = { 0xD8, 0x10 };
 			if (damageType == 0xf) {
-				sfxno = FADING_SCREAM_SFX[getRandom() % 2];
+				sfxno = FADING_SCREAM_SFX[rs.getRandomNumber(1)];
 			} else {
 				if (hasExtFlags(EXT_FEMALE)) {
-					sfxno = FEMALE_DEATH_SFX[getRandom() % 2];
+					sfxno = FEMALE_DEATH_SFX[rs.getRandomNumber(1)];
 				} else {
-					sfxno = MALE_DEATH_SFX[getRandom() % 3];
+					sfxno = MALE_DEATH_SFX[rs.getRandomNumber(2)];
 				}
 			}
 			AudioProcess::get_instance()->playSFX(sfxno, 0x10, _objId, 0, true);
@@ -1661,12 +1671,13 @@ int Actor::calculateAttackDamage(uint16 other, int damage, uint16 damage_type) {
 		damage = 0;
 	}
 
+	Common::RandomSource &rs = Ultima8Engine::get_instance()->getRandomSource();
 	bool slayer = false;
 
 	// _special attacks
 	if (damage && damage_type) {
 		if (damage_type & WeaponInfo::DMG_SLAYER) {
-			if (getRandom() % 10 == 0) {
+			if (rs.getRandomNumber(9) == 0) {
 				slayer = true;
 				damage = 255; // instant kill
 			}
@@ -1720,7 +1731,7 @@ int Actor::calculateAttackDamage(uint16 other, int damage, uint16 damage_type) {
 		if (defenddex <= 0) defenddex = 1;
 
 		if (hasActorFlags(ACT_STUNNED) ||
-		        (getRandom() % (attackdex + 3) > getRandom() % defenddex)) {
+		        (rs.getRandomNumber(attackdex + 2) > rs.getRandomNumber(defenddex -1))) {
 			hit = true;
 		}
 
diff --git a/engines/ultima/ultima8/world/actors/actor_anim_process.cpp b/engines/ultima/ultima8/world/actors/actor_anim_process.cpp
index 767abcb13f3..b58f546868f 100644
--- a/engines/ultima/ultima8/world/actors/actor_anim_process.cpp
+++ b/engines/ultima/ultima8/world/actors/actor_anim_process.cpp
@@ -388,11 +388,12 @@ void ActorAnimProcess::doSpecial() {
 	if (!GAME_IS_U8)
 		return;
 
+	Common::RandomSource &rs = Ultima8Engine::get_instance()->getRandomSource();
 	// play SFX when Avatar draws/sheathes weapon
 	if (_itemNum == 1 && (_action == Animation::readyWeapon ||
 	                      _action == Animation::unreadyWeapon) &&
 	        a->getEquip(ShapeInfo::SE_WEAPON) != 0) {
-		int sfx = (getRandom() % 2) ? 0x51 : 0x52; // constants!
+		int sfx = rs.getRandomBit() ? 0x51 : 0x52; // constants!
 		AudioProcess *audioproc = AudioProcess::get_instance();
 		if (audioproc) audioproc->playSFX(sfx, 0x60, 1, 0);
 		return;
@@ -421,8 +422,8 @@ void ActorAnimProcess::doSpecial() {
 
 			int32 x, y, z;
 			a->getLocation(x, y, z);
-			x += (getRandom() % (6 * 256)) - 3 * 256;
-			y += (getRandom() % (6 * 256)) - 3 * 256;
+			x += rs.getRandomNumberRngSigned(-3 * 256, 3 * 256);
+			y += rs.getRandomNumberRngSigned(-3 * 256, 3 * 256);
 
 			Actor *ghoul = Actor::createActor(0x8e, 0);
 			if (!ghoul) return;
@@ -503,7 +504,8 @@ void ActorAnimProcess::doSpecial() {
 
 		if (sfx) {
 			AudioProcess *audioproc = AudioProcess::get_instance();
-			if (audioproc) audioproc->playSFX(sfx, 0x60, _itemNum, 0, false, 0x10000 + (getRandom() & 0x1FFF) - 0x1000);
+			if (audioproc)
+				audioproc->playSFX(sfx, 0x60, _itemNum, 0, false, 0x10000 + rs.getRandomNumber(0x1FFF) - 0x1000);
 		}
 
 		if (splash) {
@@ -561,12 +563,13 @@ void ActorAnimProcess::doHitSpecial(Item *hit) {
 
 		if (!weapon) return;
 
+		Common::RandomSource &rs = Ultima8Engine::get_instance()->getRandomSource();
 		uint32 weaponshape = weapon->getShape();
 
 		switch (weaponshape) {
 		case 0x32F: // magic hammer
 			if (audioproc) audioproc->playSFX(23, 0x60, 1, 0, false,
-				                                  0x10000 + (getRandom() & 0x1FFF) - 0x1000);
+				                                  0x10000 + rs.getRandomNumber(0x1FFF) - 0x1000);
 			break;
 		case 0x330: { // Slayer
 			// if we killed somebody, thunder&lightning
@@ -574,7 +577,7 @@ void ActorAnimProcess::doHitSpecial(Item *hit) {
 				// calling intrinsic...
 				PaletteFaderProcess::I_lightningBolt(0, 0);
 				int sfx;
-				switch (getRandom() % 3) {
+				switch (rs.getRandomNumber(2)) {
 				case 0:
 					sfx = 91;
 					break;
@@ -591,9 +594,10 @@ void ActorAnimProcess::doHitSpecial(Item *hit) {
 		}
 		case 0x331: { // Flame Sting
 			int sfx = 33;
-			if (getRandom() % 2 == 0) sfx = 101;
+			if (rs.getRandomBit())
+				sfx = 101;
 			if (audioproc) audioproc->playSFX(sfx, 0x60, 1, 0, false,
-				                                  0x10000 + (getRandom() & 0x1FFF) - 0x1000);
+				                                  0x10000 + rs.getRandomNumber(0x1FFF) - 0x1000);
 
 			int32 x, y, z;
 			a->getLocation(x, y, z);
@@ -622,7 +626,7 @@ void ActorAnimProcess::doHitSpecial(Item *hit) {
 			        0, 0, 0, fx, fy, fz);
 			ProcId cipid = kernel->addProcess(cip);
 
-			DelayProcess *dp2 = new DelayProcess(60 + (getRandom() % 60)); //2-4s
+			DelayProcess *dp2 = new DelayProcess(rs.getRandomNumberRng(60, 120)); //2-4s
 			ProcId dp2id = kernel->addProcess(dp2);
 
 			DestroyItemProcess *dip = new DestroyItemProcess(0);
diff --git a/engines/ultima/ultima8/world/actors/actor_bark_notify_process.cpp b/engines/ultima/ultima8/world/actors/actor_bark_notify_process.cpp
index c5f37b3e7ba..1e14efa6da9 100644
--- a/engines/ultima/ultima8/world/actors/actor_bark_notify_process.cpp
+++ b/engines/ultima/ultima8/world/actors/actor_bark_notify_process.cpp
@@ -20,6 +20,7 @@
  */
 
 #include "ultima/ultima8/world/actors/actor_bark_notify_process.h"
+#include "ultima/ultima8/ultima8.h"
 #include "ultima/ultima8/kernel/delay_process.h"
 #include "ultima/ultima8/world/actors/actor.h"
 #include "ultima/ultima8/kernel/kernel.h"
@@ -61,7 +62,8 @@ void ActorBarkNotifyProcess::run() {
 
 	// wait a short while (1-2.5 seconds) before doing the next animation
 	// (or even if not doing the animation)
-	Process *delayproc = new DelayProcess(30 + (getRandom() % 45));
+	Common::RandomSource &rs = Ultima8Engine::get_instance()->getRandomSource();
+	Process *delayproc = new DelayProcess(rs.getRandomNumberRng(30, 75));
 	ProcId delaypid = Kernel::get_instance()->addProcess(delayproc);
 
 	if (doAnim)
diff --git a/engines/ultima/ultima8/world/actors/attack_process.cpp b/engines/ultima/ultima8/world/actors/attack_process.cpp
index 6b8efd44344..3daa078a1af 100644
--- a/engines/ultima/ultima8/world/actors/attack_process.cpp
+++ b/engines/ultima/ultima8/world/actors/attack_process.cpp
@@ -21,7 +21,7 @@
 
 
 #include "ultima/ultima8/world/actors/attack_process.h"
-
+#include "ultima/ultima8/ultima8.h"
 #include "ultima/ultima8/audio/audio_process.h"
 #include "ultima/ultima8/games/game_data.h"
 #include "ultima/ultima8/kernel/kernel.h"
@@ -70,7 +70,7 @@ static const int16 REG_SFX_13[] = { 0x1DD, 0x1DE, 0x1DF, 0x1E0, 0x1E1, 0x1E2, 0x
 static const int16 REG_SFX_14[] = { 0x9B, 0x9C, 0x9D, 0x9E, 0x9F };
 static const int16 REG_SFX_15[] = { 0x1E7, 0x1E8, 0x1E9, 0x1EA, 0x1ED };
 
-#define RANDOM_ELEM(array) (array[getRandom() % ARRAYSIZE(array)])
+#define RANDOM_ELEM(array) (array[rs.getRandomNumber(ARRAYSIZE(array) - 1)])
 
 // If data is referenced in the metalang with an offset of this or greater,
 // read from the data array.
@@ -83,10 +83,6 @@ int16 AttackProcess::_lastLastAttackSound = -1;
 
 static uint16 someSleepGlobal = 0;
 
-static inline int32 randomOf(int32 max) {
-	return (max > 0 ? getRandom() % max : 0);
-}
-
 AttackProcess::AttackProcess() : Process(), _block(0), _target(1), _tactic(0), _tacticDat(nullptr),
 _tacticDatReadStream(nullptr), _tacticDatStartOffset(0), _soundNo(-1), _playedStartSound(false),
 _npcInitialDir(dir_invalid), _field57(0), _field59(0), _field7f(false), _field96(false), _field97(false),
@@ -97,8 +93,9 @@ _timer3(0), _timer4(0), _timer5(0), _soundTimestamp(0), _soundDelayTicks(480), _
 		_dataArray[i] = 0;
 	}
 	if (GAME_IS_REGRET) {
-		_soundDelayTicks = (10 + randomOf(15)) * 60;
-		if (randomOf(3) == 0)
+		Common::RandomSource &rs = Ultima8Engine::get_instance()->getRandomSource();
+		_soundDelayTicks = rs.getRandomNumberRng(10, 24) * 60;
+		if (rs.getRandomNumber(2) == 0)
 			_soundTimestamp = Kernel::get_instance()->getTickNum();
 	}
 }
@@ -121,8 +118,9 @@ _soundTimestamp(0), _soundDelayTicks(480), _fireTimestamp(0) {
 	}
 
 	if (GAME_IS_REGRET) {
-		_soundDelayTicks = (10 + randomOf(15)) * 60;
-		if (randomOf(3) == 0)
+		Common::RandomSource &rs = Ultima8Engine::get_instance()->getRandomSource();
+		_soundDelayTicks = rs.getRandomNumberRng(10, 24) * 60;
+		if (rs.getRandomNumber(2) == 0)
 			_soundTimestamp = Kernel::get_instance()->getTickNum();
 	}
 
@@ -211,6 +209,7 @@ void AttackProcess::run() {
 		return;
 	}
 
+	Common::RandomSource &rs = Ultima8Engine::get_instance()->getRandomSource();
 	const Direction curdir = a->getDir();
 
 	const uint8 opcode = _tacticDatReadStream->readByte();
@@ -312,7 +311,7 @@ void AttackProcess::run() {
 			// Sleep for a random value scaled by difficult level
 			int ticks = readNextWordWithData();
 			if (ticks == someSleepGlobal) {
-				ticks = randomOf(0x32) + 0x14;
+				ticks = rs.getRandomNumberRng(0x31, 0x45);
 			}
 			ticks /= World::get_instance()->getGameDifficulty();
 			sleep(ticks);
@@ -399,10 +398,12 @@ void AttackProcess::run() {
 		case 0x9e:
 		{
 			uint16 maxval = readNextWordWithData();
-			uint16 randval = randomOf(maxval);
 			uint16 offset = readNextWordWithData();
-			if (randval != 0) {
-				_tacticDatReadStream->seek(offset);
+			if (maxval != 0) {
+				uint16 randval = rs.getRandomNumber(maxval - 1);
+				if (randval != 0) {
+					_tacticDatReadStream->seek(offset);
+				}
 			}
 			return;
 		}
@@ -569,6 +570,7 @@ void AttackProcess::genericAttack() {
 		warning("started attack for NPC %d with no weapon", _itemNum);
 	}*/
 
+	Common::RandomSource &rs = Ultima8Engine::get_instance()->getRandomSource();
 	AudioProcess *audio = AudioProcess::get_instance();
 	const Direction curdir = a->getDir();
 	const int32 ticknow = Kernel::get_instance()->getTickNum();
@@ -599,8 +601,8 @@ void AttackProcess::genericAttack() {
 #endif
 			int32 x, y, z;
 			a->getLocation(x, y, z);
-			x += -0x1ff + randomOf(0x400);
-			y += -0x1ff + randomOf(0x400);
+			x += rs.getRandomNumberRngSigned(-0x1ff, 0x1ff);
+			y += rs.getRandomNumberRngSigned(-0x1ff, 0x1ff);
 			_field96 = true;
 			const ProcId pid = Kernel::get_instance()->addProcess(
 								new CruPathfinderProcess(a, x, y, z, 12, 0x80, true));
@@ -626,7 +628,7 @@ void AttackProcess::genericAttack() {
 #endif
 			if (_timer3 >= ticknow) {
 				if (a->isInCombat()) {
-					if (randomOf(3) != 0) {
+					if (rs.getRandomNumber(2) != 0) {
 #ifdef WATCHACTOR
 						if (_itemNum == WATCHACTOR)
 							debug("Attack: toggle weapon state");
@@ -639,8 +641,8 @@ void AttackProcess::genericAttack() {
 						return;
 					}
 
-					if (randomOf(3) == 0) {
-						a->turnTowardDir(Direction_TurnByDelta(curdir, randomOf(8), dirmode_8dirs));
+					if (rs.getRandomNumber(2) == 0) {
+						a->turnTowardDir(Direction_TurnByDelta(curdir, rs.getRandomNumber(7), dirmode_8dirs));
 						return;
 					}
 
@@ -659,7 +661,7 @@ void AttackProcess::genericAttack() {
 					_wpnField8 = wpnField8;
 					if (_wpnField8 < 3) {
 						_wpnField8 = 1;
-					} else if ((_doubleDelay && (randomOf(2) == 0)) || (randomOf(5) == 0)) {
+					} else if ((_doubleDelay && rs.getRandomNumber(1) == 0) || (rs.getRandomNumber(4) == 0)) {
 						a->setAttackAimFlag(true);
 						_wpnField8 *= 4;
 					}
@@ -713,7 +715,7 @@ void AttackProcess::genericAttack() {
 			if (_itemNum == WATCHACTOR)
 				debug("Attack: targetdir == currentdir");
 #endif
-			const uint16 rnd = randomOf(10);
+			const uint16 rnd = rs.getRandomNumber(9);
 			const uint32 frameno = Kernel::get_instance()->getFrameNum();
 			const uint32 timeoutfinish = target->getAttackMoveTimeoutFinishFrame();
 
@@ -731,7 +733,7 @@ void AttackProcess::genericAttack() {
 			else
 				ready = checkReady(ticknow, targetdir);
 
-			if (_timer2set && (randomOf(5) == 0 || checkTimer2PlusDelayElapsed(ticknow))) {
+			if (_timer2set && (rs.getRandomNumber(4) == 0 || checkTimer2PlusDelayElapsed(ticknow))) {
 				_timer2set = false;
 			}
 
@@ -770,7 +772,7 @@ void AttackProcess::genericAttack() {
 					_wpnField8 = 1;
 				} else {
 					_wpnField8 = wpnField8;
-					if (_wpnField8 > 2 && ((_doubleDelay && randomOf(2) == 0) || randomOf(5) == 0)) {
+					if (_wpnField8 > 2 && ((_doubleDelay && rs.getRandomNumber(1) == 0) || rs.getRandomNumber(4) == 0)) {
 						a->setAttackAimFlag(true);
 						_wpnField8 *= 4;
 					}
@@ -855,6 +857,7 @@ int16 AttackProcess::getRandomAttackSoundRegret(const Actor *actor) {
 	if (actor->isDead())
 		return -1;
 
+	Common::RandomSource &rs = Ultima8Engine::get_instance()->getRandomSource();
 	uint32 shapeno = actor->getShape();
 
 	int16 sndno = -1;
@@ -924,11 +927,13 @@ void AttackProcess::checkRandomAttackSound(int now, uint32 shapeno) {
 		checkRandomAttackSoundRegret(getActor(_itemNum));
 		return;
 	}
+
+	Common::RandomSource &rs = Ultima8Engine::get_instance()->getRandomSource();
 	AudioProcess *audio = AudioProcess::get_instance();
 	int16 attacksound = -1;
 	if (!_playedStartSound) {
 		_playedStartSound = true;
-		if (randomOf(3) == 0) {
+		if (rs.getRandomNumber(2) == 0) {
 			switch(shapeno) {
 				case 0x371:
 					attacksound = RANDOM_ELEM(REM_SFX_3);
@@ -1060,9 +1065,10 @@ void AttackProcess::timeNowToTimerVal2(int now) {
 }
 
 void AttackProcess::setTimer3() {
+	Common::RandomSource &rs = Ultima8Engine::get_instance()->getRandomSource();
 	const int32 now = Kernel::get_instance()->getTickNum();
 	_timer3set = true;
-	_timer3 = randomOf(10) * 60 + now;
+	_timer3 = rs.getRandomNumber(9) * 60 + now;
 	return;
 }
 
diff --git a/engines/ultima/ultima8/world/actors/combat_process.cpp b/engines/ultima/ultima8/world/actors/combat_process.cpp
index 1de00e7efac..dec96b25a62 100644
--- a/engines/ultima/ultima8/world/actors/combat_process.cpp
+++ b/engines/ultima/ultima8/world/actors/combat_process.cpp
@@ -20,6 +20,7 @@
  */
 
 #include "ultima/ultima.h"
+#include "ultima/ultima8/ultima8.h"
 #include "ultima/ultima8/world/actors/combat_process.h"
 #include "ultima/ultima8/world/actors/actor.h"
 #include "ultima/ultima8/world/current_map.h"
@@ -95,10 +96,11 @@ void CombatProcess::run() {
 
 		debugC(kDebugActor, "[COMBAT %u] _target (%u) in range", _itemNum, _target);
 
+		Common::RandomSource &rs = Ultima8Engine::get_instance()->getRandomSource();
 		bool hasidle1 = a->hasAnim(Animation::idle1);
 		bool hasidle2 = a->hasAnim(Animation::idle2);
 
-		if ((hasidle1 || hasidle2) && (getRandom() % 5) == 0) {
+		if ((hasidle1 || hasidle2) && rs.getRandomNumber(4) == 0) {
 			// every once in a while, act threatening instead of attacking
 			// TODO: maybe make frequency depend on monster type
 			Animation::Sequence idleanim;
@@ -108,7 +110,7 @@ void CombatProcess::run() {
 			} else if (!hasidle2) {
 				idleanim = Animation::idle1;
 			} else {
-				if (getRandom() % 2)
+				if (rs.getRandomBit())
 					idleanim = Animation::idle1;
 				else
 					idleanim = Animation::idle2;
@@ -279,7 +281,8 @@ void CombatProcess::waitForTarget() {
 	const MonsterInfo *mi = nullptr;
 	if (shapeinfo) mi = shapeinfo->_monsterInfo;
 
-	if (mi && mi->_shifter && a->getMapNum() != 43 && (getRandom() % 2) == 0) {
+	Common::RandomSource &rs = Ultima8Engine::get_instance()->getRandomSource();
+	if (mi && mi->_shifter && a->getMapNum() != 43 && rs.getRandomBit()) {
 		// changelings (except the ones at the U8 endgame pentagram)
 
 		// shift into a tree if nobody is around
diff --git a/engines/ultima/ultima8/world/actors/cru_pathfinder_process.cpp b/engines/ultima/ultima8/world/actors/cru_pathfinder_process.cpp
index b298cae7fe0..257d8f4710f 100644
--- a/engines/ultima/ultima8/world/actors/cru_pathfinder_process.cpp
+++ b/engines/ultima/ultima8/world/actors/cru_pathfinder_process.cpp
@@ -58,7 +58,8 @@ CruPathfinderProcess::CruPathfinderProcess(Actor *actor, Item *target, int maxst
 	assert(actor && target);
 	_itemNum = actor->getObjId();
 	_type = PathfinderProcess::PATHFINDER_PROC_TYPE;
-	_randomFlag = (getRandom() % 2) != 0;
+	Common::RandomSource &rs = Ultima8Engine::get_instance()->getRandomSource();
+	_randomFlag = rs.getRandomBit() != 0;
 	_targetItem = target->getObjId();
 	target->getLocation(_targetX, _targetY, _targetZ);
 
@@ -85,7 +86,8 @@ CruPathfinderProcess::CruPathfinderProcess(Actor *actor, int32 x, int32 y, int32
 	assert(actor);
 	_itemNum = actor->getObjId();
 	_type = PathfinderProcess::PATHFINDER_PROC_TYPE;
-	_randomFlag = (getRandom() % 2) != 0;
+	Common::RandomSource &rs = Ultima8Engine::get_instance()->getRandomSource();
+	_randomFlag = rs.getRandomBit() != 0;
 
 	int32 ax, ay, az;
 	actor->getLocation(ax, ay, az);
diff --git a/engines/ultima/ultima8/world/actors/grant_peace_process.cpp b/engines/ultima/ultima8/world/actors/grant_peace_process.cpp
index 01531cf807a..cc976f9d9c4 100644
--- a/engines/ultima/ultima8/world/actors/grant_peace_process.cpp
+++ b/engines/ultima/ultima8/world/actors/grant_peace_process.cpp
@@ -32,6 +32,7 @@
 #include "ultima/ultima8/world/sprite_process.h"
 #include "ultima/ultima8/audio/audio_process.h"
 #include "ultima/ultima8/world/get_object.h"
+#include "ultima/ultima8/ultima8.h"
 
 namespace Ultima {
 namespace Ultima8 {
@@ -78,6 +79,7 @@ void GrantPeaceProcess::run() {
 		return;
 	}
 
+	Common::RandomSource &rs = Ultima8Engine::get_instance()->getRandomSource();
 	bool hit = false;
 
 	if (target->getDefenseType() & WeaponInfo::DMG_UNDEAD) {
@@ -131,9 +133,9 @@ void GrantPeaceProcess::run() {
 
 				int dir = caster->getDirToItemCentre(*t);
 
-				t->hurl(((getRandom() % 5) + 5) * x_fact[dir],
-				        ((getRandom() % 5) + 5) * y_fact[dir],
-				        ((getRandom() % 5) + 5),
+				t->hurl(engine->getRandomNumber(5, 9) * x_fact[dir],
+				        engine->getRandomNumber(5, 9) * y_fact[dir],
+				        engine->getRandomNumber(5, 9),
 				        4);
 #endif
 			}
@@ -146,7 +148,7 @@ void GrantPeaceProcess::run() {
 		if (!target->hasActorFlags(Actor::ACT_DEAD |
 								   Actor::ACT_IMMORTAL |
 								   Actor::ACT_INVINCIBLE)) {
-			if (getRandom() % 10 == 0) {
+			if (rs.getRandomNumber(9) == 0) {
 				target->receiveHit(_itemNum, dir_current, target->getHP(),
 				                   (WeaponInfo::DMG_MAGIC |
 				                    WeaponInfo::DMG_PIERCE |
@@ -164,7 +166,7 @@ void GrantPeaceProcess::run() {
 		// calling intrinsic...
 		PaletteFaderProcess::I_lightningBolt(0, 0);
 		int sfx;
-		switch (getRandom() % 3) {
+		switch (rs.getRandomNumber(2)) {
 		case 0:
 			sfx = 91;
 			break;
diff --git a/engines/ultima/ultima8/world/actors/guard_process.cpp b/engines/ultima/ultima8/world/actors/guard_process.cpp
index cbd7ccd037a..5a456465111 100644
--- a/engines/ultima/ultima8/world/actors/guard_process.cpp
+++ b/engines/ultima/ultima8/world/actors/guard_process.cpp
@@ -25,6 +25,7 @@
 #include "ultima/ultima8/kernel/kernel.h"
 #include "ultima/ultima8/kernel/delay_process.h"
 #include "ultima/ultima8/world/get_object.h"
+#include "ultima/ultima8/ultima8.h"
 
 namespace Ultima {
 namespace Ultima8 {
@@ -57,12 +58,13 @@ void GuardProcess::run() {
 		return;
 
 	if (!a->canSeeControlledActor(false)) {
-		if (getRandom() % 2) {
-			DelayProcess *dp = new DelayProcess(30 * (1 + (getRandom() % 3)));
+		Common::RandomSource &rs = Ultima8Engine::get_instance()->getRandomSource();
+		if (rs.getRandomBit()) {
+			DelayProcess *dp = new DelayProcess(30 * rs.getRandomNumberRng(1, 3));
 			Kernel::get_instance()->addProcess(dp);
 			waitFor(dp);
 		} else {
-			Animation::Sequence anim = Animation::absAnim(getRandom() % 2 ? Animation::lookLeftCru : Animation::lookRightCru);
+			Animation::Sequence anim = Animation::absAnim(rs.getRandomBit() ? Animation::lookLeftCru : Animation::lookRightCru);
 			uint16 animproc = a->doAnim(anim, dir_current);
 			a->doAnimAfter(Animation::stand, dir_current, animproc);
 		}
diff --git a/engines/ultima/ultima8/world/actors/loiter_process.cpp b/engines/ultima/ultima8/world/actors/loiter_process.cpp
index 9786823fd23..d79d2fb0364 100644
--- a/engines/ultima/ultima8/world/actors/loiter_process.cpp
+++ b/engines/ultima/ultima8/world/actors/loiter_process.cpp
@@ -73,8 +73,10 @@ void LoiterProcess::run() {
 	int32 x, y, z;
 	a->getLocation(x, y, z);
 
-	x += 32 * ((getRandom() % 20) - 10);
-	y += 32 * ((getRandom() % 20) - 10);
+	Common::RandomSource &rs = Ultima8Engine::get_instance()->getRandomSource();
+
+	x += 32 * rs.getRandomNumberRngSigned(-10, 10);
+	y += 32 * rs.getRandomNumberRngSigned(-10, 10);
 
 	Process *pfp;
 	if (GAME_IS_U8)
@@ -87,7 +89,7 @@ void LoiterProcess::run() {
 	bool hasidle1 = a->hasAnim(Animation::idle1);
 	bool hasidle2 = a->hasAnim(Animation::idle2);
 
-	if ((hasidle1 || hasidle2) && ((getRandom() % 3) == 0)) {
+	if ((hasidle1 || hasidle2) && (rs.getRandomNumber(2) == 0)) {
 		Animation::Sequence idleanim;
 
 		if (!hasidle1) {
@@ -95,7 +97,7 @@ void LoiterProcess::run() {
 		} else if (!hasidle2) {
 			idleanim = Animation::idle1;
 		} else {
-			if (getRandom() % 2)
+			if (rs.getRandomBit())
 				idleanim = Animation::idle1;
 			else
 				idleanim = Animation::idle2;
@@ -108,7 +110,7 @@ void LoiterProcess::run() {
 
 	} else {
 		// wait 4-7 sec
-		DelayProcess *dp = new DelayProcess(30 * (4 + (getRandom() % 3)));
+		DelayProcess *dp = new DelayProcess(30 * rs.getRandomNumberRng(4, 7));
 		Kernel::get_instance()->addProcess(dp);
 		dp->waitFor(pfp);
 
diff --git a/engines/ultima/ultima8/world/actors/main_actor.cpp b/engines/ultima/ultima8/world/actors/main_actor.cpp
index be1b6ef448f..84cbd7d2049 100644
--- a/engines/ultima/ultima8/world/actors/main_actor.cpp
+++ b/engines/ultima/ultima8/world/actors/main_actor.cpp
@@ -510,6 +510,7 @@ uint16 MainActor::getDamageType() const {
 }
 
 int MainActor::getDamageAmount() const {
+	Common::RandomSource &rs = Ultima8Engine::get_instance()->getRandomSource();
 	int damage = 0;
 
 	if (getLastAnim() == Animation::kick) {
@@ -523,7 +524,7 @@ int MainActor::getDamageAmount() const {
 			kick_bonus = si->_armourInfo[legs->getFrame()]._kickAttackBonus;
 		}
 
-		damage = (getRandom() % (getStr() / 2 + 1)) + kick_bonus;
+		damage = rs.getRandomNumber(getStr() / 2) + kick_bonus;
 
 		return damage;
 
@@ -541,14 +542,14 @@ int MainActor::getDamageAmount() const {
 		int base = si->_weaponInfo->_baseDamage;
 		int mod = si->_weaponInfo->_damageModifier;
 
-		damage = (getRandom() % (mod + 1)) + base + getStr() / 5;
+		damage = rs.getRandomNumber(mod) + base + getStr() / 5;
 
 		return damage;
 	}
 
 	// no weapon?
 
-	damage = (getRandom() % (getStr() / 2 + 1)) + 1;
+	damage = rs.getRandomNumber(getStr() / 2) + 1;
 
 	return damage;
 }
@@ -604,8 +605,10 @@ void MainActor::accumulateStr(int n) {
 	// already max?
 	if (_strength == 25) return; //!! constant
 
+	Common::RandomSource &rs = Ultima8Engine::get_instance()->getRandomSource();
+
 	_accumStr += n;
-	if (_accumStr >= 650 || getRandom() % (650 - _accumStr) == 0) { //!! constant
+	if (_accumStr >= 650 || rs.getRandomNumber(650 - _accumStr) == 0) { //!! constant
 		_strength++;
 		_accumStr = 0;
 		AudioProcess *audioproc = AudioProcess::get_instance();
@@ -618,8 +621,10 @@ void MainActor::accumulateDex(int n) {
 	// already max?
 	if (_dexterity == 25) return; //!! constant
 
+	Common::RandomSource &rs = Ultima8Engine::get_instance()->getRandomSource();
+
 	_accumDex += n;
-	if (_accumDex >= 650 || getRandom() % (650 - _accumDex) == 0) { //!! constant
+	if (_accumDex >= 650 || rs.getRandomNumber(650 - _accumDex) == 0) { //!! constant
 		_dexterity++;
 		_accumDex = 0;
 		AudioProcess *audioproc = AudioProcess::get_instance();
@@ -632,8 +637,10 @@ void MainActor::accumulateInt(int n) {
 	// already max?
 	if (_intelligence == 25) return; //!! constant
 
+	Common::RandomSource &rs = Ultima8Engine::get_instance()->getRandomSource();
+
 	_accumInt += n;
-	if (_accumInt >= 650 || getRandom() % (650 - _accumInt) == 0) { //!! constant
+	if (_accumInt >= 650 || rs.getRandomNumber(650 - _accumInt) == 0) { //!! constant
 		_intelligence++;
 		_accumInt = 0;
 		AudioProcess *audioproc = AudioProcess::get_instance();
diff --git a/engines/ultima/ultima8/world/actors/npc_dat.cpp b/engines/ultima/ultima8/world/actors/npc_dat.cpp
index 047b6ad0b5d..3ae3d468b3a 100644
--- a/engines/ultima/ultima8/world/actors/npc_dat.cpp
+++ b/engines/ultima/ultima8/world/actors/npc_dat.cpp
@@ -90,7 +90,8 @@ uint16 NPCDat::randomlyGetStrongerWeaponTypes(uint shapeno) {
 	// and other differences as noted.
 	// Some shapes are only valid in each game, but that's ok.
 
-	int rnd = getRandom();
+	Common::RandomSource &rs = Ultima8Engine::get_instance()->getRandomSource();
+	int rnd = rs.getRandomNumber(UINT_MAX);
 
 	switch (shapeno) {
 	case 899:	/* shape 899 - android */
diff --git a/engines/ultima/ultima8/world/actors/rolling_thunder_process.cpp b/engines/ultima/ultima8/world/actors/rolling_thunder_process.cpp
index 6b1c70dd958..0ef8ab0fd2b 100644
--- a/engines/ultima/ultima8/world/actors/rolling_thunder_process.cpp
+++ b/engines/ultima/ultima8/world/actors/rolling_thunder_process.cpp
@@ -92,7 +92,8 @@ void RollingThunderProcess::run() {
 	if (!target)
 		return;
 
-	Animation::Sequence anim = (getRandom() % 2) ? Animation::combatRollLeft : Animation::combatRollRight;
+	Common::RandomSource &rs = Ultima8Engine::get_instance()->getRandomSource();
+	Animation::Sequence anim = rs.getRandomBit() ? Animation::combatRollLeft : Animation::combatRollRight;
 
 	Direction actordir = actor->getDir();
 	Direction outdir = actordir;
@@ -132,7 +133,7 @@ void RollingThunderProcess::run() {
 		if (outdir != actordir) {
 			animpid = actor->turnTowardDir(outdir, animpid);
 		}
-		int attackcount = (getRandom() % 3) + 1;
+		int attackcount = rs.getRandomNumberRng(1, 3);
 		for (int i = 0; i < attackcount; i++) {
 			animpid = actor->doAnimAfter(Animation::attack, outdir, animpid);
 		}
diff --git a/engines/ultima/ultima8/world/actors/surrender_process.cpp b/engines/ultima/ultima8/world/actors/surrender_process.cpp
index 2c3c6cd32d7..75bd460de6f 100644
--- a/engines/ultima/ultima8/world/actors/surrender_process.cpp
+++ b/engines/ultima/ultima8/world/actors/surrender_process.cpp
@@ -38,11 +38,7 @@ static const uint16 SCIENTIST_SUR_SNDS[] = {0xe3, 0xe4, 0xec, 0xf6};
 static const uint16 HARDHAT_SUR_SNDS[] = {0xde, 0xdf, 0x8a, 0x8b};
 static const uint16 FEMALE_SUR_SNDS[] = {0xd6, 0xff, 0xd7};
 
-static inline int32 randomOf(int32 max) {
-	return (max > 0 ? getRandom() % max : 0);
-}
-
-#define RANDOM_ELEM(array) (array[getRandom() % ARRAYSIZE(array)])
+#define RANDOM_ELEM(array) (array[rs.getRandomNumber(ARRAYSIZE(array) - 1)])
 
 SurrenderProcess::SurrenderProcess() :
 	_playedSound(false), _soundDelayTicks(480), _soundTimestamp(0)
@@ -59,8 +55,9 @@ SurrenderProcess::SurrenderProcess(Actor *actor) :
 		actor->doAnim(Animation::surrender, actor->getDir());
 
 	if (GAME_IS_REGRET) {
-		_soundDelayTicks = (10 + randomOf(15)) * 60;
-		if (randomOf(3) == 0)
+		Common::RandomSource &rs = Ultima8Engine::get_instance()->getRandomSource();
+		_soundDelayTicks = rs.getRandomNumberRng(10, 24) * 60;
+		if (rs.getRandomNumber(2) == 0)
 			_soundTimestamp = Kernel::get_instance()->getTickNum();
 	}
 
@@ -114,6 +111,7 @@ int16 SurrenderProcess::checkRandomSoundRemorse() {
 
 	_playedSound = true;
 
+	Common::RandomSource &rs = Ultima8Engine::get_instance()->getRandomSource();
 	int16 soundno = -1;
 
 	switch (a->getShape()) {
diff --git a/engines/ultima/ultima8/world/actors/u8_avatar_mover_process.cpp b/engines/ultima/ultima8/world/actors/u8_avatar_mover_process.cpp
index 1227752bb44..b60e3b9c271 100644
--- a/engines/ultima/ultima8/world/actors/u8_avatar_mover_process.cpp
+++ b/engines/ultima/ultima8/world/actors/u8_avatar_mover_process.cpp
@@ -150,6 +150,8 @@ void U8AvatarMoverProcess::handleCombatMode() {
 		return;
 	}
 
+	Common::RandomSource &rs = Ultima8Engine::get_instance()->getRandomSource();
+
 	if (_mouseButton[0].isUnhandledDoubleClick()) {
 		_mouseButton[0].setState(MBS_HANDLED);
 		_mouseButton[0]._lastDown = 0;
@@ -165,8 +167,8 @@ void U8AvatarMoverProcess::handleCombatMode() {
 			_lastAttack = Kernel::get_instance()->getFrameNum();
 
 			// attacking gives str/dex
-			avatar->accumulateStr(1 + (getRandom() % 2));
-			avatar->accumulateDex(2 + (getRandom() % 2));
+			avatar->accumulateStr(rs.getRandomNumberRng(1, 2));
+			avatar->accumulateDex(rs.getRandomNumberRng(2, 3));
 		}
 
 		return;
@@ -197,8 +199,8 @@ void U8AvatarMoverProcess::handleCombatMode() {
 			_lastAttack = Kernel::get_instance()->getFrameNum();
 
 			// kicking gives str/dex
-			avatar->accumulateStr(1 + (getRandom() % 2));
-			avatar->accumulateDex(2 + (getRandom() % 2));
+			avatar->accumulateStr(rs.getRandomNumberRng(1, 2));
+			avatar->accumulateDex(rs.getRandomNumberRng(2, 3));
 		}
 
 		return;
@@ -608,17 +610,19 @@ void U8AvatarMoverProcess::handleNormalMode() {
 	// idle
 	_idleTime = currentIdleTime + 1;
 
+	Common::RandomSource &rs = Ultima8Engine::get_instance()->getRandomSource();
+
 	// currently shaking head?
 	if (lastanim == Animation::lookLeft || lastanim == Animation::lookRight) {
-		if ((getRandom() % 1500) + 30 < _idleTime) {
+		if (rs.getRandomNumber(1500) + 30 < _idleTime) {
 			_lastHeadShakeAnim = lastanim;
 			waitFor(avatar->doAnim(Animation::stand, direction));
 			_idleTime = 1;
 			return;
 		}
 	} else {
-		if ((getRandom() % 3000) + 150 < _idleTime) {
-			if (getRandom() % 5 == 0)
+		if (rs.getRandomNumber(3000) + 150 < _idleTime) {
+			if (rs.getRandomNumber(4) == 0)
 				nextanim = _lastHeadShakeAnim;
 			else if (_lastHeadShakeAnim == Animation::lookLeft)
 				nextanim = Animation::lookRight;
diff --git a/engines/ultima/ultima8/world/bobo_boomer_process.cpp b/engines/ultima/ultima8/world/bobo_boomer_process.cpp
index 676ccecc651..1e819ed645a 100644
--- a/engines/ultima/ultima8/world/bobo_boomer_process.cpp
+++ b/engines/ultima/ultima8/world/bobo_boomer_process.cpp
@@ -25,6 +25,7 @@
 #include "ultima/ultima8/kernel/delay_process.h"
 #include "ultima/ultima8/world/item.h"
 #include "ultima/ultima8/world/fire_type.h"
+#include "ultima/ultima8/ultima8.h"
 
 namespace Ultima {
 namespace Ultima8 {
@@ -46,8 +47,9 @@ void BoboBoomerProcess::run() {
 	const FireType *firetype = GameData::get_instance()->getFireType(4);
 	assert(firetype);
 
-	int32 randx = static_cast<int32>(getRandom() % 15) - 7;
-	int32 randy = static_cast<int32>(getRandom() % 15) - 7;
+	Common::RandomSource &rs = Ultima8Engine::get_instance()->getRandomSource();
+	int32 randx = rs.getRandomNumberRngSigned(-7, 7);
+	int32 randy = rs.getRandomNumberRngSigned(-7, 7);
 	Point3 pt(_x + randx * 32, _y + randy * 32, _z);
 	firetype->makeBulletSplashShapeAndPlaySound(pt.x, pt.y, pt.z);
 
@@ -62,7 +64,7 @@ void BoboBoomerProcess::run() {
 		return;
 	}
 
-	int sleep = (getRandom() % 15) + 5;
+	int sleep = rs.getRandomNumberRng(5, 20);
 	Process *wait = new DelayProcess(sleep);
 	Kernel::get_instance()->addProcess(wait);
 	waitFor(wait);
diff --git a/engines/ultima/ultima8/world/camera_process.cpp b/engines/ultima/ultima8/world/camera_process.cpp
index c466e401fc9..e4610db2cdb 100644
--- a/engines/ultima/ultima8/world/camera_process.cpp
+++ b/engines/ultima/ultima8/world/camera_process.cpp
@@ -156,8 +156,10 @@ void CameraProcess::terminate() {
 
 void CameraProcess::run() {
 	if (_earthquake) {
-		_eqX = (getRandom() % (_earthquake * 2 + 1)) - _earthquake;
-		_eqY = (getRandom() % (_earthquake * 2 + 1)) - _earthquake;
+		Common::RandomSource &rs = Ultima8Engine::get_instance()->getRandomSource();
+
+		_eqX = rs.getRandomNumberRngSigned(-_earthquake, _earthquake);
+		_eqY = rs.getRandomNumberRngSigned(-_earthquake, _earthquake);
 	} else {
 		_eqX = 0;
 		_eqY = 0;
diff --git a/engines/ultima/ultima8/world/damage_info.cpp b/engines/ultima/ultima8/world/damage_info.cpp
index d679d8b0914..40bf5a9925f 100644
--- a/engines/ultima/ultima8/world/damage_info.cpp
+++ b/engines/ultima/ultima8/world/damage_info.cpp
@@ -23,6 +23,7 @@
 #include "ultima/ultima8/world/item_factory.h"
 #include "ultima/ultima8/audio/audio_process.h"
 #include "ultima/ultima8/kernel/kernel.h"
+#include "ultima/ultima8/ultima8.h"
 
 namespace Ultima {
 namespace Ultima8 {
@@ -80,13 +81,14 @@ bool DamageInfo::applyToItem(Item *item, uint16 points) const {
 		if (item)
 			item->destroy();
 	} else if (!explodeDestroysItem()) {
+		Common::RandomSource &rs = Ultima8Engine::get_instance()->getRandomSource();
 		if (frameDataIsAbsolute()) {
 			int frameval = 1;
 			if (_data[1])
 				frameval++;
 			if (_data[2])
 				frameval++;
-			item->setFrame(_data[getRandom() % frameval]);
+			item->setFrame(_data[rs.getRandomNumber(frameval - 1)]);
 		} else {
 			int frameoff = 0;
 			for (int i = 0; i < 3; i++)
@@ -96,7 +98,7 @@ bool DamageInfo::applyToItem(Item *item, uint16 points) const {
 				item->destroy();
 			} else {
 				uint32 frame = item->getFrame();
-				item->setFrame(frame + _data[getRandom() % frameoff]);
+				item->setFrame(frame + _data[rs.getRandomNumber(frameoff - 1)]);
 			}
 		}
 	}
diff --git a/engines/ultima/ultima8/world/fire_type.cpp b/engines/ultima/ultima8/world/fire_type.cpp
index 8ff9aeb3112..d5de56f0d8f 100644
--- a/engines/ultima/ultima8/world/fire_type.cpp
+++ b/engines/ultima/ultima8/world/fire_type.cpp
@@ -49,7 +49,8 @@ FireType::FireType(uint16 typeNo, uint16 minDamage, uint16 maxDamage, uint8 rang
 uint16 FireType::getRandomDamage() const {
 	if (_minDamage == _maxDamage)
 		return _minDamage;
-	return _minDamage + (getRandom() % (_maxDamage - _minDamage));
+	Common::RandomSource &rs = Ultima8Engine::get_instance()->getRandomSource();
+	return rs.getRandomNumberRng(_minDamage, _maxDamage);
 }
 
 
@@ -68,9 +69,10 @@ static const int16 FIRESHAPE_3_REG[] = { 0x326, 0x320, 0x321, 0x323 };
 static const int16 FIRESHAPE_10_REM[] = { 0x31c, 0x31f, 0x322 };
 static const int16 FIRESHAPE_10_REG[] = { 0x31c, 0x31f, 0x321 };
 
-#define RANDOM_ELEM(array) (array[getRandom() % ARRAYSIZE(array)])
+#define RANDOM_ELEM(array) (array[rs.getRandomNumber(ARRAYSIZE(array) - 1)])
 
 void FireType::makeBulletSplashShapeAndPlaySound(int32 x, int32 y, int32 z) const {
+	Common::RandomSource &rs = Ultima8Engine::get_instance()->getRandomSource();
 	int16 sfxno = 0;
 	int16 shape = 0;
 
@@ -83,7 +85,7 @@ void FireType::makeBulletSplashShapeAndPlaySound(int32 x, int32 y, int32 z) cons
 			break;
 		case 2:
 			shape = 0x1d8;
-			if (GAME_IS_REGRET && (getRandom() % 3 == 0)) {
+			if (GAME_IS_REGRET && (rs.getRandomNumber(2) == 0)) {
 				sfxno = RANDOM_ELEM(FIRESOUND_1);
 			}
 			break;
@@ -98,7 +100,7 @@ void FireType::makeBulletSplashShapeAndPlaySound(int32 x, int32 y, int32 z) cons
 		case 5:
 			shape = 0x537;
 			if (GAME_IS_REGRET) {
-				if (getRandom() % 2)
+				if (rs.getRandomBit())
 					sfxno = 0x164;
 				else
 					sfxno = 0x71;
@@ -122,7 +124,7 @@ void FireType::makeBulletSplashShapeAndPlaySound(int32 x, int32 y, int32 z) cons
 			break;
 		case 0xd:
 			shape = 0x1d8;
-			if (GAME_IS_REMORSE || (getRandom() % 4 == 0))
+			if (GAME_IS_REMORSE || (rs.getRandomNumber(3) == 0))
 				sfxno = RANDOM_ELEM(FIRESOUND_1);
 			break;
 		case 0xe:
@@ -176,7 +178,7 @@ void FireType::makeBulletSplashShapeAndPlaySound(int32 x, int32 y, int32 z) cons
 	// now randomize frames
 	switch (shape) {
 	case 0x56b:
-		firstframe = (getRandom() % 3) * 6;
+		firstframe = rs.getRandomNumber(2) * 6;
 		lastframe = firstframe + 5;
 		break;
 	case 0x537:
@@ -184,11 +186,11 @@ void FireType::makeBulletSplashShapeAndPlaySound(int32 x, int32 y, int32 z) cons
 		break;
 	case 0x578:
 	case 0x642:
-		firstframe = (getRandom() % 3) * 5;
+		firstframe = rs.getRandomNumber(2) * 5;
 		lastframe = firstframe + 4;
 		break;
 	case 0x59b:
-		firstframe = (getRandom() % 2) * 4;
+		firstframe = rs.getRandomNumber(1) * 4;
 		lastframe = firstframe + 3;
 		break;
 	case 0x641: // No Regret only
@@ -196,7 +198,7 @@ void FireType::makeBulletSplashShapeAndPlaySound(int32 x, int32 y, int32 z) cons
 		lastframe = 3;
 		break;
 	case 0x1d8: {
-		switch (getRandom() % 4) {
+		switch (rs.getRandomNumber(3)) {
 			case 0:
 				lastframe = 4;
 				break;
diff --git a/engines/ultima/ultima8/world/fireball_process.cpp b/engines/ultima/ultima8/world/fireball_process.cpp
index 45872a82261..708f661a913 100644
--- a/engines/ultima/ultima8/world/fireball_process.cpp
+++ b/engines/ultima/ultima8/world/fireball_process.cpp
@@ -68,7 +68,8 @@ void FireballProcess::run() {
 		return;
 	}
 
-	if (_age > 300 && (getRandom() % 20 == 0)) {
+	Common::RandomSource &rs = Ultima8Engine::get_instance()->getRandomSource();
+	if (_age > 300 && rs.getRandomNumber(19) == 0) {
 		// chance of 5% to disappear every frame after 10 seconds
 		terminate();
 		return;
@@ -135,7 +136,7 @@ void FireballProcess::run() {
 		Actor *hit = getActor(hititem);
 		if (hit) {
 			// hit an actor: deal damage and explode
-			hit->receiveHit(0, Direction_Invert(targetdir), 5 + (getRandom() % 5),
+			hit->receiveHit(0, Direction_Invert(targetdir), rs.getRandomNumberRng(5, 9),
 			                WeaponInfo::DMG_FIRE);
 			terminate();
 			return;
diff --git a/engines/ultima/ultima8/world/gravity_process.cpp b/engines/ultima/ultima8/world/gravity_process.cpp
index c04a22cf9f2..a5188a01708 100644
--- a/engines/ultima/ultima8/world/gravity_process.cpp
+++ b/engines/ultima/ultima8/world/gravity_process.cpp
@@ -171,11 +171,12 @@ void GravityProcess::run() {
 				_zSpeed = 0 - _zSpeed / 3;
 				int approx_v = ABS(_xSpeed) + ABS(_ySpeed) + _zSpeed;
 
+				Common::RandomSource &rs = Ultima8Engine::get_instance()->getRandomSource();
+
 				// Apply an impulse on the x/y plane in a random direction
 				// in a 180 degree pie around the original vector in x/y
 				double heading_r = atan2((double)_ySpeed, (double)_xSpeed);
-				double deltah_r = static_cast<double>(getRandom())
-				                  * M_PI / U8_RAND_MAX - M_PI / 2;
+				double deltah_r = static_cast<double>(rs.getRandomNumber(UINT_MAX)) * M_PI / UINT_MAX - M_PI / 2.0;
 #ifdef BOUNCE_DIAG
 				double headingold_r = heading_r;
 #endif
diff --git a/engines/ultima/ultima8/world/item.cpp b/engines/ultima/ultima8/world/item.cpp
index f886bb250f8..b8282cd8f6a 100644
--- a/engines/ultima/ultima8/world/item.cpp
+++ b/engines/ultima/ultima8/world/item.cpp
@@ -1209,6 +1209,7 @@ uint16 Item::fireWeapon(int32 x, int32 y, int32 z, Direction dir, int firetype,
 	if (!firetypedat)
 		return 0;
 
+	Common::RandomSource &rs = Ultima8Engine::get_instance()->getRandomSource();
 	int damage = firetypedat->getRandomDamage();
 
 	const Item *blocker = nullptr;
@@ -1245,7 +1246,7 @@ uint16 Item::fireWeapon(int32 x, int32 y, int32 z, Direction dir, int firetype,
 		spriteframe = 0x46;
 		break;
 	case 0xe:
-		spriteframe = 0x47 + getRandom() % 5;
+		spriteframe = 0x47 + rs.getRandomNumber(4);
 		break;
 	case 0xf:
 	case 0x12: // No Regret only
@@ -1779,14 +1780,15 @@ void Item::animateItem() {
 	if (!info->_animType)
 		return;
 
+	Common::RandomSource &rs = Ultima8Engine::get_instance()->getRandomSource();
 	uint32 anim_data = info->_animData;
 	const Shape *shp = getShapeObject();
 
 	switch (info->_animType) {
 	case 2:
 		// Randomly change frame
-		if ((getRandom() & 1) && shp)
-			_frame = getRandom() % shp->frameCount();
+		if (rs.getRandomBit() && shp)
+			_frame = rs.getRandomNumber(shp->frameCount() - 1);
 		break;
 
 	case 1:
@@ -1794,7 +1796,7 @@ void Item::animateItem() {
 		// animdata 0 = always increment
 		// animdata 1 = 50 % chance of changing
 		// animdata 2+ = loop in frame blocks of size animdata
-		if (anim_data == 0 || (anim_data == 1 && (getRandom() & 1))) {
+		if (anim_data == 0 || (anim_data == 1 && rs.getRandomBit())) {
 			_frame++;
 			if (shp && _frame >= shp->frameCount())
 				_frame = 0;
@@ -1809,7 +1811,7 @@ void Item::animateItem() {
 	case 4:
 		// Randomly start animating, with chance of 1/(animdata + 2)
 		// once animating, go through all frames.
-		if (_frame || getRandom() % (anim_data + 2)) {
+		if (_frame || rs.getRandomNumber(anim_data + 1)) {
 			_frame++;
 			if (shp && _frame >= shp->frameCount())
 				_frame = 0;
@@ -1825,7 +1827,7 @@ void Item::animateItem() {
 		// animdata 0 = stick on frame 0, else loop from 1 to count
 		// animdata 1 = same as 0, but with 50% chance of change
 		// animdata 2+ = same, but loop in frame blocks of size animdata
-		if (anim_data == 0 || (anim_data == 1 && (getRandom() & 1))) {
+		if (anim_data == 0 || (anim_data == 1 && rs.getRandomBit())) {
 			if (!_frame)
 				break;
 			_frame++;
@@ -2150,6 +2152,7 @@ void Item::hurl(int xs, int ys, int zs, int grav) {
 
 
 void Item::explode(int explosion_type, bool destroy_item, bool cause_damage) {
+	Common::RandomSource &rs = Ultima8Engine::get_instance()->getRandomSource();
 	Process *p;
 	int damage_divisor = 1;
 
@@ -2166,7 +2169,7 @@ void Item::explode(int explosion_type, bool destroy_item, bool cause_damage) {
 		int32 cx, cy, cz;
 		getCentre(cx, cy, cz);
 		static const int expshapes[] = {0x31C, 0x31F, 0x326, 0x320, 0x321, 0x324, 0x323, 0x325};
-		int rnd = getRandom();
+		int rnd = rs.getRandomNumber(UINT_MAX);
 		int spriteno;
 		// NOTE: The game does some weird 32-bit stuff to decide what
 		// shapenum to use.  Just simplified to a random.
@@ -2194,10 +2197,10 @@ void Item::explode(int explosion_type, bool destroy_item, bool cause_damage) {
 	if (audioproc) {
 		int sfx;
 		if (GAME_IS_CRUSADER) {
-			sfx = (getRandom() % 2) ? 28 : 108;
+			sfx = rs.getRandomBit() ? 28 : 108;
 			audioproc->stopSFX(-1, _objId);
 		} else {
-			sfx = (getRandom() % 2) ? 31 : 158;
+			sfx = rs.getRandomBit() ? 31 : 158;
 		}
 		audioproc->playSFX(sfx, 0x60, 0, 0);
 	}
@@ -2227,7 +2230,7 @@ void Item::explode(int explosion_type, bool destroy_item, bool cause_damage) {
 
 			item->getLocation(xv, yv, zv);
 			Direction dir = Direction_GetWorldDir(xv - xv, yv - yv, dirmode_8dirs); //!! CHECKME
-			item->receiveHit(0, dir, 6 + (getRandom() % 6),
+			item->receiveHit(0, dir, rs.getRandomNumberRng(6, 11),
 							 WeaponInfo::DMG_BLUNT | WeaponInfo::DMG_FIRE);
 		}
 	} else {
@@ -2327,8 +2330,9 @@ void Item::receiveHitCru(uint16 other, Direction dir, int damage, uint16 type) {
 	static const int hurl_x_factor[] = {  0, +1, +2, +2, +2, +2, +2, +1, 0, -1, -2, -2, -2, -2, -2, -1 };
 	static const int hurl_y_factor[] = { -2, -2, -2, -1,  0, +1, +2, +2, +2, +2, +2, +1, 0, -1, -2, -2 };
 
-	int xhurl = 10 + getRandom() % 15;
-	int yhurl = 10 + getRandom() % 15;
+	Common::RandomSource &rs = Ultima8Engine::get_instance()->getRandomSource();
+	int xhurl = rs.getRandomNumberRng(10, 24);
+	int yhurl = rs.getRandomNumberRng(10, 24);
 	hurl(-xhurl * hurl_x_factor[(int)dir], -yhurl * hurl_y_factor[(int)dir], 0, 2); //!! constants
 }
 
diff --git a/engines/ultima/ultima8/world/super_sprite_process.cpp b/engines/ultima/ultima8/world/super_sprite_process.cpp
index a9cf3733579..fcc17a4fbe7 100644
--- a/engines/ultima/ultima8/world/super_sprite_process.cpp
+++ b/engines/ultima/ultima8/world/super_sprite_process.cpp
@@ -102,12 +102,14 @@ SuperSpriteProcess::SuperSpriteProcess(int shape, int frame, int sx, int sy, int
 
 		if (rng > 0x50)
 			rng = 0x50;
-		int xoff = -rng + (getRandom() % (rng * 2 + 1));
-		int yoff = -rng + (getRandom() % (rng * 2 + 1));
+
+		Common::RandomSource &rs = Ultima8Engine::get_instance()->getRandomSource();
+		int xoff = rs.getRandomNumberRngSigned(-rng, rng);
+		int yoff = rs.getRandomNumberRngSigned(-rng, rng);
 		rng /= 3;
 		if (rng > 0x18)
 			rng = 0x18;
-		int zoff = -rng + (getRandom() % (rng * 2 + 1));
+		int zoff = rs.getRandomNumberRngSigned(-rng, rng);
 
 		_destpt.move(xoff, yoff, zoff);
 		if (_destpt.z > 0xfa)




More information about the Scummvm-git-logs mailing list