You cannot select more than 25 topics
Topics must start with a letter or number, can include dashes ('-') and can be up to 35 characters long.
187 lines
6.0 KiB
Python
187 lines
6.0 KiB
Python
1 year ago
|
import csv
|
||
|
from random import *
|
||
|
global letter_count
|
||
|
letter_count = 0
|
||
|
race_name = 'elf'
|
||
|
|
||
|
class letter():
|
||
|
# Each letter has a lowercase and an uppercase character and
|
||
|
# identifiers as a vowel or consonant
|
||
|
def __init__(self, lowerchar, upperchar, is_vowel, is_consonant):
|
||
|
global letter_count
|
||
|
self.upperchar = upperchar
|
||
|
self.lowerchar = lowerchar
|
||
|
self.is_vowel = is_vowel
|
||
|
self.is_consonant = is_consonant
|
||
|
self.num = letter_count
|
||
|
letter_count += 1
|
||
|
|
||
|
def normalize(prob):
|
||
|
global alphabet
|
||
|
new_prob = prob
|
||
|
for i in range(0,len(alphabet)):
|
||
|
total = 0
|
||
|
for j in range(0,len(alphabet)):
|
||
|
total+=prob[i][j]
|
||
|
if (total > 0):
|
||
|
for j in range(0,len(alphabet)):
|
||
|
new_prob[i][j] = prob[i][j]/total
|
||
|
else:
|
||
|
for j in range(0,len(alphabet)):
|
||
|
new_prob[i][j] = len(alphabet)**(-1)
|
||
|
return new_prob
|
||
|
|
||
|
# Define the alphabet
|
||
|
global alphabet
|
||
|
alphabet = [letter('a','A',True,False),
|
||
|
letter('b','B',False,True),
|
||
|
letter('c','C',False,True),
|
||
|
letter('d','D',False,True),
|
||
|
letter('e','E',True,False),
|
||
|
letter('f','F',False,True),
|
||
|
letter('g','G',False,True),
|
||
|
letter('h','H',False,True),
|
||
|
letter('i','I',True,False),
|
||
|
letter('j','J',False,True),
|
||
|
letter('k','K',False,True),
|
||
|
letter('l','L',False,True),
|
||
|
letter('m','M',False,True),
|
||
|
letter('n','N',False,True),
|
||
|
letter('o','O',True,False),
|
||
|
letter('p','P',False,True),
|
||
|
letter('q','Q',False,True),
|
||
|
letter('r','R',False,True),
|
||
|
letter('s','S',False,True),
|
||
|
letter('t','T',False,True),
|
||
|
letter('u','U',True,False),
|
||
|
letter('v','V',False,True),
|
||
|
letter('w','W',False,True),
|
||
|
letter('x','X',False,True),
|
||
|
letter('y','Y',True,True),
|
||
|
letter('z','Z',False,True )
|
||
|
]
|
||
|
|
||
|
# Initialize probability matrix
|
||
|
# prob[i][j] = probability of letter j after letter i
|
||
|
global prob
|
||
|
file_name = 'default prob.csv' # should initialize to all 0s
|
||
|
prob = []
|
||
|
with open(file_name,newline='') as csvfile:
|
||
|
prob_reader = csv.reader(csvfile, delimiter=',', quotechar='|')
|
||
|
for row in prob_reader:
|
||
|
prob.append([])
|
||
|
for num in row:
|
||
|
prob[len(prob)-1].append(float(num))
|
||
|
|
||
|
# read list of pre-generated names. Names should be stored one per linein file
|
||
|
file_name = 'names.csv'
|
||
|
with open(file_name, newline='') as csvfile:
|
||
|
name_reader = csv.reader(csvfile, delimiter=',', quotechar='|') # Record file content
|
||
|
for names in name_reader: # Loop over names in list
|
||
|
name = names[0]
|
||
|
# Loop over letters in the current name
|
||
|
for i in range(0,len(name)-1):
|
||
|
letter1 = name[i]
|
||
|
letter2 = name[i+1]
|
||
|
num1 = 0
|
||
|
num2 = 0
|
||
|
for i in range(0, len(alphabet)):
|
||
|
if letter1 == alphabet[i].lowerchar or letter1 == alphabet[i].upperchar:
|
||
|
num1 = alphabet[i].num
|
||
|
if letter2 == alphabet[i]. lowerchar or letter2 == alphabet[i].upperchar:
|
||
|
num2 = alphabet[i].num
|
||
|
# Add one to the number of times letter number i is followed by letter number i
|
||
|
prob[num1][num2] += 1
|
||
|
|
||
|
# Normalize the probability matrix
|
||
|
prob = normalize(prob)
|
||
|
|
||
|
#Write probability matrix to file. This file will be read by the generator
|
||
|
file_name = 'nameprob.csv'
|
||
|
with open(file_name, 'w', newline='') as csvfile:
|
||
|
prob_writer = csv.writer(csvfile,delimiter=',', quotechar='|', quoting=csv.QUOTE_MINIMAL)
|
||
|
for i in range(0,len(alphabet)):
|
||
|
prob_writer.writerow(prob[i])
|
||
|
|
||
|
|
||
|
def rand_int(x1,x2):
|
||
|
# Generate random integer number between x1 and x2
|
||
|
r = int( int(x1) + random()* (int(x2)-int(x1)) )
|
||
|
return r
|
||
|
|
||
|
def make_name():
|
||
|
# Determine name length
|
||
|
lmin = 3 # Minimum length
|
||
|
lmax = 10 # Maximum length
|
||
|
name_length = rand_int(lmin,lmax)
|
||
|
|
||
|
# Initialize string
|
||
|
my_name = ""
|
||
|
my_name_nums = []
|
||
|
|
||
|
prev_vowel = False # Was the previous letter a vowel
|
||
|
prev_consonant = False # Was it a consonant
|
||
|
prev2_vowel = False # Were the 2 prev vowels
|
||
|
prev2_consonant = False # Were the 2 prev consonants
|
||
|
prev_num = 0
|
||
|
|
||
|
# Generate letters for name
|
||
|
for i in range(0, name_length):
|
||
|
if i == 0:
|
||
|
a = alphabet[rand_int(0,25)]
|
||
|
my_name = my_name + a.upperchar
|
||
|
else:
|
||
|
a = get_letter(prev_num,prev2_vowel,prev2_consonant)
|
||
|
my_name = my_name + a.lowerchar
|
||
|
prev2_vowel = a.is_vowel and prev_vowel
|
||
|
prev2_consonant = a.is_consonant and prev_consonant
|
||
|
prev_vowel = a.is_vowel
|
||
|
prev_consonant = a.is_consonant
|
||
|
prev_num = a.num
|
||
|
my_name_nums.append(a.num)
|
||
|
return [my_name, my_name_nums]
|
||
|
|
||
|
def get_letter(prev_num,need_consonant,need_vowel):
|
||
|
global alphabet
|
||
|
# Generate a random letter
|
||
|
done = False
|
||
|
while not done:
|
||
|
a = pick_letter(prev_num)
|
||
|
if (need_consonant and a.is_vowel) or (need_vowel and a.is_consonant):
|
||
|
done = False
|
||
|
else:
|
||
|
done = True
|
||
|
return a
|
||
|
|
||
|
def pick_letter(i):
|
||
|
global prob
|
||
|
r = random()
|
||
|
total = 0
|
||
|
for j in range(0,len(alphabet)):
|
||
|
total += prob[i][j]
|
||
|
if r <= total or j == len(alphabet):
|
||
|
return alphabet[j]
|
||
|
print("problem!")
|
||
|
return alphabet(25)
|
||
|
|
||
|
# Generate and print a name
|
||
|
name1 = make_name()
|
||
|
print(name1[0])
|
||
|
|
||
|
# Quality assessment
|
||
|
input_string = "Was this a good "+race_name+" name ? y/n "
|
||
|
good = input(input_string)
|
||
|
if good == 'y':
|
||
|
for i in range(0,len(name1[1])-1):
|
||
|
prob[name1[1][i]][name1[1][i+1]] *= 1.01
|
||
|
if good == 'n':
|
||
|
for i in range(0,len(name1[1])-1):
|
||
|
prob[name1[1][i]][name1[1][i+1]] *= 0.99
|
||
|
|
||
|
prob = normalize(prob)
|
||
|
|
||
|
with open(file_name, 'w', newline='') as csvfile:
|
||
|
prob_writer = csv.writer(csvfile, delimiter=',', quotechar='|', quoting=csv.QUOTE_MINIMAL)
|
||
|
for i in range(0, len(alphabet)):
|
||
|
prob_writer.writerow(prob[i])
|