code:
// cSpell:ignore RCGmod

App.EndWeek.Player.mobility = function(PC = V.PC) {
	const r = [];

	const immobilities = [];
	const noWalking = [];

	const {hisP, girlP} = getPronouns(PC).appendSuffix("P");

	mobility();
	muscularAtrophy();
	bodyAccessibility();
	hugeBreasts();
	boobAccessibility();
	hugeBelly();
	bellyAccessibility();
	hugeDick();
	dickAccessibility();
	hugeBalls();
	ballsAccessibility();
	hugeHips();
	hugeButt();
	buttAccessibility();
	hindrance();

	return r.join(" ");

	function mobility() {
		if (PC.weight >= 300) {
			immobilities.push("fat body");
		}
		if (PC.belly >= 1100000) {
			immobilities.push("belly");
		}
		if (PC.boobs >= 1500000) {
			immobilities.push("breasts");
		}
		if (PC.balls >= 160) {
			immobilities.push("balls");
		}
		if (immobilities.length > 0) {
			r.push(`You have been rendered <span class="immobile">completely immobile</span> by the size and weight of your`);
			r.push(toSentence(immobilities));
			r.push(r.pop() + `, leaving you stuck on your bed. Nothing short of industrial equipment is capable of lifting you, and the logistics of getting something like that into the penthouse make it pretty clear that you aren't going to be going anywhere until you deal with all of this.`);
		}
		if (tooFatSlave(PC) && !immobilities.includes("fat body")) {
			noWalking.push("fat body");
		}
		if (tooBigBreasts(PC) && !immobilities.includes("breasts")) {
			noWalking.push("breasts");
		}
		if (tooBigBelly(PC) && !immobilities.includes("belly")) {
			noWalking.push("belly");
		}
		if (tooBigButt(PC) && !immobilities.includes("butt")) {
			noWalking.push("butt");
		}
		if (tooBigDick(PC) && !immobilities.includes("dick")) {
			noWalking.push("dick");
		}
		if (tooBigBalls(PC) && !immobilities.includes("balls")) {
			noWalking.push("balls");
		}
		if (PC.physicalImpairment > 1 || noWalking.length > 0) {
			if (immobilities.length > 0) {
				r.push(`Ignoring the obvious,`);
				if (noWalking.length > 0) {
					r.push(`the weight of your ${toSentence(noWalking)} would prevent you from walking anyway.`);
					if (PC.physicalImpairment > 1) {
						r.push(`Your injuries may also be contributing to that, but it's hard to tell when you can't even try.`);
					}
				} else {
					r.push(`it's not like you could walk anyway, having never regained the ability after being injured.`);
				}
				if (isMovable(PC)) {
					r.push(`You have to use a wheelchair if you want to get anywhere, which is subject to its own host of day-to-day problems.`);
				}
			} else {
				r.push(`You've <span class="hindrance mid">lost the ability to walk</span> due to`);
				if (noWalking.length > 0) {
					r.push(`the size and weight of your ${toSentence(noWalking)}, forcing you to rely on a wheelchair to get around.`);
					if (PC.physicalImpairment > 1) {
						r.push(`Your injuries may also be contributing to that, but it's hard to tell when you can't even try.`);
					}
					if (canMove(PC)) {
						r.push(`At the very least, you can still crawl if needed, so you aren't completely helpless.`);
					}
				} else {
					r.push(`crippling injuries, forcing you to rely on a wheelchair to get around.`);
					if (canMove(PC)) {
						r.push(`At the very least, you can still crawl if needed, so you aren't completely helpless.`);
					}
				}
			}
		}
		if (isTrapped(PC)) {
			if (!isMovable(PC)) {
				r.push(`It's not like you could leave your room anyway; the door is too small.`);
			} else {
				r.push(`To make matters even worse, you can't leave your room; the door is too small to fit through.`);
			}
		}

		if (onBedRest(PC)) {
			// One would assume that the player will realize that being unmovable/trapped also means they are more or less on bed rest.
			if (isInduced(PC)) {
				r.push(`<span class="hindrance high">You are on bed rest,</span> getting ready to give birth, so you are a little too preoccupied to focus on anything else at the moment.`);
			} else if (PC.preg > PC.pregData.normalBirth / 1.05 && PC.pregControl !== GestationDrug.LABOR) {
				r.push(`You're past your due date and having contractions, so until you give birth, you'll be <span class="hindrance high">staying in bed</span> and focusing on that over anything else.`);
			} else if (PC.majorInjury > 0) {
				r.push(`<span class="hindrance high">You are on mandatory bed rest due to serious injury.</span> You won't be able to do much until your body recovers.`);
			} else if (PC.health.condition < -90) {
				r.push(`<span class="hindrance high">You are on mandatory bed rest due to your poor health.</span> You won't be doing much other than sleeping until you recover.`);
			} else if (PC.geneMods.rapidCellGrowth !== 1 && PC.bellyPreg >= 100000 && PC.belly > (PC.pregAdaptation * 3200) && (PC.bellyPreg >= 500000 || PC.wombImplant !== "restraint")) {
				r.push(`You are on mandatory bed rest in the hope that staying relatively still will keep ${V.seeExtreme === 1 && V.dangerousPregnancy === 1 ? "your strained belly from bursting open" : "the dam holding back the flood waters from breaking."}.`);
			} else if ((PC.womb.find((ft) => ft.genetics.geneticQuirks.polyhydramnios === 2 && ft.age >= 20)) || (PC.bellyPreg >= PC.pregAdaptation * 2200)) {
				r.push(`You are on bed rest in an attempt to not further complicate your already troublesome pregnancy. While it is not compulsory, it does cut into both your work and play time.`);
			}
		}
	}

	function muscularAtrophy() {
		if (!isMovable(PC)) {
			if (PC.muscles > -80) {
				r.push(`Being bedbound takes its toll on your musculature, as what limited, awkward movements you are capable of can do little to sustain it.`);
				if (PC.muscles > 5) {
					r.push(`You <span class="change negative">lose some muscle definition.</span>`);
					PC.muscles -= 2;
				} else {
					r.push(`What's left of your <span class="change negative">muscles steadily atrophy.</span>`);
					PC.muscles--;
				}
			}
		} else if (onBedRest(PC, true)) {
			if (PC.health.shortDamage >= 50 || PC.health.condition < -90) {
				r.push(`Stuck completely unable to move, your <span class="change negative">muscles rapidly atrophy.</span>`);
				PC.muscles -= 3;
			} else if (PC.muscles > 5) {
				r.push(`Without proper maintenance, your <span class="change negative">muscles slowly soften.</span>`);
				PC.muscles--;
			}
		} else if (!canWalk(PC) && PC.diet !== PCDiet.MUSCLE) {
			if (PC.muscles.isBetween(-80, 6)) {
				r.push(`Without any muscle definition to maintain, and an electric wheelchair alleviating most of the effort of getting around, your unused <span class="change negative">muscles slowly atrophy.</span>`);
				PC.muscles--;
			}
		}
	}

	function bodyAccessibility() {
		if (isMovable(PC) && !(onBedRest(PC, true))) {
			if (PC.physicalImpairment !== 0) {
				r.push(`Due to the lasting effects of your injuries, any exertion you undertake requires plenty of rest afterward. Understandably, this limits how much you can get done in a day.`);
			}
			if (PC.weight >= 130 || (PC.weight >= 95 + ((PC.physicalAge - 9) * 5))) {
				r.push(`You're so overweight that any <span class="hindrance low">physical activity needs to be followed by a breather</span> and a little snack to get your energy back.`);
			}
			if (PC.muscles > 95 && PC.height <= (Height.mean(PC) + 10)) {
				r.push(`Your frame is inadequate to properly support your musculature, <span class="hindrance low">limiting your range of motion.</span> Frankly, this hinders you more in the gym than it does your other work.`);
			} else if (PC.muscles < -30) {
				r.push(`You're physically frail and can't do too much without having to stop and get your strength back, <span class="hindrance low">limiting how much you can accomplish in a day.</span>`);
			}
		}
	}

	function hugeBreasts() {
		if (canWalk(PC) && !(onBedRest(PC, true))) {
			if (PC.physicalAge >= 18) {
				if (PC.boobs > 25000) {
					if (PC.muscles <= 30) {
						r.push(`Your giant tits are debilitatingly big and exceedingly heavy. It's difficult to keep yourself from hunching forward while standing and slouching while sitting, so you often find your back rather sore by evening.`);
						healthDamage(PC, 2);
					} else {
						r.push(`Your giant tits are debilitatingly big, but you know how to properly manage them. Needless to say, you do a lot of back exercises.`);
					}
				} else if (PC.boobs > 10000) {
					if (PC.muscles <= 5) {
						r.push(`Your huge boobs are troublesome for your slight form; your back is often quite <span class="health dec">sore</span> by evening.`);
						healthDamage(PC, 1);
					} else {
						r.push(`Some people would say boobs as huge as yours would be uncomfortable, but with proper exercise and support, their weight is no trouble at all.`);
					}
				} else if (PC.boobs > 4000) {
					if (PC.muscles <= 5) {
						r.push(`The weight of your big boobs is a little uncomfortable, but nothing you can't handle.`);
					}
				}
			} else if (PC.physicalAge > 12) {
				if (PC.boobs > 15000) {
					if (PC.muscles <= 50) {
						r.push(`Your giant tits are debilitatingly big and exceedingly heavy. Your youthful body can barely keep upright with them, and by day's end, your <span class="health dec">back aches</span> considerably.`);
						healthDamage(PC, 2);
					} else {
						r.push(`Your giant tits are debilitatingly big, but you know how to properly manage them; your back muscles are ripped, to say the least.`);
					}
				} else if (PC.boobs > 7500) {
					if (PC.muscles <= 30) {
						r.push(`Your huge boobs are troublesome for your youthful body; your back is often quite <span class="health dec">sore</span> by evening.`);
						healthDamage(PC, 1);
					} else {
						r.push(`Some people say huge boobs on a young ${girlP} like you must be uncomfortable, but with proper support and plenty of back exercise, their weight doesn't bother you at all.`);
					}
				} else if (PC.boobs > 3000) {
					if (PC.muscles <= 5) {
						r.push(`The weight of your big boobs is a little uncomfortable, but nothing you can't handle.`);
					}
				}
			} else {
				if (PC.boobs > 10000) {
					if (PC.muscles <= 95) {
						r.push(`Your enormous tits are nearly crippling you; your childish body just can't support that much weight hanging from your chest. You savor every moment you get to rest them on something and take the strain off your back, but each morning you still wake up with a variety of aches and pains.`);
						healthDamage(PC, 3);
					} else {
						r.push(`As a preteen ${girlP} with a pair of enormous boobs wobbling from ${hisP} chest, you catch a lot of stares and the occasional comment over how much pain your back must be in. A simple flex of your muscles tends to quell those worries quickly enough.`);
					}
				} else if (PC.boobs > 8000) {
					if (PC.muscles <= 50) {
						r.push(`Your giant tits are debilitatingly big and exceedingly heavy for your childish body. You can barely keep upright with them, and by day's end, your back aches considerably from carrying them around.`);
						healthDamage(PC, 2);
					} else {
						r.push(`Your giant tits are debilitatingly big for your preteen body, but you know how to properly carry them; your back muscles are ripped, to say the least.`);
					}
				} else if (PC.boobs > 5000) {
					if (PC.muscles <= 30) {
						r.push(`Your huge boobs are troublesome for your childish body; your back is often quite <span class="health dec">sore</span> by evening.`);
						healthDamage(PC, 1);
					} else {
						r.push(`As a preteen ${girlP} with boobs bigger than ${hisP} head, you get a lot of comments about how they'll ruin your back, but with proper support and a muscular back, you're doing just fine.`);
					}
				} else if (PC.boobs > 2000) {
					if (PC.muscles <= 5) {
						r.push(`Your big boobs are uncomfortably heavy for your childish body, but a little back pain is nothing you can't handle.`);
					}
				}
			}
		}
	}

	function boobAccessibility() {
		if (isMovable(PC) && !(onBedRest(PC, true))) {
			if (PC.boobs > 5000) {
				r.push(`Your breasts tend to get in the way when conducting business; using a tablet is awkward, you smother traditional keyboards, video calls have to be adjusted around your bust, and that's not even to mention the trouble of carrying out your daily affairs throughout the arcology.`);
				if (V.boobAccessibility === 1) {
					r.push(`Luckily, the penthouse has been adapted for life with gigantic boobs, so you feel right at home.`);
				} else if (PC.boobs > 25000) {
					r.push(`Life at home is no better:`);
					if (V.buttAccessibility === 1 || V.pregAccessibility === 1 || V.ballsAccessibility === 1) {
						r.push(`the appliances are always out of reach, the furniture tough to get out of, and things are the perfect height to jab you right in the tits. At least the doors are wide enough for you to get through.`);
					} else {
						r.push(`the appliances are always out of reach, the furniture tough to get out of, things are the perfect height to jab you right in the tits, and you cause traffic just trying to move between rooms.`);
					}
				}
			}
		}
	}

	function hugeBelly() {
		let resting = onBedRest(PC) ? 2 : 1;
		let RCGmod = 1 + PC.geneMods.rapidCellGrowth;
		if (PC.belly > (PC.pregAdaptation * 4500)) {
			r.push(`You may have made a mistake; your bloated`);
			if (PC.mpreg === 0 && PC.ovaries === 0) {
				r.push(`implant-filled middle`);
			} else {
				r.push(`womb`);
			}
			r.push(`is under immense strain and puts overwhelming pressure on your skin and organs. It's turned black and blue from the tension and the deep stretch marks are truly worrying.`);
			if (PC.geneticQuirks.uterineHypersensitivity === 2 && PC.preg > 0) {
				r.push(`You're trapped in a constant state of mixed pleasure and pain,`);
				if (V.geneticMappingUpgrade > 0) {
					r.push(`thanks to your uterine hypersensitivity,`);
				}
				r.push(`making it difficult to focus on anything other than orgasming.`);
			} else {
				r.push(`The pain is excruciating, and each`);
				if (PC.bellyPreg > 100) {
					r.push(`movement within you`);
				} else {
					r.push(`breath`);
				}
				r.push(`feels like it could force you to burst.`);
			}
			healthDamage(PC, 30, 2);
			if (PC.geneticQuirks.uterineHypersensitivity === 2) {
				PC.pregAdaptation += 5 * RCGmod;
			} else {
				PC.pregAdaptation += 1 * RCGmod;
			}
		} else if (PC.belly > (PC.pregAdaptation * 3200)) {
			r.push(`You may have overdone it a little; your`);
			if (PC.mpreg === 0 && PC.ovaries === 0) {
				r.push(`implant filled abdominal cavity`);
			} else {
				r.push(`straining womb`);
			}
			r.push(`takes up all the available space in your body, putting <span class="health dec">tremendous pressure on your skin and crushing your organs.</span>`);
			if (PC.geneticQuirks.uterineHypersensitivity === 2 && PC.preg > 0) {
				if (V.geneticMappingUpgrade > 0) {
					r.push(`Your uterine hypersensitivity renders it extremely pleasurable, often forcing you to become lost in playing with your belly.`);
				} else {
					r.push(`The uncanny way you rub, tease and grab at your belly, even in public, is becoming rather disturbing to people.`);
				}
			} else {
				r.push(`You feel a distinct, stabbing pain alongside`);
				if (PC.bellyPreg > 100) {
					r.push(`each movement inside you;`);
				} else {
					r.push(`each breath;`);
				}
				r.push(`your body can't take much more of this.`);
			}
			healthDamage(PC, 20);
			if (PC.geneticQuirks.uterineHypersensitivity === 2) {
				PC.pregAdaptation += 4 * RCGmod;
			} else {
				PC.pregAdaptation += .4 * RCGmod;
			}
		} else if (PC.belly > (PC.pregAdaptation * 2000)) {
			r.push(`Your body cavity is completely filled by your`);
			if (PC.mpreg === 0 && PC.ovaries === 0) {
				r.push(`belly implant,`);
			} else {
				r.push(`womb,`);
			}
			r.push(`<span class="health dec">putting pressure on your skin and organs.</span>`);
			if (PC.geneticQuirks.uterineHypersensitivity === 2 && PC.preg > 0) {
				if (V.geneticMappingUpgrade > 0) {
					r.push(`The pleasure derived from your uterine hypersensitivity completely masks any discomfort.`);
				} else {
					r.push(`The pressure makes you really horny for some reason.`);
				}
			} else {
				r.push(`It's really uncomfortable, but mostly limited to when`);
				if (PC.bellyPreg > 100) {
					r.push(`your babies are active.`);
				} else {
					r.push(`you have to move.`);
				}
			}
			healthDamage(PC, (10 / resting));
			if (PC.geneticQuirks.uterineHypersensitivity === 2) {
				PC.pregAdaptation += 3 * RCGmod;
			} else {
				PC.pregAdaptation += .3 * RCGmod;
			}
		} else if (PC.belly > (PC.pregAdaptation * 1000)) {
			r.push(`Your body is filled by your`);
			if (PC.mpreg === 0 && PC.ovaries === 0) {
				r.push(`belly implant,`);
			} else {
				r.push(`womb,`);
			}
			r.push(`<span class="health dec">compressing your internal organs.</span>`);
			if (PC.geneticQuirks.uterineHypersensitivity === 2 && PC.preg > 0) {
				if (V.geneticMappingUpgrade > 0) {
					r.push(`Your uterine hypersensitivity renders having such a stretched womb rather enjoyable.`);
				} else {
					r.push(`It feels pretty good, in fact.`);
				}
			} else {
				r.push(`There's no way to get comfortable around it, so all you can do is bear it.`);
			}
			healthDamage(PC, (2 / resting));
			if (PC.geneticQuirks.uterineHypersensitivity === 2) {
				PC.pregAdaptation += 2 * RCGmod;
			} else {
				PC.pregAdaptation += .2 * RCGmod;
			}
		} else if (PC.belly > (PC.pregAdaptation * 750)) {
			if (PC.geneticQuirks.uterineHypersensitivity === 2) {
				PC.pregAdaptation += 1 * RCGmod;
			} else {
				PC.pregAdaptation += .1 * RCGmod;
			}
		}
		if (PC.geneMods.progenitor === 1 && PC.belly > (PC.pregAdaptation * 750)) {
			if (PC.belly > (PC.pregAdaptation * 1000)) {
				r.push(`At least your genetically treated body is rapidly adjusting to your gravidity.`);
			}
			PC.pregAdaptation += 1;
		}
		if (PC.wombImplant === "restraint" && PC.belly >= 400000) {
			r.push(`The mesh implanted into the walls of your uterus is nearing its limit and beginning to strangle the organ it is meant to support. While it is still structurally sound, it may fail on you if it is forced to stretch much more.`);
			healthDamage(PC, 15, 2);
		}

		/* body inconvenience */
		if (canWalk(PC) && !(onBedRest(PC, true))) {
			const belly = bellyAdjective(PC);
			if (PC.physicalAge >= 18) {
				if (PC.belly >= 300000) {
					r.push(`Your ${belly} belly is debilitatingly large; waddling around is a challenge, and you need to take things extra slow to make sure you don't accidentally bump into anything.`);
				} else if (PC.belly >= 150000) {
					r.push(`Your ${belly} belly is troublesome; each step is slow and ponderous, and you have to be careful not to accidentally drive the bulbous mass into anything.`);
				} else if (PC.belly >= 75000) {
					r.push(`Your ${belly} belly juts out heavily from your frame, messing with your sense of balance and leaving you second guessing what you can fit through.`);
				}
			} else if (PC.physicalAge > 12) {
				if (PC.belly >= 300000) {
					r.push(`Your ${belly} belly constantly threatens to drag you to the floor, which would be nice to take the weight off your teenage body, but would also mean you'd need help getting back to your feet.`);
				} else if (PC.belly >= 200000) {
					r.push(`Your ${belly} belly is debilitatingly large on your teenage body; waddling around is a challenge, and you need to take things extra slow to make sure you don't accidentally bump into anything.`);
				} else if (PC.belly >= 80000) {
					r.push(`Your ${belly} belly is troublesome for your teenage body; each step is slow and ponderous, and you have to be careful not to accidentally drive the bulbous mass into anything.`);
				} else if (PC.belly >= 30000) {
					r.push(`Your ${belly} belly juts out heavily from your teenage frame, messing with your sense of balance and just how big you actually are.`);
				}
			} else {
				if (PC.belly >= 200000) {
					r.push(`Your ${belly} belly is overwhelming on your immature body. You really would like to let it rest on the floor and take its weight off you, but then you'd need help getting back upright.`);
				} else if (PC.belly >= 120000) {
					r.push(`Your ${belly} belly is debilitatingly large on your immature body; you can barely waddle at all, and you need to take things extra slow since it blocks you from seeing the floor ahead of you.`);
				} else if (PC.belly >= 60000) {
					r.push(`Your ${belly} belly is troublesome for your immature body; each step is slow and ponderous, and you have to be careful not to accidentally drive the bulbous mass into anything.`);
				} else if (PC.belly >= 30000) {
					r.push(`Your ${belly} belly juts out heavily from your juvenile frame, messing with your sense of balance and making you feel absolutely enormous.`);
				}
			}
		}
	}

	function bellyAccessibility() {
		if (isMovable(PC) && !(onBedRest(PC, true))) {
			if (PC.belly >= 60000 || PC.belly >= 60000 / (1 + Math.pow(Math.E, -0.4 * (PC.physicalAge - 14))) || PC.belly >= Math.max(10000, ((12500 / 19) * PC.height) - (1172500 / 19))) {
				r.push(`Your middle gets in the way of your typical routine; it's tough to get comfortable, you have to dress around it if you don't want to look like a harlot, and it takes way more effort than it ever should to sit at any sort of furniture.`);
				if (V.pregAccessibility === 1) {
					r.push(`Good thing the penthouse has been adapted for heavily pregnant life, alleviating most of your concerns, so long as you don't need to leave it.`);
				} else if (PC.belly >= 100000) {
					r.push(`Homelife is full of frustrations too:`);
					if (V.buttAccessibility === 1 || V.boobAccessibility === 1 || V.ballsAccessibility === 1) {
						r.push(`appliances are most easily reached sideways, you've gotten stuck sitting down, and one too many corners have made contact with your sensitive bump. At least there's plenty of room to maneuver in the halls.`);
					} else {
						r.push(`appliances are most easily reached sideways, you've gotten stuck sitting down, one too many corners have made contact with your sensitive bump, and slaves keep getting stuck behind you in the halls.`);
					}
				}
			}
		}
	}

	function hugeDick() {
		if (canWalk(PC) && !(onBedRest(PC, true))) {
			const dickLength = dickToCM(PC.dick);
			if (dickLength >= ((PC.height / 2) + 30)) {
				r.push(`Left unrestrained, your enormous penis rests on the ground, even while standing. It's easy to manage at least, though that probably wouldn't be the case if you became erect.`);
			} else if (dickLength >= (PC.height / 2)) {
				r.push(`When left hanging, your cockhead grazes the ground as you stand. It's easy to manage,`);
				if (canAchieveErection(PC)) {
					r.push(`though erections complicate things a bit; if you get too hard, there's no way you can contain it, and`);
					if (PC.belly >= 100000) {
						r.push(`it ends up painfully trapped under your belly until you deal with it.`);
					} else if (PC.weight > 130) {
						r.push(`it inadvertently presses against your gut. Attending a business meeting is pretty risky when every motion pushes your self-inflicted bellyfuck closer to completion.`);
					} else if (PC.boobs >= 300) {
						r.push(`you end up inadvertently giving yourself a titfuck. Attending a business meeting coated in your own load doesn't make you look good.`);
					} else {
						r.push(`you're stuck with your own dick prodding your face until you deal with it.`);
					}
				} else {
					r.push(`all things considered, though you doubt that would be the case if you could get erect.`);
				}
			} else if (dickLength >= (PC.height / 4)) {
				r.push(`When let loose, your cockhead hangs past your knees. It may get in the way at times, but attention your bulge gets makes it all worthwhile.`);
			}
		}
	}

	function dickAccessibility() {
		if (isMovable(PC) && !(onBedRest(PC, true))) {
			if (PC.dick >= 20) {
				if (V.dickAccessibility === 1) {
					r.push(`It was a good move having your living space redesigned around enormous dicks; taking a piss should never be that complicated.`);
				} else {
					r.push(`The penthouse itself is tolerable to live in with your cock, but the bathrooms are an unspeakable horror, for both yourself and the slaves that have to clean them.`);
				}
			}
		}
	}

	function hugeBalls() {
		if (canWalk(PC) && !(onBedRest(PC, true))) {
			const estimatedSackSag= ballsToCM(PC.balls) * .8 * (1 + ((PC.scrotum - PC.balls) * .5)); // Oval shape + scrotal sag
			if (estimatedSackSag > (PC.height / 2)) {
				r.push(`Your titanic balls never leave the floor, even when standing, unless you make an effort to lift them yourself. Once they're situated, getting around isn't too bad, though they are pretty heavy.`);
			} else if (estimatedSackSag >= (PC.height / 2) - 10) {
				r.push(`Your enormous balls hang down to the floor when you stand, and rest on it when you sit. You can get around with some sturdy supports, but you might need a cart soon.`);
			} else if (estimatedSackSag >= (PC.height / 4)) {
				r.push(`Your huge balls hang past your knees when you stand. Having them bouncing around while walking usually results in you kneeing yourself in the nuts, so supportive underwear is a must when touring your domain.`);
			}
		}
	}

	function ballsAccessibility() {
		if (isMovable(PC) && !(onBedRest(PC, true))) {
			if (PC.balls >= 14) {
				r.push(`It takes extra time to get anywhere carrying a sack like yours around, limiting the number of potential places you can be in a day, and seating is often an issue with them in the way.`);
				if (V.ballsAccessibility === 1) {
					r.push(`You never have to deal with that in the penthouse after having refitted for the comfort of those with sizable testicles.`);
				} else if (PC.balls >= 50) {
					r.push(`The latter issue follows you back to the penthouse, giving you no real place to relax and unwind; the number of rotations you need to do in the bathroom is irritating.`);
					if (V.buttAccessibility === 1 || V.pregAccessibility === 1 || V.boobAccessibility === 1) {
						r.push(`At least there is plenty of room to maneuver, due to the other structural renovations you've had done.`);
					} else {
						r.push(`You are also starting to become painfully aware of just how wide the doorframes are compared to you.`);
					}
				}
			}
		}
	}

	function hugeHips() {
		if (isMovable(PC) && !(onBedRest(PC, true))) {
			if (PC.hips > 2) {
				r.push(`Your inhumanly wide hips <span class="hindrance low">frequently get in the way</span> as your try to work and conduct business.`);
			}
		}
	}

	function hugeButt() {
		if (canWalk(PC) && !(onBedRest(PC, true))) {
			if (PC.butt > 10) {
				r.push(`Your butt is a wonderful burden; it fills out whatever you wear, but also is a real pain to dress around, and then there is the looming chance of getting chairs stuck around it when you sit down. It also substantially juts out from you, leading to a tendency of accidentally bumping people with it as you walk by; more than one person has taken this as an invitation to give it a good feel.`);
			}
		}
	}

	function buttAccessibility() {
		if (isMovable(PC) && !(onBedRest(PC, true))) {
			if (PC.butt > 6) {
				r.push(`Your rear <span class="hindrance low">slows you down considerably,</span> and you have to plan ahead of time where to meet people to avoid any embarrassing situations involving it.`);
				if (V.buttAccessibility === 1) {
					r.push(`You're free from any of those concerns in the penthouse, so long as your slaves know how to get out of your junk filled trunk's way.`);
				} else if (PC.butt > 15) {
					r.push(`Too bad the same can't be said for the penthouse; chairs constantly follow you when you try to leave them, you're always trying to avoid knocking things over,`);
					if (V.boobAccessibility === 1 || V.pregAccessibility === 1 || V.ballsAccessibility === 1) {
						r.push(`but your ass has the clearance it demands due to the widened doors and halls.`);
					} else {
						r.push(`and you swear it is impossible to get anywhere without bouncing off door frames, walls, and bewildered slaves.`);
					}
				}
			}
		}
	}

	function hindrance() {
		const degree = isHinderedDegree(PC);

		if (degree !== 1 && !onBedRest(PC, true)) {
			r.push(`Overall,`);
			if (onBedRest(PC)) {
				r.push(`<span class="hindrance high">you're pretty limited,</span> but since you're working from bed, that's to be expected.`);
			} else if (degree <= .3) {
				r.push(`your body is a crippling hindrance to you. It may be better to stop trying to live a normal life and just keep growing until you can no longer leave your bed; this way you'll never be expected to do things outside the penthouse and can work around your body.`);
			} else if (degree <= .5) {
				r.push(`your body is <span class="hindrance high">a major hindrance to you.</span>`);
			} else if (degree <= .7) {
				r.push(`your body is <span class="hindrance mid">a hindrance to you.</span>`);
			} else {
				r.push(`your body is only a <span class="hindrance low">minor hindrance.</span>`);
			}
		}
	}
};


code:
// cSpell:ignore hotnhorny

App.EndWeek.Player.pregnancy = function(PC = V.PC) {
	const r = [];

	const gigantomastiaMod = PC.geneticQuirks.gigantomastia === 2 ? (PC.geneticQuirks.macromastia === 2 ? 3 : 2) : 1;
	const rearQuirk = PC.geneticQuirks.rearLipedema === 2 ? 2 : 0;
	const uterineHypersensitivityMod = PC.geneticQuirks.uterineHypersensitivity === 2 ? 2 : 1;
	const boobSize = App.Medicine.fleshSize(PC, 'boobs');
	const oldBoobs = PC.boobs;
	const buttSize = App.Medicine.fleshSize(PC, 'butt');
	const hipSize = PC.hips - PC.hipsImplant;
	const child = (PC.pregType > 1 ? "children" : "child");

	if (PC.preg > 0) {
		pregnancyEffects();
	}
	if (V.seePreg !== 0) {
		preconception();
		pregnancySanityCheck();
	}

	return r.join(" ");

	function pregnancyEffects() {
		pregnancyDiscovery();
		pregnancyLibido();
		fetalAdjustment();
		if (PC.preg >= PC.pregData.normalBirth / 4) {
			pregnancyAdjustments();
			laborText();
			pregnancyPhysicalEffects();
		}
		if (PC.pregType === 0) { // Catch for strange cases - now with checking.
			failSafe();
		}
	}

	function pregnancyDiscovery() {
		// Add passive discovery to this once periods are added
		if (PC.preg === PC.pregData.normalBirth / 8 && PC.pregSource > 0) {
			actX(findFather(V.PC.pregSource), "PCKnockedUp");
		}
		if (PC.bellyFluid > 2000) {
			if (PC.inflation > 1) {
				r.push(`While trying to inflate yourself with ${PC.inflationType}, you discover that you can't hold more <span class="noteworthy">two liters</span> without feeling seriously ill.`);
				PC.inflation = 1;
			} else {
				r.push(`While pleasuring yourself by inflating with ${PC.inflationType}, you're forced to stop due to a sudden bout of extreme nausea.`);
				PC.bellyFluid = 2000;
			}
			SetBellySize(PC);
			if (PC.pregKnown === 0) {
				r.push(`It turns out <span class="pregnancy">you're`);
				if (PC.preg > PC.pregData.normalBirth / 4) {
					r.push(`pregnant and have been for some time.</span>`);
				} else {
					r.push(`pregnant.</span>`);
				}
			} else {
				r.push(`Unfortunately, this will likely be the case for the duration of your pregnancy; at least you'll still steadily swell, if a little slowly for your taste.`);
			}
		}
	}

	function pregnancyLibido() {
		// drop .energy on birth for uterine hypersensitivity
		if (PC.geneticQuirks.uterineHypersensitivity === 2 && V.geneticMappingUpgrade >= 1) {
			if (PC.preg >= PC.pregData.normalBirth) {
				r.push(`Your pregnancy is nearing its end and you're overwhelmed with arousal. Your uterine hypersensitivity combined with a full womb and upcoming birth confers a huge improvement to your sexual appetite.`);
				PC.energy += 7;
			} else if (PC.preg > PC.pregData.normalBirth / 1.33) {
				r.push(`Being hugely pregnant with uterine hypersensitivity confers an <span class="libido inc">improvement to your sexual appetite</span> as your womb steadily stretches.`);
				PC.energy += 5;
			} else if (PC.preg > PC.pregData.normalBirth / 2) {
				r.push(`Being pregnant with uterine hypersensitivity confers a <span class="libido inc">slow improvement to your sexual appetite</span> as your womb grows ever fuller.`);
				PC.energy += 3;
			} else if (PC.preg > PC.pregData.normalBirth / 4) {
				r.push(`You eagerly anticipate the growth of your pregnancy, producing <span class="libido inc">a very slow improvement to your sexual appetite.</span>`);
				PC.energy += 1;
			} else if (PC.preg <= PC.pregData.normalBirth / 4 && PC.preg > PC.pregData.normalBirth / 13.33) {
				if (PC.counter.birthsTotal > 0) {
					r.push(`The rigors of early pregnancy are easily tolerable when you can only quiver in anticipation of what's to come.`);
				} else {
					r.push(`The rigors of early pregnancy <span class="libido dec">slightly reduce your sexual appetite.</span>`);
					PC.energy -= 1;
				}
			}
		} else if (PC.geneticQuirks.uterineHypersensitivity === 2) {
			if (PC.preg >= PC.pregData.normalBirth) {
				r.push(`Your pregnancy is nearing its end and you're overwhelmed with arousal. The sensation of your womb stretched so full ${PC.counter.birthsTotal > 0 ? "and the anticipation of another orgasmic birth " : ""}sends your sexual appetite skyrocketing.`);
				PC.energy += 7;
			} else if (PC.preg > PC.pregData.normalBirth / 1.33) {
				r.push(`The feeling of your womb steadily expanding drives you wild, <span class="libido inc">improving your sexual appetite.</span>`);
				PC.energy += 5;
			} else if (PC.preg > PC.pregData.normalBirth / 2) {
				r.push(`The life growing in your womb leaves you feeling especially energetic, granting a <span class="libido inc">slow improvement to your sexual appetite.</span>`);
				PC.energy += 3;
			} else if (PC.preg > PC.pregData.normalBirth / 4) {
				r.push(`You feel a rush from your growing pregnancy, granting a <span class="libido inc">very slow improvement to your sexual appetite.</span>`);
				PC.energy += 1;
			} else if (PC.preg <= PC.pregData.normalBirth / 4 && PC.preg > PC.pregData.normalBirth / 13.33) {
				if (PC.counter.birthsTotal > 0) {
					r.push(`The rigors of early pregnancy are easily tolerable when you can only quiver in anticipation of what's to come.`);
				} else {
					r.push(`The rigors of early pregnancy <span class="libido dec">slightly reduce your sexual appetite.</span>`);
					PC.energy -= 1;
				}
			}
		} else if (PC.pregMood === 2) {
			if (PC.preg <= PC.pregData.normalBirth / 4 && PC.preg > PC.pregData.normalBirth / 13.33) {
				r.push(`The rigors of early pregnancy <span class="libido dec">take their toll on your sexual appetite.</span>`);
				PC.energy -= 3;
			} else if (PC.preg >= PC.pregData.normalBirth) {
				r.push(`Your pregnancy is nearing its end and you're <span class="libido inc">horny as hell.</span> Your hormones are out of control, driving you to fuck like a beast in heat despite your condition.`);
				PC.energy += 4;
			} else if (PC.preg > PC.pregData.normalBirth * .66) {
				r.push(`With your pregnancy hormones raging, you <span class="libido inc">find your thoughts focusing on sex</span> more than usual.`);
				PC.energy += 2;
			} else if (PC.preg > PC.pregData.normalBirth / 2) {
				r.push(`As your pregnancy grows, so does your desire for sex.`);
			}
		// } else if (PC.pregMood === 4) { unattractive
		} else if (PC.energy >= 90) {
			if (PC.preg <= PC.pregData.normalBirth / 4 && PC.preg > PC.pregData.normalBirth / 13.33) {
				r.push(`The rigors of early pregnancy <span class="libido dec">take their toll on your sexual appetite.</span>`);
				PC.energy -= 3;
			} else if (PC.preg >= PC.pregData.normalBirth) {
				r.push(`Your pregnancy is nearing its end and you're horny as hell. Between your hormones and already high libido, you're acting like you haven't had a good fuck in nine months.`);
				PC.energy += 2;
			} else if (PC.preg > PC.pregData.normalBirth / 1.33) {
				r.push(`Your advanced pregnancy, combined with your already high libido, leaves you aching to be filled throughout the day.`);
			} else if (PC.preg > PC.pregData.normalBirth / 2) {
				r.push(`Your growing pregnancy, combined with your already high libido, has you always itching for some sex.`);
			}
		// } else if (PC.pregMood === 3) { frigid
		// } else if (PC.pregMood === 5) { hotnhorny
		} else if (PC.energy > 60) {
			if (PC.preg <= PC.pregData.normalBirth / 4 && PC.preg > PC.pregData.normalBirth / 13.33) {
				r.push(`The rigors of early pregnancy <span class="libido dec">take their toll on your sexual appetite.</span>`);
				PC.energy -= 3;
			} else if (PC.preg >= PC.pregData.normalBirth) {
				r.push(`Your pregnancy is nearing its end and you're suffering from an <span class="libido inc">unquenchable need to be filled.</span>`);
				PC.energy += 4;
			} else if (PC.preg > PC.pregData.normalBirth / 1.33) {
				r.push(`Your advanced pregnancy comes with a hugely increased libido, <span class="libido inc">greatly increasing your sexual drive.</span>`);
				PC.energy += 3;
			} else if (PC.preg > PC.pregData.normalBirth / 2) {
				r.push(`Your growing pregnancy comes with an increased libido, <span class="libido inc">spurring your sexual appetite.</span>`);
				PC.energy += 2;
			}
		} else if (PC.energy > 40) {
			if (PC.preg <= PC.pregData.normalBirth / 4 && PC.preg > PC.pregData.normalBirth / 13.33) {
				r.push(`The rigors of early pregnancy <span class="libido dec">slightly reduce your sexual appetite.</span>`);
				PC.energy -= 1;
			} else if (PC.preg >= PC.pregData.normalBirth) {
				r.push(`Your pregnancy is nearing its end and you're <span class="libido inc">feeling rather frisky.</span>`);
				PC.energy += 2;
			} else if (PC.preg > PC.pregData.normalBirth / 1.33) {
				r.push(`As your pregnancy grows, so does that<span class="libido inc">tingling feeling</span> in your crotch.`);
				PC.energy += 1;
			}
		} else {
			if (PC.preg <= PC.pregData.normalBirth / 4 && PC.preg > PC.pregData.normalBirth / 13.33) {
				r.push(`The rigors of early pregnancy <span class="libido dec">take their toll on your sexual appetite.</span>`);
				PC.energy -= 3;
			} else if (PC.preg >= PC.pregData.normalBirth) {
				r.push(`Your pregnancy is nearing its end and you're feeling way too full for sex, <span class="libido dec">greatly suppressing your sexual appetite.</span>`);
				PC.energy -= 3;
			} else if (PC.preg > PC.pregData.normalBirth / 1.33) {
				r.push(`Your advanced pregnancy <span class="libido dec">greatly hinders your sexual appetite.</span>`);
				PC.energy -= 2;
			} else if (PC.preg > PC.pregData.normalBirth / 2) {
				r.push(`Your growing pregnancy <span class="libido dec">suppresses your sexual appetite slightly.</span>`);
				PC.energy -= 1;
			}
		}
	}

	function fetalAdjustment() {
		const oldCount = PC.pregType;
		if (PC.preg <= 2 && PC.broodmother === 0) {
			fetalSplit(PC, 1000);
			WombCleanYYFetuses(PC);
		}
		if (V.pregnancyMonitoringUpgrade === 1 && PC.pregKnown) {
			if (oldCount < PC.pregType) {
				r.push(`While exploring your new pregnancy with the monitoring tools, you get quite the surprise; <span class="pregnancy">you are more pregnant than previously thought!</span>`);
			} else if (oldCount > PC.pregType) {
				r.push(`While exploring your new pregnancy with the monitoring tools, you make an unfortunate discovery; <span class="change negative">some of your fertilized ova have not made it.</span>`);
				if (PC.pregType === 0) {
					r.push(`Since there are now none present in your womb, <span class="noteworthy">you are technically no longer pregnant.</span>`);
					TerminatePregnancy(PC);
				}
			}
		} else if (oldCount > PC.pregType && PC.pregType === 0) {
			TerminatePregnancy(PC);
		}
	}

	function pregnancyAdjustments() {
		if (PC.geneticQuirks.gigantomastia === 3 && random(1, 200) < PC.hormoneBalance) {
			PC.geneticQuirks.gigantomastia = 2;
		}
		if (PC.geneticQuirks.macromastia === 3 && random(1, 200) < PC.hormoneBalance) {
			PC.geneticQuirks.macromastia = 2;
		}
		if (PC.geneticQuirks.galactorrhea === 2 && random(1, 100) < PC.hormoneBalance && PC.lactation === 0) {
			PC.inappropriateLactation = 1;
		}
	}

	function laborText() {
		const childIs = (PC.pregType > 1 ? "children are" : "child is");
		if (isInduced(PC)) {
			r.push(`Your child${PC.pregType > 1 ? "ren stir" : "stirs"} restlessly as ${PC.pregType > 1 ? "they prepare" : "it prepares"} to enter the world. You experience several`);
			if (PC.geneticQuirks.uterineHypersensitivity === 2) {
				r.push(`${PC.counter.birthsTotal > 0 ? "overwhelmingly" : "unexpectedly"} orgasmic`);
			}
			r.push(`contractions, so it's best to stay put until it's time.`);
		} else if (PC.pregControl === GestationDrug.LABOR) {
			r.push(`Your ${childIs} far calmer that one would expect for their stage of development; it is unlikely you will give birth soon, despite being overdue.`);
		} else {
			if (PC.preg > PC.pregData.normalBirth + 1) {
				r.push(`You are constantly beset by your squirming`);
				if (PC.geneticQuirks.uterineHypersensitivity === 2) {
					r.push(`${child} and uncontrollable orgasms.`);
				} else {
					r.push(`${child}.`);
				}
				r.push(`They're overdue, so your water could break at any moment, but for now they aren't quite ready to leave their home.`);
			} else if (PC.preg > PC.pregData.normalBirth - 1 && PC.preg > PC.pregData.minLiveBirth) {
				r.push(`You are constantly beset by your squirming`);
				if (PC.geneticQuirks.uterineHypersensitivity === 2) {
					r.push(`${child} and uncontrollable orgasms.`);
				} else {
					r.push(`${child}.`);
				}
				r.push(`Given their liveliness, and how far along you are, it is likely that you will go into labor at any time now.`);
			} else if (PC.preg > PC.pregData.normalBirth - 2 && PC.preg > PC.pregData.minLiveBirth) {
				r.push(`You often have to pause and soothe your kicking`);
				if (PC.geneticQuirks.uterineHypersensitivity === 2) {
					r.push(`${child}, to spontaneously orgasm,`);
				} else {
					r.push(`${child}`);
				}
				r.push(`or to catch your breath. With how far along you are, it's possible you may go into labor any day now.`);
			} else if (PC.preg > PC.pregData.normalBirth - 3 && PC.preg > PC.pregData.minLiveBirth) {
				r.push(`You often have to pause to soothe your kicking`);
				if (PC.geneticQuirks.uterineHypersensitivity === 2) {
					r.push(`${child} or to spontaneously orgasm.`);
				} else {
					r.push(`${child}.`);
				}
				r.push(`You are far enough along that you could enter labor early.`);
			}
		}
	}

	function pregnancyPhysicalEffects() {
		let boobTarget;
		const slimnessFoodMod = (V.arcologies[0].FSSlimnessEnthusiastFoodLaw === 1 && !canEatFood(PC)) ? 0.5 : 1;
		if (PC.geneMods.NCS === 1) {
			// NCS: always working against secondary sexual characteristics even in pregnancies.
			boobTarget = 0;
		} else if (PC.geneticQuirks.androgyny === 2) {
			boobTarget = 400;
		} else if (PC.physicalAge >= 18) {
			if (PC.pregType >= 50) {
				boobTarget = 10000;
			} else if (PC.pregType >= 30) {
				boobTarget = 5000;
			} else if (PC.pregType >= 10) {
				boobTarget = 2000;
			} else if (PC.pregType >= 2) {
				boobTarget = 1000;
			} else {
				boobTarget = 800;
			}
		} else if (PC.physicalAge >= 13) {
			if (PC.pregType >= 50) {
				boobTarget = 5000;
			} else if (PC.pregType >= 30) {
				boobTarget = 3200;
			} else if (PC.pregType >= 10) {
				boobTarget = 1800;
			} else if (PC.pregType >= 2) {
				boobTarget = 1000;
			} else {
				boobTarget = 700;
			}
		} else if (PC.physicalAge >= 8) {
			if (PC.pregType >= 50) {
				boobTarget = 1800;
			} else if (PC.pregType >= 30) {
				boobTarget = 1400;
			} else if (PC.pregType >= 10) {
				boobTarget = 1000;
			} else if (PC.pregType >= 2) {
				boobTarget = 800;
			} else {
				boobTarget = 600;
			}
		} else {
			if (PC.pregType >= 50) {
				boobTarget = 1000;
			} else if (PC.pregType >= 30) {
				boobTarget = 800;
			} else if (PC.pregType >= 10) {
				boobTarget = 600;
			} else {
				boobTarget = 400;
			}
		}
		boobTarget *= gigantomastiaMod;
		boobTarget *= slimnessFoodMod;
		if (PC.geneMods.NCS === 0) {
			if (PC.pregType >= 30) {
				if (PC.weight <= 100) {
					r.push(`With the amount of food you eat to sustain your brood, <span class="change negative">you put on a little baby weight.</span>`);
					PC.weight += 1;
				}
				if (random(1, 100) > 60) {
					if (boobSize < boobTarget) {
						boobsUpText(100);
						if (PC.boobShape !== BreastShape.SAGGY && PC.preg > PC.pregData.normalBirth / 1.25 && (PC.boobsImplant / PC.boobs < 0.5) && PC.breastMesh !== 1 && PC.drugs !== Drug.SAGBGONE) {
							r.push(`Your immensely engorged <span class="change negative">mammaries begin to sag</span> as your body continues its motherly transformation in anticipation of breastfeeding.`);
							PC.boobShape = BreastShape.SAGGY;
						}
					}
					if (PC.geneticQuirks.androgyny !== 2) {
						if (hipSize < 2) {
							r.push(`Your hips <span class="change positive">widen</span> in preparation for the upcoming births.`);
							PC.hips += 1;
						}
						if (buttSize < 14 + (rearQuirk * 3)) {
							r.push(`Your butt <span class="change positive">swells with added fat</span> from your ripening body.`);
							PC.butt += 1;
						}
					}
				}
			} else if (PC.pregType >= 10) {
				if (PC.weight <= 65) {
					r.push(`With how hungry your brood is, it's no surprise that <span class="change negative">you put on a little baby weight</span> feeding their growth.`);
					PC.weight += 1;
				}
				if (random(1, 100) > 80 && boobSize < boobTarget) {
					boobsUpText(50);
					if (PC.boobShape !== BreastShape.SAGGY && (PC.boobsImplant / PC.boobs < 0.5) && PC.breastMesh !== 1 && PC.drugs !== Drug.SAGBGONE) {
						if (PC.preg > random(PC.pregData.normalBirth / 1.25, PC.pregData.normalBirth * 2.05)) {
							r.push(`Your swollen <span class="change negative">mammaries begin to sag</span> as your body continues its motherly transformation in anticipation of breastfeeding.`);
							PC.boobShape = BreastShape.SAGGY;
						}
					}
				}
			} else if (boobSize < boobTarget) {
				if (PC.weight <= 35 && random(random(1, 100) > 50)) {
					r.push(`You can't help but <span class="change negative">put on a little baby weight</span> due to your increased appetite.`);
					PC.weight += 1;
				}
				if (random(1, 100) > 80) {
					boobsUpText(25);
					if (PC.boobShape !== BreastShape.SAGGY && PC.preg > random(PC.pregData.normalBirth / 1.25, PC.pregData.normalBirth * 2.5) && (PC.boobsImplant / PC.boobs < 0.5) && PC.breastMesh !== 1 && PC.drugs !== Drug.SAGBGONE) {
						r.push(`Your <span class="change negative">mammaries begin to sag</span> as your body continues its motherly transformation in anticipation of breastfeeding.`);
						PC.boobShape = BreastShape.SAGGY;
					}
				}
			}
			if (PC.preg > PC.pregData.normalBirth / 1.25 && PC.physicalAge >= 18 && PC.hips === 1 && PC.hipsImplant === 0 && random(1, 100) > 90 / uterineHypersensitivityMod) {
				r.push(`Your hips <span class="change positive">widen</span> to better support your gravidity.`);
				PC.hips += 1;
			} else if (PC.preg > PC.pregData.normalBirth / 1.42 && PC.physicalAge >= 16 && PC.hips === 0 && PC.hipsImplant === 0 && random(1, 100) > 70 / uterineHypersensitivityMod) {
				r.push(`Your hips <span class="change positive">widen</span> to better support your gravidity.`);
				PC.hips += 1;
			} else if (PC.drugs === "hip wideners" && PC.preg > PC.pregData.normalBirth / 1.42 && PC.hips === -2 && PC.hipsImplant === 0 && random(1, 100) > 70 / uterineHypersensitivityMod) {
				r.push(`Your hips <span class="change positive">widen</span> to better support your gravidity.`);
				PC.hips += 1;
			}
			if (PC.preg > PC.pregData.normalBirth / 1.42 && PC.physicalAge >= 12 && buttSize < (4 + (rearQuirk * 3)) && PC.weight >= -30 && random(1, 100) > 70) {
				r.push(`Your butt <span class="change positive">gets a little bigger</span> as your body ripens.`);
				PC.butt += 1;
			}
		}
		if (PC.preg > PC.pregData.normalBirth / 1.42 && PC.vagina >= 0 && PC.vaginaLube < 1 && PC.energy > 20 && random(1, 100) > 80) {
			r.push(`You heard sex tends to be a little wet during pregnancy, and you now know why;`);
			if (random(1, 100) > 75) {
				r.push(`your <span class="change positive">pussy has gotten really moist.</span>`);
				PC.vaginaLube += 1;
			} else {
				r.push(`your pussy <span class="change positive">liberally soaks you, your partner, and your surroundings</span> during any sort of intimacy.`);
				PC.vaginaLube += 2;
			}
		}
		if (PC.preg === PC.pregData.normalBirth / 2.66) { // change me when nipple color gets hardset
			if (PC.pregKnown === 0) {
				r.push(`Your areolae have gotten dark. Some cursory tests reveal <span class="pregnant">you are about fifteen weeks pregnant.</span> How did that manage to slip past you?`);
				PC.pregKnown = 1;
			} else {
				r.push(`Your areolae have gotten dark. Just another step along your pregnancy.`);
			}
		} else if (PC.bellyPreg >= 1500) {
			if (PC.preg > PC.pregData.normalBirth / 2 && PC.lactation === 0) {
				if (PC.preg > random(PC.pregData.normalBirth / 2.22, PC.pregData.normalBirth / 1.33) && PC.health.condition >= -20 && PC.weight > -30) {
					r.push(`A moist sensation on your breasts draws your attention; <span class="change positive">your milk has come in.</span>`);
					PC.lactation = 1;
				}
			}
			if (PC.lactation === 1) { // If natural lactation, constantly refresh it.
				PC.lactationDuration = 2;
			}
		}
	}

	function boobsUpText(bustUp) {
		if (PC.boobs >= 90000) {
			r.push(`It's nearly impossible to tell if your inhuman breasts have gotten larger from your pregnancy, but your nipples sitting further out of reach than ever sure confirms they are.`);
		} else if (PC.boobs >= 25000) {
			r.push(`It's nearly impossible to tell if your obscene breasts are getting larger from your pregnancy, but as your nipples slowly become harder to reach, you can't deny their growth.`);
		} else if (PC.boobs >= 15000) {
			r.push(`It may be difficult to gauge growth in breasts as enormous as yours, but your back can sure feel <span class="change positive">the extra weight on your chest</span> caused by your pregnancy.`);
		} else if (PC.boobs >= 7500) {
			r.push(`It may be difficult to gauge growth in breasts as large as yours, but you can still feel <span class="change positive">the extra weight on your chest</span> caused by your pregnancy.`);
		} else if (PC.boobs >= 3950) {
			r.push(`Like the cow you are, your udders <span class="change positive">have gotten even larger</span> with your pregnancy.`);
		} else if (PC.boobs >= 1400) {
			r.push(`Unsurprisingly, your cow tits <span class="change positive">have swollen even larger</span> with your pregnancy.`);
		} else if (PC.boobs >= 1200) {
			r.push(`Your already huge breasts have <span class="change positive">grown even heavier</span> with your pregnancy.`);
		} else if (PC.boobs >= 1000) {
			r.push(`Your already large breasts have <span class="change positive">grown even larger</span> with your pregnancy.`);
		} else if (PC.boobs >= 800) {
			r.push(`Your breasts have <span class="change positive">grown a bit larger</span> to feed your coming ${child}.`);
		} else if (PC.boobs >= 650) {
			r.push(`Your breasts have <span class="change positive">grown a bit larger</span> to feed your coming ${child}.`);
		} else if (PC.boobs >= 500) {
			r.push(`Your breasts have <span class="change positive">grown a bit larger</span> to feed your coming ${child}.`);
		} else if (PC.boobs >= 400) {
			r.push(`Your breasts have <span class="change positive">gotten heavier</span> alongside your pregnancy.`);
		} else if (PC.boobs >= 300) {
			r.push(`Your breasts have <span class="change positive">swollen</span> alongside your pregnancy.`);
		} else {
			r.push(`Your chest <span class="change positive">has filled out slightly</span> with your pregnancy.`);
		}
		PC.boobs += bustUp;
		r.push(App.EndWeek.Player.bustUp(PC, oldBoobs));
	}

	function failSafe() {
		PC.pregType = setPregType(PC);
		WombImpregnate(PC, PC.pregType, PC.pregSource, PC.preg);
	}

	function preconception() {
		if (isFertile(PC)) { // && PC.pregMood === 5
			needToBreed();
		}
		if (canGetPregnant(PC)) {
			impregnation();
		}
		if (PC.ovaImplant === OvaryImplantType.ASEXUAL && isFertile(PC) && (PC.preg === 0 || (PC.preg >= 0 && PC.geneticQuirks.superfetation === 2))) {
			autoImpregnation();
		}
	}

	function needToBreed() {
		// Empty for now. Will be used for "breeder" .pregMood.
	}

	function impregnation() {
		if (PC.vagina === 0 || (PC.anus === 0 && PC.mpreg > 0)) {
			// You aren't putting out.
			if (PC.geneMods.aggressiveSperm === 1) {
				// But ejaculating with the sperm mod can result in splashback. More sex, more chances.
				if (random(1, 100) > (99 - (PC.energy / 2))) {
					tryKnockMeUp(PC, 0, 2, PC); // 0% chance is correct. Gene mod adds 75% in tryKnockMeUp().
				}
			}
		} else if (random(1, 100) > (70 - (V.reproductionFormula * 10))) {
			/** @type {Map<FC.Assignment, number>} */
			const assignmentWeight = new Map([
				[Job.CONCUBINE, 7],
				[Job.MASTERSUITE, 4],
				[Job.FUCKTOY, 3],
				[Job.HOUSE, 1],
				[Job.QUARTER, 1],
				[Job.MILKED, 1],
				[Job.BODYGUARD, 1],
				[Job.HEADGIRL, 1],
				[Job.RECRUITER, 1],
				[Job.MATRON, 1],
				[Job.NURSERY, 1],
				[Job.ATTENDANT, 1],
				[Job.STEWARD, 1],
				[Job.TEACHER, 1]
			]);
			const undesirableRace = (s) => (FutureSocieties.isActive('FSSupremacist') && (s.race !== V.arcologies[0].FSSupremacistRace)) ||
				(FutureSocieties.isActive('FSSubjugationist') && (s.race === V.arcologies[0].FSSubjugationistRace));
			const raceIsAcceptable = (s) => !undesirableRace(s) ||
				(s.relationship === -3) ||
				[Job.CONCUBINE, Job.MASTERSUITE, Job.FUCKTOY].includes(s.assignment);
			const score = (/** @type {App.Entity.SlaveState} */s) => {
				let weight = (assignmentWeight.get(s.assignment) || 0);
				if (s.relationship === -3 && isSlaveAvailable(s)) { // assumes player will seek relations with slavewife if available
					weight += 3;
				}
				if (onBedRest(PC) && weight < 3) {
					weight = 0;
				}
				if (s.geneMods.aggressiveSperm === 1) { // Doing it with someone with the sperm mod is pretty much going to have them knock you up.
					weight *= 20;
				}

				return weight;
			};

			let eligibleSlaves;
			if (V.policies.sexualOpenness === 1) {
				eligibleSlaves = V.slaves.filter(s => canImpreg(V.PC, s) && App.Utils.sexAllowed(V.PC, s) && isSlaveAvailable(s) && canAchieveErection(s) && s.devotion > 20 && raceIsAcceptable);
			} else {
				eligibleSlaves = V.slaves.filter(s => canImpreg(V.PC, s) && isSlaveAvailable(s) && s.toyHole === ToyHole.DICK);
			}
			const dadHash = eligibleSlaves.reduce((acc, cur, i) => Object.assign(acc, {[i]: score(cur)}), {});
			const chosenDadIndex = hashChoice(dadHash);
			if (chosenDadIndex) {
				tryKnockMeUp(PC, 100, 2, eligibleSlaves[chosenDadIndex]);
			}
		}
		if (canGetPregnant(PC) && !onBedRest(PC, true) && !isPCCareerInCategory("servant")) {
			// Sperm mod leavings around the penthouse. Gives servants more of a point too.
			let slobs = V.slaves.filter(s => isSlaveAvailable(s) && s.geneMods.aggressiveSperm === 1 && (s.fetish === Fetish.MINDBROKEN || s.energy > 95 || (s.devotion < -20 && s.trust > 20) || (s.intelligence + s.intelligenceImplant < -10)));
			if (slobs.length > (totalServantCapacity() / 5)) {
				tryKnockMeUp(PC, -50, 2, slobs.random());
			}
		}
	}

	function autoImpregnation() {
		tryKnockMeUp(PC, 100, 2, PC);
		if (PC.geneticQuirks.superfetation === 2 && PC.pregKnown === 1) {
			if (V.geneticMappingUpgrade === 0 && PC.counter.birthsTotal === 0) {
				r.push(`You are wracked with frequent spontaneous orgasms from your asexual reproduction modifications despite already being pregnant.`);
			} else {
				r.push(`Your asexual reproduction modifications don't care that you've already got a bun in the oven, a fact made clear as they force you into adding yet another child into your increasingly crowded womb. At this rate, you will spend the rest of your fertile years as a constantly pregnant broodmother.`);
			}
		} else {
			r.push(`Your asexual reproduction modifications leaves you writhing in constant orgasm for a short time. You are only released once you've <span class="pregnant">thoroughly impregnated yourself.</span>`);
			PC.pregKnown = 1;
		}
	}

	function pregnancySanityCheck() { // PREGNANCY TYPE SANITY CHECK (not for pregnancies started above)
		if (PC.preg <= 0) {
			if (PC.pregType !== 0) {
				WombFlush(PC);
			}
		} else if (PC.preg > 0 && PC.pregType === 0) {
			PC.pregType = setPregType(PC);
			WombImpregnate(PC, PC.pregType, PC.pregSource, 1);
		}
		if (PC.readyOva !== 0) {
			PC.readyOva = 0;
		}
	}
};

repo_name: Ducati/fc

license: mit


code:
/**
 * @returns {FC.EndWeek.FacilityReport}
 */
App.EndWeek.arcadeReport = function() {
	const beforeFrag = new DocumentFragment();
	let r;

	const arcadeStats = document.createElement("span");
	beforeFrag.append(arcadeStats);

	const slaves = App.Utils.sortedEmployees(App.Entity.facilities.arcade);
	const slavesLength = slaves.length;

	const cockMilkedSlaves = [];
	const milkedSlaves = [];
	const boobsImplantedSlaves = [];
	const prostatesImplantedSlaves = [];
	let vasectomiesUndone = 0;
	let milkProfits = 0;
	let profits = 0;

	// Statistics gathering
	V.facility = V.facility || {};
	V.facility.arcade = initFacilityStatistics(V.facility.arcade);
	const arcadeNameCaps = capFirstChar(V.arcadeName);

	if (slavesLength > 1) {
		App.UI.DOM.appendNewElement("p", beforeFrag, `There are ${slavesLength} inmates confined in ${V.arcadeName}.`, ["bold", "indent"]);
	} else {
		App.UI.DOM.appendNewElement("p", beforeFrag, `There is one inmate confined in ${V.arcadeName}.`, ["bold", "indent"]);
	}
	r = [];
	if (V.arcologies[0].FSDegradationist > 20) {
		if (V.arcologies[0].FSDegradationistLaw === 1) {
			r.push(`The tenants located near the arcade consider the facility a normal part of their surroundings, including the crowd of menial slaves waiting their turn spills out into the hallway, 24 hours a day.`);
		} else {
			r.push(`The tenants located near the arcade consider the facility a normal part of their surroundings.`);
		}
	} else if (V.arcologies[0].FSPaternalist > 20) {
		r.push(`The tenants located near the arcade consider it an <span class="red">intolerable</span> establishment.`);
	}
	App.Events.addNode(beforeFrag, r, "div", "indent");
	if (V.arcadeDecoration !== "standard") {
		App.Events.addNode(beforeFrag, [`${arcadeNameCaps}'s customers enjoy <span class="green">getting off in ${V.arcadeDecoration} surroundings.</span>`], "p", "indent");
	}

	/**
	 * @type {Array<FC.EndWeek.SlaveReport>}
	 */
	const slaveReports = [];

	for (const slave of App.SlaveAssignment.reportSlaves(slaves)) {
		r = [];
		/* for the included passages */

		/* Perform facility based rule changes */
		if (slave.clothes !== "a Fuckdoll suit") {
			slave.clothes = "no clothing";
		}
		/* Health */
		if (V.arcadeUpgradeHealth === 2 && slave.health.condition < 40) {
			improveCondition(slave, 2);
		} else if (slave.health.condition > 20) {
			healthDamage(slave, 5);
		} else if (V.arcadeUpgradeHealth === 1 && slave.health.condition < -30) {
			improveCondition(slave, 2);
		} else if (slave.health.condition > -50) {
			healthDamage(slave, 3);
		} else if (slave.health.condition > -90) {
			healthDamage(slave, 1);
		}
		/* Curatives */
		if (V.arcadeUpgradeHealth === 2) {
			slave.curatives = 2;
		} else if (V.arcadeUpgradeHealth === 1) {
			slave.curatives = 1;
		}
		/* Stimulation or lack thereof trust/devotion effect */
		if (V.arcadeUpgradeInjectors > 0) {
			if (V.arcadeUpgradeInjectors === 2) {
				slave.aphrodisiacs = 2;
			}
			slave.devotion -= 5;
			slave.trust -= 10;
		} else {
			slave.trust -= 5;
		}
		/* Muscles */
		if (slave.muscles > -100) {
			slave.muscles--;
		}
		const oldCash = V.cash;
		if ((V.favSeparateReport === 1 && V.favorites.includes(slave.ID)) || V.showEWD !== 0) {
			const {He} = getPronouns(slave);
			const slaveEntry = App.UI.DOM.makeElement("div", null, ["slave-report"]);
			const artSpan = App.UI.DOM.appendNewElement("span", slaveEntry);
			slaveEntry.append(App.SlaveAssignment.saSlaveIntro(slave, `is confined in ${V.arcadeName}.`));

			App.Events.addNode(
				slaveEntry,
				[
					He,
					App.SlaveAssignment.workAGloryHole(slave),
				],
				"div",
				"indent"
			);
			App.SlaveAssignment.appendSlaveArt(artSpan, slave);

			profits += V.cash - oldCash;

			if (V.arcadeUpgradeCollectors > 0) {
				applyCollectors(slave);
			}
			if (slave.inflation > 0) {
				deflate(slave);
			}

			slaveEntry.append(App.SlaveAssignment.standardSlaveReport(slave, false));

			slaveReports.push({
				id: slave.ID,
				report: slaveEntry
			});
		} else {
			// discard return values silently
			App.SlaveAssignment.workAGloryHole(slave);

			profits += V.cash - oldCash;

			if (V.arcadeUpgradeCollectors > 0) {
				applyCollectors(slave);
			}
			if (slave.inflation > 0) {
				deflate(slave);
			}

			App.SlaveAssignment.standardSlaveReport(slave, true);
		}
	}

	const afterFrag = new DocumentFragment();

	if (slavesLength + V.fuckdolls > 0) {
		r = [];
		if (milkedSlaves.length > 0) {
			if (milkedSlaves.length === 1) {
				const {his} = getPronouns(milkedSlaves[0]);
				r.push(`One of them is lactating and spends ${his} time in ${V.arcadeName} being simultaneously milked and fucked.`);
			} else {
				r.push(`${capFirstChar(num(milkedSlaves.length))} of them are lactating and spend their time in ${V.arcadeName} being simultaneously milked and fucked.`);
			}
		}

		if (vasectomiesUndone > 0) {
			if (vasectomiesUndone === 1) {
				r.push(`One`);
			} else {
				r.push(capFirstChar(num(vasectomiesUndone)));
			}
			r.push(`of them had severed vas deferens, so they were reattached to allow sperm through, costing <span class="red">${cashFormat(V.surgeryCost * vasectomiesUndone)}.</span>`);
		}

		if (boobsImplantedSlaves.length > 0) {
			if (boobsImplantedSlaves.length === 1) {
				const {he} = getPronouns(boobsImplantedSlaves[0]);
				r.push(`One of them was not lactating, so ${he} was`);
			} else {
				r.push(`${capFirstChar(num(boobsImplantedSlaves.length))} of them were not lactating, so they were`);
			}
			r.push(`implanted with long-acting lactation inducing drugs, costing <span class="red">${cashFormat(V.surgeryCost * boobsImplantedSlaves.length)}.</span>`);
		}

		if (prostatesImplantedSlaves.length > 0) {
			if (prostatesImplantedSlaves.length === 1) {
				const {he} = getPronouns(prostatesImplantedSlaves[0]);
				r.push(`One of them was not producing the maximum possible amount of precum, so ${he} was`);
			} else {
				r.push(`${capFirstChar(num(prostatesImplantedSlaves.length))} of them were not producing the maximum possible amount of precum, so they were`);
			}
			r.push(`implanted with long-acting prostate stimulation drugs, costing <span class="red">${cashFormat(V.surgeryCost * prostatesImplantedSlaves.length)}.</span>`);
		}

		if (cockMilkedSlaves.length > 0) {
			if (cockMilkedSlaves.length === 1) {
				const {he} = getPronouns(cockMilkedSlaves[0]);
				r.push(`One of them retains testicles and is brutally cockmilked as ${he} is used.`);
			} else {
				r.push(`${capFirstChar(num(cockMilkedSlaves.length))} of them retain testicles and are brutally cockmilked as they are used.`);
			}
		}

		r.push(`The arcade makes you`);
		if (V.policies.publicFuckdolls === 0) {
			r.push(`<span class="yellowgreen">${cashFormat(profits)}</span> from selling the inmates' holes`);
		} else {
			r.push(`<span class="green">more reputable</span> from freely providing the inmates' holes`);
		}
		if (V.arcadeUpgradeCollectors > 0 && V.policies.publicFuckdolls === 0) {
			r.push(`and`);
		}
		if (V.arcadeUpgradeCollectors > 0) {
			r.push(`<span class="yellowgreen">${cashFormat(milkProfits)}</span> from selling the fluids they produced`);
		}
		r.push(`this week.`);
		if (V.arcologies[0].FSPaternalist > 20) {
			repX(forceNeg(Math.trunc(profits / 20)), "arcade");
		}
		App.Events.addNode(afterFrag, r, "div", "indent");
	}

	if (V.arcadeUpgradeFuckdolls > 1) {
		const fuckdolls = slaves.filter(s => fuckdollQualifier(s));
		if (fuckdolls.length > 0) {
			// ascending sort by sexAmount...least popular slaves are converted first
			fuckdolls.sort((a, b) => b.sexAmount - a.sexAmount);
			for (const fuckdoll of fuckdolls) {
				const {he} = getPronouns(fuckdoll);
				App.UI.DOM.appendNewElement("div", afterFrag, `${fuckdoll.slaveName} is low-quality merchandise, so ${he} has been converted into a Fuckdoll.`, "indent");
				removeSlave(fuckdoll);
				V.fuckdolls++;
				if (V.arcadeUpgradeFuckdolls === 2) {
					break; // convert at most one per week on this setting
				}
			}
		} else {
			App.UI.DOM.appendNewElement("div", afterFrag, `No slaves have failed quality inspection for Fuckdoll conversion. ${arcadeNameCaps} will remain overcrowded this week.`, "indent");
		}
	}

	if (slavesLength > 0) {
		// Record statistics gathering
		let b = V.facility.arcade;
		b.whoreIncome = 0;
		b.customers = 0;
		b.whoreCosts = 0;
		b.rep = 0;
		for (let si of b.income.values()) {
			b.whoreIncome += si.income;
			b.customers += si.customers;
			b.whoreCosts += si.cost;
			b.rep += si.rep;
		}
		b.maintenance = V.arcade * V.facilityCost * (0.05 + 0.02 * V.arcadeUpgradeInjectors + 0.05 * V.arcadeUpgradeCollectors);
		b.totalIncome = b.whoreIncome;
		b.totalExpenses = b.whoreCosts + b.maintenance;
		b.profit = b.totalIncome - b.totalExpenses;

		// Arcade stats
		afterFrag.append(App.Facilities.Arcade.Stats(false));
		arcadeStats.append(App.Facilities.Arcade.Stats(true));
	}

	return {
		before: beforeFrag,
		slaves: slaveReports,
		after: afterFrag,
	};

	/**
	 *
	 * @param {App.Entity.SlaveState} slave
	 */
	function fuckdollQualifier(slave) {
		if (slave.sentence === 0 && slave.fuckdoll === 0 && slave.fetish === Fetish.MINDBROKEN) {
			if (slave.physicalAge > 35) {
				return true;
			} else if (slave.vagina >= 4 || slave.anus >= 4) {
				return true;
			}
		}
	}

	/**
	 * @param {App.Entity.SlaveState} slave
	 * @returns {DocumentFragment}
	 */
	function applyCollectors(slave) {
		const f = new DocumentFragment();
		if (slave.vasectomy === 1) {
			slave.vasectomy = 0;
			vasectomiesUndone++;
			cashX(forceNeg(V.surgeryCost), "slaveSurgery", slave);
			surgeryDamage(slave, 10);
		} else if (slave.lactation < 2) {
			slave.lactation = 2;
			boobsImplantedSlaves.push(slave);
			cashX(forceNeg(V.surgeryCost), "slaveSurgery", slave);
			surgeryDamage(slave, 10);
		} else if (slave.prostate === 1) {
			slave.prostate = 2;
			prostatesImplantedSlaves.push(slave);
			cashX(forceNeg(V.surgeryCost), "slaveSurgery", slave);
			surgeryDamage(slave, 10);
		} else if (slave.lactation > 0 || slave.balls > 0) {
			const {He} = getPronouns(slave);
			const milkResults = App.SlaveAssignment.getMilked(slave, 1.0);
			App.Events.addNode(f, [He, milkResults.text], "div", "indent");
			milkProfits += milkResults.cash;
			slave.boobs += boobGrowth(slave);
			if (
				slave.balls.isBetween(0, 10) &&
				(random(1, 100) > (40 + (10 * (slave.balls + (2 * slave.geneMods.NCS)))))
			) {
				slave.balls++;
			}
			if (
				(slave.dick > 0) &&
				(slave.dick < 10) &&
				(random(1, 100) > (40 + (10 * slave.dick + (2 * slave.geneMods.NCS))))
			) {
				slave.dick++;
			}
			if (slave.lactation > 0) {
				milkedSlaves.push(slave);
			}
			if (slave.balls > 0) {
				cockMilkedSlaves.push(slave);
			}
		}
		return f;
	}

	/**
	 * @param {App.Entity.SlaveState} slave
	 * @returns {number}
	 */
	function boobGrowth(slave) {
		let growth = 0;
		const gigantomastiaMod = slave.geneticQuirks.gigantomastia === 2 ? (slave.geneticQuirks.macromastia === 2 ? 3 : 2) : 1;
		if (slave.boobs < 2000) {
			growth = 100;
		} else if (slave.boobs < 5000 * gigantomastiaMod) {
			growth = 50;
		} else if (slave.boobs < 10000 * gigantomastiaMod) {
			growth = 25;
		}
		if (slave.geneMods.NCS === 1) {
			/*
			** NCS will allow some growth for Arcade milking, but not as much as the Dairy.
			*/
			growth = Math.trunc(growth / 3.5);
		}
		return growth;
	}
};


code:
/**
 * @returns {FC.EndWeek.FacilityReport}
 */
App.EndWeek.brothelReport = function() {
	const beforeFrag = document.createElement("p");

	const brothelStats = document.createElement("span");
	beforeFrag.append(brothelStats);

	const madam = S.Madam ? App.SlaveAssignment.reportSlave(S.Madam) : undefined;
	const slaves = App.Utils.sortedEmployees(App.Entity.facilities.brothel);
	const SL = slaves.length;
	let profits = 0;

	// Statistics gathering
	V.facility = V.facility || {};
	V.facility.brothel = initFacilityStatistics(V.facility.brothel);
	const brothelNameCaps = capFirstChar(V.brothelName);

	function madamText() {
		let FLsFetish = 0;
		let r = [];
		if (V.MadamID !== 0) {
			if (S.Madam.health.condition < -80) {
				improveCondition(S.Madam, 20);
			} else if (S.Madam.health.condition < -40) {
				improveCondition(S.Madam, 15);
			} else if (S.Madam.health.condition < 0) {
				improveCondition(S.Madam, 10);
			} else if (S.Madam.health.condition < 90) {
				improveCondition(S.Madam, 7);
			}
			if (S.Madam.devotion <= 45) {
				S.Madam.devotion += 5;
			}
			if (S.Madam.trust < 45) {
				S.Madam.trust += 5;
			}
			if (S.Madam.rules.living !== "luxurious") {
				S.Madam.rules.living = "luxurious";
			}
			if (S.Madam.rules.rest !== "restrictive") {
				S.Madam.rules.rest = "restrictive";
			}
			if (S.Madam.fetishStrength <= 95) {
				if (S.Madam.fetish !== Fetish.DOM) {
					if (fetishChangeChance(S.Madam) > random(0, 100)) {
						FLsFetish = 1;
						S.Madam.fetishKnown = 1;
						S.Madam.fetish = Fetish.DOM;
						S.Madam.fetishStrength = 10;
					}
				} else if (S.Madam.fetishKnown === 0) {
					FLsFetish = 1;
					S.Madam.fetishKnown = 1;
				} else {
					FLsFetish = 2;
					S.Madam.fetishStrength += 4;
				}
			}
			/* Make sure we have registered living expenses as for any other slave */
			getSlaveStatisticData(S.Madam, V.facility.brothel);
			const {
				he, him, his, himself, He, His, wife
			} = getPronouns(S.Madam);

			r = [];
			const popup = App.UI.DOM.referenceSlaveWithPreview(S.Madam, SlaveFullName(S.Madam));

			popup.classList.add("slave-name", "bold");
			r.push(popup, `is serving as the madam.`);

			if (S.Madam.relationship === -3 && S.Madam.devotion > 50) {
				r.push(`As your loving ${wife}, ${he} does ${his} best to attract attention to your brothel.`);
			}
			if (FLsFetish === 1) {
				r.push(`${He} isn't above sampling the merchandise ${himself}; before long it's obvious to ${his} girls that ${he}`);
				r.push(App.UI.DOM.makeElement("span", `really likes fucking them.`, "fetish-gain"));
			} else if (FLsFetish === 2) {
				r.push(`${He}'s careful that all of the whores under ${his} supervision are all warmed up and ready to get fucked every morning, and ${he}`);
				r.push(App.UI.DOM.makeElement("span", `really likes fucking them.`, ["fetish", "inc"]));
			}
			const improve = App.UI.DOM.makeElement("span", "improve", ["cash", "inc"]);
			if (S.Madam.skill.whoring <= 10) {
				r.push(`Though ${S.Madam.slaveName} does ${his} best to manage the brothel, with ${his} lack of skill ${he} can do little.`);
			} else if (S.Madam.skill.whoring <= 30) {
				r.push(`${S.Madam.slaveName}'s basic skills marginally`, improve, `business at ${V.brothelName}.`);
			} else if (S.Madam.skill.whoring <= 60) {
				r.push(`${S.Madam.slaveName}'s skills`, improve, `business at ${V.brothelName}.`);
			} else if (S.Madam.skill.whoring < 100) {
				r.push(`${S.Madam.slaveName}'s skills greatly`, improve, `business at ${V.brothelName}.`);
			} else {
				r.push(`${S.Madam.slaveName}'s mastery immensely`, improve, `business at ${V.brothelName}.`);
			}
			if (S.Madam.actualAge > 35) {
				r.push(`${His} age and experience also contribute.`);
			}
			if (App.Data.Careers.Leader.madam.includes(S.Madam.career)) {
				r.push(`${He} has experience from ${his} life before ${he} was a slave that helps ${him} in the seedy business of selling other people's bodies for sex.`);
			} else if (S.Madam.skill.madam >= Constant.MASTERED_XP) {
				r.push(`${He} has experience from working for you that helps ${him} in the seedy business of selling other people's bodies for sex.`);
			} else if (S.Madam.skill.madam > 120) {
				r.push(`${He} understands how to handle whores while keeping customers happy.`);
			} else if (S.Madam.skill.madam > 60) {
				r.push(`${He} understands how to read the customer and please them effectively.`);
			} else if (S.Madam.skill.madam > 20) {
				r.push(`${He} has basic knowledge of how to run a whorehouse.`);
			}
			if (S.Madam.skill.madam < Constant.MASTERED_XP) {
				const skillIncrease = jsRandom(1, Math.ceil((S.Madam.intelligence + S.Madam.intelligenceImplant) / 15) + 8);
				r.push(slaveSkillIncrease('madam', S.Madam, skillIncrease));
			}
			if (S.Madam.intelligence + S.Madam.intelligenceImplant > 15) {
				r.push(`${He} is a clever manager.`);
			}
			if (S.Madam.dick > 2 && canPenetrate(S.Madam)) {
				if (S.Madam.skill.penetrative > 90) {
					r.push(`${His} skilled dick incentivizes the bitches to behave.`);
				} else if (S.Madam.skill.penetrative > 10) {
					r.push(`${His} turgid dick helps ${him} manage the bitches.`);
				} else {
					r.push(`${He} tries to use ${his} turgid cock to keep the bitches in line, but ${his} lack of skill only leaves them off kilter.`);
				}
				slaveSkillIncrease('penetrative', S.Madam, 2);
			}
			App.Events.addParagraph(beforeFrag, r);

			r = [];
			for (const slave of slaves) {
				const {
					he2, him2, his2
				} = getPronouns(slave).appendSuffix('2');

				if (S.Madam.rivalryTarget === slave.ID) {
					r.push(`${He} forces ${his} ${rivalryTerm(S.Madam)}, ${slave.slaveName}, to service all the men in the brothel.`);
					slave.devotion -= 2;
					slave.trust -= 2;
					if (canDoVaginal(slave)) {
						seX(slave, "vaginal", "public", "penetrative", 10);
					}
					if (canDoAnal(slave)) {
						seX(slave, "anal", "public", "penetrative", 12);
					}
					seX(slave, "anal", "public", "penetrative", 10);
					if (random(1, 100) > 65) {
						S.Madam.rivalry++;
						slave.rivalry++;
					}
				} else if (S.Madam.relationshipTarget === slave.ID) {
					r.push(`${He} dotes over ${his} ${relationshipTerm(S.Madam)}, ${slave.slaveName}, making sure ${he2} is safe, but unfortunately driving potential customers away from ${him2}.`);
					slave.devotion++;
				} else if (areRelated(S.Madam, slave)) {
					r.push(`${He} pays special attention to ${his} ${relativeTerm(S.Madam, slave)}, ${slave.slaveName}, making sure ${he2} is treated well and showing off ${his2} skills.`);
					slave.trust++;
				}
				if (slave.prestigeDesc === "$He is a famed Free Cities whore, and commands top prices.") {
					r.push(`${He} makes sure to promote ${slave.slaveName}, the famed whore, in order to capitalize on ${his2} popularity.`);
				} else if (slave.prestigeDesc === "$He is a famed Free Cities slut, and can please anyone.") {
					r.push(`${He} makes sure to promote ${slave.slaveName}, the famed entertainer, in order to capitalize on ${his2} popularity.`);
				} else if (slave.prestigeDesc === "$He is remembered for winning best in show as a dairy cow.") {
					if (FutureSocieties.isActive('FSPhysicalIdealist')) {
						if (slave.muscles > 60 && slave.weight < 30 && slave.lactation > 0 && (slave.boobs - slave.boobsImplant) > 6000) {
							r.push(`${He} shows off how even a cow like ${slave.slaveName} can achieve physical perfection.`);
						} else {
							if (slave.muscles < 30) {
								r.push(`An unmuscled,`);
							} else {
								r.push(`A`);
							}
							if (slave.weight > 30) {
								r.push(`fat,`);
							}
							r.push(`'prestigious'`);
							if (slave.lactation > 0) {
								r.push(`cow`);
							} else if ((slave.boobs - slave.boobsImplant) > 6000) {
								r.push(`mass of titflesh`);
							} else {
								r.push(`slave`);
							}
							r.push(`like ${slave.slaveName} is woefully out of fashion, so ${S.Madam.slaveName} tries to draw attention away from ${him2}.`);
						}
					} else {
						if (slave.lactation > 0 && (slave.boobs - slave.boobsImplant) > 6000) {
							r.push(`${He} makes sure to massage ${slave.slaveName}'s huge breasts to get the milk flowing before enticing clients to suckle and play with ${him2}.`);
						} else {
							r.push(`${He} would like to show off ${slave.slaveName}'s huge udders, but ${slave.slaveName}`);
							if (slave.lactation === 0) {
								r.push(`isn't producing milk anymore.`);
							} else {
								r.push(`doesn't exactly have huge udders anymore.`);
							}
						}
					}
				} else if (slave.prestigeDesc === "$He is remembered for winning best in show as a cockmilker.") {
					if (FutureSocieties.isActive('FSGenderFundamentalist')) {
						/* this needs review - doesn't fit right. An XY slave would be expected to be masculine. */
						if (slave.balls === 0 && slave.dick === 0 && slave.vagina > -1) {
							r.push(`${He} uses ${slave.slaveName} as an example of how even a huge-balled freak like ${him2} can be restored to proper femininity.`);
						} else {
							r.push(`${He} tries to hide ${slave.slaveName}, 'her' body being notorious for its defiance of conventional femininity.`);
						}
					} else {
						if (((slave.balls > 5) && (slave.dick !== 0)) || ((slave.balls > 4) && (slave.dick !== 0) && (slave.prostate > 1))) {
							r.push(`${He} shows off ${slave.slaveName}'s copious loads by putting a condom over ${his2} dick and teasing ${him2} till ${he2} bursts it. The show draws multiple clients that want to play with ${his2} oversized junk and messy orgasms.`);
						} else {
							r.push(`${He} would love to show off ${slave.slaveName}'s copious loads, but`);
							if (slave.dick === 0) {
								r.push(`${slave.slaveName} doesn't have a dick.`);
							} else if (slave.balls === 0) {
								r.push(`${slave.slaveName}'s not producing cum.`);
							} else {
								r.push(`${slave.slaveName}'s orgasms just aren't messy enough.`);
							}
						}
					}
				} else if (slave.prestigeDesc === "$He is remembered for winning best in show as a breeder.") {
					if (slave.bellyPreg >= 5000) {
						r.push(`${He} makes sure ${slave.slaveName}'s growing pregnancy is well taken care of, even if it means driving away potential customers away when the mother-to-be needs a rest.`);
					} else if (canGetPregnant(slave)) {
						r.push(`${He} makes sure to play off ${slave.slaveName}'s fame and fertility by enticing potential customers to be the one to claim ${his2} womb by filling it with their child.`);
					} else {
						r.push(`${He} would love to play off of ${slave.slaveName}'s fame and fertility, but unfortunately ${he2}`);
						if (slave.pregKnown === 1 && slave.bellyPreg < 1500) {
							r.push(`is already pregnant and not far enough along to show it.`);
						} else if (slave.pregKnown === 1 && slave.bellyPreg < 5000) {
							r.push(`already pregnant, but not enough to be exciting.`);
						} else {
							r.push(`is unable to get knocked up.`);
						}
					}
				}
			}
			App.Events.addNode(beforeFrag, r);

			if ((SL + V.brothelSlavesGettingHelp < 10 * App.SlaveAssignment.PartTime.efficiencyModifier(madam)) &&
				V.MadamNoSex !== 1 && !slaveResting(madam)) {
				const oldCash = V.cash;
				if ((V.favSeparateReport === 1 && V.favorites.includes(madam.ID)) || V.showEWD !== 0) {
					App.Events.addParagraph(
						beforeFrag,
						[
							He,
							App.SlaveAssignment.whore(madam)
						]
					);
				} else {
					App.SlaveAssignment.whore(madam);
				}
				App.Events.addParagraph(
					beforeFrag,
					[
						`${He} whores ${himself} because ${he} doesn't have enough whores to manage to keep ${him} busy, and makes`,
						App.UI.DOM.makeElement("span", `${cashFormat(S.Madam.lastWeeksCashIncome)}.`, ["cash", "inc"]),
						`${He} can charge more for ${his} time, since many citizens find it erotic to fuck the Madam.`
					]
				);
				profits += V.cash - oldCash;
			}
		}
	}

	madamText();

	if (SL > 0) {
		const whoreNumber = document.createElement("p");
		whoreNumber.classList.add("indent", "bold");

		if (SL === 1) {
			whoreNumber.append(`There is one slave whore working out of ${V.brothelName}.`);
		} else {
			whoreNumber.append(`There are ${SL} slave whores working out of ${V.brothelName}.`);
		}
		beforeFrag.append(whoreNumber);
	}

	/** @type {Array<FC.EndWeek.SlaveReport>} */
	const slaveReports = [];

	if (madam) {
		tired(madam);
		if ((V.favSeparateReport === 1 && V.favorites.includes(madam.ID)) || V.showEWD) {
			const madamEntry = App.UI.DOM.makeElement("div", '', ["slave-report"]);
			const artSpan = App.UI.DOM.appendNewElement("span", madamEntry);
			madamEntry.append(App.SlaveAssignment.saSlaveIntro(madam, `is serving as the Madam.`));
			madamEntry.append(App.SlaveAssignment.standardSlaveReport(madam, false));
			App.SlaveAssignment.appendSlaveArt(artSpan, madam);
			slaveReports.push({
				id: madam.ID,
				report: madamEntry,
			});
		} else {
			App.SlaveAssignment.standardSlaveReport(madam, true);
		}
	}

	const afterFrag = new DocumentFragment();

	if (SL > 0) {
		let healthBonus = 0;
		let aphrodisiacs = 0;
		if (V.brothelUpgradeDrugs === 1) {
			healthBonus += 1;
			aphrodisiacs = 1;
		} else if (V.brothelUpgradeDrugs === 2) {
			healthBonus += 3;
			aphrodisiacs = 2;
		}
		let oldCash = V.cash;
		for (const slave of App.SlaveAssignment.reportSlaves(slaves)) {
			/* Perform facility based rule changes */
			improveCondition(slave, healthBonus);
			slave.aphrodisiacs = aphrodisiacs;
			switch (V.brothelDecoration) {
				case "Degradationist":
				case "standard":
					slave.rules.living = "spare";
					break;
				default:
					slave.rules.living = "normal";
			}
			if (slave.health.condition < -80) {
				improveCondition(slave, 20);
			} else if (slave.health.condition < -40) {
				improveCondition(slave, 15);
			} else if (slave.health.condition < 0) {
				improveCondition(slave, 10);
			} else if (slave.health.condition < 90) {
				improveCondition(slave, 7);
			}
			if (slave.devotion <= 20 && slave.trust >= -20) {
				slave.devotion -= 5;
				slave.trust -= 5;
			} else if (slave.devotion < 45) {
				slave.devotion += 4;
			} else if (slave.devotion > 50) {
				slave.devotion -= 4;
			}
			if (slave.trust < 30) {
				slave.trust += 5;
			}
			if (slave.energy.isBetween(40, 95)) {
				slave.energy++;
			}

			if (V.showEWD || (V.favSeparateReport === 1 && V.favorites.includes(slave.ID))) {
				const {He} = getPronouns(slave);
				const slaveEntry = App.UI.DOM.makeElement("div", null, ["slave-report"]);
				const artSpan = App.UI.DOM.appendNewElement("span", slaveEntry);
				slaveEntry.append(App.SlaveAssignment.saSlaveIntro(slave, `is working out of ${V.brothelName}.`));

				App.Events.addNode(
					slaveEntry,
					[
						He,
						App.SlaveAssignment.whore(slave),
					],
					"div",
					"indent"
				);
				slaveEntry.append(App.SlaveAssignment.standardSlaveReport(slave, false));
				App.SlaveAssignment.appendSlaveArt(artSpan, slave);

				slaveReports.push({
					id: slave.ID,
					report: slaveEntry,
				});
			} else {
				// discard return values silently
				App.SlaveAssignment.whore(slave);
				App.SlaveAssignment.standardSlaveReport(slave, true);
			}

			const seed = Math.max(App.Ads.getMatchedCategoryCount(slave, "brothel"), 1);
			const adsIncome = seed * random(50, 60) * Math.trunc(V.brothelAdsSpending / 1000);
			getSlaveStatisticData(slave, V.facility.brothel).adsIncome += adsIncome;
			cashX(adsIncome, "brothelAds");
		}

		App.Events.addNode(afterFrag, [App.Ads.report("brothel", false)]);

		profits += V.cash - oldCash;

		// Record statistics gathering
		const b = V.facility.brothel;
		b.whoreIncome = 0;
		b.customers = 0;
		b.whoreCosts = 0;
		b.rep = 0;
		const oldAdIncome = b.adsIncome;
		for (const si of b.income.values()) {
			b.whoreIncome += si.income + si.adsIncome;
			b.adsIncome += si.adsIncome;
			b.customers += si.customers;
			b.whoreCosts += si.cost;
			b.rep += si.rep;
		}
		b.adsCosts = V.brothelAdsSpending;
		b.maintenance = V.brothel * V.facilityCost * (1.0 + 0.2 * V.brothelUpgradeDrugs);
		b.totalIncome = b.whoreIncome + oldAdIncome;
		b.totalExpenses = b.whoreCosts + b.adsCosts + b.maintenance;
		b.profit = b.totalIncome - b.totalExpenses;

		App.Events.addNode(
			afterFrag,
			[
				`${brothelNameCaps} makes you`,
				App.UI.DOM.makeElement("span", cashFormat(profits), ["cash", "inc"]),
				`this week.`
			]
		);

		if (V.brothelDecoration !== "standard") {
			App.Events.addParagraph(
				afterFrag,
				[
					`${brothelNameCaps}'s customers enjoyed`,
					App.UI.DOM.makeElement("span", `fucking whores in ${V.brothelDecoration} surroundings.`,
						["reputation", "inc"])
				]
			);
		}

		// Brothel stats
		afterFrag.append(App.Facilities.Brothel.Stats(false));
		brothelStats.append(App.Facilities.Brothel.Stats(true));
	}
	return {
		before: beforeFrag,
		slaves: slaveReports,
		after: afterFrag,
	};
};


code:
/**
 * @returns {FC.EndWeek.FacilityReport}
 */
App.EndWeek.cellblockReport = function() {
	const beforeFrag = new DocumentFragment();
	let r = [];

	const slaves = App.Utils.sortedEmployees(App.Entity.facilities.cellblock);
	let brokenSlaves = 0;
	let idleBonus = 0;
	let softenedQuirks = 0;
	let trustMalus = 0;
	let FLsFetish = 0;
	let devBonus = (V.cellblockDecoration !== "standard") ? 1 : 0;
	let confinedResults;

	const cellblockNameCaps = capFirstChar(V.cellblockName);
	App.EndWeek.saVars.flSex = App.EndWeek.getFLSex(App.Entity.facilities.cellblock);

	if (S.Wardeness) {
		const {
			He, His,
			he, his, him, wife
		} = getPronouns(S.Wardeness);
		r = [];

		if (S.Wardeness.health.condition < -80) {
			improveCondition(S.Wardeness, 20);
		} else if (S.Wardeness.health.condition < -40) {
			improveCondition(S.Wardeness, 15);
		} else if (S.Wardeness.health.condition < 0) {
			improveCondition(S.Wardeness, 10);
		} else if (S.Wardeness.health.condition < 90) {
			improveCondition(S.Wardeness, 7);
		}
		if (S.Wardeness.devotion <= 60) {
			S.Wardeness.devotion += 2;
		}
		S.Wardeness.devotion += devBonus;
		if (S.Wardeness.trust < 60) {
			S.Wardeness.trust += 3;
		}
		if (S.Wardeness.rules.living !== "luxurious") {
			S.Wardeness.rules.living = "luxurious";
		}
		if (S.Wardeness.rules.rest !== "restrictive") {
			S.Wardeness.rules.rest = "restrictive";
		}
		if (S.Wardeness.fetishStrength <= 95) {
			if (S.Wardeness.fetish !== Fetish.SADIST) {
				if (fetishChangeChance(S.Wardeness) > random(0, 100)) {
					FLsFetish = 1;
					S.Wardeness.fetishKnown = 1;
					S.Wardeness.fetish = Fetish.SADIST;
					S.Wardeness.fetishStrength = 10;
				}
			} else if (S.Wardeness.fetishKnown === 0) {
				FLsFetish = 1;
				S.Wardeness.fetishKnown = 1;
			} else {
				FLsFetish = 2;
				S.Wardeness.fetishStrength += 4;
			}
		}
		if (S.Wardeness.energy > 95 || S.Wardeness.fetish === Fetish.SADIST) {
			devBonus++;
			trustMalus++;
			idleBonus++;
		}
		const popup = App.UI.DOM.slaveDescriptionDialog(S.Wardeness, SlaveFullName(S.Wardeness));
		popup.classList.add("slave-name", "bold");
		r.push(popup, `is serving as the Wardeness.`);

		if (S.Wardeness.relationship === -3 && S.Wardeness.devotion > 50) {
			devBonus++;
			trustMalus++;
			idleBonus++;
			r.push(`As your ${wife}, ${he} tries ${his} best to break the disobedient slaves to your will.`);
		}
		if (FLsFetish === 1) {
			r.push(`One day ${he} demands obedience. The next day ${he} strikes a slave when it isn't given. The next, ${he} seems more excited than embarrassed when beating a prisoner. Soon, ${he}'s looking for an excuse to punish. ${He}'s become more of a sadist.`);
		} else if (FLsFetish === 2) {
			r.push(`Being not only allowed but encouraged to get off while punishing prisoners <span class="lightsalmon">deepens ${his} sadism.</span>`);
		}
		if (App.Data.Careers.Leader.wardeness.includes(S.Wardeness.career)) {
			devBonus++;
			trustMalus++;
			idleBonus++;
			r.push(`${He} has experience with detecting security issues and grinding down potential miscreants from ${his} life before ${he} was a slave, making ${him} more effective.`);
		} else if (S.Wardeness.skill.wardeness >= Constant.MASTERED_XP) {
			devBonus++;
			trustMalus++;
			idleBonus++;
			r.push(`${He} has experience with detecting security issues and grinding down potential miscreants from working for you, making ${him} more effective.`);
		} else {
			const skillIncrease = random(1, Math.ceil((S.Wardeness.intelligence + S.Wardeness.intelligenceImplant) / 15) + 8);
			r.push(slaveSkillIncrease('wardeness', S.Wardeness, skillIncrease));
		}
		if (S.Wardeness.fetish === Fetish.SADIST) {
			r.push(`${He} uses the prisoners to gratify ${his} sadism, terrifying them and quickly breaking their resistance.`);
		} else if (S.Wardeness.energy > 95) {
			r.push(`${He} is so sexually depraved that ${he} constantly molests the prisoners, breaking them to a life of servitude.`);
		}
		if (S.Wardeness.sexualFlaw === SexualFlaw.MALICIOUS || S.Wardeness.sexualFlaw === SexualFlaw.ABUSIVE) {
			devBonus++;
			trustMalus += 2;
			idleBonus += 2;
			r.push(`Sexual abuse of prisoners has become an end for ${him}, not a means. ${He} inspires ${his} prisoners to do everything possible to qualify to get away from ${him}, even as ${he} slowly grinds away their interest in sex to do it.`);
		} else if (S.Wardeness.sexualQuirk === SexualQuirk.CARING) {
			devBonus--;
			trustMalus--;
			idleBonus--;
			r.push(`${His} kindness sometimes shows through ${his} tough façade, letting prisoners get off easier than they should.`);
		}
		if (S.Wardeness.dick > 2 && canPenetrate(S.Wardeness)) {
			devBonus++;
			trustMalus++;
			idleBonus++;
			r.push(`${His} molestation of the prisoners is more varied and effective because ${he} has a dick to fuck them with.`);
			slaveSkillIncrease('penetrative', S.Wardeness, 2);
		}
		if (S.Wardeness.muscles > 35) {
			devBonus++;
			trustMalus++;
			idleBonus++;
			r.push(`${He} is strong enough to restrain anyone that tries anything with ${his} own hands.`);
		}
		if (S.Wardeness.devotion > 95) {
			devBonus++;
			trustMalus++;
			idleBonus++;
			r.push(`${His} devotion to you is so absolute that ${he} sees breaking bitches for your service as a noble calling.`);
		}
		const pMod = App.SlaveAssignment.PartTime.efficiencyModifier(S.Wardeness);
		devBonus *= pMod;
		trustMalus *= pMod;
		idleBonus *= pMod;
		if (pMod < 1) {
			r.push(`Some part of ${his} day is taken up by ${his} part-time job, making ${him} less effective.`);
		}
		App.Events.addNode(beforeFrag, r, "div", "indent");

		for (const slave of slaves) {
			r = [];
			if (S.Wardeness.rivalryTarget === slave.ID) {
				r.push(`${He} greatly enjoys breaking ${his} ${rivalryTerm(S.Wardeness)}, ${slave.slaveName}'s will.`);
				slave.devotion++;
				slave.trust -= 3;
				if (random(1, 100) > 30) {
					S.Wardeness.rivalry++;
					slave.rivalry++;
				}
			} else if (S.Wardeness.relationshipTarget === slave.ID) {
				r.push(`${He} hates having to break ${his} ${relationshipTerm(S.Wardeness)}, ${slave.slaveName}, but ${his} devotion to you wins out in the end.`);
				slave.devotion++;
				slave.trust -= 3;
				if (random(1, 100) >= 50) {
					r.push(`${His} and ${slave.slaveName}'s relationship has been shattered by these events.`);
					S.Wardeness.relationship = 0;
					S.Wardeness.relationshipTarget = 0;
					slave.relationship = 0;
					slave.relationshipTarget = 0;
				}
			} else if (areRelated(S.Wardeness, slave)) {
				const {he2, his2} = getPronouns(slave).appendSuffix("2");
				r.push(`${He} shows ${his} ${relativeTerm(S.Wardeness, slave)} ${slave.slaveName} no mercy, making sure ${he2} understands ${his2} place.`);
				slave.devotion++;
				slave.trust--;
			}
			App.Events.addNode(beforeFrag, r, "div", "indent");
		}
		if (slaves.length < V.cellblock && !slaveResting(S.Wardeness)) {
			const seed = random(1, 10) + ((V.cellblock - slaves.length) * (random(150, 170) + (idleBonus * 10)));
			cashX(seed, "cellblock", S.Wardeness);
			App.Events.addNode(beforeFrag, [`Since ${he} doesn't have enough prisoners to manage to keep ${him} busy, ${he} works on citizens' slaves, earning <span class="yellowgreen"> ${cashFormat(seed)}.</span>`], "div", "indent");
		}
	}

	if (slaves.length > 0) {
		if (slaves.length === 1) {
			App.UI.DOM.appendNewElement("div", beforeFrag, `One slave is being confined in ${V.cellblockName} until they are willing to obey.`, "indent");
		} else {
			App.UI.DOM.appendNewElement("div", beforeFrag, `${slaves.length} slaves are being confined in ${V.cellblockName} until they are willing to obey.`, "indent");
		}
	}

	/** @type {Array<FC.EndWeek.SlaveReport>} */
	const slaveReports = [];

	if (S.Wardeness) {
		const slave = App.SlaveAssignment.reportSlave(S.Wardeness);
		tired(slave);
		/* apply following SA passages to facility leader */
		if (V.showEWD !== 0 || (V.favSeparateReport === 1 && V.favorites.includes(slave.ID))) {
			const wardenessEntry = App.UI.DOM.appendNewElement("div", beforeFrag, '', "slave-report");
			const artSpan = App.UI.DOM.appendNewElement("span", wardenessEntry);
			wardenessEntry.append(App.SlaveAssignment.saSlaveIntro(slave, `is serving as the Wardeness in ${V.cellblockName}.`));
			wardenessEntry.append(App.SlaveAssignment.standardSlaveReport(slave, false));
			App.SlaveAssignment.appendSlaveArt(artSpan, slave);
			slaveReports.push({
				id: slave.ID,
				report: wardenessEntry
			});
		} else {
			App.SlaveAssignment.standardSlaveReport(slave, true);
		}
	}

	for (const slave of App.SlaveAssignment.reportSlaves(slaves)) {
		const {He} = getPronouns(slave);
		if (slave.devotion <= 20) {
			if (slave.trust >= -20) {
				if (
					(slave.hears === -1 && slave.earwear !== "hearing aids") ||
					(slave.hears === 0 && slave.earwear === "muffling ear plugs") ||
					(slave.hears === -2)
				) {
					slave.devotion -= 2;
					slave.trust -= 2;
				} else {
					slave.devotion -= 4;
					slave.trust -= 4;
				}
			} else {
				slave.devotion++;
			}
		}
		switch (V.cellblockDecoration) {
			case "Paternalist":
				slave.rules.living = "normal";
				if (slave.inflation > 0) {
					deflate(slave);
				}
				break;
			case "Pastoralist":
				slave.rules.living = "spare";
				if (slave.inflation === 0) {
					if (slave.pregKnown === 0 && slave.bellyImplant < 1500) {
						slave.inflation = 2;
						slave.inflationType = InflationLiquid.MILK;
						slave.inflationMethod = 1;
					} else {
						slave.inflation = 1;
						slave.inflationType = InflationLiquid.MILK;
						slave.inflationMethod = 1;
					}
					SetBellySize(slave);
				}
				break;
			case "Hedonistic":
				slave.rules.living = "spare";
				if (slave.weight < 200) {
					if (slave.weightDirection === 1) {
						slave.weight += 5;
					} else if (slave.weightDirection === -1) {
						slave.weight += 1;
					} else {
						slave.weight += 3;
					}
				}
				if (slave.muscles > -100) {
					slave.muscles -= 2;
				}
				if (slave.inflation === 0) {
					if (slave.pregKnown === 0 && slave.bellyImplant < 1500) {
						slave.inflation = 3;
						slave.inflationType = InflationLiquid.FOOD;
						slave.inflationMethod = 1;
					} else {
						slave.inflation = 1;
						slave.inflationType = InflationLiquid.FOOD;
						slave.inflationMethod = 1;
					}
					SetBellySize(slave);
				}
				break;
			default:
				slave.rules.living = "spare";
				if (slave.inflation > 0) {
					deflate(slave);
				}
		}
		if (V.cellblockUpgrade === 1) {
			if (slave.behavioralFlaw !== BehavioralFlaw.NONE && slave.behavioralQuirk === BehavioralQuirk.NONE) {
				SoftenBehavioralFlaw(slave);
				slave.devotion -= 10;
				softenedQuirks++;
			} else if (slave.sexualFlaw !== SexualFlaw.NONE && slave.sexualQuirk === SexualQuirk.NONE) {
				SoftenSexualFlaw(slave);
				slave.devotion -= 10;
				softenedQuirks++;
			}
		}
		slave.devotion += devBonus;
		slave.trust -= trustMalus;
		if (S.Wardeness && S.Wardeness.sexualFlaw === SexualFlaw.MALICIOUS && slave.energy >= 2) {
			slave.energy -= 2;
		}
		if (slave.health.condition < -80) {
			improveCondition(slave, 20);
		} else if (slave.health.condition < -40) {
			improveCondition(slave, 15);
		} else if (slave.health.condition < 0) {
			improveCondition(slave, 10);
		} else if (slave.health.condition < 40) {
			improveCondition(slave, 7);
		} else if (slave.health.condition < 100) {
			improveCondition(slave, 3);
		}

		if (V.showEWD || (V.favSeparateReport === 1 && V.favorites.includes(slave.ID))) {
			const slaveEntry = App.UI.DOM.makeElement("div", null, ["slave-report"]);
			const artSpan = App.UI.DOM.appendNewElement("span", slaveEntry);
			slaveEntry.append(App.SlaveAssignment.saSlaveIntro(slave, `is confined in ${V.cellblockName}.`));

			confinedResults = App.SlaveAssignment.stayConfined(slave);
			App.Events.addNode(slaveEntry, [He, confinedResults.text], "div", "indent");
			if (confinedResults.broken) {
				brokenSlaves++;
				continue; // slave has been reassigned; remaining report will run at her new assignment
			}
			slaveEntry.append(App.SlaveAssignment.standardSlaveReport(slave, false));
			App.SlaveAssignment.appendSlaveArt(artSpan, slave);

			slaveReports.push({
				id: slave.ID,
				report: slaveEntry,
			});
		} else {
			// discard return values silently
			confinedResults = App.SlaveAssignment.stayConfined(slave);
			if (confinedResults.broken) {
				brokenSlaves++;
				continue; // slave has been reassigned; remaining report will run at her new assignment
			}
			App.SlaveAssignment.standardSlaveReport(slave, true);
		}
	}

	const afterFrag = new DocumentFragment();

	if (softenedQuirks || brokenSlaves) {
		r = [];
		if (softenedQuirks > 0) {
			r.push(`${cellblockNameCaps}'s advanced compliance systems successfully softened`);
			if (softenedQuirks === 1) {
				r.push(`one slave's mental flaw into an <span class="green">appealing quirk,</span> though the constant correction caused them <span class="mediumorchid">considerable anguish.</span>`);
			} else {
				r.push(`${softenedQuirks} slaves' mental flaws into <span class="green">appealing quirks,</span> though the constant correction caused them <span class="mediumorchid">considerable anguish.</span>`);
			}
		}
		if (brokenSlaves > 0) {
			if (brokenSlaves === 1) {
				r.push(`One slave is now willing to <span class="hotpink">do as they're told</span> and has been released.`);
			} else {
				r.push(`${brokenSlaves} slaves are now willing to <span class="hotpink">do as they're told</span> and have been released.`);
			}
			if (V.cellblockDecoration !== "standard") {
				App.Events.addNode(afterFrag, r, "p", "indent");
				r = [];
				r.push(`${cellblockNameCaps}'s ${V.cellblockDecoration} atmosphere <span class="hotpink">had an impact on them while they were</span> imprisoned.`);
			}
		}
		App.Events.addNode(afterFrag, r, "p", "indent");
	}
	App.EndWeek.saVars.flSex = new Set();

	return {
		before: beforeFrag,
		slaves: slaveReports,
		after: afterFrag,
	};
};