-
Notifications
You must be signed in to change notification settings - Fork 5
/
creator.py
225 lines (168 loc) · 7.19 KB
/
creator.py
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
91
92
93
94
95
96
97
98
99
100
101
102
103
104
105
106
107
108
109
110
111
112
113
114
115
116
117
118
119
120
121
122
123
124
125
126
127
128
129
130
131
132
133
134
135
136
137
138
139
140
141
142
143
144
145
146
147
148
149
150
151
152
153
154
155
156
157
158
159
160
161
162
163
164
165
166
167
168
169
170
171
172
173
174
175
176
177
178
179
180
181
182
183
184
185
186
187
188
189
190
191
192
193
194
195
196
197
198
199
200
201
202
203
204
205
206
207
208
209
210
211
212
213
214
215
216
217
218
219
220
221
222
223
224
225
import pprint
import os
import yaml
import numpy.random
import roll as r
import add as a
import stats as s
# import yaml file for race weights
races = yaml.load(open("Data/races.yaml", "r"))
# given a list of values with weights, randomly pick one
def random_from(items):
# make a value weight tuple for each item, them zip them so there is a value array and a weight array
values, weights = zip(*[(value, items[value]["weight"]) for value in items])
total = sum(weights)
probs = [weight / total for weight in weights]
return numpy.random.choice(values, p=probs)
def create(stats=None):
# create an array of values to keep track of choices
attr = []
# create object to return as created character info
character = {}
# choose a random race and add it to the list
race = random_from(yaml.load(open("Data/races.yaml")))
attr += [race]
# choose a random subrace of our chosen race and add it to the list
subrace = random_from(yaml.load(open("Data/Gen/{}/subraces.yaml".format(*attr))))
attr += [subrace]
# choose a random background for our race/subrace choices
background = random_from(yaml.load(open("Data/Gen/{}/{}/backgrounds.yaml".format(*attr))))
# save choices to character
character["background"] = background
character["race"] = race
# not all races have subraces
character["subrace"] = subrace if subrace != "" else None
# choose a random class for race/subrace choices if we aren't making a colville character
if stats is None:
cl = random_from(yaml.load(open("Data/Gen/{}/{}/classes.yaml".format(*attr))))
# colville method
else:
# stats were rolled in order
character["stats"] = dict(zip(["Strength", "Dexterity", "Constitution", "Intelligence", "Wisdom", "Charisma"],
stats))
# print out what we are working with
print("stats: ", dict(character["stats"]))
# add racial modifiers
a.add_details(character)
# determine class from new scores
cl = s.get_class(character)
# save class choice
attr += [cl]
# choose random archetype for our choices thus far
archetype = random_from(yaml.load(open("Data/Gen/{}/{}/{}/archetypes.yaml".format(*attr))))
# print out our choices
print(background, race + ("({})".format(subrace) if subrace != "" else ""), cl + "({})".format(archetype))
# save class and archetype to character
character["class"] = cl
character["archetype"] = archetype
return character
# generates basic yaml files, should only be used for creating all files
# does not deal with modifiers, proficiencies, or anything above weighting everything the same
def gen_yamls():
# base path for Data Gen folder
basepath = "Data/Gen/"
os.makedirs(basepath, 0o700, True)
# make a folder for each race
for race in sorted(races):
path = basepath
os.makedirs(path + race, 0o700, True)
path += race
subracePath = path
# make a list of subraces for each race
with open(path + "/subraces.yaml", "w") as subraces_file:
subraces = races[race]["subraces"]
if subraces is None:
subraces = [""]
for subrace in subraces:
path = subracePath
subraces_file.write("\"{}\":\n weight: 2\n".format(subrace))
if subrace:
os.makedirs(path + "/" + subrace, 0o700, True)
path += "/" + subrace
classPath = path
# make a list of classes for each subrace
with open(path + "/classes.yaml", "w") as classes:
path = classPath
cl = yaml.load(open("Data/classes.yaml"))
for c in sorted(cl):
classes.write("\"{}\":\n weight: 2\n".format(c))
os.makedirs(path + "/" + c, 0o700, True)
# make a list of archetypes for the class
with open(path + "/" + c + "/archetypes.yaml", "w") as archetypes:
for archetype in sorted(cl[c]["archetypes"]):
archetypes.write("\"{}\":\n weight: 2\n".format(archetype))
# make a list of backgrounds for each subrace
with open(path + "/backgrounds.yaml", "w") as backgrounds:
for background in sorted(yaml.load(open("Data/backgrounds.yaml"))):
backgrounds.write("\"{}\":\n weight: 2\n".format(background))
# make a "one pass" character, stats are returned as first rolled, no conditions
def make_character():
character = create()
stats = sorted(r.roll_stats(), reverse=True)
print("stats: {}".format(stats))
s.assign_stats(character, stats)
a.add_details(character)
level_character(character, 1)
return character
# make a "colville" character, roll stats in order, apply bonuses, determine class
def make_character_coville():
stats = r.roll_stats_coville()
character = create(stats)
level_character(character, 1)
return character
# create a character where the sum of the modifiers must be at least +5
def make_character_min_mod():
character = create()
stats = r.roll_stats_min_mod()
print("stats: {}".format(stats))
s.assign_stats(character, stats)
a.add_details(character)
level_character(character, 1)
return character
# create a character with at least one score above 15 and at least one below 8
def make_character_8_15():
character = create()
stats = r.roll_stats_8_15()
print("stats: {}".format(stats))
s.assign_stats(character, stats)
a.add_details(character)
level_character(character, 1)
return character
# create a character using the standard array
def make_character_standard_array():
make_character_array([15, 14, 13, 12, 10, 8])
# create a character using the high low standard array
def make_character_standard_array_high_low():
make_character_array([15, 8] * 3)
# create a character using the all mid standard array
def make_character_standard_array_mid():
make_character_array([13, 12] * 3)
# make a character given already present stats
def make_character_array(stats):
character = create()
print("stats: {}".format(stats))
s.assign_stats(character, stats)
a.add_details(character)
level_character(character, 1)
return character
# file that gives general leveling info
# right now just xp
levels = yaml.load(open("Data/level.yaml"))
# set level, xp, and proficiency bonus
def level_character(character, level):
character["level"] = level
character["xp"] = levels[level]["exp"]
character["proficiency bonus"] = levels[level]["proficiency_bonus"]
# TODO add rest of data to character
# generate yaml files if they don't exist
if not os.path.exists("Data/Gen"):
print("Generating yaml files")
gen_yamls()
character = make_character()
pprint.pprint(character)
# give user the option to save the character for later
keep = input("Keep character? ")
if keep in ("yes", "Yes", "Y", "y"):
# add character and rewrite file
with open("characters.json", "a") as characters_file:
characters_file.write(str(character) + "\n")