code:
/**
 * @param {App.Entity.SlaveState} slave
 */
window.nationalityToRace = function nationalityToRace(slave) {
	slave.race = hashChoice(setup.raceSelector[slave.nationality] || setup.raceSelector[""]);
};

/**
 * @param {App.Entity.SlaveState} slave
 */
window.raceToNationality = function raceToNationality(slave) {
	/* consider this placeholder until raceNationalities gets fixed up */
	const V = State.variables;
	slave.nationality = hashChoice(V.nationalities);
	/* Maximum of 100 attempts */
	let i = 0;
	for (; setup.raceSelector[slave.nationality] && !(slave.race in setup.raceSelector[slave.nationality]) && i < 100; i++) {
		slave.nationality = hashChoice(V.nationalities);
	}
	/* No success after 100 attempts, so just randomize according to race */
	if (setup.raceSelector[slave.nationality] && !(slave.race in setup.raceSelector[slave.nationality]) && i === 100) {
		slave.nationality = hashChoice(setup[`${slave.race.toLowerCase().replace(/[ -]/g, "")}Nationalities`]);
	}
};

/**
 * @param {string | Object} nationality
 * @param {string | Object} race
 * @param {boolean} male
 * @param {undefined} [filter] Default: allow all
 * @returns {string}
 */
window.generateName = function generateName(nationality, race, male, filter = _.stubTrue) {
	const lookup = (male ? setup.malenamePoolSelector : setup.namePoolSelector);
	const result = jsEither(
		(lookup[`${nationality}.${race}`] || lookup[nationality] ||
			(male ? setup.whiteAmericanMaleNames : setup.whiteAmericanSlaveNames)).filter(filter));
	/* fallback for males without specific male name sets: return female name */
	if (male && !result) {
		return generateName(nationality, race, false);
	}
	return result;
};

/**
 * @param {string | number} nationality
 * @param {any} race
 * @param {any} male
 * @param {Function} [filter]  Default: allow all
 * @returns {string}
 */
window.generateSurname = function generateSurname(nationality, race, male, filter = _.stubTrue) {
	const result = jsEither(
		(setup.surnamePoolSelector[`${nationality}.${race}`] ||
			setup.surnamePoolSelector[nationality] ||
			setup.whiteAmericanSlaveSurnames).filter(filter));
	if (male) {
		/* see if we have male equivalent of that surname, and return that if so */
		const maleLookup = setup.maleSurnamePoolSelector[`${nationality}.${race}`] || setup.maleSurnamePoolSelector[nationality];
		if (maleLookup && maleLookup[result]) {
			return maleLookup[result];
		}
	}
	return result || 0;
};

/**
 * @param {string} name
 * @param {string | Object} nationality
 * @param {any} race
 * @returns {boolean}
 */
window.isMaleName = function isMaleName(name, nationality, race) {
	const names = setup.malenamePoolSelector[`${nationality}.${race}`] ||
		setup.malenamePoolSelector[nationality] ||
		setup.whiteAmericanMaleNames;
	return names && names.includes(name);
};

/**
 * @param {App.Entity.SlaveState} slave
 */
window.nationalityToName = function nationalityToName(slave) {
	const V = State.variables;
	const male = (slave.genes === "XY");

	slave.birthName = generateName(slave.nationality, slave.race, male);
	slave.birthSurname = generateSurname(slave.nationality, slave.race, male);
	if (male && isMaleName(slave.birthName, slave.nationality, slave.race) && !V.allowMaleSlaveNames) {
		slave.slaveName = generateName(slave.nationality, slave.race, false);
	} else {
		slave.slaveName = slave.birthName;
	}
	slave.slaveSurname = slave.birthSurname;
	if (V.useFSNames === 1) {
		if (V.arcologies[0].FSChattelReligionist > 20) {
			slave.slaveName = jsEither(setup.chattelReligionistSlaveNames);
			slave.slaveSurname = 0;
		} else if (V.arcologies[0].FSRomanRevivalist > 20) {
			slave.slaveName = jsEither(setup.romanSlaveNames);
			slave.slaveSurname = jsEither(setup.romanSlaveSurnames);
		} else if (V.arcologies[0].FSAztecRevivalist > 20) {
			slave.slaveName = jsEither(setup.aztecSlaveNames);
			slave.slaveSurname = 0;
		} else if (V.arcologies[0].FSEgyptianRevivalist > 20) {
			slave.slaveName = jsEither(setup.ancientEgyptianSlaveNames);
			slave.slaveSurname = 0;
		} else if (V.arcologies[0].FSEdoRevivalist > 20) {
			slave.slaveName = jsEither(setup.edoSlaveNames);
			slave.slaveSurname = jsEither(setup.edoSlaveSurnames);
		} else if (V.arcologies[0].FSDegradationist !== "unset") {
			DegradingName(slave);
		}
	}
};

/**
 * @param {App.Entity.SlaveState} slave
 */
window.nationalityToAccent = function nationalityToAccent(slave) {
	const V = State.variables;
	const naturalAccent = jsEither([0, 1, 1, 2, 2, 2, 3, 3, 3, 3]);

	switch (slave.nationality) {
		case "Afghan":
			if (V.language === "Pashto") {
				slave.accent = jsEither([0, 0, 0, 0, 0, 0, 1]);
			} else if (V.language === "Dari") {
				slave.accent = jsEither([0, 0, 0, 0, 0, 0, 1]);
			} else if (V.language === "Persian") {
				slave.accent = jsEither([0, 1, 1, 1, 1, 2]);
			} else {
				slave.accent = naturalAccent;
			}
			break;
		case "Albanian":
			slave.accent = naturalAccent;
			break;
		case "Algerian":
			slave.accent = (V.language === "Arabic") ? jsEither([0, 1, 1, 1, 1, 2]) : naturalAccent;
			break;
		case "American":
			if (V.language === "English") {
				slave.accent = jsEither([0, 0, 0, 0, 0, 0, 1]);
			} else if (V.language === "Spanish" && slave.race === "latina") {
				slave.accent = jsEither([0, 1, 2, 2, 2, 3, 3]);
			} else if (V.language === "Chinese" && slave.race === "asian") {
				slave.accent = jsEither([0, 1, 2, 2, 2, 3, 3]);
			} else if (V.language === "Arabic" && slave.race === "middle eastern") {
				slave.accent = jsEither([0, 1, 2, 2, 2, 3, 3]);
			} else {
				slave.accent = naturalAccent;
			}
			break;
		case "Andorran":
			slave.accent = (V.language === "Catalan") ? jsEither([0, 0, 0, 0, 0, 0, 1]) : naturalAccent;
			break;
		case "Angolan":
			slave.accent = (V.language === "Portuguese") ? jsEither([0, 1, 1, 1, 1, 2]) : naturalAccent;
			break;
		case "Antiguan":
			slave.accent = (V.language === "English") ? jsEither([0, 1, 1, 1, 1, 2]) : naturalAccent;
			break;
		case "Argentinian":
			slave.accent = (V.language === "Spanish") ? jsEither([0, 1, 1, 1, 1, 2]) : naturalAccent;
			break;
		case "Armenian":
			if (V.language === "Russian") {
				slave.accent = jsEither([0, 1, 2, 2, 2, 3, 3]);
			} else if (V.language === "English") {
				slave.accent = jsEither([0, 1, 2, 2, 2, 3, 3]);
			} else {
				slave.accent = naturalAccent;
			}
			break;
		case "Aruban":
			if (V.language === "Dutch") {
				slave.accent = jsEither([0, 1, 1, 1, 1, 2]);
			} else if (V.language === "English") {
				slave.accent = jsEither([0, 1, 2, 2, 2, 3, 3]);
			} else if (V.language === "Portuguese") {
				slave.accent = jsEither([0, 1, 2, 2, 2, 3, 3]);
			} else {
				slave.accent = naturalAccent;
			}
			break;
		case "Australian":
			slave.accent = (V.language === "English") ? jsEither([0, 1, 1, 1, 1, 2]) : naturalAccent;
			break;
		case "Austrian":
			if (V.language === "German") {
				slave.accent = jsEither([0, 1, 1, 1, 1, 2]);
			} else if (V.language === "Serbian") {
				slave.accent = jsEither([0, 1, 2, 2, 2, 3, 3]);
			} else if (V.language === "Slovene") {
				slave.accent = jsEither([0, 1, 2, 2, 2, 3, 3]);
			} else if (V.language === "Turkish" && slave.race === "indo-aryan") {
				slave.accent = jsEither([0, 1, 2, 2, 2, 3, 3]);
			} else {
				slave.accent = naturalAccent;
			}
			break;
		case "Azerbaijani":
			slave.accent = naturalAccent;
			break;
		case "Bahamian":
			slave.accent = (V.language === "English") ? jsEither([0, 1, 1, 1, 1, 2]) : naturalAccent;
			break;
		case "Bahraini":
			slave.accent = (V.language === "Arabic") ? jsEither([0, 1, 1, 1, 1, 2]) : naturalAccent;
			break;
		case "Bangladeshi":
			if (V.language === "Bengali") {
				slave.accent = jsEither([0, 0, 0, 0, 0, 0, 1]);
			} else if (V.language === "Hindi") {
				slave.accent = jsEither([0, 1, 2, 2, 2, 3, 3]);
			} else {
				slave.accent = naturalAccent;
			}
			break;
		case "Barbadian":
			slave.accent = (V.language === "English") ? jsEither([0, 1, 1, 1, 1, 2]) : naturalAccent;
			break;
		case "Belarusian":
			slave.accent = (V.language === "Russian") ? jsEither([0, 1, 1, 1, 1, 2]) : naturalAccent;
			break;
		case "Belgian":
			if (V.language === "Dutch") {
				slave.accent = jsEither([0, 1, 1, 1, 1, 2]);
			} else if (V.language === "French") {
				slave.accent = jsEither([0, 1, 1, 1, 1, 2]);
			} else if (V.language === "German") {
				slave.accent = jsEither([0, 1, 2, 2, 2, 3, 3]);
			} else {
				slave.accent = naturalAccent;
			}
			break;
		case "Belizean":
			slave.accent = (V.language === "English") ? jsEither([0, 1, 1, 1, 1, 2]) : naturalAccent;
			break;
		case "Beninese":
			slave.accent = (V.language === "French") ? jsEither([0, 1, 1, 1, 1, 2]) : naturalAccent;
			break;
		case "Bermudian":
			slave.accent = (V.language === "English") ? jsEither([0, 1, 1, 1, 1, 2]) : naturalAccent;
			break;
		case "Bhutanese":
			slave.accent = (V.language === "Dzongkha") ? jsEither([0, 0, 0, 0, 0, 0, 1]) : naturalAccent;
			break;
		case "Bissau-Guinean":
			slave.accent = (V.language === "Portuguese") ? jsEither([0, 1, 1, 1, 1, 2]) : naturalAccent;
			break;
		case "Bolivian":
			slave.accent = (V.language === "Spanish") ? jsEither([0, 1, 1, 1, 1, 2]) : naturalAccent;
			break;
		case "Bosnian":
			if (V.language === "Croatian") {
				slave.accent = jsEither([0, 1, 1, 1, 1, 2]);
			} else if (V.language === "Serbian") {
				slave.accent = jsEither([0, 1, 1, 1, 1, 2]);
			} else {
				slave.accent = naturalAccent;
			}
			break;
		case "Brazilian":
			if (V.language === "Portuguese") {
				slave.accent = jsEither([0, 1, 1, 1, 1, 2]);
			} else if (V.language === "Spanish") {
				slave.accent = jsEither([0, 1, 2, 2, 2, 3, 3]);
			} else {
				slave.accent = naturalAccent;
			}
			break;
		case "British":
			if (V.language === "English") {
				slave.accent = jsEither([0, 1, 1, 1, 1, 2]);
			} else if (V.language === "Hindi" && slave.race === "indo-aryan") {
				slave.accent = jsEither([0, 1, 2, 2, 2, 3, 3]);
			} else {
				slave.accent = naturalAccent;
			}
			break;
		case "Bruneian":
			if (V.language === "Malay") {
				slave.accent = jsEither([0, 1, 1, 1, 1, 2]);
			} else if (V.language === "English") {
				slave.accent = jsEither([0, 1, 2, 2, 2, 3, 3]);
			} else {
				slave.accent = naturalAccent;
			}
			break;
		case "Bulgarian":
			slave.accent = naturalAccent;
			break;
		case "Burkinabé":
			slave.accent = (V.language === "French") ? jsEither([0, 1, 1, 1, 1, 2]) : naturalAccent;
			break;
		case "Burmese":
			slave.accent = naturalAccent;
			break;
		case "Burundian":
			slave.accent = (V.language === "Kirundi") ? jsEither([0, 0, 0, 0, 0, 0, 1]) : naturalAccent;
			break;
		case "Cambodian":
			if (V.language === "Khmer") {
				slave.accent = jsEither([0, 0, 0, 0, 0, 0, 1]);
			} else if (V.language === "Cham") {
				slave.accent = jsEither([0, 1, 1, 1, 1, 2]);
			} else if (V.language === "French") {
				slave.accent = jsEither([0, 1, 2, 2, 2, 3, 3]);
			} else {
				slave.accent = naturalAccent;
			}
			break;
		case "Cameroonian":
			slave.accent = (V.language === "French") ? jsEither([0, 1, 1, 1, 1, 2]) : naturalAccent;
			break;
		case "Canadian":
			if (V.language === "English") {
				slave.accent = jsEither([0, 0, 0, 0, 0, 0, 1]);
			} else if (V.language === "French") {
				slave.accent = jsEither([0, 1, 1, 1, 1, 2]);
			} else {
				slave.accent = naturalAccent;
			}
			break;
		case "Cape Verdean":
			slave.accent = (V.language === "Portuguese") ? jsEither([0, 1, 1, 1, 1, 2]) : naturalAccent;
			break;
		case "Catalan":
			slave.accent = (V.language === "Spanish") ? jsEither([0, 0, 0, 0, 0, 0, 1]) : naturalAccent;
			break;
		case "Central African":
			slave.accent = (V.language === "French") ? jsEither([0, 1, 1, 1, 1, 2]) : naturalAccent;
			break;
		case "Chadian":
			slave.accent = (V.language === "Arabic") ? jsEither([0, 1, 1, 1, 1, 2]) : naturalAccent;
			break;
		case "Chilean":
			slave.accent = (V.language === "Spanish") ? jsEither([0, 1, 1, 1, 1, 2]) : naturalAccent;
			break;
		case "Chinese":
			if (V.language === "Tibetan") {
				slave.accent = jsEither([0, 1, 2, 2, 2, 3, 3]);
			} else if (V.language === "Korean") {
				slave.accent = jsEither([0, 1, 2, 2, 2, 3, 3]);
			} else if (V.language === "Kazakh") {
				slave.accent = jsEither([0, 1, 2, 2, 2, 3, 3]);
			} else {
				slave.accent = naturalAccent;
			}
			break;
		case "Colombian":
			slave.accent = (V.language === "Spanish") ? jsEither([0, 1, 1, 1, 1, 2]) : naturalAccent;
			break;
		case "Comorian":
			if (V.language === "Arabic") {
				slave.accent = jsEither([0, 1, 2, 2, 2, 3, 3]);
			} else if (V.language === "French") {
				slave.accent = jsEither([0, 1, 2, 2, 2, 3, 3]);
			} else {
				slave.accent = naturalAccent;
			}
			break;
		case "Congolese":
			if (V.language === "Lingala") {
				slave.accent = jsEither([0, 0, 0, 0, 0, 0, 1]);
			} else if (V.language === "Kikongo") {
				slave.accent = jsEither([0, 0, 0, 0, 0, 0, 1]);
			} else if (V.language === "French") {
				slave.accent = jsEither([0, 1, 1, 1, 1, 2]);
			} else {
				slave.accent = naturalAccent;
			}
			break;
		case "a Cook Islander":
			if (V.language === "Cook Islands Māori") {
				slave.accent = jsEither([0, 0, 0, 0, 0, 0, 1]);
			} else if (V.language === "English") {
				slave.accent = jsEither([0, 1, 1, 1, 1, 2]);
			} else {
				slave.accent = naturalAccent;
			}
			break;
		case "Costa Rican":
			slave.accent = (V.language === "Spanish") ? jsEither([0, 1, 1, 1, 1, 2]) : naturalAccent;
			break;
		case "Croatian":
			if (V.language === "Bosnian") {
				slave.accent = jsEither([0, 1, 1, 1, 1, 2]);
			} else if (V.language === "Serbian") {
				slave.accent = jsEither([0, 1, 1, 1, 1, 2]);
			} else {
				slave.accent = naturalAccent;
			}
			break;
		case "Cuban":
			slave.accent = (V.language === "Spanish") ? jsEither([0, 1, 1, 1, 1, 2]) : naturalAccent;
			break;
		case "Curaçaoan":
			if (V.language === "Dutch") {
				slave.accent = jsEither([0, 1, 1, 1, 2]);
			} else if (V.language === "English") {
				slave.accent = jsEither([0, 1, 2, 2, 2, 3, 3]);
			} else if (V.language === "Portuguese") {
				slave.accent = jsEither([0, 1, 2, 2, 2, 3, 3]);
			} else {
				slave.accent = naturalAccent;
			}
			break;
		case "Cypriot":
			if (V.language === "Greek") {
				slave.accent = jsEither([0, 1, 1, 1, 1, 2]);
			} else if (V.language === "Turkish") {
				slave.accent = jsEither([0, 1, 1, 1, 1, 2]);
			} else if (V.language === "English") {
				slave.accent = jsEither([0, 1, 2, 2, 2, 3, 3]);
			} else {
				slave.accent = naturalAccent;
			}
			break;
		case "Czech":
			if (V.language === "Slovak") {
				slave.accent = jsEither([0, 1, 1, 1, 1, 2]);
			} else if (V.language === "Vietnamese" && slave.race === "asian") {
				slave.accent = jsEither([0, 1, 2, 2, 2, 3, 3]);
			} else {
				slave.accent = naturalAccent;
			}
			break;
		case "Danish":
			slave.accent = naturalAccent;
			break;
		case "Djiboutian":
			slave.accent = (V.language === "French") ? jsEither([0, 1, 1, 1, 1, 2]) : naturalAccent;
			break;
		case "Dominican":
			slave.accent = (V.language === "Spanish") ? jsEither([0, 1, 1, 1, 1, 2]) : naturalAccent;
			break;
		case "Dominiquais":
			slave.accent = (V.language === "English") ? jsEither([0, 1, 1, 1, 1, 2]) : naturalAccent;
			break;
		case "Dutch":
			slave.accent = naturalAccent;
			break;
		case "East Timorese":
			if (V.language === "Tetum") {
				slave.accent = jsEither([0, 0, 0, 0, 0, 0, 1]);
			} else if (V.language === "Portuguese") {
				slave.accent = jsEither([0, 1, 1, 1, 1, 2]);
			} else if (V.language === "Malay") {
				slave.accent = jsEither([0, 1, 2, 2, 2, 3, 3]);
			} else {
				slave.accent = naturalAccent;
			}
			break;
		case "Ecuadorian":
			slave.accent = (V.language === "Spanish") ? jsEither([0, 1, 1, 1, 1, 2]) : naturalAccent;
			break;
		case "Egyptian":
			slave.accent = (V.language === "Arabic") ? jsEither([0, 1, 1, 1, 1, 2]) : naturalAccent;
			break;
		case "Emirati":
			slave.accent = (V.language === "Arabic") ? jsEither([0, 1, 1, 1, 1, 2]) : naturalAccent;
			break;
		case "Equatoguinean":
			slave.accent = (V.language === "Spanish") ? jsEither([0, 1, 1, 1, 1, 2]) : naturalAccent;
			break;
		case "Eritrean":
			if (V.language === "Tigrinya") {
				slave.accent = jsEither([0, 0, 0, 0, 0, 0, 1]);
			} else if (V.language === "Arabic") {
				slave.accent = jsEither([0, 1, 1, 1, 1, 2]);
			} else if (V.language === "English") {
				slave.accent = jsEither([0, 1, 2, 2, 2, 3, 3]);
			} else {
				slave.accent = naturalAccent;
			}
			break;
		case "Estonian":
			slave.accent = (V.language === "Russian") ? jsEither([0, 1, 2, 2, 2, 3, 3]) : naturalAccent;
			break;
		case "Ethiopian":
			if (V.language === "Amharic") {
				slave.accent = jsEither([0, 0, 0, 0, 0, 0, 1]);
			} else if (V.language === "Arabic") {
				slave.accent = jsEither([0, 1, 2, 2, 2, 3, 3]);
			} else if (V.language === "Tigrinya") {
				slave.accent = jsEither([0, 1, 2, 2, 2, 3, 3]);
			} else {
				slave.accent = naturalAccent;
			}
			break;
		case "Fijian":
			slave.accent = (V.language === "English") ? jsEither([0, 1, 1, 1, 1, 2]) : naturalAccent;
			break;
		case "Filipina":
			if (V.language === "Filipino") {
				slave.accent = jsEither([0, 0, 0, 0, 0, 0, 1]);
			} else if (V.language === "English") {
				slave.accent = jsEither([0, 1, 1, 1, 1, 2]);
			} else if (V.language === "Tagalog") {
				slave.accent = jsEither([0, 1, 1, 1, 1, 2]);
			} else if (V.language === "Arabic") {
				slave.accent = jsEither([0, 1, 2, 2, 2, 3, 3]);
			} else if (V.language === "Spanish") {
				slave.accent = jsEither([0, 1, 2, 2, 2, 3, 3]);
			} else {
				slave.accent = naturalAccent;
			}
			break;
		case "Finnish":
			slave.accent = (V.language === "Swedish") ? jsEither([0, 1, 1, 1, 1, 2]) : naturalAccent;
			break;
		case "French":
			if (V.language === "English") {
				slave.accent = jsEither([0, 1, 2, 2, 2, 3, 3]);
			} else if (V.language === "Spanish") {
				slave.accent = jsEither([0, 1, 2, 2, 2, 3, 3]);
			} else if (V.language === "German") {
				slave.accent = jsEither([0, 1, 2, 2, 2, 3, 3]);
			} else if (V.language === "Arabic" && slave.race === "middle eastern") {
				slave.accent = jsEither([0, 1, 2, 2, 2, 3, 3]);
			} else if (V.language === "Catalan") {
				slave.accent = jsEither([0, 1, 2, 2, 2, 3, 3]);
			} else {
				slave.accent = naturalAccent;
			}
			break;
		case "French Guianan":
			slave.accent = (V.language === "French") ? jsEither([0, 1, 1, 1, 1, 2]) : naturalAccent;
			break;
		case "French Polynesian":
			if (V.language === "Tahitian") {
				slave.accent = jsEither([0, 0, 0, 0, 0, 0, 1]);
			} else if (V.language === "French") {
				slave.accent = jsEither([0, 1, 1, 1, 1, 2]);
			} else if (V.language === "Chinese") {
				slave.accent = jsEither([0, 1, 2, 2, 2, 3, 3]);
			} else {
				slave.accent = naturalAccent;
			}
			break;
		case "Gabonese":
			slave.accent = (V.language === "French") ? jsEither([0, 1, 1, 1, 1, 2]) : naturalAccent;
			break;
		case "Gambian":
			slave.accent = (V.language === "English") ? jsEither([0, 1, 1, 1, 1, 2]) : naturalAccent;
			break;
		case "Georgian":
			slave.accent = (V.language === "Abkhaz") ? jsEither([0, 1, 1, 1, 1, 2]) : naturalAccent;
			break;
		case "German":
			if (V.language === "English") {
				slave.accent = jsEither([0, 1, 2, 2, 2, 3, 3]);
			} else if (V.language === "French") {
				slave.accent = jsEither([0, 1, 2, 2, 2, 3, 3]);
			} else if (V.language === "Turkish" && slave.race === "indo-aryan") {
				slave.accent = jsEither([0, 1, 2, 2, 2, 3, 3]);
			} else {
				slave.accent = naturalAccent;
			}
			break;
		case "Ghanan":
			if (V.language === "English") {
				slave.accent = jsEither([0, 1, 1, 1, 1, 2]);
			} else if (V.language === "Hausa") {
				slave.accent = jsEither([0, 1, 2, 2, 2, 3, 3]);
			} else if (V.language === "Arabic") {
				slave.accent = jsEither([0, 1, 2, 2, 2, 3, 3]);
			} else {
				slave.accent = naturalAccent;
			}
			break;
		case "Greek":
			slave.accent = naturalAccent;
			break;
		case "Greenlandic":
			slave.accent = (V.language === "Danish") ? jsEither([0, 1, 1, 1, 1, 2]) : naturalAccent;
			break;
		case "Grenadian":
			slave.accent = (V.language === "English") ? jsEither([0, 1, 1, 1, 1, 2]) : naturalAccent;
			break;
		case "Guamanian":
			slave.accent = (V.language === "English") ? jsEither([0, 1, 1, 1, 1, 2]) : naturalAccent;
			break;
		case "Guatemalan":
			slave.accent = (V.language === "Spanish") ? jsEither([0, 1, 1, 1, 1, 2]) : naturalAccent;
			break;
		case "Guinean":
			slave.accent = (V.language === "French") ? jsEither([0, 1, 1, 1, 1, 2]) : naturalAccent;
			break;
		case "Guyanese":
			slave.accent = (V.language === "English") ? jsEither([0, 1, 1, 1, 1, 2]) : naturalAccent;
			break;
		case "Haitian":
			slave.accent = (V.language === "French") ? jsEither([0, 1, 1, 1, 1, 2]) : naturalAccent;
			break;
		case "Honduran":
			slave.accent = (V.language === "Spanish") ? jsEither([0, 1, 1, 1, 1, 2]) : naturalAccent;
			break;
		case "Hungarian":
			if (V.language === "German") {
				slave.accent = jsEither([0, 1, 2, 2, 2, 3, 3]);
			} else if (V.language === "English") {
				slave.accent = jsEither([0, 1, 2, 2, 2, 3, 3]);
			} else {
				slave.accent = naturalAccent;
			}
			break;
		case "I-Kiribati":
			if (V.language === "Gilbertese") {
				slave.accent = jsEither([0, 0, 0, 0, 0, 0, 1]);
			} else if (V.language === "English") {
				slave.accent = jsEither([0, 1, 1, 1, 1, 2]);
			} else {
				slave.accent = naturalAccent;
			}
			break;
		case "Icelandic":
			if (V.language === "Danish") {
				slave.accent = jsEither([0, 1, 2, 2, 2, 3, 3]);
			} else if (V.language === "English") {
				slave.accent = jsEither([0, 1, 2, 2, 2, 3, 3]);
			} else {
				slave.accent = naturalAccent;
			}
			break;
		case "Indian":
			if (V.language === "Hindi") {
				slave.accent = jsEither([0, 0, 0, 0, 0, 0, 1]);
			} else if (V.language === "English") {
				slave.accent = jsEither([0, 1, 1, 1, 1, 2]);
			} else {
				slave.accent = naturalAccent;
			}
			break;
		case "Indonesian":
			if (V.language === "Javanese") {
				slave.accent = jsEither([0, 1, 1, 1, 1, 2]);
			} else if (V.language === "Malay") {
				slave.accent = jsEither([0, 1, 1, 1, 1, 2]);
			} else {
				slave.accent = naturalAccent;
			}
			break;
		case "Iranian":
			if (V.language === "Persian") {
				slave.accent = jsEither([0, 0, 0, 0, 0, 0, 1]);
			} else if (V.language === "Arabic") {
				slave.accent = jsEither([0, 1, 2, 2, 2, 3, 3]);
			} else {
				slave.accent = naturalAccent;
			}
			break;
		case "Iraqi":
			if (V.language === "Arabic") {
				slave.accent = jsEither([0, 1, 1, 1, 1, 2]);
			} else if (V.language === "Kurdish") {
				slave.accent = jsEither([0, 1, 2, 2, 2, 3, 3]);
			} else {
				slave.accent = naturalAccent;
			}
			break;
		case "Irish":
			slave.accent = (V.language === "English") ? jsEither([0, 1, 1, 1, 1, 2]) : naturalAccent;
			break;
		case "Israeli":
			if (V.language === "Hebrew") {
				slave.accent = jsEither([0, 0, 0, 0, 0, 0, 1]);
			} else if (V.language === "Arabic") {
				slave.accent = jsEither([0, 1, 1, 1, 1, 2]);
			} else if (V.language === "Yiddish") {
				slave.accent = jsEither([0, 1, 2, 2, 2, 3, 3]);
			} else {
				slave.accent = naturalAccent;
			}
			break;
		case "Italian":
			slave.accent = naturalAccent;
			break;
		case "Ivorian":
			slave.accent = (V.language === "French") ? jsEither([0, 1, 1, 1, 1, 2]) : naturalAccent;
			break;
		case "Jamaican":
			slave.accent = (V.language === "English") ? jsEither([0, 1, 1, 1, 1, 2]) : naturalAccent;
			break;
		case "Japanese":
			slave.accent = naturalAccent;
			break;
		case "Jordanian":
			slave.accent = (V.language === "Arabic") ? jsEither([0, 1, 1, 1, 1, 2]) : naturalAccent;
			break;
		case "Kazakh":
			slave.accent = (V.language === "Russian") ? jsEither([0, 1, 1, 1, 1, 2]) : naturalAccent;
			break;
		case "Kenyan":
			slave.accent = (V.language === "Arabic") ? jsEither([0, 1, 2, 2, 2, 3, 3]) : naturalAccent;
			break;
		case "Kittitian":
			slave.accent = (V.language === "English") ? jsEither([0, 1, 1, 1, 1, 2]) : naturalAccent;
			break;
		case "Korean":
			slave.accent = (V.language === "Chinese") ? jsEither([0, 1, 2, 2, 2, 3, 3]) : naturalAccent;
			break;
		case "Kosovan":
			if (V.language === "Albanian") {
				slave.accent = jsEither([0, 1, 1, 1, 1, 2]);
			} else if (V.language === "Serbian") {
				slave.accent = jsEither([0, 1, 1, 1, 1, 2]);
			} else {
				slave.accent = naturalAccent;
			}
			break;
		case "Kurdish":
			if (V.language === "Arabic") {
				slave.accent = jsEither([0, 1, 2, 2, 2, 3, 3]);
			} else if (V.language === "Turkish") {
				slave.accent = jsEither([0, 1, 2, 2, 2, 3, 3]);
			} else {
				slave.accent = naturalAccent;
			}
			break;
		case "Kuwaiti":
			slave.accent = (V.language === "Arabic") ? jsEither([0, 1, 1, 1, 1, 2]) : naturalAccent;
			break;
		case "Kyrgyz":
			slave.accent = (V.language === "Russian") ? jsEither([0, 1, 1, 1, 1, 2]) : naturalAccent;
			break;
		case "Laotian":
			if (V.language === "Lao") {
				slave.accent = jsEither([0, 0, 0, 0, 0, 0, 1]);
			} else if (V.language === "Khmu") {
				slave.accent = jsEither([0, 1, 1, 1, 1, 2]);
			} else if (V.language === "French") {
				slave.accent = jsEither([0, 1, 2, 2, 2, 3, 3]);
			} else {
				slave.accent = naturalAccent;
			}
			break;
		case "Latvian":
			slave.accent = naturalAccent;
			break;
		case "Lebanese":
			slave.accent = (V.language === "Arabic") ? jsEither([0, 1, 1, 1, 1, 2]) : naturalAccent;
			break;
		case "Liberian":
			slave.accent = (V.language === "English") ? jsEither([0, 1, 1, 1, 1, 2]) : naturalAccent;
			break;
		case "Libyan":
			slave.accent = (V.language === "Arabic") ? jsEither([0, 1, 1, 1, 1, 2]) : naturalAccent;
			break;
		case "a Liechtensteiner":
			slave.accent = (V.language === "German") ? jsEither([0, 1, 1, 1, 1, 2]) : naturalAccent;
			break;
		case "Lithuanian":
			slave.accent = naturalAccent;
			break;
		case "Luxembourgian":
			if (V.language === "Luxembourgish") {
				slave.accent = jsEither([0, 0, 0, 0, 0, 0, 1]);
			} else if (V.language === "German") {
				slave.accent = jsEither([0, 1, 1, 1, 1, 2]);
			} else if (V.language === "French") {
				slave.accent = jsEither([0, 1, 1, 1, 1, 2]);
			} else {
				slave.accent = naturalAccent;
			}
			break;
		case "Macedonian":
			slave.accent = naturalAccent;
			break;
		case "Malagasy":
			if (V.language === "French") {
				slave.accent = jsEither([0, 1, 1, 1, 1, 2]);
			} else if (V.language === "English") {
				slave.accent = jsEither([0, 1, 2, 2, 2, 3, 3]);
			} else {
				slave.accent = naturalAccent;
			}
			break;
		case "Malawian":
			if (V.language === "English") {
				slave.accent = jsEither([0, 1, 1, 1, 1, 2]);
			} else if (V.language === "Chichewa") {
				slave.accent = jsEither([0, 0, 0, 0, 0, 0, 1]);
			} else {
				slave.accent = naturalAccent;
			}
			break;
		case "Malaysian":
			slave.accent = (V.language === "Malay") ? jsEither([0, 0, 0, 0, 0, 0, 1]) : naturalAccent;
			break;
		case "Maldivian":
			slave.accent = naturalAccent;
			break;
		case "Malian":
			slave.accent = (V.language === "Arabic") ? jsEither([0, 1, 2, 2, 2, 3, 3]) : naturalAccent;
			break;
		case "Maltese":
			if (V.language === "English") {
				slave.accent = jsEither([0, 1, 1, 1, 1, 2]);
			} else if (V.language === "Italian") {
				slave.accent = jsEither([0, 1, 1, 1, 1, 2]);
			} else {
				slave.accent = naturalAccent;
			}
			break;
		case "Marshallese":
			slave.accent = (V.language === "English") ? jsEither([0, 1, 1, 1, 1, 2]) : naturalAccent;
			break;
		case "Mauritanian":
			slave.accent = (V.language === "Arabic") ? jsEither([0, 1, 1, 1, 1, 2]) : naturalAccent;
			break;
		case "Mauritian":
			if (V.language === "English") {
				slave.accent = jsEither([0, 1, 1, 1, 1, 2]);
			} else if (V.language === "French") {
				slave.accent = jsEither([0, 1, 1, 1, 1, 2]);
			} else {
				slave.accent = naturalAccent;
			}
			break;
		case "Mexican":
			if (V.language === "Spanish") {
				slave.accent = jsEither([0, 1, 1, 1, 1, 2]);
			} else if (V.language === "Nahuatl" && slave.race === "amerindian") {
				slave.accent = jsEither([0, 1, 2, 2, 2, 3, 3]);
			} else {
				slave.accent = naturalAccent;
			}
			break;
		case "Micronesian":
			slave.accent = (V.language === "English") ? jsEither([0, 1, 1, 1, 1, 2]) : naturalAccent;
			break;
		case "Moldovan":
			slave.accent = (V.language === "Russian") ? jsEither([0, 1, 1, 1, 1, 2]) : naturalAccent;
			break;
		case "Monégasque":
			slave.accent = (V.language === "French") ? jsEither([0, 1, 1, 1, 1, 2]) : naturalAccent;
			break;
		case "Mongolian":
			slave.accent = naturalAccent;
			break;
		case "Montenegrin":
			slave.accent = (V.language === "Serbian") ? jsEither([0, 1, 1, 1, 1, 2]) : naturalAccent;
			break;
		case "Moroccan":
			slave.accent = (V.language === "Arabic") ? jsEither([0, 1, 2, 2, 2, 3, 3]) : naturalAccent;
			break;
		case "Mosotho":
			slave.accent = (V.language === "Sesotho") ? jsEither([0, 0, 0, 0, 0, 0, 1]) : naturalAccent;
			break;
		case "Motswana":
			slave.accent = (V.language === "English") ? jsEither([0, 1, 1, 1, 1, 2]) : naturalAccent;
			break;
		case "Mozambican":
			if (V.language === "Portuguese") {
				slave.accent = jsEither([0, 1, 1, 1, 1, 2]);
			} else if (V.language === "Makhuwa") {
				slave.accent = jsEither([0, 1, 1, 1, 1, 2]);
			} else if (V.language === "Sena") {
				slave.accent = jsEither([0, 1, 1, 1, 1, 2]);
			} else if (V.language === "Swahili") {
				slave.accent = jsEither([0, 1, 1, 1, 1, 2]);
			} else {
				slave.accent = naturalAccent;
			}
			break;
		case "Namibian":
			if (V.language === "English") {
				slave.accent = jsEither([0, 1, 1, 1, 1, 2]);
			} else if (V.language === "Afrikaans") {
				slave.accent = jsEither([0, 1, 2, 2, 2, 3, 3]);
			} else {
				slave.accent = naturalAccent;
			}
			break;
		case "Nauruan":
			slave.accent = (V.language === "English") ? jsEither([0, 1, 1, 1, 1, 2]) : naturalAccent;
			break;
		case "Nepalese":
			if (V.language === "Nepali") {
				slave.accent = jsEither([0, 0, 0, 0, 0, 0, 1]);
			} else if (V.language === "Maithili") {
				slave.accent = jsEither([0, 1, 1, 1, 1, 2]);
			} else if (V.language === "Bhojpuri") {
				slave.accent = jsEither([0, 1, 1, 1, 1, 2]);
			} else if (V.language === "English") {
				slave.accent = jsEither([0, 1, 2, 2, 2, 3, 3]);
			} else {
				slave.accent = naturalAccent;
			}
			break;
		case "New Caledonian":
			if (V.language === "French") {
				slave.accent = jsEither([0, 1, 1, 1, 1, 2]);
			} else if (V.language === "Nengone") {
				slave.accent = jsEither([0, 1, 1, 1, 1, 2]);
			} else if (V.language === "Drehu") {
				slave.accent = jsEither([0, 1, 1, 1, 1, 2]);
			} else {
				slave.accent = naturalAccent;
			}
			break;
		case "a New Zealander":
			if (V.language === "English") {
				slave.accent = jsEither([0, 1, 1, 1, 1, 2]);
			} else if (V.language === "Māori" && slave.race === "pacific islander") {
				slave.accent = jsEither([0, 1, 2, 2, 2, 3, 3]);
			} else {
				slave.accent = naturalAccent;
			}
			break;
		case "Ni-Vanuatu":
			if (V.language === "French") {
				slave.accent = jsEither([0, 1, 1, 1, 1, 2]);
			} else if (V.language === "English") {
				slave.accent = jsEither([0, 1, 1, 1, 1, 2]);
			} else {
				slave.accent = naturalAccent;
			}
			break;
		case "Nicaraguan":
			slave.accent = (V.language === "Spanish") ? jsEither([0, 1, 1, 1, 1, 2]) : naturalAccent;
			break;
		case "Nigerian":
			if (V.language === "English") {
				slave.accent = jsEither([0, 1, 1, 1, 1, 2]);
			} else if (V.language === "Hausa") {
				slave.accent = jsEither([0, 1, 1, 1, 1, 2]);
			} else if (V.language === "Arabic") {
				slave.accent = jsEither([0, 1, 2, 2, 2, 3, 3]);
			} else {
				slave.accent = naturalAccent;
			}
			break;
		case "Nigerien":
			if (V.language === "French") {
				slave.accent = jsEither([0, 1, 1, 1, 1, 2]);
			} else if (V.language === "Hausa") {
				slave.accent = jsEither([0, 1, 1, 1, 1, 2]);
			} else if (V.language === "Arabic") {
				slave.accent = jsEither([0, 1, 2, 2, 2, 3, 3]);
			} else {
				slave.accent = naturalAccent;
			}
			break;
		case "Niuean":
			slave.accent = (V.language === "English") ? jsEither([0, 1, 1, 1, 1, 2]) : naturalAccent;
			break;
		case "Norwegian":
			slave.accent = naturalAccent;
			break;
		case "Omani":
			slave.accent = (V.language === "Arabic") ? jsEither([0, 1, 1, 1, 1, 2]) : naturalAccent;
			break;
		case "Pakistani":
			slave.accent = (V.language === "Arabic") ? jsEither([0, 1, 2, 2, 2, 3, 3]) : naturalAccent;
			break;
		case "Palauan":
			if (V.language === "English") {
				slave.accent = jsEither([0, 1, 1, 1, 1, 2]);
			} else if (V.language === "Sonsorolese") {
				slave.accent = jsEither([0, 1, 1, 1, 1, 2]);
			} else if (V.language === "Tobian") {
				slave.accent = jsEither([0, 1, 1, 1, 1, 2]);
			} else if (V.language === "Japanese") {
				slave.accent = jsEither([0, 1, 2, 2, 2, 3, 3]);
			} else {
				slave.accent = naturalAccent;
			}
			break;
		case "Palestinian":
			slave.accent = (V.language === "Arabic") ? jsEither([0, 1, 1, 1, 1, 2]) : naturalAccent;
			break;
		case "Panamanian":
			slave.accent = (V.language === "Spanish") ? jsEither([0, 1, 1, 1, 1, 2]) : naturalAccent;
			break;
		case "Papua New Guinean":
			slave.accent = naturalAccent;
			break;
		case "Paraguayan":
			slave.accent = (V.language === "Spanish") ? jsEither([0, 1, 1, 1, 1, 2]) : naturalAccent;
			break;
		case "Peruvian":
			slave.accent = (V.language === "Spanish") ? jsEither([0, 1, 1, 1, 1, 2]) : naturalAccent;
			break;
		case "Polish":
			slave.accent = naturalAccent;
			break;
		case "Portuguese":
			slave.accent = (V.language === "Spanish") ? jsEither([0, 1, 2, 2, 2, 3, 3]) : naturalAccent;
			break;
		case "Puerto Rican":
			if (V.language === "Spanish") {
				slave.accent = jsEither([0, 1, 1, 1, 1, 2]);
			} else if (V.language === "English") {
				slave.accent = jsEither([0, 1, 2, 2, 2, 3, 3]);
			} else {
				slave.accent = naturalAccent;
			}
			break;
		case "Qatari":
			slave.accent = (V.language === "Arabic") ? jsEither([0, 1, 1, 1, 1, 2]) : naturalAccent;
			break;
		case "Romanian":
			slave.accent = naturalAccent;
			break;
		case "Russian":
			slave.accent = naturalAccent;
			break;
		case "Rwandan":
			slave.accent = (V.language === "Kinyarwanda") ? jsEither([0, 0, 0, 0, 0, 0, 1]) : naturalAccent;
			break;
		case "Sahrawi":
			slave.accent = (V.language === "Arabic") ? jsEither([0, 1, 1, 1, 1, 2]) : naturalAccent;
			break;
		case "Saint Lucian":
			slave.accent = (V.language === "English") ? jsEither([0, 1, 1, 1, 1, 2]) : naturalAccent;
			break;
		case "Salvadoran":
			slave.accent = (V.language === "Spanish") ? jsEither([0, 1, 1, 1, 1, 2]) : naturalAccent;
			break;
		case "Sammarinese":
			slave.accent = (V.language === "Italian") ? jsEither([0, 1, 1, 1, 1, 2]) : naturalAccent;
			break;
		case "Samoan":
			slave.accent = (V.language === "English") ? jsEither([0, 1, 1, 1, 1, 2]) : naturalAccent;
			break;
		case "São Toméan":
			slave.accent = (V.language === "Portuguese") ? jsEither([0, 1, 1, 1, 1, 2]) : naturalAccent;
			break;
		case "Saudi":
			slave.accent = (V.language === "Arabic") ? jsEither([0, 0, 0, 0, 0, 0, 1]) : naturalAccent;
			break;
		case "Scottish":
			slave.accent = (V.language === "English") ? jsEither([0, 1, 1, 1, 1, 2]) : naturalAccent;
			break;
		case "Senegalese":
			slave.accent = (V.language === "French") ? jsEither([0, 1, 1, 1, 1, 2]) : naturalAccent;
			break;
		case "Serbian":
			if (V.language === "Bosnian") {
				slave.accent = jsEither([0, 1, 1, 1, 1, 2]);
			} else if (V.language === "Serbian") {
				slave.accent = jsEither([0, 1, 1, 1, 1, 2]);
			} else {
				slave.accent = naturalAccent;
			}
			break;
		case "Seychellois":
			if (V.language === "French") {
				slave.accent = jsEither([0, 1, 1, 1, 1, 2]);
			} else if (V.language === "English") {
				slave.accent = jsEither([0, 1, 2, 2, 2, 3, 3]);
			} else {
				slave.accent = naturalAccent;
			}
			break;
		case "Sierra Leonean":
			slave.accent = (V.language === "English") ? jsEither([0, 1, 1, 1, 1, 2]) : naturalAccent;
			break;
		case "Singaporean":
			if (V.language === "English") {
				slave.accent = jsEither([0, 1, 1, 1, 1, 2]);
			} else if (V.language === "Chinese") {
				slave.accent = jsEither([0, 1, 1, 1, 1, 2]);
			} else if (V.language === "Malay") {
				slave.accent = jsEither([0, 1, 1, 1, 1, 2]);
			} else if (V.language === "Tamil") {
				slave.accent = jsEither([0, 1, 1, 1, 1, 2]);
			} else {
				slave.accent = naturalAccent;
			}
			break;
		case "Slovak":
			slave.accent = (V.language === "Czech") ? jsEither([0, 1, 1, 1, 1, 2]) : naturalAccent;
			break;
		case "Slovene":
			slave.accent = naturalAccent;
			break;
		case "a Solomon Islander":
			slave.accent = (V.language === "English") ? jsEither([0, 1, 1, 1, 1, 2]) : naturalAccent;
			break;
		case "Somali":
			slave.accent = (V.language === "Arabic") ? jsEither([0, 1, 1, 1, 1, 2]) : naturalAccent;
			break;
		case "South African":
			if (V.language === "English") {
				slave.accent = jsEither([0, 1, 1, 1, 1, 2]);
			} else if (V.language === "Afrikaans") {
				slave.accent = jsEither([0, 0, 0, 0, 0, 0, 1]);
			} else if (V.language === "Dutch") {
				slave.accent = jsEither([0, 1, 2, 2, 2, 3, 3]);
			} else {
				slave.accent = naturalAccent;
			}
			break;
		case "South Sudanese":
			slave.accent = (V.language === "English") ? jsEither([0, 1, 1, 1, 1, 2]) : naturalAccent;
			break;
		case "Spanish":
			slave.accent = (V.language === "Catalan") ? jsEither([0, 1, 2, 2, 2, 3, 3]) : naturalAccent;
			break;
		case "Sri Lankan":
			if (V.language === "Sinhalese") {
				slave.accent = jsEither([0, 0, 0, 0, 0, 0, 1]);
			} else if (V.language === "Tamil") {
				slave.accent = jsEither([0, 0, 0, 0, 0, 0, 1]);
			} else if (V.language === "English") {
				slave.accent = jsEither([0, 1, 2, 2, 2, 3, 3]);
			} else {
				slave.accent = naturalAccent;
			}
			break;
		case "Sudanese":
			slave.accent = (V.language === "Arabic") ? jsEither([0, 1, 2, 2, 2, 3, 3]) : naturalAccent;
			break;
		case "Surinamese":
			slave.accent = (V.language === "Dutch") ? jsEither([0, 1, 1, 1, 1, 2]) : naturalAccent;
			break;
		case "Swazi":
			if (V.language === "English") {
				slave.accent = jsEither([0, 1, 1, 1, 1, 2]);
			} else if (V.language === "Afrikaans") {
				slave.accent = jsEither([0, 1, 2, 2, 2, 3, 3]);
			} else if (V.language === "Tsonga") {
				slave.accent = jsEither([0, 1, 2, 2, 2, 3, 3]);
			} else if (V.language === "Zulu") {
				slave.accent = jsEither([0, 1, 2, 2, 2, 3, 3]);
			} else {
				slave.accent = naturalAccent;
			}
			break;
		case "Swedish":
			if (V.language === "English") {
				slave.accent = jsEither([0, 1, 2, 2, 2, 3, 3]);
			} else if (V.language === "Finnish") {
				slave.accent = jsEither([0, 1, 2, 2, 2, 3, 3]);
			} else if (V.language === "Norwegian") {
				slave.accent = jsEither([0, 1, 2, 2, 2, 3, 3]);
			} else if (V.language === "German") {
				slave.accent = jsEither([0, 1, 2, 2, 2, 3, 3]);
			} else {
				slave.accent = naturalAccent;
			}
			break;
		case "Swiss":
			if (V.language === "German") {
				slave.accent = jsEither([0, 1, 1, 1, 1, 2]);
			} else if (V.language === "French") {
				slave.accent = jsEither([0, 1, 1, 1, 1, 2]);
			} else if (V.language === "Italian") {
				slave.accent = jsEither([0, 1, 2, 2, 2, 3, 3]);
			} else {
				slave.accent = naturalAccent;
			}
			break;
		case "Syrian":
			slave.accent = (V.language === "Arabic") ? jsEither([0, 1, 1, 1, 1, 2]) : naturalAccent;
			break;
		case "Taiwanese":
			slave.accent = (V.language === "Chinese") ? jsEither([0, 0, 0, 0, 0, 0, 1]) : naturalAccent;
			break;
		case "Tajik":
			slave.accent = (V.language === "Russian") ? jsEither([0, 1, 2, 2, 2, 3, 3]) : naturalAccent;
			break;
		case "Tanzanian":
			slave.accent = (V.language === "Swahili") ? jsEither([0, 0, 0, 0, 0, 0, 1]) : naturalAccent;
			break;
		case "Thai":
			if (V.language === "Chinese") {
				slave.accent = jsEither([0, 1, 2, 2, 2, 3, 3]);
			} else if (V.language === "Malay") {
				slave.accent = jsEither([0, 1, 2, 2, 2, 3, 3]);
			} else if (V.language === "Khmer") {
				slave.accent = jsEither([0, 1, 2, 2, 2, 3, 3]);
			} else {
				slave.accent = naturalAccent;
			}
			break;
		case "Tibetan":
			slave.accent = (V.language === "Chinese") ? jsEither([0, 1, 1, 1, 1, 2]) : naturalAccent;
			break;
		case "Togolese":
			slave.accent = (V.language === "French") ? jsEither([0, 1, 1, 1, 1, 2]) : naturalAccent;
			break;
		case "Tongan":
			slave.accent = (V.language === "English") ? jsEither([0, 1, 1, 1, 1, 2]) : naturalAccent;
			break;
		case "Trinidadian":
			slave.accent = (V.language === "English") ? jsEither([0, 1, 1, 1, 1, 2]) : naturalAccent;
			break;
		case "Tunisian":
			slave.accent = (V.language === "Arabic") ? jsEither([0, 1, 1, 1, 1, 2]) : naturalAccent;
			break;
		case "Turkish":
			if (V.language === "Arabic") {
				slave.accent = jsEither([0, 1, 2, 2, 2, 3, 3]);
			} else if (V.language === "Kurdish") {
				slave.accent = jsEither([0, 1, 2, 2, 2, 3, 3]);
			} else if (V.language === "Zaza") {
				slave.accent = jsEither([0, 1, 2, 2, 2, 3, 3]);
			} else {
				slave.accent = naturalAccent;
			}
			break;
		case "Turkmen":
			slave.accent = (V.language === "Russian") ? jsEither([0, 1, 2, 2, 2, 3, 3]) : naturalAccent;
			break;
		case "Tuvaluan":
			slave.accent = (V.language === "English") ? jsEither([0, 1, 1, 1, 1, 2]) : naturalAccent;
			break;
		case "Ugandan":
			slave.accent = (V.language === "Swahili") ? jsEither([0, 0, 0, 0, 0, 0, 1]) : naturalAccent;
			break;
		case "Ukrainian":
			slave.accent = (V.language === "Russian") ? jsEither([0, 1, 2, 2, 2, 3, 3]) : naturalAccent;
			break;
		case "Uruguayan":
			slave.accent = (V.language === "Spanish") ? jsEither([0, 1, 1, 1, 1, 2]) : naturalAccent;
			break;
		case "Uzbek":
			slave.accent = (V.language === "Russian") ? jsEither([0, 1, 2, 2, 2, 3, 3]) : naturalAccent;
			break;
		case "Vatican":
			if (V.language === "Italian") {
				slave.accent = jsEither([0, 0, 0, 0, 0, 0, 1]);
			} else if (V.language === "Latin") {
				slave.accent = jsEither([0, 0, 0, 0, 0, 0, 1]);
			} else if (V.language === "French") {
				slave.accent = jsEither([0, 1, 2, 2, 2, 3, 3]);
			} else if (V.language === "German") {
				slave.accent = jsEither([0, 1, 2, 2, 2, 3, 3]);
			} else {
				slave.accent = naturalAccent;
			}
			break;
		case "Venezuelan":
			slave.accent = (V.language === "Spanish") ? jsEither([0, 1, 1, 1, 1, 2]) : naturalAccent;
			break;
		case "Vietnamese":
			if (V.language === "Chinese") {
				slave.accent = jsEither([0, 1, 2, 2, 2, 3, 3]);
			} else if (V.language === "English") {
				slave.accent = jsEither([0, 1, 2, 2, 2, 3, 3]);
			} else if (V.language === "French") {
				slave.accent = jsEither([0, 1, 2, 2, 2, 3, 3]);
			} else {
				slave.accent = naturalAccent;
			}
			break;
		case "Vincentian":
			slave.accent = (V.language === "English") ? jsEither([0, 1, 1, 1, 1, 2]) : naturalAccent;
			break;
		case "Yemeni":
			slave.accent = (V.language === "Arabic") ? jsEither([0, 1, 1, 1, 1, 2]) : naturalAccent;
			break;
		case "Zairian":
			if (V.language === "Lingala") {
				slave.accent = jsEither([0, 0, 0, 0, 0, 0, 1]);
			} else if (V.language === "Kikongo") {
				slave.accent = jsEither([0, 1, 1, 1, 1, 2]);
			} else if (V.language === "Swahili") {
				slave.accent = jsEither([0, 1, 1, 1, 1, 2]);
			} else if (V.language === "French") {
				slave.accent = jsEither([0, 1, 1, 1, 1, 2]);
			} else {
				slave.accent = naturalAccent;
			}
			break;
		case "Zambian":
			slave.accent = (V.language === "English") ? jsEither([0, 1, 1, 1, 1, 2]) : naturalAccent;
			break;
		case "Zimbabwean":
			if (V.language === "Shona") {
				slave.accent = jsEither([0, 0, 0, 0, 0, 0, 1]);
			} else if (V.language === "Ndebele") {
				slave.accent = jsEither([0, 1, 1, 1, 1, 2]);
			} else if (V.language === "Chewa") {
				slave.accent = jsEither([0, 1, 1, 1, 1, 2]);
			} else if (V.language === "English") {
				slave.accent = jsEither([0, 1, 1, 1, 1, 2]);
			} else {
				slave.accent = naturalAccent;
			}
			break;
		case "Ancient Chinese Revivalist":
			slave.accent = (V.language === "Chinese") ? jsEither([0, 0, 0, 0, 0, 0, 1]) : naturalAccent;
			break;
		case "Ancient Egyptian Revivalist":
			slave.accent = (V.language === "Ancient Egyptian") ? jsEither([0, 0, 0, 0, 0, 0, 1]) : naturalAccent;
			break;
		case "Arabian Revivalist":
			slave.accent = (V.language === "Arabic") ? jsEither([0, 0, 0, 0, 0, 0, 1]) : naturalAccent;
			break;
		case "Aztec Revivalist":
			slave.accent = (V.language === "Nahuatl") ? jsEither([0, 0, 0, 0, 0, 0, 1]) : naturalAccent;
			break;
		case "Edo Revivalist":
			slave.accent = (V.language === "Japanese") ? jsEither([0, 0, 0, 0, 0, 0, 1]) : naturalAccent;
			break;
		case "Roman Revivalist":
			slave.accent = (V.language === "Latin") ? jsEither([0, 0, 0, 0, 0, 0, 1]) : naturalAccent;
			break;
		default:
			slave.accent = naturalAccent;
			break;
	}

	if (slave.nationality === V.language) {
		slave.accent = jsEither([0, 0, 0, 0, 0, 0, 1]);
	}
};

/*
Backup and then apply gingering modifiers to $activeSlave - no changes should be made to $activeSlave until after calling removeGingering() to restore the backup
Called from lawCompliance
*/
window.checkForGingering = function checkForGingering() {
	const V = State.variables;
	let r = "";
	const pronouns = getPronouns(V.activeSlave);
	const he = pronouns.pronoun;
	const him = pronouns.object;
	const his = pronouns.possessive;
	const He = capFirstChar(he);
	const His = capFirstChar(his);

	/* reset in case gingered slaves were viewed but not purchased (no newSlaveIntro) */
	V.gingering = 0;
	V.gingeringDetected = 0;
	V.gingeringDetection = 0;
	V.toSearch = V.activeSlave.origin;
	if (V.applyLaw === 1 && V.HonestySMR === 1) {
		/* SMR prohibits gingering and is enforced for this slave - do nothing */
	} else if (V.activeSlave.indenture > 0) {
		/* indentured servants cannot be gingered */
	} else if (V.toSearch !== 0 && V.toSearch.indexOf("Shelter") !== -1) {
		/* is a Shelter slave - do nothing */
	} else {
		V.beforeGingering = clone(V.activeSlave);
		if (V.activeSlave.trust < -20 && jsRandom(1, 3) === 1) {
			V.gingering = "antidepressant";
			V.activeSlave.trust += jsRandom(10, 40);
		} else if (V.activeSlave.devotion < -20 && jsRandom(1, 3) === 1) {
			V.gingering = "depressant";
			V.activeSlave.devotion += jsRandom(10, 40);
		} else if (V.activeSlave.health < 60 && jsRandom(1, 3) === 1) {
			V.gingering = "stimulant";
			V.activeSlave.health += jsRandom(20, 40);
		} else if (V.activeSlave.balls > 0 && V.activeSlave.dick > 2 && jsRandom(1, 3) === 1) {
			V.gingering = "vasoconstrictor";
			V.activeSlave.dick -= jsRandom(1, 2);
		} else if (V.activeSlave.balls > 0 && V.activeSlave.dick < 5 && jsRandom(1, 3) === 1) {
			V.gingering = "vasodilator";
			V.activeSlave.dick += jsRandom(1, 2);
		} else if (V.activeSlave.attrKnown === 0 && jsRandom(1, 3) === 1) {
			V.gingering = "aphrodisiac";
			V.activeSlave.aphrodisiacs = 2;
			V.activeSlave.attrKnown = 1;
			V.activeSlave.attrXX = jsRandom(60, 90);
			V.activeSlave.attrXY = jsRandom(60, 90);
			V.activeSlave.energy = jsRandom(50, 90);
		} else if (V.activeSlave.anus > 0 && V.activeSlave.fetishKnown === 0 && jsRandom(1, 3) === 1) {
			V.gingering = "ginger";
			V.activeSlave.fetish = "buttslut";
			V.activeSlave.fetishKnown = 1;
			V.activeSlave.fetishStrength = 65;
		}
	}
	if (V.gingering !== 0) {
		if (V.PC.slaving >= 100) {
			V.gingeringDetected = 1;
			V.gingeringDetection = "slaver";
			switch (V.gingering) {
				case "antidepressant":
					r += `${He} is acting dazed and unfocused. ${He}'s obviously been given antidepressants to make ${him} appear less fearful, and will be considerably less trusting than ${he} seems.`;
					break;
				case "depressant":
					r += `${He} is acting languid and drugged. ${He}'s obviously been given a depressant to make ${him} appear less hateful, and will be considerably less accepting of slavery than ${he} seems.`;
					break;
				case "stimulant":
					r += `${He} is acting twitchy and hyperactive. ${He}'s obviously been given a stimulant to make ${him} seem healthier and more energetic, and is a lot less healthy than ${he} looks.`;
					break;
				case "vasoconstrictor":
					r += `${His} lips have the slightest blue tinge, making it obvious ${he}'s been given a vasoconstrictor. ${His} cock is a lot less of a girldick than it looks right now.`;
					break;
				case "vasodilator":
					r += `${He} has an impressive erection, but it seems quite unconnected to the rest of ${him}, as if ${he} doesn't know what to do with it. ${He}'s obviously been given a vasodilator to make ${his} dick seem a little less pathetic.`;
					break;
				case "aphrodisiac":
					r += `${His} pupils are slightly dilated, ${his} breath comes in fast pants, and ${his} skin is flushed. ${He}'s obviously been given as big of a dose of aphrodisiacs as ${he} can handle without a heart attack.`;
					break;
				default:
					r += `${He} is acting oddly, presenting ${his} ass in an awkward way and acting uncomfortable. ${He}'s obviously had an irritant shoved up ${his} butt to make ${him} act like an anal whore.`;
			}
			r += ` It's a trick you're very familiar with, given your <span class="springgreen">training as a slaver.</span>`;
		} else {
			/* not slaver */
			if (V.PC.warfare >= 100 && jsRandom(1, 2) === 1) {
				V.gingeringDetected = 1;
				V.gingeringDetection = "mercenary";
			} else if (V.PC.rumor === "force" && jsRandom(1, 2) === 1) {
				V.gingeringDetected = 1;
				V.gingeringDetection = "force";
			} else if (jsRandom(1, 3) === 1) {
				V.gingeringDetected = 1;
			}
			if (V.gingeringDetected === 1) {
				switch (V.gingering) {
					case "antidepressant":
						r += `${He} is acting dazed and unfocused, like ${he}'s been given antidepressants to make ${him} appear less fearful. ${He} may be considerably less trusting than ${he} seems. `;
						break;
					case "depressant":
						r += `${He} is acting languid and drugged, like ${he}'s been given a depressant to make ${him} appear less hateful. ${He} may be considerably less accepting of slavery than ${he} seems. `;
						break;
					case "stimulant":
						r += `${He} is acting twitchy and hyperactive, like ${he}'s been given a stimulant to make ${him} seem healthier and more energetic. ${He} may be considerably less vital than ${he} seems. `;
						break;
					case "vasoconstrictor":
						r += `${His} lips have the slightest blue tinge, suggesting that ${he} may have been given a vasoconstrictor. If ${he} has, ${his} cock may be considerably less feminine and demure than it now seems. `;
						break;
					case "vasodilator":
						r += `${He} has an impressive erection, but it seems quite unconnected to the rest of ${him}, as if ${he} doesn't know what to do with it. ${He} may have been given a vasodilator. If ${he} has, ${his} cock may be considerably less impressive than it now seems. `;
						break;
					case "aphrodisiac":
						r += `${His} pupils are slightly dilated, ${his} breath comes in fast pants, and ${his} skin is flushed. These are the characteristic symptoms of a dose of aphrodisiacs limited only by a desire to avoid giving ${him} a heart attack. `;
						break;
					default:
						r += `${He} is acting oddly, presenting ${his} ass in an awkward way and acting uncomfortable. ${He} may be considerably less interested in anal sex than ${he} seems. `;
				}
				if (V.gingeringDetection === "mercenary") {
					r += `The nervous seller confirms this in response to a direct inquiry. Your intimidating reputation from your <span class="springgreen">extensive combat training</span> has its uses.`;
				} else if (V.gingeringDetection === "force") {
					r += `The nervous seller confirms this in response to a direct inquiry. Your reputation as a <span class="springgreen"> ${V.PCTitle ? "man" : "woman"} of blood</span> has its uses.`;
				}
			}
		} /* gingering detected */
	} /* gingering !== 0 */
	return r;
};

/*
Retrieve original $activeSlave without gingering modifiers
Call as removeGingering()
Called from newSlaveIntro, bulkSlaveGenerate
*/
window.removeGingering = function removeGingering() {
	const V = State.variables;
	if (V.gingering !== 0 && V.beforeGingering !== 0 && V.activeSlave !== 0 && V.beforeGingering.ID === V.activeSlave.ID) {
		/* extra checks to ensure gingering state is not left over from a different slave that was inspected but not purchased */
		V.activeSlave = V.beforeGingering;
		V.beforeGingering = 0;
	} else {
		/* clear left over state from a different slave without modifying activeSlave
		 */
		V.gingering = 0;
		V.beforeGingering = 0;
	}
};

/**
 * @param {App.Entity.SlaveState} slave*/
window.randomizeAttraction = function randomizeAttraction(slave) {
	const sexuality = jsRandom(0, 100);
	let attraction = Math.clamp(slave.energy * 2, 60, 180);

	if (slave.balls > 0) {
		if (sexuality > 90) {
			slave.attrXY = Math.clamp(attraction, 0, 100);
			attraction -= slave.attrXY;
			slave.attrXX = Math.clamp(attraction, 0, 100);
		} else if (sexuality > 70) {
			slave.attrXY = Math.clamp(attraction + jsRandom(-5, 5), 0, 100);
			slave.attrXX = Math.clamp(attraction + jsRandom(-5, 5), 0, 100);
		} else {
			slave.attrXX = Math.clamp(attraction, 0, 100);
			attraction -= slave.attrXX;
			slave.attrXY = Math.clamp(attraction, 0, 100);
		}
	} else {
		if (sexuality > 90) {
			slave.attrXX = Math.clamp(attraction, 0, 100);
			attraction -= slave.attrXX;
			slave.attrXY = Math.clamp(attraction, 0, 100);
		} else if (sexuality > 60) {
			slave.attrXY = Math.clamp(attraction + jsRandom(-5, 5), 0, 100);
			slave.attrXX = Math.clamp(attraction + jsRandom(-5, 5), 0, 100);
		} else {
			slave.attrXY = Math.clamp(attraction, 0, 100);
			attraction -= slave.attrXY;
			slave.attrXX = Math.clamp(attraction, 0, 100);
		}
	}
	slave.attrXX = Math.clamp(slave.attrXX + jsRandom(-5, 5), 0, 100);
	slave.attrXY = Math.clamp(slave.attrXY + jsRandom(-5, 5), 0, 100);
};

window.BaseSlave = function BaseSlave() {
	return new App.Entity.SlaveState();
};

/**
 * @param {App.Entity.SlaveState} slave*/
window.generatePronouns = function generatePronouns(slave) {
	if (slave.fuckdoll > 0) {
		slave.pronoun = "it";
		slave.possessivePronoun = "its";
		slave.possessive = "its";
		slave.object = "it";
		slave.objectReflexive = "itself";
		slave.noun = "toy";
	} else if (slave.dick > 0 && slave.vagina === -1 && State.variables.diversePronouns === 1) {
		slave.pronoun = "he";
		slave.possessivePronoun = "his";
		slave.possessive = "his";
		slave.object = "him";
		slave.objectReflexive = "himself";
		slave.noun = "boy";
	} else {
		slave.pronoun = "she";
		slave.possessivePronoun = "hers";
		slave.possessive = "her";
		slave.object = "her";
		slave.objectReflexive = "herself";
		slave.noun = "girl";
	}
};

/**
 * @param {App.Entity.SlaveState} slave
 */
window.generatePuberty = function(slave) {
	if ((slave.ovaries === 1 || slave.mpreg === 1) && slave.physicalAge >= slave.pubertyAgeXX) {
		slave.pubertyXX = 1;
	} else {
		slave.pubertyXX = 0;
	}
	if (slave.balls > 0 && slave.ballType !== "sterile" && slave.physicalAge >= slave.pubertyAgeXY) {
		slave.pubertyXY = 1;
	} else {
		slave.pubertyXY = 0;
	}
};

/**
 * @param {App.Entity.SlaveState} slave
 */
window.ageImplantAdjustment = function(slave) {
	if (slave.visualAge > 80) {
		slave.visualAge -= 40;
	} else if (slave.visualAge >= 70) {
		slave.visualAge -= 30;
	} else if (slave.visualAge > 50) {
		slave.visualAge -= 20;
	} else if (slave.visualAge > 36) {
		slave.visualAge -= 10;
	} else {
		slave.visualAge -= 5;
	}
};


code:
/**
 * @file Functions for rendering lists of slave summaries for various purposes. This includes
 * lists for the penthouse/facilities, selecting a slaves, facility leaders.
 *
 * For documentation see devNotes/slaveListing.md
 */

App.UI.SlaveList = {};

/**
 * @callback slaveTextGenerator
 * @param {App.Entity.SlaveState} slave
 * @param {number} index
 * @return {string}
 */
App.UI.SlaveList.render = function() {
	'use strict';
	let V;
	/** @type {string} */
	let passageName;
	/** @type {App.Entity.SlaveState[]} */
	let slaves;
	/** @type {boolean} */
	let slaveImagePrinted;

	// potentially can be a problem if played long enough to reach Number.MAX_SAFE_INTEGER
	let listID = Number.MIN_SAFE_INTEGER;

	return renderList;

	/**
	 * @param {number[]} indices
	 * @param {Array.<{index: number, rejects: string[]}>} rejectedSlaves
	 * @param {slaveTextGenerator} interactionLink
	 * @param {slaveTextGenerator} [postNote]
	 * @returns {string}
	 */
	function renderList(indices, rejectedSlaves, interactionLink, postNote) {
		V = State.variables;
		passageName = passage();
		slaves = V.slaves;
		V.assignTo = passageName; // would be passed to the "Assign" passage
		slaveImagePrinted = (V.seeImages === 1) && (V.seeSummaryImages === 1);

		let res = [];
		if (V.useSlaveListInPageJSNavigation === 1) {
			res.push(createQuickList(indices));
		}

		const fcs = App.Entity.facilities;

		// 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 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") {
				V.returnTo = passageName;
				showTransfers = true;
			}
		}

		for (const _si of indices) {
			let ss = renderSlave(_si, interactionLink, showTransfers, postNote);
			res.push(`<div id="slave-${slaves[_si].ID}" style="clear:both">${ss}</div>`);
		}

		for (const rs of rejectedSlaves) {
			const slave = slaves[rs.index];
			const rejects = rs.rejects;
			const slaveName = SlaveFullName(slave);
			let rejectString = rejects.length === 1 ?
				rejects[0] :
				`${slaveName}: <ul>${rejects.map(e => `
${e}
`).join('')}</ul>`;
			res.push(`<div id="slave_${slave.ID}" style="clear:both">${rejectString}</div>`);
		}

		$(document).one(':passagedisplay', function() {
			$('[data-quick-index]').unbind().click(function() {
				let which = this.attributes["data-quick-index"].value;
				let quick = $("div#list_index" + which);
				quick.toggleClass("hidden");
			});
			quickListBuildLinks();
		});

		if (V.useSlaveListInPageJSNavigation === 1) {
			listID++;
		}

		return res.join("");
	}

	/**
	 * @param {number} index
	 * @param {slaveTextGenerator} interactionLink
	 * @param {boolean} showTransfers
	 * @param {slaveTextGenerator} [postNote]
	 * @returns {string}
	 */
	function renderSlave(index, interactionLink, showTransfers, postNote) {
		let res = [];
		const slave = slaves[index];

		res.push(dividerAndImage(slave));
		res.push(interactionLink(slave, index));

		if ((slave.choosesOwnClothes === 1) && (slave.clothes === "choosing her own clothes")) {
			const _oldDevotion = slave.devotion;
			saChoosesOwnClothes(slave);
			slave.devotion = _oldDevotion; /* restore devotion value so repeatedly changing clothes isn't an exploit */
		}

		SlaveStatClamp(slave);
		slave.trust = Math.trunc(slave.trust);
		slave.devotion = Math.trunc(slave.devotion);
		slave.health = Math.trunc(slave.health);
		res.push(' will ');
		if ((slave.assignment === "rest") && (slave.health >= -20)) {
			res.push(`<strong><u><span class="lawngreen">rest</span></u></strong>`);
		} else if ((slave.assignment === "stay confined") && ((slave.devotion > 20) || ((slave.trust < -20) && (slave.devotion >= -20)) || ((slave.trust < -50) && (slave.devotion >= -50)))) {
			res.push(`<strong><u><span class="lawngreen">stay confined.</span></u></strong>`);
			if (slave.sentence > 0) {
				res.push(` (${slave.sentence} weeks)`);
			}
		} else if (slave.choosesOwnAssignment === 1) {
			res.push('choose her own job');
		} else {
			res.push(slave.assignment);
			if (slave.sentence > 0) {
				res.push(` ${slave.sentence} weeks`);
			}
		}
		res.push('. ');

		if ((V.displayAssignments === 1) && (passageName === "Main") && (slave.ID !== V.HeadGirl.ID) && (slave.ID !== V.Recruiter.ID) && (slave.ID !== V.Bodyguard.ID)) {
			res.push(App.UI.jobLinks.assignments(index, "Main"));
		}
		if (showTransfers) {
			res.push('
Transfer to: ' + App.UI.jobLinks.transfers(index));
		}
		res.push('
');

		if (slaveImagePrinted) {
			res.push('    ');
		}

		clearSummaryCache();
		res.push(SlaveSummary(slave));

		if (postNote !== undefined) {
			res.push('
');
			res.push(postNote(slave, index));
		}

		return res.join('');
	}

	/**
	 * @param {number[]} indices
	 * @return {string}
	*/
	function createQuickList(indices) {
		let res = "";

		/* Useful for finding weird combinations — usages of this passage that don't yet generate the quick index.
		*	<<print 'pass/count/indexed/flag::[' + passageName + '/' + _Count + '/' + _indexed + '/' + $SlaveSummaryFiler + ']'>>
		*/

		if (((indices.length > 1) && ((passageName === "Main") && ((V.useSlaveSummaryTabs === 0) || (V.slaveAssignmentTab === "all"))))) {
			const _buttons = [];
			let _offset = -50;
			if (/Select/i.test(passageName)) {
				_offset = -25;
			}
			res += "
";
			/*
			 * we want <button data-quick-index="<<= listID>>">...
			 */
			const _buttonAttributes = {
				'id':`quick-list-toggle${listID}`,
				'data-quick-index': listID
			};
			res += App.UI.htag("Quick Index", _buttonAttributes, 'button');
			/*
			 * we want
...
			 */
			let listIndexContent = "";

			for (const _ssii of indices) {
				const _IndexSlave = slaves[_ssii];
				const _indexSlaveName = SlaveFullName(_IndexSlave);
				const _devotionClass = getSlaveDevotionClass(_IndexSlave);
				const _trustClass = getSlaveTrustClass(_IndexSlave);
				_buttons.push({
					"data-name": _indexSlaveName,
					"data-scroll-to": `#slave-${_IndexSlave.ID}`,
					"data-scroll-offset": _offset,
					"data-devotion": _IndexSlave.devotion,
					"data-trust": _IndexSlave.trust,
					"class": `${_devotionClass} ${_trustClass}`
				});
			}
			if (_buttons.length > 0) {
				V.sortQuickList = V.sortQuickList || 'Devotion';
				listIndexContent += `//Sorting:// ''<span id="qlSort">$sortQuickList</span>.'' `;
				listIndexContent += '<<link "Sort by Devotion">>' +
					'<<set $sortQuickList = "Devotion" >>' +
					'<<replace "#qlSort">> $sortQuickList <</replace>>' +
					'<<run' + '$("#qlWrapper").removeClass("trust").addClass("devotion");' + 'sortButtonsByDevotion();' + '>>' +
					'<</link>> | ' +
					'<<link "Sort by Trust">>' +
					'<<set $sortQuickList = "Trust">>' +
					'<<replace "#qlSort">> $sortQuickList <</replace>>' +
					'<<run' + '$("#qlWrapper").removeClass("devotion").addClass("trust");' + 'sortButtonsByTrust();' + '>>' +
					'<</link>>' +
					'
';
				listIndexContent += '
';
				for (const _button of _buttons) {
					const _buttonSlaveName = _button['data-name'];
					listIndexContent += App.UI.htag(_buttonSlaveName, _button, 'button');
				}
				listIndexContent += '
';
			}
			res += App.UI.htag(listIndexContent, {
				id: `list_index${listID}`,
				class: 'hidden'
			});
		}
		return res;
	}

	function SlaveArt(slave, option) {
		return `<<SlaveArtById ${slave.ID} ${option}>>`;
	}

	function slaveImage(s) {
		return `<div class="imageRef smlImg">${SlaveArt(s, 1)}</div>`;
	}

	function dividerAndImage(s, showImage) {
		showImage = showImage || true;
		const r = [V.lineSeparations === 0 ? "
" : "
"];
		if (showImage && (V.seeImages === 1) && (V.seeSummaryImages === 1)) {
			r.push(slaveImage(s));
		}
		return r.join("");
	}
}();

App.UI.SlaveList.Decoration = {};
/**
 * returns "HG", "BG", "PA", and "RC" prefixes
 * @param {App.Entity.SlaveState} slave
 * @returns {string}
 */
App.UI.SlaveList.Decoration.penthousePositions = (slave) => {
	if (App.Data.Facilities.headGirlSuite.manager.assignment === slave.assignment) {
		return 'HG';
	}
	if (App.Data.Facilities.penthouse.manager.assignment === slave.assignment) {
		return 'RC';
	}
	if (App.Data.Facilities.armory.manager.assignment === slave.assignment) {
		return 'BG';
	}
	if (Array.isArray(State.variables.personalAttention) && State.variables.personalAttention.findIndex(s => s.ID === slave.ID) !== -1) {
		return 'PA';
	}
	return '';
};

App.UI.SlaveList.SlaveInteract = {};

/**
 * @param {App.Entity.SlaveState} slave
 * @param {number} index
 * @return {string}
 */
App.UI.SlaveList.SlaveInteract.stdInteract = (slave, index) =>
	App.UI.passageLink(SlaveFullName(slave), 'Slave Interact', `$activeSlave = $slaves[${index}]`);

/**
 * @param {App.Entity.SlaveState} slave
 * @param {number} index
 * @return {string}
 */
App.UI.SlaveList.SlaveInteract.penthouseInteract = (slave, index) => {
	return App.UI.SlaveList.Decoration.penthousePositions(slave) + ' ' + App.UI.SlaveList.SlaveInteract.stdInteract(slave, index);
};

/**
 * @param {App.Entity.SlaveState} slave
 * @return {string}
 */
App.UI.SlaveList.SlaveInteract.personalAttention = (slave) =>
	App.UI.passageLink(SlaveFullName(slave), undefined, `App.UI.selectSlaveForPersonalAttention(${slave.ID});`);

/**
 * @param {App.Entity.SlaveState} slave
 * @param {number} index
 * @return {string}
 */
App.UI.SlaveList.SlaveInteract.assign = (slave, index) =>
	App.UI.passageLink(SlaveFullName(slave), "Assign", `$i = ${index}`);

/**
 * @param {App.Entity.SlaveState} slave
 * @param {number} index
 * @return {string}
 */
App.UI.SlaveList.SlaveInteract.retrieve = (slave, index) =>
	App.UI.passageLink(SlaveFullName(slave), "Retrieve", `$i = ${index}`);

/**
 * Adds/removes a slave with the given id to/from the personal attention array
 * @param {number} id slave id
 */
App.UI.selectSlaveForPersonalAttention = function(id) {
	const V = State.variables;

	if (!Array.isArray(V.personalAttention)) {
		/* first PA target */
		V.personalAttention = [{
			ID: id,
			trainingRegimen: "undecided"
		}];
	} else {
		const _pai = V.personalAttention.findIndex(function(s) {
			return s.ID === id;
		});
		if (_pai === -1) {
			/* not already a PA target; add */
			V.activeSlave = getSlave(id);
			V.personalAttention.push({
				ID: id,
				trainingRegimen: "undecided"
			});
		} else {
			/* already a PA target; remove */
			V.personalAttention.deleteAt(_pai);
			if (V.personalAttention.length === 0) {
				V.personalAttention = "sex";
			}
		}
	}
	SugarCube.Engine.play("Personal Attention Select");
};

/**
 * Generates fragment with sorting options, that link to the given pasage
 * @param {string} passage The passage to link to
 * @returns {string}
 */
App.UI.SlaveList.sortingLinks = function(passage) {
	const V = State.variables;
	let r = '    Sort by: ';
	r += ["devotion", "name", "assignment", "seniority", "actualAge", "visualAge", "physicalAge"]
		.map(so => V.sortSlavesBy !== so ?
			App.UI.passageLink(capFirstChar(so.replace(/([A-Z])/g, " $1")), passage, `$sortSlavesBy = "${so}"`) : capFirstChar(so))
		.join(" | ");

	r += '    Sort: ';
	r += ["descending", "ascending"].map(so => V.sortSlavesOrder !== so ?
		App.UI.passageLink(capFirstChar(so), passage, `$sortSlavesOrder = "${so}"`) : capFirstChar(so))
		.join(" | ");
	return r;
};

/**
 * Standard tabs for a facility with a single job (SJ)
 * @param {App.Entity.Facilities.Facility} facility
 * @param {string} [facilityPassage]
 * @param {boolean} [showTransfersTab=false]
 * @param {{assign: string, remove: string, transfer: (string| undefined)}} [tabCaptions]
 * @returns {string}
 */
App.UI.SlaveList.listSJFacilitySlaves = function(facility, facilityPassage, showTransfersTab = false, tabCaptions = undefined) {
	const V = State.variables;
	facilityPassage = facilityPassage || passage();
	tabCaptions = tabCaptions || {
		assign: 'Assign a slave',
		remove: 'Remove a slave',
		transfer: 'Transfer from Facility'
	};
	let r = '';
	if (V.sortSlavesMain) {
		r += this.sortingLinks(facilityPassage) + '
';
	}
	r += '
' +
		App.UI.tabbar.tabButton('assign',  tabCaptions.assign) +
		App.UI.tabbar.tabButton('remove', tabCaptions.remove) +
		(showTransfersTab ? App.UI.tabbar.tabButton('transfer', tabCaptions.transfer) : '')+
	'
';

	if (facility.hostedSlaves > 0) {
		let facilitySlaves = facility.job().employeesIndices();
		SlaveSort.indices(facilitySlaves);
		r += App.UI.tabbar.makeTab("remove", App.UI.SlaveList.render(facilitySlaves, [],
			App.UI.SlaveList.SlaveInteract.stdInteract,
			(slave, index) => App.UI.passageLink(`Retrieve ${slave.object} from ${facility.name}`, "Retrieve", `$i = ${index}`)));
	} else {
		r += App.UI.tabbar.makeTab("remove", `<em>${capFirstChar(facility.name)} is empty for the moment</em>`);
	}

	/**
	 * @param {number[]} slaveIdxs
	 * @returns {string}
	 */
	function assignableTabContent(slaveIdxs) {
		SlaveSort.indices(slaveIdxs);
		const slaves = V.slaves;
		let rejectedSlaves = [];
		let passedSlaves = [];
		slaveIdxs.forEach((idx) => {
			const rejects = facility.canHostSlave(slaves[idx]);
			if (rejects.length > 0) {
				rejectedSlaves.push({index: idx, rejects: rejects});
			} else {
				passedSlaves.push(idx);
			}
		}, []);
		return App.UI.SlaveList.render(passedSlaves, rejectedSlaves,
			App.UI.SlaveList.SlaveInteract.stdInteract,
			(slave, index) => App.UI.passageLink(`Send ${slave.object} to ${facility.name}`, "Assign", `$i = ${index}`));
	}
	if (facility.hasFreeSpace) {
		// slaves from the penthouse can be transferred here
		r += App.UI.tabbar.makeTab("assign", assignableTabContent(App.Entity.facilities.penthouse.employeesIndices()));
	} else {
		r += App.UI.tabbar.makeTab("assign", `<strong>${capFirstChar(facility.name)} is full and cannot hold any more slaves</strong>`);
	}

	if (showTransfersTab) {
		if (facility.hasFreeSpace) {
			// slaves from other facilities can be transferred here
			const transferableIndices = V.slaves.reduce((acc, slave, ind) => {
				if (slave.assignmentVisible === 0 && !facility.isHosted(slave)) {
					acc.push(ind);
				}
				return acc;
			}, []);
			r += App.UI.tabbar.makeTab("transfer", assignableTabContent(transferableIndices));
		} else {
			r += App.UI.tabbar.makeTab("transfer", `<strong>${capFirstChar(facility.name)} is full and cannot hold any more slaves</strong>`);
		}
	}
	App.UI.tabbar.handlePreSelectedTab();

	return r;
};

/**
 * @returns {string}
 */
App.UI.SlaveList.listNGPSlaves = function() {
	const V = State.variables;
	const thisPassage = 'New Game Plus';
	let r = this.sortingLinks(thisPassage) + '
';

	r += '
' +
		App.UI.tabbar.tabButton('assign', 'Import a slave') +
		App.UI.tabbar.tabButton('remove', 'Remove from import') +
	'
';

	const NGPassignment = "be imported";
	/** @type {App.Entity.SlaveState[]} */
	const slaves = V.slaves;

	if (V.slavesToImport > 0) {
		const importedSlavesIndices = slaves.reduce((acc, s, i) => { if (s.assignment === NGPassignment) { acc.push(i); } return acc; }, []);
		SlaveSort.indices(importedSlavesIndices);
		r += App.UI.tabbar.makeTab("remove", App.UI.SlaveList.render(importedSlavesIndices, [],
			(s) => `<u><strong><span class="pink">${SlaveFullName(s)}</span></strong></u>`,
			(s, i) => App.UI.passageLink('Remove from import list', thisPassage,
				`$slavesToImport -= 1, removeJob(${App.Utils.slaveRefString(i)}, "${NGPassignment}")`)));
	} else {
		r += App.UI.tabbar.makeTab("remove", `<em>No slaves will go with you to the new game</em>`);
	}

	if (V.slavesToImport < V.slavesToImportMax) {
		const slavesToImportIndices = slaves.reduce((acc, s, i) => { if (s.assignment !== NGPassignment) { acc.push(i); } return acc; }, []);
		SlaveSort.indices(slavesToImportIndices);
		r += App.UI.tabbar.makeTab("assign", App.UI.SlaveList.render(slavesToImportIndices, [],
			(s) => `<u><strong><span class="pink">${SlaveFullName(s)}</span></strong></u>`,
			(s, i) => App.UI.passageLink('Add to import list', thisPassage,
				`$slavesToImport += 1, assignJob(${App.Utils.slaveRefString(i)}, "${NGPassignment}")`)));
	} else {
		r += App.UI.tabbar.makeTab("assign", `<strong>Slave import limit reached</strong>`);
	}

	App.UI.tabbar.handlePreSelectedTab();
	return r;
};

/**
 * Renders facility manager summary or a note with a link to select one
 * @param {App.Entity.Facilities.Facility} facility
 * @param {string} [selectionPassage] passage name for manager selection. "${Manager} Select" if omitted
 * @returns {string}
 */
App.UI.SlaveList.displayManager = function(facility, selectionPassage) {
	const managerCapName = capFirstChar(facility.desc.manager.position);
	selectionPassage = selectionPassage || `${managerCapName} Select`;
	const manager = facility.manager.currentEmployee;
	if (manager) {
		return this.render([App.Utils.slaveIndexForId(manager.ID)], [],
			App.UI.SlaveList.SlaveInteract.stdInteract,
			() => App.UI.passageLink(`Change or remove ${managerCapName}`, selectionPassage, ""));
	} else {
		return `You do not have a slave serving as a ${managerCapName}. ${App.UI.passageLink(`Appoint one`, selectionPassage, "")}`;
	}
};

/**
 * Displays standard facility page with manager and list of workers
 * @param {App.Entity.Facilities.Facility} facility
 * @param {boolean} [showTransfersPage]
 * @returns {string}
 */
App.UI.SlaveList.stdFacilityPage = function(facility, showTransfersPage) {
	return this.displayManager(facility) + '

' + this.listSJFacilitySlaves(facility, passage(), showTransfersPage);
};

App.UI.SlaveList.penthousePage = function() {
	const V = State.variables;
	const ph = App.Entity.facilities.penthouse;
	const listElementId = 'summarylist'; // for the untabbed mode only

	function span(text, cls, id) {
		return `<span${cls ? ` class="${cls}"` : ''}${id ? ` id="${id}"` : ''}>${text}</span>`;
	}

	function overviewTabContent() {
		let r = '';
		const thisArcology = V.arcologies[0];

		if (V.HeadGirl) {
			/** @type {App.Entity.SlaveState} */
			const HG = V.HeadGirl;
			r += `<strong><u>${span(SlaveFullName(HG), "pink")}</u></strong> is serving as your Head Girl`;
			if (thisArcology.FSEgyptianRevivalistLaw === 1) {
				r += ' and Consort';
			}
			r += `. <strong> ${span(App.UI.passageLink("Manage Head Girl", "HG Select"), null, "manageHG")}</strong>  ${span("[H]", "cyan")}`;
			r += App.UI.SlaveList.render([App.Utils.slaveIndexForId(HG.ID)], [],
				App.UI.SlaveList.SlaveInteract.penthouseInteract);
		} else {
			if (V.slaves.length > 1) {
				r += `You have ${span("not", "red")} selected a Head Girl`;
				if (thisArcology.FSEgyptianRevivalistLaw === 1) {
					r += ' and Consort';
				}
				r += `. <strong>${span(App.UI.passageLink("Select One", "HG Select"), null, "manageHG")}</strong> ${span("[H]", "cyan")}`;
			} else {
				r += 'You do not have enough slaves to keep a Head Girl';
			}
		}
		r += '
';

		if (V.Recruiter) {
			/** @type {App.Entity.SlaveState} */
			const RC = V.Recruiter;
			const p = getPronouns(RC);
			r += `<strong><u>${span(SlaveFullName(RC), "pink")}</u></strong> is working `;
			if (V.recruiterTarget !== "other arcologies") {
				r += 'to recruit girls';
			} else {
				r += 'as a Sexual Ambassador';
				if (thisArcology.influenceTarget === -1) {
					r += ', but ' + span(p.object + ' has no target to influence', "red");
				} else {
					const targetName = V.arcologies.find(a => a.direction === thisArcology.influenceTarget).name;
					r += ' to ' + targetName;
				}
			}
			r += `${span('. <strong>' + App.UI.passageLink("Manage Recruiter", "Recruiter Select") + '</strong>', null, "manageRecruiter")} ${span("[U]", "cyan")}`;
			r += App.UI.SlaveList.render([App.Utils.slaveIndexForId(RC.ID)], [],
				App.UI.SlaveList.SlaveInteract.penthouseInteract);
		} else {
			r += `You have ${span("not", "red")} selected a Recruiter. `;
			r += `${span('<strong>' + App.UI.passageLink("Select one", "Recruiter Select") + '</strong>', null, "manageRecruiter")} ${span("[U]", "cyan")}`;
		}

		if (V.dojo) {
			r += '
';
			/** @type {App.Entity.SlaveState} */
			const BG = V.Bodyguard;
			if (BG) {
				r += `<strong><u>${span(SlaveFullName(BG), "pink")}</u></strong> is serving as your bodyguard. `;
				r += span(`<strong>${App.UI.passageLink("Manage Bodyguard", "BG Select")}</strong>`, null, "manageBG") +
					span("[B]", "cyan");
				r += App.UI.SlaveList.render([App.Utils.slaveIndexForId(BG.ID)], [],
					App.UI.SlaveList.SlaveInteract.penthouseInteract);
			} else {
				r += `You have ${span("not", "red")} selected a Bodyguard. `;
				r += span(`<strong>${App.UI.passageLink("Select one", "BG Select")}</strong>`, null, "manageBG") +
					span("[B]", "cyan");
			}

			/* Start Italic event text */
			if (BG && BG.assignment === "guard you") {
				const p = getPronouns(BG);
				V.i = App.Utils.slaveIndexForId(BG.ID);
				const interactLinkSetters = `$activeSlave = $slaves[${V.i}], $nextButton = "Back", $nextLink = "AS Dump", $returnTo = "Main"`;
				r += '
';
				// <<= App.Interact.UseGuard($slaves[$i])>>//
				let useHimLinks = [];
				useHimLinks.push(App.UI.passageLink(`Use ${p.his} mouth`, "FLips", interactLinkSetters));
				useHimLinks.push(App.UI.passageLink(`Play with ${p.his} tits`, "FBoobs", interactLinkSetters));
				if (canDoVaginal(BG)) {
					useHimLinks.push(App.UI.passageLink(`Fuck ${p.him}`, "FVagina", interactLinkSetters));
					if (canDoAnal(BG)) {
						useHimLinks.push(App.UI.passageLink(`Use ${p.his} holes`, "FButt", interactLinkSetters));
					}
					if (BG.belly >= 300000) {
						useHimLinks.push(App.UI.passageLink(`Fuck ${p.him} over ${p.his} belly`, "FBellyFuck", interactLinkSetters));
					}
				}
				/* check */
				if (canPenetrate(BG)) {
					useHimLinks.push(App.UI.passageLink(`Ride ${p.him}`, "FDick", interactLinkSetters));
				}
				if (canDoAnal(BG)) {
					useHimLinks.push(App.UI.passageLink(`Fuck ${p.his} ass`, "FAnus", interactLinkSetters));
				}
				useHimLinks.push(App.UI.passageLink(`Abuse ${p.him}`, "Gameover", '$gameover ="idiot ball"'));

				r += `<br>    ${useHimLinks.join(' | ')}`;
				/* End Italic event text */
			}
			r += "
";
		}
		return r;
	}

	/**
	 * @param {string} job
	 * @returns {{n: number, text: string}}
	 */
	function _slavesForJob(job) {
		const employeesIndices = job === 'all' ? ph.employeesIndices() : ph.job(job).employeesIndices();
		if (employeesIndices.length === 0) { return {n: 0, text: ''}; }

		SlaveSort.indices(employeesIndices);
		return {
			n: employeesIndices.length,
			text: App.UI.SlaveList.render(employeesIndices, [], App.UI.SlaveList.SlaveInteract.penthouseInteract)
		};
	}

	/**
	 * Displays job filter links, whose action are generated by the callback
	 * @param {assignmentFilterGenerateCallback} callback
	 * @returns {string}
	 */
	function _jobFilter(callback) {
		const jd = App.Data.Facilities.penthouse.jobs;
		let links = [];
		links.push(`<<link "All">>${callback('all')}<</link>>`);
		// seems like SC2 does not process data-setter when data-passage is not set
		for (const jn in jd) {
			links.push(`<<link "${capFirstChar(jd[jn].position)}">>${callback(jn)}<</link>>`);
		}

		return links.join(' | ');
	}

	function _updateList(job) {
		State.temporary.mainPageUpdate.job = job;
		App.UI.replace('#' + listElementId, _slavesForJob(job).text);
	}

	/**
	 * @typedef tabDesc
	 * @property {string} tabName
	 * @property {string} caption
	 * @property {string} content
	 */

	/**
	 * @param {string} tabName
	 * @param {string} caption
	 * @param {string} content
	 * @returns {tabDesc}
	 */
	function makeTabDesc(tabName, caption, content) {
		return {
			tabName: tabName,
			caption: caption,
			content: content
		};
	}

	let r = '';

	if (V.positionMainLinks >= 0) {
		r += '' + App.UI.View.MainLinks() + '
';
	}

	if (V.sortSlavesMain) {
		r += '
' + this.sortingLinks("Main") + '
';
	}

	if (V.useSlaveSummaryTabs) {
		/** @type {tabDesc[]} */
		let tabs = [];

		if (V.useSlaveSummaryOverviewTab) {
			tabs.push(makeTabDesc('overview', 'Overview', overviewTabContent()));
		}

		for (const jn of ph.jobsNames) {
			const slaves = _slavesForJob(jn);
			if (slaves.n > 0) {
				tabs.push(makeTabDesc(jn, `${ph.desc.jobs[jn].position} (${slaves.n})`, slaves.text));
			}
		}

		// now generate the "All" tab
		const penthouseSlavesIndices = ph.employeesIndices();
		SlaveSort.indices(penthouseSlavesIndices);
		tabs.push(makeTabDesc('all', `All (${penthouseSlavesIndices.length})`,
			this.render(penthouseSlavesIndices, [], App.UI.SlaveList.SlaveInteract.penthouseInteract)));

		r += '
';
		for (const tab of tabs) {
			r += App.UI.tabbar.tabButton(tab.tabName, tab.caption);
		}
		r += '
';

		for (const tab of tabs) {
			r += App.UI.tabbar.makeTab(tab.tabName, tab.content);
		}
	} else {
		State.temporary.mainPageUpdate = {
			job: State.temporary.mainPageUpdate ? State.temporary.mainPageUpdate.job : 'all',
			update: _updateList
		};

		$(document).one(':passagedisplay', () => { _updateList(State.temporary.mainPageUpdate.job); });
		r += `<div>${_jobFilter(s => `<<run _mainPageUpdate.update("${s}")>>`)} <div id=${listElementId}></div></div>`;
	}

	if (V.positionMainLinks <= 0) {
		r += '
' + App.UI.View.MainLinks() + '';
	}

	App.UI.tabbar.handlePreSelectedTab();
	return r;
};

/**
 * @callback assignmentFilterGenerateCallback
 * @param {string} value
 * @returns {string}
 */

/**
 * @callback slaveFilterCallbackReasoned
 * @param {App.Entity.SlaveState} slave
 * @returns {string[]}
 */

 /**
 * @callback slaveFilterCallbackSimple
 * @param {App.Entity.SlaveState} slave
 * @returns {boolean}
 */

 /**
 * @callback slaveTestCallback
 * @param {App.Entity.SlaveState} slave
 * @returns {boolean}
 */

App.UI.SlaveList.slaveSelectionList = function() {
	const selectionElementId = "slaveSelectionList";

	return selection;

	/**
	 * @typedef ListOptions
	 * @property {slaveFilterCallbackReasoned|slaveFilterCallbackSimple} filter
	 * @property {slaveTestCallback} [expCheck]
	 * @property {slaveTextGenerator} interactionLink
	 * @property {slaveTextGenerator} [postNote]
	 */

	/**
	 * @param {slaveFilterCallbackReasoned|slaveFilterCallbackSimple} filter
	 * @param {slaveTextGenerator} interactionLink
	 * @param {slaveTestCallback} [experianceChecker]
	 * @param {slaveTextGenerator} [postNote]
	 * @returns {string}
	*/
	function selection(filter, interactionLink, experianceChecker, postNote) {
		if (experianceChecker === null) { experianceChecker = undefined; }
		State.temporary.slaveSelection = {
			filter: filter,
			expCheck: experianceChecker,
			interactionLink: interactionLink,
			postNote: postNote,
			update: _updateList
		};

		$(document).one(':passagedisplay', () => { _updateList('all'); });
		return `<div>${_assignmentFilter(s => `<<run _slaveSelection.update('${s}')>>`, experianceChecker !== undefined)} <div id=${selectionElementId}></div></div>`;
	}

	function _updateList(assignment) {
		App.UI.replace('#' + selectionElementId, _listSlaves(assignment, State.temporary.slaveSelection));
	}
	/**
	 * Displays assignment filter links, whose action are generated by the callback
	 * @param {assignmentFilterGenerateCallback} callback
	 * @param {boolean} includeExperienced
	 * @returns {string}
	 */
	function _assignmentFilter(callback, includeExperienced) {
		let filters = {
			all: "All"
		};
		let fNames = Object.keys(App.Entity.facilities);
		fNames.sort();
		for (const fn of fNames) {
			/** @type {App.Entity.Facilities.Facility} */
			const f = App.Entity.facilities[fn];
			if (f.established && f.hostedSlaves > 0) {
				filters[fn] = f.name;
			}
		}
		let links = [];
		/* seems like SC2 does not process data-setter when data-passage is not set
		for (const f in filters) {
			links.push(App.UI.passageLink(filters[f], passage, callback(f)));
		}
		if (includeExperienced) {
			links.push(`<span class="lime">${App.UI.passageLink('Experienced', passage, callback('experienced'))}</span>`);
		}*/
		for (const f in filters) {
			links.push(`<<link "${filters[f]}">>${callback(f)}<</link>>`);
		}
		if (includeExperienced) {
			links.push(`<span class="lime"><<link "Experienced">>${callback('experienced')}<</link>></span>`);
		}

		return links.join(' | ');
	}

	/**
	 *
	 * @param {string} assignmentStr
	 * @param {ListOptions} options
	 * @returns {string}
	 */
	function _listSlaves(assignmentStr, options) {
		/** @type {App.Entity.SlaveState[]} */
		const slaves = State.variables.slaves;
		let unfilteredIndices = [];
		switch (assignmentStr) {
			case 'all':
				unfilteredIndices = Array.from({length: slaves.length}, (v, i) => i);
				break;
			case 'experienced':
				unfilteredIndices = slaves.reduce((acc, s, idx) => {
					if (options.expCheck(s)) {
						acc.push(idx);
					}
					return acc;
				}, []);
				break;
			default:
				unfilteredIndices = App.Entity.facilities[assignmentStr].employeesIndices();
				break;
		}
		SlaveSort.indices(unfilteredIndices);
		let passingIndices = [];
		let rejects = [];

		unfilteredIndices.forEach(idx => {
			const fr = options.filter(slaves[idx]);
			if (fr === true || (Array.isArray(fr) && fr.length === 0)) {
				passingIndices.push(idx);
			} else {
				if (Array.isArray(fr)) { rejects.push({index: idx, rejects: fr}); }
			}
		});

		// clamsi fragment to create a function which combines results of two optional tests
		// done this way to test for tests presense only once
		const listPostNote = options.expCheck ?
			(options.postNote ?
				(s, i) => options.expCheck(s) ? 'Has applicable career experience.
' : '' + options.postNote(s, i) :
				(s) => options.expCheck(s) ? 'Has applicable career experience.' : '') :
			options.postNote ?
				(s, i) => options.postNote(s, i) :
				() => '';

		return App.UI.SlaveList.render(passingIndices, rejects, options.interactionLink, listPostNote);
	}
}();

/**
 * @param {App.Entity.Facilities.Facility} facility
 * @param {string} [passage] one of the *Workaround passages. Will be composed from the position name if omitted
 * @returns {string}
 */
App.UI.SlaveList.facilityManagerSelection = function(facility, passage) {
	passage = passage || capFirstChar(facility.manager.desc.position) + " Workaround";
	return this.slaveSelectionList(slave => facility.manager.canEmploy(slave),
		(slave, index) => App.UI.passageLink(SlaveFullName(slave), passage, `$i = ${index}`),
		slave => facility.manager.slaveHasExperience(slave));
};