code:
App.Events.SECoursing = class SECoursing extends App.Events.BaseEvent {
	eventPrerequisites() {
		return [
			() => V.LurcherID !== 0,
			() => V.policies.coursingAssociation === 1,
			() => (Math.trunc(V.week / 4) === (V.week / 4)),
			() => V.coursed === 0
		];
	}

	actorPrerequisites() {
		return [];
	}

	execute(node) {
		let r = [];
		V.coursed = 1;
		let caught = false;
		let phallus;

		const activeLurcher = getSlave(V.LurcherID);
		const {
			He, His,
			he, him, himself, his, wife, woman
		} = getPronouns(activeLurcher);

		/** @type {Array<"housewife" | "heavily pregnant" | "virgin" | "disobedient young" | "huge balled" | "feminized" | "disobedient young dickgirl">} */
		const possibleOrigins = [];
		if (V.seeDicks !== 100) {
			possibleOrigins.push("housewife");
			if (V.seePreg !== 0) {
				possibleOrigins.push("heavily pregnant");
			}
			possibleOrigins.push("virgin");
			possibleOrigins.push("disobedient young");
		}
		if (V.seeDicks !== 0) {
			possibleOrigins.push("huge balled");
			possibleOrigins.push("feminized");
			possibleOrigins.push("disobedient young dickgirl");
		}

		const hares = [
			genHare(1),
			genHare(2),
			genHare(3)
		];

		App.Events.drawEventArt(node, activeLurcher, "no clothing");

		r.push(`It's time to go coursing. You meet with fellow members of the Coursing Association while the automated maintenance drones clear the plaza and lay down the green, sharing a refined discussion of recent events`);
		if (V.PC.refreshmentType === 0) {
			r.push(`over a ${V.PC.refreshment}.`);
		} else if (V.PC.refreshmentType === 1) {
			r.push(`over glasses of ${V.PC.refreshment}.`);
		} else if (V.PC.refreshmentType === 2) {
			r.push(`over plates of ${V.PC.refreshment}.`);
		} else if (V.PC.refreshmentType === 3) {
			r.push(`over hits of ${V.PC.refreshment}.`);
		} else if (V.PC.refreshmentType === 4) {
			r.push(`over shots of ${V.PC.refreshment}.`);
		} else if (V.PC.refreshmentType === 5) {
			r.push(`over handfuls of ${V.PC.refreshment}.`);
		} else if (V.PC.refreshmentType === 6) {
			r.push(`over tabs of ${V.PC.refreshment}.`);
		} else {
			r.push(`over.`);
		}
		r.push(`Once the field is ready, the day's hares are led out and chained in a row along one side of the plaza, naked. You and the other members watch this process intently, since you won't get any more information on them than what you can learn by looking.`);
		App.Events.addParagraph(node, r);
		r = [];
		r.push(`The rules have been explained to the hares: they're to be freed if they can reach the other side of the plaza without being caught and raped by the lurchers who will be released to chase them.`);

		App.Events.addParagraph(node, r);
		r = [];
		r.push(`You lead your lurcher ${activeLurcher.slaveName} out on a leash, naked just like the hares.`);

		if (activeLurcher.dick > 0) {
			if (canPenetrate(activeLurcher) && activeLurcher.energy > 60 && activeLurcher.devotion > 20) {
				if (activeLurcher.dick > 4) {
					r.push(`${He}'s sporting an enormous half-erection, which has already been heavily lubricated to prevent permanent damage to the hares' holes. As you bring ${him} up to the mark, ${he} grabs its base and begins to slap it against ${his} thigh, hard. The hares look around to see what the wet smacking noise is, and are understandably frightened; one of them begins to beg openly. Your fellow competitors think this is hilarious.`);
					repX(250, "event", activeLurcher);
					phallus = "huge dick";
				} else {
					r.push(`${He}'s ready to do ${his} best. Since ${he}'s concentrating on the immediate challenge of catching rather than the secondary challenge of raping, ${he} isn't hard yet, but ${he}'s not indifferent to the prospect of getting ${his} dick wet. There's a bead of precum forming at ${his} tip.`);
					phallus = "dick";
				}
			} else if (activeLurcher.tail === "sex") {
				r.push(`Although ${his} dick isn't really up to performing a sexual assault today, ${his} spade-tipped pleasure tail is sweeping back and forth and dripping lube. It's an unusual instrument for a lurcher, and one that fascinates the watching crowd of spectators.`);
				repX(250, "event", activeLurcher);
				phallus = "tail";
			} else if (!canAchieveErection(activeLurcher)) {
				r.push(`There's no way ${he}'s going to be able to achieve an erection, so ${he}'s holding a lubricated dildo in one hand. This is technically permitted under the rules, but your fellow competitors and the crowd gathering to spectate consider it poor form.`);
				repX(-50, "event", activeLurcher);
				phallus = "dildo";
			} else if (activeLurcher.energy <= 60 || activeLurcher.devotion <= 20) {
				r.push(`${He} looks nervous, and obviously doesn't find the situation arousing. ${He} knows ${he}'s to catch and then rape a slave, but may not be able to get hard enough to do the deed properly. Your fellow competitors and the crowd gathering to spectate are unimpressed by ${his} lack of spirit.`);
				repX(-50, "event", activeLurcher);
				phallus = "fingers";
			} else {
				r.push(`${His} dick is not a fit instrument for sexual assault, so ${he}'s holding a lubricated dildo in one hand. This is technically permitted under the rules, but your fellow competitors and the crowd gathering to spectate consider it poor form.`);
				repX(-50, "event", activeLurcher);
				phallus = "dildo";
			}
		} else if (activeLurcher.clit > 1 && activeLurcher.energy > 60 && activeLurcher.devotion > 20) {
			r.push(`${He}'s gently masturbating as you bring ${him} up to the mark, ${his} enormous clit becoming engorged and stiff. Your fellow competitors and the gathering crowd of spectators are fascinated, realizing that ${he} intends to attempt rape with it.`);
			repX(250, "event", activeLurcher);
			phallus = "clit";
		} else if (activeLurcher.tail === "sex") {
			r.push(`${His} spade-tipped pleasure tail is sweeping back and forth and dripping lube, as if ${he}'s already seeking a target for it. It's an unusual instrument for a lurcher, and one that fascinates the watching crowd of spectators.`);
			repX(250, "event", activeLurcher);
			phallus = "tail";
		} else if (V.seeDicks !== 0) {
			r.push(`${He}'s holding a lubricated dildo in one hand, since ${he}'s missing a natural phallus of ${his} own. This is technically permitted under the rules, but your fellow competitors and the crowd gathering to spectate consider it poor form.`);
			repX(-50, "event", activeLurcher);
			phallus = "dildo";
		} else {
			r.push(`${He}'s holding a lubricated dildo in one hand. As you bring ${him} up to the mark, ${he} begins to slap it against ${his} thigh out of nervousness and eagerness to begin. The hares look around to see what the wet smacking noise is, and are understandably frightened; one of them begins to cry openly.`);
			phallus = "dildo";
		}

		if (canSee(activeLurcher)) {
			r.push(`${activeLurcher.slaveName} looks at you questioningly, wondering which of the hares ${he} should try to chase down and molest.`);
		} else {
			r.push(`${activeLurcher.slaveName} looks at you questioningly, wondering which of the dinging bells ${he} should try to chase down and molest.`);
		}
		App.Events.addParagraph(node, r);

		const table = App.UI.DOM.appendNewElement("table", node, null, "invisible");
		for (const hare of hares) {
			table.append(hare.row);
		}

		/** @returns {hareResults} */
		function genHare(num) {
			let r = [];
			const row = App.UI.DOM.makeElement("tr");
			let hareSpeed = 10;
			const origin = possibleOrigins.pluck(); /* select random origin and remove from list to avoid using same origin multiple times */
			let slave;
			if (origin === "virgin") {
				slave = GenerateNewSlave("XX", {maxAge: 20, disableDisability: 1});
				generateSalonModifications(slave);
				slave.anus = 1;
				slave.vagina = 0;
				actX(slave, "anal");
				if (slave.pubertyXX > 0) {
					slave.preg = -1;
				}
				slave.ovaries = 1;
				slave.skill.vaginal = 0;
				slave.skill.oral = 0;
				slave.skill.anal = 0;
				slave.skill.whoring = 0;
				slave.weight = random(-50, 50);
			} else if (origin === "heavily pregnant") {
				slave = GenerateNewSlave("XX", {
					minAge: V.fertilityAge, maxAge: 20, disableDisability: 1, ageOverridesPedoMode: 1
				});
				slave.anus = 1;
				slave.vagina = 1;
				actX(slave, "vaginal");
				slave.preg = random(30, 40);
				slave.pregKnown = 1;
				slave.pregType = 1;
				slave.pregWeek = slave.preg;
				SetBellySize(slave);
				slave.ovaries = 1;
				slave.skill.vaginal = 0;
				slave.skill.oral = 0;
				slave.skill.anal = 0;
				slave.skill.whoring = 0;
				slave.weight = random(-20, 100);
			} else if (origin === "housewife") {
				slave = GenerateNewSlave("XX", {minAge: 35, maxAge: 39, disableDisability: 1});
				slave.boobs += 800;
				slave.boobsImplant += 800;
				slave.boobsImplantType = "normal";
				slave.butt += 1;
				slave.buttImplant += 1;
				slave.buttImplantType = "normal";
				slave.face = 55;
				slave.faceImplant += 20;
				slave.anus = 1;
				slave.vagina = 1;
				actX(slave, "anal");
				slave.preg = -1;
				slave.ovaries = 1;
				slave.skill.vaginal = 35;
				slave.skill.oral = 100;
				slave.skill.anal = 15;
				slave.skill.whoring = 35;
				slave.career = either("a housewife", "a trophy wife");
				slave.weight = random(-50, 100);
			} else if (origin === "disobedient young") {
				slave = GenerateNewSlave("XX", {maxAge: 25, disableDisability: 1});
				generateSalonModifications(slave);
				slave.anus = 1;
				slave.vagina = 1;
				actX(slave, "anal");
				if (slave.pubertyXX > 0) {
					slave.preg = -1;
				}
				slave.ovaries = 1;
				slave.skill.vaginal = 15;
				slave.skill.oral = 15;
				slave.skill.anal = 15;
				slave.skill.whoring = 15;
				slave.sexualFlaw = either("hates anal", "hates oral", "hates penetration", "idealistic");
				slave.behavioralFlaw = either("arrogant", "bitchy", "hates men");
				slave.energy = 10;
				slave.fetish = "none";
				slave.muscles = random(20, 50);
				slave.weight = random(-20, 20);
			} else if (origin === "disobedient young dickgirl") {
				slave = GenerateNewSlave("XY", {maxAge: 25, disableDisability: 1});
				generateSalonModifications(slave);
				slave.anus = 2;
				actX(slave, "anal");
				slave.dick = random(2, 4);
				slave.balls = random(2, 4);
				slave.skill.oral = 0;
				slave.skill.anal = 0;
				slave.skill.whoring = 0;
				slave.sexualFlaw = either("hates oral", "hates anal", "hates penetration");
				slave.behavioralFlaw = either("arrogant", "bitchy", "hates men");
				slave.attrXY = 0;
				slave.attrXX = 70;
				slave.fetish = "none";
				slave.muscles = random(20, 50);
				slave.weight = random(-20, 50);
			} else if (origin === "huge balled") {
				slave = GenerateNewSlave("XY", {maxAge: 25, disableDisability: 1});
				generateSalonModifications(slave);
				slave.anus = 1;
				actX(slave, "anal");
				slave.balls = 5;
				slave.scrotum = 5;
				slave.dick = random(3, 5);
				slave.skill.oral = 0;
				slave.skill.anal = 0;
				slave.skill.whoring = 0;
				slave.weight = random(-50, 100);
			} else if (origin === "feminized") {
				slave = GenerateNewSlave("XY", {maxAge: 25, disableDisability: 1});
				generateSalonModifications(slave);
				slave.boobs += 800;
				slave.boobsImplant += 800;
				slave.boobsImplantType = "fillable";
				slave.butt += 1;
				slave.buttImplant += 1;
				slave.buttImplantType = "normal";
				slave.face = Math.clamp(slave.face + 20, -100, 100);
				slave.faceImplant += 20;
				slave.anus = 3;
				actX(slave, "anal");
				slave.balls = random(0, 1);
				slave.dick = random(1, 2);
				slave.skill.oral = 15;
				slave.skill.anal = 35;
				slave.skill.whoring = 15;
				slave.attrXY = 100;
				slave.attrXX = 0;
				slave.weight = random(-100, 200);
			}
			const {
				He2, His2,
				he2, his2, him2, girl2, woman2
			} = getPronouns(slave).appendSuffix("2");
			if (V.seeImages && V.seeReportImages) {
				App.UI.DOM.appendNewElement("div", row, App.Art.SlaveArtElement(slave, 0, 0), ["imageRef", "tinyImg"]);
			}
			r.push(`The ${ordinalSuffix(num)}`);

			if (origin === "virgin") {
				r.push(`is an appealingly young ${slave.race} ${girl2}, and has V symbols drawn over ${his2} cunt and on ${his2} lower back, in the interests of fairness. ${He2}'s a <span class="pink">double virgin. </span>`);
				if (!canSee(activeLurcher)) {
					r.push(`To accommodate your blind lurcher, a bell is fastened around ${his2} neck.`);
				}
			} else if (origin === "heavily pregnant") {
				r.push(`is ${addA(slave.race)} ${girl2}, young and healthy but <span class="pink">heavily pregnant.</span> ${He2}'s probably been selected to be a hare as a joke, or because someone hates ${him2}.`);
				if (!canSee(activeLurcher)) {
					r.push(`To accommodate your blind lurcher, a bell is attached to ${his2} popped navel.`);
				}
			} else if (origin === "housewife") {
				r.push(`is ${addA(slave.race)} ${woman2}, no longer young, but attractive enough in a fake sort of way. ${He2} has obviously been crying, and has probably been recently enslaved from a comfortable life, like that of a house${wife} or a trophy ${wife}. `);
				if (!canSee(activeLurcher)) {
					r.push(`To accommodate your blind lurcher, a bell is fastened around ${his2} neck.`);
				}
			} else if (origin === "disobedient young") {
				r.push(`is a fit young ${slave.race} ${girl2}, and is far more watchful and alert than ${his2} fellow hares. ${He2} may be a disobedient slave here because ${he2} was difficult to train.`);
				if (!canSee(activeLurcher)) {
					r.push(`To accommodate your blind lurcher, a bell is fastened around ${his2} neck.`);
				}
			} else if (origin === "disobedient young dickgirl") {
				r.push(`is a strong young ${slave.race} slave who retains ${his2} cock and balls, and looks determined. Perhaps ${he2}'s a resistant dickgirl who's been difficult to turn into a good girl.`);
				if (!canSee(activeLurcher)) {
					r.push(`To accommodate your blind lurcher, a bell is fastened around ${his2} cock.`);
				}
			} else if (origin === "huge balled") {
				r.push(`is ${addA(slave.race)} slave whose distinguishing characteristic is a dangling scrotum and a pair of huge balls. This impediment bumps against ${his2} thighs as ${he2}'s made ready.`);
				if (!canSee(activeLurcher)) {
					r.push(`To accommodate your blind lurcher, a bell is fastened around ${his2} hefty testicles.`);
				}
			} else if (origin === "feminized") {
				r.push(`is ${addA(slave.race)} bitch with a tiny dick who has been heavily feminized, yet seems terrified and very new to slavery. ${His2} fake tits and girly behavior must be from ${his2} life before ${he2} was a slave.`);
				if (!canSee(activeLurcher)) {
					r.push(`To accommodate your blind lurcher, a bell is fastened around ${his2} neck.`);
				}
			}

			slave.origin = `Your lurcher ${activeLurcher.slaveName} caught $him coursing; $he was a ${origin} hare.`;
			setHealth(slave, jsRandom(30, 50));
			slave.devotion = random(-45, -25);
			slave.trust = random(-60, -75);
			slave.oldDevotion = slave.devotion;

			if (slave.physicalAge >= 100) {
				r.push(`${He2} is really, really old and won't stand a chance of shuffling off, though tackling ${him2} seems like it may be a bad idea.`);
				hareSpeed -= 5;
			} else if (slave.physicalAge >= 85) {
				r.push(`${He2} is very old and should be an easy catch.`);
				hareSpeed -= 4;
			} else if (slave.physicalAge >= 70) {
				r.push(`${He2} is old and slow.`);
				hareSpeed -= 3;
			}
			if (slave.weight > 190) {
				r.push(`${He2}'s practically all fat and no slave; ${he2}'s half-expected to roll ${his2} way to the finish like an overfed slutty bowling ball.`);
				hareSpeed -= 5;
			} else if (slave.weight > 160) {
				r.push(`${He2}'s a catastrophically fat slut of a slave, and may stand a better chance of getting away rolling than running.`);
				hareSpeed -= 3;
			} else if (slave.weight > 95) {
				r.push(`${He2}'s a ridiculously fat slut of a slave with plenty of flesh to grab on to; ${his2} constant jiggling will be a sight to behold, however.`);
				hareSpeed -= 2;
			} else if (slave.weight > 30) {
				r.push(`${He2}'s chubby enough that ${his2} weight will reduce ${his2} speed.`);
				hareSpeed -= 1;
			} else if (slave.weight < -95) {
				r.push(`${He2}'s so skinny that it's not likely ${he2}'s physically fit enough to be quick.`);
				hareSpeed -= 1;
			}
			if (slave.muscles > 50) {
				r.push(`${He2}'s so heavily muscled that ${he2}'s probably slower than ${he2} would be if ${he2} were merely fit.`);
				hareSpeed -= 1;
			} else if (slave.muscles > 30) {
				r.push(`${He2}'s quite toned, which will give ${him2} an edge once ${he2}'s up to speed.`);
				hareSpeed += 1;
			} else if (slave.muscles <= 5) {
				r.push(`${He2}'s soft, and ${his2} legs show no sign of tone at all.`);
				hareSpeed -= 1;
			}
			if (slave.height >= 185) {
				r.push(`${He2}'s tall enough that ${his2} height will probably slow ${him2} down.`);
				hareSpeed -= 1;
			} else if (slave.height < 150) {
				r.push(`${He2}'s short enough that ${his2} short legs will probably slow ${him2} down.`);
				hareSpeed -= 2;
			}
			if (slave.boobs >= 2000) {
				r.push(`${He2} has absurd tits that will destroy any chance ${he2} has of getting away.`);
				hareSpeed -= 2;
			} else if (slave.boobs >= 800) {
				r.push(`${He2} has huge boobs that will make it painful for ${him2} to run hard.`);
				hareSpeed -= 1;
			}
			if (slave.butt >= 6) {
				r.push(`${He2} has a monstrous bottom that won't help ${his2} gait.`);
				hareSpeed -= 1;
			}
			if (slave.dick >= 5) {
				r.push(`${His2} big cock is going to bounce around cruelly.`);
				hareSpeed -= 1;
			}
			if (slave.balls >= 5 && slave.scrotum > 0) {
				r.push(`${His2} balls are likely to hurt badly enough, running naked, to slow ${him2} down.`);
				hareSpeed -= 1;
			}
			if (slave.belly >= 60000) {
				r.push(`${He2}'s so massively pregnant it'll be lucky if ${he2} even makes it anywhere.`);
				hareSpeed -= 10;
			} else if (slave.belly >= 10000) {
				r.push(`${His2} pregnant belly will probably stop ${him2} from running at all.`);
				hareSpeed -= 5;
			} else if (slave.belly >= 5000) {
				r.push(`${He2}'s visibly pregnant and likely to be cautious and unsure about running.`);
				hareSpeed -= 3;
			} else if (slave.belly >= 1500) {
				r.push(`There is a slight roundness to ${his2} middle, likely an early pregnancy that will distract ${him2}.`);
				hareSpeed -= 1;
			}
			if (slave.health.tired > 90) {
				r.push(`${He2} is obviously tired and will likely be a quick catch.`);
				hareSpeed -= 5;
			} else if (slave.health.tired > 60) {
				r.push(`${He2} seems to be rather tired, which will slow ${him2} out of the gate.`);
				hareSpeed -= 2;
			} else if (slave.health.tired > 30) {
				r.push(`${He2} seems a little tired, which will slow ${his2} acceleration.`);
				hareSpeed -= 1;
			}
			if (V.debugMode) {
				r.push(`(Harespeed: ${hareSpeed})`);
			}
			/**
			 * @typedef hareResults
			 * @property {App.Entity.SlaveState} slave
			 * @property {number} number
			 * @property {string} origin
			 * @property {number} speed
			 * @property {HTMLTableRowElement} row
			 */

			/** @type {hareResults} */
			const result = {
				slave: slave, number: num, origin: origin, speed: hareSpeed, row: row
			};
			r.push(App.UI.DOM.makeElement("div", App.UI.DOM.link(
				`The ${ordinalSuffixWords(num)} hare`,
				() => {
					jQuery(node).empty().append(coursingRace(result));
				}
			), ['indent']));
			App.Events.addNode(row, r);
			return result;
		}

		function coursingRace(hare) {
			const result = new DocumentFragment();
			let r = [];
			let His2;
			let his2;
			let him2;
			let himself2;
			let He2;
			let he2;
			let woman2;
			let girl2;

			({
				He2, His2,
				he2, his2, him2, himself2, woman2, girl2
			} = getPronouns(hare.slave).appendSuffix("2")); // If you add to this, please add to the slower hare too.

			App.Events.drawEventArt(result, [activeLurcher, hare.slave], "no clothing");
			r.push(`You place your hand on the leash's quick release and`);
			if (canHear(activeLurcher)) {
				r.push(`whisper your direction into ${his} ear without letting the other competitors or their lurchers hear.`);
			} else {
				r.push(`gently point ${him} towards the target hare without letting the other competitors or their lurchers see.`);
			}
			r.push(`Then, you gently push ${him} down into ${his} starting crouch. The umpire trips the hares' releases, a few`);
			if (V.showInches === 2) {
				r.push(`yards`);
			} else {
				r.push(`meters`);
			}
			r.push(`in front of you and ${activeLurcher.slaveName}, and you instantly let your lurcher off ${his} leash.`);

			let lurcherSpeed = 10;
			if (activeLurcher.devotion > 50) {
				r.push(`${He}'s eager to do well for you, and immediately takes off.`);
				lurcherSpeed += 2;
			} else if (activeLurcher.trust < -20) {
				r.push(`${He}'s frightened of failing you, and immediately takes off.`);
				lurcherSpeed += 1;
			} else if (activeLurcher.devotion < -20) {
				r.push(`${He}'s disgusted by this, and is slow to start.`);
				lurcherSpeed -= 1;
			} else {
				r.push(`${He}'s a bit hesitant about this, but gets off reasonably well.`);
			}
			if (V.AgePenalty !== 0) {
				if (activeLurcher.physicalAge >= 100) {
					r.push(`The crowd bursts into raucous laughter as ${he} shuffles full speed ahead.`);
					lurcherSpeed -= 5;
				} else if (activeLurcher.physicalAge >= 85) {
					r.push(`The crowd bursts into laughter at the old ${woman} completely out of ${his} element.`);
					lurcherSpeed -= 3;
				} else if (activeLurcher.physicalAge >= 70) {
					r.push(`${He} isn't as young as ${he} used to be.`);
					lurcherSpeed -= 1;
				}
			}
			if (activeLurcher.health.condition > 60) {
				r.push(`${His} shining health allows ${him} to pour it on.`);
				lurcherSpeed += 1;
			} else if (activeLurcher.health.condition < 0) {
				r.push(`${His} poor health slows ${him} down.`);
				lurcherSpeed -= 1;
			}
			if (activeLurcher.health.tired > 90) {
				r.push(`${He} is exhausted and can barely stay awake; side bets are starting up on how far ${he}'ll make it around the track.`);
				lurcherSpeed -= 5;
			} else if (activeLurcher.health.tired > 60) {
				r.push(`${He} is fatigued, sapping the strength ${he}'ll need to reach ${his} top speed.`);
				lurcherSpeed -= 2;
			} else if (activeLurcher.health.tired > 30) {
				r.push(`${He} is tired and liable to be a slow start.`);
				lurcherSpeed -= 1;
			}
			if (!canSee(activeLurcher)) {
				r.push(`${His} inability to see causes ${him} to be cautious of ${his} footing, making ${his} first several strides slow and uncertain.`);
				lurcherSpeed -= 1;
			}
			if (activeLurcher.weight > 190) {
				r.push(`${He}'s so fat that ${his} run is nothing more than an out of breath waddle.`);
				lurcherSpeed -= 5;
			} else if (activeLurcher.weight > 160) {
				r.push(`It takes ${him} a while to get ${his} fat ass up to ${his} (rather pathetic) top speed, such as it is.`);
				lurcherSpeed -= 3;
			} else if (activeLurcher.weight > 95) {
				r.push(`It takes ${him} a while to get ${his} fat ass up to ${his} top speed, such as it is.`);
				lurcherSpeed -= 2;
			} else if (activeLurcher.weight > 30) {
				r.push(`It takes ${him} a while to get ${his} chubby body up to speed.`);
				lurcherSpeed -= 1;
			} else if (activeLurcher.weight < -95) {
				r.push(`${He}'s so thin that ${he} lacks the vigor to run really well.`);
				lurcherSpeed -= 1;
			}
			if (activeLurcher.muscles > 50) {
				r.push(`${He}'s muscle-bound, without the range of motion to move freely.`);
				lurcherSpeed -= 1;
			} else if (activeLurcher.muscles > 30) {
				r.push(`${He}'s fit, and is able to maintain ${his} speed quite well once ${he} reaches it.`);
				lurcherSpeed += 1;
			} else if (activeLurcher.muscles <= 5) {
				r.push(`${He}'s soft, and is panting desperately within a few short strides.`);
				lurcherSpeed -= 1;
			} else if (activeLurcher.muscles <= -30) {
				r.push(`${He}'s very weak, and is panting desperately from just walking to the starting line.`);
				lurcherSpeed -= 4;
			} else if (activeLurcher.muscles <= -95) {
				r.push(`${He}'s physically frail, barely capable of walking let alone running.`);
				lurcherSpeed -= 20;
			}
			if (activeLurcher.height >= 185) {
				r.push(`${His} steps are long — too long, in fact: ${his} long legs slow ${his} gait.`);
				lurcherSpeed -= 1;
			} else if (activeLurcher.height < 150) {
				r.push(`${His} stride is too short, but it's the best ${his} little legs can manage.`);
				lurcherSpeed -= 1;
			}
			if (activeLurcher.boobs >= 2000) {
				r.push(`${His} naked breasts slosh around wildly, ruining ${his} attempt at running.`);
				lurcherSpeed -= 2;
			} else if (activeLurcher.boobs >= 800) {
				r.push(`${His} big tits bounce energetically, looking quite nice but hurting ${his} speed.`);
				lurcherSpeed -= 1;
			}
			if (activeLurcher.butt >= 6) {
				r.push(`${He} does ${his} best to stay light on ${his} feet despite ${his} inconveniently huge buttocks.`);
				lurcherSpeed -= 1;
			}
			if (activeLurcher.dick >= 5) {
				r.push(`${His} cock bounces up and down wildly; ${he} does ${his} best to ignore it, but it does get in the way.`);
				lurcherSpeed -= 1;
			}
			if (activeLurcher.balls >= 5) {
				r.push(`As you watch ${him} go, ${his} testicles smack into ${his} thigh, and ${he} gasps with pain.`);
				lurcherSpeed -= 1;
			}
			if (activeLurcher.preg >= activeLurcher.pregData.normalBirth) {
				r.push(`${He} seems terrified that ${his} water might break if ${he} tried to move too fast.`);
				lurcherSpeed -= 10;
			} else if (activeLurcher.belly >= 120000) {
				r.push(`${He} can barely move ${himself}, let alone consider chasing something with ${his} titanic`);
				if (activeLurcher.bellyImplant > 100) {
					r.push(`belly implant`);
				} else {
					r.push(`pregnant belly`);
				}
				r.push(`in the way.`);
				lurcherSpeed -= 20;
			} else if (activeLurcher.belly >= 60000) {
				r.push(`${He} can barely waddle with ${his}`);
				if (activeLurcher.bellyImplant > 100) {
					r.push(`enormous belly implant.`);
				} else {
					r.push(`enormously pregnant belly.`);
				}
				lurcherSpeed -= 10;
			} else if (activeLurcher.belly >= 10000 && activeLurcher.bellyFluid < 2000) {
				r.push(`${He} can barely waddle along with ${his} huge`);
				if (activeLurcher.bellyImplant > 100) {
					r.push(`belly implant.`);
				} else {
					r.push(`pregnant belly.`);
				}
				lurcherSpeed -= 5;
			} else if (activeLurcher.bellyPreg >= 5000) {
				r.push(`${He} seems unwilling to really run while pregnant.`);
				lurcherSpeed -= 3;
			} else if (activeLurcher.bellyImplant >= 5000) {
				r.push(`${His} big belly implant hinders ${his} ability to run`);
				lurcherSpeed -= 2;
			} else if (activeLurcher.belly >= 1500) {
				r.push(`${He} keeps one hand on ${his} slightly swollen middle as ${he} runs.`);
				lurcherSpeed -= 1;
			}
			if (activeLurcher.bellyFluid >= 10000) {
				r.push(`${His} hugely bloated, ${activeLurcher.inflationType}-filled belly is taut and painful, forcing ${him} to a slow waddle.`);
				lurcherSpeed -= 5;
			} else if (activeLurcher.bellyFluid >= 5000) {
				r.push(`${His} bloated, ${activeLurcher.inflationType}-stuffed belly is constantly jiggling and moving, making it extremely difficult to run.`);
				lurcherSpeed -= 4;
			} else if (activeLurcher.bellyFluid >= 2000) {
				r.push(`${His} distended, ${activeLurcher.inflationType}-belly is uncomfortable and heavy, slowing ${him} down.`);
				lurcherSpeed -= 2;
			}

			if (lurcherSpeed > 10) {
				r.push(`${His} turn of speed is impressive.`);
			} else if (lurcherSpeed > 8) {
				r.push(`${He} runs reasonably fast.`);
			} else if (lurcherSpeed > 6) {
				r.push(`In all, ${he} runs slowly.`);
			} else if (lurcherSpeed > 4) {
				r.push(`In all, ${he} barely manages a quick jog.`);
			} else {
				r.push(`In all, ${he} can barely do more than stumble after the hares.`);
			}

			if (hare.speed >= lurcherSpeed) {
				if (hare.origin === "virgin") {
					r.push(`The virgin, however,`);
				} else if (hare.origin === "heavily pregnant") {
					r.push(`Despite ${his2} pregnancy, the hare`);
				} else if (hare.origin === "housewife") {
					r.push(`Despite ${his2} fake boobs, the hare`);
				} else if (hare.origin === "disobedient young") {
					r.push(`The fit young slave, however,`);
				} else if (hare.origin === "disobedient young dickgirl") {
					r.push(`The strong young slave, however,`);
				} else if (hare.origin === "huge balled") {
					r.push(`Despite ${his2} ridiculous ballsack, the hare`);
				} else {
					r.push(`Despite ${his2} fake boobs and exaggeratedly feminine gait, the hare`);
				}
				if (hare.speed > lurcherSpeed) {
					r.push(`immediately pulls away.`);
				} else {
					r.push(`manages to maintain ${his2} narrow head start.`);
				}
				r.push(`Realizing that ${he} stands no chance of catching ${his} assigned target, ${activeLurcher.slaveName}`);
				if (canSee(activeLurcher)) {
					r.push(`looks around for a slower hare.`);
				} else {
					r.push(`listens for a nearby bell.`);
				}

				// Secondary target
				const slowHare = hares.find(h => h.speed < hare.speed);
				if (slowHare) {
					hare = slowHare;
					({
						He2, His2,
						he2, his2, him2, himself2, woman2, girl2
					} = getPronouns(hare.slave).appendSuffix("2"));
					if (canSee(activeLurcher)) {
						r.push(`Seeing that the ${hare.origin} hare is slower,`);
					} else {
						r.push(`hearing the ${hare.origin} hare's bell nearby,`);
					}
					r.push(`${he} angles after ${him2} instead.`);
					if (hare.speed >= lurcherSpeed) {
						r.push(`${He} does no better with ${his} new target; ${his} course is over.`);
					} else if (random(1, 2) === 1) {
						r.push(`One of ${his} rival lurchers has the same idea, however, and tries to trip ${him} up.`);
						if (!canSee(activeLurcher)) {
							r.push(`Unable to see it coming, ${he} goes down with a crash; ${his} course is over.`);
						} else if (activeLurcher.skill.combat === 1) {
							r.push(`${He} parries the attempt with contemptuous ease and catches up to ${his} new target.`);
							caught = true;
						} else if (activeLurcher.tail === "combat") {
							r.push(`${He} lashes out at ${his} competitor with ${his} combat tail; ${his} rival stumbles in surprise, and ${he} easily catches up to ${his} new target.`);
							caught = true;
						} else if (activeLurcher.muscles > 30) {
							r.push(`${He} muscles through the attempt and catches up to ${his} new target.`);
							caught = true;
						} else {
							r.push(`${He} goes down with a crash; ${his} course is over.`);
						}
					} else {
						r.push(`${He} manages to overtake ${his} new target.`);
						caught = true;
					}
				} else {
					r.push(`${He} is stymied as every hare is faster than his ${hare.origin} hare.`);
				}
			} else {
				r.push(`${He} rapidly overtakes the ${hare.origin} hare.`);
				caught = true;
			}

			if (V.debugMode) {
				r.push(`(Lurcher's speed: ${lurcherSpeed}, Hare's speed: ${hare.speed})`);
			}

			App.Events.addParagraph(result, r);
			r = [];

			if (caught === true) {
				if (hare.origin === "heavily pregnant") {
					r.push(`${His} quarry is unwilling to be tackled, probably out of fear for ${his2} baby, and flings ${himself2} down as soon as ${activeLurcher.slaveName} gets near.`);
					if (!canSee(activeLurcher)) {
						r.push(`${He2} screams as ${he2} sees ${activeLurcher.slaveName} preparing to dive on ${him2}, alerting the blind lurcher that ${his} prey has already surrendered.`);
					}
				} else if (!canSee(activeLurcher) && random(1, 3) === 1) {
					r.push(`${His} prey takes advantage of ${his} lack of eyesight, baiting ${activeLurcher.slaveName} to dive in the wrong direction. As ${he} rises to ${his} feet, the slave is too far gone to make another lunge. ${activeLurcher.slaveName}'s course is over.`);
					caught = false;
				} else if (activeLurcher.skill.combat === 1) {
					r.push(`${His} tackle is expert: ${he} wraps ${his} quarry up and pulls ${him2} down, falling on top of the struggling body.`);
				} else if (activeLurcher.muscles > 30) {
					r.push(`${He}'s burly enough that ${he} tackles ${his} quarry by simple force, an approach no less effective for its inelegance.`);
				} else if (hare.origin === "virgin") {
					if (random(1, 3) === 1) {
						r.push(`The young slave manages to evade ${his} inexpert tackle, however, and there is no space for another before ${he} crosses the plaza. ${activeLurcher.slaveName}'s course is over.`);
						caught = false;
					} else {
						r.push(`${His} tackle is inexpert, but the young slave stumbles and falls anyway.`);
					}
				} else if (hare.origin === "housewife") {
					if (random(1, 4) === 1) {
						r.push(`The spoiled slave shows surprising agility, however, and evades ${activeLurcher.slaveName}'s inexpert attempts to tackle all the way across the plaza. ${His} course is over.`);
						caught = false;
					} else {
						r.push(`${His} tackle is inexpert, but the top-heavy bimbo goes down anyway.`);
					}
				} else if (hare.origin === "feminized") {
					if (random(1, 4) === 1) {
						r.push(`The sissy bitch shows surprising agility, however, and evades ${activeLurcher.slaveName}'s inexpert attempts to tackle all the way across the plaza. ${His} course is over.`);
						caught = false;
					} else {
						r.push(`${His} tackle is inexpert, but the sissy bitch goes down with a wail.`);
					}
				} else if (hare.origin === "huge balled") {
					if (random(1, 4) === 1) {
						r.push(`The slave shows surprising agility despite ${his2} flopping ballsack, and evades ${activeLurcher.slaveName}'s inexpert attempts to tackle all the way across the plaza. ${His} course is over.`);
						caught = false;
					} else {
						r.push(`${His} tackle is inexpert, but the slave goes down, screaming with pain when ${his2} balls get trapped under their combined weight.`);
					}
				} else {
					if (random(1, 2) === 1) {
						r.push(`The determined young slave evades ${his} inexpert attempts to tackle all the way across the plaza, however. ${activeLurcher.slaveName}'s course is over.`);
						caught = false;
					} else {
						r.push(`${His} tackle is inexpert, but the determined slave is unlucky, stumbling and going down anyway.`);
					}
				}
			}

			if (caught === true) { // Caught may have changed, check again.
				r.push(`The hare knows that once ${his2} knees touched the field, ${his2} chance at freedom was gone. ${He2} begins to cry`);
				if (phallus === "huge dick") {
					r.push(`and then scream as ${activeLurcher.slaveName}`);
					if (hare.origin === "virgin") {
						r.push(`rapes ${his2} virgin ass. The lurcher has to fuck the slave to claim ${him2} for you, and ${he} knows that a virgin pussy is more valuable than a virgin rosebud. ${He} has to be very careful, since ${his} cock is big enough to seriously hurt an anal virgin, but despite ${his} care the racket is appallingly loud.`);
					} else if (hare.origin === "heavily pregnant") {
						r.push(`fucks ${his2} cunt. As ${his2} belly attests, ${he2}'s no virgin, but the lurcher's dick is big enough to reach ${his2} cervix. ${His2} screams crescendo into shrieks as ${he2} experiences this internal torment.`);
					} else if (hare.origin === "housewife") {
						r.push(`fucks ${him2} in the ass. A kept ${woman2} like ${him2} is probably no stranger to giving up ${his2} butthole to please a cock, but ${he2} apparently isn't used to dick quite this formidable. The lurcher leaves ${him2} sobbing disconsolately with a fresh load of cum leaking out of ${his2} backdoor.`);
					} else if (hare.origin === "feminized") {
						r.push(`fucks ${him2} in the ass. The high-pitched shrieking produces some discussion in the crowd. If the slave didn't want huge cock up ${his2} girly anus, why did ${he2} feminize ${himself2} so thoroughly? A mystery.`);
					} else if (hare.origin === "huge balled") {
						r.push(`fucks ${him2} in the ass. The lurcher pounds ${him2} doggy style, taking nice long strokes that slide ${his} formidable shaft almost all the way out of ${his} victim's poor butthole before shoving it back in again. The slave's balls brush the field with each thrust.`);
					} else {
						r.push(`fucks ${him2} in the ass. ${He2} never stops struggling, though this isn't much proof of undiminished resistance. After all, the lurcher's dick is so big that ${he2}'d probably fight to get it out of ${his2} butthole even if ${he2} weren't in need of breaking.`);
					}
				} else if (phallus === "dick") {
					r.push(`as ${activeLurcher.slaveName}`);
					if (hare.origin === "virgin") {
						r.push(`penetrates ${his2} virgin ass. The lurcher has to fuck the slave to claim ${him2} for you, and ${he} knows that a virgin pussy is more valuable than a virgin rosebud. You see ${his} back stiffen with overstimulation as ${he} experiences the rare delight of raping an anal virgin.`);
					} else if (hare.origin === "heavily pregnant") {
						r.push(`uses ${his2} cunt. The lurcher pulls the slave upright so ${he} can cradle ${his2} pregnant belly while ${he} fucks ${him2}. When ${he2} climaxes, ${he} thrusts as deeply as ${he} can manage, though more cum won't make the slave any more pregnant.`);
					} else if (hare.origin === "housewife") {
						r.push(`fucks ${him2} in the ass. ${His2} tears seem to come more from disappointment than anal pain; a kept ${woman2} like ${him2} has probably put up with more than one buttfuck ${he2} didn't want.`);
					} else if (hare.origin === "feminized") {
						r.push(`fucks ${him2} in the ass. The whining produces some discussion in the crowd. If the slave didn't want cock up ${his2} girly anus, why did ${he2} feminize ${himself2} so thoroughly? A mystery.`);
					} else if (hare.origin === "huge balled") {
						r.push(`uses ${his2} anus. With them facing away from you, the coupling takes the usual stacked symmetry of a dickgirl fucking a dickgirl, though the bottom's generous balls sway eye-catchingly back and forth with the rhythm of the assrape.`);
					} else {
						r.push(`fucks ${him2} in the ass. ${He2} never stops struggling, which is eloquent proof of the slave's undiminished resolve to resist ${his2} lot in life. ${He2}'s probably been assraped more than once before today, but ${he2} fights this like it's the first time.`);
					}
				} else if (phallus === "clit") {
					r.push(`as ${activeLurcher.slaveName}`);
					if (hare.origin === "virgin") {
						r.push(`grinds ${himself} against the hare to get ${his} pseudophallic clit into ${his} victim's virgin ass. The lurcher has to fuck the slave to claim ${him2} for you, and ${he} knows that a virgin pussy is more valuable than a virgin rosebud. You see ${his} back stiffen with overstimulation as ${his} enormous bitch button slips up the slave's asshole.`);
					} else if (hare.origin === "heavily pregnant") {
						r.push(`grinds ${himself} against the hare to get ${his} pseudophallic clit inside ${his} victim's cunt. The lurcher has to force the hare down, legs spread, in order to work ${his} enormous clit inside the slave, but ${he} manages it and you see ${his} back stiffen as ${his} pseudophallus, small by the standards of penises but much more sensitive, slides inside.`);
					} else if (hare.origin === "housewife") {
						r.push(`grinds ${himself} against the hare to get ${his} pseudophallic clit inside ${his} victim's cunt. The slave doesn't seem to know what to make of this. Being raped by a huge clit is very probably a novel experience for ${him2}, but it isn't really painful. ${He2} closes ${his2} eyes and visibly tries to pretend it's a small penis.`);
					} else if (hare.origin === "feminized") {
						r.push(`grinds ${himself} against the hare to get ${his} pseudophallic clit inside ${his} victim's experienced anus. The slave stiffens with shock. ${He2}'s obviously had quite a variety of things pushed up ${his2} girly butthole, but apparently this is ${his2} first time being fucked by a clit.`);
					} else if (hare.origin === "huge balled") {
						r.push(`grinds ${himself} against the hare to get ${his} pseudophallic clit inside ${his} victim's asshole. The slave stiffens with shock. Though it's huge by the standards of clitorises, the pseudophallus isn't big enough to make assrape painful, but the extreme inversion of gender roles makes up for it, to go by the slave's horror.`);
					} else {
						r.push(`grinds ${himself} against the hare to get ${his} pseudophallic clit inside ${his} victim's asshole. The slave never stops struggling, which is eloquent proof of the slave's undiminished resolve to resist ${his2} lot in life. ${He2}'s probably been assraped by much larger phalli, but ${he2} fights it anyway.`);
					}
				} else if (phallus === "dildo") {
					r.push(`as ${activeLurcher.slaveName}`);
					if (hare.origin === "virgin") {
						r.push(`inserts ${his} dildo into the slave's virgin ass. The lurcher has to fuck the slave to claim ${him2} for you, and ${he} knows that a virgin pussy is more valuable than a virgin rosebud. The dildo is reasonably sized and well lubricated, but the poor slave shrieks with anal pain anyway.`);
					} else if (hare.origin === "heavily pregnant") {
						r.push(`pushes ${his} dildo inside the slave's fertile cunt. Desperate to preserve ${his2} baby, the slave complies as best ${he2} can. Taking the cue, your lurcher caresses ${him2}, producing a grotesque parody of loving pregnant sex that holds the crowd's attention.`);
					} else if (hare.origin === "housewife") {
						r.push(`pushes ${his} dildo up the slave's ass. A kept ${woman2} like ${him2} is not likely to be any stranger to sex toys, but to go by ${his2} reaction, ${he2} probably prefers to put them in ${his2} cunt.`);
					} else if (hare.origin === "feminized") {
						r.push(`pushes ${his} dildo up the slave's sissy ass. The whining produces some discussion in the crowd. Why would a ${girl2} who feminized ${himself2} so thoroughly have any problem with something being shoved inside ${his2} rear pussy? A mystery.`);
					} else if (hare.origin === "huge balled") {
						r.push(`pushes ${his} dildo up the slave's ass. Knowing that ${he} should do ${his} best to create a spectacle, ${he} takes the slave's dangling balls in one hand, squeezing them to force ${his} bottom to be a good little butthole bitch, and then stimulating them until the slave achieves a shameful anal orgasm.`);
					} else {
						r.push(`pushes ${his} dildo up the slave's ass. The slave never stops struggling, which is eloquent proof of the slave's undiminished resolve to resist ${his2} lot in life. ${He2}'s probably had several dildos pushed up ${his2} disobedient asshole, but it seems ${he2}'s determined to learn nothing.`);
					}
				} else if (phallus === "tail") {
					r.push(`as ${activeLurcher.slaveName}`);
					if (hare.origin === "virgin") {
						r.push(`pushes the well-lubricated tip of ${his} pleasure tail into the slave's virgin ass. The lurcher has to fuck the slave to claim ${him2} for you, and ${he} knows that a virgin pussy is more valuable than a virgin rosebud. ${His} tail is not too thick and ${he} uses the lubrication function generously, but the poor slave shrieks with anal pain anyway.`);
					} else if (hare.origin === "heavily pregnant") {
						r.push(`pushes the tip of ${his} pleasure tail inside the slave's fertile cunt. Desperate to preserve ${his2} baby, the slave complies as best ${he2} can. Taking the cue, your lurcher caresses ${him2} gently as ${his} flexible tail seeks ${his2} g-spot to make ${him2} cum.`);
					} else if (hare.origin === "housewife") {
						r.push(`pushes the tip of ${his} pleasure tail up the slave's ass. A kept ${woman2} like ${him2} is not likely to be any stranger to sex toys, but being assfucked by a tail is likely a completely novel experience for ${him2}.`);
					} else if (hare.origin === "feminized") {
						r.push(`pushes the tip of ${his} pleasure tail up the slave's sissy ass. The slave stiffens with shock. ${He2}'s obviously had quite a variety of things pushed up ${his2} girly butthole, but apparently this is ${his2} first time being fucked by a tail.`);
					} else if (hare.origin === "huge balled") {
						r.push(`pushes the tip of ${his} pleasure tail up the slave's ass. The slave stiffens with shock. Regardless of how much experience ${he2}'s had with anal toys, a tail squirming through ${his2} bowels and pushing on ${his2} prostate must be a novel experience. Playing up the spectacle, ${activeLurcher.slaveName} massages ${his2} balls with both hands, stimulating them until the hare achieves a shameful anal orgasm.`);
					} else {
						r.push(`pushes the tip of ${his} pleasure tail up the slave's ass. The slave never stops struggling, which is eloquent proof of the slave's undiminished resolve to resist ${his2} lot in life. ${He2}'s probably had things pushed up ${his2} ass before, but a tail worming its way uninvited into ${his2} bowels is not going to be easily forgotten.`);
					}
				} else {
					r.push(`as ${activeLurcher.slaveName} hesitates over ${him2}. The lurcher realizes that ${he} won't be able to get hard. Desperate to avoid failure, ${he}`);
					if (hare.origin === "virgin") {
						r.push(`shoves a couple of fingers into the slave's virgin ass. ${He} has to fuck the slave to claim ${him2} for you, and ${he} knows that a virgin pussy is more valuable than a virgin rosebud.`);
					} else if (hare.origin === "heavily pregnant") {
						r.push(`gives up and fingerfucks the pregnant ${girl2}. Desperate to preserve ${his2} baby, the slave complies as best ${he2} can, producing a contest between ${his2} attempts to go along and the lurcher's attempts to make it unpleasant. This degenerates into a sobbing cunt fisting session.`);
					} else if (hare.origin === "housewife") {
						r.push(`shoves a couple of fingers up the slave's ass. A kept ${woman2} like ${him2} is not likely to be any stranger to a little anal play, but ${he2} doesn't seem to be much of a fan. ${He2} does ${his2} best to relax, but it's obvious that ${he2} doesn't appreciate having ${his2} asshole fingered.`);
					} else if (hare.origin === "feminized") {
						r.push(`shoves ${his} fingers up the slave's sissy ass. It's so loose that this fails to have the desired effect. Afraid that ${he} has to produce some sort of reaction, the lurcher shoves ${his} entire fist up there, producing a wail of anal anguish.`);
					} else if (hare.origin === "huge balled") {
						r.push(`shoves a couple of fingers up the slave's ass. Casting about for something to do to distract from ${his} inadequacy, the lurcher seizes the slave's dangling balls and shoves one of them up ${his2} loosened butt. This produces a shriek of pain and surprise, followed by a long fight to get the other one up there.`);
					} else {
						r.push(`shoves a couple of fingers up the slave's ass. The slave never stops struggling, producing nothing more interesting than an extended wrestling match in which one of the parties has some fingers inside the other's butthole.`);
					}
					r.push(`The crowd is unimpressed by this disappointing display.`);
				}
				if (activeLurcher.fetishKnown === 1 && activeLurcher.fetishStrength > 60) {
					if (activeLurcher.fetish === "sadist") {
						r.push(`<span class="hotpink">What is finest in life,</span> in the mind of your sadistic lurcher?`);
						if (hare.origin === "virgin") {
							r.push(`To sodomize a virgin asshole, and to`);
							if (canHear(activeLurcher)) {
								r.push(`hear`);
							} else {
								r.push(`feel`);
							}
							r.push(`screams of anal pain.`);
						} else if (hare.origin === "heavily pregnant") {
							r.push(`To molest a pregnant slut, and`);
							if (canHear(activeLurcher)) {
								r.push(`hear`);
							} else {
								r.push(`see`);
							}
							r.push(`${him2} sob with fear.`);
						} else if (hare.origin === "housewife") {
							r.push(`To rape a stuck-up bitch, and`);
							if (canHear(activeLurcher)) {
								r.push(`hear`);
							} else {
								r.push(`see`);
							}
							r.push(`${him2} cry with anal pain.`);
						} else if (hare.origin === "feminized") {
							r.push(`To rape a sissy's asspussy, and`);
							if (canHear(activeLurcher)) {
								r.push(`hear`);
							} else {
								r.push(`see`);
							}
							r.push(`${him2} squeal.`);
						} else if (hare.origin === "huge balled") {
							r.push(`To abuse defenseless testicles, and make their owner scream.`);
						} else {
							r.push(`To rape a struggling victim, and`);
							if (canTaste(activeLurcher)) {
								r.push(`taste`);
							} else {
								r.push(`drink`);
							}
							r.push(`${his2} tears of defeat.`);
						}
						activeLurcher.devotion += 5;
					} else if (activeLurcher.fetish === "pregnancy" && hare.origin === "heavily pregnant") {
						r.push(`You lurcher is <span class="hotpink">thrilled</span> to have had the privilege of chasing down and raping a pregnant ${woman2}.`);
						activeLurcher.devotion += 5;
					}
				}
				activeLurcher.counter.penetrative += 1;
				V.penetrativeTotal += 1;
				newSlave(hare.slave);/* skip New Slave Intro */
			} else {
				if (activeLurcher.devotion > 50) {
					r.push(`${He} makes ${his} way back to you dejectedly, hanging ${his} head.`);
				} else {
					r.push(`${He} makes ${his} way back to you slowly, doing ${his} best to look contrite.`);
				}
				const {hisU} = getNonlocalPronouns(V.seeDicks).appendSuffix("U");
				r.push(`On the other side of the plaza, there is a scream of triumph followed by tears of joy as one of the hares successfully wins ${hisU} freedom. This cheerful noise mixes strangely with screams of a very different sort and the slap of flesh on flesh as a more successful lurcher rapes ${hisU} capture.`);
			}
			App.Events.addParagraph(result, r);
			return result;
		}
	}
};


code:
App.Events.SEcustomSlaveDelivery = class SEcustomSlaveDelivery extends App.Events.BaseEvent {
	constructor(actors, params) {
		super(actors, params);
	}

	eventPrerequisites() {
		return [
			() => V.customSlaveOrdered === 1,
			() => V.customSlaveReorder !== 1
		];
	}

	execute(node) {
		V.customSlaveOrdered = 0;
		V.encyclopedia = "Enslaving People";

		const delivery = generateDelivery();
		const {
			He, His,
			he, him
		} = getPronouns(delivery);

		const cost = slaveCost(delivery) * 2;

		App.UI.DOM.appendNewElement("p", node, "A slave dealer has submitted a slave to satisfy the order you posted.");

		App.UI.DOM.appendNewElement("p", node, "As usual, the asking price is quite high, to cover the costs of finding a slave to order. In compensation, you can freely decline the slave and keep the order open, or even modify it later.", "scene-intro");

		App.UI.DOM.appendNewElement("p", node, App.Desc.longSlave(delivery, {market: "generic"}));

		App.UI.DOM.appendNewElement("p", node, `${His} price is ${cashFormat(cost)}.`);

		const result = App.UI.DOM.appendNewElement("p", node);

		if (V.cash >= cost) {
			App.UI.DOM.appendNewElement("div", result, App.UI.DOM.link(
				"Accept the offered slave",
				() => {
					cashX(forceNeg(cost), "slaveTransfer", delivery);
					jQuery(result).empty().append(`${He} has been reasonably broken by the dealer that offered ${him} to you. ${He} has also picked up on the fact that ${he} was specially selected, and is a little hopeful that this means ${he} may be treated well. ${He} is now awaiting your instructions.`, App.UI.newSlaveIntro(delivery));
				}
			));
		} else {
			App.UI.DOM.appendNewElement("div", result, App.UI.DOM.disabledLink("Accept the offered slave", [`You lack the necessary funds to accept the offered slave.`]), "note");
		}
		App.UI.DOM.appendNewElement("div", result, App.UI.DOM.link(
			"Reject this offer and place the same order again",
			() => {
				V.customSlaveOrdered = 1;
				V.customSlaveReorder = 1;
			},
			[],
			V.nextLink
		));

		function generateDelivery() {
			const pram = {
				mature: 0,
				nationality: (V.customSlave.nationality !== "Nationality is unimportant") ? V.customSlave.nationality : undefined,
				ageOverridesPedoMode: 1
			};
			if (V.customSlave.age === 2) {
				pram.minAge = V.minimumSlaveAge;
				pram.maxAge = 2;
			} else if (V.customSlave.age === 4) {
				pram.minAge = 3;
				pram.maxAge = 4;
			} else if (V.customSlave.age === 6) {
				pram.minAge = 5;
				pram.maxAge = 6;
			} else if (V.customSlave.age === 9) {
				pram.minAge = 7;
				pram.maxAge = 9;
			} else if (V.customSlave.age === 12) {
				pram.minAge = 10;
				pram.maxAge = 12;
			} else if (V.customSlave.age === 14) {
				pram.minAge = 13;
				pram.maxAge = 14;
			} else if (V.customSlave.age === 17) {
				pram.minAge = 15;
				pram.maxAge = 17;
			} else if (V.customSlave.age === 19) {
				pram.minAge = 18;
				pram.maxAge = 19;
			} else if (V.customSlave.age === 20) {
				pram.minAge = 20;
				pram.maxAge = V.retirementAge - 1;
			} else if (V.customSlave.age === 24) {
				pram.minAge = 20;
				pram.maxAge = 24;
			} else if (V.customSlave.age === 25) {
				pram.minAge = 25;
				pram.maxAge = V.retirementAge - 1;
			} else if (V.customSlave.age === 29) {
				pram.minAge = 25;
				pram.maxAge = 29;
			} else if (V.customSlave.age === 30) {
				pram.minAge = 30;
				pram.maxAge = V.retirementAge - 1;
			} else if (V.customSlave.age === 39) {
				pram.minAge = 30;
				pram.maxAge = 39;
			} else if (V.customSlave.age === 40) {
				pram.minAge = 40;
				pram.maxAge = V.retirementAge - 1;
			} else if (V.customSlave.age === 49) {
				pram.minAge = 40;
				pram.maxAge = 49;
			} else if (V.customSlave.age === 50) {
				pram.minAge = 50;
				pram.maxAge = V.retirementAge - 1;
			} else if (V.customSlave.age === 59) {
				pram.minAge = 50;
				pram.maxAge = 59;
			} else if (V.customSlave.age === 60) {
				pram.minAge = 60;
				pram.maxAge = V.retirementAge - 1;
			} else if (V.customSlave.age === 69) {
				pram.minAge = 60;
				pram.maxAge = 69;
			} else if (V.customSlave.age === 70) {
				pram.minAge = 70;
				pram.maxAge = V.retirementAge - 1;
			} else if (V.customSlave.age === 79) {
				pram.minAge = 70;
				pram.maxAge = 79;
			} else if (V.customSlave.age === 80) {
				pram.minAge = 80;
				pram.maxAge = V.retirementAge - 1;
			} else if (V.customSlave.age === 89) {
				pram.minAge = 80;
				pram.maxAge = 89;
			} else if (V.customSlave.age === 90) {
				pram.minAge = 90;
				pram.maxAge = V.retirementAge - 1;
			} else if (V.customSlave.age === 99) {
				pram.minAge = 90;
				pram.maxAge = 99;
			} else if (V.customSlave.age === 100) {
				pram.minAge = 100;
				pram.maxAge = V.retirementAge - 1;
			} else if (V.customSlave.age === 109) {
				pram.minAge = 100;
				pram.maxAge = 109;
			} else if (V.customSlave.age === 110) {
				pram.minAge = 110;
				pram.maxAge = V.retirementAge - 1;
			} else if (V.customSlave.age === 119) {
				pram.minAge = 110;
				pram.maxAge = 119;
			} else if (V.customSlave.age === 120) {
				pram.minAge = 120;
				pram.maxAge = V.retirementAge - 1;
			} else if (V.customSlave.age === 129) {
				pram.minAge = 120;
				pram.maxAge = 129;
			} else {
				pram.minAge = 130;
				pram.maxAge = V.retirementAge - 1;
			}
			if (V.customSlave.race !== "ethnicity is unimportant") {
				pram.race = V.customSlave.race;
			}

			const delivery = GenerateNewSlave((V.customSlave.sex === 2) ? "XY" : "XX", pram);

			if (V.customSlave.sex === 2) {
				delivery.dick = V.customSlave.dick;
				delivery.balls = V.customSlave.balls;
				delivery.scrotum = delivery.balls;
				delivery.foreskin = delivery.dick;
			} else {
				if (V.customSlave.virgin === 0) {
					delivery.vagina = V.customSlave.virgin;
				}
				delivery.labia = V.customSlave.labia;
				delivery.vaginaLube = V.customSlave.vaginaLube;
				delivery.skill.vaginal = V.customSlave.skills;
				if (V.customSlave.sex === 3) {
					delivery.dick = V.customSlave.dick;
					delivery.balls = V.customSlave.balls;
					delivery.scrotum = delivery.balls;
					delivery.foreskin = delivery.dick;
					if (delivery.dick === 0) {
						delivery.clit = V.customSlave.clit;
						delivery.foreskin = delivery.clit;
					}
				} else {
					delivery.clit = V.customSlave.clit;
				}
			}

			/* I have no clue what I'm doing here */
			if (V.customSlave.heightMod === "greatly below average") {
				delivery.height = Height.random(delivery, {skew: -5, spread: 0.15, limitMult: [-5, -2]});
			} else if (V.customSlave.heightMod === "below average") {
				delivery.height = Height.random(delivery, {skew: -1, limitMult: [-2, 0]});
			} else if (V.customSlave.heightMod === "normal") {
				delivery.height = Height.random(delivery, {limitMult: [-1, 1]});
			} else if (V.customSlave.heightMod === "above average") {
				delivery.height = Height.random(delivery, {skew: 1, limitMult: [0, 2]});
			} else {
				delivery.height = Height.random(delivery, {skew: 5, spread: 0.15, limitMult: [2, 5]});
			}

			if (V.customSlave.intelligence === 3) {
				delivery.intelligence = random(96, 100);
			} else if (V.customSlave.intelligence === 2) {
				delivery.intelligence = random(51, 95);
			} else if (V.customSlave.intelligence === 1) {
				delivery.intelligence = random(15, 50);
			} else if (V.customSlave.intelligence === -1) {
				delivery.intelligence = random(-50, -16);
			} else if (V.customSlave.intelligence === -2) {
				delivery.intelligence = random(-95, -51);
			} else if (V.customSlave.intelligence === -3) {
				delivery.intelligence = random(-100, -96);
			} else {
				delivery.intelligence = random(-15, 15);
			}
			delivery.intelligenceImplant = V.customSlave.intelligenceImplant;

			if (V.customSlave.analVirgin === 0) {
				delivery.anus = V.customSlave.analVirgin;
			}
			delivery.voice = V.customSlave.voice >= 0 ? V.customSlave.voice : random(0, 3);
			setHealth(delivery, V.customSlave.health * 80, 0, 0, 0, 0);
			delivery.muscles = V.customSlave.muscles;
			delivery.weight = V.customSlave.weight;
			delivery.face = V.customSlave.face;
			delivery.lips = V.customSlave.lips;
			if (V.customSlave.skin !== "left natural") {
				delivery.origSkin = V.customSlave.skin;
				delivery.skin = getGeneticSkinColor(delivery);
			}
			delivery.boobs = V.customSlave.boobs;
			delivery.butt = V.customSlave.butt;
			delivery.skill.anal = V.customSlave.skills;
			delivery.skill.oral = V.customSlave.skills;
			delivery.skill.entertainment = V.customSlave.skill.whore;
			delivery.skill.whoring = V.customSlave.skill.whore;
			delivery.skill.combat = V.customSlave.skill.combat;
			delivery.eye.left.vision = V.customSlave.eye.left.vision;
			delivery.eye.right.vision = V.customSlave.eye.right.vision;
			delivery.hears = V.customSlave.hears;
			delivery.smells = V.customSlave.smells;
			delivery.tastes = V.customSlave.tastes;
			delivery.arm = V.customSlave.arm;
			delivery.leg = V.customSlave.leg;
			delivery.weekAcquired = V.week;
			delivery.origin = "You purchased $him by special order.";
			delivery.career = "a slave";
			delivery.sexualFlaw = either("none");
			delivery.behavioralFlaw = either("none");
			delivery.devotion = random(-10, 10);
			delivery.trust = random(-10, 10);
			return delivery;
		}
	}
};

repo_name: Banyanael/fc

license: mit


code:
App.Events.SEFcnnStation = class SEFcnnStation extends App.Events.BaseEvent {
	eventPrerequisites() {
		return [
			() => V.rivalOwner === 0,
			() => V.seeFCNN === 1,
			() => V.FCNNstation === 0,
			() => V.week > 95,
			() => V.cash > 200000,
			() => V.rep > 7500
		];
	}

	execute(node) {
		V.encyclopedia = "FCTV";
		V.FCNNstation = -1;

		const cost = 100000;
		const {girlP} = getPronouns(V.PC).appendSuffix("P");
		App.Events.addParagraph(node, [`One of the first groups to take advantage of the Free Cities' nearly nonexistent regulations for media and communications was the Free Cities News Network. As one of the few stations covering news within the Free Cities, and the only one doing so without any form of censorship, FCNN quickly became one the most popular news networks in the world. Presently, however, the network's future looks grim. Its reluctance on portraying explicitly pornographic content has lead to plummeting audience figures, especially in comparison to the upstart 8HGG Inc. media empire. In addition, governments within and outside the Free Cities have become increasingly restrictive towards the press, to the point that many FCNN branches have been effectively silenced.`]);

		App.Events.addParagraph(node, [`This is the situation when you receive a personal video call from the network's beleaguered president. The former FCNN headquarters has been outright destroyed for reporting on its host nation's human rights abuses, and they're hoping to relocate to ${V.arcologies[0].name}. "We are, of course, in dire financial straits," the president nervously explains, "So we'll need a small subsidy to establish our new headquarters. Probably, oh, let's say... ${cashFormat(cost)} or so?" He flinches while forcing a grin.`]);

		App.Events.addParagraph(node, [`You ponder their proposal to yourself. ${(V.seeFCNN === 1) ? `While you're not exactly a FCNN fan${girlP},` : `Though you may not listen to FCNN regularly,`} and the price certainly seems outrageous, accepting the offer would likely be a boost to your public reputation, as well as the local economy. The network is clearly at the end of their rope; the fact they would even ask for money beforehand is proof enough of that. If you don't accept their offer now, they'll probably go bankrupt or worse before you can get another chance to.`]);

		const choices = [];
		if (V.cash > cost) {
			choices.push(new App.Events.Result(`Accept`, accept));
		} else {
			choices.push(new App.Events.Result(null, null, `You cannot afford the asking price`));
		}

		choices.push(new App.Events.Result(`Decline`, decline));
		App.Events.addResponses(node, choices);

		function accept() {
			cashX(forceNeg(cost), "capEx");
			V.arcologies[0].prosperity += 2;
			V.FCNNstation = 1;
			return `You accept the FCNN president's offer. He looks like he's about to burst into tears after hearing this, especially since you offer no caveats as well, but struggles to maintain a professional composure regardless. Before the week is over, FCNN has established their new headquarters in ${V.arcologies[0].name}.`;
		}

		function decline() {
			V.FCNNstation = -1;
			return `You decline the FCNN president's offer. There's very little change in his expression; he was probably expecting this response. He accepts your decision, thanks you for your time, and unenthusiastically claims the network will soldier on regardless.`;
		}
	}
};


code:
App.Events.SEFctvInstall = class SEFctvInstall extends App.Events.BaseEvent {
	eventPrerequisites() {
		return [
			() => App.Events.effectiveWeek() >= 5,
			() => V.FCTV.receiver === -1
		];
	}

	execute(node) {
		V.encyclopedia = "FCTV";
		V.FCTV.receiver = 0;
		App.Events.addParagraph(node, [`You've been sitting in your office into the early afternoon going over bothersome lease documents that need your approval. When you take a break to look out the window, ${V.assistant.name} speaks up. "${properTitle()}, you have received an approval welcome packet from 8HGG Inc. in regards to Free Cities TV. It seems that they've determined that ${V.arcologies[0].name} is now sufficiently developed enough to warrant a FCTV-Citizen connection. All the details and contracts necessary are included in the packet. From there, a receiver will need to be built onto ${V.arcologies[0].name} in order to access FCTV."`]);

		App.Events.addParagraph(node, [`You browse the guide: home shopping networks, random dramas, how-to shows and a myriad of other things. Of more interest are some of the programs showing glimpses into foreign arcologies and how they are using the service to help mold society.`]);

		App.UI.DOM.appendNewElement("p", node, `While FCTV attempts to exclude any dick-based, pregnancy, hyperpregnancy, and extreme content based on your settings, it may still hint at that content, especially the more mundane of it. If you wish to be absolutely sure, don't watch FCTV or do not install the receiver.`, "note");
	}
};


code:
App.Events.SEfctvRemote = class SEfctvRemote extends App.Events.BaseEvent {
	constructor(actors, params) {
		super(actors, params);
	}

	eventPrerequisites() {
		return [
			() => V.FCTV.receiver > 0,
			() => V.FCTV.pcViewership.frequency !== -1,
			() => V.FCTV.pcViewership.count === 0,
			() => V.week > 50,
			() => V.FCTV.remote < 2,
		];
	}

	execute(node) {
		V.encyclopedia = "FCTV";
		let r = [];

		V.FCTV.remote = 2;

		const tech = GenerateNewSlave(null, {
			minAge: 25, maxAge: 35, ageOverridesPedoMode: 1, race: "nonslave", disableDisability: 1
		});

		tech.devotion = 0;
		tech.trust = 0;
		tech.muscles = 60;
		tech.lips = 35;
		tech.origin = "You enslaved $him for poor customer service as an FCTV tech.";
		tech.career = "an installation technician";
		tech.behavioralFlaw = "arrogant";
		tech.markings = "none";
		tech.hLength = 10;
		tech.eyewear = "glasses";
		tech.clothes = "conservative clothing";
		tech.shoes = "flats";
		setHealth(tech, jsRandom(60, 80));
		if (tech.weight > 130) {
			tech.weight -= 100;
			tech.waist = jsRandom(-10, 50);
		}
		if (tech.dick > 0) {
			tech.boobs = 0;
			tech.butt = 0;
			// slave.hStyle = "messy";
		} else {
			tech.hStyle = "ponytail";
		}

		App.Events.drawEventArt(node, tech);
		const {
			He, His,
			he, his, him, himself
		} = getPronouns(tech);
		const {
			heA
		} = getPronouns(assistant.pronouns().main).appendSuffix("A");
		r.push(`You have a gap in your schedule in the morning, and decide to watch some`);
		if (S.Concubine) {
			r.push(
				`FCTV with your concubine,`,
				App.UI.DOM.makeElement("span", `${S.Concubine.slaveName}.`, ["slave", "name", "simple"])
			);
		} else {
			r.push(`FCTV.`);
		}
		r.push(`No sooner do you begin to watch a random show, than you have a notification that someone is here to see you. It seems to be a tech of some sort, complete with a small utility drone. A camera reveals the back of ${his} shirt, on which is written in block letters "FCTV SERVICE." Incredible. How do these people always find the worst time to stop in?`);
		if (V.assistant.personality > 0) {
			r.push(`Your assistant shrugs. At a gesture from you, ${heA} lets ${him} in.`);
		} else {
			r.push(`You push a button to allow ${him} to come in.`);
		}
		r.push(`This had better be good.`);
		App.Events.addParagraph(node, r);

		r = [];
		r.push(`Presently, the tech enters the room and asks how your FCTV product is working. You tersely reply that it is fine,`);
		if (V.FCTV.remote === 1) {
			r.push(`although you're annoyed you had to purchase your own remote,`);
		} else {
			r.push(`although you find the random nature of the shows a little annoying,`);
		}
		r.push(`then ask the tech to cut to the point. ${He} shifts from one foot to the other, and then sheepishly admits that the service comes with a free remote that allows you to change the channels. Incredible! Why didn't you receive one? "It's, uh, 8HGG Inc. policy to distribute remotes only after a trial period." ${capFirstChar(V.assistant.name)} quietly notifies you that "${He}'s lying. We've had no notification from 8HGG Inc. of a visit. It's definitely the same tech as last time; ${he}'s trying to cover up ${his} mistake on a big contract. They don't know ${he}'s here."`);
		App.Events.addParagraph(node, r);

		r = [];
		r.push(`${He} unboxes the new remote and turns ${his} back to you, eagerly demonstrating how you can use it to watch any show you want. This could be your chance to turn the tables on FCTV and get some special "customer support" of your own.`);
		App.Events.addParagraph(node, r);

		App.Events.addResponses(node, [new App.Events.Result(`"Upgrade" the tech for a little humiliation`, upgrade)]);

		function upgrade() {
			const frag = new DocumentFragment();
			let r = [];
			/* set up customer */
			const genParam = {
				minAge: 25, maxAge: 35, ageOverridesPedoMode: 1, race: "nonslave", disableDisability: 1
			};
			const customer = GenerateNewSlave((V.seeDicks > random(1, 99)) ? "XY" : "XX", genParam);
			customer.devotion = 0;
			customer.trust = 0;
			setHealth(customer, jsRandom(60, 80));
			customer.muscles = 60;
			if (customer.weight > 130) {
				customer.weight -= 100;
				customer.waist = random(-10, 50);
			}
			if (customer.dick > 0) {
				customer.dick = 8;
				customer.boobs = 0;
				customer.butt = 0;
				customer.hLength = 10;
				customer.clothes = "spats and a tank top";
			} else {
				customer.boobs = 1000;
				customer.butt = 3;
				customer.hLength = 30;
				customer.clothes = "sport shorts and a sports bra";
			}

			customer.behavioralFlaw = "arrogant";
			customer.markings = "none";
			customer.shoes = "flats";
			const {
				He2,
				he2, him2, his2, woman2
			} = getPronouns(customer).appendSuffix("2");

			/* set up tech */
			tech.piercing.genitals.weight = 2;
			tech.piercing.genitals.smart = true;
			let backTat;
			if (V.seeDicks === 0) {
				backTat = "clits";
			} else if (V.seeDicks === 100) {
				backTat = "dicks";
			} else {
				backTat = "clits and dicks";
			}
			tech.backTat = `'FCTV SERVICE for ${backTat}' is tattooed across $his upper back.`;
			tech.stampTat = "'Shove that upgraded package here' is tattooed above $his rear.";
			cashX(forceNeg((V.modCost * 2) + V.SPcost), "slaveMod", tech); // two tats and a smart piercing

			r.push(`With a barely perceptible signal to ${V.assistant.name}, ${his} drone whirs to a stop and begins to fall to the floor. Before it lands, a dart hits ${him} in the neck. ${He} collapses into darkness.`);
			App.Events.addParagraph(frag, r);

			r = [];
			r.push(`As the tech wakes up ${he} finds ${himself} resting on your couch, with you looking`);
			if (hasAnyEyes(tech)) {
				r.push(`into ${his} ${hasBothEyes(tech) ? "eyes" : "eye"}`);
			} else {
				r.push(`at ${him}`);
			}
			r.push(`with concern. ${He} winces in pain and asks what happened. You gravely inform ${him} that ${he} must been working very hard and may have been dehydrated: ${he} passed out. ${His} back was quite bruised but other than some nausea, your systems report ${he} should be fine. You encourage ${him} to keep up ${his} fluids, then hand ${him} back ${his} communicator and mention it looks like ${he} is going to be late for ${his} other appointment. With a panicked look on ${his} face the tech thanks you, seizes ${his} device and heads out the door followed by ${his} drone. "I haven't seen that much debt outside of a slave in quite some time," ${V.assistant.name} remarks. "${He}'s fortunate to have that job."`);
			App.Events.addParagraph(frag, r);

			r = [];
			r.push(`The tech, ${tech.slaveName}, shoves ${his} way through the crowd as quickly as ${he} can. In front of ${him} no one pays much attention, but the crowd behind begins to titter and even point and laugh. Oblivious, ${tech.slaveName} arrives at the desired address and pauses to catch a breath. Watching from the eyes of ${his} drone, you can tell ${his} back is stiff and ${his} running had been uncomfortable. You can't help but laugh at ${his} shirt. Unknown to ${tech.slaveName}, the entire back of ${his} shirt has been replaced with a clear panel of similar feeling material. It clearly shows ${his} ${tech.skin} skin, as well as ${his} new tattoo. Like the lettered shirt it replaced it also says "FCTV SERVICE" in block letters, but below that it reads "for ${backTat}." You finger your new TV remote, as well as a second remote designed for... other devices.`);
			App.Events.addParagraph(frag, r);

			r = [];
			if (V.seeImages > 0) {
				App.Events.drawEventArt(frag, [tech, customer]);
			}
			r.push(`The door opens, and one of your citizens appears. ${tech.slaveName} doesn't know it, but you've made a small change to ${his} calendar. ${His} new client has a`);
			if (customer.dick > 0) {
				r.push(`legendarily large dick,`);
			} else {
				r.push(`legendary love of anal,`);
			}
			r.push(`even for ${V.arcologies[0].name}. The tech loses ${his} professional façade for a moment, glancing at the customer's`);
			if (customer.dick > 0) {
				r.push(`enormous bulge`);
			} else {
				r.push(`hips`);
			}
			r.push(`before gulping and gluing ${his} eyes on the customer's face. "Hi, I'm ${tech.slaveName} from FCTV; I'm here to take a look at your receiver?"`);
			App.Events.addParagraph(frag, r);

			r = [];
			r.push(
				Spoken(customer, `"Certainly, it's in the bedroom on the bottom shelf."`),
				`As the tech takes a step forward you touch the first button on your other remote. The tech freezes. You know from the work you did that ${he} would be experiencing a puzzling throbbing or buzzing sensation at the moment. ${His} smart piercing was installed with a few blockers to pain, but ${his} sense of touch should be very acute, even heightened with some local aphrodisiacs. There is also a vibe deep inside ${his} ass, with a glue that will take some time to wear off. `
			);
			if (tech.prostate) {
				r.push(`Its buzzing should be impacting ${his} prostrate directly, albeit subtly.`);
			}
			App.Events.addParagraph(frag, r);

			r = [];
			r.push(
				Spoken(customer, `"Are you OK, ${(tech.dick > 0) ? "sir" : "ma'am"}?"`),
				`The customer looks concerned.`,
				Spoken(tech, `"It's... it's nothing."`),
				`The tech replies. What on earth was happening? ${He} enters the house and follows the customer inside. You can see everything from the drone, and the tech seems to struggle a bit going up the stairs. The customer gestures inside a door,`,
				Spoken(customer, `"It's just in here, like I said, bottom shelf."`),
				Spoken(tech, `"Thank you!"`),
				`the tech responds, and you notice ${him} checking out ${his2} `
			);
			if (customer.dick > 0) {
				r.push(`crotch`);
			} else {
				r.push(`hips`);
			}
			r.push(
				`a second time. This time ${he}'s a little slower to meet ${his} customer's eyes. It's difficult to tell from the low quality of the drone camera, but you think you can begin to see a question forming there. As the tech passes ${him2} and enters the room, even you can hear the sharp intake of breath from the customer.`,
				Spoken(customer, `"Everything OK?"`),
				`${tech.slaveName} asks, turning stiffly.`,
				Spoken(tech, `"Uh, sure. Yeah."`),
				`The customer responds. The tech turns back to the TV and the customer stares at ${his} back. You move the drone into the room and subtly find a good angle, then bump up the vibration a few levels with the remote.`
			);
			App.Events.addParagraph(frag, r);

			r = [];
			r.push(`${tech.slaveName} stands perfectly still for a moment, clearly not sure what was going on. ${He}'d never been dehydrated before, and surely it always made you feel hot and dizzy. The head of the arcology had mentioned nausea; did that cover this odd feeling down below? ${He} felt... horny.`);
			App.Events.addParagraph(frag, r);

			r = [];
			r.push(`The customer quietly places a hand on ${his} shoulder and the tech jumps several`);
			if (V.showInches === 2) {
				r.push(`inches.`);
			} else {
				r.push(`centimeters.`);
			}
			r.push(
				Spoken(customer, `"Like I said, bottom shelf,"`),
				`${he2} repeats softly in ${his} ear.`
			);
			App.Events.addParagraph(frag, r);

			r = [];
			r.push(
				`The tech slowly bends toward the floor, and as ${his} modified shirt rides up and ${his} pants ride down, they reveal your second modification: a tramp stamp that reads "Shove that upgraded package here." The customer whistles and in an instant grabs a handful of ass. Perfect! The tech tries to stand up and object:`,
				Spoken(tech, `"Excuse me ${(customer.dick > 0) ? "sir" : "ma'am"}, what...!"`),
				Spoken(customer, `"Hold on, baby,"`),
				`the confused customer replies and you pick that moment to hit the third button.`
			);
			App.Events.addParagraph(frag, r);

			r = [];
			r.push(
				`Channel 14 had fascinated you. Thanks to this bumbling tech you hadn't been able to see it very often, but the idea of an aphrodisiac that took effect instantly and then quickly vanished seemed incredibly useful to you. How fortunate that it had arrived in time for this moment. The tech would have felt a fairly large liquid 'splurt' from the vibe inside ${his} ass that would have been difficult to explain. Equally difficult to explain would be the now undeniably raging vibrations. But as ${he} turns ${his} head and you can see ${his} face on the camera, it's clear none of that matters.`,
				Spoken(tech, `"Please,"`),
				`the now flushed tech says.`,
				Spoken(tech, `"M...mm my ass."`)
			);
			App.Events.addParagraph(frag, r);

			r = [];
			if (customer.dick === 0) {
				r.push(
					Spoken(customer, `"Hmmm, I'm not sure I have the right`),
					App.UI.DOM.makeElement("span", Spoken(customer, "cable."), "note"),
					`The ${woman2} replies with a lewd smirk.`,
					Spoken(customer, `"Let me see what I can do."`),
					`The titanic plug ${he2} produces was clearly purchased from the FCTV shopping network, but from the fact it was still in the box ${he2} hadn't worked up the guts to try it ${himself} and hadn't had any other takers either.`
				);
				App.Events.addParagraph(frag, r);

				r = [];
				r.push(
					`Some part of the tech's mind is clearly alarmed by the size of the plug, but after a moment of shyness ${he} quickly drops ${his} pants and bends over.`,
					Spoken(customer, `"Now I want to make sure that the remote works correctly, so start testing it."`),
					`The bent over tech turns and begins cycling through porn, watching anal insertion after anal insertion.`,
					Spoken(customer, `"Annnnnd IN!"`),
					`the ${woman2} proclaims. ${He2} slowly grinds the plug home, ridges, bumps, warts and all. The tech winds up with ${his} nose pressed into the box, and ${his} lower back pressed into the TV, ${his} butt unable to go higher (or further from the intruder!) Then, with a slip you've seen many times, it slides home.`);
				App.Events.addParagraph(frag, r);

				r = [];
				r.push(
					Spoken(customer, `"Hmm, let me see. I think I have my OWN remote"`),
					`the ${woman2} says, as ${he2} leans back on ${his2} bed. Vibration sets in, strong enough that you can see ${tech.slaveName}'s ass quaking from your own suite. The ${woman2} leans further back and beings to masturbate, moving ${his2} eyes from the porn on the TV to the ass in front of ${his2}.`,
					Spoken(customer, `"Ahh,"`),
					`${he2} says with a bit of malice.`,
					Spoken(customer, `"I think..."`),
					`${he2} stretches,`,
					Spoken(customer, `"I think your box needs an`),
					App.UI.DOM.makeElement("span", Spoken(customer, "update."), "note"),
					`This time you have the drone in place to see the button ${he2} presses, so you know it's "Fluid: All." You aren't sure how much "all" is, but the dildo is enormous, and you can see the tech's stomach distend. They both come at the same time.`);
			} else {
				r.push(`The customer doesn't even blink. In an instant both pants are down and ${he2}'s inside. There's no lube at first, but as you watch the scene unfolding in front of you it seems likely that some aphrodisiac is leaking out and helping. You hope it's safe for your citizen. The tech, of course, can get fucked. And ${he} is.`);
				App.Events.addParagraph(frag, r);

				r = [];
				r.push(
					Spoken(customer, `"Uh, that`),
					App.UI.DOM.makeElement("span", Spoken(customer, `virgin ass!"`), ["virginity", "loss"]),
					`the customer exclaims.`,
					Spoken(customer, `"How's THIS for an upgraded package. Last time I had a billing problem you folks told me where to shove it. Well. Here! It! Goes!"`),
					`From the way they collapse over each other, it seems they orgasmed at about the same time.`
				);
			}
			App.Events.addParagraph(frag, r);

			r = [];
			tech.anus = 1;
			seX(tech, "anal", "public", "penetrative");
			r.push(`Time passes...`);
			App.Events.addParagraph(frag, r);

			r = [];
			r.push(`It seems the aphrodisiacs are wearing off, and the tech is stirring. Sitting up, ${he} looks confused. Time for a call.`);
			App.Events.addParagraph(frag, r);

			r = [];
			r.push(`Once ${he} is standing back in your office, you sternly show ${him} portions of video, explaining how unprofessional ${his} behavior is and how deeply upset you are at the way your citizen was treated. You tell ${him} you know ${he} was on the clock, and you know ${he} was not supposed to be here, CERTAINLY not while getting fucked with a mockery of ${his} employer marked on ${his} back. ${He} begins to quake, and begs you to help ${him}. Nice to have the TV company begging you to help them, for once.`);
			App.Events.addParagraph(frag, r);

			const contractCost = 1000;
			const choices = [];
			if (V.cash >= contractCost) {
				choices.push(new App.Events.Result(`Enslave ${him}`, enslave));
				choices.push(new App.Events.Result(`Sentence ${him} to a day in a wall with a TV, then enslave ${him}`, stocks));
			} else {
				choices.push(new App.Events.Result(null, null, `Cannot afford the ${contractCost} to enslave`));
			}
			choices.push(new App.Events.Result(`Let ${him} go`, release));
			choices.push(new App.Events.Result(`Let ${him} go but release the footage`, releaseFootage));

			App.Events.addResponses(frag, choices);

			return frag;

			function enslave() {
				const frag = new DocumentFragment();
				let r = [];
				cashX(forceNeg(contractCost), "slaveTransfer", tech);
				r.push(`${tech.slaveName} knows ${he} has nowhere to turn. Sobbing, ${he} complies with the process.`);
				r.push(App.UI.newSlaveIntro(tech));

				App.Events.addParagraph(frag, r);
				return frag;
			}

			function stocks() {
				const frag = new DocumentFragment();
				let r = [];
				cashX(forceNeg(contractCost), "slaveTransfer", tech);

				r.push(
					`You can't possibly be the only one annoyed at FCTV customer service. You soon have ${him} bent over with ${his} upper half encased in a wall, and ${his} lower half along with ${his} "shove that upgraded package here" tramp stamp exposed to the entire arcology. A large monitor above ${his} ass ensures every detail of ${his} expressions are available, and aphrodisiacs ensure they are interesting. Long waits for tech support are common in this broken world, but even so, the queue that forms as the word gets out is quite impressive. ${He} spends a torturous day in the wall before being hauled in for enslavement, somewhat`,
					App.UI.DOM.makeElement("span", "the worse for wear", ["health", "dec"]),
					`and`,
					App.UI.DOM.makeElement("span", "acting oddly", ["flaw", "gain"]),
					`due to ${his} ordeal, bruises all over ${his} body, cum leaking from ${his}`,
					App.UI.DOM.makeElement("span", "loosened", ["virginity", "loss"])
				);
				if (tech.vagina > -1) {
					r.push(
						`anus and`,
						App.UI.DOM.makeElement("span", "fucked-out", ["virginity", "loss"]),
						`pussy.`
					);
				} else {
					r.push(`anus.`);
				}

				healthDamage(tech, 10);
				tech.behavioralFlaw = "odd";
				tech.sexualFlaw = "hates penetration";
				tech.anus = 2;
				const fuckCount = random(20, 35);
				seX(tech, "anal", "public", "penetrative", fuckCount);
				if (tech.vagina > -1) {
					if (tech.vagina < 2) {
						tech.vagina = 2;
					}
					if (isFertile(tech) && tech.eggType === "human") {
						r.push(knockMeUp(tech, 40, 2, -2));
					}
					seX(tech, "vaginal", "public", "penetrative", fuckCount * 2);
				}

				r.push(
					`The public`,
					App.UI.DOM.makeElement("span", "enjoys the fun.", ["reputation", "inc"])
				);
				if (V.FCTV.receiver <= 3) {
					r.push(`Frustrations released, they also seem more likely to watch FCTV.`);
					V.FCTV.receiver++;
				}
				repX(500, "event", tech);
				V.arcologies[0].prosperity += 2;
				r.push(App.UI.newSlaveIntro(tech));
				App.Events.addParagraph(frag, r);
				return frag;
			}

			function release() {
				return `You consider yourself well repaid for the fun you have had today, and dismiss the tech. ${He} seems incredulous for a second, and then incredibly thankful. ${He} hobbles out of the room as quickly as ${he} can, leaking a little fluid with every step. Naturally, you remember the vibe as soon as ${he} leaves. Oh well, it will work itself loose eventually, and you have plenty more. A fair exchange, really — one small forgotten tech product for another.`;
			}

			function releaseFootage() {
				const frag = new DocumentFragment();
				let r = [];
				r.push(`You know well that in`);
				if (V.arcologies[0].FSRomanRevivalist !== "unset") {
					r.push(`Roman days,`);
				} else if (V.arcologies[0].FSNeoImperialist !== "unset") {
					r.push(`the Dark Ages,`);
				} else if (V.arcologies[0].FSAztecRevivalist !== "unset") {
					r.push(`Aztec days,`);
				} else if (V.arcologies[0].FSEgyptianRevivalist !== "unset") {
					r.push(`Ancient Egypt,`);
				} else if (V.arcologies[0].FSEdoRevivalist !== "unset") {
					r.push(`the Edo period,`);
				} else if (V.arcologies[0].FSArabianRevivalist !== "unset") {
					r.push(`the Caliphates,`);
				} else if (V.arcologies[0].FSChineseRevivalist !== "unset") {
					r.push(`imperial China,`);
				} else {
					r.push(`ancient times,`);
				}
				r.push(`exile was the worst punishment. You let ${him} know you have no intention of helping ${him}. In fact, you plan to release video of ${his} scandalous behavior on the web. As ${his} knees quake you again show ${him} slightly doctored video of ${him} eagerly receiving ${his} tattoos, and then undoctored video of ${him} enjoying ${his} "customer service." You doubt 8HGG Inc. will be pleased with ${his} enthusiasm for the brand. But, it's not your problem. Begging for mercy, the tech trails a small stream of fluids across the floor as your drones carry ${him} out. A smaller drone follows along cleaning up the mess. As the doors shut, you set the slave remote on max and break it in half over the trash.`);

				App.Events.addParagraph(frag, r);
				return frag;
			}
		}
	}
};


code:
App.Events.SEfctvWatch = class SEfctvWatch extends App.Events.BaseEvent {
	constructor(actors, params) {
		super(actors, params);
	}

	eventPrerequisites() {
		return [
			() => V.FCTV.receiver > 0,
			() => V.FCTV.pcViewership.frequency !== -1,
			() => V.FCTV.pcViewership.count === 0,
			() => !(V.week > 50 && V.FCTV.remote < 2) // Run remote event instead
		];
	}

	execute(node) {
		V.encyclopedia = "FCTV";
		const TVDiv = App.UI.DOM.appendNewElement("div", node, watch());
		TVDiv.id = "fctv-watch";

		function watch({usedRemote = 0, seeAll = 0, selectedChannel = 0} = {}) {
			const frag = new DocumentFragment();
			let p;
			let div;
			let span;
			V.FCTV.pcViewership.count = V.FCTV.pcViewership.frequency;
			let possibleChannels = FCTV.channels();

			p = document.createElement("p");

			p.append(`Tired after a long day, you tell `);
			if (S.Concubine) {
				p.append(`your concubine: `);
				App.UI.DOM.appendNewElement("span", p, S.Concubine.slaveName, "pink");
			} else {
				p.append(V.assistant.name);
			}
			p.append(` to turn on the TV and `);
			if (!usedRemote) {
				p.append(`set FCTV to find a random show. Your larger-than-life screen flashes on, and is soon playing content from the popular streaming service. `);
				if (V.cheatMode > 0 || (V.debugMode > 0 && V.debugModeEventSelection > 0) || V.FCTV.remote) {
					// Create "Use remote" link. Hide once clicked.
					span = document.createElement("span");
					span.id = "use-remote";
					span.append(
						App.UI.DOM.link(
							"Use your remote",
							() => {
								usedRemote = 1;
								jQuery("#remote").empty().append(createRemote());
								jQuery("#use-remote").empty();
							}
						)
					);
					p.append(span);
				}
				p.append(randomShow());
			} else if (usedRemote && (V.cheatMode > 0 || (V.debugMode > 0 && V.debugModeEventSelection > 0) || V.FCTV.remote)) {
				p.append(`bring you the remote so you can choose whatever show you find interesting. `);
				if (selectedChannel === V.FCTV.channel.last) {
					App.UI.DOM.appendNewElement("div", p, `You tuned into this channel last week, you may want to choose something else.`);
				}
				if (seeAll) {
					div = document.createElement("div");
					div.append(`There is an audible tone from your screen, which then displays a message: `);
					App.UI.DOM.appendNewElement("span", div, `Showing all content, for testing purposes.`, "note");
					p.append(div);
				}
			}

			frag.append(p);

			p = document.createElement("p");
			p.classList.add("FCTV");
			span = document.createElement("span");
			span.id = "remote";
			if (usedRemote && (V.cheatMode > 0 || (V.debugMode > 0 && V.debugModeEventSelection > 0) || V.FCTV.remote)) {
				span.append(createRemote());
			}
			p.append(span);
			if (usedRemote) {
				p.append(`You select `);
			} else {
				p.append(`It looks like the random function chose `);
			}
			App.UI.DOM.appendNewElement("span", p, `channel number: ${selectedChannel}`, "bold");

			// A little glue to get unique data based stuff to stick.
			if (selectedChannel === 16) {
				p.append(`. `);
			} else {
				p.append(`, `);
				if (selectedChannel === 11 && usedRemote) {
					p.append(`for some foolish reason`);
				}
			}
			p.append(displayShow());
			frag.append(p);
			return frag;

			function refresh({usedRemote = 0, seeAll = 0, selectedChannel = 0} = {}) {
				jQuery(TVDiv).empty().append(watch.apply(this, arguments));
			}

			/** Creates a remote control for FCTV
			 * @returns {HTMLParagraphElement}
			 */
			function createRemote() {
				const p = document.createElement("p");
				p.classList.add("fctv-remote");
				let div;
				let span;
				const buttons = [];

				for (const i of possibleChannels) {
					if (showChannel(i).canSelect > 0) {
						if (selectedChannel !== i) { // Selected button
							buttons.push(
								App.UI.DOM.link(
									i.toFixed(0),
									() => {
										refresh({usedRemote: 1, seeAll: seeAll, selectedChannel: i});
									}
								)
							);
						} else { // Channel you can choose
							span = document.createElement("span");
							span.classList.add("white");
							span.style.fontWeight = "bold";
							span.append(
								App.UI.DOM.link(
									i.toFixed(0),
									() => {
										refresh({usedRemote: 1, seeAll: seeAll, selectedChannel: i});
									},
									[],
									"",
									`Current channel`
								)
							);
							buttons.push(span);
						}
					} else { // Channel you cannot choose
						buttons.push(
							App.UI.DOM.disabledLink(i.toFixed(0), [showChannel(i).text])
						);
					}
				}

				buttons.splice(4, 0, App.UI.DOM.makeElement("span", "4")); // 4 is no longer a real channel, so put in a dummy button. 404, channel not found.

				div = document.createElement("div");
				div.classList.add("fctv-remote-numbers", /* "fctv-remote-button" */);
				for (const button of buttons) {
					div.append(button);
				}
				p.append(div);
				App.UI.DOM.appendNewElement(
					"div",
					p,
					App.UI.DOM.link(
						`Random`,
						() => {
							refresh({usedRemote: 0, seeAll: seeAll, selectedChannel: selectedChannel});
						}
					),
					["fctv-remote-button"]
				);
				if (V.debugMode > 0 && V.debugModeEventSelection > 0) {
					App.UI.DOM.appendNewElement(
						"div",
						p,
						App.UI.DOM.link(
							`Toggle inappropriate`,
							() => {
								if (seeAll) {
									seeAll = 0;
								} else {
									seeAll = 1;
								}
								refresh({usedRemote: usedRemote, seeAll: seeAll, selectedChannel: selectedChannel});
							}
						),
						["fctv-remote-button"]
					);
				}
				return p;
			}

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

				if (!usedRemote) {
					const channels = FCTV.channels();
					channels.push(3); // Double chance for slave sale. Replaces old channel 4.
					for (let i = 0; ; i++) {
						// Roll for a channel
						const channel = _.sample(channels);
						// See if we can show it
						const x = showChannel(channel);
						if (x.canSelect === -1) {
							App.UI.DOM.appendNewElement("p", frag, channelFailed(x.text));
						} else {
							selectedChannel = channel;
							break;
						}

						// Three strikes, then move on
						if (i > 2) {
							App.UI.DOM.appendNewElement("p", frag, `It looks like there is simply nothing on FCTV tonight worth watching.`);
							return frag;
						}
					}
				}
				return frag;
			}

			function showChannel(i = 1) {
				let x = {canSelect: 1};
				if (seeAll) {
					return x;
				}
				if (App.Data.FCTV.channels.hasOwnProperty(i)) {
					if (App.Data.FCTV.channels[i].hasOwnProperty("tags")) {
						x = checkTags(App.Data.FCTV.channels[i].tags);
					}
					if (App.Data.FCTV.channels[i].hasOwnProperty("disableSelection")) {
						if (usedRemote !== 0) {
							x.canSelect = -1;
						}
						x.text = `This channel appears at random times`;
					}
				} else {
					throw Error(`Channel "${i}" does not exist`);
				}
				if (i === 11) {
					if (V.purchasedSagBGone && V.FCTV.channel[num(i, true)] > 2) {
						x.canSelect = -1;
						x.text = `Product purchase detected, skipping commercials`;
					}
				}
				return x;
			}

			/**
			 * Text to frame if content won't work due to tags.
			 * @param {string} text Reason this channel/episode can't be shown
			 * @returns {Node}
			 */
			function channelFailed(text) {
				const frag = new DocumentFragment;
				frag.append(`A notification is shown: `);
				App.UI.DOM.appendNewElement("span", frag, text, "note");
				frag.append(`, changing program.`);
				return frag;
			}

			/**
			 * Displays just the channel itself, including art
			 * @returns {Node}
			 */
			function displayShow() {
				const frag = new DocumentFragment();

				/** @type {FctvChannel} */
				const channel = App.Data.FCTV.channels[selectedChannel];
				const epToShow = getEpisode(selectedChannel);

				// Fail code, so we fail
				if (epToShow === -1) {
					frag.append(`no valid episodes`);
					return frag;
				}

				// Increment the viewing record for this channel
				V.FCTV.channel[num(selectedChannel, true)]++;

				// Slave, if needed. Hosts and market slaves.
				let slave;
				if (channel.episode[epToShow].slaves) {
					slave = channel.episode[epToShow].slaves[0];
					if (!channel.disableSelection) { // Art for the slave market will be shown in longSlave
						App.Events.drawEventArt(frag, channel.episode[epToShow].slaves);
					}
				}
				if (channel.intro) {
					$(frag).append(channel.intro);
				}
				const episodeText = channel.episode[epToShow].text;
				if (episodeText) {
					if (typeof episodeText === 'function') {
						$(frag).wiki(episodeText(slave));
					} else {
						$(frag).wiki(episodeText);
					}
				}
				if (channel.outro) {
					if (typeof channel.outro === 'function') {
						frag.append(channel.outro(slave, epToShow));
					} else {
						frag.append(channel.outro);
					}
				}
				V.FCTV.channel.last = selectedChannel;
				return frag;

				function getEpisode(sel) {
					let epToShow = -1; // -1 is the fail code.
					const epsArray = [];
					/** @type {FctvChannel} */
					const channel = App.Data.FCTV.channels[sel];
					const viewedCount = V.FCTV.channel[num(sel, true)] || 0;

					// Produce an array of episodes we can watch.
					for (let i = 0; i < App.Data.FCTV.channels[sel].episode.length; i++) {
						const ep = App.Data.FCTV.channels[sel].episode[i];
						if (ep.tags) {
							const x = checkTags(ep.tags);
							if (x.canSelect !== -1) {
								epsArray.push(i);
							}
						} else {
							epsArray.push(i);
						}
					}
					const availableEp = epsArray.length;
					if (epsArray.length === 0) {
						return -1; // Nothing to watch, fail.
					}

					if (availableEp > viewedCount) { // If we watched ep 0 last time, our view count will be 1. Now we can use 1 as our new ep, etc.
						epToShow = viewedCount;
					} else if (channel.loop === true) {
						// How many times have we been through this series. Let's say we watched 10 episodes, but there are only 3 uniques [0,1,2].
						const watchedEntireSeason = Math.trunc(viewedCount / availableEp); // we went through 3 times fully
						epToShow = viewedCount - (watchedEntireSeason * availableEp); // 10 - 3 seasons (9) is 1. So our last episode was the first, 0 in the array. And 1 is the next ep!
					} else { // We have seen all the episodes, return a random one
						epToShow = jsRandom(0, availableEp - 1);
					}
					if (epToShow === -1) {
						return epToShow;
					}
					return epsArray[epToShow];
				}
			}

			/**
			 * Checks the tags on a channel or an episode to determine if it can be shown.
			 * @param {FctvTags} tags
			 * @returns {Object} x
			 */
			function checkTags(tags) {
				let x = {
					canSelect: 1,
				};
				for (const tag in tags) {
					if (tag) {
						switch (tag) {
							case "hyperPreg":
								if (!V.seeHyperPreg) {
									x.canSelect = -1;
									x.text = `Too much happiness detected`;
								}
								break;
							case "preg":
								if (!V.seePreg) {
									x.canSelect = -1;
									x.text = `Too much baking detected`;
								}
								break;
							case "extreme":
								if (!V.seeExtreme) {
									x.canSelect = -1;
									x.text = `Too much hugging detected`;
								}
								break;
							case "dicks":
								if (!V.seeDicks && !V.makeDicks) {
									x.canSelect = -1;
									x.text = `Too many hot dogs detected`;
								}
								break;
							case "incest":
								if (!V.seeIncest && tag === "incest") {
									x.canSelect = -1;
									x.text = `Too much familiarity detected`;
								}
								break;
							case "loli":
								if (V.minimumSlaveAge > 13 && tag === "loli") {
									x.canSelect = -1;
									x.text = `Actor not vintage enough`;
								}
								break;
							default:
								throw Error(`Tag "${tag}" unknown for ${tags}`);
						}
					}
				}
				return x;
			}
		}
	}
};