diff --git a/src/js/utilJS.js b/src/js/utilJS.js
index b15f8aacceca1f5aea2c30e320a6e04cbdab916c..ef3b9883654d38553f43afd8888e330ae4578cea 100644
--- a/src/js/utilJS.js
+++ b/src/js/utilJS.js
@@ -3217,3 +3217,22 @@ window.mapIdList = function(list) {
 	}
 	return mappedList;
 };
+
+/**
+ * Returns a "disobedience factor" between 0 (perfectly obedient) and 100 (completely defiant)
+ * @param {App.Entity.SlaveState} slave
+ * @returns {number}
+ */
+window.disobedience = function(slave) {
+	const devotionBaseline = 20; // with devotion above this number slaves will obey completely
+	const trustBaseline = -20; // with trust below this number slaves will obey completely
+
+	if (slave.devotion > devotionBaseline || slave.trust < trustBaseline) {
+		return 0; // no chance of disobedience
+	}
+
+	// factors are between 0 (right on the boundary of perfectly obedient) and 10 (completely disobedient)
+	let devotionFactor = 10 - ((10 * (slave.devotion + 100))/(devotionBaseline + 100));
+	let trustFactor = (10 * (slave.trust - trustBaseline))/(100 - trustBaseline);
+	return Math.round(devotionFactor * trustFactor);
+};