diff --git a/src/data/backwardsCompatibility/backwardsCompatibility.js b/src/data/backwardsCompatibility/backwardsCompatibility.js
index ed44cd202d2b3a2958464e9a90de42a2329437a3..07ce59668170cc28bba63d831fd0205b8b05a2d1 100644
--- a/src/data/backwardsCompatibility/backwardsCompatibility.js
+++ b/src/data/backwardsCompatibility/backwardsCompatibility.js
@@ -1252,8 +1252,11 @@ App.Update.slaveRecords = function(node) {
 		nurseryDiv.append(`Checking and fixing records for nursery cribs... `);
 		V.cribs.forEach((child) => {
 			if (child.actualAge < 3) {
-				// infants are not slaves, they need their own update code (but there isn't any yet)
+				// infants are not slaves, they need their own update code (but there isn't much yet)
 				// note that some infants have been *converted into* corrupted slaves by bad old BCs...no attempt is made to fix them here
+				if (child.spermY === undefined) {
+					child.spermY = normalRandInt(50, 5);
+				}
 				App.Facilities.Nursery.InfantDatatypeCleanup(child);
 			} else {
 				App.Update.Slave(child);
@@ -2033,6 +2036,9 @@ App.Update.oldVersions = function(node) {
 			V.PC.faceShape = "normal";
 		}
 	}
+	if (typeof V.PC.spermY === "undefined") {
+		V.PC.spermY = 50; // exactly
+	}
 
 	if ((typeof V.familyTesting === "undefined") && V.releaseID < 1065) {
 		// possibly vanilla FC; compel V.familyTesting to 0 so that the family upgrade will run on slaves
diff --git a/src/data/backwardsCompatibility/updateSlaveObject.js b/src/data/backwardsCompatibility/updateSlaveObject.js
index 0c05bba36abed80bbc64e9e091907baa85b73fd8..0e63c24a3c0498114559e63f64870f2c5a23a9ba 100644
--- a/src/data/backwardsCompatibility/updateSlaveObject.js
+++ b/src/data/backwardsCompatibility/updateSlaveObject.js
@@ -1007,6 +1007,10 @@ App.Update.Slave = function(slave, genepool = false) {
 	delete slave.relationTarget;
 	delete slave.recruiter;
 
+	if (slave.spermY === undefined) {
+		slave.spermY = normalRandInt(50, 3); // narrower range to avoid surprises
+	}
+
 	if (slave.geneticQuirks.albinism === 2 && !slave.albinismOverride) {
 		induceAlbinism(slave, 2);
 	}
diff --git a/src/facilities/nursery/widgets/children/ChildState.js b/src/facilities/nursery/widgets/children/ChildState.js
index 8b787dd89806b31e7088844d26d8ec40704c51a5..8de31f2d3e8fb185dbe124bb6123328325e7dd3b 100644
--- a/src/facilities/nursery/widgets/children/ChildState.js
+++ b/src/facilities/nursery/widgets/children/ChildState.js
@@ -1568,6 +1568,8 @@ App.Facilities.Nursery.ChildState = class ChildState {
 			/** Slave can only ever birth girls */
 			girlsOnly: 0
 		};
+		/** chance of generating sperm with a Y chromosome (yields male baby). inherited by sons, with mutation */
+		this.spermY = 50;
 		/** Counts various acts slave participated in */
 		this.counter = new App.Entity.ChildActionsCountersState();
 		/** Values provided by players */
diff --git a/src/facilities/nursery/widgets/infants/InfantState.js b/src/facilities/nursery/widgets/infants/InfantState.js
index 87f0b6a7545f8a29c4dc1ad3ee40154e64d1dd5b..f50c3506b54d851f0bbd744d250c0b8ab9f8644b 100644
--- a/src/facilities/nursery/widgets/infants/InfantState.js
+++ b/src/facilities/nursery/widgets/infants/InfantState.js
@@ -183,6 +183,8 @@ App.Facilities.Nursery.InfantState = class InfantState {
 			/** child can only ever birth girls */
 			girlsOnly: 0
 		};
+		/** chance of generating sperm with a Y chromosome (yields male baby). inherited by sons, with mutation */
+		this.spermY = 50;
 		/** how many weeks until the child is ready for release */
 		this.growTime = 156;
 	}
diff --git a/src/gui/options/options.tw b/src/gui/options/options.tw
index 46bd823470bfb6f6f3a1375c1257db830ed263f3..8cd9ef8151ef0e2c32b9737cd1363cc392548620 100644
--- a/src/gui/options/options.tw
+++ b/src/gui/options/options.tw
@@ -302,8 +302,8 @@
 		.addValue("Enabled", 1).on().addValue("Disabled", 0).off()
 		.addComment("<<if $seeDicksAffectsPregnancy === 1>>Currently <<print $seeDicks>>% of children will be born male. <</if>>Will not affect existing pregnancies already in-game.")>>
 
-		<<if $seeDicksAffectsPregnancy > 0>>
-			<<run _options.addOption("XX slaves can have sons", "adamPrinciple")
+		<<if $seeDicksAffectsPregnancy === 0>>
+			<<run _options.addOption("XX slaves only father daughters", "adamPrinciple")
 			.addValue("Enabled", 1).on().addValue("Disabled", 0).off()
 			.addComment("Will not affect existing pregnancies already in-game.")>>
 		<</if>>
diff --git a/src/js/SlaveState.js b/src/js/SlaveState.js
index cd6e9f7e093f671f91531c3a615866e948593623..861d83d377ff43c9abf07ddc4d492a76b27fa10f 100644
--- a/src/js/SlaveState.js
+++ b/src/js/SlaveState.js
@@ -2124,6 +2124,8 @@ App.Entity.SlaveState = class SlaveState {
 			/** slave can only ever birth girls */
 			girlsOnly: 0
 		};
+		/** chance of generating sperm with a Y chromosome (yields male baby). inherited by sons, with mutation */
+		this.spermY = 50;
 		/** Counts various acts slave participated in */
 		this.counter = new App.Entity.SlaveActionsCountersState();
 		/** Values provided by players */
diff --git a/src/npc/descriptions/descriptionWidgets.js b/src/npc/descriptions/descriptionWidgets.js
index b9f5035a7c033ff5e749065d362e585912f14369..fb2d4a310b6ef56166ec7838e8ffa192a1b4f84b 100644
--- a/src/npc/descriptions/descriptionWidgets.js
+++ b/src/npc/descriptions/descriptionWidgets.js
@@ -1536,6 +1536,9 @@ App.Desc.geneticQuirkAssessment = function(slave) {
 		if (slave.geneticQuirks.mLoss === 1 && V.geneticMappingUpgrade >= 2) {
 			r.push(`${He} is a myotonic dystrophy carrier.`);
 		}
+		if (slave.genes === "XY" && !V.seeDicksAffectsPregnancy) {
+			r.push(`Analysis of ${his} sperm shows that ${he} has a ${slave.spermY}% chance of fathering a son.`);
+		}
 	}
 	return r.join(` `);
 };
diff --git a/src/npc/generate/generateGenetics.js b/src/npc/generate/generateGenetics.js
index ff7dd2751c6dafa8a83ef8b1e36b3b283e29cf02..250afa87426477062e046f46b602395e402c13e3 100644
--- a/src/npc/generate/generateGenetics.js
+++ b/src/npc/generate/generateGenetics.js
@@ -44,7 +44,8 @@ globalThis.generateGenetics = (function() {
 			clone: 0,
 			cloneID: 0,
 			geneticQuirks: {},
-			fetish: "none"
+			fetish: "none",
+			spermY: 50
 		};
 		if (actor1.ID > 0) {
 			mother = V.genePool.find(s => s.ID === actor1.ID);
@@ -114,10 +115,28 @@ globalThis.generateGenetics = (function() {
 		genes.sexualFlaw = setSexualFlaw(father, mother);
 		genes.behavioralFlaw = setBehavioralFlaw(father, mother);
 		genes.fetish = setFetish(father, mother);
+		genes.spermY = setSpermY(father, mother);
 
 		return genes;
 	}
 
+	// get spermY value of the parent that's donating the Y chromosome
+	function getSpermY(father, mother) {
+		let sourceSpermY = 50; // default if no inherited Y chromosome (should be impossible, but the Adam Principle is optional, so it can happen)
+		if (father !== 0 && father.genes === "XY") {
+			sourceSpermY = father.spermY;
+		} else if (mother.genes === "XY") {
+			sourceSpermY = father.spermY;
+		}
+		return sourceSpermY;
+	}
+
+	// generation chance of y-chormosome carrying sperm
+	function setSpermY(father, mother) {
+		// Y-linked trait, so figure out where the Y chromosome is coming from and start from there
+		return normalRandInt(getSpermY(father, mother), 5); // mutation
+	}
+
 	// gender
 	function setGender(father, mother) {
 		let gender;
@@ -128,17 +147,26 @@ globalThis.generateGenetics = (function() {
 		} else if (V.adamPrinciple === 1) {
 			if (father !== 0) {
 				if (father.genes === "XX" && mother.genes === "XX") {
-					gender = "XX";
+					gender = "XX"; // neither parent has a Y chromosome, it's definitely a girl
 				} else if (father.genes !== mother.genes) {
-					gender = jsEither(["XX", "XY"]);
+					gender = jsRandom(0, 99) < getSpermY(father, mother) ? "XY" : "XX"; // "normal" conception
 				} else {
-					gender = jsEither(["XX", "XY", "XY", "YY"]);
+					// both parents have a Y chromosome that they could donate; treat them as independent events
+					const motherY = jsRandom(0, 99) < mother.spermY;
+					const fatherY = jsRandom(0, 99) < father.spermY;
+					if (motherY && fatherY) {
+						gender = "YY"; // inviable, but retain for now
+					} else if (!motherY && !fatherY) {
+						gender = "XX"; // it's a girl!
+					} else {
+						gender = "XY"; // it's a boy!
+					}
 				}
 			} else {
-				gender = jsEither(["XX", "XY"]);
+				gender = jsRandom(0, 99) < getSpermY(father, mother) ? "XY" : "XX";
 			}
 		} else {
-			gender = jsEither(["XX", "XY"]);
+			gender = jsRandom(0, 99) < getSpermY(father, mother) ? "XY" : "XX";
 		}
 		return gender;
 	}
@@ -1156,6 +1184,7 @@ globalThis.generateChild = function (mother, ovum, incubator=false) {
 		child.origHColor = genes.hColor;
 		child.skin = getGeneticSkinColor(child);
 		child.hColor = getGeneticHairColor(child);
+		child.spermY = genes.spermY;
 		child.pubicHColor = child.hColor;
 		child.underArmHColor = child.hColor;
 		child.eyebrowHColor = child.hColor;
@@ -1209,6 +1238,7 @@ globalThis.generateChild = function (mother, ovum, incubator=false) {
 		child.origHColor = genes.hColor;
 		child.skin = getGeneticSkinColor(child);
 		child.hColor = getGeneticHairColor(child);
+		child.spermY = genes.spermY;
 		resetEyeColor(child, "both");
 		child.pubicHColor = child.hColor;
 		child.underArmHColor = child.hColor;
diff --git a/src/npc/generate/generateNewSlaveJS.js b/src/npc/generate/generateNewSlaveJS.js
index 61b02bfe1717a7cdc5dce32b3aee1588e7911d77..b3c83d8531c21bc43f4a868ef00f951db0d11dd4 100644
--- a/src/npc/generate/generateNewSlaveJS.js
+++ b/src/npc/generate/generateNewSlaveJS.js
@@ -103,6 +103,7 @@ globalThis.GenerateNewSlave = (function() {
 		slave.hColor = getGeneticHairColor(slave);
 		slave.skin = getGeneticSkinColor(slave);
 		resetEyeColor(slave, "both");
+		slave.spermY = normalRandInt(50, 5);
 	}
 
 	function GenerateXXSlave() {
diff --git a/src/player/js/PlayerState.js b/src/player/js/PlayerState.js
index 115a70c6f1b6ae32d518a055d72e76447d3dc0ec..4efbdaf320adf2e8d164496d3c6f4216be6eab5f 100644
--- a/src/player/js/PlayerState.js
+++ b/src/player/js/PlayerState.js
@@ -1691,6 +1691,8 @@ App.Entity.PlayerState = class PlayerState {
 			/** slave can only ever birth girls */
 			girlsOnly: 0
 		};
+		/** chance of generating sperm with a Y chromosome (yields male baby). inherited by sons, with mutation */
+		this.spermY = 50;
 		/** Counts various thing you have done in */
 		this.counter = new App.Entity.PlayerActionsCountersState();
 		/** Values provided by players */
diff --git a/src/pregmod/managePersonalAffairs.tw b/src/pregmod/managePersonalAffairs.tw
index f782157ba7d27aa190b06d30f117194d8f03e7ac..8a212bc09f387e17146aa93caeb98c42edb38c21 100644
--- a/src/pregmod/managePersonalAffairs.tw
+++ b/src/pregmod/managePersonalAffairs.tw
@@ -17,6 +17,15 @@
 	<div>
 		You pause for a moment from your busy day to day life to return to <<if $masterSuite != 0>>$masterSuiteName<<else>>your room<</if>> to consider some things about yourself.
 	</div>
+
+<<if $geneticMappingUpgrade >= 1>>
+	<div>
+		<<if $PC.genes === "XY" && $seeDicksAffectsPregnancy === 0>>
+			Analysis of your sperm shows that you have a <<= $PC.spermY>>% chance of fathering a son.
+		<</if>>
+	</div>
+<</if>>
+
 	<div>
 		You take yourself in a full length mirror. You are <<= addA($PC.race)>> <<if $PC.dick != 0 && $PC.vagina != -1>>futanari<<elseif $PC.dick != 0>>man<<else>>woman<</if>> with<<if $PC.markings == "freckles">> freckled<<elseif $PC.markings == "heavily freckled">> heavily freckled<</if>> <<print $PC.skin>> skin, $PC.hColor hair, <<print App.Desc.eyesColor($PC)>> and a perfect $PC.faceShape face.
 		<<if $PC.actualAge >= 65>>