code:
/** Administer rewards and punishments for the slave
 * @param {App.Entity.SlaveState} forSlave
 * @returns {string}
 */
App.SlaveAssignment.rewardAndPunishment = function rewardAndPunish(forSlave) {
	/** @type {string[]} */
	const r = [];

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

	let rewards = 0;
	let punishments = 0;
	let combinedText = false;

	if (slave.assignment === Job.CLINIC && random(-200, 200) < slave.health.health) {
		r.push(`${He} does not feel up to doing much, so ${he} needs neither rewards nor punishments this week.`);
	} else {
		const you = (slave.assignment !== Job.HEADGIRLSUITE) ? `you` : `you and ${S.HeadGirl.slaveName}`;
		if (slave.devotion > 50) {
			r.push(`${He} does ${his} best for ${you}, so ${he} frequently deserves a reward and never needs to be punished.`);
			punishments = 0;
			rewards = 3;
		} else if (slave.devotion > 20) {
			r.push(`${He}'s obedient out of acceptance of ${his} place, so ${he} often deserves a reward and rarely needs to be punished.`);
			punishments = 1;
			rewards = 2;
		} else if (slave.devotion >= -20) {
			if (slave.trust < -20) {
				r.push(`${He}'s obedient out of fear, so ${he} only rarely deserves a reward and sometimes needs to be punished.`);
				punishments = 1;
				rewards = 1;
			} else {
				r.push(`${He}'s too trusting for obedience and often needs to be punished.`);
				punishments = 2;
				rewards = 0;
			}
		} else {
			if (slave.trust < -50) {
				r.push(`${He}'s only obedient out of terror, so ${he} sometimes needs to be punished.`);
				punishments = 1;
				rewards = 0;
			} else {
				r.push(`${He} hates ${you} too much to obey, so ${he} needs constant punishment.`);
				punishments = 3;
				rewards = 0;
			}
		}
	}

	combinedText = (slave.rules.reward === slave.rules.punishment) && rewards > 0 && punishments > 0;
	if (rewards > 0) {
		r.push(...reward(slave, slave.rules.reward));
	}
	if (punishments > 0) {
		r.push(...punish(slave, slave.rules.punishment));
	}
	return r.join(' ');

	/**
	 * @param {FC.SlaveState} slave
	 * @param {"relaxation" | "drugs" | "orgasm" | "situational" | "confinement"} type
	 * @returns {string[]}
	 */
	function reward(slave, type) {
		/** @type {string[]} */
		const r = [];
		switch (type) {
			case "relaxation":
				r.push(`${He}'s given free time, which ${he}`);
				if (slave.assignment === Job.CLINIC) {
					r.push(`spends with the amenities present in ${V.clinicName} for recovering slaves to pass the time.`);
				} else if (slave.assignment === Job.ATTENDANT) {
					r.push(`usually spends soaking in a hot bath or enjoying the amenities ${his} facility has to offer.`);
				} else if (slave.assignment === Job.CONCUBINE) {
					if (V.spa !== 0) {
						r.push(`usually sets aside to spend with you in ${V.spaName}.`);
					} else {
						r.push(`usually spends relaxing with you.`);
					}
				} else if (V.spa !== 0) {
					const where = (slave.assignment !== Job.SPA) ? V.spaName : `a private bath`;
					const attendant = S.Attendant ? `, enjoying ${S.Attendant.slaveName}'s care` : ``;
					r.push(`usually spends in ${where}${attendant}.`);
				} else if (slave.assignment === Job.MASTERSUITE) {
					r.push(`usually spends relaxing on ${his} favorite pillow.`);
				} else if (slave.assignment === Job.HEADGIRLSUITE) {
					r.push(`usually spends relaxing in your Head Girl's private room.`);
				} else if (slave.rules.living === "luxurious") {
					let roomActivity = '';
					if (slave.assignment === Job.NURSE) {
						roomActivity = ` amusing ${himself} with the amenities for recovering slaves`;
					} else if (slave.assignment === Job.WARDEN && App.Entity.facilities.cellblock.employeesIDs().size > 0) {
						roomActivity = ` teaching a disobedient slave how to properly use their mouth`;
					} else if (slave.assignment === Job.TEACHER && App.Entity.facilities.schoolroom.employeesIDs().size > 0) {
						roomActivity = ` giving private lessons to a student`;
					} else if (slave.assignment === Job.STEWARD && App.Entity.facilities.servantsQuarters.employeesIDs().size > 0) {
						roomActivity = ` while enjoying some service from ${his} underlings`;
					} else if (slave.assignment === Job.MILKMAID && App.Entity.facilities.dairy.employeesIDs().size > 0) {
						roomActivity = ` with the softest cow available`;
					} else if (slave.assignment === Job.FARMER && App.Entity.facilities.farmyard.employeesIDs().size > 0) {
						roomActivity = ` with the softest cow available`; // FIXME: needs improvement
					} else if (canSee(slave) && (slave.intelligence + slave.intelligenceImplant > 50)) {
						roomActivity = ` reading books`;
					} else if (canSee(slave) && canHear(slave)) {
						roomActivity = ` watching television`;
					} else if (canSee(slave)) {
						roomActivity = ` reading magazines`;
					} else if (canHear(slave)) {
						roomActivity = ` listening to music`;
					}
					r.push(`usually spends relaxing in ${his} private room${roomActivity}.`);
				} else if (slave.assignment === Job.SCHOOL) {
					r.push(`usually spends relaxing in ${his} dorm room.`);
				} else {
					r.push(`usually spends relaxing in the slave quarters.`);
				}
				if (slave.relationship > 0) {
					r.push(`${He} often asks to save these breaks so ${he} can spend them with ${his} ${relationshipTerm(slave)}.`);
				}
				r.push(`These breaks are <span class="health inc">good for ${him}.</span>`);
				improveCondition(slave, rewards);
				return r;

			case "drugs":
				r.push(`${He}'s <span class="hotpink">rewarded</span> with hits of mild recreational drugs, which <span class="health dec">isn't healthy,</span> but helps bind ${him} to you strongly.`);
				if ([Job.CLUB, Job.PUBLIC].includes(slave.assignment)) {
					r.push(`${His} patrons don't complain either.`);
				}
				healthDamage(slave, rewards);
				slave.devotion += rewards * 2;
				return r;

			case "orgasm":
				r.push(`${He}'s <span class="hotpink">rewarded</span> with`);
				if (slave.piercing.genitals.smart) {
					r.push(`sustained orgasm from ${his}`);
					if (slave.dick === 0) {
						r.push(`clit`);
					} else {
						r.push(`dick`);
					}
					r.push(`piercing,`);
					if (slave.assignment === Job.CLUB) {
						r.push(`often on stage during a dance,`);
					}
				} else if ([Job.CONCUBINE, Job.MASTERSUITE, Job.FUCKTOY].includes(slave.assignment)) {
					if (slave.rules.release.master) {
						r.push(`immediate sex with you,`);
						seX(slave, canDoVaginal(slave) ? "vaginal" : "anal", V.PC);
					} else {
						r.push(`an orgasm directly from the hand of ${his} ${getWrittenTitle(slave)},`);
					}
				} else if (slave.rules.release.slaves === 1) {
					r.push(`immediate sex with any nearby slave,`);
					seX(slave, canDoVaginal(slave) ? "vaginal" : "anal", "slaves");
				} else {
					r.push(`a quick climax from a vibrator,`);
				}
				r.push(`<span class="libido inc">boosting ${his} libido.</span>`);
				if (slave.energy < 98) {
					slave.energy += rewards;
				}
				slave.need -= (rewards * 10);
				slave.devotion += rewards;
				return r;

			case "situational":
				r.push(`${He}'s <span class="hotpink">rewarded</span>`);
				if (combinedText) {
					r.push(`and <span class="gold">punished</span>`);
				}
				r.push(`situationally, letting ${him} develop normally.`);
				slave.devotion += rewards;
				return r;
		}
	}

	/**
	 * @param {FC.SlaveState} slave
	 * @param {"confinement" | "whipping" | "chastity" | "situational"} type
	 * @returns {string[]}
	 */
	function punish(slave, type) {
		/** @type {string[]} */
		const r = [];
		switch (type) {
			case "confinement":
				r.push(`When ${he} disobeys,`);
				if (slave.assignment === Job.CLINIC) {
					r.push(`${he} spends ${his} time <span class="gold">strapped</span> to ${his} bed until ${he} behaves.`);
				} else if (slave.assignment === Job.DAIRY) {
					r.push(`${he} spends ${his} time <span class="gold">getting milked in a cramped dark stall</span> until ${he} behaves.`);
				} else if (V.cellblock !== 0) {
					if (slave.assignment === Job.CELLBLOCK) {
						r.push(`${he} <span class="gold">spends ${his} day in solitary.</span>`);
					} else if (slave.assignment === Job.SCHOOL) {
						r.push(`${he} <span class="gold">is assigned detention after school in ${V.cellblockName}</span>${S.Wardeness ? `, where ${he} can experience ${S.Wardeness.slaveName}'s teaching methods` : ``}.`);
					} else if (slave.assignment === Job.QUARTER) {
						r.push(`${he} <span class="gold">spends ${his} day (and night) cleaning the cells in ${V.cellblockName}</span>${S.Wardeness ? `, where ${he} can experience ${S.Wardeness.slaveName}'s tender mercies` : ``}.`);
					} else {
						r.push(`${he} <span class="gold">spends ${his} off hours in ${V.cellblockName}</span>${S.Wardeness ? `, where ${he} can experience ${S.Wardeness.slaveName}'s tender mercies` : ``}.`);
					}
				} else {
					r.push(`${he} spends ${his} off hours <span class="gold">shut up in a box</span> until ${he} behaves.`);
				}
				slave.trust -= punishments;
				return r;

			case "whipping":
				r.push(`When ${he} disobeys, ${he}'s`);
				if (slave.assignment === Job.SCHOOL) {
					r.push(`dragged to the front of the class and`);
				}
				r.push(`<span class="gold">whipped,</span> not hard enough to mark ${him}${slave.assignment === Job.CLINIC ? `or complicate ${his} stay` : ``}, but hard enough to hurt, breaking ${him} quickly.`);
				healthDamage(slave, punishments);
				slave.trust -= 2 * punishments;
				return r;

			case "chastity":
				r.push(`When ${he} disobeys,`);
				if (slave.assignment === Job.BROTHEL) {
					r.push(`${he} finds ${his} next client is into <span class="gold">orgasm denial,</span>`);
				} else if (slave.assignment === Job.CLUB) {
					r.push(`${he} finds ${his} next dance to be both extremely sexual and <span class="gold">completely unsatisfying,</span>`);
				} else if (slave.assignment === Job.CELLBLOCK) {
					r.push(`${he}'s given a hit of mild aphrodisiacs and <span class="gold">left to squirm without release,</span>`);
				} else if (slave.assignment === Job.SCHOOL) {
					r.push(`${he}'s dragged to the front of the class for a lesson on edging. ${He} is kept <span class="gold">just shy of orgasm</span> for the rest of the day,`);
				} else if (slave.assignment === Job.QUARTER) {
					r.push(`${he} finds ${himself} cleaning up around an ongoing orgy, yet <span class="gold">forbidden from getting off,</span>`);
				} else if (slave.assignment === Job.DAIRY) {
					r.push(`${he} finds ${his} <span class="gold">milkings fewer and farther between,</span>`);
				} else {
					r.push(`${he}'s <span class="gold">denied</span> ${his} next orgasm,`);
				}
				r.push(`<span class="libido dec">reducing ${his} libido</span> but breaking ${him} to <span class="hotpink">sexual obedience.</span>`);
				if (slave.energy > 2) {
					slave.energy -= 2 * punishments;
				}
				slave.devotion += punishments;
				slave.trust -= punishments;
				return r;

			case "situational":
				if (!combinedText) {
					r.push(`When ${he} disobeys, ${he}'s <span class="gold">punished</span> situationally, letting ${him} develop normally.`);
				}
				slave.trust -= punishments;
				return r;
		}
	}
};


code:
/**
 * @param {App.Entity.SlaveState} slave
 * @returns {string}
 */
App.SlaveAssignment.rivalries = function saRivalries(slave) {
	/** @type {string[]} */
	const r = [];

	let changed = false;

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

	if (canStartRivalry(slave)) {
		if (isSlaveAvailable(slave) && slave.assignment !== Job.CONFINEMENT) {
			generateRivalry(slave);
		}
	} else if (slave.rivalry) {
		existingRivalry(slave);
	}
	if (slave.rivalry) {
		rivalryValidation(slave);
	}

	return r.join(" ");

	/** Can this slave possibly get a new rival?
	 * @param {App.Entity.SlaveState} slave
	 * @returns {boolean}
	 */
	function canStartRivalry(slave) {
		const headstrong = (slave.devotion < jsRandom(20, 100)) && (slave.trust > jsRandom(-100, -20));
		const distant = (slave.assignment === Job.AGENTPARTNER || slave.assignment === Job.AGENT);
		return (slave.rivalry === 0 && slave.fetish !== Fetish.MINDBROKEN && slave.fuckdoll === 0 && !distant && headstrong);
	}

	/**
	 * @param {App.Entity.SlaveState} slave
	 *
	 */
	function generateRivalry(slave) {
		let foundRival = 0;

		for (const potentialRival of V.slaves) {
			if (canStartRivalry(potentialRival) && potentialRival.ID !== slave.ID && potentialRival.ID !== slave.relationshipTarget) {
				if (potentialRival.origBodyOwnerID === slave.ID && potentialRival.devotion > 0 && slave.devotion < -30) {
					r.push(`${slave.slaveName} loathes that ${SlaveFullName(potentialRival)} is using ${his} body to benefit you and makes it abundantly clear every chance ${he} gets. They start to dislike each other.`);
					foundRival = 1;
				}
				if (foundRival !== 1 && slave.behavioralFlaw !== "none") {
					switch (slave.behavioralFlaw) {
						case "arrogant":
							if (potentialRival.intelligence > slave.intelligence + slave.intelligenceImplant) {
								r.push(`${slave.slaveName} is an arrogant bitch, and ${SlaveFullName(potentialRival)} is authentically smarter than ${he} is, which of course ${he} cannot stand. They start to dislike each other.`);
								foundRival = 1;
							}
							break;
						case "bitchy":
							if (potentialRival.behavioralFlaw === "odd") {
								r.push(`${slave.slaveName} is a bit of a bitch, and poor odd ${SlaveFullName(potentialRival)} is a convenient target for ${his} bullying. <span class="rivalry inc">They start to dislike each other.</span>`);
								foundRival = 1;
							}
							break;
						case "odd":
							if (potentialRival.behavioralFlaw === "bitchy") {
								r.push(`${slave.slaveName} is rather strange. ${SlaveFullName(potentialRival)}, who is kind of a bitch, frequently bullies ${him} about it. <span class="rivalry inc">They start to dislike each other.</span>`);
								foundRival = 1;
							}
							break;
						case "hates men":
							if (potentialRival.attrXX > 35) {
								if (potentialRival.faceShape === "masculine" || potentialRival.faceShape === "androgynous") {
									if (potentialRival.muscles > 10) {
										if (potentialRival.vagina > -1) {
											r.push(`${slave.slaveName} hates men, and poor butch ${SlaveFullName(potentialRival)} really gets to ${him}, despite having a pussy and everything. They start to dislike each other.`);
											foundRival = 1;
										} else {
											r.push(`${slave.slaveName} hates men, and poor masculine ${SlaveFullName(potentialRival)} really gets to ${him}. <span class="rivalry inc">They start to dislike each other.</span>`);
											foundRival = 1;
										}
									}
								}
							}
							break;
						case "hates women":
							if (potentialRival.attrXY > 35) {
								if (potentialRival.faceShape !== "masculine") {
									if (potentialRival.muscles <= 30) {
										if (potentialRival.vagina > -1) {
											r.push(`${slave.slaveName} hates women, and something about the feminine ${SlaveFullName(potentialRival)} really gets to ${him}. <span class="rivalry inc">They start to dislike each other.</span>`);
											foundRival = 1;
										} else {
											r.push(`${slave.slaveName} hates women, and something about the girly ${SlaveFullName(potentialRival)} really gets to ${him}, despite poor ${potentialRival.slaveName} not being perfectly female at all. They start to dislike each other.`);
											foundRival = 1;
										}
									}
								}
							}
							break;
						case "gluttonous":
							if (potentialRival.behavioralFlaw === "anorexic") {
								r.push(`${slave.slaveName}, who loves food, can't stand ${SlaveFullName(potentialRival)}'s prissy anorexia. <span class="rivalry inc">They start to dislike each other.</span>`);
								foundRival = 1;
							} else if (potentialRival.weight < -30) {
								r.push(`${slave.slaveName}, who loves food, can't stand ${SlaveFullName(potentialRival)}'s severe emaciation. <span class="rivalry inc">They start to dislike each other.</span>`);
								foundRival = 1;
							}
							break;
						case "anorexic":
							if (potentialRival.behavioralFlaw === "gluttonous") {
								r.push(`${slave.slaveName}, an anorexic, can't stand ${SlaveFullName(potentialRival)}'s disgusting gluttony. <span class="rivalry inc">They start to dislike each other.</span>`);
								foundRival = 1;
							} else if (potentialRival.weight > 95) {
								r.push(`${slave.slaveName}, an anorexic, can't stand ${SlaveFullName(potentialRival)}'s immense girth. <span class="rivalry inc">They start to dislike each other.</span>`);
								foundRival = 1;
							}
							break;
						case "devout":
							if (potentialRival.behavioralFlaw === "liberated") {
								r.push(`${slave.slaveName}, who is devout and might be considered rather conservative if ${he} were free, can't stand ${SlaveFullName(potentialRival)}'s revolting gender liberation. They start to dislike each other.`);
								foundRival = 1;
							}
							break;
						case "liberated":
							if (potentialRival.behavioralFlaw === "devout") {
								r.push(`${slave.slaveName}, who is liberated and might be considered rather liberal if ${he} were free, can't stand ${SlaveFullName(potentialRival)}'s bigoted religious faith. They start to dislike each other.`);
								foundRival = 1;
							}
							break;
					}
				}
				if (foundRival !== 1 && potentialRival.assignment === slave.assignment) {
					if (jsRandom(0, 1) === 1) {
						r.push(`${slave.slaveName} and ${SlaveFullName(potentialRival)} see too much of each other while they`);
						switch (potentialRival.assignment) {
							case Job.HOUSE:
							case Job.QUARTER:
								r.push(`work as servants`);
								break;
							case Job.SUBORDINATE:
								r.push(`prepare to serve your other slaves`);
								break;
							case Job.GLORYHOLE:
								r.push(`work nearby glory holes`);
								break;
							case Job.CELLBLOCK:
								r.push(`are confined in nearby cells`);
								break;
							case Job.FUCKTOY:
								r.push(`wait for you to use them`);
								break;
							default:
								r.push(potentialRival.assignment);
						}
						r.push(`and <span class="rivalry inc">start to dislike each other.</span>`);
						foundRival = 1;
					}
				}
				if (foundRival === 1) {
					// needed to break the loop if the case statement picked a rival.
					// might as well use it to condense all the rival sets too.
					slave.rivalry = 1;
					slave.rivalryTarget = potentialRival.ID;
					potentialRival.rivalry = 1;
					potentialRival.rivalryTarget = slave.ID;
					break;
				}
			}
		}
	}

	/**
	 * @param {App.Entity.SlaveState} slave
	 * @param {App.Entity.SlaveState} rival
	 */
	function reduce(slave, rival) {
		rival.rivalry--;
		slave.rivalry--;
		if (slave.rivalry === 0) {
			rival.rivalryTarget = 0;
			slave.rivalryTarget = 0;
		}
		changed = true;
	}

	/**
	 * @param {App.Entity.SlaveState} slave
	 * @param {App.Entity.SlaveState} rival
	 */
	function increase(slave, rival) {
		rival.rivalry++;
		slave.rivalry++;
		changed = true;
	}

	/**
	 * @param {App.Entity.SlaveState} slave
	 * @param {App.Entity.SlaveState} rival
	 */
	function reconcile(slave, rival) {
		rival.rivalry = 0;
		rival.rivalryTarget = 0;
		slave.rivalry = 0;
		slave.rivalryTarget = 0;
		changed = true;
	}

	/**
	 * @param {App.Entity.SlaveState} slave
	 */
	function existingRivalry(slave) {
		const rival = getSlave(slave.rivalryTarget);
		let roll = jsRandom(0, 100);
		changed = false;

		if (rival === undefined) {
			r.push(`<span class="red">Error, rivalryTarget not found.</span>`);
		} else {
			if (slave.fuckdoll) {
				r.push(`${slave.slaveName} is a living sex toy, not a person, it <span class="rivalry dec">can't really maintain any meaningful rivalry</span> with ${SlaveFullName(rival)}.`);
				reconcile(slave, rival);
			} else if (slave.fetish === Fetish.MINDBROKEN) {
				r.push(`Since ${slave.slaveName} is mindbroken, ${he} <span class="rivalry dec">can't really maintain any meaningful rivalry</span> with ${SlaveFullName(rival)}.`);
				reconcile(slave, rival);
			} else if (rival.ID === slave.relationshipTarget && slave.relationship > 3) {
				r.push(`Since ${slave.slaveName} and ${slave.slaveName} are in a committed sexual relationship, they can't really maintain any meaningful rivalry; most disputes just end in a quick hatefucking.`);
				reconcile(slave, rival);
			} else {
				if (slave.need) {
					if (V.universalRulesConsent === 0) {
						if (App.Utils.sexAllowed(slave, rival)) {
							if (slave.fetishKnown) {
								if (slave.fetish === "sadist") {
									r.push(`${slave.slaveName} is horny and sadistic, so ${he} rapes ${his} rival ${SlaveFullName(rival)} every chance ${he} gets; this thrills ${slave.slaveName}, but ${rival.slaveName} is frightened that you let it happen.`);
									slave.need = 0;
									slave.devotion += 3;
									rival.trust -= 3;
									if (slave.rivalry < 3) {
										r.push(`Of course, this <span class="rivalry inc">worsens their rivalry.</span>`);
										increase(slave, rival);
									}
									SimpleSexAct.Slaves(rival, slave, 5);
								} else if (slave.fetish === "dom") {
									r.push(`${slave.slaveName} is horny and dominant, so ${he} forces ${his} rival ${SlaveFullName(rival)} to submit to ${him} whenever ${he} can; this thoroughly satisfies ${slave.slaveName}, but ${rival.slaveName} is angered that you let it happen.`);
									slave.need = 0;
									slave.devotion += 3;
									rival.devotion -= 3;
									if (slave.rivalry < 3) {
										r.push(`Of course, this <span class="rivalry inc">worsens their rivalry.</span>`);
										increase(slave, rival);
									}
									SimpleSexAct.Slaves(rival, slave, 5);
								}
							}
						}
					}
				}
				if (!changed && roll > 50) {
					if (rival.fetish === slave.fetish) {
						r.push(`${slave.slaveName} and ${SlaveFullName(rival)} share sexual interests, and in the sexual atmosphere of the arcology, it's difficult for them to keep up their dislike of one another with the mutual attraction.`);
						reduce(slave, rival);
					}
					if (roll > 80 && slave.rivalry > 0) {
						if (!changed && rival.trust < -20) {
							if (slave.trust < -20) {
								r.push(`Since both ${slave.slaveName} and ${SlaveFullName(rival)} are terrified of you, they work together to <span class="rivalry dec">get over their feud,</span> since it brings punishment on both of them.`);
								reduce(slave, rival);
							}
						}
						if (!changed && rival.devotion > 50) {
							if (slave.devotion > 50) {
								r.push(`Since both ${slave.slaveName} and ${SlaveFullName(rival)} are devoted to you, they work together to <span class="rivalry dec">get over their feud,</span> since it gets in the way of their duties.`);
								reduce(slave, rival);
							}
						}
						if (roll > 90 && slave.rivalry > 0) {
							if (!changed && slave.energy > 95) {
								r.push(`${slave.slaveName} lusts after ${SlaveFullName(rival)}, and does everything ${he} can to <span class="rivalry dec">patch up their differences.</span>`);
								reduce(slave, rival);
							}
							if (!changed && slave.attrXX > 85) {
								if (rival.vagina > -1 || rival.faceShape !== "masculine") {
									r.push(`${slave.slaveName} lusts after ${SlaveFullName(rival)}, and does everything ${he} can to <span class="rivalry dec">patch up their differences.</span>`);
									reduce(slave, rival);
								}
							}
							if (!changed && slave.attrXY > 85) {
								if (canAchieveErection(rival) || rival.faceShape === "masculine") {
									r.push(`${slave.slaveName} lusts after ${SlaveFullName(rival)}, and does everything ${he} can to <span class="rivalry dec">patch up their differences.</span>`);
									reduce(slave, rival);
								}
							}
							if (!changed && rival.assignment !== slave.assignment) {
								if (slave.subTarget !== rival.ID && rival.subTarget !== slave.ID) {
									r.push(`With time apart ${slave.slaveName} and ${SlaveFullName(rival)} <span class="rivalry dec">dislike each other less.</span>`);
									reduce(slave, rival);
								}
							}
						}
					}
				}
				if (!changed && areRelated(slave, rival)) {
					if (roll > 70 && slave.rivalry < 3) {
						r.push(`${slave.slaveName} and ${SlaveFullName(rival)} <span class="rivalry inc">pursue their family rivalry.</span>`);
						increase(slave, rival);
					} else if (roll > 40 && slave.rivalry > 0) {
						r.push(`${slave.slaveName} and ${SlaveFullName(rival)} <span class="rivalry dec">patch up their family relationship.</span>`);
						reduce(slave, rival);
					}
				}
				if (!changed && rival.origBodyOwnerID === slave.ID) {
					if (slave.rivalry < 3) {
						r.push(`${slave.slaveName} <span class="rivalry inc">refuses to accept ${SlaveFullName(rival)}'s control of ${his} former body,</span> worsening their rivalry.`);
						increase(slave, rival);
					}
				} else if (!changed && roll > (slave.devotion - slave.trust + 10)) {
					if (slave.rivalry < 3) {
						r.push(`${slave.slaveName} <span class="rivalry inc">bickers with ${SlaveFullName(rival)}</span> whenever ${he} can, worsening their rivalry.`);
						increase(slave, rival);
					}
				} else if (!changed && roll < (slave.devotion - slave.trust - 10) && slave.rivalry > 0) {
					r.push(`${slave.slaveName} does ${his} best to be nice to ${SlaveFullName(rival)}, and manages to <span class="rivalry dec">de-escalate their little feud.</span>`);
					reduce(slave, rival);
				}
			}
		}
	}

	/**
	 * @param {App.Entity.SlaveState} slave
	 *
	 */
	function rivalryValidation(slave) {
		// This will be obsoleted with multiple rivals system
		const rival = getSlave(slave.rivalryTarget);
		if (rival !== undefined && slave.ID !== rival.rivalryTarget) {
			rival.rivalry = 0;
			rival.rivalryTarget = 0;
			slave.rivalry = 0;
			slave.rivalryTarget = 0;
		}
	}
};

repo_name: DontAskDontTell/fc

license: mit