From f73644b18fc3a6f1927aa56051e1ef23c2b05af9 Mon Sep 17 00:00:00 2001
From: Svornost <11434-svornost@users.noreply.gitgud.io>
Date: Thu, 30 Dec 2021 18:24:24 -0500
Subject: [PATCH 1/4] Add a juvenile detention facility to the prison circuit,
 when appropriate for the game settings.

---
 devTools/types/FC/misc.d.ts                   |   4 +-
 js/003-data/gameVariableData.js               |   2 +-
 js/003-data/miscData.js                       |   3 +
 .../backwardsCompatibility.js                 |   3 +
 src/endWeek/nextWeek/nextWeek.js              |   3 +
 src/init/storyInit.js                         |   3 +
 src/markets/gingering.js                      |   2 +-
 src/markets/marketUI.js                       |   1 +
 .../specificMarkets/criminalMarkets.js        |  24 +++
 src/markets/theMarket/marketData.js           |  13 +-
 src/npc/generate/generateMarketSlave.js       | 156 +++++++++++++++++-
 11 files changed, 205 insertions(+), 9 deletions(-)

diff --git a/devTools/types/FC/misc.d.ts b/devTools/types/FC/misc.d.ts
index 5756b821a71..1fc19d9677d 100644
--- a/devTools/types/FC/misc.d.ts
+++ b/devTools/types/FC/misc.d.ts
@@ -1,7 +1,7 @@
 declare namespace FC {
 	type SlaveSchoolName = "GRI" | "HA" | "NUL" | "SCP" | "TCR" | "TFS" | "TGA" | "TSS" | "LDE" | "TUO";
-	type LawlessMarkets = "generic" | "gangs and smugglers" | "heap" | "indentures" | "low tier criminals" | "military prison" | "neighbor" |
-		"wetware" | "white collar" | SlaveSchoolName;
+	type LawlessMarkets = "generic" | "gangs and smugglers" | "heap" | "indentures" | "low tier criminals" | "military prison" | "juvenile detention" |
+		"neighbor" | "wetware" | "white collar" | SlaveSchoolName;
 	type OrdinaryMarkets = "kidnappers" | "trainers" | "hunters" | "raiders" | "underage raiders" | "corporate";
 	type SlaveMarketName = LawlessMarkets | OrdinaryMarkets;
 	type Gingering = Zeroable<"antidepressant" | "depressant" | "stimulant" | "vasoconstrictor" | "vasodilator" | "aphrodisiac" | "ginger">;
diff --git a/js/003-data/gameVariableData.js b/js/003-data/gameVariableData.js
index 186a86f319b..1e4f364e773 100644
--- a/js/003-data/gameVariableData.js
+++ b/js/003-data/gameVariableData.js
@@ -952,7 +952,7 @@ App.Data.resetOnNGPlus = {
 
 	justiceEvents: ["slave deal", "slave training", "majority deal", "indenture deal", "virginity deal", "breeding deal"], /* not in setupVars because we remove events from this array as they occur */
 	/** @type {Array<FC.SlaveMarketName>} */
-	prisonCircuit: ["low tier criminals", "gangs and smugglers", "white collar", "military prison"],
+	prisonCircuit: ["low tier criminals", "gangs and smugglers", "white collar", "military prison", "juvenile detention"],
 	prisonCircuitIndex: 0,
 
 	ui: "start",
diff --git a/js/003-data/miscData.js b/js/003-data/miscData.js
index d07b7b4df15..0702bdab943 100644
--- a/js/003-data/miscData.js
+++ b/js/003-data/miscData.js
@@ -1461,6 +1461,8 @@ App.Data.misc = {
 
 	militaryCriminalPool: ["deserter", "gunner", "officer", "private", "sniper", "soldier", "specOps", "spy", "terrorist", "war criminal"],
 
+	juvenileCriminalPool: ["theft", "robbery", "pickpocketing", "assault", "manslaughter", "smuggling", "mule", "prostitution", "truancy", "curfew"],
+
 	fakeBellies: ["a huge empathy belly", "a large empathy belly", "a medium empathy belly", "a small empathy belly"],
 	/* lets fake bellies be separated from other .bellyAccessory */
 
@@ -1870,6 +1872,7 @@ App.Data.misc.lawlessMarkets = [
 	"indentures",
 	"low tier criminals",
 	"military prison",
+	"juvenile detention",
 	"neighbor",
 	"wetware",
 	"white collar",
diff --git a/src/data/backwardsCompatibility/backwardsCompatibility.js b/src/data/backwardsCompatibility/backwardsCompatibility.js
index c5540e649d1..07a3ecdf088 100644
--- a/src/data/backwardsCompatibility/backwardsCompatibility.js
+++ b/src/data/backwardsCompatibility/backwardsCompatibility.js
@@ -329,6 +329,9 @@ App.Update.globalVariables = function(node) {
 		V.prisonCircuit = ["low tier criminals", "gangs and smugglers", "white collar", "military prison"];
 		V.prisonCircuitIndex = random(0, V.prisonCircuit.length - 1);
 	}
+	if (V.prisonCircuit.length === 4) {
+		V.prisonCircuit.push("juvenile detention");
+	}
 
 	App.Update.CustomSlaveOrder(V.huskSlave);
 	App.Update.CustomSlaveOrder(V.customSlave);
diff --git a/src/endWeek/nextWeek/nextWeek.js b/src/endWeek/nextWeek/nextWeek.js
index 9196b5ab14d..03ea46a5da8 100644
--- a/src/endWeek/nextWeek/nextWeek.js
+++ b/src/endWeek/nextWeek/nextWeek.js
@@ -323,6 +323,9 @@ App.EndWeek.nextWeek = function() {
 	V.thisWeeksFSWares = V.merchantFSWares.randomMany(2);
 	V.thisWeeksIllegalWares = V.merchantIllegalWares.randomMany(1);
 	V.prisonCircuitIndex++;
+	if (V.prisonCircuit[V.prisonCircuitIndex] === "juvenile detention" && (V.minimumSlaveAge > 16 || V.pedo_mode === 1)) {
+		V.prisonCircuitIndex++; // skip juvenile detention if juvenile slaves are not allowed, or we're in pedo mode (where all prisoners are juvenile)
+	}
 	if (V.prisonCircuitIndex >= V.prisonCircuit.length) {
 		V.prisonCircuitIndex = 0;
 	}
diff --git a/src/init/storyInit.js b/src/init/storyInit.js
index e1c188bb07f..2eafb65ba8a 100644
--- a/src/init/storyInit.js
+++ b/src/init/storyInit.js
@@ -54,6 +54,9 @@ App.Intro.init = function() {
 	V.weatherType = 1;
 	V.weatherRemaining = 6;
 	V.prisonCircuitIndex = random(0, V.prisonCircuit.length-1);
+	if (V.prisonCircuit[V.prisonCircuitIndex] === "juvenile detention" && (V.minimumSlaveAge > 16 || V.pedo_mode === 1)) {
+		V.prisonCircuitIndex = 0; // skip juvenile detention if juvenile slaves are not allowed, or we're in pedo mode (where all prisoners are juvenile)
+	}
 
 	/* I am not a slave object! Do not treat me like one! */
 	V.customSlave = new App.Entity.CustomSlaveOrder();
diff --git a/src/markets/gingering.js b/src/markets/gingering.js
index 11f90fbbf5a..cc25ffaed69 100644
--- a/src/markets/gingering.js
+++ b/src/markets/gingering.js
@@ -17,7 +17,7 @@ App.Entity.GingeringParameters = class {
 			/* SMR prohibits gingering and is enforced for this seller - do nothing */
 		} else if (App.Data.misc.schools.has(market)) {
 			/* slave schools have a reputation to maintain, and will never ginger their slaves */
-		} else if (["wetware", "heap", "gangs and smugglers", "low tier criminals", "military prison", "white collar", "corporate"].includes(market)) {
+		} else if (["wetware", "heap", "gangs and smugglers", "low tier criminals", "military prison", "juvenile detention", "white collar", "corporate"].includes(market)) {
 			/* these sellers see no reason to ginger their slaves */
 		} else if (market === "neighbor" && App.Neighbor.opinion(V.arcologies[0], V.arcologies[arcIndex]) >= 50) {
 			/* socially-aligned neighbors will not try to cheat you */
diff --git a/src/markets/marketUI.js b/src/markets/marketUI.js
index f368ab9951c..0b823840f1a 100644
--- a/src/markets/marketUI.js
+++ b/src/markets/marketUI.js
@@ -208,6 +208,7 @@ App.Markets.marketName = function(market, arcIndex = 1) {
 			case "gangs and smugglers":
 			case "white collar":
 			case "military prison":
+			case "juvenile detention":
 				return `the prisoner sale`;
 			default:
 				return `Someone messed up. ${market} is not known.`;
diff --git a/src/markets/specificMarkets/criminalMarkets.js b/src/markets/specificMarkets/criminalMarkets.js
index ce1ffb66681..7899a3b658c 100644
--- a/src/markets/specificMarkets/criminalMarkets.js
+++ b/src/markets/specificMarkets/criminalMarkets.js
@@ -71,3 +71,27 @@ App.Markets["military prison"] = function() {
 	el.append(App.Markets.purchaseFramework("military prison", {sTitleSingular: "prisoner", sTitlePlural: "prisoners"}));
 	return el;
 };
+
+App.Markets["juvenile detention"] = function() {
+	const r = new SpacedTextAccumulator();
+	// mixed prisoners
+	r.push(`You board the transport to a small brick-clad juvenile detention facility on the outskirts of the Free City. You might have confused the building for a high school, if not for the double fence topped with razor wire. Although the owners of this facility once viewed it as a rehabilitation center, a lack of funding and serious overcrowding have made them open to seeing slavery as a path to that goal.`);
+	if (V.PC.career === "hoodlum" || V.PC.career === "street urchin" || V.PC.career === "child prostitute") {
+		r.push(`You brace yourself inwardly; some of your friends from the streets ended up in places like this, and you easily could have too, if your fortunes hadn't turned.`);
+	}
+	r.toParagraph();
+	r.push(`You walk into the lobby of the facility and are greeted by a stern-looking heavyset woman in a warden's uniform. "Always happy to have you visit, `);
+	if (V.PC.title === 1) {
+		r.push(`Mister`);
+	} else {
+		r.push(`Miss`);
+	}
+	r.push(`${V.PC.slaveSurname}. Your patronage is appreciated. I've arranged for a few of our detainees that need some extra discipline to be present in the courtyard, right this way."`);
+	r.toParagraph();
+	r.push(`Entering the courtyard, you see lines painted on the asphalt for athletic activity, faded through time and wear. A pair of tired basketball hoops and patched soccer goals frame the scene, while a cluster of teens mills around in one corner. A short blast from a guard's whistle brings them to attention and the warden begins calling them forward, one at a time.`);
+	r.toParagraph();
+
+	const el = r.container();
+	el.append(App.Markets.purchaseFramework("juvenile detention", {sTitleSingular: "detainee", sTitlePlural: "detainees"}));
+	return el;
+};
diff --git a/src/markets/theMarket/marketData.js b/src/markets/theMarket/marketData.js
index fb53bf18d6d..72ee489efeb 100644
--- a/src/markets/theMarket/marketData.js
+++ b/src/markets/theMarket/marketData.js
@@ -114,20 +114,25 @@ App.Data.Markets = {
 						return `Slaves will tend to be medium to high quality with a variety of useful backgrounds.`;
 					case "military prison":
 						return `Slaves will tend to be high quality but defiant.`;
+					case "juvenile detention":
+						return `Slaves will tend to be young and healthy but defiant.`;
 					default:
 						return ``;
 				}
 			},
 			get sale() {
+				let tw = "This week ";
 				switch (V.prisonCircuit[V.prisonCircuitIndex]) {
 					case "low tier criminals":
-						return `a minor prison is selling inmates.`;
+						return tw + `a minor prison is selling inmates.`;
 					case "gangs and smugglers":
-						return `a major prison is selling hardened criminals.`;
+						return tw + `a major prison is selling hardened criminals.`;
 					case "white collar":
-						return `a white collar prison is selling inmates.`;
+						return tw + `a white collar prison is selling inmates.`;
 					case "military prison":
-						return `a military prison is selling inmates.`;
+						return tw + `a military prison is selling inmates.`;
+					case "juvenile detention":
+						return tw + `a juvenile detention facility is selling inmates.`;
 					default:
 						return ``;
 				}
diff --git a/src/npc/generate/generateMarketSlave.js b/src/npc/generate/generateMarketSlave.js
index 3e4c5790937..0307992e505 100644
--- a/src/npc/generate/generateMarketSlave.js
+++ b/src/npc/generate/generateMarketSlave.js
@@ -7,7 +7,7 @@
 globalThis.generateMarketSlave = function(market = "kidnappers", numArcology = 1) {
 	let r = ``;
 	let slave;
-	let SGProp = {};
+	let SGProp = new GenerateNewSlavePram();
 
 	switch (market) {
 		case "corporate": {
@@ -3176,6 +3176,160 @@ globalThis.generateMarketSlave = function(market = "kidnappers", numArcology = 1
 			}
 			break;
 		}
+		case "juvenile detention": {
+			// age of criminal responsibility/minimum age of incarceration is currently:
+			//  7-9 in most of the Middle East, India, Burma, Thailand, Indonesia, and Ethiopia
+			//  10 in most US states, Australia, New Zealand, Malaysia, the UK, Ireland, and Switzerland
+			//  11 in Japan, and for federal crimes in the US
+			//  12-14 in Canada, China, Saudi Arabia, Egypt, and most of Europe and Latin America
+			// that's the Old World, though; an argument could be made for just using minimum slave age here...
+			SGProp.minAge = Math.max(V.minimumSlaveAge, 10);
+			SGProp.maxAge = 17;
+			SGProp.disableDisability = 1;
+			if (random(0, 100) > 80 && (V.continent === "North America" || V.continent === "South America" || V.continent === "Australia")) {
+				// indigenous kids are substantially more likely to end up in juvenile detention
+				SGProp.race = V.continent === "Australia" ? "pacific islander" : "amerindian";
+			}
+			slave = GenerateNewSlave(null, SGProp);
+			// detained kids are fed and given medical attention by the facility
+			setHealth(slave, jsRandom(0, 60));
+			if (!slave.weight.isBetween(-60, 60)) {
+				slave.weight = jsRandom(-30, 15);
+			}
+
+			const criminal = App.Data.misc.juvenileCriminalPool.random();
+			switch (criminal) {
+				case "theft":
+					slave.origin = "You purchased $his life at a prison sale. $He was locked away for theft.";
+					r += "is detained for theft.";
+					slave.career = either("a street urchin", "an orphan", "a juvenile delinquent");
+					slave.devotion = jsRandom(-70, -20);
+					slave.trust = jsRandom(-100, -60);
+					slave.hStyle = "buzzcut";
+					slave.hLength = 0;
+					break;
+				case "robbery":
+					slave.origin = "You purchased $his life at a prison sale. $He was locked away for robbery.";
+					r += "is detained for robbery.";
+					slave.career = either("a street urchin", "a juvenile delinquent");
+					slave.devotion = jsRandom(-70, -20);
+					slave.trust = jsRandom(-100, -60);
+					slave.hStyle = "buzzcut";
+					slave.hLength = 0;
+					break;
+				case "pickpocketing":
+					slave.origin = "You purchased $his life at a prison sale. $He was locked away for repeat pick-pocketing.";
+					r += "is detained for pick-pocketing.";
+					slave.career = "a pick-pocket";
+					slave.devotion = jsRandom(-50, 0);
+					slave.trust = jsRandom(-100, -60);
+					slave.hStyle = "buzzcut";
+					slave.hLength = 0;
+					if (slave.weight > 10) {
+						slave.weight = jsRandom(-50, 0);
+					}
+					break;
+				case "assault":
+					slave.origin = "You purchased $his life at a prison sale. $He was locked away for assault.";
+					r += "is detained for assault.";
+					slave.career = either("a bully", "a bully hunter");
+					slave.devotion = jsRandom(-70, -20);
+					slave.trust = jsRandom(-100, -60);
+					slave.hStyle = "buzzcut";
+					slave.hLength = 0;
+					if (slave.muscles < 10) {
+						slave.muscles = jsRandom(10, 45);
+					}
+					slave.skill.combat = 1;
+					break;
+				case "manslaughter":
+					slave.origin = "You purchased $his life at a prison sale. $He was locked away for manslaughter.";
+					r += "is detained for manslaughter.";
+					slave.devotion = jsRandom(-70, -20);
+					slave.trust = jsRandom(-100, -60);
+					slave.hStyle = "buzzcut";
+					slave.hLength = 0;
+					break;
+				case "smuggling":
+					slave.origin = "You purchased $his life at a prison sale. $He was locked away for smuggling goods into the Free City.";
+					r += "is detained for smuggling goods.";
+					slave.career = "a sweatshop worker";
+					slave.devotion = jsRandom(-50, 0);
+					slave.trust = jsRandom(-50, 0);
+					slave.hStyle = "buzzcut";
+					slave.hLength = 0;
+					break;
+				case "mule":
+					slave.origin = "You purchased $his life at a prison sale. $He was locked away for smuggling illegal contraband inside $his body.";
+					r += "is detained for being a drug mule.";
+					slave.career = "a drug mule";
+					slave.devotion = jsRandom(-20, 20);
+					slave.trust = jsRandom(0, 20);
+					slave.hStyle = "buzzcut";
+					slave.hLength = 0;
+					slave.anus = 4;
+					slave.bellySag += 5;
+					slave.chem = 10 * jsRandom(1, 3);
+					slave.addict = 100;
+					break;
+				case "prostitution": // the gem of the bunch
+					slave.origin = "You purchased $his life at a prison sale. $He was locked away for child prostitution.";
+					r += "is detained for child prostitution, ironically.";
+					slave.career = "a child prostitute";
+					slave.devotion = jsRandom(0, 40); // likes the cut of your jib
+					slave.trust = jsRandom(0, 20);
+					slave.hStyle = "buzzcut";
+					slave.hLength = 0;
+					if (slave.anus === 0) {
+						slave.anus = jsRandom(2, 3);
+					}
+					if (slave.vagina === 0) {
+						slave.vagina = jsRandom(2, 3);
+					}
+					slave.skill.whoring = jsRandom(15, 30);
+					slave.skill.anal = jsRandom(15, 30);
+					slave.skill.oral = jsRandom(15, 30);
+					if (slave.vagina > 0) {
+						slave.skill.vaginal = jsRandom(15, 30);
+						if (slave.vaginaLube === 0) {
+							slave.vaginaLube = 1;
+						}
+					}
+					if (slave.energy < 20) {
+						slave.energy = jsRandom(40, 95);
+					}
+					break;
+				case "truancy":
+					slave.origin = "You purchased $his life at a prison sale. $He was locked away for repeated truancy.";
+					r += "is detained for repeated truancy.";
+					slave.career = either("a student from a public school", "a student from a private school");
+					slave.devotion = jsRandom(-70, -20);
+					slave.trust = jsRandom(-50, 0);
+					slave.hStyle = "buzzcut";
+					slave.hLength = 0;
+					if (slave.intelligenceImplant === 0) {
+						slave.intelligenceImplant = 15;
+					}
+					break;
+				case "curfew":
+					slave.origin = "You purchased $his life at a prison sale. $He was locked away for repeated curfew violations.";
+					r += "is detained for repeated curfew violations.";
+					slave.career = either("a party girl", "a juvenile delinquent");
+					slave.devotion = jsRandom(-70, -20);
+					slave.trust = jsRandom(-50, 0);
+					slave.hStyle = "buzzcut";
+					slave.hLength = 0;
+					if (slave.vagina === 0) {
+						slave.vagina = jsRandom(1, 3);
+						slave.skill.vaginal = jsRandom(5, 20);
+					}
+					if (slave.energy < 20) {
+						slave.energy = jsRandom(20, 80);
+					}
+					break;
+			}
+			break;
+		}
 		default: {
 			r += "Someone messed up. Market is not known.";
 			break;
-- 
GitLab


From f65270a4220574be4db06e0a8d23091cb26bd3b6 Mon Sep 17 00:00:00 2001
From: Svornost <11434-svornost@users.noreply.gitgud.io>
Date: Thu, 30 Dec 2021 18:32:05 -0500
Subject: [PATCH 2/4] strip them

---
 src/markets/specificMarkets/criminalMarkets.js | 2 +-
 1 file changed, 1 insertion(+), 1 deletion(-)

diff --git a/src/markets/specificMarkets/criminalMarkets.js b/src/markets/specificMarkets/criminalMarkets.js
index 7899a3b658c..37fd1acbabd 100644
--- a/src/markets/specificMarkets/criminalMarkets.js
+++ b/src/markets/specificMarkets/criminalMarkets.js
@@ -88,7 +88,7 @@ App.Markets["juvenile detention"] = function() {
 	}
 	r.push(`${V.PC.slaveSurname}. Your patronage is appreciated. I've arranged for a few of our detainees that need some extra discipline to be present in the courtyard, right this way."`);
 	r.toParagraph();
-	r.push(`Entering the courtyard, you see lines painted on the asphalt for athletic activity, faded through time and wear. A pair of tired basketball hoops and patched soccer goals frame the scene, while a cluster of teens mills around in one corner. A short blast from a guard's whistle brings them to attention and the warden begins calling them forward, one at a time.`);
+	r.push(`Entering the courtyard, you see lines painted on the asphalt for athletic activity, faded through time and wear. A pair of tired basketball hoops and patched soccer goals frame the scene, while a cluster of teens mills around in one corner. A short blast from a guard's whistle brings them to attention and the warden begins calling them forward, one at a time, and ordering them to strip for inspection.`);
 	r.toParagraph();
 
 	const el = r.container();
-- 
GitLab


From 3134d7572fab28ea81458907f4dc1d7602a3ecac Mon Sep 17 00:00:00 2001
From: Svornost <11434-svornost@users.noreply.gitgud.io>
Date: Thu, 30 Dec 2021 18:33:52 -0500
Subject: [PATCH 3/4] reduce overlap with existing prisons

---
 src/endWeek/nextWeek/nextWeek.js | 2 +-
 src/init/storyInit.js            | 2 +-
 2 files changed, 2 insertions(+), 2 deletions(-)

diff --git a/src/endWeek/nextWeek/nextWeek.js b/src/endWeek/nextWeek/nextWeek.js
index 03ea46a5da8..c22693fb2bf 100644
--- a/src/endWeek/nextWeek/nextWeek.js
+++ b/src/endWeek/nextWeek/nextWeek.js
@@ -323,7 +323,7 @@ App.EndWeek.nextWeek = function() {
 	V.thisWeeksFSWares = V.merchantFSWares.randomMany(2);
 	V.thisWeeksIllegalWares = V.merchantIllegalWares.randomMany(1);
 	V.prisonCircuitIndex++;
-	if (V.prisonCircuit[V.prisonCircuitIndex] === "juvenile detention" && (V.minimumSlaveAge > 16 || V.pedo_mode === 1)) {
+	if (V.prisonCircuit[V.prisonCircuitIndex] === "juvenile detention" && (V.minimumSlaveAge >= 16 || V.pedo_mode === 1)) {
 		V.prisonCircuitIndex++; // skip juvenile detention if juvenile slaves are not allowed, or we're in pedo mode (where all prisoners are juvenile)
 	}
 	if (V.prisonCircuitIndex >= V.prisonCircuit.length) {
diff --git a/src/init/storyInit.js b/src/init/storyInit.js
index 2eafb65ba8a..1245717fa59 100644
--- a/src/init/storyInit.js
+++ b/src/init/storyInit.js
@@ -54,7 +54,7 @@ App.Intro.init = function() {
 	V.weatherType = 1;
 	V.weatherRemaining = 6;
 	V.prisonCircuitIndex = random(0, V.prisonCircuit.length-1);
-	if (V.prisonCircuit[V.prisonCircuitIndex] === "juvenile detention" && (V.minimumSlaveAge > 16 || V.pedo_mode === 1)) {
+	if (V.prisonCircuit[V.prisonCircuitIndex] === "juvenile detention" && (V.minimumSlaveAge >= 16 || V.pedo_mode === 1)) {
 		V.prisonCircuitIndex = 0; // skip juvenile detention if juvenile slaves are not allowed, or we're in pedo mode (where all prisoners are juvenile)
 	}
 
-- 
GitLab


From 326e904024b77d462276ddf0739ca4da399f930b Mon Sep 17 00:00:00 2001
From: Svornost <11434-svornost@users.noreply.gitgud.io>
Date: Thu, 30 Dec 2021 18:34:20 -0500
Subject: [PATCH 4/4] reduce overlap with existing prisons

---
 src/npc/generate/generateMarketSlave.js | 2 +-
 1 file changed, 1 insertion(+), 1 deletion(-)

diff --git a/src/npc/generate/generateMarketSlave.js b/src/npc/generate/generateMarketSlave.js
index 0307992e505..2505d59dd5c 100644
--- a/src/npc/generate/generateMarketSlave.js
+++ b/src/npc/generate/generateMarketSlave.js
@@ -3184,7 +3184,7 @@ globalThis.generateMarketSlave = function(market = "kidnappers", numArcology = 1
 			//  12-14 in Canada, China, Saudi Arabia, Egypt, and most of Europe and Latin America
 			// that's the Old World, though; an argument could be made for just using minimum slave age here...
 			SGProp.minAge = Math.max(V.minimumSlaveAge, 10);
-			SGProp.maxAge = 17;
+			SGProp.maxAge = 16;
 			SGProp.disableDisability = 1;
 			if (random(0, 100) > 80 && (V.continent === "North America" || V.continent === "South America" || V.continent === "Australia")) {
 				// indigenous kids are substantially more likely to end up in juvenile detention
-- 
GitLab