From 19843a00b132665c6cc3dbc603e6fae8ced21ea6 Mon Sep 17 00:00:00 2001
From: Pregmodder <pregmodder@gmail.com>
Date: Sat, 23 Jun 2018 14:33:51 -0400
Subject: [PATCH] fixes

---
 devNotes/VersionChangeLog-Premod+LoliMod.txt |    5 +
 devNotes/twine CSS                           |   23 +
 devNotes/twine JS                            | 8516 ++++++++++++++----
 src/pregmod/widgets/bodySwapReaction.tw      |    6 +-
 src/pregmod/widgets/seBirthWidgets.tw        |    2 +
 src/uncategorized/longSlaveDescription.tw    |    2 +-
 src/uncategorized/newSlaveIntro.tw           |    4 +-
 src/uncategorized/reMalefactor.tw            |    2 +-
 8 files changed, 7018 insertions(+), 1542 deletions(-)

diff --git a/devNotes/VersionChangeLog-Premod+LoliMod.txt b/devNotes/VersionChangeLog-Premod+LoliMod.txt
index d04591b1fbe..5f2674e4c4a 100644
--- a/devNotes/VersionChangeLog-Premod+LoliMod.txt
+++ b/devNotes/VersionChangeLog-Premod+LoliMod.txt
@@ -4,6 +4,11 @@
 
 6/22/2018
 
+	2
+	-various fixes to the RA
+	-various additions to the RA
+	-other fixes
+
 	1
 	-vas's total RA overhaul
 	-various little fixes and tweaks
diff --git a/devNotes/twine CSS b/devNotes/twine CSS
index ff4365aaf12..b4d4513e589 100644
--- a/devNotes/twine CSS	
+++ b/devNotes/twine CSS	
@@ -84,6 +84,7 @@ img {
 	height: 100%;
 	background: linear-gradient(90deg, rgba(17,17,17,1), rgba(17,17,17,0.8) 60%, rgba(17,17,17,0));
 	z-index: 1;
+	/*position: absolute;*/
 }
 
 .lrgRender > img, .lrgRender > video {
@@ -257,6 +258,28 @@ max-width: 100%;
 word-break: break-all;
 white-space: normal;
 }
+/* css rules for rules assistant */
+.rajs-listitem {
+	display: inline-block;
+	color: #68D;
+	margin-right: 1em;
+}
+.rajs-listitem:last-of-type { margin-right: 0; }
+.rajs-listitem:hover {
+	cursor: pointer;
+	text-decoration: underline;
+}
+.rajs-list strong:first-of-type, .rajs-list input {
+	margin-right: 2em;
+}
+.rajs-listitem input {
+	margin: 0.25em;
+}
+.rajs-section h1 {
+	border-bottom: 1px solid white;
+	cursor: pointer;
+}
+.rajs-section h1:hover { text-decoration: underline; }
 
 /*:: accordionStyleSheet [stylesheet]*/
 /* Accordion 000-250-006 */
diff --git a/devNotes/twine JS b/devNotes/twine JS
index 8449c0e28c3..2cca73226be 100644
--- a/devNotes/twine JS	
+++ b/devNotes/twine JS	
@@ -1436,141 +1436,27 @@ window.getIncubatorReserved = function(slaves) {
 	return count;
 }
 
-/*:: RA Selector JS [script]*/
+/*:: SetBellySize [script]*/
 
-window.growAdvSelector = function(slave, rule) {
+window.SetBellySize = function SetBellySize(slave) {
+	let _implantSize
+	WombNormalizePreg(slave) /*now with support for legacy code that advance pregnancy by setting .preg++ */ 
 
-	var ret = "";
-	var setd = 0;
-
-	if ((rule.breastSize == "small" && slave.boobs < 350) ||
-		(rule.breastSize == "c-cup" && slave.boobs < 550) ||
-		(rule.breastSize == "f-cup" && slave.boobs < 1100) ||
-		(rule.breastSize == "k-cup" && slave.boobs < 2150) ||
-		(rule.breastSize == "p-cup" && slave.boobs < 3700) ||
-		(rule.breastSize == "unlimited" && slave.boobs < 24000))	
-	{ 
-		slave.drugs = "breast injections"; 
-		ret = slave.slaveName + "'s boobs could be bigger, so she's been put on breast injections.";
-		return ret;
-	}
-	
-	if ((rule.buttSize == "small" && slave.butt < 1) ||
-		(rule.buttSize == "plump" && slave.butt < 3) ||
-		(rule.buttSize == "huge" && slave.butt < 4) ||
-		(rule.buttSize == "enormous" && slave.butt < 6) ||
-		(rule.buttSize == "unlimited" && slave.butt < 19))	
-	{ 
-		slave.drugs = "butt injections"; 
-		ret = slave.slaveName + "'s butt could be bigger, so she's been put on butt injections.";
-		return ret;
-	}
-
-	if (slave.balls > 0 &&
-		((rule.ballSize == "small" && slave.balls < 2) ||
-		 (rule.ballSize == "big" && slave.balls < 4) ||
-		 (rule.ballSize == "huge" && slave.balls < 6) ||
-		 (rule.ballSize == "unlimited" && slave.balls < 9)))	
-	{ 
-		slave.drugs = "testicle enhancement"; 
-		ret = slave.slaveName + "'s balls aren't large enough, so she's been put on testicle enhancement.";
-		return ret;
-	}
-
-	if (slave.dick > 0 &&
-		((rule.penisSize == "small" && slave.dick < 2) ||
-		 (rule.penisSize == "big" && slave.dick < 4) ||
-		 (rule.penisSize == "huge" && slave.dick < 6) ||
-		 (rule.penisSize == "unlimited" && slave.dick < 12)))
-	{ 
-		slave.drugs = "penis enhancement"; 
-		ret = slave.slaveName + "'s dick isn't large enough, so she's been put on penis enhancement.";
-		return ret;
-	}
-
-	if ((rule.lipSize == "normal" && slave.lips < 15) ||
-		(rule.lipSize == "pretty" && slave.lips < 30) ||
-		(rule.lipSize == "plush" && slave.lips < 55) ||
-		(rule.lipSize == "huge" && slave.lips < 85) ||
-		(rule.lipSize == "facepussy" && slave.lips < 99))	
-	{ 
-		slave.drugs = "lip injections"; 
-		ret = slave.slaveName + "'s lips aren't large enough, so she's been put on lips enhancement.";
-		return ret;
-	}
-
-	if (slave.drugs != "no drugs")
-	{
-		slave.drugs = "no drugs";
-		ret = slave.slaveName + " has reached growth targets and has been taken off growth injections.";
-	}
-
-	return ret;
-
-}
-
-window.growAdvSelectorSlim = function(slave, rule) {
-
-	var ret = "";
-	var setd = 0;
-
-	if ((rule.breastSize == "small" && slave.boobs > 350) ||
-		(rule.breastSize == "c-cup" && slave.boobs > 550) ||
-		(rule.breastSize == "f-cup" && slave.boobs > 1100) ||
-		(rule.breastSize == "k-cup" && slave.boobs > 2150) ||
-		(rule.breastSize == "p-cup" && slave.boobs > 3700))	
-	{ 
-		slave.drugs = "breast redistributors"; 
-		ret = slave.slaveName + "'s boobs are too big, so she's been put on breast reduction drugs.";
-		return ret;
-	}
+	if (slave.bellyImplant > 0)
+		_implantSize = slave.bellyImplant
+	else
+		_implantSize = 0
+		
+	if (slave.inflation == 3)	
+		slave.bellyFluid = 10000
+	else if (slave.inflation == 2)
+		slave.bellyFluid = 5000
+	else if (slave.inflation == 1)
+		slave.bellyFluid = 2000
+	else
+		slave.bellyFluid = 0
 	
-	if ((rule.buttSize == "small" && slave.butt > 1) ||
-		(rule.buttSize == "plump" && slave.butt > 3) ||
-		(rule.buttSize == "huge" && slave.butt > 4) ||
-		(rule.buttSize == "enormous" && slave.butt > 6))	
-	{ 
-		slave.drugs = "butt redistributors"; 
-		ret = slave.slaveName + "'s butt is too big, so she's been put on butt reduction drugs.";
-		return ret;
-	}
-
-	if ((rule.ballSize == "small" && slave.balls > 2) ||
-		(rule.ballSize == "big" && slave.balls > 4) ||
-		(rule.ballSize == "huge" && slave.balls > 6))	
-	{ 
-		slave.drugs = "testicle atrophiers"; 
-		ret = slave.slaveName + "'s balls are too big, so she's been put on testicle atrophiers.";
-		return ret;
-	}
-
-	if ((rule.penisSize == "small" && slave.dick > 2) ||
-		(rule.penisSize == "big" && slave.dick > 4) ||
-		(rule.penisSize == "huge" && slave.dick > 6))	
-	{ 
-		slave.drugs = "penis atrophiers"; 
-		ret = slave.slaveName + "'s dick is too big, so she's been put on penis atrophiers.";
-		return ret;
-	}
-
-	if ((rule.lipSize == "normal" && slave.lips > 15) ||
-		(rule.lipSize == "pretty" && slave.lips > 30) ||
-		(rule.lipSize == "plush" && slave.lips > 55) ||
-		(rule.lipSize == "huge" && slave.lips > 85))	
-	{ 
-		slave.drugs = "lip atrophiers"; 
-		ret = slave.slaveName + "'s lips are too big, so she's been put on lips atrophiers.";
-		return ret;
-	}
-
-	if (slave.drugs != "no drugs")
-	{
-		slave.drugs = "no drugs";
-		ret = slave.slaveName + " has reached growth targets and has been taken off growth injections.";
-	}
-
-	return ret;
-
+	slave.belly = slave.bellyPreg+slave.bellyFluid+_implantSize
 }
 
 /*:: rbuttonJS [script]*/
@@ -2389,711 +2275,323 @@ Number.prototype.toFixedHTML = function() {
 
 /*:: rulesAssistant [script]*/
 
-function panic(message) {
-    message = message || "panic";
-    if (typeof Error !== "undefined") {
-        throw new Error(message);
-    }
-    throw message;
-}
-
-function assert(condition, message) {
-    if (!condition)
-        panic(message || "Assertion failed");
-}
-
-
-window.isSimpleCondition = function(expr, validNames) {
-    assert(validNames, "validNames was not given");
-
-    switch (expr.id) {
-    case "true": case "false":
-        return true;
-
-    case "<": case "<=": case ">": case ">=":
-        return (
-            expr.first.id === "(name)"              // first operand should be a name
-            && validNames.includes(expr.first.name) // among the valid ones
-            && expr.second.id === "(number)"        // and second should be a literal
-        );
-
-    case "&&": case "||":
-        return (
-            (expr.first.id == "<" || expr.first.id == "<=")
-            && (expr.second.id == ">" || expr.second.id == ">=")
-            && isSimpleCondition(expr.first, validNames)
-            && isSimpleCondition(expr.second, validNames)
-            && expr.first.first.name === expr.second.first.name
-        );
-    }
-    return false;
-}
-
-
-window.getVariable = function(expr) {
-    switch (expr.id) {
-    case "true":
-        return "always";
-    case "false":
-        return "none";
-    case "<": case "<=": case ">": case ">=":
-        return expr.first.name === "energy" ? "sex drive" : expr.first.name;
-    case "&&": case "||":
-        return getVariable(expr.first);
-    }
-}
-
-window.changeVariable = function(expr, newVar) {
-    //assert(isSimpleCondition(expr), "expr is not simple");
-
-    switch (expr.id) {
-    case "true": case "false":
-        return {
-            id: "<",
-            first: {id: "(name)", name: newVar},
-            second: {id: "(number)", value: 0}
-        };
-
-    case "<": case "<=": case ">": case ">=":
-        expr.first.name = newVar;
-        return expr;
-
-    case "&&": case "||":
-        expr.first.first.name = newVar;
-        expr.second.first.name = newVar;
-        return expr;
-    }
-}
-
-
-window.changeComparison = function(expr, newComparison) {
-    assert(expr.id !== "true" && expr.id !== "false", "expr is constant");
-    //assert(isSimpleCondition(expr), "expr is not simple");
-
-    var newOperand = {
-        id: newComparison,
-        first: {id: "(name)", name: expr.first.name},
-        second: {id: "(number)", value: 0}
-    };
-
-    if (newComparison === "<" || newComparison === "<=") {
-        switch (expr.id) {
-        case "<": case "<=":
-            expr.id = newComparison;
-            return expr;
-        case ">": case ">=":
-            return { id: "&&", first: newOperand, second: expr };
-        case "&&": case "||":
-            expr.first.id = newComparison;
-            return expr;
-        }
-    } else {
-        switch (expr.id) {
-        case "<": case "<=":
-            return { id: "&&", first: expr, second: newOperand };
-        case ">": case ">=":
-            expr.id = newComparison;
-            return expr;
-        case "&&": case "||":
-            expr.second.id = newComparison;
-            return expr;
-        }
-    }
-}
-
-window.removeComparison = function(expr, comparisonType) {
-    assert(expr.id !== "true" && expr.id !== "false", "expr is constant");
-    //assert(isSimpleCondition(expr), "expr is not simple");
-    assert(comparisonType === "lower" || comparisonType === "upper",
-           "invalid comparisonType '" + comparisonType + "'");
-
-    if (comparisonType === "lower") {
-        switch (expr.id) {
-        case "<": case "<=":
-            return expr;
-        case ">": case ">=":
-            return { id: "true" };
-        case "&&": case "||":
-            return expr.first;
-        }
-    } else {
-        switch (expr.id) {
-        case "<": case "<=":
-            return { id: "false" };
-        case ">": case ">=":
-            return expr;
-        case "&&": case "||":
-            return expr.second;
-        }
-    }
-}
-
-
-window.changeConnective = function(expr, newConnective) {
-    switch (expr.id) {
-    case "true": case "false":
-    case "<": case "<=": case ">": case ">=":
-        return expr;
-    case "&&": case "||":
-        expr.id = newConnective;
-        return expr;
-    }
-}
-
-
-window.unparseExpr = function(expr) {
-    switch (expr.id) {
-
-    // literals
-    case "true":
-        return "true";
-    case "false":
-        return "false";
-	case "(number)": 
-		return expr.value;
-	case "(string)":
-		return '"' + expr.value + '"';
-
-    // names
-    case "(name)":
-        return expr.name;
-
-    // logical infix operators
-    case "&&": case "||":
-    // numerical infix comperators
-    case "<": case "<=":
-    case ">": case ">=":
-    case "=": case "!=":
-    // numerical infix operators (excluding minus)
-    case "+": case "*": case "/": case "^":
-        return [unparseExpr(expr.first),
-                expr.id,
-                unparseExpr(expr.second)].join(" ");
-
-    // unary/prefix operators
-    case "!":
-        return expr.id + unparseExpr(expr.first);
-
-    case "-":
-        if (expr.second !== undefined) {
-            return unparseExpr(expr.first) + " - " + unparseExpr(expr.second);
-        } else {
-            return "-" + unparseExpr(expr.first);
-        }
-
-    // parentheses
-    case "(":
-        return "(" + unparseExpr(expr.first) + ")";
-    }
-
-    panic("how did I get here? unknown expr.id: " + expr.id);
-}
-
-window.typeExpr = function(expr, env) {
-    switch (expr.id) {
-
-    case "true": case "false":
-        return "bool";
-    case "(number)":
-        return "number";
-    case "(string)":
-        return "string";
-
-    case "(name)":
-        return env[expr.name];
-
-    case "&&": case "||":
-        return "bool";
-
-    case "<": case "<=":
-    case ">": case ">=":
-        return "bool";
-    case "=": case "!=":
-        return "bool";
-
-    case "*": case "/":  case "^":
-        return "number";
-
-    case "+":
-        return typeExpr(expr.first, env) === "string" ? "string" : "number";
-
-    case "!":
-        return typeExpr(expr.first, env);
-    case "-":
-        if (expr.second !== undefined) {
-            return "number";
-        } else {
-            return typeExpr(expr.first, env);
-        }
-
-    case "(":
-        return typeExpr(expr.first, env);
-    }
-}
-
-window.evalExpr = function(expr, env) {
-    switch (expr.id) {
-
-    case "true":
-        return true;
-    case "false":
-        return false;
-    case "(number)":
-        return expr.value;
-	case "(string)":
-		if(expr.value.startsWith('"') && expr.value.endsWith('"')) {
-			return JSON.parse(expr.value);
-		} else {
-			return expr.value;
-		}
-    case "(name)":
-        return env[expr.name];
-
-    case "&&":
-        return evalExpr(expr.first, env) && evalExpr(expr.second, env);
-    case "||":
-        return evalExpr(expr.first, env) || evalExpr(expr.second, env);
-    case "<":
-        return evalExpr(expr.first, env) < evalExpr(expr.second, env);
-    case "<=":
-        return evalExpr(expr.first, env) <= evalExpr(expr.second, env);
-    case ">":
-        return evalExpr(expr.first, env) > evalExpr(expr.second, env);
-    case ">=":
-        return evalExpr(expr.first, env) >= evalExpr(expr.second, env);
-    case "=":
-        return evalExpr(expr.first, env) == evalExpr(expr.second, env);
-    case "!=":
-        return evalExpr(expr.first, env) != evalExpr(expr.second, env);
-
-    case "+":
-        return evalExpr(expr.first, env) + evalExpr(expr.second, env);
-    case "*":
-        return evalExpr(expr.first, env) * evalExpr(expr.second, env);
-    case "/":
-        return evalExpr(expr.first, env) / evalExpr(expr.second, env);
-    case "^":
-        return Math.pow(evalExpr(expr.first, env), evalExpr(expr.second, env));
-
-    case "!":
-        return !evalExpr(expr.first, env);
-    case "-":
-        if (expr.second !== undefined) {
-            return evalExpr(expr.first, env) - evalExpr(expr.second, env);
-        } else {
-            return -evalExpr(expr.first, env);
-        }
-
-    case "(":
-        return evalExpr(expr.first, env);
-    }
-}
-
-
-window.optimizeExpr = function(expr) {
-    switch (expr.id) {
-    case "true": case "false":
-    case "(number)": case "(string)":
-    case "(name)":
-        return expr;
-
-    case "-":
-        // The only "optimization" we are doing.  Obviously, this is not done
-        // for the sake of speed, rather, to make the UI and isSimpleCondition
-        // simpler, since they don't have to explicitly check for negative
-        // numbers.
-        if (expr.second === undefined && expr.first.id === "(number)")
-            return {id: "(number)", value: evalExpr(expr)};
-        // fallthrough, if the minus was not unary
-
-    case "&&": case "||":
-    case "<": case "<=": case ">": case ">=":
-    case "=": case "!=":
-    case "+": case "*": case "/": case "^":
-        return {
-            id: expr.id,
-            first: optimizeExpr(expr.first),
-            second: optimizeExpr(expr.second)
-        };
-
-    case "!": case "(":
-        return {
-            id: expr.id,
-            first: optimizeExpr(expr.first)
-        };
-    }
-}
-
-window.printError = function(exprStr, error) {
-    var result = [],
-        inError = false;
-    for (var i = 0; i < exprStr.length; i++) {
-        if (i === error.index)
-            result.push("@@.red;");
-        result.push(exprStr[i]);
-    }
-    result.push("@@");
-    return result.join("");
-}
-
-/*:: rulesAssistantParser.tw [script]*/
-
-// Implements a Top Down Operator Precedence parser, also know as a Pratt
-// parser, after its "inventor", Vaughan Pratt.  The one implemented here
-// closely follows what's presented here,
-//     * http://javascript.crockford.com/tdop/tdop.html
-// by Douglas Crockford, that uses that technique in JSLint.  Other relevant
-// resources on the interweb
-//     * http://effbot.org/zone/simple-top-down-parsing.htm
-//     * http://eli.thegreenplace.net/2010/01/02/top-down-operator-precedence-parsing
-//     * http://journal.stuffwithstuff.com/2011/03/19/pratt-parsers-expression-parsing-made-easy/
-//     * https://higherlogics.blogspot.gr/2009/11/extensible-statically-typed-pratt.html
-//     * https://github.com/fholm/Vaughan
-//     * https://github.com/DasIch/pratt
-// included here mostly as bookmarks for potential future reference.
-//
-// With regards to the lexer, I used the following with many changes
-//     * http://eli.thegreenplace.net/2013/06/25/regex-based-lexical-analysis-in-python-and-javascript/
-//
-// Other useful things that I may not use any more but wouldn't want to lose,
-//     * https://plainjs.com/javascript/utilities/merge-two-javascript-objects-19/
-//     * https://developer.mozilla.org/en-US/docs/Web/JavaScript/Guide/Regular_Expressions
-
-
-if (!RegExp.escape) {
-    RegExp.escape = function(s) {
-        return s.replace(/[.*+?^${}()|[\]\\]/g, "\\$&");
-    };
-}
-
-if (!String.prototype.format) {
-    String.prototype.format = function() {
-        var args = arguments;
-        return this.replace(/{(\d+)}/g, function(match, number) {
-            return typeof args[number] !== "undefined" ? args[number] : match;
-        });
-    };
-}
-
-function panic(index, msg) {
-    throw {index: index, message: msg};
-}
-
-
-
-var Lexer = function(skipWhitespace) {
-    this.rules = [];
-    this.index = 0;
-    this.buffer = "";
-    this.skipWhitespace = skipWhitespace ? /\S/ : null;
-}
-
-Lexer.prototype.addRule = function(id, defn) {
-    var pattern = (defn && defn.pattern) || RegExp.escape(id);
-    this.rules.push({
-        id: id,
-        pattern: new RegExp('^' + pattern)
-    });
-}
-
-Lexer.prototype.feed = function(buffer) {
-    this.buffer = buffer;
-    this.index = 0;
-}
-
-Lexer.prototype.nextInterestingChar = function() {
-    if (this.skipWhitespace) {
-        var match = this.skipWhitespace.exec(this.buffer.substr(this.index));
-        return match ? this.index + match.index
-                     : this.buffer.length;
-    }
-    return this.index;
-}
-
-Lexer.prototype.next = function() {
-    this.index = this.nextInterestingChar();
-
-    if (this.index >= this.buffer.length)
-        return { done: true };
-
-    for (var i = 0; i < this.rules.length; ++i) {
-        var rule = this.rules[i],
-            match = rule.pattern.exec(this.buffer.substr(this.index));
-        if (match) {
-            var token = {
-                id: rule.id,
-                value: match[0],
-                index: this.index,
-            };
-            this.index += token.value.length;
-            return { done: false, value: token };
-        }
-    }
-
-    panic(this.index, "illegal character");
-}
-
-
-
-var BaseSymbol = {
-    lbp: 0,
-    nud: function() { panic(this.index, "unexpected '" + this.id + "'"); },
-    led: function() { panic(this.index, "not an operator"); }
+window.hasSurgeryRule = function(slave, rules) {
+	return rules.some(
+		rule => ruleApplied(slave, rule.ID) && rule.autoSurgery > 0);
 };
 
-var Parser = function(eofToken) {
-    this.lexer = new Lexer(true);
-    this.currentSymbol = null;
-
-    this.eofToken = eofToken;
-    this.symbolTable = {
-        [this.eofToken]: Object.create(BaseSymbol, {id: {value: this.eofToken}})
-    };
-}
-
-Parser.prototype.addSymbol = function(id, defn) {
-    var s = this.symbolTable[id];
-    if (s) {
-        if (defn) {
-            if (defn.lbp !== undefined) s.lbp = defn.lbp;
-            if (defn.nud !== undefined) s.nud = defn.nud;
-            if (defn.led !== undefined) s.led = defn.led;
-        }
-    } else {
-        s = Object.create(BaseSymbol);
-        s.id = id;
-        if (defn && defn.lbp !== undefined) s.lbp = defn.lbp;
-        if (defn && defn.nud) s.nud = defn.nud;
-        if (defn && defn.led) s.led = defn.led;
-        this.symbolTable[id] = s;
-        this.lexer.addRule(id, defn);
-    }
-    return this;
-}
-
-Parser.prototype.addInfix = function(id, lbp, callback) {
-    this.addSymbol(id, {
-        lbp: lbp,
-        led: function(p, left) { return callback(this, left, p.parse(lbp)); }
-    });
-    return this;
-}
-
-Parser.prototype.addInfixR = function(id, lbp, callback) {
-    this.addSymbol(id, {
-        lbp: lbp,
-        led: function(p, left) { return callback(this, left, p.parse(lbp-1)); }
-    });
-    return this;
-}
-
-Parser.prototype.addPrefix = function(id, callback) {
-    this.addSymbol(id, {
-        // FIXME: this should not always be 70
-        nud: function (p) { return callback(this, p.parse(70)); }
-    });
-    return this;
-}
-
-Parser.prototype.addConstant = function(id, callback) {
-    this.addSymbol(id, {
-        nud: function () { return callback(this); }
-    });
-    return this;
-}
+window.hasRuleFor = function(slave, rules, what) {
+	return rules.some(
+		rule => ruleApplied(slave, rule) && rule[what] !== "no default setting");
+};
 
-Parser.prototype.advance = function(id) {
-    if (id !== undefined && this.currentSymbol.id !== id)
-        panic(this.currentSymbol.index, "expected '" + id + "', got '" + this.currentSymbol.id + "'");
+window.hasHColorRule = function(slave, rules) {
+	return hasRuleFor(slave, rules, "hColor");
+};
 
-    var iter = this.lexer.next(),
-        token = iter.value;
-    if (iter.done)
-        token = {
-            id: this.eofToken,
-            index: this.lexer.buffer.length
-        };
+window.hasHStyleRule = function(slave, rules) {
+	return hasRuleFor(slave, rules, "hStyle");
+};
 
-    var symbol = this.symbolTable[iter.done ? this.eofToken : token.id];
-    if (!symbol)
-        panic(token.index, "unknown token '" + token.id + "'");
+window.hasEyeColorRule = function(slave, rules) {
+	return hasRuleFor(slave, rules, "eyeColor");
+};
 
-    var newSymbol = Object.create(symbol);
-    newSymbol.value = token.value;
-    newSymbol.index = token.index;
-    return this.currentSymbol = newSymbol;
-}
+window.lastPregRule = function(slave, rules) {
+	return rules.some(rule =>
+		ruleApplied(slave, rule) && rule.set.preg === -1);
+};
 
-Parser.prototype.parse = function(rbp) {
-    var symbol = this.currentSymbol;
-    this.advance();
-    var left = symbol.nud(this);
+window.mergeRules = function mergeRules(rules) {
+	const combinedRule = {};
+	rules.forEach(rule => {
+		// A rule overrides any preceding ones if,
+		//   * there are no preceding ones,
+		//   * or it sets autoBrand,
+		//   * or it does not set autoBrand and is not "no default setting"
+		Object.keys(rule).forEach(key => {
+			const applies = (combinedRule[key] === undefined ||
+				(key === "autoBrand" && rule[key]) ||
+				(key !== "autoBrand" && rule[key] !== "no default setting"));
+			if (!applies) return;
+			combinedRule[key] = rule[key];
+		});
+	});
+	return combinedRule;
+};
 
-    rbp = rbp || 0;
-    while (rbp < this.currentSymbol.lbp) {
-        symbol = this.currentSymbol;
-        this.advance();
-        left = symbol.led(this, left);
-    }
-    return left;
-}
+// return if a rule is applied on a slave
+window.ruleApplied = function(slave, rule) {
+	return slave.currentRules.includes(rule.ID);
+};
 
-Parser.prototype.parseString = function(string) {
-    this.lexer.feed(string);
-    this.advance();  // "kickstart" the lexer
-    var result = this.parse();
-    this.advance(this.eofToken);
-    return result;
-}
+// checks if any rules apply on the slave, and applies them
+window.CheckAutoRulesActivate = function CheckAutoRulesActivate(slave) {
+	const V = State.variables;
+	let r = "";
 
+	V.defaultRules.forEach(rule => {
+		let applies = ruleAppliesP(rule.condition, slave);
+		if (applies) {
+			if (!ruleApplied(slave, rule)) {
+				slave.currentRules.push(rule.ID);
+				r += `<br><span class="tan">Rule ${rule.ID} (${rule.name}) now applies to ${slave.slaveName}, who is assigned to ${slave.assignment}</span>\n`;
+			}
+		} else if (ruleApplied(slave, rule))
+			r += RARemoveRule(slave, rule);
+	});
+	return r;
+};
 
+// remove the RA rule from the slave
+window.RARemoveRule = function RARemoveRule(slave, rule) {
+	let r = "";
+	const index = slave.currentRules.findIndex(rule => rule.ID === rule);
+	if (index === -1) return r;
+	const slave_rule = slave.currentRules[index];
+	slave.currentRules.splice(index, 1);
+	r += `<br><span class="tan">Rule ${rule.ID} (${rule.name}) no longer applies to ${slave.slaveName}, who is assignmed to ${slave.assignment}</span>`;
+	r += RAFacilityRemove(slave, slave_rule.set);
+	return r;
+};
 
-var ASTBuilder = function(eofToken) {
-    this.parser = new Parser(eofToken);
-}
+// remove slave from the facility described by the rule
+window.RAFacilityRemove = function RAFacilityRemove(slave, rule) {
+	const V = State.variables;
+	let r = "";
+	if (!rule.facilityRemove) return r;
+	switch(rule.setAssignment) {
+	case "be confined in the arcade":
+		if (slave.assignment === rule.setAssignment) {
+			r += `<br>${slave.slaveName} has been removed from ${V.arcadeName} and has been assigned to ${rule.removalAssignment}.`;
+			assignJob(slave, rule.removalAssignment);
+		}
+		break;
 
-ASTBuilder.prototype.addSymbol = function(id, extra) {
-    this.parser.addSymbol(id, extra);
-    return this;
-}
+	case "work in the brothel":
+		if (slave.assignment === rule.setAssignment) {
+			r += `<br>${slave.slaveName} has been removed from ${V.brothelName} and has been assigned to ${rule.removalAssignment}.`;
+			assignJob(slave, rule.removalAssignment);
+		}
+		break;
 
-ASTBuilder.prototype.addInfix = function(id, lbp) {
-    this.parser.addInfix(id, lbp, function(symbol, left, right) {
-        return {
-            id: id,
-            first: left,
-            second: right,
-        };
-    });
-    return this;
-}
+	case "serve in the club":
+		if (slave.assignment === rule.setAssignment) {
+			r += `<br>${slave.slaveName} has been removed from ${clubName} and has been assigned to ${rule.removalAssignment}.`;
+			assignJob(slave, rule.removalAssignment);
+		}
+		break;
 
-ASTBuilder.prototype.addInfixR = function(id, lbp) {
-    this.parser.addInfixR(id, lbp, function(symbol, left, right) {
-        return {
-            id: id,
-            first: left,
-            second: right,
-        };
-    });
-    return this;
-}
+	case "work in the dairy":
+		if (slave.assignment === rule.setAssignment) {
+			r += `<br>${slave.slaveName} has been removed from ${V.dairyName} and has been assigned to ${rule.removalAssignment}.`;
+			assignJob(slave, rule.removalAssignment);
+		}
+		break;
 
-ASTBuilder.prototype.addPrefix = function(id) {
-    this.parser.addPrefix(id, function(symbol, left) {
-        return {
-            id: id,
-            first: left,  // it's not really the left is it?
-        };
-    });
-    return this;
-}
+	case "rest in the spa":
+		if (slave.assignment === rule.setAssignment) {
+			r += `<br>${slave.slaveName} has been removed from ${V.spaName} and has been assigned to ${rule.removalAssignment}.`;
+			assignJob(slave, rule.removalAssignment);
+		}
+		break;
 
-ASTBuilder.prototype.addConstant = function(id, value) {
-    this.parser.addConstant(id, function(symbol) {
-        return {
-            id: id,
-            value: value,
-        };
-    });
-    return this;
-}
+	case "get treatment in the clinic":
+		if (slave.assignment === rule.setAssignment) {
+			r += `<br>{slave.slaveName} has been removed from ${V.clinicName} and has been assigned to ${rule.removalAssignment}.`;
+			assignJob(slave, rule.removalAssignment);
+		}
+		break;
 
+	case "serve in the master suite":
+		if (slave.assignment === rule.setAssignment) {
+			r += `<br>{slave.slaveName} has been removed from ${V.masterSuiteName} and has been assigned to ${rule.removalAssignment}.`;
+			assignJob(slave, rule.removalAssignment);
+		}
+		break;
 
-var op = {
-    add: function(a, b) { return a + b; },
-    sub: function(a, b) { return a - b; },
-    mul: function(a, b) { return a * b; },
-    div: function(a, b) { return a / b; },
-    pow: function(a, b) { return Math.pow(a, b); },
+	case "live with your Head Girl":
+		if (slave.assignment === rule.setAssignment) {
+			r += `<br>${slave.slaveName} has been removed from ${HGSuiteName} and has been assigned to ${rule.removalAssignment}.`;
+			assignJob(slave, rule.removalAssignment);
+		}
+		break;
 
-    neg: function(a) { return -a; },
+	case "work as a servant":
+		if (slave.assignment === rule.setAssignment) {
+			r += `<br>${slave.slaveName} has been removed from ${V.servantsQuartersName} and has been assigned to ${rule.removalAssignment}.`;
+			assignJob(slave, rule.removalAssignment);
+		}
+		break;
 
-    lt: function(a, b) { return a < b; },
-    le: function(a, b) { return a <= b; },
-    gt: function(a, b) { return a > b; },
-    ge: function(a, b) { return a >= b; },
-    eq: function(a, b) { return a === b; },
-    neq: function(a, b) { return a !== b; },
+	case "learn in the schoolroom":
+		if (slave.assignment === rule.setAssignment) {
+			r += `<br>${slave.slaveName} has been removed from ${V.schoolroomName} and has been assigned to ${rule.removalAssignment}.`;
+			assignJob(slave, rule.removalAssignment);
+		}
+		break;
 
-    not: function(a) { return !a; },
-    or: function(a, b) { return a || b; },
-    and: function(a, b) { return a && b; },
+	case "be confined in the cellblock":
+		if (slave.assignment === rule.setAssignment) {
+			r += `<br>${slave.slaveName} has been removed from ${V.cellblockName} and has been assigned to ${rule.removalAssignment}.`;
+			assignJob(slave, rule.removalAssignment);
+		}
+		break;
+	}
 };
 
-var parserBuilder = new ASTBuilder("(end)")
-    // XXX: need to be first to not be recognized as a (name)
-    .addConstant("true", true)
-    .addConstant("false", false)
-
-    .addSymbol("(number)", {
-        pattern: "\\d+",
-        nud: function() {
-            return {
-                id: "(number)",
-                value: parseInt(this.value),
-            };
-        }
-    })
-
-    .addSymbol("(string)", {
-        pattern: "\"(?:[^\\\\\"]|\\\\\"|\\\\(?!\"))*\"",
-        nud: function(p) {
-            return {
-                id: "(string)",
-                value: this.value.replace(/^\"|\"$/g, ""),
-            };
-        }
-    })
-
-    .addSymbol("(name)", {
-        pattern: "[a-zA-Z]\\w*",
-        nud: function(p) {
-            return {
-                id: "(name)",
-                name: this.value,
-            };
-        }
-    })
-
-    .addInfix("+", 50,  op.add)
-    .addInfix("-", 50,  op.sub)
-    .addInfix("*", 60,  op.mul)
-    .addInfix("/", 60,  op.div)
-    .addInfixR("^", 70, op.pow)
-
-    .addPrefix("-", op.neg)
-
-    .addInfix("<=", 40, op.le)
-    .addInfix("<",  40, op.lt)
-    .addInfix(">=", 40, op.ge)
-    .addInfix(">",  40, op.gt)
-    .addInfix("!=", 40, op.neq)
-    .addInfix("=",  40, op.eq)
-
-    .addPrefix("!", op.not)
-    .addInfix("||", 30, op.or)
-    .addInfix("&&", 30, op.and)
-
-    .addSymbol(")")
-    .addSymbol("(", {
-        nud: function(p) {
-            var expr = p.parse(0);
-            p.advance(")");
-            return expr;
-        }
-    });
+// return whether the rule applies to the slave
+window.ruleAppliesP = function ruleAppliesP(cond, slave) {
+	let flag;
 
-var parser = parserBuilder.parser;
-window.parser = parser;
+	// attribute / function check
+	switch (cond.function) {
+	case true: // always applies
+		flag = true;
+		break;
+	case false: // never applies
+		flag = false;
+		break;
+	case "between": // between two values of a slave's attribute
+		flag = between(
+			slave[cond.data.attribute],
+			cond.data.value[0],
+			cond.data.value[1]);
+		break;
+	case "belongs": // the attribute belongs in the list of values
+		flag = cond.data.value.includes(slave[cond.data.attribute])
+		break;
+	case "custom": // user provided JS function
+		flag = eval(cond.data)(slave);
+		break;
+	}
+	// assignment / facility / special slaves / specific slaves check
+	flag = flag &&
+		!(cond.excludeSpecialSlaves && isLeaderP(slave)) &&
+		(cond.assignment.length === 0 || cond.assignment.includes(slave.assignment)) &&
+		(cond.selectedSlaves.length === 0 || cond.selectedSlaves.includes(slave.ID)) &&
+		!(cond.excludedSlaves.includes(slave.ID));
+	return flag;
+};
 
-window.parseCondition = function(condition) {
-    try {
-        return {expr: parser.parseString(condition), error: null};
-    } catch (e) {
-        return {expr: null, error: e};
-    }
-}
+window.emptyDefaultRule = function emptyDefaultRule() {
+	const id = generateNewID();
+	const rule = {
+		ID: id,
+		name: `Rule ${id}`,
+		condition: {
+			function: false,
+			data: {},
+			excludeSpecialSlaves: false,
+			assignment: [],
+			selectedSlaves: [],
+			excludedSlaves: [],
+		},
+		set: {
+			releaseRules: "no default setting",
+			clitSetting: "no default setting",
+			clitSettingXY: "no default setting",
+			clitSettingXX: "no default setting",
+			clitSettingEnergy: "no default setting",
+			speechRules: "no default setting",
+			clothes: "no default setting",
+			collar: "no default setting",
+			shoes: "no default setting",
+			virginAccessory: "no default setting",
+			aVirginAccessory: "no default setting",
+			vaginalAccessory: "no default setting",
+			aVirginDickAccessory: "no default setting",
+			dickAccessory: "no default setting",
+			bellyAccessory: "no default setting",
+			aVirginButtplug: "no default setting",
+			buttplug: "no default setting",
+			eyeColor: "no default setting",
+			makeup: "no default setting",
+			nails: "no default setting",
+			hColor: "no default setting",
+			hLength: "no default setting",
+			hStyle: "no default setting",
+			pubicHColor: "no default setting",
+			pubicHStyle: "no default setting",
+			nipplesPiercing: "no default setting",
+			areolaePiercing: "no default setting",
+			clitPiercing: "no default setting",
+			vaginaLube: "no default setting",
+			vaginaPiercing: "no default setting",
+			dickPiercing: "no default setting",
+			anusPiercing: "no default setting",
+			lipsPiercing: "no default setting",
+			tonguePiercing: "no default setting",
+			earPiercing: "no default setting",
+			nosePiercing: "no default setting",
+			eyebrowPiercing: "no default setting",
+			navelPiercing: "no default setting",
+			corsetPiercing: "no default setting",
+			boobsTat: "no default setting",
+			buttTat: "no default setting",
+			vaginaTat: "no default setting",
+			dickTat: "no default setting",
+			lipsTat: "no default setting",
+			anusTat: "no default setting",
+			shouldersTat: "no default setting",
+			armsTat: "no default setting",
+			legsTat: "no default setting",
+			backTat: "no default setting",
+			stampTat: "no default setting",
+			curatives: "no default setting",
+			livingRules: "no default setting",
+			relationshipRules: "no default setting",
+			standardPunishment: "no default setting",
+			standardReward: "no default setting",
+			diet: "no default setting",
+			dietCum: "no default setting",
+			dietMilk: "no default setting",
+			muscles: "no default setting",
+			XY: "no default setting",
+			XX: "no default setting",
+			gelding: "no default setting",
+			preg: "no default setting",
+			growth_boobs: "no default setting",
+			growth_butt: "no default setting",
+			growth_lips: "no default setting",
+			growth_dick: "no default setting",
+			growth_balls: "no default setting",
+			aphrodisiacs: "no default setting",
+			autoSurgery: 0,
+			autoBrand: 0,
+			pornFameSpending: "no default setting",
+			dietGrowthSupport: 0,
+			eyewear: "no default setting",
+			setAssignment: "no default setting",
+			facilityRemove: false,
+			removalAssignment: "rest",
+			surgery_eyes: "no default setting",
+			surgery_lactation: "no default setting",
+			surgery_prostate: "no default setting",
+			surgery_cosmetic: "no default setting",
+			surgery_accent: "no default setting",
+			surgery_shoulders: "no default setting",
+			surgery_shouldersImplant: "no default setting",
+			surgery_boobs: "no default setting",
+			surgery_hips: "no default setting",
+			surgery_hipsImplant: "no default setting",
+			surgery_butt: "no default setting",
+			surgery_faceShape: "no default setting",
+			surgery_lips: "no default setting",
+			surgery_holes: "no default setting",
+			surgery_hair: "no default setting",
+			surgery_bodyhair: "no default setting",
+			underArmHColor: "no default setting",
+			underArmHStyle: "no default setting",
+			drug: "no default setting",
+			eyes: "no default setting",
+			pregSpeed: "no default setting",
+			bellyImplantVol: -1,
+			teeth: "no default setting",
+		}
+	};
+	return rule;
+};
 
 /*:: textinput [script]*/
 
@@ -3292,25 +2790,25 @@ window.Height = (function(){
 		}
 		if(_.isFinite(conf.skew)) { skew = Math.clamp(conf.skew, -1000, 1000); }
 		if(_.isFinite(conf.spread)) { spread = Math.clamp(conf.spread, 0.001, 0.5); }
-		if(_.isArray(conf.limitMult) && conf.limitMult.length === 2 && conf.limitMult[0] !== conf.limitMult[1]
-			&& _.isFinite(conf.limitMult[0]) && _.isFinite(conf.limitMult[1])) {
+		if(_.isArray(conf.limitMult) && conf.limitMult.length === 2 && conf.limitMult[0] !== conf.limitMult[1] &&
+		   _.isFinite(conf.limitMult[0]) && _.isFinite(conf.limitMult[1])) {
 			minMult = Math.min(conf.limitMult[0], conf.limitMult[1]);
 			maxMult = Math.max(conf.limitMult[0], conf.limitMult[1]);
 		}
-		if(_.isArray(conf.limitHeight) && conf.limitHeight.length === 2 && conf.limitHeight[0] !== conf.limitHeight[1]
-			&& _.isFinite(conf.limitHeight[0]) && _.isFinite(conf.limitHeight[1])) {
+		if(_.isArray(conf.limitHeight) && conf.limitHeight.length === 2 && conf.limitHeight[0] !== conf.limitHeight[1] &&
+		   _.isFinite(conf.limitHeight[0]) && _.isFinite(conf.limitHeight[1])) {
 			minHeight = Math.min(conf.limitHeight[0], conf.limitHeight[1]);
 			maxHeight = Math.max(conf.limitHeight[0], conf.limitHeight[1]);
 		}
 		return {limitMult: [minMult, maxMult], limitHeight: [minHeight, maxHeight], skew: skew, spread: spread};
-	}
+	};
 	
 	/* if you can find an average for an undefined, add it in! */
 	const xxMeanHeight = {
 		"Afghan": 163.8, "Albanian": 161.8, "Algerian": 162, "American.asian": 158.4, "American.black": 163.6, "American.latina": 158.9, "American.white": 165, "American": 161.8, 
 		"Andorran": undefined, "Angolan": undefined, "Antiguan": 156.8, "Argentinian": 159.6, "Armenian": 158.1, "Aruban": 158, "Australian": 161.8, "Austrian": 166, "Azerbaijani": 162.4, 
 		"Bahamian": 157.1, "Bahraini": 165.2, "Bangladeshi": 150.6, "Barbadian": 158.5, "Belarusian": 166.8, "Belgian": 168.1, "Belizean": undefined, "Beninese": 159.3, "Bermudian": undefined, 
-		"Bhutanese": 153.4, "Bissau-Guinean": undefined, "Bolivian": 142.2, "Bosnian": 171.1, "Brazilian": 158.8, "British": 161.9, "Bruneian": undefined, "Bulgarian": 163.2, "Bulgarian": 163.2, 
+		"Bhutanese": 153.4, "Bissau-Guinean": undefined, "Bolivian": 142.2, "Bosnian": 171.1, "Brazilian": 158.8, "British": 161.9, "Bruneian": undefined, "Bulgarian": 163.2,
 		"Burkinabé": 161.6, "Burmese": undefined, "Burundian": 157, "Cambodian": 152.4, "Cameroonian": 161.3, "Canadian": 162.3, "Cape Verdean": undefined, "Catalan": undefined, 
 		"Central African": 158.9, "Chadian": 162.6, "Chilean": 157.2, "Chinese": 155.8, "Colombian": 158.7, "Comorian": 154.8, "Congolese": 159, "a Cook Islander": 162.3, "Costa Rican": undefined, 
 		"Croatian": 166.3, "Cuban": 156, "Cypriot": 163.4, "Czech": 167.22, "Danish": 168.7, "Djiboutian": undefined, "Dominican": 156.4, "Dominiquais": 157.2, "Dutch": 169, "East Timorese": 149.1, 
@@ -3412,18 +2910,26 @@ window.Height = (function(){
 		switch(genes) {
 			case 'XX': // female
 			case 'XXX': // Triple X syndrome female
-				minHeight = 85; midHeight = height * 157 / 164; midAge = 13;
+				minHeight = 85;
+				midHeight = height * 157 / 164;
+				midAge = 13;
 				break;
 			case 'XY': // male
 			case 'XXY': // Kinefelter syndrome male
 			case 'XYY': // XYY syndrome male
-				minHeight = 86; midHeight = height * 170 / 178; midAge = 15;
+				minHeight = 86;
+				midHeight = height * 170 / 178;
+				midAge = 15;
 				break;
 			case 'X0': case 'X': // Turner syndrome female
-				minHeight = 85 * 0.93; midHeight = height * 157 / 164; midAge = 13;
+				minHeight = 85 * 0.93;
+				midHeight = height * 157 / 164;
+				midAge = 13;
 				break;
 			default:
-				minHeight = 85.5, midHeight = height * 327 / 342, midAge = 14;
+				minHeight = 85.5;
+				midHeight = height * 327 / 342;
+				midAge = 14;
 				break;
 		}
 		if(age > midAge) {
@@ -3466,8 +2972,7 @@ window.Height = (function(){
 				break;
 			default:
 				console.log("Height.mean(): unknown genes " + genes + ", returning mean between XX and XY");
-				result = nationalityMeanHeight(xxMeanHeight, nationality, race) * 0.5
-					+ nationalityMeanHeight(xyMeanHeight, nationality, race) * 0.5;
+				result = nationalityMeanHeight(xxMeanHeight, nationality, race) * 0.5 + nationalityMeanHeight(xyMeanHeight, nationality, race) * 0.5;
 				break;
 		}
 		return applyAge(result, age, genes);
@@ -3525,7 +3030,7 @@ if(!Array.prototype.findIndex) {
 		}
 		return -1;
 	};
-};
+}
 
 /*
 A categorizer is used to "slice" a value range into distinct categories in an efficient manner.
@@ -3562,8 +3067,8 @@ As a categorizer
 window.Categorizer = function() {
 	this.cats = Array.prototype.slice.call(arguments)
 		.filter(function(e, i, a) {
-			return e instanceof Array && e.length == 2 && typeof e[0] === 'number' && !isNaN(e[0])
-				&& a.findIndex(function(val) { return e[0] === val[0]; }) === i; /* uniqueness test */ })
+			return e instanceof Array && e.length == 2 && typeof e[0] === 'number' && !isNaN(e[0]) &&
+				a.findIndex(function(val) { return e[0] === val[0]; }) === i; /* uniqueness test */ })
 		.sort(function(a, b) { return b[0] - a[0]; /* reverse sort */ });
 };
 window.Categorizer.prototype.cat = function(val, def) {
@@ -3577,7 +3082,7 @@ window.Categorizer.prototype.cat = function(val, def) {
 	// Record the value for the result's getter, if it is an object
 	// and doesn't have the property yet
 	if(result === Object(result)) {
-		result['value'] = val;
+		result.value = val;
 	}
 	return result;
 };
@@ -3586,27 +3091,28 @@ window.commaNum = function(s) {
 	if(!s) { return 0; }
 	if(State.variables.formatNumbers != 1) { return s; }
 	return s.toString().replace(/\B(?=(\d{3})+(?!\d))/g, ",");
-}
+};
 
 window.cashFormat = function(s) {
 	if(!s) { s = 0; }
 	return "¤"+commaNum(s);
-}
+};
 
 window.isFloat = function(n){
     return n === +n && n !== (n|0);
-}
+};
+
 window.isInt = function(n) {
     return n === +n && n === (n|0);
-}
+};
+
 window.numberWithCommas = function(x) {
     return x.toString().replace(/\B(?=(\d{3})+(?!\d))/g, ",");
-}
-
+};
 
 window.jsRandom = function(min,max) {
     return Math.floor(Math.random()*(max-min+1)+min);
-}
+};
 
 window.jsRandomMany = function (arr, count) {
 	var result = [];
@@ -3616,13 +3122,13 @@ window.jsRandomMany = function (arr, count) {
 		result.push(_tmp.splice(index, 1)[0]);
 	}
 	return result;
-}
+};
 
 //This function wants an array - which explains why it works like array.random(). Give it one or you'll face a NaN
 window.jsEither = function(choices) {
 	var index = Math.floor(Math.random() * choices.length);
 	return choices[index];
-}
+};
 
 //This function is alternative to clone - usage needed if nested objects present. Slower but result is separate object tree, not with reference to source object.
 window.deepCopy = function (o) {
@@ -3633,7 +3139,7 @@ window.deepCopy = function (o) {
        output[key] = (typeof v === "object") ? deepCopy(v) : v;
    }
    return output;
-}
+};
 
 /*
 Make everything waiting for this execute. Usage:
@@ -3649,7 +3155,6 @@ if(typeof Categorizer === 'function') {
 */
 jQuery(document).trigger('categorizer.ready');
 
-
 window.hashChoice = function hashChoice(obj) {
 	let randint = Math.floor(Math.random()*hashSum(obj));
 	let ret;
@@ -3689,86 +3194,115 @@ window.weightedArray2HashMap = function weightedArray2HashMap(arr) {
 	arr.forEach(item => {
 		if (obj[item] === undefined) obj[item] = 1;
 		else obj[item] += 1;
-	})
+	});
 	return obj;
 };
 
-window.capFirstChar = function capFirstChar(string) {
-	return string.charAt(0).toUpperCase() + string.substr(1);
-}
 
-window.getSlaveDisplayName = function (slave) 
-{
-    if  (   (!slave)
-        ||  (!State)
-        )
-    {
-        return  undefined;
-    }
-    var     surnamesFirstCountries  =   [   "Cambodian", "Chinese", "Hungarian", "Japanese", "Korean",
-                                            "Mongolian", "Taiwanese", "Vietnamese"
-                                        ]
-        ,   names   =   [   slave.slaveName, slave.slaveSurname || ""
-                        ];
-        ;
-    if  (   (1  !=  State.variables.surnameOrder)
-        &&  (surnamesFirstCountries.includes(slave.nationality))
-        )
-    {
-        names.reverse();
-    }
-    return  names.join(" ").trim();
-}
+window.between = function between(a, low, high) {
+	if (low === null) low = -Infinity;
+	if (high === null) high = Infinity;
+	return (a > low && a < high);
+};
 
-window.getSlaveDevotionClass = function (slave) 
-{
-    if  (   (!slave)
-        ||  (!State)
-        )
-    {
-        return  undefined;
-    }
-    if  ('mindbroken' == slave.fetish)  return  'mindbroken';
-
-    if      (-95 >  slave.devotion)     return  'very-hateful';
-    else if (-50 >  slave.devotion)     return  'hateful';
-    else if (-20 >  slave.devotion)     return  'resistant';
-    else if (20  >= slave.devotion)     return  'ambivalent';
-    else if (50  >= slave.devotion)     return  'accepting';
-    else if (95  >= slave.devotion)     return  'devoted';
-    else                                return  'worshipful';
-}
+// generate a random, almost unique ID
+// if two are generated the same second every second,
+// duplicates appear approximately once every 100 trillion years
+// this is ~7000 times the age of the universe
+window.generateNewID = function generateNewID() {
+	let randint = "";
+	for(let i = 0; i < 12; i++)
+		randint += jsEither("0123456789abcdefghijklmnopqrstuvwxyzABCDEFGHIJKLMNOPQRSTUVWXYZ");
+	const timestamp = Date.now();
+	return (randint + timestamp.toString(36));
+};
 
-window.getSlaveTrustClass = function (slave) 
-{
-    if  (   (!slave)
-        ||  (!State)
-        )
-    {
-        return  undefined;
-    }
-    if  ('mindbroken' == slave.fetish)  return  '';
-
-    if      (-95 >  slave.trust)        return  'extremely-terrified';
-    else if (-50 >  slave.trust)        return  'terrified';
-    else if (-20 >  slave.trust)        return  'frightened';
-    else if (20  >= slave.trust)        return  'fearful';
-    else if (50  >= slave.trust)
-    {
-        if (-20 >  slave.devotion)      return  'hate-careful';
-        else                            return  'careful';
-    }
-    else if (95  >= slave.trust)
-    {
-        if (-20 >  slave.devotion)      return  'bold';
-        else                            return  'trusting';
-    }
-    else
-    {
-        if (-20 >  slave.devotion)      return  'defiant';
-        else                            return  'profoundly-trusting';
-    }
-}
+window.arraySwap = function arraySwap(array, a, b) {
+	const tmp = array[a];
+	array[a] = array[b];
+	array[b] = tmp;
+};
+
+// circumvents sugarcube, allowing a plain HTML5 UI within it
+window.html5passage = function html5passage(passage_function) {
+	$(document).one(':passagedisplay', ev => {
+		const element = document.createElement("div");
+		element.classList.add("passage");
+		document.getElementById("passages").appendChild(element);
+		passage_function(element);
+		$(document).off(':passagedisplay');
+	});
+};
+
+window.capFirstChar = function capFirstChar(string) {
+	return string.charAt(0).toUpperCase() + string.substr(1);
+};
+
+window.getSlaveDisplayName = function (slave) {
+	if ((!slave) || (!State))
+		return undefined;
+	var surnamesFirstCountries = [
+		"Cambodian",
+		"Chinese",
+		"Hungarian",
+		"Japanese",
+		"Korean",
+		"Mongolian",
+		"Taiwanese",
+		"Vietnamese"];
+        var names = [slave.slaveName, slave.slaveSurname || ""];
+	if ((1 !== State.variables.surnameOrder) && (surnamesFirstCountries.includes(slave.nationality)))
+		names.reverse();
+	return names.join(" ").trim();
+};
+
+window.getSlaveDevotionClass = function (slave) {
+	if ((!slave) || (!State))
+		return undefined;
+	if  ('mindbroken' == slave.fetish)
+		return 'mindbroken';
+	if (slave.devotion < -95)
+		return 'very-hateful';
+	else if (slave.devotion < -50)
+		return 'hateful';
+	else if (slave.devotion < -20)
+		return 'resistant';
+	else if (slave.devotion <= 20)
+		return 'ambivalent';
+	else if (slave.devotion <= 50)
+		return 'accepting';
+	else if (slave.devotion <= 95)
+		return 'devoted';
+	else
+		return 'worshipful';
+};
+
+window.getSlaveTrustClass = function (slave) {
+	if ((!slave) || (!State))
+		return undefined;
+
+	if ('mindbroken' == slave.fetish)
+		return '';
+
+	if (slave.trust < -95)
+		return 'extremely-terrified';
+	else if (slave.trust < -50)
+		return 'terrified';
+	else if (slave.trust < -20)
+		return 'frightened';
+	else if (slave.trust <= 20)
+		return 'fearful';
+	else if (slave.trust <= 50) {
+		if (slave.devotion < -20) return  'hate-careful';
+		else return 'careful';
+	} else if (slave.trust <= 95) {
+		if (slave.devotion < -20) return 'bold';
+		else return 'trusting';
+	} else {
+		if (slave.devotion < -20) return 'defiant';
+		else return 'profoundly-trusting';
+	}
+};
 
 /*:: Span Macro JS [script]*/
 
@@ -6790,11 +6324,11 @@ window.isSlim = function(slave) {
 	}
 	
 	return slim;
-}
+};
 
 window.isStacked = function(slave) {
 	return (slave.butt > 4) && (slave.boobs > 800);
-}
+};
 
 window.isModded = function(slave) {
 	var tatScore = TatScore(slave);
@@ -6802,34 +6336,34 @@ window.isModded = function(slave) {
 	var modScore = piercingScore+tatScore;
 		
 	return ((modScore > 15) || (piercingScore > 8) && (tatScore > 5));
-}
+};
 
 window.isUnmodded = function(slave) {
 	var tatScore = TatScore(slave);
 	var piercingScore = PiercingScore(slave);
 	
 	return !isModded(slave) && (slave.corsetPiercing == 0) && (piercingScore < 3) && (tatScore < 2);
-}
+};
 
 window.isXY = function(slave) {
 	return (slave.dick > 0);
-}
+};
 
 window.isYoung = function(slave) {
 	return (slave.visualAge < 30);
-}
+};
 
 window.isPreg = function(slave) {
 	return ((slave.bellyPreg >= 5000) || (slave.bellyImplant >= 5000));
-}
+};
 
 window.isNotPreg = function(slave) {
 	return !isPreg(slave) && (slave.belly < 100) && (slave.weight < 30) && !setup.fakeBellies.includes(slave.bellyAccessory);
-}
+};
 
 window.isPure = function(slave) {
 	return ((slave.boobsImplant == 0) && (slave.buttImplant == 0) && (slave.waist >= -95) && (slave.lipsImplant == 0) && (slave.faceImplant < 30) && (slave.bellyImplant == -1) && (Math.abs(slave.shouldersImplant) < 2) && (Math.abs(slave.hipsImplant) < 2));
-}
+};
 
 window.PiercingScore = function(slave) {
 	var piercingScore = 0;
@@ -6876,7 +6410,7 @@ window.PiercingScore = function(slave) {
 		piercingScore += slave.anusPiercing*0.75-0.25;
 	}
 	return piercingScore;
-}
+};
 
 window.TatScore = function(slave) {
 	var tatScore = 0;
@@ -6933,7 +6467,7 @@ window.TatScore = function(slave) {
 	}
 	
 	return tatScore;
-}
+};
 
 window.slimPass = function(slave) {
 	var slimPass = 0;
@@ -6958,57 +6492,538 @@ window.slimPass = function(slave) {
 	}
 	
 	return slimPass;
-}
+};
 
 window.sameAssignmentP = function sameAssignmentP(A, B) {
-	return A.assignment === B.assignment
-}
+	return A.assignment === B.assignment;
+};
 
 window.haveRelationP = function haveRelationP(slave, target) {
-	return slave.relationTarget === target.ID
-}
+	return slave.relationTarget === target.ID;
+};
 
 window.haveRelationshipP = function haveRelationshipP(slave, target) {
-	return slave.relationshipTarget === target.ID
-}
+	return slave.relationshipTarget === target.ID;
+};
 
 window.isRivalP = function isRivalP(slave, target) {
-	return slave.rivalryTarget === target.ID
-}
+	return slave.rivalryTarget === target.ID;
+};
 
 window.supremeRaceP = function supremeRaceP(slave) {
-	return State.variables.arcologies[0].FSSupremacistRace === slave.race
-}
+	return State.variables.arcologies[0].FSSupremacistRace === slave.race;
+};
 
 window.inferiorRaceP = function inferiorRaceP(slave) {
-	return State.variables.arcologies[0].FSSubjugationistRace === slave.race
-}
+	return State.variables.arcologies[0].FSSubjugationistRace === slave.race;
+};
+
+window.isLeaderP = function isLeaderP(slave) {
+	const V = State.variables;
+	const leaders = [V.HeadGirl, V.Bodyguard, V.Recruiter, V.Concubine, V.Nurse, V.Attendant, V.Madam, V.DJ, V.Milkmaid, V.Stewardess, V.Schoolteacher, V.Wardeness];
+	return leaders.some(leader => leader.ID && leader.ID === slave.ID);
+};
+
+// helper function returning PC's title
+window.properTitle = function properTitle() {
+	const PC = State.variables.PC;
+	if (PC.customTitle) return PC.customTitle;
+	else if (PC.title !== 0) return "Sir";
+	else return "Ma'am";
+};
 
 window.addSlave = function addSlave(slave) {
 	State.variables.slaves.push(slave);
 	State.variables.slaveIndices[slave.ID] = State.variables.slaves.length - 1;
 };
-
 window.removeSlave = function removeSlave(index) {
 	const ret = State.variables.slaves.deleteAt(index);
 	State.variables.slaveIndices = slaves2indices();
 	return ret;
 };
-
 window.slaves2indices = function slaves2indices() {
 	const obj = {};
 	State.variables.slaves.forEach((slave, i) => obj[slave.ID] = i);
 	return obj;
 };
-
 window.getSlave = function getSlave(ID) {
 	const index = State.variables.slaveIndices[ID];
 	if (index === undefined) return undefined;
 	else return State.variables.slaves[index];
 };
-
 window.getPronouns = function getPronouns(slave) {
-	return {pronoun: slave.pronoun, possessivePronoun: slave.possessivePronoun, possessive: slave.possessive, object: slave.object, objectReflexive: slave.objectReflexive, noun: slave.noun}
+	return {
+		pronoun: slave.pronoun,
+		possessivePronoun: slave.possessivePronoun,
+		possessive: slave.possessive,
+		object: slave.object,
+		objectReflexive: slave.objectReflexive,
+		noun: slave.noun };
+};
+
+/*:: assignJob [script]*/
+
+window.assignJob = function assignJob(slave, job) {
+	"use strict";
+	const V = State.variables;
+	let r = "";
+
+	if (job === "Pit" || job === "Coursing Association")
+		return r;
+	
+	removeJob(slave, slave.assignment);
+	const idx = V.slaveIndices[slave.ID];
+
+	/* use .toLowerCase() to get rid of a few dupe conditions. */
+	switch (job.toLowerCase()) {
+		case "be confined in the arcade":
+		case "arcade":
+			slave.assignment = "be confined in the arcade";
+			slave.assignmentVisible = 0;
+			V.arcadeSlaves++;
+			V.ArcadeiIDs.push(slave.ID);
+			slave.clothing = "none";
+			slave.shoes = "none";
+			slave.collar = "none";
+			slave.livingRules = "spare";
+			break;
+
+		case "work in the brothel":
+		case "brothel":
+			slave.assignment = "work in the brothel";
+			slave.assignmentVisible = 0;
+			V.brothelSlaves++;
+			V.BrothiIDs.push(slave.ID);
+			switch (V.brothelDecoration) {
+				case "Degradationist":
+				case "standard":
+					slave.livingRules = "spare";
+					break;
+				default:
+					slave.livingRules = "normal";
+					break;
+			}
+			break;
+
+		case "be confined in the cellblock":
+		case "cellblock":
+			slave.assignment = "be confined in the cellblock";
+			slave.assignmentVisible = 0;
+			V.cellblockSlaves++;
+			V.CellBiIDs.push(slave.ID);
+			switch (V.cellblockDecoration) {
+				case "Paternalist":
+					slave.livingRules = "normal";
+					break;
+				default:
+					slave.livingRules = "spare";
+					break;
+			}
+			break;
+
+		case "get treatment in the clinic":
+		case "clinic":
+			slave.assignment = "get treatment in the clinic";
+			slave.assignmentVisible = 0;
+			V.clinicSlaves++;
+			V.CliniciIDs.push(slave.ID);
+			switch (V.clinicDecoration) {
+				case "Repopulation Focus":
+				case "Eugenics":
+				case "Gender Radicalist":
+				case "Gender Fundamentalist":
+				case "Paternalist":
+				case "Maturity Preferentialist":
+				case "Youth Preferentialist":
+				case "Slimness Enthusiast":
+				case "Hedonistic":
+					slave.livingRules = "luxurious";
+					break;
+				
+				case "Roman Revivalist":
+				case "Aztec Revivalist":
+				case "Egyptian Revivalist":
+				case "Arabian Revivalist":
+				case "Chinese Revivalist":
+				case "Chattel Religionist":
+				case "Edo Revivalist":
+					slave.livingRules = "normal";
+					break;
+				
+				default:
+					slave.livingRules = "spare";
+					break;
+			}
+			break;
+
+		case "serve in the club":
+		case "club":
+			slave.assignment = "serve in the club";
+			slave.assignmentVisible = 0;
+			V.clubSlaves++;
+			V.ClubiIDs.push(slave.ID);
+			slave.livingRules = "normal";
+			break;
+
+		case "work in the dairy":
+		case "dairy":
+			slave.assignment = "work in the dairy";
+			slave.assignmentVisible = 0;
+			V.dairySlaves++;
+			V.DairyiIDs.push(slave.ID);
+			switch (V.dairyDecoration) {
+				case "Roman Revivalist":
+				case "Aztec Revivalist":
+				case "Chinese Revivalist":
+				case "Chattel Religionist":
+				case "Edo Revivalist":
+				case "Arabian Revivalist":
+				case "Egyptian Revivalist":
+				case "Supremacist":
+				case "Subjugationist":
+				case "Degradationist":
+					slave.livingRules = "spare";
+					break;
+				default:
+					slave.livingRules = "normal";
+					break;
+			}
+			break;
+
+		case "live with your head girl":
+		case "head girl suite":
+		case "hgsuite":
+			slave.assignment = "live with your Head Girl";
+			slave.assignmentVisible = 0;
+			V.HGSuiteSlaves++;
+			V.HGSuiteiIDs.push(slave.ID);
+			slave.livingRules = "luxurious";
+			break;
+
+		case "serve in the master suite":
+		case "master suite":
+		case "mastersuite":
+			slave.assignment = "serve in the master suite";
+			slave.assignmentVisible = 0;
+			V.masterSuiteSlaves++;
+			V.MastSiIDs.push(slave.ID);
+			if(V.masterSuiteUpgradeLuxury > 0)
+				slave.livingRules = "luxurious";
+			else
+				slave.livingRules = "spare";
+			break;
+
+		case "learn in the schoolroom":
+		case "schoolroom":
+			slave.assignment = "learn in the schoolroom";
+			slave.assignmentVisible = 0;
+			V.schoolroomSlaves++;
+			V.SchlRiIDs.push(slave.ID);
+			slave.livingRules = "normal";
+			break;
+
+		case "work as a servant":
+		case "servants' quarters":
+		case "servantsquarters":
+			slave.assignment = "work as a servant";
+			slave.assignmentVisible = 0;
+			V.servantsQuartersSlaves++;
+			V.ServQiIDs.push(slave.ID);
+			switch (V.servantsQuartersDecoration) {
+				case "Roman Revivalist":
+				case "Aztec Revivalist":
+				case "Chinese Revivalist":
+				case "Chattel Religionist":
+				case "Edo Revivalist":
+				case "Supremacist":
+				case "Subjugationist":
+				case "Degradationist":
+				case "Arabian Revivalist":
+				case "Egyptian Revivalist":
+					slave.livingRules = "spare";
+					break;
+				default:
+					slave.livingRules = "normal";
+					break;
+			}
+			break;
+
+		case "rest in the spa":
+		case "spa":
+			slave.assignment = "rest in the spa";
+			slave.assignmentVisible = 0;
+			V.spaSlaves++;
+			V.SpaiIDs.push(slave.ID);
+			switch (V.spaDecoration) {
+				case "Chattel Religionist":
+				case "Chinese Revivalist":
+					slave.livingRules = "normal";
+					break;
+				case "Degradationist":
+					slave.livingRules = "spare";
+					break;
+				default:
+					slave.livingRules = "luxurious";
+					break;
+			}
+			break;
+
+		case "be the attendant":
+		case "be the dj":
+		case "be the madam":
+		case "be the milkmaid":
+		case "be the nurse":
+		case "be the schoolteacher":
+		case "be the stewardess":
+		case "be the wardeness":
+			slave.assignment = job;
+			slave.assignmentVisible = 0;     /* non-visible leadership roles */
+			slave.livingRules = "luxurious";
+			break;
+
+		case "be your concubine":
+			slave.assignment = job;
+			slave.assignmentVisible = 0;     /* non-visible leadership roles */
+			if(V.masterSuiteUpgradeLuxury > 0)
+				slave.livingRules = "luxurious";
+			else
+				slave.livingRules = "normal";
+			break;
+
+		case "be your head girl":
+			slave.assignment = job;
+			if (V.HGSuite === 1) {
+				slave.livingRules = "luxurious";
+			}
+			break;
+
+		case "guard you":
+			slave.assignment = job;
+			if (V.dojo > 1) {
+				slave.livingRules = "luxurious";
+			}
+			if (V.pitBG == 1 && V.fighterIDs.includes(slave.ID))
+				V.fighterIDs.delete(slave.ID);
+			break;
+
+		case "be your agent":
+		case "live with your agent":
+			slave.assignment = job;
+			slave.assignmentVisible = 0;
+			slave.useRulesAssistant = 0; /* non-visible roles exempt from Rules Assistant */
+			if (job === "be your agent") {
+				V.leaders.push(slave);
+			}
+			break;
+
+		case "choose her own job":
+			slave.assignment = job;
+			slave.choosesOwnAssignment = 1;  /* removeJob already set assignmentVisible = 1 */
+			break;
+
+		default:
+			slave.assignment = job; /* removeJob already set assignmentVisible = 1 and choosesOwnAssignment = 0 */
+			break;
+	}
+
+	if (slave.assignmentVisible === 0 && Array.isArray(V.personalAttention)) {
+		const awi = V.personalAttention.findIndex(function(s) { return s.ID === slave.ID; });
+		if (awi != -1) {
+			V.personalAttention.deleteAt(awi);
+			if (V.personalAttention.length === 0) {
+				if (V.PC.career === "escort") 
+					V.personalAttention = "whoring";
+				else if (V.PC.career === "servant")
+					V.personalAttention = "upkeep";
+				else
+					V.personalAttention = "business";
+				r += `${slave.slaveName} no longer has your personal attention; you plan to focus on ${V.personalAttention}.`;
+			} else
+				r += `${slave.slaveName} no longer has your personal attention.`;
+		}
+	}
+	if (idx >= 0)
+		V.slaves[idx] = slave;
+
+	return r;
+};
+
+window.removeJob = function removeJob(slave, assignment) {
+	"use strict";
+	const V = State.variables;
+	let r = "";
+	
+	const idx = V.slaveIndices[slave.ID];
+
+	if (assignment === "Pit")
+		V.fighterIDs.delete(slave.ID);
+
+	else if (assignment === "Coursing Association")
+		V.Lurcher = 0;
+
+	else {
+		if (V.HeadGirl !== 0 && slave.ID === V.HeadGirl.ID)
+			V.HeadGirl = 0;
+		if (V.Recruiter !== 0 && slave.ID == V.Recruiter.ID)
+			V.Recruiter = 0;
+		if (V.Bodyguard !== 0 && slave.ID === V.Bodyguard.ID)
+			V.Bodyguard = 0;
+		if (V.Madam !== 0 && slave.ID === V.Madam.ID)
+			V.Madam = 0;
+		if (V.DJ !== 0 && slave.ID === V.DJ.ID)
+			V.DJ = 0;
+		if (V.Milkmaid !== 0 && slave.ID === V.Milkmaid.ID)
+			V.Milkmaid = 0;
+		if (V.Schoolteacher !== 0 && slave.ID === V.Schoolteacher.ID)
+			V.Schoolteacher = 0;
+		if (V.Attendant !== 0 && slave.ID === V.Attendant.ID)
+			V.Attendant = 0;
+		if (V.Nurse !== 0 && slave.ID === V.Nurse.ID)
+			V.Nurse = 0;
+		if (V.Stewardess !== 0 && slave.ID === V.Stewardess.ID)
+			V.Stewardess = 0;
+		if (V.Wardeness !== 0 && slave.ID === V.Wardeness.ID)
+			V.Wardeness = 0;
+		if (V.Concubine !== 0 && slave.ID === V.Concubine.ID)
+			V.Concubine = 0;
+		if (V.Collectrix !== 0 && slave.ID === V.Collectrix.ID)
+			V.Collectrix = 0;
+
+		/* use .toLowerCase() to get rid of a few dupe conditions. */
+		switch (assignment.toLowerCase()) {
+		case "be confined in the arcade":
+		case "arcade":
+			slave.assignment = "work a glory hole";
+			V.ArcadeiIDs.delete(slave.ID);
+			V.arcadeSlaves--;
+			break;
+
+		case "work in the brothel":
+		case "brothel":
+			slave.assignment = "whore";
+			V.BrothiIDs.delete(slave.ID);
+			V.brothelSlaves--;
+			break;
+
+		case "be confined in the cellblock":
+		case "cellblock":
+			slave.assignment = "rest";
+			if (slave.inflation > 0) {
+				slave.inflation = 0;
+				slave.inflationType = "none";
+				slave.inflationMethod = 0;
+				SetBellySize(slave);
+			}
+			V.CellBiIDs.delete(slave.ID);
+			V.cellblockSlaves--;
+			break;
+
+		case "get treatment in the clinic":
+		case "clinic":
+			slave.assignment = "rest";
+			V.CliniciIDs.delete(slave.ID);
+			V.clinicSlaves--;
+			break;
+
+		case "serve in the club":
+		case "club":
+			slave.assignment = "serve the public";
+			V.ClubiIDs.delete(slave.ID);
+			V.clubSlaves--;
+			break;
+
+		case "work in the dairy":
+		case "dairy":
+			slave.assignment = "get milked";
+			V.DairyiIDs.delete(slave.ID);
+			V.dairySlaves--;
+			break;
+
+		case "learn in the schoolroom":
+		case "schoolroom":
+			slave.assignment = "rest";
+			V.SchlRiIDs.delete(slave.ID);
+			V.schoolroomSlaves--;
+			break;
+
+		case "rest in the spa":
+		case "spa":
+			slave.assignment = "rest";
+			V.SpaiIDs.delete(slave.ID);
+			V.spaSlaves--;
+			break;
+
+		case "work as a servant":
+		case "servants' quarters":
+		case "servantsquarters":
+			slave.assignment = "be a servant";
+			V.ServQiIDs.delete(slave.ID);
+			V.servantsQuartersSlaves--;
+			break;
+
+		case "serve in the master suite":
+		case "master suite":
+		case "mastersuite":
+			slave.assignment = "please you";
+			V.MastSiIDs.delete(slave.ID);
+			V.masterSuiteSlaves--;
+			break;
+
+		case "live with your head girl":
+		case "head girl suite":
+		case "hgsuite":
+			slave.assignment = "rest";
+			V.HGSuiteiIDs.delete(slave.ID);
+			V.HGSuiteSlaves--;
+			break;
+
+		case "be your head girl":
+			slave.assignment = "rest";
+			if (V.HGSuiteEquality === 0 && V.personalAttention === "HG") {
+				if (V.PC.career === "escort")
+					V.personalAttention = "whoring";
+				else if (V.PC.career === "servant")
+					V.personalAttention = "upkeep";
+				else
+					V.personalAttention = "business";
+				
+				r += `You no longer have a slave assigned to be your Head Girl, so you turn your personal attention to focus on ${V.personalAttention}.`;
+			}
+			break;
+			
+		case "be your agent":
+		case "live with your agent":
+			slave.assignment = "rest";
+			const _leaderIndex = V.leaders.findIndex(function(x) { return x.ID === slave.ID; });
+			if (_leaderIndex !== -1)
+				V.leaders.deleteAt(_leaderIndex);
+			
+			if (slave.relationshipTarget > 0) { /* following code assumes there can be at most one companion */
+				const _lover = V.slaves.findIndex(function(s) { return haveRelationshipP(s, slave) && s.assignment === "live with your agent"; });
+				if (_lover !== -1) {
+					V.slaves[_lover].assignment = "rest";
+					V.slaves[_lover].assignmentVisible = 1;
+				}
+			}
+			break;
+			
+		default:
+			slave.assignment = "rest";
+			break;
+		}
+
+		
+		if (slave.livingRules === "luxurious" && slave.assignmentVisible !== 1)
+			slave.livingRules = "normal";
+		
+		slave.assignmentVisible = 1;
+		slave.choosesOwnAssignment = 0;
+		slave.sentence = 0;
+	}
+	if (idx >= 0)
+		V.slaves[idx] = slave;
+
+	return r;
 };
 
 /*:: wombJS [script]*/
@@ -7039,322 +7054,268 @@ $slave.bellyPreg = WombGetWolume($slave) - return double, with current womb volu
 
 */
 
-window.WombInit = function(actor) //Init womb system.
-{
-    
-    if (!Array.isArray(actor.womb))
-    {   
-       //alert("creating new womb"); //debugging
-	   actor.womb = [];
-    }
+//Init womb system.
+window.WombInit = function(actor) {
+	if (!Array.isArray(actor.womb)) {   
+		//alert("creating new womb"); //debugging
+		actor.womb = [];
+	}
 
-//    console.log("broodmother:" + typeof actor.broodmother);
-    
-    if ( typeof actor.broodmother != "number" )
-    {
-          actor.broodmother = 0;
-          actor.broodmotherFetuses = 0;
-    }
-    
-    if ( typeof actor.readyOva != "number" )
-    {
-          actor.readyOva = 0;
-    }
+	//    console.log("broodmother:" + typeof actor.broodmother);
+	
+	if ( typeof actor.broodmother != "number" ) {
+		actor.broodmother = 0;
+		actor.broodmotherFetuses = 0;
+	}
+	
+	if ( typeof actor.readyOva != "number" ) {
+		actor.readyOva = 0;
+	}
 
-    if (actor.womb.length == 0 && actor.pregType != 0 && actor.broodmother == 0) //backward compatibility setup. Fully accurate for normal pregnancy only.
-    {
-        WombImpregnate(actor, actor.pregType, actor.pregSource, actor.preg);
-    }
-    else if (actor.womb.length == 0 && actor.pregType != 0 && actor.broodmother > 0 && actor.broodmotherOnHold < 1) //sorry but for already present broodmothers it's impossible to calculate fully, aproximation used.
-    {
-        var i, pw = actor.preg, bCount, bLeft;
-        if (pw > 40)
-            pw = 40; //to avoid disaster.
-        bCount = Math.floor(actor.pregType/pw);
-        bLeft = actor.pregType - (bCount*pw);
-        if (pw > actor.pregType)
-        {
-            pw = actor.pregType // low children count broodmothers not supported here. It's emergency/backward compatibility code, and they not in game anyway. So minimum is 1 fetus in week.
-            actor.preg = pw; // fixing initial pregnancy week.
-        }
-        for (i=0; i<pw; i++)
-        {
-            WombImpregnate(actor, bCount, actor.pregSource, i); // setting fetuses for every week, up to 40 week at max.
-        }
+	//backward compatibility setup. Fully accurate for normal pregnancy only.
+	if (actor.womb.length == 0 && actor.pregType != 0 && actor.broodmother == 0)  {
+		WombImpregnate(actor, actor.pregType, actor.pregSource, actor.preg);
+	} else if (actor.womb.length == 0 && actor.pregType != 0 && actor.broodmother > 0 && actor.broodmotherOnHold < 1) {
+		//sorry but for already present broodmothers it's impossible to calculate fully, aproximation used.
+		var i, pw = actor.preg, bCount, bLeft;
+		if (pw > 40) pw = 40; //to avoid disaster.
+		bCount = Math.floor(actor.pregType/pw);
+		bLeft = actor.pregType - (bCount*pw);
+		if (pw > actor.pregType) {
+			pw = actor.pregType; // low children count broodmothers not supported here. It's emergency/backward compatibility code, and they not in game anyway. So minimum is 1 fetus in week.
+			actor.preg = pw; // fixing initial pregnancy week.
+		}
+		for (i=0; i<pw; i++) {
+			WombImpregnate(actor, bCount, actor.pregSource, i); // setting fetuses for every week, up to 40 week at max.
+		}
 
-        if (bLeft > 0)
-        {
-            WombImpregnate(actor, bLeft, actor.pregSource, i+1); // setting up leftower of fetuses.
-        }
-    }
-}
+		if (bLeft > 0) {
+			WombImpregnate(actor, bLeft, actor.pregSource, i+1); // setting up leftower of fetuses.
+		}
+	}
+};
 
-window.WombImpregnate = function(actor, fCount, fatherID, age)
-{
-    var i;
-    var tf;
-    for (i=0; i<fCount; i++)
-    {
-	tf = {}; //new Object
-    tf.age = age; //initial age
-    tf.fatherID = fatherID; //We can store who is father too.
-	tf.sex = Math.round(Math.random())+1; // 1 = male, 2 = female. For possible future usage, just as concept now.
-    tf.volume = 1; //Initial, to create property. Updated with actual data after WombGetVolume call.
-	tf.identical = 0; //Initial, to create property. Updated with actual data during fetalSplit call.
-
-    try {
-            if (actor.womb.length == 0)
-            {
-                actor.pregWeek = age;
-                actor.preg = age;
-            }
+window.WombImpregnate = function(actor, fCount, fatherID, age) {
+	var i;
+	var tf;
+	for (i=0; i<fCount; i++) {
+		tf = {}; //new Object
+		tf.age = age; //initial age
+		tf.fatherID = fatherID; //We can store who is father too.
+		tf.sex = Math.round(Math.random())+1; // 1 = male, 2 = female. For possible future usage, just as concept now.
+		tf.volume = 1; //Initial, to create property. Updated with actual data after WombGetVolume call.
+		tf.identical = 0; //Initial, to create property. Updated with actual data during fetalSplit call.
 
-	        actor.womb.push(tf);
-        }catch(err){
-            WombInit(actor);
-            actor.womb.push(tf);
-            alert("WombImpregnate warning - " + actor.slaveName+" "+err);
-        }
+		try {
+			if (actor.womb.length == 0) {
+				actor.pregWeek = age;
+				actor.preg = age;
+			}
+			actor.womb.push(tf);
+		} catch(err){
+			WombInit(actor);
+			actor.womb.push(tf);
+			alert("WombImpregnate warning - " + actor.slaveName+" "+err);
+		}
 
-    }
-    
-}
+	}
+};
 
-window.WombProgress = function(actor, ageToAdd)
-{
-    var i, ft;
-    ageToAdd = Math.ceil(ageToAdd*10)/10;
-    try {
-            for (i in actor.womb)
-            {
-                ft = actor.womb[i];
-                ft.age += ageToAdd;
-            }
-    }catch(err){
-            WombInit(actor);
-            alert("WombProgress warning - " + actor.slaveName+" "+err);
-    }
-}
+window.WombProgress = function(actor, ageToAdd) {
+	var i, ft;
+	ageToAdd = Math.ceil(ageToAdd*10)/10;
+	try {
+		actor.womb.forEach(ft => ft.age += ageToAdd);
+	} catch(err){
+		WombInit(actor);
+		alert("WombProgress warning - " + actor.slaveName+" "+err);
+	}
+};
 
-window.WombBirth = function(actor, readyAge)
-{
-    try{
-        WombSort(actor); //For normal processing fetuses that more old should be first. Now - they are.
-        }catch(err){
-            WombInit(actor);
-            alert("WombBirth warning - " + actor.slaveName+" "+err);       
+window.WombBirth = function(actor, readyAge) {
+	try {
+		WombSort(actor); //For normal processing fetuses that more old should be first. Now - they are.
+        } catch(err){
+		WombInit(actor);
+		alert("WombBirth warning - " + actor.slaveName+" "+err);       
         }
 
-    var birthed = [];    
-    var ready = WombBirthReady(actor, readyAge);
-    var i;
-
-    for (i=0; i<ready; i++) //here can't be used "for .. in .." syntax.
-    {
-        birthed.push(actor.womb.shift());
-    }
-
-    return birthed;
-}
-
-window.WombFlush = function(actor)
-{
-    actor.womb = [];
-}
-
-window.WombBirthReady = function(actor, readyAge)
-{
+	var birthed = [];    
+	var ready = WombBirthReady(actor, readyAge);
+	var i;
 
-    var i, ft;
-    var readyCnt = 0;
-    try {
-        for (i in actor.womb)
-        {
-            ft = actor.womb[i];
-            if (ft.age >= readyAge)
-                  readyCnt++;
-        }
-    }catch(err){
-        WombInit(actor);
-        alert("WombBirthReady warning - " + actor.slaveName+" "+err);    
+	for (i=0; i<ready; i++) { //here can't be used "for .. in .." syntax.
+		birthed.push(actor.womb.shift());
+	}
 
-        return 0;
-    }
+	return birthed;
+};
 
-    return readyCnt;
-}
+window.WombFlush = function(actor) {
+	actor.womb = [];
+};
 
-window.WombGetVolume = function(actor) //most code from pregJS.tw with minor adaptation.
-{
-    var i, ft;
-    var gestastionWeek;
-    var phi = 1.618;
-    var targetLen;
-    var wombSize = 0;
-    
-    try{
-
-        for (i in actor.womb)
-        {
-            ft = actor.womb[i];
-            gestastionWeek = ft.age;
-            
-            if (gestastionWeek <= 32) 
-            {
-                targetLen = (0.00006396 * Math.pow(gestastionWeek, 4)) - (0.005501 * Math.pow(gestastionWeek, 3)) + (0.161 * Math.pow(gestastionWeek, 2)) - (0.76 * gestastionWeek) + 0.208;
-            } 
-            else if (gestastionWeek <= 106) 
-            {
-                targetLen = (-0.0000004675 * Math.pow(gestastionWeek, 4)) + (0.0001905 * Math.pow(gestastionWeek, 3)) - (0.029 * Math.pow(gestastionWeek, 2)) + (2.132 * gestastionWeek) - 16.575;
-            } 
-            else 
-            {
-                targetLen = (-0.00003266 * Math.pow(gestastionWeek,2)) + (0.076 * gestastionWeek) + 43.843;
-            }
+window.WombBirthReady = function(actor, readyAge) {
+	var i, ft;
+	var readyCnt = 0;
+	try {
+		readyCnt += actor.womb.filter(ft => ft.age >= readyAge).length;
+	} catch(err){
+		WombInit(actor);
+		alert("WombBirthReady warning - " + actor.slaveName+" "+err);    
+		return 0;
+	}
 
-            ft.volume = ((4 / 3) * (Math.PI) * (phi / 2) * (Math.pow((targetLen / 2), 3)));
-        
-            wombSize += ft.volume;
-        }
-    }catch(err){
-        WombInit(actor);
-        alert("WombGetVolume warning - " + actor.slaveName + " " + err);       
-    }
-  
-    if (wombSize < 0) //catch for strange cases, to avoid messing with outside code.
-        wombSize = 0;
+	return readyCnt;
+};
 
-    return wombSize;
-}
+window.WombGetVolume = function(actor) { //most code from pregJS.tw with minor adaptation.
+	var gestastionWeek;
+	var phi = 1.618;
+	var targetLen;
+	var wombSize = 0;
+	try {
+		actor.womb.forEach(ft => {
+			gestastionWeek = ft.age;
+			if (gestastionWeek <= 32)  {
+				targetLen = (0.00006396 * Math.pow(gestastionWeek, 4)) -
+					(0.005501 * Math.pow(gestastionWeek, 3)) +
+					(0.161 * Math.pow(gestastionWeek, 2)) -
+					(0.76 * gestastionWeek) +
+					0.208;
+			} else if (gestastionWeek <= 106) {
+				targetLen = (-0.0000004675 * Math.pow(gestastionWeek, 4)) +
+					(0.0001905 * Math.pow(gestastionWeek, 3)) -
+					(0.029 * Math.pow(gestastionWeek, 2)) +
+					(2.132 * gestastionWeek) -
+					16.575;
+			} else {
+				targetLen = (-0.00003266 * Math.pow(gestastionWeek,2)) +
+					(0.076 * gestastionWeek) +
+					43.843;
+			}
+			ft.volume = ((4 / 3) * (Math.PI) * (phi / 2) * (Math.pow((targetLen / 2), 3)));
+			wombSize += ft.volume;
+		});
+	} catch(err){
+		WombInit(actor);
+		alert("WombGetVolume warning - " + actor.slaveName + " " + err);       
+	}
+	if (wombSize < 0) //catch for strange cases, to avoid messing with outside code.
+		wombSize = 0;
+	return wombSize;
+};
 
 window.WombUpdatePregVars = function(actor) {
+	WombSort(actor);
+	if (actor.womb.length > 0) {
+		if (actor.preg > 0 && actor.womb[0].age > 0) {
+			actor.preg = actor.womb[0].age;
+		}
+		actor.pregType = actor.womb.length;
+		actor.bellyPreg = WombGetVolume(actor);
+	}
+};
 
-    WombSort(actor);
-    if (actor.womb.length > 0)
-    {
-        if (actor.preg > 0 && actor.womb[0].age > 0)
-        {
-            actor.preg = actor.womb[0].age;
-        }
-
-        actor.pregType = actor.womb.length;
-        
-        actor.bellyPreg = WombGetVolume(actor);
+window.WombMinPreg = function(actor) {
+	WombSort(actor);
+	if (actor.womb.length > 0) 
+		return actor.womb[actor.womb.length-1].age;
+	else
+		return 0;
+};
 
-    }
-
-}
-
-window.WombMinPreg = function(actor)
-{
-    WombSort(actor);
-
-    if (actor.womb.length > 0) 
-        return actor.womb[actor.womb.length-1].age;
-    else
-        return 0;
-}
-
-window.WombMaxPreg = function(actor)
-{
-    WombSort(actor);
-    if (actor.womb.length > 0) 
-        return actor.womb[0].age;
-    else
-        return 0;
-}
+window.WombMaxPreg = function(actor) {
+	WombSort(actor);
+	if (actor.womb.length > 0) 
+		return actor.womb[0].age;
+	else
+		return 0;
+};
 
 window.WombNormalizePreg = function(actor)
 {
-//    console.log("New actor: " + actor.slaveName + " ===============" + actor.name);
-    WombInit(actor);
-
-    if (actor.womb.length == 0 && actor.broodmother >= 1) // this is broodmother on hold.
-    {
-        actor.pregType = 0; 
-        actor.pregKnown = 0;
-        
-        if (actor.preg >= 0)
-            actor.preg = 0.1; //to avoid legacy code conflicts - broodmother on hold can't be impregnated, but she not on normal contraceptives. So we set this for special case.
-        
-        if (actor.pregSource > 0)
-            actor.pregSource = 0;
-
-        if (actor.pregWeek > 0) 
-            actor.pregWeek = 0;
-            
-        actor.broodmotherCountDown = 0;
-    }
-    
-    if (actor.womb.length > 0)
-    {
-        var max = WombMaxPreg(actor);
-//        console.log("max: " + max);
-//        console.log(".preg: "+ actor.preg);
-        if (actor.pregWeek < 1 )
-            actor.pregWeek = 1
-
-        if (max < actor.preg)
-        {
-            WombProgress(actor, actor.preg - max);
-//            console.log("progressin womb");
-        }
-        else if ( max > actor.preg)
-        {
-            actor.preg = max;
-//            console.log("advancing .preg");
-        }
-
-        actor.pregType = actor.womb.length;
-        actor.pregSource = actor.womb[0].fatherID;
-    } 
-    else if (actor.womb.length == 0 && actor.broodmother < 1) //not broodmother
-    {
-//        console.log("preg fixing");
-        actor.pregType = 0;
-        actor.pregKnown = 0;
-        
-        if (actor.preg > 0)
-            actor.preg = 0;
-        
-        if (actor.pregSource > 0)
-            actor.pregSource = 0;
-
-        if (actor.pregWeek > 0) // We can't properly set postpartum here, but can normalize obvious error with forgotten property.
-            actor.pregWeek = 0;
-    }
+	// console.log("New actor: " + actor.slaveName + " ===============" + actor.name);
+	WombInit(actor);
+	
+	// this is broodmother on hold.
+	if (actor.womb.length == 0 && actor.broodmother >= 1) { 
+		actor.pregType = 0; 
+		actor.pregKnown = 0;
+
+		// to avoid legacy code conflicts - broodmother on hold
+		// can't be impregnated, but she not on normal contraceptives.
+		// So we set this for special case.
+		if (actor.preg >= 0)
+			actor.preg = 0.1; 
+		
+		if (actor.pregSource > 0)
+			actor.pregSource = 0;
 
-    actor.bellyPreg = WombGetVolume(actor);
-}
+		if (actor.pregWeek > 0) 
+			actor.pregWeek = 0;
+		
+		actor.broodmotherCountDown = 0;
+	}
+	
+	if (actor.womb.length > 0) {
+		var max = WombMaxPreg(actor);
+		//        console.log("max: " + max);
+		//        console.log(".preg: "+ actor.preg);
+		if (actor.pregWeek < 1 )
+			actor.pregWeek = 1;
+
+		if (max < actor.preg) {
+			WombProgress(actor, actor.preg - max);
+			//            console.log("progressin womb");
+		}
+		else if ( max > actor.preg) {
+			actor.preg = max;
+			//            console.log("advancing .preg");
+		}
+
+		actor.pregType = actor.womb.length;
+		actor.pregSource = actor.womb[0].fatherID;
+	} else if (actor.womb.length == 0 && actor.broodmother < 1) {
+		//not broodmother
+		//        console.log("preg fixing");
+		actor.pregType = 0;
+		actor.pregKnown = 0;
+		
+		if (actor.preg > 0)
+			actor.preg = 0;
+		
+		if (actor.pregSource > 0)
+			actor.pregSource = 0;
 
-window.WombZeroID = function(actor, id)
-{
-    WombInit(actor);
-    var i, ft;
-    for (i in actor.womb)
-    {
-        ft = actor.womb[i];
-        if (ft.fatherID == id)
-            ft.fatherID = 0;
-    }
+		// We can't properly set postpartum here,
+		// but can normalize obvious error with forgotten property.
+		if (actor.pregWeek > 0) 
+			actor.pregWeek = 0;
+	}
+	actor.bellyPreg = WombGetVolume(actor);
+};
 
-    WombNormalizePreg(actor);
-}
+window.WombZeroID = function(actor, id) {
+	WombInit(actor);
+	actor.womb
+		.filter(ft => ft.fatherID === id)
+		.forEach(ft => ft.fatherID = 0);
+	WombNormalizePreg(actor);
+};
 
 /* Sorts the womb object by age with oldest and thus soonest to be born, first. This will be needed in the future once individual fertilization is a possiblity.*/
-window.WombSort = function(actor)
-{
-	actor.womb.sort(function (a, b){return b.age - a.age});
-}
+window.WombSort = function(actor) {
+	actor.womb.sort((a, b) => { return b.age - a.age; });
+};
 
-window.fetalSplit = function(actor)
-{
+window.fetalSplit = function(actor) {
 	var i, ft;
 	var nft = {};
-    nft.age = actor.preg;
-    nft.fatherID = actor.pregSource;
+	nft.age = actor.preg;
+	nft.fatherID = actor.pregSource;
 	nft.sex = Math.round(Math.random())+1;
-    nft.volume = 1;
+	nft.volume = 1;
 	nft.identical = 0;
 
 	actor.womb.forEach(function(s){
@@ -7370,8 +7331,7 @@ window.fetalSplit = function(actor)
 		}
 	});
 	WombNormalizePreg(actor);
-
-}
+};
 
 /* alt
 window.fetalSplit = function(actor)
@@ -8397,172 +8357,6 @@ window.FResult = (function() {
 	return FResult;
 })();
 
-/*:: RA JS [script]*/
-
-window.ruleApplied = function(slave, ID) {
-	if (!slave || !slave.currentRules)
-		return null;
-	return slave.currentRules.includes(ID);
-};
-
-window.ruleSlaveSelected = function(slave, rule) {
-	if (!slave || !rule || !rule.selectedSlaves)
-		return false;
-	return rule.selectedSlaves.includes(slave.ID);
-};
-
-window.ruleSlaveExcluded = function(slave, rule) {
-	if (!slave || !rule || !rule.excludedSlaves)
-		return false;
-	return rule.excludedSlaves.includes(slave.ID);
-};
-
-window.ruleAssignmentSelected = function(slave, rule) {
-	if (!slave || !rule || (!rule.assignment && !rule.facility))
-		return false;
-	var assignment = rule.assignment.concat(expandFacilityAssignments(rule.facility));
-	return assignment.includes(slave.assignment);
-}
-
-window.ruleAssignmentExcluded = function(slave, rule) {
-	if (!slave || !rule || (!rule.excludeAssignment && !rule.excludeFacility))
-		return false;
-	var excludeAssignment = rule.excludeAssignment.concat(expandFacilityAssignments(rule.excludeFacility));
-	return excludeAssignment.includes(slave.assignment);
-}
-
-window.hasSurgeryRule = function(slave, rules) {
-	if (!slave || !rules || !slave.currentRules)
-		return false;
-
-	for (var d = rules.length-1; d >= 0; d--) {
-		if (ruleApplied(slave, rules[d].ID)) {
-			if (rules[d].autoSurgery > 0) {
-				return true;
-			}
-		}
-	}
-	return false;
-};
-
-window.hasRuleFor = function(slave, rules, what) {
-	if (!slave || !rules || !slave.currentRules)
-		return false;
-
-	for (var d = rules.length-1; d >= 0; d--) {
-		if (ruleApplied(slave, rules[d].ID)) {
-			if (rules[d][what] !== "no default setting") {
-				return true;
-			}
-		}
-	}
-	return false;
-};
-
-window.hasHColorRule = function(slave, rules) {
-	return hasRuleFor(slave, rules, "hColor");
-}
-
-window.hasHStyleRule = function(slave, rules) {
-	return hasRuleFor(slave, rules, "hStyle");
-};
-
-window.hasEyeColorRule = function(slave, rules) {
-	return hasRuleFor(slave, rules, "eyeColor");
-};
-
-window.lastPregRule = function(slave, rules) {
-	if (!slave || !rules)
-		return null;
-	if (!slave.currentRules)
-		return false;
-
-	for (var d = rules.length-1; d >= 0; d--) {
-		if (ruleApplied(slave, rules[d].ID)) {
-			if (rules[d].preg == -1) {
-				return true;
-			}
-		}
-	}
-
-	return null;
-};
-
-window.autoSurgerySelector = function(slave, ruleset)
-{
-
-	var appRules = ruleset.filter(function(rule){
-			return (rule.autoSurgery == 1) && this.currentRules.contains(rule.ID);
-		}, slave);
-
-	var surgery = {eyes: "no default setting", lactation: "no default setting", cosmetic: "nds", accent: "no default setting", shoulders: "no default setting", shouldersImplant: "no default setting", boobs: "no default setting", hips: "no default setting", hipsImplant: "no default setting", butt: "no default setting", faceShape: "no default setting", lips: "no default setting", holes: "nds", bodyhair: "nds", hair: "nds", bellyImplant: "no default setting"};
-	var i, key, ruleSurgery;
-
-	for (i in appRules)
-	{
-		ruleSurgery = appRules[i].surgery;
-		for (key in ruleSurgery)
-		{
-			if (ruleSurgery[key] != "no default setting" || ruleSurgery[key] != "nds")
-			{	
-				surgery[key] = ruleSurgery[key];
-			}
-		}
-	}
-
-	return surgery;
-}
-
-window.mergeRules = function(rules) {
-    var combinedRule = {};
-
-    for (var i = 0; i < rules.length; i++) {
-        for (var prop in rules[i]) {
-            // A rule overrides any preceding ones if,
-            //   * there are no preceding ones,
-            //   * or it sets autoBrand,
-            //   * or it does not set autoBrand and is not "no default setting"
-            var applies = (
-                combinedRule[prop] === undefined
-                || (prop === "autoBrand" && rules[i][prop])
-                || (prop !== "autoBrand" && rules[i][prop] !== "no default setting")
-            );
-
-            if (applies)
-            {
-
-            	//Objects in JS in operations "=" pass by reference, so we need a completely new object to avoid messing up previous rules.
-            	if ("object" == typeof rules[i][prop] && "object" != typeof combinedRule[prop])
-            		combinedRule[prop] = new Object();
-
-            	//If we already have object - now we will process its properties, but object itself should be skipped.
-            	if ("object" != typeof combinedRule[prop])
-                	combinedRule[prop] = rules[i][prop];
-
-            	/*Some properties of rules now have second level properties. We need to check it, and change ones in combinedRule. (Good example - growth drugs. Breasts, butt, etc...) */
-            	if ( "object" == typeof rules[i][prop])
-    	        {
-	            	for (var subprop in rules[i][prop])
-    	        	{
-    	           		var subapplies = (
-            	    	combinedRule[prop][subprop] === undefined
-                			|| (rules[i][prop][subprop] !== "no default setting")
-	            		);
-
-		            	if (subapplies)
-    		            	combinedRule[prop][subprop] = rules[i][prop][subprop];
-    		        }
-
-            	}
-           	}
-
-        }
-
-    }
-
-    return combinedRule;
-}
-
 /* End Week Passage Conversions */
 
 /*:: SA rest [script]*/
@@ -9621,41 +9415,26 @@ window.setColors = function(colorMap){
  * Usage: <<htag atributes>>...<</htag>>    
  * Usage: <<htag atributes tag>>...<</htag>>    
  */
-Macro
-    .add(
-        'htag',
-        {   tags            : null
-        ,   handler()
-            {
-		const payload   =   this.payload[0].contents.replace(/(^\n+|\n+$)/, '');
-		let htag        =   'div';
+Macro.add('htag', {
+	tags: null,
+	handler() {
+		const payload = this.payload[0].contents.replace(/(^\n+|\n+$)/, '');
+		let htag = 'div';
 		let attributes;
-
-                var     munge   =   function (val, key) 
-                {
-                    return  key + '="' + val + '"';
-                };
+		function munge (val, key)  {
+			return  key + '="' + val + '"';
+		}
 		
-                if  (1  >  this.args.length)
-                {
-                    return  
-                        this.error(
-                            'invalid syntax, format: <<htag [id [ tag ] | attributes [ tag ] >>'
-                        );
-		}
-                if  (1  <  this.args.length)
-                {
-                    htag    =   String(this.args[1]).trim();
-                }
-                if  ("object"   === typeof this.args[0])
-                {
-                    attributes  =   $.map(this.args[0], munge).join(" ");
-                }
-                else
-                {
-                    attributes  =   'id="' + String(this.args[0]).trim() + '"';
-                }
-		Config.debug && this.debugView.modes({block: true});
+		if (1  >  this.args.length)
+			return this.error('invalid syntax, format: <<htag [id [ tag ] | attributes [ tag ] >>');
+		if (1  <  this.args.length)
+			htag = String(this.args[1]).trim();
+		if ("object" === typeof this.args[0])
+			attributes = $.map(this.args[0], munge).join(" ");
+		else
+			attributes = 'id="' + String(this.args[0]).trim() + '"';
+		if (Config.debug)
+			this.debugView.modes({block: true});
 		
 		jQuery('<' + htag + ' ' + attributes + ' />')
 			.wiki(payload)
@@ -9665,136 +9444,5803 @@ Macro
 
 /*:: Quick List [script]*/
 
-window.sortDomObjects = function (objects, attrName, reverse = 0)
-{
-    reverse =   (reverse)
-            ?   -1
-            :   1
-            ;
-    var sortingByAttr = function (a, b)
-    {
-        var     aVal    =   a.getAttribute(attrName)
-            ,   bVal    =   b.getAttribute(attrName)
-            ;
-        var     aInt    =   parseInt(aVal)
-            ;
-        if  (!isNaN(aInt))
-        {
-            return  ((parseInt(bVal) - aInt) * reverse);
-        }
-        else if (bVal > aVal)
-        {
-            return  -1 * reverse;
-        }
-        return  ((aVal == bVal) ? 0 : 1) * reverse;
-    };
-    return  objects.toArray().sort(sortingByAttr);
+window.sortDomObjects = function (objects, attrName, reverse = 0) {
+	reverse = (reverse) ? -1 : 1;
+	function sortingByAttr (a, b) {
+		var aVal = a.getAttribute(attrName);
+		var bVal = b.getAttribute(attrName);
+		var aInt = parseInt(aVal);
+		if  (!isNaN(aInt))
+			return ((parseInt(bVal) - aInt) * reverse);
+		else if (bVal > aVal)
+			return -1 * reverse;
+		return ((aVal == bVal) ? 0 : 1) * reverse;
+	}
+	return objects.toArray().sort(sortingByAttr);
 };
 
-window.sortButtonsByDevotion    =   function ()
-{
-    var $sortedButtons   =  $('#qlWrapper button').remove();
+window.sortButtonsByDevotion = function () {
+	var $sortedButtons = $('#qlWrapper button').remove();
+	$sortedButtons = sortDomObjects($sortedButtons, 'data-devotion');
+	$($sortedButtons).appendTo($('#qlWrapper'));
+	quickListBuildLinks();
+};
+
+window.sortButtonsByTrust = function () {
+	var $sortedButtons = $('#qlWrapper button').remove();
+	$sortedButtons = sortDomObjects($sortedButtons, 'data-trust');
+	$($sortedButtons).appendTo($('#qlWrapper'));
+	quickListBuildLinks();
+};
 
-    $sortedButtons  =   sortDomObjects($sortedButtons, 'data-devotion');
+window.quickListBuildLinks = function () {
+	$("[data-scroll-to]").click(function() {
+		var $this = $(this), $toElement = $this.attr('data-scroll-to');
+		// note the * 1 enforces $offset to be an integer, without
+		// it we scroll to True, which goes nowhere fast.
+                var $offset = $this.attr('data-scroll-offset') * 1 || 0;
+                var $speed =   $this.attr('data-scroll-speed') * 1 || 500;
+		// Use javascript scrollTop animation for in page navigation.
+		$('html, body').animate({
+			scrollTop: $($toElement).offset().top + $offset
+		}, $speed);
+	});
+};
 
-    $($sortedButtons).appendTo($('#qlWrapper'));
-    quickListBuildLinks();
+window.sortIncubatorPossiblesByName = function () {
+	var $sortedIncubatorPossibles = $('#qlIncubator div.possible').detach();
+	$sortedIncubatorPossibles = sortDomObjects($sortedIncubatorPossibles, 'data-name');
+	$($sortedIncubatorPossibles).appendTo($('#qlIncubator'));
 };
 
-window.sortButtonsByTrust   =   function ()
-{
-    var $sortedButtons   =  $('#qlWrapper button').remove();
+window.sortIncubatorPossiblesByPregnancyWeek = function () {
+	var $sortedIncubatorPossibles = $('#qlIncubator div.possible').detach();
+	$sortedIncubatorPossibles = sortDomObjects($sortedIncubatorPossibles, 'data-preg-week');
+	$($sortedIncubatorPossibles).appendTo($('#qlIncubator'));
+};
 
-    $sortedButtons  =   sortDomObjects($sortedButtons, 'data-trust');
+window.sortIncubatorPossiblesByPregnancyCount = function () {
+	var $sortedIncubatorPossibles = $('#qlIncubator div.possible').detach();
+	$sortedIncubatorPossibles = sortDomObjects($sortedIncubatorPossibles, 'data-preg-count');
+	$($sortedIncubatorPossibles).appendTo($('#qlIncubator'));
+};
 
-    $($sortedButtons).appendTo($('#qlWrapper'));
-    quickListBuildLinks();
+window.sortIncubatorPossiblesByReservedSpots = function () {
+	var $sortedIncubatorPossibles = $('#qlIncubator div.possible').detach();
+	$sortedIncubatorPossibles = sortDomObjects($sortedIncubatorPossibles, 'data-reserved-spots');
+	$($sortedIncubatorPossibles).appendTo($('#qlIncubator'));
 };
 
-window.quickListBuildLinks  =   function ()
-{
-    $("[data-scroll-to]").click(function() {
-            var     $this = $(this), $toElement = $this.attr('data-scroll-to'),
-                    /*
-                    * note the * 1 enforces $offset to be an integer, without
-                    *       it we scroll to True, which goes nowhere fast.
-                    */
-                    $offset =   $this.attr('data-scroll-offset')    * 1 || 0,
-                    $speed  =   $this.attr('data-scroll-speed')     * 1 || 500
-                ;
-            /*
-            *   Use javascript scrollTop animation for in page navigation.
-            */
-            $('html, body').animate({
-                    scrollTop: $($toElement).offset().top + $offset
-            }, $speed);
-    });
+window.sortIncubatorPossiblesByPreviousSort = function () {
+	var sort = State.variables.sortIncubatorList;
+	console.log(State.variables);
+	console.log('sort', sort);
+	if ('unsorted' !==  sort) {
+		console.log("sort isn't unsorted", sort);
+		if  ('Name' ===  sort) {
+			console.log("sort is name", sort);
+			sortIncubatorPossiblesByName();
+		} else if ('Reserved Incubator Spots' === sort) {
+			console.log("sort is spots", sort);
+			sortIncubatorPossiblesByReservedSpots();
+		} else if ('Pregnancy Week' === sort) {
+			console.log("sort is week", sort);
+			sortIncubatorPossiblesByPregnancyWeek();
+		} else if ('Number of Children' === sort) {
+			console.log("sort is count", sort);
+			sortIncubatorPossiblesByPregnancyCount();
+		}
+	}
 };
 
-window.sortIncubatorPossiblesByName =   function ()
-{
-    var $sortedIncubatorPossibles   =  $('#qlIncubator div.possible').detach();
+/*:: DefaultRules [script]*/
+// this code applies RA rules onto slaves
 
-    $sortedIncubatorPossibles   =   sortDomObjects($sortedIncubatorPossibles, 'data-name');
+window.DefaultRules = (function() {
+	"use strict";
+	let V;
+	let r;
 
-    $($sortedIncubatorPossibles).appendTo($('#qlIncubator'));
-};
+	function DefaultRules(slave) {
+		V = State.variables;
+		r = "";
+		let rule = MergeRules(slave);
+
+		if (Object.keys(rule).length === 0) return r; // no rules apply
+
+		AssignJobToSlave(slave, rule);
+		if(slave.fuckdoll === 0) {
+			ProcessClothing(slave, rule);
+			ProcessCollar(slave, rule);
+			ProcessEyewear(slave, rule);
+			ProcessDildos(slave, rule);
+			ProcessDickAccessories(slave, rule);
+			ProcessAnalAccessories(slave, rule);
+			ProcessShoes(slave, rule);
+			ProcessBellyAccessories(slave, rule);
+		}
+		ProcessBellyImplant(slave, rule);
+		if (isFertile(slave))
+			ProcessFertilityDrugs(slave, rule);
+		ProcessAssetGrowthDrugs(slave, rule);
+		ProcessOtherDrugs(slave, rule);
+		ProcessDiet(slave, rule);
+		ProcessCuratives(slave, rule);
+		ProcessAphrodisiacs(slave, rule);
+		ProcessPenisHormones(slave, rule);
+		ProcessFemaleHormones(slave, rule);
+		ProcessPregnancyDrugs(slave, rule);
+		if(slave.fuckdoll === 0) {
+			ProcessLivingStandard(slave, rule);
+			ProcessSpeech(slave, rule);
+			ProcessRelationship(slave, rule);
+			ProcessRelease(slave, rule);
+			ProcessPunishment(slave, rule);
+			ProcessReward(slave, rule);
+		}
+		ProcessDietCum(slave, rule);
+		ProcessDietMilk(slave, rule);
+		ProcessTeeth(slave, rule);
+		ProcessStyle(slave, rule);
+		ProcessPiercings(slave, rule);
+		ProcessSmartPiercings(slave, rule);
+		ProcessTattoos(slave, rule);
+		ProcessPorn(slave, rule);
+		return r;
+	}
+
+	function MergeRules(slave) {
+		// merge all rules applying on a slave into one big rule
+		const rules = V.defaultRules
+			.filter(rule => ruleAppliesP(rule.condition, slave))
+			.map(rule => ProcessAssignments(slave, Object.assign({}, rule.set)));
+		return mergeRules(rules);
+	}
+
+	function ProcessAssignments(slave, rule) {
+		// Before merging rules, we process assignments for each rule separately so we can remove slaves from facilities when they no longer qualify, even if the final "winning" rule assigns them elsewhere 
+		// We also ignore inapplicable assignments for the current slave, so we only merge assignments that are valid 
+		switch (rule.setAssignment) {
+			case "no default setting":
+				delete rule.setAssignment;
+				break;
+			
+			case "rest":
+			case "please you":
+				// slaves always qualify for this assignment 
+				break;
 
-window.sortIncubatorPossiblesByPregnancyWeek    =   function ()
-{
-    var $sortedIncubatorPossibles   =  $('#qlIncubator div.possible').detach();
+			case "live with your Head Girl":
+				if ((V.HGSuiteSlaves < 1 && slave.indentureRestrictions <= 0))
+					break;
+				else {
+					RAFacilityRemove(slave, rule); // before deleting rule.setAssignment 
+					delete rule.setAssignment;
+				}
+				break;
 
-    $sortedIncubatorPossibles   =   sortDomObjects($sortedIncubatorPossibles, 'data-preg-week');
+			case "be confined in the arcade":
+				if ((V.arcadeSlaves < V.arcade && slave.indentureRestrictions <= 0 && slave.breedingMark != 1))
+					break;
+				else {
+					RAFacilityRemove(slave, rule); // before deleting rule.setAssignment 
+					delete rule.setAssignment;
+				}
+				break;
 
-    $($sortedIncubatorPossibles).appendTo($('#qlIncubator'));
-};
+			case "serve in the master suite":
+				if ((V.masterSuiteSlaves < V.masterSuite && (slave.devotion > 20 || slave.trust < -50 || (slave.devotion >= -50 && slave.trust < -20))))
+					break;
+				else {
+					RAFacilityRemove(slave, rule); // before deleting rule.setAssignment 
+					delete rule.setAssignment;
+				}
+				break;
 
-window.sortIncubatorPossiblesByPregnancyCount   =   function ()
-{
-    var $sortedIncubatorPossibles   =  $('#qlIncubator div.possible').detach();
+			case "get treatment in the clinic":
+				if ((V.clinicSlaves < V.clinic && (slave.health < 20 || (slave.chem > 15 && V.Nurse !== 0 && V.clinicUpgradeFilters == 1)) || ((slave.bellyImplant > -1) && (V.bellyImplants == 1)) || slave.preg > 1))
+					break;
+				else {
+					RAFacilityRemove(slave, rule); // before deleting rule.setAssignment 
+					delete rule.setAssignment;
+				}
+				break;
 
-    $sortedIncubatorPossibles   =   sortDomObjects($sortedIncubatorPossibles, 'data-preg-count');
+			case "rest in the spa":
+				if ((V.spaSlaves < V.spa) && (slave.health < 20) || (slave.trust < 60) || (slave.devotion <= 60) || (slave.fetish == "mindbroken") && (slave.devotion >= -20))
+					break;
+				else {
+					RAFacilityRemove(slave,rule); // before deleting rule.setAssignment 
+					delete rule.setAssignment;
+				}
+				break;
 
-    $($sortedIncubatorPossibles).appendTo($('#qlIncubator'));
-};
+			case "work in the brothel":
+				if ((V.brothelSlaves < V.brothel && (slave.devotion > 50 || slave.trust > 50 || slave.trust < -50 || (slave.devotion >= -50 && slave.trust < -20)) && slave.breedingMark != 1))
+					break;
+				else {
+					RAFacilityRemove(slave, rule); // before deleting rule.setAssignment 
+					delete rule.setAssignment;
+				}
+				break;
 
-window.sortIncubatorPossiblesByReservedSpots    =   function ()
-{
-    var $sortedIncubatorPossibles   =  $('#qlIncubator div.possible').detach();
+			case "serve in the club":
+				if ((V.clubSlaves < V.club && (slave.devotion > 50 || slave.trust > 50 || slave.trust < -50 || (slave.devotion >= -50 && slave.trust < -20)) && slave.breedingMark != 1))
+					break;
+				else {
+					RAFacilityRemove(slave, rule); // before deleting rule.setAssignment 
+					delete rule.setAssignment;
+				}
+				break;
 
-    $sortedIncubatorPossibles   =   sortDomObjects($sortedIncubatorPossibles, 'data-reserved-spots');
+			case "work in the dairy":
+				if ((V.dairy > V.dairySlaves+V.bioreactorsXY+V.bioreactorsXX+V.bioreactorsHerm+V.bioreactorsBarren)) {
+					if ((slave.indentureRestrictions > 0) && (V.dairyRestraintsSetting > 1))
+						break;
+					else if (((slave.indentureRestrictions > 1) && (V.dairyRestraintsSetting > 0)) || (slave.breedingMark == 1 && V.dairyRestriantsSettings > 0) || ((V.dairyPregSetting > 0) && ((slave.bellyImplant != -1) || (slave.broodmother !== 0))))
+						break;
+					else {
+						if ((slave.lactation > 0 || ((V.dairySlimMaintainUpgrade === 0 || V.dairySlimMaintain === 0) && (slave.boobs > 300 || slave.dick === 0 || V.dairyImplantsSetting == 1) && V.dairyImplantsSetting != 2)) || (slave.balls > 0)) {
+							if ((slave.devotion > 20) || ((slave.devotion >= -50) && (slave.trust < -20)) || (slave.trust < -50) || (slave.amp == 1) || (V.dairyRestraintsUpgrade == 1)) {
+								if ((V.dairyStimulatorsSetting < 2) || (slave.anus > 2) || (V.dairyPrepUpgrade == 1)) {
+									if ((V.dairyPregSetting < 2) || (slave.vagina > 2) || (slave.ovaries === 0) || (V.dairyPrepUpgrade == 1))
+										break;
+									else {
+										RAFacilityRemove(slave,rule); // before deleting rule.setAssignment 
+										delete rule.setAssignment;
+									}
+								} else {
+									RAFacilityRemove(slave,rule); // before deleting rule.setAssignment 
+									delete rule.setAssignment;
+								}
+							} else {
+								RAFacilityRemove(slave,rule); // before deleting rule.setAssignment 
+								delete rule.setAssignment;
+							}
+						} else {
+							RAFacilityRemove(slave,rule); // before deleting rule.setAssignment 
+							delete rule.setAssignment;
+						}
+					}
+				}
+				break;
 
-    $($sortedIncubatorPossibles).appendTo($('#qlIncubator'));
-};
+			case "work as a servant":
+				if ((V.servantsQuartersSlaves < V.servantsQuarters && canSee(slave) && canWalk(slave) && (slave.devotion >= -20 || slave.trust < -20 || (slave.devotion >= -50 && slave.trust <= 20))))
+					break;
+				else {
+					RAFacilityRemove(slave,rule); // before deleting rule.setAssignment 
+					delete rule.setAssignment;
+				}
+				break;
 
-window.sortIncubatorPossiblesByPreviousSort    =   function ()
-{
-    var     sort    =   State.variables.sortIncubatorList
-        ;
-console.log(State.variables);
-console.log('sort', sort);
-    if  ('unsorted' !=  sort)
-    {
-console.log("sort isn't unsorted", sort);
-        if  ('Name' ==  sort)
-        {
-console.log("sort is name", sort);
-            sortIncubatorPossiblesByName();
-        }
-        else if ('Reserved Incubator Spots' ==  sort)
-        {
-console.log("sort is spots", sort);
-            sortIncubatorPossiblesByReservedSpots();
-        }
-        else if ('Pregnancy Week'   ==  sort)
-        {
-console.log("sort is week", sort);
-            sortIncubatorPossiblesByPregnancyWeek();
-        }
-        else if ('Number of Children'   ==  sort)
-        {
-console.log("sort is count", sort);
-            sortIncubatorPossiblesByPregnancyCount();
-        }
-    }
-};
+			case "learn in the schoolroom":
+				if ((V.schoolroomSlaves < V.schoolroom && slave.fetish != "mindbroken" && (slave.devotion >= -20 || slave.trust < -50 || (slave.devotion >= -50 && slave.trust < -20))))
+					if ((slave.intelligenceImplant < 1) || (slave.voice !== 0 && slave.accent+V.schoolroomUpgradeLanguage > 2) || (slave.oralSkill <= 10+V.schoolroomUpgradeSkills*20) || (slave.whoreSkill <= 10+V.schoolroomUpgradeSkills*20) || (slave.entertainSkill <= 10+V.schoolroomUpgradeSkills*20) || (slave.analSkill < 10+V.schoolroomUpgradeSkills*20) || ((slave.vagina >= 0) && (slave.vaginalSkill < 10+V.schoolroomUpgradeSkills*20)))
+						break;
+					else {
+						RAFacilityRemove(slave,rule); // before deleting rule.setAssignment 
+						delete rule.setAssignment;
+					}
+				else {
+					RAFacilityRemove(slave,rule); // before deleting rule.setAssignment 
+					delete rule.setAssignment;
+				}
+				break;
+
+			case "be confined in the cellblock":
+				if ((V.cellblockSlaves < V.cellblock && ((slave.devotion < -20 && slave.trust >= -20) || (slave.devotion < -50 && slave.trust >= -50))))
+					break;
+				else {
+					RAFacilityRemove(slave,rule); // before deleting rule.setAssignment 
+					delete rule.setAssignment;
+				}
+				break;
+
+			case "take classes":
+				if (slave.intelligenceImplant !== 1 && slave.fetish != "mindbroken" && (slave.devotion >= -20 || slave.trust < -50 || (slave.trust < -20 && slave.devotion >= -50)))
+					break;
+				else
+					delete rule.setAssignment;
+				break;
+
+			case "choose her own job":
+				if ((slave.fetish != "mindbroken"))
+					break;
+				else
+					delete rule.setAssignment;
+				break;
+
+			case "get milked":
+				if ((slave.lactation > 0 || slave.balls > 0))
+					break;
+				else
+					delete rule.setAssignment;
+				break;
+
+			case "be a servant":
+				if ((canWalk(slave) && canSee(slave) && (slave.devotion >= -20 || slave.trust < -50 || (slave.trust < -20 && slave.devotion >= -50))))
+					break;
+				else
+					delete rule.setAssignment;
+				break;
+
+			case "work a glory hole":
+				if (slave.indentureRestrictions <= 0 && slave.breedingMark != 1)
+					break;
+				else
+					delete rule.setAssignment;
+				break;
+
+			case "whore":
+			case "serve the public":
+			case "stay confined":
+				if ((slave.fuckdoll === 0) && slave.breedingMark != 1)
+					break;
+				else
+					delete rule.setAssignment;
+				break;
+
+			default:
+				r += `<span class="red">raWidgets missing case for assignment 'V.{rule.setAssignment}'</span>.`;
+				break;
+		}
+		return rule;
+	}
+
+	function AssignJobToSlave(slave, rule) {
+		// place slave on assignment defined by the rule
+		if ((rule.setAssignment !== undefined && rule.setAssignment != "no default setting")) {
+			if (((rule.setAssignment == "choose her own job" && !slave.choosesOwnAssignment) || rule.setAssignment != slave.assignment)) {
+				switch (rule.setAssignment) {
+					case "live with your Head Girl":
+						r += `<br>${slave.slaveName} has been automatically assigned to live in your Head Girl's private suite.`;
+						break;
+					case "be confined in the arcade":
+						r += `<br>${slave.slaveName} has been automatically assigned to be confined in ${V.arcadeName}.`;
+						break;
+					case "serve in the master suite":
+						r += `<br>${slave.slaveName} has been automatically assigned to ${V.masterSuiteName}.`;
+						break;
+					case "get treatment in the clinic":
+						r += `<br>${slave.slaveName} has been automatically assigned to get treatment in ${V.clinicName}.`;
+						break;
+					case "rest in the spa":
+						r += `<br>${slave.slaveName} has been automatically assigned to rest in ${V.spaName}.`;
+						break;
+					case "work in the brothel":
+						r += `<br>${slave.slaveName} has been automatically assigned to work in ${V.brothelName}.`;
+						break;
+					case "serve in the club":
+						r += `<br>${slave.slaveName} has been automatically assigned to serve in ${V.clubName}.`;
+						break;
+					case "work in the dairy":
+						r += `<br>${slave.slaveName} has been automatically assigned to be milked in ${V.dairyName}.`;
+						break;
+					case "work as a servant":
+						r += `<br>${slave.slaveName} has been automatically assigned to work in ${V.servantsQuartersName}.`;
+						break;
+					case "work as a servant":
+						r += `<br>${slave.slaveName} has been automatically assigned to work in ${V.servantsQuartersName}.`;
+						break;
+					case "learn in the schoolroom":
+						r += `<br>${slave.slaveName} has been automatically assigned to study in ${V.schoolroomName}.`;
+						break;
+					case "be confined in the cellblock":
+						r += `<br>${slave.slaveName} has been automatically assigned to be confined in ${V.cellblockName}.`;
+						break;
+					case "choose her own job":
+						r += `<br>${slave.slaveName} is now allowed to select her own assignments.`;
+						break;
+					default:
+						r += `<br>${slave.slaveName} has been automatically assigned to ${rule.setAssignment}.`;
+						break;
+				}
+				assignJob(slave, rule.setAssignment);
+			}
+		}
+	}
+
+	function ProcessClothing(slave, rule) {
+		// apply clothes to slave
+		if ((rule.clothes !== undefined) && (rule.clothes !== "no default setting")) {
+			if ((rule.clothes == "choosing her own clothes")) {
+				if ((slave.choosesOwnClothes === 0)) {
+					slave.clothes = "choosing her own clothes";
+					slave.choosesOwnClothes = 1;
+					r += `<br>${slave.slaveName} is now allowed to choose her own clothes.`;
+				}
+			} else if ((slave.clothes !== rule.clothes)) {
+				slave.clothes = rule.clothes;
+				slave.choosesOwnClothes = 0;
+				r += `<br>${slave.slaveName} is now wearing ${slave.clothes}.`;
+			}
+		}
+	}
+
+	function ProcessCollar(slave, rule) {
+		// apply collar to slave
+		if ((rule.collar !== undefined) && (rule.collar != "no default setting")) {
+			if ((slave.collar !== rule.collar)) {
+				r += '<br>';
+				if ((rule.collar == "preg biometrics" && slave.preg <= -1)) {
+					slave.collar = "none";
+					r += `${slave.slaveName} cannot utilize preg biometrics.`;
+				} else if ((rule.collar == "massive dildo gag" && slave.oralSkill <= 50)) {
+					slave.collar = "none";
+					r += `${slave.slaveName} lacks the oral skill to successfully keep the massive dildo gag in her throat.`;
+				} else
+					slave.collar = rule.collar;
+				if ((slave.collar == "none"))
+					r += `${slave.slaveName} has been given no collar.`;
+				else
+					r += `${slave.slaveName} has been given a ${slave.collar} collar.`;
+			}
+		}
+	}
+
+	function ProcessEyewear(slave, rule) {
+		// apply glasses, contacts to slave
+		if ((rule.eyewear !== undefined) && (rule.eyewear !== "no default setting")) {
+			switch (rule.eyewear) {
+				case "correct with glasses":
+					if (slave.eyes == -1) {
+						if (slave.eyewear != "corrective glasses") {
+							slave.eyewear = "corrective glasses";
+							V.cash -= V.modCost;
+							r += `<br>${slave.slaveName} has been given corrective glasses.`;
+						}
+					} else {
+						if (slave.eyewear != "none") {
+							slave.eyewear = "none";
+							r += `<br>${slave.slaveName}'s eyewear has been removed.`;
+						}
+					}
+					break;
+
+				case "correct with contacts":
+					if (slave.eyes == -1) {
+						if (slave.eyewear != "corrective contacts") {
+							slave.eyewear = "corrective contacts";
+							V.cash -= V.modCost;
+							r += `<br>${slave.slaveName} has been given corrective contacts.`;
+						}
+					} else {
+						if (slave.eyewear != "none") {
+							slave.eyewear = "none";
+							r += `<br>${slave.slaveName}'s eyewear has been removed.`;
+						}
+					}
+					break;
+
+				case "blur with glasses":
+					if (slave.eyes > -1) {
+						if (slave.eyewear != "blurring glasses") {
+							slave.eyewear = "blurring glasses";
+							V.cash -= V.modCost;
+							r += `<br>${slave.slaveName} has been given blurring glasses.`;
+						}
+					} else {
+						if (slave.eyewear != "none") {
+							slave.eyewear = "none";
+							r += `<br>${slave.slaveName}'s eyewear has been removed.`;
+						}
+					}
+					break;
+
+				case "blur with contacts":
+					if (slave.eyes > -1) {
+						if (slave.eyewear != "blurring contacts") {
+							slave.eyewear = "blurring contacts";
+							V.cash -= V.modCost;
+							r += `<br>${slave.slaveName} has been given blurring contacts.`;
+						}
+					} else {
+						if (slave.eyewear != "none") {
+							slave.eyewear = "none";
+							r += `<br>Since ${slave.slaveName}'s eyewear has been removed.`;
+						}
+					}
+					break;
+
+				case "universal glasses":
+					if (slave.eyes == -1) {
+						if (slave.eyewear != "corrective glasses") {
+							slave.eyewear = "corrective glasses";
+							V.cash -= V.modCost;
+							r += `<br>${slave.slaveName} has been given corrective glasses.`;
+						}
+					} else {
+						if (slave.eyewear != "glasses") {
+							slave.eyewear = "glasses";
+							V.cash -= V.modCost;
+							r += `<br>${slave.slaveName} has been given decorative glasses.`;
+						}
+					}
+					break;
+
+				default:
+					if (slave.eyewear != "none") {
+						slave.eyewear = "none";
+						r += `<br>${slave.slaveName}'s eyewear has been removed.`;
+					}
+					break;
+			}
+		}
+	}
+
+	function ProcessDildos(slave, rule) {
+		// apply vaginal dildos to slave
+		if (slave.vagina === 0)
+			ProcessVVirginDildos(slave, rule);
+		else if ((slave.vagina > 0) && (slave.anus === 0))
+			ProcessAVirginDildos(slave, rule);
+		else if (slave.vagina > 0)
+			ProcessNonVirginDildos(slave, rule);
+	}
+
+	function ProcessVVirginDildos(slave, rule) {
+		// apply vaginal dildos to varginal virgins
+		if ((rule.virginAccessory !== undefined) && (rule.virginAccessory !== "no default setting")) {
+			if (slave.vaginalAccessory !== rule.virginAccessory) {
+				slave.vaginalAccessory = rule.virginAccessory;
+				switch (slave.vaginalAccessory) {
+					case "huge dildo":
+						r += `<br>${slave.slaveName} is a virgin and has been given a`;
+						if (slave.vagina >= 2)
+							r += `massive dildo to permanently gape her cunt.`;
+						else {
+							r += `large dildo for her pussy, since it must be stretched before it can accommodate a huge one.`;
+							slave.vaginalAccessory = "large dildo";
+						}
+						break;
+
+					case "long dildo":
+						if (slave.breedingMark == 1) {
+							r += `<br>Breeding regulations forbid the use of cervix penetrating dildos on marked slaves, so the virgin ${slave.slaveName} has been given a standard length dildo for her pussy.`;
+							slave.vaginalAccessory = "dildo";
+						}
+						break;
+
+					case "long, large dildo":
+						if (slave.breedingMark == 1) {
+							r += `<br>Breeding regulations forbid the use of cervix penetrating dildos on marked slaves, so the virgin ${slave.slaveName} has been given a standard length large dildo for her pussy.`;
+							slave.vaginalAccessory = "large dildo";
+						}
+						break;
+
+					case "long, huge dildo":
+						if (slave.breedingMark == 1) {
+							r += `<br>Breeding regulations forbid the use of cervix penetrating dildos on marked slaves, so the virgin ${slave.slaveName} has been given a standard length huge dildo for her pussy.`;
+							slave.vaginalAccessory = "huge dildo";
+						} else {
+							r += `<br>slave.slaveName is a virgin and has been given a`;
+							if (slave.vagina >= 2)
+								r += `massive and oversized dildo to permanently gape her cunt.`;
+							else {
+								r += `long, large dildo for her pussy, since it must be stretched before it can accommodate a huge one.`;
+								slave.vaginalAccessory = "long, large dildo";
+							}
+						}
+						break;
+
+					case "none":
+						r += `<br>${slave.slaveName} is a virgin and has been instructed not to use a vaginal accessory.`;
+						break;
+
+					default:
+						r += `<br>${slave.slaveName} is a virgin and has been given a ${slave.vaginalAccessory} for her pussy.`;
+						break;
+				}
+			}
+		}
+	}
+
+	function ProcessAVirginDildos(slave, rule) {
+		// apply vaginal dildos to anal virgins
+		if ((rule.aVirginAccessory !== undefined) && (rule.aVirginAccessory !== "no default setting")) {
+			if (slave.vaginalAccessory !== rule.aVirginAccessory) {
+				slave.vaginalAccessory = rule.aVirginAccessory;
+				switch (slave.vaginalAccessory) {
+					case "huge dildo":
+						r += `<br>${slave.slaveName} is a virgin and has been given a`;
+						if (slave.vagina >= 2)
+							r += `massive dildo to permanently gape her cunt.`;
+						else {
+							r += `large dildo for her pussy, since it must be stretched before it can accommodate a huge one.`;
+							slave.vaginalAccessory = "large dildo";
+						}
+						break;
+
+					case "long dildo":
+						if (slave.breedingMark == 1) {
+							r += `<br>Breeding regulations forbid the use of cervix penetrating dildos on marked slaves, so the virgin ${slave.slaveName} has been given a standard length dildo for her pussy.`;
+							slave.vaginalAccessory = "dildo";
+						}
+						break;
+
+					case "long, large dildo":
+						if (slave.breedingMark == 1) {
+							r += `<br>Breeding regulations forbid the use of cervix penetrating dildos on marked slaves, so the virgin ${slave.slaveName} has been given a standard length large dildo for her pussy.`;
+							slave.vaginalAccessory = "large dildo";
+						}
+						break;
+
+					case "long, huge dildo":
+						if (slave.breedingMark == 1) {
+							r += `<br>Breeding regulations forbid the use of cervix penetrating dildos on marked slaves, so the virgin ${slave.slaveName} has been given a standard length huge dildo for her pussy.`;
+							slave.vaginalAccessory = "huge dildo";
+						} else {
+							r += `<br>${slave.slaveName} is a virgin and has been given a`;
+							if (slave.vagina >= 2)
+								r += `massive and oversized dildo to permanently gape her cunt.`;
+							else {
+								r += `long, large dildo for her pussy, since it must be stretched before it can accommodate a huge one.`;
+								slave.vaginalAccessory = "long, large dildo";
+							}
+						}
+						break;
+
+					case "none":
+						r += `<br>slave.slaveName is a virgin and has been instructed not to use a vaginal accessory.`;
+						break;
+
+					default:
+						r += `<br>slave.slaveName is a virgin and has been given a slave.vaginalAccessory for her pussy.`;
+						break;
+				}
+			}
+		}
+	}
+
+	function ProcessNonVirginDildos(slave, rule) {
+		// apply vaginal dildos to non-virgins
+		if ((rule.vaginalAccessory !== undefined) && (rule.vaginalAccessory !== "no default setting")) {
+			if (slave.vaginalAccessory !== rule.vaginalAccessory) {
+				slave.vaginalAccessory = rule.vaginalAccessory;
+				switch (slave.vaginalAccessory) {
+					case "huge dildo":
+						r += `<br>${slave.slaveName} has been given a`;
+						if (slave.vagina >= 2)
+							r += `massive dildo to permanently gape her cunt.`;
+						else {
+							r += `large dildo for her pussy, since it must be stretched before it can accommodate a huge one.`;
+							slave.vaginalAccessory = "large dildo";
+						}
+						break;
+
+					case "long dildo":
+						if (slave.breedingMark == 1) {
+							r += `<br>Breeding regulations forbid the use of cervix penetrating dildos on marked slaves, so ${slave.slaveName} has been given a standard length dildo for her pussy.`;
+							slave.vaginalAccessory = "dildo";
+						}
+						break;
+
+					case "long, large dildo":
+						if (slave.breedingMark == 1) {
+							r += `<br>Breeding regulations forbid the use of cervix penetrating dildos on marked slaves, so ${slave.slaveName} has been given a standard length large dildo for her pussy.`;
+							slave.vaginalAccessory = "large dildo";
+						}
+						break;
+
+					case "long, huge dildo":
+						if (slave.breedingMark == 1) {
+							r += `<br>Breeding regulations forbid the use of cervix penetrating dildos on marked slaves, so ${slave.slaveName} has been given a standard length huge dildo for her pussy.`;
+							slave.vaginalAccessory = "huge dildo";
+						} else {
+							r += `<br>${slave.slaveName} has been given a`;
+							if (slave.vagina >= 2)
+								r += `massive and oversized dildo to permanently gape her cunt.`;
+							else {
+								r += `long, large dildo for her pussy, since it must be stretched before it can accommodate a huge one.`;
+								slave.vaginalAccessory = "long, large dildo";
+							}
+						}
+						break;
+					case "none":
+						r += `<br>${slave.slaveName} has been instructed not to use a vaginal accessory.`;
+						break;
+
+					default:
+						r += `<br>${slave.slaveName} has been given a slave.vaginalAccessory for her pussy.`;
+						break;
+				}
+			}
+		}
+	}
+
+	function ProcessDickAccessories(slave, rule) {
+		// apply dick accessories to slave
+		if ((slave.dick > 0)) {
+			if (slave.anus === 0) {
+				if ((rule.aVirginDickAccessory !== undefined) && (rule.aVirginDickAccessory !== "no default setting")) {
+					if ((slave.dickAccessory !== rule.aVirginDickAccessory)) {
+						slave.dickAccessory = rule.aVirginDickAccessory;
+						if (slave.dickAccessory == "none")
+							r += `<br>${slave.slaveName} is a virgin and has been instructed not to wear a dick accessory.`;
+						else
+							r += `<br>${slave.slaveName} is a virgin and has been given a ${slave.dickAccessory} accessory for her cock.`;
+					}
+				}
+			} else {
+				if ((rule.dickAccessory !== undefined) && (rule.dickAccessory !== "no default setting")) {
+					if ((slave.dickAccessory !== rule.dickAccessory)) {
+						slave.dickAccessory = rule.dickAccessory;
+						if (slave.dickAccessory == "none")
+							r += `<br>${slave.slaveName} has been instructed not to wear a dick accessory.`;
+						else
+							r += `<br>${slave.slaveName} has been given a slave.dickAccessory accessory for her cock.`;
+					}
+				}
+			}
+		}
+	}
+
+	function ProcessShoes(slave, rule) {
+		// apply shoes to slave
+		if ((rule.shoes !== undefined) && (rule.shoes !== "no default setting")) {
+			if ((slave.shoes !== rule.shoes)) {
+				if ((slave.amp != 1)) {
+					slave.shoes = rule.shoes;
+					r += `<br>${slave.slaveName}'s shoes have been set to ${slave.shoes}.`;
+				}
+			}
+		}
+	}
+
+	function ProcessBellyAccessories(slave, rule) {
+		// apply belly accessories to slave
+		if ((rule.bellyAccessory !== undefined) && (rule.bellyAccessory !== "no default setting")) {
+			if ((slave.bellyAccessory !== rule.bellyAccessory)) {
+				if ((slave.belly >= 1500 || slave.weight >= 130) && setup.fakeBellies.includes(rule.bellyAccessory)) {
+					r += `<br>${slave.slaveName}'s natural belly is too big to properly wear an empathy belly.`;
+					slave.bellyAccessory = "none";
+				} else {
+					slave.bellyAccessory = rule.bellyAccessory;
+					if (slave.bellyAccessory == "none")
+						r += `<br>${slave.slaveName} has been instructed not to wear a torso accessory.`;
+					else
+						r += `<br>${slave.slaveName} has been given ${slave.bellyAccessory} to wear.`;
+				}
+			}
+		}
+	}
+
+	function ProcessAnalAccessories(slave, rule) {
+		// apply buttplugs to slave
+		if ((slave.vaginalAccessory !== "anal chastity") && (slave.vaginalAccessory !== "combined chastity") && (slave.dickAccessory !== "anal chastity") && (slave.dickAccessory !== "combined chastity")) {
+			if (slave.anus === 0)
+				ProcessAnalVirginButtplugs(slave, rule);
+			else
+				ProcessNonVirginButtplugs(slave, rule);
+		}
+	}
+
+	function ProcessAnalVirginButtplugs(slave, rule) {
+		// apply buttplugs to virgins
+		if ((rule.aVirginButtplug !== undefined) && (rule.aVirginButtplug !== "no default setting")) {
+			if ((slave.buttplug !== rule.aVirginButtplug)) {
+				slave.buttplug = rule.aVirginButtplug;
+				switch (slave.buttplug) {
+					case "huge plug":
+						r += `<br>${slave.slaveName} is an anal virgin and has been given a`;
+						if ((slave.anus >= 2))
+							r += `massive plug to permanently gape her asshole.`;
+						else {
+							slave.buttplug = "large plug";
+							r += `large buttplug for her asshole, since it must be stretched before it can accommodate a huge one.`;
+						}
+						break;
+
+					case "long plug":
+						if (slave.breedingMark == 1) {
+							r += `<br>Breeding regulations forbid the use of anal plugs that can damage a growing fetus on marked slaves, so the anal virgin ${slave.slaveName} has been given a standard length plug for her anus.`;
+							slave.buttplug = "plug";
+						}
+						break;
+
+					case "long, large plug":
+						if (slave.breedingMark == 1) {
+							r += `<br>Breeding regulations forbid the use of anal plugs that can damage a growing fetus on marked slaves, so the anal virgin ${slave.slaveName} has been given a standard length large plug for her anus.`;
+							slave.buttplug = "large plug";
+						}
+						break;
+
+					case "long, huge plug":
+						if (slave.breedingMark == 1) {
+							r += `<br>Breeding regulations forbid the use of anal plugs that can damage a growing fetus on marked slaves, so the anal virgin ${slave.slaveName} has been given a standard length huge plug for her anus.`;
+							slave.buttplug = "huge plug";
+						} else {
+							r += `<br>slave.slaveName is an anal virgin and has been given a`;
+							if (slave.anus >= 2)
+								r += `massive and oversized plug to permanently gape her asshole.`;
+							else {
+								r += `long, large buttplug for her asshole, since it must be stretched before it can accommodate a huge one.`;
+								slave.buttplug = "long, large plug";
+							}
+						}
+						break;
+
+					case "none":
+						r += `<br>${slave.slaveName} is an anal virgin and has been instructed not to use an anal accessory.`;
+						break;
+
+					default:
+						r += `<br>${slave.slaveName} is an anal virgin and has been given a slave.buttplug for her asshole.`;
+						break;
+				}
+			}
+		}
+	}
+
+	function ProcessNonVirginButtplugs(slave, rule) {
+		// apply buttplugs to non-virgins
+		if ((rule.buttplug !== undefined) && (rule.buttplug !== "no default setting")) {
+			if ((slave.buttplug !== rule.buttplug)) {
+				slave.buttplug = rule.buttplug;
+				switch (slave.buttplug) {
+					case "huge plug":
+						r += `<br>${slave.slaveName} has been given a`;
+						if ((slave.anus >= 2))
+							r += `massive plug to permanently gape her asshole.`;
+						else {
+							slave.buttplug = "large plug";
+							r += `large buttplug for her asshole, since it must be stretched before it can accommodate a huge one.`;
+						}
+						break;
+
+					case "long plug":
+						if (slave.breedingMark == 1) {
+							r += `<br>Breeding regulations forbid the use of anal plugs that can damage a growing fetus on marked slaves, so ${slave.slaveName} has been given a standard length plug for her anus.`;
+							slave.buttplug = "plug";
+						}
+						break;
+						
+					case "long, large plug":
+						if (slave.breedingMark == 1) {
+							r += `<br>Breeding regulations forbid the use of anal plugs that can damage a growing fetus on marked slaves, so ${slave.slaveName} has been given a standard length large plug for her anus.`;
+							slave.buttplug = "large plug";
+						}
+						break;
+
+					case "long, huge plug":
+						if (slave.breedingMark == 1) {
+							r += `<br>Breeding regulations forbid the use of anal plugs that can damage a growing fetus on marked slaves, so ${slave.slaveName} has been given a standard length huge plug for her anus.`;
+							slave.buttplug = "huge plug";
+						} else {
+							r += `<br>${slave.slaveName} has been given a`;
+							if (slave.anus >= 2)
+								r += `massive and oversized plug to permanently gape her asshole.`;
+							else {
+								r += `long, large buttplug for her asshole, since it must be stretched before it can accommodate a huge one.`;
+								slave.buttplug = "long, large plug";
+							}
+						}
+						break;
+
+					case "none":
+						r += `<br>${slave.slaveName} has been instructed not to use an anal accessory.`;
+						break;
+
+					default:
+						r += `<br>${slave.slaveName} has been given a slave.buttplug for her asshole.`;
+						break;
+				}
+			}
+		}
+	}
+
+	function ProcessBellyImplant(slave, rule) {
+		// Here is belly implant size control, it's used in Surgery Degradation passage to setup devotion and trust changes.
+		// silent calls to surgery degradation have been replaced with a js function, which is less hacky
+		if ((rule.bellyImplantVol !== undefined) && slave.bellyImplant >= 0 && rule.bellyImplantVol >= 0) {
+			r += "<br>";
+			if (slave.health > -10 ) {
+				let diff = rule.bellyImplantVol - slave.bellyImplant;
+				if (diff >= 5000 && slave.bellyPain === 0 && slave.health > 50) {
+					r += `${slave.slaveName}'s belly is way too small, so she has been directed to have intensive belly implant filling procedures throughout this week.`;
+					slave.bellyImplant += 1000;
+					slave.bellyPain += 2;
+					BellySurgery(slave, diff);
+				} else if (diff >= 500 && slave.bellyPain < 2 ) {
+					r += `${slave.slaveName}'s belly has not reached the desired size, so she has been directed to have belly implant filling procedures throughout this week.`;
+					slave.bellyImplant += 500;
+					slave.bellyPain += 1;
+					BellySurgery(slave, diff);
+				} else if (diff <= -5000 ) {
+					r += `${slave.slaveName}'s belly is way too big, so she has been directed to have intensive belly implant draining procedures throughout this week.`;
+					slave.bellyImplant -= 1000;
+					BellySurgery(slave, diff);
+				} else if (diff <= -500 ) {
+					r += `${slave.slaveName}'s belly is too big, so she has been directed to have belly implant draining procedures throughout this week.`;
+					slave.bellyImplant -= 500;
+					BellySurgery(slave, diff);
+				}
+			} else {
+				r += `${slave.slaveName} is not healthy enough to safely adjust her belly implant.`;
+			}
+		}
+	}
+
+	function BellySurgery(slave, volume) {
+		// this is a port of the belly implant portion of surgeryDegradation.tw
+		// that way, we don't have to use ugly hacks
+		// the original still exists, and may be worth replacing
+		if (volume > 0) { // bellyUp
+			SetBellySize(slave);
+			if (slave.bellyPain === 1) {
+				if (slave.devotion > 50) {
+					slave.devotion += 4;
+				} else if (slave.devotion >= -20) {
+					slave.trust -= 5;
+				} else {
+					slave.trust -= 10;
+					slave.devotion -= 5;
+				}
+			} else if (slave.bellyPain === 2) {
+				if (slave.devotion > 50) {
+					slave.devotion += 2;
+				} else if (slave.devotion >= -20) {
+					slave.trust -= 7;
+				} else {
+					slave.trust -= 12;
+					slave.devotion -= 7;
+				}
+			}
+		} else { // bellyDown
+			if (slave.bellyImplant < 0)
+				slave.bellyImplant = 0;
+			SetBellySize(slave);
+			if (slave.devotion > 50) {
+				slave.devotion += 3;
+				slave.trust += 3;
+			} else if (slave.devotion >= -20) {
+				slave.trust += 2;
+			} else {
+				slave.devotion += 1;
+				slave.trust -= 10;
+			}
+		}
+	}
+
+	function ProcessFertilityDrugs(slave, rule) {
+		// Fertility 
+		if ((rule.preg !== undefined) && (rule.preg !== "no default setting")) {
+			if ((rule.preg == -1)) {
+				if (slave.preg !== -1) {
+					r += `<br>${slave.slaveName} is fertile, so she has been put on the appropriate contraceptive regime.`;
+					slave.preg = -1;
+				}
+				if (slave.drugs == "fertility drugs" || slave.drugs == "super fertility drugs") {
+					slave.drugs = "no drugs";
+				}
+			} else if ((rule.preg === 0)) {
+				if (slave.preg !== 0) {
+					r += `<br>${slave.slaveName} is fertile, so she has been taken off contraceptives.`;
+					slave.preg = 0;
+				}
+				if (slave.drugs == "fertility drugs" || slave.drugs == "super fertility drugs") {
+					slave.drugs = "no drugs";
+				}
+			} else if ((rule.preg == 1)) {
+				if (slave.preg !== 0 || slave.drugs !== "fertility drugs" || slave.hormones !== 0) {
+					slave.preg = 0;
+					slave.drugs = "fertility drugs";
+					slave.hormones = 0;
+					r += `<br>${slave.slaveName} is fertile, so she has been put on the appropriate fertility regime.`;
+				}
+			} else if ((rule.preg == 2)) {
+				if (slave.preg !== 0 || slave.drugs !== "fertility drugs" || slave.hormones !== 2) {
+					slave.preg = 0;
+					slave.drugs = "fertility drugs";
+					slave.hormones = 2;
+					r += `<br>${slave.slaveName} is fertile, so she has been put on the appropriate fertility regime.`;
+				}
+			} else if ((rule.preg == 3) && slave.indentureRestrictions < 1) {
+				if (slave.preg !== 0 || slave.drugs !== "super fertility drugs" || slave.hormones !== 0) {
+					slave.preg = 0;
+					slave.drugs = "super fertility drugs";
+					slave.hormones = 0;
+					r += `<br>${slave.slaveName} is fertile, so she has been put on the appropriate fertility regime.`;
+				}
+			} else if ((rule.preg == 4) && slave.indentureRestrictions < 1) {
+				if (slave.preg !== 0 || slave.drugs !== "super fertility drugs" || slave.hormones !== 2) {
+					slave.preg = 0;
+					slave.drugs = "super fertility drugs";
+					slave.hormones = 2;
+					r += `<br>${slave.slaveName} is fertile, so she has been put on the appropriate fertility regime.`;
+				}
+			}
+		}
+	}
+
+	function ProcessAssetGrowthDrugs(slave, rule) {
+		// Asset Growth 
+		const growth_drugs = new Set(["breast injections", "intensive breast injections", "breast redistributors", "butt injections", "intensive butt injections", "butt redistributors", "lip injections", "lip atrophiers", "penis enhancement", "intensive penis enhancement", "penis atrophiers", "testicle enhancement", "intensive testicle enhancement", "testicle atrophiers", "hyper breast injections", "hyper butt injections", "hyper penis enhancement", "hyper testicle enhancement"]);
+		if ((slave.drugs == "super fertility drugs" || slave.drugs == "fertility drugs") && isFertile(slave)) {
+			r += `<br>slave.slaveName is on slave.drugs and will not be considered for drug enhancement until that regime is complete.`;
+			return;
+		} else if ((rule.growth_boobs == "no default setting" && rule.growth_butt == "no default setting" && rule.growth_lips == "no default setting" && rule.growth_dick == "no default setting" && rule.growth_dick == "no default setting" && rule.growth_balls == "no default setting")) {
+			return;
+		}
+		if (slave.assignmentVisible) { // More resource intensive version with prioritizing. Possible to give this a toggle rather than basing it on visibility. 
+			let _priorities = [];
+			if (rule.growth_boobs != "no default setting") {
+				let _priority;
+				if (slave.boobs < rule.growth_boobs) {
+					_priority = {drug: "breast injections", weight: (rule.growth_boobs-slave.boobs)/rule.growth_boobs};
+					_priorities.push(_priority);
+				} else if ((slave.boobs > rule.growth_boobs+200) && slave.weight < 100 && (V.arcologies[0].FSSlimnessEnthusiastResearch == 1)) {
+					_priority = {
+						drug: "breast redistributors",
+						weight: (1+((slave.boobs-slave.boobsImplant-rule.growth_boobs)/rule.growth_boobs)) };
+					_priorities.push(_priority);
+				}
+			}
+			if (rule.growth_butt != "no default setting") {
+				let _priority;
+				if (slave.butt < rule.growth_butt) {
+					_priority = {drug: "butt injections", weight: (rule.growth_butt-slave.butt)/rule.growth_butt};
+					_priorities.push(_priority);
+				} else if ((Math.trunc(slave.butt) > rule.growth_butt) && slave.weight < 100 && (V.arcologies[0].FSSlimnessEnthusiastResearch == 1)) {
+					_priority = {
+						drug: "butt redistributors",
+						weight: (1+((slave.butt-slave.buttImplant-rule.growth_butt)/rule.growth_butt)) };
+					_priorities.push(_priority);
+				}
+			}
+			if (rule.growth_lips != "no default setting") {
+				let _priority;
+				if (slave.lips < rule.growth_lips) {
+					_priority = {drug: "lip injections", weight: (rule.growth_lips-slave.lips)/rule.growth_lips};
+					_priorities.push(_priority);
+				} else if ((slave.lips > rule.growth_lips) && (V.arcologies[0].FSSlimnessEnthusiastResearch == 1)) {
+					_priority = {
+						drug: "lip atrophiers",
+						weight: (1+((slave.lips-slave.lipsImplant-rule.growth_lips)/rule.growth_lips))};
+					_priorities.push(_priority);
+				}
+			}
+			if (rule.growth_dick != "no default setting" && slave.dick) {
+				let _priority;
+				if (slave.dick < rule.growth_dick) {
+					_priority = {drug: "penis enhancement", weight: (rule.growth_dick-slave.dick)/rule.growth_dick};
+					_priorities.push(_priority);
+				} else if ((slave.dick > rule.growth_dick) && (V.arcologies[0].FSSlimnessEnthusiastResearch == 1)) {
+					_priority = {
+						drug: "penis atrophiers",
+						weight: (1+((slave.dick-rule.growth_dick)/rule.growth_dick))};
+					_priorities.push(_priority);
+				}
+			}
+			if (rule.growth_balls != "no default setting" && slave.balls) {
+				let _priority;
+				if (slave.balls < rule.growth_balls) {
+					_priority = {drug: "testicle enhancement", weight: (rule.growth_balls-slave.balls)/rule.growth_balls};
+					_priorities.push(_priority);
+				} else if ((slave.balls > rule.growth_balls) && (V.arcologies[0].FSSlimnessEnthusiastResearch == 1)) {
+					_priority = {
+						drug: "testicle atrophiers",
+						weight: (1+((slave.balls-rule.growth_balls)/rule.growth_balls))};
+					_priorities.push(_priority);
+				}
+			}
+			if (_priorities.length > 1) {
+				_priorities = _priorities.sort(function(a, b){if(a.weight > b.weight) return -1; if(a.weight < b.weight) return 1; return 0;});
+				if (slave.drugs != _priorities[0].drug) {
+					slave.drugs = _priorities[0].drug;
+					r += `<br>${slave.slaveName} has been put on `;
+					if (rule.growth_intensity && slave.drugs != "lip injections" && slave.health > 0) {
+						slave.drugs = "intensive " + slave.drugs;
+						r += `${slave.drugs}, since she's healthy enough to take them, and `;
+					} else {
+						r += `${slave.drugs}, since`;
+					}
+					r += `that part of her body is ${Math.trunc(_priorities[0].weight*100)}>>% `;
+					if (_priorities[0].weight < 1) r+= "below ";
+					else r+= "above ";
+					r += "the targeted size.";
+				}
+				return;
+			} else if (_priorities.length > 0) {
+				if (slave.drugs != _priorities[0].drug) {
+					slave.drugs = _priorities[0].drug;
+					r += `<br>${slave.slaveName} has been put on `;
+					if (rule.growth_intensity && slave.drugs != "lip injections" && slave.health > 0) {
+						slave.drugs = "intensive " + slave.drugs;
+						r += `${slave.drugs}, since she's healthy enough to take them, and `;
+					} else
+						r += `${slave.drugs}, since `;
+					r += `that is the only part of her body that does not meet the targeted size.`;
+				}
+				return;
+			} else if (growth_drugs.has(slave.drugs)) {
+				slave.drugs = "no drugs";
+				r += `<br>${slave.slaveName}'s body has met all relevant growth targets, so her pharmaceutical regime has been ended.`;
+				return;
+			}
+		} else {
+			let _hyper;
+			if (V.arcologies[0].FSAssetExpansionistResearch == 1)
+				_hyper = "hyper ";
+			else
+				_hyper = "";
+			if (rule.growth_boobs != "no default setting") {
+				if (slave.boobs < rule.growth_boobs) {
+					if (slave.drugs != _hyper + "breast injections") {
+						slave.drugs = _hyper + "breast injections";
+						r += `<br>${slave.slaveName} has been put on ${slave.drugs}.`;
+					}
+					return;
+				}
+			}
+			if (rule.growth_butt != "no default setting") {
+				if (slave.butt < rule.growth_butt) {
+					if (slave.drugs != _hyper + "butt injections") {
+						slave.drugs = _hyper + "butt injections";
+						r += `<br>${slave.slaveName} has been put on ${slave.drugs}.`;
+					}
+					return;
+				}
+			}
+			if (rule.growth_lips != "no default setting") {
+				if (slave.lips < rule.growth_lips) {
+					if (slave.drugs != "lip injections") {
+						slave.drugs = "lip injections";
+						r += `<br>${slave.slaveName} has been put on ${slave.drugs}.`;
+					}
+					return;
+				}
+			}
+			if (rule.growth_dick != "no default setting" && slave.dick) {
+				if (slave.dick < rule.growth_dick) {
+					if (slave.drugs != _hyper + "penis enhancement") {
+						slave.drugs = _hyper + "penis enhancement";
+						r += `<br>${slave.slaveName} has been put on ${slave.drugs}.`;
+					}
+					return;
+				}
+			}
+			if (rule.growth_balls != "no default setting" && slave.balls) {
+				if (slave.balls < rule.growth_balls) {
+					if (slave.drugs != _hyper + "testicle enhancement") {
+						slave.drugs = _hyper + "testicle enhancement";
+						r += `<br>${slave.slaveName} has been put on ${slave.drugs}.`;
+					}
+					return;
+				}
+			}
+			if (V.arcologies[0].FSSlimnessEnthusiastResearch == 1) {
+				if (rule.growth_boobs != "no default setting") {
+					if (slave.boobs-slave.boobsImplant > rule.growth_boobs+200 && slave.weight < 100) {
+						if (slave.drugs != "breast redistributors") {
+							slave.drugs = "breast redistributors";
+							r += `<br>${slave.slaveName} has been put on ${slave.drugs}.`;
+						}
+						return;
+					}
+				}
+				if (rule.growth_butt != "no default setting") {
+					if (Math.trunc(slave.butt-slave.buttImplant) > rule.growth_butt && slave.weight < 100) {
+						if (slave.drugs != "butt redistributors") {
+							slave.drugs = "butt redistributors";
+							r += `<br>${slave.slaveName} has been put on ${slave.drugs}.`;
+						}
+						return;
+					}
+				}
+				if (rule.growth_lips != "no default setting") {
+					if (slave.lips-slave.lipsImplant > rule.growth_lips) {
+						if (slave.drugs != "lip atrophiers") {
+							slave.drugs = "lip atrophiers";
+							r += `<br>${slave.slaveName} has been put on ${slave.drugs}.`;
+						}
+						return;
+					}
+				}
+				if (rule.growth_dick != "no default setting" && slave.dick) {
+					if (slave.dick > rule.growth_dick) {
+						if (slave.drugs != "penis atrophiers") {
+							slave.drugs = "penis atrophiers";
+							r += `<br>${slave.slaveName} has been put on ${slave.drugs}.`;
+						}
+						return;
+					}
+				}
+				if (rule.growth_balls != "no default setting" && slave.balls) {
+					if (slave.balls > rule.growth_balls) {
+						if (slave.drugs != "testicle atrophiers") {
+							slave.drugs = "testicle atrophiers";
+							r += `<br>${slave.slaveName} has been put on ${slave.drugs}.`;
+						}
+						return;
+					}
+				}
+			}
+			if (growth_drugs.has(slave.drugs)) {
+				slave.drugs = "no drugs";
+				r += `<br>${slave.slaveName} has met all relevant growth targets, so her pharmaceutical regime has been ended.`;
+				return;
+			}
+		}
+	}
+
+	function ProcessOtherDrugs(slave, rule) {
+		// Other Drugs 
+		const drugs = new Set(["psychosuppressants", "no drugs", "steroids", "hormone enhancers", "hormone blockers", "anti-aging cream", "growth stimulants", "sag-B-gone", "male hormone injections", "female hormone injections", "none"]);
+		if (drugs.has(rule.drug)) {
+			if (drugs.has(slave.drugs) && (slave.drugs != rule.drug)) {
+				switch (rule.drug) {
+				case "anti-aging cream":
+					if (slave.visualAge > 18) {
+						slave.drugs = rule.drug ;
+						r += `<br>${slave.slaveName} has been put on ${slave.drugs}.`;
+					} else {
+						slave.drugs = "no drugs" ;
+						r += `<br>${slave.slaveName} cannot benefit from her assigned drug and has been defaulted to ${slave.drugs}.`;
+					}
+					break;
+
+				case "growth stimulants":
+					if (slave.height < 274 && slave.height < Math.clamp((Height.mean(slave) * 1.25),0,274)) {
+						slave.drugs = rule.drug;
+						r += `<br>${slave.slaveName} has been put on ${slave.drugs}.`;
+					} else {
+						slave.drugs = "no drugs" ;
+						r += `<br>${slave.slaveName} cannot benefit from her assigned drug and has been defaulted to ${slave.drugs}.`;
+					}
+					break;
+
+				case "sag-B-gone":
+					if (slave.boobs > 250 && slave.boobShape != "saggy") {
+						slave.drugs = rule.drug;
+						r += `<br>${slave.slaveName} has been put on ${slave.drugs}.`;
+					} else {
+						slave.drugs = "no drugs";
+						r += `<br>${slave.slaveName} cannot benefit from her assigned drug and has been defaulted to ${slave.drugs}.`;
+					}
+					break;
+
+				case "female hormone injections":
+					if (slave.breedingMark != 1 && (slave.ovaries == 1 || slave.mpreg == 1) && slave.pubertyXX === 0) {
+						slave.drugs = rule.drug ;
+						r += `<br>${slave.slaveName} has been put on ${slave.drugs}.`;
+					} else {
+						slave.drugs = "no drugs" ;
+						r += `<br>${slave.slaveName} cannot benefit from her assigned drug and has been defaulted to ${slave.drugs}.`;
+					}
+					break;
+
+				case "male hormone injections":
+					if (slave.breedingMark != 1 && slave.balls > 0 && slave.pubertyXY === 0) {
+						slave.drugs = rule.drug ;
+						r += `<br>${slave.slaveName} has been put on ${slave.drugs}.`;
+					} else {
+						slave.drugs = "no drugs" ;
+						r += `<br>${slave.slaveName} cannot benefit from her assigned drug and has been defaulted to ${slave.drugs}.`;
+					}
+					break;
+
+				default:
+					slave.drugs = rule.drug ;
+					r += `<br>${slave.slaveName} has been put on ${slave.drugs}.`;
+					break;
+				}
+			}
+		}
+	}
+
+	function ProcessDiet(slave, rule) {
+		// Diet Setting 
+		if (rule.diet !== undefined && rule.diet !== "no default setting") {
+			/*
+			if ((slave.boobs >= 1600) && (slave.muscles <= 5) && (slave.amp != 1) && ((rule.muscles == "no default setting") || (rule.muscles === 0))) {
+				if ((slave.diet !== "muscle building")) {
+					slave.diet = "muscle building"
+					r += `<br>${slave.slaveName} has big tits and no back muscles, so she's been assigned to gain some.`
+				}
+			} else if ((slave.boobs >= 1600) && (slave.muscles > 5) && (slave.diet == "muscle building") && ((rule.muscles == "no default setting") || (rule.muscles === 0))) {
+			*/
+			if (rule.diet === "healthy" && slave.diet !== "healthy") {
+				r += `<br>${slave.slaveName} has been assigned to a healthy diet.`;
+			} else if ((slave.boobs >= 1600) && (slave.muscles > 5) && (slave.diet == "muscle building") && ((rule.muscles == "no default setting") || (rule.muscles === 0))) {
+				slave.diet = "healthy";
+				r += `<br>${slave.slaveName} has huge boobs, but she already has the back muscles to bear them, so she's been assigned to stop working out so hard.`;
+			} else if ((rule.dietGrowthSupport == 1) && ((slave.drugs == "breast injections") || (slave.drugs == "butt injections")) && (slave.weight <= 95)) {
+				if (slave.diet !== "fattening") {
+					slave.diet = "fattening";
+					r += `<br>${slave.slaveName} is on drugs designed to expand major body parts, so she's been put on a fattening diet to provide her body as much fuel for growth as possible.`;
+				}
+			} else {
+				if (!(isNaN(rule.diet))) {
+					if ((slave.weight > rule.diet)) {
+						if ((slave.diet !== "restricted")) {
+							slave.diet = "restricted";
+							r += `<br>${slave.slaveName} is too fat so her diet has been set to restricted.`;
+						}
+						if ((V.arcologies[0].FSSlimnessEnthusiastResearch == 1 && (slave.drugs == "no drugs" || slave.drugs == "none"))) {
+							slave.drugs = "appetite suppressors";
+							r += `<br>${slave.slaveName} is too fat so she will be given weight loss pills.`;
+						}
+					} else if ((slave.weight < rule.diet)) {
+						if ((slave.diet !== "fattening")) {
+							slave.diet = "fattening";
+							r += `<br>${slave.slaveName} is too skinny so her diet has been set to fattening.`;
+						}
+						if ((slave.drugs == "appetite suppressors")) {
+							slave.drugs = "no drugs";
+							r += `<br>${slave.slaveName} is too skinny so she will no longer be given weight loss pills.`;
+						}
+					} else if ((rule.muscles !== undefined) && (rule.muscles !== "no default setting") && (slave.amp != 1)) {
+						if ((slave.muscles >= rule.muscles+8)) {
+							if ((slave.diet !== "slimming")) {
+								slave.diet = "slimming";
+								r += `<br>${slave.slaveName} has been put on a slimming exercise regime.`;
+							}
+						} else if ((slave.muscles <= rule.muscles-2)) {
+							if ((slave.diet !== "muscle building")) {
+								slave.diet = "muscle building";
+								r += `<br>${slave.slaveName} has been put on a muscle building exercise regime.`;
+							}
+						} else {
+							if ((slave.diet !== "healthy")) {
+								slave.diet = "healthy";
+								r += `<br>${slave.slaveName} is at the target weight, so her diet has been normalized.`;
+							}
+						}
+					} else {
+						if ((slave.diet !== "healthy")) {
+							slave.diet = "healthy";
+							r += `<br>${slave.slaveName} is at the target weight, so her diet has been normalized.`;
+						}
+						if ((slave.drugs == "appetite suppressors")) {
+							slave.drugs = "no drugs";
+							r += `<br>${slave.slaveName} is at the target weight, so she will no longer be given weight loss pills.`;
+						}
+					}
+				} else if ((rule.diet == "attractive")) {
+					if (((slave.weight > 95) || ((slave.weight > 30) && (slave.hips < 2)))) {
+						if ((slave.diet !== "restricted")) {
+							slave.diet = "restricted";
+							r += `<br>${slave.slaveName} is too fat so her diet has been set to restricted.`;
+						}
+						if ((V.arcologies[0].FSSlimnessEnthusiastResearch == 1 && (slave.drugs == "no drugs" || slave.drugs == "none"))) {
+							slave.drugs = "appetite suppressors";
+							r += `<br>${slave.slaveName} is too fat so she will be given weight loss pills.`;
+						}
+					} else if (((slave.weight < -95) || ((slave.weight < -30) && (slave.hips > -2)))) {
+						if ((slave.diet !== "fattening")) {
+							slave.diet = "fattening";
+							r += `<br>${slave.slaveName} is too skinny so her diet has been set to fattening.`;
+						}
+						if ((slave.drugs == "appetite suppressors")) {
+							slave.drugs = "no drugs";
+							r += `<br>${slave.slaveName} is too skinny so she will no longer be given weight loss pills.`;
+						}
+					} else if ((rule.muscles !== undefined) && (rule.muscles !== "no default setting") && (slave.amp != 1)) {
+						if ((slave.muscles >= rule.muscles+8)) {
+							if ((slave.diet !== "slimming")) {
+								slave.diet = "slimming";
+								r += `<br>${slave.slaveName} has been put on a slimming exercise regime.`;
+							}
+						} else if ((slave.muscles <= rule.muscles-2)) {
+							if ((slave.diet !== "muscle building")) {
+								slave.diet = "muscle building";
+								r += `<br>${slave.slaveName} has been put on a muscle building exercise regime.`;
+							}
+						} else {
+							if ((slave.diet !== "healthy")) {
+								slave.diet = "healthy";
+								r += `<br>${slave.slaveName} is at the target weight, so her diet has been normalized.`;
+							}
+							if ((slave.drugs == "appetite suppressors")) {
+								slave.drugs = "no drugs";
+								r += `<br>${slave.slaveName} is at the target weight, so she will no longer be given weight loss pills.`;
+							}
+						}
+					} else {
+						if ((slave.diet !== "healthy")) {
+							slave.diet = "healthy";
+							r += `<br>${slave.slaveName} is at the target weight, so her diet has been normalized.`;
+						}
+						if ((slave.drugs == "appetite suppressors")) {
+							slave.drugs = "no drugs";
+							r += `<br>${slave.slaveName} is at the target weight, so she will no longer be given weight loss pills.`;
+						}
+					}
+				} else if ((rule.diet == "XX")) {
+					if ((slave.diet !== "XX")) {
+						slave.diet = "XX";
+						r += `<br>${slave.slaveName} has been put on a diet that favors feminine development.`;
+					}
+				} else if ((rule.diet == "XY")) {
+					if ((slave.diet !== "XY")) {
+						slave.diet = "XY";
+						r += `<br>${slave.slaveName} has been put on a diet that favors masculine development.`;
+					}
+				} else if ((rule.diet == "XXY")) {
+					if (slave.balls > 0 && (slave.ovaries == 1 || slave.mpreg == 1)) {
+						if ((slave.diet !== "XXY")) {
+							slave.diet = "XXY";
+							r += `<br>${slave.slaveName} has been put on a diet that enhances a herm's unique sexuality.`;
+						}
+					} else {
+						if ((slave.diet !== "healthy")) {
+							slave.diet = "healthy";
+							r += `<br>${slave.slaveName} has been put on a standard diet since she is not a hermaphrodite.`;
+						}
+					}
+				} else if ((rule.diet == "cleansing")) {
+					if (((slave.diet !== "cleansing") && (slave.health < 100))) {
+						slave.diet = "cleansing";
+						r += `<br>${slave.slaveName} has been put on a diet of cleansers.`;
+					}
+				} else if ((rule.diet == "fertility")) {
+					if (canGetPregnant(slave)) {
+						if ((slave.diet !== "fertility")) {
+							slave.diet = "fertility";
+							r += `<br>${slave.slaveName} has been put on a diet to enhance fertility.`;
+						}
+					} else {
+						if ((slave.diet !== "healthy")) {
+							slave.diet = "healthy";
+							if (slave.pregKnown === 0 && slave.preg > 0) {
+								r += `<br>${slave.slaveName} has been put on a standard diet since tests reveal she has become pregnant.`;
+								slave.pregKnown = 1;
+							} else {
+								r += `<br>${slave.slaveName} has been put on a standard diet since she is currently unable to become pregnant.`;
+							}
+						}
+					}
+				} else if ((rule.diet == "cum production")) {
+					if ((slave.balls > 0)) {
+						if ((slave.diet !== "cum production")) {
+							slave.diet = "cum production";
+							r += `<br>${slave.slaveName} has been put on a diet to promote cum production.`;
+						}
+					} else {
+						if ((slave.diet !== "healthy")) {
+							slave.diet = "healthy";
+							r += `<br>${slave.slaveName} has been put on a standard diet since she is no longer able to produce cum.`;
+						}
+					}
+				}
+			}
+		} else if ((rule.muscles !== undefined) && (rule.muscles !== "no default setting") && (slave.amp != 1)) { // no diet rule, muscles only 
+			if ((slave.muscles >= rule.muscles+8)) {
+				if ((slave.diet !== "slimming")) {
+					slave.diet = "slimming";
+					r += `<br>${slave.slaveName} has been put on a slimming exercise regime.`;
+				}
+			} else if ((slave.muscles <= rule.muscles-2)) {
+				if ((slave.diet !== "muscle building")) {
+					slave.diet = "muscle building";
+					r += `<br>${slave.slaveName} has been put on a muscle building exercise regime.`;
+				}
+			} else {
+				if ((slave.diet !== "healthy")) {
+					slave.diet = "healthy";
+					r += `<br>${slave.slaveName} has achieved the target musculature, so her exercise regime has been normalized.`;
+				}
+			}
+		}
+	}
+
+	function ProcessCuratives(slave, rule) {
+		if ((rule.curatives !== undefined) && (rule.curatives !== "no default setting")) {
+			if (slave.curatives !== rule.curatives) {
+				if (rule.curatives === 2) {
+					if (slave.health > 100) {
+						if ((slave.curatives != 1)) {
+							r += `<br>${slave.slaveName} has been put on preventatives, since curatives cannot improve her health further.`;
+							slave.curatives = 1;
+						}
+					} else {
+						r += `<br>${slave.slaveName} has been put on curatives.`;
+						slave.curatives = rule.curatives;
+					}
+				} else {
+					r += `<br>${slave.slaveName} has been ${rule.curatives > 0 ? `put on preventatives` : `taken off health drugs`}`;
+					slave.curatives = rule.curatives;
+				}
+			}
+		}
+	}
+
+	function ProcessAphrodisiacs(slave, rule) {
+		if ((rule.aphrodisiacs !== undefined) && (rule.aphrodisiacs != "no default setting")) {
+			if (slave.aphrodisiacs != rule.aphrodisiacs) {
+				r += `<br>${slave.slaveName} has been ${rule.aphrodisiacs > 0 ? `put on the proper` : `taken off`} aphrodisiacs.`;
+				slave.aphrodisiacs = rule.aphrodisiacs;
+			}
+		}
+	}
+
+	function ProcessPenisHormones(slave, rule) {
+		if ((slave.dick > 0)) {
+			if ((slave.balls === 0)) {
+				if ((rule.gelding !== undefined) && (rule.gelding !== "no default setting")) {
+					if ((slave.hormones !== rule.gelding)) {
+						const _oldHormones = slave.hormones;
+						slave.hormones = rule.gelding;
+						if (slave.indentureRestrictions >= 2) {
+							slave.hormones = Math.clamp(slave.hormones, -1, 1);
+						}
+						if (slave.hormones != _oldHormones) {
+							r += `<br>${slave.slaveName} is a gelding, so she has been put on the appropriate hormonal regime.`;
+						}
+					}
+				}
+			} else if ((slave.balls > 0)) {
+				if ((rule.XY !== undefined) && (rule.XY !== "no default setting")) {
+					if ((slave.hormones !== rule.XY)) {
+						if ((slave.assignment != "recruit girls")) {
+							if ((slave.assignment != "be the Wardeness")) {
+								if ((slave.assignment != "be the Madam")) {
+									const _oldHormones = slave.hormones;
+									slave.hormones = rule.XY;
+									if (slave.indentureRestrictions >= 2) {
+										slave.hormones = Math.clamp(slave.hormones, -1, 1);
+									}
+									if (slave.hormones != _oldHormones) {
+										r += `<br>${slave.slaveName} is a shemale, so she has been put on the appropriate hormonal regime.`;
+									}
+								}
+							}
+						}
+					}
+				}
+			}
+		}
+	}
+
+	function ProcessFemaleHormones(slave, rule) {
+		if ((slave.vagina > -1) && (slave.dick === 0) && (rule.XX !== undefined) && (rule.XX !== "no default setting")) {
+			if ((slave.hormones !== rule.XX)) {
+				const _oldHormones = slave.hormones;
+				slave.hormones = rule.XX;
+				if (slave.indentureRestrictions >= 2) {
+					slave.hormones = Math.clamp(slave.hormones, -1, 1);
+				}
+				if (slave.hormones != _oldHormones) {
+					r += `<br>${slave.slaveName} is a female, so she has been put on the appropriate hormonal regime.`;
+				}
+			}
+		}
+	}
+
+	function ProcessPregnancyDrugs(slave, rule) {
+		if (slave.pregKnown == 1 && rule.pregSpeed != "no default setting" && slave.breedingMark != 1 && slave.indentureRestrictions < 1 && slave.broodmother === 0) {
+			if (rule.pregSpeed == "slow" && slave.preg < 35) {
+				slave.pregControl = "slow gestation";
+				r += `<br>slave.slaveName is pregnant, so she has been put on the gestation slowing agents.`;
+			} else if (rule.pregSpeed == "fast" && slave.preg < 35 && slave.health > -50) {
+				slave.pregControl = "speed up";
+				r += `<br>slave.slaveName is pregnant, so she has been put on rapid gestation  agents. CAUTION! Can be dangerous. Clinic supervision is recommended.`;
+			} else if (rule.pregSpeed == "suppress" && slave.preg > 34 && slave.health > -50) {
+				slave.pregControl = "labor supressors";
+				r += `<br>slave.slaveName is ready to birth, so she has been put on labor suppressing agents.`;
+			} else if (rule.pregSpeed == "stimulate" && slave.preg >= 37 && slave.health > -50) {
+				slave.labor = 1;
+				slave.induce = 1;
+				V.birthee = 1;
+				r += `<br>slave.slaveName is ready to birth, so her labor has been stimulated.`;
+			} else if (rule.pregSpeed == "fast" && slave.pregControl == "speed up" && slave.health <= -50) {
+				slave.pregControl = "none";
+				r += `<br>slave.slaveName is on rapid gestation agents and dangerously unhealthy, so her agent regimen has been stopped.`;
+			} else if (rule.pregSpeed == "suppress" && slave.pregControl == "labor supressors" && slave.health <= -50) {
+				slave.pregControl = "none";
+				r += `<br>slave.slaveName is on labor suppression agents and unhealthy, so her agent regimen has been stopped.`;
+			}
+		}
+	}
+
+	function ProcessLivingStandard(slave, rule) {
+		if ((rule.livingRules !== undefined) && (rule.livingRules !== "no default setting")) {
+			if (setup.facilityCareers.includes(slave.assignment)) {
+				r += `` // `<br>${slave.slaveName}'s living standards are controlled by her assignment.`;
+			} else if (((slave.assignment == "be your Head Girl") && (V.HGSuite == 1)) || ((slave.assignment == "guard you") && (V.dojo > 1))) {
+				r += `<br>${slave.slaveName} has a private room.`;
+			} else if ((slave.fetish == "mindbroken")) {
+				if ((slave.livingRules !== "spare")) {
+					slave.livingRules = "spare";
+					r += `<br>Since ${slave.slaveName} is mindbroken her living standard has been set to spare.`;
+				}
+			} else if (slave.livingRules !== rule.livingRules) {
+				if (rule.livingRules !== "luxurious") {
+					if (V.roomsPopulation <= V.rooms-0.5) {
+						slave.livingRules = rule.livingRules;
+						r += `<br>${slave.slaveName}'s living standard has been set to ${rule.livingRules}.`;
+						if (slave.relationship >= 4)
+							V.roomsPopulation += 0.5;
+						else
+							V.roomsPopulation += 1;
+					} else {
+						slave.livingRules = "normal";
+						r += `<br>${slave.slaveName}'s living standard has been set to normal, since there is no room for her to occupy.`;
+					}
+				} else {
+					slave.livingRules = rule.livingRules;
+					r += `<br>${slave.slaveName}'s living standard has been set to ${rule.livingRules}.`;
+				}
+			}
+		}
+	}
+
+	function ProcessSpeech(slave, rule) {
+		if ((rule.speechRules !== undefined) && (rule.speechRules !== "no default setting")) {
+			if ((slave.fetish == "mindbroken")) {
+				if ((slave.speechRules !== "restrictive")) {
+					slave.speechRules = "restrictive";
+					r += `<br>Since ${slave.slaveName} is mindbroken her speech rules have been set to restrictive.`;
+				}
+			} else if ((slave.speechRules !== rule.speechRules)) {
+				slave.speechRules = rule.speechRules;
+				r += `<br>${slave.slaveName}'s speech rules have been set to ${rule.speechRules}.`;
+			}
+		}
+	}
+
+	function ProcessRelationship(slave, rule) {
+		if ((slave.fetish !== "mindbroken")) {
+			if ((rule.relationshipRules !== undefined) && (rule.relationshipRules !== "no default setting")) {
+				if ((slave.relationshipRules !== rule.relationshipRules )) {
+					slave.relationshipRules = rule.relationshipRules ;
+					r += `<br>${slave.slaveName}'s relationship rules have been set to ${rule.relationshipRules}.`;
+				}
+			}
+		}
+	}
+
+	function ProcessRelease(slave, rule) {
+		if ((rule.releaseRules !== undefined) && (rule.releaseRules !== "no default setting")) {
+			let _release = 0;
+			if (rule.releaseRules === "restrictive" &&
+				!(["serve the public", "serve in the club", "whore", "work in the brothel", "please you", "serve in the master suite", "be a subordinate slave", "work a glory hole", "be confined in the arcade", "get milked", "work in the dairy", "be your Head Girl"].contains(slave.assignment)))
+				_release = 1;
+			else
+				_release = 1;
+			if ((slave.fetish == "mindbroken") && (slave.releaseRules !== "permissive")) {
+				slave.releaseRules = "permissive";
+				r += `<br>Since ${slave.slaveName} is mindbroken her masturbation rules have been set to permissive.`;
+			} else if ((slave.amp === 1 || slave.fuckdoll > 0) && (slave.releaseRules === "masturbation")) {
+				slave.releaseRules = "restrictive";
+				r += `<br>Since ${slave.slaveName} is unable to masturbate, her masturbation rules have been set to restrictive.`;
+			} else if ((_release !== 0) && (slave.releaseRules !== rule.releaseRules)) {
+				slave.releaseRules = rule.releaseRules;
+				r += `<br>${slave.slaveName}'s masturbation rules have been set to ${rule.releaseRules}.`;
+			}
+		}
+	}
+
+	function ProcessPunishment(slave, rule) {
+		if ((rule.standardPunishment !== undefined) && (rule.standardPunishment !== "no default setting")) {
+			if ((slave.standardPunishment !== rule.standardPunishment)) {
+				slave.standardPunishment = rule.standardPunishment ;
+				r += `<br>${slave.slaveName}'s typical punishment has been updated to ${rule.standardPunishment}.`;
+			}
+		}
+	}
+
+	function ProcessReward(slave, rule) {
+		if ((rule.standardReward !== undefined) && (rule.standardReward !== "no default setting")) {
+			if ((slave.standardReward !== rule.standardReward)) {
+				slave.standardReward = rule.standardReward ;
+				r += `<br>${slave.slaveName}'s typical reward has been updated to ${rule.standardReward}.`;
+			}
+		}
+	}
+
+	function ProcessDietCum(slave, rule) {
+		if ((rule.dietCum !== undefined) && (rule.dietCum !== "no default setting")) {
+			if (slave.dietCum != rule.dietCum) {
+				slave.dietCum = rule.dietCum;
+				if (slave.dietCum == 2) {
+					r += `<br>${slave.slaveName} has been put on a diet based on cum.`;
+					slave.dietMilk = 0;
+				}
+				if (slave.dietCum == 1)
+					r += `<br>${slave.slaveName} has had cum added to her diet.`;
+				else
+					r += `<br>${slave.slaveName} has had cum removed from her diet.`;
+			}
+		}
+	}
+
+	function ProcessDietMilk(slave, rule) {
+		if ((rule.dietMilk !== undefined) && (rule.dietMilk !== "no default setting")) {
+			if (slave.dietMilk != rule.dietMilk) {
+				slave.dietMilk = rule.dietMilk;
+				if (slave.dietMilk == 2) {
+					r += `<br>${slave.slaveName} has been put on a diet based on human milk.`;
+					slave.dietCum = 0;
+				}
+				if (slave.dietMilk == 1)
+					r += `<br>${slave.slaveName} has had human milk added to her diet.`;
+				else
+					r += `<br>${slave.slaveName} has had human milk removed from her diet.`;
+			}
+		}
+	}
+
+	function ProcessTeeth(slave, rule) {
+		if ((rule.teeth !== undefined) && (rule.teeth !== "no default setting")) {
+			if ((rule.teeth == "universal")) {
+				if ((slave.teeth == "crooked")) {
+					slave.teeth = "straightening braces";
+					V.cash -= V.surgeryCost;
+					r += `<br>${slave.slaveName} has been given braces for her crooked teeth.`;
+				} else if ((slave.teeth == "normal")) {
+					slave.teeth = "cosmetic braces";
+					V.cash -= V.surgeryCost;
+					r += `<br>${slave.slaveName} has been given cosmetic braces.`;
+				}
+			} else if ((rule.teeth == "straighten")) {
+				if ((slave.teeth == "crooked")) {
+					slave.teeth = "straightening braces";
+					V.cash -= V.surgeryCost;
+					r += `<br>${slave.slaveName} has been given braces for her crooked teeth.`;
+				} else if ((slave.teeth == "cosmetic braces")) {
+					slave.teeth = "normal";
+					r += `<br>${slave.slaveName} has gotten her braces off, since her teeth are straight.`;
+				}
+			} else if ((rule.teeth == "none")) {
+				if ((slave.teeth == "straightening braces")) {
+					slave.teeth = "crooked";
+					r += `<br>${slave.slaveName} has gotten her braces off.`;
+				} else if ((slave.teeth == "cosmetic braces")) {
+					slave.teeth = "normal";
+					r += `<br>${slave.slaveName} has gotten her braces off.`;
+				}
+			}
+		}
+	}
+
+	function ProcessStyle(slave, rule) {
+		if (rule.eyeColor !== undefined && (rule.eyeColor !== "no default setting")) {
+			if ((slave.eyeColor !== rule.eyeColor)) {
+				slave.eyeColor = rule.eyeColor;
+				V.cash -= V.modCost;
+				r += `<br>${slave.slaveName} has been given ${slave.eyeColor} contact lenses.`;
+			}
+		}
+
+		if (rule.makeup !== undefined && (rule.makeup !== "no default setting")) {
+			if ((slave.makeup !== rule.makeup)) {
+				slave.makeup = rule.makeup;
+				V.cash -= V.modCost;
+				r += `<br>${slave.slaveName} has been assigned the standard makeup.`;
+			}
+		}
+
+		if ((slave.amp != 1)) {
+			if (rule.nails !== undefined && (rule.nails !== "no default setting")) {
+				if ((slave.nails !== rule.nails)) {
+					slave.nails = rule.nails;
+					V.cash -= V.modCost;
+					r += `<br>${slave.slaveName} has been assigned the standard nails.`;
+				}
+			}
+		}
+
+		if (rule.hColor !== undefined && (rule.hColor !== "no default setting")) {
+			if (slave.bald != 1) {
+				if ((slave.hColor !== rule.hColor)) {
+					slave.hColor = rule.hColor;
+					V.cash -= V.modCost;
+					r += `<br>${slave.slaveName}'s hair has been dyed ${rule.hColor}.`;
+				}
+			}
+		}
+
+		if (rule.hStyle !== undefined && (rule.hStyle !== "no default setting")) {
+			if (slave.bald != 1) {
+				if ((slave.hStyle !== rule.hStyle)) {
+					slave.hStyle = rule.hStyle;
+					V.cash -= V.modCost;
+					if ((rule.hStyle == "shaved")) {
+						slave.hLength = 0;
+						r += `<br>${slave.slaveName}'s hair has been shaved.`;
+					} else
+						r += `<br>${slave.slaveName}'s hair has been restyled.`;
+				}
+			}
+		}
+
+		if (rule.hLength !== undefined && (rule.hLength !== "no default setting")) {
+			if (slave.bald != 1) {
+				if ((slave.hLength !== rule.hLength)) {
+					if ((slave.hLength > rule.hLength)) {
+						V.cash -= V.modCost;
+						r += `<br>${slave.slaveName}'s hair has been cut; it `;
+					} else {
+						V.cash -= V.modCost*Math.trunc((rule.hLength-slave.hLength)/10);
+						r += `<br>${slave.slaveName} has been given extensions; her hair `;
+					}
+				r += `is now rule.hLength cm long.`;
+				slave.hLength = rule.hLength;
+				}
+			}
+		}
+
+		if (rule.pubicHColor !== undefined && (rule.pubicHColor !== "no default setting")) {
+			if (slave.pubicHStyle != "bald" && slave.pubicHStyle != "hairless") {
+				if ((slave.pubicHColor !== rule.pubicHColor)) {
+					slave.pubicHColor = rule.pubicHColor;
+					V.cash -= V.modCost;
+					r += `<br>${slave.slaveName}'s pubic hair, if present, has been dyed ${rule.pubicHColor}.`;
+				}
+			}
+		}
+
+		if (rule.pubicHStyle !== undefined && (rule.pubicHStyle !== "no default setting")) {
+			if (slave.pubicHStyle != "bald" && slave.pubicHStyle != "hairless") {
+				if ((slave.pubicHStyle !== rule.pubicHStyle)) {
+					slave.pubicHStyle = rule.pubicHStyle;
+					V.cash -= V.modCost;
+					r += `<br>${slave.slaveName}'s pubic hair has been restyled; it is now ${rule.pubicHStyle}.`;
+				}
+			}
+		}
+
+		if (rule.underArmHColor !== undefined && (rule.underArmHColor !== "no default setting")) {
+			if (slave.underArmHStyle != "bald" && slave.underArmHStyle != "hairless") {
+				if ((slave.underArmHColor !== rule.underArmHColor)) {
+					slave.underArmHColor = rule.underArmHColor;
+					V.cash -= V.modCost;
+					r += `<br>${slave.slaveName}'s underarm hair, if present, has been dyed ${rule.underArmHColor}.`;
+				}
+			}
+		}
+
+		if (rule.underArmHStyle !== undefined && (rule.underArmHStyle !== "no default setting")) {
+			if (slave.underArmHStyle != "bald" && slave.underArmHStyle != "hairless") {
+				if ((slave.underArmHStyle !== rule.underArmHStyle)) {
+					slave.underArmHStyle = rule.underArmHStyle;
+					V.cash -= V.modCost;
+					r += `<br>${slave.slaveName}'s underarm hair has been restyled; it is now ${rule.underArmHStyle}.`;
+				}
+			}
+		}
+	}
+
+	function ProcessPiercings(slave, rule) {
+		if (rule.nipplesPiercing !== undefined && (rule.nipplesPiercing !== "no default setting")) {
+			if ((slave.nipplesPiercing !== rule.nipplesPiercing)) {
+				if ((rule.nipplesPiercing === 0)) {
+					slave.nipplesPiercing = 0;
+					r += `<br>${slave.slaveName}'s nipple piercings have been removed.`;
+				} else if (slave.nipples !== "fuckable") {
+					slave.nipplesPiercing = rule.nipplesPiercing;
+					V.cash -= V.modCost;
+					r += `<br>${slave.slaveName}'s nipples have been pierced.`;
+				} else {
+					r += `<br>${slave.slaveName}'s nipples are inverted and cannot be pierced.`;
+				}
+			}
+		}
+
+		if (rule.areolaePiercing !== undefined && (rule.areolaePiercing !== "no default setting")) {
+			if ((slave.areolaePiercing !== rule.areolaePiercing)) {
+				if ((rule.areolaePiercing === 0)) {
+					slave.areolaePiercing = 0;
+					r += `<br>${slave.slaveName}'s areolae piercings have been removed.`;
+				} else {
+					slave.areolaePiercing = rule.areolaePiercing;
+					V.cash -= V.modCost;
+					r += `<br>${slave.slaveName}'s areolae have been given stud piercings.`;
+				}
+			}
+		}
+
+		if (rule.clitPiercing !== undefined && (rule.clitPiercing !== "no default setting")) {
+			if ((slave.clitPiercing !== rule.clitPiercing)) {
+				if ((rule.clitPiercing === 0)) {
+					slave.clitPiercing = 0;
+					if (slave.dick > 0)
+						r += `<br>${slave.slaveName}'s frenulum piercing has been removed.`;
+					else
+						r += `<br>${slave.slaveName}'s clit piercing has been removed.`;
+
+				} else if ((slave.vagina != -1) || (slave.dick !== 0)) {
+					slave.clitPiercing = rule.clitPiercing;
+					if (slave.dick > 0)
+						r += `<br>${slave.slaveName}'s frenulum has been pierced.`;
+					else
+						r += `<br>${slave.slaveName}'s clit has been pierced.`;
+
+					if (rule.clitPiercing == 3)
+						V.cash -= 1000;
+					else
+						V.cash -= V.modCost;
+				}
+			}
+		}
+
+		if ((slave.vagina != -1)) {
+			if (rule.vaginaPiercing !== undefined && (rule.vaginaPiercing !== "no default setting")) {
+				if ((slave.vaginaPiercing !== rule.vaginaPiercing)) {
+					if ((rule.vaginaPiercing === 0)) {
+						slave.vaginaPiercing = 0;
+						r += `<br>${slave.slaveName}'s labia piercings have been removed.`;
+					} else {
+						slave.vaginaPiercing = rule.vaginaPiercing;
+						V.cash -= V.modCost;
+						r += `<br>${slave.slaveName}'s pussylips have been pierced.`;
+					}
+				}
+			}
+		}
+
+		if ((slave.dick > 0)) {
+			if (rule.dickPiercing !== undefined && (rule.dickPiercing !== "no default setting")) {
+				if ((slave.dickPiercing !== rule.dickPiercing)) {
+					if ((rule.dickPiercing === 0)) {
+						slave.dickPiercing = 0;
+						r += `<br>${slave.slaveName}'s shaft piercings have been removed.`;
+					} else {
+						slave.dickPiercing = rule.dickPiercing;
+						V.cash -= V.modCost;
+						r += `<br>${slave.slaveName}'s shaft has been pierced.`;
+					}
+				}
+			}
+		}
+
+		if (rule.anusPiercing !== undefined && (rule.anusPiercing !== "no default setting")) {
+			if ((slave.anusPiercing !== rule.anusPiercing)) {
+				if ((rule.anusPiercing === 0)) {
+					slave.anusPiercing = 0;
+					r += `<br>${slave.slaveName}'s asshole piercings have been removed.`;
+				} else {
+					slave.anusPiercing = rule.anusPiercing;
+					V.cash -= V.modCost;
+					r += `<br>${slave.slaveName}'s asshole has been pierced.`;
+				}
+			}
+		}
+
+		if (rule.lipsPiercing !== undefined && (rule.lipsPiercing !== "no default setting")) {
+			if ((slave.lipsPiercing !== rule.lipsPiercing)) {
+				if ((rule.lipsPiercing === 0)) {
+					slave.lipsPiercing = 0;
+					r += `<br>${slave.slaveName}'s lip piercings have been removed.`;
+				} else {
+					slave.lipsPiercing = rule.lipsPiercing;
+					V.cash -= V.modCost;
+					r += `<br>${slave.slaveName}'s lips have been pierced.`;
+				}
+			}
+		}
+
+		if (rule.tonguePiercing !== undefined && (rule.tonguePiercing !== "no default setting")) {
+			if ((slave.tonguePiercing !== rule.tonguePiercing)) {
+				if ((rule.tonguePiercing === 0)) {
+					slave.tonguePiercing = 0;
+					r += `<br>${slave.slaveName}'s tongue piercings have been removed.`;
+				} else {
+					slave.tonguePiercing = rule.tonguePiercing;
+					V.cash -= V.modCost;
+					r += `<br>${slave.slaveName}'s tongue has been pierced.`;
+				}
+			}
+		}
+
+		if (rule.earPiercing !== undefined && (rule.earPiercing !== "no default setting")) {
+			if ((slave.earPiercing !== rule.earPiercing)) {
+				if ((rule.earPiercing === 0)) {
+					slave.earPiercing = 0;
+					r += `<br>${slave.slaveName}'s ear piercings have been removed.`;
+				} else {
+					slave.earPiercing = rule.earPiercing;
+					V.cash -= V.modCost;
+					r += `<br>${slave.slaveName}'s ears have been pierced.`;
+				}
+			}
+		}
+
+		if (rule.nosePiercing !== undefined && (rule.nosePiercing !== "no default setting")) {
+			if ((slave.nosePiercing !== rule.nosePiercing)) {
+				if ((rule.nosePiercing === 0)) {
+					slave.nosePiercing = 0;
+					r += `<br>${slave.slaveName}'s nose piercing has been removed.`;
+				} else {
+					slave.nosePiercing = rule.nosePiercing;
+					V.cash -= V.modCost;
+					r += `<br>${slave.slaveName}'s nose has been pierced.`;
+				}
+			}
+		}
+
+		if (rule.eyebrowPiercing !== undefined && (rule.eyebrowPiercing !== "no default setting")) {
+			if ((slave.eyebrowPiercing !== rule.eyebrowPiercing)) {
+				if ((rule.eyebrowPiercing === 0)) {
+					slave.eyebrowPiercing = 0;
+					r += `<br>${slave.slaveName}'s eyebrow piercings have been removed.`;
+				} else {
+					slave.eyebrowPiercing = rule.eyebrowPiercing;
+					V.cash -= V.modCost;
+					r += `<br>${slave.slaveName}'s eyebrows have been pierced.`;
+				}
+			}
+		}
+
+		if (rule.navelPiercing !== undefined && (rule.navelPiercing !== "no default setting")) {
+			if ((slave.navelPiercing !== rule.navelPiercing)) {
+				if ((rule.navelPiercing === 0)) {
+					slave.navelPiercing = 0;
+					r += `<br>${slave.slaveName}'s navel piercing have been removed.`;
+				} else {
+					slave.navelPiercing = rule.navelPiercing;
+					V.cash -= V.modCost;
+					r += `<br>${slave.slaveName}'s navel has been pierced.`;
+				}
+			}
+		}
+
+		if (rule.corsetPiercing !== undefined && (rule.corsetPiercing !== "no default setting")) {
+			if ((slave.corsetPiercing !== rule.corsetPiercing)) {
+				if ((rule.corsetPiercing === 0)) {
+					slave.corsetPiercing = 0;
+					r += `<br>${slave.slaveName}'s corset piercings have been removed.`;
+				} else {
+					slave.corsetPiercing = rule.corsetPiercing;
+					V.cash -= V.modCost;
+					r += `<br>${slave.slaveName} has been given a set of corset piercings.`;
+				}
+			}
+		}
+	}
+
+	function ProcessSmartPiercings(slave, rule) {
+		if ((slave.clitPiercing == 3)) {
+			let _used = 0;
+			if (rule.clitSetting !== undefined && (rule.clitSetting !== "no default setting")) {
+				if (slave.clitSetting !== rule.clitSetting) {
+					slave.clitSetting = rule.clitSetting;
+					_used = 1;
+					r += `<br>${slave.slaveName}'s smart piercing has been set to ${slave.clitSetting}.`;
+				} else if (slave.fetishStrength < 100) {
+					_used = 1;
+				}
+			}
+			if (_used === 0) {
+				if (rule.clitSettingEnergy !== undefined && (rule.clitSettingEnergy !== "no default setting")) {
+					if (slave.energy < rule.clitSettingEnergy) {
+						if (slave.clitSetting !== "all") {
+							r += `<br>${slave.slaveName}'s smart piercing has been set to enhance libido.`;
+						}
+						slave.clitSetting = "all";
+						_used = 1;
+					} else if (slave.energy >= rule.clitSettingEnergy + 10) {
+						if (slave.clitSetting !== "none") {
+							r += `<br>${slave.slaveName}'s smart piercing has been set to suppress libido.`;
+						}
+						slave.clitSetting = "none";
+						_used = 1;
+					}
+				}
+			}
+			if (_used === 0) {
+				if (rule.clitSettingXY !== undefined && (rule.clitSettingXY !== "no default setting")) {
+					if (slave.attrXY < rule.clitSettingXY) {
+						if (slave.clitSetting !== "men") {
+							r += `<br>${slave.slaveName}'s smart piercing has been set to encourage attraction to men.`;
+						}
+						slave.clitSetting = "men";
+						_used = 1;
+					} else if (slave.attrXY >= rule.clitSettingXY + 10) {
+						if (slave.clitSetting !== "anti-men") {
+							r += `<br>${slave.slaveName}'s smart piercing has been set to discourage attraction to men.`;
+						}
+						slave.clitSetting = "anti-men";
+						_used = 1;
+					}
+				}
+			}
+			if (_used === 0) {
+				if (rule.clitSettingXX !== undefined && (rule.clitSettingXX !== "no default setting")) {
+					if (slave.attrXX < rule.clitSettingXX) {
+						if (slave.clitSetting !== "women") {
+							r += `<br>${slave.slaveName}'s smart piercing has been set to encourage attraction to women.`;
+						}
+						slave.clitSetting = "women";
+						_used = 1;
+					} else if (slave.attrXX >= rule.clitSettingXX + 10) {
+						if (slave.clitSetting !== "anti-women") {
+							r += `<br>${slave.slaveName}'s smart piercing has been set to discourage attraction to women.`;
+						}
+						slave.clitSetting = "anti-women";
+						_used = 1;
+					}
+				}
+			}
+		}
+	}
+
+	function ProcessTattoos(slave, rule) {
+		if (rule.boobsTat !== undefined && (rule.boobsTat !== "no default setting")) {
+			if ((slave.boobsTat !== rule.boobsTat)) {
+				slave.boobsTat = rule.boobsTat;
+				V.cash -= V.modCost;
+				r += `<br>${slave.slaveName}'s chest has been tattooed.`;
+			}
+		}
+
+		if (rule.buttTat !== undefined && (rule.buttTat !== "no default setting")) {
+			if ((slave.buttTat !== rule.buttTat)) {
+				slave.buttTat = rule.buttTat;
+				V.cash -= V.modCost;
+				r += `<br>${slave.slaveName}'s butt has been tattooed.`;
+			}
+		}
+
+		if (rule.vaginaTat !== undefined && (rule.vaginaTat !== "no default setting")) {
+			if ((slave.vaginaTat !== rule.vaginaTat)) {
+				slave.vaginaTat = rule.vaginaTat;
+				V.cash -= V.modCost;
+				r += `<br>${slave.slaveName}'s abdomen has been tattooed.`;
+			}
+		}
+
+		if ((slave.dick > 0)) {
+			if (rule.dickTat !== undefined && (rule.dickTat !== "no default setting")) {
+				if ((slave.dickTat !== rule.dickTat)) {
+					slave.dickTat = rule.dickTat;
+					V.cash -= V.modCost;
+					r += `<br>${slave.slaveName}'s dick has been tattooed.`;
+				}
+			}
+		}
+
+		if (rule.lipsTat !== undefined && (rule.lipsTat !== "no default setting")) {
+			if ((slave.lipsTat !== rule.lipsTat)) {
+				slave.lipsTat = rule.lipsTat;
+				V.cash -= V.modCost;
+				r += `<br>${slave.slaveName}'s face has been tattooed.`;
+			}
+		}
+
+		if (rule.anusTat !== undefined && (rule.anusTat !== "no default setting")) {
+			if ((slave.anusTat !== rule.anusTat)) {
+				slave.anusTat = rule.anusTat;
+				V.cash -= V.modCost;
+				r += `<br>${slave.slaveName}'s asshole has been modded.`;
+			}
+		}
+
+		if (rule.shouldersTat !== undefined && (rule.shouldersTat !== "no default setting")) {
+			if ((slave.shouldersTat !== rule.shouldersTat)) {
+				slave.shouldersTat = rule.shouldersTat;
+				V.cash -= V.modCost;
+				r += `<br>${slave.slaveName}'s shoulders have been tattooed.`;
+			}
+		}
+
+		if (rule.armsTat !== undefined && (rule.armsTat !== "no default setting")) {
+			if ((slave.armsTat !== rule.armsTat)) {
+				slave.armsTat = rule.armsTat;
+				V.cash -= V.modCost;
+				r += `<br>${slave.slaveName}'s arms have been tattooed.`;
+			}
+		}
+
+		if (rule.legsTat !== undefined && (rule.legsTat !== "no default setting")) {
+			if ((slave.legsTat !== rule.legsTat)) {
+				slave.legsTat = rule.legsTat;
+				V.cash -= V.modCost;
+				r += `<br>${slave.slaveName}'s legs have been tattooed.`;
+			}
+		}
+
+		if (rule.stampTat !== undefined && (rule.stampTat !== "no default setting")) {
+			if ((slave.stampTat !== rule.stampTat)) {
+				slave.stampTat = rule.stampTat;
+				V.cash -= V.modCost;
+				r += `<br>${slave.slaveName}'s lower back has been tattooed.`;
+			}
+		}
+		if ((rule.autoBrand == 1)) {
+			if ((slave.brand === 0)) {
+				if ((slave.health > -20)) {
+					slave.brand = V.brandDesign;
+					slave.brandLocation = V.brandTarget;
+					if ((slave.devotion < 18))
+						slave.devotion -= 5;
+					slave.trust -= 5;
+					slave.health -= 10;
+					r += `<br>${slave.slaveName} has been branded, with <span class="gold">fear</span>${slave.devotion < 18? `, <span class="mediumorchid">regard,</span>`:``} and <span class="red">health</span> consequences.`;
+				}
+			}
+		}
+	}
+
+	function ProcessPorn(slave, rule) {
+		if ((rule.pornFameSpending !== undefined) && (rule.pornFameSpending !== "no default setting")) {
+			if ((slave.prestige < 3)) {
+				if ((slave.pornFameSpending !== rule.pornFameSpending)) {
+					slave.pornFameSpending = rule.pornFameSpending;
+					r += `<br>${slave.slaveName}'s porn publicity has been corrected.`;
+				}
+			}
+		}
+	}
+
+	return DefaultRules;
+})();
+
+/*:: Rules Assistant Options [script]*/
+// rewrite of the rules assistant options page in javascript
+// uses an object-oriented widget pattern
+// wrapped in a closure so as not to polute the global namespace
+// the widgets are generic enough to be reusable; if similar user interfaces are ported to JS, we could move the classes to the global scope
+
+window.rulesAssistantOptions = (function() {
+	"use strict";
+	let V, current_rule;
+
+	function rulesAssistantOptions(element) {
+		V = State.variables;
+		V.nextButton = "Back to Main";
+		V.nextLink = "Main";
+		V.returnTo = "Main";
+		V.showEncyclopedia = 1;
+		V.encyclopedia = "Personal Assistant";
+		if (V.currentRule !== null) {
+			const idx = V.defaultRules.findIndex(rule => rule.ID === V.currentRule);
+			if (idx === -1)
+				current_rule = V.defaultRules[0];
+			else
+				current_rule = V.defaultRules[idx];
+		}
+		const root = new Root(element);
+	}
+
+	function returnP(e) { return e.keyCode === 13; }
+
+	function newRule(root) {
+		const rule = emptyDefaultRule();
+		V.defaultRules.push(rule);
+		V.currentRule = rule.ID;
+		reload(root);
+	}
+
+	function removeRule(root) {
+		const idx = V.defaultRules.findIndex(rule => rule.ID === current_rule.ID);
+		V.defaultRules.splice(idx, 1);
+		if (V.defaultRules.length > 0) {
+			const new_idx = idx < V.defaultRules.length ? idx : V.defaultRules.length - 1;
+			V.currentRule = V.defaultRules[new_idx].ID;
+		} else V.currentRule = null;
+		reload(root);
+	}
+
+	function lowerPriority(root) {
+		if (V.defaultRules.length === 1) return; // nothing to swap with
+		const idx = V.defaultRules.findIndex(rule => rule.ID === current_rule.ID);
+		if (idx === 0) return; // no lower rule
+		arraySwap(V.defaultRules, idx, idx-1);
+		reload(root);
+	}
+
+	function higherPriority(root) {
+		if (V.defaultRules.length === 1) return; // nothing to swap with
+		const idx = V.defaultRules.findIndex(rule => rule.ID === current_rule.ID);
+		if (idx === V.defaultRules.length - 1) return; // no higher rule
+		arraySwap(V.defaultRules, idx, idx+1);
+		reload(root);
+	}
+
+	function changeName(name, root) {
+		if (name === current_rule.name) return;
+		current_rule.name = name;
+		reload(root);
+	}
+
+	// reload the passage
+	function reload(root) {
+		const elem = root.element;
+		elem.innerHTML = "";
+		rulesAssistantOptions(elem);
+	}
+
+	const parse = {
+		integer(string) {
+			let n = parseInt(string, 10);
+			return isNaN(n)? 0: n;
+		},
+		boobs(string) {
+			return Math.clamp(parse.integer(string), 0, 48000);
+		},
+		butt(string) {
+			return Math.clamp(parse.integer(string), 0, 20);
+		},
+		lips(string) {
+			return Math.clamp(parse.integer(string), 0, 100);
+		},
+		dick(string) {
+			return Math.clamp(parse.integer(string), 0, 30);
+		},
+		balls(string) {
+			return Math.clamp(parse.integer(string), 0, 125);
+		},
+	};
+
+	// the Element class wraps around a DOM element and adds extra functionality
+	// this is safer than extending DOM objects directly
+	// it also turns DOM manipulation into an implementation detail
+	class Element {
+		constructor(...args) {
+			this.parent = null;
+			this.element = this.render(...args);
+			this.children = [];
+		}
+
+		appendChild(child) {
+			child.parent = this;
+			this.children.push(child);
+			this.element.appendChild(child.element);
+		}
+
+		// return the first argument to simplify creation of basic container items
+		render(...args) {
+			return args[0];
+		}
+
+		remove() {
+			const idx = this.parent.children.findIndex(child => child === this);
+			this.parent.children.slice(idx, 1);
+			this.element.remove();
+		}
+	}
+	
+	class Section extends Element {
+		constructor(header, hidden=false) {
+			super(header);
+			this.hidey = this.element.querySelector("div");
+			if (hidden) this.toggle_hidey();
+		}
+		
+		render(header) {
+			const section = document.createElement("section");
+			section.classList.add("rajs-section");
+			const h1 = document.createElement("h1");
+			h1.onclick = () => { this.toggle_hidey(); };
+			h1.innerHTML = header;
+			const hidey = document.createElement("div");
+			section.appendChild(h1);
+			section.appendChild(hidey);
+			return section;
+		}
+
+		appendChild(child) {
+			child.parent = this;
+			this.children.push(child);
+			this.hidey.appendChild(child.element);
+		}
+
+		toggle_hidey() {
+			switch(this.hidey.style.display) {
+				case "none":
+					this.hidey.style.display = "initial";
+					break;
+				default:
+					this.hidey.style.display = "none";
+					break;
+			}
+		}
+	}
+
+	// list of clickable elements
+	// has a short explanation (the prefix) and a value display
+	// value display can optionally be an editable text input field
+	// it can be "bound" to a variable by setting its "onchange" method
+	class List extends Element {
+		constructor(prefix, data=[], textinput=false) {
+			super(prefix + ": ", textinput);
+			this.selectedItem = null;
+			data.forEach(item => this.appendChild(new ListItem(...item)));
+		}
+
+		render(prefix, textinput) {
+			const elem = document.createElement("div");
+			const label = document.createElement("span");
+			label.innerHTML = prefix;
+			let value;
+			if (textinput) {
+				value = document.createElement("input");
+				value.setAttribute("type", "text");
+				value.classList.add("rajs-value"); // 
+				// call the variable binding when the input field is no longer being edited, and when the enter key is pressed
+				value.onfocusout = () => { this.inputEdited(); };
+				value.onblur = () => {this.inputEdited(); };
+				value.onkeypress = (e) => { if (returnP(e)) this.inputEdited(); };
+			} else {
+				value = document.createElement("strong");
+			}
+			this.value = value;
+			elem.appendChild(label);
+			elem.appendChild(value);
+			elem.classList.add("rajs-list");
+			return elem;
+		}
+
+		inputEdited() {
+			if (this.selectedItem) this.selectedItem.deselect();
+			this.propagateChange();
+		}
+
+		selectItem(item) {
+			if (this.selectedItem) this.selectedItem.deselect();
+			this.selectedItem = item;
+			this.setValue(item.data);
+			this.propagateChange();
+		}
+
+		setValue(what) {
+			if (this.value.tagName === "INPUT")
+				this.value.value = ""+what;
+			else
+				this.value.innerHTML = ""+what;
+		}
+
+		getData(what) {
+			return (this.value.tagName === "INPUT" ? this.parse(this.value.value): this.selectedItem.data);
+		}
+
+		// customisable input field parser / sanity checker
+		parse(what) { return what; }
+
+		propagateChange() {
+			if (this.onchange instanceof Function)
+				this.onchange(this.getData());
+		}
+	}
+
+	// a clickable item of a list
+	class ListItem extends Element {
+		constructor(displayvalue, data) {
+			super(displayvalue);
+			this.data = data !== undefined ? data: displayvalue;
+			this.selected = false;
+		}
+
+		render(displayvalue) {
+			const elem = document.createElement("span");
+			elem.classList.add("rajs-listitem");
+			elem.innerHTML = displayvalue;
+			elem.onclick = () => { return this.select(); };
+			return elem;
+		}
+
+		select() {
+			if (this.selected) return false;
+			this.parent.selectItem(this);
+			this.element.classList.add("selected");
+			this.selected = true;
+			return true;
+		}
+
+		deselect() {
+			this.element.classList.remove("selected");
+			this.selected = false;
+		}
+	}
+
+	// a way to organise lists with too many elements in subsections
+	// children are bound to the master list
+	class ListSubSection extends Element {
+		constructor(parent, label, pairs) {
+			super(label);
+			this.parent = parent;
+			pairs.forEach(item => this.appendChild(new ListItem(...item)));
+		}
+		
+		render(label) {
+			const elem = document.createElement("div");
+			const lelem = document.createElement("em");
+			lelem.innerText = label + ": ";
+			elem.appendChild(lelem);
+			return elem;
+		}
+
+		appendChild(child) {
+			super.appendChild(child);
+			child.parent = this.parent;
+			this.parent.children.push(child);
+		}
+	}
+
+	// similar to list, but is just a collection of buttons
+	class Options extends Element {
+		constructor(elements=[]) {
+			super();
+			elements.forEach(element => { this.appendChild(element); });
+		}
+
+		render() {
+			const elem = document.createElement("div");
+			elem.classList.add("rajs-list");
+			return elem;
+		}
+	}
+
+	// options equivalent of ListItem
+	class OptionsItem extends Element {
+		constructor(label, onclick) {
+			super(label);
+			this.label = label;
+			this.onclick = onclick;
+		}
+		render(label, onclick) {
+			const elem = document.createElement("span");
+			elem.classList.add("rajs-listitem");
+			elem.innerHTML = label;
+			elem.onclick = () => { return this.onclick(this); };
+			return elem;
+		}
+	}
+
+	class ButtonList extends Element {
+		render(label) {
+			const elem = document.createElement("div");
+			const labelel = document.createElement("span");
+			labelel.innerHTML = label += ": ";
+			elem.appendChild(labelel);
+			return elem;
+		}
+
+		getSelection() {
+			return (this.children
+				.filter(child => child.selected)
+				.map(child => child.setvalue)
+			);
+		}
+
+		onchange() { return; }
+	}
+
+	class ButtonItem extends Element {
+		constructor(label, setvalue, selected=false) {
+			super(label, selected);
+			this.selected = selected;
+			this.setvalue = setvalue ? setvalue : label;
+		}
+
+		render(label, selected) {
+			const container = document.createElement("div");
+			container.classList.add("rajs-listitem");
+
+			const labelel = document.createElement("span");
+			labelel.innerHTML = label;
+
+			const button = document.createElement("input");
+			button.setAttribute("type", "checkbox");
+			button.checked = selected;
+			button.onchange = () => this.onchange(button.checked);
+			labelel.onclick = () => button.click();
+
+			container.appendChild(labelel);
+			container.appendChild(button);
+
+			return container;
+		}
+
+		onchange(value) {
+			this.selected = value;
+			this.parent.onchange(this);
+		}
+	}
+
+	// rule import field
+	class NewRuleField extends Element {
+		constructor(root) {
+			super();
+			this.root = root;
+		}
+
+		render() {
+			const container = document.createElement("div");
+			const textarea = document.createElement("textarea");
+			textarea.placeholder = "Paste your rule here";
+			container.appendChild(textarea);
+			this.textarea = textarea;
+			const button = document.createElement("button");
+			button.name = "Load";
+			button.innerHTML = "Load";
+			button.onclick = () => { this.loadNewRule(); };
+			container.appendChild(button);
+			return container;
+		}
+
+		loadNewRule() {
+			const text = this.textarea.value;
+			try {
+				const rule = JSON.parse(text);
+				if (!rule.ID) rule.ID = generateNewID();
+				V.defaultRules.push(rule);
+				reload(this.root);
+			} catch (e) {
+				alert("Couldn't import that rule:\n" + e.message);
+			}
+		}
+	}
+
+	// the base element, parent of all elements
+	class Root extends Element {
+		constructor(element) {
+			super(element);
+			if(V.defaultRules.length === 0) {
+				const paragraph = document.createElement("p");
+				paragraph.innerHTML = "<strong>No rules</strong>";
+				this.appendChild(new Element(paragraph));
+				this.appendChild(new NoRules(this));
+				return;
+			}
+			this.appendChild(new RuleSelector(this));
+			this.appendChild(new RuleOptions(this));
+			this.appendChild(new ConditionEditor(this));
+			this.appendChild(new EffectEditor(this));
+		}
+
+		render(element) {
+			const greeting = document.createElement("p");
+			greeting.innerHTML = `<em>${properTitle()}, I will review your slaves and make changes that will have a beneficial effect. Apologies, ${properTitle()}, but this function is... not fully complete. It may have some serious limitations. Please use the 'no default setting' option to identify areas I should not address.</em>`;
+			element.appendChild(greeting);
+			return element;
+		}
+	}
+
+	// optoins displayed when there are no rules
+	class NoRules extends Options {
+		constructor(root) {
+			super();
+			this.root = root;
+			const newrule = new OptionsItem("Add a new rule", () => { newRule(this.root); });
+			this.appendChild(newrule);
+			const importrule = new OptionsItem("Import a rule", () => { this.root.appendChild(new NewRuleField(this.root)); });
+			this.appendChild(importrule);
+		}
+	}
+
+	// buttons for selecting the current rule
+	class RuleSelector extends List {
+		constructor(root) {
+			super("Current rule", V.defaultRules.map(i => [i.name, i]));
+			this.setValue(current_rule.name);
+			this.onchange = function (rule) {
+				V.currentRule = rule.ID;
+				reload(root);
+			};
+		}
+	}
+
+	// buttons for doing transformations on rules
+	class RuleOptions extends Options {
+		constructor(root) {
+			super();
+			this.appendChild(new OptionsItem("New Rule", () => newRule(root)));
+			this.appendChild(new OptionsItem("Remove Rule", () => removeRule(root)));
+			this.appendChild(new OptionsItem("Apply rules", () => this.appendChild(new ApplicationLog())));
+			this.appendChild(new OptionsItem("Lower Priotity", () => lowerPriority(root)));
+			this.appendChild(new OptionsItem("Higher Priority", () => higherPriority(root)));
+			this.appendChild(new OptionsItem("Rename", () => this.appendChild(new RenameField(root))));
+			this.appendChild(new OptionsItem("Export this rule", () => this.appendChild(new ExportField(current_rule))));
+			this.appendChild(new OptionsItem("Export all rules", () => this.appendChild(new ExportField(...V.defaultRules))));
+			this.appendChild(new OptionsItem("Import a rule", () => this.appendChild(new NewRuleField(root))));
+		}
+	}
+
+	class ApplicationLog extends Element {
+		render() {
+			const elem = document.createElement("div");
+			elem.innerHTML = V.slaves.map(slave => DefaultRules(slave)).join("");
+			return elem;
+		}
+	}
+
+	class RenameField extends Element {
+		constructor(root) {
+			super();
+			this.element.onfocusout = () => changeName(this.element.value, root);
+			this.element.onkeypress = (e) => { if (returnP(e)) changeName(this.element.value, root); };
+		}
+
+		render() {
+			const elem = document.createElement("input");
+			elem.setAttribute("type", "text");
+			elem.setAttribute("value", current_rule.name);
+			return elem;
+		}
+	}
+
+	class ExportField extends Element {
+		render(...args) {
+			let element = document.getElementById("exportfield");
+			if (element === null) {
+				element = document.getElementById("exportfield") || document.createElement("textarea");
+				element.id = "exportfield";
+			}
+			element.value = args.map(i => JSON.stringify(i, null, 2)).join("\n\n");
+			return element;
+		}
+	}
+
+	// parent section for condition editing
+	class ConditionEditor extends Section {
+		constructor() {
+			super("Activation Condition");
+			this.appendChild(new ConditionFunction());
+			this.appendChild(new AssignmentInclusion());
+			this.appendChild(new SpecialExclusion());
+			this.appendChild(new SpecificInclusionExclusion());
+		}
+	}
+
+	class ConditionFunction extends Element {
+		constructor() {
+			super();
+			const items = [
+				["Never", false],
+				["Always", true],
+				["Custom", "custom"],
+				["Devotion", "devotion"],
+				["Trust", "trust"],
+				["Health", "health"],
+				["Sex drive", "energy"],
+				["Weight", "weight"],
+				["Age", "actualAge"],
+				["Body Age", "physicalAge"],
+				["Visible Age", "visualAge"],
+				["Muscles", "muscles"],
+				["Lactation", "lactation"],
+				["Pregnancy", "preg"],
+				["Pregnancy Multiples", "pregType"],
+				["Belly Implant", "bellyImplant"],
+				["Belly Size", "belly"],
+				["Education", "intelligenceImplant"],
+				["Intelligence", "intelligence"],
+				["Fetish", "fetish"],
+			];
+			this.fnlist = new List("Activation function", items);
+			this.fnlist.setValue(current_rule.condition.function === "between" ? current_rule.condition.data.attribute : current_rule.condition.function);
+			this.fnlist.onchange = (value) => this.fnchanged(value);
+			this.appendChild(this.fnlist);
+			this.fneditor = null;
+
+			switch(current_rule.condition.function) {
+				case false:
+				case true:
+					break;
+				case "custom":
+					this.show_custom_editor(CustomEditor, current_rule.condition.data);
+					break;
+				case "between":
+					this.show_custom_editor(RangeEditor, current_rule.condition.function, current_rule.condition.data);
+					break;
+				case "belongs":
+					this.show_custom_editor(ItemEditor, current_rule.condition.function, current_rule.condition.data);
+					break;
+			}
+		}
+
+		betweenP(attribute) {
+			return [
+				"devotion",
+				"trust",
+				"health",
+				"energy",
+				"weight",
+				"actualAge",
+				"physicalAge",
+				"visualAge",
+				"muscles",
+				"lactation",
+				"preg",
+				"pregType",
+				"bellyImplant",
+				"belly",
+				"intelligenceImplant",
+				"intelligence",
+			].includes(attribute);
+		}
+
+		belongsP(attribute) {
+			return [
+				"fetish",
+			].includes(attribute);
+		}
+
+		show_custom_editor(what, ...args) {
+			if (this.custom_editor !== null) this.hide_custom_editor();
+			this.custom_editor = new what(...args);
+			this.appendChild(this.custom_editor);
+		}
+
+		hide_custom_editor() {
+			if (this.custom_editor) {
+				this.custom_editor.remove();
+				this.custom_editor = null;
+			}
+		}
+
+		render() {
+			const elem = document.createElement("div");
+			return elem;
+		}
+
+		fnchanged(value) {
+			if (this.fneditor !== null) {
+				this.fneditor.element.remove();
+				this.fneditor = null;
+			}
+			if (value === true || value === false) {
+				current_rule.condition.function = value;
+				current_rule.condition.data = {};
+				this.hide_custom_editor();
+			} else if (value === "custom") {
+				current_rule.condition.function = "custom";
+				current_rule.condition.data = "";
+				this.show_custom_editor(CustomEditor, current_rule.condition.data);
+			} else if (this.betweenP(value)) {
+				current_rule.condition.function = "between";
+				current_rule.condition.data = { attribute: value, value: [null, null] };
+				this.show_custom_editor(RangeEditor, current_rule.condition.function, current_rule.condition.data);
+			} else if (this.belongsP(value)) {
+				current_rule.condition.function = "belongs";
+				current_rule.condition.data = { attribute: value, value: [] };
+				this.show_custom_editor(ItemEditor, current_rule.condition.function, current_rule.condition.data);
+			}
+		}
+	}
+
+	class CustomEditor extends Element {
+		constructor(data) {
+			if (data.length === 0) data = "(function(slave) { return slave.slaveName === 'Fancy Name'; })";
+			super(data);
+		}
+
+		render(data) {
+			const elem = document.createElement("textarea");
+			elem.innerHTML = data;
+			elem.onblur = () => current_rule.condition.data = elem.value;
+			return elem;
+		}
+	}
+
+	class RangeEditor extends Element {
+		render(fn, data) {
+			const elem = document.createElement("div");
+
+			const minlabel = document.createElement("label");
+			minlabel.innerHTML = "Lower bound: ";
+			elem.appendChild(minlabel);
+
+			const min = document.createElement("input");
+			min.setAttribute("type", "text");
+			min.value = "" + data.value[0];
+			min.onkeypress = e => { if (returnP(e)) this.setmin(min.value); };
+			min.onfocusout = e => this.setmin(min.value);
+			this.min = min;
+			elem.appendChild(min);
+
+			elem.appendChild(document.createElement("br"));
+
+			const maxlabel = document.createElement("label");
+			maxlabel.innerHTML = "Upper bound: ";
+			elem.appendChild(maxlabel);
+
+			const max = document.createElement("input");
+			max.setAttribute("type", "text");
+			max.value = "" + data.value[1];
+			max.onkeypress = e => { if (returnP(e)) this.setmax(max.value); };
+			max.onfocusout = e => this.setmax(max.value);
+			this.max = max;
+			elem.appendChild(max);
+
+			const infobar = document.createElement("div");
+			infobar.innerHTML = this.info(data.attribute);
+			elem.appendChild(infobar);
+
+			return elem;
+		}
+
+		parse(value) {
+			value = value.trim();
+			if (value === "null") value = null;
+			else {
+				value = parseInt(value);
+				if (isNaN(value)) value = null;
+			}
+			return value;
+		}
+
+		setmin(value) {
+			current_rule.condition.data.value[0] = this.parse(value);
+			this.min.value = ""+current_rule.condition.data.value[0];
+		}
+
+		setmax(value) {
+			current_rule.condition.data.value[1] = this.parse(value);
+			this.max.value = ""+current_rule.condition.data.value[1];
+		}
+
+		info(attribute) {
+			return ({
+				"devotion": "Very Hateful: (-∞, -95), Hateful: [-95, -50), Resistant: [-50, -20), Ambivalent: [-20, 20], Accepting: (20, 50], Devoted: (50, 95], Worshipful: (95, ∞)",
+				"trust": "Extremely terrified: (-∞, -95), Terrified: [-95, -50), Frightened: [-50, -20), Fearful: [-20, 20], Careful: (20, 50], Trusting: (50, 95], Total trust: (95, ∞)",
+				"health": "Death: (-∞, -100), Near Death: [-100, -90), Extremely Unhealthy: [-90, -50), Unhealthy: [-50, -20), Healthy: [-20, 20], Very Healthy: (20, 50], Extremely Healthy: (50, 90], Unnaturally Healthy: (90, ∞)",
+				"energy": "Frigid: (-∞, 20], Poor: (20, 40], Average: (40, 60], Powerful: (60, 80], Sex Addict: (80, 100), Nympho: 100",
+				"weight": "Emaciated: (-∞, -95), Skinny: [-95, -30), Thin: [-30, -10), Average: [-10, 10], Plush: (10, 30], Fat: (30, 95], Overweight: (95, ∞)",
+				"lactation": "None: 0, 1: Natural, 2: Lactation implant",
+				"preg": "Barren: -2, On contraceptives: -1, Not pregnant: 0, Pregnancy weeks: [1, ∞)",
+				"pregType": "Fetus count, known only after the 10th week of pregnancy",
+				"bellyImplant": "Volume in CCs. None: -1",
+				"belly": "Volume in CCs, any source",
+				"intelligenceImplant": "Education level. 0: uneducated, 1: educated, (0, 1): incomplete education.",
+				"intelligence": "From moronic to brilliant: [-3, 3]",
+			}[attribute] || " ");
+		}
+	}
+
+	class ItemEditor extends Element {
+		render(fn, data) {
+			const elem = document.createElement("div");
+
+			const input = document.createElement("input");
+			input.setAttribute("type", "text");
+			input.value = JSON.stringify(data.value);
+			input.onkeypress = e => { if (returnP(e)) this.setValue(input); };
+			input.onfocusout = e => this.setValue(input);
+			this.input = input;
+			elem.appendChild(input);
+
+			const infobar = document.createElement("div");
+			infobar.innerHTML = this.info(data.attribute);
+			elem.appendChild(infobar);
+
+			return elem;
+		}
+
+		info(attribute) {
+			return "Insert a valid JSON array. Known values: " + {
+				"fetish": "buttslut, cumslut, masochist, sadist, dom, submissive, boobs, pregnancy, none (AKA vanilla)",
+			}[attribute];
+		}
+		
+		setValue(input) {
+			try {
+				const arr = JSON.parse(input.value);
+				current_rule.condition.data.value = arr;
+				input.value = JSON.stringify(arr);
+			} catch (e) {
+				alert(e);
+			}
+		}
+	}
+
+
+	class AssignmentInclusion extends ButtonList {
+		constructor() {
+			super("Apply to assignments and facilities");
+			const items = ["Rest", "Fucktoy", "Subordinate Slave", "House Servant", "Confined", "Whore", "Public Servant", "Classes", "Milked", "Gloryhole"];
+			if (V.HGSuite > 0) items.push("Head Girl Suite");
+			if (V.brothel > 0) items.push("Brothel");
+			if (V.club > 0) items.push("Club");
+			if (V.arcade > 0) items.push("Arcade");
+			if (V.dairy > 0) items.push("Dairy");
+			if (V.servantQuarters > 0) items.push("Servant Quarters");
+			if (V.masterSuite > 0) items.push("Master Suite");
+			if (V.schoolroom > 0) items.push("Schoolroom");
+			if (V.spa > 0) items.push("Spa");
+			if (V.clinic > 0) items.push("Clinic");
+			if (V.cellblock > 0) items.push("Cellblock");
+			items.forEach(
+				i => this.appendChild(new ButtonItem(i, this.getAttribute(i), current_rule.condition.assignment.includes(i))));
+		}
+
+		onchange() {
+			current_rule.condition.assignment = this.getSelection();
+		}
+
+		getAttribute(what) {
+			return {
+				"Rest": "rest",
+				"Fucktoy": "please you",
+				"Subordinate Slave": "be a subordinate slave",
+				"House Servant": "be a servant",
+				"Confined": "stay confined",
+				"Whore": "whore",
+				"Public Servant": "serve the public",
+				"Classes": "take classes",
+				"Milked": "get milked",
+				"Gloryhole": "work a glory hole",
+				"Head Girl Suite": "live with your Head Girl",
+				"Brothel": "work in the brothel",
+				"Club": "serve in the club",
+				"Arcade": "be confined in the arcade",
+				"Dairy": "work in the dairy",
+				"Servant Quarters": "work as a servant",
+				"Master Suite": "serve in the master suite",
+				"Schoolroom": "learn in the schoolroom",
+				"Spa": "rest in the spa",
+				"Clinic": "get treatment in the clinic",
+				"Cellblock": "be confined in the cellblock",
+			}[what];
+		}
+	}
+
+	class SpecialExclusion extends List {
+		constructor() {
+			const items = [
+				["Yes", true],
+				["No", false]
+			];
+			super("Exclude special slaves", items);
+			this.setValue(current_rule.condition.excludeSpecialSlaves);
+			this.onchange = (value) => current_rule.condition.excludeSpecialSlaves = value;
+		}
+	}
+
+	class SpecificInclusionExclusion extends Options {
+		constructor() {
+			super();
+			this.appendChild(new OptionsItem("Limit to specific slaves", () => this.show_slave_selection()));
+			this.appendChild(new OptionsItem("Exclude specific slaves", () => this.show_slave_exclusion()));
+			this.subwidget = null;
+		}
+
+		show_slave_selection() {
+			if (this.subwidget) this.subwidget.remove();
+			this.subwidget = new SlaveSelection();
+			this.appendChild(this.subwidget);
+		}
+
+		show_slave_exclusion() {
+			if (this.subwidget) this.subwidget.remove();
+			this.subwidget = new SlaveExclusion();
+			this.appendChild(this.subwidget);
+		}
+	}
+
+	class SlaveSelection extends ButtonList {
+		constructor() {
+			super("Include specific slaves");
+			V.slaves.forEach(slave => this.appendChild(new ButtonItem(
+				[slave.slaveName, slave.slaveSurname].join(" "),
+				slave.ID,
+				current_rule.condition.selectedSlaves.includes(slave.ID))));
+		}
+
+		onchange() {
+			current_rule.condition.selectedSlaves = this.getSelection();
+		}
+	}
+
+	class SlaveExclusion extends ButtonList {
+		constructor() {
+			super("Exclude specific slaves");
+			V.slaves.forEach(slave => this.appendChild(new ButtonItem(
+				[slave.slaveName, slave.slaveSurname].join(" "),
+				slave.ID,
+				current_rule.condition.excludedSlaves.includes(slave.ID))));
+		}
+
+		onchange() {
+			current_rule.condition.excludedSlaves = this.getSelection();
+		}
+	}
+
+	// parent section for effect editing
+	class EffectEditor extends Element {
+		constructor() {
+			super();
+			this.appendChild(new AppearanceSection());
+			this.appendChild(new CosmeticSection());
+			this.appendChild(new BodyModSection());
+			this.appendChild(new AutosurgerySection());
+			this.appendChild(new RegimenSection());
+			this.appendChild(new BehaviourSection());
+		}
+
+		render() {
+			const element = document.createElement("div");
+			return element;
+		}
+	}
+
+	class AppearanceSection extends Section {
+		constructor() {
+			super("Appearance Settings");
+			this.appendChild(new ClothesList());
+			this.appendChild(new CollarList());
+			this.appendChild(new ShoeList());
+			this.appendChild(new CorsetList());
+			this.appendChild(new VagAccVirginsList());
+			this.appendChild(new VagAccAVirginsList());
+			this.appendChild(new VagAccOtherList());
+			if (V.seeDicks !== 0 || V.makeDicks !== 0) {
+				this.appendChild(new DickAccVirginsList());
+				this.appendChild(new DickAccOtherList());
+			}
+			this.appendChild(new ButtplugsVirginsList());
+			this.appendChild(new ButtplugsOtherList());
+			this.appendChild(new ImplantVolumeList());
+			this.appendChild(new AutosurgerySwitch());
+
+		}
+	}
+
+	class RegimenSection extends Section {
+		constructor() {
+			super("Physical Regimen Settings");
+			this.appendChild(new GrowthList());
+			this.appendChild(new CurrativesList());
+			this.appendChild(new AphrodisiacList());
+			this.appendChild(new ContraceptiveList());
+			if (V.pregSpeedControl)
+				this.appendChild(new PregDrugsList());
+			this.appendChild(new FemaleHormonesList());
+			this.appendChild(new ShemaleHormonesList());
+			this.appendChild(new GeldingHormonesList());
+			this.appendChild(new OtherDrugsList());
+			this.appendChild(new DietList());
+			this.appendChild(new DietGrowthList());
+			this.appendChild(new DietBaseList());
+			this.appendChild(new MuscleList());
+			this.appendChild(new BraceList());
+		}
+	}
+
+	class BehaviourSection extends Section {
+		constructor() {
+			super("Behavior Settings");
+			this.appendChild(new AutomaticAssignmentList());
+			this.appendChild(new LivingStandardList());
+			this.appendChild(new PunishmentList());
+			this.appendChild(new RewardList());
+			this.appendChild(new ReleaseList());
+			this.appendChild(new SmartFetishList());
+			this.appendChild(new SmartXYAttractionList());
+			this.appendChild(new SmartXXAttractionList());
+			this.appendChild(new SmartEnergyList());
+			this.appendChild(new SpeechList());
+			this.appendChild(new RelationshipList());
+			if (V.studio === 1)
+				this.appendChild(new PornList());
+		}
+	}
+
+	class CosmeticSection extends Section {
+		constructor() {
+			super("Cosmetic Settings", true);
+			this.appendChild(new EyewearList());
+			this.appendChild(new LensesList());
+			this.appendChild(new MakeupList());
+			this.appendChild(new NailsList());
+			this.appendChild(new HairLengthList());
+			this.appendChild(new HairColourList());
+			this.appendChild(new HairStyleList());
+			this.appendChild(new PubicHairColourList());
+			this.appendChild(new PubicHairStyleList());
+			this.appendChild(new ArmpitHairColourList());
+			this.appendChild(new ArmpitHairStyleList());
+		}
+	}
+
+	class BodyModSection extends Section {
+		constructor() {
+			super("Body Mod Settings", true);
+			this.appendChild(new EarPiercingList());
+			this.appendChild(new NosePiercingList());
+			this.appendChild(new EyebrowPiercingList());
+			this.appendChild(new NavelPiercingList());
+			this.appendChild(new NipplePiercingList());
+			this.appendChild(new AreolaPiercingList());
+			this.appendChild(new LipPiercingList());
+			this.appendChild(new TonguePiercingList());
+			this.appendChild(new ClitPiercingList());
+			this.appendChild(new LabiaPiercingList());
+			this.appendChild(new ShaftPiercingList());
+			this.appendChild(new PerineumPiercingList());
+			this.appendChild(new CorsetPiercingList());
+
+			this.appendChild(new AutoBrandingList());
+			this.appendChild(new BrandingLocationList());
+			this.appendChild(new BrandDesignList());
+
+			this.appendChild(new FaceTattooList());
+			this.appendChild(new ShoulderTattooList());
+			this.appendChild(new ChestTattooList());
+			this.appendChild(new ArmTattooList());
+			this.appendChild(new UpperBackTattooList());
+			this.appendChild(new LowerBackTattooList());
+			this.appendChild(new AbdomenTattooList());
+			if (V.seeDicks || V.makeDicks)
+				this.appendChild(new DickTattooList());
+			this.appendChild(new ButtockTattooList());
+			this.appendChild(new AnalTattooList());
+			this.appendChild(new LegTattooList());
+		}
+	}
+
+	class AutosurgerySection extends Section {
+		constructor() {
+			super("Autosurgery Settings", true);
+			this.appendChild(new VisionSurgeryList());
+			this.appendChild(new LactationSurgeryList());
+			if (V.seeDicks || V.makeDicks)
+				this.appendChild(new SemenSurgeryList());
+			this.appendChild(new CosmeticSurgeryList());
+			this.appendChild(new LipSurgeryList());
+			this.appendChild(new ButtSurgeryList());
+			this.appendChild(new BreastSurgeryList());
+			this.appendChild(new TighteningSurgeryList());
+			this.appendChild(new BodyHairSurgeryList());
+			this.appendChild(new HairSurgeryList());
+		}
+	}
+
+	class ClothesList extends List {
+		constructor() {
+			const items = [
+				["Select her own outfit", "choosing her own clothes"]
+			];
+			super("Clothes", items);
+
+			const nclothes = [
+				["No default clothes setting", "no default setting"],
+				["Apron", "an apron"],
+				["Bangles", "slutty jewelry"],
+				["Bodysuit", "a comfortable bodysuit"],
+				["Cheerleader outfit", "a cheerleader outfit"],
+				["Clubslut netting", "clubslut netting"],
+				["Cybersuit", "a cybersuit"],
+				["Cutoffs and a t-shirt", "cutoffs and a t-shirt"],
+				["Fallen nun", "a fallen nuns habit"],
+				["Halter top", "a halter top dress"],
+				["Hijab and abaya", "a hijab and abaya"],
+				["Latex catsuit", "a latex catsuit"],
+				["Leotard", "a leotard"],
+				["Maid (nice)", "a nice maid outfit"],
+				["Maid (slutty)", "a slutty maid outfit"],
+				["Military uniform", "a military uniform"],
+				["Schutzstaffel uniform", "a schutzstaffel uniform"],
+				["Schutzstaffel uniform (slutty)", "a slutty schutzstaffel uniform"],
+				["Red Army uniform", "a red army uniform"],
+				["Mini dress", "a mini dress"],
+				["Monokini", "a monokini"],
+				["Nice lingerie", "attractive lingerie"],
+				["Nurse (nice)", "a nice nurse outfit"],
+				["Schoolgirl", "a schoolgirl outfit"],
+				["Silken ballgown", "a ball gown"],
+				["Skimpy battledress", "battledress"],
+				["Slave gown", "a slave gown"],
+				["Slutty outfit", "a slutty outfit"],
+				["String bikini", "a stirng bikini"],
+				["Scalemail bikini", "a scalemail bikini"],
+				["Succubus costume", "a succubus outfit"],
+				["Suit (nice)", "nice business sattire"],
+				["Suit (slutty", "slutty business attire"],
+				["Spats and tank top", "spats and a tank top"]
+			];
+			const fsnclothes = [
+				["Body oil (FS)", "body oil"],
+				["Bunny outfit (FS)", "a bunny outfit"],
+				["Chattel habit (FS)", "a chattel habit"],
+				["Conservative clothing (FS)", "conservative clothing"],
+				["Harem gauze (FS)", "harem gauze"],
+				["Huipil (FS)", "a huipil"],
+				["Kimono (FS)", "a kimono"],
+				["Maternity dress (FS)", "a maternity dress"],
+				["Maternity lingerie (FS)", "attractive lingerie for a pregnant woman"],
+				["Slutty qipao (FS)", "a slutty qipao"],
+				["Stretch pants and a crop-top (FS)", "stretch pants and a crop-top"],
+				["Toga (FS)", "a toga"],
+				["Western clothing (FS)", "Western clothing"],
+			];
+			fsnclothes.forEach(pair => { if (isItemAccessible(pair[1])) nclothes.push(pair); });
+			const nice = new ListSubSection(this, "Nice", nclothes);
+			this.appendChild(nice);
+
+			const hclothes = [
+				["Nude", "no clothing"],
+				["Penitent nun", "a penitent nuns habit"],
+				["Restrictive latex", "restrictive latex"],
+				["Shibari ropes", "shibari ropes"],
+				["Uncomfortable straps", "uncomfortable straps"]
+			];
+			const fshclothes = [
+				["Chains (FS)", "chains"],
+			];
+			fshclothes.forEach(pair => { if (isItemAccessible(pair[1])) hclothes.push(pair); });
+
+			const harsh = new ListSubSection(this, "Harsh", hclothes);
+			this.appendChild(harsh);
+
+			this.setValue(current_rule.set.clothes);
+			this.onchange = (value) => current_rule.set.clothes = value;
+		}
+	}
+
+	class CollarList extends List {
+		constructor() {
+			const items = [
+				["No default collar setting", "no default setting"],
+				["No collar", "none"],
+			];
+			super("Collar", items);
+
+			const ncollars = [
+				["Stylish leather", "stylish leather"],
+				["Satin choker", "satin choker"],
+				["Silken Ribbon", "silk ribbon"],
+				["Heavy Gold", "heavy gold"],
+				["Pretty jewelry", "pretty jewelry"],
+				["Cowbell", "leather with cowbell"]
+			];
+			if (V.seeAge !== 0)
+				ncollars.push(["Nice retirement counter", "nice retirement counter"]);
+			const fsncollars = [
+				["Bowtie collar", "bowtie"],
+				["ancient Egyptian", "ancient Egyptian"],
+			];
+			fsncollars.forEach(pair => { if (isItemAccessible(pair[1])) ncollars.push(pair); });
+			const nice = new ListSubSection(this, "Nice", ncollars);
+			this.appendChild(nice);
+
+			const hcollars = [
+				["Tight steel", "tight steel"],
+				["Uncomfortable leather", "uncomfortable leather"],
+				["Pregnancy biometrics", "preg biometrics"],
+				["Shock punishment", "shock punishment"],
+				["Dildo gag", "dildo gag"],
+				["Ball gag", "ball gag"],
+				["Bit gag", "bit gag"],
+				["Neck corset", "neck corset"],
+			];
+			if (V.seeAge !== 0)
+				hcollars.push(["Cruel retirement counter", "cruel retirement counter"]);
+			if (V.toysBoughtGags === 1)
+				hcollars.push(["Massive dildo gag", "massive dildo gag"]);
+			const harsh = new ListSubSection(this, "Harsh", hcollars);
+			this.appendChild(harsh);
+
+			this.setValue(current_rule.set.collar);
+			this.onchange = (value) => current_rule.set.collar = value;
+		}
+	}
+
+	class ShoeList extends List {
+		constructor() {
+			super("Shoes", setup.shoes.map(i => [i.name, i.value]));
+			this.setValue(current_rule.set.shoes);
+			this.onchange = (value) => current_rule.set.shoes = value;
+		}
+	}
+
+	class CorsetList extends List {
+		constructor() {
+			const bellies = [];
+			setup.bellyAccessories.forEach(acc => {
+				if (acc.fs === undefined && acc.rs === undefined)
+					bellies.push([acc.name, acc.value]);
+				else if (acc.fs === "repopulation" && V.arcologies[0].FSRepopulationFocus !== "unset")
+					bellies.push([acc.name + " (FS)", acc.value]);
+				else if (acc.rs === "boughtBelly" && V.clothesBoughtBelly === 1)
+					bellies.push([acc.name + " (Purchased)", acc.value]);
+			});
+			super("Corsetage", bellies);
+			this.setValue(current_rule.set.bellyAccessory);
+			this.onchange = (value) => current_rule.set.bellyAccessory = value;
+		}
+	}
+
+	class VagAccVirginsList extends List {
+		constructor() {
+			const accs = [];
+			setup.vaginalAccessories.forEach(acc => {
+				if (acc.fs === undefined && acc.rs === undefined)
+					accs.push([acc.name, acc.value]);
+				else if (acc.rs === "buyBigDildos" && V.toysBoughtDildos === 1)
+					accs.push([acc.name + " (Purchased)", acc.value]);
+			});
+			super("Vaginal accessories for virgins", accs);
+			this.setValue(current_rule.set.virginAccessory);
+			this.onchange = (value) => current_rule.set.virginAccessory = value;
+		}
+	}
+
+	class VagAccAVirginsList extends List {
+		constructor() {
+			const accs = [];
+			setup.vaginalAccessories.forEach(acc => {
+				if (acc.fs === undefined && acc.rs === undefined)
+					accs.push([acc.name, acc.value]);
+				else if (acc.rs === "buyBigDildos" && V.toysBoughtDildos === 1)
+					accs.push([acc.name + " (Purchased)", acc.value]);
+			});
+			super("Vaginal accessories for anal virgins", accs);
+			this.setValue(current_rule.set.aVirginAccessory);
+			this.onchange = (value) => current_rule.set.aVirginAccessory = value;
+		}
+	}
+
+	class VagAccOtherList extends List {
+		constructor() {
+			const accs = [];
+			setup.vaginalAccessories.forEach(acc => {
+				if (acc.fs === undefined && acc.rs === undefined)
+					accs.push([acc.name, acc.value]);
+				else if (acc.rs === "buyBigDildos" && V.toysBoughtDildos === 1)
+					accs.push([acc.name + " (Purchased)", acc.value]);
+			});
+			super("Vaginal accessories for other slaves", accs);
+			this.setValue(current_rule.set.vaginalAccessory);
+			this.onchange = (value) => current_rule.set.vaginalAccessory = value;
+		}
+	}
+
+	class DickAccVirginsList extends List {
+		constructor() {
+			super("Dick accessories for anal virgins", setup.dickAccessories.map(i => [i.name, i.value]));
+			this.setValue(current_rule.set.aVirginDickAccessory);
+			this.onchange = (value) => current_rule.set.aVirginDickAccessory = value;
+		}
+	}
+
+	class DickAccOtherList extends List {
+		constructor() {
+			super("Dick accessories for other slaves", setup.dickAccessories.map(i => [i.name, i.value]));
+			this.setValue(current_rule.set.dickAccessory);
+			this.onchange = (value) => current_rule.set.dickAccessory = value;
+		}
+	}
+
+	class ButtplugsVirginsList extends List {
+		constructor() {
+			const accs = [];
+			setup.buttplugs.forEach(acc => {
+				if (acc.fs === undefined && acc.rs === undefined)
+					accs.push([acc.name, acc.value]);
+				else if (acc.rs === "buyBigPlugs" && V.toysBoughtButtPlugs === 1)
+					accs.push([acc.name + " (Purchased)", acc.value]);
+			});
+			super("Buttplugs for anal virgins", accs);
+			this.setValue(current_rule.set.aVirginButtplug);
+			this.onchange = (value) => current_rule.set.aVirginButtplug = value;
+		}
+	}
+
+	class ButtplugsOtherList extends List {
+		constructor() {
+			const accs = [];
+			setup.buttplugs.forEach(acc => {
+				if (acc.fs === undefined && acc.rs === undefined)
+					accs.push([acc.name, acc.value]);
+				else if (acc.rs === "buyBigPlugs" && V.toysBoughtButtPlugs === 1)
+					accs.push([acc.name + " (Purchased)", acc.value]);
+			});
+			super("Buttplugs for other slaves", accs);
+			this.setValue(current_rule.set.buttplug);
+			this.onchange = (value) => current_rule.set.buttplug = value;
+		}
+	}
+
+	class ImplantVolumeList extends List {
+		constructor() {
+			const pairs = [
+				["No changes", -1],
+				["Empty implant", 0],
+				["Early pregnancy", 1500],
+				["Second trimester pregnancy", 5000],
+				["Full-term pregnancy", 15000],
+				["Full-term with twins", 30000],
+				["Full-term with triplets", 45000],
+				["Full-term with quadruplets", 60000],
+				["Full-term with quintuplets", 75000],
+				["Full-term with sextuplets", 90000],
+				["Full-term with septuplets", 105000],
+				["Full-term with octuplets", 120000]
+			];
+			super("Belly implant target volume (if present)", pairs);
+			this.setValue(current_rule.set.bellyImplantVol);
+			this.onchange = (value) => current_rule.set.bellyImplantVol = value;
+		}
+	}
+
+	class AutosurgerySwitch extends List {
+		constructor() {
+			const pairs = [
+				["Activate", 1],
+				["Off", 0],
+			];
+			super("Assistant-applied implants (Autosurgery global switch)", pairs);
+			this.setValue(current_rule.set.autoSurgery);
+			this.onchange = (value) => current_rule.set.autoSurgery = value;
+		}
+	}
+
+	class GrowthList extends Options {
+		constructor() {
+			super();
+			this.sublists = [];
+			const pairs = [
+				["No default setting", () => this.nds()],
+				["Girlish figure", () => this.girlish()],
+				["Stacked figure", () => this.stacked()],
+				["Huge but functional", () => this.huge()],
+				["Unlimited", () => this.unlimited()],
+				["None", () => this.none()]
+			];
+			pairs.forEach(pair => this.appendChild(new OptionsItem(...pair)));
+
+			this.breasts = new BreastGrowthList();
+			this.butts = new ButtGrowthList();
+			this.lips = new LipGrowthList();
+			this.sublists.push(this.breasts, this.butts, this.lips);
+
+			if (V.seeDicks > 0 || V.makeDicks > 0) {
+				this.dicks = new DickGrowthList();
+				this.balls = new BallGrowthList();
+				this.sublists.push(this.dicks, this.balls);
+			}
+
+			this.sublists.forEach(i => this.appendChild(i));
+		}
+
+		render() {
+			const elem = document.createElement("div");
+			const span = document.createElement("span");
+			span.innerHTML = "Growth hormone regimes for healthy slaves: ";
+			elem.appendChild(span);
+			return elem;
+		}
+
+		nds() {
+			[this.breasts, this.butts, this.lips, this.dicks, this.balls].forEach(i => {
+				i.setValue("no default change");
+				i.propagateChange();
+			});
+		}
+
+		girlish() {
+			this.breasts.setValue(350);
+			this.butts.setValue(2);
+			this.lips.setValue(25);
+			if (this.dicks) this.dicks.setValue(0);
+			if (this.balls) this.balls.setValue(0);
+			this.sublists.forEach(i => i.propagateChange());
+		}
+
+		stacked() {
+			this.breasts.setValue(1000);
+			this.butts.setValue(4);
+			this.lips.setValue(25);
+			if (this.dicks) this.dicks.setValue(4);
+			if (this.balls) this.balls.setValue(4);
+			this.sublists.forEach(i => i.propagateChange());
+		}
+
+		huge() {
+			this.breasts.setValue(9000);
+			this.butts.setValue(10);
+			this.lips.setValue(45);
+			if (this.dicks) this.dicks.setValue(6);
+			if (this.balls) this.balls.setValue(6);
+			this.sublists.forEach(i => i.propagateChange());
+		}
+
+		unlimited() {
+			this.breasts.setValue(48000);
+			this.butts.setValue(20);
+			this.lips.setValue(100);
+			if (this.dicks) this.dicks.setValue(30);
+			if (this.balls) this.balls.setValue(125);
+			this.sublists.forEach(i => i.propagateChange());
+		}
+
+		none() {
+			this.sublists.forEach(i => {
+				i.setValue(0);
+				i.propagateChange();
+			});
+		}
+	}
+
+	class BreastGrowthList extends List {
+		constructor() {
+			const pairs = [
+				["No default setting", "no default setting"],
+				["B Cup", 350],
+				["D Cup", 1000],
+				["Monstrous", 9000],
+				["Unlimited", 48000],
+				["None", 0]
+			];
+			super("Breasts", pairs, true);
+			this.setValue(current_rule.set.growth_boobs);
+			this.onchange = (value) => current_rule.set.growth_boobs = value;
+		}
+	}
+
+	class ButtGrowthList extends List {
+		constructor() {
+			const pairs = [
+				["No default setting", "no default setting"],
+				["Cute", 2],
+				["Big", 4],
+				["Huge", 6],
+				["Unlimited", 20],
+				["None", 0]
+			];
+			super("Butts", pairs, true);
+			this.setValue(current_rule.set.growth_butt);
+			this.onchange = (value) => current_rule.set.growth_butt = value;
+		}
+	}
+
+	class LipGrowthList extends List {
+		constructor() {
+			const pairs = [
+				["No default setting", "no default setting"],
+				["Plump", 25],
+				["Beestung", 45],
+				["Facepussy", 100],
+				["None", 0]
+			];
+			super("Lips", pairs, true);
+			this.setValue(current_rule.set.growth_lips);
+			this.onchange = (value) => current_rule.set.growth_lips = value;
+		}
+	}
+
+	class DickGrowthList extends List {
+		constructor() {
+			const pairs = [
+				["No default setting", "no default setting"],
+				["Above average", 4],
+				["Pornstar", 6],
+				["Unlimited", 30],
+				["None", 0]
+			];
+			super("Dicks, if present", pairs, true);
+			this.setValue(current_rule.set.growth_dick);
+			this.onchange = (value) => current_rule.set.growth_dick = value;
+		}
+	}
+
+	class BallGrowthList extends List {
+		constructor() {
+			const pairs = [
+				["No default setting", "no default setting"],
+				["Sizeable", 4],
+				["Cumslave", 6],
+				["Unlimited", 125],
+				["None", 0]
+			];
+			super("Balls, if present", pairs, true);
+			this.setValue(current_rule.set.growth_balls);
+			this.onchange = (value) => current_rule.set.growth_balls = value;
+		}
+	}
+
+	class CurrativesList extends List {
+		constructor() {
+			const pairs = [
+				["No default setting", "no default setting"],
+				["None", 0],
+				["Preventatives", 1],
+				["Curatives", 2],
+			];
+			super("Health drugs", pairs);
+			this.setValue(current_rule.set.curatives);
+			this.onchange = (value) => current_rule.set.curatives = value;
+		}
+	}
+
+	class AphrodisiacList extends List {
+		constructor() {
+			const pairs = [
+				["No default setting", "no default setting"],
+				["None", 0],
+				["Standard", 1],
+				["Extreme", 2],
+				["Anaphrodisiacs", -1]
+			];
+			super("Aphrodisiacs", pairs);
+			this.setValue(current_rule.set.aphrodisiacs);
+			this.onchange = (value) => current_rule.set.aphrodisiacs = value;
+		}
+	}
+
+	class ContraceptiveList extends List {
+		constructor() {
+			const drugs =  [
+				["No default setting", "no default setting"],
+				["Contraceptives", -1],
+				["Fertile", 0],
+				["Very fertile", 1],
+				["Extremely fertile", 2],
+			];
+			if (V.seeHyperPreg === 1 && V.superFertilityDrugs === 1) {
+				drugs.push(["Hyper fertile", 3]);
+				drugs.push(["Maximize fertility", 4]);
+			}
+			super("Contraceptives for fertile slaves", drugs);
+			this.setValue(current_rule.set.preg);
+			this.onchange = (value) => current_rule.set.preg = value;
+		}
+	}
+
+	class PregDrugsList extends List {
+		constructor() {
+			const pairs = [
+				["No changes", "no default setting"],
+				["None", "none"],
+				["Fast gestation", "fast"],
+				["Slow gestation", "slow"],
+				["Birth supressors", "suppress"],
+				["Birth stimulators", "stimulate"]
+			];
+			super("Pregnancy control agents for pregnant slaves", pairs);
+			this.setValue(current_rule.set.pregSpeed);
+			this.onchange = (value) => current_rule.set.pregSpeed = value;
+		}
+	}
+
+	class FemaleHormonesList extends List {
+		constructor() {
+			const pairs = [
+				["No default setting", "no default setting"],
+				["Intensive Female", 2],
+				["Female", 1],
+				["None", 0],
+				["Male", -1],
+				["Intensive Male", -2]
+			];
+			super("Hormones for female slaves", pairs);
+			this.setValue(current_rule.set.XX);
+			this.onchange = (value) => current_rule.set.XX = value;
+		}
+	}
+
+	class GeldingHormonesList extends List {
+		constructor() {
+			const pairs = [
+				["No default setting", "no default setting"],
+				["Intensive Female", 2],
+				["Female", 1],
+				["None", 0],
+				["Male", -1],
+				["Intensive Male", -2]
+			];
+			super("Hormones for geldings", pairs);
+			this.setValue(current_rule.set.gelding);
+			this.onchange = (value) => current_rule.set.gelding = value;
+		}
+	}
+
+	class ShemaleHormonesList extends List {
+		constructor() {
+			const pairs = [
+				["No default setting", "no default setting"],
+				["Intensive Female", 2],
+				["Female", 1],
+				["None", 0],
+				["Male", -1],
+				["Intensive Male", "intensive male", -2]
+			];
+			super("Hormones for shemales", pairs);
+			this.setValue(current_rule.set.XY);
+			this.onchange = (value) => current_rule.set.XY = value;
+		}
+	}
+
+	class OtherDrugsList extends List {
+		constructor() {
+			const drugs = [];
+			setup.drugs.forEach(drug => {
+				if (drug.fs === undefined && drug.rs === undefined)
+					drugs.push([drug.name, drug.value]);
+				else if (drug.rs === "growth" && V.growthStim === 1)
+					drugs.push([drug.name + " (Research)", drug.value]);
+				else if (drug.rs === "pubHorm" && V.precociousPuberty === 1 && V.pubertyHormones === 1)
+					drugs.push([drug.name + " (Research)", drug.value]);
+				else if (drug.rs === "nosag" && V.purchasedSagBGone === 1)
+					drugs.push([drug.name + " (Product)", drug.value]);
+				else if (drug.fs === "slimness" && V.arcologies[0].FSSlimnessEnthusiastResearch === 1)
+					drugs.push([drug.name + " (FS)", drug.value]);
+				else if (drug.fs === "youth" && V.arcologies[0].FSYouthPreferentialistResearch === 1)
+					drugs.push([drug.name + " (FS)", drug.value]);
+			});
+			super("Other drugs (Will be overriden by hormones and other drugs where applicable)", drugs);
+			this.setValue(current_rule.set.drug);
+			this.onchange = (value) => current_rule.set.drug = value;
+		}
+	}
+
+	class DietList extends List {
+		constructor() {
+			const diets = [
+				["no default setting", "no default setting"],
+				["Healthy diet", "healthy"],
+				["Fix fat and skinny slaves", "attractive"],
+				["Curvy", 30],
+				["Average",  0],
+				["Thin", -30]
+			];
+			if (V.feeder === 1) {
+				diets.push(
+					["Feminine", "XX"],
+					["Masculine", "XY"]
+				);
+				if (V.dietXXY === 1)
+					diets.push(["Futanari", "XXY"]);
+			}
+			if (V.dietCleanse === 1)
+				diets.push(["Cleansing", "cleansing"]);
+			if (V.dietFertility === 1)
+				diets.push(["Feritlity", "fertility"]);
+			if (V.cumProDiet === 1)
+				diets.push(["Cum production", "cum production"]);
+
+			super("Slave diets", diets, true);
+			this.setValue(current_rule.set.diet);
+			this.onchange = (value) => current_rule.set.diet = value;
+		}
+	}
+
+	class DietGrowthList extends List {
+		constructor() {
+			const pairs = [
+				["On", 1],
+				["Off", 0]
+			];
+			super("Diet support for growth drugs", pairs);
+			this.setValue(current_rule.set.dietGrowthSupport);
+			this.onchange = (value) => current_rule.set.dietGrowthSupport = value;
+		}
+	}
+
+	class DietBaseList extends List {
+		constructor() {
+			// TODO: better data structure?
+			const pairs = [
+				["No default setting", {cum: "no default setting", milk: "no default setting"}],
+				["Normal Diet", {cum: 0, milk: 0}],
+				["Cum Added", {cum: 1, milk: 0}],
+				["Milk Added", {cum: 0, milk: 1}],
+				["Cum &amp; Milk Added", {cum: 1, milk: 1}],
+				["Cum-Based", {cum: 2, milk: 0}],
+				["Milk-Based", {cum: 0, milk: 2}],
+			];
+			super("Diet base", pairs);
+			this.setValue(this.value2string(current_rule.set.dietCum, current_rule.set.dietMilk));
+			this.onchange = (value) => {
+				current_rule.set.dietCum = value.cum;
+				current_rule.set.dietMilk = value.milk;
+			};
+		}
+
+		value2string(cum, milk) {
+			return `cum: ${cum}, milk: ${milk}`;
+		}
+
+		setValue(what) {
+			what = this.value2string(what.cum, what.milk);
+			super.setValue(what);
+		}
+
+	}
+
+	class MuscleList extends List {
+		constructor() {
+			const pairs = [
+				["No default setting", "no default setting"],
+				["None", 0],
+				["Toned", 20],
+				["Ripped", 50],
+				["Massive", 100],
+				["Weak", -20]
+			];
+			super("Muscles", pairs, true);
+			this.setValue(current_rule.set.muscles);
+			this.onchange = (value) => current_rule.set.muscles = value;
+		}
+	}
+
+	class BraceList extends List {
+		constructor() {
+			const pairs = [
+				["No default setting", "no default setting"],
+				["None", "none"],
+				["Straighten", "straighten"],
+				["Universal", "universal"]
+			];
+			super("Braces", pairs);
+			this.setValue(current_rule.set.teeth);
+			this.onchange = (value) => current_rule.set.teeth = value;
+		}
+	}
+
+	class LivingStandardList extends List {
+		constructor() {
+			const pairs = [
+				["No default setting", "no default setting"],
+				["Luxurious", "luxurious"],
+				["Normal", "normal"],
+				["Spare", "spare"]
+			];
+			super("Living standard", pairs);
+			this.setValue(current_rule.set.livingRules);
+			this.onchange = (value) => current_rule.set.livingRules = value;
+		}
+	}
+
+	class PunishmentList extends List {
+		constructor() {
+			const pairs = [
+				["No default setting", "no default setting"],
+				["Confinement", "confinement"],
+				["Whipping", "whipping"],
+				["Chastity", "chastity"],
+				["Situational", "situational"]
+			];
+			super("Typical punishment", pairs);
+			this.setValue(current_rule.set.standardPunishment);
+			this.onchange = (value) => current_rule.set.standardPunishment = value;
+		}
+	}
+
+	class RewardList extends List {
+		constructor() {
+			const pairs = [
+				["No default setting", "no default setting"],
+				["Relaxation", "relaxation"],
+				["Drugs", "drugs"],
+				["Orgasm", "orgasm"],
+				["Situational", "situational"]
+			];
+			super("Typical reward", pairs);
+			this.setValue(current_rule.set.standardReward);
+			this.onchange = (value) => current_rule.set.standardReward = value;
+		}
+	}
+
+	class ReleaseList extends List {
+		constructor() {
+			const pairs = [
+				["No default setting", "no default setting"],
+				["Permissive", "permissive"],
+				["Sapphic", "sapphic"],
+				["Masturbation", "masturbation"],
+				["Restritive", "restrictive"]
+			];
+			super("Release rules", pairs);
+			this.setValue(current_rule.set.releaseRules);
+			this.onchange = (value) => current_rule.set.releaseRules = value;
+		}
+	}
+
+	class SmartFetishList extends List {
+		constructor() {
+			const pairs = [
+				["No default setting", "no default setting"],
+				["Vanilla", "vanilla"],
+				["Oral", "oral"],
+				["Anal", "anal"],
+				["Boobs", "boobs"],
+				["Sub", "submissive"],
+				["Dom", "dom"],
+				["Humiliation", "humiliation"],
+				["Preg", "pregnancy"],
+				["Pain", "masochist"],
+				["Sadism", "sadist"]
+			];
+			super("Smart piercing fetish target", pairs);
+			this.setValue(current_rule.set.clitSetting);
+			this.onchange = (value) => current_rule.set.clitSetting = value;
+		}
+	}
+
+	class SmartXYAttractionList extends List {
+		constructor() {
+			const pairs = [
+				["No default setting", "no default setting"],
+				["Passionate", 100],
+				["Attracted", 75],
+				["Indifferent", 45],
+				["None", 0]
+			];
+			super("Smart piercing XY attraction target", pairs);
+			this.setValue(current_rule.set.clitSettingXY);
+			this.onchange = (value) => current_rule.set.clitSettingXY = value;
+		}
+	}
+
+	class SmartXXAttractionList extends List {
+		constructor() {
+			const pairs = [
+				["No default setting", "no default setting"],
+				["Passionate", 100],
+				["Attracted", 75],
+				["Indifferent", 45],
+				["None", 0]
+			];
+			super("Smart piercing XX attraction target", pairs);
+			this.setValue(current_rule.set.clitSettingXX);
+			this.onchange = (value) => current_rule.set.clitSettingXX = value;
+		}
+	}
+
+	class SmartEnergyList extends List {
+		constructor() {
+			const pairs = [
+				["Nympho", 100],
+				["Sex Addict", 85],
+				["Powerful", 65],
+				["Healthy", 45],
+				["Weak", 25],
+				["Frigid", 0]
+			];
+			super("Smart piercing sex drive target", pairs);
+			this.setValue(current_rule.set.clitSettingEnergy);
+			this.onchange = (value) => current_rule.set.clitSettingEnergy = value;
+		}
+	}
+
+	class SpeechList extends List {
+		constructor() {
+			const pairs = [
+				["No default setting", "no default setting"],
+				["Permissive", "permissive"],
+				["Suppress accents", "accent elimination"],
+				["Restrictive", "restrictive"]
+			];
+			super("Speech rules", pairs);
+			this.setValue(current_rule.set.speechRules);
+			this.onchange = (value) => current_rule.set.speechRules = value;
+		}
+	}
+
+	class RelationshipList extends List {
+		constructor() {
+			const pairs =[
+				["No default setting", "no default setting"],
+				["Permissive", "permissive"],
+				["Just friends", "just friends"],
+				["Restrictive", "restrictive"]
+			];
+			super("Relationship rules", pairs);
+			this.setValue(current_rule.set.relationshipRules);
+			this.onchange = (value) => current_rule.set.relationshipRules = value;
+		}
+	}
+
+	class PornList extends List {
+		constructor() {
+			const pairs = [
+				["No default setting", "no default setting"],
+				["No broadcasting", -1],
+				["No subsidy", 0],
+				["1000", 1000],
+				["2000", 2000],
+				["3000", 3000],
+				["4000", 4000],
+				["5000", 5000]
+			];
+			super("Weekly porn publicity subsidy", pairs);
+			this.setValue(current_rule.set.pornFameSpending);
+			this.onchange = (value) => current_rule.set.pornFameSpending = value;
+		}
+	}
+
+	class EyewearList extends List {
+		constructor() {
+			const pairs = [
+				["no default setting"],
+				["correct with glasses"],
+				["correct with contacts"],
+				["universal glasses"],
+				["blur with glasses"],
+				["blur with contacts"]
+			];
+			super("Eyewear", pairs);
+			this.setValue(current_rule.set.eyewear);
+			this.onchange = (value) => current_rule.set.eyewear = value;
+		}
+	}
+
+	class LensesList extends Element {
+		constructor() {
+			super(current_rule.set.eyeColor);
+			this.appendChild(new OptionsItem("No default Setting", () => this.setValue("no default setting")));
+			this.colourlist = new LensesColourList();
+			this.shapelist = new LensesShapeList();
+			this.appendChild(this.colourlist);
+			this.appendChild(this.shapelist);
+		}
+
+		render(color) {
+			const elem = document.createElement("div");
+			elem.innerHTML = "Eye coloring: ";
+			this.label = document.createElement("strong");
+			this.label.innerText = color;
+			elem.appendChild(this.label);
+			return elem;
+		}
+
+		combine() {
+			const lst = [];
+			if (this.colourlist.value !== "no default setting")
+				lst.push(this.colourlist.value);
+			if (this.shapelist.value !== "no default setting")
+				lst.push(this.shapelist.value);
+			if (lst.length === 0) return "no default value";
+			else return lst.join(" ");
+		}
+
+		setValue(val) {
+			if (val === undefined) val = this.combine();
+			this.label.innerText = val;
+			current_rule.set.eyeColor = val;
+		}
+	}
+
+	class LensesColourList extends Options {
+		constructor() {
+			const items = [];
+			[
+				"no default setting",
+				"blue",
+				"black",
+				"brown",
+				"green",
+				"turquoise",
+				"sky-blue",
+				"hazel",
+				"pale-grey",
+				"white",
+				"pink",
+				"amber",
+				"red"
+			].forEach(i => items.push(new OptionsItem(i, item => {
+				this.value = item.label;
+				this.parent.setValue();
+			})));
+			super(items);
+		}
+	}
+
+	class LensesShapeList extends Options {
+		constructor() {
+			const items = [];
+			[
+				"no default setting",
+				"catlike",
+				"serpent-like",
+				"devilish",
+				"demonic",
+				"hypnotic",
+				"heart-shaped",
+				"wide-eyed",
+				"almond-shaped",
+				"bright",
+				"teary",
+				"vacant"
+			].forEach(i => items.push(new OptionsItem(i, item => {
+				this.value = item.label;
+				this.parent.setValue();
+			})));
+			super(items);
+		}
+	}
+
+	class MakeupList extends List {
+		constructor() {
+			super("Makeup");
+			[
+				["no default setting"],
+				["makeup-free", 0],
+				["nice", 1],
+				["gorgeous", 2],
+				["color-coordinate with hair", 3],
+				["slutty", 4]
+			].forEach(pair => this.appendChild(new ListItem(...pair)));
+			this.setValue(current_rule.set.makeup);
+			this.onchange = (value) => current_rule.set.makeup = value;
+		}
+	}
+
+	class NailsList extends List {
+		constructor() {
+			super("Nails");
+			[
+				["no default setting"],
+				["clipped", 0],
+				["extended", 1],
+				["color-coordinate with hair", 2],
+				["sharp and claw-like", 3],
+				["bright and glittery", 4],
+				["hooker nails", 5]
+			].forEach(pair => this.appendChild(new ListItem(...pair)));
+			this.setValue(current_rule.set.nails);
+			this.onchange = (value) => current_rule.set.nails = value;
+		}
+	}
+
+	class HairLengthList extends List {
+		constructor() {
+			const pairs = [
+				["no default setting"],
+				["very short", 5],
+				["short", 10],
+				["shoulder length", 30],
+				["long", 60],
+				["very long", 100],
+				["floor length", 150]
+			];
+			super("Hair length", pairs);
+			this.setValue(current_rule.set.hLength);
+			this.onchange = (value) => current_rule.set.hLength = value;
+		}
+	}
+	class HairColourList extends List {
+		constructor() {
+			const pairs = [
+				["no default setting"],
+				["blonde"],
+				["golden"],
+				["platinum blonde"],
+				["strawbery-blonde"],
+				["copper"],
+				["ginger"],
+				["red"],
+				["green"],
+				["blue"],
+				["pink"],
+				["dark brown"],
+				["brown"],
+				["auburn"],
+				["burgundy"],
+				["chocolate"],
+				["chestnut"],
+				["hazel"],
+				["black"],
+				["grey"],
+				["silver"],
+				["white"],
+				["blue-violet"],
+				["blazing red"],
+				["neon green"],
+				["neon blue"],
+				["neon pink"]
+			];
+			super("Hair color", pairs);
+			this.setValue(current_rule.set.hColor);
+			this.onchange = (value) => current_rule.set.hColor = value;
+		}
+	}
+
+	class HairStyleList extends List {
+		constructor() {
+			const pairs = [
+				["no default setting"],
+				["neat"],
+				["shaved"],
+				["trimmed"],
+				["buzzcut"],
+				["up"],
+				["ponytail"],
+				["bun"],
+				["messy bun"],
+				["curled"],
+				["permed"],
+				["luxurious"],
+				["dreadlocks"],
+				["cornrows"],
+				["braided"],
+				["tails"],
+				["afro"],
+				["strip"]
+			];
+			super("Hair style", pairs);
+			this.setValue(current_rule.set.hStyle);
+			this.onchange = (value) => current_rule.set.hStyle = value;
+		}
+	}
+
+	class PubicHairColourList extends List {
+		constructor() {
+			const pairs = [
+				["no default setting"],
+				["blonde"],
+				["golden"],
+				["platinum blonde"],
+				["strawerry-blonde"],
+				["copper"],
+				["ginger"],
+				["red"],
+				["green"],
+				["blue"],
+				["pink"],
+				["dark brown"],
+				["brown"],
+				["auburn"],
+				["burgundy"],
+				["chocolate"],
+				["chestnut"],
+				["hazel"],
+				["black"],
+				["grey"],
+				["silver"],
+				["white"],
+				["blue-violet"],
+				["blazing red"],
+				["neon green"],
+				["neon blue"],
+				["neon pink"]
+			];
+			super("Pubic hair color, when present", pairs);
+			this.setValue(current_rule.set.pubicHColor);
+			this.onchange = (value) => current_rule.set.pubicHColor = value;
+		}
+	}
+
+	class PubicHairStyleList extends List {
+		constructor() {
+			const pairs = [
+				["no default setting"],
+				["waxed"],
+				["in a strip"],
+				["neat"],
+				["bushy"],
+				["bushy in the front and neat in the rear"],
+				["very bushy"]
+			];
+			super("Pubic hairstyle", pairs);
+			this.setValue(current_rule.set.pubicHStyle);
+			this.onchange = (value) => current_rule.set.pubicHStyle = value;
+		}
+	}
+
+	class ArmpitHairColourList extends List {
+		constructor() {
+			const pairs = [
+				["no default setting"],
+				["blonde"],
+				["golden"],
+				["platinum blonde"],
+				["strawberry-blonde"],
+				["copper"],
+				["ginger"],
+				["red"],
+				["green"],
+				["blue"],
+				["pink"],
+				["dark brown"],
+				["brown"],
+				["auburn"],
+				["burgundry"],
+				["chocolate"],
+				["chestnut"],
+				["hazel"],
+				["black"],
+				["grey"],
+				["silver"],
+				["white"],
+				["blue-violet"],
+			];
+			super("Underarm hair color, when present", pairs);
+			this.setValue(current_rule.set.underArmHColor);
+			this.onchange = (value) => current_rule.set.underArmHColor = value;
+		}
+	}
+
+	class ArmpitHairStyleList extends List {
+		constructor() {
+			const pairs = [
+				["no default setting"],
+				["waxed"],
+				["shaved"],
+				["neat"],
+				["bushy"]
+			];
+			super("Underarm hair style", pairs);
+			this.setValue(current_rule.set.underArmHStyle);
+			this.onchange = (value) => current_rule.set.underArmHStyle = value;
+		}
+	}
+
+	class EarPiercingList extends List {
+		constructor() {
+			const pairs = [
+				["No default setting", "no default setting"],
+				["None", 0],
+				["Light", 1],
+				["Heavy", 2]
+			];
+			super("Ear piercings", pairs);
+			this.setValue(current_rule.set.earPiercing);
+			this.onchange = (value) => current_rule.set.earPiercing = value;
+		}
+	}
+
+	class NosePiercingList extends List {
+		constructor() {
+			const pairs = [
+				["No default setting", "no default setting"],
+				["None", 0],
+				["Light", 1],
+				["Heavy", 2]
+			];
+			super("Nasal piercings", pairs);
+			this.setValue(current_rule.set.nosePiercing);
+			this.onchange = (value) => current_rule.set.earPiercing = value;
+		}
+	}
+
+	class EyebrowPiercingList extends List {
+		constructor() {
+			const pairs = [
+				["No default setting", "no default setting"],
+				["None", 0],
+				["Light", 1],
+				["Heavy", 2]
+			];
+			super("Eyebrow piercings", pairs);
+			this.setValue(current_rule.set.eyebrowPiercing);
+			this.onchange = (value) => current_rule.set.eyebrowPiercing = value;
+		}
+	}
+
+	class NavelPiercingList extends List {
+		constructor() {
+			const pairs = [
+				["No default setting", "no default setting"],
+				["None", 0],
+				["Light", 1],
+				["Heavy", 2]
+			];
+			super("Navel piercings", pairs);
+			this.setValue(current_rule.set.navelPiercing);
+			this.onchange = (value) => current_rule.set.navelPiercing = value;
+		}
+	}
+
+	class NipplePiercingList extends List {
+		constructor() {
+			const pairs = [
+				["No default setting", "no default setting"],
+				["None", 0],
+				["Light", 1],
+				["Heavy", 2]
+			];
+			super("Nipple piercings", pairs);
+			this.setValue(current_rule.set.nipplesPiercing);
+			this.onchange = (value) => current_rule.set.nipplesPiercing = value;
+		}
+	}
+
+	class AreolaPiercingList extends List {
+		constructor() {
+			const pairs = [
+				["No default setting", "no default setting"],
+				["None", 0],
+				["Studded", 1]
+			];
+			super("Areola studs", pairs);
+			this.setValue(current_rule.set.areolaePiercing);
+			this.onchange = (value) => current_rule.set.areolaePiercing = value;
+		}
+	}
+
+	class LipPiercingList extends List {
+		constructor() {
+			const pairs = [
+				["No default setting", "no default setting"],
+				["None", 0],
+				["Light", 1],
+				["Heavy", 2]
+			];
+			super("Lip piercings", pairs);
+			this.setValue(current_rule.set.lipsPiercing);
+			this.onchange = (value) => current_rule.set.lipsPiercing = value;
+		}
+	}
+
+	class TonguePiercingList extends List {
+		constructor() {
+			const pairs = [
+				["No default setting", "no default setting"],
+				["None", 0],
+				["Light", 1],
+				["Heavy", 2]
+			];
+			super("Tongue piercing", pairs);
+			this.setValue(current_rule.set.tonguePiercing);
+			this.onchange = (value) => current_rule.set.tonguePiercing = value;
+		}
+	}
+
+	class ClitPiercingList extends List {
+		constructor() {
+			const pairs = [
+				["No default setting", "no default setting"],
+				["None", 0],
+				["Light", 1],
+				["Heavy", 2],
+				["Smart (expensive)", 3]
+			];
+			super("Clit piercing", pairs);
+			this.setValue(current_rule.set.clitPiercing);
+			this.onchange = (value) => current_rule.set.clitPiercing = value;
+		}
+	}
+
+	class LabiaPiercingList extends List {
+		constructor() {
+			const pairs = [
+				["No default setting", "no default setting"],
+				["None", 0],
+				["Light", 1],
+				["Heavy", 2]
+			];
+			super("Pussylips piercings", pairs);
+			this.setValue(current_rule.set.vaginaPiercing);
+			this.onchange = (value) => current_rule.set.vaginaPiercing = value;
+		}
+	}
+
+	class ShaftPiercingList extends List {
+		constructor() {
+			const pairs = [
+				["No default setting", "no default setting"],
+				["None", 0],
+				["Light", 1],
+				["Heavy", 2]
+			];
+			super("Shaft piercings", pairs);
+			this.setValue(current_rule.set.dickPiercing);
+			this.onchange = (value) => current_rule.set.dickPiercing = value;
+		}
+	}
+
+	class PerineumPiercingList extends List {
+		constructor() {
+			const pairs = [
+				["No default setting", "no default setting"],
+				["None", 0],
+				["Light", 1],
+				["Heavy", 2]
+			];
+			super("Perianal piercings", pairs);
+			this.setValue(current_rule.set.anusPiercing);
+			this.onchange = (value) => current_rule.set.anusPiercing = value;
+		}
+	}
+
+	class CorsetPiercingList extends List {
+		constructor() {
+			const pairs = [
+				["No default setting", "no default setting"],
+				["None", 0],
+				["Apply", 1]
+			];
+			super("Corset piercings", pairs);
+			this.setValue(current_rule.set.corsetPiercing);
+			this.onchange = (value) => current_rule.set.corsetPiercing = value;
+		}
+	}
+
+	class AutoBrandingList extends List {
+		constructor() {
+			const pairs = [
+				["Activate", 1],
+				["Off", 0],
+			];
+			super("Automatic branding", pairs);
+			this.setValue(current_rule.set.autoBrand);
+			this.onchange = (value) => current_rule.set.autoBrand = value;
+		}
+	}
+
+	class BrandingLocationList extends List {
+		constructor() {
+			super("Your preferred location for brands is", []);
+
+			const ears = new ListSubSection(this, "Ears", [
+				["Left", "left ear"],
+				["Right", "right ear"],
+				["Both", "ears"]
+			]);
+			this.appendChild(ears);
+
+			const cheeks = new ListSubSection(this, "Cheeks", [
+				["Left", "left cheek"],
+				["Right", "right cheek"],
+				["Both", "cheeks"]
+			]);
+			this.appendChild(cheeks);
+
+			const shoulders = new ListSubSection(this, "Shoulders", [
+				["Left", "left shoulder"],
+				["Right", "right shoulder"],
+				["Both", "shoulders"]
+			]);
+			this.appendChild(shoulders);
+
+			const breasts = new ListSubSection(this, "Breasts", [
+				["Left", "right breast"],
+				["Right", "left breast"],
+				["Both", "breasts"]
+			]);
+			this.appendChild(breasts);
+
+			const upper_arms = new ListSubSection(this, "Arms, upper", [
+				["Left", "left upper arm"],
+				["Right", "right upper arm"],
+				["Both", "upper arms"]
+			]);
+			this.appendChild(upper_arms);
+
+			const lower_arms = new ListSubSection(this, "Arms, lower", [
+				["Left", "left lower arm"],
+				["Right", "right lower arm"],
+				["Both", "lower arms"]
+			]);
+			this.appendChild(lower_arms);
+
+			const wrist = new ListSubSection(this, "Wrist", [
+				["Left", "left wrist"],
+				["Right", "right wrist"],
+				["Both", "wrists"]
+			]);
+			this.appendChild(wrist);
+
+			const hand = new ListSubSection(this, "Hand", [
+				["Left", "left hand"],
+				["Right", "right hand"],
+				["Both", "hands"]
+			]);
+			this.appendChild(hand);
+
+			const buttocks = new ListSubSection(this, "Buttocks", [
+				["Left", "left buttock"],
+				["Right", "right buttock"],
+				["Both", "buttocks"]
+			]);
+			this.appendChild(buttocks);
+
+			const thigh = new ListSubSection(this, "Thigh", [
+				["Left", "left thigh"],
+				["Right", "right thigh"],
+				["Both", "thighs"]
+			]);
+			this.appendChild(thigh);
+
+			const calf = new ListSubSection(this, "Calf", [
+				["Left", "left calf"],
+				["Right", "right calf"],
+				["Both", "calves"]
+			]);
+			this.appendChild(calf);
+
+			const ankle = new ListSubSection(this, "Ankle", [
+				["Left", "left ankle"],
+				["Right", "right ankle"],
+				["Both", "ankles"]
+			]);
+			this.appendChild(ankle);
+
+			const feet = new ListSubSection(this, "Feet", [
+				["Left", "left foot"],
+				["Right", "right foot"],
+				["Both", "feet"]
+			]);
+			this.appendChild(feet);
+
+			const other = new ListSubSection(this, "Other", [
+				["Neck", "neck"],
+				["Chest", "chest"],
+				["Belly", "belly"],
+				["Pubic mound", "pubic mound"],
+				["Back", "back"],
+				["Lower Back", "lower back"]
+			]);
+			this.appendChild(other);
+
+			this.setValue(V.brandTarget);
+			this.onchange = (value) => V.brandTarget = value;
+		}
+	}
+
+	class BrandDesignList extends List {
+		constructor() {
+			const items = [
+				["Your  slaving emblem", "your personal symbol"],
+				["Your initials", "your initials"],
+				["SLUT"],
+				["WHORE"],
+				["SLAVE"],
+				["COW"],
+				["MEAT"],
+				["CUMDUMP"],
+				["LOVER"],
+				["Pussy symbol", "a pussy symbol"],
+				["Anus symbol", "an anus symbol"],
+				["Penis symbol", "a penis symbol"],
+				["Lady", "a lady silhouette"],
+				["Princess", "a princess silhouette"],
+				["Queen", "a queen silhouette"],
+				["Angel", "an angel silhouette"],
+				["Devil", "a devil silhouette"]
+			];
+			
+			if (V.arcologies[0].FSSupremacist !== "unset" || V.arcologies[0].FSSubjugationist !== "unset")
+				items.push(["(FS) Racial Slur", "a racial slur"]);
+			
+			if (V.arcologies[0].FSSupremacist !== "unset" && V.arcologies[0].FSSupremacistRace === "white")
+				items.push(["(FS) Swastika", "a swastika"]);
+			
+			if (V.arcologies[0].FSSubjugationist !== "unset" && V.arcologies[0].FSSubjugationistRace === "semitic")
+				items.push(["(FS) Star of David", "a Star of David"]);
+
+			if (V.arcologies[0].FSGenderRadicalist !== "unset" || V.arcologies.FSGenderFundamentalist !== "unset")
+				items.push(["(FS) Gender Symbol", "a gender symbol"]);
+
+			if (V.arcologies[0].FSPaternalist !== "unset")
+				items.push(["(FS) Personal Symbol", "her own personal symbol"]);
+
+			if (V.arcologies[0].FSDegradationist !== "unset")
+				items.push(["(FS) Chain Symbol", "a chain symbol"]);
+
+			if (V.arcologies[0].FSBodyPurist !== "unset")
+				items.push(["(FS) Vitruvian Man", "a Vitruvian man"]);
+
+			if (V.arcologies[0].FSTransformationFetishist !== "unset")
+				items.push(["(FS) Most Desired Implants", "a shortlist of desired implants"]);
+
+			if (V.arcologies[0].FSYouthPreferentialist !== "unset")
+				items.push(["(FS) Virginity Status", "her virginity status"]);
+
+			if (V.arcologies[0].FSMaturityPreferentialist !== "unset")
+				items.push(["(FS) Sexual Skill Info", "her sexual skills"]);
+
+			if (V.arcologies[0].FSSlimnessEnthusiast !== "unset")
+				items.push(["(FS) Breast Ceiling", "her absolute maximum breast size"]);
+
+			if (V.arcologies[0].FSAssetExpansionist !== "unset")
+				items.push(["(FS) Breast Floor", "her absolute minimum breast size"]);
+
+			if (V.arcologies[0].FSPastoralist !== "unset")
+				items.push(["(FS) Product Quality", "her body product quality"]);
+
+			if (V.arcologies[0].FSPhysicalIdelist !== "unset")
+				items.push(["(FS) Deadlift Info", "her deadlift record"]);
+
+			if (V.arcologies[0].FSHedonisticDecadence !== "unset")
+				items.push(["(FS) Weight Record", "her highest weigh-in"]);
+
+			if (V.arcologies[0].FSHedonisticDecadence && V.PC.refreshmentType == 2)
+				items.push(["(FS) Favorite Food", `a big helping of ${V.PC.refreshment}`]);
+
+			if (V.arcologies[0].FSRepopulationFocus !== "unset")
+				items.push(["(FS) Birth Count", "the number of children she has birthed"]);
+
+			if (V.arcologies[0].FSChattelReligionist !== "unset")
+				items.push(["(FS) Religious Symbol", "a religious symbol"]);
+
+			if (V.arcologies[0].FSRomanRevivalist !== "unset")
+				items.push(["(FS) Republican Crest", "a small crest of your Republic"]);
+
+			if (V.arcologies[0].FSAztecRevivalist !== "unset")
+				items.push(["(FS) Seven Serpents", "a small symbol of the Aztec gods"]);
+
+			if (V.arcologies[0].FSEgyptianRevivalist !== "unset")
+				items.push(["(FS) Dynastic Sigil", "a small sigil of your Dynasty"]);
+
+			if (V.arcologies[0].FSEdoRevivalist !== "unset")
+				items.push(["(FS) Mon", "a small image of the Shogunate's mon"]);
+
+			if (V.arcologies[0].FSArabianRevivalist !== "unset")
+				items.push(["(FS) Caliphate Symbol", "a small symbol of the Caliphate"]);
+
+			if (V.arcologies[0].FSChineseRevivalist !== "unset")
+				items.push(["(FS) Imperial Seal", "a small image of your Imperial Seal"]);
+			
+			super("Your brand design is", items, true);
+		}
+	}
+
+	class FaceTattooList extends List {
+		constructor() {
+			const items = [
+				["no default setting"],
+				["none", 0],
+				["tribal patterns"],
+				["flowers"],
+				["counting"],
+				["advertisements"],
+				["rude words"],
+				["degradation"],
+				["bovine patterns"],
+				["Asian art"],
+				["permanent makeup"],
+				["sacrament"],
+				["sacrilege"],
+				["possessive"],
+				["paternalist"]
+			];
+			super("Facial tattoos", items);
+			this.setValue(current_rule.set.lipsTat);
+			this.onchange = (value) => current_rule.set.lipsTat = value;
+		}
+	}
+	
+	class ShoulderTattooList extends List {
+		constructor() {
+			const items = [
+				["no default setting"],
+				["none", 0],
+				["tribal patterns"],
+				["flowers"],
+				["counting"],
+				["advertisements"],
+				["rude words"],
+				["degradation"],
+				["bovine patterns"],
+				["Asian art"],
+				["scenes"],
+				["sacrament"],
+				["sacrilege"],
+				["possessive"],
+				["paternalist"]
+			];
+			super("Shoulder tattoos", items);
+			this.setValue(current_rule.set.shouldersTat);
+			this.onchange = (value) => current_rule.set.shouldersTat = value;
+		}
+	}
+
+	class ChestTattooList extends List {
+		constructor() {
+			const items = [
+				["no default setting"],
+				["none", 0],
+				["tribal patterns"],
+				["flowers"],
+				["counting"],
+				["advertisements"],
+				["rude words"],
+				["degradation"],
+				["bovine patterns"],
+				["Asian art"],
+				["scenes"],
+				["sacrament"],
+				["sacrilege"],
+				["possessive"],
+				["paternalist"]
+			];
+			super("Chest tattoos", items);
+			this.setValue(current_rule.set.boobsTat);
+			this.onchange = (value) => current_rule.set.boobsTat = value;
+		}
+	}
+
+	class ArmTattooList extends List {
+		constructor() {
+			const items = [
+				["no default setting"],
+				["none", 0],
+				["tribal patterns"],
+				["flowers"],
+				["counting"],
+				["advertisements"],
+				["rude words"],
+				["degradation"],
+				["bovine patterns"],
+				["Asian art"],
+				["scenes"],
+				["sacrament"],
+				["sacrilege"],
+				["possessive"],
+				["paternalist"]
+			];
+			super("Arm tattoos", items);
+			this.setValue(current_rule.set.armsTat);
+			this.onchange = (value) => current_rule.set.armsTat = value;
+		}
+	}
+
+	class UpperBackTattooList extends List {
+		constructor() {
+			const items = [
+				["no default setting"],
+				["none", 0],
+				["tribal patterns"],
+				["flowers"],
+				["counting"],
+				["advertisements"],
+				["rude words"],
+				["degradation"],
+				["bovine patterns"],
+				["Asian art"],
+				["scenes"],
+				["sacrament"],
+				["sacrilege"],
+				["possessive"],
+				["paternalist"],
+			];
+			super("Upper back tattoos", items);
+			this.setValue(current_rule.set.backTat);
+			this.onchange = (value) => current_rule.set.backTat = value;
+		}
+	}
+
+	class LowerBackTattooList extends List {
+		constructor() {
+			const items = [
+				["no default setting"],
+				["none", 0],
+				["tribal patterns"],
+				["flowers"],
+				["counting"],
+				["advertisements"],
+				["rude words"],
+				["degradation"],
+				["bovine patterns"],
+				["Asian art"],
+				["scenes"],
+				["sacrament"],
+				["sacrilege"],
+				["possessive"],
+				["paternalist"]
+			];
+			super("Lower back tattoos", items);
+			this.setValue(current_rule.set.stampTat);
+			this.onchange = (value) => current_rule.set.stampTat = value;
+		}
+	}
+
+	class AbdomenTattooList extends List {
+		constructor() {
+			const items = [
+				["no default setting"],
+				["none", 0],
+				["tribal patterns"],
+				["flowers"],
+				["counting"],
+				["advertisements"],
+				["rude words"],
+				["degradation"],
+				["bovine patterns"],
+				["Asian art"],
+				["scenes"],
+				["sacrament"],
+				["sacrilege"],
+				["possessive"],
+				["paternalist"],
+			];
+			super("Abdomen tattoos", items);
+			this.setValue(current_rule.set.vaginaTat);
+			this.onchange = (value) => current_rule.set.vaginaTat = value;
+		}
+	}
+
+	class DickTattooList extends List {
+		constructor() {
+			const items = [
+				["no default setting"],
+				["none", 0],
+				["tribal patterns"],
+				["flowers"],
+				["counting"],
+				["advertisements"],
+				["rude words"],
+				["degradation"],
+				["bovine patterns"],
+				["Asian art"],
+				["sacrament"],
+				["sacrilege"],
+				["possessive"],
+				["paternalist"],
+			];
+			super("Dick tattoos", items);
+			this.setValue(current_rule.set.dickTat);
+			this.onchange = (value) => current_rule.set.dickTat = value;
+		}
+	}
+
+	class ButtockTattooList extends List {
+		constructor() {
+			const items = [
+				["no default setting"],
+				["none", 0],
+				["tribal patterns"],
+				["flowers"],
+				["counting"],
+				["advertisements"],
+				["rude words"],
+				["degradation"],
+				["bovine patterns"],
+				["Asian art"],
+				["scenes"],
+				["sacrament"],
+				["sacrilege"],
+				["possessive"],
+				["paternalist"],
+			];
+			super("Buttock tattoos:", items);
+			this.setValue(current_rule.set.buttTat);
+			this.onchange = (value) => current_rule.set.buttTat = value;
+		}
+	}
+
+	class AnalTattooList extends List {
+		constructor() {
+			const items = [
+				["no default setting"],
+				["none", 0],
+				["tribal patterns"],
+				["flowers"],
+				["counting"],
+				["advertisements"],
+				["rude words"],
+				["degradation"],
+				["bovine patterns"],
+				["bleached"],
+				["sacrament"],
+				["sacrilege"],
+				["possessive"],
+				["paternalist"],
+			];
+			super("Anal tattoo or bleaching", items);
+			this.setValue(current_rule.set.anusTat);
+			this.onchange = (value) => current_rule.set.anusTat = value;
+		}
+	}
+
+	class LegTattooList extends List {
+		constructor() {
+			const items = [
+				["no default setting"],
+				["none", 0],
+				["tribal patterns"],
+				["flowers"],
+				["counting"],
+				["advertisements"],
+				["rude words"],
+				["degradation"],
+				["bovine patterns"],
+				["Asian art"],
+				["scenes"],
+				["sacrament"],
+				["sacrilege"],
+				["possessive"],
+				["paternalist"],
+			];
+			super("Leg tattoos", items);
+			this.setValue(current_rule.set.legsTat);
+			this.onchange = (value) => current_rule.set.legsTat = value;
+		}
+	}
+
+	class VisionSurgeryList extends List {
+		constructor() {
+			const items = [
+				["no default setting"],
+				["fixed", 1],
+				["blurred", -1],
+			];
+			super("Vision correction", items);
+			this.setValue(current_rule.set.surgery_eyes);
+			this.onchange = (value) => current_rule.set.surgery_eyes = value;
+		}
+	}
+
+	class LactationSurgeryList extends List {
+		constructor() {
+			const items = [
+				["no default setting"],
+				["implanted", 1],
+				["removed", 0],
+			];
+			super("Lactation drug implants", items);
+			this.setValue(current_rule.set.surgery_lactation);
+			this.onchange = (value) => current_rule.set.surgery_lactation = value;
+		}
+	}
+
+	class SemenSurgeryList extends List {
+		constructor() {
+			const items = [
+				["no default setting"],
+				["implanted", 1],
+				["removed", 0],
+			];
+			super("Prostate production enhancing drug implants", items);
+			this.setValue(current_rule.set.surgery_prostate);
+			this.onchange = (value) => current_rule.set.surgery_prostate = value;
+		}
+	}
+
+	class CosmeticSurgeryList extends List {
+		constructor() {
+			const items = [
+				["none", 0],
+				["subtle", 1],
+				["invasive", 2],
+			];
+			super("Cosmetic Surgery", items);
+			this.setValue(current_rule.set.surgery_cosmetic);
+			this.onchange = (value) => current_rule.set.surgery_cosmetic = value;
+		}
+	}
+
+	class LipSurgeryList extends List {
+		constructor() {
+			const items = [
+				["no default setting"],
+				["removed", 0],
+				["plush", 20],
+				["big", 40],
+				["huge", 70],
+				["facepussy", 95],
+			];
+			super("Lip implants", items);
+			this.setValue(current_rule.set.surgery_lips);
+			this.onchange = (value) => current_rule.set.surgery_lips = value;
+		}
+	}
+
+	class ButtSurgeryList extends List {
+		constructor() {
+			const items = [
+				["no default setting"],
+				["removed", 0],
+				["slim", 2],
+				["stacked", 4],
+				["huge", 6],
+				["maximised", 9],
+			];
+			super("Buttock implants", items);
+			this.setValue(current_rule.set.surgery_butt);
+			this.onchange = (value) => current_rule.set.surgery_butt = value;
+		}
+	}
+
+	class BreastSurgeryList extends List {
+		constructor() {
+			const items = [
+				["no default setting"],
+				["removed", 0],
+				["slim", 400],
+				["stacked", 1000],
+				["huge", 2000],
+				["barely functional", 9000],
+				["maximised", 48000]
+			];
+			super("Breast implants", items);
+			this.setValue(current_rule.set.surgery_boobs);
+			this.onchange = (value) => current_rule.set.surgery_boobs = value;
+		}
+	}
+
+	class TighteningSurgeryList extends List {
+		constructor() {
+			const items = [
+				["no default setting"],
+				["tightening", 1],
+				["virginity restoration", 2],
+			];
+			super("Orifice Tightening", items);
+			this.setValue(current_rule.set.surgery_holes);
+			this.onchange = (value) => current_rule.set.surgery_holes = value;
+		}
+	}
+
+	class BodyHairSurgeryList extends List {
+		constructor() {
+			const items = [
+				["no default setting"],
+				["keep", 1],
+				["removal", 2],
+			];
+			super("Body Hair", items);
+			this.setValue(current_rule.set.surgery_bodyhair);
+			this.onchange = (value) => current_rule.set.surgery_bodyhair = value;
+		}
+	}
+
+	class HairSurgeryList extends List {
+		constructor() {
+			const items = [
+				["no default setting"],
+				["keep", 1],
+				["removal", 2],
+			];
+			super("Hair", items);
+			this.setValue(current_rule.set.surgery_hair);
+			this.onchange = (value) => current_rule.set.surgery_hair = value;
+		}
+	}
+
+	class AutomaticAssignmentList extends List {
+		constructor() {
+			const items = [
+				["No default setting", "no default setting"],
+				["Rest", "rest"],
+				["Fucktoy", "please you"],
+				["Subordinate Slave", "be a subordinate slave"],
+				["House Servant", "be a servant"],
+				["Confined", "stay confined"],
+				["Whore", "whore"],
+				["Public Servant", "serve the public"],
+				["Classes", "take classes"],
+				["Milked", "get milked"],
+				["Gloryhole", "work a glory hole"]
+			];
+			
+			if (V.HGSuite > 0) items.push(["Head Girl Suite", "live with your Head Girl"]);
+			if (V.brothel > 0) items.push(["Brothel", "work in the brothel"]);
+			if (V.club > 0) items.push(["Club", "serve in the club"]);
+			if (V.arcade > 0) items.push(["Arcade", "be confined in the arcade"]);
+			if (V.dairy > 0) items.push(["Dairy", "work in the dairy"]);
+			if (V.servantQuarters > 0) items.push(["Servant Quarters", "work as a servant"]);
+			if (V.masterSuite > 0) items.push(["Master Suite", "serve in the master suite"]);
+			if (V.schoolroom > 0) items.push(["Schoolroom", "learn in the schoolroom"]);
+			if (V.spa > 0) items.push(["Spa", "rest in the spa"]);
+			if (V.clinic > 0) items.push(["Clinic", "get treatment in the clinic"]);
+			if (V.cellblock > 0) items.push(["Cellblock", "be confined in the cellblock"]);
+			
+			super("Automatically set assignment", items);
+			this.setValue(current_rule.set.setAssignment);
+			this.onchange = (value) => current_rule.set.setAssignment = value;
+		}
+	}
+	
+	return rulesAssistantOptions;
+})();
+
+/*:: rules autosurgery js [script]*/
+
+window.rulesAutosurgery = (function() {
+	"use strict";
+	let V;
+	let r = "";
+	return rulesAutoSurgery;
+
+	function rulesAutoSurgery(slave) {
+		V = State.variables;
+		const surgeries = [];
+		const thisSurgery = ProcessHGTastes(slave);
+		if (slave.health > 20)
+			CommitSurgery(slave, thisSurgery, surgeries);
+		if (surgeries.length > 0)
+			PrintResult(slave, thisSurgery, surgeries);
+		return r
+	}
+	
+	function autoSurgerySelector(slave, ruleset) {
+		const apply = ruleset.filter(rule => rule.set.autoSurgery == 1 && slave.currentRules.contains(rule.ID));
+
+		const surgery = {
+			surgery_eyes: "no default setting",
+			surgery_lactation: "no default setting",
+			surgery_cosmetic: "no default setting",
+			surgery_accent: "no default setting",
+			surgery_shoulders: "no default setting",
+			surgery_shouldersImplant: "no default setting",
+			surgery_boobs: "no default setting",
+			surgery_hips: "no default setting",
+			surgery_hipsImplant: "no default setting",
+			surgery_butt: "no default setting",
+			surgery_faceShape: "no default setting",
+			surgery_lips: "no default setting",
+			surgery_holes: "no default setting",
+			surgery_bodyhair: "no default setting",
+			surgery_hair: "no default setting",
+			surgery_bellyImplant: "no default setting"
+		};
+		apply.forEach(rule => {
+			Object.keys(surgery).forEach(key => {
+				if (rule[key] !== "no default setting")
+					surgery[key] = rule[key];
+			})
+		});
+		return surgery;
+	}
+
+	function ProcessHGTastes(slave) {
+		let thisSurgery;
+		switch (V.HGTastes) {
+		case 1:
+			thisSurgery = {
+				surgery_lactation: 0,
+				surgery_cosmetic: 1,
+				surgery_faceShape: "cute",
+				surgery_lips: 10,
+				surgery_hips: 0,
+				surgery_hipsImplant: 0,
+				surgery_butt: 0,
+				surgery_accent: 0,
+				surgery_shoulders: 0,
+				surgery_shouldersImplant: 0,
+				surgery_boobs: 0,
+				surgery_holes: 0
+			};
+			break ;
+		case 2:
+			thisSurgery = {
+				surgery_lactation: 0,
+				surgery_cosmetic: 1,
+				surgery_faceShape: "cute",
+				surgery_lips: 60,
+				surgery_hips: 0,
+				surgery_hipsImplant: 0,
+				surgery_butt: 4,
+				surgery_accent: 0,
+				surgery_shoulders: 0,
+				surgery_shouldersImplant: 0,
+				surgery_boobs: 1200,
+				surgery_holes: 0
+			};
+			break;
+		case 3:
+			thisSurgery = {
+				surgery_lactation: 0,
+				surgery_cosmetic: 1,
+				surgery_faceShape: "cute",
+				surgery_lips: 95,
+				surgery_hips: 0,
+				surgery_hipsImplant: 0,
+				surgery_butt: 8,
+				surgery_accent: 0,
+				surgery_shoulders: 0,
+				surgery_shouldersImplant: 0,
+				surgery_boobs: 10000,
+				surgery_holes: 2
+			};
+			break;
+		case 4:
+			thisSurgery = {
+				surgery_lactation: 1,
+				surgery_cosmetic: 1,
+				surgery_faceShape: "cute",
+				surgery_lips: 10,
+				surgery_hips: 3,
+				surgery_hipsImplant: 0,
+				surgery_butt: 0,
+				surgery_accent: 0,
+				surgery_shoulders: 0,
+				surgery_shouldersImplant: 0,
+				surgery_boobs: 0,
+				surgery_holes: 0
+			};
+			break;
+		default:
+			thisSurgery = autoSurgerySelector(slave, V.defaultRules);
+			if ((thisSurgery.surgery_hips !== "no default setting") && (thisSurgery.surgery_butt !== "no default setting")) {
+				if (slave.hips < -1) {
+					if (thisSurgery.surgery_butt > 2)
+						thisSurgery.surgery_butt = 2;
+				} else if (slave.hips < 0) {
+					if (thisSurgery.surgery_butt > 4)
+						thisSurgery.surgery_butt = 4;
+				} else if (slave.hips > 0) {
+					if (thisSurgery.surgery_butt > 8)
+						thisSurgery.surgery_butt = 8;
+				} else if (slave.hips > 1) {
+					true;
+				} else {
+					if (thisSurgery.surgery_butt > 6)
+						thisSurgery.surgery_butt = 6;
+				}
+			};
+			break;
+		}
+		return thisSurgery;
+	}
+
+	function CommitSurgery(slave, thisSurgery, surgeries) {
+		if ((slave.eyes == -1) && (thisSurgery.eyes == 1)) {
+			surgeries.push("surgery to correct her vision");
+			slave.eyes = 1;
+			V.cash -= V.surgeryCost;
+			if (V.PC.medicine >= 100) slave.health -= 5;
+			else slave.health -= 10;
+			
+		} else if ((slave.eyes == 1) && (thisSurgery.eyes == -1)) {
+			surgeries.push("surgery to blur her vision");
+			slave.eyes = -1;
+			V.cash -= V.surgeryCost;
+			if (V.PC.medicine >= 100) slave.health -= 5;
+			else slave.health -= 10;
+			
+		} else if ((slave.lactation == 2) && (thisSurgery.lactation == 0)) {
+			surgeries.push("surgery to remove her lactation implants");
+			slave.lactation = 0;
+			V.cash -= V.surgeryCost;
+			if (V.PC.medicine >= 100) slave.health -= 5;
+			else slave.health -= 10;
+			
+		} else if (slave.lactation != 2 && (thisSurgery.lactation == 1)) {
+			surgeries.push("lactation inducing implanted drugs");
+			slave.lactation = 2;
+			V.cash -= V.surgeryCost;
+			if (V.PC.medicine >= 100) slave.health -= 5;
+			else slave.health -= 10;
+			
+		} else if ((slave.prostate == 2) && (thisSurgery.prostate == 0)) {
+			surgeries.push("surgery to remove her prostate implant");
+			slave.prostate = 0;
+			V.cash -= V.surgeryCost;
+			if (V.PC.medicine >= 100) slave.health -= 5;
+			else slave.health -= 10;
+			
+		} else if (slave.prostate == 1 && (thisSurgery.prostate == 1)) {
+			surgeries.push("a precum production enhancing drug implant");
+			slave.prostate = 2;
+			V.cash -= V.surgeryCost;
+			if (V.PC.medicine >= 100) slave.health -= 5;
+			else slave.health -= 10;
+			
+		} else if ((slave.anus > 3) && (thisSurgery.cosmetic > 0)) {
+			surgeries.push("a restored anus");
+			slave.anus = 3;
+			if (slave.analSkill > 10)
+				slave.analSkill -= 10;
+			V.cash -= V.surgeryCost;
+			if (V.PC.medicine >= 100) slave.health -= 5;
+			else slave.health -= 10;
+			
+		} else if ((slave.vagina > 3) && (thisSurgery.cosmetic > 0)) {
+			surgeries.push("a restored pussy");
+			slave.vagina = 3;
+			if (slave.vaginalSkill > 10)
+				slave.vaginalSkill -= 10;
+			V.cash -= V.surgeryCost;
+			if (V.PC.medicine >= 100) slave.health -= 5;
+			else slave.health -= 10;
+			
+		} else if ((slave.faceImplant <= 15) && (slave.face <= 95) && (thisSurgery.cosmetic > 0)) {
+			surgeries.push("a nicer face");
+			if (slave.faceShape == "masculine") {slave.faceShape = "androgynous"};
+			slave.faceImplant += 25-5*Math.trunc(V.PC.medicine/50)-5*V.surgeryUpgrade;
+			slave.face = Math.clamp(slave.face+20,-100,100);
+			V.cash -= V.surgeryCost;
+			if (V.PC.medicine >= 100) slave.health -= 5;
+			else slave.health -= 10;
+			
+		} else if ((slave.faceImplant <= 15) && (slave.ageImplant != 1) && (slave.visualAge >= 25) && (thisSurgery.cosmetic > 0)) {
+			surgeries.push("an age lift");
+			slave.ageImplant = 1;
+			slave.faceImplant += 25-5*Math.trunc(V.PC.medicine/50)-5*V.surgeryUpgrade;
+			if (slave.visualAge > 80) slave.visualAge -= 40;
+			else if (slave.visualAge >= 70) slave.visualAge -= 30;
+			else if (slave.visualAge > 50) slave.visualAge -= 20;
+			else if (slave.visualAge > 36) slave.visualAge -= 10;
+			else slave.visualAge -= 5;
+			V.cash -= V.surgeryCost;
+			if (V.PC.medicine >= 100) slave.health -= 5;
+			else slave.health -= 10;
+			
+		} else if (((slave.underArmHStyle != "bald" && slave.underArmHStyle != "hairless") || (slave.pubicHStyle != "bald" && slave.pubicHStyle != "hairless")) && (thisSurgery.bodyhair == 2)) {
+			surgeries.push("body hair removal");
+			if (slave.underArmHStyle != "hairless") {slave.underArmHStyle = "bald"};
+			if (slave.pubicHStyle != "hairless") {slave.pubicHStyle = "bald"};
+			V.cash -= V.surgeryCost;
+			
+		} else if ((slave.bald == 0 || slave.hStyle != "bald") && (thisSurgery.hair == 2)) {
+			surgeries.push("hair removal");
+			slave.hStyle = "bald";
+			slave.bald = 1;
+			V.cash -= V.surgeryCost;
+			
+		} else if ((slave.weight >= 10) && (thisSurgery.cosmetic > 0)) {
+			surgeries.push("liposuction");
+			slave.weight -= 50;
+			V.cash -= V.surgeryCost;
+			if (V.PC.medicine >= 100) slave.health -= 5;
+			else slave.health -= 10;
+			
+		} else if ((slave.voice == 1) && (slave.voiceImplant == 0) && (thisSurgery.cosmetic > 0)) {
+			surgeries.push("a feminine voice");
+			slave.voice += 1;
+			slave.voiceImplant += 1;
+			V.cash -= V.surgeryCost;
+			if (V.PC.medicine >= 100) slave.health -= 5;
+			else slave.health -= 10;
+			
+		} else if ((slave.waist >= -10) && (thisSurgery.cosmetic > 0)) {
+			surgeries.push("a narrower waist");
+			slave.waist -= 20;
+			V.cash -= V.surgeryCost;
+			if (V.PC.medicine >= 100) slave.health -= 5;
+			else slave.health -= 10;
+			
+		} else if (((slave.boobShape == "saggy") || (slave.boobShape == "downward-facing")) && (thisSurgery.cosmetic > 0) && (slave.breastMesh != 1)) {
+			surgeries.push("a breast lift");
+			slave.boobShape = "normal";
+			V.cash -= V.surgeryCost;
+			if (V.PC.medicine >= 100) slave.health -= 5;
+			else slave.health -= 10;
+			
+		} else if (((slave.boobShape == "normal") || (slave.boobShape == "wide-set")) && (thisSurgery.cosmetic > 0) && (slave.breastMesh != 1)) {
+			if (slave.boobs > 800)
+				slave.boobShape = "torpedo-shaped";
+			else
+				slave.boobShape = "perky";
+			surgeries.push("more interestingly shaped breasts");
+			V.cash -= V.surgeryCost;
+			if (V.PC.medicine >= 100) slave.health -= 5;
+			else slave.health -= 10;
+			
+		} else if ((thisSurgery.lips == 0) && (slave.lipsImplant > 0)) {
+			surgeries.push("surgery to remove her lip implants");
+			slave.lips -= slave.lipsImplant;
+			slave.lipsImplant = 0;
+			if (slave.oralSkill > 10)
+				slave.oralSkill -= 10;
+			V.cash -= V.surgeryCost;
+			if (V.PC.medicine >= 100) slave.health -= 5;
+			else slave.health -= 10;
+			
+		} else if ((slave.lips <= 95) && (slave.lips < thisSurgery.lips)) {
+			if (thisSurgery.lips !== "no default setting") {
+				surgeries.push("bigger lips");
+				slave.lipsImplant += 10;
+				slave.lips += 10;
+				if (slave.oralSkill > 10)
+					slave.oralSkill -= 10;
+				V.cash -= V.surgeryCost;
+				if (V.PC.medicine >= 100) slave.health -= 5;
+				else slave.health -= 10;
+			}
+			
+		} else if ((slave.faceImplant <= 45) && (slave.face <= 95) && (thisSurgery.cosmetic == 2)) {
+			surgeries.push("a nicer face");
+			if (slave.faceShape == "masculine") slave.faceShape = "androgynous";
+			slave.faceImplant += 25-5*Math.trunc(V.PC.medicine/50)-5*V.surgeryUpgrade;
+			slave.face = Math.clamp(slave.face+20,-100,100);
+			V.cash -= V.surgeryCost;
+			if (V.PC.medicine >= 100) slave.health -= 5;
+			else slave.health -= 10;
+			
+		} else if ((slave.hips < 1) && (slave.hips < thisSurgery.hips) && (V.surgeryUpgrade == 1)) {
+			surgeries.push("wider hips");
+			slave.hips++;
+			slave.hipsImplant++;
+			V.cash -= V.surgeryCost;
+			if (V.PC.medicine >= 100) slave.health -= 5;
+			else slave.health -= 10;
+			
+		} else if ((slave.faceImplant <= 45) && (slave.ageImplant != 1) && (slave.visualAge >= 25) && (thisSurgery.cosmetic == 2)) {
+			surgeries.push("an age lift");
+			slave.ageImplant = 1;
+			if (slave.visualAge > 80) {
+				slave.visualAge -= 40;
+			} else if (slave.visualAge >= 70) {
+				slave.visualAge -= 30;
+			} else if (slave.visualAge > 50) {
+				slave.visualAge -= 20;
+			} else if (slave.visualAge > 36) {
+				slave.visualAge -= 10;
+			} else {
+				slave.visualAge -= 5;
+			}
+			slave.faceImplant += 25-5*Math.trunc(V.PC.medicine/50)-5*V.surgeryUpgrade;
+			V.cash -= V.surgeryCost;
+			if (V.PC.medicine >= 100) slave.health -= 5;
+			else slave.health -= 10;
+			
+		} else if ((slave.waist >= -95) && (thisSurgery.cosmetic == 2) && (V.seeExtreme == 1)) {
+			surgeries.push("a narrower waist");
+			slave.waist = Math.clamp(slave.waist-20,-100,100);
+			V.cash -= V.surgeryCost;
+			if (V.PC.medicine >= 100) slave.health -= 5;
+			else slave.health -= 10;
+			
+		} else if ((slave.voice < 3) && (slave.voiceImplant == 0) && (thisSurgery.cosmetic == 2)) {
+			surgeries.push("a bimbo's voice");
+			slave.voice += 1;
+			slave.voiceImplant += 1;
+			V.cash -= V.surgeryCost;
+			if (V.PC.medicine >= 100) slave.health -= 5;
+			else slave.health -= 10;
+			
+		} else if ((thisSurgery.butt == 0) && (slave.buttImplant > 0)) {
+			surgeries.push("surgery to remove her butt implants");
+			slave.butt -= slave.buttImplant;
+			slave.buttImplant = 0;
+			slave.buttImplantType = 0;
+			V.cash -= V.surgeryCost;
+			if (V.PC.medicine >= 100) slave.health -= 5;
+			else slave.health -= 10;
+			
+		} else if ((thisSurgery.boobs == 0) && (slave.boobsImplant > 0)) {
+			surgeries.push("surgery to remove her boob implants");
+			slave.boobs -= slave.boobsImplant;
+			slave.boobsImplant = 0;
+			slave.boobsImplantType = 0;
+			V.cash -= V.surgeryCost;
+			if (V.PC.medicine >= 100) slave.health -= 5;
+			else slave.health -= 10;
+		} else if ((slave.butt <= 3) && (slave.butt < thisSurgery.butt)) {
+			if (thisSurgery.butt !== "no default setting") {
+				surgeries.push("a bigger butt");
+				slave.buttImplant = 1;
+				slave.butt += 1;
+				V.cash -= V.surgeryCost;
+				if (V.PC.medicine >= 100) slave.health -= 5;
+				else slave.health -= 10;
+			}
+		} else if ((slave.boobs <= 600) && (slave.lactation < 2) && (slave.boobs+400 <= thisSurgery.boobs)) {
+			if (thisSurgery.boobs !== "no default setting") {
+				surgeries.push("bigger boobs");
+				slave.boobsImplant += 400;
+				slave.boobs += 400;
+				V.cash -= V.surgeryCost;
+				if (V.PC.medicine >= 100) slave.health -= 5;
+				else slave.health -= 10;
+			}
+		} else if ((slave.boobs <= 600) && (slave.lactation < 2) && (slave.boobs+200 <= thisSurgery.boobs)) {
+			if (thisSurgery.boobs !== "no default setting") {
+				surgeries.push("modestly bigger boobs");
+				slave.boobsImplant += 200;
+				slave.boobs += 200;
+				V.cash -= V.surgeryCost;
+				if (V.PC.medicine >= 100) slave.health -= 5;
+				else slave.health -= 10;
+			}
+			
+		} else if ((slave.butt <= 5) && (slave.butt < thisSurgery.butt)) {
+			if (thisSurgery.butt !== "no default setting") {
+				surgeries.push("a bigger butt");
+				slave.buttImplant = 1;
+				slave.butt += 1;
+				V.cash -= V.surgeryCost;
+				if (V.PC.medicine >= 100) slave.health -= 5;
+				else slave.health -= 10;
+			}
+			
+		} else if ((slave.boobs <= 2000) && (slave.lactation < 2) && (slave.boobs+400 < thisSurgery.boobs)) {
+			if (thisSurgery.boobs !== "no default setting") {
+				surgeries.push("bigger boobs");
+				slave.boobsImplant += 400;
+				slave.boobs += 400;
+				V.cash -= V.surgeryCost;
+				if (V.PC.medicine >= 100) slave.health -= 5;
+				else slave.health -= 10;
+			}
+			
+		} else if ((slave.anus > 0) && (V.surgeryUpgrade == 1) && (thisSurgery.holes == 2)) {
+			surgeries.push("a virgin anus");
+			slave.anus = 0;
+			if (slave.analSkill > 10) {
+				slave.analSkill -= 10;
+			}
+			V.cash -= V.surgeryCost;
+			if (V.PC.medicine >= 100) slave.health -= 5;
+			else slave.health -= 10;
+			
+		} else if ((slave.vagina > 0) && (V.surgeryUpgrade == 1) && (thisSurgery.holes == 2)) {
+			surgeries.push("a virgin pussy");
+			slave.vagina = 0;
+			if (slave.vaginalSkill > 10)
+				slave.vaginalSkill -= 10;
+			V.cash -= V.surgeryCost;
+			if (V.PC.medicine >= 100) slave.health -= 5;
+			else slave.health -= 10;
+			
+		} else if ((slave.hips < 2) && (slave.hips < thisSurgery.hips) && (V.surgeryUpgrade == 1)) {
+			surgeries.push("wider hips");
+			slave.hips++;
+			slave.hipsImplant++;
+			V.cash -= V.surgeryCost;
+			if (V.PC.medicine >= 100) slave.health -= 5;
+			else slave.health -= 10;
+			
+		} else if ((slave.anus > 1) && (thisSurgery.holes == 1)) {
+			surgeries.push("a tighter anus");
+			slave.anus = 1;
+			if (slave.analSkill > 10) {
+				slave.analSkill -= 10;
+			}
+			V.cash -= V.surgeryCost;
+			if (V.PC.medicine >= 100) slave.health -= 5;
+			else slave.health -= 10;
+			
+		} else if ((slave.vagina > 1) && (thisSurgery.holes == 1)) {
+			surgeries.push("a tighter pussy");
+			slave.vagina = 1;
+			if (slave.vaginalSkill > 10) {
+				slave.vaginalSkill -= 10;
+			}
+			V.cash -= V.surgeryCost;
+			if (V.PC.medicine >= 100) slave.health -= 5;
+			else slave.health -= 10;
+			
+		} else if ((slave.butt <= 8) && (slave.butt < thisSurgery.butt)) {
+			if (thisSurgery.butt !== "no default setting") {
+				surgeries.push("a bigger butt");
+				slave.buttImplant = 1;
+				slave.butt += 1;
+				V.cash -= V.surgeryCost;
+				if (V.PC.medicine >= 100) slave.health -= 5;
+				else slave.health -= 10;
+			}
+			
+		} else if ((slave.boobs <= 9000) && (slave.lactation < 2) && (slave.boobs < thisSurgery.boobs)) {
+			if (thisSurgery.boobs !== "no default setting") {
+				surgeries.push("bigger boobs");
+				slave.boobsImplant += 200;
+				slave.boobs += 200;
+				V.cash -= V.surgeryCost;
+				if (V.PC.medicine >= 100) slave.health -= 5;
+				else slave.health -= 10;
+			}
+			
+		} else if ((slave.hips < 3) && (slave.hips < thisSurgery.hips) && (V.surgeryUpgrade == 1)) {
+			surgeries.push("wider hips");
+			slave.hips++;
+			slave.hipsImplant++;
+			V.cash -= V.surgeryCost;
+			if (V.PC.medicine >= 100) slave.health -= 5;
+			else slave.health -= 10;
+			
+		} else if (slave.bellyImplant < 0 && V.bellyImplants > 0 && thisSurgery.bellyImplant == "install" && slave.womb.length == 0 && slave.broodmother == 0) {
+			slave.bellyImplant = 100;
+			slave.preg = -2;
+			V.cash -= V.surgeryCost;
+			if (V.activeSlave.ovaries == 1 || V.activeSlave.mpreg == 1) {
+				surgeries.push("belly implant");
+				V.surgeryType = "bellyIn";
+				if (V.PC.medicine >= 100) slave.health -= 5;
+				else slave.health -= 10;
+			} else {
+				surgeries.push("male belly implant");
+				V.surgeryType = "bellyInMale";
+				if (V.PC.medicine >= 100) slave.health -= 25;
+				else slave.health -= 50;
+			}
+			bellyIn(slave);
+			
+		} else if (slave.bellyImplant >= 0 && thisSurgery.bellyImplant == "remove") {
+			surgeries.push("belly implant removal");
+			V.surgeryType = "bellyOut";
+			if (V.PC.medicine >= 100)
+				slave.health -= 5;
+			else
+				slave.health -= 10;
+			slave.preg = 0;
+			slave.bellyImplant = -1;
+			V.cash -= V.surgeryCost;
+		}
+	}
+
+	function PrintResult(slave, thisSurgery, surgeries) {
+		let surgeriesDisplay = "";
+		if (surgeries.length === 1)
+			surgeriesDisplay = surgeries[0];
+		else {
+			surgeriesDisplay = surgeries.slice(0, surgeries.length - 1).join(", ");
+			surgeriesDisplay += ", and" + surgeries[surgeries.length - 1];
+		}
+		r += `${V.assistantName === "your personal assistant" ? "Your personal assistant" : V.assistantName}, ordered to apply surgery, gives ${slave.slaveName} <span class="lime">${surgeriesDisplay}.</span>`;
+	}
+
+	function bellyIn(slave) {
+		// less hacky version of calling surgery degradation silently
+		if (slave.devotion > 50)
+			slave.devotion += 4;
+		else if (slave.devotion >= -20)
+			slave.trust -= 5;
+		else {
+			slave.trust -= 5;
+			slave.devotion -= 5;
+		}
+	}
+})();
\ No newline at end of file
diff --git a/src/pregmod/widgets/bodySwapReaction.tw b/src/pregmod/widgets/bodySwapReaction.tw
index ff06ce7499e..7a53d2f4476 100644
--- a/src/pregmod/widgets/bodySwapReaction.tw
+++ b/src/pregmod/widgets/bodySwapReaction.tw
@@ -1150,7 +1150,7 @@ Now you only have to wait for her to wake up.
 				<</if>>
 			<</if>>
 			<<set _weightChange = 1>>
-		<<elseif $args[0].bellyImplant < $args[1].bellyImplant>> /*(belly implant filled*/
+		<<elseif $args[0].bellyImplant < $args[1].bellyImplant>> /*belly implant reduced*/
 			<br><br>
 			Her hands drift over her stomach, where she
 			<<if $args[0].bellyImplant >= 450000>>
@@ -1166,7 +1166,7 @@ Now you only have to wait for her to wake up.
 			<<elseif $args[0].bellyImplant >= 100>>
 				feels a @@.pink;slight swell to her stomach.@@
 			<<else>>
-				discovers
+				finds @@.pink;no signs of an implant swollen belly.@@
 			<</if>>
 			<<if $args[0].devotion >= 20>>
 				She appreciates how much easier it will be with a smaller middle.
@@ -2600,7 +2600,7 @@ Now you only have to wait for her to wake up.
 				<</if>>
 			<</if>>
 			<<set _weightChange = 1>>
-		<<elseif $args[0].bellyImplant < $args[1].bellyImplant>> /*(belly implant filled*/
+		<<elseif $args[0].bellyImplant < $args[1].bellyImplant>> /*belly implant reduced*/
 			<br><br>
 			She wiggles into a better position to view her stomach, where she
 			<<if $args[0].bellyImplant >= 450000>>
diff --git a/src/pregmod/widgets/seBirthWidgets.tw b/src/pregmod/widgets/seBirthWidgets.tw
index d9183ef7a07..91f876f50ce 100644
--- a/src/pregmod/widgets/seBirthWidgets.tw
+++ b/src/pregmod/widgets/seBirthWidgets.tw
@@ -381,6 +381,8 @@ This decriptions can be expanded with more outcomes later. But it's not practica
 			, but $possessive stomach barely shrank at all. $possessiveCap body gave life to
 		<<elseif $diffSize < 1.3>>
 			, but $possessive overfilled womb barely lost any size. $possessiveCap body gave life to
+		<<else>>
+			to
 		<</if>>
 	<</if>>
 
diff --git a/src/uncategorized/longSlaveDescription.tw b/src/uncategorized/longSlaveDescription.tw
index 1220bac2e2e..da6ddb620eb 100644
--- a/src/uncategorized/longSlaveDescription.tw
+++ b/src/uncategorized/longSlaveDescription.tw
@@ -1561,7 +1561,7 @@ when a dick is pushed inside <<if $activeSlave.vagina >= -1>>either of its lower
 	<<elseif $activeSlave.whoreSkill <= 60>>
 		<<if $activeSlave.entertainSkill <= 10>>$He is <</if>>a @@.aquamarine;skilled streetwalker.@@
 	<<elseif $activeSlave.whoreSkill < 100>>
-		<<if $activeSlave.entertainSkill <= 10>>$He is <</if>>a @@.aquamarine;expert working girl.@@
+		<<if $activeSlave.entertainSkill <= 10>>$He is <</if>>an @@.aquamarine;expert working girl.@@
 	<<else>>
 		<<if $activeSlave.entertainSkill <= 10>>$He is <</if>>a @@.aquamarine;masterful whore.@@
 	<</if>>
diff --git a/src/uncategorized/newSlaveIntro.tw b/src/uncategorized/newSlaveIntro.tw
index 3aff8989f08..d9e34e9b2ef 100644
--- a/src/uncategorized/newSlaveIntro.tw
+++ b/src/uncategorized/newSlaveIntro.tw
@@ -871,7 +871,7 @@ The legalities completed, ''__@@.pink;<<SlaveFullName $activeSlave>>@@__'' <<if
 	<br>&nbsp;&nbsp;&nbsp;&nbsp;
 	<<link "Use her big sister as an example">>
 		<<replace "#introResult">>
-			Your new slave appears <<if $activeSlave.devotion < -10>>reluctant to assume her new duties.<<else>>unsure what her new duties are.<</if>> You gesture towards $eventSlave.slaveName. She is <<if $eventSlave.intelligence > 0>>bright enough<<elseif (($eventSlave.vaginalSkill + $eventSlave.analSkill + $eventSlave.oralSkill) > 100)>>skilled enough<<else>>obedient enough<</if>> to understand you mean a demonstration is in order. $eventSlave.slaveName starts things off with a <<if $eventSlave.entertainSkill >= 100>>masterful<<elseif $eventSlave.entertainSkill > 10>>skillful<<else>>passable<</if>> striptease, culminating in <<if ($eventSlave.anus > 0) && ($eventSlave.fetish != "cumslut")>>bending over<<else>>kneeling<</if>> in front of you. She eagerly moans as you enter her, begging for your seed<<if $eventSlave.energy > 95>> like the slut she is<<elseif $eventSlave.whoreSkill > 30>> like the whore she is<<elseif ($eventSlave.assignment == "serve in the master suite") || ($eventSlave.assignment == "please you")>> like the fucktoy she is<</if>>. As you finish, she <<if $eventSlave.fetish == "cumslut">>opens her mouth and savors your gift, thanking you once she's swallowed enough to be able to talk again.<<elseif ($eventSlave.fetish == "buttslut") || ($eventSlave.fetish == "submissive")>>collapses on the floor with her ass high in the air, thanking you for painting her hole white.<<else>>thanks you.<</if>> Witnessing this display of servitude from her big sister @@.hotpink;eases $activeSlave.slaveName into her new life,@@ and @@.mediumaquamarine;gives her hope@@ she can find a place here.
+			Your new slave appears <<if $activeSlave.devotion < -10>>reluctant to assume her new duties.<<else>>unsure what her new duties are.<</if>> You gesture towards $eventSlave.slaveName. She is <<if $eventSlave.intelligence > 0>>bright enough<<elseif (($eventSlave.vaginalSkill + $eventSlave.analSkill + $eventSlave.oralSkill) > 100)>>skilled enough<<else>>obedient enough<</if>> to understand you mean a demonstration is in order. $eventSlave.slaveName starts things off with a <<if $eventSlave.entertainSkill >= 100>>masterful<<elseif $eventSlave.entertainSkill > 10>>skillful<<else>>passable<</if>> striptease, culminating in<<if ($eventSlave.anus > 0) && ($eventSlave.fetish != "cumslut")>>bending over<<else>>kneeling<</if>> in front of you. She eagerly moans as you enter her, begging for your seed<<if $eventSlave.energy > 95>> like the slut she is<<elseif $eventSlave.whoreSkill > 30>> like the whore she is<<elseif ($eventSlave.assignment == "serve in the master suite") || ($eventSlave.assignment == "please you")>> like the fucktoy she is<</if>>. As you finish, she <<if $eventSlave.fetish == "cumslut">>opens her mouth and savors your gift, thanking you once she's swallowed enough to be able to talk again.<<elseif ($eventSlave.fetish == "buttslut") || ($eventSlave.fetish == "submissive")>>collapses on the floor with her ass high in the air, thanking you for painting her hole white.<<else>>thanks you.<</if>> Witnessing this display of servitude from her big sister @@.hotpink;eases $activeSlave.slaveName into her new life,@@ and @@.mediumaquamarine;gives her hope@@ she can find a place here.
 		<</replace>>
 		<<set $activeSlave.devotion += 4>>
 		<<set $activeSlave.trust += 4>>
@@ -919,7 +919,7 @@ The legalities completed, ''__@@.pink;<<SlaveFullName $activeSlave>>@@__'' <<if
 	<br>&nbsp;&nbsp;&nbsp;&nbsp;
 	<<link "Use her parent as an example">>
 		<<replace "#introResult">>
-			You gesture towards $eventSlave.slaveName. She is <<if $eventSlave.intelligence > 0>>bright enough<<elseif (($eventSlave.vaginalSkill + $eventSlave.analSkill + $eventSlave.oralSkill) > 100)>>skilled enough<<else>>obedient enough<</if>> to understand you mean a demonstration is in order. $eventSlave.slaveName starts things off with a <<if $eventSlave.entertainSkill >= 100>>masterful<<elseif $eventSlave.entertainSkill > 10>>skillful<<else>>passable<</if>> striptease, culminating in <<if ($eventSlave.anus > 0) && ($eventSlave.fetish != "cumslut")>>bending over<<else>>kneeling<</if>> in front of you. She eagerly moans as you enter her, begging for your seed<<if $eventSlave.energy > 95>> like the slut she is<<elseif $eventSlave.whoreSkill > 30>> like the whore she is<<elseif ($eventSlave.assignment == "serve in the master suite") || ($eventSlave.assignment == "please you")>> like the fucktoy she is<</if>>. As you finish, she<<if $eventSlave.fetish == "cumslut">>opens her mouth and savors your gift, thanking you once she's swallowed enough to be able to talk again.<<elseif ($eventSlave.fetish == "buttslut") || ($eventSlave.fetish == "submissive")>>collapses on the floor with her ass high in the air, thanking you for painting her hole white.<<else>>thanks you.<</if>> Witnessing this display of servitude from her <<if $activeSlave.mother == $eventSlave.ID>>mother<<else>>father<</if>> @@.hotpink;eases $activeSlave.slaveName into her new life,@@ and @@.mediumaquamarine;gives her hope@@ she can find a place here.
+			You gesture towards $eventSlave.slaveName. She is <<if $eventSlave.intelligence > 0>>bright enough<<elseif (($eventSlave.vaginalSkill + $eventSlave.analSkill + $eventSlave.oralSkill) > 100)>>skilled enough<<else>>obedient enough<</if>> to understand you mean a demonstration is in order. $eventSlave.slaveName starts things off with a <<if $eventSlave.entertainSkill >= 100>>masterful<<elseif $eventSlave.entertainSkill > 10>>skillful<<else>>passable<</if>> striptease, culminating in <<if ($eventSlave.anus > 0) && ($eventSlave.fetish != "cumslut")>>bending over<<else>>kneeling<</if>> in front of you. She eagerly moans as you enter her, begging for your seed<<if $eventSlave.energy > 95>> like the slut she is<<elseif $eventSlave.whoreSkill > 30>> like the whore she is<<elseif ($eventSlave.assignment == "serve in the master suite") || ($eventSlave.assignment == "please you")>> like the fucktoy she is<</if>>. As you finish, she <<if $eventSlave.fetish == "cumslut">>opens her mouth and savors your gift, thanking you once she's swallowed enough to be able to talk again.<<elseif ($eventSlave.fetish == "buttslut") || ($eventSlave.fetish == "submissive")>>collapses on the floor with her ass high in the air, thanking you for painting her hole white.<<else>>thanks you.<</if>> Witnessing this display of servitude from her <<if $activeSlave.mother == $eventSlave.ID>>mother<<else>>father<</if>> @@.hotpink;eases $activeSlave.slaveName into her new life,@@ and @@.mediumaquamarine;gives her hope@@ she can find a place here.
 		<</replace>>
 		<<set $activeSlave.devotion += 4>>
 		<<set $activeSlave.trust += 4>>
diff --git a/src/uncategorized/reMalefactor.tw b/src/uncategorized/reMalefactor.tw
index 1018a0471a2..b17ae65c18d 100644
--- a/src/uncategorized/reMalefactor.tw
+++ b/src/uncategorized/reMalefactor.tw
@@ -394,7 +394,7 @@
 		<<elseif $malefactor == "whore">>
 			An example must be made. Free people must understand that criminals who commit outrages against them will be severely punished. The protesting malefactor is stripped and stuffed into your remote surgery on public video feed. She begs and pleads until she sees her doom in the form of the surgical machinery, at which point she switches to fighting vainly to escape. Of course, @@.red;her health is affected@@ and the horrible experience has left her @@.red;acting oddly.@@ Then it's off to the penthouse for basic slave induction. The public @@.green;approves of this harshness,@@ since she can hardly attempt to steal anything without hands.
 		<<elseif $malefactor == "rapist">>
-			An example must be made. Rape is rare in your arcology, since citizens are so generously provided with means of sexual outlet. When the price of renting a slave it's impossible to rape is as low as it is, sexual assault of a free woman is doubly unforgivable. The protesting malefactor is stripped and stuffed into your remote surgery on public video feed. She begs and pleads until she sees her doom in the form of the surgical machinery, at which point she switches to fighting vainly to escape. Of course, @@.red;her health is affected@@ and the horrible experience has left her @@.red;acting oddly.@@ Then it's off to the penthouse for basic slave induction. The public @@.green;approves of this harshness,@@ since even if she cheers up and ever manages an erection again, she's not likely to rape anyone without arms or legs.
+			An example must be made. Rape is rare in your arcology, since citizens are so generously provided with means of sexual outlet. When the price of renting a slave that's impossible to rape is as low as it is, sexual assault of a free woman is doubly unforgivable. The protesting malefactor is stripped and stuffed into your remote surgery on public video feed. She begs and pleads until she sees her doom in the form of the surgical machinery, at which point she switches to fighting vainly to escape. Of course, @@.red;her health is affected@@ and the horrible experience has left her @@.red;acting oddly.@@ Then it's off to the penthouse for basic slave induction. The public @@.green;approves of this harshness,@@ since even if she cheers up and ever manages an erection again, she's not likely to rape anyone without arms or legs.
 		<<else>>
 			An example must be made. Slave ownership is the cornerstone of the society you're building in your arcology, and this woman attempted to undermine it. The protesting malefactor is stripped and stuffed into your remote surgery on public video feed. She begs and pleads until she sees her doom in the form of the surgical machinery, at which point she switches to fighting vainly to escape. Of course, @@.red;her health is affected@@ and the horrible experience has left her @@.red;acting oddly.@@ Then it's off to the penthouse for basic slave induction. The public @@.green;approves of this harshness,@@ since she will scarcely be able to liberate anyone without arms or legs.
 		<</if>>
-- 
GitLab