code:
/**
 * @param {App.Entity.SlaveState} slave
 * @param {"canine"|"hooved"|"feline"} type
 * @param {FC.SlaveActs} act
 * @returns {DocumentFragment}
 */
App.Interact.fAnimal = function(slave, type, act) {
	const frag = new DocumentFragment();

	const {
		He, His,
		he, him, his, girl
	} = getPronouns(slave);

	/** @enum {string} */
	const Acts = {
		VAGINAL: "vaginal",
		ANAL: "anal",
		ORAL: "oral",
	};

	const approvingFetishes = [Fetish.MASOCHIST, Fetish.HUMILIATION, Fetish.BESTIALITY, "perverted", "sinful"];	// not strictly fetishes, but approvingFetishesAndBehavioralQuirksAndSexualQuirks doesn't have the same ring to it

	/** @type {App.Entity.Animal} */
	const animal = getAnimal(V.active[type]);

	/** @type {0|1|2} */
	let hole;
	/** @type {string} */
	let fetishDesc;
	/** @type {() => string} */
	let orifice;

	const anAnimal = `${animal.articleAn} ${animal.name}`;
	const hasFuckedAnimals = slave.partners.has(-8);

	seX(slave, act, "animal");

	const slaveApproves =
		approvingFetishes.includes(slave.fetish) ||
		approvingFetishes.includes(slave.sexualQuirk) ||
		approvingFetishes.includes(slave.behavioralQuirk) ||
		slave.fetish === Fetish.BUTTSLUT && act === Acts.ANAL ||
		slave.fetish === Fetish.CUMSLUT && act === Acts.ORAL ||
		slave.sexualQuirk === "gagfuck queen" && act === Acts.ORAL;

	switch (act) {
		case Acts.ORAL:
			orifice = () => either("mouth", "throat");
			break;
		case Acts.VAGINAL:
			orifice = () => either("pussy", "cunt", "slit");
			hole = 0;
			break;
		case Acts.ANAL:
			orifice = () => either("asshole", "rectum");
			hole = 1;
			break;
		default:
			throw new Error(`Unexpected act type '${act}' in fAnimal()`);
	}

	if (slave.fetish === Fetish.CUMSLUT && act === Acts.ORAL) {
		fetishDesc = `getting to drink more cum`;
	} else if (slave.fetish === Fetish.HUMILIATION) {
		fetishDesc = `committing such a humiliating act`;
	} else if (slave.fetish === Fetish.BUTTSLUT && act === Acts.ANAL) {
		fetishDesc = `getting to take a cock up ${his} ass`;
	} else if (slave.fetish === Fetish.MASOCHIST) {
		fetishDesc = `committing such a painful act`;
	} else if (slave.sexualQuirk === "perverted") {
		fetishDesc = `committing such a perverted act`;
	} else if (slave.sexualQuirk === "gagfuck queen" && act === Acts.ORAL) {
		fetishDesc = `getting to suck more dick`;
	} else if (slave.behavioralQuirk === "sinful") {
		fetishDesc = `committing such a sinful act`;
	}

	const text = new SpacedTextAccumulator(frag);

	text.push(
		intro(),
		setup(),
		consummation(),
	);

	if (act === Acts.VAGINAL) {
		slave.vagina = Math.max(slave.vagina, animal.dick.size);
	} else if (act === Acts.ANAL) {
		// @ts-ignore
		slave.anus = Math.max(slave.anus, stretchedAnusSize(animal.dick.size));
	}

	if (act !== Acts.ORAL && canGetPregnant(slave) && canBreed(slave, animal)) {
		knockMeUp(slave, 5, hole, -8);
	}

	if (random(1, 100) > 100 + slave.devotion && slave.energy < 95) {
		text.push(slaveGainsFlaw());
	} else if (slave.devotion > 20) {
		text.push(slaveGainsQuirk());
	}
	if (random(100) > 10 &&
		slave.fetish === Fetish.NONE ||
		(!approvingFetishes.includes(slave.fetish) && slave.fetishStrength < 75)) {
		text.push(slaveGainsFetish());
	}

	if (V.postSexCleanUp) {
		text.push(cleanup());
	}

	text.toParagraph();

	return frag;

	// Text Functions

	function intro() {
		const text = [];

		if (canWalk(slave)) {
			text.push(`You call ${him} over and`);
		} else {
			text.push(`You order another slave to bring ${slave.slaveName} over. Once ${he} is situated, you`);
		}

		text.push(`tell ${him} you want to watch ${him} ${act === Acts.ORAL
			? `suck off`
			: act === Acts.VAGINAL
				? `get fucked by`
				: `get fucked in the ass by`} ${anAnimal}.`);

		if (slave.fetish === Fetish.MINDBROKEN) {
			text.push(`${slave.slaveName} nods ${his} head dumbly, ${his} eyes vacant${!canSee(slave) ? ` as always` : ``}.`);
		} else {
			if (slave.devotion > 50) {
				if (act === Acts.ORAL) {
					if (slaveApproves) {
						text.push(`${slave.slaveName}'s face visibly brightens at the prospect of ${fetishDesc}, even if it's ${anAnimal}${slave.fetish === Fetish.CUMSLUT ? `'s cum` : ` that ${he} has to suck off`}.`);
					} else {
						text.push(`${slave.slaveName} visibly blanches at the thought of having to suck down ${anAnimal}'s cum,`);
						if (!hasFuckedAnimals) {
							text.push(`especially because ${he}'s never fucked an animal before,`);
						}
						text.push(`but ${he} is so devoted to you that ${he} reluctantly agrees.`);
					}
				} else {
					if ((act === Acts.VAGINAL && slave.vagina > 0) ||
						(act === Acts.ANAL && slave.anus > 0)) {
						if (slaveApproves) {
							text.push(`${slave.slaveName}'s face visibly brightens at the thought of ${fetishDesc}, even if the dick is ${anAnimal}'s.`);
						} else {
							if (hasFuckedAnimals) {
								text.push(`This wouldn't be the first time ${he}'s had to fuck an animal, and ${he} so is willing to do absolutely anything for you that ${he} nonchalantly agrees.`);
							} else {
								text.push(`${slave.slaveName} looks visibly disturbed because ${he}'s never fucked an animal before, but is so attentive to your will that ${he} reluctantly agrees.`);
							}
						}
					} else {
						if (slaveApproves) {
							text.push(`${slave.slaveName}'s face visibly brightens at the thought of ${fetishDesc}, although ${he} seems a bit hesitant at the thought of giving ${his} virginity to an animal.`);
						} else {
							text.push(`${slave.slaveName} looks visibly shaken at the thought of having ${his} precious ${!canDoVaginal(slave) ? `anal ` : ``}virginity taken by an animal, but is so attentive to your will that ${he} ultimately agrees.`);
						}
					}
				}
			} else if (slave.devotion > 20) {
				if (act === Acts.ORAL) {
					if (slaveApproves) {
						text.push(`${slave.slaveName} isn't too keen on the idea of sucking off an animal, but the idea of ${fetishDesc} is enough to get ${him} to comply.`);
					} else {
						text.push(`${slave.slaveName} tries in vain to conceal ${his} horror at the thought of blowing an animal,`);
						if (!hasFuckedAnimals) {
							text.push(`especially because ${he}'s never fucked an animal before,`);
						}
						text.push(`but quickly regains ${his} composure.`);
					}
				} else {
					if (
						(act === Acts.VAGINAL && slave.vagina > 0) ||
							(act === Acts.ANAL && slave.anus > 0)
					) {
						if (slaveApproves) {
							text.push(`${slave.slaveName} doesn't seem terribly keen on the idea of fucking an animal ${hasFuckedAnimals ? `again` : ``}, but the thought of ${fetishDesc} seems to be enough to win ${him} over.`);
						} else {
							if (hasFuckedAnimals) {
								text.push(`This wouldn't be the first time ${he}'s had to fuck an animal, but you can tell ${he} still isn't exactly thrilled about the idea.`);
							} else {
								text.push(`${slave.slaveName} tries in vain to conceal ${his} horror at the thought of fucking an animal, but quickly regains ${his} composure.`);
							}
						}
					} else {
						if (slaveApproves) {
							text.push(`${slave.slaveName} clearly has some reservations about having ${his} ${act === Acts.ANAL ? `anal ` : ``}virginity taken by ${anAnimal}, but the thought of ${fetishDesc} is enough to make agree to comply.`);
						} else {
							text.push(`${slave.slaveName} tries in vain to conceal ${his} horror at the thought of having ${his} precious ${act === Acts.ANAL ? `rosebud` : `pearl`} taken by a beast, but quickly regains ${his} composure.`);
						}
					}
				}
			} else if (slave.devotion >= -20) {
				if (act === Acts.ORAL) {
					if (slaveApproves) {
						text.push(`${slave.slaveName} looks disgusted at the thought of sucking off an animal at first, but the thought of the ${fetishDesc} that comes with it seems to spark a small flame of lust in ${him}.`);
					} else {
						if (hasFuckedAnimals) {
							text.push(`This wouldn't be the first time ${he}'s had to fuck an animal, and you can tell the memories of ${his} previous encounters are flooding back as ${he} pales.`);
						} else {
							text.push(`${slave.slaveName} tries in vain to conceal ${his} horror at the thought of blowing an animal${canWalk(slave) ? `, and only the threat of worse punishment keeps ${him} from running away as fast as ${he} can` : ``}.`);
						}
					}
				} else {
					if ((act === Acts.VAGINAL && slave.vagina > 0) || (act === Acts.ANAL && slave.anus > 0)) {
						if (slaveApproves) {
							text.push(`${slave.slaveName} looks disgusted at the thought of fucking an animal at first, but the thought of the ${fetishDesc} that comes with it seems to spark a small flame of lust in ${him}.`);
						} else {
							if (hasFuckedAnimals) {
								text.push(`This wouldn't be the first time ${he}'s had to fuck an animal, and you can tell the memories of ${his} previous encounters are flooding back as ${he} pales.`);
							} else {
								text.push(`${slave.slaveName} tries in vain to conceal ${his} horror at the thought of fucking an animal${canWalk(slave) ? `, and only the threat of worse punishment keeps ${him} from running away as fast as ${he} can` : ``}.`);
							}
						}
					} else {
						if (slaveApproves) {
							text.push(`${slave.slaveName} clearly has some reservations about having ${his} ${act === Acts.ANAL ? `anal ` : ``}virginity taken by ${anAnimal}, but the thought of ${fetishDesc} is enough to make agree to comply.`);
						} else {
							text.push(`${slave.slaveName} tries in vain to conceal ${his} horror at the thought of having ${his} precious ${act === Acts.ANAL ? `rosebud` : `pearl`} taken by a beast${canWalk(slave) ? `, and only the threat of worse punishment keeps ${him} from running away as fast as ${he} can` : ``}.`);
						}
					}
				}
			} else {
				text.push(`${slave.slaveName}'s face contorts into a mixture of ${slave.devotion < -50 ? `hatred, anger, and disgust` : `anger and disgust`}, ${canWalk(slave)
					? `and only the threat of far worse punishment is enough to prevent ${him} from running out of the room`
					: `but ${he} knows ${he} is powerless to stop you`}.`);
			}
		}

		return text.join(' ');
	}

	function setup() {
		const text = [];

		if (slave.devotion > 50) {
			if (act === Acts.ORAL) {
				text.push(`You have ${him} kneel on the floor before calling in the ${animal.name}. The beast slowly saunters up to the slave where ${he} waits, showing little concern when the slave reaches out and begins masturbating it to begin the process of getting the animal hard. Once the ${animal.name} is hard enough, ${slave.slaveName} takes its cock and begins to give it a few tentative licks before finally putting it in ${his} mouth.`);
			} else {
				text.push(`You have ${him} ${App.Data.clothes.get(slave.clothes).exposure <= 3 ? `take off ${his} clothes and ` : ``}get on the floor, ass in the air, before calling in the ${animal.name}. The beast slowly saunters up to the slave, where it takes only a few short moments for its animal brain to realize that what it is standing behind is a warm hole that needs to be filled with seed.`);
			}

			switch (animal.name) {
				case V.active.canine:
					if (act === Acts.ORAL) {
						if (slaveApproves) {
							text.push(`The slave seems to quickly get over the fact that the dick currently in ${his} mouth belongs to a canine as ${his} more carnal desires kick in.`);
						} else {
							text.push(`The slave visibly gags as the ${hasFuckedAnimals ? `strange` : `unfamiliar`} texture of ${anAnimal}'s cock fills it, then gives a groan as the beast thrusts, filling ${his} throat.`);
						}
					} else {
						if (canWalk(slave)) {
							text.push(`The canine clambers up to mount ${slave.slaveName}, eliciting a squeal from the ${girl} as its claws dig into ${his} flesh.`);
						} else {
							text.push(`The canine takes a few curious sniffs, then lines up its large cock with ${slave.slaveName}'s ${orifice()}.`);
						}

						text.push(`It takes a few tries, but the ${animal.name} finally manages to sink its cock into ${his} ${slaveApproves && act === Acts.VAGINAL ? `wet ` : ``}${orifice()}.`);
					}
					break;
				case V.active.hooved:
					if (act === Acts.ORAL) {
						if (slaveApproves) {
							text.push(`The slave seems to quickly get over the fact that dick currently in ${his} mouth is not a human one as ${his} more carnal desires kick in.`);
						} else {
							text.push(`The slave visibly gags as the ${hasFuckedAnimals ? `strange` : `unfamiliar`} texture of ${anAnimal}'s cock fills it, then gives a groan as the beast thrusts, stretching ${his} poor throat to the limit.`);
						}
					} else {
						text.push(`${slave.slaveName} gives a long, drawn-out moan as the huge phallus `, slave.vagina < 4 ? `<span class="change positive">stretches</span>` : `fills`, ` ${his} ${orifice()} nearly to its breaking point.`);
					}
					break;
				case V.active.feline:
					if (act === Acts.ORAL) {
						if (slaveApproves) {
							text.push(`The slave seems to quickly get over the fact that dick currently in ${his} mouth belongs to ${anAnimal} as ${his} more carnal desires kick in.`);
						} else {
							text.push(`The slave visibly gags as the ${hasFuckedAnimals ? `strange` : `unfamiliar`} texture of ${anAnimal}'s cock fills it, then gives a groan as the beast thrusts, the barbs on its cock rubbing the inside of ${his} mouth raw.`);
						}
					} else {
						text.push(`${slave.slaveName} gives a squeal of pain as the barbed cock makes its way into ${his} ${orifice()}.`);
					}
					break;
				default:
					throw new Error(`Unexpected animal type '${animal}' in fAnimal()`);
			}

			if (act !== Acts.ORAL) {
				text.push(virginityCheck(act));
			}
		} else if (slave.devotion > 20) {
			if (act === Acts.ORAL) {
				text.push(`You tell ${him} to kneel on the floor before calling in the ${animal.name}. The beast slowly saunters up to the slave where ${he} waits, showing little concern when the slave hesitantly reaches out and begins masturbating it to begin the process of getting the animal hard. Once the ${animal.name} is hard enough, ${slave.slaveName} takes its cock, and, after taking a moment to steel ${his} resolve, begins to give it a few reluctant licks before putting it in ${his} mouth.`);
			} else {
				text.push(`You tell ${him} to ${App.Data.clothes.get(slave.clothes).exposure <= 3 ? `take off ${his} clothes and ` : ``}get on the floor, ass in the air, before calling in the ${animal.name}. The beast slowly saunters up to the slave, where it takes only a few seconds for its animal brain to realize that what it is standing behind is a warm hole that needs to be filled with seed.`);
			}

			switch (animal.name) {
				case V.active.canine:
					if (type === Acts.ORAL) {
						if (slaveApproves) {
							text.push(`Though the slave still seems to have some reservations about sucking off an animal, ${he} seems to forget that the cock in ${his} mouth belongs to ${anAnimal} soon enough, once ${his} carnal desires kick in.`);
						} else {
							text.push(`The slave visibly gags as the ${hasFuckedAnimals ? `strange` : `unfamiliar`} texture of ${anAnimal}'s cock fills it, and you get the feeling ${he} is beginning to reevaluate just how much ${he} wants to avoid punishment.`);
						}
					} else {
						if (canWalk(slave)) {
							text.push(`The canine clambers up to mount ${slave.slaveName}, eliciting a squeal from the ${girl} as its claws dig into ${his} flesh.`);
						} else {
							text.push(`The canine takes a few curious sniffs, then lines up its large cock with ${slave.slaveName}'s ${orifice()}.`);
						}

						text.push(`It takes a few tries, but the ${animal.name} finally manages to sink its cock into ${his} ${slaveApproves && act === Acts.VAGINAL ? `wet ` : ``}${orifice()}.`);
					}
					break;
				case V.active.hooved:
					if (type === Acts.ORAL) {
						if (slaveApproves) {
							text.push(`Though the slave still seems to have some reservations about sucking off ${anAnimal}, ${he} seems to forget that the cock in ${his} mouth isn't human soon enough, once ${his} carnal desires kick in.`);
						} else {
							text.push(`The slave visibly gags as the ${hasFuckedAnimals ? `strange` : `unfamiliar`} texture of ${anAnimal}'s cock fills it, and you get the feeling ${he} is beginning to reevaluate just how much ${he} wants to avoid punishment.`);
						}
					} else {
						text.push(`${slave.slaveName} gives a long, drawn-out groan as the huge phallus `, slave.vagina < 4 ? `<span class="change positive">stretches</span>` : `fills`, ` ${his} ${orifice()} nearly to its breaking point.`);
					}
					break;
				case V.active.feline:
					if (type === Acts.ORAL) {
						if (slaveApproves) {
							text.push(`Though the slave still seems to have some reservations about sucking off an animal, ${he} seems to forget that the cock in ${his} mouth belongs to a feline soon enough, once ${his} carnal desires kick in.`);
						} else {
							text.push(`The slave visibly gags as the ${hasFuckedAnimals ? `strange` : `unfamiliar`} texture of ${anAnimal}'s barbed dick fills it, and you get the feeling ${he} is beginning to reevaluate just how much ${he} wants to avoid punishment.`);
						}
					} else {
						text.push(`${slave.slaveName} gives a squeal of pain as the barbed cock makes its way into ${his} ${orifice()}.`);
					}
					break;
				default:
					throw new Error(`Unexpected animal type '${animal}' in fAnimal()`);
			}

			if (act !== Acts.ORAL) {
				text.push(virginityCheck(act));
			}
		} else if (slave.devotion > -20) {
			if (act === Acts.ORAL) {
				text.push(`You force ${him} to kneel on the floor before calling in the ${animal.name}. The beast slowly saunters up to the slave where ${he} waits, showing little concern when the slave reluctantly reaches out and begins masturbating it to begin the process of getting the animal hard. Once the ${animal.name} is hard enough, ${slave.slaveName} takes its cock and begins to give it a few tentative licks before finally putting it in ${his} mouth.`);
			} else {
				text.push(`You force ${him} to ${App.Data.clothes.get(slave.clothes).exposure <= 3 ? `take off ${his} clothes and ` : ``}get on the floor, ass in the air, before calling in the ${animal.name}. The beast slowly saunters up to the slave, where it takes only a few short moments for its animal brain to realize that what it is standing behind is a warm hole that needs to be filled with seed.`);
			}

			switch (animal.name) {
				case V.active.canine:
					if (type === Acts.ORAL) {
						if (slaveApproves) {
							text.push(`Though the slave still seems to have some reservations about sucking off an animal, ${he} seems to forget that the cock in ${his} mouth belongs to ${anAnimal} soon enough, once ${his} carnal desires kick in.`);
						} else {
							text.push(`The slave visibly gags as the ${hasFuckedAnimals ? `strange` : `unfamiliar`} texture of ${anAnimal}'s cock fills it, and you get the feeling ${he} is beginning to reevaluate just how much ${he} wants to avoid punishment.`);
						}
					} else {
						if (canWalk(slave)) {
							text.push(`The canine clambers up to mount ${slave.slaveName}, eliciting a squeal from the ${girl} as its claws dig into ${his} flesh.`);
						} else {
							text.push(`The canine takes a few curious sniffs, then lines up its large cock with ${slave.slaveName}'s ${orifice()}.`);
						}

						text.push(`It takes a few tries, but the ${animal.name} finally manages to sink its cock into ${his} ${slaveApproves && act === Acts.VAGINAL ? `wet ` : ``}${orifice()}.`);
					}
					break;
				case V.active.hooved:
					if (type === Acts.ORAL) {
						if (slaveApproves) {
							text.push(`Though the slave still seems to have some reservations about sucking off ${anAnimal}, ${he} seems to forget that the cock in ${his} mouth isn't human soon enough, once ${his} carnal desires kick in.`);
						} else {
							text.push(`The slave visibly gags as the ${hasFuckedAnimals ? `strange` : `unfamiliar`} texture of ${anAnimal}'s cock fills it, and you get the feeling ${he} is beginning to reevaluate just how much ${he} wants to avoid punishment.`);
						}
					} else {
						text.push(`${slave.slaveName} gives a long, drawn-out groan as the huge phallus `, slave.vagina < 4 ? `<span class="change positive">stretches</span>` : `fills`, ` ${his} ${orifice()} nearly to its breaking point.`);
					}
					break;
				case V.active.feline:
					if (type === Acts.ORAL) {
						if (slaveApproves) {
							text.push(`Though the slave still seems to have some reservations about sucking off an animal, ${he} seems to forget that the cock in ${his} mouth belongs to a feline soon enough, once ${his} carnal desires kick in.`);
						} else {
							text.push(`The slave visibly gags as the ${hasFuckedAnimals ? `strange` : `unfamiliar`} texture of ${anAnimal}'s barbed dick fills it, and you get the feeling ${he} is beginning to reevaluate just how much ${he} wants to avoid punishment.`);
						}
					} else {
						text.push(`${slave.slaveName} gives a squeal of pain as the barbed cock makes its way into ${his} ${orifice()}.`);
					}
					break;
				default:
					throw new Error(`Unexpected animal type '${animal}' in fAnimal()`);
			}

			if (act !== Acts.ORAL) {
				text.push(virginityCheck(act));
			}
		} else {
			if (act === Acts.ORAL) {
				text.push(`You have to physically force ${him} to kneel on the floor before calling in the ${animal.name}. The beast slowly saunters up to the slave where ${he} is restrained, showing little concern when another slave reaches out and begins masturbating it to begin the process of getting the animal hard. Once the ${animal.name} is hard enough, the slave takes its cock and lines it up with ${slave.slaveName}'s mouth. The animal needs no prompting, and thrusts itself into ${his} ring-gagged mouth.`);
			} else {
				text.push(`You have to physically force ${him} to ${App.Data.clothes.get(slave.clothes).exposure <= 3 ? `take off ${his} clothes and ` : ``} get on the floor, ass in the air and restraints around ${his} wrists and ankles, before calling in the ${animal.name}. The beast slowly saunters up to the slave, where it takes only a few short moments for its animal brain to realize that what it is standing behind is a warm hole that needs to be filled with seed.`);
			}

			switch (animal.name) {
				case V.active.canine:
					if (type === Acts.ORAL) {
						if (slaveApproves) {
							text.push(`The slave glares daggers at you as ${he} takes the full length of the canine's cock in ${his} mouth, but ${slave.dick
								? canAchieveErection(slave)
									? `${his} fully-erect dick`
									: `the precum leaking from ${his} dick`
								: slave.vagina > -1
									? `a slight sheen on ${his} pussylips`
									: `a slight blush to ${his} cheeks`}
									tells you that ${he}'s enjoying this, at least a little.`);
						} else {
							text.push(`The slave visibly gags as the ${hasFuckedAnimals ? `strange` : `unfamiliar`} texture of ${anAnimal}'s cock fills it, and you get the feeling ${he} would have run away a long time ago if ${he} wasn't more than a little tied up at the moment.`);
						}
					} else {
						if (canWalk(slave)) {
							text.push(`The canine clambers up to mount ${slave.slaveName}, eliciting a squeal from the ${girl} as its claws dig into ${his} flesh.`);
						} else {
							text.push(`The canine takes a few curious sniffs, then lines up its large cock with ${slave.slaveName}'s ${orifice()}.`);
						}

						text.push(`It takes a few tries, but the ${animal.name} finally manages to sink its cock into ${his} ${slaveApproves && act === Acts.VAGINAL ? `wet ` : ``}${orifice()}.`);
					}
					break;
				case V.active.hooved:
					if (type === Acts.ORAL) {
						if (slaveApproves) {
							text.push(`The slave glares daggers at you as ${he} takes the full length of the ${animal.name}'s cock in ${his} mouth, but ${slave.dick
								? canAchieveErection(slave)
									? `${his} fully-erect dick`
									: `the precum leaking from ${his} dick`
								: slave.vagina > -1
									? `a slight sheen on ${his} pussylips`
									: `a slight blush to ${his} cheeks`}
									tells you that ${he}'s enjoying this, at least a little.`);
						} else {
							text.push(`The slave visibly gags as the ${hasFuckedAnimals ? `strange` : `unfamiliar`} texture of ${anAnimal}'s cock fills it, and you get the feeling ${he} would have run away a long time ago if ${he} wasn't a little tied up at the moment.`);
						}
					} else {
						text.push(`${slave.slaveName} lets out a blood-curdling scream as the huge phallus `, slave.vagina < 4 ? `<span class="change positive">stretches</span>` : `fills`, ` ${his} ${orifice()} nearly to its breaking point.`);
					}
					break;
				case V.active.feline:
					if (type === Acts.ORAL) {
						if (slaveApproves) {
							text.push(`The slave glares daggers at you as ${he} takes the full length of the feline's cock in ${his} mouth, but ${slave.dick
								? canAchieveErection(slave)
									? `${his} fully-erect dick`
									: `the precum leaking from ${his} dick`
								: slave.vagina > -1
									? `a slight sheen on ${his} pussylips`
									: `a slight blush to ${his} cheeks`}
									tells you that ${he}'s enjoying this, at least a little.`);
						} else {
							text.push(`The slave visibly gags as the ${hasFuckedAnimals ? `strange` : `unfamiliar`} texture of ${anAnimal}'s barbed dick fills it, and you get the feeling ${he} would have run away a long time ago if ${he} wasn't a little tied up at the moment .`);
						}
					} else {
						text.push(`${slave.slaveName} lets out a blood-curdling scream as the barbed cock makes its way into ${his} ${orifice()}.`);
					}
					break;
				default:
					throw new Error(`Unexpected animal type '${animal}' in fAnimal()`);
			}

			if (act !== Acts.ORAL) {
				text.push(virginityCheck(act));
			}
		}

		return text.join(' ');
	}

	function consummation() {
		const text = [];

		switch (animal.name) {
			case V.active.canine:
				if (act === Acts.ORAL) {
					text.push(`${slave.slaveName} gets to work, ${his} head bobbing back and forth rhythmically as ${he} works on bringing the ${animal.name} to orgasm. ${His} efforts pay off after a few minutes when the ${animal.species === "dog" ? `hound` : animal.name}'s knot begins to swell. Eyes wide and brimming with tears from the sudden lack of oxygen, ${he} realizes has no choice but to finish what ${he} started and swallow all of the semen pouring down ${his} abused throat. Soon enough, the ${animal.name} finally finishes cumming and its knot is sufficiently small enough to slip out of ${slave.slaveName}'s mouth, causing ${him} to immediately begin coughing and retching uncontrollably. Having finished its business, the ${animal.name} runs off, presumably in search of food.`);
				} else {
					text.push(`The ${animal.species === "dog" ? `hound` : animal.name} wastes no time in beginning to hammer away at ${his} ${orifice()} in the way only canines can, causing ${slave.slaveName} to moan uncontrollably as its thick, veiny member probes the depths of ${his} ${orifice()}. A few short minutes later, ${he} gives a loud groan ${slaveApproves ? `and shakes in orgasm ` : ``}as the ${animal.name}'s knot begins to swell and its dick begins to erupt a thick stream of jizz into ${his} ${orifice()}. Soon enough, the ${animal.name} finally finishes cumming and its knot is sufficiently small enough to slip out of ${slave.slaveName}'s ${act === Acts.VAGINAL && slave.vagina < 3 || act === Acts.ANAL && slave.anus < 2
						? `now-gaping ${orifice()}`
						: orifice()}, causing a thick stream of cum to slide out of it. Having finished its business, the ${animal.name} runs off, presumably in search of food.`);
				}
				break;
			case V.active.hooved:
				if (act === Acts.ORAL) {
					text.push(`${slave.slaveName} gets to work, ${his} head bobbing back and forth rhythmically as ${he} works on bringing the ${animal.name} to orgasm. ${His} efforts pay off after a few minutes when the ${animal.species === "horse" ? `stallion` : animal.name} begins to pant as its orgasm approaches. Before too long, the ${animal.name}'s movements begin to slow, and you can see its large testicles contract as its begins to erupt and pour its thick semen down ${his} throat and into ${his} stomach, filling it to the brim. After what seems like an impossibly long time, the ${animal.name}'s dick finally begins to soften and pull out, causing ${slave.slaveName} to begin coughing and retching uncontrollably. You have another slave lead the ${animal.name} away, with a fresh apple as a treat for its good performance.`);
				} else {
					text.push(`The ${animal.species === "horse" ? `stallion` : animal.name} begins to thrust faster and faster, causing ${him} to moan and groan as the huge ${animal.species} cock ${act === Acts.VAGINAL ? `batters ${his} cervix` : `fills ${him} completely`}. Before too long, the ${animal.name}'s movements begin to slow, and you can see its large testicles contract as its begins to erupt and fill ${his} ${orifice()} with its thick baby batter. After what seems like an impossibly long time, the ${animal.name}'s dick finally begins to soften and pull out, leaving ${slave.slaveName} panting and covered in sweat. You have another slave lead the ${animal.name} away, with a fresh apple as a treat for its good performance.`);
				}
				break;
			case V.active.feline:
				if (act === Acts.ORAL) {
					text.push(`${slave.slaveName} gets to work, ${his} head bobbing back and forth rhythmically as ${he} works on bringing the ${animal.name} to orgasm. ${His} efforts pay off after a few minutes when the ${animal.name} begins to pant as its orgasm approaches.  After a few minutes of painful coupling, the ${animal.species}'s thrusts finally slow, then stop completely as its ${animal.species !== "cat" ? `large` : ``} cock erupts down ${slave.slaveName}'s throat. With a ${animal.species !== "cat" ? `deep bellow` : `loud meow`}, he finally dismounts, gives you a long look, then stalks off.`);
				} else {
					text.push(`The ${animal.name} begins to move, thrusting faster and faster. The ${girl} underneath it can't stop a groan of pain from escaping ${his} lips as the ${animal.species}'s barbed dick rubs the inside of ${his} ${orifice()} raw. After a few minutes of painful coupling, the ${animal.species}'s thrusts finally slow, then stop completely as its ${animal.species !== "cat" ? `large` : ``} cock erupts, filling ${slave.slaveName} with its sperm. With a ${animal.species !== "cat" ? `deep bellow` : `loud meow`}, he finally dismounts, gives you a long look, then stalks off.`);
				}

				healthDamage(slave, 1);
				break;
			default:
				throw new Error(`Unexpected animal type '${animal}' in fAnimal()`);
		}

		return text.join(' ');
	}

	function cleanup() {
		const text = [];

		if (act !== Acts.ORAL) {
			if (act === Acts.VAGINAL) {
				if (slave.vagina === 3) {
					text.push(`${capFirstChar(animal.name)} cum drips out of ${his} fucked-out hole.`);
				} else if (slave.vagina === 2) {
					text.push(`${capFirstChar(animal.name)} cum drips out of ${his} stretched vagina.`);
				} else if (slave.vagina === 1) {
					text.push(`${His} still-tight pussy keeps the ${animal.name}'s cum inside ${him}.`);
				} else {
					text.push(`${capFirstChar(animal.name)} cum slides right out of ${his} gaping hole.`);
				}
			} else {
				if (slave.anus === 1) {
					text.push(`${His} still-tight asshole keeps the ${animal.name}'s cum inside ${him}.`);
				} else if (slave.anus === 2) {
					text.push(`${capFirstChar(animal.name)} cum drips out of ${his} loosened anus.`);
				} else {
					text.push(`${capFirstChar(animal.name)} cum slides right out of ${his} fucked-out asshole.`);
				}
			}

			if (canWalk(slave)) {
				if (act === "vaginal") {
					text.push(`${He} uses a quick douche to clean ${his} ${slave.vagina < 2 ? `tight` : slave.vagina > 3 ? `loose` : ``} pussy,`);
				} else {
					text.push(`${He} uses an enema to clean ${his} ${slave.anus < 2 ? `tight` : slave.anus < 3 ? `used` : `gaping`} butthole,`);
				}

				switch (slave.assignment) {
					case Job.BROTHEL:
						text.push(`just like ${he} does between each customer.`);
						break;
					case Job.CLUB:
						text.push(`just like ${he} does in the club.`);
						break;
					case Job.DAIRY:
						text.push(`to avoid besmirching the nice clean dairy.`);
						break;
					case Job.FARMYARD:
						text.push(`to avoid tainting the food in ${V.farmyardName}.`);
						break;
					case Job.QUARTER:
						text.push(`mostly to keep everything ${he} has to clean from getting any dirtier.`);
						break;
					case Job.WHORE:
						text.push(`before returning to offering it for sale.`);
						break;
					case Job.PUBLIC:
						text.push(`before returning to offering it for free.`);
						break;
					case Job.REST:
						text.push(`before crawling back into bed.`);
						break;
					case Job.MILKED:
						text.push(`${slave.lactation > 0 ? `before going to get ${his} uncomfortably milk-filled tits drained` : `and then rests until ${his} balls are ready to be drained again`}.`);
						break;
					case Job.HOUSE:
						text.push(`since ${his} chores didn't perform themselves while you used ${his} fuckhole.`);
						break;
					case Job.FUCKTOY:
						text.push(`before returning to await your next use of ${his} fuckhole, as though nothing had happened.`);
						break;
					case Job.SUBORDINATE:
						text.push(`though it's only a matter of time before another slave decides to play with ${his} fuckhole.`);
						break;
					case Job.HEADGIRL:
						text.push(`worried that ${his} charges got up to trouble while ${he} enjoyed ${his} ${properMaster()}'s use.`);
						break;
					case Job.BODYGUARD:
						text.push(`so ${he} can be fresh and ready for more sexual use even as ${he} guards your person.`);
						break;
					case Job.TEACHER:
						text.push(`before ${he} returns to teaching ${his} classes.`);
						break;
					default:
						text.push(`before ${he} returns to ${slave.assignment}.`);
						break;
				}
			}
		}

		return text.join(' ');
	}

	function slaveGainsFlaw() {
		switch (act) {
			case Acts.ORAL:
				if (slave.sexualFlaw !== "hates oral") {
					slave.sexualFlaw = "hates oral";

					return `<span class="flaw gain">Having ${anAnimal} fuck ${his} throat by force has given ${him} a hatred of oral sex.</span>`;
				}

				break;
			case Acts.VAGINAL:
				if (slave.sexualFlaw !== "hates penetration") {
					slave.sexualFlaw = "hates penetration";

					return `<span class="flaw gain">Having ${anAnimal} fuck ${him} by force has given ${him} a hatred of penetration.</span>`;
				}

				break;
			case Acts.ANAL:
				if (slave.sexualFlaw !== "hates anal") {
					slave.sexualFlaw = "hates anal";

					return `<span class="flaw gain">Having ${anAnimal} fuck ${his} asshole by force has given ${him} a hatred of anal penetration.</span>`;
				}

				break;
			default:
				throw new Error(`Unexpected act type '${act}' in fAnimal().`);
		}
	}

	function slaveGainsQuirk() {
		if (slave.behavioralQuirk === "none") {
			if (random(1, 100) > 90) {	// 10% chance of gaining quirk
				/** @type {FC.BehavioralQuirk[]} */
				const quirks = [];

				if (V.policies.bestialityOpenness === 0) {
					quirks.push("sinful");
				}

				const quirk = quirks.random() ?? "none";

				slave.behavioralQuirk = quirk;

				if (quirk === "sinful") {
					return `The ${girl} seemed to take great pleasure in doing something as taboo as fucking an animal. You might notice ${him} begin to try to break more and more cultural norms in the days to come <span class="fetish gain">as ${his} sinful side begins to come out.</span>`;
				}
			}
		}
		if (slave.sexualQuirk === "none") {
			if (random(1, 100) > 90) {	// 10% chance of gaining quirk
				/** @type {FC.SexualQuirk[]} */
				const quirks = [
					"perverted",
					"unflinching",
				];

				if (act === Acts.ANAL) {
					quirks.push("painal queen");
				}
				if (animal.dick.size > 4) {
					quirks.push("size queen");
				}

				const quirk = quirks.random() ?? "none";

				slave.sexualQuirk = quirk;

				if (quirk === "painal queen") {
					return `${slave.slaveName}'s asshole took quite the pounding during the rutting, and ${he}${slave.dick > 0 ? `'s sporting an erection` : ``}${slave.vagina > -1 ? slave.dick > 0 ? ` and ` : ` has a distinct sheen on ${his} pussylips` : ` seems distinctly uncomfortable`} after the fact. <span class="fetish gain">It seems ${he} got off on the painal.</span`;
				}
				if (quirk === "perverted") {
					return `${He} seems distinctly uncomfortable after the rutting has finished, as though <span class="fetish gain">doing something so perverted had turned ${him} on.</span>`;
				}
				if (quirk === "size queen") {
					return `The ${animal.name} had a dick large enough to put even well-endowed men to shame, and the orgasm it had given ${him} left ${him} wondering aloud if <span class="fetish gain">normal-sized cocks would ever satisfy ${him} again.</span>`;
				}
				if (quirk === "unflinching") {
					return `Being bred like an animal by an <i>actual</i> animal isn't an easy task, but you can tell it's one ${he} enjoyed. <span class="fetish gain">It seems ${he} is now more receptive to doing more taboo and even downright disturbing acts.</span>`;
				}
			}
		}
	}

	function slaveGainsFetish() {
		if (random(1, 100) > 90) {	// 10% chance of gaining fetish
			/** @type {FC.Fetish[]} */
			const fetishes = [
				Fetish.HUMILIATION,
				Fetish.MASOCHIST,
				Fetish.BESTIALITY,
			];

			if (act === Acts.ANAL) {
				fetishes.push(Fetish.BUTTSLUT);
			}

			const fetish = fetishes.random();

			fetishChange(slave, fetish);

			if (fetish === Fetish.BUTTSLUT) {
				return `${He} couldn't help but orgasm when the ${animal.name} filled ${him} with its seed, and now the thought of another member in ${his} bottom <span class="fetish gain>turns ${him} on.</span>`;
			}
			if (fetish === Fetish.HUMILIATION) {
				return `You can't help but notice that ${he} ${slave.dick > 0 ? `is sporting an erection` : ``}${slave.vagina > -1 ? slave.dick > 0 ? ` and ` : `has a distinct sheen on ${his} pussylips` : `seems distinctly uncomfortable`} after the beast has finished. <span class="fetish gain">It seems ${he} is a bit of a humiliation slut!</span>`;
			}
			if (fetish === Fetish.MASOCHIST) {
				return `${He} didn't seem to mind the pain – in fact, it seems ${he} got off on it. <span class="fetish gain">${He}'s a masochist!</span>`;
			}
			if (fetish === Fetish.BESTIALITY) {
				return `${He} seems to have <span class="devotion inc">really taken to</span> getting fucked by animals – <span class="fetish gain">${he} has a bestiality fetish!</span>`;
			}
		}
	}

	// Virginity Check Functions

	function virginityCheck(type) {
		const text = [];

		switch (type) {
			case Acts.VAGINAL:
				if (act === Acts.VAGINAL && slave.vagina === 0) {
					text.push(`The slave gives a loud ${slave.devotion > 20 ? `moan` : `groan`} as <span class="virginity loss">${his} virginity is taken from ${him}${slave.devotion < -20 ? ` by force` : ``}.</span>`);

					if (slave.devotion >= -20) {
						if (slaveApproves) {
							text.push(`Losing ${his} virginity in such a painful manner has <span class="devotion inc">increased ${his} devotion to you.</span>`);

							slave.devotion += 10;
						} else {
							if (slave.devotion > 50) {
								text.push(`Since ${he} is well broken, losing ${his} virginity in such a manner has <span class="devotion inc">increased ${his} submission to you.</span>`);

								slave.devotion += 5;
							} else if (slave.devotion >= -20) {
								text.push(`Losing ${his} virginity in such a manner has <span class="devotion inc">increased ${his} submission to you,</span> though ${he} is <span class="trust dec">fearful</span> that you'll decide to only use ${him} to sate your animals' lust.`);

								slave.devotion += 5;
								slave.trust -= 5;
							} else {
								text.push(`${He} is clearly <span class="devotion dec">unhappy</span> in the manner in which ${his} virginity has been taken, and ${he} <span class="trust dec">fears</span> you'll decide to only use ${him} to sate your animals' lust.`);

								slave.devotion -= 10;
								slave.trust -= 10;
							}
						}
					} else {
						text.push(`Having ${his} pearl of great price taken by a mere beast has <span class="devotion dec">reinforced the hatred ${he} holds towards you,</span> and ${he} is <span class="trust dec">terrified</span> you'll only use ${him} as a plaything for your animals.`);

						slave.devotion -= 10;
						slave.trust -= 10;
					}

					text.push(`Having ${his} cherry popped in such a manner was extremely painful and <span class="health dec">slightly damaged ${his} health.</span>`);

					healthDamage(slave, 5);
				}

				break;
			case Acts.ANAL:
				if (act === Acts.ANAL && slave.anus === 0) {
					text.push(`The slave gives a loud ${slave.devotion > 20 ? `moan` : `groan`} as <span class="virginity loss">${his} anal virginity is taken from ${him}${slave.devotion < -20 ? ` by force` : ``}.</span>`);

					if (slave.devotion >= -20) {
						if (slaveApproves) {
							text.push(`Losing ${his} anal virginity in such a painful manner has <span class="devotion inc">increased ${his} devotion to you.</span>`);

							slave.devotion += 10;
						} else {
							if (slave.devotion > 50) {
								text.push(`Since ${he} is well broken, losing ${his} anal virginity in such a manner has <span class="devotion inc">increased ${his} submission to you.</span>`);

								slave.devotion += 5;
							} else if (slave.devotion >= -20) {
								text.push(`Losing ${his} anal virginity in such a manner has <span class="devotion inc">increased ${his} submission to you,</span> though ${he} is <span class="trust dec">fearful</span> that you'll decide to only use ${him} to sate your animals' lust.`);

								slave.devotion += 5;
								slave.trust -= 5;
							} else {
								text.push(`${He} is clearly <span class="devotion dec">unhappy</span> in the manner in which ${his} anal virginity has been taken, and ${he} <span class="trust dec">fears</span> you'll decide to only use ${him} to sate your animals' lust.`);

								slave.devotion -= 10;
								slave.trust -= 10;
							}
						}
					} else {
						text.push(`Having ${his} pearl of great price taken by a mere beast has <span class="devotion dec">reinforced the hatred ${he} holds towards you,</span> and ${he} is <span class="trust dec">terrified</span> you'll only use ${him} as a plaything for your animals.`);

						slave.devotion -= 10;
						slave.trust -= 10;
					}

					text.push(`Having ${his} rosebud broken in in such a manner was extremely painful and <span class="health dec">slightly damaged ${his} health.</span>`);

					healthDamage(slave, 5);
				}

				break;
		}

		return text.join(' ');
	}
};


code:
/**
 *
 * @param {App.Entity.SlaveState} slave
 * @returns {DocumentFragment}
 */
App.Interact.fAnus = function(slave) {
	const frag = new DocumentFragment();

	const {
		He, His,
		he, his, him, himself, girl
	} = getPronouns(slave);

	seX(slave, "anal", V.PC, "penetrative");

	const text = new SpacedTextAccumulator(frag);

	text.push(
		setup(),
		consummation(),
		belly(),
		anusTat(),
	);

	if (random(1, 100) > (100 + slave.devotion)) {
		slaveGainsFlaw();
	} else if (random(1, 100) > (110 - slave.devotion)) {
		slaveGainsQuirk();
	}

	if (V.postSexCleanUp) {
		text.push(cleanup());
	}

	text.toParagraph();

	return frag;

	function setup() {
		const text = [];

		text.push(`You call ${him} over so you can`);

		if (slave.anus > 3) {
			text.push(`fuck ${his} gaping anus.`);
		} else if (slave.anus === 3) {
			text.push(`fuck ${his} loose butthole.`);
		} else if (slave.anus === 2) {
			text.push(`use ${his} whorish asshole.`);
		} else if (slave.anus === 1) {
			text.push(`use ${his} tight butt.`);
		} else {
			text.push(`take ${his} anal virginity.`);
		}

		if (slave.fetish === "buttslut" && slave.devotion >= -20) {
			text.push(`${He}'s delighted at the prospect of ${his} favorite activity.`);
		} else if (slave.fetish === "buttslut") {
			text.push(`${He} perks up at the prospect of ${his} favorite activity, but the idea of spending it with you instantly sours ${his} mood.`);
		}

		if (slave.anusTat === "tribal patterns") {
			text.push(`${His} bleached asshole is an inviting sight, after all.`);
		} else if (slave.anusTat === "scenes") {
			text.push(`${His} tattooed asshole invites sodomy, after all.`);
		} else if (slave.anusTat === "degradation") {
			text.push(`The tattoos on ${his} asshole make it clear ${he}'s an anal slut, after all.`);
		}

		if (slave.heels === 1) {
			if (shoeHeelCategory(slave) > 0) {
				text.push(`As ${he} went past your desk, ${his} high heels and surgically altered legs enforced a gait that presented ${his} butt enticingly.`);
			} else {
				text.push(`As ${he} crawls along on`);
				if (hasAllLimbs(slave)) {
					text.push(`all fours,`);
				} else {
					text.push(`the ground,`);
				}
				text.push(`${his} anus is readily available.`);
			}
		}

		if (slave.piercing.anus.weight > 1) {
			text.push(`The ring of stud piercings around ${his} anus should massage you delightfully as you sodomize ${him}.`);
		} else if (slave.piercing.anus.weight === 1) {
			text.push(`${His} perineum piercing has a big ring in it, which you should be able to feel when you hilt yourself in ${his} ass.`);
		}

		if (slave.anusTat !== 0 && slave.anusTat === "bleached") {
			text.push(`${His} anus is invitingly bleached,`);
			if (slave.vagina > -1) {
				text.push(`which is appropriate: rather than looking like ${he} has a hole for fucking and an ass, it looks like ${he} has two fuckholes.`);
			} else {
				text.push(`making ${his} sole fuckable hole look nice and natural.`);
			}
		}

		return text.join(' ');
	}

	function consummation() {
		const text = [];

		if (slave.anus === 0) {
			if (slave.devotion > 20) {
				text.push(`${He} accepts your orders without comment and presents ${his} virgin anus for defloration. You`);
				if (V.PC.dick === 0) {
					text.push(`don a strap-on and`);
				}
				text.push(`gently sodomize ${him}. You gently ease into ${his} butthole and slowly accelerate your thrusting into ${his} ass. Since ${he} is already well broken, this new connection with ${his} ${getWrittenTitle(slave)} increases ${his} devotion to you. ${His} tight little ass has been broken in. ${He} looks forward to having ${his} asshole fucked by you again.`);
				slave.devotion += 4;
			} else if (slave.devotion >= -20) {
				text.push(`${He} is clearly unhappy at the idea of taking a dick up ${his} butt. ${He} obeys orders anyway, and lies there wincing and moaning as you`);
				if (V.PC.dick === 0) {
					text.push(`don a strap-on and`);
				}
				text.push(`fuck ${his} ass. You gently ease into ${his} butthole and slowly accelerate your thrusting into ${his} ass. However ${he} still squeals in pain as you continue pounding. ${His} tight little ass has been broken in, and ${he} fears further anal pain.`);
				slave.trust -= 5;
			} else {
				text.push(`${He} is appalled at the idea of taking it up the ass${(V.PC.dick === 0) ? ` and cries with fear as you don a strap-on` : ``}. ${He} does anyway though, sobbing into the cushions`);
				if (hasAnyArms(slave)) {
					text.push(`while you hold ${his} ${hasBothArms(slave) ? `arms` : `arm`} behind ${him}`);
				}
				text.push(text.pop() + `.`);
				text.push(`You force yourself into ${his} butthole and continue thrusting your member into ${his} ass. ${He} sobs and cries with disgust while you pump into ${his} rear. The painful anal rape decreases ${his} devotion to you. ${His} tight little ass has been broken in, and ${he} is terrified of further anal pain.`);
				slave.devotion -= 10;
				slave.trust -= 10;
			}
			slave.anus++;
		} else if (slave.fetish === "mindbroken") {
			if (hasAnyArms(slave)) {
				text.push(`You instruct ${him} to present ${his} anus. ${He} dully`);
				if (hasBothLegs(slave)) {
					text.push(`kneels`);
				} else {
					text.push(`bends over`);
				}
				text.push(`and spreads ${his} buttocks${V.PC.dick === 0 ? ` as you don a strap-on` : ``}. You spit on ${his} hole and ram`);
			} else {
				text.push(`Talking to a broken mind is pointless, so you simply set ${him} on the couch, spread ${his} buttocks with one hand, spit on ${his} hole, and ram`);
			}
			if (V.PC.dick === 0) {
				text.push(`it`);
			} else {
				text.push(`your cock`);
			}
			text.push(`up ${his}`);
			if (V.seeRace === 1) {
				text.push(slave.race);
			}
			text.push(`butt. ${His} butthole spasms as you assrape ${him},`);
			if (V.PC.dick === 0) {
				text.push(`an amusing sight.`);
			} else {
				text.push(`squeezing your dick nicely.`);
			}
			if (slave.dick !== 0 && canAchieveErection(slave)) {
				if (slave.chastityPenis === 1) {
					text.push(`Automatic responses give ${him} an erection, which ${his} chastity makes so uncomfortable that ${he} spasms. This cycle continues repeatedly, ${his} rectum squeezing unconsciously each time.`);
				} else if (slave.prostate !== 0) {
					text.push(`Despite ${his} mental deficiency, the prostate stimulation gives ${him} an erection anyway.`);
				} else {
					text.push(`Without a prostate, there's little stimulation to provoke an involuntary response, and ${his} cock stays limp.`);
				}
			} else if (slave.chastityPenis === 1) {
				text.push(`${His} dick chastity keeps ${his} pointless cock hidden away while you use ${his} anus like a pussy.`);
			} else if (slave.dick !== 0) {
				text.push(`${His} cock is totally flaccid throughout.`);
			}
		} else if (slave.devotion < -20) {
			if (!isAmputee(slave)) {
				text.push(`You instruct ${him} to present ${his} anus${V.PC.dick === 0 ? ` as you don a strap-on` : ``}. Horrified, ${he} tries to back away, but you catch ${him} and throw ${him} on the couch next to your desk. ${He} tries to`);
				if (hasAnyArms(slave)) {
					text.push(`shield ${his} asshole,`);
				} else {
					text.push(`back away,`);
				}
				text.push(`but you pin`);
				if (hasAnyArms(slave)) {
					text.push(`${his} ${hasBothArms(slave) ? "hands" : "hand"} behind ${him} with one hand,`);
				} else {
					text.push(`${him} down,`);
				}
				text.push(`spit on ${his} hole, and ram your`);
				if (V.PC.dick === 0) {
					text.push(`fake dick`);
				} else {
					text.push(`cock`);
				}
				text.push(`up ${his} butt with the other hand.`);
			} else {
				text.push(`You tell ${him} it's time for an assfuck. ${He}'s horrified, but as an amputee can do nothing about it. You spit on ${his} hole and ram your`);
				if (V.PC.dick === 0) {
					text.push(`fake dick`);
				} else {
					text.push(`cock`);
				}
				text.push(`up ${his}`);
				if (V.seeRace === 1) {
					text.push(slave.race);
				}
				text.push(`butt.`);
			}
			text.push(`${His} butthole spasms as you assrape ${him},`);
			if (V.PC.dick === 0) {
				text.push(`an amusing sight.`);
			} else {
				text.push(`squeezing your dick nicely.`);
			}
			if (slave.dick !== 0 && canAchieveErection(slave)) {
				if (slave.prostate === 0) {
					text.push(`${He} lacks a prostate, denying ${him} any real pleasure from this. ${His} dick stays flaccid as you rape ${him}.`);
				} else if (slave.chastityPenis === 1) {
					text.push(`Despite ${his} unwillingness to be sodomized, the prostate stimulation starts to give ${him} an erection, which ${his} dick chastity makes horribly uncomfortable. ${He} bucks with the pain, ${his} asshole spasming delightfully.`);
				} else {
					text.push(`Despite ${his} unwillingness to be sodomized, the prostate stimulation gives ${him} an erection. ${He}'s mortified that ${he} would get hard while being anally raped.`);
				}
			} else if (slave.chastityPenis === 1) {
				text.push(`${His} dick chastity keeps ${his} bitch cock hidden away while you use ${his} anus like a pussy.`);
			} else if (slave.dick !== 0) {
				text.push(`${His} flaccid dick is ground into the back of the couch as you rape ${him}.`);
			}
		} else if (slave.devotion <= 20 && slave.vagina < 0) {
			if (!isAmputee(slave)) {
				text.push(`You instruct ${him} to present ${his} anus${V.PC.dick === 0 ? ` as you don a strap-on` : ``}. ${He} knows a sissy slave takes it up the butt, and lies on the couch next to your desk with ${his}`);
				if (!hasAnyLegs(slave)) {
					text.push(`hips`);
				} else {
					text.push(hasBothLegs(slave) ? `legs` : `leg`);
				}
				text.push(`in the air, spreading ${his} buttocks`);
				if (!hasAnyArms(slave)) {
					text.push(`as best ${he} can.`);
				} else {
					text.push(`with ${his} ${hasBothArms(slave) ? `hands` : `hand`}.`);
				}
			} else {
				text.push(`You tell ${him} it's time for an assfuck. ${He}'s hesitant, but as an amputee can do nothing about it.`);
			}
			text.push(`You take your time and fuck ${his}`);
			if (V.seeRace === 1) {
				text.push(slave.race);
			}
			text.push(`butthole for a good long while`);
			if (slave.chastityPenis !== 1) {
				if (slave.dick !== 0) {
					text.push(`so ${his} limp dick flops around`);
				} else if (slave.balls !== 0) {
					text.push(`as ${his} erect dick waves in the air`);
				}
			}
			text.push(text.pop() + `.`);
			text.push(`This gives you enough time to stroke ${him} until ${he} gets aroused despite ${his} discomfort with anal. ${He} doesn't orgasm, but ${he}'s getting accustomed to ${his} asshole as a sexual organ.`);
		} else if (slave.devotion < 10) {
			if (!isAmputee(slave)) {
				text.push(`You instruct ${him} to present ${his}`);
				if (V.seeRace === 1) {
					text.push(slave.race);
				}
				text.push(`anus${V.PC.dick === 0 ? ` as you don a strap-on` : ``}. ${He} hesitates but eventually lies on the couch next to your desk with ${his}`);
				if (!hasAnyLegs(slave)) {
					text.push(`hips`);
				} else {
					text.push(hasBothLegs(slave) ? `legs` : `leg`);
				}
				text.push(`in the air, spreading ${his} buttocks`);
				if (!hasAnyArms(slave)) {
					text.push(`as best ${he} can.`);
				} else {
					text.push(`with ${his} ${hasBothArms(slave) ? `hands` : `hand`}.`);
				}
			} else {
				text.push(`You tell ${him} it's time for an assfuck. ${He}'s hesitant, but as an amputee can do nothing about it.`);
			}
			text.push(`You take your time and fuck ${his} butthole for a good long while.`);
			if (slave.anus === 1) {
				text.push(`${His} ass is so tight that ${he} winces with anal pain`);
			} else if (slave.anus === 2) {
				text.push(`${His} experienced ass takes your`);
				if (V.PC.dick === 0) {
					text.push(`fake dick`);
				} else {
					text.push(`cock`);
				}
				text.push(`without trouble`);
			} else {
				text.push(`${His} asspussy is so loose you can pound it as hard as you like`);
			}
			if (slave.dick !== 0 && !canAchieveErection(slave)) {
				text.push(`as ${his} limp dick flops around.`);
			} else if (slave.dick !== 0 && canAchieveErection(slave)) {
				text.push(`as ${his} erect dick waves in the air.`);
			} else if (slave.vagina === -1) {
				text.push(`as it does its duty as ${his} sole fuckhole.`);
			} else {
				text.push(`as it substitutes for ${his} pussy.`);
			}
			text.push(`${He} gets aroused despite ${his} discomfort with anal, though ${he} doesn't orgasm.`);
		} else {
			if (hasAnyLegs(slave)) {
				text.push(`${He} kneels on the couch`);
			} else {
				text.push(`You lay ${him} on the couch`);
			}
			text.push(`with ${his}`);
			if (V.seeRace === 1) {
				text.push(slave.race);
			}
			text.push(`butt facing you, back strongly arched to angle ${his} rectum for more comfortable anal coupling.`);
			if (hasAnyArms(slave) && slave.prostate > 1 && slave.dick > 3) {
				if (V.PC.dick === 0) {
					text.push(`While you don a strap-on, ${he}`);
				} else {
					text.push(`${He}`);
				}
				text.push(`shoves ${his} slavering dick down and around towards ${his} ass and squeezes it, pushing a lot of ${his} precum out to lube ${his} own asshole.`);
			} else {
				if (V.PC.dick === 0) {
					text.push(`You don a strap-on and let some saliva fall onto its head`);
				} else {
					text.push(`You let some saliva fall onto your dickhead`);
				}
				text.push(`before penetrating ${him}.`);
			}
			text.push(`You take your time and fuck ${his} butthole for a good long while.`);
			if (slave.anus === 1) {
				text.push(`${His} ass is so tight that ${he} has to concentrate on relaxing for you.`);
			} else if (slave.anus === 2) {
				text.push(`${His} experienced ass feels great.`);
			} else {
				text.push(`${His} asspussy is so loose you can pound it as hard as you like.`);
			}
			text.push(`${He} rubs ${his}`);
			if (!hasAnyArms(slave)) {
				text.push(`body against you as much as ${he} can manage,`);
			} else if (canAchieveErection(slave)) {
				text.push(`hard-on,`);
			} else if (slave.dick !== 0) {
				text.push(`soft dick,`);
			} else if (slave.chastityVagina || slave.clit === 0) {
				text.push(`nipples,`);
			} else if (slave.clit > 2) {
				text.push(`huge, stiff clit,`);
			} else {
				text.push(`clit,`);
			}
			text.push(`and brings ${himself} to orgasm before you.`);
			if (V.PC.dick === 0) {
				text.push(`The sight of ${him} gasping and shaking ${his} way through an anal orgasm brings you to climax yourself, and you shove yourself against the strap-on harness with enough force to give the slave's sensitized hole a final brutal stretching.`);
			} else {
				text.push(`${His} orgasmic rectal spasms squeeze your cock and you blow your load inside ${his} ass.`);
			}
		}

		return text.join(' ');
	}

	function belly() {
		if (slave.bellyPreg >= 1500) {
			return `The poor slave's pregnant belly causes ${him} some discomfort as you sodomize ${him}.`;
		} else if (slave.bellyImplant >= 1500) {
			return `The poor ${girl}'s implant filled belly causes ${him} some discomfort as you sodomize ${him}.`;
		} else if (slave.bellyFluid >= 1500) {
			return `The poor ${girl}'s sloshing belly causes ${him} some discomfort as you sodomize ${him}, though the lewd jiggling the pounding sends through it is quite a sight.`;
		}

		return ``;
	}

	function anusTat() {
		if (slave.anusTat === "scenes" && slave.anus === 1) {
			return `As you fucked ${his} butt, the decorative pattern around ${his} ass stretched open. When you pull out, ${his} momentary gape closes the pattern up quickly.`;
		} else if (slave.anusTat === "scenes") {
			return `As you fucked ${his} butt, the decorative pattern around ${his} ass stretched open. When you pull out, ${his} gape leaves the pattern distorted.`;
		} else if (slave.anusTat === "degradation") {
			return `As you fucked ${his} butt, the offensive language around ${his} ass stretched and distorted.`;
		}

		return ``;
	}

	function slaveGainsFlaw() {
		if (slave.fetish !== "buttslut" && slave.energy <= 95 && slave.sexualFlaw !== "hates anal") {
			slave.sexualFlaw = "hates anal";

			return `Being assraped has given ${him} a <span class="flaw gain">hatred of anal sex.</span>`;
		}

		return ``;
	}

	function slaveGainsQuirk() {
		if (slave.fetish === "none" && slave.sexualFlaw !== "hates anal") {
			slave.fetish = "buttslut";
			slave.fetishKnown = 1;

			return `Orgasming to the sensation of your member in ${his} bottom <span class="fetish gain">has ${him} eager for anal.</span>`;
		}

		return ``;
	}

	function cleanup() {
		const text = [];

		if (V.PC.dick !== 0) {
			if (slave.cervixImplant === 2 || slave.cervixImplant === 3) {
				slave.bellyImplant += random(10, 20);
			}

			if (slave.anus > 3) {
				text.push(`Your cum falls out of ${his} gaping hole.`);
			} else if (slave.anus > 2) {
				text.push(`Cum flows out of ${his} gaped butthole.`);
			} else if (slave.anus === 2) {
				text.push(`Cum drips out of ${his} newly gaped anus.`);
			} else if (slave.anus === 1) {
				text.push(`${His} still-tight ass keeps your load inside ${him}.`);
			}

			if (canImpreg(slave, V.PC)) {
				text.push(knockMeUp(slave, 5, 1, -1));
			}

			if (V.postSexCleanUp > 0) {
				if (canMove(slave)) {
					let anus;
					if (slave.anus < 2) {
						anus = "tight butt";
					} else if (slave.anus < 3) {
						anus = "used butthole";
					} else if (slave.anus < 4) {
						anus = "gaping butthole";
					} else {
						anus = "anal gape";
					}
					switch (slave.assignment) {
						case "work in the brothel":
							text.push(`${He} goes to wash ${his} ${anus} so ${his} next customer can have the illusion that he's the first to use it today.`);
							break;
						case "serve in the club":
							text.push(`${He} goes to wash and delicately perfume ${his} ${anus} so it can gratify the finest citizen.`);
							break;
						case "work in the dairy":
							text.push(`${He} goes off to carefully wash ${his} ${anus} to avoid besmirching the nice clean dairy.`);
							break;
						case "work as a farmhand":
							text.push(`${He} goes off to wash ${his} ${anus} to avoid tainting the food in ${V.farmyardName}.`);
							break;
						case "work as a servant":
							text.push(`${He} rushes to wash ${his} ${anus}, impatient to get back to ${his} many chores.`);
							break;
						case "work as a nanny":
							text.push(`${He} goes off to wash ${his} ${anus}, before hurrying to continue taking care of the children in ${V.nurseryName}.`);
							break;
						case "whore":
							text.push(`${He} uses an enema to clean ${his} ${anus} before returning to offering it for sale.`);
							break;
						case "serve the public":
							text.push(`${He} uses an enema to clean ${his} ${anus} before returning to offering it for free.`);
							break;
						case "be a servant":
							text.push(`${He} uses an enema to clean ${his} ${anus}, since ${his} chores didn't perform themselves while you used ${his} backdoor.`);
							break;
						case "rest":
							text.push(`${He} uses an enema to clean ${his} ${anus} before crawling back into bed, face-down.`);
							break;
						case "get milked":
							text.push(`${He} uses an enema to clean ${his} ${anus}`);
							if (slave.lactation > 0) {
								text.push(`before going to get ${his} uncomfortably milk-filled tits drained.`);
							} else {
								text.push(`and then rests until ${his} balls are ready to be drained again.`);
							}
							break;
						case "please you":
							text.push(`${He} uses an enema to clean ${his} ${anus} before returning to await your next use of ${his} backdoor, as though nothing had happened.`);
							break;
						case "be a subordinate slave":
							text.push(`${He} uses an enema to clean ${his} ${anus}, though it's only a matter of time before another slave decides to play with ${his} backdoor.`);
							break;
						case "be your Head Girl":
							text.push(`${He} uses an enema to clean ${his} ${anus}, worried that ${his} charges got up to trouble while ${he} enjoyed the buttsex.`);
							break;
						case "guard you":
							text.push(`${He} hurries off to wash ${his} ${anus} so you'll be unguarded for as little time as possible.`);
							break;
						case "be the Schoolteacher":
							text.push(`${He} uses an enema to clean ${his} ${anus} before ${he} returns to teaching ${his} classes, a little bow-legged.`);
							break;
						default:
							text.push(`${He} hurries off to wash ${his} ${anus} before going back to ${slave.assignment}.`);
					}
				}
			}
		}

		return text.join(' ');
	}
};

license: mit


code:
/**
 *
 * @param {App.Entity.SlaveState} slave
 * @returns {DocumentFragment}
 */
App.Interact.fAssistedSex = function(slave) {
	const frag = new DocumentFragment();

	const {
		He,
		he, his, him, himself
	} = getPronouns(slave);

	seX(slave, "oral", V.PC);

	const text = new SpacedTextAccumulator(frag);

	text.push(
		intro(),
		setup(),
		consummation(),
		cleanup(),
	);

	text.toParagraph();

	return frag;

	function intro() {
		const text = [];

		text.push(`You order ${his} servants forward so that ${he} can tease you with ${his} enormously swollen body.`);

		if (slave.devotion > 95) {
			text.push(`Smirking, ${he} leans backwards,`);
			if (hasBothArms(slave)) {
				text.push(`raising ${his} hands above ${his} head`);
			} else if (hasAnyArms(slave)) {
				text.push(`raising ${his} hand above ${his} head`);
			} else {
				text.push(`with two slender arms rising upward behind ${him}, making it look like ${he} has limbs once more`);
			}
			text.push(`as a gaggle of ${his} trained menials slide underneath ${his} belly, lifting the monolithic organ off the ground and setting the tightly packed orb to wobbling.`);
		} else if (slave.trust < -20 && slave.devotion > -10) {
			text.push(`Smiling nervously, ${he} leans backwards,`);
			if (hasBothArms(slave)) {
				text.push(`raising ${his} hands above ${his} head`);
			} else if (hasAnyArms(slave)) {
				text.push(`raising ${his} hand above ${his} head`);
			} else {
				text.push(`with two slender arms rising upward behind ${him}, making it look like ${he} has limbs once more`);
			}
			text.push(`as a gaggle of ${his} trained menials slide underneath ${his} belly, lifting the monolithic organ off the ground and setting the tightly packed orb to wobbling.`);
		} else {
			if (hasBothArms(slave)) {
				text.push(`${He} covers ${his}`);
				if (canSee(slave)) {
					text.push(`eyes`);
				} else {
					text.push(`face`);
				}
				text.push(`with ${his} hands,`);
			} else if (hasAnyArms(slave)) {
				text.push(`${He} tries to cover ${his}`);
				if (canSee(slave)) {
					text.push(`eyes`);
				} else {
					text.push(`face`);
				}
				text.push(`with ${his} hand,`);
			} else {
				text.push(`Two slender arms snake around from behind ${him}, almost making it look like ${he} has limbs once more. They cover ${his} quivering`);
				if (canSee(slave)) {
					text.push(`eyes`);
				} else {
					text.push(`expression`);
				}
			}

			text.push(`as a gaggle of ${his} trained menials slide underneath ${his} belly, lifting the monolithic organ off the ground and setting the tightly packed orb to wobbling.`);

			if (hasBothArms(slave)) {
				text.push(`Two more servants take hold of ${his} arms, forcing ${him} to lift them above ${his} head.`);
			} else if (hasAnyArms(slave)) {
				text.push(`Another servant takes hold of ${his} arm, forcing ${him} to lift it above ${his} head.`);
			} else {
				text.push(`The hands covering ${his}`);
				if (canSee(slave)) {
					text.push(`eyes`);
				} else {
					text.push(`head`);
				}
				text.push(`draw away, revealing ${his} crying face, then lift above ${his} head in a deliberately provocative pose.`);
			}

			text.push(`${He} tenses in a moment of instinctive resistance, then surrenders ${his} body to ${his} aids' total control, clearly afraid of punishment.`);
		}

		return text.join(' ');
	}

	function setup() {
		const text = [];

		text.push(`You remove your clothes and lie back on the office couch,`);

		if (V.PC.dick !== 0) {
			text.push(`allowing your exposed, full-mast dick to loll in front of you.`);
		} else {
			text.push(`spreading your exposed, oozing twat.`);
		}

		return text.join(' ');
	}

	function consummation() {
		const text = [];

		if (slave.devotion > 95) {
			text.push(`Licking ${his} lips,`);
		} else if (slave.trust < -20 && slave.devotion > -10) {
			text.push(`Breathing heavily,`);
		} else {
			text.push(`With a fake smile,`);
		}

		text.push(`${he} draws toward you, half-floating on a river of silent, groping hands. When ${he} is mere`);

		if (V.showInches === 2) {
			text.push(`inches`);
		} else {
			text.push(`centimeters`);
		}

		text.push(`away from you, ${his} servants lift ${him} higher, and ${he}`);

		if (V.PC.dick !== 0) {
			text.push(`teases your dick with a series of masterful — and carefully balanced — belly isolations, rubbing the thick nub of ${his} belly button in small semicircles around your oozing cockhead as ${he} does so. Right when you feel ready to explode, ${he} rotates around, bringing`);

			if (slave.butt > 11) {
				text.push(`${his} overgrown, wobbling ass cheeks`);
			} else if (slave.butt > 5) {
				text.push(`${his} huge, wobbling ass cheeks`);
			} else if (Math.floor(slave.buttImplant/slave.butt) > .60) {
				text.push(`${his} saline inflated ass cheeks`);
			} else if (slave.butt > 2) {
				text.push(`${his} wobbling ass cheeks`);
			} else {
				text.push(`the shallow inverted bowls of ${his} petite ass cheeks`);
			}

			text.push(`level with your erection. Two of ${his} servants reach around ${his} inflated profile and push ${his} cheeks together, wrapping your dick in a firm layer of butt cleavage. ${He} lifts ${his} ass, then drops it, again and again, smacking your chest on the downswing as ${his} servants manipulate ${his} hotdogging to maximize your pleasure.`);

			if (canDoVaginal(slave)) {
				text.push(`When you feel the tension within you reaching its apex, you signal to ${his} servants to hold ${him} in place. With ${his} silent menials, still as statues, anchoring ${his} bloated body at the perfect angle for fucking while contorting their anonymous bodies to frame ${him} in a manner that maximizes ${his} visual attractiveness, you grab hold of ${his} flanks and ram into ${his} pregnant pussy, driving ${him} to the first of many orgasms in just a few casual thrusts.`);
				text.push(VCheck.Vaginal(slave, 1));
				text.push(`When you feel your own orgasm approaching, you pull out, ejaculating`);
			} else if (canDoAnal(slave)) {
				text.push(`When you feel the tension within you reaching its apex, you signal to ${his} servants to hold ${him} in place. With ${his} silent menials, still as statues, anchoring ${his} bloated body at the perfect angle for fucking while contorting their anonymous bodies to frame ${him} in a manner that maximizes ${his} visual attractiveness, you grab hold of ${his} flanks and ram into ${his} asshole, driving ${him} to the first of many orgasms with just a few casual thrusts.`);
				text.push(VCheck.Anal(slave, 1));
				text.push(`When you feel your own orgasm approaching, you pull out, ejaculating`);
			} else {
				text.push(`When you feel the tension with your reaching its apex, you signal to ${his} servants and they pull ${him} forward. You ejaculate`);
			}

			text.push(`a thick stream of semen all over ${his} ass and back, ${he} shifts into a kneeling position on the ground in front of you, tilted sideways so that ${his} massive fecundity can pool on the ground beside ${him}, and gently sucks you off, cleaning your dick with ${his} mouth.`);
		} else {
			text.push(`Presses the thick nub of ${his} belly button into your pussy, rubbing it back and forth against your engorged clit as ${he} performs a series of masterful — and carefully balanced — belly isolations. After ${he} has you quaking at the edge of release, ${he} rolls forward and buries ${his} head in your lap, plying you with ${his}`);

			if (slave.devotion > 95) {
				text.push(`devoted tongue`);
			} else if (slave.trust < -20 && slave.devotion > -10) {
				text.push(`dedicated tongue`);
			} else {
				text.push(`tongue`);
			}

			text.push(`and driving you into a series of crashing orgasms. When ${his} tongue tires, ${he} tries to draw away, but you grab hold of ${his} head and hold ${him} in place until you are finished.`);
		}

		return text.join(' ');
	}

	function cleanup() {
		return `Once you are satisfied, you send ${him} away to clean ${himself} up before returning to ${his} duties.`;
	}
};