initial import
This commit is contained in:
@@ -0,0 +1,14 @@
|
||||
import importlib
|
||||
import pkgutil
|
||||
import sys
|
||||
|
||||
|
||||
def import_submodules(module):
|
||||
pkgs = pkgutil.iter_modules(module.__path__)
|
||||
for loader, module_name, is_pkg in pkgs:
|
||||
yield importlib.import_module(f"{module.__name__}.{module_name}")
|
||||
|
||||
|
||||
supported_languages = dict(
|
||||
(module.__name__.split(".")[-1], module) for module in list(import_submodules(sys.modules[__name__]))
|
||||
)
|
||||
@@ -0,0 +1,16 @@
|
||||
### Abyssal
|
||||
|
||||
Low-ranking demons speak in a guttural, broken dialect that is louder and more
|
||||
consonant, like dogs barking. The written language and naming conventions
|
||||
reflect the more refined language of demons, a quiet, sibilant susurrus that
|
||||
sounds at times like waves, at others like buzzing, keening insects.
|
||||
|
||||
*Whuewhezoawh ..uesewhaza whs..uwhiezowhisoi aizi..wheuz, whoshesowhewh
|
||||
she..iwhzzos..ozi iuzu..ueshes izsha..ua..uashezshuesas, ..awho....uza
|
||||
whuashoowhsz!*
|
||||
|
||||
**Abyssal Names:**
|
||||
|
||||
* Aa..Whaazwhis
|
||||
* Az..Zazzou
|
||||
* Uzeushsoshe..Osezawhwh
|
||||
@@ -0,0 +1,7 @@
|
||||
"""
|
||||
Abyssal
|
||||
"""
|
||||
from .base import Language
|
||||
from .names import Name, NobleName
|
||||
|
||||
__all__ = [Language, Name, NobleName]
|
||||
@@ -0,0 +1,18 @@
|
||||
from language import defaults, types
|
||||
|
||||
vowels = types.equal_weights(["a", "e", "i"], 1.0, blank=False)
|
||||
consonants = types.equal_weights(["z", "sh", "s", "wh", ".."], 1.0, blank=False)
|
||||
|
||||
Language = types.Language(
|
||||
name="celstial",
|
||||
vowels=defaults.vowels,
|
||||
consonants=consonants,
|
||||
prefixes=None,
|
||||
suffixes=None,
|
||||
rules=[],
|
||||
syllables=types.SyllableSet(
|
||||
(types.Syllable(template="vowel|consonant") * 10, 1.0),
|
||||
(types.Syllable(template="vowel|consonant") * 15, 1.0),
|
||||
(types.Syllable(template="vowel|consonant") * 20, 1.0),
|
||||
),
|
||||
)
|
||||
@@ -0,0 +1,11 @@
|
||||
from language import types
|
||||
from language.languages.abyssal import Language
|
||||
|
||||
Name = types.NameGenerator(
|
||||
language=Language,
|
||||
templates=types.NameSet(
|
||||
(types.NameTemplate("name"), 1.0),
|
||||
),
|
||||
)
|
||||
|
||||
NobleName = Name
|
||||
@@ -0,0 +1,15 @@
|
||||
### Celestial
|
||||
|
||||
Celestial is sung, not spoken, and sounds to mortal ears like stacked harmonies
|
||||
of an impossible choir. Written Celestial is akin to sheet music; it records
|
||||
the grammar and vocabulary, but cannot convey meaning.
|
||||
|
||||
*U̇ôeȧäuueüiäûoîịėeöäueaȯịo äuäuiaîiüoûoėeäoîeȧü öoaịäu̇ôuüöeiääoȧėu
|
||||
ôaîaêaịeiîäoöiôoėöi, ueûuêûiüȧuuȧaüeeêeuȯ oääuêaüâiîȧiûeu̇ėaâaȧ
|
||||
uîoėu̇au̇oîäeiäüuȧoêaiêu̇u uaäeîeoäuiaịôoėȯîiäiȧė îûȧäuaûėuoäôiûäuaȧ!
|
||||
Âȧuȯüiêịiäaiėöaöoi.*
|
||||
|
||||
**Celestial Names:**
|
||||
* Ịaêäuuȧoeėuäuoaịooȯîoäu̇Au̇Aû
|
||||
* Ûịịeịuȧoȯuȯaäâeeu̇Ėuiüaị
|
||||
* Au̇Üaoịėuüöaâaėoöȧeäėu
|
||||
@@ -0,0 +1,7 @@
|
||||
"""
|
||||
Celestial
|
||||
"""
|
||||
from .base import Language
|
||||
from .names import Name, NobleName
|
||||
|
||||
__all__ = [Language, Name, NobleName]
|
||||
@@ -0,0 +1,21 @@
|
||||
from language import defaults, types
|
||||
|
||||
vowels = types.equal_weights(["a", "e", "i", "o", "u"], 1.0, blank=False)
|
||||
consonants = types.equal_weights(
|
||||
["î", "ê", "â", "û", "ô", "ä", "ö", "ü", "äu", "ȧ", "ė", "ị", "ȯ", "u̇"], 1.0, blank=False
|
||||
)
|
||||
|
||||
Language = types.Language(
|
||||
name="celstial",
|
||||
vowels=defaults.vowels,
|
||||
consonants=consonants,
|
||||
prefixes=None,
|
||||
suffixes=None,
|
||||
rules=[],
|
||||
syllables=types.SyllableSet(
|
||||
(types.Syllable(template="vowel|consonant") * 20, 1.0),
|
||||
(types.Syllable(template="vowel|consonant") * 25, 1.0),
|
||||
(types.Syllable(template="vowel|consonant") * 30, 1.0),
|
||||
(types.Syllable(template="vowel|consonant") * 35, 1.0),
|
||||
),
|
||||
)
|
||||
@@ -0,0 +1,11 @@
|
||||
from language import types
|
||||
from language.languages.celestial import Language
|
||||
|
||||
Name = types.NameGenerator(
|
||||
language=Language,
|
||||
templates=types.NameSet(
|
||||
(types.NameTemplate("name"), 1.0),
|
||||
),
|
||||
)
|
||||
|
||||
NobleName = Name
|
||||
@@ -0,0 +1,16 @@
|
||||
### Common
|
||||
|
||||
Common is a complicated pidgin of influences with multiple regional dialects. Written Common is the language of
|
||||
traders, and can be relied upon to be understood by most peoples to a greater or lesser degree.
|
||||
|
||||
*Proitsiiiy be itkif eesof detytaen. Ojaot tyskuaz apsoo nirtoet prenao.*
|
||||
|
||||
**Common Names:**
|
||||
* Rubi Ca Momaman
|
||||
* "Quiet" Gushi Murk Lirpusome
|
||||
* Fewse Kerloborg
|
||||
|
||||
**Noble Common Names:**
|
||||
* Lord Pasti Quusi Maghiheim
|
||||
* Lady Gotki Lane Lopileigh III
|
||||
* Dame Cu Lehaberry IX
|
||||
@@ -0,0 +1,7 @@
|
||||
"""
|
||||
Common
|
||||
"""
|
||||
from .base import Language
|
||||
from .names import Name, NobleName
|
||||
|
||||
__all__ = [Language, Name, NobleName]
|
||||
@@ -0,0 +1,158 @@
|
||||
from language import types
|
||||
|
||||
from .rules import rules
|
||||
|
||||
vowels = types.WeightedSet(
|
||||
("a", 1.0),
|
||||
("e", 1.0),
|
||||
("i", 1.0),
|
||||
("o", 0.8),
|
||||
("u", 0.7),
|
||||
("y", 0.01),
|
||||
)
|
||||
consonants = types.WeightedSet(
|
||||
("b", 0.5),
|
||||
("c", 0.5),
|
||||
("d", 0.5),
|
||||
("f", 0.3),
|
||||
("g", 0.3),
|
||||
("h", 0.5),
|
||||
("j", 0.2),
|
||||
("k", 0.3),
|
||||
("l", 1.0),
|
||||
("m", 0.5),
|
||||
("n", 1.0),
|
||||
("p", 0.5),
|
||||
("q", 0.05),
|
||||
("r", 1.0),
|
||||
("s", 1.0),
|
||||
("t", 1.0),
|
||||
("v", 0.3),
|
||||
("w", 0.2),
|
||||
("x", 0.2),
|
||||
("y", 0.01),
|
||||
("z", 0.1),
|
||||
("bs", 0.3),
|
||||
("ct", 0.4),
|
||||
("ch", 0.4),
|
||||
("ck", 0.4),
|
||||
("dd", 0.2),
|
||||
("ff", 0.2),
|
||||
("gh", 0.3),
|
||||
("gs", 0.2),
|
||||
("ms", 0.4),
|
||||
("ns", 0.4),
|
||||
("ps", 0.3),
|
||||
("qu", 0.2),
|
||||
("rb", 0.1),
|
||||
("rd", 0.2),
|
||||
("rf", 0.1),
|
||||
("rk", 0.2),
|
||||
("rl", 0.2),
|
||||
("rm", 0.2),
|
||||
("rn", 0.2),
|
||||
("rp", 0.1),
|
||||
("rs", 0.75),
|
||||
("rt", 0.75),
|
||||
("ry", 0.5),
|
||||
("sh", 1.0),
|
||||
("sk", 0.5),
|
||||
("ss", 0.75),
|
||||
("st", 1.0),
|
||||
("sy", 0.5),
|
||||
("th", 1.0),
|
||||
("tk", 0.5),
|
||||
("ts", 1.0),
|
||||
("tt", 1.0),
|
||||
("ty", 1.0),
|
||||
("ws", 0.5),
|
||||
)
|
||||
|
||||
prefixes = types.equal_weights(["ex", "re", "pre", "de", "pro", "anti"], 0.05)
|
||||
|
||||
suffixes = types.equal_weights(
|
||||
[
|
||||
"ad",
|
||||
"ed",
|
||||
"id",
|
||||
"od",
|
||||
"ud",
|
||||
"af",
|
||||
"ef",
|
||||
"if",
|
||||
"of",
|
||||
"uf",
|
||||
"ah",
|
||||
"eh",
|
||||
"ih",
|
||||
"oh",
|
||||
"uh",
|
||||
"al",
|
||||
"el",
|
||||
"il",
|
||||
"ol",
|
||||
"ul",
|
||||
"am",
|
||||
"em",
|
||||
"im",
|
||||
"om",
|
||||
"um",
|
||||
"an",
|
||||
"en",
|
||||
"in",
|
||||
"on",
|
||||
"un",
|
||||
"ar",
|
||||
"er",
|
||||
"ir",
|
||||
"or",
|
||||
"ur",
|
||||
"as",
|
||||
"es",
|
||||
"is",
|
||||
"os",
|
||||
"us",
|
||||
"at",
|
||||
"et",
|
||||
"it",
|
||||
"ot",
|
||||
"ut",
|
||||
"ax",
|
||||
"ex",
|
||||
"ix",
|
||||
"ox",
|
||||
"ux",
|
||||
"ay",
|
||||
"ey",
|
||||
"iy",
|
||||
"oy",
|
||||
"uy",
|
||||
"az",
|
||||
"ez",
|
||||
"iz",
|
||||
"oz",
|
||||
"uz",
|
||||
"ing",
|
||||
],
|
||||
0.05,
|
||||
)
|
||||
|
||||
Language = types.Language(
|
||||
name="common",
|
||||
vowels=vowels,
|
||||
consonants=consonants,
|
||||
prefixes=prefixes,
|
||||
suffixes=suffixes,
|
||||
syllables=types.SyllableSet(
|
||||
(types.Syllable(template="vowel|consonant"), 0.01),
|
||||
(types.Syllable(template="vowel|consonant") * 2, 0.2),
|
||||
(types.Syllable(template="vowel|consonant") * 3, 0.4),
|
||||
(types.Syllable(template="vowel|consonant") * 3, 0.5),
|
||||
(types.Syllable(template="vowel|consonant") * 4, 1.0),
|
||||
(types.Syllable(template="vowel|consonant") * 5, 0.3),
|
||||
(types.Syllable(template="vowel|consonant") * 6, 0.2),
|
||||
(types.Syllable(template="vowel|consonant") * 7, 0.05),
|
||||
),
|
||||
rules=rules,
|
||||
minimum_grapheme_count=1,
|
||||
)
|
||||
@@ -0,0 +1,82 @@
|
||||
from language import defaults, types
|
||||
from language.languages.common import Language
|
||||
|
||||
suffixes = types.equal_weights(
|
||||
[
|
||||
"berg",
|
||||
"borg",
|
||||
"borough",
|
||||
"bury",
|
||||
"berry",
|
||||
"by",
|
||||
"ford",
|
||||
"gard",
|
||||
"grave",
|
||||
"grove",
|
||||
"gren",
|
||||
"hardt",
|
||||
"hart",
|
||||
"heim",
|
||||
"holm",
|
||||
"land",
|
||||
"leigh",
|
||||
"ley",
|
||||
"ly",
|
||||
"lof",
|
||||
"love",
|
||||
"lund",
|
||||
"man",
|
||||
"mark",
|
||||
"ness",
|
||||
"olf",
|
||||
"olph",
|
||||
"quist",
|
||||
"rop",
|
||||
"rup",
|
||||
"stad",
|
||||
"stead",
|
||||
"stein",
|
||||
"strom",
|
||||
"thal",
|
||||
"thorpe",
|
||||
"ton",
|
||||
"vall",
|
||||
"wich",
|
||||
"win",
|
||||
"some",
|
||||
"smith",
|
||||
"bridge",
|
||||
"cope",
|
||||
"town",
|
||||
"er",
|
||||
"don",
|
||||
"den",
|
||||
"dell",
|
||||
"son",
|
||||
]
|
||||
)
|
||||
|
||||
Name = types.NameGenerator(
|
||||
language=Language,
|
||||
syllables=types.SyllableSet(
|
||||
(types.Syllable(template="vowel|consonant"), 0.01),
|
||||
(types.Syllable(template="consonant,vowel"), 0.2),
|
||||
(types.Syllable(template="consonant,vowel") * 2, 1.0),
|
||||
),
|
||||
templates=types.NameSet(
|
||||
(types.NameTemplate("adjective,title,name,surname,count"), 1.0),
|
||||
(types.NameTemplate("title,name,name,surname,count"), 1.0),
|
||||
(types.NameTemplate("title,name,name,surname,surname,count"), 1.0),
|
||||
),
|
||||
names=None,
|
||||
surnames=None,
|
||||
nicknames=None,
|
||||
adjectives=defaults.adjectives,
|
||||
titles=defaults.titles,
|
||||
counts=defaults.counts,
|
||||
suffixes=suffixes,
|
||||
)
|
||||
Name.language.prefixes = None
|
||||
Name.language.suffixes = None
|
||||
|
||||
NobleName = Name
|
||||
@@ -0,0 +1,115 @@
|
||||
import logging
|
||||
import re
|
||||
|
||||
from language.rules import default_rules
|
||||
from language.types import Language
|
||||
|
||||
logger = logging.getLogger()
|
||||
|
||||
permitted_starting_clusters = [
|
||||
"bh",
|
||||
"bl",
|
||||
"br",
|
||||
"bw",
|
||||
"by",
|
||||
"ch",
|
||||
"cl",
|
||||
"cr",
|
||||
"cw",
|
||||
"cy",
|
||||
"dh",
|
||||
"dj",
|
||||
"dr",
|
||||
"dw",
|
||||
"dy",
|
||||
"fl",
|
||||
"fn",
|
||||
"fr",
|
||||
"fw",
|
||||
"fy",
|
||||
"gh",
|
||||
"gl",
|
||||
"gn",
|
||||
"gr",
|
||||
"gw",
|
||||
"gy",
|
||||
"hy",
|
||||
"jh",
|
||||
"jy",
|
||||
"kh",
|
||||
"kl",
|
||||
"kr",
|
||||
"kw",
|
||||
"ky",
|
||||
"ll",
|
||||
"ly",
|
||||
"mw",
|
||||
"my",
|
||||
"ny",
|
||||
"ph",
|
||||
"pl",
|
||||
"pn",
|
||||
"pr",
|
||||
"pw",
|
||||
"py",
|
||||
"rh",
|
||||
"ry",
|
||||
"sb",
|
||||
"sc",
|
||||
"sd",
|
||||
"sf",
|
||||
"sg",
|
||||
"sh",
|
||||
"sj",
|
||||
"sk",
|
||||
"sl",
|
||||
"sm",
|
||||
"sn",
|
||||
"sp",
|
||||
"sr",
|
||||
"st",
|
||||
"sv",
|
||||
"sw",
|
||||
"sy",
|
||||
"th",
|
||||
"tr",
|
||||
"tw",
|
||||
"ty",
|
||||
"vy",
|
||||
"wh",
|
||||
"wr",
|
||||
"wy",
|
||||
"xh",
|
||||
"xy",
|
||||
"yh",
|
||||
"zb",
|
||||
"zc",
|
||||
"zd",
|
||||
"zh",
|
||||
"zl",
|
||||
"zm",
|
||||
"zn",
|
||||
"zr",
|
||||
"zw",
|
||||
"zy",
|
||||
]
|
||||
|
||||
|
||||
def cannot_start_with_two_consonants(language: Language, word: str) -> bool:
|
||||
found = re.compile(r"(^[bcdfghjklmnpqrstvwxz]{2})").search(word)
|
||||
if not found:
|
||||
return True
|
||||
first, second = found.group(1)
|
||||
|
||||
if first == second:
|
||||
logger.debug(f"{word} starts with a repeated consonant.")
|
||||
return False
|
||||
|
||||
return found in permitted_starting_clusters
|
||||
|
||||
|
||||
rules = default_rules.union(
|
||||
{
|
||||
cannot_start_with_two_consonants,
|
||||
}
|
||||
)
|
||||
@@ -0,0 +1,23 @@
|
||||
### Draconic
|
||||
|
||||
The tongue of dragons and the Dragonborn. It is punctuated by low, gutteral
|
||||
grunts denoted by an apostrophe ('), the particular inflections of which can
|
||||
change the meaning of an utterance dramatically. When shouting, a speaker of
|
||||
Draconic should accentuate these grunts with spurts of flame, acid, ice, and so
|
||||
on.
|
||||
|
||||
The high form is reserved for the names of nobility -- that is, dragons -- who
|
||||
typically choose an appelation for themselves in the common tongue, the better
|
||||
to spread the terror of their name.
|
||||
|
||||
*Sey'so'jsii ysuut 'sei'gk gf'seiv 'se'su'rx 'se'yv hsi', sahsei' k'si'saa' f'si''see?*
|
||||
|
||||
**Draconic Names:**
|
||||
* V'Sei'Sey'a
|
||||
* Sir''Seytza
|
||||
* 'Soh'Suutus
|
||||
|
||||
**Noble (Dragon) Names:**
|
||||
* Seytthix the Willful
|
||||
* Saseezex the Enervated
|
||||
* Sahkzis the Miserly
|
||||
@@ -0,0 +1,7 @@
|
||||
"""
|
||||
Draconic
|
||||
"""
|
||||
from .base import Language
|
||||
from .names import Name, NobleName
|
||||
|
||||
__all__ = [Language, Name, NobleName]
|
||||
@@ -0,0 +1,47 @@
|
||||
from language import types
|
||||
|
||||
from .rules import rules
|
||||
|
||||
vowels = types.equal_weights(
|
||||
["sa", "saa", "sah", "se", "see", "sei", "sey", "si", "sii", "sir", "so", "su", "suu"], 1.0, blank=False
|
||||
)
|
||||
|
||||
consonants = types.WeightedSet(
|
||||
("d", 1.0),
|
||||
("f", 0.5),
|
||||
("g", 0.5),
|
||||
("h", 1.0),
|
||||
("j", 1.0),
|
||||
("k", 1.0),
|
||||
("l", 0.3),
|
||||
("n", 0.3),
|
||||
("r", 0.2),
|
||||
("t", 1.0),
|
||||
("v", 1.0),
|
||||
("x", 1.0),
|
||||
("y", 1.0),
|
||||
("z", 1.0),
|
||||
)
|
||||
|
||||
|
||||
class DraconicLanguage(types.Language):
|
||||
stops = types.equal_weights(["'"], 1.0)
|
||||
|
||||
def get_grapheme_vowel(self) -> str:
|
||||
return self.stops.random() + self.vowels.random() + self.stops.random()
|
||||
|
||||
|
||||
Language = DraconicLanguage(
|
||||
name="draconic",
|
||||
vowels=vowels,
|
||||
consonants=consonants,
|
||||
prefixes=None,
|
||||
suffixes=None,
|
||||
syllables=types.SyllableSet(
|
||||
(types.Syllable(template="consonant|vowel") * 2, 0.2),
|
||||
(types.Syllable(template="consonant|vowel") * 3, 1.0),
|
||||
(types.Syllable(template="consonant|vowel") * 4, 1.0),
|
||||
),
|
||||
rules=rules,
|
||||
minimum_grapheme_count=2,
|
||||
)
|
||||
@@ -0,0 +1,88 @@
|
||||
from language import defaults, types
|
||||
from language.languages.draconic import Language
|
||||
|
||||
# dragon_titles = types.equal_weights([
|
||||
# ], 1.0)
|
||||
|
||||
|
||||
class DraconicNameGenerator(types.NameGenerator):
|
||||
def __init__(self):
|
||||
super().__init__(
|
||||
language=Language,
|
||||
templates=types.NameSet(
|
||||
(types.NameTemplate("name"), 1.0),
|
||||
(types.NameTemplate("adjective,name"), 1.0),
|
||||
),
|
||||
adjectives=defaults.adjectives,
|
||||
)
|
||||
self.language.minimum_grapheme_count = 2
|
||||
self.suffixes = types.equal_weights(["us", "ius", "eus", "a", "an", "is"], 1.0, blank=False)
|
||||
|
||||
def get_name(self) -> str:
|
||||
return super().get_name() + self.suffixes.random()
|
||||
|
||||
|
||||
class NobleDraconicNameGenerator(types.NameGenerator):
|
||||
def __init__(self):
|
||||
super().__init__(
|
||||
language=Language,
|
||||
templates=types.NameSet(
|
||||
(types.NameTemplate("surname,the,title"), 1.0),
|
||||
),
|
||||
# titles=dragon_titles,
|
||||
syllables=types.SyllableSet(
|
||||
(types.Syllable(template="consonant|vowel") * 2, 1.0),
|
||||
),
|
||||
)
|
||||
self.language.minimum_grapheme_count = 2
|
||||
self.suffixes = types.equal_weights(
|
||||
[
|
||||
"thus",
|
||||
"thux",
|
||||
"thas",
|
||||
"thax",
|
||||
"this",
|
||||
"thix",
|
||||
"thes",
|
||||
"thex",
|
||||
"xus",
|
||||
"xux",
|
||||
"xas",
|
||||
"xax",
|
||||
"xis",
|
||||
"xix",
|
||||
"xes",
|
||||
"xex",
|
||||
"ssus",
|
||||
"ssux",
|
||||
"ssas",
|
||||
"ssax",
|
||||
"ssis",
|
||||
"ssix",
|
||||
"sses",
|
||||
"ssex",
|
||||
"zus",
|
||||
"zux",
|
||||
"zas",
|
||||
"zax",
|
||||
"zis",
|
||||
"zix",
|
||||
"zes",
|
||||
"zex",
|
||||
],
|
||||
1.0,
|
||||
blank=False,
|
||||
)
|
||||
|
||||
def get_title(self) -> str:
|
||||
p = ""
|
||||
while not p:
|
||||
p = defaults.personality.random()
|
||||
return p
|
||||
|
||||
def get_surname(self) -> str:
|
||||
return super().get_name().replace("'", "").title() + self.suffixes.random()
|
||||
|
||||
|
||||
Name = DraconicNameGenerator()
|
||||
NobleName = NobleDraconicNameGenerator()
|
||||
@@ -0,0 +1,7 @@
|
||||
import logging
|
||||
|
||||
from language.rules import default_rules
|
||||
|
||||
logger = logging.getLogger("draconic-rules")
|
||||
|
||||
rules = default_rules
|
||||
@@ -0,0 +1,14 @@
|
||||
### Dwarvish
|
||||
|
||||
Dwarvish words are short, sharp, and to the point. Much like the Dwarves
|
||||
themselves. This is "Low Dwarvish"; an ancient form of High Dwarvish still
|
||||
exists in some regions, notably the Dewa Q'Asos area of southern Vosh, but it
|
||||
is considered "dead" by most scholars and is reserved for arcane legal
|
||||
contracts (and those signifying a high social status).
|
||||
|
||||
*Dowêchâ khâ, natu phe tu, futê dêdachî pê she wu?*
|
||||
|
||||
**Dwarvish Names:**
|
||||
* "Black" Yzh Se
|
||||
* Ka Shidothir
|
||||
* Zhâ Syzhon
|
||||
@@ -0,0 +1,7 @@
|
||||
"""
|
||||
Dwarvish
|
||||
"""
|
||||
from .base import Language
|
||||
from .names import Name, NobleName
|
||||
|
||||
__all__ = [Language, Name, NobleName]
|
||||
@@ -0,0 +1,54 @@
|
||||
from language import types
|
||||
|
||||
from .rules import rules
|
||||
|
||||
vowels = types.WeightedSet(
|
||||
("a", 1.0),
|
||||
("e", 1.0),
|
||||
("i", 0.3),
|
||||
("o", 0.8),
|
||||
("u", 0.7),
|
||||
("y", 0.3),
|
||||
("j", 0.05),
|
||||
("î", 0.3),
|
||||
("ê", 1.0),
|
||||
("â", 1.0),
|
||||
("û", 1.0),
|
||||
)
|
||||
consonants = types.WeightedSet(
|
||||
("b", 0.3),
|
||||
("c", 0.5),
|
||||
("d", 1.0),
|
||||
("f", 0.5),
|
||||
("k", 1.0),
|
||||
("l", 0.3),
|
||||
("m", 0.3),
|
||||
("n", 0.3),
|
||||
("p", 1.0),
|
||||
("s", 1.0),
|
||||
("t", 1.0),
|
||||
("v", 0.5),
|
||||
("w", 0.5),
|
||||
("y", 0.3),
|
||||
("ph", 1.0),
|
||||
("th", 1.0),
|
||||
("ch", 1.0),
|
||||
("kh", 1.0),
|
||||
("zh", 1.0),
|
||||
("sh", 1.0),
|
||||
)
|
||||
|
||||
Language = types.Language(
|
||||
name="dwarvish",
|
||||
vowels=vowels,
|
||||
consonants=consonants,
|
||||
prefixes=None,
|
||||
suffixes=None,
|
||||
syllables=types.SyllableSet(
|
||||
(types.Syllable(template="consonant,vowel|consonant") * 1, 1.0),
|
||||
(types.Syllable(template="consonant,vowel|consonant") * 2, 0.5),
|
||||
(types.Syllable(template="consonant,vowel|consonant") * 3, 0.2),
|
||||
),
|
||||
rules=rules,
|
||||
minimum_grapheme_count=1,
|
||||
)
|
||||
@@ -0,0 +1,25 @@
|
||||
from language import defaults, types
|
||||
from language.languages.dwarvish import Language
|
||||
|
||||
|
||||
class DwarvishNameGenerator(types.NameGenerator):
|
||||
def __init__(self):
|
||||
super().__init__(
|
||||
language=Language,
|
||||
templates=types.NameSet(
|
||||
# (types.NameTemplate("adjective,name,nickname,surname"), 1.0),
|
||||
(types.NameTemplate("adjective,name,surname"), 1.0),
|
||||
),
|
||||
affixes=None,
|
||||
adjectives=defaults.adjectives,
|
||||
titles=defaults.titles,
|
||||
)
|
||||
self.language.minimum_grapheme_count = 2
|
||||
self.suffixes = types.equal_weights(["son", "sson", "zhon", "dottir", "dothir", "dottyr"], 1.0)
|
||||
|
||||
def get_surname(self) -> str:
|
||||
return super().get_surname() + self.suffixes.random()
|
||||
|
||||
|
||||
Name = DwarvishNameGenerator()
|
||||
NobleName = Name
|
||||
@@ -0,0 +1,24 @@
|
||||
import logging
|
||||
import re
|
||||
|
||||
from language.rules import default_rules
|
||||
from language.types import Language
|
||||
|
||||
logger = logging.getLogger("dwarvish-rules")
|
||||
|
||||
|
||||
def cannot_start_with_repeated_consonants(language: Language, word: str) -> bool:
|
||||
found = re.compile(r"(^[bcdfghklmnpqrstvwxz]{2})").search(word)
|
||||
if not found:
|
||||
return True
|
||||
|
||||
first, second = found.group(1)
|
||||
if first == second:
|
||||
logger.debug(f"{word} starts with a repeated consonant.")
|
||||
return False
|
||||
|
||||
return True
|
||||
|
||||
|
||||
rules = default_rules
|
||||
rules.add(cannot_start_with_repeated_consonants)
|
||||
@@ -0,0 +1,20 @@
|
||||
### Elvish
|
||||
|
||||
> The Elvish tongue flows like a river and pools upon the lips like sweetest wine. -- Anwin am Vakaralithien
|
||||
|
||||
Elvish is an ornate, multisyllabic language featuring a complex and nuanced set
|
||||
of vowel sounds that can take non-native speakers decades to master. Surnames
|
||||
are typically derived from place names; the more noble the name, the more
|
||||
baroque its construction.
|
||||
|
||||
*Aaclysmior uewhön fyaeiath nöagefniath iedyglion ryavies, eamwien acyöe, uëstr udrocrem!*
|
||||
|
||||
**Elvish Names:**
|
||||
* Afydyioth um Envyien
|
||||
* Wjillias am Aofll
|
||||
* Anyir um Edyoieth
|
||||
|
||||
**Noble Elvish Names:**
|
||||
* Uebs Sviiies um Udjsmierios
|
||||
* Nytyuia Oudryhn um Ioltier
|
||||
* Emyea Whonoel an Ofyediar
|
||||
@@ -0,0 +1,7 @@
|
||||
"""
|
||||
Elvish
|
||||
"""
|
||||
from .base import Language
|
||||
from .names import Name, NobleName
|
||||
|
||||
__all__ = [Language, Name, NobleName]
|
||||
@@ -0,0 +1,129 @@
|
||||
from language import types
|
||||
|
||||
from .rules import rules
|
||||
|
||||
vowels = types.WeightedSet(
|
||||
("a", 1.0),
|
||||
("e", 1.0),
|
||||
("i", 0.3),
|
||||
("o", 0.8),
|
||||
("u", 0.7),
|
||||
("y", 0.3),
|
||||
("j", 0.05),
|
||||
("ä", 0.1),
|
||||
("ë", 0.1),
|
||||
("ö", 0.1),
|
||||
("ü", 0.1),
|
||||
)
|
||||
consonants = types.WeightedSet(
|
||||
("b", 0.5),
|
||||
("c", 0.3),
|
||||
("d", 0.3),
|
||||
("f", 0.4),
|
||||
("g", 0.3),
|
||||
("h", 0.5),
|
||||
("k", 0.05),
|
||||
("l", 1.0),
|
||||
("m", 1.0),
|
||||
("n", 1.0),
|
||||
("p", 0.5),
|
||||
("r", 1.0),
|
||||
("s", 1.0),
|
||||
("t", 0.7),
|
||||
("v", 0.3),
|
||||
("w", 0.2),
|
||||
("y", 0.3),
|
||||
) + types.equal_weights(
|
||||
[
|
||||
"ch",
|
||||
"cl",
|
||||
"cr",
|
||||
"cw",
|
||||
"cy",
|
||||
"dh",
|
||||
"dj",
|
||||
"dr",
|
||||
"dw",
|
||||
"dy",
|
||||
"fl",
|
||||
"fn",
|
||||
"fr",
|
||||
"fw",
|
||||
"fy",
|
||||
"gl",
|
||||
"ll",
|
||||
"ly",
|
||||
"ml",
|
||||
"mw",
|
||||
"my",
|
||||
"ny",
|
||||
"rh",
|
||||
"ry",
|
||||
"sh",
|
||||
"sl",
|
||||
"sm",
|
||||
"sn",
|
||||
"st",
|
||||
"sv",
|
||||
"sw",
|
||||
"sy",
|
||||
"th",
|
||||
"tr",
|
||||
"tw",
|
||||
"ty",
|
||||
"vy",
|
||||
"wh",
|
||||
"wr",
|
||||
"wy",
|
||||
"yh",
|
||||
]
|
||||
)
|
||||
|
||||
suffixes = types.equal_weights(
|
||||
[
|
||||
"a",
|
||||
"i",
|
||||
"e",
|
||||
"t",
|
||||
"s",
|
||||
"m",
|
||||
"n",
|
||||
"l",
|
||||
"r",
|
||||
"d",
|
||||
"a",
|
||||
"th",
|
||||
"ss",
|
||||
"ieth",
|
||||
"ies",
|
||||
"ier",
|
||||
"ien",
|
||||
"iath",
|
||||
"ias",
|
||||
"iar",
|
||||
"ian",
|
||||
"ioth",
|
||||
"ios",
|
||||
"ior",
|
||||
"ion",
|
||||
],
|
||||
weight=1.0,
|
||||
)
|
||||
|
||||
Language = types.Language(
|
||||
name="elvish",
|
||||
vowels=vowels,
|
||||
consonants=consonants,
|
||||
prefixes=None,
|
||||
suffixes=suffixes,
|
||||
syllables=types.SyllableSet(
|
||||
(types.Syllable(template="vowel|consonant") * 3, 0.4),
|
||||
(types.Syllable(template="vowel|consonant") * 3, 0.5),
|
||||
(types.Syllable(template="vowel|consonant") * 4, 1.0),
|
||||
(types.Syllable(template="vowel|consonant") * 5, 0.5),
|
||||
(types.Syllable(template="vowel|consonant") * 6, 0.1),
|
||||
(types.Syllable(template="vowel|consonant") * 7, 0.1),
|
||||
),
|
||||
rules=rules,
|
||||
minimum_grapheme_count=3,
|
||||
)
|
||||
@@ -0,0 +1,77 @@
|
||||
from language import defaults, types
|
||||
from language.languages.elvish import Language
|
||||
from language.languages.elvish.base import suffixes
|
||||
|
||||
PlaceName = types.NameGenerator(
|
||||
language=Language,
|
||||
syllables=types.SyllableSet(
|
||||
(types.Syllable(template="vowel,vowel|consonant,vowel|consonant"), 1.0),
|
||||
(types.Syllable(template="consonant,vowel|consonant,vowel|consonant"), 0.3),
|
||||
),
|
||||
templates=types.NameSet(
|
||||
(types.NameTemplate("affix,name"), 1.0),
|
||||
),
|
||||
affixes=types.WeightedSet(("el", 1.0)),
|
||||
adjectives=defaults.adjectives,
|
||||
suffixes=suffixes,
|
||||
)
|
||||
|
||||
|
||||
class ElvishNameGenerator(types.NameGenerator):
|
||||
def __init__(self):
|
||||
super().__init__(
|
||||
language=Language,
|
||||
syllables=Language.syllables,
|
||||
templates=types.NameSet(
|
||||
(types.NameTemplate("name,affix,surname"), 1.0),
|
||||
),
|
||||
affixes=types.equal_weights(["am", "an", "al", "um"], weight=1.0, blank=False),
|
||||
adjectives=defaults.adjectives,
|
||||
titles=defaults.titles,
|
||||
suffixes=suffixes,
|
||||
)
|
||||
self.language.minimum_grapheme_count = 2
|
||||
self.place_generator = PlaceName
|
||||
|
||||
def get_surname(self) -> str:
|
||||
return self.place_generator.name()[0]["name"][0]
|
||||
|
||||
|
||||
class NobleElvishNameGenerator(types.NameGenerator):
|
||||
def __init__(self):
|
||||
super().__init__(
|
||||
language=Language,
|
||||
syllables=Language.syllables,
|
||||
templates=types.NameSet(
|
||||
(types.NameTemplate("name,name,affix,surname"), 1.0),
|
||||
),
|
||||
affixes=types.equal_weights(["am", "an", "al", "um"], weight=1.0, blank=False),
|
||||
adjectives=defaults.adjectives,
|
||||
titles=defaults.titles,
|
||||
)
|
||||
self.language.minimum_grapheme_count = 2
|
||||
self.place_generator = PlaceName
|
||||
self.suffixes = types.equal_weights(
|
||||
[
|
||||
"ieth",
|
||||
"ies",
|
||||
"ier",
|
||||
"ien",
|
||||
"iath",
|
||||
"ias",
|
||||
"iar",
|
||||
"ian",
|
||||
"ioth",
|
||||
"ios",
|
||||
"ior",
|
||||
"ion",
|
||||
],
|
||||
1.0,
|
||||
)
|
||||
|
||||
def get_surname(self) -> str:
|
||||
return self.place_generator.name()[0]["name"][0] + self.suffixes.random()
|
||||
|
||||
|
||||
Name = ElvishNameGenerator()
|
||||
NobleName = NobleElvishNameGenerator()
|
||||
@@ -0,0 +1,109 @@
|
||||
import logging
|
||||
import re
|
||||
|
||||
from language.types import Language
|
||||
|
||||
logger = logging.getLogger("elvish-rules")
|
||||
|
||||
permitted_starting_clusters = [
|
||||
"ch",
|
||||
"cl",
|
||||
"cr",
|
||||
"cw",
|
||||
"cy",
|
||||
"dh",
|
||||
"dj",
|
||||
"dr",
|
||||
"dw",
|
||||
"dy",
|
||||
"fl",
|
||||
"fn",
|
||||
"fr",
|
||||
"fw",
|
||||
"fy",
|
||||
"gl",
|
||||
"ll",
|
||||
"ly",
|
||||
"ml",
|
||||
"mw",
|
||||
"my",
|
||||
"ny",
|
||||
"rh",
|
||||
"ry",
|
||||
"sh",
|
||||
"sl",
|
||||
"sm",
|
||||
"sn",
|
||||
"st",
|
||||
"sv",
|
||||
"sw",
|
||||
"sy",
|
||||
"th",
|
||||
"tr",
|
||||
"tw",
|
||||
"ty",
|
||||
"vy",
|
||||
"wh",
|
||||
"wr",
|
||||
"wy",
|
||||
"yh",
|
||||
]
|
||||
|
||||
|
||||
def cannot_start_with_two_consonants(language: Language, word: str) -> bool:
|
||||
found = re.compile(r"(^[bcdfghklmnpqrstvwxz]{2})").search(word)
|
||||
if not found:
|
||||
return True
|
||||
|
||||
first, second = found.group(1)
|
||||
if first == second and first != "l":
|
||||
logger.debug(f"{word} starts with a repeated consonant.")
|
||||
return False
|
||||
|
||||
if found.group(1) not in permitted_starting_clusters:
|
||||
logger.debug("f{word} cannot start with {first}{second}")
|
||||
return False
|
||||
return True
|
||||
|
||||
|
||||
def too_many_vowels(language: Language, word: str) -> bool:
|
||||
found = re.compile(r"[" + "".join(language.vowels.members) + "]{4}").findall(word)
|
||||
if found == []:
|
||||
return True
|
||||
logger.debug(f"{word} has too many contiguous vowels: {found}")
|
||||
return False
|
||||
|
||||
|
||||
def too_many_consonants(language: Language, word: str) -> bool:
|
||||
found = re.compile(r"[bcdfghklmnprstvw]{3}").findall(word)
|
||||
if found == []:
|
||||
return True
|
||||
logger.debug(f"{word} has too many contiguous consonants: {found}")
|
||||
return False
|
||||
|
||||
|
||||
def cannot_have_just_repeated_vowels(language: Language, word: str) -> bool:
|
||||
if len(word) == 1:
|
||||
return True
|
||||
uniq = {letter for letter in word}
|
||||
if len(uniq) > 1:
|
||||
return True
|
||||
logger.debug(f"{word} consists of only one repeated letter.")
|
||||
return False
|
||||
|
||||
|
||||
def must_have_a_vowel(language: Language, word: str) -> bool:
|
||||
for vowel in language.vowels.members:
|
||||
if vowel in word:
|
||||
return True
|
||||
logger.debug(f"{word} does not contain a vowel.")
|
||||
return False
|
||||
|
||||
|
||||
rules = {
|
||||
must_have_a_vowel,
|
||||
too_many_vowels,
|
||||
too_many_consonants,
|
||||
cannot_have_just_repeated_vowels,
|
||||
cannot_start_with_two_consonants,
|
||||
}
|
||||
@@ -0,0 +1,13 @@
|
||||
### Gnomish
|
||||
|
||||
Several distinct dialects of Gnomish exist; a provincial Rock Gnome may not
|
||||
understand a Forest Gnome at all! This is "Golden Gnomish," the mother tongue
|
||||
of these localized variants, and functions much like Common -- a trader's
|
||||
tongue of common understanding.
|
||||
|
||||
*Nuio duy lao guey houe lo nouo, pia roa tai.*
|
||||
|
||||
**Gnomish Names:**
|
||||
* Fuey Voii
|
||||
* Juio See
|
||||
* Tuai Reaa
|
||||
@@ -0,0 +1,7 @@
|
||||
"""
|
||||
Gnomish
|
||||
"""
|
||||
from .base import Language
|
||||
from .names import Name, NobleName
|
||||
|
||||
__all__ = [Language, Name, NobleName]
|
||||
@@ -0,0 +1,48 @@
|
||||
from language import defaults, types
|
||||
|
||||
from .rules import rules
|
||||
|
||||
consonants = types.WeightedSet(
|
||||
("b", 0.5),
|
||||
("d", 0.5),
|
||||
("f", 0.3),
|
||||
("g", 0.3),
|
||||
("h", 0.5),
|
||||
("j", 0.2),
|
||||
("l", 1.0),
|
||||
("m", 0.5),
|
||||
("n", 1.0),
|
||||
("p", 0.5),
|
||||
("r", 1.0),
|
||||
("s", 1.0),
|
||||
("t", 1.0),
|
||||
("v", 0.3),
|
||||
("w", 0.2),
|
||||
("z", 0.1),
|
||||
)
|
||||
|
||||
suffixes = types.equal_weights(
|
||||
[
|
||||
"a",
|
||||
"e",
|
||||
"i",
|
||||
"o",
|
||||
"y",
|
||||
],
|
||||
1.0,
|
||||
blank=False,
|
||||
)
|
||||
|
||||
Language = types.Language(
|
||||
name="gnomish",
|
||||
vowels=defaults.vowels,
|
||||
consonants=consonants,
|
||||
prefixes=None,
|
||||
suffixes=suffixes,
|
||||
syllables=types.SyllableSet(
|
||||
(types.Syllable(template="consonant,vowel,vowel"), 1.0),
|
||||
(types.Syllable(template="consonant,vowel"), 0.33),
|
||||
),
|
||||
rules=rules,
|
||||
minimum_grapheme_count=2,
|
||||
)
|
||||
@@ -0,0 +1,10 @@
|
||||
from language import types
|
||||
from language.languages.gnomish import Language
|
||||
|
||||
Name = types.NameGenerator(
|
||||
language=Language,
|
||||
templates=types.NameSet(
|
||||
(types.NameTemplate("name,surname"), 1.0),
|
||||
),
|
||||
)
|
||||
NobleName = Name
|
||||
@@ -0,0 +1,7 @@
|
||||
import logging
|
||||
|
||||
from language.rules import default_rules
|
||||
|
||||
logger = logging.getLogger()
|
||||
|
||||
rules = default_rules
|
||||
@@ -0,0 +1,13 @@
|
||||
### Halfling
|
||||
|
||||
Halfings speak a trilling, lilting language with meaning and inflection rooted
|
||||
in meter. It has proven to be nearly impossisble for most non-Halflings to
|
||||
master, to the point that most cosmopolitan Halfings choose a Common nickname
|
||||
by which they are known.
|
||||
|
||||
*Siheme'li'ba'e lo'neno'ne'o, mo'tepa'ga'i wezyropi'a lo'se'ni'metyo zevypiwee vyta'mo'a, da'na'jo'lee ti'soe fe'soe!*
|
||||
|
||||
**Halfling Names:**
|
||||
* Hi'rina'pa'no'y Nylao Pe'lawyle'lo'a "Temperate"
|
||||
* Jo'la'rogi'o Mi'li're'ne'pe'y Terinite've'e "Wise"
|
||||
* Sa'la're'ta'je'o Re'dya Fetobo'a "Meritorious"
|
||||
@@ -0,0 +1,7 @@
|
||||
"""
|
||||
Halfling
|
||||
"""
|
||||
from .base import Language
|
||||
from .names import Name, NobleName
|
||||
|
||||
__all__ = [Language, Name, NobleName]
|
||||
@@ -0,0 +1,54 @@
|
||||
from language import types
|
||||
|
||||
from .rules import rules
|
||||
|
||||
vowels = types.equal_weights(["a'", "e'", "i'", "o'"], 1.0, blank=False) + types.equal_weights(
|
||||
["a", "e", "i", "o", "y"], 0.5, blank=False
|
||||
)
|
||||
|
||||
consonants = types.WeightedSet(
|
||||
("b", 0.5),
|
||||
("d", 0.5),
|
||||
("f", 0.3),
|
||||
("g", 0.3),
|
||||
("h", 0.5),
|
||||
("j", 0.2),
|
||||
("l", 1.0),
|
||||
("m", 0.5),
|
||||
("n", 1.0),
|
||||
("p", 0.5),
|
||||
("r", 1.0),
|
||||
("s", 1.0),
|
||||
("t", 1.0),
|
||||
("v", 0.3),
|
||||
("w", 0.2),
|
||||
("z", 0.1),
|
||||
)
|
||||
|
||||
suffixes = types.equal_weights(
|
||||
[
|
||||
"a",
|
||||
"e",
|
||||
"i",
|
||||
"o",
|
||||
"y",
|
||||
],
|
||||
1.0,
|
||||
blank=False,
|
||||
)
|
||||
|
||||
Language = types.Language(
|
||||
name="halfling",
|
||||
vowels=vowels,
|
||||
consonants=consonants,
|
||||
prefixes=None,
|
||||
suffixes=suffixes,
|
||||
syllables=types.SyllableSet(
|
||||
(types.Syllable(template="consonant,vowel") * 2, 0.5),
|
||||
(types.Syllable(template="consonant,vowel") * 3, 0.75),
|
||||
(types.Syllable(template="consonant,vowel") * 4, 1.0),
|
||||
(types.Syllable(template="consonant,vowel") * 5, 1.0),
|
||||
),
|
||||
rules=rules,
|
||||
minimum_grapheme_count=2,
|
||||
)
|
||||
@@ -0,0 +1,17 @@
|
||||
from language import defaults, types
|
||||
from language.languages.halfling import Language
|
||||
|
||||
|
||||
class HalflingNameGenerator(types.NameGenerator):
|
||||
def get_name(self) -> str:
|
||||
return super().get_name().lower().capitalize()
|
||||
|
||||
|
||||
Name = HalflingNameGenerator(
|
||||
language=Language,
|
||||
nicknames=defaults.positive_adjectives,
|
||||
templates=types.NameSet(
|
||||
(types.NameTemplate("name,name,name,nickname"), 1.0),
|
||||
),
|
||||
)
|
||||
NobleName = Name
|
||||
@@ -0,0 +1,7 @@
|
||||
import logging
|
||||
|
||||
from language.rules import default_rules
|
||||
|
||||
logger = logging.getLogger()
|
||||
|
||||
rules = default_rules
|
||||
@@ -0,0 +1,19 @@
|
||||
### Infernal
|
||||
|
||||
The language of devils is a collection of gutteral barks that is unmistakable,
|
||||
and unmistakably terrifying, to the ear of common folk. Traditional names
|
||||
typically begin with the name of the ruler of whatever circle of Hell the devil
|
||||
calls home, but some Tieflings (and others of Infernal origin) reject their
|
||||
Infernal legacies and choose less noble names.
|
||||
|
||||
*Z'zait cocf k'd z'xz t'ugoo! Yipd k'j x'euy, z'edu k'oczu!*
|
||||
|
||||
**Infernal Names:**
|
||||
* P'Utufus
|
||||
* Golden Bdaeus
|
||||
* Timeless Ujius
|
||||
|
||||
**Noble Infernal Names:**
|
||||
* Mephistopheles T'Xieis
|
||||
* Asmodeus T'Opakan
|
||||
* Mammon K'Nusan
|
||||
@@ -0,0 +1,7 @@
|
||||
"""
|
||||
Infernal
|
||||
"""
|
||||
from .base import Language
|
||||
from .names import Name, NobleName
|
||||
|
||||
__all__ = [Language, Name, NobleName]
|
||||
@@ -0,0 +1,52 @@
|
||||
from language import defaults, types
|
||||
|
||||
from .rules import rules
|
||||
|
||||
consonants = types.WeightedSet(
|
||||
("b", 1.0),
|
||||
("c", 1.0),
|
||||
("d", 1.0),
|
||||
("f", 0.5),
|
||||
("g", 0.5),
|
||||
("j", 1.0),
|
||||
("k", 1.0),
|
||||
("l", 0.3),
|
||||
("m", 0.3),
|
||||
("n", 0.3),
|
||||
("p", 1.0),
|
||||
("r", 0.2),
|
||||
("s", 0.1),
|
||||
("t", 1.0),
|
||||
("v", 1.0),
|
||||
("x", 1.0),
|
||||
("y", 1.0),
|
||||
("z", 1.0),
|
||||
)
|
||||
|
||||
prefixes = types.equal_weights(
|
||||
[
|
||||
"t'",
|
||||
"x'",
|
||||
"k'",
|
||||
"p'",
|
||||
"z'",
|
||||
],
|
||||
0.5,
|
||||
)
|
||||
|
||||
Language = types.Language(
|
||||
name="infernal",
|
||||
vowels=defaults.vowels,
|
||||
consonants=consonants,
|
||||
prefixes=prefixes,
|
||||
suffixes=None,
|
||||
syllables=types.SyllableSet(
|
||||
(types.Syllable(template="consonant|vowel") * 2, 0.05),
|
||||
(types.Syllable(template="consonant|vowel") * 3, 1.0),
|
||||
(types.Syllable(template="consonant|vowel") * 4, 0.75),
|
||||
(types.Syllable(template="consonant|vowel") * 5, 0.5),
|
||||
(types.Syllable(template="consonant|vowel") * 6, 0.25),
|
||||
),
|
||||
rules=rules,
|
||||
minimum_grapheme_count=2,
|
||||
)
|
||||
@@ -0,0 +1,87 @@
|
||||
from language import types
|
||||
from language.languages.infernal import Language
|
||||
|
||||
adjectives = types.equal_weights(
|
||||
[
|
||||
"eternal",
|
||||
"wondrous",
|
||||
"luminous",
|
||||
"perfect",
|
||||
"essential",
|
||||
"golden",
|
||||
"unfailing",
|
||||
"perpetual",
|
||||
"infinite",
|
||||
"exquisite",
|
||||
"sinless",
|
||||
"ultimate",
|
||||
"flawless",
|
||||
"timeless",
|
||||
"glorious",
|
||||
"absolute",
|
||||
"boundless",
|
||||
"true",
|
||||
"incredible",
|
||||
"virtuous",
|
||||
"supreme",
|
||||
"enchanted",
|
||||
"magnificent",
|
||||
"superior",
|
||||
"spectacular",
|
||||
"divine",
|
||||
],
|
||||
0.25,
|
||||
)
|
||||
|
||||
bloodlines = types.equal_weights(
|
||||
[
|
||||
"Asmodeus",
|
||||
"Baalzebul",
|
||||
"Rimmon",
|
||||
"Dispater",
|
||||
"Fierna",
|
||||
"Glasya",
|
||||
"Levistus",
|
||||
"Mammon",
|
||||
"Mephistopheles",
|
||||
"Zariel",
|
||||
]
|
||||
)
|
||||
|
||||
|
||||
class InfernalNameGenerator(types.NameGenerator):
|
||||
def __init__(self):
|
||||
super().__init__(
|
||||
language=Language,
|
||||
templates=types.NameSet(
|
||||
# (types.NameTemplate("adjective,name,nickname,surname"), 1.0),
|
||||
(types.NameTemplate("name"), 0.25),
|
||||
(types.NameTemplate("adjective,name"), 0.25),
|
||||
),
|
||||
adjectives=adjectives,
|
||||
)
|
||||
self.language.minimum_grapheme_count = 2
|
||||
self.suffixes = types.equal_weights(["us", "ius", "eus", "a", "an", "is"], 1.0, blank=False)
|
||||
|
||||
def get_name(self) -> str:
|
||||
return super().get_name() + self.suffixes.random()
|
||||
|
||||
|
||||
class NobleInfernalNameGenerator(types.NameGenerator):
|
||||
def __init__(self):
|
||||
super().__init__(
|
||||
language=Language,
|
||||
templates=types.NameSet(
|
||||
(types.NameTemplate("adjective,name"), 1.0),
|
||||
),
|
||||
adjectives=bloodlines,
|
||||
)
|
||||
self.language.minimum_grapheme_count = 2
|
||||
self.suffixes = types.equal_weights(["us", "ius", "to", "tro", "eus", "a", "an", "is"], 1.0, blank=False)
|
||||
|
||||
def get_name(self) -> str:
|
||||
return super().get_name() + self.suffixes.random()
|
||||
|
||||
|
||||
Name = InfernalNameGenerator()
|
||||
NobleName = NobleInfernalNameGenerator()
|
||||
@@ -0,0 +1,7 @@
|
||||
import logging
|
||||
|
||||
from language.rules import default_rules
|
||||
|
||||
logger = logging.getLogger("infernal-rules")
|
||||
|
||||
rules = default_rules
|
||||
@@ -0,0 +1,14 @@
|
||||
### Lizardfolk
|
||||
|
||||
The Lizardfolk language is a unique form of telepathy borne by pheramonne
|
||||
exchange. It is literally impossible for non-Lizardfolk to speak it, though
|
||||
with practice they can learn to recognize particular smells. Lizardfolk names
|
||||
are collections of scent pattterns, the first of which denotes the Lizardfolk's
|
||||
family origins.
|
||||
|
||||
*[No written language]*
|
||||
|
||||
**Lizardfolk Name Scents:**
|
||||
* Carmelized Roast Pomegranate
|
||||
* Rotting Hazelnut Citric
|
||||
* Pepper Broth Grape
|
||||
@@ -0,0 +1,7 @@
|
||||
"""
|
||||
Lizardfolk
|
||||
"""
|
||||
from .base import Language
|
||||
from .names import Name, NobleName
|
||||
|
||||
__all__ = [Language, Name, NobleName]
|
||||
@@ -0,0 +1,118 @@
|
||||
from language import types
|
||||
|
||||
scents = types.equal_weights(
|
||||
[
|
||||
"honey",
|
||||
"caramel",
|
||||
"maple syrup",
|
||||
"molasses",
|
||||
"dark chocolate",
|
||||
"chocolate",
|
||||
"almond",
|
||||
"hazelnut",
|
||||
"peanut",
|
||||
"clove",
|
||||
"cinnamon",
|
||||
"nutmeg",
|
||||
"anise",
|
||||
"malt",
|
||||
"grain",
|
||||
"roast",
|
||||
"smoke",
|
||||
"ash",
|
||||
"acrid",
|
||||
"rubber",
|
||||
"skunk",
|
||||
"petroleum",
|
||||
"medicine",
|
||||
"salt",
|
||||
"bitter",
|
||||
"phrenolic",
|
||||
"meat",
|
||||
"broth",
|
||||
"animal",
|
||||
"musty",
|
||||
"earth",
|
||||
"mould",
|
||||
"damp",
|
||||
"wood",
|
||||
"paper",
|
||||
"cardboard",
|
||||
"stale",
|
||||
"herb",
|
||||
"hay",
|
||||
"grass",
|
||||
"peapod",
|
||||
"whisky",
|
||||
"wine",
|
||||
"malic",
|
||||
"citric",
|
||||
"isovaleric",
|
||||
"butyric",
|
||||
"acetic",
|
||||
"lime",
|
||||
"lemon",
|
||||
"orange",
|
||||
"grapefruit",
|
||||
"pear",
|
||||
"peach",
|
||||
"apple",
|
||||
"grape",
|
||||
"pineapple",
|
||||
"pomegranate",
|
||||
"cherry",
|
||||
"coconut",
|
||||
"prune",
|
||||
"raisin",
|
||||
"strawberry",
|
||||
"blueberry",
|
||||
"raspberry",
|
||||
"blackberry",
|
||||
"jasmine",
|
||||
"rose",
|
||||
"camomile",
|
||||
"tobacco",
|
||||
],
|
||||
1.0,
|
||||
blank=False,
|
||||
)
|
||||
|
||||
family = types.equal_weights(
|
||||
[
|
||||
"sweet",
|
||||
"floral",
|
||||
"fruity",
|
||||
"sour",
|
||||
"fermented",
|
||||
"green",
|
||||
"vegetal",
|
||||
"old",
|
||||
"roasted",
|
||||
"spiced",
|
||||
"nutty",
|
||||
"cocoa",
|
||||
"pepper",
|
||||
"pungent",
|
||||
"burnt",
|
||||
"carmelized",
|
||||
"raw",
|
||||
"rotting",
|
||||
"dead",
|
||||
"young",
|
||||
],
|
||||
1.0,
|
||||
blank=False,
|
||||
)
|
||||
|
||||
Language = types.Language(
|
||||
name="lizardfolk",
|
||||
vowels=scents,
|
||||
consonants=family,
|
||||
prefixes=None,
|
||||
suffixes=None,
|
||||
syllables=types.SyllableSet(
|
||||
(types.Syllable(template="vowel"), 1.0),
|
||||
),
|
||||
rules=(),
|
||||
minimum_grapheme_count=1,
|
||||
)
|
||||
@@ -0,0 +1,19 @@
|
||||
from language import types
|
||||
from language.languages.lizardfolk import Language
|
||||
|
||||
|
||||
class LizardfolkNameGenerator(types.NameGenerator):
|
||||
def __init__(self):
|
||||
super().__init__(
|
||||
language=Language,
|
||||
templates=types.NameSet(
|
||||
(types.NameTemplate("surname,name,name"), 1.0),
|
||||
),
|
||||
)
|
||||
|
||||
def get_surname(self) -> str:
|
||||
return self.language.consonants.random().title()
|
||||
|
||||
|
||||
Name = LizardfolkNameGenerator()
|
||||
NobleName = Name
|
||||
@@ -0,0 +1,13 @@
|
||||
### Orcish
|
||||
|
||||
Spoken by Full- and Half-Orcs alike, Orcish bears some similarlities to
|
||||
Dwarvish's clipped, mono-syllablic construction. They differ in Half-Orc's
|
||||
prominent use of sibilants, perhaps as a result of being spoken by people with
|
||||
large, protruding tusks.
|
||||
|
||||
*Dbod hanot neb, hushi dupo shiza fesha keke fucha tpu.*
|
||||
|
||||
**Orcish Names:**
|
||||
* "Mad" Nha Pazk
|
||||
* Zashi Dizh
|
||||
* Pik Decht
|
||||
@@ -0,0 +1,7 @@
|
||||
"""
|
||||
Orcish
|
||||
"""
|
||||
from .base import Language
|
||||
from .names import Name, NobleName
|
||||
|
||||
__all__ = [Language, Name, NobleName]
|
||||
@@ -0,0 +1,36 @@
|
||||
from language import defaults, types
|
||||
|
||||
from .rules import rules
|
||||
|
||||
consonants = types.WeightedSet(
|
||||
("b", 1.0),
|
||||
("c", 1.0),
|
||||
("d", 1.0),
|
||||
("f", 0.5),
|
||||
("h", 1.0),
|
||||
("k", 1.0),
|
||||
("m", 0.3),
|
||||
("n", 0.3),
|
||||
("p", 1.0),
|
||||
("r", 0.2),
|
||||
("s", 0.1),
|
||||
("t", 1.0),
|
||||
("z", 1.0),
|
||||
("ch", 1.0),
|
||||
("sh", 0.7),
|
||||
("br", 1.0),
|
||||
)
|
||||
|
||||
Language = types.Language(
|
||||
name="orcish",
|
||||
vowels=defaults.vowels,
|
||||
consonants=consonants,
|
||||
prefixes=None,
|
||||
suffixes=None,
|
||||
syllables=types.SyllableSet(
|
||||
(types.Syllable(template="consonant,vowel") * 2, 1.0),
|
||||
(types.Syllable(template="consonant,vowel,consonant,vowel,consonant"), 0.5),
|
||||
),
|
||||
rules=rules,
|
||||
minimum_grapheme_count=1,
|
||||
)
|
||||
@@ -0,0 +1,60 @@
|
||||
from language import defaults, types
|
||||
from language.languages.orcish import Language
|
||||
|
||||
|
||||
class OrcishNameGenerator(types.NameGenerator):
|
||||
def __init__(self):
|
||||
super().__init__(
|
||||
language=Language,
|
||||
templates=types.NameSet(
|
||||
# (types.NameTemplate("adjective,name,nickname,surname"), 1.0),
|
||||
(types.NameTemplate("adjective,name,surname"), 1.0),
|
||||
),
|
||||
affixes=None,
|
||||
adjectives=defaults.adjectives,
|
||||
titles=defaults.titles,
|
||||
)
|
||||
self.language.minimum_grapheme_count = 2
|
||||
self.suffixes = types.equal_weights(
|
||||
[
|
||||
"acht",
|
||||
"echt",
|
||||
"icht",
|
||||
"ocht",
|
||||
"ucht",
|
||||
"ak",
|
||||
"ek",
|
||||
"ik",
|
||||
"ok",
|
||||
"uk",
|
||||
"ach",
|
||||
"ech",
|
||||
"ich",
|
||||
"och",
|
||||
"uch",
|
||||
"atch",
|
||||
"etch",
|
||||
"itch",
|
||||
"otch",
|
||||
"utch",
|
||||
"azk",
|
||||
"ezk",
|
||||
"izk",
|
||||
"ozk",
|
||||
"uzk",
|
||||
"azh",
|
||||
"ezh",
|
||||
"izh",
|
||||
"ozh",
|
||||
"uzh",
|
||||
],
|
||||
1.0,
|
||||
blank=False,
|
||||
)
|
||||
|
||||
def get_surname(self) -> str:
|
||||
return self.language.add_grapheme(word="", template="consonant").strip().title() + self.suffixes.random()
|
||||
|
||||
|
||||
Name = OrcishNameGenerator()
|
||||
NobleName = Name
|
||||
@@ -0,0 +1,24 @@
|
||||
import logging
|
||||
import re
|
||||
|
||||
from language.rules import default_rules
|
||||
from language.types import Language
|
||||
|
||||
logger = logging.getLogger("orcish-rules")
|
||||
|
||||
|
||||
def cannot_start_with_repeated_consonants(language: Language, word: str) -> bool:
|
||||
found = re.compile(r"(^[bcdfghklmnpqrstvwxz]{3})").search(word)
|
||||
if not found:
|
||||
return True
|
||||
|
||||
first, second, third = found.group(1)
|
||||
if first == second == third:
|
||||
logger.debug(f"{word} starts with a repeated consonant.")
|
||||
return False
|
||||
|
||||
return True
|
||||
|
||||
|
||||
rules = default_rules
|
||||
rules.add(cannot_start_with_repeated_consonants)
|
||||
@@ -0,0 +1,18 @@
|
||||
### Undercommon
|
||||
|
||||
The language of the Drow is the defacto language of the Underdark, and is
|
||||
spoken by most peoples there. Like the Drow themselves, Undercommon diverged
|
||||
from an Elvish dialect in ancient times. The two still bear some resemblance,
|
||||
notably in the construction of names.
|
||||
|
||||
*Okvösaa licopod lohiwia uüyötüe uywubit uegäsit uäpisoa, caquyee redoxöd, mraomoa.*
|
||||
|
||||
**Undercommon Names:**
|
||||
* Tfubam Umaiuhüen
|
||||
* Nanosd Aneedaöbaas
|
||||
* Rerwus Amzuremolr
|
||||
|
||||
**Noble Undercommon (Drow) Names:**
|
||||
* Uopiyie Alzejakäurn
|
||||
* Opyäulol Elchöläss
|
||||
* Iqyäuwed Anlcoduir
|
||||
@@ -0,0 +1,7 @@
|
||||
"""
|
||||
Undercommon
|
||||
"""
|
||||
from .base import Language
|
||||
from .names import Name, NobleName
|
||||
|
||||
__all__ = [Language, Name, NobleName]
|
||||
@@ -0,0 +1,21 @@
|
||||
from language import defaults, types
|
||||
|
||||
from .rules import rules
|
||||
|
||||
vowels = defaults.vowels + types.equal_weights(["ä", "ö", "ü", "äu"], 0.5, blank=False)
|
||||
prefixes = defaults.vowels + types.equal_weights(["c", "g", "l", "m", "n", "r", "s", "t", "v", "z"], 1.0, blank=False)
|
||||
suffixes = types.equal_weights(["a", "e", "i", "t", "s", "m", "n", "l", "r", "d", "a", "th"], 1.0, blank=False)
|
||||
|
||||
Language = types.Language(
|
||||
name="undercommon",
|
||||
vowels=vowels,
|
||||
consonants=defaults.consonants,
|
||||
prefixes=prefixes,
|
||||
suffixes=suffixes,
|
||||
syllables=types.SyllableSet(
|
||||
(types.Syllable(template="vowel,consonant,vowel") * 2, 0.15),
|
||||
(types.Syllable(template="consonant|vowel,consonant,vowel,consonant,vowel"), 1.0),
|
||||
),
|
||||
rules=rules,
|
||||
minimum_grapheme_count=2,
|
||||
)
|
||||
@@ -0,0 +1,37 @@
|
||||
import random
|
||||
|
||||
from language import defaults, types
|
||||
from language.languages.undercommon import Language
|
||||
|
||||
PlaceName = types.NameGenerator(
|
||||
language=Language,
|
||||
syllables=Language.syllables,
|
||||
templates=types.NameSet(
|
||||
(types.NameTemplate("affix,name"), 1.0),
|
||||
),
|
||||
affixes=types.WeightedSet(("el", 1.0)),
|
||||
adjectives=defaults.adjectives,
|
||||
suffixes=Language.suffixes,
|
||||
)
|
||||
|
||||
|
||||
class DrowName(types.NameGenerator):
|
||||
def __init__(self):
|
||||
super().__init__(
|
||||
language=Language,
|
||||
syllables=Language.syllables,
|
||||
templates=types.NameSet(
|
||||
(types.NameTemplate("name,surname"), 1.0),
|
||||
),
|
||||
)
|
||||
self.language.minimum_grapheme_count = 2
|
||||
self.place_generator = PlaceName
|
||||
self.affixes = types.equal_weights(["am", "an", "al", "um"], weight=1.0, blank=False)
|
||||
|
||||
def get_surname(self) -> str:
|
||||
name = self.place_generator.name()[0]["name"][0]
|
||||
return (self.affixes.random() + name + random.choice(["th", "s", "r", "n"])).title()
|
||||
|
||||
|
||||
Name = DrowName()
|
||||
NobleName = Name
|
||||
@@ -0,0 +1,88 @@
|
||||
import logging
|
||||
import re
|
||||
|
||||
from language.rules import default_rules
|
||||
from language.types import Language
|
||||
|
||||
logger = logging.getLogger()
|
||||
|
||||
valid_consonant_sequences = [
|
||||
"cc",
|
||||
"ht",
|
||||
"kd",
|
||||
"kl",
|
||||
"km",
|
||||
"kp",
|
||||
"kt",
|
||||
"kv",
|
||||
"kw",
|
||||
"ky",
|
||||
"lc",
|
||||
"ld",
|
||||
"lf",
|
||||
"ll",
|
||||
"lm",
|
||||
"lp",
|
||||
"lt",
|
||||
"lv",
|
||||
"lw",
|
||||
"ly",
|
||||
"mb",
|
||||
"mm",
|
||||
"mp",
|
||||
"my",
|
||||
"nc",
|
||||
"nd",
|
||||
"ng",
|
||||
"nn",
|
||||
"nt",
|
||||
"nw",
|
||||
"ny",
|
||||
"ps",
|
||||
"pt",
|
||||
"rc",
|
||||
"rd",
|
||||
"rm",
|
||||
"rn",
|
||||
"rp",
|
||||
"rr",
|
||||
"rs",
|
||||
"rt",
|
||||
"rw",
|
||||
"ry",
|
||||
"sc",
|
||||
"ss",
|
||||
"ts",
|
||||
"tt",
|
||||
"th",
|
||||
"tw",
|
||||
"ty",
|
||||
]
|
||||
|
||||
|
||||
def valid_sequences(language: Language, word: str) -> bool:
|
||||
found = re.compile(r"([bcdfghjklmnpqrstvwxz]{2})").findall(word)
|
||||
if not found:
|
||||
return True
|
||||
|
||||
invalid = [seq for seq in found if seq not in valid_consonant_sequences]
|
||||
if invalid:
|
||||
logger.debug(f"{word} contains invalid consonant sequences: {invalid}")
|
||||
return False
|
||||
return True
|
||||
|
||||
|
||||
def too_many_vowels(language: Language, word: str) -> bool:
|
||||
found = re.compile(r"[" + "".join(language.vowels.members) + r"]{3}").findall(word)
|
||||
if found == []:
|
||||
return True
|
||||
logger.debug(f"{word} has too many contiguous vowels: {found}")
|
||||
return False
|
||||
|
||||
|
||||
rules = default_rules.union(
|
||||
{
|
||||
valid_sequences,
|
||||
too_many_vowels,
|
||||
}
|
||||
)
|
||||
Reference in New Issue
Block a user