diff --git a/src/js/random.js b/src/js/random.js
new file mode 100644
index 0000000000000000000000000000000000000000..1f7f6c4812f4c9c3119d8d9ea885320bc64f2189
--- /dev/null
+++ b/src/js/random.js
@@ -0,0 +1,75 @@
+/**
+ * generate two independent Gaussian numbers using Box-Muller transform.
+ * mean and deviation specify the desired mean and standard deviation.
+ * @returns {number[]}
+ */
+window.gaussianPair = function(mean = 0, deviation = 1) {
+	const r = Math.sqrt(-2.0 * Math.log(1 - Math.random()));
+	const sigma = 2.0 * Math.PI * (1 - Math.random());
+	return [r * Math.cos(sigma), r * Math.sin(sigma)].map(val => val * deviation + mean);
+};
+
+// Generate a random integer with a normal distribution between min and max (both inclusive).
+// Default parameters result in truncating the standard normal distribution between -3 and +3.
+// Not specifying min/max results in rerolling val approximately 0.3% of the time.
+window.normalRandInt = function(mean = 0, deviation = 1, min = mean - 3 * deviation, max = mean + 3 * deviation) {
+	let val = gaussianPair(mean, deviation)[0];
+	while (val < min || val > max) {
+		val = gaussianPair(mean, deviation)[0];
+	}
+	return Math.round(val);
+}
+
+/**
+ * Returns a random integer between min and max (both inclusive).
+ * If count is defined, chooses that many random numbers between min and max and returns the average. This is an approximation of a normal distribution.
+ * @param {number} min
+ * @param {number} max
+ * @returns {number}
+ */
+window.jsRandom = function(min, max, count = 1) {
+	function rand() {
+		return Math.random() * (max - min + 1) + min;
+	}
+
+	if (count === 1) {
+		return Math.floor(rand());
+	}
+
+	let total = 0;
+	for (let i = 0; i < count; i++) {
+		total += rand();
+	}
+	return Math.floor(total/count);
+};
+
+/**
+ * Chooses multiple random elements of an array.
+ * @param {number[]} arr
+ * @param {number} count
+ * @returns {number[]}
+ */
+window.jsRandomMany = function(arr, count) {
+	let result = [];
+	let _tmp = arr.slice();
+	for (let i = 0; i < count; i++) {
+		let index = Math.floor(Math.random() * _tmp.length);
+		result.push(_tmp.splice(index, 1)[0]);
+	}
+	return result;
+};
+
+/**
+ * Accepts both an array and a list, returns undefined if nothing is passed.
+ * @param {number|string|number[]|string[]} choices
+ * @param {...(number|string|number[]|string[])} otherChoices
+ * @returns {number|string|number[]|string[]|undefined}
+ */
+window.jsEither = function(choices, ...otherChoices) {
+	if (otherChoices.length === 0 && Array.isArray(choices)) {
+		return choices[Math.floor(Math.random() * choices.length)];
+	}
+	const allChoices = otherChoices;
+	allChoices.push(choices);
+	return allChoices[Math.floor(Math.random() * allChoices.length)];
+};
diff --git a/src/js/utilJS.js b/src/js/utilJS.js
index e3c55587afe30d6d4d093d1c7c64e6387d4008cc..8dc1e4ab0ad6f3f5064405069fce3dfe5a9ee726 100644
--- a/src/js/utilJS.js
+++ b/src/js/utilJS.js
@@ -881,19 +881,6 @@ window.Intelligence = (function() {
 	};
 })();
 
-/**
- * Helper method - generate two independent Gaussian numbers using Box-Muller transform
- * @returns {number[]}
- */
-window.gaussianPair = function() {
-	let r = Math.sqrt(-2.0 * Math.log(1 - Math.random()));
-	let sigma = 2.0 * Math.PI * (1 - Math.random());
-	return [r * Math.cos(sigma), r * Math.sin(sigma)];
-};
-
-// generate a random integer with a normal distribution
-window.normalRandInt = (mean, scale) => Math.floor(mean + gaussianPair()[0] * scale);
-
 /*
 A categorizer is used to "slice" a value range into distinct categories in an efficient manner.
 
@@ -1289,46 +1276,6 @@ window.isFloat = function(n) {
 	return Number.isFinite(n) && Math.floor(n) !== n;
 };
 
-/**
- * Returns a random number between min and max
- * @param {number} min
- * @param {number} max
- * @returns {number}
- */
-window.jsRandom = function(min, max) {
-	return Math.floor(Math.random() * (max - min + 1) + min);
-};
-
-/**
- * @param {number[]} arr
- * @param {number} count
- * @returns {number[]}
- */
-window.jsRandomMany = function(arr, count) {
-	let result = [];
-	let _tmp = arr.slice();
-	for (let i = 0; i < count; i++) {
-		let index = Math.ceil(Math.random() * 10) % _tmp.length;
-		result.push(_tmp.splice(index, 1)[0]);
-	}
-	return result;
-};
-
-/**
- * Accepts both an array and a list, returns undefined if nothing is passed.
- * @param {number|string|number[]|string[]} choices
- * @param {...(number|string|number[]|string[])} otherChoices
- * @returns {number|string|number[]|string[]|undefined}
- */
-window.jsEither = function(choices, ...otherChoices) {
-	if (otherChoices.length === 0 && Array.isArray(choices)) {
-		return choices[Math.floor(Math.random() * choices.length)];
-	}
-	const allChoices = otherChoices;
-	allChoices.push(choices);
-	return allChoices[Math.floor(Math.random() * allChoices.length)];
-};
-
 /*
 Make everything waiting for this execute. Usage: