code:
:: rules autosurgery js [script]

window.rulesAutosurgery = (function() {
	"use strict";
	let V;
	let r;
	return rulesAutoSurgery;

	function rulesAutoSurgery(slave) {
		V = State.variables;
		r = "";
		const surgeries = [];
		const thisSurgery = ProcessHGTastes(slave);
		console.log(thisSurgery);
		if (slave.health > 20)
			CommitSurgery(slave, thisSurgery, surgeries);
		if (surgeries.length > 0)
			PrintResult(slave, thisSurgery, surgeries);
		return r;
	}

	function autoSurgerySelector(slave, ruleset) {
		const surgery = {};
		ruleset.forEach(rule => {
			Object.keys(rule)
				.filter(key => key.startsWith("surgery_") && rule[key] !== "no default setting")
				.forEach(key => {
					surgery[key] = rule[key];
				});
		});
		return surgery;
	}

	function ProcessHGTastes(slave) {
		let thisSurgery;
		switch (V.HGTastes) {
		case 1:
			thisSurgery = {
				surgery_lactation: 0,
				surgery_cosmetic: 1,
				surgery_faceShape: "cute",
				surgery_lips: 10,
				surgery_hips: 0,
				surgery_hipsImplant: 0,
				surgery_butt: 0,
				surgery_accent: 0,
				surgery_shoulders: 0,
				surgery_shouldersImplant: 0,
				surgery_boobs: 0,
				surgery_holes: 0
			};
			break ;
		case 2:
			thisSurgery = {
				surgery_lactation: 0,
				surgery_cosmetic: 1,
				surgery_faceShape: "cute",
				surgery_lips: 60,
				surgery_hips: 0,
				surgery_hipsImplant: 0,
				surgery_butt: 4,
				surgery_accent: 0,
				surgery_shoulders: 0,
				surgery_shouldersImplant: 0,
				surgery_boobs: 1200,
				surgery_holes: 0
			};
			break;
		case 3:
			thisSurgery = {
				surgery_lactation: 0,
				surgery_cosmetic: 1,
				surgery_faceShape: "cute",
				surgery_lips: 95,
				surgery_hips: 0,
				surgery_hipsImplant: 0,
				surgery_butt: 8,
				surgery_accent: 0,
				surgery_shoulders: 0,
				surgery_shouldersImplant: 0,
				surgery_boobs: 10000,
				surgery_holes: 2
			};
			break;
		case 4:
			thisSurgery = {
				surgery_lactation: 1,
				surgery_cosmetic: 1,
				surgery_faceShape: "cute",
				surgery_lips: 10,
				surgery_hips: 3,
				surgery_hipsImplant: 0,
				surgery_butt: 0,
				surgery_accent: 0,
				surgery_shoulders: 0,
				surgery_shouldersImplant: 0,
				surgery_boobs: 0,
				surgery_holes: 0
			};
			break;
		default:
			thisSurgery = autoSurgerySelector(
				slave,
				V.defaultRules
					.filter(x => ruleApplied(slave, x) && x.set.autoSurgery === 1)
					.map(x => x.set));
			if ((thisSurgery.surgery_hips !== "no default setting") && (thisSurgery.surgery_butt !== "no default setting")) {
				if (slave.hips < -1) {
					if (thisSurgery.surgery_butt > 2)
						thisSurgery.surgery_butt = 2;
				} else if (slave.hips < 0) {
					if (thisSurgery.surgery_butt > 4)
						thisSurgery.surgery_butt = 4;
				} else if (slave.hips > 0) {
					if (thisSurgery.surgery_butt > 8)
						thisSurgery.surgery_butt = 8;
				} else if (slave.hips > 1) {
					true;
				} else {
					if (thisSurgery.surgery_butt > 6)
						thisSurgery.surgery_butt = 6;
				}
			}
			break;
		}
		return thisSurgery;
	}

	function CommitSurgery(slave, thisSurgery, surgeries) {
		if ((slave.eyes == -1) && (thisSurgery.surgery_eyes == 1)) {
			surgeries.push("surgery to correct her vision");
			slave.eyes = 1;
			V.cash -= V.surgeryCost;
			if (V.PC.medicine >= 100) slave.health -= 5;
			else slave.health -= 10;

		} else if ((slave.eyes == 1) && (thisSurgery.surgery_eyes == -1)) {
			surgeries.push("surgery to blur her vision");
			slave.eyes = -1;
			V.cash -= V.surgeryCost;
			if (V.PC.medicine >= 100) slave.health -= 5;
			else slave.health -= 10;

		} else if ((slave.lactation == 2) && (thisSurgery.surgery_lactation == 0)) {
			surgeries.push("surgery to remove her lactation implants");
			slave.lactation = 0;
			V.cash -= V.surgeryCost;
			if (V.PC.medicine >= 100) slave.health -= 5;
			else slave.health -= 10;

		} else if (slave.lactation != 2 && (thisSurgery.surgery_lactation == 1)) {
			surgeries.push("lactation inducing implanted drugs");
			slave.lactation = 2;
			V.cash -= V.surgeryCost;
			if (V.PC.medicine >= 100) slave.health -= 5;
			else slave.health -= 10;

		} else if ((slave.prostate == 2) && (thisSurgery.surgery_prostate == 0)) {
			surgeries.push("surgery to remove her prostate implant");
			slave.prostate = 0;
			V.cash -= V.surgeryCost;
			if (V.PC.medicine >= 100) slave.health -= 5;
			else slave.health -= 10;

		} else if (slave.prostate == 1 && (thisSurgery.surgery_prostate == 1)) {
			surgeries.push("a precum production enhancing drug implant");
			slave.prostate = 2;
			V.cash -= V.surgeryCost;
			if (V.PC.medicine >= 100) slave.health -= 5;
			else slave.health -= 10;

		} else if ((slave.anus > 3) && (thisSurgery.surgery_cosmetic > 0)) {
			surgeries.push("a restored anus");
			slave.anus = 3;
			if (slave.analSkill > 10)
				slave.analSkill -= 10;
			V.cash -= V.surgeryCost;
			if (V.PC.medicine >= 100) slave.health -= 5;
			else slave.health -= 10;

		} else if ((slave.vagina > 3) && (thisSurgery.surgery_cosmetic > 0)) {
			surgeries.push("a restored pussy");
			slave.vagina = 3;
			if (slave.vaginalSkill > 10)
				slave.vaginalSkill -= 10;
			V.cash -= V.surgeryCost;
			if (V.PC.medicine >= 100) slave.health -= 5;
			else slave.health -= 10;

		} else if ((slave.faceImplant <= 15) && (slave.face <= 95) && (thisSurgery.surgery_cosmetic > 0)) {
			surgeries.push("a nicer face");
			if (slave.faceShape == "masculine") slave.faceShape = "androgynous";
			slave.faceImplant += 25-5*Math.trunc(V.PC.medicine/50)-5*V.surgeryUpgrade;
			slave.face = Math.clamp(slave.face+20,-100,100);
			V.cash -= V.surgeryCost;
			if (V.PC.medicine >= 100) slave.health -= 5;
			else slave.health -= 10;

		} else if ((slave.faceImplant <= 15) && (slave.ageImplant != 1) && (slave.visualAge >= 25) && (thisSurgery.surgery_cosmetic > 0)) {
			surgeries.push("an age lift");
			slave.ageImplant = 1;
			slave.faceImplant += 25-5*Math.trunc(V.PC.medicine/50)-5*V.surgeryUpgrade;
			if (slave.visualAge > 80) slave.visualAge -= 40;
			else if (slave.visualAge >= 70) slave.visualAge -= 30;
			else if (slave.visualAge > 50) slave.visualAge -= 20;
			else if (slave.visualAge > 36) slave.visualAge -= 10;
			else slave.visualAge -= 5;
			V.cash -= V.surgeryCost;
			if (V.PC.medicine >= 100) slave.health -= 5;
			else slave.health -= 10;

		} else if (((slave.underArmHStyle != "bald" && slave.underArmHStyle != "hairless") || (slave.pubicHStyle != "bald" && slave.pubicHStyle != "hairless")) && (thisSurgery.surgery_bodyhair == 2)) {
			surgeries.push("body hair removal");
			if (slave.underArmHStyle != "hairless") slave.underArmHStyle = "bald";
			if (slave.pubicHStyle != "hairless") slave.pubicHStyle = "bald";
			V.cash -= V.surgeryCost;

		} else if ((slave.bald == 0 || slave.hStyle != "bald") && (thisSurgery.surgery_hair == 2)) {
			surgeries.push("hair removal");
			slave.hStyle = "bald";
			slave.bald = 1;
			V.cash -= V.surgeryCost;

		} else if ((slave.weight >= 10) && (thisSurgery.surgery_cosmetic > 0)) {
			surgeries.push("liposuction");
			slave.weight -= 50;
			V.cash -= V.surgeryCost;
			if (V.PC.medicine >= 100) slave.health -= 5;
			else slave.health -= 10;

		} else if ((slave.voice == 1) && (slave.voiceImplant == 0) && (thisSurgery.surgery_cosmetic > 0)) {
			surgeries.push("a feminine voice");
			slave.voice += 1;
			slave.voiceImplant += 1;
			V.cash -= V.surgeryCost;
			if (V.PC.medicine >= 100) slave.health -= 5;
			else slave.health -= 10;

		} else if ((slave.waist >= -10) && (thisSurgery.surgery_cosmetic > 0)) {
			surgeries.push("a narrower waist");
			slave.waist -= 20;
			V.cash -= V.surgeryCost;
			if (V.PC.medicine >= 100) slave.health -= 5;
			else slave.health -= 10;

		} else if (((slave.boobShape == "saggy") || (slave.boobShape == "downward-facing")) && (thisSurgery.surgery_cosmetic > 0) && (slave.breastMesh != 1)) {
			surgeries.push("a breast lift");
			slave.boobShape = "normal";
			V.cash -= V.surgeryCost;
			if (V.PC.medicine >= 100) slave.health -= 5;
			else slave.health -= 10;

		} else if (((slave.boobShape == "normal") || (slave.boobShape == "wide-set")) && (thisSurgery.surgery_cosmetic > 0) && (slave.breastMesh != 1)) {
			if (slave.boobs > 800)
				slave.boobShape = "torpedo-shaped";
			else
				slave.boobShape = "perky";
			surgeries.push("more interestingly shaped breasts");
			V.cash -= V.surgeryCost;
			if (V.PC.medicine >= 100) slave.health -= 5;
			else slave.health -= 10;

		} else if ((thisSurgery.surgery_lips == 0) && (slave.lipsImplant > 0)) {
			surgeries.push("surgery to remove her lip implants");
			slave.lips -= slave.lipsImplant;
			slave.lipsImplant = 0;
			if (slave.oralSkill > 10)
				slave.oralSkill -= 10;
			V.cash -= V.surgeryCost;
			if (V.PC.medicine >= 100) slave.health -= 5;
			else slave.health -= 10;

		} else if ((slave.lips <= 95) && (slave.lips < thisSurgery.surgery_lips)) {
			if (thisSurgery.surgery_lips !== "no default setting") {
				surgeries.push("bigger lips");
				slave.lipsImplant += 10;
				slave.lips += 10;
				if (slave.oralSkill > 10)
					slave.oralSkill -= 10;
				V.cash -= V.surgeryCost;
				if (V.PC.medicine >= 100) slave.health -= 5;
				else slave.health -= 10;
			}

		} else if ((slave.faceImplant <= 45) && (slave.face <= 95) && (thisSurgery.surgery_cosmetic == 2)) {
			surgeries.push("a nicer face");
			if (slave.faceShape == "masculine") slave.faceShape = "androgynous";
			slave.faceImplant += 25-5*Math.trunc(V.PC.medicine/50)-5*V.surgeryUpgrade;
			slave.face = Math.clamp(slave.face+20,-100,100);
			V.cash -= V.surgeryCost;
			if (V.PC.medicine >= 100) slave.health -= 5;
			else slave.health -= 10;

		} else if ((slave.hips < 1) && (slave.hips < thisSurgery.surgery_hips) && (V.surgeryUpgrade == 1)) {
			surgeries.push("wider hips");
			slave.hips++;
			slave.hipsImplant++;
			V.cash -= V.surgeryCost;
			if (V.PC.medicine >= 100) slave.health -= 5;
			else slave.health -= 10;

		} else if ((slave.faceImplant <= 45) && (slave.ageImplant != 1) && (slave.visualAge >= 25) && (thisSurgery.surgery_cosmetic == 2)) {
			surgeries.push("an age lift");
			slave.ageImplant = 1;
			if (slave.visualAge > 80) {
				slave.visualAge -= 40;
			} else if (slave.visualAge >= 70) {
				slave.visualAge -= 30;
			} else if (slave.visualAge > 50) {
				slave.visualAge -= 20;
			} else if (slave.visualAge > 36) {
				slave.visualAge -= 10;
			} else {
				slave.visualAge -= 5;
			}
			slave.faceImplant += 25-5*Math.trunc(V.PC.medicine/50)-5*V.surgeryUpgrade;
			V.cash -= V.surgeryCost;
			if (V.PC.medicine >= 100) slave.health -= 5;
			else slave.health -= 10;

		} else if ((slave.waist >= -95) && (thisSurgery.surgery_cosmetic == 2) && (V.seeExtreme == 1)) {
			surgeries.push("a narrower waist");
			slave.waist = Math.clamp(slave.waist-20,-100,100);
			V.cash -= V.surgeryCost;
			if (V.PC.medicine >= 100) slave.health -= 5;
			else slave.health -= 10;

		} else if ((slave.voice < 3) && (slave.voiceImplant == 0) && (thisSurgery.surgery_cosmetic == 2)) {
			surgeries.push("a bimbo's voice");
			slave.voice += 1;
			slave.voiceImplant += 1;
			V.cash -= V.surgeryCost;
			if (V.PC.medicine >= 100) slave.health -= 5;
			else slave.health -= 10;

		} else if ((thisSurgery.surgery_butt == 0) && (slave.buttImplant > 0)) {
			surgeries.push("surgery to remove her butt implants");
			slave.butt -= slave.buttImplant;
			slave.buttImplant = 0;
			slave.buttImplantType = 0;
			V.cash -= V.surgeryCost;
			if (V.PC.medicine >= 100) slave.health -= 5;
			else slave.health -= 10;

		} else if ((thisSurgery.surgery_boobs == 0) && (slave.boobsImplant > 0)) {
			surgeries.push("surgery to remove her boob implants");
			slave.boobs -= slave.boobsImplant;
			slave.boobsImplant = 0;
			slave.boobsImplantType = 0;
			V.cash -= V.surgeryCost;
			if (V.PC.medicine >= 100) slave.health -= 5;
			else slave.health -= 10;
		} else if ((slave.butt <= 3) && (slave.butt < thisSurgery.surgery_butt)) {
			if (thisSurgery.surgery_butt !== "no default setting") {
				surgeries.push("a bigger butt");
				slave.buttImplant = 1;
				slave.butt += 1;
				V.cash -= V.surgeryCost;
				if (V.PC.medicine >= 100) slave.health -= 5;
				else slave.health -= 10;
			}
		} else if ((slave.boobs <= 600) && (slave.lactation < 2) && (slave.boobs+400 <= thisSurgery.surgery_boobs)) {
			if (thisSurgery.surgery_boobs !== "no default setting") {
				surgeries.push("bigger boobs");
				slave.boobsImplant += 400;
				slave.boobs += 400;
				V.cash -= V.surgeryCost;
				if (V.PC.medicine >= 100) slave.health -= 5;
				else slave.health -= 10;
			}
		} else if ((slave.boobs <= 600) && (slave.lactation < 2) && (slave.boobs+200 <= thisSurgery.surgery_boobs)) {
			if (thisSurgery.surgery_boobs !== "no default setting") {
				surgeries.push("modestly bigger boobs");
				slave.boobsImplant += 200;
				slave.boobs += 200;
				V.cash -= V.surgeryCost;
				if (V.PC.medicine >= 100) slave.health -= 5;
				else slave.health -= 10;
			}

		} else if ((slave.butt <= 5) && (slave.butt < thisSurgery.surgery_butt)) {
			if (thisSurgery.surgery_butt !== "no default setting") {
				surgeries.push("a bigger butt");
				slave.buttImplant = 1;
				slave.butt += 1;
				V.cash -= V.surgeryCost;
				if (V.PC.medicine >= 100) slave.health -= 5;
				else slave.health -= 10;
			}

		} else if ((slave.boobs <= 2000) && (slave.lactation < 2) && (slave.boobs+400 < thisSurgery.surgery_boobs)) {
			if (thisSurgery.surgery_boobs !== "no default setting") {
				surgeries.push("bigger boobs");
				slave.boobsImplant += 400;
				slave.boobs += 400;
				V.cash -= V.surgeryCost;
				if (V.PC.medicine >= 100) slave.health -= 5;
				else slave.health -= 10;
			}

		} else if ((slave.anus > 0) && (V.surgeryUpgrade == 1) && (thisSurgery.surgery_holes == 2)) {
			surgeries.push("a virgin anus");
			slave.anus = 0;
			if (slave.analSkill > 10) {
				slave.analSkill -= 10;
			}
			V.cash -= V.surgeryCost;
			if (V.PC.medicine >= 100) slave.health -= 5;
			else slave.health -= 10;

		} else if ((slave.vagina > 0) && (V.surgeryUpgrade == 1) && (thisSurgery.surgery_holes == 2)) {
			surgeries.push("a virgin pussy");
			slave.vagina = 0;
			if (slave.vaginalSkill > 10)
				slave.vaginalSkill -= 10;
			V.cash -= V.surgeryCost;
			if (V.PC.medicine >= 100) slave.health -= 5;
			else slave.health -= 10;

		} else if ((slave.hips < 2) && (slave.hips < thisSurgery.surgery_hips) && (V.surgeryUpgrade == 1)) {
			surgeries.push("wider hips");
			slave.hips++;
			slave.hipsImplant++;
			V.cash -= V.surgeryCost;
			if (V.PC.medicine >= 100) slave.health -= 5;
			else slave.health -= 10;

		} else if ((slave.anus > 1) && (thisSurgery.surgery_holes == 1)) {
			surgeries.push("a tighter anus");
			slave.anus = 1;
			if (slave.analSkill > 10) {
				slave.analSkill -= 10;
			}
			V.cash -= V.surgeryCost;
			if (V.PC.medicine >= 100) slave.health -= 5;
			else slave.health -= 10;

		} else if ((slave.vagina > 1) && (thisSurgery.surgery_holes == 1)) {
			surgeries.push("a tighter pussy");
			slave.vagina = 1;
			if (slave.vaginalSkill > 10) {
				slave.vaginalSkill -= 10;
			}
			V.cash -= V.surgeryCost;
			if (V.PC.medicine >= 100) slave.health -= 5;
			else slave.health -= 10;

		} else if ((slave.butt <= 8) && (slave.butt < thisSurgery.surgery_butt)) {
			if (thisSurgery.surgery_butt !== "no default setting") {
				surgeries.push("a bigger butt");
				slave.buttImplant = 1;
				slave.butt += 1;
				V.cash -= V.surgeryCost;
				if (V.PC.medicine >= 100) slave.health -= 5;
				else slave.health -= 10;
			}

		} else if ((slave.boobs <= 9000) && (slave.lactation < 2) && (slave.boobs < thisSurgery.surgery_boobs)) {
			if (thisSurgery.surgery_boobs !== "no default setting") {
				surgeries.push("bigger boobs");
				slave.boobsImplant += 200;
				slave.boobs += 200;
				V.cash -= V.surgeryCost;
				if (V.PC.medicine >= 100) slave.health -= 5;
				else slave.health -= 10;
			}

		} else if ((slave.hips < 3) && (slave.hips < thisSurgery.surgery_hips) && (V.surgeryUpgrade == 1)) {
			surgeries.push("wider hips");
			slave.hips++;
			slave.hipsImplant++;
			V.cash -= V.surgeryCost;
			if (V.PC.medicine >= 100) slave.health -= 5;
			else slave.health -= 10;

		} else if (slave.bellyImplant < 0 && V.bellyImplants > 0 && thisSurgery.surgery_bellyImplant == "install" && slave.womb.length == 0 && slave.broodmother == 0) {
			slave.bellyImplant = 100;
			slave.preg = -2;
			V.cash -= V.surgeryCost;
			if (slave.ovaries == 1 || slave.mpreg == 1) {
				surgeries.push("belly implant");
				V.surgeryType = "bellyIn";
				if (V.PC.medicine >= 100) slave.health -= 5;
				else slave.health -= 10;
			} else {
				surgeries.push("male belly implant");
				V.surgeryType = "bellyInMale";
				if (V.PC.medicine >= 100) slave.health -= 25;
				else slave.health -= 50;
			}
			bellyIn(slave);

		} else if (slave.bellyImplant >= 0 && thisSurgery.surgery_bellyImplant == "remove") {
			surgeries.push("belly implant removal");
			V.surgeryType = "bellyOut";
			if (V.PC.medicine >= 100)
				slave.health -= 5;
			else
				slave.health -= 10;
			slave.preg = 0;
			slave.bellyImplant = -1;
			V.cash -= V.surgeryCost;
		} else if (slave.balls > 0 && slave.vasectomy === 0 && thisSurgery.surgery_vasectomy === true) {
			surgeries.push("vasectomy");
			V.surgeryType = "vasectomy";
			if (V.PC.medicine >= 100)
				slave.health -= 5;
			else
				slave.health -= 10;
			slave.vasectomy = 1;
			V.cash -= V.surgeryCost;
		} else if (slave.balls > 0 && slave.vasectomy === 1 && thisSurgery.surgery_vasectomy === false) {
			surgery.push("undo vasectomy");
			V.surgeryType = "vasectomy undo";
			if (V.PC.medicine >= 100)
				slave.health -=5;
			else
				slave.health -= 10;
			slave.vasectomy = 0;
			V.cash -= V.surgeryCost;
		}
	}

	function PrintResult(slave, thisSurgery, surgeries) {
		let surgeriesDisplay = "";
		if (surgeries.length === 1)
			surgeriesDisplay = surgeries[0];
		else {
			surgeriesDisplay = surgeries.slice(0, surgeries.length - 1).join(", ");
			surgeriesDisplay += ", and" + surgeries[surgeries.length - 1];
		}
		r += `${V.assistantName === "your personal assistant" ? "Your personal assistant" : V.assistantName}, ordered to apply surgery, gives ${slave.slaveName} <span class="lime">${surgeriesDisplay}.</span>`;
	}

	function bellyIn(slave) {
		// less hacky version of calling surgery degradation silently
		if (slave.devotion > 50)
			slave.devotion += 4;
		else if (slave.devotion >= -20)
			slave.trust -= 5;
		else {
			slave.trust -= 5;
			slave.devotion -= 5;
		}
	}
})();

repo_name: drakeashordcataclysm/fc


code:
:: saChoosesOwnClothes [script]

window.saChoosesOwnClothes = function saChoosesOwnClothes(slave) {
	"use strict";
	const V = State.variables;
	let r = "";
	if (slave.choosesOwnClothes !== 1) return r;
	const pronouns = getPronouns(slave);
	const he = pronouns.pronoun;
	const him = pronouns.object;
	const his = pronouns.possessive;
	const hers = pronouns.posessivePronoun;
	const himself = pronouns.objectReflexive;
	const boy = pronouns.noun;
	const He = capFirstChar(he);
	const His = capFirstChar(his);

	const belly_accessory = slave.bellyAccesory;

	if (slave.fetish === "mindbroken") {
		let corsetChoice = todaysCorset(slave);
		let clothingChoice = todaysOutfit(slave);
		slave.bellyAccesory = corsetChoice.bellyAccesory;
		slave.clothes = clothingChoice.clothes;
		r += `${He} is fundamentally broken, but still follows some faint memories of standing within the wardrobe. `;
		if (slave.amp !== 1) {
			let shoeChoice = todaysShoes(slave);
			r += `${shoeChoice.text} `;
			slave.shoes = shoeChoice.shoes;
		}
		r += `${corsetChoice.text} Faced with so many choices and no thought on the matter; ${clothingChoice.text}. `;
	} else if (slave.devotion <= 20) {
		let clothingChoice = todaysOutfit(slave);
		slave.clothes = clothingChoice.clothes;
		r += `${clothingChoice.text} `;
		if (slave.amp !== 1) {
			let shoeChoice = todaysShoes(slave);
			r += `${shoeChoice.text} `;
			slave.shoes = shoeChoice.shoes;
		}
		r += `<span class="mediumorchid">increasing ${his} independence.</span>`;
		slave.devotion -= 5;
	} else {
		let neckChoice = todaysCollar(slave);
		let corsetChoice = todaysCorset(slave);
		let clothingChoice = todaysOutfit(slave);
		slave.collar = neckChoice.collar;
		slave.bellyAccesory = corsetChoice.bellyAccesory;
		slave.clothes = clothingChoice.clothes;
		r += `${He} <span class="hotpink">loves</span> being able to dress ${himself}, ${neckChoice.text} ${corsetChoice.text} ${clothingChoice.text} `;
		slave.devotion += 1;

		if (V.arcologies[0].FSRestart !== "unset" && slave.choosesOwnChastity == 1) {
			if (slave.vagina > -1 && slave.breedingMark === 1 && (slave.vaginalAccessory === "chastity belt" || slave.vaginalAccessory === "combined chastity")) {
				r += `${He} unfastens ${his} chastity belt knowing full well ${his} role in life is to carry ${his} ${WrittenMaster(slave)}'s children. `;
				slave.vaginalAccessory = "none";
			} else if (slave.vagina > -1 && slave.ovaries === 1 && slave.preg === 0 && slave.vaginalAccessory !== "chastity belt") {
				r += `${He} also affixes a chastity belt over ${his} vagina to discourage use of ${his} reproductive organ. `;
				slave.vaginalAccessory = "chastity belt";
			} else if (slave.vagina > -1 && (slave.ovaries === 0 || slave.preg < -1) && slave.vaginalAccessory === "chastity belt") {
				r += `${He} removes ${his} chastity belt since no matter how hard someone tries, ${he} can never become pregnant. `;
				slave.vaginalAccessory = "none";
			}
			if (slave.dick > 0 && slave.balls > 0 && slave.dickAccessory !== "chastity") {
				r += `${He} also affixes a chastity cage onto ${his} dick to discourage use of ${his} reproductive organ. `;
				slave.dickAccessory = "chastity";
			} else if (slave.dick > 0 && slave.balls === 0 && slave.dickAccessory === "chastity") {
				r += `${He} removes ${his} chastity cage since even if ${he} could get erect, ${he} only shoots blanks. `;
				slave.dickAccessory = "none";
			}
		}

		if (slave.amp !== 1) {
			let shoeChoice = todaysShoes(slave);
			r += `${shoeChoice.text}`;
			slave.shoes = shoeChoice.shoes;
		}
	}
	return r;
};


code:
:: sexActJS [script]

/*
 times is how many times to increment the anal counts.
 if left undefined it will assume it to be 1.
*/
window.AnalVCheck = function AnalVCheck(times) {
	const V = State.variables;
	const slave = V.activeSlave;
	let r = ``;
	if (canDoAnal(slave) && slave.anus === 0) {
		r += `@@.lime;This breaks in ${slave.slaveName}'s virgin ass.@@ `;
		if (slave.devotion > 50 || slave.career == "a slave since birth") {
			r += `Since it's her first time, you gently ease yourself into her butthole and gradually increase the intensity of your thrusts. Before long she's moaning loudly as you continue working away at her butthole. `;
			if (slave.tankBaby == 2) {
				r += `She thinks of losing her anal virginity to her ${WrittenMaster(slave)} a @@.hotpink;necessity.@@ She expects her asshole to be seeing a lot more attention now.`;
			}
			else {
				r += `She thinks of losing her anal virginity to you as a @@.hotpink;connection@@ with her beloved ${WrittenMaster(slave)}. `;
				if ((slave.fetishKnown && slave.fetish == "buttslut") || (slave.energy > 95) || (slave.attrXX >= 85 && V.PC.dick === 0)) {
					r += `She can't wait to be fucked in the ass by you again.`;
				}
				else {
					r += `She looks forward to having her asshole fucked by you again.`;
				}
			}
			slave.devotion += 4;
		}
		else if (slave.devotion > 20) {
			r += `Since it's her first time, you gently ease yourself into her butthole and gradually increase the intensity of your thrusts. Her moans become louder and louder as you continue working away at her butthole. She accepts the pain and humiliation of anal sex as part of her sexual servitude, though she hopes that her next time will be less painful.`;
		}
		else if (slave.devotion >= -20) {
			r += `You force yourself into her butthole. She sobs and cries with disgust while you continue thrusting into her ass. She @@.gold;fears@@ her next anal sex, remembering the pain of losing her anal virginity. She dreads having her ass violated by you again.`;
			slave.trust -= 5;
		}
		else {
			r += `You force yourself into her butthole. She sobs and cries with disgust while you continue thrusting into her ass. She @@.mediumorchid;hates@@ and @@.gold;fears@@ you for violating her virgin butt. She dreads having her ass fucked by you again.`;
			slave.trust -= 5;
			slave.devotion -= 5;
		}
		slave.anus = 1;
	}
	if (canDoAnal(slave)) {
		if (V.PC.dick === 1 && canGetPregnant(slave) && slave.eggType == "human") {
			r += knockMeUp(slave, 10, 1, -1, 1);
		}
		if (!times) {
			V.analTotal += 1;
			slave.analCount += 1;
		}
		else {
			V.analTotal += times;
			slave.analCount += times;
		}
	}
	return r;
}

/*
 times is how many times to increment the vaginal counts.
 if left undefined it will assume it to be 1.
*/
window.VaginalVCheck = function VaginalVCheck(times) {
	const V = State.variables;
	const slave = V.activeSlave;
	let r = ``;
	if (canDoVaginal(slave) && slave.vagina === 0) {
		r += `@@.lime;This breaks in ${slave.slaveName}'s virgin pussy.@@ `;
		if (slave.devotion > 50 || slave.career == "a slave since birth") {
			r += `You ease yourself into her pussy, since it's her first time, then gradually speed up your thrusts while she slowly learns to move her hips along with you. She moans loudly. `;
			if (slave.tankBaby == 2) {
				r += `She thinks of losing her virginity to her ${WrittenMaster(slave)} a @@.hotpink;necessity to be happy.@@ She expects her pussy to be seeing a lot more attention in the future.`;
			}
			else {
				r += `@@.hotpink;She enjoys losing her cherry to you.@@ `;
				if ((slave.fetishKnown && slave.fetish == "pregnancy") || (slave.energy > 95) || (slave.attrXY >= 85 && V.PC.dick === 1)) {
					r += `She can't wait to have her pussy fucked by you again.`;
				}
				else {
					r += `She looks forward to having her pussy fucked by you again.`;
				}
			}
			slave.devotion += 4;
		}
		else if (slave.devotion > 20) {
			r += `You ease yourself into her pussy, since it's her first time, then gradually speed up your thrusts while she slowly learns to move her hips along with you. She accepts losing her virginity to her owner and she looks forward to having her pussy fucked by you again.`;
		}
		else if (slave.devotion >= -20) {
			r += `You force yourself into her pussy. She sobs and cries with disgust while you continue thrusting into her fuck hole. She @@.mediumorchid;hates@@ losing her virginity this way and @@.gold;fears@@ the next time you'll conquer her. She dreads getting violated by you again.`;
			slave.trust -= 5;
			slave.devotion -= 5;
		}
		else {
			r += `You force yourself into her pussy. She sobs and cries with disgust while you continue working her fuck hole. She tries to struggle, but you only pound harder. She @@.mediumorchid;hates@@ and @@.gold;fears@@ you for robbing her of her virginity. She dreads getting fucked by you again.`;
			slave.trust -= 10;
			slave.devotion -= 15;
		}
		slave.vagina = 1;

		if (V.PC.dick === 1 && canGetPregnant(slave) && slave.eggType == "human") {
			r += knockMeUp(slave, 10, 0, -1, 1);
		}
		if (!times) {
			V.vaginalTotal += 1;
			slave.vaginalCount += 1;
		}
		else {
			V.vaginalTotal += times;
			slave.vaginalCount += times;
		}
	}
	return r;
}

/*
 analTimes is how many times to increment the anal counts, if there is no vagina available.
 bothTimes is how many times to increment both holes counts (usually it is half of analTimes).
 In both cases if left undefined it will assume it to be 1.
*/
window.BothVCheck = function BothVCheck(analTimes, bothTimes) {
	const V = State.variables;
	const slave = V.activeSlave;
	let r = ``;
	if (canDoVaginal(slave)) {
		if (slave.vagina === 0) {
			if (canDoAnal(slave) && slave.anus == 0) {
				r += `@@.lime;This breaks in ${slave.slaveName}'s virgin holes.@@ `;
				if (slave.devotion > 50 || slave.career == "a slave since birth") {
					r += `As it's her first time, you ease yourself into her pussy before gradually working your way into her ass and alternate between the two holes while she moans. `;
					if (slave.tankBaby == 2) {
						r += `She believes you taking her virgin holes @@.hotpink;will keep her from suffering.@@ She expects you to require her holes as tribute again soon.`;
					}
					else {
						r += `@@.hotpink;She's so devoted she enjoys being fucked in both holes for the first time.@@ She looks forward to having her holes fucked by you again.`;
					}
					slave.devotion += 4;
				}
				else if (slave.devotion <= 20) {
					r += `You force yourself into her pussy before working your way into her ass. She sobs and cries with disgust while you alternate between the two holes. She @@.mediumorchid;hates@@ losing her virginity and anal virginity in one @@.gold;brutal@@ incident. She dreads having her holes violated by you again.`;
					slave.trust -= 5;
					slave.devotion -= 5;
				}
				else {
					r += `As it's her first time, you ease yourself into her pussy before gradually working your way into her ass and alternate between the two holes while she moans. She accepts being fucked in both holes for the first time. She looks forward to having her holes fucked by you again.`;
				}
				slave.anus = 1;
			}
			else {
				r += `@@.lime;This breaks in ${slave.slaveName}'s virgin pussy.@@ `;
				if (slave.devotion > 50 || slave.career == "a slave since birth") {
					r += `As it's her first time, you ease yourself into her pussy and gradually speed up your thrusts while she slowly learns to move her hips along with you. She moans loudly. `;
					if (slave.tankBaby == 2) {
						r += `She thinks of losing her virginity to her ${WrittenMaster(slave)} a @@.hotpink;necessity to be happy.@@ She expects her pussy to be seeing a lot more attention in the future.`;
					}
					else {
						r += `@@.hotpink;She enjoys losing her cherry to you.@@ She looks forward to having her pussy fucked by you again.`;
					}
					slave.devotion += 4;
				}
				else if (slave.devotion <= 20) {
					r += `You force yourself into her pussy. She sobs and cries with disgust while you continue working her fuck hole. She @@.mediumorchid;hates@@ and @@.gold;fears@@ you for taking her virginity. She dreads having her pussy violated by you again.`;
					slave.trust -= 5;
					slave.devotion -= 5;
				}
				else {
					r += `As it's her first time, you ease yourself into her pussy before gradually increasing the intensity of your thrusts while she softly moans. She accepts losing her virginity to her owner and she looks forward to having her pussy fucked by you again.`;
				}
			}
			slave.vagina = 1;
		}
		else if (canDoAnal(slave) && slave.anus == 0) {
			r += `@@.lime;This breaks in ${slave.slaveName}'s virgin ass.@@ `;
			if (slave.devotion > 50 || slave.career == "a slave since birth") {
				r += `As it's her first time, you ease yourself into her butthole and gradually speed up your thrusts while she slowly learns to move her hips along with you. She moans loudly. `;
				if (slave.tankBaby == 2) {
					r += `She thinks of losing her anal virginity to her ${WrittenMaster(slave)} a @@.hotpink;necessity.@@ She expects her asshole to be seeing a lot more attention now.`;
				}
				else {
					r += `She thinks of losing her anal virginity to you as a @@.hotpink;connection@@ with her beloved ${WrittenMaster(slave)}. She looks forward to having her asshole fucked by you again.`
				}
				slave.devotion += 4;
			}
			else if (slave.devotion > 20){
				r += `As it's her first time, you ease yourself into her butthole and gradually increase the intensity of your thrusts. She accepts the pain and humiliation of anal sex as part of her sexual servitude, though she hopes that her next time will be less painful.`;
			}
			else if (slave.devotion >= -20) {
				r += `You force yourself into her butthole. She sobs and cries with disgust while you continue thrusting into her ass. She @@.gold;fears@@ her next anal sex, remembering the pain of losing her anal virginity. She dreads having her ass violated by you again.`;
				slave.trust -= 5;
			}
			else {
				r += `You force yourself into her butthole. She sobs and cries with disgust while you continue thrusting into her ass. She @@.mediumorchid;hates@@ and @@.gold;fears@@ you for violating her virgin butt. She dreads having her ass fucked by you again.`;
				slave.trust -= 5;
				slave.devotion -= 5;
			}
			slave.anus = 1;
		}
		if (canDoAnal(slave)) {
			if (!bothTimes) {
				V.vaginalTotal += 1;
				V.analTotal += 1;
				slave.vaginalCount += 1;
				slave.analCount += 1;
			}
			else {
				V.vaginalTotal += bothTimes;
				V.analTotal += bothTimes;
				slave.vaginalCount += bothTimes;
				slave.analCount += bothTimes;
			}
			if (V.PC.dick === 1 && canGetPregnant(slave) && slave.eggType == "human") {
				r += knockMeUp(slave, 10, 2, -1, 1);
			}
		}
		else {
			if (!bothTimes) {
				V.vaginalTotal += 1;
				slave.vaginalCount += 1;
			}
			else {
				V.vaginalTotal += bothTimes;
				slave.vaginalCount += bothTimes;
			}
			if (V.PC.dick == 1 && canGetPregnant(slave) && slave.eggType == "human") {
				r += knockMeUp(slave, 10, 0, -1, 1);
			}
		}
	}
	else if (canDoAnal(slave)) {
		if (slave.anus == 0) {
			r += `@@.lime;This breaks in ${slave.slaveName}'s virgin ass.@@ `;
			if (slave.devotion > 50 || slave.career == "a slave since birth") {
				r += `As it's her first time, you ease yourself into her butthole and gradually speed up your thrusts while she slowly learns to move her hips along with you. She moans loudly. `;
				if (slave.tankBaby == 2) {
					r += `She thinks of losing her anal virginity to her ${WrittenMaster(slave)} a @@.hotpink;necessity.@@ She expects her asshole to be seeing a lot more attention now.`;
				}
				else {
					r += `She thinks of losing her anal virginity to you as a @@.hotpink;connection@@ with her beloved ${WrittenMaster(slave)}. She looks forward to having her asshole fucked by you again.`;
				}
				slave.devotion += 4;
			}
			else if (slave.devotion > 20) {
				r += `As it's her first time, you ease yourself into her butthole and gradually increase the intensity of your thrusts. She accepts the pain and humiliation of anal sex as part of her sexual servitude, though she hopes that her next time will be less painful.`;
			}
			else if (slave.devotion >= -20) {
				r += `You force yourself into her butthole. She sobs and cries with disgust while you continue thrusting into her ass. She @@.gold;fears@@ her next anal sex, remembering the pain of losing her anal virginity. She dreads having her ass violated by you again.`;
				slave.trust -= 5;
			}
			else {
				r += `You force yourself into her butthole. She sobs and cries with disgust while you continue thrusting into her ass. She @@.mediumorchid;hates@@ and @@.gold;fears@@ you for violating her virgin butt. She dreads having her ass fucked by you again.`
				slave.trust -= 5;
				slave.devotion -= 5;
			}
			slave.anus = 1;
		}
		if (!analTimes) {
			V.analTotal += 1;
			slave.analCount += 1;
		}
		else {
			V.analTotal += analTimes;
			slave.analCount += analTimes;
		}
		if (V.PC.dick === 1 && canGetPregnant(slave) && slave.eggType == "human") {
			r += knockMeUp(slave, 10, 1, -1, 1);
		}
	}
	return r;
}

/*
 times is how many times to increment either the Vaginal or the Anal counts, if there is no Vagina available.
 If left undefined it will assume it to be 1.
*/
window.SimpleVCheck = function SimpleVCheck(times) {
	let r = ``;
	if (canDoVaginal(State.variables.activeSlave)) {
		r += VaginalVCheck(times);
	}
	else if (canDoAnal(State.variables.activeSlave)) {
		r += AnalVCheck(times);
	}
	return r;
}

/*
 Before using this function, set $partner to the index of the partner in the $slaves array
 analTimes is how many times to increment the Anal counts, if there is no Vagina available.
 bothTimes is how many times to increment both holes counts (usually it is half of Anal).
 In both cases if left undefined it will assume it to be 1.
 This also checks for a valid Vagina/Accessory, though most code I've seen does this already, you
 never know when someone might use the routine and forget to do such.
*/
window.PartnerVCheck = function PartnerVCheck(analTimes, bothTimes) {
	const V = State.variables;
	const partner = V.slaves[V.partner];
	let r = ``;

	if (V.partner < 0 || V.partner >= V.slaves.length) {
		r += `@@.red;PartnerVCheck called with invalid partner '$partner' from passage ${passage()}.@@`;
	}
	else if (canDoVaginal(partner)) {
		if (partner.vagina === 0) {
			if (canDoAnal(partner) && partner.anus === 0) {
				r += `Since it's ${partner.slaveName}'s first time, you take your time and gently ease yourself into her pussy before gradually working your way into her butthole, alternating between her holes. @@.lime;This breaks in ${partner.slaveName}'s virgin holes.@@ `;
				partner.vagina = 1;
				partner.anus = 1;
			}
			else {
				r += `Since it's ${partner.slaveName}'s first time, you take your time and gently ease yourself into her pussy before gradually increasing the intensity of your thrusts. @@.lime;This breaks in partner.slaveName's virgin pussy.@@ `;
				partner.vagina = 1;
			}
		}
		else if (canDoAnal(partner) && partner.anus == 0) {
			r += `Since it's ${partner.slaveName}'s first time, you take your time and gently ease yourself into her butthole before gradually increasing the intensity of your thrusts into her ass. @@.lime;This breaks in ${partner.slaveName}'s virgin ass.@@ `;
			partner.anus = 1;
		}

		if (canDoAnal(partner)) {
			if (!bothTimes) {
				V.vaginalTotal += 1;
				V.analTotal += 1;
				partner.vaginalCount += 1;
				partner.analCount += 1;
			}
			else {
				V.vaginalTotal += bothTimes;
				V.analTotal += bothTimes;
				partner.vaginalCount += bothTimes;
				partner.analCount += bothTimes;
			}
			if (V.PC.dick === 1 && canGetPregnant(partner) && partner.eggType == "human") {
				r += knockMeUp(partner, 10, 2, -1);
			}
		}
		else {
			if (!bothTimes) {
				V.vaginalTotal += 1;
				partner.vaginalCount += 1;
			}
			else {
				V.vaginalTotal += bothTimes;
				partner.vaginalCount += bothTimes;
			}
			if (V.PC.dick === 1 && canGetPregnant(partner) && partner.eggType == "human") {
				r += knockMeUp(partner, 10, 0, -1);
			}
		}
	}
	else if (canDoAnal(partner)) {
		if (partner.anus === 0) {
			r += `Since it's ${partner.slaveName}'s first time, you take your time and gently ease yourself into her butthole before gradually increasing the intensity of your thrusts into her ass. @@.lime;This breaks in ${partner.slaveName}'s virgin ass.@@ `;
			partner.anus = 1;
		}
		if (!analTimes) {
			V.analTotal += analTimes;
			partner.analCount += analTimes;
		}
		else {
			V.analTotal += 1;
			partner.analCount += 1;
		}
		if (V.PC.dick === 1 && canGetPregnant(partner) && partner.eggType == "human") {
			r += knockMeUp(partner, 10, 1, -1);
		}
	}
	return r;
}

/*
 count is how many times to increment either the Vaginal, Anal, or Oral counts, depending on availability of slave.
 If count is left undefined it will assume it to be 1.
 Intended to be a simple "I want to fuck x and not have to code a bunch of logic for it".
*/
window.SimpleSexAct = function SimpleSexAct(slave, count) {
	const V = State.variables;
	const fuckTarget = jsRandom(1,100);
	let fuckCount = 1;
	let r = ``;
	if (count) {
		fuckCount = count;
	}
	for (var i = 0; i < fuckCount; i++) {
		if (slave.nipples == "fuckable" && V.PC.dick === 1 && fuckTarget > 80) {
			V.mammaryTotal += 1;
			slave.mammaryCount += 1;
		}
		else if (canDoVaginal(slave) && slave.vagina > 0 && fuckTarget > 33) {
			V.vaginalTotal += 1;
			slave.vaginalCount += 1;
			if (V.PC.dick === 1 && canGetPregnant(slave) && slave.eggType == "human") {
				r += knockMeUp(slave, 10, 0, -1, 1);
			}
		}
		else if (canDoAnal(slave) && slave.anus > 0 && fuckTarget > 10) {
			V.analTotal += 1;
			slave.analCount += 1;
			if (V.PC.dick == 1 && canGetPregnant(slave) && slave.eggType == "human") {
				r += knockMeUp(slave, 10, 1, -1, 1);
			}
		}
		else {
			V.oralTotal += 1;
			slave.oralCount += 1;
		}
	}
	return r;
}

/*
 count is how many times to increment either the Vaginal, Anal, or Oral counts, depending on availability of slave.
 If count is left undefined it will assume it to be 1.
 Intended to be a simple "x got fucked y times and I don't want to keep coding it".
 Pregnancy chance is handled in saLongTermEffects.tw.
*/
window.SimpleSlaveFucking = function SimpleSlaveFucking(slave, count) {
	const V = State.variables;
	const fuckTarget = jsRandom(1,100);
	let fuckCount = 1;
	if (count) {
		fuckCount = count;
	}
	for (var i = 0; i < fuckCount; i++) {
		if (slave.nipples == "fuckable" && fuckTarget > 80) {
			V.mammaryTotal += 1;
			slave.mammaryCount += 1;
		}
		else if (canDoVaginal(slave) && slave.vagina > 0 && fuckTarget > 33) {
			V.vaginalTotal += 1;
			slave.vaginalCount += 1;
		}
		else if (canDoAnal(slave) && slave.anus > 0 && fuckTarget > 10) {
			V.analTotal += 1;
			slave.analCount += 1;
		}
		else {
			V.oralTotal += 1;
			slave.oralCount += 1;
		}
	}
	return;
}

/*
 count is how many times to increment either the Vaginal, Anal, or Oral counts, depending on availability of slave.
 If count is left undefined it will assume it to be 1.
 Intended to be a simple "x got fucked y times by z and I don't want to keep coding it".
*/
window.SimpleSexAct = function SimpleSlaveSlaveFucking(subslave, domslave, count) {
    const V = State.variables;
    let fuckTarget = 0;
    let fuckCount = 1;
    let r = ``;
    if (count) {
        fuckCount = count;
    }
    for (var i = 0; i < fuckCount; i++) {
        //there is a reason randomization happens inside cycle - to spread fuck around, otherwise cycle isn't even needed
        fuckTarget = jsRandom(1,100);
        //why PC.dick? it's not PC doing any fucking
        if (subslave.nipples === "fuckable" && canPenetrate(domslave) && fuckTarget > 80) {
            if (passage() === "SA serve your other slaves") {
                //number of current slave in State.variables.slaves array is not going to be visible from function, even if it was $i is shadowed by 'for (var i = 0; i < fuckCount; i++)'
                //also not sure if xxxUse variables even exist in this scope? i guess they do, actual dev will know for sure
                //don't know how to properly convert this, but slaves[i] is definitely wrong
                if (subslave.ID == V.slaves[V.i].ID) {
                    V.mammaryUse++;
                    V.penetrativeTotal++;
                    domslave.penetrativeCount++;
                }
                else {
                    V.mammaryTotal++;
                    V.penetrativeUse++;
                    subslave.mammaryCount++;
                }
            }
            else {
                V.mammaryTotal++;
                V.penetrativeTotal++;
                subslave.mammaryCount++;
                domslave.penetrativeCount++;
            }
        }
        else if (canDoVaginal(subslave) && subslave.vagina > 0 && canPenetrate(domslave) && fuckTarget > 33) {
            if (passage() === "SA serve your other slaves") {
                if (subslave.ID == V.slaves[V.i].ID) {
                    V.vaginalUse++;
                    V.penetrativeTotal++;
                    domslave.penetrativeCount++;
                }
                else {
                    V.penetrativeUse++;
                    V.vaginalTotal++;
                    subslave.vaginalCount++;
                }
            }
            else {
                V.vaginalTotal++;
                subslave.vaginalCount++;
                V.penetrativeTotal++;
                domslave.penetrativeCount++;
            }
            if (canImpreg(subslave, domslave)) {
                r += knockMeUp(subslave, 3, 0, domslave.ID, 1);
            }
        }
        else if (canDoAnal(subslave) && subslave.anus > 0 && canPenetrate(domslave) && fuckTarget > 10) {
            //i think would impregnate from anal here even without .mpreg? same in original widget too
            if (canImpreg(subslave, domslave) && subslave.mpreg == 1) {
                r += knockMeUp(subslave, 3, 1, domslave.ID, 1);
            }
            if (passage() === "SA serve your other slaves") {
                if (subslave.ID == V.slaves[V.i].ID) {
                    V.analUse++;
                    V.penetrativeTotal++;
                    domslave.penetrativeCount++;
                }
                else {
                    V.penetrativeUse++;
                    V.analTotal++;
                    subslave.analCount++;
                }
            }
            else {
                V.analTotal++;
                subslave.analCount++;
                V.penetrativeTotal++;
                domslave.penetrativeCount++;
            }
        }
        else {
            V.oralTotal++;
            subslave.oralCount++;
        }
    }
    return r;
}


code:
:: Slave Summary Widgets JS [script]

window.clearSummaryCache = function clearSummaryCache(slave) {
	if (!slave)
		setup.summaryCache = {};
	else if (slave instanceof Object && slave.ID !== Infinity && slave.ID !== -Infinity)
		setup.summaryCache[slave.ID] = undefined;
	else
		setup.summaryCache[slave] = undefined;
};


code:
:: Span Macro JS [script]

/*
 * <> macro
 * A minimal macro which allows to create  elements with dynamic IDs.
 *
 * Usage: <>...<>
 */
Macro.add('span', {
	skipArgs : true,
	tags     : null,

	handler() {
		const payload        = this.payload[0].contents.replace(/(^\n+|\n+$)/, '');
		let statement        = this.args.raw.trim();
		let result;

		if(statement.length === 0) {
			return this.error('invalid syntax, format: <>');
		}

		try {
			result = Scripting.evalTwineScript(statement);
		} catch (ex) {
			return this.error(`bad evaluation: ${typeof ex === 'object' ? ex.message : ex}`);
		}

		Config.debug && this.debugView.modes({block: true});

		jQuery("")
			.wiki(payload)
			.appendTo(this.output);
	}
});


code:
:: StoryJS [script]

/*config.history.tracking = false;*/
window.variableAsNumber = function(x, defaultValue, minValue, maxValue) {
	x = Number(x)
	if (x != x) {//NaN
		return defaultValue || 0;//In case the default value was not supplied.
	}
	if (x < minValue) {//Works even if minValue is undefined.
		return minValue;
	}
	if (x > maxValue) {//Works even if maxValue is undefined.
		return maxValue;
	}
	return x;
};
window.isSexuallyPure = function(slave) {
	if (!slave) {
		return null;
	}
	if (slave.vagina < 1 && slave.anus < 1 && !slave.analCount && !slave.vaginalCount && !slave.oralCount && !slave.mammaryCount && !slave.penetrativeCount) {
		return true;
	} else {
		return false;
	}
};
if (typeof interpolate == "undefined") {
	var interpolate = function(x0,y0,x1,y1,x) {
		if(x <= x0) {
			return y0;
		} else if(x >= x1) {
			return y1;
		} else {
			return (x - x0) * ((y1 - y0) / (x1 - x0)) + y0;
		}
	};
	window.interpolate = interpolate;
}
config.history.maxStates = 1;

config.saves.autosave = "autosave";
window.isFullyPotent = function(slave) {
	if (!slave) {
		return null;
	} else if (slave.dick > 0 && slave.balls > 0 && slave.hormoneBalance < 100 && slave.drugs !== 'hormone blockers') {
		return true;
	} else {
		return false;
	}
};

/* mousetrap v1.5.3 craig.is/killing/mice */
(function(C,r,g){function t(a,b,h){a.addEventListener?a.addEventListener(b,h,!1):a.attachEvent("on"+b,h)}function x(a){if("keypress"==a.type){var b=String.fromCharCode(a.which);a.shiftKey||(b=b.toLowerCase());return b}return l[a.which]?l[a.which]:p[a.which]?p[a.which]:String.fromCharCode(a.which).toLowerCase()}function D(a){var b=[];a.shiftKey&&b.push("shift");a.altKey&&b.push("alt");a.ctrlKey&&b.push("ctrl");a.metaKey&&b.push("meta");return b}function u(a){return"shift"==a||"ctrl"==a||"alt"==a||
"meta"==a}function y(a,b){var h,c,e,g=[];h=a;"+"===h?h=["+"]:(h=h.replace(/\+{2}/g,"+plus"),h=h.split("+"));for(e=0;e<h.length;++e)c=h[e],z[c]&&(c=z[c]),b&&"keypress"!=b&&A[c]&&(c=A[c],g.push("shift")),u(c)&&g.push(c);h=c;e=b;if(!e){if(!k){k={};for(var m in l)95<m&&112>m||l.hasOwnProperty(m)&&(k[l[m]]=m)}e=k[h]?"keydown":"keypress"}"keypress"==e&&g.length&&(e="keydown");return{key:c,modifiers:g,action:e}}function B(a,b){return null===a||a===r?!1:a===b?!0:B(a.parentNode,b)}function c(a){function b(a){a=
a||{};var b=!1,n;for(n in q)a[n]?b=!0:q[n]=0;b||(v=!1)}function h(a,b,n,f,c,h){var g,e,l=[],m=n.type;if(!d._callbacks[a])return[];"keyup"==m&&u(a)&&(b=[a]);for(g=0;g<d._callbacks[a].length;++g)if(e=d._callbacks[a][g],(f||!e.seq||q[e.seq]==e.level)&&m==e.action){var k;(k="keypress"==m&&!n.metaKey&&!n.ctrlKey)||(k=e.modifiers,k=b.sort().join(",")===k.sort().join(","));k&&(k=f&&e.seq==f&&e.level==h,(!f&&e.combo==c||k)&&d._callbacks[a].splice(g,1),l.push(e))}return l}function g(a,b,n,f){d.stopCallback(b,
b.target||b.srcElement,n,f)||!1!==a(b,n)||(b.preventDefault?b.preventDefault():b.returnValue=!1,b.stopPropagation?b.stopPropagation():b.cancelBubble=!0)}function e(a){"number"!==typeof a.which&&(a.which=a.keyCode);var b=x(a);b&&("keyup"==a.type&&w===b?w=!1:d.handleKey(b,D(a),a))}function l(a,c,n,f){function e(c){return function(){v=c;++q[a];clearTimeout(k);k=setTimeout(b,1E3)}}function h(c){g(n,c,a);"keyup"!==f&&(w=x(c));setTimeout(b,10)}for(var d=q[a]=0;d<c.length;++d){var p=d+1===c.length?h:e(f||
y(c[d+1]).action);m(c[d],p,f,a,d)}}function m(a,b,c,f,e){d._directMap[a+":"+c]=b;a=a.replace(/\s+/g," ");var g=a.split(" ");1<g.length?l(a,g,b,c):(c=y(a,c),d._callbacks[c.key]=d._callbacks[c.key]||[],h(c.key,c.modifiers,{type:c.action},f,a,e),d._callbacks[c.key][f?"unshift":"push"]({callback:b,modifiers:c.modifiers,action:c.action,seq:f,level:e,combo:a}))}var d=this;a=a||r;if(!(d instanceof c))return new c(a);d.target=a;d._callbacks={};d._directMap={};var q={},k,w=!1,p=!1,v=!1;d._handleKey=function(a,
c,e){var f=h(a,c,e),d;c={};var k=0,l=!1;for(d=0;d<f.length;++d)f[d].seq&&(k=Math.max(k,f[d].level));for(d=0;d<f.length;++d)f[d].seq?f[d].level==k&&(l=!0,c[f[d].seq]=1,g(f[d].callback,e,f[d].combo,f[d].seq)):l||g(f[d].callback,e,f[d].combo);f="keypress"==e.type&&p;e.type!=v||u(a)||f||b(c);p=l&&"keydown"==e.type};d._bindMultiple=function(a,b,c){for(var d=0;d<a.length;++d)m(a[d],b,c)};t(a,"keypress",e);t(a,"keydown",e);t(a,"keyup",e)}var l={8:"backspace",9:"tab",13:"enter",16:"shift",17:"ctrl",18:"alt",
20:"capslock",27:"esc",32:"space",33:"pageup",34:"pagedown",35:"end",36:"home",37:"left",38:"up",39:"right",40:"down",45:"ins",46:"del",91:"meta",93:"meta",224:"meta"},p={106:"*",107:"+",109:"-",110:".",111:"/",186:";",187:"=",188:",",189:"-",190:".",191:"/",192:"`",219:"[",220:"\\",221:"]",222:"'"},A={"~":"`","!":"1","@":"2","#":"3",$:"4","%":"5","^":"6","&":"7","*":"8","(":"9",")":"0",_:"-","+":"=",":":";",'"':"'","<":",",">":".","?":"/","|":"\\"},z={option:"alt",command:"meta","return":"enter",
escape:"esc",plus:"+",mod:/Mac|iPod|iPhone|iPad/.test(navigator.platform)?"meta":"ctrl"},k;for(g=1;20>g;++g)l[111+g]="f"+g;for(g=0;9>=g;++g)l[g+96]=g;c.prototype.bind=function(a,b,c){a=a instanceof Array?a:[a];this._bindMultiple.call(this,a,b,c);return this};c.prototype.unbind=function(a,b){return this.bind.call(this,a,function(){},b)};c.prototype.trigger=function(a,b){if(this._directMap[a+":"+b])this._directMap[a+":"+b]({},a);return this};c.prototype.reset=function(){this._callbacks={};this._directMap=
{};return this};c.prototype.stopCallback=function(a,b){return-1<(" "+b.className+" ").indexOf(" mousetrap ")||B(b,this.target)?!1:"INPUT"==b.tagName||"SELECT"==b.tagName||"TEXTAREA"==b.tagName||b.isContentEditable};c.prototype.handleKey=function(){return this._handleKey.apply(this,arguments)};c.init=function(){var a=c(r),b;for(b in a)"_"!==b.charAt(0)&&(c[b]=function(b){return function(){return a[b].apply(a,arguments)}}(b))};c.init();C.Mousetrap=c;"undefined"!==typeof module&&module.exports&&(module.exports=
c);"function"===typeof define&&define.amd&&define(function(){return c})})(window,document);

Mousetrap.bind("enter", function () {
	$("#story-caption #endWeekButton a.macro-link").trigger("click");
});
Mousetrap.bind("space", function () {
	$("#story-caption #nextButton a.macro-link").trigger("click");
});
Mousetrap.bind("c", function () {
	$("#story-caption #manageArcology a.macro-link").trigger("click");
});
Mousetrap.bind("p", function () {
	$("#story-caption #managePenthouse a.macro-link").trigger("click");
});
Mousetrap.bind("left", function () {
	$("#prevSlave a.macro-link").trigger("click");
	$("#prevRule a").trigger("click");
});
Mousetrap.bind("q", function () {
	$("#prevSlave a.macro-link").trigger("click");
	$("#prevRule a").trigger("click");
});
Mousetrap.bind("shift+left", function () {
	$("#firstRule a").trigger("click");
});
Mousetrap.bind("shift+q", function () {
	$("#firstRule a").trigger("click");
});
Mousetrap.bind("right", function () {
	$("#nextSlave a.macro-link").trigger("click");
	$("#nextRule a").trigger("click");
});
Mousetrap.bind("shift+right", function () {
	$("#lastRule a").trigger("click");
});
Mousetrap.bind("e", function () {
	$("#nextSlave a.macro-link").trigger("click");
	$("#nextRule a").trigger("click");
});
Mousetrap.bind("shift+e", function () {
	$("#lastRule a").trigger("click");
});
Mousetrap.bind("f", function () {
	$("#walkpast a.macro-link").trigger("click");
});
Mousetrap.bind("h", function () {
	$("#manageHG a.macro-link").trigger("click");
});
Mousetrap.bind("s", function () {
	$("#buySlaves a.macro-link").trigger("click");
});
Mousetrap.bind("a", function () {
	$("#managePA a.macro-link").trigger("click");
});
Mousetrap.bind("b", function () {
	$("#manageBG a.macro-link").trigger("click");
});
Mousetrap.bind("u", function () {
	$("#manageRecruiter a.macro-link").trigger("click");
});
Mousetrap.bind("o", function () {
	$("#story-caption #optionsButton a.macro-link").trigger("click");
});
Mousetrap.bind("y", function () {
	$("#story-caption #policyButton a.macro-link").trigger("click");
});
Mousetrap.bind("f", function () {
	$("#story-caption #FSButton a.macro-link").trigger("click");
});
Mousetrap.bind("t", function () {
	$("#story-caption #PAOButton a.macro-link").trigger("click");
});
Mousetrap.bind("v", function () {
	$("#story-caption #URButton a.macro-link").trigger("click");
});
Mousetrap.bind("r", function () {
	$("#RAButton a.macro-link").trigger("click");
});
Mousetrap.bind("x", function () {
	$("#story-caption #managePerson a.macro-link").trigger("click");
});
Mousetrap.bind("z", function () {
	$("#story-caption #SFMButton a.macro-link").trigger("click");
});
Mousetrap.bind("d", function () {
	$("#story-caption #edictButton a.macro-link").trigger("click");
});
Mousetrap.bind("shift+s", function () {
	$("#story-caption #securityHQ a.macro-link").trigger("click");
});
Mousetrap.bind("shift+a", function () {
	$("#story-caption #secBarracks a.macro-link").trigger("click");
});
Mousetrap.bind("shift+h", function () {
	$("#story-caption #propHub a.macro-link").trigger("click");
});
Mousetrap.bind("shift+r", function () {
	$("#story-caption #riotCenter a.macro-link").trigger("click");
});
/**
 * BoobGenerator namespace.
 */
if (typeof BoobGenerator == "undefined") {
	var BoobGenerator = {
		rollBreast: function (modif) {
			var volume = [0, 300, 500, 650, 800, 1000, 1200, 1400, 1600, 1800, 2050, 2300, 2600, 2900, 3250, 3600, 3950, 4300, 4700, 5100, 5500, 5900];
			var volume_dist = [90000, 470000, 720000, 840000, 908574, 947759, 970151, 982946, 990258, 994436, 996824, 998188, 998968, 999414, 999669, 999814, 999897, 999945, 999972, 999987, 999995, 1000000];
			var randomRoll = Math.floor(Math.random() * 1000000) + 1
			var actualSize = 0
			while (randomRoll > volume_dist[actualSize]) {
				actualSize = actualSize + 1
			}
			var minorSizeAdjustment = 0
			if (Math.random()<.5) {
				minorSizeAdjustment = (Math.floor(Math.random() * 2) + 1) * 50
			}
			var volResult = volume[actualSize] + minorSizeAdjustment + modif
			if (volResult < 0) {volResult = 0}
			return volResult
		}
	};
	// Raise namespace scope to Global.
	window.BoobGenerator = BoobGenerator;
};

/**
 * Slave checker namespace.
 */
if (typeof SlaveStatsChecker == "undefined") {
	var SlaveStatsChecker = {
		checkForLisp: function (slave) {
				/* Begin mod section: toggle whether slaves lisp. */
				if (State && State.variables.disableLisping == 1) {
					return false;
				}
				/* End mod section: toggle whether slaves lisp. */
				return ((slave.lips > 70) || (slave.lipsPiercing + slave.tonguePiercing > 2))
			}
	};
	// Raise namespace scope to Global.
	window.SlaveStatsChecker = SlaveStatsChecker;
};

window.removeFromArray = function(arr, val) {
	for (var i = 0; i < arr.length; i++) {
		if (val == arr[i])
			return arr.splice(i,1);
	}
	return null;
};

window.filterInPlace = function(arr, callback, thisArg) {
	var j = 0;

	arr.forEach(function(e, i) {
		if (callback.call(thisArg, e, i, arr))
			arr[j++] = e;
	});

	arr.length = j;
	return arr;
};

if (typeof FertilityAge == "undefined") {
	var FertilityAge = {
		setAge: function (age) {
			age = Number(age)
				if (age != age) {
					return 13;
				} else {
				return age
			}
		}
	};
	// Raise namespace scope to Global.
	window.FertilityAge = FertilityAge;
};

window.canGetPregnant = function(slave) {
	if (!slave) {
		return null;
	} else if (slave.preg == -1) { /* contraceptives check */
		return false;
	} else if (!isFertile(slave)) { /* check other fertility factors */
		return false;
	} else if ((slave.ovaries == 1) && (canDoVaginal(slave))) {
		return true;
	} else if ((slave.mpreg == 1) && (canDoAnal(slave))) { /* pregmod */
		return true;
	} else {
		return false;
	}
};

/* pregmod: are slave2's sperm compatible with slave1's eggs? */
window.canBreed = function(slave1, slave2) {
	if (!slave1 || !slave2) {
		return null;
	} else if (slave1.eggType == slave2.ballType) {
		return true;
	} else {
		return false;
	}
};

/* assuming slave1 is fertile, could slave2 impregnate slave1? slave2 must have dick and balls with compatible sperm; both slaves must not be in chastity; slave2 need not achieve erection */
window.canImpreg = function(slave1, slave2) {
	if (!slave1 || !slave2) {
		return null;
	} else if (slave2.dick < 1) {
		return false;
	} else if (slave2.balls < 1) {
		return false;
	} else if (slave2.dickAccessory == "chastity") {
		return false;
	} else if (slave2.dickAccessory == "combined chastity") {
		return false;
	} else if (slave2.pubertyXY == 0) { /* pregmod start */
		return false;
	} else if (slave2.vasectomy == 1) {
		return false;
	} else if (!canBreed(slave1, slave2)) {
		return false;                   /* pregmod end */
	} else if (!canGetPregnant(slave1)) { /* includes chastity checks */
		return false;
	} else {
		return true;
	}
};

/* contraceptives (.preg == -1) do not negate this function */
window.isFertile = function(slave) {
	if (!slave) {
		return null;
	}

	WombInit(slave);

	if (slave.womb.length > 0 || slave.broodmother > 0) { /* currently pregnant or broodmother */
		return false;
	} else if (slave.preg < -1) { /* sterile */
		return false;
	} else if (slave.pregWeek < 0) { /* postpartum */
		return false;
	} else if (slave.pubertyXX == 0) { /* pregmod start */
		return false;
	} else if (slave.ovaryAge >= 47) {
		return false;
	} else if (slave.inflation != 0) {
		return false;
	} else if (slave.bellyImplant != -1) {
		return false;
	} else if (slave.mpreg == 1) {
		return true;                   /* pregmod end */
	} else if (slave.ovaries == 1) {
		return true;
	} else {
		return false;
	}
};

window.isPlayerFertile = function(PC) {
	if (!PC) {
		return null;
	} else if (PC.preg != 0) { /* currently pregnant, sterile, menopausal or on contraceptives */
		return false;
	} else if (PC.pregWeek < 0) { /* postpartum */
		return false;
	} else if (PC.vagina == 1) {
		return true;
	} else {
		return false;
	}
};

window.canAchieveErection = function(slave) {
	if (!slave) {
		return null;
	} else if (slave.dick < 7 && slave.dick > 0 && slave.drugs !== 'hormone blockers' && (slave.balls > 0 ? slave.hormoneBalance < 100 : slave.hormoneBalance <= -100)) {
		return true;
	} else {
		return false;
	}
};

window.canPenetrate = function(slave) {
	if (!slave) {
		return null;
	} else if (!canAchieveErection(slave)) {
		return false;
	} else if (slave.dickAccessory == "chastity") {
		return false;
	} else if (slave.dickAccessory == "combined chastity") {
		return false;
	} else if (slave.dick > 7) {
		return false;
	}
	return true;
};

window.canSee = function(slave) {
	if (!slave) {
		return null;
	} else if (slave.eyes > -2) {
		return true;
	} else {
		return false;
	}
};

window.canWalk = function(slave) {
	if (!slave) {
		return null;
	} else if (slave.amp == 1)  {
		return false;
	} else if (tooFatSlave(slave)) {
		return false;
	} else if (tooBigBreasts(slave)) {
		return false;
	} else if (tooBigDick(slave)) {
		return false;
	} else if (tooBigBalls(slave)) {
		return false;
	} else if (tooBigButt(slave)) {
		return false;
	} else if (tooBigBelly(slave)) {
		return false;
	} else if (slave.heels == 0) {
		return true;
	} else if (slave.shoes == "heels") {
		return true;
	} else if (slave.shoes == "extreme heels") {
		return true;
	} else if (slave.shoes == "boots") {
		return true;
	} else {
		return false;
	}
};

window.canTalk = function(slave) {
	if (!slave) {
		return null;
	} else if (slave.accent > 2)  {
		return false;
	} else if (slave.voice == 0) {
		return false;
	} else if (slave.lips > 95) {
		return false;
	} else if (slave.collar == "dildo gag") {
		return false;
	} else if (slave.collar == "massive dildo gag") {
		return false;
	} else if (slave.collar == "ball gag") {
		return false;
	} else if (slave.collar == "bit gag") {
		return false;
	} else {
		return true;
	}
};

window.canDoAnal = function(slave) {
	if (!slave) {
		return null;
	} else if (slave.vaginalAccessory == "anal chastity") {
		return false;
	} else if (slave.dickAccessory == "anal chastity") {
		return false;
	} else if (slave.vaginalAccessory == "combined chastity") {
		return false;
	} else if (slave.dickAccessory == "combined chastity") {
		return false;
	}
	return true;
};

window.canDoVaginal = function(slave) {
	if (!slave) {
		return null;
	} else if (slave.vagina < 0) {
		return false;
	} else if (slave.vaginalAccessory == "chastity belt") {
		return false;
	} else if (slave.vaginalAccessory == "combined chastity") {
		return false;
	}
	return true;
};

window.tooFatSlave = function(slave){
	if (!slave) {
		return null;
	} else if (slave.weight > 190+(slave.muscles/5) && slave.physicalAge >= 18) {
		return true;
	} else if (slave.weight > 130+(slave.muscles/20) && slave.physicalAge <= 3) {
		return true;
	} else if (slave.weight > 160+(slave.muscles/15) && slave.physicalAge <= 12) {
		return true;
	} else if (slave.weight > 185+(slave.muscles/10) && slave.physicalAge < 18) {
		return true;
	} else {
		return false;
	}
};

window.tooBigBreasts = function(slave){
	if (!slave) {
		return null;
	} else if (slave.boobs > 30000+(slave.muscles*100) && slave.physicalAge >= 18) {
		return true;
	} else if (slave.boobs > 5000+(slave.muscles*10) && slave.physicalAge <= 3) {
		return true;
	} else if (slave.boobs > 10000+(slave.muscles*20) && slave.physicalAge <= 12) {
		return true;
	} else if (slave.boobs > 20000+(slave.muscles*50) && slave.physicalAge < 18) {
		return true;
	} else {
		return false;
	}
};

window.tooBigBelly = function(slave){
	if (!slave) {
		return null;
	} else if (slave.belly >= 450000+(slave.muscles*2000) && slave.physicalAge >= 18) {
		return true;
	} else if (slave.belly >= 350000+(slave.muscles*1000) && slave.physicalAge >= 13) {
		return true;
	} else if (slave.belly >= 150000+(slave.muscles*500) && slave.physicalAge <= 3) {
		return true;
	} else if (slave.belly >= 250000+(slave.muscles*800) && slave.physicalAge <= 12) {
		return true;
	} else {
		return false;
	}
};

window.tooBigBalls = function(slave){
	if (!slave) {
		return null;
	} else if (slave.balls >= 30+(slave.muscles*.3) && slave.physicalAge <= 3) {
		return true;
	} else if (slave.balls >= 60+(slave.muscles*.5) && slave.physicalAge <= 12) {
		return true;
	} else if (slave.balls >= 90+(slave.muscles*.7)) {
		return true;
	} else {
		return false;
	}
};

window.tooBigDick = function(slave){
	if (!slave) {
		return null;
	} else if (slave.dick >= 15+(slave.muscles*.1) && slave.physicalAge <= 3 && slave.dick !== 0) {
		return true;
	} else if (slave.dick >= 30+(slave.muscles*.3) && slave.physicalAge <= 12) {
		return true;
	} else if (slave.dick >= 68+(slave.muscles*.4)) {
		return true;
	} else {
		return false;
	}
};

window.tooBigButt = function(slave){
	if (!slave) {
		return null;
	} else if (slave.butt > 10 && slave.physicalAge <= 3) {
		return true;
	} else if (slave.butt > 14 && slave.physicalAge <= 12) {
		return true;
	} else {
		return false;
	}
};

window.relationTargetWord = function(slave) {
	if (!slave) {
		return null;
	} else if (slave.relation == "daughter") {
		return "mother";
	} else if (slave.relation == "mother") {
		return "daughter";
	}
	return slave.relation;
};

/* intended to condense the clothing/toy/etc availability checks into something less asinine */
window.isItemAccessible = function(string) {
	if (State.variables.cheatMode === 1){
		return true;
	} else {
		switch(string) {
		case 'attractive lingerie for a pregnant woman':
			if ((State.variables.arcologies[0].FSRepopulationFocus > 0) || (State.variables.clothesBoughtMaternityLingerie === 1)) {
				return true;
			} else {
				return false;
			}
			break;
		case 'a bunny outfit':
			if ((State.variables.arcologies[0].FSGenderFundamentalist > 0) || (State.variables.clothesBoughtBunny === 1)) {
				return true;
			} else {
				return false;
			}
			break;
		case 'body oil':
			if ((State.variables.arcologies[0].FSPhysicalIdealist > 0) || (State.variables.clothesBoughtOil === 1)) {
				return true;
			} else {
				return false;
			}
			break;
		case 'chains':
			if ((State.variables.arcologies[0].FSDegradationist > 0) || (State.variables.clothesBoughtChains === 1)) {
				return true;
			} else {
				return false;
			}
			break;
		case 'a chattel habit':
			if ((State.variables.arcologies[0].FSChattelReligionist > 0) || (State.variables.clothesBoughtHabit === 1)) {
				return true;
			} else {
				return false;
			}
			break;
		case 'conservative clothing':
			if ((State.variables.arcologies[0].FSPaternalist > 0) || (State.variables.clothesBoughtConservative === 1)) {
				return true;
			} else {
				return false;
			}
			break;
		case 'harem gauze':
			if ((State.variables.arcologies[0].FSArabianRevivalist > 0) || (State.variables.clothesBoughtHarem === 1)) {
				return true;
			} else {
				return false;
			}
			break;
		case 'a huipil':
			if ((State.variables.arcologies[0].FSAztecRevivalist > 0) || (State.variables.clothesBoughtHuipil === 1)) {
				return true;
			} else {
				return false;
			}
			break;
		case 'a kimono':
			if ((State.variables.arcologies[0].FSEdoRevivalist > 0) || (State.variables.clothesBoughtKimono === 1)) {
				return true;
			} else {
				return false;
			}
			break;
		case 'a maternity dress':
			if ((State.variables.arcologies[0].FSRepopulationFocus > 0) || (State.variables.clothesBoughtMaternityDress === 1)) {
				return true;
			} else {
				return false;
			}
			break;
		case 'a slutty qipao':
			if ((State.variables.arcologies[0].FSChineseRevivalist > 0) || (State.variables.clothesBoughtQipao === 1)) {
				return true;
			} else {
				return false;
			}
			break;
		case 'stretch pants and a crop-top':
			if ((State.variables.arcologies[0].FSHedonisticDecadence > 0) || (State.variables.clothesBoughtLazyClothes === 1)) {
				return true;
			} else {
				return false;
			}
			break;
		case 'a toga':
			if ((State.variables.arcologies[0].FSRomanRevivalist > 0) || (State.variables.clothesBoughtToga === 1)) {
				return true;
			} else {
				return false;
			}
			break;
		case 'Western clothing':
			if ((State.variables.arcologies[0].FSPastoralist > 0) || (State.variables.clothesBoughtWestern === 1)) {
				return true;
			} else {
				return false;
			}
			break;
		case 'bowtie':
			if ((State.variables.arcologies[0].FSGenderFundamentalist > 0) || (State.variables.clothesBoughtBunny === 1)) {
				return true;
			} else {
				return false;
			}
			break;
		case 'ancient Egyptian':
			if ((State.variables.arcologies[0].FSEgyptianRevivalist > 0) || (State.variables.clothesBoughtEgypt === 1)) {
				return true;
			} else {
				return false;
			}
			break;
		case 'massive dildo gag':
			if (State.variables.toysBoughtGags === 1) {
				return true;
			} else {
				return false;
			}
			break;
		case 'a small empathy belly': case 'a medium empathy belly': case 'a large empathy belly': case 'a huge empathy belly':
			if ((State.variables.arcologies[0].FSRepopulationFocus > 0) || (State.variables.clothesBoughtBelly === 1)) {
				return true;
			} else {
				return false;
			}
			break;
		case 'long dildo': case 'long, large dildo': case 'long, huge dildo':
			if (State.variables.toysBoughtDildos === 1) {
				return true;
			} else {
				return false;
			}
			break;
		case 'long plug': case 'long, large plug': case 'long, huge plug':
			if (State.variables.toysBoughtButtPlugs === 1) {
				return true;
			} else {
				return false;
			}
			break;
		case 'tail':
			if (State.variables.toysBoughtButtPlugTails === 1) {
				return true;
			} else {
				return false;
			}
			break;
		default:
			return true;
			break;
		}
	}
};

window.expandFacilityAssignments = function(facilityAssignments) {
	var assignmentPairs = {
		"serve in the club": "be the DJ",
		"rest in the spa": "be the Attendant",
		"work in the brothel": "be the Madam",
		"work in the dairy": "be the Milkmaid",
		"work as a servant": "be the Stewardess",
		"get treatment in the clinic": "be the Nurse",
		"live with your Head Girl": "be your Head Girl",
		"serve in the master suite": "be your Concubine",
		"learn in the schoolroom": "be the Schoolteacher",
		"be confined in the cellblock": "be the Wardeness",
	};

	if (!facilityAssignments || !facilityAssignments.length)
		return [];
	var fullList = facilityAssignments.map(function(a) {
		if (a in assignmentPairs)
			return [a, assignmentPairs[a]];
		return a;
	});
	return fullList.flatten();
};

window.milkAmount = function(slave) {
	var milk;
	var calcs;
	if (!slave) {
		return null;
	} else {
		calcs = slave.boobs-slave.boobsImplant
		if (calcs > 40000) {
			milk = (158+((calcs-10000)/600))
		} else if (calcs > 25000) {
			milk = (128+((calcs-10000)/500))
		} else if (calcs > 10000) {
			milk = (78+((calcs-10000)/300))
		} else if (calcs > 5000) {
			milk = (53+((calcs-5000)/200))
		} else if (calcs > 2000) {
			milk = (29+((calcs-2000)/125))
		} else if (calcs > 800) {
			milk = (16+((calcs-800)/80))
		} else {
			milk = (8+((calcs-400)/50))
		}
		if (slave.lactation == 2) {
			milk *= 1.2
		}
		milk += (milk*((slave.devotion-50)/200))
		if (slave.boobsImplant > 200) {
			milk *= 0.9
		}
		calcs = (slave.hormoneBalance/50)
		if (slave.balls != 0 && calcs > -2) {
			calcs -= 1
		} else if (slave.ovaries != 1 && calcs < 2) {
			calcs += 1
		}
		milk *= (1+(calcs*0.1))
		milk *= (1+(slave.preg/100))
		milk *= (1+(slave.health/50))
		milk *= (1+(slave.weight/500))
		milk *= (1+(slave.lactationAdaptation/500))
		milk = Math.trunc(milk)
		milk = Math.clamp(milk,1,1000000000000000000)
		return milk
	}
};

window.cumAmount = function(slave) {
	var cum = 0;
	var calcs = 0;
	if (!slave) {
		return null;
	} else {
		if (slave.drugs == "testicle enhancement") {
			cum = ((slave.balls*3.5)+1)
		} else if (slave.drugs == "hyper testicle enhancement") {
			cum = ((slave.balls*5)+1)
		} else {
			cum = ((slave.balls*2.5)+1)
		}
		if (slave.diet == "cum production") {
			cum *= 1.2
		}
		calcs = (slave.hormoneBalance/50)
		cum *= (1-(calcs*0.1))
		if (slave.scrotum == 0) {
			cum *= 0.8
		}
		if (slave.prostate == 0) {
			cum *= 0.2 // being generous here
		} else if (slave.prostate == 2) {
			cum *= 1.2
		} else if (slave.prostate == 3) {
			cum *= 1.5
		}
		if (slave.devotion > 50) {
			cum += (cum*(slave.devotion/100))
		} else if (slave.devotion < -50) {
			cum += (cum*(slave.devotion/100))
		}
		if (slave.health > 50) {
			cum += (cum*(slave.health/50))
		} else if (slave.health < -50) {
			cum += (cum*(slave.health/50))
		}
		cum = Math.trunc(cum)
		cum = Math.clamp(cum,1,1000000000000000000)
		return cum
	}
};

window.lispReplace = function(text)
{
	text = text.replace("Sh", "Th");
	text = text.replace("SS", "Th");
	text = text.replace("Ss", "Th");
	text = text.replace("sS", "Th");
	text = text.replace("S", "Th");
	text = text.replace("aX", "aKTH");
	text = text.replace("eX", "eKTH");
	text = text.replace("iX", "iKTH");
	text = text.replace("oX", "oKTH");
	text = text.replace("uX", "uKTH");
	text = text.replace("yX", "yKTH");
	text = text.replace("AX", "AKTH");
	text = text.replace("EX", "EKTH");
	text = text.replace("IX", "IKTH");
	text = text.replace("OX", "OKTH");
	text = text.replace("UX", "UKTH");
	text = text.replace("YX", "YKTH");
	text = text.replace("Xa", "Tha");
	text = text.replace("Xe", "The");
	text = text.replace("Xi", "Thi");
	text = text.replace("Xo", "Tho");
	text = text.replace("Xu", "Thu");
	text = text.replace("Xy", "Thy");
	text = text.replace("XA", "THA");
	text = text.replace("XE", "THE");
	text = text.replace("XI", "THI");
	text = text.replace("XO", "THO");
	text = text.replace("XU", "THU");
	text = text.replace("XY", "THY");
	text = text.replace("X", "EKTH");
	text = text.replace("zZ", "Th");
	text = text.replace("Zz", "Th");
	text = text.replace("ZZ", "TH");
	text = text.replace("Z", "Th");
	text = text.replace("Ci", "Thi");
	text = text.replace("Ce", "The");
	text = text.replace("Cy", "Thy");
	text = text.replace("CI", "THI");
	text = text.replace("CE", "THE");
	text = text.replace("CY", "THY");
	text = text.replace("ss", "th");
	text = text.replace("sh", "th");
	text = text.replace("s", "th");
	text = text.replace("zz", "th");
	text = text.replace("z", "th");
	text = text.replace("ax", "akth");
	text = text.replace("ex", "ekth");
	text = text.replace("ix", "ikth");
	text = text.replace("ox", "okth");
	text = text.replace("ux", "ukth");
	text = text.replace("yx", "ykth");
	text = text.replace("Ax", "Akth");
	text = text.replace("Ex", "Ekth");
	text = text.replace("Ix", "Ikth");
	text = text.replace("Ox", "Okth");
	text = text.replace("Ux", "Ukth");
	text = text.replace("Yx", "Ykth");
	text = text.replace("xa", "tha");
	text = text.replace("xe", "the");
	text = text.replace("xi", "thi");
	text = text.replace("xo", "tho");
	text = text.replace("xu", "thu");
	text = text.replace("xy", "thy");
	text = text.replace("xA", "thA");
	text = text.replace("xE", "thE");
	text = text.replace("xI", "thI");
	text = text.replace("xO", "thO");
	text = text.replace("xU", "thU");
	text = text.replace("xY", "thY");
	text = text.replace("x", "ekth");
	text = text.replace("ci", "thi");
	text = text.replace("ce", "the");
	text = text.replace("cy", "thy");
	text = text.replace("cI", "thI");
	text = text.replace("cE", "thE");
	text = text.replace("cY", "thY");
	return text;
}

window.isVegetable = function(slave) {
	slave = slave || State.variables.activeSlave;
	if(!slave) { return false; }
	return (slave.fetish === 'mindbroken');
};

window.repGainSacrifice = function(slave, arcology) {
	slave = slave || State.variables.activeSlave;
	arcology = arcology || State.variables.arcologies[0];
	if(!slave || !arcology || arcology.FSAztecRevivalist === "unset" || arcology.FSAztecRevivalist <= 0) {
		return 0;
	}
	return Math.ceil(
		(Math.min(100, Math.pow(1.0926, State.variables.week - slave.weekAcquired)) + slave.prestige * 30)
			* arcology.FSAztecRevivalist / 100 / ((State.variables.slavesSacrificedThisWeek || 0) + 1));
};

window.bodyguardSuccessorEligible = function(slave) {
	if(!slave) { return false; }
	return (slave.devotion > 50 && slave.muscles >= 0 && slave.weight < 100 && slave.boobs < 8000 && slave.butt < 10 && slave.belly < 5000 && slave.balls < 10 && slave.dick < 10 && slave.preg < 20 && slave.fuckdoll == 0 && slave.fetish != "mindbroken" && canWalk(slave));
};

window.ngUpdateGenePool = function(genePool) {
  var transferredSlaveIds = (State.variables.slaves || [])
    .filter(function(s) { return s.ID >= 1200000; })
    .map(function(s) { return s.ID - 1200000; });
  return (genePool || [])
    .filter(function(s) { return transferredSlaveIds.indexOf(s.ID) >= 0; })
    .map(function(s) {
      var result = jQuery.extend(true, {}, s);
      result.ID += 1200000;
      return result;
    });
}

window.toJson = function(obj) {
    var jsontext = JSON.stringify(obj);
    jsontext = jsontext.replace(/^{/,"");
    jsontext = jsontext.replace(/}$/,"");
    return jsontext;
};

window.nippleColor = function(slave) {
	slave = slave || State.variables.activeSlave;
	if(slave.skin === 'tanned' || slave.skin === 'fair') {
		if(slave.preg > 10 || (slave.birthsTotal > 0 && slave.lactation > 0)) {
			return 'dark brown';
		} else {
			return 'pink';
		}
	} else if((slave.skin === 'pale' || slave.race === 'white')) {
		if(slave.preg > 10 || (slave.birthsTotal > 0 && slave.lactation > 0)) {
			return 'brown';
		} else {
			return 'pink';
		}
	} else if((slave.skin === 'brown' || slave.race === 'black')) {
		if(slave.preg > 10 || (slave.birthsTotal > 0 && slave.lactation > 0)) {
			return 'black';
		} else {
			return 'dark brown';
		}
	} else {
		if(slave.preg > 10 || (slave.birthsTotal > 0 && slave.lactation > 0)) {
			return 'dark brown';
		} else {
			return 'brown';
		}
	}
}

window.overpowerCheck = function(slave, PC) {
	var strength;

	if(State.variables.arcologies[0].FSPhysicalIdealist != "unset") {
		if(PC.title == 1) {
			strength = 130;
		} else {
			strength = 100;
		}
	} else if(PC.title == 1) {
		strength = 50;
	} else {
		strength = 30;
	}
	strength += (185-slave.height);
	strength -= (PC.belly/1000);

	return strength;
}

window.impregnatedBy = function(slave) { /* returns array of IDs of all characters who impregnated slave */
	var IDArray = [];
	if (!Array.isArray(slave.womb)) {
		WombInit(slave);
	}
	for (var i = 0; i < slave.womb.length; i++) {
		IDArray.push(slave.womb[i].fatherID);
	}
	return IDArray;
}

window.isImpregnatedBy = function(mother, father) { /* returns true if mother was impregnated by father */
	return impregnatedBy(mother).includes(father.ID);
}

window.jsAlert = function(obj)
{
	alert(obj);
}

window.jsConsoleInfo = function(obj)
{
	console.info(obj);
}


code:
:: Summary Widgets JS [script]

window.SlaveStatClamp = function SlaveStatClamp(slave) {
	slave.energy = Math.clamp(slave.energy, 0, 100);
	const V = State.variables;

	if (slave.devotion > 100) {
		if (slave.trust < -95)
			slave.trust = -100;
		else if ((slave.trust < 100) && (slave.trust >= 20))
			slave.trust += (Math.trunc((slave.devotion-100)*5)/10);
		else
			V.rep += 10*(slave.devotion-100);
		slave.devotion = 100;
	} else if (slave.devotion < -95)
		slave.devotion = -100;
	if (slave.trust > 100) {
		if (slave.devotion < -95)
			slave.devotion = -100;
		else if (slave.devotion < 100 && slave.devotion >= 20)
			slave.devotion += Math.trunc(slave.trust-100);
		else
			V.rep += 10*(slave.trust-100);
		slave.trust = 100;
	} else if (slave.trust < -95)
		slave.trust = -100;
	if (slave.trust < -100)
		slave.trust = -100;
	if (slave.devotion < -100)
		slave.devotion = -100;
	if (isNaN(slave.oralCount)) {
		slave.oralCount = 0;
		alert("Oral count has broken, report what you just did!");
	}
	if (isNaN(slave.analCount)) {
		slave.analCount = 0;
		alert("Anal count has broken, report what you just did!");
	}
	if (isNaN(slave.vaginalCount)) {
		slave.vaginalCount = 0;
		alert("Vaginal count has broken, report what you just did!");
	}
	if (isNaN(slave.mammaryCount)) {
		slave.mammaryCount = 0;
		alert("Titfuck count has broken, report what you just did!");
	}
	if (isNaN(slave.penetrativeCount)) {
		slave.penetrativeCount = 0;
		alert("Penetration count has broken, report what you just did!");
	}
	if (slave.foreskin === undefined)
		slave.foreskin = 0;
	if (slave.amp != 0 && slave.heels == 1)
		slave.heels = 0;
	if (slave.vagina < 0 && slave.mpreg == 0 && slave.preg == -1) {
		slave.preg = 0;
		WombFlush(slave);
	}

};


code:
:: textinput [script]

Macro.add("textinput", {
    // Signifies that the macro is a container macro.
    tags: null,

    handler: function() {
        if (this.args.length < 2) {
            var errors = [];
            if (this.args.length < 1) { errors.push("variable name"); }
            if (this.args.length < 2) { errors.push("default value"); }
            return this.error("no " + errors.join(" or ") + " specified");
        }

        // Ensure that the variable name argument is a string.
        if (typeof this.args[0] !== "string") {
            return this.error("variable name argument is not a string");
        }

        var varName = this.args[0].trim();

        // Try to ensure that we receive the variable's name (incl. sigil), not its value.
        if (varName[0] !== "$" && varName[0] !== "_") {
            return this.error("variable name '" + varName + "' is missing its sigil ($ or _)");
        }

        var that = this;
        var defaultValue = this.args[1];
        var el = document.createElement("textarea");

        // Setup and append the textarea element to the output buffer.
        jQuery(el)
            .attr({
                rows: 4,
                // cols: 68, // instead of setting "cols" we set the `min-width` in CSS
                tabindex: 0 // for accessiblity
            })
            .addClass("macro-textarea")  // "hijack" the .macro-textarea class
            .on("input", function() {
                Wikifier.setValue(varName, this.value);
                if (that.payload[0].contents !== "")
                    Wikifier.wikifyEval(that.payload[0].contents.trim());
            })
            .appendTo(this.output);

        // Set the story variable and textarea element to the default value.
        Wikifier.setValue(varName, defaultValue);

        // Ideally, we should be setting `.defaultValue` here, but IE doesn't support it,
        // so we have to use `.textContent`, which is equivalent.
        el.textContent = defaultValue;
    }
});


code:
:: textboxJS [script]

/* Nicked off greyelf, works for replace textboxes */
window.setReplaceTextboxMaxLength = function (storyVarName, maxLength) {
	var textboxId = '#textbox-' + Util.slugify(storyVarName);
	$(textboxId)
			.attr('maxlength', maxLength)
			.css({
				'min-width' : 'initial',
				width       : maxLength + 'em',
				padding		: '3px 2px'
			});
};

/* Nicked off TheMadExile, works for non-replace textboxes */
window.setTextboxMaxLength = function (storyVarName, maxLength) {
	var textboxId = '#textbox-' + Util.slugify(storyVarName);
	postdisplay[textboxId + '-maxlength'] = function (taskName) {
		delete postdisplay[taskName];
		$(textboxId)
			.attr('maxlength', maxLength)
			.css({
				'min-width' : 'initial',
				width       : maxLength + 'em',
				padding		: '3px 2px'
			});
	};
};