From be448a6c2ed3c1900d04a2c6fe3c68a8e083ec4a Mon Sep 17 00:00:00 2001
From: Svornost <11434-svornost@users.noreply.gitgud.io>
Date: Mon, 8 Jun 2020 18:36:07 -0700
Subject: [PATCH] Do not apply SMR price minima to markets where SMRs are not
 applied.  Fix law compliance to not throw errors with intelligence and height
 SMRs.

---
 src/Corporation/corporateMarket.tw    |   2 +-
 src/js/slaveCostJS.js                 | 134 ++++++++++++++------------
 src/npc/descriptions/lawCompliance.js |  16 +--
 src/uncategorized/slaveMarkets.tw     |   2 +-
 4 files changed, 85 insertions(+), 69 deletions(-)

diff --git a/src/Corporation/corporateMarket.tw b/src/Corporation/corporateMarket.tw
index 47706c42641..285a7aece6d 100644
--- a/src/Corporation/corporateMarket.tw
+++ b/src/Corporation/corporateMarket.tw
@@ -95,7 +95,7 @@ while you browse.
 
 <br><br>
 
-<<set _slaveCost = slaveCost($activeSlave)>>
+<<set _slaveCost = slaveCost($activeSlave, false, true)>>
 <<if $slavesSeen > $slaveMarketLimit>><<set _slaveCost += _slaveCost*(($slavesSeen-$slaveMarketLimit)*0.1)>><</if>>
 
 <<if $corp.Market == 1>>
diff --git a/src/js/slaveCostJS.js b/src/js/slaveCostJS.js
index 8746c0a8ad9..2b315489b94 100644
--- a/src/js/slaveCostJS.js
+++ b/src/js/slaveCostJS.js
@@ -1,4 +1,8 @@
-globalThis.minimumSlaveCost = function() {
+/** Calculate the minimum slave cost for a given market
+ * @param {boolean} includeLaws
+ * @returns {number}
+ */
+globalThis.minimumSlaveCost = function(includeLaws) {
 	let value = 3000;
 
 	if (V.terrain === "urban") {
@@ -10,55 +14,57 @@ globalThis.minimumSlaveCost = function() {
 		value -= 1000;
 	}
 
-	if (V.policies.SMR.basicSMR === 1) {
-		value += 500;
-	}
-	if (V.policies.SMR.healthInspectionSMR === 1) {
-		value += 500;
-	}
-	if (V.policies.SMR.educationSMR === 1) {
-		value += 500;
-	}
-	if (V.policies.SMR.frigiditySMR === 1) {
-		value += 500;
-	}
-	if (V.policies.SMR.honestySMR === 1) {
-		value += 500;
-	}
-	value += policies.countEugenicsSMRs() * 500;
+	if (includeLaws) {
+		if (V.policies.SMR.basicSMR === 1) {
+			value += 500;
+		}
+		if (V.policies.SMR.healthInspectionSMR === 1) {
+			value += 500;
+		}
+		if (V.policies.SMR.educationSMR === 1) {
+			value += 500;
+		}
+		if (V.policies.SMR.frigiditySMR === 1) {
+			value += 500;
+		}
+		if (V.policies.SMR.honestySMR === 1) {
+			value += 500;
+		}
+		value += policies.countEugenicsSMRs() * 500;
 
-	if (V.policies.SMR.weightSMR === 1) {
-		value += 3000;
-	}
-	if (V.policies.SMR.beauty.basicSMR === 1) {
-		value += 3000;
-	}
-	if (V.policies.SMR.beauty.qualitySMR === 1) {
-		value += 10000;
-	}
-	if (V.policies.SMR.height.basicSMR !== 0) {
-		value += 5000;
-	}
-	if (V.policies.SMR.height.advancedSMR !== 0) {
-		value += 10000;
-	}
-	if (V.policies.SMR.intelligence.basicSMR === 1) {
-		value += 2000;
-	}
-	if (V.policies.SMR.intelligence.qualitySMR === 1) {
-		value += 10000;
-	}
+		if (V.policies.SMR.weightSMR === 1) {
+			value += 3000;
+		}
+		if (V.policies.SMR.beauty.basicSMR === 1) {
+			value += 3000;
+		}
+		if (V.policies.SMR.beauty.qualitySMR === 1) {
+			value += 10000;
+		}
+		if (V.policies.SMR.height.basicSMR !== 0) {
+			value += 5000;
+		}
+		if (V.policies.SMR.height.advancedSMR !== 0) {
+			value += 10000;
+		}
+		if (V.policies.SMR.intelligence.basicSMR === 1) {
+			value += 2000;
+		}
+		if (V.policies.SMR.intelligence.qualitySMR === 1) {
+			value += 10000;
+		}
 
-	const FS = [
-	'FSPaternalistSMR', 'FSBodyPuristSMR', 'FSTransformationFetishistSMR',
-	'FSYouthPreferentialistSMR', 'FSMaturityPreferentialistSMR', 'FSSlimnessEnthusiastSMR',
-	'FSAssetExpansionistSMR', 'FSPastoralistSMR', 'FSPhysicalIdealistSMR',
-	'FSHedonisticDecadenceSMR', 'FSEgyptianRevivalistSMR', 'FSEdoRevivalistSMR',
-	'FSArabianRevivalistSMR', 'FSChineseRevivalistSMR'
-	];
-	for (const key of FS) {
-		if (V.arcologies[0][key]) {
-			value += 500;
+		const FS = [
+			'FSPaternalistSMR', 'FSBodyPuristSMR', 'FSTransformationFetishistSMR',
+			'FSYouthPreferentialistSMR', 'FSMaturityPreferentialistSMR', 'FSSlimnessEnthusiastSMR',
+			'FSAssetExpansionistSMR', 'FSPastoralistSMR', 'FSPhysicalIdealistSMR',
+			'FSHedonisticDecadenceSMR', 'FSEgyptianRevivalistSMR', 'FSEdoRevivalistSMR',
+			'FSArabianRevivalistSMR', 'FSChineseRevivalistSMR'
+		];
+		for (const key of FS) {
+			if (V.arcologies[0][key]) {
+				value += 500;
+			}
 		}
 	}
 
@@ -2234,9 +2240,15 @@ globalThis.FResultTooltip = function(slave) {
 	}
 };
 
-globalThis.slaveCost = function(slave, isStartingSlave) {
+/**
+ * @param {App.Entity.SlaveState} slave
+ * @param {boolean} [isStartingSlave=false] is the slave a "starting slave"
+ * @param {boolean} [followLaws=false] Apply cost variations from enacted Slave Market Regulations
+ * @returns {number}
+ */
+globalThis.slaveCost = function(slave, isStartingSlave=false, followLaws=false) {
 	const milked = App.SlaveAssignment.getMilked(slave, true);
-	const beauty = slaveCostBeauty(slave, isStartingSlave);
+	const beauty = slaveCostBeauty(slave, isStartingSlave, followLaws);
 	if ((milked*52) > beauty && !isStartingSlave) { // Arbitrarily, let's say their milk worth is what they would make in a year. Blocking starting slave for now because milk makes so much money, the estimation makes game start impossible.
 		return milked*52;
 	} else {
@@ -2253,14 +2265,14 @@ globalThis.slaveCostBeauty = (function() {
 
 	/**
 	 * @param {App.Entity.SlaveState} slave
-	 * @param {number} isStartingSlave
-	 * @returns {number} Any number here means the slave
-	 * is a "starting slave"
+	 * @param {boolean} isStartingSlave is the slave a "starting slave"
+	 * @param {boolean} followLaws Apply cost variations from enacted Slave Market Regulations
+	 * @returns {number}
 	 */
-	function slaveCost(slave, isStartingSlave) {
+	function slaveCost(slave, isStartingSlave, followLaws) {
 		arcology = V.arcologies[0];
 		multiplier = V.slaveCostFactor;
-		cost = Beauty(slave) * FResult(slave, 1);
+		cost = Beauty(slave) * FResult(slave);
 
 		calcGenitalsCost(slave);
 		calcDevotionTrustCost(slave);
@@ -2277,7 +2289,7 @@ globalThis.slaveCostBeauty = (function() {
 		calcMiscCost(slave);
 		calcIndentureCost(slave); /* multipliers */
 
-		calcCost();
+		calcCost(followLaws);
 		if (isStartingSlave) {
 			calcStartingSlaveCost(slave);
 		}
@@ -2673,11 +2685,15 @@ globalThis.slaveCostBeauty = (function() {
 		}
 	}
 
-	function calcCost( /* slave */ ) {
+	/**
+	 * @param {boolean} followLaws
+	 */
+	function calcCost(followLaws) {
 		cost *= multiplier * 50;
 		cost = Number(cost) || 0;
-		if (cost < minimumSlaveCost()) {
-			cost = minimumSlaveCost();
+		const minimumCost = minimumSlaveCost(followLaws);
+		if (cost < minimumCost) {
+			cost = minimumCost;
 		} else if (cost <= 100000) {
 			/* do nothing */
 		} else if (cost <= 200000) {
diff --git a/src/npc/descriptions/lawCompliance.js b/src/npc/descriptions/lawCompliance.js
index 35768bc5dde..ff22f7e5857 100644
--- a/src/npc/descriptions/lawCompliance.js
+++ b/src/npc/descriptions/lawCompliance.js
@@ -239,7 +239,7 @@ App.Desc.lawCompliance = function(slave) {
 			slave.boobs += jsRandom(0, 2) * 100;
 			slave.butt += jsRandom(0, 1);
 			if (slave.face < 95) {
-				slave.face = Math.trunc(slave.face + jsRandom(0, 20), -100, 100);
+				slave.face = Math.clamp(slave.face + jsRandom(0, 20), -100, 100);
 			}
 			return `${His} balls were removed as soon as ${he} was enslaved, and ${he}'s been kept on powerful female hormones for long enough to have a general feminizing effect.`;
 		}
@@ -298,20 +298,20 @@ App.Desc.lawCompliance = function(slave) {
 
 	function FSPetiteAdmirationSMR() {
 		if (!heightPass(slave)) {
-			slave.height = Math.trunc(Height.jsRandom(slave, {limitMult: [-4, -2]}));
+			slave.height = Math.trunc(Height.random(slave, {limitMult: [-4, -2]}));
 		}
 		return `${His} height was meticulously taken before being allowed into the markets.`;
 	}
 
 	function FSStatuesqueGlorificationSMR() {
 		if (!heightPass(slave)) {
-			slave.height = Math.trunc(Height.jsRandom(slave, {limitMult: [2, 4]}));
+			slave.height = Math.trunc(Height.random(slave, {limitMult: [2, 4]}));
 		}
 		return `${His} height, as well as ${his} potential for growth, were meticulously taken before being allowed into the markets.`;
 	}
 
 	function FSIntellectualDependencySMR() {
-		slave.intelligence = Intelligence.jsRandom({limitIntelligence: [-100, -50]});
+		slave.intelligence = Intelligence.random({limitIntelligence: [-100, -50]});
 		slave.devotion += 5;
 		return `${He} passed the intelligence exam needed to be qualify ${him} for sale. A truly <span class= "hotpink">joyous achievement</span> for ${him}.`;
 	}
@@ -637,7 +637,7 @@ App.Desc.lawCompliance = function(slave) {
 	}
 
 	function heightAdvancedSMRup() {
-		slave.height = Math.round(Height.jsRandom(slave, {skew: V.policies.SMR.height.advancedSMR, limitMult: [0, 5 * V.AdvancedHeightSMR]}));
+		slave.height = Math.round(Height.random(slave, {skew: V.policies.SMR.height.advancedSMR, limitMult: [0, 5 * V.policies.SMR.height.advancedSMR]}));
 		r.push(`While ${he} was in the slave pens, ${he} saw that slaves on the shorter end of the height curve were immediately designated as menials and Fuckdolls.`);
 		if (slave.physicalAge < 16) {
 			r.push(`${He} is <span class="gold">terrified</span> that if ${he} doesn't keep growing, ${he}'ll be reassigned on the spot without a second thought.`);
@@ -649,7 +649,7 @@ App.Desc.lawCompliance = function(slave) {
 	}
 
 	function heightAdvancedSMRdown() {
-		slave.height = Math.round(Height.jsRandom(slave, {skew: V.policies.SMR.height.advancedSMR, limitMult: [0, 5 * V.AdvancedHeightSMR]}));
+		slave.height = Math.round(Height.random(slave, {skew: V.policies.SMR.height.advancedSMR, limitMult: [0, 5 * V.policies.SMR.height.advancedSMR]}));
 		r.push(`While ${he} was in the slave pens, ${he} saw that slaves on the taller end of the height curve were immediately designated as menials and Fuckdolls.`);
 		if (slave.physicalAge < 16) {
 			r.push(`${He} is <span class="gold">terrified</span> that if ${he} goes through a growth spurt, ${he}'ll be reassigned on the spot without a second thought.`);
@@ -663,7 +663,7 @@ App.Desc.lawCompliance = function(slave) {
 
 	function intelligenceBasicSMR() {
 		if (slave.intelligence <= -15) {
-			slave.intelligence = Intelligence.jsRandom({limitIntelligence: [0, 40]});
+			slave.intelligence = Intelligence.random({limitIntelligence: [0, 40]});
 		}
 		slave.trust -= 5;
 		return `intelligence`;
@@ -671,7 +671,7 @@ App.Desc.lawCompliance = function(slave) {
 
 	function intelligenceQualitySMR() {
 		if (slave.intelligence <= 15) {
-			slave.intelligence = Intelligence.jsRandom({limitIntelligence: [16, 100]});
+			slave.intelligence = Intelligence.random({limitIntelligence: [16, 100]});
 		}
 		slave.trust -= 5;
 		return `intelligence`;
diff --git a/src/uncategorized/slaveMarkets.tw b/src/uncategorized/slaveMarkets.tw
index afa58266093..a3dd396b858 100644
--- a/src/uncategorized/slaveMarkets.tw
+++ b/src/uncategorized/slaveMarkets.tw
@@ -177,7 +177,7 @@ You visit the slave markets off the arcology plaza. It's always preferable to ex
 
 <br><br>
 
-<<set _slaveCost = slaveCost($activeSlave)>>
+<<set _slaveCost = slaveCost($activeSlave, false, !App.Data.misc.lawlessMarkets.includes($slaveMarket))>>
 <<if $slavesSeen > $slaveMarketLimit>><<set _slaveCost += _slaveCost*(($slavesSeen-$slaveMarketLimit)*0.1)>><</if>>
 
 <<set _slaveCost = 500*Math.trunc(_slaveCost/500)>>
-- 
GitLab