diff --git a/js/003-data/gameVariableData.js b/js/003-data/gameVariableData.js
index 8522712cc491de56f8f840314549f545b9329bba..1382eb00f66d173abd84817eb7e91f54ab64edfb 100644
--- a/js/003-data/gameVariableData.js
+++ b/js/003-data/gameVariableData.js
@@ -671,8 +671,8 @@ App.Data.resetOnNGPlus = {
 	upgradeMultiplierMedicine: 0,
 	upgradeMultiplierTrade: 0,
 	nationalities: {},
-	/** @type {Object.<string, number[]>} */
-	JobIDArray: {},
+	/** @type {Object.<string, Set<number>>} */
+	JobIDMap: {},
 	averageTrust: 0,
 	averageDevotion: 0,
 	enduringTrust: 0,
@@ -1101,6 +1101,7 @@ App.Data.resetOnNGPlus = {
 	week: 1,
 
 	weddingPlanned: 0,
+	/** @type {string|Array<{ID:number, trainingRegimen:string}>} */
 	personalAttention: "sex",
 	/** @type {FC.SlaveStateOrZero}  */
 	HeadGirl: 0,
diff --git a/src/004-base/facility.js b/src/004-base/facility.js
index d782fed825463467e877224ea7d8eedbbea62ab2..1ca29008502fd1c447d80f93ba746d23374859cf 100644
--- a/src/004-base/facility.js
+++ b/src/004-base/facility.js
@@ -64,13 +64,22 @@ App.Entity.Facilities.Job = class {
 		return this.checkRequirements(slave);
 	}
 
+	/**
+	 * Is slave with the given ID already assigned to this job
+	 * @param {number} id
+	 * @returns {boolean}
+	 */
+	hasEmployeeWithId(id) {
+		return this.employeesIDs().has(id);
+	}
+
 	/**
 	 * Is slave already assigned to this job
 	 * @param {App.Entity.SlaveState} slave
 	 * @returns {boolean}
 	 */
 	isEmployed(slave) {
-		return slave.assignment === this.desc.assignment;
+		return this.hasEmployeeWithId(slave.ID);
 	}
 
 	/**
@@ -118,26 +127,15 @@ App.Entity.Facilities.Job = class {
 	 * @returns {App.Entity.SlaveState[]}
 	 */
 	employees() {
-		const slaves = V.slaves;
-		const slaveIndices = V.slaveIndices;
-		return this.employeesIds().map(id => slaves[slaveIndices[id]]);
-	}
-
-	/**
-	 * Indices in the slaves array for all slaves that are employed at this job
-	 * @returns {number[]}
-	 */
-	employeesIndices() {
-		const slaveIndices = V.slaveIndices;
-		return this.employeesIds().map(id => slaveIndices[id]);
+		return [...this.employeesIDs()].map(id => slaveStateById(id));
 	}
 
 	/**
 	 * IDs for all slaves that are employed at this job
-	 * @returns {number[]}
+	 * @returns {Set<number>}
 	 */
-	employeesIds() {
-		return V.JobIDArray[this.desc.assignment];
+	employeesIDs() {
+		return V.JobIDMap[this.desc.assignment];
 	}
 
 	/**
@@ -319,7 +317,7 @@ App.Entity.Facilities.Facility = class {
 	/** Number of already hosted slaves
 	 * @returns {number} */
 	get hostedSlaves() {
-		return this.jobs.reduce((acc, job) => { return acc + job.employeesIds().length; }, 0);
+		return this.jobs.reduce((acc, job) => { return acc + job.employeesIDs().size; }, 0);
 	}
 
 	get hasFreeSpace() {
@@ -460,30 +458,23 @@ App.Entity.Facilities.Facility = class {
 		return V.slaves.filter(s => jobArray.some(j => j.isEmployed(s)));
 	}
 
-	/**
-	 * Indices in the slaves array for all slaves that are employed at this facility (excluding the manager)
-	 * @returns {number[]}
-	 */
-	employeesIndices() {
-		const jobArray = Object.values(this._jobs);
-		if (jobArray.length === 1) {
-			return this.job().employeesIndices();
-		}
-		return jobArray.reduce(
-			(acc, cur, idx) => { acc = acc.concat(cur.employeesIndices()); return acc; }, []);
-	}
-
 	/**
 	 * IDs for all slaves that are employed at this facility (excluding the manager)
-	 * @returns {number[]}
+	 * @returns {Set<number>}
 	 */
-	employeesIds() {
+	employeesIDs() {
 		const jobArray = Object.values(this._jobs);
 		if (jobArray.length === 1) {
-			return this.job().employeesIds();
+			return this.job().employeesIDs();
+		}
+		const res = new Set();
+		for (const j of jobArray) {
+			const ids = j.employeesIDs();
+			for (const id of ids) {
+				res.add(id);
+			}
 		}
-		return jobArray.reduce(
-			(acc, cur, idx) => { acc = acc.concat(cur.employeesIds()); return acc; }, []);
+		return res;
 	}
 
 	/**
diff --git a/src/data/backwardsCompatibility/backwardsCompatibility.js b/src/data/backwardsCompatibility/backwardsCompatibility.js
index d3e7d3c15ff8618ab22f9cbdfaaf6a1ea854a2c5..e0cc74cc4b22c4f932cd36df641f1cfcf0ad14de 100644
--- a/src/data/backwardsCompatibility/backwardsCompatibility.js
+++ b/src/data/backwardsCompatibility/backwardsCompatibility.js
@@ -166,7 +166,7 @@ App.Update.globalVariables = function(node) {
 
 	// Jobs
 	{
-		V.JobIDArray = resetJobIDArray();
+		V.JobIDMap = makeJobIdMap();
 	}
 	// Reminders
 	{
diff --git a/src/facilities/nursery/nurseryWidgets.js b/src/facilities/nursery/nurseryWidgets.js
index 9bfe61dfa6451f26c87ee401a8ca2af44c2df14d..d33e5cbd3a39c8112fa0e4005f0b0e0b87093369 100644
--- a/src/facilities/nursery/nurseryWidgets.js
+++ b/src/facilities/nursery/nurseryWidgets.js
@@ -18247,7 +18247,7 @@ App.Facilities.Nursery.nurseryReport = function nurseryReport() {
 		const
 			slave = getSlave(V.NurseryiIDs[dI]);
 
-		V.i = App.Utils.slaveIndexForId(slave.ID);
+		V.i = V.slaveIndices[slave.ID];
 
 		slave.devotion += devBonus, slave.trust += trustBonus;
 		improveCondition(slave, healthBonus);
diff --git a/src/facilities/pit/pitFramework.js b/src/facilities/pit/pitFramework.js
index 82c6db8a3830880f7248966963da3c4190c517fc..f0d6be5a636bb9ebc5f4b572381eb5c6609ae12a 100644
--- a/src/facilities/pit/pitFramework.js
+++ b/src/facilities/pit/pitFramework.js
@@ -47,7 +47,7 @@ App.Entity.Facilities.Pit = class extends App.Entity.Facilities.SingleJobFacilit
 	}
 
 	get capacity() {
-		return this.established ? Number.MAX_VALUE : 0;
+		return super.capacity > 0 ? Number.MAX_VALUE : 0;
 	}
 };
 
diff --git a/src/init/storyInit.tw b/src/init/storyInit.tw
index 79c2ea431c584ac573db829803d9e8d4ca92dd0e..ec134ed408094c618cd53e4dc0f92c2049bc3e43 100644
--- a/src/init/storyInit.tw
+++ b/src/init/storyInit.tw
@@ -45,7 +45,7 @@ You should have received a copy of the GNU General Public License along with thi
 <<run setup.prostheticIDs.forEach(function(id) {
 	$prosthetics[id] = {amount: 0, research: 0};
 })>>
-<<set $JobIDArray = resetJobIDArray()>>
+<<set $JobIDMap = makeJobIdMap()>>
 
 /*SFVAR*/ <<set $SF = Object.assign({}, $SF, {Toggle:0, Active: -1}), $SF.Facility = Object.assign({}, $SF.Facility, {Toggle:0, Active:0})>>
 
diff --git a/src/js/assignJS.js b/src/js/assignJS.js
index 8f988a64aabbbfc528fb71c96f26872e05deaafc..4a6da40cbfc55890ba8c2db785077418d7475bd9 100644
--- a/src/js/assignJS.js
+++ b/src/js/assignJS.js
@@ -428,7 +428,7 @@ globalThis.assignJob = function(slave, job) {
 			}
 		}
 	}
-	V.JobIDArray = resetJobIDArray();
+	V.JobIDArray = makeJobIdMap();
 	if (idx >= 0) { V.slaves[idx] = slave; }
 
 	return r;
@@ -666,7 +666,7 @@ globalThis.removeJob = function(slave, assignment, saveRecord = false) {
 		slave.sentence = 0;
 		slave.subTarget = 0;
 	}
-	V.JobIDArray = resetJobIDArray();
+	V.JobIDArray = makeJobIdMap();
 	if (idx >= 0) {
 		V.slaves[idx] = slave;
 	}
@@ -727,24 +727,24 @@ globalThis.assignmentVisible = function(slave) {
 };
 
 /**
- * @returns {Object.<string, number[]>} dictionary assignment -> slave IDs
+ * @returns {Object.<string, Set<number>>} dictionary assignment -> slave IDs
  */
-globalThis.resetJobIDArray = function() {
-	/** @type {Object.<string, number[]>} */
-	const JobIDArray = {};
+globalThis.makeJobIdMap = function() {
+	/** @type {Object.<string, Set<number>>} */
+	const res = {};
 	for (const jn of Object.values(Job)) {
-		JobIDArray[jn] = [];
+		res[jn] = new Set();
 	}
 
 	for (const slave of V.slaves) {
-		JobIDArray[slave.assignment].push(slave.ID);
+		res[slave.assignment].add(slave.ID);
 	}
 
 	// special cases
-	JobIDArray[Job.PIT] = V.fighterIDs;
-	JobIDArray[Job.LURCHER].push(V.LurcherID);
+	res[Job.PIT] = new Set(V.fighterIDs);
+	res[Job.LURCHER].add(V.LurcherID);
 
-	return JobIDArray;
+	return res;
 };
 
 /**
diff --git a/src/js/economyJS.js b/src/js/economyJS.js
index 957cd720551e5c37afc041b2abc6d91b7477519f..42395682832263d843fd9c660fae760103903ee9 100644
--- a/src/js/economyJS.js
+++ b/src/js/economyJS.js
@@ -289,7 +289,7 @@ globalThis.calculateCosts = (function() {
 		V.ServQiIDs.forEach(ID => {
 			number += getSlaveMinorCosts(V.slaves[V.slaveIndices[ID]]);
 		});
-		V.JobIDArray[Job.HOUSE].forEach(ID => {
+		V.JobIDMap[Job.HOUSE].forEach(ID => {
 			number += getSlaveMinorCosts(V.slaves[V.slaveIndices[ID]]);
 		});
 		if (V.slaves.length > number) {
@@ -310,7 +310,7 @@ globalThis.calculateCosts = (function() {
 		V.ServQiIDs.forEach(ID => {
 			numberServed += getSlaveMinorCosts(V.slaves[V.slaveIndices[ID]]);
 		});
-		V.JobIDArray[Job.HOUSE].forEach(ID => {
+		V.JobIDMap[Job.HOUSE].forEach(ID => {
 			numberServed += getSlaveMinorCosts(V.slaves[V.slaveIndices[ID]]);
 		});
 
@@ -471,7 +471,7 @@ globalThis.calculateCosts = (function() {
 				cashX(Math.abs(slaveCostMinor), "slaveAssignmentQuarter", V.slaves[V.slaveIndices[ID]]);
 			}
 		});
-		V.JobIDArray[Job.HOUSE].forEach(ID => {
+		V.JobIDMap[Job.HOUSE].forEach(ID => {
 			if (V.slaves.length > numberServed) {
 				slaveCostMinor = Math.trunc(reducibleUpkeep / V.slaves.length * getSlaveMinorCosts(V.slaves[V.slaveIndices[ID]]));
 				cashX(Math.abs(slaveCostMinor), "slaveAssignmentHouse", V.slaves[V.slaveIndices[ID]]);
@@ -1613,7 +1613,7 @@ globalThis.slaveJobValues = function(lowerClassSexDemandRef, middleClassSexDeman
 	}
 
 	// Glory hole slaves adding to 'arcade'
-	V.JobIDArray[Job.GLORYHOLE].forEach(ID => {
+	V.JobIDMap[Job.GLORYHOLE].forEach(ID => {
 		const s = V.slaves[V.slaveIndices[ID]];
 		s.sexAmount = Math.trunc(restEffects(s, 20) * ((normalRandInt(600, 20) + (4 - s.anus) * 10 + (4 - s.vagina) * 10 + Math.trunc(s.health.condition / 2)) * 0.75));
 		tiredFucks(s);
@@ -1628,7 +1628,7 @@ globalThis.slaveJobValues = function(lowerClassSexDemandRef, middleClassSexDeman
 	});
 
 	// Public sluts adding to 'club'
-	V.JobIDArray[Job.PUBLIC].forEach(ID => {
+	V.JobIDMap[Job.PUBLIC].forEach(ID => {
 		SJVClub(V.slaves[V.slaveIndices[ID]]);
 	});
 
@@ -1643,7 +1643,7 @@ globalThis.slaveJobValues = function(lowerClassSexDemandRef, middleClassSexDeman
 	}
 
 	// Street whores adding to 'brothel'
-	V.JobIDArray[Job.WHORE].forEach(ID => {
+	V.JobIDMap[Job.WHORE].forEach(ID => {
 		SJVBrothel(V.slaves[V.slaveIndices[ID]]);
 	});
 
diff --git a/src/js/removeActiveSlave.js b/src/js/removeActiveSlave.js
index 0f70407f7fd204f1b1827a2d81d098d1ead11d6e..6cecd81599ac51d47aca9c44f156914f2c609500 100644
--- a/src/js/removeActiveSlave.js
+++ b/src/js/removeActiveSlave.js
@@ -235,7 +235,7 @@ globalThis.removeActiveSlave = function() {
 		removeSlave(INDEX);
 		LENGTH--;
 		V.activeSlave = 0;
-		V.JobIDArray = resetJobIDArray(); /* need to call this once more to update count of resting slaves*/
+		V.JobIDMap = makeJobIdMap(); /* need to call this once more to update count of resting slaves*/
 	}
 };
 /**
diff --git a/src/js/slaveListing.js b/src/js/slaveListing.js
index b81ac228afc990217712bb50c2b1a83c3662898a..dfa08d04690c2f9ecbe2d39dccbfd2bae515bf11 100644
--- a/src/js/slaveListing.js
+++ b/src/js/slaveListing.js
@@ -10,19 +10,18 @@ App.UI.SlaveList = {};
 /**
  * @callback slaveTextGenerator
  * @param {App.Entity.SlaveState} slave
- * @param {number} index
  * @returns {string}
  */
 
 /**
  * @callback slaveToElement
  * @param {App.Entity.SlaveState} slave
- * @param {number} index
  * @returns {HTMLElement|DocumentFragment}
  */
 
 App.UI.SlaveList.render = function() {
-	'use strict';
+	const facilityPassages = new Set(
+		["Main", "Head Girl Suite", "Spa", "Brothel", "Club", "Arcade", "Clinic", "Schoolroom", "Dairy", "Farmyard", "Servants' Quarters" , "Master Suite", "Cellblock"]);
 
 	/** @type {string} */
 	let passageName;
@@ -43,39 +42,46 @@ App.UI.SlaveList.render = function() {
 	};
 
 	/**
-	 * @param {number[]} indices
-	 * @param {Array.<{index: number, rejects: string[]}>} rejectedSlaves
+	 * @param {number[]} IDs
+	 * @param {Array.<{id: number, rejects: string[]}>} rejectedSlaves
 	 * @param {slaveToElement} interactionLink
 	 * @param {slaveToElement} [postNote]
 	 * @returns {DocumentFragment}
 	 */
-	function listDOM(indices, rejectedSlaves, interactionLink, postNote) {
+	function listDOM(IDs, rejectedSlaves, interactionLink, postNote) {
 		passageName = passage();
 		slaves = V.slaves;
 
 		let res = document.createDocumentFragment();
 
 		if (V.useSlaveListInPageJSNavigation === 1) {
-			res.appendChild(createQuickList(indices));
+			res.appendChild(createQuickList(IDs));
 		}
 
 		const fcs = App.Entity.facilities;
+		const penthouse = fcs.penthouse;
 
-		// can't simply loop over fcs attributes, as there is the penthouse among them, which always exists
-		const anyFacilityExists = fcs.brothel.established || fcs.club.established || fcs.dairy.established || fcs.farmyard.established || fcs.servantsQuarters.established || fcs.masterSuite.established || fcs.spa.established || fcs.clinic + fcs.schoolroom.established || fcs.cellblock.established || fcs.arcade.established || fcs.headGirlSuite.established;
+		let anyFacilityExists = false;
+
+		for (const f of Object.values(fcs)) {
+			if (f !== penthouse && f.established) {
+				anyFacilityExists = true;
+				break;
+			}
+		}
 
 		let showTransfers = false;
 		if (anyFacilityExists) {
-			if (passageName === "Main" || passageName === "Head Girl Suite" || passageName === "Spa" || passageName === "Brothel" || passageName === "Club" || passageName === "Arcade" || passageName === "Clinic" || passageName === "Schoolroom" || passageName === "Dairy" || passageName === "Farmyard" || passageName === "Servants' Quarters" || passageName === "Master Suite" || passageName === "Cellblock") {
+			if (facilityPassages.has(passageName)) {
 				V.returnTo = passageName;
 				showTransfers = true;
 			}
 		}
 
-		for (const _si of indices) {
-			let ss = renderSlave(_si, interactionLink, showTransfers, postNote);
+		for (const _sid of IDs) {
+			let ss = renderSlave(_sid, interactionLink, showTransfers, postNote);
 			let slaveDiv = document.createElement("div");
-			slaveDiv.id = `slave-${slaves[_si].ID}`;
+			slaveDiv.id = `slave-${_sid}`;
 			slaveDiv.classList.add("slaveSummary");
 			if (V.slavePanelStyle === 2) {
 				slaveDiv.classList.add("card");
@@ -85,7 +91,7 @@ App.UI.SlaveList.render = function() {
 		}
 
 		for (const rs of rejectedSlaves) {
-			const slave = slaves[rs.index];
+			const slave = slaveStateById(rs.id);
 			const rejects = rs.rejects;
 			const slaveName = SlaveFullName(slave);
 			let slaveDiv = document.createElement("div");
@@ -110,15 +116,15 @@ App.UI.SlaveList.render = function() {
 	}
 
 	/**
-	 * @param {number[]} indices
-	 * @param {Array.<{index: number, rejects: string[]}>} rejectedSlaves
+	 * @param {number[]} IDs
+	 * @param {Array.<{id: number, rejects: string[]}>} rejectedSlaves
 	 * @param {slaveToElement} interactionLink
 	 * @param {slaveToElement} [postNote]
 	 * @returns {string}
 	 */
-	function listMarkup(indices, rejectedSlaves, interactionLink, postNote) {
+	function listMarkup(IDs, rejectedSlaves, interactionLink, postNote) {
 		const listIDStr = `slave-list-${listID}`;
-		readyResults[listID] = listDOM(indices, rejectedSlaves, interactionLink, postNote);
+		readyResults[listID] = listDOM(IDs, rejectedSlaves, interactionLink, postNote);
 
 		$(document).one(':passagedisplay', function() {
 			for (const e of document.querySelectorAll('[id^=slave-list]')) {
@@ -141,13 +147,13 @@ App.UI.SlaveList.render = function() {
 
 
 	/**
-	 * @param {number} index
+	 * @param {number} id
 	 * @param {slaveToElement} interactionLink
 	 * @param {boolean} showTransfers
 	 * @param {slaveToElement} [postNote]
 	 * @returns {DocumentFragment}
 	 */
-	function renderSlave(index, interactionLink, showTransfers, postNote) {
+	function renderSlave(id, interactionLink, showTransfers, postNote) {
 		let res = document.createDocumentFragment();
 		if (V.slavePanelStyle === 0) {
 			res.appendChild(document.createElement("br"));
@@ -156,7 +162,7 @@ App.UI.SlaveList.render = function() {
 			hr.style.margin = "0";
 			res.appendChild(hr);
 		}
-		const slave = slaves[index];
+		const slave = slaveStateById(id);
 
 		if ((V.seeImages === 1) && (V.seeSummaryImages === 1)) {
 			let imgDiv = document.createElement("div");
@@ -166,7 +172,7 @@ App.UI.SlaveList.render = function() {
 			res.appendChild(imgDiv);
 		}
 		// res.push(dividerAndImage(slave));
-		res.appendChild(interactionLink(slave, index));
+		res.appendChild(interactionLink(slave));
 
 		if ((slave.choosesOwnClothes === 1) && (slave.clothes === "choosing her own clothes")) {
 			const _oldDevotion = slave.devotion;
@@ -329,8 +335,8 @@ App.UI.SlaveList.render = function() {
 
 		res.appendChild(App.UI.SlaveSummary.render(slave));
 
-		if (postNote !== undefined) {
-			const pn = postNote(slave, index);
+		if (postNote) {
+			const pn = postNote(slave);
 			if (pn) {
 				let r = document.createElement("p");
 				r.classList.add("si");
@@ -343,10 +349,10 @@ App.UI.SlaveList.render = function() {
 	}
 
 	/**
-	 * @param {number[]} indices
+	 * @param {number[]} IDs
 	 * @returns {DocumentFragment}
 	 */
-	function createQuickList(indices) {
+	function createQuickList(IDs) {
 		/**
 		 *
 		 * @param {Node} container
@@ -384,7 +390,7 @@ App.UI.SlaveList.render = function() {
 		*	<<print 'pass/count/indexed/flag::[' + passageName + '/' + _Count + '/' + _indexed + '/' + $SlaveSummaryFiler + ']'>>
 		*/
 
-		if (indices.length > 1 && passageName === "Main") {
+		if (IDs.length > 1 && passageName === "Main") {
 			const _buttons = [];
 			let _offset = -50;
 			if (/Select/i.test(passageName)) {
@@ -409,8 +415,8 @@ App.UI.SlaveList.render = function() {
 			const listIndex = makeElement(res, "div", undefined, "hidden");
 			listIndex.id = `list_index${listID}`;
 
-			for (const _ssii of indices) {
-				const _IndexSlave = slaves[_ssii];
+			for (const sID of IDs) {
+				const _IndexSlave = slaveStateById(sID);
 				const _indexSlaveName = SlaveFullName(_IndexSlave);
 				const _devotionClass = getSlaveDevotionClass(_IndexSlave);
 				const _trustClass = getSlaveTrustClass(_IndexSlave);
@@ -464,17 +470,18 @@ App.UI.SlaveList.Decoration = {};
  * @param {App.Entity.SlaveState} slave
  * @returns {HTMLElement}
  */
-App.UI.SlaveList.Decoration.penthousePositions = (slave) => {
-	if (App.Data.Facilities.headGirlSuite.manager.assignment === slave.assignment) {
+App.UI.SlaveList.Decoration.penthousePositions = function(slave) {
+	const fcs = App.Entity.facilities;
+	if (fcs.headGirlSuite.manager.isEmployed(slave)) {
 		return App.UI.DOM.makeElement("span", 'HG', ['lightcoral', 'strong']);
 	}
-	if (App.Data.Facilities.penthouse.manager.assignment === slave.assignment) {
+	if (fcs.penthouse.manager.isEmployed(slave)) {
 		return App.UI.DOM.makeElement("span", 'RC', ['lightcoral', 'strong']);
 	}
-	if (App.Data.Facilities.armory.manager.assignment === slave.assignment) {
+	if (fcs.armory.manager.isEmployed(slave)) {
 		return App.UI.DOM.makeElement("span", 'BG', ['lightcoral', 'strong']);
 	}
-	if (Array.isArray(V.personalAttention) && V.personalAttention.findIndex(s => s.ID === slave.ID) !== -1) {
+	if (Array.isArray(V.personalAttention) && V.personalAttention.some(s => s.ID === slave.ID)) {
 		return App.UI.DOM.makeElement("span", 'PA', ['lightcoral', 'strong']);
 	}
 	return null;
@@ -510,21 +517,23 @@ App.UI.SlaveList.SlaveInteract = {};
 
 /**
  * @param {App.Entity.SlaveState} slave
- * @param {number} index
  * @returns {HTMLElement}
  */
-App.UI.SlaveList.SlaveInteract.stdInteract = (slave, index) =>
-	App.UI.DOM.passageLink(SlaveFullName(slave), 'Slave Interact', () => { App.UI.SlaveList.ScrollPosition.record(); App.Utils.setActiveSlaveByIndex(index); });
+App.UI.SlaveList.SlaveInteract.stdInteract = function(slave) {
+	return App.UI.DOM.passageLink(SlaveFullName(slave), 'Slave Interact', () => {
+		App.UI.SlaveList.ScrollPosition.record();
+		V.activeSlave = slave;
+	});
+};
 
 
 /**
  * @param {App.Entity.SlaveState} slave
- * @param {number} index
  * @returns {DocumentFragment|HTMLElement}
  */
-App.UI.SlaveList.SlaveInteract.penthouseInteract = (slave, index) => {
+App.UI.SlaveList.SlaveInteract.penthouseInteract = function(slave) {
 	let decoration = App.UI.SlaveList.Decoration.penthousePositions(slave);
-	let stdLink = App.UI.SlaveList.SlaveInteract.stdInteract(slave, index);
+	let stdLink = App.UI.SlaveList.SlaveInteract.stdInteract(slave);
 	if (decoration) {
 		let fr = document.createDocumentFragment();
 		fr.appendChild(decoration);
@@ -647,8 +656,8 @@ App.UI.SlaveList.listSJFacilitySlaves = function(facility, facilityPassage, show
 		'</div>';
 
 	if (facility.hostedSlaves > 0) {
-		let facilitySlaves = job.employeesIndices();
-		SlaveSort.indices(facilitySlaves);
+		const facilitySlaves = [...job.employeesIDs()];
+		SlaveSort.IDs(facilitySlaves);
 		r += App.UI.tabbar.makeTab("remove", App.UI.SlaveList.render.listMarkup(facilitySlaves, [],
 			App.UI.SlaveList.SlaveInteract.stdInteract,
 			(slave) => App.UI.DOM.link(`Retrieve ${getPronouns(slave).object} from ${facility.name}`, () => removeJob(slave, job.desc.assignment), [], facilityPassage)
@@ -658,20 +667,19 @@ App.UI.SlaveList.listSJFacilitySlaves = function(facility, facilityPassage, show
 	}
 
 	/**
-	 * @param {number[]} slaveIdxs
+	 * @param {number[]} slaveIDs
 	 * @returns {string}
 	 */
-	function assignableTabContent(slaveIdxs) {
-		SlaveSort.indices(slaveIdxs);
-		const slaves = V.slaves;
+	function assignableTabContent(slaveIDs) {
+		SlaveSort.IDs(slaveIDs);
 		let rejectedSlaves = [];
 		let passedSlaves = [];
-		slaveIdxs.forEach((idx) => {
-			const rejects = facility.canHostSlave(slaves[idx]);
+		slaveIDs.forEach((id) => {
+			const rejects = facility.canHostSlave(slaveStateById(id));
 			if (rejects.length > 0) {
-				rejectedSlaves.push({index: idx, rejects: rejects});
+				rejectedSlaves.push({id: id, rejects: rejects});
 			} else {
-				passedSlaves.push(idx);
+				passedSlaves.push(id);
 			}
 		}, []);
 		return App.UI.SlaveList.render.listMarkup(passedSlaves, rejectedSlaves,
@@ -679,10 +687,10 @@ App.UI.SlaveList.listSJFacilitySlaves = function(facility, facilityPassage, show
 			(slave) => App.UI.DOM.link(`Send ${getPronouns(slave).object} to ${facility.name}`, () => { assignmentTransition(slave, job.desc.assignment, facilityPassage); }));
 	}
 	if (facility.hasFreeSpace) {
-		const assignableSlaveIdxs = job.desc.partTime ?
-			Array.apply(null, {length: V.slaves.length}).map(Number.call, Number) : // all slaves can work here
-			App.Entity.facilities.penthouse.employeesIndices(); // only slaves from the penthouse can be transferred here
-		r += App.UI.tabbar.makeTab("assign", assignableTabContent(assignableSlaveIdxs));
+		const assignableSlaveIDs = job.desc.partTime ?
+			V.slaves.map(slave => slave.ID) : // all slaves can work here
+			[...App.Entity.facilities.penthouse.employeesIDs()]; // only slaves from the penthouse can be transferred here
+		r += App.UI.tabbar.makeTab("assign", assignableTabContent(assignableSlaveIDs));
 	} else {
 		r += App.UI.tabbar.makeTab("assign", `<strong>${capFirstChar(facility.name)} is full and cannot hold any more slaves</strong>`);
 	}
@@ -690,13 +698,13 @@ App.UI.SlaveList.listSJFacilitySlaves = function(facility, facilityPassage, show
 	if (showTransfersTab) {
 		if (facility.hasFreeSpace) {
 			// slaves from other facilities can be transferred here
-			const transferableIndices = V.slaves.reduce((acc, slave, ind) => {
+			const transferableIDs = V.slaves.reduce((acc, slave) => {
 				if (!assignmentVisible(slave) && !facility.isHosted(slave)) {
-					acc.push(ind);
+					acc.push(slave.ID);
 				}
 				return acc;
 			}, []);
-			r += App.UI.tabbar.makeTab("transfer", assignableTabContent(transferableIndices));
+			r += App.UI.tabbar.makeTab("transfer", assignableTabContent(transferableIDs));
 		} else {
 			r += App.UI.tabbar.makeTab("transfer", `<strong>${capFirstChar(facility.name)} is full and cannot hold any more slaves</strong>`);
 		}
@@ -787,7 +795,7 @@ App.UI.SlaveList.displayManager = function(facility, selectionPassage) {
 	selectionPassage = selectionPassage || `${managerCapName} Select`;
 	const manager = facility.manager.currentEmployee;
 	if (manager) {
-		return this.render.listMarkup([App.Utils.slaveIndexForId(manager.ID)], [],
+		return this.render.listMarkup([manager.ID], [],
 			App.UI.SlaveList.SlaveInteract.stdInteract,
 			() => App.UI.DOM.passageLink(`Change or remove ${managerCapName}`, selectionPassage));
 	} else {
@@ -825,7 +833,7 @@ App.UI.SlaveList.penthousePage = function() {
 			const link = App.UI.DOM.makeElement("span", App.UI.DOM.passageLink("Manage Head Girl", "HG Select"), "major-link");
 			link.id = "manageHG";
 			slaveWrapper.append(link, " ", App.UI.DOM.makeElement("span", "[H]", "hotkey"));
-			slaveWrapper.append(App.UI.SlaveList.render.listDOM([App.Utils.slaveIndexForId(HG.ID)], [],
+			slaveWrapper.append(App.UI.SlaveList.render.listDOM([HG.ID], [],
 				App.UI.SlaveList.SlaveInteract.penthouseInteract));
 		} else {
 			if (V.slaves.length > 1) {
@@ -868,7 +876,7 @@ App.UI.SlaveList.penthousePage = function() {
 			const link = App.UI.DOM.makeElement("span", App.UI.DOM.passageLink("Manage Recruiter", "Recruiter Select"), "major-link");
 			link.id = "manageRecruiter";
 			slaveWrapper.append(link, " ", App.UI.DOM.makeElement("span", "[U]", "hotkey"));
-			slaveWrapper.append(App.UI.SlaveList.render.listDOM([App.Utils.slaveIndexForId(RC.ID)], [],
+			slaveWrapper.append(App.UI.SlaveList.render.listDOM([RC.ID], [],
 				App.UI.SlaveList.SlaveInteract.penthouseInteract));
 		} else {
 			slaveWrapper.append("You have ", App.UI.DOM.makeElement("span", "not", "warning"), " selected a Recruiter. ",
@@ -891,7 +899,7 @@ App.UI.SlaveList.penthousePage = function() {
 				const link = App.UI.DOM.makeElement("span", App.UI.DOM.passageLink("Manage Bodyguard", "BG Select"), "major-link");
 				link.id = "manageBG";
 				slaveWrapper.append(link, " ", App.UI.DOM.makeElement("span", "[B]", "hotkey"));
-				slaveWrapper.append(App.UI.SlaveList.render.listDOM([App.Utils.slaveIndexForId(BG.ID)], [],
+				slaveWrapper.append(App.UI.SlaveList.render.listDOM([BG.ID], [],
 					App.UI.SlaveList.SlaveInteract.penthouseInteract));
 				slaveWrapper.append(App.MainView.useGuard());
 			} else {
@@ -914,28 +922,16 @@ App.UI.SlaveList.penthousePage = function() {
 	 * @returns {{n: number, dom: DocumentFragment}}
 	 */
 	function _slavesForJob(job) {
-		const employeesIndices = job === 'all' ? ph.employeesIndices() : ph.job(job).employeesIndices();
-		if (employeesIndices.length === 0) {
+		const employeesIDs = job === 'all' ? [...ph.employeesIDs()] : [...ph.job(job).employeesIDs()];
+		if (employeesIDs.length === 0) {
 			return {n: 0, dom: document.createDocumentFragment()};
 		}
 
-		SlaveSort.indices(employeesIndices);
-
-		if (V.fucktoyInteractionsPosition === 1 && job === "fucktoy") {
-			const fragment = document.createDocumentFragment();
-			for (const i of employeesIndices) {
-				fragment.append(App.UI.SlaveList.render.listDOM([i], [], App.UI.SlaveList.SlaveInteract.penthouseInteract));
-				fragment.append(App.MainView.useFucktoy(V.slaves[i]));
-			}
-			return {
-				n: employeesIndices.length,
-				dom: fragment
-			};
-		}
-
+		SlaveSort.IDs(employeesIDs);
 		return {
-			n: employeesIndices.length,
-			dom: App.UI.SlaveList.render.listDOM(employeesIndices, [], App.UI.SlaveList.SlaveInteract.penthouseInteract)
+			n: employeesIDs.length,
+			dom: App.UI.SlaveList.render.listDOM(employeesIDs, [], App.UI.SlaveList.SlaveInteract.penthouseInteract,
+				V.fucktoyInteractionsPosition === 1 && job === "fucktoy" ? App.MainView.useFucktoy : null)
 		};
 	}
 
@@ -1011,10 +1007,10 @@ App.UI.SlaveList.penthousePage = function() {
 	}
 
 	function allTab() {
-		const penthouseSlavesIndices = ph.employeesIndices();
-		SlaveSort.indices(penthouseSlavesIndices);
-		return makeTabDesc('all', `All${V.useSlaveSummaryTabs > 0 ? ` (${penthouseSlavesIndices.length})` : ""}`,
-			App.UI.SlaveList.render.listDOM(penthouseSlavesIndices, [], App.UI.SlaveList.SlaveInteract.penthouseInteract));
+		const penthouseSlavesIDs = [...ph.employeesIDs()];
+		SlaveSort.IDs(penthouseSlavesIDs);
+		return makeTabDesc('all', `All${V.useSlaveSummaryTabs > 0 ? ` (${penthouseSlavesIDs.length})` : ""}`,
+			App.UI.SlaveList.render.listDOM(penthouseSlavesIDs, [], App.UI.SlaveList.SlaveInteract.penthouseInteract));
 	}
 
 	let fragment = document.createDocumentFragment();
@@ -1192,33 +1188,33 @@ App.UI.SlaveList.slaveSelectionList = function() {
 	 */
 	function _listSlaves(assignmentStr, options) {
 		const slaves = V.slaves;
-		let unfilteredIndices = [];
+		let unfilteredIDs = [];
 		switch (assignmentStr) {
 			case 'all':
-				unfilteredIndices = Array.from({length: slaves.length}, (v, i) => i);
+				unfilteredIDs = slaves.map(s => s.ID);
 				break;
 			case 'experienced':
-				unfilteredIndices = slaves.reduce((acc, s, idx) => {
+				unfilteredIDs = slaves.reduce((acc, s, idx) => {
 					if (options.expCheck(s)) {
-						acc.push(idx);
+						acc.push(s.ID);
 					}
 					return acc;
 				}, []);
 				break;
 			default:
-				unfilteredIndices = App.Entity.facilities[assignmentStr].employeesIndices();
+				unfilteredIDs = [...App.Entity.facilities[assignmentStr].employeesIDs()]; // set to array
 				break;
 		}
-		SlaveSort.indices(unfilteredIndices);
-		let passingIndices = [];
+		SlaveSort.IDs(unfilteredIDs);
+		let passingIDs = [];
 		let rejects = [];
 
-		unfilteredIndices.forEach(idx => {
-			const fr = options.filter(slaves[idx]);
+		unfilteredIDs.forEach(id => {
+			const fr = options.filter(slaveStateById(id));
 			if (fr === true || (Array.isArray(fr) && fr.length === 0)) {
-				passingIndices.push(idx);
+				passingIDs.push(id);
 			} else {
-				if (Array.isArray(fr)) { rejects.push({index: idx, rejects: fr}); }
+				if (Array.isArray(fr)) { rejects.push({id: id, rejects: fr}); }
 			}
 		});
 
@@ -1226,17 +1222,17 @@ App.UI.SlaveList.slaveSelectionList = function() {
 		// done this way to test for tests presence only once
 		const listPostNote = options.expCheck ?
 			(options.postNote ?
-				(s, i) => options.expCheck(s) ? App.UI.DOM.combineNodes(
+				s => options.expCheck(s) ? App.UI.DOM.combineNodes(
 					App.UI.DOM.makeElement("span", "Has applicable career experience.", "lime"),
 					document.createElement("br"),
-					options.postNote(s, i)
-				) : options.postNote(s, i) :
-				(s) => options.expCheck(s) ? App.UI.DOM.makeElement("span", "Has applicable career experience.", "lime") : null) :
+					options.postNote(s)
+				) : options.postNote(s) :
+				s => options.expCheck(s) ? App.UI.DOM.makeElement("span", "Has applicable career experience.", "lime") : null) :
 			options.postNote ?
-				(s, i) => options.postNote(s, i) :
+				s => options.postNote(s) :
 				() => null;
 
-		return App.UI.SlaveList.render.listDOM(passingIndices, rejects, options.interactionLink, listPostNote);
+		return App.UI.SlaveList.render.listDOM(passingIDs, rejects, options.interactionLink, listPostNote);
 	}
 }();
 
diff --git a/src/js/utilsFC.js b/src/js/utilsFC.js
index 1016f35b2e0c89bf561bacc6bd2f3648b519f60a..a3ba9217eb5b8197bc334e6876b69a9b0d26f935 100644
--- a/src/js/utilsFC.js
+++ b/src/js/utilsFC.js
@@ -2677,15 +2677,6 @@ App.Utils.setActiveSlaveByIndex = function(index) {
 	}
 };
 
-/**
- * Returns index in the slave array for the given ID
- * @param {number} id slave ID
- * @returns {number}
- */
-App.Utils.slaveIndexForId = function(id) {
-	return V.slaveIndices[id];
-};
-
 /**
  * Sets temporary variables named by the scheme, described below, to pronouns for the given slave
  * @param {App.Entity.SlaveState} slave
@@ -2836,8 +2827,8 @@ globalThis.getBestSlaves = function({part, count = 3, largest = true, filter = (
  * @param {{}} info see getBestSlaves()
  * @returns {number[]}
  */
-globalThis.getBestSlavesIndices = function(info) {
-	return getBestSlaves(info).map(slave => V.slaveIndices[slave.ID]);
+globalThis.getBestSlavesIDs = function(info) {
+	return getBestSlaves(info).map(slave => slave.ID);
 };
 
 /*
diff --git a/src/uncategorized/coursingAssociation.tw b/src/uncategorized/coursingAssociation.tw
index b6b48633449faa5acd9b38a9cd227c0acce0cf4d..a1d356c18ad9c96810ca230b75a0f323c046e479 100644
--- a/src/uncategorized/coursingAssociation.tw
+++ b/src/uncategorized/coursingAssociation.tw
@@ -16,7 +16,7 @@ The chasing slaves are known as lurchers, the term once used for the sighthounds
 
 <<if $LurcherID != 0>>
 	<br><br>''Fire your Lurcher:''
-	<<= App.UI.SlaveList.render.listMarkup([App.Utils.slaveIndexForId($LurcherID)], [],
+	<<= App.UI.SlaveList.render.listMarkup([$LurcherID], [],
 		(slave) => App.UI.DOM.passageLink(SlaveFullName(slave), 'Coursing Association', () => removeJob(slave, Job.LURCHER)))>>
 <</if>>
 
diff --git a/src/uncategorized/summaryOptions.tw b/src/uncategorized/summaryOptions.tw
index 4999d533ca7683a578afd6ba0dce66ce2b074a02..74411f44be29f280123bfec197c36ffec5970c28 100644
--- a/src/uncategorized/summaryOptions.tw
+++ b/src/uncategorized/summaryOptions.tw
@@ -35,7 +35,7 @@
 	.addValueList([["Ascending", "ascending"], ["Descending", "descending"]])>>
 
 	<<run _options.addOption("Slaves are sorted by", "sortSlavesBy")
-	.addValueList([["Devotion", "devotion"], ["Name", "name"], ["Date purchased", "seniority"], ["Age", "actualAge"], 
+	.addValueList([["Devotion", "devotion"], ["Name", "name"], ["Date purchased", "seniority"], ["Age", "actualAge"],
 	["How old they look", "visualAge"], ["Age of their body", "physicalAge"], ["Assignment", "assignment"], ["Weekly Income", "weeklyIncome"]])>>
 <</if>>
 
@@ -44,7 +44,7 @@
 <h2>Individual panels</h2>
 Sample summary:
 <<= App.UI.SlaveList.render.listMarkup(
-	[App.Utils.slaveIndexForId($activeSlave.ID)],
+	[$activeSlave.ID],
 	[],
 	App.UI.SlaveList.SlaveInteract.stdInteract
 )>>
diff --git a/src/uncategorized/underperformingSlaves.tw b/src/uncategorized/underperformingSlaves.tw
index ee7a8cf6587305d964cd62bab48a434dcfb57caa..0646e3bc07008725760592264fbd7c1b126d283d 100644
--- a/src/uncategorized/underperformingSlaves.tw
+++ b/src/uncategorized/underperformingSlaves.tw
@@ -30,7 +30,7 @@
 			Take the rough value of a slave and divide it by how much they made overall last week. This will tell you how many weeks it might take them to earn the same amount you'd get for selling them right now.
 		</div>
 		<<print App.UI.SlaveList.render.listMarkup(
-			getBestSlavesIndices(
+			getBestSlavesIDs(
 				{
 					part:(slave) => {
 						const ratio = slaveCost(slave) / (slave.lastWeeksCashIncome - getSlaveCost(slave));
@@ -59,7 +59,7 @@
 			This list looks for moochers by weighing their weekly income against the weekly cost of providing for them.
 		</div>
 		<<print App.UI.SlaveList.render.listMarkup(
-			getBestSlavesIndices(
+			getBestSlavesIDs(
 				{
 					part:(slave) => (slave.lastWeeksCashIncome - getSlaveCost(slave)),
 					largest: false,