code:
App.UI.SlaveInteract.physicalRegimen = function(slave) {
	const {
		// eslint-disable-next-line no-unused-vars
		he,
		him,
		his,
		himself,
		He,
		His
	} = getPronouns(slave);
	const el = new DocumentFragment();
	el.append(drugs());
	el.append(curatives());
	el.append(aphrodisiacs());
	el.append(fertility());
	el.append(incubator());
	el.append(nursery());
	el.append(breederEligibility());
	el.append(bloating());
	el.append(hormones());
	el.append(diet());
	el.append(dietBase());
	el.append(snacks());
	return el;

	function drugs() {
		let el = document.createElement('div');

		const drugLevelOptions = [];
		const lips = [];
		const breasts = [];
		const nipples = [];
		const butt = [];
		const dick = [];
		const balls = [];
		const fertility = [];
		const hormones = [];
		const psych = [];
		const misc = [];

		if (slave.drugs !== "no drugs") {
			drugLevelOptions.push({text: `None`, updateSlave: {drugs: `no drugs`}});
		}
		if (slave.indentureRestrictions < 2) {
			// Psych
			if (slave.intelligence > -100 && slave.indentureRestrictions < 1) {
				psych.push({text: `Psychosuppressants`, updateSlave: {drugs: `psychosuppressants`}});
			} else if (slave.intelligence > -100) {
				psych.push({text: `Psychosuppressants`, disabled: `Cannot suppress indentured slave`});
			} else if (slave.indentureRestrictions < 1) {
				psych.push({text: `Psychosuppressants`, disabled: `Too stupid to suppress`});
			} else {
				psych.push({text: `Psychosuppressants`, disabled: `Too stupid and indentured to suppress`});
			}
			if (V.arcologies[0].FSSlaveProfessionalismResearch === 1) {
				if (canImproveIntelligence(slave)) {
					psych.push({text: `Psychostimulants`, updateSlave: {drugs: `psychostimulants`}});
				} else {
					psych.push({text: `Psychostimulants`, disabled: `Cannot improve intelligence`});
				}
			}

			// Breasts
			if (V.arcologies[0].FSSlimnessEnthusiastResearch === 1) {
				if ((slave.boobs - slave.boobsImplant - slave.boobsMilk) > 100) {
					breasts.push({text: `Reducers`, updateSlave: {drugs: `breast redistributors`}});
				} else {
					breasts.push({text: `Reducers`, disabled: `Boobs are too small`});
				}
			}
			if (slave.boobs < 50000) {
				breasts.push({text: `Enhancement`, updateSlave: {drugs: `breast injections`}});
				breasts.push({text: `Intensive enhancement`, updateSlave: {drugs: `intensive breast injections`}});
			} else {
				breasts.push({text: `Enhancement`, disabled: `Boobs are too large`});
			}
			if (V.arcologies[0].FSAssetExpansionistResearch === 1) {
				if (slave.boobs < 50000) {
					breasts.push({text: `Hyper enhancement`, updateSlave: {drugs: `hyper breast injections`}});
				} else {
					breasts.push({text: `Hyper enhancement`, disabled: `Boobs are too large`});
				}
			}

			// Nipples
			if (V.arcologies[0].FSSlimnessEnthusiastResearch === 1) {
				if (slave.nipples === "huge" || slave.nipples === "puffy" || slave.nipples === "cute") {
					nipples.push({text: `Reducers`, updateSlave: {drugs: `nipple atrophiers`}});
				} else {
					nipples.push({text: `Reducers`, disabled: `Nipples are ${slave.nipples}`});
				}
			}
			if (V.dispensary) {
				if (["inverted", "partially inverted", "cute", "tiny", "puffy"].includes(slave.nipples)) {
					nipples.push({text: `Enhancement`, updateSlave: {drugs: `nipple enhancers`}});
				} else if (slave.nipples === "huge") {
					nipples.push({text: `Enhancement`, disabled: `Nipples are already huge`});
				} else {
					nipples.push({text: `Enhancement`, disabled: `Has no effect on ${slave.nipples} nipples`});
				}
			}

			// Butt
			if (V.arcologies[0].FSSlimnessEnthusiastResearch === 1) {
				if (slave.butt - slave.buttImplant > 0) {
					butt.push({text: `Reducers`, updateSlave: {drugs: `butt redistributors`}});
				} else {
					butt.push({text: `Reducers`, disabled: `Butt is too small`});
				}
			}
			if (slave.butt < 9) {
				butt.push({text: `Enhancement`, updateSlave: {drugs: `butt injections`}});
				butt.push({text: `Intensive enhancement`, updateSlave: {drugs: `intensive butt injections`}});
			} else {
				butt.push({text: `Enhancement`, disabled: `Butt is too large`});
			}
			if (V.arcologies[0].FSAssetExpansionistResearch === 1) {
				if (slave.butt < 20) {
					butt.push({text: `Hyper enhancement`, updateSlave: {drugs: `hyper butt injections`}});
				} else {
					butt.push({text: `Hyper enhancement`, disabled: `Butt is too large`});
				}
			}

			// Lips
			if (V.arcologies[0].FSSlimnessEnthusiastResearch === 1) {
				if (slave.lips - slave.lipsImplant > 0) {
					lips.push({text: `Reducers`, updateSlave: {drugs: `lip atrophiers`}});
				} else {
					lips.push({text: `Reducers`, disabled: `Lips are too small`});
				}
			}
			if (slave.lips <= 95 || (slave.lips <= 85 && V.seeExtreme !== 1)) {
				lips.push({text: `Enhancement`, updateSlave: {drugs: `lip injections`}});
			} else {
				lips.push({text: `Enhancement`, disabled: `Lips are too large`});
			}

			// Fertility
			fertility.push({text: `Fertility`, updateSlave: {drugs: `fertility drugs`}});
			if (V.seeHyperPreg === 1 && slave.indentureRestrictions < 1 && V.superFertilityDrugs === 1 && (slave.breedingMark !== 1 || V.propOutcome === 0 || V.eugenicsFullControl === 1 || V.arcologies[0].FSRestart === "unset")) {
				fertility.push({text: `Fertility+`, updateSlave: {drugs: `super fertility drugs`}});
			}

			// Dick/clit
			if (V.arcologies[0].FSSlimnessEnthusiastResearch === 1) {
				if (slave.dick > 1) {
					dick.push({text: `Reducers`, updateSlave: {drugs: `penis atrophiers`}});
				} else if (slave.dick === 1) {
					dick.push({text: `Reducers`, disabled: `Dick is already at minimum size`});
				}
				if (slave.clit > 0) {
					dick.push({text: `Reducers`, updateSlave: {drugs: `clitoris atrophiers`}});
				}
			}
			if (slave.dick > 0) {
				if (slave.dick < 10) {
					dick.push({text: `Enhancement`, updateSlave: {drugs: `penis enhancement`}});
					dick.push({text: `Intensive enhancement`, updateSlave: {drugs: `intensive penis enhancement`}});
				} else {
					dick.push({text: `Enhancement`, disabled: `Dick is too large`});
				}
			} else {
				if (slave.clit < 5) {
					dick.push({text: `Enhancement`, updateSlave: {drugs: `penis enhancement`}});
					dick.push({text: `Intensive enhancement`, updateSlave: {drugs: `intensive penis enhancement`}});
				} else {
					dick.push({text: `Enhancement`, disabled: `Clit is too large`});
				}
			}
			if (V.arcologies[0].FSAssetExpansionistResearch === 1) {
				if (slave.dick > 0) {
					if (slave.dick < 31) {
						dick.push({text: `Hyper enhancement`, updateSlave: {drugs: `hyper penis enhancement`}});
					} else {
						dick.push({text: `Hyper enhancement`, disabled: `Dick is too large`});
					}
				} else {
					if (slave.clit < 5) {
						dick.push({text: `Hyper enhancement`, updateSlave: {drugs: `penis enhancement`}});
					} else {
						dick.push({text: `Hyper enhancement`, disabled: `Clit is too large`});
					}
				}
			}
			if (slave.dick > 0 && slave.dick < 11 && !canAchieveErection(slave) && slave.chastityPenis !== 1) {
				dick.push({text: `Erectile dysfunction circumvention`, updateSlave: {drugs: `priapism agents`}});
			}

			// Balls
			if (V.arcologies[0].FSSlimnessEnthusiastResearch === 1) {
				if (slave.balls > 1) {
					balls.push({text: `Reducers`, updateSlave: {drugs: `testicle atrophiers`}});
				} else if (slave.balls === 1) {
					balls.push({text: `Reducers`, disabled: `Balls are already at minimum size`});
				}
			}
			if (slave.balls > 0) {
				balls.push({text: `Enhancement`, updateSlave: {drugs: `testicle enhancement`}});
				balls.push({text: `Intensive enhancement`, updateSlave: {drugs: `intensive testicle enhancement`}});
				if (V.arcologies[0].FSAssetExpansionistResearch === 1) {
					balls.push({text: `Hyper enhancement`, updateSlave: {drugs: `hyper testicle enhancement`}});
				}
			}

			// Hormones
			if (V.precociousPuberty === 1 && V.pubertyHormones === 1 && (slave.breedingMark !== 1 || V.propOutcome === 0 || V.eugenicsFullControl === 1 || V.arcologies[0].FSRestart === "unset")) {
				if ((slave.ovaries === 1 || slave.mpreg === 1) && slave.pubertyXX === 0) {
					hormones.push({text: `Female injections`, updateSlave: {drugs: `female hormone injections`}});
				}
				if (slave.balls > 0 && slave.pubertyXY === 0) {
					hormones.push({text: `Male injections`, updateSlave: {drugs: `male hormone injections`}});
				}
			}
			hormones.push({text: `Blockers`, updateSlave: {drugs: `hormone blockers`}});
			hormones.push({text: `Enhancement`, updateSlave: {drugs: `hormone enhancers`}});

			// Misc
			if (V.arcologies[0].FSSlimnessEnthusiastResearch === 1) {
				if (slave.labia > 0) {
					misc.push({text: `Labia reducers`, updateSlave: {drugs: `labia atrophiers`}});
				}
			}
			if (V.growthStim === 1) {
				if (canImproveHeight(slave)) {
					misc.push({text: `Growth Stimulants`, updateSlave: {drugs: `growth stimulants`}});
				} else {
					misc.push({text: `Growth Stimulants`, disabled: `Cannot increase height further`});
				}
			}
			if (V.arcologies[0].FSSlimnessEnthusiastResearch === 1) {
				if (slave.weight > -95) {
					misc.push({text: `Weight loss pills`, updateSlave: {drugs: `appetite suppressors`}});
				} else {
					misc.push({text: `Weight loss pills`, disabled: `Slave is already at low weight`});
				}
			}
			misc.push({text: `Steroids`, updateSlave: {drugs: `steroids`}});
			if (slave.boobs > 250 && slave.boobShape !== "saggy" && V.purchasedSagBGone === 1) {
				misc.push({text: `Sag-B-Gone breast lifting cream`, updateSlave: {drugs: `sag-B-gone`}});
			}
			if (V.arcologies[0].FSYouthPreferentialistResearch === 1) {
				if (slave.visualAge > 18) {
					misc.push({text: `Anti-aging cream`, updateSlave: {drugs: `anti-aging cream`}});
				} else {
					misc.push({text: `Anti-aging cream`, disabled: `Slave already looks young enough`});
				}
			}
		}

		let title = document.createElement('div');
		title.textContent = `Drugs: `;
		let chosenDrug = document.createElement('span');
		chosenDrug.textContent = `${capFirstChar(slave.drugs)}. `;
		chosenDrug.style.fontWeight = "bold";
		title.append(chosenDrug);
		title.appendChild(App.UI.SlaveInteract.generateRows(drugLevelOptions, slave, "", false, refresh));
		el.append(title);

		appendLabeledChoiceRow("Lips", lips, el);
		appendLabeledChoiceRow("Breasts", breasts, el);
		appendLabeledChoiceRow("Nipples", nipples, el);
		appendLabeledChoiceRow("Butt", butt, el);
		appendLabeledChoiceRow(slave.dick > 0 ? "Dick" : "Clit", dick, el);
		appendLabeledChoiceRow("Balls", balls, el);
		appendLabeledChoiceRow("Fertility", fertility, el);
		appendLabeledChoiceRow("Hormones", hormones, el);
		appendLabeledChoiceRow("Psych", psych, el);
		appendLabeledChoiceRow("Misc", misc, el);

		return el;
	}

	function curatives() {
		const curativeOptions = [];

		curativeOptions.push({text: `None`, updateSlave: {curatives: 0}});
		curativeOptions.push({text: `Preventatives`, updateSlave: {curatives: 1}});
		curativeOptions.push({text: `Curatives`, updateSlave: {curatives: 2}});

		let el = document.createElement('div');
		let title = document.createElement('div');
		title.append(`Health: `);
		let chosenOption = document.createElement('span');
		chosenOption.style.fontWeight = "bold";
		if (slave.curatives > 1) {
			chosenOption.textContent = `curatives`;
		} else if (slave.curatives > 0) {
			chosenOption.textContent = `preventatives`;
		} else {
			chosenOption.textContent = `none`;
		}
		title.appendChild(chosenOption);
		title.append(`.`);
		let link = document.createElement('div');
		link.className = "choices";
		link.appendChild(App.UI.SlaveInteract.generateRows(curativeOptions, slave, "", false, refresh));
		el.append(title);
		el.append(link);
		return el;
	}

	function aphrodisiacs() {
		const aphrodisiacOptions = [];

		aphrodisiacOptions.push({text: `None`, updateSlave: {aphrodisiacs: 0}});
		aphrodisiacOptions.push({text: `Aphrodisiacs`, updateSlave: {aphrodisiacs: 1}});
		aphrodisiacOptions.push({text: `Extreme aphrodisiacs`, updateSlave: {aphrodisiacs: 2}});
		aphrodisiacOptions.push({text: `Anaphrodisiacs`, updateSlave: {aphrodisiacs: -1}, note: `Suppresses libido`});

		let el = document.createElement('div');
		let title = document.createElement('div');
		title.append(`Aphrodisiacs: `);
		let chosenOption = document.createElement('span');
		chosenOption.style.fontWeight = "bold";
		if (slave.aphrodisiacs > 1) {
			chosenOption.textContent = `extreme`;
		} else if (slave.aphrodisiacs > 0) {
			chosenOption.textContent = `applied`;
		} else if (slave.aphrodisiacs === -1) {
			chosenOption.textContent = `anaphrodisiacs`;
		} else {
			chosenOption.textContent = `none`;
		}
		title.appendChild(chosenOption);
		title.append(`.`);
		let link = document.createElement('div');
		link.className = "choices";
		link.appendChild(App.UI.SlaveInteract.generateRows(aphrodisiacOptions, slave, "", false, refresh));
		el.append(title);
		el.append(link);
		return el;
	}

	function fertility() {
		let fertilityBlock = document.createElement('span');
		let linkArray = [];
		if (slave.ovaries === 1 || slave.mpreg === 1 || slave.preg > 0) {
			let note = "";
			if (slave.preg < -1) {
				note += `${He} is sterile`;
			} else if (slave.pubertyXX === 0 && slave.preg < 1) {
				note += `${He} is not yet fertile`;
			} else if (slave.ovaryAge >= 47 && slave.preg < 1) {
				note += `${He} is too old to become pregnant`;
				if (slave.preg === -1) {
					slave.preg = 0;
					SetBellySize(slave);
				}
			} else if (slave.broodmotherOnHold === 1) {
				note += `${His} pregnancy implant is turned off`;
				if (slave.broodmotherCountDown > 0) {
					note += `${he} is expected to be completely emptied of ${his} remaining brood in ${slave.broodmotherCountDown} week`;
					if (slave.broodmotherCountDown > 1) {
						note += `s`;
					}
					note += `.`;
					linkArray.push(App.UI.DOM.link(
						`Turn on implant`,
						() => {
							slave.broodmotherOnHold = 0;
							slave.broodmotherCountDown = 0;
							refresh();
						},
					));
				}
			} else if (slave.preg >= -1) {
				fertilityBlock.append("Contraception and fertility: ");
				let fertility = "";
				// fertility.id = "fertility";
				if (slave.preg === -1) {
					fertility = "using contraceptives";
				} else if (slave.pregWeek < 0) {
					fertility = "postpartum";
				} else if (slave.preg === 0) {
					fertility = "fertile";
				} else if (slave.preg < 4 && (slave.broodmother === 0 || slave.broodmotherOnHold === 1)) {
					fertility = "may be pregnant";
				} else if (slave.preg < 2) {
					fertility = "1 week pregnant";
				} else {
					fertility = `${Math.trunc(slave.preg * 1000) / 1000} weeks pregnant`; // * and / needed to avoid seeing something like 20.1000000008 in some cases.
					if (slave.broodmother > 0) {
						fertility += " broodmother";
					}
				}
				fertility += ". ";
				App.UI.DOM.appendNewElement("span", fertilityBlock, fertility, "bold");

				if (slave.preg === 0) {
					linkArray.push(App.UI.DOM.link(
						`Use contraceptives`,
						() => {
							slave.preg = -1;
							refresh();
						},
					));
				} else if (slave.preg === -1) {
					linkArray.push(App.UI.DOM.link(
						`Let ${him} get pregnant`,
						() => {
							slave.preg = 0;
							refresh();
						},
					));
				} else if (isInduced(slave)) {
					note += `Hormones are being slipped into ${his} food; ${he} will give birth suddenly and rapidly this week`;
				} else if (
					slave.preg > slave.pregData.normalBirth - 2 &&
						slave.preg > slave.pregData.minLiveBirth &&
						slave.broodmother === 0 &&
						!isInLabor(slave)
				) {
					linkArray.push(App.UI.DOM.link(
						`Induce labor`,
						() => {
							induce(slave);
							refresh();
						},
					));
					linkArray.push(App.UI.DOM.passageLink(`Give ${him} a cesarean section`, "csec"));
				} else if (slave.broodmother > 0) {
					if (slave.broodmotherOnHold !== 1) {
						linkArray.push(App.UI.DOM.link(
							`Turn off implant`,
							() => {
								slave.broodmotherOnHold = 1;
								slave.broodmotherCountDown = 38 - WombMinPreg(slave);
								refresh();
							},
						));
					}
					if (slave.preg > 37) {
						linkArray.push(App.UI.DOM.passageLink(`Induce mass childbirth`, "BirthStorm"));
					}
				} else if (slave.preg > slave.pregData.minLiveBirth) {
					linkArray.push(App.UI.DOM.link(
						`Give ${him} a cesarean section`,
						() => {
							slave.broodmotherOnHold = 0;
							slave.broodmotherCountDown = 0;
						},
						[],
						"csec"
					));
				} else if (slave.preg > 0 && slave.breedingMark === 1 && V.propOutcome === 1 && V.arcologies[0].FSRestart !== "unset" && V.eugenicsFullControl !== 1 && (slave.pregSource === -1 || slave.pregSource === -6)) {
					note += "You are forbidden from aborting an Elite child";
				} else if (slave.preg > 0) {
					linkArray.push(App.UI.DOM.link(
						`Abort ${his} pregnancy`,
						() => {
							slave.broodmotherOnHold = 0;
							slave.broodmotherCountDown = 0;
						},
						[],
						"Abort"
					));
				}
			}
			App.UI.DOM.appendNewElement("span", fertilityBlock, note, "note");
			App.UI.DOM.appendNewElement("div", fertilityBlock, App.UI.DOM.generateLinksStrip(linkArray), "choices");
		}
		if (
			(slave.pregKnown === 1) &&
				(V.pregSpeedControl === 1) &&
				(
					slave.breedingMark !== 1 ||
					V.propOutcome === 0 ||
					V.eugenicsFullControl === 1 ||
					V.arcologies[0].FSRestart === "unset"
				) &&
				(slave.indentureRestrictions < 1) &&
				(slave.broodmother === 0) &&
				V.seePreg !== 0
		) {
			let title = document.createElement('div');
			let underline = document.createElement('span');
			underline.style.textDecoration = "underline";
			underline.textContent = "Pregnancy control";
			title.appendChild(underline);
			title.append(": ");

			if (slave.pregControl === "labor suppressors") {
				title.append("Labor is suppressed. ");
			} else if (slave.pregControl === "slow gestation") {
				title.append("Slowed gestation speed. ");
			} else if (slave.pregControl === "speed up") {
				title.append("Faster gestation speed, staffed clinic recommended. ");
			} else {
				title.append("Normal gestation and birth. ");
			}
			fertilityBlock.appendChild(title);

			linkArray = [];
			if (slave.pregControl !== "none") {
				linkArray.push(App.UI.DOM.link(
					`Normal ${slave.preg < slave.pregData.normalBirth ? "Gestation" : "Birth"}`,
					() => {
						slave.pregControl = "none";
						refresh();
					},
				));
			}
			if (slave.preg < slave.pregData.normalBirth) {
				if (slave.pregControl !== "slow gestation") {
					linkArray.push(App.UI.DOM.link(
						`Slow Gestation`,
						() => {
							slave.pregControl = "slow gestation";
							refresh();
						},
					));
				}
				if (slave.pregControl !== "speed up") {
					linkArray.push(App.UI.DOM.link(
						`Fast Gestation`,
						() => {
							slave.pregControl = "speed up";
							refresh();
						},
					));
				}
			}
			if (slave.preg >= slave.pregData.minLiveBirth) {
				if (slave.pregControl !== "labor suppressors") {
					linkArray.push(App.UI.DOM.link(
						`Suppress Labor`,
						() => {
							slave.pregControl = "labor suppressors";
							refresh();
						},
					));
				}
			}
			App.UI.DOM.appendNewElement("div", fertilityBlock, App.UI.DOM.generateLinksStrip(linkArray), "choices");
		}
		return fertilityBlock;
	}

	function incubator() {
		const reservedChildren = FetusGlobalReserveCount("incubator");
		let _reservedIncubator = WombReserveCount(slave, "incubator");
		let _reservedNursery = WombReserveCount(slave, "nursery");
		let _WL = slave.womb.length;
		let el = document.createElement('div');
		const linkArray = [];

		if (V.incubator > 0) {
			if (slave.preg > 0 && slave.broodmother === 0 && slave.pregKnown === 1 && slave.eggType === "human") {
				if ((slave.assignment !== Job.DAIRY || V.dairyPregSetting === 0) && (slave.assignment !== Job.FARMYARD || V.farmyardBreeding === 0)) {
					let title = document.createElement('div');
					if (_WL - _reservedNursery === 0) {
						title.textContent = `${His} children are already reserved for ${V.nurseryName}`;
						title.style.fontStyle = "italic";
					} else {
						const freeTanks = (V.incubator - V.tanks.length);
						if (_reservedIncubator > 0) {
							if (_WL === 1) {
								title.textContent = `${His} child will be placed in ${V.incubatorName}. `;
							} else if (_reservedIncubator < _WL) {
								title.textContent = `${_reservedIncubator} of ${his} children will be placed in ${V.incubatorName}.`;
							} else if (_WL === 2) {
								title.textContent = `Both of ${his} children will be placed in ${V.incubatorName}. `;
							} else {
								title.textContent = `All ${_reservedIncubator} of ${his} children will be placed in ${V.incubatorName}. `;
							}
							if ((_reservedIncubator + _reservedNursery < _WL) && (reservedChildren < freeTanks)) {
								linkArray.push(
									App.UI.DOM.link(`Keep another child`, () => wombUpdateIncubator(1, true))
								);
								if (_reservedIncubator > 0) {
									linkArray.push(
										App.UI.DOM.link(`Keep one less child`, () => wombUpdateIncubator(1, false))
									);
								}
								if (_reservedIncubator > 1) {
									linkArray.push(
										App.UI.DOM.link(`Keep none of ${his} children`, () => wombUpdateIncubator(9999, false))
									);
								}
								if ((reservedChildren + _WL - _reservedIncubator) <= freeTanks) {
									linkArray.push(
										App.UI.DOM.link(`Keep the rest of ${his} children`, () => wombUpdateIncubator(9999, true))
									);
								}
							} else if ((_reservedIncubator === _WL) || (reservedChildren === freeTanks) || (_reservedIncubator - _reservedNursery >= 0)) {
								linkArray.push(
									App.UI.DOM.link(`Keep one less child`, () => wombUpdateIncubator(1, false))
								);
								if (_reservedIncubator > 1) {
									linkArray.push(
										App.UI.DOM.link(`Keep none of ${his} children`, () => wombUpdateIncubator(9999, false))
									);
								}
							}
						} else if (reservedChildren < freeTanks) {
							title.textContent = `${He} is pregnant and you have `;
							if (freeTanks === 1) {
								title.textContent += `an `;
							}
							let tank = document.createElement('span');
							tank.className = "lime";
							tank.textContent = `available aging tank`;
							if (freeTanks > 1) {
								tank.textContent += `s`;
							}
							tank.textContent += `.`;
							let _cCount = (_WL > 1 ? "a" : "the");
							linkArray.push(
								App.UI.DOM.link(`Keep ${_cCount} child`, () => wombUpdateIncubator(1, true))
							);
							title.appendChild(tank);
							if ((_WL > 1) && (reservedChildren + _WL) <= freeTanks) {
								linkArray.push(
									App.UI.DOM.link(`Keep all of ${his} children`, () => wombUpdateIncubator(9999, true))
								);
							}
						} else if (reservedChildren === freeTanks) {
							title.textContent = `You have no available tanks for ${his} children. `;
						}
					}
					el.append(title);
					App.UI.DOM.appendNewElement("div", el, App.UI.DOM.generateLinksStrip(linkArray), "choices");
				}
			}
		}

		function wombUpdateIncubator(count, addToWomb) {
			if (addToWomb) {
				WombAddToGenericReserve(slave, "incubator", count);
			} else {
				WombCleanGenericReserve(slave, "incubator", count);
			}
			refresh();
		}

		return el;
	}

	function nursery() {
		let el = document.createElement('div');
		if (V.nursery > 0) {
			const reservedChildrenNursery = FetusGlobalReserveCount("nursery");
			let reservedIncubator = WombReserveCount(slave, "incubator");
			let reservedNursery = WombReserveCount(slave, "nursery");
			let _WL = slave.womb.length;
			if (slave.preg > 0 && slave.broodmother === 0 && slave.pregKnown === 1 && slave.eggType === "human") {
				if ((slave.assignment !== Job.DAIRY || V.dairyPregSetting === 0) && (slave.assignment !== Job.FARMYARD || V.farmyardBreeding === 0)) {
					let title = document.createElement('div');
					const linkArray = [];
					if (_WL - reservedIncubator === 0) {
						title.textContent = `${His} children are already reserved for ${V.incubatorName}`;
						title.style.fontStyle = "italic";
					} else {
						const freeCribs = (V.nursery - V.cribs.length);
						if (reservedNursery > 0) {
							if (_WL === 1) {
								title.textContent = `${His} child will be placed in ${V.nurseryName}. `;
							} else if (reservedNursery < _WL) {
								title.textContent = `_reservedNursery of ${his} children will be placed in ${V.nurseryName}.`;
							} else if (_WL === 2) {
								title.textContent = `Both of ${his} children will be placed in ${V.nurseryName}. `;
							} else {
								title.textContent = `All ${reservedNursery} of ${his} children will be placed in ${V.nurseryName}. `;
							}
							if ((reservedIncubator + reservedNursery < _WL) && (reservedChildrenNursery < freeCribs)) {
								linkArray.push(
									App.UI.DOM.link(`Keep another child`, () => wombUpdateNursery(1, true))
								);

								if (reservedNursery > 0) {
									linkArray.push(
										App.UI.DOM.link(`Keep one less child`, () => wombUpdateNursery(1, false))
									);
								}
								if (reservedNursery > 1) {
									linkArray.push(
										App.UI.DOM.link(`Keep none of ${his} children`, () => wombUpdateNursery(9999, false))
									);
								}
								if ((reservedChildrenNursery + _WL - reservedNursery) <= freeCribs) {
									linkArray.push(
										App.UI.DOM.link(`Keep the rest of ${his} children`, () => wombUpdateNursery(9999, true))
									);
								}
							} else if ((reservedNursery === _WL) || (reservedChildrenNursery === freeCribs) || (reservedNursery - reservedIncubator >= 0)) {
								linkArray.push(
									App.UI.DOM.link(`Keep one less child`, () => wombUpdateNursery(1, false))
								);

								if (reservedNursery > 1) {
									linkArray.push(
										App.UI.DOM.link(`Keep none of ${his} children`, () => wombUpdateNursery(9999, false))
									);
								}
							}
						} else if (reservedChildrenNursery < freeCribs) {
							title.textContent = `${He} is pregnant and you have `;
							if (freeCribs === 1) {
								title.textContent += `an `;
							}
							let crib = document.createElement('span');
							crib.className = "lime";
							crib.textContent = `available room`;
							if (freeCribs > 1) {
								crib.textContent += `s`;
							}
							crib.textContent += `.`;
							let _cCount = (_WL > 1 ? "a" : "the");
							linkArray.push(
								App.UI.DOM.link(`Keep ${_cCount} child`, () => wombUpdateNursery(1, true))
							);
							title.appendChild(crib);
							if ((_WL > 1) && (reservedChildrenNursery + _WL) <= freeCribs) {
								linkArray.push(
									App.UI.DOM.link(`Keep all of ${his} children`, () => wombUpdateNursery(9999, true))
								);
							}
						} else if (reservedChildrenNursery === freeCribs) {
							title.textContent = `You have no available rooms for ${his} children. `;
						}
					}
					el.append(title);
					App.UI.DOM.appendNewElement("div", el, App.UI.DOM.generateLinksStrip(linkArray), "choices");
				}
			}
		}

		function wombUpdateNursery(count, addToWomb) {
			if (addToWomb) {
				WombAddToGenericReserve(slave, "nursery", count);
			} else {
				WombCleanGenericReserve(slave, "nursery", count);
			}
			refresh();
		}

		return el;
	}

	function breederEligibility() {
		const el = document.createElement("div");
		if (V.propOutcome === 1 && V.arcologies[0].FSRestart !== "unset") {
			if (slave.breedingMark === 0 && slave.fuckdoll === 0 && slave.eggType === "human" && isFertile(slave) && slave.preg === 0) {
				el.classList.add("choices");
				el.append(
					App.UI.DOM.passageLink(
						`Breeder Eligibility Exam`,
						`BreedingTest`
					)
				);
			}
		}
		return el;
	}

	function bloating() {
		let bloating = document.createElement('div');
		if (slave.inflation > 0) {
			let intro = document.createElement('span');
			intro.textContent = "Required Bloating";
			intro.style.textDecoration = "underline";
			bloating.append(intro);

			bloating.append(": ");

			let requirement = document.createElement('span');
			requirement.style.fontWeight = "bold";
			requirement.id = "inflate";
			if (slave.inflation === 3) {
				requirement.textContent = `${He} is required to keep 2 gallons of ${slave.inflationType} in ${him} at all times`;
			} else if (slave.inflation === 2) {
				requirement.textContent = `${He} is required to keep 4 liters of ${slave.inflationType} in ${him} at all times`;
			} else if (slave.inflation === 1) {
				requirement.textContent = `${He} is required to keep 2 liters of ${slave.inflationType} in ${him} at all times`;
			}
			bloating.append(requirement);
			bloating.append(". ");

			let link = App.UI.DOM.link(
				`Let ${him} deflate`,
				() => {
					deflate(slave);
					refresh();
				},
			);
			bloating.append(link);
		}
		// make sure it updates itself after run
		return bloating;
	}

	function hormones() {
		let el = document.createElement('div');
		const options = [];
		const level = [];

		if (slave.hormones !== 0) {
			level.push({text: `None`, updateSlave: {hormones: 0}});
		}

		if (slave.indentureRestrictions < 2) {
			options.push({text: `Intensive Female`, updateSlave: {hormones: 2}});
		} else {
			options.push({text: `Intensive Female`, disabled: `Cannot use intensive hormones on indentured slaves`});
		}
		options.push({text: `Female`, updateSlave: {hormones: 1}});
		options.push({text: `Male`, updateSlave: {hormones: -1}});
		if (slave.indentureRestrictions < 2) {
			options.push({text: `Intensive Male`, updateSlave: {hormones: -2}});
		} else {
			options.push({text: `Intensive Male`, disabled: `Cannot use intensive hormones on indentured slaves`});
		}

		let title = document.createElement('div');
		title.textContent = `Hormones: `;
		let choice = document.createElement('span');
		choice.style.fontWeight = "bold";
		switch (slave.hormones) {
			case 2: {
				choice.textContent = `intensive female. `;
				break;
			}
			case 1: {
				choice.textContent = `female. `;
				break;
			}
			case 0: {
				choice.textContent = `none. `;
				break;
			}
			case -1: {
				choice.textContent = `male. `;
				break;
			}
			case -2: {
				choice.textContent = `intensive male. `;
				break;
			}
			default: {
				choice.textContent = `Not set. `;
			}
		}

		title.append(choice);
		title.appendChild(App.UI.SlaveInteract.generateRows(level, slave, "", false, refresh));
		el.append(title);

		let links = document.createElement('div');
		links.appendChild(App.UI.SlaveInteract.generateRows(options, slave, "", false, refresh));
		links.className = "choices";
		el.append(links);

		return el;
	}

	function diet() {
		let el = document.createElement('div');

		let title = document.createElement('div');
		title.textContent = `Diet: `;
		let choice = document.createElement('span');
		choice.style.fontWeight = "bold";
		choice.textContent = `${capFirstChar(slave.diet)}. `;

		title.append(choice);
		el.append(title);

		const health = [];
		health.push({text: `Healthy`, updateSlave: {diet: "healthy"}});
		if (V.dietCleanse === 1) {
			if (slave.health.condition < 90 || slave.chem >= 10) {
				health.push({text: `Cleanse`, updateSlave: {diet: "cleansing"}});
			} else {
				health.push({text: `Cleanse`, disabled: `${He} is already healthy`});
			}
		}

		const weight = [];
		if (slave.weight >= -95) {
			weight.push({text: `Lose weight`, updateSlave: {diet: "restricted"}});
		} else {
			weight.push({text: `Lose weight`, disabled: `${He} is already underweight`});
		}
		if (slave.fuckdoll === 0 && slave.fetish !== "mindbroken" && V.feeder === 1) {
			if (slave.weight > 10 || slave.weight < -10) {
				weight.push({text: `Correct weight`, updateSlave: {diet: "corrective"}});
			} else {
				weight.push({text: `Correct weight`, disabled: `${He} is already a healthy weight`});
			}
		}
		if (slave.weight <= 200) {
			weight.push({text: `Fatten`, updateSlave: {diet: "fattening"}});
		} else {
			weight.push({text: `Fatten`, disabled: `${He} is already overweight`});
		}

		const muscle = [];
		if (slave.muscles < 100 && !isAmputee(slave)) {
			muscle.push({text: `Build muscle`, updateSlave: {diet: "muscle building"}});
		} else if (!isAmputee(slave)) {
			muscle.push({text: `Build muscle`, disabled: `${He} is maintaining ${his} enormous musculature`});
		} else {
			muscle.push({text: `Build muscle`, disabled: `${He} has no limbs and thus can't effectively build muscle`});
		}

		if ((slave.muscles > 0 || slave.fuckdoll === 0) && canWalk(slave)) {
			muscle.push({text: `Slim down`, updateSlave: {diet: "slimming"}});
		} else if (!canWalk(slave)) {
			muscle.push({text: `Slim down`, disabled: `${He} can't walk and thus can't trim down`});
		} else if (slave.fuckdoll > 0) {
			muscle.push({text: `Slim down`, disabled: `${He} has no muscles left to lose`});
		}

		const production = [];
		if (slave.balls > 0 && V.cumProDiet === 1) {
			production.push({text: `Cum production`, updateSlave: {diet: "cum production"}});
		}
		if (((isFertile(slave) && slave.preg === 0) || (slave.geneticQuirks.superfetation === 2 && canGetPregnant(slave) && V.geneticMappingUpgrade !== 0)) && V.dietFertility === 1) {
			production.push({text: `Fertility`, updateSlave: {diet: "fertility"}});
		}

		const hormone = [];
		if (V.feeder === 1) {
			hormone.push({text: `Estrogen enriched`, updateSlave: {diet: "XX"}});
			hormone.push({text: `Testosterone enriched`, updateSlave: {diet: "XY"}});
			if (V.dietXXY === 1 && slave.balls > 0 && (slave.ovaries === 1 || slave.mpreg === 1)) {
				hormone.push({text: `Herm hormone blend`, updateSlave: {diet: "XXY"}});
			}
		}

		appendLabeledChoiceRow("Health", health, el);
		appendLabeledChoiceRow("Weight", weight, el);
		appendLabeledChoiceRow("Muscle", muscle, el);
		appendLabeledChoiceRow("Production", production, el);
		appendLabeledChoiceRow("Hormone", hormone, el);

		return el;
	}

	function dietBase() {
		let el = document.createElement('div');
		const milk = [];
		const cum = [];

		// Milk
		if (slave.dietCum < 2) {
			milk.push({text: `Milk added`, updateSlave: {dietMilk: 1}});
			if (slave.dietCum < 2) {
				milk.push({text: `Milk based`, updateSlave: {dietMilk: 2, dietCum: 0}});
			}
			if (slave.dietMilk) {
				milk.push({text: `Remove milk`, updateSlave: {dietMilk: 0}});
			}
		} else {
			milk.push({text: `Milk`, disabled: `Diet is based entirely on cum`});
		}

		// Cum
		if (slave.dietMilk < 2) {
			cum.push({text: `Cum added`, updateSlave: {dietCum: 1}});
			cum.push({text: `Cum based`, updateSlave: {dietCum: 2, dietMilk: 0}});
			if (slave.dietCum) {
				cum.push({text: `Remove cum`, updateSlave: {dietCum: 0}});
			}
		} else {
			cum.push({text: `Cum`, disabled: `Diet is based entirely on milk`});
		}

		let title = document.createElement('div');
		title.textContent = `Diet base: `;
		let choice = document.createElement('span');
		choice.style.fontWeight = "bold";
		if (slave.dietCum === 2) {
			choice.textContent = `cum based. `;
		} else if (slave.dietCum === 1 && slave.dietMilk === 0) {
			choice.textContent = `cum added. `;
		} else if (slave.dietCum === 1 && slave.dietMilk === 1) {
			choice.textContent = `cum and milk added. `;
		} else if (slave.dietMilk === 1 && slave.dietCum === 0) {
			choice.textContent = `milk added. `;
		} else if (slave.dietMilk === 2) {
			choice.textContent = `milk based. `;
		} else if (slave.dietCum === 0 && slave.dietMilk === 0) {
			choice.textContent = `normal. `;
		} else {
			choice.textContent = `THERE HAS BEEN AN ERROR.`;
		}

		title.append(choice);
		el.append(title);

		appendLabeledChoiceRow("Milk", milk, el);
		appendLabeledChoiceRow("Cum", cum, el);

		return el;
	}

	function snacks() {
		let el = document.createElement('div');
		let options = [];

		if (V.arcologies[0].FSHedonisticDecadenceResearch === 1) {
			let title = document.createElement('div');
			title.textContent = `Solid Slave Food Access: `;
			let choice = document.createElement('span');
			choice.style.fontWeight = "bold";
			if (slave.onDiet === 0) {
				choice.textContent = `Free to stuff ${himself}.`;
			} else {
				choice.textContent = `On a strict diet.`;
			}
			title.append(choice);
			el.append(title);

			options.push({text: `No access`, updateSlave: {onDiet: 1}});
			options.push({text: `Full access`, updateSlave: {onDiet: 0}});

			let links = document.createElement('div');
			links.appendChild(App.UI.SlaveInteract.generateRows(options, slave, "", false, refresh));
			links.className = "choices";
			el.append(links);
		}

		return el;
	}

	function refresh() {
		jQuery("#content-physical-regimen").empty().append(App.UI.SlaveInteract.physicalRegimen(slave));
	}

	/** Append a simple row of choices with a label to a container, if there are choices to be made.
	 * @param {string} label
	 * @param {RowItem[]} array
	 * @param {HTMLElement} el
	 */
	function appendLabeledChoiceRow(label, array, el) {
		if (array.length > 0) {
			const links = document.createElement('div');
			links.append(`${label}: `);
			links.appendChild(App.UI.SlaveInteract.generateRows(array, slave, "", false, refresh));
			links.className = "choices";
			return el.appendChild(links);
		}
	}
};


code:
App.UI.SlaveInteract.rules = function(slave) {
	const frag = new DocumentFragment();
	let p;
	let div;
	let array;
	let choices;
	const {
		He, His,
		he, him, his, himself
	} = getPronouns(slave);

	if (V.seePreg !== 0) {
		if (V.universalRulesImpregnation === "PC") {
			updateBreederLink("you", "PCExclude");
		} else if (V.universalRulesImpregnation === "HG") {
			updateBreederLink("the Head Girl", "HGExclude");
		} else if (V.universalRulesImpregnation === "Stud") {
			updateBreederLink("your Stud", "StudExclude");
		}
	}

	function updateBreederLink(breeder, exclude) {
		p = document.createElement('p');
		const exempt = slave[exclude] ? "Exempt" : "Include";

		p.append(`Will be bred by ${breeder} when fertile. `);
		p.append(
			App.UI.DOM.link(`${exempt} ${him}`, () => {
				slave[exclude] = slave[exclude] ^ 1; // switch 0 and 1
				refresh();
			})
		);
		frag.append(p);
	}

	p = document.createElement('p');

	array = [];
	if (slave.useRulesAssistant === 0) {
		App.UI.DOM.appendNewElement("span", p, `Not subject `, ["bold", "gray"]);
		App.UI.DOM.appendNewElement("span", p, `to the Rules Assistant.`, "gray");
		array.push(
			App.UI.DOM.link(
				`Include ${him}`,
				() => {
					slave.useRulesAssistant = 1;
					refresh();
				}
			)
		);
	} else {
		App.UI.DOM.appendNewElement("h3", p, `Rules Assistant`);

		if (slave.hasOwnProperty("currentRules") && slave.currentRules.length > 0) {
			const ul = document.createElement("UL");
			ul.style.margin = "0";
			V.defaultRules.filter(
				x => ruleApplied(slave, x)
			).map(
				x => {
					const li = document.createElement('li');
					li.append(x.name);
					ul.append(li);
				}
			);

			// set up rules display
			if ($("ul").has("li").length) {
				App.UI.DOM.appendNewElement("div", p, `Rules applied: `);
				p.append(ul);
			} else {
				App.UI.DOM.appendNewElement("div", p, `There are no rules that would apply to ${him}.`, "gray");
			}
		}
		array.push(
			App.UI.DOM.link(
				`Apply rules`,
				() => {
					DefaultRules(slave);
					refresh();
				}
			)
		);
		array.push(
			App.UI.DOM.link(
				`Exempt ${him}`,
				() => {
					slave.useRulesAssistant = 0;
					refresh();
				}
			)
		);
		array.push(
			App.UI.DOM.link(
				`Apply all rules to ${him} again`,
				() => {
					removeFromRulesToApplyOnce(slave);
					DefaultRules(slave);
					refresh();
				}
			)
		);
		array.push(App.UI.DOM.passageLink("Rules Assistant Options", "Rules Assistant"));
	}
	p.append(App.UI.DOM.generateLinksStrip(array));
	frag.append(p);

	p = document.createElement('p');
	App.UI.DOM.appendNewElement("h3", p, `Other Rules`);

	if (slave.fuckdoll > 0) {
		App.UI.DOM.appendNewElement("span", p, "Rules have little meaning for living sex toys", "note");
	} else {
		// Living
		penthouseCensus();
		p.append("Living standard: ");

		if (setup.facilityCareers.includes(slave.assignment)) {
			App.UI.DOM.appendNewElement("span", p, ` ${His} living conditions are managed by ${his} assignment.`, "note");
		} else if ((slave.assignment === "be your Head Girl") && (V.HGSuite === 1)) {
			App.UI.DOM.appendNewElement("span", p, ` ${He} has ${his} own little luxurious room in the penthouse with everything ${he} needs to be a proper Head Girl.`, "note");
		} else if ((slave.assignment === "guard you") && (V.dojo > 1)) {
			App.UI.DOM.appendNewElement("span", p, ` ${He} has a comfortable room in the armory to call ${his} own.`, "note");
		} else {
			choices = [
				{value: "spare"},
				{value: "normal"},
			];
			if (canMoveToRoom(slave) || slave.rules.living === "luxurious") {
				choices.push({value: "luxurious"});
			} else {
				choices.push({
					title: `Luxurious`,
					disabled: ["No luxurious rooms available"]
				});
			}

			p.append(listChoices(choices, "living"));
		}

		// Rest
		if (["be a servant", "be a subordinate slave", "get milked", "please you", "serve in the club", "serve the public", "whore", "work as a farmhand", "work in the brothel", "work a glory hole"].includes(slave.assignment) || (V.dairyRestraintsSetting < 2 && slave.assignment === "work in the dairy")) {
			div = document.createElement("div");
			div.append("Sleep rules: ");
			choices = [
				{value: "none"},
				{value: "cruel"},
				{value: "restrictive"},
				{value: "permissive"},
				{value: "mandatory"},
			];
			div.append(listChoices(choices, "rest"));
			p.append(div);
		}

		// Mobility Aids
		if (!canWalk(slave) && canMove(slave)) {
			div = document.createElement("div");
			div.append("Use of mobility aids: ");
			choices = [
				{value: "restrictive"},
				{value: "permissive"},
			];
			div.append(listChoices(choices, "mobility"));
			p.append(div);
		}

		// Punishment
		div = document.createElement("div");
		div.append("Typical punishment: ");
		choices = [
			{value: "confinement"},
			{value: "whipping"},
			{value: "chastity"},
			{value: "situational"},
		];
		div.append(listChoices(choices, "punishment"));
		p.append(div);

		// Reward
		div = document.createElement("div");
		div.append("Typical reward: ");
		choices = [
			{value: "relaxation"},
			{value: "drugs"},
			{value: "orgasm"},
			{value: "situational"},
		];
		div.append(listChoices(choices, "reward"));
		p.append(div);

		// Lactation
		if (slave.lactation !== 2) {
			div = document.createElement("div");
			div.append("Lactation maintenance: ");
			choices = [
				{
					title: "Left alone",
					value: "none",
				},
			];

			if (slave.lactation === 0) {
				choices.push(
					{
						title: "Induce lactation",
						value: "induce",
					}
				);
			} else {
				choices.push(
					{
						title: "Maintain lactation",
						value: "maintain",
					}
				);
			}
			div.append(listChoices(choices, "lactation"));
			p.append(div);
		}

		p.append(orgasm(slave));

		if (slave.voice !== 0) {
			div = document.createElement("div");
			div.append("Speech rules: ");
			choices = [
				{value: "restrictive"},
				{value: "permissive"},
			];
			if (slave.accent > 0 && slave.accent < 4) {
				choices.push(
					{value: "accent elimination"},
				);
			} else if (slave.accent > 3) {
				choices.push(
					{value: "language lessons"},
				);
			}
			div.append(listChoices(choices, "speech"));
			p.append(div);
		}

		div = document.createElement("div");
		div.append("Relationship rules: ");
		choices = [
			{value: "restrictive"},
			{value: "just friends"},
			{value: "permissive"},
		];
		div.append(listChoices(choices, "relationship"));
		p.append(div);

		p.append(smartSettings(slave));
	}
	frag.append(p);
	return frag;

	function listChoices(choices, property) {
		const links = [];
		for (const c of choices) {
			const title = c.title || capFirstChar(c.value);
			if (c.disabled) {
				links.push(
					App.UI.DOM.disabledLink(
						title, c.disabled
					)
				);
			} else if (slave.rules[property] === c.value) {
				links.push(
					App.UI.DOM.disabledLink(
						title,
						["Current Setting"]
					)
				);
			} else {
				links.push(
					App.UI.DOM.link(
						title,
						() => {
							slave.rules[property] = c.value;
							refresh();
						}
					)
				);
			}
		}
		return App.UI.DOM.generateLinksStrip(links);
	}
	function orgasm(slave) {
		let el = document.createElement('div');

		let title = document.createElement('div');
		title.textContent = `Non-assignment orgasm rules: `;
		el.append(title);

		const choices = [
			{
				title: "Masturbation",
				value: "masturbation",
				note: `Controls whether ${he} is allowed to pleasure ${himself}, should ${he} feel the need`
			},
			{
				title: "Partner",
				value: "partner",
				note: `Controls whether ${he} is allowed sexual contact with ${his} romantic partner, should you permit ${him} to have one`
			},
			{
				title: "Facility Leader",
				value: "facilityLeader",
				note: `Controls whether development facility leaders (Nurse, Attendant, etc) are allowed to satisfy ${his} sexual needs while ${he} is assigned to their facility; does not apply to production facilities`
			},
			{
				title: "Family",
				value: "family",
				note: `Controls whether ${he} is allowed sexual contact with close family members`
			},
			{
				title: "Other slaves",
				value: "slaves",
				note: `Controls whether ${he} is allowed sexual contact with your other slaves that do not fit any of the above categories`
			},
			{
				title: "Master",
				value: "master",
				note: `Controls whether you will fuck ${him} personally when ${he} needs it`,
				master: true
			},
		];

		for (const orgasmObj of choices) {
			const row = document.createElement("div");
			row.classList.add("choices");
			row.append(`${orgasmObj.title}: `);
			row.append(makeLinks(orgasmObj));
			App.UI.DOM.appendNewElement("span", row, ` ${orgasmObj.note}`, "note");
			el.append(row);
		}

		return el;

		function makeLinks(orgasmObj) {
			const linkArray = [];
			makeALink(1);
			makeALink(0);

			return App.UI.DOM.generateLinksStrip(linkArray);

			function makeALink(onOff) {
				const allow = orgasmObj.master ? `Grant` : `Allow`;
				const forbid = orgasmObj.master ? `Deny` : `Forbid`;
				const title = onOff ? allow : forbid;
				if (slave.rules.release[orgasmObj.value] === onOff) {
					linkArray.push(App.UI.DOM.makeElement("span", title, "bold"));
				} else {
					linkArray.push(
						App.UI.DOM.link(
							title,
							() => {
								slave.rules.release[orgasmObj.value] = onOff;
								refresh();
							}
						)
					);
				}
			}
		}
	}

	function smartSettings(slave) {
		let el = document.createElement('div');
		const smartBulletVibe = slave.vaginalAccessory === "smart bullet vibrator" || slave.dickAccessory === "smart bullet vibrator";
		const smartDildoVibe = slave.vaginalAttachment === "smart vibrator";

		if (slave.clitPiercing === 3 || smartBulletVibe || smartDildoVibe) {
			const level = new Map();
			const bodyPart = new Map();
			const BDSM = new Map();
			const gender = new Map();

			// Level
			level.set(`No sex`, `none`);
			level.set(`All sex`, `all`);

			// Body part
			bodyPart.set(`Vanilla`, `vanilla`);
			bodyPart.set(`Oral`, `oral`);
			bodyPart.set(`Anal`, `anal`);
			bodyPart.set(`Boobs`, `boobs`);
			if (V.seePreg !== 0) {
				bodyPart.set(`Preg`, `pregnancy`);
			}
			// BDSM
			BDSM.set(`Sub`, `submissive`);
			BDSM.set(`Dom`, `dom`);
			BDSM.set(`Masochism`, `masochist`);
			BDSM.set(`Sadism`, `sadist`);
			BDSM.set(`Humiliation`, `humiliation`);

			// Gender
			gender.set(`Men`, `men`);
			gender.set(`Women`, `women`);
			gender.set(`Anti-men`, `anti-men`);
			gender.set(`Anti-women`, `anti-women`);
			let label = null;
			if (slave.clitPiercing === 3) {
				label = `Smart ${slave.dick < 1 ? "clit" : "frenulum"} piercing `;
				label += (smartBulletVibe || smartDildoVibe) ? `and smart vibrator setting: ` : `setting: `;
			} else if (smartBulletVibe) {
				label = `Smart bullet vibrator setting: `;
			} else if (smartDildoVibe) {
				label = `Smart vibrating dildo attachment setting: `;
			}
			let title = App.UI.DOM.appendNewElement('div', el, label);
			let selected = App.UI.DOM.appendNewElement('span', title, `${slave.clitSetting}. `);
			selected.style.fontWeight = "bold";

			choices("Level", level);
			choices("Body part", bodyPart);
			choices("Body part", BDSM);
			choices("Gender", gender);
		}

		return el;

		function choices(title, map) {
			const row = document.createElement("div");
			row.classList.add("choices");
			row.append(`${title}: `);

			const linkArray = [];
			for (const [text, value] of map) {
				if (slave.clitSetting === value) {
					linkArray.push(
						App.UI.DOM.disabledLink(
							text,
							["Currently selected"]
						)
					);
				} else {
					linkArray.push(
						App.UI.DOM.link(
							text,
							() => {
								slave.clitSetting = value;
								refresh();
							}
						)
					);
				}
			}
			row.append(App.UI.DOM.generateLinksStrip(linkArray));
			el.append(row);
		}
	}
	function refresh() {
		jQuery("#content-rules").empty().append(App.UI.SlaveInteract.rules(slave));
	}
};

repo_name: Welptard/fc

license: mit


code:
/** Find the previous and next slaves' IDs based on the current sort order
 * @param {App.Entity.SlaveState} slave
 * @returns {[number, number]} - previous and next slave ID
 */
App.UI.SlaveInteract.placeInLine = function(slave) {
	const useSlave = assignmentVisible(slave) ? ((s) => assignmentVisible(s)) : ((s) => slave.assignment === s.assignment);
	const slaveList = V.slaves.filter(useSlave);
	SlaveSort.slaves(slaveList);
	const curSlaveIndex = slaveList.findIndex((s) => s.ID === slave.ID);

	let nextIndex;
	if (curSlaveIndex + 1 > slaveList.length - 1) {
		nextIndex = 0; // wrap around to first slave
	} else {
		nextIndex = curSlaveIndex + 1;
	}
	let prevIndex;
	if (curSlaveIndex - 1 < 0) {
		prevIndex = slaveList.length - 1; // wrap around to last slave
	} else {
		prevIndex = curSlaveIndex - 1;
	}

	return [slaveList[prevIndex].ID, slaveList[nextIndex].ID];
};

/** @typedef RowItem
 * @type {object}
 * @property {string} [FS] - FS requirement, if any
 * @property {string} [text] - link text
 * @property {object} [updateSlave] - properties to be merged onto the slave
 * @property {object} [update] - properties to be merged into global state
 * @property {string} [disabled] - text indicating why the option is unavailable
 * @property {string} [note]
 */

/** Generate a row of choices
 * @param {RowItem[]} array
 * @param {App.Entity.SlaveState} slave
 * @param {string} [category] - should be in the form of slave.category, the thing we want to update.
 * @param {boolean} [accessCheck=false]
 * @param {Function} refresh
 * @returns {HTMLSpanElement}
 */
App.UI.SlaveInteract.generateRows = function(array, slave, category, accessCheck = false, refresh) {
	const linkArray = [];
	for (const item of array) {
		let link;
		// Some items will never be in App.Data.slaveWear, especially "none" if it falls in between harsh and nice data sets. Trying to look it up would cause an error, which is what access check works around.
		let unlocked = false;
		if (accessCheck === true) {
			const itemName = (category === "chastity") ? item.text.toLowerCase() : item.updateSlave[category]; // Yucky. Category name does not match for chastity (since it sets multiple kinds of chastity at once). Compare using a lowercase name instead.
			unlocked = isItemAccessible.entry(itemName, category, slave);
		}
		if (accessCheck === false || unlocked) {
			// is it just text?
			if (item.disabled) {
				link = App.UI.DOM.disabledLink(item.text, [item.disabled]);
			} else if (typeof unlocked === 'string') {
				link = App.UI.DOM.disabledLink(item.text, [unlocked]);
			} else {
				link = document.createElement('span');

				// Set up the link
				link.appendChild(
					App.UI.DOM.link(
						`${item.text} `,
						() => { click(item); },
					)
				);

				if (item.FS) {
					let FS = App.UI.DOM.disabledLink(`FS`, [FutureSocieties.displayAdj(item.FS)]);
					FS.style.fontStyle = "italic";
					link.appendChild(FS);
				}

				// add a note node if required
				if (item.note) {
					link.appendChild(App.UI.DOM.makeElement('span', ` ${item.note}`, 'note'));
				}
			}
			linkArray.push(link);
		}
	}

	return App.UI.DOM.generateLinksStrip(linkArray);

	/** @param {RowItem} arrayOption */
	function click(arrayOption) {
		if (arrayOption.updateSlave) {
			for (const slaveProperty in arrayOption.updateSlave) {
				_.set(slave, slaveProperty, arrayOption.updateSlave[slaveProperty]);
			}
		}
		if (arrayOption.update) {
			Object.assign(V, arrayOption.update);
		}
		refresh();
	}
};


code:
App.UI.SlaveInteract.wardrobe = function(slave) {
	const {
		// eslint-disable-next-line no-unused-vars
		he,
		him,
		his,
	} = getPronouns(slave);
	const el = new DocumentFragment();
	el.append(clothes());
	if (slave.fuckdoll === 0) {
		el.append(collar());
		el.append(mask());
		el.append(mouth());
		el.append(armAccessory());
		el.append(shoes());
		el.append(legAccessory());
		el.append(bellyAccessory());
		el.append(buttplug());
		el.append(buttplugAttachment());
		el.append(vaginalAccessory());
		el.append(vaginalAttachment());
		el.append(dickAccessory());
		el.append(chastity());
	}

	App.UI.DOM.appendNewElement("h3", el, `Shopping`);
	el.append(shopping());

	return el;

	function clothes() {
		let el = document.createElement('div');
		let links;
		if (slave.fuckdoll === 0) {
			// <<= App.Desc.clothing($activeSlave)>>

			let label = document.createElement('div');
			label.append(`Clothes: `);

			let choice = document.createElement('span');
			choice.style.fontWeight = "bold";
			choice.textContent = (`${slave.clothes} `);
			label.appendChild(choice);

			// Choose her own
			if (slave.clothes !== `choosing her own clothes`) {
				let choiceOptionsArray = [];
				choiceOptionsArray.push({text: `Let ${him} choose`, updateSlave: {clothes: `choosing her own clothes`, choosesOwnClothes: 1}});
				label.appendChild(App.UI.SlaveInteract.generateRows(choiceOptionsArray, slave, "clothes", false, refresh));
			}
			el.appendChild(label);

			let niceOptionsArray = [];
			let harshOptionsArray = [];

			let clothingOption;
			// Nice clothes
			App.Data.slaveWear.niceClothes.forEach(item => {
				clothingOption = {
					text: item.name,
					updateSlave: {clothes: item.value, choosesOwnClothes: 0},
					FS: item.fs
				};
				niceOptionsArray.push(clothingOption);
			});
			// Harsh clothes
			App.Data.slaveWear.harshClothes.forEach(item => {
				clothingOption = {
					text: item.name,
					updateSlave: {clothes: item.value, choosesOwnClothes: 0},
					FS: item.fs
				};
				if (item.value !== "choosing her own clothes") {
					harshOptionsArray.push(clothingOption);
				}
			});

			// Sort
			niceOptionsArray = niceOptionsArray.sort((a, b) => (a.text > b.text) ? 1 : -1);
			harshOptionsArray = harshOptionsArray.sort((a, b) => (a.text > b.text) ? 1 : -1);

			// Nice options
			links = document.createElement('div');
			links.className = "choices";
			links.append(`Nice: `);
			links.appendChild(App.UI.SlaveInteract.generateRows(niceOptionsArray, slave, "clothes", true, refresh));
			el.appendChild(links);

			// Harsh options
			links = document.createElement('div');
			links.className = "choices";
			links.append(`Harsh: `);
			links.appendChild(App.UI.SlaveInteract.generateRows(harshOptionsArray, slave, "clothes", true, refresh));
			el.appendChild(links);
		}
		if (slave.fuckdoll !== 0 || slave.clothes === "restrictive latex" || slave.clothes === "a latex catsuit" || slave.clothes === "a cybersuit" || slave.clothes === "a comfortable bodysuit") {
			if (V.seeImages === 1 && V.imageChoice === 1) {
				// Color options
				links = document.createElement('div');
				links.className = "choices";
				links.append(`Color: `);
				links.appendChild(colorOptions("clothingBaseColor"));
				el.appendChild(links);
			}
		}

		return el;
	}

	function collar() {
		// <<= App.Desc.collar($activeSlave)>>
		let el = document.createElement('div');

		let label = document.createElement('div');
		label.append(`Collar: `);

		let choice = document.createElement('span');
		choice.style.fontWeight = "bold";
		choice.textContent = (`${slave.collar} `);
		label.appendChild(choice);

		// Choose her own
		if (slave.collar !== `none`) {
			let choiceOptionsArray = [];
			choiceOptionsArray.push({text: `None`, updateSlave: {collar: `none`}});
			label.appendChild(App.UI.SlaveInteract.generateRows(choiceOptionsArray, slave, "collar", false, refresh));
		}

		el.appendChild(label);

		let niceOptionsArray = [];
		let harshOptionsArray = [];

		let clothingOption;
		// Nice collar
		App.Data.slaveWear.niceCollars.forEach(item => {
			clothingOption = {
				text: item.name,
				updateSlave: {collar: item.value},
				FS: item.fs
			};
			niceOptionsArray.push(clothingOption);
		});
		// Harsh collar
		App.Data.slaveWear.harshCollars.forEach(item => {
			clothingOption = {
				text: item.name,
				updateSlave: {collar: item.value},
				FS: item.fs
			};
			harshOptionsArray.push(clothingOption);
		});

		// Sort
		niceOptionsArray = niceOptionsArray.sort((a, b) => (a.text > b.text) ? 1 : -1);
		harshOptionsArray = harshOptionsArray.sort((a, b) => (a.text > b.text) ? 1 : -1);

		// Nice options
		let links = document.createElement('div');
		links.className = "choices";
		links.append(`Nice: `);
		links.appendChild(App.UI.SlaveInteract.generateRows(niceOptionsArray, slave, "collar", true, refresh));
		el.appendChild(links);

		// Harsh options
		links = document.createElement('div');
		links.className = "choices";
		links.append(`Harsh: `);
		links.appendChild(App.UI.SlaveInteract.generateRows(harshOptionsArray, slave, "collar", true, refresh));
		el.appendChild(links);

		return el;
	}

	function mask() {
		let el = document.createElement('div');

		let label = document.createElement('div');
		label.append(`Mask: `);

		let choice = document.createElement('span');
		choice.style.fontWeight = "bold";
		choice.textContent = (`${slave.faceAccessory} `);
		label.appendChild(choice);

		// Choose her own
		if (slave.faceAccessory !== `none`) {
			let choiceOptionsArray = [];
			choiceOptionsArray.push({text: `None`, updateSlave: {faceAccessory: `none`}});
			label.appendChild(App.UI.SlaveInteract.generateRows(choiceOptionsArray, slave, "faceAccessory", false, refresh));
		}

		el.appendChild(label);

		let array = [];

		let clothingOption;
		App.Data.slaveWear.faceAccessory.forEach(item => {
			clothingOption = {
				text: item.name,
				updateSlave: {faceAccessory: item.value},
				FS: item.fs
			};
			array.push(clothingOption);
		});

		// Sort
		array = array.sort((a, b) => (a.text > b.text) ? 1 : -1);

		let links = document.createElement('div');
		links.className = "choices";
		links.appendChild(App.UI.SlaveInteract.generateRows(array, slave, "faceAccessory", true, refresh));
		el.appendChild(links);

		if (slave.eyewear === "corrective glasses" || slave.eyewear === "glasses" || slave.eyewear === "blurring glasses" || slave.faceAccessory === "porcelain mask") {
			// Color options
			links = document.createElement('div');
			links.className = "choices";
			links.append(`Color: `);
			links.appendChild(colorOptions("glassesColor"));
			let note = document.createElement('span');
			note.className = "note";
			note.textContent = ` Only glasses and porcelain masks support a custom color. If both are worn, they will share the same color.`;
			links.appendChild(note);
			el.appendChild(links);
		}

		return el;
	}

	function mouth() {
		let el = document.createElement('div');

		let label = document.createElement('div');
		label.append(`Gag: `);

		let choice = document.createElement('span');
		choice.style.fontWeight = "bold";
		choice.textContent = (`${slave.mouthAccessory} `);
		label.appendChild(choice);

		// Choose her own
		if (slave.mouthAccessory !== `none`) {
			let choiceOptionsArray = [];
			choiceOptionsArray.push({text: `None`, updateSlave: {mouthAccessory: `none`}});
			label.appendChild(App.UI.SlaveInteract.generateRows(choiceOptionsArray, slave, "mouthAccessory", false, refresh));
		}

		el.appendChild(label);

		let array = [];

		let clothingOption;
		// mouthAccessory
		App.Data.slaveWear.mouthAccessory.forEach(item => {
			clothingOption = {
				text: item.name,
				updateSlave: {mouthAccessory: item.value},
				FS: item.fs
			};
			array.push(clothingOption);
		});

		// Sort
		array = array.sort((a, b) => (a.text > b.text) ? 1 : -1);

		let links = document.createElement('div');
		links.className = "choices";
		links.appendChild(App.UI.SlaveInteract.generateRows(array, slave, "mouthAccessory", true, refresh));
		el.appendChild(links);

		return el;
	}

	function armAccessory() {
		let el = document.createElement('div');
		// App.Desc.armwear(slave)

		let label = document.createElement('div');
		label.append(`Arm accessory: `);

		let choice = document.createElement('span');
		choice.style.fontWeight = "bold";
		choice.textContent = (`${slave.armAccessory} `);
		label.appendChild(choice);

		let array = [];

		// Choose her own
		if (slave.armAccessory !== "none") {
			array.push({text: `None`, updateSlave: {armAccessory: `none`}});
			label.appendChild(App.UI.SlaveInteract.generateRows(array, slave, "armAccessory", false, refresh));
		}

		el.appendChild(label);

		let links = document.createElement('div');
		links.className = "choices";
		array = [
			{text: "Hand gloves", updateSlave: {armAccessory: "hand gloves"}},
			{text: "Elbow gloves", updateSlave: {armAccessory: "elbow gloves"}}
		];
		links.appendChild(App.UI.SlaveInteract.generateRows(array, slave, "armAccessory", false, refresh));
		el.appendChild(links);

		return el;
	}

	function shoes() {
		let el = document.createElement('div');

		let label = document.createElement('div');
		label.append(`Shoes: `);

		let choice = document.createElement('span');
		choice.style.fontWeight = "bold";
		choice.textContent = (`${slave.shoes} `);
		label.appendChild(choice);

		/* We have "barefoot" in App.Data.slaveWear to cover for this
			// Choose her own
			if (slave.shoes !== `none`) {
				let choiceOptionsArray = [];
				choiceOptionsArray.push({text: `None`, updateSlave: {shoes: `none`}});
				label.appendChild(App.UI.SlaveInteract.generateRows(choiceOptionsArray, slave, "shoes", false, refresh));
			}
			*/
		el.appendChild(label);

		let optionsArray = [];

		let clothingOption;
		App.Data.slaveWear.shoes.forEach(item => {
			clothingOption = {
				text: item.name,
				updateSlave: {shoes: item.value},
				FS: item.fs
			};
			optionsArray.push(clothingOption);
		});

		// Sort
		// No sort here since we want light -> advanced. optionsArray = optionsArray.sort((a, b) => (a.text > b.text) ? 1 : -1);

		// Options
		let links = document.createElement('div');
		links.className = "choices";
		links.appendChild(App.UI.SlaveInteract.generateRows(optionsArray, slave, "shoes", true, refresh));
		el.appendChild(links);

		if (V.seeImages === 1 && V.imageChoice === 1 && slave.shoes !== "none") {
			// Color options
			links = document.createElement('div');
			links.className = "choices";
			links.append(`Color: `);
			links.appendChild(colorOptions("shoeColor"));
			el.appendChild(links);
		}

		return el;
	}

	function legAccessory() {
		let el = document.createElement('div');

		let label = document.createElement('div');
		label.append(`Leg accessory: `);

		let choice = document.createElement('span');
		choice.style.fontWeight = "bold";
		choice.textContent = (`${slave.legAccessory} `);
		label.appendChild(choice);

		let array = [];

		// Choose her own
		if (slave.legAccessory !== "none") {
			array.push({text: `None`, updateSlave: {legAccessory: `none`}});
			label.appendChild(App.UI.SlaveInteract.generateRows(array, slave, "legAccessory", false, refresh));
		}

		el.appendChild(label);

		let links = document.createElement('div');
		links.className = "choices";
		array = [
			{text: "Short stockings", updateSlave: {legAccessory: "short stockings"}},
			{text: "Long stockings", updateSlave: {legAccessory: "long stockings"}}
		];
		links.appendChild(App.UI.SlaveInteract.generateRows(array, slave, "legAccessory", false, refresh));
		el.appendChild(links);

		return el;
	}

	function bellyAccessory() {
		// <<waistDescription>><<= App.Desc.pregnancy($activeSlave)>><<clothingCorsetDescription>>
		let choiceOptionsArray = [];
		choiceOptionsArray.push({text: `None`, updateSlave: {bellyAccessory: `none`}});

		let optionsArray = [];

		let clothingOption;
		App.Data.slaveWear.bellyAccessories.forEach(item => {
			clothingOption = {
				text: item.name,
				updateSlave: {bellyAccessory: item.value},
				FS: item.fs
			};
			if (item.value !== "none") {
				// skip none in set, we set the link elsewhere.
				optionsArray.push(clothingOption);
			}
		});
		// Sort
		// No sort here since we want small -> large.optionsArray = optionsArray.sort((a, b) => (a.text > b.text) ? 1 : -1);

		let el = document.createElement('div');

		let label = document.createElement('div');
		label.append(`Belly accessory: `);

		let choice = document.createElement('span');
		choice.style.fontWeight = "bold";
		choice.textContent = (`${slave.bellyAccessory} `);
		label.appendChild(choice);

		// Choose her own
		if (slave.bellyAccessory !== `none`) {
			label.appendChild(App.UI.SlaveInteract.generateRows(choiceOptionsArray, slave, "bellyAccessory", false, refresh));
		}

		el.appendChild(label);

		// Options
		let links = document.createElement('div');
		links.className = "choices";
		links.appendChild(App.UI.SlaveInteract.generateRows(optionsArray, slave, "bellyAccessory", true, refresh));
		if (slave.pregKnown === 1) {
			let note = document.createElement('span');
			note.className = "note";
			note.textContent = ` Extreme corsets will endanger the life within ${him}.`;
			links.appendChild(note);
		}
		el.appendChild(links);

		return el;
	}

	function buttplug() {
		// App.Desc.buttplug(slave)
		let el = document.createElement('div');

		let label = document.createElement('div');
		label.append(`Anal accessory: `);

		let choice = document.createElement('span');
		choice.style.fontWeight = "bold";
		choice.textContent = (`${slave.buttplug} `);
		label.appendChild(choice);

		if (slave.buttplug !== `none`) {
			let choiceOptionsArray = [];
			choiceOptionsArray.push({text: `None`, updateSlave: {buttplug: `none`, buttplugAttachment: `none`}});
			label.appendChild(App.UI.SlaveInteract.generateRows(choiceOptionsArray, slave, "buttplug", false, refresh));
		}
		el.appendChild(label);

		let optionsArray = [];

		let clothingOption;
		App.Data.slaveWear.buttplugs.forEach(item => {
			clothingOption = {
				text: item.name,
				updateSlave: {buttplug: item.value},
				FS: item.fs
			};
			if (item.value !== "none") {
				// skip none in set, we set the link elsewhere.
				optionsArray.push(clothingOption);
			}
		});

		// Sort
		// No sort here since we want small -> large. optionsArray = optionsArray.sort((a, b) => (a.text > b.text) ? 1 : -1);

		// Options
		let links = document.createElement('div');
		links.className = "choices";
		links.appendChild(App.UI.SlaveInteract.generateRows(optionsArray, slave, "buttplug", true, refresh));
		el.appendChild(links);

		return el;
	}

	function buttplugAttachment() {
		let el = document.createElement('div');
		if (slave.buttplug === "none") {
			return el;
		}

		let label = document.createElement('div');
		label.append(`Anal accessory attachment: `);

		let choice = document.createElement('span');
		choice.style.fontWeight = "bold";
		choice.textContent = (`${slave.buttplugAttachment} `);
		label.appendChild(choice);

		if (slave.buttplugAttachment !== `none`) {
			let choiceOptionsArray = [];
			choiceOptionsArray.push({text: `None`, updateSlave: {buttplugAttachment: `none`}});
			label.appendChild(App.UI.SlaveInteract.generateRows(choiceOptionsArray, slave, "buttplugAttachment", false, refresh));
		}
		el.appendChild(label);

		let optionsArray = [];

		let clothingOption;
		App.Data.slaveWear.buttplugAttachments.forEach(item => {
			clothingOption = {
				text: item.name,
				updateSlave: {buttplugAttachment: item.value},
				FS: item.fs
			};
			if (item.value !== "none") {
				// skip none in set, we set the link elsewhere.
				optionsArray.push(clothingOption);
			}
		});

		// Sort
		optionsArray = optionsArray.sort((a, b) => (a.text > b.text) ? 1 : -1);

		// Options
		let links = document.createElement('div');
		links.className = "choices";
		links.appendChild(App.UI.SlaveInteract.generateRows(optionsArray, slave, "buttplugAttachment", true, refresh));
		el.appendChild(links);

		return el;
	}

	function vaginalAccessory() {
		// <<vaginalAccessoryDescription>>

		let el = document.createElement('div');

		let label = document.createElement('div');
		label.append(`Vaginal accessory: `);

		let choice = document.createElement('span');
		choice.style.fontWeight = "bold";
		choice.textContent = (`${slave.vaginalAccessory} `);
		label.appendChild(choice);

		if (slave.vaginalAccessory !== `none`) {
			let choiceOptionsArray = [];
			choiceOptionsArray.push({text: `None`, updateSlave: {vaginalAccessory: `none`}});
			label.appendChild(App.UI.SlaveInteract.generateRows(choiceOptionsArray, slave, "vaginalAccessory", false, refresh));
		}
		el.appendChild(label);

		let optionsArray = [];

		let clothingOption;
		App.Data.slaveWear.vaginalAccessories.forEach(item => {
			clothingOption = {
				text: item.name,
				updateSlave: {vaginalAccessory: item.value},
				FS: item.fs
			};
			if (item.value !== "none") {
				// skip none in set, we set the link elsewhere.
				optionsArray.push(clothingOption);
			}
		});

		// Sort
		// No sort here since we want small -> large. optionsArray = optionsArray.sort((a, b) => (a.text > b.text) ? 1 : -1);

		// Options
		let links = document.createElement('div');
		links.className = "choices";
		links.appendChild(App.UI.SlaveInteract.generateRows(optionsArray, slave, "vaginalAccessory", true, refresh));
		el.appendChild(links);

		return el;
	}

	function vaginalAttachment() {
		let el = document.createElement('div');
		if (["none", "bullet vibrator", "smart bullet vibrator"].includes(slave.vaginalAccessory)) {
			return el;
		}

		let label = document.createElement('div');
		label.append(`Vaginal accessory attachment: `);

		let choice = document.createElement('span');
		choice.style.fontWeight = "bold";
		choice.textContent = (`${slave.vaginalAttachment} `);
		label.appendChild(choice);

		if (slave.vaginalAttachment !== `none`) {
			let choiceOptionsArray = [];
			choiceOptionsArray.push({text: `None`, updateSlave: {vaginalAttachment: `none`}});
			label.appendChild(App.UI.SlaveInteract.generateRows(choiceOptionsArray, slave, "vaginalAttachment", false, refresh));
		}
		el.appendChild(label);

		let optionsArray = [];

		let clothingOption;
		App.Data.slaveWear.vaginalAttachments.forEach(item => {
			clothingOption = {
				text: item.name,
				updateSlave: {vaginalAttachment: item.value},
				FS: item.fs
			};
			if (item.value !== "none") {
				// skip none in set, we set the link elsewhere.
				optionsArray.push(clothingOption);
			}
		});

		// Sort
		optionsArray = optionsArray.sort((a, b) => (a.text > b.text) ? 1 : -1);

		// Options
		let links = document.createElement('div');
		links.className = "choices";
		links.appendChild(App.UI.SlaveInteract.generateRows(optionsArray, slave, "vaginalAttachment", true, refresh));
		el.appendChild(links);

		return el;
	}

	function dickAccessory() {
		// <<= App.Desc.dickAccessory($activeSlave)>>
		let el = document.createElement('div');

		let label = document.createElement('div');
		label.append(`Dick accessory: `);

		let choice = document.createElement('span');
		choice.style.fontWeight = "bold";
		choice.textContent = (`${slave.dickAccessory} `);
		label.appendChild(choice);

		if (slave.dickAccessory !== `none`) {
			let choiceOptionsArray = [];
			choiceOptionsArray.push({text: `None`, updateSlave: {dickAccessory: `none`}});
			label.appendChild(App.UI.SlaveInteract.generateRows(choiceOptionsArray, slave, "dickAccessory", false, refresh));
		}
		el.appendChild(label);

		let optionsArray = [];

		let clothingOption;
		App.Data.slaveWear.dickAccessories.forEach(item => {
			clothingOption = {
				text: item.name,
				updateSlave: {dickAccessory: item.value},
				FS: item.fs
			};
			if (item.value !== "none") {
				// skip none in set, we set the link elsewhere.
				optionsArray.push(clothingOption);
			}
		});

		// Sort
		// No sort here since we want small -> large. optionsArray = optionsArray.sort((a, b) => (a.text > b.text) ? 1 : -1);

		// Options
		let links = document.createElement('div');
		links.className = "choices";
		links.appendChild(App.UI.SlaveInteract.generateRows(optionsArray, slave, "dickAccessory", true, refresh));
		el.appendChild(links);

		return el;
	}

	function chastity() {
		let el = document.createElement('div');

		let label = document.createElement('div');
		label.append(`Chastity devices: `);

		let choice = document.createElement('span');
		choice.style.fontWeight = "bold";
		if (slave.choosesOwnChastity === 1) {
			choice.textContent = `choosing ${his} own chastity `;
		} else if (slave.chastityAnus === 1 && slave.chastityPenis === 1 && slave.chastityVagina === 1) {
			choice.textContent = `full chastity `;
		} else if (slave.chastityPenis === 1 && slave.chastityVagina === 1) {
			choice.textContent = `genital chastity `;
		} else if (slave.chastityAnus === 1 && slave.chastityPenis === 1) {
			choice.textContent = `combined chastity cage `;
		} else if (slave.chastityAnus === 1 && slave.chastityVagina === 1) {
			choice.textContent = `combined chastity belt `;
		} else if (slave.chastityVagina === 1) {
			choice.textContent = `chastity belt `;
		} else if (slave.chastityPenis === 1) {
			choice.textContent = `chastity cage `;
		} else if (slave.chastityAnus === 1) {
			choice.textContent = `anal chastity `;
		} else if (slave.chastityAnus === 0 && slave.chastityPenis === 0 && slave.chastityVagina === 0) {
			choice.textContent = `none `;
		} else {
			choice.textContent = `THERE HAS BEEN AN ERROR `;
		}
		label.appendChild(choice);

		if (slave.chastityAnus !== 0 || slave.chastityPenis !== 0 || slave.chastityVagina !== 0) {
			let choiceOptionsArray = [];
			choiceOptionsArray.push({
				text: `None`,
				updateSlave: {
					choosesOwnChastity: 0,
					chastityAnus: 0,
					chastityPenis: 0,
					chastityVagina: 0
				}
			});
			label.appendChild(App.UI.SlaveInteract.generateRows(choiceOptionsArray, slave, "chastity", false, refresh));
		}
		el.appendChild(label);

		let optionsArray = [];

		let clothingOption;
		App.Data.slaveWear.chastityDevices.forEach(item => {
			clothingOption = {
				text: item.name,
				updateSlave: {},
				FS: item.fs
			};
			Object.assign(clothingOption.updateSlave, item.updateSlave);
			if (item.value !== "none") {
				// skip none in set, we set the link elsewhere.
				optionsArray.push(clothingOption);
			}
		});

		// Sort
		// skip sort for this one too. optionsArray = optionsArray.sort((a, b) => (a.text > b.text) ? 1 : -1);

		// Options
		let links = document.createElement('div');
		links.className = "choices";
		links.appendChild(App.UI.SlaveInteract.generateRows(optionsArray, slave, "chastity", true, refresh));
		el.appendChild(links);

		return el;
	}

	function shopping() {
		return App.UI.DOM.passageLink(
			`Go shopping for more options`,
			"Wardrobe"
		);
	}

	/**
	 * @param {string} update
	 * @returns {Node}
	 */
	function colorOptions(update) {
		let el = new DocumentFragment();
		let colorChoice = App.UI.DOM.colorInput(
			slave[update],
			v => {
				slave[update] = v;
				refresh();
			}
		);
		el.appendChild(colorChoice);

		if (slave[update]) {
			el.appendChild(
				App.UI.DOM.link(
					` Reset`,
					() => {
						delete slave[update];
						refresh();
					},
				)
			);
		}
		return el;
	}

	function refresh() {
		App.Art.refreshSlaveArt(slave, 3, "art-frame");
		jQuery("#content-appearance").empty().append(App.UI.SlaveInteract.wardrobe(slave));
	}
};