code:
/**
 * @param {ParentNode} renderContainer
 */
App.EndWeek.computeSexualServicesModel = function(renderContainer) {
	const arcology = V.arcologies[0];

	/* Sexual services demand per class */
	/* We can add milk etc. to this as well, though this is a good that can be traded beyond the arcology and also needs its own market much like the slave market. TODO: */
	/* In the default scenario these numbers indicate the amount of money each individual citizen of a particular class is looking to spend on sex (and milk) every week
	Depending on the conditions they may derive more or less 'utility' out of their credits spent
	i.e. a highly paternalist arcology with little choice for its lower class but Fuckdolls may still put money into them but not get the same satisfaction out of it*/
	/* Low rent increases demand/available money for sexual services, high rent decreases it */
	if (V.brothelBoost.selected > 0 && V.rep < V.brothelBoost.selected * 500 + 2000) {
		V.brothelBoost.eligible = Math.trunc((V.rep - 2000) / 500);
		if (V.brothelBoost.eligible < 0) {
			V.brothelBoost.eligible = 0;
		}
	} else {
		V.brothelBoost.eligible = V.brothelBoost.selected;
	}
	repX(forceNeg(50 * V.brothelBoost.eligible), "brothel");

	let lowerClassSexDemand = Math.trunc(V.lowerClass * V.whoreBudget.lowerClass) * 2;
	let lowerClassSexDemandRef = Math.max(lowerClassSexDemand, 1);
	let visitorsSexDemand = Math.trunc(V.visitors) * 40;
	let middleClassSexDemand = Math.trunc(V.middleClass * V.whoreBudget.middleClass + visitorsSexDemand * 0.5) * 2;
	let middleClassSexDemandRef = Math.max(middleClassSexDemand, 1);
	let upperClassSexDemand = Math.trunc(V.upperClass * V.whoreBudget.upperClass + visitorsSexDemand * 0.5) * 2;
	let upperClassSexDemandRef = Math.max(upperClassSexDemand, 1);
	let topClassSexDemand = Math.trunc(V.topClass * V.whoreBudget.topClass) * 2;
	let topClassSexDemandRef = Math.max(topClassSexDemand, 1);
	let arcadeSupply = {lowerClass: 0, middleClass: 0, upperClass: 0};
	let clubSupply = {lowerClass: 0, middleClass: 0};

	App.EndWeek.saVars.whorePriceAdjustment = {
		lowerClass: 0, middleClass: 0, upperClass: 0, topClass: 0
	};
	V.NPCMarketShare = {
		lowerClass: 0, middleClass: 0, upperClass: 0, topClass: 0
	};
	V.sexDemandResult = {
		lowerClass: 0, middleClass: 0, upperClass: 0, topClass: 0
	};
	App.EndWeek.saVars.slaveJobValues = slaveJobValues(lowerClassSexDemandRef, middleClassSexDemandRef, upperClassSexDemandRef, topClassSexDemandRef);
	const sjv = App.EndWeek.saVars.slaveJobValues;

	let lowerClassArcadeSexDemand = 0;
	let middleClassArcadeSexDemand = 0;
	let upperClassArcadeSexDemand = 0;
	let arcadeDemand = 0;
	let arcadeDemandDeg = 0;
	// Arcade Specific Demand for Degradationists to give it higher priority
	if (arcology.FSDegradationist !== "unset" && arcology.FSDegradationist > 0) {
		lowerClassArcadeSexDemand = Math.trunc(lowerClassSexDemand * arcology.FSDegradationist * 0.0015);
		middleClassArcadeSexDemand = Math.trunc(middleClassSexDemand * arcology.FSDegradationist * 0.0002);
		upperClassArcadeSexDemand = Math.trunc(upperClassSexDemand * arcology.FSDegradationist * 0.000025);
		arcadeDemandDeg = lowerClassArcadeSexDemand + middleClassArcadeSexDemand + upperClassArcadeSexDemand;
		if (arcology.FSDegradationistLaw === 1) {
			arcadeDemandDeg += V.ASlaves * 3;
		}
		if (sjv.arcade < arcadeDemandDeg) {
			if (arcadeDemandDeg > 20000 || arcology.FSDegradationist > 50) {
				const degradationistPenalty = ((arcadeDemandDeg - sjv.arcade) / arcadeDemandDeg);
				arcology.FSDegradationist -= Math.trunc(5 * degradationistPenalty);
				repX(forceNeg(100 * degradationistPenalty), "futureSocieties");
				V.arcadeDemandDegResult = degradationistPenalty > 0.5 ? 1 : 2;
			} else {
				V.arcadeDemandDegResult = 3;
			}
			arcadeSupply.lowerClass += Math.trunc(1.15 * sjv.arcade * (lowerClassArcadeSexDemand / arcadeDemandDeg));
			lowerClassSexDemand -= arcadeSupply.lowerClass;
			arcadeSupply.middleClass += Math.trunc(1.15 * sjv.arcade * (middleClassArcadeSexDemand / arcadeDemandDeg));
			middleClassSexDemand -= arcadeSupply.middleClass;
			arcadeSupply.upperClass += Math.trunc(1.15 * sjv.arcade * (upperClassArcadeSexDemand / arcadeDemandDeg));
			upperClassSexDemand -= arcadeSupply.upperClass; // There's a 15% satisfaction bonus from getting release in a societally approved way
		} else {
			if (sjv.arcade >= arcadeDemandDeg * 1.5) {
				arcology.FSDegradationist += 2;
				V.arcadeDemandDegResult = 4;
				repX(500, "futureSocieties");
			} else {
				V.arcadeDemandDegResult = 5;
			}
			arcadeSupply.lowerClass += Math.trunc(1.15 * lowerClassArcadeSexDemand);
			lowerClassSexDemand -= arcadeSupply.lowerClass;
			arcadeSupply.middleClass += Math.trunc(1.15 * middleClassArcadeSexDemand);
			middleClassSexDemand -= arcadeSupply.middleClass;
			arcadeSupply.upperClass += Math.trunc(1.15 * upperClassArcadeSexDemand);
			upperClassSexDemand -= arcadeSupply.upperClass;
		}
	}

	// Public slut sex supply. Top and upper class won't partake
	let clubDemand = lowerClassSexDemand + middleClassSexDemand;
	let lowerClassClubRatio = lowerClassSexDemand / clubDemand;
	let middleClassClubRatio = middleClassSexDemand / clubDemand;

	if (sjv.club * sjv.clubSP < clubDemand) {
		lowerClassSexDemand -= Math.trunc(sjv.club * sjv.clubSP * lowerClassClubRatio);
		middleClassSexDemand -= Math.trunc(sjv.club * sjv.clubSP * middleClassClubRatio);
	} else {
		lowerClassSexDemand = 0;
		middleClassSexDemand = 0;
	}

	clubSupply.lowerClass = Math.trunc(sjv.club * sjv.clubSP * lowerClassClubRatio);
	clubSupply.middleClass = Math.trunc(sjv.club * sjv.clubSP * middleClassClubRatio);

	// Brothel or street whore sex supply
	if (lowerClassSexDemand < sjv.brothel.lowerClass) {
		App.EndWeek.saVars.whorePriceAdjustment.lowerClass = Math.max(Math.pow(lowerClassSexDemand / (sjv.brothel.lowerClass + V.NPCSexSupply.lowerClass), 1.513), 0.3);
		lowerClassSexDemand = 0; // This accounts for people having too much choice and getting more picky how they spend their money
	} else {
		App.EndWeek.saVars.whorePriceAdjustment.lowerClass = Math.pow(lowerClassSexDemand / (sjv.brothel.lowerClass + V.NPCSexSupply.lowerClass), 0.5);
		lowerClassSexDemand -= sjv.brothel.lowerClass; // People are willing to pay more for a scarce good, but within reason
	}
	if (middleClassSexDemand < sjv.brothel.middleClass) {
		App.EndWeek.saVars.whorePriceAdjustment.middleClass = Math.max(Math.pow((middleClassSexDemand * 1.1) / (sjv.brothel.middleClass + V.NPCSexSupply.middleClass), 1.513), 0.33);
		middleClassSexDemand = 0;
	} else {
		App.EndWeek.saVars.whorePriceAdjustment.middleClass = Math.pow((middleClassSexDemand * 1.1) / (sjv.brothel.middleClass + V.NPCSexSupply.middleClass), 0.5);
		middleClassSexDemand -= sjv.brothel.middleClass;
	}
	if (upperClassSexDemand < sjv.brothel.upperClass) {
		App.EndWeek.saVars.whorePriceAdjustment.upperClass = Math.max(Math.pow((upperClassSexDemand * 1.21) / (sjv.brothel.upperClass + V.NPCSexSupply.upperClass), 1.513), 0.363);
		upperClassSexDemand = 0;
	} else {
		App.EndWeek.saVars.whorePriceAdjustment.upperClass = Math.pow((upperClassSexDemand * 1.21) / (sjv.brothel.upperClass + V.NPCSexSupply.upperClass), 0.5);
		upperClassSexDemand -= sjv.brothel.upperClass;
	}
	if (topClassSexDemand < sjv.brothel.topClass) {
		App.EndWeek.saVars.whorePriceAdjustment.topClass = Math.max(Math.pow((topClassSexDemand * 1.331) / (sjv.brothel.topClass + V.NPCSexSupply.topClass), 1.513), 0.3993);
		topClassSexDemand = 0;
	} else {
		App.EndWeek.saVars.whorePriceAdjustment.topClass = Math.pow((topClassSexDemand * 1.331) / (sjv.brothel.topClass + V.NPCSexSupply.topClass), 0.5);
		topClassSexDemand -= sjv.brothel.topClass;
	}

	// Price for sex in the arcade or at a glory hole
	if (arcology.FSPaternalist !== "unset" && arcology.FSPaternalist > 0) {
		arcadeDemand = Math.max((arcadeDemandDeg + lowerClassSexDemand) * (1 - arcology.FSPaternalist / 50), 0); // Paternalists sap demand for the arcade
	} else {
		arcadeDemand = arcadeDemandDeg + lowerClassSexDemand;
	}
	if (sjv.arcade + V.NPCSexSupply.lowerClass > 0) {
		V.arcadePrice = Math.clamp(Math.pow((arcadeDemand / (sjv.arcade + V.NPCSexSupply.lowerClass)), 0.5), 0.5, 3); // This calculates the price charged per fuck
	} else {
		V.arcadePrice = 0.5; // minimum price no matter what
	}

	// Arcade usage beyond degradationist demand
	if (sjv.arcade > arcadeDemandDeg) {
		sjv.arcade -= arcadeDemandDeg;
	} else {
		sjv.arcade = 0;
	}
	if (sjv.arcade > lowerClassSexDemand) {
		lowerClassSexDemand = 0;
	} else {
		lowerClassSexDemand -= sjv.arcade;
	}
	arcadeSupply.lowerClass += sjv.arcade;

	// NPC sex supply
	V.NPCSexSupply = NPCSexSupply(lowerClassSexDemand, lowerClassSexDemandRef, middleClassSexDemand, middleClassSexDemandRef, upperClassSexDemand, upperClassSexDemandRef, topClassSexDemand, topClassSexDemandRef);
	V.NPCMarketShare.lowerClass = Math.trunc((V.NPCSexSupply.lowerClass * 1000) / lowerClassSexDemandRef);
	V.NPCMarketShare.middleClass = Math.trunc((V.NPCSexSupply.middleClass * 1000) / middleClassSexDemandRef);
	V.NPCMarketShare.upperClass = Math.trunc((V.NPCSexSupply.upperClass * 1000) / upperClassSexDemandRef);
	V.NPCMarketShare.topClass = Math.trunc((V.NPCSexSupply.topClass * 1000) / topClassSexDemandRef);
	if (lowerClassSexDemand < V.NPCSexSupply.lowerClass) {
		lowerClassSexDemand = 0;
	} else {
		lowerClassSexDemand -= V.NPCSexSupply.lowerClass;
	}

	if (middleClassSexDemand < V.NPCSexSupply.middleClass) {
		middleClassSexDemand = 0;
	} else {
		middleClassSexDemand -= V.NPCSexSupply.middleClass;
	}

	if (upperClassSexDemand < V.NPCSexSupply.upperClass) {
		upperClassSexDemand = 0;
	} else {
		upperClassSexDemand -= V.NPCSexSupply.upperClass;
	}

	if (topClassSexDemand < V.NPCSexSupply.topClass) {
		topClassSexDemand = 0;
	} else {
		topClassSexDemand -= V.NPCSexSupply.topClass;
	}

	if (V.cheatMode === 1 || V.debugMode === 1) {
		_printDebugInfo(renderContainer);
	}

	// Sexual satisfaction effects
	V.sexDemandResult.lowerClass = Math.trunc(((V.NPCSexSupply.lowerClass + sjv.brothel.lowerClass + clubSupply.lowerClass + arcadeSupply.lowerClass) * 1000) / lowerClassSexDemandRef);
	V.sexDemandResult.middleClass = Math.trunc(((V.NPCSexSupply.middleClass + sjv.brothel.middleClass + clubSupply.middleClass + arcadeSupply.middleClass) * 1000) / middleClassSexDemandRef);
	V.sexDemandResult.upperClass = Math.trunc(((V.NPCSexSupply.upperClass + sjv.brothel.upperClass + arcadeSupply.upperClass) * 1000) / upperClassSexDemandRef);
	V.sexDemandResult.topClass = Math.trunc(((V.NPCSexSupply.topClass + sjv.brothel.topClass) * 1000) / topClassSexDemandRef);

	if (V.sexDemandResult.lowerClass < 400) { // You are providing < 40% of their desired amount of sex
		if (V.week <= 30) {
			V.classSatisfied.lowerClass = 0;
		} else {
			V.classSatisfied.lowerClass = -1;
		}
	} else if (V.sexDemandResult.lowerClass < 600) { // You are providing between 40 and 60% of their desired amount of sex
		if (V.week <= 40) {
			V.classSatisfied.lowerClass = 1;
		} else if (V.week <= 60) {
			V.classSatisfied.lowerClass = 0;
		} else {
			V.classSatisfied.lowerClass = -1;
		}
	} else if (V.sexDemandResult.lowerClass < 800) { // You are providing between 60 and 80% of their desired amount of sex
		if (V.week <= 50) {
			V.classSatisfied.lowerClass = 1;
		} else {
			V.classSatisfied.lowerClass = 0;
		}
	} else if (V.sexDemandResult.lowerClass === 1000) { // You are providing 100% or more of their desired amount of sex
		V.classSatisfied.lowerClass = 2;
	} else { // You are providing > 80% of their desired amount of sex
		V.classSatisfied.lowerClass = 1;
	}

	if (V.sexDemandResult.middleClass < 400) { // You are providing < 40% of their desired amount of sex
		if (V.week <= 30) {
			V.classSatisfied.middleClass = 0;
		} else {
			V.classSatisfied.middleClass = -1;
		}
	} else if (V.sexDemandResult.middleClass < 600) { // You are providing between 40 and 60% of their desired amount of sex
		if (V.week <= 40) {
			V.classSatisfied.middleClass = 1;
		} else if (V.week <= 60) {
			V.classSatisfied.middleClass = 0;
		} else {
			V.classSatisfied.middleClass = -1;
		}
	} else if (V.sexDemandResult.middleClass < 800) { // You are providing between 60 and 80% of their desired amount of sex
		if (V.week <= 50) {
			V.classSatisfied.middleClass = 1;
		} else {
			V.classSatisfied.middleClass = 0;
		}
	} else if (V.sexDemandResult.middleClass === 1000) { // You are providing 100% or more of their desired amount of sex
		V.classSatisfied.middleClass = 2;
	} else { // You are providing > 80% of their desired amount of sex
		V.classSatisfied.middleClass = 1;
	}

	if (V.sexDemandResult.upperClass < 400) { // You are providing < 40% of their desired amount of sex
		if (V.week <= 30) {
			V.classSatisfied.upperClass = 0;
		} else {
			V.classSatisfied.upperClass = -1;
		}
	} else if (V.sexDemandResult.upperClass < 600) { // You are providing between 40 and 60% of their desired amount of sex
		if (V.week <= 40) {
			V.classSatisfied.upperClass = 1;
		} else if (V.week <= 60) {
			V.classSatisfied.upperClass = 0;
		} else {
			V.classSatisfied.upperClass = -1;
		}
	} else if (V.sexDemandResult.upperClass < 800) { // You are providing between 60 and 80% of their desired amount of sex
		if (V.week <= 50) {
			V.classSatisfied.upperClass = 1;
		} else {
			V.classSatisfied.upperClass = 0;
		}
	} else if (V.sexDemandResult.upperClass === 1000) { // You are providing 100% or more of their desired amount of sex
		V.classSatisfied.upperClass = 2;
	} else { // You are providing > 80% of their desired amount of sex
		V.classSatisfied.upperClass = 1;
	}

	if (V.sexDemandResult.topClass < 400) { // You are providing < 40% of their desired amount of sex
		if (V.week <= 30) {
			V.classSatisfied.topClass = 0;
		} else {
			V.classSatisfied.topClass = -1;
		}
	} else if (V.sexDemandResult.topClass < 600) { // You are providing between 40 and 60% of their desired amount of sex
		if (V.week <= 40) {
			V.classSatisfied.topClass = 1;
		} else if (V.week <= 60) {
			V.classSatisfied.topClass = 0;
		} else {
			V.classSatisfied.topClass = -1;
		}
	} else if (V.sexDemandResult.topClass < 800) { // You are providing between 60 and 80% of their desired amount of sex
		if (V.week <= 50) {
			V.classSatisfied.topClass = 1;
		} else {
			V.classSatisfied.topClass = 0;
		}
	} else if (V.sexDemandResult.topClass === 1000) { // You are providing 100% or more of their desired amount of sex
		V.classSatisfied.topClass = 2;
	} else { // You are providing > 80% of their desired amount of sex
		V.classSatisfied.topClass = 1;
	}

	/**
	 * @param {ParentNode} c
	 */
	function _printDebugInfo(c) {
		App.UI.DOM.appendNewElement("div", c, "Slave services supply and demand this week:");

		const table = App.UI.DOM.appendNewElement("table", c, null, "finance");
		table.style.border = "1";
		const titleRow = App.UI.DOM.appendNewElement("tr", table);
		titleRow.style.textAlign = "center";
		const tcl = App.UI.DOM.appendNewElement("th", titleRow, "Client's class");
		tcl.style.textAlign = "right";
		App.UI.DOM.appendNewElement("th", titleRow, "Lower");
		App.UI.DOM.appendNewElement("th", titleRow, "Middle");
		App.UI.DOM.appendNewElement("th", titleRow, "Upper");
		App.UI.DOM.appendNewElement("th", titleRow, "Top");

		/**
		 *
		 * @param {string} caption
		 * @param {number} [lower]
		 * @param {number} [middle]
		 * @param {number} [upper]
		 * @param {number} [top]
		 */
		function numericRow(caption, lower, middle, upper, top) {
			const row = App.UI.DOM.appendNewElement("tr", table);
			row.align = "right";
			App.UI.DOM.appendNewElement("td", row, caption);
			App.UI.DOM.appendNewElement("td", row, lower == null ? "N/A" : commaNum(lower));
			App.UI.DOM.appendNewElement("td", row, middle == null ? "N/A" : commaNum(middle));
			App.UI.DOM.appendNewElement("td", row, upper == null ? "N/A" : commaNum(upper));
			App.UI.DOM.appendNewElement("td", row, top == null ? "N/A" : commaNum(top));
		}

		numericRow("Demand", lowerClassSexDemandRef, middleClassSexDemandRef, upperClassSexDemandRef, topClassSexDemandRef);
		numericRow("Brothel Supply", sjv.brothel.lowerClass, sjv.brothel.middleClass, sjv.brothel.upperClass, sjv.brothel.topClass);
		if (clubSupply.lowerClass || clubSupply.middleClass) {
			numericRow("Club Supply", clubSupply.lowerClass, clubSupply.middleClass);
		}
		if (arcadeSupply.lowerClass || arcadeSupply.middleClass || arcadeSupply.upperClass) {
			numericRow("Arcade Supply", arcadeSupply.lowerClass, arcadeSupply.middleClass, arcadeSupply.upperClass);
		}
		numericRow("NPC Supply", V.NPCSexSupply.lowerClass, V.NPCSexSupply.middleClass, V.NPCSexSupply.upperClass, V.NPCSexSupply.topClass);
		numericRow("Unsatisfied", lowerClassSexDemand, middleClassSexDemand, upperClassSexDemand, topClassSexDemand);
	}
};


code:
App.EndWeek.slaveAssignmentReport = function() {
	const facilities = App.Entity.facilities;
	const arcology = V.arcologies[0];

	const initialEmployeesCount = App.Utils.countFacilityWorkers(); // will be used to show differences after all the assignment changes
	const initialPenthouseTotalEmployeesCount = _countPenthousePopulation();

	/* Initialize global SA variables */
	App.EndWeek.saVars = new App.EndWeek.SASharedVariables();

	/* Spa room */
	if (facilities.spa.established) {
		V.spaSpots = (facilities.spa.capacity - App.Entity.facilities.spa.employeesIDs().size) * 20;
		if (S.Attendant) {
			V.spaSpots = Math.trunc(V.spaSpots * (1 + (S.Attendant.skill.attendant / 400))); // A skilled attendant improves available space by 25%
		}
	}

	const skillsToTest = {
		whoring: "whore",
		entertainment: "entertain",
		vaginal: "vaginal",
		anal: "anal",
		oral: "oral"
	};

	const res = document.createDocumentFragment();

	/* perform reassignments before generating reports */
	for (const slave of V.slaves) {
		for (const sk in skillsToTest) {
			if (_.isNil(slave.skill[sk])) {
				_printSlaveError(`Reset bad ${skillsToTest[sk]} skill`, slave);
				slave.skill[sk] = 0;
			}
		}

		// fire unqualified special slaves
		_ensureEmployeeMeetsJobRequirements(slave);

		// first pass on choosesOwnJob is silent
		if (slave.choosesOwnAssignment === 1) {
			App.SlaveAssignment.choosesOwnJob(slave);
		}
	}

	App.EndWeek.computeSexualServicesModel(res);

	let slavesWithWorkingDicks = 0;
	for (const slave of V.slaves) {
		if ((V.seeDicks > 0) && canPenetrate(slave) && App.Utils.hasNonassignmentSex(slave)) {
			App.EndWeek.saVars.averageDick += slave.dick;
			slavesWithWorkingDicks++;
		}

		if (slave.lactation === 1) {
			slave.lactationDuration--;
		}

		switch (slave.assignment) {
			case Job.HEADGIRLSUITE:
				if (slave.devotion >= random(-30, 20)) {
					App.EndWeek.saVars.HGSlaveSuccess = true;
					App.EndWeek.saVars.HGEnergy++;
				}
				break;
			case Job.SUBORDINATE: {
				const map = App.EndWeek.saVars.subSlaveMap;
				const curSubs = map.get(slave.subTarget);
				if (curSubs) {
					curSubs.push(slave.ID);
				} else {
					map.set(slave.subTarget, [slave.ID]);
				}
				break;
			}
		}

		if (slave.bellyPain !== 0) {
			slave.bellyPain = 0;
		}

		/* preg speed and advance*/

		if (slave.preg > 0) {
			let pregSpeed = 1; // base speed is normal
			if (slave.pregControl === "slow gestation") {
				pregSpeed = 0.25;
			} else if (slave.pregControl === "speed up") {
				pregSpeed = 2;
			}

			if (slave.broodmother === 1 && slave.broodmotherOnHold !== 1) { /* broodmother advance block */
				if ((V.week / slave.broodmotherFetuses === Math.round(V.week / slave.broodmotherFetuses)) && slave.broodmotherFetuses < 1) {
					// one fetus in few week - selection and adding
					WombImpregnate(slave, 1, slave.pregSource, 0);
				} else {
					// one or more fetuses in one week
					WombImpregnate(slave, Math.floor(slave.broodmotherFetuses), slave.pregSource, 0); /* really 0, it's will be advanced right few lines down.*/
				}
				if (slave.ovaryAge >= 47) {
					slave.broodmotherOnHold = 1;
					slave.broodmotherCountDown = 37 - WombMinPreg(slave);
				}
			}

			WombProgress(slave, pregSpeed, 1); /* drugs can affect speed of gestation, but not a real time */

			slave.pregKnown = 1;
			slave.pregWeek++;
		}
		if (slave.pregWeek < 0) { // postpartum state
			slave.pregWeek++;
		}

		SetBellySize(slave); /* here will be also set through WombGetVolume .bellyPreg, .pregType, to current values. */

		/* end of preg speed and advance*/

		/* set up sexual need */
		if (slave.devotion >= -50) {
			if (slave.energy > 20) {
				if (slave.physicalAge < slave.pubertyAgeXY && slave.genes === "XY" && slave.energy <= 80) {
					slave.need = slave.energy / 3;
				} else if (slave.physicalAge < slave.pubertyAgeXX && slave.genes === "XX" && slave.energy <= 80) {
					slave.need = slave.energy / 3;
				} else if (slave.physicalAge < 50) {
					slave.need = slave.energy;
				} else {
					slave.need = slave.energy / 5;
				}
				if (slave.balls > 0 && slave.pubertyXY === 1 && slave.physicalAge <= (slave.pubertyAgeXY + 1) && (slave.physicalAge > slave.pubertyAgeXY) && slave.physicalAge < 18) {
					slave.need *= 1.25;
				}
				if ((slave.ovaries === 1 || slave.mpreg === 1) && slave.pubertyXX === 1 && slave.physicalAge <= (slave.pubertyAgeXX + 1) && (slave.physicalAge > slave.pubertyAgeXX) && slave.physicalAge < 18) {
					slave.need *= 1.25;
				}
				if (slave.diet === "fertility") {
					slave.need += 10;
				}
				if (slave.aphrodisiacs === -1) {
					slave.need *= 0.5;
				} else if (slave.aphrodisiacs === 1) {
					slave.need *= 1.5;
				} else if (slave.aphrodisiacs === 2) {
					slave.need *= 2;
				}
				poorHealthNeedReduction(slave);
				slave.need = Math.round(slave.need);
				slave.needCap = slave.need;
			}
		}

		if (slave.fetish === "mindbroken" && slave.relationship === -3) {
			if (slave.kindness > 0) {
				slave.kindness--;
			}
		}

		if (slave.assignment === Job.AGENT || slave.assignment === Job.AGENTPARTNER) {
			App.SlaveAssignment.agent(slave);
		}
	} // for (const slave of V.slaves)

	if (V.HeadGirlID !== 0) {
		App.EndWeek.saVars.HGEnergy++;
		const slave = slaveStateById(V.HeadGirlID);
		if (V.personalAttention.task === PersonalAttention.SUPPORTHG && V.PC.health.shortDamage < 30) {
			App.EndWeek.saVars.HGEnergy++;
			if (slave.trust > 95) {
				App.EndWeek.saVars.HGEnergy++;
			}
		}
		if (arcology.FSChineseRevivalistLaw === 1) {
			App.EndWeek.saVars.HGEnergy++;
		}
		if (slaveResting(slave)) {
			App.EndWeek.saVars.HGEnergy = 0;
		}
		if (canAchieveErection(slave)) {
			App.EndWeek.saVars.HGCum = resetHGCum(slave);
		}
	}

	// Stud gets off based on impregnations, so we need to check and see if they actually do anyone
	if (V.StudID) {
		const stud = S.Stud;
		App.EndWeek.saVars.StudCum = 2 + Math.trunc(((stud.balls / 5) + (stud.energy / 95) + (stud.health.condition / 95) + (stud.devotion / 95) + (V.reproductionFormula * 5) - (stud.health.tired / 25)) * restEffects(stud, 5));
		if (stud.drugs === "hyper testicle enhancement") {
			App.EndWeek.saVars.StudCum += 3;
		} else if (stud.drugs === "testicle enhancement") {
			App.EndWeek.saVars.StudCum += 1;
		}
		if (stud.diet === "cum production") {
			App.EndWeek.saVars.StudCum += 1;
		}
		let studCumLimit = App.EndWeek.saVars.StudCum;
		for (const slave of V.slaves) {
			if (studCumLimit === 0 || stud.need <= 0) {
				break;
			}
			if (canGetPregnant(slave) && canBreed(stud, slave) && slave.ID !== V.StudID) {
				stud.need -= 20;
				if (stud.fetish === "pregnancy") {
					stud.need -= 30;
				}
			}
		}
	}

	if (App.EndWeek.saVars.averageDick > 0) {
		App.EndWeek.saVars.averageDick = App.EndWeek.saVars.averageDick / slavesWithWorkingDicks;
	}
	App.EndWeek.saVars.freeSexualEnergy = V.PC.sexualEnergy - fuckSlavesLength();
	const penthouseSlaves = App.Entity.facilities.penthouse.employees().length;
	if (App.EndWeek.saVars.freeSexualEnergy > 0) {
		if (App.EndWeek.saVars.freeSexualEnergy > penthouseSlaves / 2) {
			App.EndWeek.saVars.freeSexualEnergy = 3;
		} else if (App.EndWeek.saVars.freeSexualEnergy > penthouseSlaves / 4) {
			App.EndWeek.saVars.freeSexualEnergy = 2;
		} else {
			App.EndWeek.saVars.freeSexualEnergy = 1;
		}
	}

	// initialize slave art
	if (V.seeImages && V.seeReportImages) {
		// agents and partners are not drawn; penthouse partners and the head girl's slave will be drawn via a different mechanism (since they are larger and right-aligned)
		const undrawnJobs = [Job.AGENT, Job.AGENTPARTNER, ...App.Entity.facilities.penthouse.jobsNames, Job.HEADGIRLSUITE];
		const drawnSlaveIDs = V.slaves.filter(s => !undrawnJobs.includes(s.assignment)).map(s => s.ID);
		// this batch renderer object will be accessible to all the facility reports
		App.EndWeek.saVars.slaveArt = new App.Art.SlaveArtBatch(drawnSlaveIDs, 0);
		res.append(App.EndWeek.saVars.slaveArt.writePreamble());
	}

	/**
	 * Accordion
	 * @version 0.7RC
	 * @author 000-250-006
	 *
	 * @param array _facListArr
	 *	Multidimensional temporary array
	 *	0: The DOM function for the facility's report
	 *	1: A facility object, or the title of the report if there is no facility object
	 *	2: If there is no facility object, a truthy value indicating whether the facility exists
	 *	3: If there is no facility object, the maximum capacity of the facility
	 *
	 * TODO: This is a proof of concept construct, if it works and cuts overhead, intended to create an object
	 *	for deeper use in multiple locations, including streamlining reports/facilities code to one widget
	 * TODO: Figure out if this would be better as an object rather than an array for overhead
	 *	StoryInit also?
	 */

	const facListArr = [
		[App.EndWeek.arcadeReport, App.Entity.facilities.arcade],
		[App.EndWeek.brothelReport, App.Entity.facilities.brothel],
		[App.EndWeek.cellblockReport, App.Entity.facilities.cellblock],
		[App.EndWeek.clinicReport, App.Entity.facilities.clinic],
		[App.EndWeek.clubReport, App.Entity.facilities.club],
		[App.EndWeek.dairyReport, App.Entity.facilities.dairy],
		[App.EndWeek.farmyardReport, App.Entity.facilities.farmyard],
		[App.EndWeek.schoolroomReport, App.Entity.facilities.schoolroom],
		[App.EndWeek.spaReport, App.Entity.facilities.spa],
		[App.EndWeek.servantsQuartersReport, App.Entity.facilities.servantsQuarters],
		[App.Facilities.Nursery.nurseryReport, App.Entity.facilities.nursery],
		[App.Facilities.Nursery.childrenReport, "Nursery Children", V.nursery, V.nurseryChildren],
		[App.EndWeek.incubatorReport, App.Entity.facilities.incubator],
		[App.EndWeek.masterSuiteReport, App.Entity.facilities.masterSuite],
		[App.EndWeek.penthouseReport, "The Penthouse"],
		[App.EndWeek.rulesAssistantReport, "Rules Assistant", V.rulesAssistantAuto], /** should be last — may reassign slaves **/
		[App.EndWeek.labReport, "Lab", V.researchLab.level]
	];

	function _getReportElementStats(ar) {
		if (typeof ar[1] === "string") {
			if (ar[1] === "The Penthouse") { // special case because we have to combine several facilities
				return {
					name: ar[1],
					established: 1,
					entriesNumberInitial: initialPenthouseTotalEmployeesCount,
					entriesNumber: _countPenthousePopulation(),
					manager: null,
					alwaysExists: 0,
				};
			} else {
				return {
					name: ar[1],
					established: ar[2],
					entriesNumberInitial: null,
					entriesNumber: ar[3],
					manager: null,
					alwaysExists: ar[3] === undefined ? 1 : 0,
				};
			}
		} else {
			return {
				name: capFirstChar(ar[1].name),
				established: ar[1].established,
				entriesNumberInitial: initialEmployeesCount[ar[1].desc.baseName],
				entriesNumber: ar[1].hostedSlaves,
				manager: ar[1].manager,
				alwaysExists: 0,
			};
		}
	}

	for (const facSubArr of facListArr) {
		// needs to be inside the loop after the report passage to get the employees number after re-assignments
		const stats = _getReportElementStats(facSubArr);

		if (stats.established) { // Do we have one of these facilities?
			const header = document.createDocumentFragment();
			App.UI.DOM.appendNewElement("span", header, `${stats.name} Report`, "title");

			if (!stats.alwaysExists) {
				const diffNum = stats.entriesNumber - stats.entriesNumberInitial;
				const diffText = diffNum === 0 ? "" : (diffNum > 0 ? ` (+${diffNum})` : ` (${diffNum})`);
				// Display the bar with information
				if (stats.entriesNumber > 0) {
					App.UI.DOM.appendNewElement("span", header,
						`${stats.entriesNumber}${diffText} slave${stats.entriesNumber !== 1 ? "s" : ""} ${
							stats.manager && stats.manager.currentEmployee
								? `and ${capFirstChar(stats.manager.desc.position)}` : ""
						} in ${stats.name}`, ["info", "green"]);
				} else if (stats.manager && stats.manager.currentEmployee) {
					App.UI.DOM.appendNewElement("span", header,
						`${diffText} Only ${capFirstChar(stats.manager.desc.position)} in ${stats.name}`,
						["info", "orange"]);
				} else {
					App.UI.DOM.appendNewElement("span", header, `${diffText} ${stats.name} is empty`,
						["info", "gray"]);
				}
			}

			// Is there anyone inside the facility?
			if (stats.entriesNumber > 0 || (stats.manager && stats.manager.currentEmployee) || stats.alwaysExists) {
				// @ts-ignore - the first element of the subarray is always callable but TS isn't smart enough to figure that out
				const reportContent = App.UI.DOM.makeElement("div", facSubArr[0]());
				res.append(App.UI.DOM.accordion(header, reportContent, V.useAccordion > 0));
			} else {
				res.append(App.UI.DOM.accordion(header));
			}
		}
	}

	/* Clean up global SA variables */
	App.EndWeek.saVars = null;
	delete V.flSex; // FIXME: remove, once this is passed as a parameter to saRules

	return res;

	function _countPenthousePopulation() {
		const fs = App.Entity.facilities;
		return fs.penthouse.employeesIDs().size + fs.headGirlSuite.totalEmployeesCount + fs.armory.totalEmployeesCount;
	}

	function _printSlaveError(warning, slave) {
		const warningLine = App.UI.DOM.appendNewElement("div", res);
		App.UI.DOM.appendNewElement("span", warningLine, warning + `for ${slave.slaveName}.`, "yellow");
		warningLine.appendChild(document.createTextNode(" Report this as a bug if it reoccurs."));
	}

	/**
	 * Check key employees. Fire those who do not satisfy their job requirements
	 * @param {App.Entity.SlaveState} slave
	 */
	function _ensureEmployeeMeetsJobRequirements(slave) {
		switch (slave.assignment) {
			case Job.HEADGIRL:
				if (slave.fetish === "mindbroken") {
					_printSlaveUnassignedNote(slave, "is mindbroken");
					V.HeadGirlID = 0;
				} else if (!canTalk(slave)) {
					_printSlaveUnassignedNote(slave, "can't give slaves verbal orders");
					V.HeadGirlID = 0;
				} else if (!canWalk(slave)) {
					_printSlaveUnassignedNote(slave, "is no longer independently mobile");
					V.HeadGirlID = 0;
				} else if (!canHold(slave)) {
					_printSlaveUnassignedNote(slave, "is no longer able to handle your slaves");
					V.HeadGirlID = 0;
				} else if (!canSee(slave)) {
					_printSlaveUnassignedNote(slave, "can no longer see");
					V.HeadGirlID = 0;
				} else if (!canHear(slave)) {
					_printSlaveUnassignedNote(slave, "can no longer hear");
					V.HeadGirlID = 0;
				} else if (slave.preg > 37 && slave.broodmother === 2) {
					_printSlaveUnassignedNote(slave, "spends so much time giving birth and laboring that", `${getPronouns(slave).he} cannot effectively serve as your Head Girl any longer`);
					V.HeadGirlID = 0;
				} else if (slave.devotion <= 20) {
					_printSlaveUnassignedNote(slave, "is no longer even accepting of you");
					V.HeadGirlID = 0;
				}
				if (V.HeadGirlID === 0) {
					removeJob(slave, Job.HEADGIRL);
				}
				break;
			case Job.RECRUITER:
				V.RecruiterID = slave.ID;
				if (slave.fetish === "mindbroken") {
					_printSlaveUnassignedNote(slave, "is mindbroken");
					V.RecruiterID = 0;
				} else if (!canTalk(slave)) {
					_printSlaveUnassignedNote(slave, "can't verbally entice marks");
					V.RecruiterID = 0;
				} else if (slave.preg > 37 && slave.broodmother === 2) {
					_printSlaveUnassignedNote(slave, "spends so much time giving birth and laboring that", `${getPronouns(slave).he} cannot effectively serve as your recruiter any longer`);
					V.RecruiterID = 0;
				} else if (!canWalk(slave)) {
					_printSlaveUnassignedNote(slave, "is no longer independently mobile");
					V.RecruiterID = 0;
				} else if (!canSee(slave)) {
					_printSlaveUnassignedNote(slave, "can no longer see");
					V.RecruiterID = 0;
				} else if (!canHear(S.Recruiter)) {
					_printSlaveUnassignedNote(slave, "an no longer hear");
					V.RecruiterID = 0;
				}
				if (V.RecruiterID === 0) {
					removeJob(slave, Job.RECRUITER);
				}
				break;
			case Job.MADAM:
				if (!canTalk(slave)) {
					_printSlaveUnassignedNote(slave, "can't give whores verbal orders");
					V.MadamID = 0;
				} else if (slave.preg > 37 && slave.broodmother === 2) {
					_printSlaveUnassignedNote(slave, "spends so much time giving birth and laboring that", `${getPronouns(slave).he} cannot effectively serve as your Madam any longer`);
					V.MadamID = 0;
				} else if (slave.fetish === "mindbroken") {
					_printSlaveUnassignedNote(slave, "is mindbroken");
					V.MadamID = 0;
				} else if (!canWalk(slave)) {
					_printSlaveUnassignedNote(slave, "is no longer independently mobile");
					V.MadamID = 0;
				} else if (!canSee(slave)) {
					_printSlaveUnassignedNote(slave, "can no longer see");
					V.MadamID = 0;
				} else if (!canHear(slave)) {
					_printSlaveUnassignedNote(slave, "can no longer hear");
					V.MadamID = 0;
				} else if (!canHold(slave)) {
					_printSlaveUnassignedNote(slave, `can no longer handle ${getPronouns(slave).his} underlings`);
					V.MadamID = 0;
				}
				if (V.MadamID === 0) {
					removeJob(slave, Job.MADAM);
				}
				break;
			case Job.DJ:
				if (!canTalk(slave)) {
					_printSlaveUnassignedNote(slave, "can't speak");
					V.djID = 0;
				} else if (slave.preg > 37 && slave.broodmother === 2) {
					_printSlaveUnassignedNote(slave, "spends so much time giving birth and laboring that", `${getPronouns(slave).he} cannot effectively serve as your DJ any longer`);
					V.djID = 0;
				} else if (slave.fetish === "mindbroken") {
					_printSlaveUnassignedNote(slave, "is mindbroken");
					V.djID = 0;
				} else if (!canWalk(slave)) {
					_printSlaveUnassignedNote(slave, "is no longer independently mobile");
					V.djID = 0;
				} else if (!canHear(slave)) {
					_printSlaveUnassignedNote(slave, "can no longer hear");
					V.djID = 0;
				}
				if (V.djID === 0) {
					removeJob(slave, Job.DJ);
				}
				break;
			case Job.MILKMAID:
				if (slave.fetish === "mindbroken") {
					_printSlaveUnassignedNote(slave, "is mindbroken");
					V.MilkmaidID = 0;
				} else if (slave.preg > 37 && slave.broodmother === 2) {
					_printSlaveUnassignedNote(slave, "spends so much time giving birth and laboring that", `${getPronouns(slave).he} cannot effectively serve as your Milkmaid any longer`);
					V.MilkmaidID = 0;
				} else if (!canWalk(slave)) {
					_printSlaveUnassignedNote(slave, "is no longer independently mobile");
					V.MilkmaidID = 0;
				} else if (!canHold(slave)) {
					_printSlaveUnassignedNote(slave, "can no longer handle nor milk your slaves");
					V.MilkmaidID = 0;
				} else if (!canSee(slave)) {
					_printSlaveUnassignedNote(slave, "can no longer see");
					V.MilkmaidID = 0;
				} else if (!canHear(slave)) {
					_printSlaveUnassignedNote(slave, "can no longer hear");
					V.MilkmaidID = 0;
				}
				if (V.MilkmaidID === 0) {
					removeJob(slave, Job.MILKMAID);
				}
				break;
			case Job.FARMER:
				if (S.Farmer.fetish === "mindbroken") {
					_printSlaveUnassignedNote(slave, "is mindbroken");
					V.FarmerID = 0;
				} else if (S.Farmer.preg > 37 && S.Farmer.broodmother === 2) {
					_printSlaveUnassignedNote(slave, "spends so much time giving birth and laboring that", `${getPronouns(slave).he} cannot effectively serve as your Farmer any longer`);
					V.FarmerID = 0;
				} else if (!canWalk(S.Farmer)) {
					_printSlaveUnassignedNote(slave, "is no longer independently mobile");
					V.FarmerID = 0;
				} else if (!canHold(S.Farmer)) {
					_printSlaveUnassignedNote(slave, "can no longer grip things");
					V.FarmerID = 0;
				} else if (!canSee(S.Farmer)) {
					_printSlaveUnassignedNote(slave, "can no longer see");
					V.FarmerID = 0;
				} else if (!canHear(S.Farmer)) {
					_printSlaveUnassignedNote(slave, "can no longer hear");
					V.FarmerID = 0;
				}
				if (V.FarmerID === 0) {
					removeJob(slave, Job.FARMER);
				}
				break;
			case Job.STEWARD:
				if (!canTalk(slave)) {
					_printSlaveUnassignedNote(slave, "can't give servants verbal orders");
					V.StewardessID = 0;
				} else if (slave.preg > 37 && slave.broodmother === 2) {
					_printSlaveUnassignedNote(slave, "spends so much time giving birth and laboring that", `${getPronouns(slave).he} cannot effectively serve as your Stewardess any longer`);
					V.StewardessID = 0;
				} else if (slave.fetish === "mindbroken") {
					_printSlaveUnassignedNote(slave, "is mindbroken");
					V.StewardessID = 0;
				} else if (!canWalk(slave)) {
					_printSlaveUnassignedNote(slave, "is no longer independently mobile");
					V.StewardessID = 0;
				} else if (!canHold(slave)) {
					_printSlaveUnassignedNote(slave, `can no longer handle ${getPronouns(slave).his} underlings nor effectively clean`);
					V.StewardessID = 0;
				} else if (!canSee(slave)) {
					_printSlaveUnassignedNote(slave, "can no longer see");
					V.StewardessID = 0;
				} else if (!canHear(slave)) {
					_printSlaveUnassignedNote(slave, "can no longer hear");
					V.StewardessID = 0;
				}
				if (V.StewardessID === 0) {
					removeJob(slave, Job.STEWARD);
				}
				break;
			case Job.TEACHER:
				if (!canTalk(slave)) {
					_printSlaveUnassignedNote(slave, "can't give verbal instruction");
					V.SchoolteacherID = 0;
				} else if (slave.preg > 37 && slave.broodmother === 2) {
					_printSlaveUnassignedNote(slave, "spends so much time giving birth and laboring that", `${getPronouns(slave).he} cannot effectively serve as your Schoolteacher any longer`);
					V.SchoolteacherID = 0;
				} else if (slave.fetish === "mindbroken") {
					_printSlaveUnassignedNote(slave, "is mindbroken");
					V.SchoolteacherID = 0;
				} else if (!canSee(slave)) {
					_printSlaveUnassignedNote(slave, "can no longer see");
					V.SchoolteacherID = 0;
				} else if (!canHear(slave)) {
					_printSlaveUnassignedNote(slave, "can no longer hear");
					V.SchoolteacherID = 0;
				}
				if (V.SchoolteacherID === 0) {
					removeJob(slave, Job.TEACHER);
				}
				break;
			case Job.WARDEN:
				if (!canWalk(slave)) {
					_printSlaveUnassignedNote(slave, "is no longer independently mobile");
					V.WardenessID = 0;
				} else if (!canHold(slave)) {
					_printSlaveUnassignedNote(slave, `can no longer handle ${getPronouns(slave).his} charges`);
					V.WardenessID = 0;
				} else if (slave.preg > 37 && slave.broodmother === 2) {
					_printSlaveUnassignedNote(slave, "spends so much time giving birth and laboring that", `${getPronouns(slave).he} cannot effectively serve as your Wardeness any longer`);
					V.WardenessID = 0;
				} else if (!canSee(slave)) {
					_printSlaveUnassignedNote(slave, "can no longer see");
					V.WardenessID = 0;
				} else if (!canHear(slave)) {
					_printSlaveUnassignedNote(slave, "can no longer hear");
					V.WardenessID = 0;
				}
				if (V.WardenessID === 0) {
					removeJob(slave, Job.WARDEN);
				}
				break;
			case Job.ATTENDANT:
				if (slave.fetish === "mindbroken") {
					_printSlaveUnassignedNote(slave, "is mindbroken");
					V.AttendantID = 0;
				} else if (slave.preg > 37 && slave.broodmother === 2) {
					_printSlaveUnassignedNote(slave, "spends so much time giving birth and laboring that", `${getPronouns(slave).he} cannot effectively serve as your Attendant any longer`);
					V.AttendantID = 0;
				} else if (!canWalk(slave)) {
					_printSlaveUnassignedNote(slave, "is no longer independently mobile");
					V.AttendantID = 0;
				} else if (!canHold(slave)) {
					_printSlaveUnassignedNote(slave, `can no longer support ${getPronouns(slave).his} charges`);
					V.AttendantID = 0;
				} else if (!canHear(slave)) {
					_printSlaveUnassignedNote(slave, "can no longer hear");
					V.AttendantID = 0;
				}
				if (V.AttendantID === 0) {
					removeJob(slave, Job.ATTENDANT);
				}
				break;
			case Job.MATRON:
				if (slave.fetish === "mindbroken") {
					_printSlaveUnassignedNote(slave, "is mindbroken");
					V.MatronID = 0;
				} else if (slave.preg > 37 && slave.broodmother === 2) {
					_printSlaveUnassignedNote(slave, "spends so much time giving birth and laboring that", `${getPronouns(slave).he} cannot effectively serve as your Matron any longer`);
					V.MatronID = 0;
				} else if (!canWalk(slave)) {
					_printSlaveUnassignedNote(slave, "is no longer independently mobile");
					V.MatronID = 0;
				} else if (!canHold(slave)) {
					_printSlaveUnassignedNote(slave, "can no longer hold infants");
					V.MatronID = 0;
				} else if (!canHear(slave)) {
					_printSlaveUnassignedNote(slave, "can no longer hear");
					V.MatronID = 0;
				} else if (!canSee(slave)) {
					_printSlaveUnassignedNote(slave, "can no longer see");
					V.MatronID = 0;
				}
				if (V.MatronID === 0) {
					removeJob(slave, Job.MATRON);
				}
				break;
			case Job.NURSE:
				if (slave.fetish === "mindbroken") {
					_printSlaveUnassignedNote(slave, "is mindbroken");
					V.NurseID = 0;
				} else if (slave.preg > 37 && slave.broodmother === 2) {
					_printSlaveUnassignedNote(slave, "spends so much time giving birth and laboring that", `${getPronouns(slave).he} cannot effectively serve as your Nurse any longer`);
					V.NurseID = 0;
				} else if (!canWalk(slave)) {
					_printSlaveUnassignedNote(slave, "is no longer independently mobile");
					V.NurseID = 0;
				} else if (!canHold(slave)) {
					_printSlaveUnassignedNote(slave, "can no longer hold onto patients");
					V.NurseID = 0;
				} else if (!canSee(slave)) {
					_printSlaveUnassignedNote(slave, "can no longer see");
					V.NurseID = 0;
				} else if (!canHear(slave)) {
					_printSlaveUnassignedNote(slave, "can no longer hear");
					V.NurseID = 0;
				}
				if (V.NurseID === 0) {
					removeJob(slave, Job.NURSE);
				}
				break;
			case Job.BODYGUARD:
				if (slave.fetish === "mindbroken") {
					_printSlaveUnassignedNote(slave, "is mindbroken");
					V.BodyguardID = 0;
				} else if (!canWalk(slave)) {
					_printSlaveUnassignedNote(slave, "is no longer independently mobile");
					V.BodyguardID = 0;
				} else if (!canHold(slave)) {
					_printSlaveUnassignedNote(slave, "is no longer able to hold a weapon");
					V.BodyguardID = 0;
				} else if (slave.preg > 37 && slave.broodmother === 2) {
					_printSlaveUnassignedNote(slave, "spends so much time giving birth and laboring that", `${getPronouns(slave).he} cannot effectively serve as your bodyguard any longer`);
					V.BodyguardID = 0;
				} else if (!canSee(slave)) {
					_printSlaveUnassignedNote(slave, "can no longer see");
					V.BodyguardID = 0;
				} else if (!canHear(slave)) {
					_printSlaveUnassignedNote(slave, "can no longer hear");
					V.BodyguardID = 0;
				}
				if (V.BodyguardID === 0) {
					removeJob(slave, Job.BODYGUARD);
				}
				break;
			case Job.SUBORDINATE:
				if (slave.subTarget === -1) {
					V.StudID = slave.ID;
					if (slave.balls === 0) {
						_printSlaveUnassignedNote(slave, "no longer has sperm", null, "@Stud");
						V.StudID = 0;
					} else if (slave.ballType === "sterile") {
						_printSlaveUnassignedNote(slave, "no longer produces potent sperm", null, "@Stud");
						V.StudID = 0;
					} else if (slave.pubertyXY !== 1) {
						_printSlaveUnassignedNote(slave, "no longer produces mature sperm", null, "@Stud");
						V.StudID = 0;
					} else if (slave.vasectomy === 1) {
						_printSlaveUnassignedNote(slave, "shoots blanks due to a vasectomy", null, "@Stud");
						V.StudID = 0;
					} else if (V.universalRulesImpregnation !== "Stud") {
						_printSlaveUnassignedNote(slave, "is", "no longer needed as a Stud", "@Stud");
					}
					if (V.StudID === 0) {
						slave.subTarget = 0;
					}
				}
				break;
			case Job.AGENT: {
				const arc = V.arcologies.find((a) => a.leaderID === slave.ID);
				if (!arc) {
					_printSlaveUnassignedNote(slave, "is not assigned to an arcology");
					removeJob(slave, Job.AGENT);
				} else if (arc.government !== "your agent") {
					_printSlaveUnassignedNote(slave, "is assigned to an arcology that is not lead by an agent");
					removeJob(slave, Job.AGENT);
				}
				break;
			}
		}

		if (slave.ID === V.LurcherID) {
			if (!canWalk(slave)) {
				_printSlaveUnassignedNote(slave, "is no longer able to run", null, Job.LURCHER);
				V.LurcherID = 0;
			} else if (!canHold(slave)) {
				_printSlaveUnassignedNote(slave, "is no longer able to catch the hares", null, Job.LURCHER);
				V.LurcherID = 0;
			} else if (!canHear(slave) && !canSee(slave)) {
				_printSlaveUnassignedNote(slave, "is no longer able to track the hares", null, Job.LURCHER);
				V.LurcherID = 0;
			} else if (slave.bellyPreg >= 60000) {
				_printSlaveUnassignedNote(slave, "is too pregnant to run", null, Job.LURCHER);
				V.LurcherID = 0;
			}
		}

		if (V.pit && V.pit.fighterIDs.includes(slave.ID)) {
			if (!canWalk(slave)) {
				_printSlaveUnassignedNote(slave, "is no longer independently mobile",
					`and cannot fight any more. ${getPronouns(slave).He} has been removed from ${App.Entity.facilities.pit.name} roster`);
				removeJob(slave, Job.PIT, true);
			} else if (!canHold(slave)) {
				_printSlaveUnassignedNote(slave, "is no longer able to strike",
					`and cannot fight any more. ${getPronouns(slave).he} has been removed from ${App.Entity.facilities.pit.name} roster`);
				removeJob(slave, Job.PIT, true);
			}
		}
	}

	/**
	 *
	 * @param {App.Entity.SlaveState} slave
	 * @param {string} condition
	 * @param {string} [outcome]
	 * @param {string} [assignment]
	 */
	function _printSlaveUnassignedNote(slave, condition, outcome, assignment) {
		const cantServeNotes = new Map([
			[Job.HEADGIRL, "cannot serve as your Head Girl any more"],
			[Job.RECRUITER, "and cannot serve as your recruiter any more"],
			[Job.MADAM, "cannot serve as your Madam any more"],
			[Job.DJ, "cannot serve as your DJ any more"],
			[Job.MILKMAID, "cannot serve as your Milkmaid any more"],
			[Job.FARMER, "cannot serve as your Farmer any more"],
			[Job.STEWARD, "cannot serve as your Stewardess any more"],
			[Job.TEACHER, "cannot serve as your Schoolteacher any more"],
			[Job.WARDEN, "cannot serve as your Wardeness any more"],
			[Job.ATTENDANT, "cannot serve as your Attendant any more"],
			[Job.BODYGUARD, " cannot serve as your Bodyguard any more"],
			["@Stud", "cannot serve as a Stud any more"],
			[Job.NURSE, "cannot serve as your Nurse any more"],
			[Job.MATRON, "cannot serve as your Matron any more"],
			[Job.LURCHER, "cannot course as a lurcher"],
			[Job.AGENT, "cannot serve as an Agent any more"]
		]);

		const warningLine = App.UI.DOM.appendNewElement("div", res);
		App.UI.DOM.appendNewElement("span", warningLine, slave.slaveName, 'slave-name');
		warningLine.appendChild(document.createTextNode(' ' + condition + ' '));
		App.UI.DOM.appendNewElement("span", warningLine, outcome ? outcome : `and ${cantServeNotes.get(assignment || slave.assignment)}`, "yellow");
		warningLine.appendChild(document.createTextNode("."));
	}
};

repo_name: Banyanael/fc

license: mit


code:
/**
 * Generates (and returns if not silent) a standard slave report
 * This is the part after the slave's job in most facilities.
 * @param {FC.ReportSlave} slave
 * @param {boolean} silent
 * @returns {DocumentFragment|null}
 */
App.SlaveAssignment.standardSlaveReport = function(slave, silent = false) {
	const clothes = App.SlaveAssignment.choosesOwnClothes(slave);
	const individualReport = App.SlaveAssignment.individualSlaveReport(slave);
	const devotion = App.SlaveAssignment.devotion(slave);

	if (!silent) {
		const container = document.createDocumentFragment();
		App.Events.addNode(container, [clothes, ...individualReport], "div", "indent");
		App.Events.addNode(container, [devotion], "div", "indent");
		return container;
	}
};

/**
 * Generates the main part of the standard slave report for an individual slave.
 * This is the section that's identical for all slaves regardless of facility.
 * @param {FC.ReportSlave} slave
 * @returns {Array<DocumentFragment|string>}
 */
App.SlaveAssignment.individualSlaveReport = function(slave) {
	return [
		App.SlaveAssignment.rules(slave),
		App.SlaveAssignment.diet(slave),
		App.SlaveAssignment.longTermEffects(slave),
		App.SlaveAssignment.drugs(slave),
		App.SlaveAssignment.relationships(slave),
		App.SlaveAssignment.rivalries(slave),
	];
};

/**
 * Render slave assignment report art
 * @param {ParentNode} node
 * @param {App.Entity.SlaveState} slave
 */
App.SlaveAssignment.appendSlaveArt = function(node, slave) {
	if (V.seeImages && V.seeReportImages) {
		App.UI.DOM.appendNewElement("div", node, App.EndWeek.saVars.slaveArt.render(slave), ["imageRef", "tinyImg"]);
	}
};

/**
 * Render favorite and reminder links
 * @param {ParentNode} node
 * @param {App.Entity.SlaveState} slave
 */
App.SlaveAssignment.appendSlaveLinks = function(node, slave) {
	node.append(
		App.UI.favoriteToggle(slave), " ",
		App.Reminders.slaveLink(slave.ID), " "
	);
};


code:
/*  Events are organized into several files and folders								*/
/*	genericPlotEvents.tw															*/
/*	PESS.tw: Player Event, Single Slave												*/
/*	PETS.tw: Player Event, Two Slaves												*/
/*	RECI.tw: Random Event, Check In													*/
/*	REFI.tw: Random Event, Fetish Interest											*/
/*	REFS.tw: Random Event, Future Societies											*/
/*	RESS.tw: Random Event, Single Slave												*/
/*	RESSTR.tw: Random Event, Single Slave (Test Realm, for debugging events)		*/
/*	RETS.tw: Random Event, Two Slaves												*/
/*																					*/
/* Events can also be in a dedicated *.tw file, formatted as follows:				*/
/*	jeXXXXX.tw: Justice Event														*/
/*	pXXXXXX.tw: Player event														*/
/*	peXXXXX.tw: Player Event focused on a slave										*/
/*	reXXXXX.tw: Random Event														*/
/*	resXXXX.tw: Random Event, School												*/
/*	seXXXXX.tw: Slave Event, focuses on slaves coming or going						*/
/*	securityForceXXXXX.tw: Special (Security) Force event							*/

path: src/events/About Events.txt


code:
App.Events.eliteTakeOver = class eliteTakeOver extends App.Events.BaseEvent {
	eventPrerequisites() {
		return [
			() => V.arcologies[0].FSRestart !== "unset",
			() => V.failedElite > 300,
			() => V.eugenicsFullControl !== 1
		];
	}

	execute(node) {
		const container = App.UI.DOM.appendNewElement("div", node);
		let r = [];
		/* Elites */
		let eliteTotal = 12;
		let eliteDead = 0;
		let eliteVegetable = 0;
		let mercenariesMessageSent = 0;
		let specialForcesMessageSent = 0;
		V.nextButton = " ";
		const {
			He,
			he, his
		} = getPronouns(S.Bodyguard ? S.Bodyguard : {pronoun: App.Data.Pronouns.Kind.neutral});

		let pregSurrender = 0; // preg/lobotomization check
		r.push(`You knew this day would come. Surrounding yourself with powerful people has its boons, but also poses a distinct threat. You've heard them murmuring when you enter the room, you've seen them excuse themselves from your presence, and lately they've been overtly hostile. The Societal Elite${(V.arcologies[0].FSNeoImperialistLaw2 === 1) ? ", likely with the support of your ever-plotting Barons," : ""} have turned on you.`);
		App.Events.addNode(container, r, "div");
		r = [];
		r.push(`You look up from your desk as the locked door to your office unseals, and a dozen individuals brazenly walk into your view.`);
		if (S.Bodyguard) {
			r.push(`${S.Bodyguard.slaveName} stands between you and them. A single glare from the leader of the bunch and ${he} backs off, eyes to the ground.`);
		}
		App.Events.addNode(container, r, "div");
		r = [];
		if (V.PC.pregSource === -1 || V.PC.pregSource === -6) {
			if (V.PC.refreshmentType === 0) {
				r.push(`Taking a drag from a fresh ${V.PC.refreshment},`);
			} else if (V.PC.refreshmentType === 1) {
				r.push(`Taking a drink of a fresh glass of ${V.PC.refreshment},`);
			} else if (V.PC.refreshmentType === 2) {
				r.push(`Taking a bite of a fresh ${V.PC.refreshment},`);
			} else if (V.PC.refreshmentType === 3) {
				r.push(`Doing a line of ${V.PC.refreshment},`);
			} else if (V.PC.refreshmentType === 4) {
				r.push(`Injecting a hit of ${V.PC.refreshment} into your arm,`);
			} else if (V.PC.refreshmentType === 5) {
				r.push(`Swallowing a ${V.PC.refreshment},`);
			} else if (V.PC.refreshmentType === 6) {
				r.push(`Placing a tab of ${V.PC.refreshment} under your tongue,`);
			}
			r.push(`you greet your rather unwelcome guests.`);
			App.Events.addParagraph(container, r);
			r = [];
			r.push(`"You are no longer worthy of being a part of our society. But you carry within you one of our heirs. A conundrum for some, but we have already solved that problem."`);
			App.Events.addNode(container, r, "div");
			r = [];
			r.push(`What was that last thing he said? It's getting hard to think right. The ${V.PC.refreshment}... Drugged... You collapse onto your desk, unconscious.`);
			App.Events.addNode(container, r, "div");
			r = [];
			if (S.Bodyguard) {
				r.push(`A sharp pain and a rush of adrenaline drags you back to your senses. Sneaking a peak, you witness ${S.Bodyguard.slaveName} valiantly trying to protect you, despite`);
				if (hasAnyProstheticLimbs(S.Bodyguard)) {
					r.push(`${his} cybernetics being locked down.`);
				} else {
					r.push(`the overwhelming odds.`);
				}
				r.push(`As ${he} and their leader struggle closer to your desk, his revolver and a syringe are dislodged onto your desk. It seems drugging you wasn't their first thought. With ${S.Bodyguard.slaveName}'s risky gamble, your fate has fallen back into your hands.`);
			} else {
				r.push(`You'll spend the rest of your life a breeder to the Societal Elite; blinded and muted. More than a slave, but still less than your master. Life isn't so bad, your two most devoted slaves were taken along to keep you happy, and you are treated quite well, possibilities considered. Though once your eggs dry up, odds are your little remaining usefulness will be at an end. Best not to think too much into it.`);
				pregSurrender = 1;
				V.ui = "start";
				App.Events.addParagraph(container, r);
				r = [];
				App.UI.DOM.appendNewElement("p", container, "GAME OVER", "bold");
			}
		} else {
			r.push(`The leader reaches into his jacket and extracts a syringe, you recognize it as a powerful drug used in lobotomies, and places it to your left. From his hip he pulls a revolver, six-chambered, and loads five bullets, spins the chamber, and places it to your right.`);
			App.Events.addNode(container, r, "div");
			r = [];
			r.push(`"You are no longer worthy of being a part of our society. You know you can't be allowed to spread any information. But we are not merciless; one of our members has taken an interest in having you as her pet. You may choose to lose your mind, and service her until she tires of you, or gamble for your life and serve her anyway. Now decide."`);
		}
		App.Events.addParagraph(container, r);

		if (pregSurrender === 0) {
			App.UI.DOM.appendNewElement("div", container, "You decide to");

			const choices = [];
			if (S.Bodyguard) {
				if (V.PC.pregSource === -1 || V.PC.pregSource === -6) {
					choices.push(new App.Events.Result(null, null, `${S.Bodyguard.slaveName} is already doing everything in ${his} power to save you.`));
				} else {
					choices.push(new App.Events.Result(`Attempt to signal ${S.Bodyguard.slaveName}, your bodyguard`, BG));
				}
			}
			if (V.mercenaries >= 1) {
				choices.push(new App.Events.Result(`Send a message to the leader of the ${V.mercenariesTitle}`, mercenaries));
			}
			if (V.SF.Toggle && V.SF.Active >= 1) {
				choices.push(new App.Events.Result(`Send a message to ${App.SF.SFC()}`, SF));
			}
			if (V.PC.pregSource !== -1 && V.PC.pregSource !== -6) {
				choices.push(new App.Events.Result(`Try and enrage them.`, enrage));
			}
			choices.push(new App.Events.Result(`Make a final stand`, finalStand));
			choices.push(new App.Events.Result(`Give in`, giveIn));
			App.Events.addResponses(container, choices);
		}
		function BG() {
			$(container).empty().append(eliteTakeOverFight("bodyguard"));
			return [];
		}
		function mercenaries() {
			$(container).empty().append(eliteTakeOverFight("mercenaries"));
			return [];
		}
		function SF() {
			$(container).empty().append(eliteTakeOverFight("SF"));
			return [];
		}
		function enrage() {
			$(container).empty().append(eliteTakeOverFight("enrage"));
			return [];
		}
		function finalStand() {
			$(container).empty().append(eliteTakeOverFight("final stand"));
			return [];
		}
		function giveIn() {
			$(container).empty().append(eliteTakeOverFight("give in"));
			return [];
		}
		function eliteTakeOverFight(finalChoice) {
			const node = new DocumentFragment();
			let r = [];
			let bgSignaled;
			let eliteEnraged;

			switch (finalChoice) {
				case "bodyguard": {
					const roll = random(0, 100);
					if (V.PC.career === "mercenary") {
						r.push(`As a result of your prior experience as a mercenary you were able to successfully signal ${S.Bodyguard.slaveName} without the Elites noticing.`);
						bgSignaled = 1;
					} else if (V.PC.skill.warfare >= 100 && roll > 20) {
						r.push(`As a result of your mastery of warfare you were able to successfully signal ${S.Bodyguard.slaveName} without the Elites noticing.`);
						bgSignaled = 1;
					} else if (V.PC.skill.warfare >= 60 && roll > 30) {
						r.push(`As a result of your expertness of warfare you were able to successfully signal ${S.Bodyguard.slaveName} without the Elites noticing.`);
						bgSignaled = 1;
					} else if (V.PC.skill.warfare >= 30 && roll > 40) {
						r.push(`As a result of having some skill in warfare you were able to successfully signal ${S.Bodyguard.slaveName} without the elites noticing.`);
						bgSignaled = 1;
					} else if (V.PC.skill.warfare >= 10 && roll > 50) {
						r.push(`As a result of having a small amount of skill in warfare you were able to successfully signal ${S.Bodyguard.slaveName} without the Elites noticing.`);
						bgSignaled = 1;
					} else if (V.PC.skill.warfare < 10 && roll > 60) {
						r.push(`By blind luck and what little you remember of your lessons in warfare are were able to successfully signal ${S.Bodyguard.slaveName} without the Elites noticing.`);
						bgSignaled = 1;
					} else {
						r.push(`One of the Elites shouts "What the fuck are you trying to do?" Well, there goes that option.`);
						bgSignaled = 0;
					}
					App.Events.addNode(node, r, "div");
					r = [];
					r.push(`You then pick up the revolver and quickly take aim.`);
					break;
				}
				case "mercenaries":
					r.push(`You send a quick message to the leader of your ${V.mercenariesTitle}, about your situation, then you pick up the revolver and quickly take aim.`);
					mercenariesMessageSent = 1;
					break;
				case "SF":
					r.push(`You send a quick message to`);
					App.SF.SFC();
					r.push(`about your situation, then you pick up the revolver and quickly take aim.`);
					specialForcesMessageSent = 1;
					break;
				case "enrage":
					if (["arcology owner", "BlackHat", "capitalist", "celebrity", "child prostitute", "escort", "gang", "hacker", "hoodlum", "medical assistant", "medicine", "prostitute", "rich kid", "rising star", "trust fund", "wealth"].includes(V.PC.career)) {
						r.push(`You know exactly what to say in order to enrage them.`);
						eliteEnraged = 1;
					} else if (random(0, 100) > 50) {
						r.push(`You manage to select the right words to enrage them.`);
						eliteEnraged = 1;
					} else {
						r.push(`You try to enrage them, but your words have had no effect.`);
						eliteEnraged = 0;
					}
					App.Events.addNode(node, r, "div");
					r = [];
					r.push(`You then pick up the revolver and quickly take aim.`);
					break;
				case "final stand":
					r.push(`You pick up the revolver and quickly take aim.`);
					break;
				case "give in":
					r.push(`You pick up the revolver and hold the barrel to your temple.`);
					break;
			}

			if (finalChoice === "give in") {
				if (V.PC.pregSource === -1 || V.PC.pregSource === -6) {
					r.push(`Screw their plans, you're out of here.`);
				}
				r.push(`With a "Bang!" you drop dead.`);
				V.ui = "start";
				App.Events.addParagraph(node, r);
				App.UI.DOM.appendNewElement("p", node, "GAME OVER", "bold");
			} else {
				/* PC shooting */
				/* higher skill means a higher chance to hit due to lower requirements and if the elites are enraged they very slightly become easier targets. */
				/* 5/6 = 83% rounded down is the chance that it was loaded chamber (simplified version based off the Wikipedia article) */

				/* variables: */
				/* Revolver */
				let revolverChambers = 6;
				let revolverBullets = 5;

				/* To Hit chance */
				let toHit;
				if (V.PC.pregSource === -1 || V.PC.pregSource === -6) { /* still woozy */
					toHit = 56;
				} else if (V.PC.career === "mercenary" || V.PC.skill.warfare >= 100) {
					toHit = 83;
				} else if (V.PC.skill.warfare >= 60) {
					toHit = 76;
				} else if (V.PC.skill.warfare >= 30) {
					toHit = 67;
				} else if (V.PC.skill.warfare >= 10) {
					toHit = 60;
				} else {
					toHit = 56;
				}
				if (eliteEnraged === 1) {
					toHit += 5;
				}

				/* shooting */
				/* in the end I removed the messages from the cycle. I don't think having 6 lines of "you shot" is pretty looking. Feel free to re add them in however */
				for (let i = revolverChambers; i > 0; i--) {
					if (random(0, 100) <= toHit && revolverBullets > 0) {
						eliteDead += 1;
						revolverBullets -= 1;
					} else if (revolverBullets > 0) {
						revolverBullets -= 1;
					}
				}
				App.Events.addNode(node, r, "div");
				r = [];
				if (eliteDead >= 1) {
					r.push(`You managed to kill several Elites in rapid succession, leaving the rest in shock and fear.`);
				} else if (eliteDead === 1) {
					r.push(`You managed to kill one Elite, leaving the rest in shock and fear.`);
				} else {
					r.push(`Unfortunately you fail to kill a single Elite.`);
				}
				App.Events.addNode(node, r, "div");
				r = [];

				/* syringe shot */
				eliteVegetable = 0;
				let druggedThrow = 0;

				if (eliteDead > 0) {
					r.push(`With ${eliteDead} Elites dead, you pick up the syringe from the desk and aim for the forehead of another.`);
				} else {
					r.push(`Having failed to kill them with the revolver, in a desperate move you pick up the syringe from the desk and aim for the forehead of one of the elite.`);
				}
				if (V.PC.pregSource === -1 || V.PC.pregSource === -6) {
					r.push(`But there's two of them... Shaking your head, you realize it's the drugs messing with you. You just need to focus.`);
				}
				const hitRoll = (random(0, 100) - druggedThrow);
				let syringeHeadShot;
				if (V.PC.career === "mercenary" && hitRoll > 0) {
					r.push(`With your prior history as a mercenary, making the throw is child's play.`);
					syringeHeadShot = 1;
				} else if (V.PC.skill.warfare >= 100) {
					if (hitRoll > 50) {
						r.push(`As a result of your mastery of warfare you successfully made the throw.`);
						syringeHeadShot = 1;
					} else {
						r.push(`Unfortunately you miss the shot.`);
						syringeHeadShot = 0;
					}
				} else if (V.PC.skill.warfare >= 60) {
					if (hitRoll > 60) {
						r.push(`As a result of your combat expertise you successfully made the throw.`);
						syringeHeadShot = 1;
					} else {
						r.push(`Unfortunately you miss the shot.`);
						syringeHeadShot = 0;
					}
				} else if (V.PC.skill.warfare >= 30) {
					if (hitRoll > 70) {
						r.push(`As you have some skill, you successfully made the throw.`);
						syringeHeadShot = 1;
					} else {
						r.push(`Unfortunately you miss the shot.`);
						syringeHeadShot = 0;
					}
				} else if (V.PC.skill.warfare >= 10) {
					if (hitRoll > 80) {
						r.push(`Your small amount of skill assisted you in making the throw.`);
						syringeHeadShot = 1;
					} else {
						r.push(`Unfortunately you miss the shot.`);
						syringeHeadShot = 0;
					}
				} else if (V.PC.skill.warfare < 10) {
					if (hitRoll > 90) {
						r.push(`By blind luck you successfully made the throw.`);
						syringeHeadShot = 1;
					} else {
						r.push(`Unfortunately you miss the shot.`);
						syringeHeadShot = 0;
					}
				}
				App.Events.addNode(node, r, "div");
				r = [];
				let spentRevolverHitSyringePlunger;
				if (syringeHeadShot === 1) {
					r.push(`Picking up the spent revolver, you aim for the syringe's plunger.`);
					if (V.PC.career === "mercenary") {
						r.push(`With your prior history as a mercenary, making the throw is child's play.`);
						spentRevolverHitSyringePlunger = 1;
					} else if (V.PC.skill.warfare >= 100 && random(0, 100) > 50) {
						r.push(`As a result of your mastery of warfare you successfully made the throw.`);
						spentRevolverHitSyringePlunger = 1;
					} else if (V.PC.skill.warfare >= 60 && random(0, 100) > 60) {
						r.push(`As a result of your expertness of warfare you successfully made the throw.`);
						spentRevolverHitSyringePlunger = 1;
					} else if (V.PC.skill.warfare >= 30 && random(0, 100) > 70) {
						r.push(`As you have some skill you successfully made the throw.`);
						spentRevolverHitSyringePlunger = 1;
					} else if (V.PC.skill.warfare >= 10 && random(0, 100) > 80) {
						r.push(`Your small amount of skill assisted you in making the throw.`);
						spentRevolverHitSyringePlunger = 1;
					} else if (V.PC.skill.warfare < 10 && random(0, 100) > 90) {
						r.push(`By blind luck you successfully made the throw.`);
						spentRevolverHitSyringePlunger = 1;
					} else {
						r.push(`Unfortunately you miss the shot.`);
						spentRevolverHitSyringePlunger = 0;
					}
				}
				App.Events.addNode(node, r, "div");
				r = [];
				if (spentRevolverHitSyringePlunger === 1) {
					if (random(0, 100) > 50) {
						r.push(`The target dies of nervous system overload brought about by the drug.`);
						eliteDead += 1;
					} else {
						r.push(`The target is still alive but is nothing more than a vegetable.`);
						eliteVegetable = 1;
					}
				}
			}

			let eliteLeft = eliteTotal - eliteDead - eliteVegetable;

			/* if the player has managed to make enough damage to the Elite and the rep is high enough the citizens will come to save the PC */
			/* this is to give reason to exist for the "enrage" and "last stand" option */
			/* result							*/
			/* fate:							*/
			/*		killed = 0					*/
			/*		enslaved = 1				*/
			/*		had fun (and enslaved) = 2	*/

			if (bgSignaled === 1) {
				const {title: Master} = getEnunciation(S.Bodyguard);
				r.push(`${S.Bodyguard.slaveName} asks, "${Master}, what should I do with the`);
				if (eliteLeft < eliteTotal) {
					r.push(`remaining`);
				}
				r.push(`'Elite' left?"`);
				App.Events.addNode(node, r, "div");
				node.append(resultLinks());
			} else if (mercenariesMessageSent === 1) {
				r.push(`It is now that a squad of ${V.mercenariesTitle} makes their entrance, pointing their guns at the`);
				if (eliteLeft < eliteTotal) {
					r.push(`remaining`);
				}
				r.push(`Elite. The officer asks, "Your orders, ${properTitle()}?"`);

				App.Events.addNode(node, r, "div");
				node.append(resultLinks());
			} else if (specialForcesMessageSent) {
				r.push(`It is now that a squad of ${V.SF.Lower} makes their entrance, pointing their guns at the`);
				if (eliteLeft < eliteTotal) {
					r.push(`remaining`);
				}
				r.push(`Elite. The officer asks, "Your orders, ${properTitle()}?"`);

				node.append(resultLinks());
			} else if (V.BodyguardID !== 0) {
				const {title: Master} = getEnunciation(S.Bodyguard);
				r.push(`It is now that ${S.Bodyguard.slaveName} makes ${his} entrance, pointing ${his} guns at the`);
				if (eliteLeft < eliteTotal) {
					r.push(`remaining`);
				}
				r.push(`Elite. ${He} then asks "${Master}, what should I do with the`);
				if (eliteLeft < eliteTotal) {
					r.push(`remaining`);
				}
				r.push(`'Elite' left?"`);
				node.append(resultLinks());
			} else if (eliteLeft <= 9 && V.rep >= 10000) {
				r.push(`Some of the citizens waiting outside your penthouse to see you hear the ruckus and rush inside, worried. Time seems to freeze for a few seconds, while the remaining Elite recover from their terror and the citizens digest the gory scene in front of them.`);
				r.push(`The newcomers are quick to take your side. In little time the Elites, outgunned and outnumbered, are neutralized.`);
				App.Events.addNode(node, r, "div");
				r = [];
				r.push(`One of the more courageous citizens approaches you and asks "${properTitle()}, what should we do with them?"`);
				App.Events.addNode(node, r, "div");
				node.append(resultLinks());
			} else if (finalChoice !== "give in") {
				r.push(`With nothing else left, you remain powerless to stop the`);
				if (eliteLeft < eliteTotal) {
					r.push(`remaining`);
				}
				r.push(`Elite, who quickly capture and enslave you. Your personal story may continue, but the part of it worthy of retelling has now ended.`);
				V.ui = "start";
				App.Events.addParagraph(node, r);
				App.UI.DOM.appendNewElement("p", node, "GAME OVER", "bold");
			}
			return node;

			function resultLinks() {
				const div = document.createElement("div");
				App.UI.DOM.appendNewElement("div", div, App.UI.DOM.link(
					"Open fire",
					() => {
						$(container).empty().append(eliteTakeOverResult(0));
					}
				));
				App.UI.DOM.appendNewElement("div", div, App.UI.DOM.link(
					"Enslave them",
					() => {
						$(container).empty().append(eliteTakeOverResult(1));
					}
				));
				App.UI.DOM.appendNewElement("div", div, App.UI.DOM.link(
					"Have fun with them",
					() => {
						$(container).empty().append(eliteTakeOverResult(2));
					}
				));
				return div;
			}

			/**
			 *
			 * @param {0|1|2} fate
			 * @returns {DocumentFragment}
			 */
			function eliteTakeOverResult(fate) {
				const node = new DocumentFragment();
				let r = [];

				V.nextButton = "Continue";
				App.Utils.updateUserButton(); /* unlock Continue button */

				const {
					himU, hisU
				} = getNonlocalPronouns(V.seeDicks).appendSuffix("U");
				let sfHappyEverAfter;

				switch (fate) {
					case 0:
						if (mercenariesMessageSent === 1) {
							r.push(`The mercenaries open fire as ordered. Shortly after, the conspiring Elite are dead.`);
						} else if (specialForcesMessageSent === 1) {
							r.push(`The soldiers open fire as ordered. Shortly after, the conspiring Elite are dead.`);
						} else if (eliteLeft <= 9 && V.rep >= 10000) {
							r.push(`Your citizens freeze for a second, then obey your orders. Shortly after, the conspiring Elite are dead.`);
						} else {
							r.push(`Your bodyguard opens fire as ordered. Shortly after, the conspiring Elite are dead.`);
						}
						break;
					case 1:
						if (random(0, 100) > 50) {
							r.push(`An Elite bites down on a cyanide pill hidden in a false tooth and`);
							if (random(0, 100) > 75) {
								r.push(`takes the coward's way out (how predictable), frothing at the mouth.`);
								eliteDead += 1;
							} else {
								r.push(`experiences great pain but unfortunately (for them at least) survives.`);
							}
						}
						App.Events.addNode(node, r, "div");
						r = [];
						if (mercenariesMessageSent === 1) {
							r.push(`The`);
							if (eliteLeft < eliteTotal) {
								r.push(`remaining`);
							}
							r.push(`Elite are quickly captured and enslaved by your mercenaries.`);
						} else if (specialForcesMessageSent === 1) {
							r.push(`The`);
							if (eliteLeft < eliteTotal) {
								r.push(`remaining`);
							}
							r.push(`Elite are quickly captured and enslaved by your soldiers.`);
						} else if (eliteLeft <= 9 && V.rep >= 10000) {
							r.push(`The`);
							if (eliteLeft < eliteTotal) {
								r.push(`remaining`);
							}
							r.push(`Elite are quickly captured and enslaved by your loyal citizens.`);
						} else {
							r.push(`The`);
							if (eliteLeft < eliteTotal) {
								r.push(`remaining`);
							}
							r.push(`Elite are quickly captured and enslaved by your bodyguard.`);
						}
						break;
					case 2:
						if (random(0, 100) > 50) {
							r.push(`An Elite bites down on a cyanide pill hidden in a false tooth and`);
							if (random(0, 100) > 75) {
								r.push(`takes the coward's way out (how predictable), frothing at the mouth.`);
								eliteDead += 1;
							} else {
								r.push(`experiences great pain but unfortunately (for them at least) survives.`);
							}
						}
						App.Events.addNode(node, r, "div");
						r = [];
						if (mercenariesMessageSent === 1) {
							r.push(`The`);
							if (eliteLeft < eliteTotal) {
								r.push(`remaining`);
							}
							r.push(`Elite are quickly captured, abused and enslaved. The officer is thankful for giving the troops a chance to let off some stream. Two soldiers decide to double team an Elite; one ass fucks while the other facefucks. Another soldier takes a particular interest in an Elite and politely asks you "${properTitle()}, can I keep ${himU}?"`);
							App.Events.addNode(node, r, "div");

							App.Events.addResponses(node, [
								new App.Events.Result(`No`, no),
								new App.Events.Result(`Yes`, yes)
							]);

							function no() {
								return `Your rejection upsets some of them, but their professionalism ensures it isn't visible.`;
							}
							function yes() {
								eliteLeft -= 1;
								repX(2500, "event");
								return `For a second your acceptance shocks them. Once they recover they are very grateful. "Thank you ${properTitle()}, I'll make sure to look after ${himU}." Soon the story spreads of the kind arcology owner, enhancing your reputation.`;
							}
						} else if (specialForcesMessageSent) {
							r.push(`The`);
							if (eliteLeft < eliteTotal) {
								r.push(`remaining`);
							}
							r.push(`Elite are quickly captured, abused and enslaved.`);
							if (V.SF.Depravity <= 0.3) {
								r.push(`Two soldiers decide to double team an Elite; one gropes ${hisU} ass while the other gropes ${hisU} tits.`);
							} else if (V.SF.Depravity <= 1.2) {
								r.push(`Two soldiers decide to double team an Elite; one assfucks while the other facefucks.`);
							} else {
								r.push(`Two soldiers decide to double team an Elite; one breaks out their knife and begins to make little breaks in the Elite's skin while the other soldier facefucks them.`);
							}
							r.push(`Another soldier takes a particular interest in an Elite and politely asks you "${properTitle()}, can I keep ${himU}?"`);
							App.Events.addParagraph(node, r);
							r = [];

							App.Events.addResponses(node, [
								new App.Events.Result(`No`, no),
								new App.Events.Result(`Yes`, yes)
							]);

							function no() {
								sfHappyEverAfter = 0;
								return `Your rejection upsets some of them, but their professionalism ensures it isn't visible.`;
							}
							function yes() {
								eliteLeft -= 1;
								sfHappyEverAfter = 1;
								repX(2500, "event");
								return `For a second your acceptance shocks them. Once they recover they are very grateful. "Thank you ${properTitle()}, I'll make sure to look after ${himU}." Soon the story spreads of the kind arcology owner, enhancing your reputation.`;
							}
							if (V.SF.MercCon.CanAttend === -2) {
								switch (V.SF.Colonel.Core) {
									case "kind":
										r.push(`The Colonel is shocked that you would allow her troops to do this but understands that it comes with the territory.`);
										if (sfHappyEverAfter === 1) { // TODO: this never worked in tw since this is set by a link that doesn't refresh this content.
											r.push(`"Thanks for being kind to one of my soldiers."`);
										}
										break;
									case "brazen":
									case "cruel":
									case "jaded":
										r.push(`The Colonel is grateful that you let her troops let off some steam.`);
										if (sfHappyEverAfter === 1) {
											r.push(`"Thanks for being kind to one of my soldiers."`);
										}
								}
							}
							V.SF.Depravity += 0.05;
						} else if (eliteLeft <= 9 && V.rep >= 10000) {
							if (V.arcologies[0].FSDegradationist !== "unset") {
								r.push(`An evil smile appears on the faces of your loyal citizens, while the surviving Elite freeze in terror. The impromptu festivity will go on for hours, getting more and more depraved.`);
							} else {
								r.push(`While some citizens respectfully step out, some join you in the fun. The impromptu festivities will go on for hours, getting more and more depraved.`);
							}
						} else {
							if (S.Bodyguard.fetish === "sadist") {
								r.push(`${S.Bodyguard.slaveName} gets out ${his} melee weapon and starts to give them many small cuts, the look of pleasure on ${his} face is evident.`);
							} else {
								r.push(`${S.Bodyguard.slaveName} ties them and then gets out ${his} melee weapon and starts to abuse them; ${his} face is blank.`);
							}
							App.Events.addNode(node, r, "div");
							r = [];
							r.push(`Shortly after, the terrified`);
							if (eliteLeft < eliteTotal) {
								r.push(`remaining`);
							}
							r.push(`Elite are quickly brought away to be officially enslaved.`);
						}
				}
				App.Events.addParagraph(node, r);

				if (fate >= 1) {
					if (eliteVegetable === 1) {
						eliteLeft--;
						let slave;
						const gender = (V.seeDicks === 100 || (random(1, 100) > 50)) ? "XY" : "XX"; /* 50% chance of getting girl or boy */

						slave = GenerateNewSlave(
							gender,
							{
								minAge: 25, maxAge: V.retirementAge - 2, disableDisability: 1, race: "nonslave"
							});
						slave.origin = "$He was a member of the Societal Elite, captured in their failed attempt at expressing their displeasure.";
						slave.career = "a well connected individual";
						slave.prestige = either(2, 2, 3); /* 33% chance of getting level 3 prestige */
						slave.prestigeDesc = "$He was once considered influential in society, but now $he's the one getting fucked.";
						slave.face = random(70, 100);
						if (slave.boobShape === "saggy" || slave.boobShape === "downward-facing") {
							slave.boobShape = either("perky", "torpedo-shaped", "wide-set");
						}
						applyMindbroken(slave, random(70, 100));
						slave.pubicHStyle = "waxed";
						slave.underArmHStyle = "waxed";
						slave.anus = 0;
						slave.weight = random(10, 75);
						setHealth(slave, jsRandom(60, 75), 0, 0, 0, jsRandom(0, 20));
						slave.canRecruit = 0;
						newSlave(slave); /* skip New Slave Intro */
					}
					for (let i = eliteLeft; i > 0; i--) {
						const gender = (V.seeDicks === 100 || (random(1, 100) > 50)) ? "XY" : "XX"; /* 50% chance of getting girl or boy */
						const slave = GenerateNewSlave(gender, {minAge: 25, maxAge: V.retirementAge - 2, race: "nonslave"});
						slave.origin = "$He was a member of the Societal Elite, captured in their failed attempt at expressing their displeasure.";
						slave.career = "a well connected individual";
						slave.prestige = either(2, 2, 3);
						slave.prestigeDesc = "$He was once considered influential in society, but now $he's the one getting fucked.";
						slave.face = random(70, 100);
						slave.devotion = random(-10, -20);
						slave.trust = random(-20, -30);
						if (slave.boobShape === "saggy" || slave.boobShape === "downward-facing") {
							slave.boobShape = either("perky", "torpedo-shaped", "wide-set");
						}
						slave.pubicHStyle = "waxed";
						slave.underArmHStyle = "waxed";
						slave.anus = 0;
						slave.weight = random(-30, 75);
						slave.intelligence = random(0, 60);
						slave.intelligenceImplant = 30;
						slave.skill.entertainment = 0;
						slave.skill.whoring = 0;
						setHealth(slave, jsRandom(60, 75), 0, 0, 0, jsRandom(0, 20));
						slave.canRecruit = 0;
						slave.behavioralFlaw = either("arrogant", "bitchy");
						if (fate === 2 && random(1, 100) >= 75) { /* 25% chance of getting mindbroken elites if they were abused */
							applyMindbroken(slave);
						}
						newSlave(slave); /* skip New Slave Intro */
					}
				}

				/* clean up */
				V.failedElite = 0;
				V.eugenicsFullControl = 1;
				return node;
			}
		}
	}
};


code:
App.Events.jeCommon = function() {
	return `${capFirstChar(V.assistant.name)} breaks in on your sleep with an urgent message. You push a slave off you and sit up to take it. As the owner of the arcology, you perform some functions that would traditionally be the province of a government. In this anarcho-liberal polity, it's still necessary for people making deals to have someone to appeal to when disputes arise. Part of your agreement with your tenants is that you will perform this duty on deals between two tenants. The message is about just such a disagreement; they always seem to happen in the middle of the night, and they're always urgent.`;
};


code:
App.Events.JESlaveDisputeBreedingDeal = class JESlaveDisputeBreedingDeal extends App.Events.BaseEvent {
	eventPrerequisites() {
		return [
			() => V.justiceEvents.includes("breeding deal"),
		];
	}

	get weight() {
		return V.justiceEvents.length > 2 ? 2 : 1;
	}

	execute(node) {
		let r = [];
		const index = V.justiceEvents.indexOf("breeding deal");
		V.justiceEvents.splice(index, 1);
		const contractCost = 40000;
		const slave = GenerateNewSlave("XX", {
			minAge: V.fertilityAge + 3, maxAge: 42, ageOverridesPedoMode: 1, disableDisability: 1
		});
		slave.origin = "$He was raised to be a mother.";
		slave.career = "a breeder";
		slave.devotion = random(10, 25);
		slave.trust = slave.devotion;
		setHealth(slave, jsRandom(80, 90), 0, 0, 0, jsRandom(10, 30));
		slave.anus = 0;
		slave.vagina = 3;
		slave.skill.anal = 0;
		slave.skill.oral = 0;
		slave.skill.whoring = 0;
		slave.skill.vaginal = 0;
		slave.skill.entertainment = 0;
		slave.bellySag = 10;
		slave.bellySagPreg = 10;
		slave.counter.birthsTotal = 3;
		slave.hips = 2;
		slave.boobs = random(4, 6) * 100;
		if (V.seePreg === 1) {
			slave.belly = 18000;
		}
		const {he, his, girl} = getPronouns(slave);

		App.Events.drawEventArt(node, slave);
		App.UI.DOM.appendNewElement("p", node, App.Events.jeCommon());
		r.push(`A small-time slave breeder is accusing a customer of reneging on their agreement. For the last nine months, one of his best breeders has been busy growing his client's future slave and now`);
		if (V.seePreg === 1) {
			r.push(`that ${he}'s ready to give birth,`);
			slave.belly = 0;
			slave.pregWeek = -3;
		} else {
			r.push(`that it's born,`);
		}
		r.push(`he's refusing to transfer the funds, placing the entire operation in jeopardy.`);
		App.Events.addParagraph(node, r);
		r = [];
		r.push(`The father${(V.seePreg === 1) ? "-to-be" : ""} claims that the child is not his and as such, the contract has not been fulfilled. Despite offers from the breeder to perform a paternity test, he adamantly insists on using his private, and rather expensive, physician to run the test; a cost high enough to put them out of business anyway.`);

		App.Events.addParagraph(node, r);

		const choices = [];
		choices.push(new App.Events.Result(`Privately inform both parties you'll settle this in favor of the most generous`, bribe,));
		choices.push(new App.Events.Result(`Settle the dispute in favor of the accuser`, accuser,));
		choices.push(new App.Events.Result(`Settle the dispute in favor of the breeder`, breeder,));
		choices.push(new App.Events.Result(`Compromise on the compensation and offer to buy out the deal`, buy, `This will cost ${cashFormat(contractCost)} and give you the slave`));
		App.Events.addResponses(node, choices);

		function bribe() {
			const frag = new DocumentFragment();
			let r = [];
			r.push(`You privately inform both parties you'll settle this in favor of the most generous. You instantly receive two notices of escrow payments contingent on the case going the payer's way. You select the bigger of the two, a clear choice, and decide the matter before returning to bed in a good mood. However, the next day it becomes apparent that although he isn't stupid enough to make a public accusation of corruption, the loser is proclaiming that he is not pleased with your administration of justice.`);
			repX(-100, "event");
			cashX(random(150, 200) * 10, "event");
			App.Events.addParagraph(frag, r);
			return frag;
		}

		function accuser() {
			const frag = new DocumentFragment();
			let r = [];
			r.push(`You settle the dispute in favor of the wealthy accuser. While he is a little disappointed that he didn't get the slave he wanted, he speaks positively in public about how you helped protect his investments from potential mismanagement. Slave trading to and from your arcology is somewhat lessened however, since the breeder lets it be known that trading in your arcology is a risk.`);
			V.arcologies[0].prosperity -= 5;
			repX(2500, "event");
			App.Events.addParagraph(frag, r);
			return frag;
		}
		function breeder() {
			const frag = new DocumentFragment();
			let r = [];
			r.push(`You settle the dispute in favor of the slave breeder, and against the prominent accuser, by declaring that the standard paternity test will suffice.`);
			if (V.seePreg === 1) {
				r.push(`As if on queue, the ${girl}'s water breaks and soaks ${his} pants. The call ends to the sight of ${his} crotch bulging as ${his} child is born into ${his} clothing.`);
			}
			r.push(`While he is satisfied with his future slave, he speaks openly in public about how you were so quick to use cheap services to settle the claim instead of listening to his requests. The breeder, however, passes a good word around the industry that slavers trading with your arcology can expect to be protected from abusive claims.`);
			V.arcologies[0].prosperity += 5;
			repX(-500, "event");
			App.Events.addParagraph(frag, r);
			return frag;
		}
		function buy() {
			const frag = new DocumentFragment();
			let r = [];
			cashX(forceNeg(contractCost), "slaveTransfer");
			r.push(`You offer to buy out the deal, paying the breeder and taking the slave yourself, and passing the child off to the buyer. The citizen gets what he wants and speaks kindly in public about how you helped smooth over a rather rough dispute. The breeder sends a positive note around the industry to the effect that slavers trading with your arcology can expect to be aided in times of need; though the loss of a star mother always stings.`);
			V.arcologies[0].prosperity += 3;
			repX(300, "event");
			App.Events.addParagraph(frag, r);
			frag.append(App.UI.newSlaveIntro(slave));
			return frag;
		}
	}
};


code:
App.Events.JESlaveDisputeIndentureDeal = class JESlaveDisputeIndentureDeal extends App.Events.BaseEvent {
	eventPrerequisites() {
		return [
			() => V.justiceEvents.includes("indenture deal"),
		];
	}

	get weight() {
		return V.justiceEvents.length > 2 ? 2 : 1;
	}

	execute(node) {
		let r = [];
		const index = V.justiceEvents.indexOf("indenture deal");
		V.justiceEvents.splice(index, 1);

		const contractCost = 7500;
		const slave = GenerateNewSlave(null, {minAge: 24, maxAge: 42, disableDisability: 1});
		setHealth(slave, jsRandom(-20, 20));
		slave.anus = 2;
		if (slave.vagina > -1) {
			slave.vagina = 2;
		}
		slave.skill.vaginal = 15;
		slave.skill.oral = 15;
		slave.skill.anal = 15;
		slave.skill.whoring = 0;
		slave.skill.entertainment = 15;
		slave.boobs += 600;
		slave.boobsImplant = 600;
		slave.boobsImplantType = "normal";
		slave.butt += 1;
		slave.buttImplant = 1;
		slave.buttImplantType = "normal";
		slave.lips += 10;
		slave.lipsImplant = 10;
		slave.piercing.lips.weight = 1;
		slave.piercing.tongue.weight = 1;
		slave.piercing.ear.weight = 1;
		slave.piercing.nose.weight = 1;
		slave.piercing.eyebrow.weight = 1;
		slave.piercing.navel.weight = 1;
		slave.piercing.nipple.weight = 1;
		slave.piercing.genitals.weight = 1;
		slave.stampTat = either("flowers", "tribal patterns");
		const {
			He,
			he, him, his, girl
		} = getPronouns(slave);

		App.Events.drawEventArt(node, slave);
		App.UI.DOM.appendNewElement("p", node, App.Events.jeCommon());
		r.push(`A slutty-looking ${girl} appears, bearing a split lip and a black eye, accusing a slave trader of tricking ${him}. ${He} sends you a lengthy contract of indentured servitude. Nothing seems out of order, though indentured servants are becoming less common, since slave labor is usually cheaper and less limited. The angry accuser claims that the trader told ${him} that ${he} wouldn't be required to have sex while indentured. The promise doesn't seem to be in writing, but the ${girl} bitterly insists that it was made. "And now," ${he} almost shrieks, "he's making me be a whore. I got assfucked five times yesterday. Five!"`);
		App.Events.addParagraph(node, r);
		r = [];
		r.push(`The trader indignantly denies ever making any such commitment, and points out, correctly, that ${he} has no proof. He protests that he only made the indentured servitude deal as a favor to ${him}, and is angry that ${he}'s repaying his courtesy in not insisting on enslavement by this ingratitude. "I see here in the record that ${he} was indeed used anally five times yesterday," he observes acidly. "But that's ${his} job."`);

		App.Events.addParagraph(node, r);

		const choices = [];
		choices.push(new App.Events.Result(`Privately inform both parties you'll settle this in favor of the most generous`, bribe,));
		choices.push(new App.Events.Result(`Settle the dispute in favor of the indentured whore`, whore,));
		choices.push(new App.Events.Result(`Settle the dispute in favor of the indenture holder`, holder,));
		choices.push(new App.Events.Result(`Buy out the contract and ${his} indenture`, buyAndIndent, `This will cost ${cashFormat(contractCost)} and give you the servant as such`));
		choices.push(new App.Events.Result(`Buy out the contract and enslave ${him}`, enslave, `This will cost ${cashFormat(contractCost)} and give you the servant as a slave`));
		App.Events.addResponses(node, choices);

		function bribe() {
			const frag = new DocumentFragment();
			let r = [];
			r.push(`You privately inform both parties you'll settle this in favor of the most generous. You instantly receive a single notice of escrow payment contingent on the case going the payer's way. You select the bigger of the two and decide the matter before returning to bed in a good mood. However, the next day it becomes apparent that although ${he} isn't stupid enough to make a public accusation, the whore has been whispering to ${his} peers that you helped the trader cheat ${him} into prostitution. Few citizens care, but there is a faint scent of corruption.`);
			repX(-50, "event");
			cashX(random(150, 200)*10, "event");
			App.Events.addParagraph(frag, r);
			return frag;
		}

		function whore() {
			const frag = new DocumentFragment();
			let r = [];
			r.push(`You settle the dispute in favor of the indentured whore, adding a requirement to the indentured servitude that ${he} not be required to fuck against ${his} will. The story of the brave prostitute and the conniving trader is told and retold, impressing the more credulous citizens. It also raises doubts among the wealthier, more business-minded residents about whether you can be depended on to promote their interests.`);
			V.arcologies[0].prosperity -= 5;
			repX(2500, "event");
			App.Events.addParagraph(frag, r);
			return frag;
		}

		function holder() {
			const frag = new DocumentFragment();
			let r = [];
			r.push(`You settle the dispute in favor of the owner of the indenture. No change in the contract is necessary, since it already says what it should: that he controls ${him} for the required period. That's all. The story of your strictness in business disputes impresses some of the more commercially powerful citizens of the arcology, but is hissed by the stupider, more romantic residents, who see only a brave whore being beaten down by a conniving slave trader.`);
			V.arcologies[0].prosperity += 5;
			repX(-500, "event");
			App.Events.addParagraph(frag, r);
			return frag;
		}

		function buyAndIndent() {
			const frag = new DocumentFragment();
			let r = [];
			slave.devotion = random(10, 15);
			slave.trust = slave.devotion+4;
			slave.oldDevotion = slave.devotion;
			slave.indenture = random(52, 78);
			slave.indentureRestrictions = 2;
			slave.origin = "You took over $his indenture after $he launched a legal complaint against an abusive master.";
			cashX(forceNeg(contractCost), "slaveTransfer");
			r.push(`You offer to simply buy out the indenture contract, thereby acquiring ${him}, to which both parties readily agree. This decision is viewed as incredibly generous by both your arcology's romantically-minded and financially-inclined citizens. For their part, your new servant is hopeful that you will be more considerate of ${his} health, while the former holder is just happy to have ${him} off his hands.`);
			V.arcologies[0].prosperity += 3;
			repX(1500, "event");
			frag.append(App.UI.newSlaveIntro(slave));
			App.Events.addParagraph(frag, r);
			return frag;
		}

		function enslave() {
			const frag = new DocumentFragment();
			let r = [];
			slave.origin = "$He was enslaved after you manipulated $his deal for indentured servitude.";
			slave.devotion = random(-10, -15);
			slave.trust = slave.devotion+4;
			slave.oldDevotion = slave.devotion;
			cashX(forceNeg(contractCost), "slaveTransfer");
			r.push(`You quietly contact the trader and suggest an alternative method of settling the dispute. He is surprised, but agrees readily, chuckling at how the "recalcitrant bitch" is going to be dealt with. To ${his} horror, ${he} finds that your near-total power over deals made in your arcology has been employed to saddle ${him} with additional debts that, under ${his} indentured servitude, ${he} cannot hope to repay. It is then the work of ten minutes to demand payment, and when ${he} cannot pay, demand ${his} body for enslavement. The story of your cunning impresses the slave traders, but is booed by fairer-minded citizens.`);
			V.arcologies[0].prosperity += 5;
			repX(-100, "event");
			frag.append(App.UI.newSlaveIntro(slave));
			App.Events.addParagraph(frag, r);
			return frag;
		}
	}
};