Skip to main content

Wyrdbound Random Name Generator

A comprehensive random name generator library for tabletop RPGs, designed to create authentic-sounding names by analyzing and recombining syllables from existing name corpora.

This library is designed for use in wyrdbound, a text-based RPG system that emphasizes narrative and player choice.

CI Python 3.8+ License: MIT Ruff

📣 This library is experimental and was built with much ❤️ and vibe coding. Perfect for your tabletop RPG adventures, but maybe not for launching 🚀 or performing 🧠 surgery! Enjoy!

Features

Simplified Interface

  • Built-in Name Lists: Reference name corpora using simple identifiers
  • Auto-Discovery: Automatically finds built-in name lists without specifying file paths
  • Flexible Input: Supports both built-in identifiers and custom file paths
  • Help Integration: CLI tools show available built-in name lists in help text

Multiple Generation Algorithms

  • Very Simple: Quick and random syllable combination
  • Simple: Basic syllable recombination with weighted selection
  • Bayesian: Advanced probabilistic analysis for more realistic names

Flexible Segmentation

  • Fantasy Names: Optimized for Western fantasy naming conventions
  • Japanese Names: Specialized for Japanese name syllable patterns
  • Extensible: Easy to add new segmentation strategies

YAML Input Format

  • Built-in Name Lists: Use simple identifiers for included corpora
  • Custom YAML Files: Support for user-provided YAML files with metadata
  • Mixed Sources: Combine multiple input files and built-in lists

Advanced Analysis

  • Syllable Statistics: Detailed breakdown of syllable patterns
  • Probability Analysis: Bayesian probability calculations
  • Corpus Validation: Check if generated names exist in source data
  • Source Tracking: Track which names influenced generation

Installation

pip install wyrdbound-rng

Quick Start

from wyrdbound_rng import Generator, FantasyNameSegmenter

# Create generator with built-in name list (simple identifier)
generator = Generator("generic-fantasy", segmenter=FantasyNameSegmenter())

# Generate a name using the simple algorithm
name = generator.generate_name(max_len=12, algorithm='simple')
print(name.name)  # "Aldric"

# Generate using Bayesian algorithm for more realistic results
name = generator.generate_name(max_len=12, algorithm='bayesian')
print(name.name)  # "Theron"
print(f"Probability: {name.probability:.2e}")

# You can also use custom YAML files
custom_generator = Generator("./my-custom-names.yaml")

Command Line Usage

# Generate 5 names using built-in name list identifier
wyrdbound-rng --list generic-fantasy

# Generate 10 names with Bayesian algorithm
wyrdbound-rng --list japanese-sengoku -n 10 -a bayesian --segmenter japanese

# Show syllable breakdown and sources
wyrdbound-rng --list generic-fantasy --syllables --show-sources

# Show analysis info: corpus existence for all algorithms, plus probability for Bayesian
wyrdbound-rng --list generic-fantasy --show-analysis

# Bayesian algorithm with full analysis (probability + corpus existence)
wyrdbound-rng --list generic-fantasy --show-analysis -a bayesian

# Analyze probability for specific syllables
wyrdbound-rng --list generic-fantasy --probabilities "ar" -a bayesian

# You can also use custom YAML files
wyrdbound-rng --list /path/to/your/custom-names.yaml
wyrdbound-rng --list ./my-names.yaml

Supported Name Corpora

The library comes with several built-in name corpora. You can reference them using simple identifiers:

Built-in Name Lists

  • generic-fantasy - Traditional Western fantasy names (mixed)
  • generic-fantasy-male - Traditional Western fantasy male names
  • generic-fantasy-female - Traditional Western fantasy female names
  • ancestry-dwarf-male - Dwarf names, Old Norse / Old Icelandic register
  • ancestry-dwarf-female - Dwarf names, feminine Old Norse register
  • ancestry-elf-male - Elf names, Welsh / Brythonic register
  • ancestry-elf-female - Elf names, feminine Welsh register
  • ancestry-halfling-male - Halfling names, medieval English hypocoristics
  • ancestry-halfling-female - Halfling names, feminine pet-forms
  • ancestry-human-male - Human names, Frankish / Norman register
  • ancestry-human-female - Human names, feminine Frankish register
  • ancestry-goblin-male - Goblin names, original constructed phonology
  • ancestry-goblin-female - Goblin names, feminine constructed phonology
  • japanese-sengoku - Historical Japanese names from the Sengoku period (mixed)
  • japanese-sengoku-clan - Japanese Sengoku clan names
  • japanese-sengoku-daimyo - Japanese Sengoku daimyo names
  • japanese-sengoku-religious - Japanese Sengoku religious names
  • japanese-sengoku-rogue - Japanese Sengoku rogue names
  • japanese-sengoku-samurai - Japanese Sengoku samurai names
  • japanese-sengoku-women - Japanese Sengoku women names
  • japanese-swordsmen - Japanese swordsmen names
  • warhammer40k-space-marine-names - Warhammer 40k Space Marine names

Custom Files

You can also provide your own YAML files using relative or absolute paths:

  • ./my-names.yaml - Relative path
  • /absolute/path/to/names.yaml - Absolute path

Data directory override

Set WYRDBOUND_RNG_DATA_DIR to point the resolver at your own corpora directory instead of the packaged one:

WYRDBOUND_RNG_DATA_DIR=/path/to/corpora wyrdbound-rng --list my-list

Reproducible generation

Pass a random.Random to get identical names from the same seed:

import random
from wyrdbound_rng import Generator

generator = Generator("ancestry-elf-female", rng=random.Random(42))
names = [generator.generate_name(11, "bayesian").name for _ in range(5)]

Omitting rng uses the module-level random, so existing callers are unchanged.

API Reference

Main Classes

Generator

The main entry point for name generation.

Generator(name_source, segmenter=None, rng=None)
  • name_source: Built-in name list identifier (e.g., "generic-fantasy") or path to YAML file
  • segmenter: Syllable segmentation strategy (optional, auto-detected from YAML metadata)
  • rng: random.Random instance for reproducible generation (optional; defaults to the module-level random)

Methods:

  • generate_name(max_len, algorithm='simple', min_probability_threshold=1e-8, min_len=3): Generate a single name
  • generate(n, max_chars=15, algorithm='simple', min_probability_threshold=1e-8, min_len=3): Generate multiple names
  • name_exists_in_corpus(name): Check if a name exists in the source corpus

min_len rejects names shorter than the given length (default 3); it must not exceed max_len.

Name validity. Generated names are validated against a cluster inventory derived from the loaded corpus. The unit is the inter-nuclear consonant cluster — the run of consonants between one vowel and the next, plus the word-initial and word-final runs (y counts as a vowel) — and a cluster is legal if it was observed in the corpus at that position or splits into an attested onset plus an attested coda in either order. This is what lets a legitimate novel combination like Ragnrikr through (gnv is attested in Ragnvindr) while rejecting Hrgils. A corpus below 100 names is too sparse to derive a rule from and falls back to the earlier four-consonant heuristic.

GeneratedName

Represents a generated name with metadata.

Properties:

  • name (str): The generated name
  • syllables (list): List of syllables used
  • source_names (list): Names that influenced generation
  • probability (float): Bayesian probability (if applicable)
  • exists_in_corpus (bool): Whether name exists in source data

Segmenters

FantasyNameSegmenter

Optimized for Western fantasy names.

JapaneseNameSegmenter

Specialized for Japanese name patterns.

Data Format

YAML Format

The YAML format is used to define name corpora with metadata. Below is an example structure:

metadata:
  description: Fantasy names from Middle-earth
  segmenter: fantasy
  sources:
    - The Lord of the Rings by J.R.R. Tolkien
  version: "1.0"
names:
  - Aragorn
  - Arwen
  - Bilbo
  - Boromir
  - Frodo
  - Gandalf
  - Gimli
  - Legolas
  - Samwise

Each entry in the names list represents a name. The metadata section provides additional information about the corpus, including its description, segmentation strategy, sources, and version.

Command Line Tools

Generate Names

wyrdbound-rng --list <name_source> [options]

Options:
  -l, --list SOURCE     Built-in name list identifier or path to YAML file (required)
  -n, --number N        Number of names to generate (default: 5)
  --length N            Maximum name length (default: 12)
  -a, --algorithm ALG   Algorithm: simple, bayesian, very_simple (default: simple)
  -s, --segmenter SEG   Segmenter: fantasy, japanese (default: fantasy)
  --show-sources        Show source names used in generation
  --show-analysis       Show analysis info: corpus existence for all algorithms, plus probability for bayesian
  --min-probability N   Minimum probability threshold (default: 1e-8)
  --syllables           Show syllable breakdown
  --probabilities SYL   Analyze probability for specific syllable(s) (comma-separated)

Advanced Tools

The tools/ directory contains additional command-line utilities for advanced analysis and generation.

Corpus Analysis Tool

python tools/analyze.py --list <name_source> [options]

Options:
  -l, --list SOURCE     Built-in name list identifier or path to YAML file (required)
  -s, --segmenter SEG   Segmenter: fantasy, japanese (default: fantasy)
  -v, --verbose         Show detailed analysis including name/syllable length statistics
  --top-syllables N     Number of top syllables to show (default: 20)
  --json                Output results as JSON

Example:

# Basic analysis
python tools/analyze.py --list generic-fantasy

# Detailed analysis with top 30 syllables
python tools/analyze.py --list japanese-sengoku -v --top-syllables 30 -s japanese

# JSON output for data processing
python tools/analyze.py --list generic-fantasy --json > analysis.json

# Analyze custom file
python tools/analyze.py --list ./my-names.yaml

Advanced Generation Tool

python tools/generate.py --list <name_source> [options]

Options:
  -l, --list SOURCE     Built-in name list identifier or path to YAML file (required)
  -n, --count N         Number of names to generate (default: 1)
  -a, --algorithm ALG   Algorithm: simple, bayesian, very_simple (default: simple)
  -s, --segmenter SEG   Segmenter: fantasy, japanese (default: fantasy)
  --json                Output results as JSON
  -v, --verbose         Show detailed breakdown (syllables, sources, probability)
  --min-probability N   Minimum probability threshold for bayesian generation
  --max-length N        Maximum name length (default: 12)

Example:

# Generate single name with detailed info
python tools/generate.py --list generic-fantasy -v -a bayesian

# Generate 5 names as JSON for data processing
python tools/generate.py --list japanese-sengoku -n 5 --json -s japanese

# Batch generation with custom parameters
python tools/generate.py --list generic-fantasy -n 100 -a bayesian --min-probability 1e-6

# Use custom file
python tools/generate.py --list ./my-names.yaml -n 5

Examples

Basic Usage

from wyrdbound_rng import Generator, FantasyNameSegmenter

# Create generator using built-in name list
generator = Generator("generic-fantasy", segmenter=FantasyNameSegmenter())

# Generate names
for i in range(5):
    name = generator.generate_name(max_len=12, algorithm='simple')
    print(f"{i+1}. {name.name}")

# You can also use custom files
custom_generator = Generator("./my-names.yaml")

Advanced Analysis

# Generate with probability analysis
name = generator.generate_name(max_len=12, algorithm='bayesian', min_probability_threshold=1e-6)
print(f"Name: {name.name}")
print(f"Probability: {name.probability:.2e}")
print(f"Exists in corpus: {generator.name_exists_in_corpus(name.name)}")
if hasattr(name, 'source_names') and name.source_names:
    print(f"Source names: {[n.name for n in name.source_names]}")

Multiple Corpora

# Load from multiple built-in sources by creating separate generators
generator1 = Generator("generic-fantasy-male")
generator2 = Generator("generic-fantasy-female")

# Generate names from each corpus
male_names = [generator1.generate_name(max_len=12) for _ in range(5)]
female_names = [generator2.generate_name(max_len=12) for _ in range(5)]

# Mix built-in and custom sources
japanese_gen = Generator("japanese-sengoku")
custom_gen = Generator("./my-custom-names.yaml")

Development

Setting Up Development Environment

# Clone the repository
git clone https://github.com/wyrdbound/wyrdbound-rng.git
cd wyrdbound-rng

# Create and activate virtual environment
python -m venv .venv
source .venv/bin/activate  # On Windows: .venv\Scripts\activate

# Install with development dependencies
pip install -e ".[dev]"

Running Tests

# Run all tests (ensure .venv is activated)
python -m pytest tests/

# Run with coverage
python -m pytest tests/ --cov=wyrdbound_rng

# Run with coverage and generate HTML report
python -m pytest tests/ --cov=wyrdbound_rng --cov-report=html

Code Quality

# Lint and format with Ruff (ensure .venv is activated)
ruff check src/ tests/ tools/
ruff format src/ tests/ tools/

# Or run both together
ruff check --fix src/ tests/ tools/

Contributing

Contributions are welcome! Please feel free to submit a Pull Request. For major changes, please open an issue first to discuss what you would like to change.

Areas for Contribution

  • New segmentation strategies for different cultures/languages
  • Additional name corpora
  • Performance optimizations
  • Enhanced probability models
  • Documentation improvements

License

This project is licensed under the MIT License - see the LICENSE file for details.

Acknowledgments

  • Inspired by the original Ruby RNG gem
  • Built for the diverse naming needs of tabletop RPG systems
  • Thanks to the RPG community for feedback and name corpus contributions

Release files for wyrdbound-rng 0.0.12

For a detailed explanation of source distributions (sdists) and built distributions (wheels), please see the package formats documentation.

Source distribution (sdist)

Source distribution for wyrdbound-rng 0.0.12
File Size Uploaded
wyrdbound_rng-0.0.12.tar.gz 80.8 kB Details

Built distribution (wheel)

Table of built distributions (wheels) for wyrdbound-rng 0.0.12
File Interpreter ABI Platform
wyrdbound_rng-0.0.12-py3-none-any.whl Python 3 none any Details

Total release size: 151.9 kB

Release files / wyrdbound_rng-0.0.12.tar.gz

Download URL wyrdbound_rng-0.0.12.tar.gz
Size 80.8 kB
Tags Source
SHA-256 checksum
How to use checksums
bafd4aa08ad5a33915a2f99974e98681bf541d656462ccdd711da85f70a639cd
BLAKE2b-256 checksum
How to use checksums
d1776661b88dbcdf812a02b82627a6eac7ba113b4458be812d3ec4dd92e5c4e3
Upload date
Uploaded using Trusted Publishing?
What is trusted publishing?
No
Uploaded via twine/7.0.0 CPython/3.11.16

Release files / wyrdbound_rng-0.0.12-py3-none-any.whl

Download URL wyrdbound_rng-0.0.12-py3-none-any.whl
Size 71.1 kB
Tags Python 3
SHA-256 checksum
How to use checksums
ad57eec6d8dcfa806676551644cac31b1a0db84b46fdcf57fe62baa75de3ac78
BLAKE2b-256 checksum
How to use checksums
f0c0ec6a80fc27ef4b7450a8f118abb10373aee614c0dd1b2fdb9edfe783d33e
Upload date
Uploaded using Trusted Publishing?
What is trusted publishing?
No
Uploaded via twine/7.0.0 CPython/3.11.16

Release history Release notifications | RSS feed

This release

0.0.12 This release

2 release files

0.0.1

2 release files

Anthropic, PBC Visionary sponsor Bloomberg Visionary sponsor Hudson River Trading Visionary sponsor Meta Visionary sponsor NVIDIA Visionary sponsor Microsoft Sustainability sponsor Depot Continuous Integration AWS Cloud computing and Security Sponsor Datadog Monitoring Fastly CDN Google Download Analytics Sentry Error logging StatusPage Status page