first commit

This commit is contained in:
LukeMS 2017-02-11 15:37:27 -02:00
commit 2dd6129cef
7 changed files with 2049 additions and 0 deletions

3
.gitignore vendored Normal file
View File

@ -0,0 +1,3 @@
*.sublime-workspace
*.sublime-project
*.log

287
README.rst Normal file
View 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

File diff suppressed because one or more lines are too long

1
namegen.index Normal file
View File

@ -0,0 +1 @@
namegen.cfg

423
namegen.lua Normal file
View 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
View 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
View 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