diff --git a/src/endWeek/saRelationships.js b/src/endWeek/saRelationships.js index 4f5b92ae7c5d273f2c5a67bc36d713eb5e35ede6..2fa47bd4136b865d927f72b97694b5c5429a68ae 100644 --- a/src/endWeek/saRelationships.js +++ b/src/endWeek/saRelationships.js @@ -1177,34 +1177,154 @@ App.SlaveAssignment.relationships = (function() { * */ function familyFeelings(slave) { + /** @param {Map<string, Array<App.Entity.SlaveState>>} map + * @param {App.Entity.SlaveState} relative */ + function addToRelativeMap(map, relative) { + const term = relativeTerm(slave, relative); + if (!map.has(term)) { + map.set(term, [relative]); + } else { + map.get(term).push(relative); + } + } + + /** @param {Map<string, Array<App.Entity.SlaveState>>} map + * @returns {Array<string>} */ + function relativeMapToGroupArray(map) { + let groups = []; + for (const [type, people] of map) { + if (people.length > 1) { + groups.push(`${his} ${type}s ${arrayToSentence(people.map(s => s.slaveName))}`); + } else { + groups.push(`${his} ${type} ${people[0].slaveName}`); + } + } + return groups; + } + + /** @param {Map<string, Array<App.Entity.SlaveState>>} map + * @returns {App.Entity.SlaveState} */ + function singleRelativeInMap(map) { + if (map.size !== 1) { + return null; + } + /** @type {App.Entity.SlaveState[]} */ + const slavesOfType = map.values().next().value; + if (slavesOfType.length !== 1) { + return null; + } + return slavesOfType[0]; + } + + /** @param {Map<string, Array<App.Entity.SlaveState>>} map + * @returns {number} */ + function relativeMapTotalSize(map) { + let size = 0; + for (const people of map.values()) { + size += people.length; + } + return size; + } + + const overwhelmed = 5; if (slave.trust <= 95) { - let relatives = V.slaves.filter((s) => areRelated(slave, s)); // Is it possible to move this into the loop? - for (const relative of relatives) { - const {he2, him2} = getPronouns(relative).appendSuffix("2"); - if (slave.trust < -20) { + let relatives = V.slaves.filter((s) => areRelated(slave, s)); + if (slave.trust < -20) { + /** @type {Array<App.Entity.SlaveState>} */ + const worriedAboutChildren = []; + /** @type {Map<string, Array<App.Entity.SlaveState>>} */ + const worriedAboutRelatives = new Map(); + for (const relative of relatives) { if (slave.rivalryTarget !== relative.ID) { if (isParentP(relative, slave)) { - r.push(`${slave.slaveName} is <span class="trust dec">agonizingly aware</span> that ${his} child ${relative.slaveName} is also your slave and might suffer if either of them angers you, and <span class="devotion inc">does ${his} best</span> to protect ${him2}.`); - slave.trust -= 2; - slave.devotion += 6; + worriedAboutChildren.push(relative); + if (worriedAboutChildren.length <= overwhelmed) { + slave.trust -= 2; + slave.devotion += 6; + } } else { - r.push(`${slave.slaveName} is <span class="trust dec">painfully conscious</span> that ${his} ${relativeTerm(slave, relative)} ${relative.slaveName} is also your slave and might suffer if either of them displeases you, and <span class="devotion inc">tries to obey</span> as best ${he} can.`); - slave.trust -= 1; - slave.devotion += 3; + addToRelativeMap(worriedAboutRelatives, relative); + if (relativeMapTotalSize(worriedAboutRelatives) <= overwhelmed) { + slave.trust -= 1; + slave.devotion += 3; + } } } - } else { - r.push(`${slave.slaveName} knows that ${his} ${relativeTerm(slave, relative)} ${relative.slaveName}`); + } + if (worriedAboutChildren.length > 1) { + r.push(`${slave.slaveName} is <span class="trust dec">agonizingly aware</span> that ${his} children ${arrayToSentence(worriedAboutChildren.map(s => s.slaveName))} are also your slaves and might suffer if any of them angers you, and <span class="devotion inc">does ${his} best</span> to protect them.`); + } else if (worriedAboutChildren.length > 0) { + const {him2} = getPronouns(worriedAboutChildren[0]).appendSuffix("2"); + r.push(`${slave.slaveName} is <span class="trust dec">agonizingly aware</span> that ${his} child ${worriedAboutChildren[0].slaveName} is also your slave and might suffer if either of them angers you, and <span class="devotion inc">does ${his} best</span> to protect ${him2}.`); + } + if (worriedAboutChildren.length > overwhelmed) { + r.push(`${He} has so many children to worry about that ${he} is overwhelmed with fear and <span class="trust inc">forced to trust you.</span>`); + } + let singleRelative = singleRelativeInMap(worriedAboutRelatives); + if (singleRelative) { + r.push(`${slave.slaveName} is <span class="trust dec">painfully conscious</span> that ${his} ${relativeTerm(slave, singleRelative)} ${singleRelative.slaveName} is also your slave and might suffer if either of them displeases you, and <span class="devotion inc">tries to obey</span> as best ${he} can.`); + } else if (worriedAboutRelatives.size > 0) { + const groups = relativeMapToGroupArray(worriedAboutRelatives); + r.push(`${slave.slaveName} is <span class="trust dec">painfully conscious</span> that ${arrayToSentence(groups)} are also your slaves and might suffer if any of them displeases you, and <span class="devotion inc">tries to obey</span> as best ${he} can.`); + } + if (relativeMapTotalSize(worriedAboutRelatives) > overwhelmed) { + r.push(`${He} has so many relatives to worry about that ${he} is overwhelmed with fear and <span class="trust inc">forced to trust you.</span>`); + } + } else { + /** @type {Map<string, Array<App.Entity.SlaveState>>} */ + const devotedRelatives = new Map(); + /** @type {Map<string, Array<App.Entity.SlaveState>>} */ + const obedientRelatives = new Map(); + /** @type {Map<string, Array<App.Entity.SlaveState>>} */ + const hatefulRelatives = new Map(); + for (const relative of relatives) { if (relative.devotion > 50) { - r.push(`loves being your sex slave, and is <span class="devotion inc">happy</span> for ${him2}.`); - slave.devotion += 4; + addToRelativeMap(devotedRelatives, relative); + if (relativeMapTotalSize(devotedRelatives) <= overwhelmed) { + slave.devotion += 4; + } } else if (relative.devotion > 20 || relative.trust < -20) { - r.push(`is an obedient sex slave, and hopes ${he2}'ll avoid punishment.`); + addToRelativeMap(obedientRelatives, relative); } else { - r.push(`hates being a sex slave, and is <span class="trust dec">afraid</span> for ${him2}.`); - slave.trust -= 1; + addToRelativeMap(hatefulRelatives, relative); + if (relativeMapTotalSize(hatefulRelatives) <= overwhelmed) { + slave.trust -= 1; + } } } + let singleRelative = singleRelativeInMap(devotedRelatives); + if (singleRelative) { + const {him2} = getPronouns(singleRelative).appendSuffix('2'); + r.push(`${slave.slaveName} knows that ${his} ${relativeTerm(slave, singleRelative)} ${singleRelative.slaveName} loves being your sex slave, and is <span class="devotion inc">happy</span> for ${him2}.`); + } else if (devotedRelatives.size > 0) { + const groups = relativeMapToGroupArray(devotedRelatives); + r.push(`${slave.slaveName} knows that ${arrayToSentence(groups)} all love being your sex slaves, and is <span class="devotion inc">happy</span> for them.`); + } + if (relativeMapTotalSize(devotedRelatives) > overwhelmed) { + r.push(`${He} has so many relatives that love being your slaves that ${he} is sometimes overwhelmed with joy and <span class="devotion dec">neglects ${his} duties.</span>`); + } + singleRelative = singleRelativeInMap(obedientRelatives); + if (singleRelative) { + const {he2} = getPronouns(singleRelative).appendSuffix('2'); + r.push(`${slave.slaveName} knows that ${his} ${relativeTerm(slave, singleRelative)} ${singleRelative.slaveName} is an obedient sex slave, and hopes ${he2}'ll avoid punishment.`); + } else if (obedientRelatives.size > 0) { + const groups = relativeMapToGroupArray(obedientRelatives); + r.push(`${slave.slaveName} knows that ${arrayToSentence(groups)} are obedient sex slaves, and hopes they'll avoid punishment.`); + } + if (relativeMapTotalSize(obedientRelatives) > overwhelmed) { + r.push(`${He} has so many obedient relatives that ${he} sometimes forgets about some of them.`); + } + singleRelative = singleRelativeInMap(hatefulRelatives); + if (singleRelative) { + const {him2} = getPronouns(singleRelative).appendSuffix('2'); + r.push(`${slave.slaveName} knows that ${his} ${relativeTerm(slave, singleRelative)} ${singleRelative.slaveName} hates being a sex slave, and is <span class="trust dec">afraid</span> for ${him2}.`); + } else if (hatefulRelatives.size > 0) { + const groups = relativeMapToGroupArray(hatefulRelatives); + r.push(`${slave.slaveName} knows that ${arrayToSentence(groups)} all hate being sex slaves, and is <span class="trust dec">afraid</span> for them.`); + } + if (relativeMapTotalSize(hatefulRelatives) > overwhelmed) { + r.push(`${He} has so many relatives that hate being your sex slaves that ${he} is overwhelmed with fear and <span class="trust inc">just has to trust you to take care of them.</span>`); + } } } }