Roll20 uses cookies to improve your experience on our site. Cookies enable you to enjoy certain features, social sharing functionality, and tailor message and display ads to your interests on our site and others. They also help us understand how our site is being used. By continuing to use our site, you consent to our use of cookies. Update your cookie preferences .
×
Create a free account

Random Name Generator

1490498728

Edited 1490585400
Paul S.
Sheet Author
API Scripter
EDIT : So, I guess this should now be called the Random Name, Town Name, Tavern Name Generator . But, that title is too long. It now has 9 nationalities for names (both male & female - African, Arabic, Asian, English, Germanic[Ancient], Hindi, Medieval, Sanskrit, Thai)... thousands of names (at least 100 for each nationality if I remember correctly). !namegen [language] [gender] (gender is optional) It has place names from 6 geographic regions (African[South Africa, Nigeria, Ghana, Ethiopia, Egypt], Arabic, Asian, Dwarf[German], Elf[Czech], Indian) ... &gt;1000 geographic place names (at least 100 for each geographic region). !towngen [location] It has over 700 Tavern/Inn names ... !taverngen I've given the output some style so it looks visually pleasing. Hopefully you like it. &nbsp;Over the next little while I will push updates regularly as I add more nationalities/geographic regions. &nbsp;The link to the github below should work - let me know if it doesn't. NEXT Update will add male/female native american names...&nbsp; END EDIT . Hey all, So, I wanted an in-game random name generator. &nbsp;So I built one. At first I used trigraphs built from real names...&nbsp; This yielded ... less than optimal results with randomly piecing together the trigraphs.... So then I said ... the world is full of cool languages that have cool names.... So I downloaded them. &nbsp;Ok, not ALL of them... just male and female common names for the following: Arabic, English, Medieval, Hindi, Sanskrit, Thai. That gives me THOUSANDS of names. &nbsp;THOUSANDS. &nbsp;(copying/reformatting/copying again/reformatting again .... all made easy with Excel and Word... if you want to know how, I can share my secrets). Here's the github link (hopefully it works for you all) ...&nbsp; <a href="https://github.com/happywanderer/namegen/tree/mast" rel="nofollow">https://github.com/happywanderer/namegen/tree/mast</a>... Oh - and the macro to make this work super easy is: !namegen ?{Gender|boy|girl} ?{Nationality|arabic|english|hindi|medieval|sanskrit|thai} I will update it in the future to add some more nationalities... African, Chinese, and Japanese are next on the list - look for that tomorrow or the next day. OHHHH - and I am a complete java hack (meaning I think of something I want to do, and look up how to write the code. &nbsp;I don't actually know java/js)... Soooo - if you can help me figure a way to pull a truly random name from multiple arrays that'd be groovy (meaning run through all the boy nationalities instead of just one). &nbsp;Also - is there a cleaner method for this than a separate function for each? &nbsp;Curious because I know efficient coding = good coding.
1490501025
Kirsty
Pro
Sheet Author
I can't wait to try this one out! Thank you for sharing it!
First off, you'd be better off having a single event handler, and parsing the arguments. You can use the split function to do that. e.g.: var args = msg.content.split(" "); if (args[0] != "!namegen") { return; } var boygirl = args[1]; var culture = args[2]; Then you can use the 'boygirl' and 'culture' variables to decide which list of names to use. To see how to do that, you might find it useful to take a look at a name generator I wrote a couple of weeks ago: <a href="https://github.com/samuelpenn/rpg/blob/master/roll20/scripts/PfNames/PfNames.js" rel="nofollow">https://github.com/samuelpenn/rpg/blob/master/roll20/scripts/PfNames/PfNames.js</a> It's a bit more complex, in that it assumes Pathfinder character sheets are being used, reads the race and gender from the token's character sheet values, and automatically determines which list of names to use, then automatically sets the names of the selected tokens. It also tries to ensure it doesn't ever use a duplicate name. For tokens which don't have a recognised race/gender (e.g., monsters), it just appends #1, #2 etc to the current token name. You may want to look at the bit at the end though, where the structures are used to store the names in a way that's easier to reference.
1490538525
Paul S.
Sheet Author
API Scripter
Thanks Samuel, I'll take a look at that - so basically a bunch of nested Ifs... If (boygirl == 'boy') { &nbsp;if (culture == 'arabic') { &nbsp; &nbsp;rando generator &nbsp;} &nbsp;elseif (etc etc etc) .... I don't want this to be tied to character sheets. &nbsp;I want it as agnostic as possible so that all systems can use it. &nbsp;However, applying the name to a targeted token as an option might be worth trying to do.
1490542338

Edited 1490542755
The Aaron
Pro
API Scripter
Nesting a bunch of ifs would work, but you could make a minor change and get a bit more bang for your buck. Much of programming is really about structuring data. &nbsp;I'd probably suggest going with a structure more like this (actual names left out for brevity): &nbsp; &nbsp; var names = { &nbsp; &nbsp; &nbsp; &nbsp; english: { &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; boy: [], &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; girl: [] &nbsp; &nbsp; &nbsp; &nbsp; }, &nbsp; &nbsp; &nbsp; &nbsp; german: { &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; boy: [], &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; girl: [] &nbsp; &nbsp; &nbsp; &nbsp; }, &nbsp; &nbsp; &nbsp; &nbsp; medieval: { &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; boy: [], &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; girl: [] &nbsp; &nbsp; &nbsp; &nbsp; } &nbsp; &nbsp; }; This makes it easy to do several nice things. &nbsp;Your logic can then operate off of the properties of the names object and its contained objects through introspection. &nbsp;That allows you to validate language choices, provide feedback about what are valid choices, etc. &nbsp;It also makes it pretty easy to add more choices without having to edit the logic. &nbsp;I'd probably restructure your code like this: ;(function(){ &nbsp; &nbsp; "use strict"; &nbsp; &nbsp; var names = { &nbsp; &nbsp; &nbsp; &nbsp; english: { &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; boy: ['bob','sam'], &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; girl: ['nancy','sue'] &nbsp; &nbsp; &nbsp; &nbsp; }, &nbsp; &nbsp; &nbsp; &nbsp; german: { &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; boy: ['hanz','fritz'], &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; girl: ['helga','hannah'] &nbsp; &nbsp; &nbsp; &nbsp; }, &nbsp; &nbsp; &nbsp; &nbsp; medieval: { &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; boy: ['geoffrey','richard'], &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; girl: ['isabella','joan'] &nbsp; &nbsp; &nbsp; &nbsp; } &nbsp; &nbsp; }; &nbsp; &nbsp; on('chat:message',function(msg){ &nbsp; &nbsp; &nbsp; &nbsp; if('api' !== msg.type){ &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; return; &nbsp; &nbsp; &nbsp; &nbsp; } &nbsp; &nbsp; &nbsp; &nbsp; let cmds = msg.content.split(/\s+/), &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; who = (getObj('player',msg.playerid)||{get:()=&gt;'API'}).get('_displayname'); &nbsp; &nbsp; &nbsp; &nbsp; if( '!namegen' === cmds.shift()){ &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; if(cmds.length) { &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; let language=(cmds.shift()||'').toLowerCase(); &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; if(_.has(names,language)){ &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; let boygirl = (cmds.shift()||'').toLowerCase(); &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; boygirl = _.has(names[language],boygirl) ? boygirl : _.sample(_.keys(names[language])); &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; sendChat('',`/w "${who}" Name is ${_.sample(names[language][boygirl])}`); &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; } else { &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; sendChat('',`/w "${who}" No language &lt;b&gt;${language}&lt;/b&gt;. &nbsp;Available options are: &lt;b&gt;${_.keys(names).join(', ')}&lt;/b&gt;`); &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; } &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; } else { &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; sendChat('',`/w "${who}"&lt;div&gt;Usage: &lt;br&gt;&lt;code&gt;!namegen [language] [boy|girl]&lt;/code&gt;&lt;br&gt;Specifying boy or girl is optional. Available language options are: &lt;b&gt;${_.keys(names).join(', ')}&lt;/b&gt;`); &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; } &nbsp; &nbsp; &nbsp; &nbsp; } &nbsp; &nbsp; }); }()); I changed the order of your parameters to !namegen [language] [boy|girl], as that makes it easy to leave boy|girl off and randomly choose between the two. &nbsp;I'm making heavy use of Underscore.js, which is a very useful library that's bundled in the API: _.has() -- checks to see if a given key is a property on an object. _.sample() -- randomly chooses one entry from an array. _.keys() -- returns an array of all the properties on an object. Walking the above, I've enclosed it in an anonymous function that is immediately called. &nbsp;This is called an IIFE (Immediately-Invoked Function Expression), which you can read more about on Google. &nbsp;It creates a Closure, basically a container for your functionality which prevents it from being in the global namespace, a pretty good practice. &nbsp;Placing the string "use strict" in a scrope holds your code to higher standards and will warn you about certain coding practices that are out of vogue (for good reason!). Next is the data structure I mentioned at the top. &nbsp;Each of the properties is the name of a language, which lets you pull a list of supported languages with _.keys(names) or check for support for a language with _.has(names, language). &nbsp;Each language property holds an object with boy and girl properties for the names in that language. &nbsp;Adding another language becomes very easy, you just add the additional data to the structure. It registers a single chat event handler which exists for non-api messages. &nbsp; It splits msg.content on any sequence of 1 or more spaces or tabs (/\s+/ is a regular expression, if you want to Google those. &nbsp;\s means whitespace, + means 1 or more). &nbsp;Doing it this way means you don't get strange behavior if someone accidentally hits two spaces between arguments. &nbsp;cmds ends up being an array of each argument, so "!namegen english boy" would result in ['!namegen','english','boy'].&nbsp; The who variable will contain the name of the player running the command, or 'API' if it wasn't a player. Now to the processing. &nbsp;cmds.shift() will remove the first value from the cmds array and return it. &nbsp;It is then compared to '!namegen' to see if this is a command for your program. &nbsp;You should always use === and !== instead of == and != until you understand the difference (and then you'll know there's pretty much never a reason to use == and !=). &nbsp;The nice thing about removing the entry with .shift() instead of just referencing it with cmds[0] is that it simplifies later work. &nbsp;For the example from before, the cmds array will now be ['english','boy']. &nbsp;If they just typed !namegen, it would be [], so checking if there are enough arguments is as simple as checking if there is a positive length with if(cmds.length). &nbsp;If there aren't any more arguments, we drop down to an else case that tells them how to use the script and what the available languages are with _.keys() (introspection for the win!). Next we grab the language argument with cmds.shift() and convert it to lowercase (in case they typed German or GERMAN). Then check it's a language that is supported with _.has(). &nbsp;If it isn't, we tell them we don't have the language they typed (showing what they said allows them to spot misspellings, like 'midevil') and list the available languages with _.keys() again. Now we can grab the boy/girl argument and lowercase it. &nbsp;Next we check if it's one of the keys in the language (this lets you later add things like 'place', or 'emotion' or 'neutral' without changing the logic!). &nbsp;If it isn't one of the specified keys, (or is empty) we use _.sample() to grab one at random. &nbsp;You could split this out and only use sample if they didn't specify one and give an error otherwise. &nbsp;That can be an exercise to the reader. =D Finally, with all the arguments validated and collected, we return the random name with _.sample(names[language][boygirl]). One last note on the sendChat() calls I'm making. &nbsp;Take special note of the type of quotes, the "backtick": ` These are new in Javascript ES2015, they're called template literals. &nbsp;The practical upshot of them is you can embed variables within template literals using the ${ } syntax. &nbsp;You can also embed function calls, as I've done. &nbsp;You can read more about them on Google. They are super handy, but easy to miss when comparing ` to '. Hope that's helpful to you! &nbsp;Happy Rolling!
1490544924
Paul S.
Sheet Author
API Scripter
Ok Aaron, that all makes sense I think. &nbsp;I will test it today with reformatted coding. I'm also adding functionality to generate Town/City names and Inn/Tavern names... because I can.
Seems multiple people doing this sort of thing various ways.&nbsp; The Markov script in the one-click install API's - according to the documentation - can work off of data in journal handouts.&nbsp; Logically this is a great way of dong it as individual GM's can choose their own name lists.
1490547571
Paul S.
Sheet Author
API Scripter
Ok Aaron, got it working with the names.. Now going to add the towns/inns & taverns ... Huge thanks...It is much more elegant that way. Only thing I had to do different was use double-quotes inside the boy:/girl: arrays instead of single-quotes... This was due to having some names with apostrophes that got treated as breaks. (if that makes sense in my non-coder speak). @Jim This is my attempt at a more "universal" name generator for various game systems/settings. &nbsp;Also - Markov chains are only as good as their base digraphs or trigraphs and the logic used to combine the digraphs/trigraphs (not having 4 or 5 vowels or consonants in a row is important). &nbsp; As I said, I attempted the Markov chain approach but found it too limited. &nbsp;So - instead, there are enough "fantasy" names in existence using names from other languages... Thai is great for elves for example. &nbsp;Medieval - well ... are good for humans. &nbsp;I'm going to add Slavic/Germanic for Dwarves.. etc... Oh - and I'm also adding Klingon ... because ....&nbsp;
So no value in holding the name lists in documents rather than in the code?
1490554348

Edited 1490554707
Paul S.
Sheet Author
API Scripter
Ok everyone - I just overhauled the script to reflect The Aaron's and Samuel's tips/help. &nbsp; <a href="https://github.com/happywanderer/namegen/blob/mast" rel="nofollow">https://github.com/happywanderer/namegen/blob/mast</a>... The script now generates: 1) Names based on gender/culture (or completely random) !namegen [language] [gender] 2) Town/City names based on location (currently have Asian, Arabic, Dwarf (really German), and Elf (really Czech)). !towngen [location] 3) Tavern Names - just a large (700+!!!) random pull !taverngen I will be adding extra name cultures (African, Chinese, etc...) as well as extra Town/City names based on geographic region (India, Africa, etc...) I might make it "Pretty" with some formatting stuff... maybe. &nbsp; @Jim, no - this script doesn't store anything in local sheets... if a DM wants to add specific location/name lists (like Klingon for example), they'd have to go into the API. &nbsp;But with 1000's of names & locations ... This tool is just meant to give DM's a quick - "Oh crap I need an NPC name" tool for on-the-fly improv... Or it can be used for campaign pre-planning.&nbsp; Also - if someone has a CSV or excel of Elf, Dwarf, Halfling, etc... (basically race-specific fantasy) names ... I'd be more than happy to add those specific race-specific fantasy names... a pool of 100+ is good enough for on-the-fly random generation (in my opinion). &nbsp;
1490554936

Edited 1490555006
Paul S.
Sheet Author
API Scripter
Can't figure out how to embed the code here for easy copy/paste... Tips?
1490556216

Edited 1490556239
Paul S. said: Can't figure out how to embed the code here for easy copy/paste... Tips? Use github? attach a txt doc?
Paul S. said: Can't figure out how to embed the code here for easy copy/paste... Tips? If you select the Paragraph button when you type a post, one of the options is "code". &nbsp; Text entered there looks like this. Use that option for easy copy/paste.
1490576031
Paul S.
Sheet Author
API Scripter
@Three of Swords Thanks! So - I added African, Germanic, and Asian names and African and Indian place names. &nbsp;The Germanic names are fun (ancient germanic)
1495577575

Edited 1495577609
Richard T.
Pro
Marketplace Creator
Sheet Author
Compendium Curator
Saw your script in the script library, were you planning on adding command syntax in the description?&nbsp; Also, what are "Medieval" names?&nbsp;
1495639511
Paul S.
Sheet Author
API Scripter
Medieval names are just that - medieval...names taken from historical lists of names used in medieval times....