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

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])