first commit
This commit is contained in:
commit
2dd6129cef
3
.gitignore
vendored
Normal file
3
.gitignore
vendored
Normal file
@ -0,0 +1,3 @@
|
||||
*.sublime-workspace
|
||||
*.sublime-project
|
||||
*.log
|
287
README.rst
Normal file
287
README.rst
Normal file
@ -0,0 +1,287 @@
|
||||
LuaNameGen - Lua Name Generator v1.0.0
|
||||
=======================================
|
||||
|
||||
|
||||
Inspiration
|
||||
------------
|
||||
|
||||
|
||||
Code
|
||||
*****
|
||||
|
||||
This script is heavily inspired by `libtcod's namegen`_, written by Dominik "Mingos" Marczuk.
|
||||
|
||||
.. _`libtcod's namegen`: https://bitbucket.org/libtcod/libtcod/src/afba13253a79f16d10f596e2c9c99cf183f94b3c/src/namegen_c.c
|
||||
|
||||
|
||||
Names
|
||||
******
|
||||
|
||||
*Some of the appeal of imaginative literature comes from the exotic worlds and characters it conjures up. One way it distances itself from the everyday world is by using unfamiliar and evocative names. If the characters are Sally, Bill, and Fred, you are rooted in the mundane. If they are Hyssome, Drythe, and Rimsall, you are obviously beyond the fields we know, and the stage is set for wonders. The same applies to role-playing games using imaginative settings.*
|
||||
Gary Gygax (Gary Gygax's Extraordinary Book of Names)
|
||||
|
||||
The patterns that ship with this script here are based on:
|
||||
|
||||
* `libtcod's namegen existing sets`, written by Mingos and Jice;
|
||||
* Gary Gygax's Extraordinary Book of Names suggestions for fantastic names;
|
||||
* `fantasynamegenerators.com`_;
|
||||
* `fantasynamegen.com`_;
|
||||
* `creative-role-playing.com`_ fantasy-sounding-names;
|
||||
|
||||
.. _`fantasynamegenerators.com`: https://fantasynamegenerators.com/
|
||||
.. _`fantasynamegen.com`: https://www.fantasynamegen.com/
|
||||
.. _`creative-role-playing.com`: http://web.archive.org/web/20141009095317/https://www.creative-role-playing.com/fantasy-sounding-names/
|
||||
|
||||
|
||||
Basic usage
|
||||
------------
|
||||
|
||||
To get a dwarf name and surname, using default sets, just do
|
||||
|
||||
.. code-block:: lua
|
||||
|
||||
local namegen = require("namegen")
|
||||
|
||||
local name = namegen.generate("dwarf male") -- Dolin
|
||||
local surname = namegen.generate("dwarf surname") -- Steelcutter
|
||||
|
||||
|
||||
How does it works?
|
||||
-------------------
|
||||
|
||||
When loaded/required, the module "namegen" parses the set files pointed by 'namegen.index' (a plain text file).
|
||||
Each set file (also plain text files) follows a simple syntax (libtcod's syntax, so any .cfg file from it can be used), and may contains multiple sets. This is an example of a basic set:
|
||||
|
||||
.. code-block:: none
|
||||
|
||||
name "dwarf male" {
|
||||
syllablesStart = "Do, Due"
|
||||
syllablesEnd = "lin, rin"
|
||||
rules = "$s$e"
|
||||
}
|
||||
|
||||
Sample generated names
|
||||
-----------------------
|
||||
|
||||
This is a list of a few names genereated by the default sets:
|
||||
|
||||
|
||||
|
||||
* "doughty dwarf female"
|
||||
|
||||
"Baldis", "Baldis", "Bornlind", "Bornnis", "Brimdis", "Brimlind", "Brodvis", "Brokkdis", "Brombis", "Bruhild", "Burlna", "Burrun", "Burrun", "Burvis", "Dahild", "Danis", "Dorlis", "Drimrith", "Dromlind", "Dromrun", "Durmlind", "Fromdis", "Frorda", "Fundga", "Fundris", "Gimdis", "Gonddis", "Gormda", "Gormda", "Grodda", "Hordna", "Nadis", "Navis", "Nordrun", "Ormda", "Skonddis", "Skondlind", "Stromvis", "Sturis", "Sturlda", "Sturlhild", "Sturlif", "Sturlis", "Sundrith", "Thornlis", "Thrada", "Throdis", "Throllif", "Throrlis", "Thunddis"
|
||||
|
||||
|
||||
* "doughty dwarf male"
|
||||
|
||||
"Baldin", "Balir", "Ballin", "Bornin", "Bornli", "Brimdin", "Brimli", "Brodrur", "Bruvi", "Burlin", "Burrin", "Dali", "Dalin", "Dorvor", "Dralin", "Dralror", "Durdin", "Durmir", "Durnli", "Fundrin", "Gloir", "Gormri", "Gradri", "Grimvi", "Grodrur", "Grodrur", "Gromdin", "Gromri", "Gromvir", "Guldin", "Guldri", "Gurin", "Hordnir", "Hordrok", "Nali", "Nordri", "Ormri", "Skandbor", "Skandnir", "Skondin", "Sturllin", "Sturlri", "Thornin", "Thornnir", "Thornvor", "Throllin", "Throlrur", "Thrubor", "Thrurror", "Thundrok"
|
||||
|
||||
|
||||
* "dragon female"
|
||||
|
||||
"Adastraborossa", "Adracalchaxis", "Adraneriaxis", "Aragcalchaxis", "Archocalchaxis", "Atrabazia", "Atramandrossa", "Baravoraxis", "Bhakribradaxis", "Biamanthysa", "Biazzebraxis", "Bradophylaxis", "Branaluxis", "Chrysocordaxis", "Glaunaluxis", "Harbazia", "Hurocordaxis", "Jazramalaxis", "Jazrazzemalis", "Jurgabazia", "Jurgamalaxis", "Keruxaneriaxis", "Keruxavorunga", "Kralkavorunga", "Marmalaxis", "Marmorazzemalis", "Marvoraxis", "Melkarneriaxis", "Orgracalchaxis", "Orgracordaxis", "Phorolagonis", "Phorovoraxis", "Pyrabazia", "Pyramalaxis", "Rauzzebraxis", "Rauzzemalis", "Rhadacalchaxis", "Rhemanthysa", "Rhodophylaxis", "Sarbradaxis", "Sarcunaluxis", "Sardacordaxis", "Scarvalagonis", "Scarvamordaxis", "Sulchrunadralix", "Trochoneriaxis", "Zalarborossa", "Zalarmandrossa", "Zerulcalchaxis", "Zerulcalchaxis"
|
||||
|
||||
|
||||
* "dragon male"
|
||||
|
||||
"Abramanthys", "Abravorung", "Adastrazzebrax", "Adastrazzemal", "Adracalchax", "Ancaboros", "Ancaboros", "Ancacordax", "Andralagon", "Aragphylax", "Archomanthys", "Archonalux", "Archovorax", "Archozuthrax", "Barcordax", "Beruzzemal", "Bhakriboros", "Bhakribradax", "Bhakriphylax", "Biamordax", "Biazzemal", "Brimabazius", "Glaunadral", "Glauzuthrax", "Jalanzzebrax", "Jarzemxenor", "Jazranalux", "Jazravorax", "Majurinadral", "Majurizzebrax", "Malachonadral", "Malachoxenor", "Malachozzebrax", "Marboros", "Orgrazuthrax", "Peridonalux", "Phorocalchax", "Phrixumalax", "Pyramandros", "Rhodomandros", "Rhodomanthys", "Scarvabradax", "Skhiaphylax", "Sulchruzuthrax", "Tchalcedonalux", "Tchazarbazius", "Tchazarmordax", "Trochonalux", "Trochozzebrax", "Zalarcalchax"
|
||||
|
||||
|
||||
* "dwarf female"
|
||||
|
||||
"Abra", "Alba", "Alden", "Atha", "Banryn", "Bina", "Boghild", "Boghild", "Bomtha", "Darhild", "Dedi", "Difra", "Diiess", "Diya", "Dogra", "Dora", "Duema", "Duerali", "Dunda", "Edsyl", "Farihild", "Farika", "Flosen", "Frelaani", "Fukala", "Gabida", "Grodmila", "Gwarev", "Inmae", "Jegna", "Kalona", "Kanka", "Kitu", "Manda", "Meya", "Nadeth", "Nalla", "Odrun", "Oev", "Rasmala", "Rasnuda", "Rasov", "Rinka", "Roiess", "Telev", "Telryn", "Thonta", "Toriess", "Zanuda", "Zeshan"
|
||||
|
||||
|
||||
* "dwarf male"
|
||||
|
||||
"Balbek", "Banderel", "Bomni", "Bondir", "Brutram", "Catomir", "Dandrum", "Darrin", "Dhozolir", "Dolin", "Dueni", "Dwatri", "Falri", "Falvil", "Fimil", "Firil", "Fithur", "Fremil", "Gaden", "Garbur", "Gimvri", "Glotri", "Gomran", "Groril", "Hotdram", "Ibrin", "Ibvi", "Jorran", "Jorun", "Kani", "Karin", "Kavim", "Kivil", "Krob", "Loni", "Lurin", "Ragthran", "Rasri", "Renden", "Svun", "Tathur", "Telvi", "Thimur", "Thovil", "Velkias", "Viros", "Vonchar", "Vonthur", "Werfri", "Werin"
|
||||
|
||||
|
||||
* "dwarf surname"
|
||||
|
||||
"Bear-Executioner", "Bearbane", "Blackhead", "Bronzeaxe", "Bronzecarver", "Bronzehead", "Bronzesmith", "Coalbender", "Coalheart", "Coalheart", "Dragonbutcher", "Dragonchoker", "Ettinchoker", "Fieryfist", "Foe-Battler", "Giant-Garrotter", "Gnome-Beheader", "Goldbreaker", "Goldenhammer", "Granitecarver", "Granitedigger", "Graniteforger", "Graniteminer", "Greymace", "Hammercrusher", "Hardfist", "Ironhammer", "Ironsmasher", "Marblecrusher", "Metalclub", "Metalfist", "Mithrildigger", "Moonpike", "Noblefoot", "Oakshield", "Orc-Executioner", "Orc-Strangler", "Orcslicer", "Redfinger", "Steelfoot", "Stonedigger", "Stonefinger", "Stonesmasher", "Stronghand", "Strongspike", "Strongsword", "Thunderminer", "Wolfbutcher", "Wolfkicker", "Wyvernsmasher"
|
||||
|
||||
|
||||
* "elf female"
|
||||
|
||||
"Alaglossa", "Alaglossa", "Alaglossa", "Alea", "Alea", "Alyndra", "Alyndra", "Alyndra", "Axilya", "Caerthynna", "Caerthynna", "Caerthynna", "Cyithrel", "Cyithrel", "Cyithrel", "Cyithrel", "Cyithrel", "Darunia", "Deularla", "Elasha", "Elasha", "Eloimaya", "Eloimaya", "Esyae", "Falenas", "Faraine", "Gaylia", "Haera", "Isilynor", "Iythronel", "Kethryllia", "Lura", "Lymsleia", "Lymsleia", "Lyra", "Nyna", "Phyrra", "Pyria", "Pyria", "Shadowmoon", "Shandalar", "Sheedra", "Teryani", "Tsarra", "Tsarra", "Urmicca", "Urmicca", "Vestele", "Viansola", "Yaereene"
|
||||
|
||||
|
||||
* "elf male"
|
||||
|
||||
"Ailluin", "Aiwin", "Alabyran", "Almon", "Alosrin", "Anfalen", "Anlyth", "Anlyth", "Aywin", "Cluhurach", "Felaern", "Folmar", "Folmon", "Goras", "Inialos", "Josidiah", "Josidiah", "Khatar", "Kiirion", "Kolvar", "Maeral", "Maiele", "Maiele", "Melandrach", "Melandrach", "Molostroi", "Morthil", "Myrddin", "Mythanthar", "Nremyn", "Nremyn", "Oenel", "Oenel", "Olaurae", "Orist", "Phraan", "Rhys", "Rhys", "Rilitar", "Rilitar", "Riluaneth", "Shaundyl", "Theodred", "Theodred", "Triandal", "Vander", "Vesstan", "Vulmon", "Vulmon", "Xhalth"
|
||||
|
||||
|
||||
* "empyreal female"
|
||||
|
||||
"Alanteleth", "Alantes", "Amaneleth", "Amarset", "Ansamet", "Araneleth", "Asaneth", "Asarnel", "Asarnenth", "Atarenth", "Avareth", "Avraler", "Avraleseth", "Avraleth", "Jal-ravan", "Jaranenth", "Jasarmenth", "Kalasten", "Katarnes", "Kavalen", "Paladeseth", "Palanteth", "Ranaleseth", "Ranaleseth", "Ranarer", "Rasanet", "Ravaneleth", "Ravanen", "Samarenth", "Sar-alant", "Saranereth", "Saranes", "Saraneseth", "Saraten", "Sarnatenth", "Solarenth", "Solarer", "Talaneth", "Talareth", "Talasel", "Tar-aran", "Taranenth", "Taranes", "Valareth", "Valareth", "Valmaret", "Valnoreth", "Valorenth", "Vanaren", "Var-kalad"
|
||||
|
||||
|
||||
* "empyreal male"
|
||||
|
||||
"Adrastathal", "Alantan", "Alantas", "Amadathal", "Amanath", "Amarsal", "Amartat", "Ar-ravan", "Aradan", "Aradanth", "Aradath", "Aramath", "Aranat", "Aranath", "Asanar", "Asanat", "Astarath", "Atarathar", "Avralath", "Jasalath", "Kal-jasal", "Kaladath", "Kalasathal", "Katarnathar", "Kavalathal", "Klaronath", "Palantar", "Palantas", "Paloranth", "Ral-vardar", "Ranalan", "Ranarath", "Rasanas", "Rasanath", "Ravanas", "Samaranth", "Saranathas", "Sardanathas", "Solaranth", "Tal-kalar", "Talaras", "Talonathas", "Tavalan", "Valkaran", "Valkaranth", "Valmaras", "Valnarath", "Vanarathas", "Varamath", "Voltarathar"
|
||||
|
||||
|
||||
* "fair noble elf female"
|
||||
|
||||
"Aegmindadril", "Aegraelthalel", "Aegserenien", "Aelthaloliel", "Aermarolsil", "Aethsilenedel", "Anmelevwë", "Arnimesedel", "Arseldaledel", "Bersaramril", "Caelmindthalriel", "Caelmitholeth", "Caelthirthalien", "Caersilmthalrien", "Caertheloliel", "Callithedrial", "Calmarerroël", "Calnimemrian", "Calninthaliel", "Celsarilrian", "Cirlarevian", "Cirraelirriel", "Earlithanien", "Elrinevril", "Elthaeladsil", "Elthmeledeth", "Eolsaerasroël", "Ermelthaledel", "Faerimadiel", "Faersaradsil", "Feannitholwë", "Findrindthalloth", "Findsaeredwen", "Findthaerirriel", "Galmelebriel", "Galmiradrian", "Galnimthalwen", "Ganralarel", "Garsaerelriel", "Gellorelrial", "Gelrilemrian", "Gilranesrien", "Ilmnithebel", "Ithnithanian", "Laegmelthonroël", "Laegrindarriel", "Lendmaegarwen", "Lendsarirrial", "Lendtheliniel", "Lendthiranrial"
|
||||
|
||||
|
||||
* "fair noble elf male"
|
||||
|
||||
"Aelmithenrod", "Aelthaerelion", "Aesmarthallas", "Aethseldedion", "Anistildan", "Arnimevros", "Arranebdir", "Arrimalad", "Belsaerendel", "Belseldthalros", "Belthaledrior", "Bermaegesion", "Bermindaror", "Caelseredlad", "Caelthaerevdil", "Caerlithilion", "Caermithadion", "Caertherirlad", "Calrimaslad", "Calthaeladnar", "Caristaslas", "Celranirion", "Celsilendil", "Cirlirelros", "Cirnirthalrod", "Clarinthonthir", "Crissilebion", "Earnithasdir", "Elbninarfal", "Elbninarlas", "Estlirevad", "Faerinadnar", "Faerliremad", "Findsilmasdil", "Finmindarrod", "Finraneddan", "Galiremdil", "Galmindinrond", "Garranasad", "Gilinthaldel", "Gilmirandan", "Gilnithanrior", "Gilralenrior", "Gilranthalrior", "Ilmmelalfal", "Ilmrimindel", "Ithsilmebras", "Laegrindeldil", "Laegtheradrior", "Lindnithenorn"
|
||||
|
||||
|
||||
* "giant female"
|
||||
|
||||
"Daoh-Giree", "Daoh-Lugh", "Daoh-Peh", "DaohGhad", "DaohMoghahgquagi", "DaohShom", "DaohShul", "DaohYeeh", "Dhaktih", "Doh-Ghad", "Doh-Mehbohr", "Doh-Shlo", "DohShlo", "Fah-Shlo", "FahGhah", "FahKhem", "Ghamrei", "Gireefah", "Gunri-Lah", "Hatoo-Rei", "Hatoo-Tih", "Lah-Naoh", "LahHoo", "Mih-Pogh", "MihGunrifeehm", "MihPuhguh", "MihWuh", "Nuh-Fah", "Pogh-Doh", "Pugh-Doh", "Rahoosoh", "Rei-Hah", "Rei-Snaoh", "ReiIgwah", "Rifoolah", "Snaohdaoh", "Soh-Khan", "SohAhg", "SohNaoh", "SohRahoo", "SohShourronkh", "Tih-Zhamchah", "TihMaoh", "TihSnaoh", "TihYaum", "Tuhlithomtih", "Ub-Daoh", "Ushsoh", "Yaumchahdaoh", "Yaumsoh"
|
||||
|
||||
|
||||
* "giant male"
|
||||
|
||||
"Bul-Gunri", "Chah", "Ehm-Gonkh", "Ghat", "Ghaw-Peh", "Ghee", "Ghee-Thom", "Giree", "Goun", "Goush-Faogh", "Gunri", "Hani-Hoo", "Haogh-Gunri", "Hatoobaod", "Hoo", "Khan", "Khan", "Khankham", "Khaznaroo", "Khee", "Khee-Shehi", "Lugh", "Maoh-Shul", "Meh-Baod", "Mogh-Hah", "Moghquagi", "Mouh", "Mugh", "Naoh", "Nuh", "Orf-Zham", "Oughbul", "Ouh", "Ouh-Wuh", "Ouhlugh", "Peh", "Pogh-Khaz", "Puh", "Rahoo-Maoh", "Rhoo-Shom", "Rhoofeehm", "Ronkh-Peh", "Saomehm", "Shom-Faogh", "Suth", "Thom", "Tregh", "Ub", "Ubghat", "Wahhah"
|
||||
|
||||
|
||||
* "gnome female"
|
||||
|
||||
"Banus", "Billeklinkle", "Bimkiulo", "Bimrgo", "Bipflonk", "Byloflink", "Byloflink", "Cargus", "Carvizz", "Dibink", "Dimbick", "Dimbick", "Dimbick", "Dindamink", "Dindamink", "Dinkulo", "Ditink", "Ditink", "Dosizz", "Fenflynk", "Fenyvizzle", "Filgus", "Fynkkink", "Gelulo", "Gelulo", "Glinbynus", "Glinbynus", "Gynnoago", "Juladink", "Katdomink", "Ketklinkle", "Ketris", "Kitlelinkey", "Liskink", "Liskink", "Lokeefizzy", "Lymtink", "Lymtink", "Lysthink", "Merdiwack", "Nittlebik", "Tallinkey", "Tallinkey", "Tallinkey", "Tannus", "Thinbythin", "Thinkkeesizzle", "Thinkkeesizzle", "Tilkink", "Tilkitinkle"
|
||||
|
||||
|
||||
* "gnome male"
|
||||
|
||||
"Baolink", "Bawack", "Bilkeefinkle", "Bimleeble", "Bimliarn", "Binaris", "Binkflonk", "Binklbus", "Binklbus", "Binwick", "Binwick", "Bolink", "Bonkbus", "Bonleble", "Bonleble", "Buris", "Burtink", "Carlobrick", "Diledus", "Dinkbitank", "Dobeeble", "Dobeeble", "Dobeeble", "Dodibrick", "Donkleedink", "Fenklink", "Fenklink", "Fenlflonk", "Finflonk", "Finkvash", "Gelklink", "Gelsizz", "Gelsizz", "Gimlulo", "Hinbmink", "Hinklosizz", "Hinklosizz", "Laflink", "Nitago", "Nitkeeklonk", "Nitkeeklonk", "Tenkathink", "Tenlink", "Tenlink", "Tenlink", "Thenflink", "Tockawick", "Tockawick", "Tovash", "Tovash"
|
||||
|
||||
|
||||
* "gnome surname"
|
||||
|
||||
"Acerpipe", "Berryspindle", "Berryspinner", "Blackbus", "Blackbus", "Castfizzle", "Clickgear", "Clickgear", "Clickspring", "Coggauge", "Draxlepipe", "Fastspring", "Finecrank", "Finefizzle", "Finesteel", "Finesteel", "Fizzleblast", "Fizzlepipe", "Gearwizzle", "Grindspan", "Mechaspan", "Mechasteel", "Mekkakettle", "Mekkakettle", "Puddlehouse", "Puddlehouse", "Puddlepipe", "Puddlespinner", "Sadbus", "Shortwhistle", "Spannerblast", "Spannerblast", "Sparkspanner", "Sparkspanner", "Sparkwhistle", "Springgear", "Sprygrinder", "Steamgauge", "Steamnozzle", "Steamnozzle", "Stormgrinder", "Stormgrinder", "Stormtorque", "Stormwizzle", "Swiftdwadle", "Swiftnozzle", "Tinkcrank", "Tinkmaster", "Twistcrank", "Wobblecrank"
|
||||
|
||||
|
||||
* "goblin female"
|
||||
|
||||
"Achgukgah", "Achshukah", "Adznazah", "Azakay", "Azsnigy", "Bilgyigy", "Blokbolgy", "Bloksniknigay", "Bolgdrikya", "Bugkrigay", "Burkblidya", "Drizkrigay", "Drizzizgah", "Dufbalgay", "Fluggaah", "Gadgaty", "Gahblidy", "Gakyipgah", "Gazbloty", "Ghagirkah", "Gitblokya", "Gliggligay", "Glokazy", "Glokspikay", "Guknazghy", "Higroky", "Kakflugghy", "Khadgadya", "Khadmazah", "Krigligy", "Maknagah", "Nadgazlakay", "Nadrokay", "Niggazghy", "Ragkhady", "Shrigadzya", "Shriggargah", "Shukglizay", "Skragyaggy", "Skugratya", "Snabligah", "Snatnokya", "Sniggatgah", "Snikshukay", "Togsnikghy", "Yagglikkay", "Yarpgarghy", "Yigslaigah", "Yiproky", "Zibkrigay"
|
||||
|
||||
|
||||
* "goblin male"
|
||||
|
||||
"Achzat", "Adzglat", "Adzgnat", "Blidglag", "Blidgrat", "Blidloz", "Bloknok", "Burkguk", "Burksnat", "Drikyip", "Drikzit", "Dufslog", "Flugsnat", "Gadduf", "Gadloznogg", "Gagblok", "Gakyig", "Glakglat", "Gligsnik", "Gogzib", "Higvark", "Khadach", "Krigirk", "Mizyad", "Nigsnit", "Nikkglag", "Ragglak", "Ragyark", "Ratsna", "Rokblid", "Rokgrat", "Shukmaz", "Skugslai", "Snatgar", "Snigglag", "Snignikk", "Spikzit", "Toggatgak", "Togloz", "Tognigsnig", "Togyarp", "Urfmak", "Urfmak", "Varknazgah", "Yarksog", "Yarpgad", "Yigga", "Yiggah", "Yipsnat", "Zizbolg"
|
||||
|
||||
|
||||
* "halfling female"
|
||||
|
||||
"Allison", "Alpaide", "Alyssa", "Amanda", "Amaranth", "Amber", "Bave", "Bave", "Berenga", "Bertha", "Camelia", "Camelia", "Cheryl", "Chrodechildis", "Diamond", "Engelberga", "Erica", "Erica", "Esmee", "Esmee", "Fatima", "Gudula", "Gudula", "Jenna", "Kaitlyn", "Kunegund", "Kunegund", "Leesha", "Leesha", "Luitgarde", "Marcatrude", "Marcatrude", "Marigold", "Mary", "Melissa", "Moira", "Moira", "Myrna", "Myrtle", "Pervinca", "Rotrudis", "Saffron", "Savanna", "Selina", "Shelby", "Tabitha", "Tasha", "Theoderada", "Theodrada", "Vulfegundis"
|
||||
|
||||
|
||||
* "halfling male"
|
||||
|
||||
"Aega", "Arnoul", "Arnoul", "Balbo", "Basso", "Bero", "Bilba", "Bilbo", "Bildad", "Blanco", "Bucca", "Clodio", "Drogon", "Enurchus", "Erard", "Faro", "Fastred", "Giseler", "Giseler", "Grossman", "Guntram", "Guntramn", "Heribert", "Hildibrand", "Lo", "Lotho", "Madoc", "Majorian", "Majorian", "Marachar", "Mauger", "Melampus", "Merimac", "Ragnfred", "Rathar", "Rathar", "Rathar", "Rathar", "Sadoc", "Taurin", "Thankmar", "Togo", "Togo", "Unroch", "Waldolanus", "Waltgaud", "Waltgaud", "Waltgaud", "Waltgaud", "Willibrord"
|
||||
|
||||
|
||||
* "halfling surname"
|
||||
|
||||
"Bolger-Baggins", "Brandagamba", "Brandybuck", "Brandybuck", "Brown", "Brown", "Brown", "Brownlock", "Burrowes", "Elvellon", "Featherbottom", "Fleetfoot", "Gammidge", "Gammidge", "Gluttonbelly", "Gluttonbelly", "Gluttonbelly", "Goodbody", "Goodbody", "Goold", "Greenhill", "Greenhill", "Hairyfoot", "Harfoot", "Hayward", "Heathertoes", "Heathertoes", "Heathertoes", "Hornblower", "Hornblower", "Hornwood", "Labingi", "Labingi", "Longfoot", "Lothran", "Lothran", "Oldbuck", "Proudfoot", "Proudfoot", "Proudmead", "Sandyman", "Smallburrow", "Took-Brandybuck", "Townsend", "Townsend", "Twofoot", "Twofoot", "Underlake", "Undertree", "Zaragamba"
|
||||
|
||||
|
||||
* "homely halfling female"
|
||||
|
||||
"Adelia", "Adina", "Adrice", "Adrwisa", "Albina", "Bandwisa", "Bardwisa", "Bena", "Biffia", "Biffia", "Bildia", "Bildice", "Bomba", "Bombina", "Brama", "Droca", "Droca", "Drocice", "Durla", "Ernwina", "Everwina", "Falca", "Falca", "Falcina", "Ferdily", "Gamwisa", "Haldia", "Hascia", "Hoda", "Hoda", "Hodwina", "Hodwisa", "Huga", "Huga", "Ivia", "Ivia", "Ivia", "Markwina", "Mungily", "Oda", "Oda", "Sabwisa", "Sama", "Samice", "Samina", "Sega", "Wanwisa", "Wiga", "Wyda", "Wyda"
|
||||
|
||||
|
||||
* "homely halfling male"
|
||||
|
||||
"Adelert", "Adelwin", "Adert", "Adro", "Ailwise", "Almert", "Ambard", "Bandfast", "Bandfast", "Bandold", "Bardo", "Benfast", "Biffo", "Biffwin", "Bildold", "Blanco", "Bombo", "Bungo", "Bungo", "Drogo", "Durlald", "Durlwin", "Erdo", "Erno", "Ernwise", "Falco", "Ferdard", "Ferdard", "Ferdo", "Frobwin", "Fulbo", "Gamo", "Haldard", "Haldert", "Haldfast", "Hasco", "Hasco", "Hodert", "Hodo", "Hugo", "Ivard", "Ivwise", "Milard", "Milo", "Milo", "Odo", "Othert", "Sabo", "Wano", "Wydald"
|
||||
|
||||
|
||||
* "human female"
|
||||
|
||||
"Adinor", "Adissra", "Aelfsig", "Aethelbeald", "Aethelmaer", "Aethelraed", "Bealdhere", "Beranweald", "Betomina", "Cwenburg", "Cynein", "Demelza", "Deorburg", "Deorsige", "Eadflaed", "Eadstan", "Ealdmaer", "Ealdrun", "Ealdson", "Frithbeald", "Goddeal", "Graegmaer", "Gunnwaru", "Haligwig", "Heathusige", "Helmsige", "Herlecyne", "Hildsige", "Isenor", "Islynn", "Ivithra", "Layedavea", "Leofmaer", "Leofor", "Leofwil", "Mayoldakira", "Mildrun", "Morwenna", "Nerama", "Rozenwyn", "Salywyn", "Secgflaed", "Thuror", "Velalle", "Vorokira", "Wiggifu", "Wineflaed", "Xerawe", "Zubana", "Zubuwyn"
|
||||
|
||||
|
||||
* "human male"
|
||||
|
||||
"A-bri", "Aelfkettil", "Aelfmund", "Aenesric", "Alagise", "Balrach", "Bardahard", "Beorhthun", "Bregudeor", "Breguson", "Cenarm", "Censige", "Chalrochak", "Chaltorek", "Cynebeorht", "Delmkor", "Deorgar", "Deorweald", "Ealdcromb", "Ealdmaer", "Ealhbeald", "Ervan", "Garsige", "Gilrek", "Godbeorht", "Godweard", "Gunndur", "Heanawulf", "Herebrand", "Hlar", "Hrofweard", "Hwitnoth", "Instan", "Leodhere", "Leofric", "Myghal", "Osraed", "Osstan", "Perran", "Sigeleof", "Sigeric", "Sigeweard", "Sjarguri", "Thurheard", "Wella", "Wigarm", "Winewulf", "Wulfheard", "Zldir", "Zlen"
|
||||
|
||||
|
||||
* "human surname"
|
||||
|
||||
"'Bishop' Trafield", "'Contemptible' Russell", "'Old' Cripps", "'Palmer' Dorain", "'Pegram' Hawkeye", "'Strong' Bulwark", "'Sweltering' Conidwine", "'Young' Brandy-Shield", "Andrewartha", "Atruius", "Baines", "Biedwulf", "Bold", "Brandy-Shield", "Brittle-Maiden", "Brown", "Care", "Cheek", "Cloud-Strider", "Coad", "Crow", "Curicinnius", "Dark-Bearer", "Despicable", "Fraslle", "Fraslle", "Godwin", "Harding", "Harorkesdottir", "Helton", "Mantanus", "Mojensvesdottir", "Moody", "Moreley", "Nuncdes", "Peacock", "Pelitian", "Pettit", "Plalia", "Plalia", "Presley", "Pudding", "Quick", "Remington", "Rosewarne", "Royston", "Stevens", "Swift", "Trevorrow", "the Peacock"
|
||||
|
||||
|
||||
* "infernal dull heavy"
|
||||
|
||||
"Algzourb", "Barg-izkolg", "Bubzudregh", "Bulgvifelg", "Chagojbub", "Dreghulthog", "Dreghzakrolg", "Droogujyeeg", "Frubrafrub", "Glaag-rokrolg", "Glablatzolg", "Gragyaulb", "Grolbazvulb", "Gubujzugt", "Hegalrung", "Hegrodrog", "Hurgarjulb", "Iog-joolb", "Iogivnaug", "Iugyimag", "Julbrukag", "Kleguvdergh", "Kolg-yurung", "Krolgortzolg", "Kwargzaglab", "Maug-jusug", "Naug-yemog", "Nogvaulb", "Nud-jelaug", "Nuguvgub", "Nulbivgaub", "Nulbjodruj", "Nyogvidraug", "Olburbulg", "Raagiyolb", "Raagvavub", "Rungaynaag", "Saugazgaub", "Shubaraag", "Sugojgrolb", "Trobizghad", "Tzolgvomag", "Urbuykolg", "Vulbyuyibb", "Yibb-urlaug", "Yibbejglaag", "Yibbivhaag", "Zug-yaagh", "Zugaviog", "Zugvuagh"
|
||||
|
||||
|
||||
* "infernal sharp spiky"
|
||||
|
||||
"Achoybrax", "Akkvaslarv", "Barlavap", "Brax-ursark", "Dek-zikrych", "Dunazbar", "Dunjaoch", "Duumyuech", "Duumzakrych", "Gaanzabahor", "Gaurlamuth", "Glaur-vusark", "Glaurlulok", "Gochlinam", "Gochovhaerx", "Hraxzunazt", "Inaxuvdak", "Irschjotlizit", "Khorjurolk", "Khoryithak", "Kirluazt", "Kosilmoch", "Lachuznazt", "Lis-zovap", "Lothluoth", "Luthlolach", "Luthujlazt", "Met-libor", "Metizgoth", "Metvikhor", "Moth-vuutuk", "Noc-evmet", "Nur-uyoth", "Ralkulgoth", "Raukozfesh", "Ruaakvosark", "Sarklaazt", "Slarvalach", "Slarvuvirsch", "Sothjuazt", "Sotviigm", "Sutovralk", "Tashlubrax", "Tlizituvazt", "Turzethalk", "Urtvaakk", "Utukurgith", "Uztrulok", "Vach-azdek", "Vachaynyth"
|
||||
|
||||
|
||||
* "infernal soft spongy"
|
||||
|
||||
"Alzivbre", "Baalrobul", "Baelovmau", "Baz-zubial", "Bre-ulalu", "Buyihuz", "Chru-ezssu", "Draualyee", "Druoygel", "Garl-jathalu", "Garu-uyreoz", "Garulibu", "Garuuyghu", "Gelyubaal", "Ghaaevhez", "Glayuhuz", "Glezahra", "Guzeyidrau", "Hezjoziel", "Hriz-orglau", "Hruz-azbial", "Juuruyaa", "Kraayuidrau", "Mauyorezu", "Nee-uzmuz", "Neeruthu", "Neeuvgzi", "Oazo-ivzuu", "Oazourgro", "Raz-lamuz", "Razayhra", "Razyuzu", "Rhuu-jihra", "Riz-ulgla", "Ruazergarl", "Ruazurgla", "Saaellilu", "Sauzonee", "Shai-rotho", "Soaz-ujmoz", "Thaajidrau", "Thaluuzru", "Thuyuchru", "Tzauiltze", "Tzauyuolth", "Utuyuhez", "Vuliyrezu", "Yeejagel", "Zulritha", "Zuyahez"
|
||||
|
||||
|
||||
* "malevolent female"
|
||||
|
||||
"Aaggiu", "Alurdusla", "Arakziu", "Azulla", "Bralizil", "Brazxhiu", "Drulgjiul", "Idrudusla", "Jurgizil", "Jurzija", "Jurzsula", "Kaazrhyl", "Krivgiu", "Kuazsula", "Luribau", "Lurigiu", "Mulkrhyl", "Mulkskiu", "Mulkskiu", "Naurhyl", "Nauulla", "Nidzihyl", "Ninjbau", "Nulanil", "Nymnalu", "Ranaganil", "Rilthudusla", "Rilthusula", "Rukjiul", "Rukziu", "Ulthuulla", "Urzgiu", "Urzsula", "Uznidanil", "Virnziu", "Vlaajbau", "Vlagdiu", "Vlashxhiu", "Vluzakdiu", "Vulkbau", "Xidzihyl", "Xurajdiu", "Xurajdusla", "Xurajziu", "Zugdiu", "Zuglin", "Zuldudiu", "Zulduija", "Zuvdusla", "Zuvziu"
|
||||
|
||||
|
||||
* "malevolent male"
|
||||
|
||||
"Aagsuruk", "Alurlun", "Alurull", "Arakbru", "Araklurug", "Brallurr", "Draaninu", "Drulguvik", "Guzsuruk", "Hauglurug", "Hauguvik", "Jidinu", "Jidzuk", "Jiusuruk", "Jurglun", "Jurgundak", "Jurzzuk", "Kaazull", "Kargzuk", "Kharkundak", "Kraurul", "Kuazdrul", "Kuduzuk", "Nidarag", "Nullurug", "Nymlurug", "Ranaglurug", "Ranagsuruk", "Rilthunal", "Rilthuxulg", "Rulksalk", "Ruzlurr", "Ruzzu", "Ulthuruzuk", "Utizuk", "Uznidlun", "Virnsul", "Vlaglun", "Vlashsalk", "Vluzaksalk", "Vluzakxulg", "Vrazinu", "Vrazsuruk", "Xaulank", "Xidsalk", "Xiduvik", "Xurajarag", "Xurajzu", "Zauvarag", "Zauvxulg"
|
||||
|
||||
|
||||
* "ogre female"
|
||||
|
||||
"Arghklobglugah", "Arghthulkya", "Bogduzya", "Burzguhlay", "Dubdulghy", "Dubshuzay", "Dubulgghy", "Dugkugya", "Dusharghgah", "Dushmugay", "Duzkaigah", "Fugglugghy", "Ghashgluby", "Gholhurgya", "Ghortrugghy", "Ghukkbogay", "Ghulgrulay", "Ghulgrumfay", "Ghulthragy", "Gradsludah", "Grashdrokay", "Groggkaiay", "Grulshugah", "Grumfkurah", "Grumslubay", "Grutduzy", "Gruzdofy", "Gruzmudya", "Gulvgluzobbgah", "Hurgludghy", "Hurgsnogy", "Lukhklobya", "Lukhlumgah", "Lushrukhgah", "Mauggruya", "Mugdrubah", "Mugobbgah", "Nakhlumgah", "Nargbarshghy", "Slubdurshghy", "Slubgludy", "Slugmolgay", "Snoglushy", "Trugobby", "Urdhrungy", "Urghakhay", "Urghkrody", "Urobbah", "Uzguhlay", "Uzgulvgah"
|
||||
|
||||
|
||||
* "ogre male"
|
||||
|
||||
"Arghargh", "Arghdursh", "Barshgluz", "Boglorg", "Bogthurk", "Burzlug", "Burzlukhgrumf", "Drugkrod", "Duglorg", "Dugmakh", "Dulburz", "Dushthrag", "Duzgrut", "Duzlurz", "Ghashmuzd", "Gludyur", "Grobrolb", "Groggkrod", "Grokshud", "Grollurzmolg", "Grukkrod", "Grulgom", "Grumfnakh", "Grumgulv", "Guhlhai", "Haigrul", "Haishuz", "Klobgrum", "Klobmolg", "Lorgdub", "Lukhgrash", "Lummul", "Makhkai", "Mughai", "Mugsnog", "Murkgrum", "Nakhgrum", "Nakhslud", "Nargkug", "Obbmud", "Rukhshud", "Shudgrash", "Shudlush", "Shudmakh", "Shurburz", "Shuzmudshug", "Slugruz", "Thulktrug", "Urkhgrul", "Yugduz"
|
||||
|
||||
|
||||
* "orc female"
|
||||
|
||||
"Augbragy", "Bagumshgah", "Bazkrudgah", "Blagkhagruday", "Dagkragy", "Drabrorgah", "Dugmolkghy", "Ghazsnurry", "Glakhmukah", "Glolzahkghy", "Gnarlhroggnashy", "Gnashlubgah", "Gobragghy", "Gokhbrogghy", "Gorhrugah", "Grakhdakky", "Grakholggah", "Grashslurah", "Grathlashghy", "Grazshaday", "Grotlobghy", "Grotlufghy", "Grubgrathah", "Gutkharbakhya", "Hagglufah", "Hakkbragya", "Khagghazghy", "Kharaugya", "Lubyashlufya", "Lukgrazy", "Mukbadya", "Olgdagay", "Olggrubghy", "Olgshogah", "Raghrogy", "Rashgolay", "Roggsnubya", "Rotsnorlghy", "Rudsodah", "Rutdrabah", "Shaglobya", "Shoggnashghazghy", "Skardaggah", "Snorlghazay", "Sodbruzah", "Sodlufya", "Thakrudghy", "Troghrugay", "Uthkragghy", "Yobgudgrakhya"
|
||||
|
||||
|
||||
* "orc male"
|
||||
|
||||
"Aglash", "Bakhag", "Bazgokh", "Bragzahkmuz", "Brogzahk", "Dobzog", "Drabgrath", "Dugshaz", "Ghazbrag", "Ghazglur", "Glazmuk", "Glolrud", "Gnashdog", "Gokhluk", "Grathbakh", "Grathung", "Grotgrot", "Grotruft", "Grubgol", "Grublub", "Grubskar", "Gutbrag", "Haggokh", "Khaggor", "Khagluk", "Khargraz", "Kragskar", "Krudgrathgob", "Krudgraz", "Lakhsnurr", "Ludug", "Lufgud", "Mukogg", "Muzbash", "Muzglursnorl", "Olghrug", "Rashgut", "Rorggrub", "Rutdag", "Shakbruzrut", "Skulgbag", "Skulgdur", "Skulgslur", "Slurglol", "Snarug", "Snurrzog", "Thakrag", "Trogdarg", "Uthsnub", "Yashgrash"
|
||||
|
||||
|
||||
* "orc surname"
|
||||
|
||||
"Bagdlor", "Barad", "Barlob", "Basgakh", "Boggrak", "Bogugk", "Bogugol", "Buglul", "Bugpok", "Bumptur", "Bural", "Buraum", "Burbrkub", "Burgk", "Burgul", "Burorz", "Dugk", "Duguh", "Dullump", "Dushgub", "Gashur", "Hubor", "Khagth", "Khalob", "Laglob", "Largbek", "Logrgul", "Lumoim", "Luzph", "Magrg", "Malgdum", "Maroar", "Maroar", "Mashma", "Mashma", "Masrag", "Morbak", "Morggurz", "Muzurn", "Nayba", "Ogduborgob", "Orbuduk", "Shadra", "Shulharzol", "Shulz", "Trairbag", "Ugrump", "Ulargk", "Uzgh", "Yarurga"
|
||||
|
||||
|
||||
* "sinister dark elf female"
|
||||
|
||||
"Balnosylna", "Balnyllivil", "Baltorlinvra", "Bursullevia", "Burthalsylil", "Charyaspirra", "Choryolrindra", "Colsinelene", "Colsoldylia", "Dolmyrlavtra", "Dortullenra", "Doryolralith", "Drirhasylhel", "Drisinralrin", "Drisinrilrin", "Dulrelrillin", "Dulyaslavdra", "Durorrildril", "Eilnelrinith", "Eksusidvra", "Enonlenistra", "Envolisia", "Erolgsiniln", "Eronralna", "Gonothsinil", "Gonporlevdril", "Gulmyrpelna", "Gultormlivvril", "Imnilrana", "Insnellevistra", "Inssabsinrin", "Insvilrailn", "Insyaserrin", "Istverelna", "Jegtullenlin", "Jegvrilenna", "Jermyrilra", "Lilothenvril", "Lilvillinra", "Lultorelra", "Mabsunsinna", "Mabtormpelil", "Mabyaslenrin", "Marsinpirrin", "Marsuspelra", "Mersabralia", "Molorgpirrin", "Nothorlavra", "Nothtulidlin", "Olsollavil"
|
||||
|
||||
|
||||
* "sinister dark elf male"
|
||||
|
||||
"Balsinlavul", "Baltelilrim", "Balthalidrid", "Bertullavriv", "Burolgilird", "Buronpeluld", "Buronrilald", "Choronernaz", "Chortormlavlim", "Chorvorenred", "Colorgsylald", "Colsunervid", "Divnylenred", "Divsusrineld", "Divveklivnid", "Dolverisird", "Drirhalenid", "Driteldylird", "Drivekpelviz", "Driyelidriv", "Drommyrsylriv", "Dromvekralim", "Durpelsinild", "Eilsulsylnim", "Eiltelennim", "Eknesylild", "Eknylelviz", "Erporelred", "Gonrhaenrid", "Gulorgerred", "Insnelavred", "Instelisvim", "Insyaslavid", "Istruelrim", "Istyolidvim", "Jegsullivul", "Lilnoenvim", "Lulyellinrim", "Maborlevviz", "Mabtormenild", "Mezvilrilnid", "Mezvirlinrid", "Mezvrillavnid", "Molsekidvim", "Molsundyluld", "Moltenpelnim", "Morrhalenvir", "Morsabrinald", "Olondylriv", "Olothlenid"
|
||||
|
||||
|
||||
* "small spry female 1"
|
||||
|
||||
"Dexerel", "Flissifer", "Flissifer", "Fossafer", "Fossamer", "Fossenti", "Friskerel", "Frissirel", "Frissirel", "Glanirel", "Glaxenti", "Glimarel", "Glimirel", "Glissamer", "Glissinel", "Glissinel", "Glissirel", "Gossenti", "Lissefer", "Minenti", "Minimer", "Miskafer", "Miskamer", "Miskimer", "Ressirel", "Riffafer", "Riffamer", "Riffimer", "Riffinel", "Rillanel", "Rillerel", "Rillimer", "Shimafer", "Shimarel", "Tinkenti", "Tinkinel", "Tissafer", "Trillasti", "Tristimer", "Tristinel", "Tristirel", "Twillanel", "Twillefer", "Twispamer", "Twispefer", "Weftafer", "Weftafer", "Weskasti", "Winnarel", "Wispasti"
|
||||
|
||||
|
||||
* "small spry female 2"
|
||||
|
||||
"Brisliss", "Brisnyx", "Crylkiss", "Crylnyx", "Elsikiss", "Elsiynx", "Emberla", "Emberla", "Eskriss", "Eskynx", "Ferisnyx", "Ferisree", "Friminyx", "Ganree", "Glinknyx", "Glinkynx", "Iphilkiss", "Iphilsa", "Ispelliss", "Ispelnyx", "Istleriss", "Jusniss", "Lirrakiss", "Lirrala", "Lirraliss", "Malitiss", "Minkla", "Mirradee", "Mistlenyx", "Mistleree", "Ninkakiss", "Ninkariss", "Ninkasa", "Opalkiss", "Orifdee", "Orifdee", "Orifree", "Orisree", "Oristiss", "Sarmliss", "Sprinmee", "Stithdee", "Stithmee", "Stithsa", "Tansikiss", "Tansiniss", "Trumpla", "Trumpriss", "Zandokiss", "Zandoynx"
|
||||
|
||||
|
||||
* "small spry male 1"
|
||||
|
||||
"Dexaroll", "Dexeroll", "Dexesto", "Flaxaroll", "Flaxasto", "Flissaldo", "Flissaron", "Flixeron", "Fossallo", "Friskaldo", "Friskaron", "Frissendo", "Gessaldo", "Gessaroll", "Glanamo", "Glimaroll", "Glimaron", "Glimendo", "Glimeron", "Glissendo", "Hexaron", "Lissaldo", "Lissando", "Lisseroll", "Minaron", "Mineroll", "Miskondo", "Rafferoll", "Rafferon", "Ressasto", "Riffando", "Rillaroll", "Rilleroll", "Saffondo", "Saffondo", "Shimaldo", "Tinkesto", "Trillallo", "Trilleroll", "Tristamo", "Tristaron", "Twissendo", "Twissondo", "Twixaron", "Weftando", "Weskondo", "Winnaroll", "Wispasto", "Wisperoll", "Wisperon"
|
||||
|
||||
|
||||
* "small spry male 2"
|
||||
|
||||
"Brismit", "Crylbrix", "Elsitross", "Emberbik", "Emberbik", "Emberfrell", "Emberfret", "Embermit", "Emberzisk", "Feriswin", "Frimibik", "Ganbik", "Ganfrell", "Halzisk", "Helrix", "Histwin", "Josttwik", "Jostzisk", "Juskin", "Lirrarix", "Malikin", "Maliwin", "Malizisk", "Mirrabik", "Mirrazisk", "Mistlefrell", "Mistlemit", "Mistletross", "Mistlezisk", "Opalfret", "Opalkin", "Opaltwik", "Oriftwik", "Oriftwik", "Orifzisk", "Orisfrell", "Oriskin", "Perifrell", "Perikin", "Peritross", "Sarmfrell", "Sprinbrix", "Tansimit", "Tirratross", "Tirrawin", "Whisfrell", "Whistwik", "Zandofrell", "Zandotross", "Zandotross"
|
1229
namegen.cfg
Normal file
1229
namegen.cfg
Normal file
File diff suppressed because one or more lines are too long
1
namegen.index
Normal file
1
namegen.index
Normal file
@ -0,0 +1 @@
|
||||
namegen.cfg
|
423
namegen.lua
Normal file
423
namegen.lua
Normal file
@ -0,0 +1,423 @@
|
||||
local namegen = {
|
||||
_VERSION = 'LuaNameGen - Lua Name Generator v1.0.0',
|
||||
_DESCRIPTION = 'A name generator written in Lua',
|
||||
_URL = 'https://github.com/LukeMS/lua-namegen',
|
||||
_LICENSE = [[
|
||||
MIT LICENSE
|
||||
|
||||
Copyright (c) 2017 Lucas Siqueira
|
||||
|
||||
Permission is hereby granted, free of charge, to any person obtaining a
|
||||
copy of this software and associated documentation files (the
|
||||
"Software"), to deal in the Software without restriction, including
|
||||
without limitation the rights to use, copy, modify, merge, publish,
|
||||
distribute, sublicense, and/or sell copies of the Software, and to
|
||||
permit persons to whom the Software is furnished to do so, subject to
|
||||
the following conditions:
|
||||
|
||||
The above copyright notice and this permission notice shall be included
|
||||
in all copies or substantial portions of the Software.
|
||||
|
||||
THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS
|
||||
OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF
|
||||
MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT.
|
||||
IN NO EVENT SHALL THE AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY
|
||||
CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN AN ACTION OF CONTRACT,
|
||||
TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN CONNECTION WITH THE
|
||||
SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE.
|
||||
]]
|
||||
}
|
||||
|
||||
local function loadrequire(module)
|
||||
local loaded
|
||||
local function requiref(module)
|
||||
loaded = require(module)
|
||||
end
|
||||
pcall(requiref, module)
|
||||
return loaded
|
||||
end
|
||||
|
||||
local RangedTable = require("rangedtable")
|
||||
|
||||
local inspect = loadrequire('inspect') or function(t)
|
||||
s = "{"
|
||||
for k, v in t do
|
||||
s = s .. string.format("%s: %s;", k, v)
|
||||
end
|
||||
s = s .. "}"
|
||||
return s
|
||||
end
|
||||
|
||||
|
||||
-- ======================
|
||||
-- CONSTANTS
|
||||
-- ======================
|
||||
|
||||
-- set this to true for a debug/verbose mode
|
||||
-- requires 'inspect' (https://github.com/kikito/inspect.lua)
|
||||
local DEBUG = false
|
||||
|
||||
|
||||
-- ======================
|
||||
-- VARIABLES
|
||||
-- ======================
|
||||
|
||||
-- the table containing the generators
|
||||
local namegen_generators_list = {}
|
||||
|
||||
|
||||
-- ======================
|
||||
-- UTILITIES
|
||||
-- ======================
|
||||
|
||||
local function file_exists(name)
|
||||
local f=io.open(name,"r")
|
||||
if f~=nil then io.close(f) return true else return false end
|
||||
end
|
||||
|
||||
local function get_path(filename)
|
||||
if filename:find("%.cfg$") then
|
||||
return filename
|
||||
else
|
||||
return filename .. ".cfg"
|
||||
end
|
||||
end
|
||||
|
||||
local function split(str)
|
||||
local t = {}
|
||||
for v in string.gmatch(str:gsub(",", ""), "%S+") do
|
||||
t[#t + 1] = v
|
||||
end
|
||||
return t
|
||||
end
|
||||
|
||||
local function ng_debug(str, ...)
|
||||
if DEBUG == true then
|
||||
print(string.format(str, ...))
|
||||
end
|
||||
end
|
||||
|
||||
|
||||
-- ======================
|
||||
-- PARSERS
|
||||
-- ======================
|
||||
|
||||
local function parse_rules(rules)
|
||||
local rules_weight = {}
|
||||
local rule_pattern = [[^%%*(%d*)(%S+)]]
|
||||
for _, v in pairs(rules) do
|
||||
local chance, rule = string.match(v, rule_pattern)
|
||||
ng_debug([[chance: "%s", rule: "%s"]], chance, rule)
|
||||
chance = chance == "" and 100 or tonumber(chance)
|
||||
rules_weight[#rules_weight + 1] = {chance, rule}
|
||||
end
|
||||
ng_debug(inspect(rules), inspect(rules_weight))
|
||||
return RangedTable(rules_weight)
|
||||
end
|
||||
|
||||
local function parse_property(name, value, parser_data)
|
||||
local v = name == "name" and value or split(value)
|
||||
if name == "name" then
|
||||
ng_debug([[parse_property: "%s"]], value)
|
||||
parser_data["name"] = v
|
||||
elseif name == "syllablesStart" then
|
||||
parser_data["start"] = v
|
||||
elseif name == "syllablesMiddle" then
|
||||
parser_data["middle"] = v
|
||||
elseif name == "syllablesEnd" then
|
||||
parser_data["end"] = v
|
||||
elseif name =="syllablesPre" then
|
||||
parser_data["pre"] = v
|
||||
elseif name =="syllablesPost" then
|
||||
parser_data["post"] = v
|
||||
elseif name == "phonemesVocals" then
|
||||
parser_data["vocals"] = v
|
||||
elseif name =="phonemesConsonants" then
|
||||
parser_data.consonants = v
|
||||
elseif name == "rules" then
|
||||
parser_data["rules"] = parse_rules(v)
|
||||
elseif name == "illegal" then
|
||||
-- /* illegal strings are converted to lowercase */
|
||||
parser_data.illegal = split(string.lower(value))
|
||||
else
|
||||
local cg = string.match(name, "^customGroup(%a)")
|
||||
if cg then
|
||||
parser_data["cg" .. cg:lower()] = v
|
||||
else
|
||||
ng_debug("parse_property else")
|
||||
return false
|
||||
end
|
||||
end
|
||||
return true
|
||||
end
|
||||
|
||||
local function parse_lines(path, data)
|
||||
ng_debug("starting `parse_lines`", path)
|
||||
local data
|
||||
local name_pattern = [[name ?"(.+)" ?{]]
|
||||
local property_pattern = [[ +(.+) = "(.+)"]]
|
||||
local end_body_pattern = [[}]]
|
||||
|
||||
local body = false
|
||||
for line in io.lines(path) do
|
||||
local name = string.match(line, name_pattern)
|
||||
if name ~= nil then
|
||||
namegen_generators_list[name] = {}
|
||||
data = namegen_generators_list[name]
|
||||
parse_property("name", name, data)
|
||||
body = true
|
||||
elseif body == true then
|
||||
if string.match(line, end_body_pattern) then
|
||||
body = false
|
||||
else
|
||||
local name, value = string.match(line, property_pattern)
|
||||
if name and value then
|
||||
parse_property(name, value, data)
|
||||
end
|
||||
end
|
||||
end
|
||||
end
|
||||
ng_debug("ending `parse_lines`")
|
||||
end
|
||||
|
||||
local function parse_file(filename)
|
||||
ng_debug("starting `parse_file`")
|
||||
local path = get_path(filename)
|
||||
if not file_exists(path) then
|
||||
error(string.format("File \"%s\" not found!\n",path))
|
||||
end
|
||||
parse_lines(get_path(filename))
|
||||
ng_debug("ending `parse_file`")
|
||||
end
|
||||
|
||||
local function parse_index()
|
||||
ng_debug("starting `parse_index`")
|
||||
|
||||
for line in io.lines("namegen.index") do
|
||||
parse_file(line)
|
||||
end
|
||||
ng_debug("ending `parse_index`")
|
||||
end
|
||||
|
||||
|
||||
-- ======================
|
||||
-- WORD VALIDATION
|
||||
-- ======================
|
||||
|
||||
-- check for occurrences of triple characters (case-insensitive)
|
||||
local function word_has_triples(str)
|
||||
local str = str:lower()
|
||||
for i = 1, #str - 2 do
|
||||
local a = str:sub(i, i)
|
||||
local b = str:sub(i+1, i+1)
|
||||
local c = str:sub(i+2, i+2)
|
||||
if a == b and a == c then
|
||||
return true
|
||||
end
|
||||
end
|
||||
return false
|
||||
end
|
||||
|
||||
-- check for occurrences of illegal strings (case-insensitive)
|
||||
local function word_has_illegal(data, str)
|
||||
local str = str:lower()
|
||||
|
||||
if not data.illegal then return false end
|
||||
|
||||
for i = 1, #data.illegal do
|
||||
if str:find(data.illegal[i]) then
|
||||
return true
|
||||
end
|
||||
end
|
||||
return false
|
||||
end
|
||||
|
||||
-- check for repeated syllables (case-insensitive)
|
||||
local function word_repeated_syllables(str)
|
||||
local str = str:lower()
|
||||
|
||||
for step = 2, 3 do
|
||||
for i = 1, #str - step * 2 + 1, 1 do
|
||||
local a0 = i
|
||||
local a1 = a0 + step - 1
|
||||
local b0 = a1 + 1
|
||||
local b1 = b0 + step - 1
|
||||
local a = str:sub(a0, a1)
|
||||
local b = str:sub(b0, b1)
|
||||
if a == b then
|
||||
ng_debug(a, b)
|
||||
return true
|
||||
end
|
||||
end
|
||||
end
|
||||
return false
|
||||
end
|
||||
|
||||
-- verify if the word passes the above checks
|
||||
local function word_is_ok(data, str)
|
||||
return ((#str > 0) and
|
||||
not word_has_triples(str) and
|
||||
not word_has_illegal(data, str) and
|
||||
not word_repeated_syllables(str))
|
||||
end
|
||||
|
||||
-- removes double, leading and ending spaces
|
||||
local function word_prune_spaces(str)
|
||||
str = str:gsub(" +$", "")
|
||||
str = str:gsub("^ +", "")
|
||||
str = str:gsub(" +", " ")
|
||||
return str
|
||||
end
|
||||
|
||||
local function generate_custom(name, rule)
|
||||
local random = math.random
|
||||
|
||||
local data = namegen_generators_list[name]
|
||||
if data == nil then
|
||||
error(string.format("The name \"%s\" has not been found.\n",name))
|
||||
end
|
||||
|
||||
-- start name generation
|
||||
local buf, i, it
|
||||
repeat
|
||||
buf = ""
|
||||
i = 1
|
||||
while i <= #rule do
|
||||
it = rule:sub(i, i)
|
||||
-- append normal character
|
||||
if ((it >= 'a' and it <= 'z') or
|
||||
(it >= 'A' and it <= 'Z') or
|
||||
it == '\'' or it == '-')
|
||||
then
|
||||
ng_debug("buf case 1")
|
||||
buf = buf .. it
|
||||
elseif it == '/' then
|
||||
-- special character
|
||||
i = i + 1
|
||||
ng_debug("buf case 2")
|
||||
buf = buf .. it
|
||||
elseif it == '_' then
|
||||
-- convert underscore to space
|
||||
ng_debug("buf case 3")
|
||||
buf = buf .. " "
|
||||
-- interpret a wildcard
|
||||
elseif it == '$' then
|
||||
local chance = 100;
|
||||
i = i + 1
|
||||
local it = rule:sub(i, i)
|
||||
ng_debug("buf case 4, it: %s", it)
|
||||
-- food for the randomiser
|
||||
if it >= '0' and it <= '9' then
|
||||
ng_debug("buf case 4.1")
|
||||
chance = 0
|
||||
while it >= '0' and it <= '9' do
|
||||
chance = chance * 10
|
||||
chance = chance + tonumber(it)
|
||||
i = i + 1
|
||||
it = rule:sub(i, i);
|
||||
end
|
||||
end
|
||||
-- evaluate the wildcard according to its chance
|
||||
if chance >= random(100) then
|
||||
ng_debug("buf case 4.2")
|
||||
local lst
|
||||
if it == 'P' then
|
||||
ng_debug("buf case 4.2.1")
|
||||
lst = data["pre"]
|
||||
elseif it == 's' then
|
||||
ng_debug("buf case 4.2.2")
|
||||
lst = data["start"]
|
||||
elseif it == 'm' then
|
||||
ng_debug("buf case 4.2.3")
|
||||
lst = data["middle"]
|
||||
elseif it == 'e' then
|
||||
ng_debug("buf case 4.2.4")
|
||||
lst = data["end"]
|
||||
elseif it == 'p' then
|
||||
ng_debug("buf case 4.2.5")
|
||||
lst = data["post"]
|
||||
elseif it == 'v' then
|
||||
ng_debug("buf case 4.2.6")
|
||||
lst = data["vocals"]
|
||||
elseif it == 'c' then
|
||||
ng_debug("buf case 4.2.7")
|
||||
lst = data["consonants"]
|
||||
elseif it == '?' then
|
||||
ng_debug("buf case 4.2.8")
|
||||
lst = ((random(1, 2) == 1) and data.vocals or
|
||||
data.consonants)
|
||||
else
|
||||
if it >= "A" and it < "P" then
|
||||
lst = data["cg" .. it:lower()]
|
||||
else
|
||||
error(string.format(
|
||||
[[Wrong rules syntax(it:"%s", rule:"%s")]],
|
||||
it, rule))
|
||||
end
|
||||
end
|
||||
if #lst == 0 then
|
||||
error(string.format(
|
||||
"No data found in the requested string (wildcard %s). Check your name generation rule %s.",
|
||||
it,rule
|
||||
))
|
||||
else
|
||||
buf = buf .. (lst[random(1, #lst)]:gsub('_', ' '))
|
||||
end
|
||||
end
|
||||
end
|
||||
ng_debug([[i: %d, buf: %s, it: %s, rule: %s]],
|
||||
i, buf, it, rule)
|
||||
i = i + 1
|
||||
end
|
||||
until word_is_ok(data, buf)
|
||||
ng_debug([[ending "generate_custom 'repeat ... until'"]])
|
||||
|
||||
-- prune undesired spaces and return the name
|
||||
return word_prune_spaces(buf)
|
||||
end
|
||||
|
||||
-- generate a new name with one of the rules from set
|
||||
local function generate(name)
|
||||
ng_debug([[starting "generate(%s)"]], name)
|
||||
local data = namegen_generators_list[name]
|
||||
if data == nil then
|
||||
error(string.format("The name \"%s\" has not been found.\n",name))
|
||||
end
|
||||
-- check if the rules list is present */
|
||||
if data.rules:size() == 0 then
|
||||
error("The rules list is empty!")
|
||||
end
|
||||
|
||||
-- choose the rule */
|
||||
local res = generate_custom(name, data.rules:choice())
|
||||
ng_debug([[starting "generate(%s)"]], name)
|
||||
return res
|
||||
end
|
||||
|
||||
local function get_sets()
|
||||
local t = {}
|
||||
for k, _ in pairs(namegen_generators_list) do
|
||||
if namegen_generators_list[k].rules then
|
||||
t[#t + 1] = k
|
||||
end
|
||||
end
|
||||
return t
|
||||
end
|
||||
|
||||
|
||||
-- ------------------------------
|
||||
-- load default sets (as specified on `namegen.index`)
|
||||
-- ------------------------------
|
||||
parse_index()
|
||||
|
||||
|
||||
-- ------------------------------
|
||||
-- publicly available functions
|
||||
-- ------------------------------
|
||||
|
||||
namegen.get_sets = get_sets
|
||||
namegen.parse_file = parse_file
|
||||
namegen.generate = generate
|
||||
namegen.generate_custom = generate_custom
|
||||
|
||||
return namegen
|
87
rangedtable.lua
Normal file
87
rangedtable.lua
Normal file
@ -0,0 +1,87 @@
|
||||
-- RangedTable - table with range or group entries
|
||||
-- Author: Lucas Siqueira
|
||||
-- License: Public Domain / CC0.
|
||||
|
||||
local RangedTable = {}
|
||||
RangedTable.__index = RangedTable
|
||||
|
||||
setmetatable(RangedTable, {
|
||||
__call = function(class, ...)
|
||||
local instance = setmetatable({}, class)
|
||||
if instance.initialize then
|
||||
instance:initialize(...)
|
||||
end
|
||||
return instance
|
||||
end
|
||||
})
|
||||
|
||||
local function cmp_number(k, t)
|
||||
for i = 1, #t do
|
||||
local entry = t[i]
|
||||
local range, v = entry[1], entry[2]
|
||||
if k >= range[1] and k <= range[2] then
|
||||
return v
|
||||
end
|
||||
end
|
||||
end
|
||||
|
||||
local function cmp_group(k, t)
|
||||
for i = 1, #t do
|
||||
local entry = t[i]
|
||||
local group, v = entry[1], entry[2]
|
||||
for i = 1, #group do
|
||||
if k == group[i] then
|
||||
return v
|
||||
end
|
||||
end
|
||||
end
|
||||
end
|
||||
|
||||
function RangedTable:get(k)
|
||||
local cmp = type(k) == "number" and cmp_number or cmp_group
|
||||
return cmp(k, self.ranges)
|
||||
end
|
||||
|
||||
function RangedTable:choice()
|
||||
return self:get(math.random(1, self.max))
|
||||
end
|
||||
|
||||
function RangedTable:initialize(t)
|
||||
self.ranges = {}
|
||||
for i = 1, #t do
|
||||
self.ranges[#self.ranges + 1] = t[i]
|
||||
end
|
||||
self:normalize()
|
||||
return self
|
||||
end
|
||||
|
||||
function RangedTable:size()
|
||||
return #self.ranges
|
||||
end
|
||||
|
||||
function RangedTable:normalize()
|
||||
local normalized = {}
|
||||
local sum = 1
|
||||
local range
|
||||
for i = 1, #self.ranges do
|
||||
local entry = self.ranges[i]
|
||||
local chance = entry[1]
|
||||
local content = entry[2]
|
||||
if type(chance) == "number" then
|
||||
range = chance
|
||||
elseif #chance == 1 then
|
||||
range = chance[1]
|
||||
elseif type(chance[1]) == "string" then
|
||||
return
|
||||
else
|
||||
range = chance[2] - chance[1] + 1
|
||||
end
|
||||
normalized[#normalized + 1] = {{sum, sum + range - 1}, content}
|
||||
sum = sum + range
|
||||
end
|
||||
self.ranges = normalized
|
||||
self.max = sum - 1
|
||||
end
|
||||
|
||||
|
||||
return RangedTable
|
19
test.lua
Normal file
19
test.lua
Normal file
@ -0,0 +1,19 @@
|
||||
math.randomseed(1)
|
||||
math.random()
|
||||
|
||||
|
||||
local inspect = require("inspect")
|
||||
local namegen = require("namegen")
|
||||
|
||||
|
||||
local sets = namegen.get_sets()
|
||||
table.sort(sets)
|
||||
for _, set in ipairs(sets) do
|
||||
print("\n\n" .. "* " .. string.format([["%s"]], set) .. "\n")
|
||||
local names = {}
|
||||
for i = 1, 50 do
|
||||
names[#names + 1] = namegen.generate(set)
|
||||
end
|
||||
table.sort(names)
|
||||
print(" " .. inspect(names):gsub("[{}]", ""))
|
||||
end
|
Loading…
x
Reference in New Issue
Block a user