code:
/**
 * @param {App.Entity.SlaveState} slave
 * @param {function():void} refresh
 * @returns {HTMLDivElement}
 */
App.UI.SlaveInteract.custom = function(slave, refresh) {
	const {
		He, His,
		he, his, him,
	} = getPronouns(slave);

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

	el.append(intro());

	App.UI.DOM.appendNewElement("h3", el, `Art`);
	el.append(
		customSlaveImage(),
		customHairImage()
	);

	App.UI.DOM.appendNewElement("h3", el, `Names`);
	el.append(
		playerTitle(),
		slaveFullName()
	);

	App.UI.DOM.appendNewElement("h3", el, `Description`);
	el.append(
		hair(),
		eyeColor(),
		customTattoo(),
		customOriginStory(),
		customDescription(),
		customLabel()
	);

	return el;

	function intro() {
		const frag = new DocumentFragment();
		let p;
		p = document.createElement('p');
		p.id = "rename";
		frag.append(p);

		p = document.createElement('p');
		p.className = "scene-p";
		p.append(`You may enter custom descriptors for your slave's hair color, hair style, tattoos, or anything else here. After typing, press `);
		p.appendChild(App.UI.DOM.makeElement("kbd", "enter"));
		p.append(` to commit your change. These custom descriptors will appear in descriptions of your slave, but will have no gameplay effect. Changing them is free.`);
		frag.append(p);
		return frag;
	}

	function playerTitle() {
		let playerTitle = document.createElement('p');
		const label = document.createElement('div');
		let result;
		if (slave.devotion >= -50) {
			if (slave.custom.title !== "") {
				label.textContent = `You have instructed ${him} to always refer to you as ${slave.custom.title}, which, should ${he} lisp, comes out as ${slave.custom.titleLisp}.`;
			} else {
				label.textContent = `You expect ${him} to refer to you as all your other slaves do.`;
			}
			result = document.createElement('div');
			result.id = "result";
			result.className = "choices";

			let hiddenTextBox = document.createElement('span');
			let shownTextBox = document.createElement('span');
			if (slave.custom.title === "") {
				hiddenTextBox.appendChild(
					App.UI.DOM.link(
						`Set a custom title for ${him} to address you as`,
						() => {
							jQuery('#result').empty().append(shownTextBox);
						}
					)
				);
				result.appendChild(hiddenTextBox);
				shownTextBox.textContent = `Custom title: `;
				shownTextBox.append(
					App.UI.DOM.makeTextBox(
						"",
						v => {
							slave.custom.title = v;
							jQuery('#result').empty().append(
								document.createTextNode(`${He}'ll try ${his} best to call you ${slave.custom.title}.`)
							);
							slave.custom.titleLisp = lispReplace(slave.custom.title);
						}
					)
				);
			} else {
				result.append(`${He}'s trying ${his} best to call you `);
				result.append(
					App.UI.DOM.makeTextBox(
						slave.custom.title,
						v => {
							slave.custom.title = v;
							jQuery('#result').empty().append(
								document.createTextNode(`${He}'ll try ${his} best to call you ${slave.custom.title}.`)
							);
							slave.custom.titleLisp = lispReplace(slave.custom.title);
						}
					)
				);
				result.appendChild(
					App.UI.DOM.link(
						` Stop using a custom title`,
						() => {
							jQuery('#result').empty().append(
								document.createTextNode(`${He} will no longer refer to you with a special title.`)
							);
							slave.custom.title = "";
							slave.custom.titleLisp = "";
						}
					)
				);
			}
			label.appendChild(result);
		} else {
			label.textContent = `You must break ${his} will further before ${he} will refer to you by a new title. `;
			if (SlaveStatsChecker.checkForLisp(slave)) {
				if (slave.custom.titleLisp && slave.custom.titleLisp !== "") {
					label.textContent += `For now, ${he} intends to keep calling you "${slave.custom.titleLisp}."`;
				}
			} else {
				if (slave.custom.title && slave.custom.title !== "") {
					label.textContent += `For now, ${he} intends to keep calling you "${slave.custom.title}."`;
				}
			}
		}
		playerTitle.appendChild(label);
		return playerTitle;
	}

	function slaveFullName() {
		let slaveFullNameNode = document.createElement('span');
		if (
			((slave.devotion >= -50 || slave.trust < -20) && (slave.birthName !== slave.slaveName)) ||
			(slave.devotion > 20 || slave.trust < -20)
		) {
			slaveFullNameNode.appendChild(slaveName());
			slaveFullNameNode.appendChild(slaveSurname());
		} else {
			slaveFullNameNode.textContent = `You must break ${his} will further before you can successfully force a new name on ${him}.`;
			slaveFullNameNode.className = "note";
		}

		return slaveFullNameNode;

		function slaveName() {
			const oldName = slave.slaveName;
			const oldSurname = slave.slaveSurname;
			// Slave Name
			let slaveNameNode = document.createElement('p');
			let label = document.createElement('div');
			let result = document.createElement('div');
			result.id = "result";
			result.className = "choices";
			const linkArray = [];

			label.append(`Change ${his} given name`);
			if (slave.birthName !== slave.slaveName) {
				label.append(` (${his} birth name was ${slave.birthName})`);
			}
			label.append(`: `);

			label.append(
				App.UI.DOM.makeTextBox(
					slave.slaveName,
					v => {
						slave.slaveName = v;
						updateName(slave, {oldName: oldName, oldSurname: oldSurname});
					},
					false,
				)
			);

			slaveNameNode.appendChild(label);

			if (slave.slaveName === slave.birthName) {
				linkArray.push(App.UI.DOM.disabledLink(`${He} has ${his} birth name`, [`Nothing to reset`]));
			} else {
				linkArray.push(App.UI.DOM.link(
					`Restore ${his} birth name`,
					() => {
						slave.slaveName = slave.birthName;
						updateName(slave, {oldName: oldName, oldSurname: oldSurname});
					}
				));
			}

			if (V.arcologies[0].FSPastoralist !== "unset") {
				if (slave.lactation > 0) {
					linkArray.push(chooseThreeNames(`Choose a random cow name for ${him}`, App.Data.misc.cowSlaveNames, "cow-names"));
				}
			}
			if (V.arcologies[0].FSIntellectualDependency !== "unset") {
				if (slave.intelligence + slave.intelligenceImplant < -10) {
					linkArray.push(chooseThreeNames(`Give ${him} a random stripper given name`, App.Data.misc.bimboSlaveNames, "bimbo-names"));
				}
			}
			if (V.arcologies[0].FSChattelReligionist !== "unset") {
				linkArray.push(chooseThreeNames(`Give ${him} a random devotional given name`, App.Data.misc.chattelReligionistSlaveNames, "devotional-names"));
			}
			if (slave.race === "catgirl") {
				linkArray.push(chooseThreeNames(`Give ${him} a random cat name`, App.Data.misc.catSlaveNames, "cat-names"));
			}
			result.append(App.UI.DOM.generateLinksStrip(linkArray));
			slaveNameNode.appendChild(result);
			return slaveNameNode;

			function chooseThreeNames(title, array, id) {
				const el = document.createElement("span");
				el.id = id;
				el.append(
					App.UI.DOM.link(
						title,
						() => {
							linkGuts();
						}
					)
				);
				return el;

				function linkGuts() {
					// Randomize the array
					const shuffled = array.sort(() => 0.5 - Math.random());

					// Get the first three new names
					const names = [];
					for (let i = 0; names.length < 3; i++) {
						if (i > shuffled.length) {
							break;
						}
						if (shuffled[i] !== slave.slaveName) {
							names.push(shuffled[i]);
						}
					}

					// return the three names as links
					const nameLinks = [];
					for (const name of names) {
						nameLinks.push(
							App.UI.DOM.link(
								name,
								() => {
									slave.slaveName = name;
									updateName(slave, {oldName: oldName, oldSurname: oldSurname});
								}
							)
						);
					}
					nameLinks.push(
						App.UI.DOM.link(
							"...",
							() => {
								linkGuts();
							}
						)
					);
					jQuery(`#${id}`).empty().append(App.UI.DOM.generateLinksStrip(nameLinks));
				}
			}
		}

		function slaveSurname() {
			// Slave Surname
			const oldName = slave.slaveName;
			const oldSurname = slave.slaveSurname;
			const linkArray = [];
			let slaveSurnameNode = document.createElement('p');
			let label = document.createElement('div');
			let result = document.createElement('div');
			result.id = "result";
			result.className = "choices";

			label.append(`Change ${his} surname`);
			if (slave.birthSurname !== slave.slaveSurname) {
				label.append(` (${his} birth surname was ${slave.birthSurname})`);
			}
			label.append(`: `);

			label.append(
				App.UI.DOM.makeTextBox(
					slave.slaveSurname,
					v => {
						slave.slaveSurname = v;
						updateName(slave, {oldName: oldName, oldSurname: oldSurname});
					},
					false,
				)
			);

			slaveSurnameNode.appendChild(label);

			if (slave.slaveSurname === slave.birthSurname) {
				linkArray.push(
					App.UI.DOM.disabledLink(
						`Restore ${his} birth surname`,
						[`${He} has ${his} birth surname`]
					)
				);
			} else {
				linkArray.push(App.UI.DOM.link(
					`Restore ${his} birth surname`,
					() => {
						slave.slaveSurname = slave.birthSurname;
						updateName(slave, {oldName: oldName, oldSurname: oldSurname});
					}
				));
			}
			if (getSlave(slave.mother) || getSlave(slave.father) || slave.mother === -1 || slave.father === -1) {
				linkArray.push(App.UI.DOM.link(
					`Regenerate ${his} surname based on current Universal Rules`,
					() => {
						regenerateSurname(slave);
						updateName(slave, {oldName: oldName, oldSurname: oldSurname});
					}
				));
			}
			if (V.surnameArcology) {
				linkArray.push(App.UI.DOM.link(
					`Give ${him} the arcology surname ${V.surnameArcology}`,
					() => {
						slave.slaveSurname = V.surnameArcology;
						updateName(slave, {oldName: oldName, oldSurname: oldSurname});
					}
				));
			}
			if (slave.slaveSurname) {
				linkArray.push(App.UI.DOM.link(
					`Take ${his} surname away`,
					() => {
						slave.slaveSurname = 0;
						updateName(slave, {oldName: oldName, oldSurname: oldSurname});
					}
				));
			}
			if (slave.relationship >= 5) {
				const spouse = getSlave(slave.relationshipTarget);
				if (spouse.slaveSurname && slave.slaveSurname !== spouse.slaveSurname) {
					const wifePronouns = getPronouns(spouse);
					linkArray.push(
						App.UI.DOM.link(
							`Give ${him} ${his} ${wifePronouns.wife}'s surname`,
							() => {
								slave.slaveSurname = spouse.slaveSurname;
								updateName(slave, {oldName: oldName, oldSurname: oldSurname});
							}
						)
					);
				}
			}
			if (slave.relationship === -3) {
				if (V.PC.slaveSurname && slave.slaveSurname !== V.PC.slaveSurname) {
					linkArray.push(
						App.UI.DOM.link(
							`Give ${him} your surname`,
							() => {
								slave.slaveSurname = V.PC.slaveSurname;
								updateName(slave, {oldName: oldName, oldSurname: oldSurname});
							}
						)
					);
				}
			}
			if (V.arcologies[0].FSRomanRevivalist !== "unset") {
				linkArray.push(
					App.UI.DOM.link(
						`Give ${him} a random full Roman name`,
						() => {
							slave.slaveName = App.Data.misc.romanSlaveNames.random();
							slave.slaveSurname = App.Data.misc.romanSlaveSurnames.random();
							updateName(slave, {oldName: oldName, oldSurname: oldSurname});
						}
					)
				);
			} else if (V.arcologies[0].FSAztecRevivalist !== "unset") {
				linkArray.push(
					App.UI.DOM.link(
						`Give ${him} a random full Aztec name`,
						() => {
							slave.slaveName = App.Data.misc.aztecSlaveNames.random();
							slave.slaveSurname = 0;
							updateName(slave, {oldName: oldName, oldSurname: oldSurname});
						}
					)
				);
			} else if (V.arcologies[0].FSEgyptianRevivalist !== "unset") {
				linkArray.push(
					App.UI.DOM.link(
						`Give ${him} a random full ancient Egyptian name`,
						() => {
							slave.slaveName = App.Data.misc.ancientEgyptianSlaveNames.random();
							slave.slaveSurname = 0;
							updateName(slave, {oldName: oldName, oldSurname: oldSurname});
						}
					)
				);
			} else if (V.arcologies[0].FSEdoRevivalist !== "unset") {
				linkArray.push(
					App.UI.DOM.link(
						`Give ${him} a random full feudal Japanese name`,
						() => {
							slave.slaveName = App.Data.misc.edoSlaveNames.random();
							slave.slaveSurname = App.Data.misc.edoSlaveSurnames.random();
							updateName(slave, {oldName: oldName, oldSurname: oldSurname});
						}
					)
				);
			} else if (V.arcologies[0].FSChineseRevivalist !== "unset") {
				linkArray.push(
					App.UI.DOM.link(
						`Give ${him} a random full Ancient Chinese name`,
						() => {
							slave.slaveName = App.Data.misc.chineseSlaveNames.random();
							slave.slaveSurname = App.Data.misc.chineseRevivalistSlaveSurnames.random();
							updateName(slave, {oldName: oldName, oldSurname: oldSurname});
						}
					)
				);
			}
			if (V.arcologies[0].FSDegradationist > -1) {
				linkArray.push(
					App.UI.DOM.link(
						`Give ${him} a degrading full name`,
						() => {
							DegradingName(slave);
							updateName(slave, {oldName: oldName, oldSurname: oldSurname});
						}
					)
				);
			}
			result.append(App.UI.DOM.generateLinksStrip(linkArray));
			slaveSurnameNode.appendChild(result);
			return slaveSurnameNode;
		}

		function updateName(slave, {oldName: oldName, oldSurname: oldSurname}) {
			App.UI.SlaveInteract.rename(slave, {oldName: oldName, oldSurname: oldSurname});
			refresh();
		}
	}

	function hair() {
		let hairNode = new DocumentFragment();
		hairNode.appendChild(hairStyle());
		hairNode.appendChild(hairColor());
		return hairNode;

		function hairStyle() {
			let hairStyleNode = document.createElement('p');
			let label = document.createElement('div');
			label.append(`Custom hair description: `);

			label.append(
				App.UI.DOM.makeTextBox(
					slave.hStyle,
					v => {
						slave.hStyle = v;
						refresh();
					}
				)
			);

			switch (slave.hStyle) {
				case "tails":
				case "dreadlocks":
				case "drills":
				case "cornrows":
				case "bangs":
					label.append(` "${His} hair is in ${slave.hStyle}."`);
					break;
				case "ponytail":
					label.append(` "${His} hair is in a ${slave.hStyle}."`);
					break;
				case "hime":
					label.append(` "${His} hair is in a ${slave.hStyle} cut."`);
					break;
				default:
					label.append(` "${His} hair is ${slave.hStyle}."`);
					break;
			}
			hairStyleNode.appendChild(label);

			let choices = document.createElement('div');
			choices.className = "choices";
			choices.appendChild(App.UI.DOM.makeElement('span', ` For best results, use a short, uncapitalized and unpunctuated description; for example: 'back in a ponytail'`, 'note'));
			hairStyleNode.appendChild(choices);
			return hairStyleNode;
		}

		function hairColor() {
			let hairStyleNode = document.createElement('p');
			let label = document.createElement('div');
			label.append(`Custom hair color: `);
			label.append(
				App.UI.DOM.makeTextBox(
					slave.hColor,
					v => {
						slave.hColor = v;
						refresh();
					}
				)
			);
			label.append(` "${His} hair is ${slave.hColor}."`);
			hairStyleNode.appendChild(label);

			let choices = document.createElement('div');
			choices.className = "choices";
			choices.appendChild(App.UI.DOM.makeElement('span', ` For best results, use a short, uncapitalized and unpunctuated description; for example: 'black with purple highlights'`, 'note'));
			hairStyleNode.appendChild(choices);
			return hairStyleNode;
		}
	}

	function eyeColor() {
		let eyeColorNode = document.createElement('p');
		let label = document.createElement('div');
		if (getLenseCount(slave) > 0) {
			label.textContent = `${He} is wearing ${App.Desc.eyesColor(slave, "", "lense", "lenses")}.`;
		} else {
			label.textContent = `${He} has ${App.Desc.eyesColor(slave)}.`;
		}
		eyeColorNode.appendChild(label);

		let choices = document.createElement('div');
		choices.className = "choices";

		let eye;

		if (hasLeftEye(slave)) {
			eye = document.createElement('div');
			eye.append(`Custom left eye color: `);
			eye.append(
				App.UI.DOM.makeTextBox(
					slave.eye.left.iris,
					v => {
						slave.eye.left.iris = v;
						refresh();
					}
				)
			);
			choices.appendChild(eye);
		}
		if (hasRightEye(slave)) {
			eye = document.createElement('div');
			eye.append(`Custom right eye color: `);
			eye.append(
				App.UI.DOM.makeTextBox(
					slave.eye.right.iris,
					v => {
						slave.eye.right.iris = v;
						refresh();
					}
				)
			);
			choices.appendChild(eye);
		}
		choices.appendChild(App.UI.DOM.makeElement('span', `For best results, use a short, uncapitalized and unpunctuated description; for example: 'blue'`, 'note'));
		eyeColorNode.appendChild(choices);
		return eyeColorNode;
	}

	function customTattoo() {
		let el = document.createElement('p');
		el.append(`Change ${his} custom tattoo: `);
		el.appendChild(App.UI.DOM.makeTextBox(
			slave.custom.tattoo,
			v => {
				slave.custom.tattoo = v;
				refresh();
			}));

		let choices = document.createElement('div');
		choices.className = "choices";
		choices.appendChild(App.UI.DOM.makeElement('span', `For best results, use complete sentences; for example: '${He} has blue stars tattooed along ${his} cheekbones.'`, 'note'));
		el.appendChild(choices);

		return el;
	}

	function customOriginStory() {
		let el = document.createElement('p');
		el.append(`Change ${his} origin story: `);
		el.appendChild(App.UI.DOM.makeTextBox(
			slave.origin,
			v => {
				slave.origin = v;
				refresh();
			}));

		let choices = document.createElement('div');
		choices.className = "choices";
		choices.appendChild(App.UI.DOM.makeElement('span', ` For best results, use complete, capitalized and punctuated sentences; for example: '${He} followed you home from the pet store.'`, 'note'));
		el.appendChild(choices);

		return el;
	}

	function customDescription() {
		let el = document.createElement('p');
		el.append(`Change ${his} custom description: `);
		el.appendChild(
			App.UI.DOM.makeTextBox(
				pronounsForSlaveProp(slave, slave.custom.desc),
				v => {
					slave.custom.desc = v;
					refresh();
				}
			)
		);

		let choices = document.createElement('div');
		choices.className = "choices";
		choices.appendChild(App.UI.DOM.makeElement('span', ` For best results, use complete, capitalized and punctuated sentences; for example: '${He} has a beauty mark above ${his} left nipple.'`, 'note'));
		el.appendChild(choices);

		return el;
	}

	function customLabel() {
		let el = document.createElement('p');
		el.append(`Change ${his} custom label: `);
		el.appendChild(App.UI.DOM.makeTextBox(
			slave.custom.label,
			v => {
				slave.custom.label = v;
				refresh();
			}));

		let choices = document.createElement('div');
		choices.className = "choices";
		choices.appendChild(App.UI.DOM.makeElement('span', ` For best results, use a short phrase; for example: 'Breeder.'`, 'note'));
		el.appendChild(choices);

		return el;
	}

	function customSlaveImage() {
		let el = document.createElement('p');
		el.append(`Assign ${him} a custom image: `);

		const textbox = document.createElement("input");
		textbox.value = slave.custom.image === null ? "" : slave.custom.image.filename;
		el.appendChild(textbox);

		let kbd = document.createElement('kbd');
		const select = document.createElement('select');
		select.style.border = "none";

		[
			"png",
			"jpg",
			"gif",
			"webm",
			"webp",
			"mp4"
		].forEach((fileType) => {
			const el = document.createElement('option');
			el.value = fileType;
			el.text = fileType.toUpperCase();
			select.add(el);
		});
		select.value = slave.custom.image ? slave.custom.image.format : "png";

		kbd.append(`.`);
		kbd.appendChild(select);
		el.appendChild(kbd);

		el.appendChild(
			App.UI.DOM.link(
				` Reset`,
				() => {
					slave.custom.image = null;
					refresh();
					App.Events.refreshEventArt(slave);
				},
			)
		);

		let choices = document.createElement('div');
		choices.className = "choices";
		let note = document.createElement('span');
		note.className = "note";
		note.append(`Place file in the `);
		note.appendChild(App.UI.DOM.makeElement('kbd', 'resources'));
		note.append(` folder. Choose the extension from the menu first, then enter the filename in the space and press enter. For example, for a file with the path `);
		note.appendChild(App.UI.DOM.makeElement('kbd', `\\bin\\resources\\headgirl.png`));
		note.append(`, choose `);
		note.appendChild(App.UI.DOM.makeElement('kbd', 'png'));
		note.append(` then enter `);
		note.appendChild(App.UI.DOM.makeElement('kbd', 'headgirl'));
		note.append(`.`);

		choices.appendChild(note);
		el.appendChild(choices);

		textbox.onchange = () => {
			const c = slave.custom;
			if (textbox.value.length === 0) {
				c.image = null;
			} else {
				if (c.image === null) {
					c.image = {
						filename: textbox.value,
						format: /** @type {FC.ImageFormat} */ (select.value)
					};
				} else {
					c.image.filename = textbox.value;
				}
				App.Events.refreshEventArt(slave);
			}
		};
		select.onchange = () => {
			if (slave.custom.image !== null) {
				slave.custom.image.format = /** @type {FC.ImageFormat} */ (select.value);
			}
		};

		return el;
	}

	function customHairImage() {
		let el = document.createElement('p');
		if (V.seeImages === 1 && V.imageChoice === 1) {
			if (!slave.custom.hairVector) {
				slave.custom.hairVector = 0;
			}
			el.append(`Assign ${him} a custom hair SVG image: `);

			el.appendChild(App.UI.DOM.makeTextBox(
				slave.custom.hairVector,
				v => {
					slave.custom.hairVector = v;
					refresh();
				}));

			el.appendChild(
				App.UI.DOM.link(
					` Reset`,
					() => {
						slave.custom.hairVector = 0;
						refresh();
						App.Events.refreshEventArt(slave);
					},
				)
			);
		}

		return el;
	}
};

repo_name: Mirarara/fc

license: mit


code:
App.UI.SlaveInteract.description = function(slave) {
	const el = new DocumentFragment();
	const descriptionLink = document.createElement("div");
	descriptionLink.style.fontStyle = "italic";
	descriptionLink.id = "description-link";

	if (V.seeDetails === 1) {
		const descriptionOptions = document.createElement("div");

		descriptionOptions.id = "description-options";
		el.append(descriptionOptions);

		el.append(App.Desc.longSlave(slave, {noArt: true}));

		descriptionLink.append(showOptions());
		el.append(descriptionLink);
	} else {
		descriptionLink.append(
			App.UI.DOM.link(
				"Show descriptions",
				() => {
					V.seeDetails = 1;
				},
				[],
				"Slave Interact"
			)
		);
		el.append(descriptionLink);
	}

	el.append(App.Reminders.slaveDisplay(slave.ID));

	return el;

	function showOptions() {
		return App.UI.DOM.link(
			"Description Options",
			() => {
				jQuery("#description-link").empty().append(hideOptions());
				jQuery("#description-options").empty().append(App.UI.descriptionOptions());
			}
		);
	}

	function hideOptions() {
		return App.UI.DOM.link(
			"Description Options",
			() => {
				jQuery("#description-link").empty().append(showOptions());
				jQuery("#description-options").empty().append();
			}
		);
	}
};


code:
/**
 * @param {App.Entity.SlaveState} slave
 * @returns {HTMLParagraphElement}
 */
App.UI.SlaveInteract.family = function(slave) {
	const p = document.createElement("p");
	p.id = "family";
	p.append(renderFamilyTree(V.slaves, slave.ID));

	return p;
};


code:
/**
 * @param {App.Entity.SlaveState} slave
 * @returns {DocumentFragment}
 */
App.UI.SlaveInteract.modify = function(slave) {
	const {he, his} = getPronouns(slave);
	let el = new DocumentFragment();

	const isAgent = [Job.AGENT, Job.AGENTPARTNER].includes(slave.assignment);

	App.UI.DOM.appendNewElement('p', el, isAgent ? "Recall your agent to modify them." : "Take slave to another room.", ["scene-intro"]);

	if (isAgent) {
		return el;
	}

	el.append(rooms());

	return el;

	/**
	 * Makes a paragraph of link to send slaves to specific rooms
	 * @returns {HTMLParagraphElement}
	 */
	function rooms() {
		const p = document.createElement("p");

		makeRoomLink(p, "Auto salon", "Salon", ' Modify hair (color, length, style), nails, and even skin color.');

		makeRoomLink(p, "Body mod studio", "Body Modification", ' Mark your slave with piercings, tattoos, brands or even scars.',
			() => {
				V.tattooChoice = undefined;
			},
		);

		makeRoomLink(p, "Remote surgery", "Remote Surgery", ` Surgically modify your slave with state of the art plastic surgery and more. Alter ${his} senses, skeletal structure, organs, and even more.`);

		// Prosthetics
		if (V.prostheticsUpgrade > 0) {
			makeRoomLink(p, "Configure cybernetics", "Prosthetics Configuration", ` Configure prosthetics, if ${he} has been surgically implanted with interfaces that support it.`,
				() => {
					V.prostheticsConfig = "main";
				}
			);
		}

		// Analyze Pregnancy
		if (V.pregnancyMonitoringUpgrade > 0) {
			makeRoomLink(p, "Internal scan", "Analyze Pregnancy", ` Full scan of abdomen and reproductive organs.`);
		}

		return p;
	}

	/**
	 * Create a link with a note to send a slave to a specific room
	 * @param {Node} c
	 * @param {string} caption
	 * @param {string} passage
	 * @param {string} note
	 * @param {function ():void} [handler]
	 */
	function makeRoomLink(c, caption, passage, note, handler = () => {}) {
		const res = document.createElement('div');
		c.appendChild(res);
		res.appendChild(App.UI.DOM.link(caption, handler, [], passage));
		App.UI.DOM.appendNewElement('span', res, note, "note");
		return res;
	}
};


code:
/**
 * @param {App.Entity.SlaveState} slave
 * @returns {DocumentFragment}
 */
App.UI.SlaveInteract.navigation = function(slave) {
	const f = new DocumentFragment();

	if (V.cheatMode) {
		App.UI.DOM.appendNewElement("div", f,
			App.UI.DOM.passageLink("Cheat Edit Slave", "Cheat Edit JS", () => {
				V.cheater = 1;
				delete V.tempSlave;
			}),
			"cheat-menu"
		);
	}

	const p = document.createElement("p");
	p.classList.add("center");

	const placeInLine = App.UI.SlaveInteract.placeInLine(slave);
	const div = App.UI.DOM.appendNewElement("div", p, null);
	const previous = App.UI.DOM.makeElement("span", null, ['margin-right']);
	const next = App.UI.DOM.makeElement("span", null, ['margin-left']);
	const name = App.UI.DOM.makeElement("span", slave.slaveName, ['slave-name', "si-header"]);

	previous.id = "prev-slave";
	next.id = "next-slave";

	previous.append(
		App.UI.DOM.makeElement("span", App.UI.Hotkeys.hotkeys("prev-slave"), ['hotkey']),
		" ",
		App.UI.DOM.makeElement("span", App.UI.DOM.passageLink("Prev", "Slave Interact", () => {
			V.AS = placeInLine[0];
		}), ["adjacent-slave"]),
	);
	next.append(
		App.UI.DOM.makeElement("span", App.UI.DOM.passageLink("Next", "Slave Interact", () => {
			V.AS = placeInLine[1];
		}), ["adjacent-slave"]),
		" ",
		App.UI.DOM.makeElement("span", App.UI.Hotkeys.hotkeys("next-slave"), ['hotkey']),
	);

	function content() {
		const frag = new DocumentFragment();

		frag.append(
			previous,
			name,
			' ',
			App.UI.DOM.makeElement("span", App.UI.favoriteToggle(slave, () => {
				App.UI.DOM.replace(div, content());
			}), ['si-header']),
			next,
		);

		return frag;
	}

	div.append(content());

	f.append(p);

	return f;
};


code:
/**
 * @param {App.Entity.SlaveState} slave
 * @param {function():void} refresh
 * @returns {DocumentFragment}
 */
App.UI.SlaveInteract.physicalRegimen = function(slave, refresh) {
	const {
		he,
		him,
		his,
		himself,
		He,
		His
	} = getPronouns(slave);

	const el = new DocumentFragment();

	el.append(
		drugs(),
		curatives(),
		aphrodisiacs(),
		fertility(),
		incubator(),
		nursery(),
		breederEligibility(),
		bloating(),
		hormones(),
		diet(),
		dietBase(),
		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", "flat"].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.isBetween(0, 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 < -2) {
				note += `${He} has been sterilized`;
			} else 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: ");
				/** @type {string} */
				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.capacity > 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.capacity - V.incubator.tanks.length);
						if (reservedIncubator > 0) {
							if (WL === 1) {
								title.textContent = `${His} child `;
							} else if (reservedIncubator < WL) {
								title.textContent = `${reservedIncubator} of ${his} children `;
							} else if (WL === 2) {
								title.textContent = `Both of ${his} children `;
							} else {
								title.textContent = `All ${reservedIncubator} of ${his} children `;
							}
							title.textContent += ` will be placed in ${V.incubator.name}. `;
							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.incubator.name}`;
						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;
	}

	/** 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:
/**
 * @param {App.Entity.SlaveState} slave
 * @param {function():void} refresh
 * @returns {DocumentFragment}
 */
App.UI.SlaveInteract.records = function(slave, refresh) {
	const el = new DocumentFragment();
	let r;
	let linkArray;
	const {
		He, His,
		his, him
	} = getPronouns(slave);

	if (V.studio === 1) {
		App.UI.DOM.appendNewElement("h3", el, "Media");
		slave.porn.spending = Math.clamp(Math.ceil(slave.porn.spending / 1000) * 1000, 0, 5000);

		if (slave.porn.prestige === 3) {
			App.UI.DOM.appendNewElement("div", el, `${He} is so prestigious in the realm of ${slave.porn.fameType} porn that ${his} fame is self-sustaining.`, ["note"]);
		} else if (slave.porn.feed === 0) {
			r = [];
			r.push(`The media hub is not releasing highlights of ${his} sex life.`);
			r.push(
				App.UI.DOM.link(
					"Release",
					() => {
						slave.porn.feed = 1;
						refresh();
					}
				)
			);
			App.Events.addNode(el, r, "div");
		} else {
			r = [];
			r.push(`The media hub is releasing highlights of ${his} sex life`);
			if (slave.porn.spending < 500) {
				r.push(`to those who can find it.`);
			} else if (slave.porn.spending < 2500) {
				r.push(`on several websites.`);
			} else if (slave.porn.spending > 5000) {
				r.push(`through your old distributor.`);
			} else {
				r.push(`on many websites.`);
			}
			if (slave.porn.spending === 0) {
				linkArray = [];
				linkArray.push(
					App.UI.DOM.link(
						"Halt",
						() => {
							slave.porn.feed = 0;
							slave.porn.focus = "none";
							refresh();
						}
					)
				);
				linkArray.push(
					App.UI.DOM.link(
						"Publicize",
						() => {
							slave.porn.spending += 1000;
							refresh();
						},
						[],
						"",
						`Will cost ${cashFormat(1000)} weekly.`
					)
				);
				r.push(App.UI.DOM.generateLinksStrip(linkArray));
				App.Events.addNode(el, r, "div");
			} else {
				r.push(
					App.UI.DOM.makeTextBox(
						slave.porn.spending,
						v => {
							slave.porn.spending = v;
						},
						true
					)
				);
				r.push(`weekly is spent to publicize them.`);

				linkArray = [];
				linkArray.push(
					App.UI.DOM.link(
						"Halt",
						() => {
							slave.porn.spending = 0;
							slave.porn.feed = 0;
							slave.porn.focus = "none";
							V.PCSlutContacts = 1;
							refresh();
						}
					)
				);
				if (slave.porn.spending <= 4000) {
					linkArray.push(
						App.UI.DOM.link(
							"Increase",
							() => {
								slave.porn.spending += 1000;
								refresh();
							},
							[],
							"",
							`Spending more than ${cashFormat(5000)} weekly will have no effect.`
						)
					);
				}
				linkArray.push(
					App.UI.DOM.link(
						"Decrease",
						() => {
							slave.porn.spending -= 1000;
							refresh();
						},
						[],
						"",
						`Will cost ${cashFormat(1000)} weekly.`
					)
				);
				r.push(App.UI.DOM.generateLinksStrip(linkArray));
				App.Events.addNode(el, r, "div");

				if (V.PC.career === "escort" || V.PC.career === "prostitute" || V.PC.career === "child prostitute") {
					r = [];
					if (V.PC.career === "escort") {
						r.push(`You retain some contacts from your past life in the industry that may be willing to cut you some discounts should you return to it.`);
					} else {
						r.push(`You were approached in the past to star in some adult films and they may be willing to cut you some discounts should you accept their offer.`);
					}
					if (V.PCSlutContacts !== 2) {
						r.push(`You are not baring your body for all to see.`);
						r.push(
							App.UI.DOM.link(
								`Star in porn for a discount`,
								() => {
									V.PCSlutContacts = 2;
									refresh();
								}
							)
						);
					} else {
						if (V.PC.career === "escort") {
							r.push(`You are starring in hardcore porn once more.`);
						} else if (V.PC.actualAge < V.minimumSlaveAge) {
							r.push(`You are taking part in porn that may disturb people.`);
						} else {
							r.push(`You are starring in some hardcore porn.`);
						}
						r.push(
							App.UI.DOM.link(
								`Stop doing porn for a discount`,
								() => {
									V.PCSlutContacts = 1;
									refresh();
								}
							)
						);
					}
					App.Events.addNode(el, r, "div");
				}
			}
			if (V.studioFeed === 1) {
				r = [];
				if (slave.porn.viewerCount < 100) {
					r.push(`${He} lacks the fame in porn needed to discern what ${his} feed is getting tagged as.`);
				} else {
					if (slave.porn.prestige > 0) {
						r.push(`${He} is known for ${slave.porn.fameType === "generic" ? `standard, vanilla` : slave.porn.fameType} porn${(slave.porn.prestige > 1) ? ` and viewers have grown to expect it from ${him}` : ``}.`);
					}
					if (slave.porn.focus === "none") {
						r.push(`You are allowing ${his} viewers to guide the direction of ${his} content.`);
					} else {
						r.push(`You are focusing attention on the ${slave.porn.focus} aspect of ${his} content.`);
					}
					r.push(App.Porn.genreChoiceLinks("Slave Interact", slave));
				}
				App.Events.addNode(el, r, "div");
			}
		}
	}
	App.UI.DOM.appendNewElement("h3", el, "Financial");
	App.UI.DOM.appendNewElement("p", el, slaveExpenses(slave));

	App.UI.DOM.appendNewElement("h3", el, `Statistics`);
	App.UI.DOM.appendNewElement("p", el, statistics());

	function statistics() {
		const div = document.createElement("div");
		const text = [];

		const slaves = [...slave.partners].filter(i => i > 0);
		const ownedSlaves = slaves.filter(s => getSlave(s));
		const unownedSlaves = slaves.length - ownedSlaves.length;
		const other = [];

		const ownedSlavesSpan = document.createElement("span");

		for (let i = 0; i < ownedSlaves.length; i++) {
			const innerSpan = document.createElement("span");
			const target = getSlave(ownedSlaves[i]);

			innerSpan.style.display = 'inline-block';	// hack to prevent span breaking line and giving unusable tooltip
			innerSpan.style.marginRight = '4px';

			if (ownedSlaves.length > 1) {
				if (i === ownedSlaves.length - 1) {
					innerSpan.append(
						` and `,
						contextualIntro(slave, target, true),
					);

					if (unownedSlaves > 0) {
						innerSpan.append(`, as well as ${numberWithPlural(unownedSlaves, 'slave')} you don't currently own`);
					}

					innerSpan.append(`.`);
				} else {
					innerSpan.append(contextualIntro(slave, target, true));

					if (ownedSlaves.length > 2) {
						innerSpan.append(`, `);
					}
				}
			} else {
				innerSpan.append(
					contextualIntro(slave, target, true, true),
					`.`,
				);
			}

			ownedSlavesSpan.append(innerSpan);
		}

		const partners = new Map([
			[-1, "you"],
			[-2, `citizens of ${V.arcologies[0].name}`],
			[-3, `your former master`],
			[-4, `another arcology owner`],
			[-6, `members of the Societal Elite`],
			[-8, `your animals`],
			[-9, `members of the Futanari Sisters`],
		]);

		for (const [ID, name] of partners) {
			if (slave.partners.has(ID)) {
				other.push(name);
			}
		}

		const link = App.UI.DOM.link(`${numberWithPluralOne(slaves.length, 'other slave')}`, () => {
			const innerDiv = document.createElement("div");

			innerDiv.append(
				`${slave.slaveName} has ${other.length > 0 ? `been fucked by ${toSentence(other)}, as well as `: `slept with`}`,
				ownedSlavesSpan
			);

			App.UI.DOM.replace(div, innerDiv);
		});

		if (slaves.length > 0) {
			text.push(
				`${He}'s had sex with`,
				link,
				`so far.`,
			);
		} else if (other.length === 0) {
			text.push(`${He} hasn't had sex with anyone yet.`);
		}

		if (other.length > 0) {
			text.push(`${He} has ${slaves.length > 0 ? `also` : `only`} had sex with ${toSentence(other)}.`);
		}

		App.Events.addNode(div, text);

		return div;
	}

	r = [];
	linkArray = [];
	if (V.slaveCostFactor > 1) {
		r.push(App.UI.DOM.makeElement("span", `The slave market is bullish; the price of slaves is high.`, ["yellow"]));
	} else if (V.slaveCostFactor < 1) {
		r.push(App.UI.DOM.makeElement("span", `The slave market is bearish; the price of slaves is low.`, ["yellow"]));
	}

	if (V.slaves.length < 2) {
		r.push("You cannot sell your last slave");
	} else if (slave.origin === "You bought $him from a body dump, completely broken." && (V.week - slave.weekAcquired <= 8)) {
		r.push(`A discarded slave must be kept for at least two months to ensure health before being sold.`);
	} else {
		if (slave.accent < 4) {
			linkArray.push(
				App.UI.DOM.link(
					`Sell ${him}`,
					() => {
						cashX(-500, "personalBusiness", slave);
					},
					[],
					"Sell Slave",
					`Listing ${him} for sale will cost ${cashFormat(500)}`
				)
			);
		} else {
			r.push(`${His} lack of language and basic life skills is a red sign to most slave appraisers. ${He} must not act like a child to be sold without raising suspicion.`);
		}
		if ((V.seeAge !== 0) && (slave.indenture < 1)) {
			linkArray.push(
				App.UI.DOM.passageLink(
					`Retire ${him}`,
					"retire",
				)
			);
		}
		linkArray.push(
			App.UI.DOM.passageLink(
				`Discard ${him}`,
				"Discard Confirm",
			)
		);
		if (V.seeExtreme) {
			if (V.threatened[0].includes(slave.ID)) {
				linkArray.push(
					App.UI.DOM.disabledLink(
						`Threaten ${his} life`,
						[
							`You've already threatened ${him} this week.`,
						]
					)
				);
			} else {
				linkArray.push(
					App.UI.DOM.passageLink(
						`Threaten ${his} life`,
						"KillSlave",
						() => {
							V.threatened[0].push(slave.ID);
						}
					)
				);
			}
		}
	}
	linkArray.push(
		App.UI.DOM.passageLink(
			`Export this slave`,
			"Export Slave",
		)
	);
	if (V.cheatMode) {
		linkArray.push(
			App.UI.DOM.passageLink(
				`Import a slave`,
				"Import Slave",
			)
		);
	}
	r.push(App.UI.DOM.generateLinksStrip(linkArray));
	App.Events.addNode(el, r, "p");
	return el;
};


code:
/**
 * @param {App.Entity.SlaveState} slave
 * @param {function():void} refresh
 * @returns {DocumentFragment}
 */
App.UI.SlaveInteract.rules = function(slave, refresh) {
	const frag = new DocumentFragment();
	let p;
	let div;
	let array;
	/**
	 * @type {Array<listChoice>}
	 */
	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] ? "Include" : "Exempt";

		p.append(`Will ${slave[exclude] ? "not " : ""}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 (App.Data.misc.facilityCareers.includes(slave.assignment)) {
			App.UI.DOM.appendNewElement("span", p, ` ${His} living conditions are managed by ${his} assignment.`, ["note"]);
		} else if ((slave.assignment === Job.HEADGIRL) && (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 === Job.BODYGUARD) && (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({
					value: "luxurious",
					disabled: ["No luxurious rooms available"]
				});
			}

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

		// Rest
		div = document.createElement("div");
		div.append("Sleep rules: ");
		if ([Job.NURSE, Job.HEADGIRL, Job.TEACHER, Job.STEWARD, Job.MATRON, Job.FARMER, Job.MADAM, Job.WARDEN, Job.DJ, Job.MILKMAID].includes(slave.assignment)) {
			App.UI.DOM.appendNewElement("span", div, ` ${His} sleeping schedule is managed by ${his} assignment.`, "note");
		} else if ([Job.GLORYHOLE, Job.FARMYARD, Job.CLUB, Job.PUBLIC, Job.WHORE, Job.BROTHEL, Job.SUBORDINATE, Job.HOUSE, Job.QUARTER, Job.FUCKTOY, Job.MASTERSUITE, Job.MILKED].includes(slave.assignment) || (V.dairyRestraintsSetting < 2 && slave.assignment === Job.DAIRY)) {
			choices = [
				{value: "none", tooltip: "Never"},
				{value: "cruel", tooltip: "When Exhausted"},
				{value: "restrictive", tooltip: "When Fatigued"},
				{value: "permissive", tooltip: "When Tired"},
				{value: "mandatory", tooltip: "Every Week"},
			];
			div.append(listChoices(choices, "rest"));
		} else {
			App.UI.DOM.appendNewElement("span", div, ` ${His} assignment does not allow setting a sleeping schedule.`, ["note"]);
		}
		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", tooltip: App.UI.DOM.combineNodes(`Increases `, App.UI.DOM.makeElement("span", `fear`, ["trust", "dec"]), ` when the slave is punished.`)},
			{value: "whipping", tooltip: App.UI.DOM.combineNodes(`Significantly increases `, App.UI.DOM.makeElement("span", `fear`, ["trust", "dec"]), ` at the cost of `, App.UI.DOM.makeElement("span", `health`, ["health", "dec"]), ` when the slave is punished.`)},
			{value: "chastity", tooltip: App.UI.DOM.combineNodes(`Increases both `, App.UI.DOM.makeElement("span", `fear`, ["trust", "dec"]), ` and `, App.UI.DOM.makeElement("span", `devotion`, ["devotion", "inc"]), ` at the cost of `, App.UI.DOM.makeElement("span", `libido`, ["libido", "dec"]), ` when the slave is punished.`)},
			{value: "situational", tooltip: App.UI.DOM.combineNodes(`Increases `, App.UI.DOM.makeElement("span", `fear`, ["trust", "dec"]), ` when the slave is punished.`)},
		];
		div.append(listChoices(choices, "punishment"));
		p.append(div);

		// Reward
		div = document.createElement("div");
		div.append("Typical reward: ");
		choices = [
			{value: "relaxation", tooltip: App.UI.DOM.combineNodes(`Improves `, App.UI.DOM.makeElement("span", `health`, ["health", "inc"]), ` when a reward is earned.`)},
			{value: "drugs", tooltip: App.UI.DOM.combineNodes(`Significantly improves `, App.UI.DOM.makeElement("span", `devotion`, ["devotion", "inc"]), ` at the cost of `, App.UI.DOM.makeElement("span", `health`, ["health", "dec"]), ` when a reward is earned.`)},
			{value: "orgasm", tooltip: App.UI.DOM.combineNodes(`Improves `, App.UI.DOM.makeElement("span", `devotion`, ["devotion", "inc"]), ` and raises `, App.UI.DOM.makeElement("span", `libido`, ["libido", "inc"]), ` when a reward is earned.`)},
			{value: "situational", tooltip: App.UI.DOM.combineNodes(`Improves `, App.UI.DOM.makeElement("span", `devotion`, ["devotion", "inc"]), ` when a reward is earned.`)},
		];
		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) {
				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;

	/**
	 * @typedef {Object} listChoice
	 * @property {string} value
	 * @property {string} [title]
	 * @property {string|HTMLElement|DocumentFragment} [tooltip]
	 * @property {Array<string>} [disabled]
	 */

	/**
	 * @param {Array<listChoice>} choices
	 * @param {string} property
	 * @returns {HTMLUListElement}
	 */
	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,
						c.tooltip ? ["Current Setting", c.tooltip] : ["Current Setting"]
					)
				);
			} else {
				links.push(
					App.UI.DOM.link(
						title,
						() => {
							slave.rules[property] = c.value;
							refresh();
						},
						[],
						"",
						c.tooltip ? c.tooltip : ""
					)
				);
			}
		}
		return App.UI.DOM.generateLinksStrip(links);
	}

	function orgasm(slave) {
		const el = document.createElement('div');

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

		const choices = [
			{
				title: "Masturbation",
				value: "masturbation",
				enabled: `Will be allowed to pleasure ${himself}`,
				disabled: `Will not be allowed to pleasure ${himself}`,
			},
			{
				title: "Partner",
				value: "partner",
				enabled: `Will be allowed sexual contact with ${his} romantic partner`,
				disabled: `Will not be allowed sexual contact with ${his} romantic partner`,
			},
			{
				title: "Facility leaders",
				value: "facilityLeader",
				enabled: `Development facility leaders are allowed to satisfy ${his} sexual needs while ${he} is assigned to their facility`,
				disabled: `Development facility leaders are not allowed to satisfy ${his} sexual needs while ${he} is assigned to their facility`,
			},
			{
				title: "Family",
				value: "family",
				enabled: `Will be allowed sexual contact with close family members`,
				disabled: `Will not be allowed sexual contact with close family members`,
			},
			{
				title: "Other slaves",
				value: "slaves",
				enabled: `Will be allowed sexual contact with other slaves`,
				disabled: `Will not be allowed sexual contact with other slaves`,
			},
			{
				title: "Master",
				value: "master",
				enabled: `You will fuck ${him} when ${he} needs it`,
				disabled: `You will not fuck ${him} when ${he} needs it`,
				master: true
			},
		];

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

		return el;

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

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

			function makeLinks() {
				const allow = orgasmObj.master ? `Grant` : `Allow`;
				const forbid = orgasmObj.master ? `Deny` : `Forbid`;
				if (!slave.rules.release[orgasmObj.value]) {
					linkArray.push(App.UI.DOM.link(allow, () => {
						slave.rules.release[orgasmObj.value] = 1;
						refresh();
					}));
					linkArray.push(App.UI.DOM.disabledLink(forbid, [orgasmObj.disabled]));
				} else {
					linkArray.push(App.UI.DOM.disabledLink(allow, [orgasmObj.enabled]));
					linkArray.push(App.UI.DOM.link(forbid, () => {
						slave.rules.release[orgasmObj.value] = 0;
						refresh();
					}));
				}
			}
		}
	}

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

		if (slave.piercing.genitals.smart || 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`);
			level.set(`Disabled`, `off`);

			// 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.piercing.genitals.smart) {
				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("BDSM", 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);
		}
	}
};


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 {FC.FutureSociety} [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.
		/** @type {boolean|string} */
		let unlocked;
		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); },
						[],
						"",
						item.note ? item.note : ""
					)
				);

				if (item.FS) {
					link.append(App.UI.DOM.spanWithTooltip(`FS`,
						FutureSocieties.displayAdj(item.FS), "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();
	}
};