#!/usr/bin/python
#
# This class generates names in the quality of the planet names used in
# the classic game Elite. The algorithm used in this class comes from 
# the Mote project (http://mote.sourceforge.net/)

import sys
import random
import string

class NameGenerator:
    names = []
    numDGs = 95
    digraphs = [
            "la",  "ve",  "ta",  "re",  "or",  "za",  "us",  "ac"
            "te",  "ce",  "at",  "a",   "e",   "o",   "le",  "fa",
            "he",  "na",  "ar",  "to",  "oi",  "ne",  "no",  "ba",
            "bo",  "ha",  "ve",  "va",  "ax",  "is",  "or",  "in",
            "mo",  "on",  "cra", "ud",  "sa",  "tu",  "ju",  "pi",
            "mi",  "gu",  "it",  "ob",  "os",  "ut",  "ne",  "as",
            "en",  "ky",  "tha", "um",  "ka",  "qt",  "zi",  "ou",
            "ga",  "dro", "dre", "pha", "phi", "sha", "she", "fo",
            "cre", "tri", "ro",  "sta", "stu", "de",  "gi",  "pe",
            "the", "thi", "thy", "lo",  "ol",  "clu", "cla", "le",
            "di",  "so",  "ti",  "es",  "ed",  "bi",  "po",  "ni",
            "ex",  "ad",  "un",  "pho", "ci",  "ge",  "se",  "co"
        ]
        
    def sensibleName(self, name):
        vowels = 0
        samechar = 0
        lastchar = "*"
        
        i = 0
        while i < len(name):
            c = name[i]
            
            # Abort if more then two vowels are found together
            if c in ('a', 'e', 'i', 'o', 'u'): 
                vowels = vowels + 1
            else:
                vowels = 0;
            if vowels == 3:
                return 0
            
            # Abort if three same letters are found together    
            if c == lastchar:
                samechar = samechar + 1
            else:
                samechar = 0
            if samechar == 2:
                return 0
                
            lastchar = c

            i = i + 1
            
        return 1
       
    def duplicated(self, name):
        # Check if name was already used
        if name in self.names:
            return 1
        return 0
        
    def getNextName(self):
        # Create names with 2-3 syllables
        length = 2 + int(random.random() * 2)
        
        # But sometimes use 4 syllables
        if int(random.random() * 15) == 1:
            length = length + 1
            
        # Repeat until the generated name is ok
        nameok = 0
        while not nameok:
            name = ""
            i = 0
            while i < length:
                ok = 0
                while not ok:
                    ok = 1
                    
                    # Get a random syllable and make sure that no
                    # three-letter syllable is used as the last one
                    dgr = self.digraphs[int(random.random() * self.numDGs)]
                    if (i == length - 1) and (len(dgr) > 2):
                        ok = 0
                      
                # Add the syllable to the name
                name = name + dgr
                
                # Repeat
                i = i + 1
                
            # Capitalize it properly
            name = string.capitalize(name)
            
            # Check if name is pronounceable and unique
            nameok = self.sensibleName(name) and not self.duplicated(name)
            
        # Add the name to the cache so further names can be checked for
        # signleness.
        self.names.append(name)
        
        return name        

# Example (Outputs 10 names):
namegen = NameGenerator()

i = 0
while i < 10:
    print namegen.getNextName()
    i = i +1

