function getRandomInteger(min, max) { return Math.floor(Math.random() * (max - min + 1)) + min; } function getRandomFloat(min, max) { return Math.random() * (max - min + 1) + min; } function getRandom(seed) { var x = Math.sin(seed) * 10000 return x - Math.floor(x) } function shuffle(array, seed) { let currentIndex = array.length while (currentIndex != 0) { let randomIndex = Math.floor(getRandom(seed + currentIndex) * currentIndex) currentIndex-- [array[currentIndex], array[randomIndex]] = [ array[randomIndex], array[currentIndex]] } } function pointDistance(x1, y1, x2, y2) { return Math.sqrt(Math.pow(x1 - x2, 2) + Math.pow(y1 - y2, 2)) } function rotate(cx, cy, x, y, angle) { var radians = (Math.PI / 180) * angle var cos = Math.cos(radians) var sin = Math.sin(radians) var nx = (cos * (x - cx)) + (sin * (y - cy)) + cx var ny = (cos * (y - cy)) - (sin * (x - cx)) + cy return [nx, ny]; } function createLocation(x, y, name) { x = Math.round(x) y = Math.round(y) var existingLocationIndex = state.locations.findIndex(element => element.name.toLowerCase() == name.toLowerCase()) var location if (existingLocationIndex == -1) { location = { x: x, y: y, name: name } state.locations.push(location) } else { location = state.locations[existingLocationIndex] location.x = x location.y = y location.name = name } addStoryCard(location.name, "", "location") return location } function sanitizeText(text) { if (/^\s*>.*says? ".*/.test(text)) { text = text.replace(/^\s*>\s/, "") text = text.replace(/says? "/, "") text = text.replace(/"\n$/, "") } else if (/^\s*>\s.*/.test(text)) { text = text.replace(/^\s*>\s/, "") text = text.replace(/\.?\n$/, "") } return text } function getCharacterName(rawText) { var matches = rawText.match(/(?<=\s+> ).*(?=(\s+#)|( says? "))/) if (matches != null && matches[0].trim() != "") { return matches[0].trim() } matches = rawText.match(/.*(?= #)/) if (matches != null && matches[0].trim() != "") { return matches[0].trim() } return null } function getPossessiveName(name) { var possesiveName = "Your" if (name != "You") { possesiveName = name if (name.endsWith("s")) possesiveName += "'" else possesiveName += "'s" } return possesiveName } function getCommandName(command) { var args = getArguments(command) if (args.length == 0) return null return args[0] } const argumentPattern = /("[^"\\]*(?:\\[\S\s][^"\\]*)*"|'[^'\\]*(?:\\[\S\s][^'\\]*)*'|\/[^\/\\]*(?:\\[\S\s][^\/\\]*)*\/[gimy]*(?=\s|$)|(?:\\\s|\S)+)/g function getArguments(command) { var matches = command.match(new RegExp(argumentPattern)) var returnValue = [] matches.forEach(match => { match = match.replaceAll(/(^")|("$)/g, "").replaceAll(/\\"/g, '"') returnValue.push(match) }) return returnValue } function getArgument(command, index) { var args = getArguments(command) index++ if (index >= args.length) return null return args[index] } function getArgumentRemainder(command, index) { var counter = 0 const pattern = new RegExp(argumentPattern) while ((match = pattern.exec(command)) != null) { if (counter++ == index + 1) { var result = command.substring(match.index) if (/^".*"$/g.test(result)) result = result.replace(/^"/, "").replace(/"$/, "") return result.replaceAll(/\\"/g, '"') } } } function searchArgument(command, pattern) { var index = searchArgumentIndex(command, pattern) if (index == -1) return null return getArgument(command, index) } function searchArgumentIndex(command, pattern) { var args = getArguments(command) if (args.length <= 1) return -1 args.splice(0, 1) const search = (element) => pattern.test(element) var index = args.findIndex(search) if (index != -1) return index return -1 } function arrayToOrPattern(array) { var pattern = "^" array.forEach(element => { pattern += `(${element})|` }) pattern += pattern.substring(0, pattern.length - 1) pattern += "$" return new RegExp(pattern, "gi") } function statsToOrPattern(stats) { var array = [] stats.forEach(element => { array.push(element.name) }) return arrayToOrPattern(array) } function getDice(rolltext) { var matches = rolltext.match(/\d+(?=d)/) if (matches != null) { return matches[0] } return 1 } function getSides(rolltext) { var matches = rolltext.match(/(?<=d)\d+/) if (matches != null) { return matches[0] } return 20 } function formatRoll(text) { var matches = text.match(/(?<=.*)\d*d\d+(?=.*)/) if (matches != null) { return matches[0] } matches = text.match(/\d+/) if (matches != null) { return "d" + matches[0] } return "d20" } function calculateRoll(rolltext) { rolltext = rolltext.toLowerCase() var dice = getDice(rolltext) var sides = getSides(rolltext) var score = 0; for (i = 0; i < dice; i++) { score += getRandomInteger(1, sides) } return score } function getCharacter(characterName) { if (characterName == null) characterName = state.characterName if (characterName == null) return null return state.characters.find(element => element.name.toLowerCase() == characterName.toLowerCase()) } function hasCharacter(characterName) { return getCharacter(characterName) != null } function createCharacter(name) { var existingCharacter = getCharacter(name) if (existingCharacter != null) { existingCharacter.name = name existingCharacter.className = "adventurer" existingCharacter.summary = "An auto generated character. Use #create to create this character" existingCharacter.inventory = [] existingCharacter.spells = [] existingCharacter.stats = [] existingCharacter.spellStat = null existingCharacter.meleeStat = null existingCharacter.rangedStat = null existingCharacter.skills = [] existingCharacter.experience = 0 existingCharacter.health = 10 return existingCharacter } var character = { name: name, className: "adventurer", summary: "An auto generated character. Use #create to create this character", inventory: [], spells: [], stats: [], spellStat: null, meleeStat: null, rangedStat: null, skills: [], experience: 0, health: 10 } state.characters.push(character) return character } function copyCharacter(fromCharacter, toCharacter) { if (toCharacter != null && fromCharacter != null) { toCharacter.className = fromCharacter.className toCharacter.summary = fromCharacter.summary toCharacter.inventory = [...new Set(fromCharacter.inventory)] toCharacter.spells = [...new Set(fromCharacter.spells)] toCharacter.stats = [...new Set(fromCharacter.stats)] toCharacter.spellStat = fromCharacter.spellStat toCharacter.meleeStat = fromCharacter.meleeStat toCharacter.rangedStat = fromCharacter.rangedStat toCharacter.skills = [...new Set(fromCharacter.skills)] toCharacter.experience = fromCharacter.experience toCharacter.health = fromCharacter.health return toCharacter } } function deleteCharacter(name) { var index = state.characters.findIndex((element) => element.name == name) state.characters.splice(index, 1) } const levelSplits = [0, 300, 900, 2700, 6500, 14000, 23000, 34000, 48000, 64000, 85000, 100000, 120000, 140000, 165000, 195000, 225000, 265000, 305000, 355000] function getLevel(experience) { if (experience < 0) experience = 0 var level for (level = 0; level < levelSplits.length; level++) { if (experience < levelSplits[level]) break } return level } function getNextLevelXp(experience) { if (experience < 0) experience = 0 var level for (level = 0; level < levelSplits.length; level++) { if (experience < levelSplits[level]) return levelSplits[level] } return -1 } function addXpToAll(experience) { if (experience == 0) return "" var leveledUp = `\n[The party has gained ${experience} experience!]` state.characters.forEach(x => { var haveWord = x.name == "You" ? "have" : "has" const oldLevel = getLevel(x.experience) x.experience += experience const newLevel = getLevel(x.experience) if (newLevel > oldLevel) leveledUp += `\n[${x.name} ${haveWord} leveled up to ${newLevel}!]` }) return leveledUp } function getHealthMax(character) { if (character == null) character = getCharacter() var modifier = 0 var stat = character.stats.find((element) => element.name.toLowerCase() == "constitution") if (stat != null) modifier = getModifier(stat.value) var level = getLevel(character.experience) return 10 + level * (6 + modifier) } function getModifier(statValue) { return Math.floor((statValue - 10) / 2) } function findSpellCardIndex(name) { return storyCards.findIndex((element) => element.type == "spell" && element.keys == name) } String.prototype.replaceAt = function(index, replacement) { return this.substring(0, index) + replacement + this.substring(index + replacement.length); } String.prototype.plural = function(revert) { var plural = { '(quiz)$' : "$1zes", '^(ox)$' : "$1en", '([m|l])ouse$' : "$1ice", '(matr|vert|ind)ix|ex$' : "$1ices", '(x|ch|ss|sh)$' : "$1es", '([^aeiouy]|qu)y$' : "$1ies", '(hive)$' : "$1s", '(?:([^f])fe|([lr])f)$' : "$1$2ves", '(shea|lea|loa|thie)f$' : "$1ves", 'sis$' : "ses", '([ti])um$' : "$1a", '(tomat|potat|ech|her|vet)o$': "$1oes", '(bu)s$' : "$1ses", '(alias)$' : "$1es", '(octop)us$' : "$1i", '(ax|test)is$' : "$1es", '(us)$' : "$1es", '([^s]+)$' : "$1s" }; var singular = { '(quiz)zes$' : "$1", '(matr)ices$' : "$1ix", '(vert|ind)ices$' : "$1ex", '^(ox)en$' : "$1", '(alias)es$' : "$1", '(octop|vir)i$' : "$1us", '(cris|ax|test)es$' : "$1is", '(shoe)s$' : "$1", '(o)es$' : "$1", '(bus)es$' : "$1", '([m|l])ice$' : "$1ouse", '(x|ch|ss|sh)es$' : "$1", '(m)ovies$' : "$1ovie", '(s)eries$' : "$1eries", '([^aeiouy]|qu)ies$' : "$1y", '([lr])ves$' : "$1f", '(tive)s$' : "$1", '(hive)s$' : "$1", '(li|wi|kni)ves$' : "$1fe", '(shea|loa|lea|thie)ves$': "$1f", '(^analy)ses$' : "$1sis", '((a)naly|(b)a|(d)iagno|(p)arenthe|(p)rogno|(s)ynop|(t)he)ses$': "$1$2sis", '([ti])a$' : "$1um", '(n)ews$' : "$1ews", '(h|bl)ouses$' : "$1ouse", '(corpse)s$' : "$1", '(us)es$' : "$1", 's$' : "" }; var irregular = { 'move' : 'moves', 'foot' : 'feet', 'goose' : 'geese', 'sex' : 'sexes', 'child' : 'children', 'man' : 'men', 'tooth' : 'teeth', 'person' : 'people', 'woman' : 'women', }; var uncountable = [ 'sheep', 'fish', 'deer', 'moose', 'series', 'species', 'money', 'rice', 'information', 'equipment', 'gold', 'bass', 'milk', 'food', 'water', 'bread', 'sugar', 'tea', 'cheese', 'coffee', 'currency', 'seafood', 'oil', 'software' ]; // save some time in the case that singular and plural are the same if(uncountable.indexOf(this.toLowerCase()) >= 0) return this; // check for irregular forms for(word in irregular){ if(revert){ var pattern = new RegExp(irregular[word]+'$', 'i'); var replace = word; } else{ var pattern = new RegExp(word+'$', 'i'); var replace = irregular[word]; } if(pattern.test(this)) return this.replace(pattern, replace); } if(revert) var array = singular; else var array = plural; // check for matches using regular expressions for(reg in array){ var pattern = new RegExp(reg, 'i'); if(pattern.test(this)) return this.replace(pattern, array[reg]); } return this; } function clamp(num, min, max) { return num <= min ? min : num >= max ? max : num } function toTitleCase(str) { return str.replace( /\w\S*/g, text => text.charAt(0).toUpperCase() + text.substring(1).toLowerCase() ); } function stripPunctuation(str) { return str.replaceAll(/((\.)|(!))\s*$/g, "") } var fantasyFemaleNames = ["Luna", "Kayla", "Serenity", "Eira", "Mirah", "Elowen", "Keira", "Calantha", "Natalia", "Eirlys", "Freya", "Ophelia", "Piper", "Alethea", "Melara", "Seraphina", "Delilah", "Lorna", "Echo", "Bree", "Daniella", "Branwen", "Matilda", "Eve", "Brynhild", "Ithilda", "Belinda", "Catarina", "Jora", "Zelda", "Thalia", "Rowan", "Aurora", "Coral", "Vivian", "Briella", "Elvina", "Lylah", "Mirastral", "Nadira", "Marcella", "Kestrel", "Avis", "Laura", "Vesper", "Lucilla", "Sabine", "Evelyn", "Kalinda", "Celeste", "Lilith", "Wren", "Jasmine", "Ondine", "Gabriella", "Astrid", "Elise", "Helena", "Nova", "Lyndal", "Zara", "Niamh", "Vynessa", "Erin", "Lyriel", "Dracaena", "Lila", "Brynna", "Zephyr", "Kira", "Ava", "Elinor", "Carmilla", "Isabella", "Ariana", "Rhianna", "Sylvie", "Kymberley", "Hazel", "Lirien", "Bridget", "Lyra", "Galatea", "Nadine", "Alethia", "Larissa", "Sariel", "Theodora", "Gwynneth", "Eleanor", "Odessa", "Meryll", "Sophia", "Kaia", "Brynhilda", "Haven", "Eluned", "Selene", "Bryony", "Ciara"] var fantasyMaleNames = ["Alexander", "Thane", "Gabriel", "Orion", "Grayson", "Cedric", "Sebastian", "Arin", "Liam", "Byerson", "Julian", "Zaneth", "Kel", "Eramon", "Ashfur", "Tristam", "Leonidas", "Ryzlen", "Caspian", "Jarron", "Eudicles", "Tarquin", "Terrence", "Ereth", "Thayon", "Braxton", "Twilight", "Argent", "Whisper", "Daemon", "Victor", "Blackthorn", "Dawnrunner", "Gareth", "Caelum", "Zephyr", "Brennan", "Theo", "Draco", "Cian", "Valoric", "Skye", "Sunfor", "Damon", "Maverick", "Bryson", "Lumo", "Drakken", "Ewen", "Waverley", "Lachlan", "Atlas", "Arden", "Ryker", "Asterion", "Bryon", "Judson", "Griffith", "Logan", "Ethan", "Darius", "Brodeth", "Cassius", "Eamon", "Rowan", "Paxton", "Michael", "Dommon", "Aragorn", "Bastier", "Maximus", "Kenrick", "Jasper", "Lucien", "Bryce", "Ryder", "Damian", "Daxton", "Brantley", "Griffin", "Xander", "Galen", "Brody", "Erek", "Drake", "Thayer", "Kieran", "Heath", "Raeleus", "Alistair", "Bastian", "Asher", "Ronan", "Zane", "Jaxon", "Ambrose", "Malcolm", "Axel", "Ehtan", "Avery", "Kael", "Riley"] var scifiFemaleNames = ["Jala", "Clea", "Jocosa", "Artemis", "Serafina", "Sevyn", "Tesla", "Lux", "Nine", "Kiara", "Valentina", "Morticia", "Rio", "Xyleena", "Libby", "Valkyrie", "Panika", "Lara", "Fenglina", "Makiko", "Katja", "Paige", "Elie", "Lucie", "Samanta", "Hazel", "Helena", "Leia", "Luminara", "Katan", "Vala", "Inara", "Saffron", "Zoe", "Jayne", "Kaylee", "Maeve", "Kara", "Athena", "Cally", "Anastasia", "Pegi", "Alita", "Alkhema", "Arcena", "Ko", "Bodika", "Candi", "Chi", "Rae", "Cylla", "Daria", "Chalma", "Elita", "Eryx", "Eva", "Nova", "Celeste", "Guri", "Hexen", "Indigo", "Juli", "Katana", "Talia", "Lala", "Mika", "Miranda", "Nebula", "Six", "Sasha", "Silica", "Sky", "Strika", "Terra", "Yori", "Andromeda", "Astra", "Bellatrix", "Callista", "Cosima", "Delphine", "Electra", "Phantasy", "Farrah", "Geneva", "Haven", "Jade", "Juno", "Lillix", "Lynx", "Nya", "Oria", "Parris", "Priya", "Rue", "Clarity", "Bloom", "Decca", "Domonique", "Grazi", "Helvetica", "Cadence"] var scifiMaleNames = ["Ares", "Astro", "Macro", "Cadmus", "Cyno", "Fade", "Hack", "Hax", "Indigo", "Hinge", "Jarno", "Jax", "Knox", "Link", "Maxx", "Merrick", "Miles", "Mirari", "Niko", "Nano", "Oberon", "Onyx", "Orion", "Osso", "Paradox", "Pip", "Phoenix", "Radius", "Rexx", "Razlin", "Reznor", "Rian", "Roscoe", "Ryker", "Rush", "Riden", "Drake", "Frost", "Cassian", "Neyo", "Maverick", "Azriel", "Auryn", "Daggar", "Evyn", "Jace", "Jaron", "Loki", "Oren", "Ridley", "Sagan", "Silas","Solon", "Stellan", "Sorrel", "Seth", "Theron", "Zen", "Klay", "Blaze", "Xander", "Mace", "Dozer", "Eno", "Tip", "Ray", "Genesis", "Galac", "Eclipse", "Zev", "Zaid", "Wilder", "Sol", "Jupiter", "Mars", "Star", "Cosmo", "Aster", "Lazer", "Zeno", "Sirius", "Azra", "Atom", "Teague", "Rigel", "Cato", "Zhane", "Ace", "Rocket", "Kip", "Meter", "Starbuck", "Roman", "Fiat", "Kyron", "Nyx", "Rune", "Nero", "Quantum", "Nym", "Morphius", "Striker", "Bridger"] var modernFemaleNames = ["Olivia", "Emma", "Amelia", "Ella", "Isabella", "Mia", "Valerie", "Eliana", "Charlotte", "Mila", "Aria", "Luna", "Harper", "Grace", "Zoey", "Jemma", "Priscilla", "Scarlett", "Hazel", "Ellie", "Naya", "Nila", "Tamia", "Cecilia", "Arianna", "Abigail", "Riley", "Autumn", "Maya", "Madelyn", "Maria", "Melody", "Sophia", "Ava", "Luz", "Eleanor", "Ivy", "Freya", "Alice", "Violet", "Clara", "Daphne", "Evelyn", "Nora", "Lucy", "Poppy", "Rose", "Chloe", "Phoebe", "Elsie", "Cordelia", "Willow", "Daisy", "Thea", "Adeline", "Arabella", "Maisie", "Lola", "Olive", "Sienna", "Sierra", "Elena", "Sadie", "Sophie", "Julia", "Alexandra", "Jane", "Mira", "Talia", "Zara", "Vera", "Amara", "Cynthia", "Hannah", "Aurora", "Anya", "Erin", "Felicity", "Juno", "Yelena", "Naomi", "Caroline", "Miriam", "Veronica", "Molly", "June", "Nina", "Piper", "Helena", "Amari", "Everly", "Bonnie", "Alina", "Emilia", "Harriet", "Isabel", "Sofia", "Kayla", "Lena", "Megan", "Diana"] var modernMaleNames = ["Jackson", "Aiden", "Charles", "Adam", "Christopher", "Daniel", "Liam", "Oliver", "Mateo", "Henry", "Lucas", "William", "Theodore", "Noah", "John", "Arnold", "Norman", "Ralph", "Virgil", "Will", "Sam", "Luca", "David", "Joseph", "Mason", "Luke", "Matthew", "Dylan", "Jacob", "Isaac", "Anthony", "Carter", "Caleb", "Cooper", "Josiah", "Nolan", "Cameron", "Nathan", "Josh", "Angel", "Andrew", "Aaron", "Ian", "Eli", "Ryan", "Everett", "Enzo", "Parker", "Jeremiah", "Landon", "Jordan", "Austin", "Jameson", "Myles", "Dominic", "Nicholas", "Kayden", "Hunter", "Harrison", "Milo", "Arthur", "Ryder", "Archer", "Luis", "George", "Evan", "Carlos", "Juan", "Jason", "Leon", "Calvin", "Ivan", "Cole", "Chase", "Dean", "Jayce", "Olliver", "Alan", "Jesus", "Charlie", "Tyler", "Elliot", "Kevin", "Ayden", "Felix", "Tate", "Jesse", "Brody", "Tucker", "Peter", "Joel", "Edward", "Oscar", "Victor", "Brandon", "Bruce", "Abel", "Richard", "Riley", "Patrick", "Eric", "Elian", "Louis"] var nordicFemaleNames = ["Freya", "Dagny", "Ingrid", "Froya", "Elin", "Solveig", "Maja", "Sol", "Linnea", "Vilde", "Var", "Aldis", "Alfrida", "Alfsol", "Alva", "Alvdis", "Alvida", "Andora", "Anveig", "Asa", "Astri", "Astrid", "Bolette", "Brynhild", "Disa", "Eir", "Eira", "Eidis", "Elevine", "Elfi", "Embla", "Erna", "Freja", "Frida", "Fredrikke", "Gerda", "Gry", "Gurina", "Gurine", "Gyda", "Haddy", "Halgerd", "Helga", "Helje", "Helle", "Herdis", "Herfrid", "Hilde", "Hulda", "Inga", "Idun", "Isfrid", "Iverna", "Iverine", "Jorgina", "Kari", "Lagertha", "Liv", "Livunn", "Malfrid", "Malmfrid", "Nanna", "Oda", "Odel", "Odine", "Olava", "Runa", "Ragnfrid", "Randi", "Ragnhild", "Saga", "Sif", "Sigrid", "Siv", "Solvei", "Soma", "Svanild", "Thora", "Tora", "Thurid", "Torveig", "Torfrid", "Trude", "Tyra", "Tyri", "Udna", "Unni", "Una", "Unnlaug", "Unnveig", "Valdine", "Vedis", "Valborg", "Vivil", "Ylva", "Yngva", "Thoril", "Thorine", "Sigfrida", "Sigun", "Sigvor", "Signe", "Reidunn"] var nordicMaleNames = ["Erik", "Bjorn", "Lars", "Asmund", "Harald", "Arne", "Odin", "Ivar", "Leif", "Aesir", "Axel", "Aren", "Aric", "Balder", "Birger", "Bjarke", "Bjarne", "Nils", "Steig", "Erling", "Espen", "Fenrir", "Frey", "Einar", "Garald", "Anders", "Gunnar", "Hagan", "Halfthor", "Halfdan", "Kjell", "Hanne", "Ingvar", "Helge", "Herleif", "Jarl", "Joran", "Magnus", "Norrell", "Njord", "Olaf", "Osman", "Ragnar", "Sigurd", "Steffen", "Sten", "Sven", "Tor", "Torben", "Troels", "Tyr", "Tyrell", "Ulf", "Viggo", "Vali", "Vidar", "Volund", "Wayde", "Waddell", "Alviss", "Anneli", "Stig", "Eino", "Haakon", "Haldor", "Iver", "Sindri", "Trym", "Varg", "Alf", "Amund", "Arn", "Arnstein", "Arvid", "Bjarni", "Bjoern", "Bragi", "Brede", "Dag", "Dagfinn", "Egil", "Endre", "Erlend", "Even", "Finn", "Flosi", "Fredrik", "Frode", "Freyr", "Geir", "Gisli", "Grim", "Gudbrand", "Gustav", "Hakan", "Hakon", "Hans", "Helgi", "Ingolf", "Jomar", "Knut", "Orm"] function generateName(genre, male) { if (genre.toLowerCase() == "fantasy") { if (male) { if (state.fantasyMaleIndex == null || state.fantasyMaleIndex >= fantasyMaleNames.length) { state.fantasyMaleIndex = 0 state.fantasyMaleSeed = getRandomInteger(1, 1000) } shuffle(fantasyMaleNames, state.fantasyMaleSeed) return fantasyMaleNames[state.fantasyMaleIndex++] } else { if (state.fantasyFemaleIndex == null || state.fantasyFemaleIndex >= fantasyFemaleNames.length) { state.fantasyFemaleIndex = 0 state.fantasyFemaleSeed = getRandomInteger(1, 1000) } shuffle(fantasyFemaleNames, state.fantasyFemaleSeed) return fantasyFemaleNames[state.fantasyFemaleIndex++] } } else if (genre.toLowerCase() == "modern") { if (male) { if (state.modernMaleIndex == null || state.modernMaleIndex >= modernMaleNames.length) { state.modernMaleIndex = 0 state.modernMaleSeed = getRandomInteger(1, 1000) } shuffle(modernMaleNames, state.modernMaleSeed) return modernMaleNames[state.modernMaleIndex++] } else { if (state.modernFemaleIndex == null || state.modernFemaleIndex >= modernFemaleNames.length) { state.modernFemaleIndex = 0 state.modernFemaleSeed = getRandomInteger(1, 1000) } shuffle(modernFemaleNames, state.modernFemaleSeed) return modernFemaleNames[state.modernFemaleIndex++] } } else if (genre.toLowerCase() == "scifi") { if (male) { if (state.scifiMaleIndex == null || state.scifiMaleIndex >= scifiMaleNames.length) { state.scifiMaleIndex = 0 state.scifiMaleSeed = getRandomInteger(1, 1000) } shuffle(scifiMaleNames, state.scifiMaleSeed) return scifiMaleNames[state.scifiMaleIndex++] } else { if (state.scifiFemaleIndex == null || state.scifiFemaleIndex >= scifiFemaleNames.length) { state.scifiFemaleIndex = 0 state.scifiFemaleSeed = getRandomInteger(1, 1000) } shuffle(scifiFemaleNames, state.scifiFemaleSeed) return scifiFemaleNames[state.scifiFemaleIndex++] } } else if (genre.toLowerCase() == "nordic") { if (male) { if (state.nordicMaleIndex == null || state.nordicMaleIndex >= nordicMaleNames.length) { state.nordicMaleIndex = 0 state.nordicMaleSeed = getRandomInteger(1, 1000) } shuffle(nordicMaleNames, state.nordicMaleSeed) return nordicMaleNames[state.nordicMaleIndex++] } else { if (state.nordicFemaleIndex == null || state.nordicFemaleIndex >= nordicFemaleNames.length) { state.nordicFemaleIndex = 0 state.nordicFemaleSeed = getRandomInteger(1, 1000) } shuffle(nordicFemaleNames, state.nordicFemaleSeed) return nordicFemaleNames[state.nordicFemaleIndex++] } } }