diff --git a/src/004-base/proxies.js b/src/004-base/proxies.js
index 9ce94c7366f622e34bf28802f616152f3dc35320..e271aa87d62bcb6d30f0f25ed1fc674a65537614 100644
--- a/src/004-base/proxies.js
+++ b/src/004-base/proxies.js
@@ -1,36 +1,93 @@
 window.createReadonlyProxy = function(target) {
 	if (target.__isReadonlyProxy) { return target; }
-	return new Proxy(target, {
-		get: function(o, prop) {
-			if (prop == '__isReadonlyProxy') { return true; }
-			return createReadonlyProxy(o[prop]);
-		},
-		set: function(o, prop, value) {
-			return false;
-		},
-		deleteProperty: function(o, prop) {
-			return false;
-		}
-	});
+	if (_.isArray(target)) {
+		return new Proxy(target, {
+			get:function(o, prop) {
+			const val = o[prop];
+				if (typeof val === 'function') {
+					if (['push', 'unshift', 'pop'].includes(prop)) {
+						return function () {
+							throw Error("Cannot modify a readonly array");
+						}
+					}
+					return val.bind(target);
+				}
+				return createReadonlyProxy(val);
+			},
+			set:function(o, prop, value) {
+				return true;
+			},
+			deleteProperty:function(o, prop) {
+				return true;
+			}
+		});
+	}
+	if (_.isObject(target)) {
+		return new Proxy(target, {
+			get:function(o, prop) {
+				if(prop == '__isReadonlyProxy') { return true; }
+				return createReadonlyProxy(o[prop]);
+			},
+			set:function(o, prop, value) {
+				return true;
+			},
+			deleteProperty:function(o, prop) {
+				return true;
+			}
+		});
+	}
+	return target;
 };
 window.createCheatProxy = function(target) {
 	if (target.__isCheatProxy) { return target; }
-	return new Proxy(target, {
-		get: function(o, prop) {
-			if (prop == '__isCheatProxy') { return true; }
-			return createCheatProxy(o[prop]);
-		},
-		set: function(o, prop, value) {
-			o[prop] = value;
-			State.variables.cheater = 1;
-			return true;
-		},
-		deleteProperty: function(o, prop) {
-			delete o[prop];
-			State.variables.cheater = 1;
-			return false;
-		}
-	});
+	if (_.isArray(target)) {
+		return new Proxy(target, {
+			get:function(o, prop) {
+				const val = o[prop];
+				if (typeof val === 'function') {
+					if (['push', 'unshift', 'pop'].includes(prop)) {
+						return function (el) {
+							const retval = Array.prototype[prop].apply(o, arguments);
+							//Make sure we set cheater after calling the function
+							State.variables.cheater = 1;
+							return retval;
+						}
+					}
+					return val.bind(target);
+				}
+				return createCheatProxy(val);
+			},
+			set:function(o, prop, value) {
+				o[prop] = value;
+				State.variables.cheater = 1;
+				return true;
+			},
+			deleteProperty:function(o, prop) {
+				delete o[prop];
+				State.variables.cheater = 1;
+				return true;
+			}
+		});
+	}
+	if (_.isObject(target)) {
+		return new Proxy(target, {
+			get:function(o, prop) {
+				if(prop == '__isCheatProxy') { return true; }
+				return createCheatProxy(o[prop]);
+			},
+			set:function(o, prop, value) {
+				o[prop] = value;
+				State.variables.cheater = 1;
+				return true;
+			},
+			deleteProperty:function(o, prop) {
+				delete o[prop];
+				State.variables.cheater = 1;
+				return true;
+			}
+		});
+	}
+	return target;
 };
 Object.defineProperty(window, "V", {
 	get: function() {
@@ -38,18 +95,20 @@ Object.defineProperty(window, "V", {
 		return State.variables;
 	}
 });
+//This should be used if the user might use V under normal, non-cheating circumstances but shouldn't be punished for accidentally setting the value. The attempt to make the change will simply be disregarded.
 window.runWithReadonlyProxy = function(callback) {
 	window.storyProxy = createReadonlyProxy(State.variables);
 	try {
-		callback();
+		return callback();
 	} finally {
 		window.storyProxy = null;
 	}
 };
+// This should be used if setting values would constitute cheating. For example, a debug view that shows all variables in an editable form; showing isn't cheating, but making a change would be.
 window.runWithCheatProxy = function(callback) {
 	window.storyProxy = createCheatProxy(State.variables);
 	try {
-		callback();
+		return callback();
 	} finally {
 		window.storyProxy = null;
 	}
diff --git a/src/js/DefaultRules.js b/src/js/DefaultRules.js
index ad0ec052a1263b54b0acff0a2969e7f30c922c34..2e340cab4cff0ed901d637e1ad7c54ee46e08fcd 100644
--- a/src/js/DefaultRules.js
+++ b/src/js/DefaultRules.js
@@ -16,7 +16,8 @@ window.DefaultRules = (function() {
 		if (slave.useRulesAssistant === 0) { return r; } // exempted
 		r = "";
 		({he, him, his} = getPronouns(slave));
-		let rule = MergeRules(slave);
+		let slaveReadOnly = createReadonlyProxy(slave);
+		let rule = runWithReadonlyProxy(()=>MergeRules(slaveReadOnly));
 		if (Object.keys(rule).length === 0) { return r; } // no rules apply
 
 		AssignJobToSlave(slave, rule);