From 1f3be2d5730dd6ec6dc7f8b66dbd3af3c658bb4a Mon Sep 17 00:00:00 2001
From: Svornost <11434-svornost@users.noreply.gitgud.io>
Date: Mon, 23 Dec 2019 13:42:50 -0800
Subject: [PATCH] Add a group of utility functions for determining how a slave
 is actually getting release (as opposed to how they are allowed to do so).

---
 src/js/releaseRules.js | 46 ++++++++++++++++++++++++++++++++++++++++++
 1 file changed, 46 insertions(+)

diff --git a/src/js/releaseRules.js b/src/js/releaseRules.js
index 2a19f47f112..03df626bd74 100644
--- a/src/js/releaseRules.js
+++ b/src/js/releaseRules.js
@@ -21,6 +21,52 @@ App.Utils.sexAllowed = function sexAllowed(slaveA, slaveB) {
 	}
 };
 
+/**
+ * Returns true if a slave has a romantic partner other than the PC who is both willing and allowed to have sex with her.
+ * @param {App.Entity.SlaveState} slave
+ * @returns {boolean}
+ */
+App.Utils.hasPartnerSex = function hasPartnerSex(slave) {
+	const hasWillingSlavePartner = (slave.rules.relationship === "permissive") && (slave.relationship >= 3) && (slave.relationshipTarget > 0);
+	return hasWillingSlavePartner && this.sexAllowed(slave, getSlave(slave.relationshipTarget));
+};
+
+/**
+ * Returns true if a slave has a close family member other than the PC who is both willing and allowed to have sex with her.
+ * @param {App.Entity.SlaveState} slave
+ * @returns {boolean}
+ */
+App.Utils.hasFamilySex = function hasFamilySex(slave) {
+	if (V.seeIncest === 0 || slave.rules.release.family === 0) {
+		return false;
+	}
+	if (V.familyTesting === 0 && slave.relationTarget > 0) {
+		return this.sexAllowed(slave, getSlave(slave.relationTarget));
+	} else { // familyTesting === 1
+		return jsDef(randomRelatedSlave(slave, (s) => { return this.sexAllowed(slave, s); }));
+	}
+};
+
+/**
+ * Returns true if a slave has no practical form of release.
+ * @param {App.Entity.SlaveState} slave
+ * @returns {boolean}
+ */
+App.Utils.hasNoOutlet = function hasNoOutlet(slave) {
+	const rel = slave.rules.release;
+	return (rel.masturbation === 0) && (rel.master === 0) && (rel.slaves === 0) && !this.hasPartnerSex(slave) && !this.hasFamilySex(slave);
+};
+
+/**
+ * Returns true if a slave's only practical form of release is masturbation.
+ * @param {App.Entity.SlaveState} slave
+ * @returns {boolean}
+ */
+App.Utils.mustMasturbate = function mustMasturbate(slave) {
+	const rel = slave.rules.release;
+	return (rel.masturbation === 1) && (rel.master === 0) && (rel.slaves === 0) && !this.hasPartnerSex(slave) && !this.hasFamilySex(slave);
+};
+
 /**
  * Returns a short summary of the slave's release rules
  * @param {App.Entity.SlaveState} slave
-- 
GitLab