-
Notifications
You must be signed in to change notification settings - Fork 0
/
Copy pathprocgen.py
170 lines (159 loc) · 4.59 KB
/
procgen.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
import random as r
import sys, os
from PIL import Image
def createDungeon(x=None, y=None, seed=None):
""" Initializes an x by y grid.
x is width, y is height
seed is the chance that a given cell will be "live" and should be an integer between 1-99.
If True is equivalent to "wall", then higher seeds make more walls.
"""
x = 10 if x == None else int(x)
y = 10 if y == None else int(y)
seed = 45 if seed == None else int(seed)
new_map = []
for j in range(y):
new_row = []
for i in range(x):
new_row.append(True if r.randint(1,99) <= seed else False)
new_map.append(new_row)
return new_map
def refineDungeon(d_map, d_lmt=None, a_lmt=None):
""" Refines the grid.
"""
d_lmt = 4 if d_lmt == None else int(d_lmt)
a_lmt = 4 if a_lmt == None else int(a_lmt)
new_map = []
for j in range(len(d_map)):
new_line = []
for i in range(len(d_map[j])):
x, y = i, j
n_count = countAliveNeighbors(d_map, x, y)
if d_map[y][x]:
# It's a wall.
if n_count < d_lmt:
# It has too few wall neighbors, so kill it.
new_line.append(False)
else:
# It has enough wall neighbors, so keep it.
new_line.append(True)
else:
# It's a path.
if n_count > a_lmt:
# It has too many wall neighbors, so it becomes a wall.
new_line.append(True)
else:
# It's not too crowded, so it stays a path.
new_line.append(False)
new_map.append(new_line)
return new_map
def countAliveNeighbors(d_map, x, y):
count = 0
for j in range(-1,2):
for i in range(-1,2):
n_x, n_y = x+i, y+j
if i == 0 and j == 0:
continue
if n_x < 0 or n_x >= len(d_map[j]) or n_y == 0 or n_y >= len(d_map):
# The target cell is at the edge of the map and this neighbor is off the edge.
# So we make this neighbor count as a wall.
count += 1
#pass
elif d_map[n_y][n_x]:
# This neighbor is on the map and is a wall.
count += 1
return count
def printDungeon(d_map, wall=None, path=None):
wall = "II" if wall == None else wall
path = " " if path == None else path
for line in d_map:
print("".join([wall if x else path for x in line]))
print()
def createImage(d_map, color=None, chunky=None, fn=None):
color = False if color == None else bool(color)
chunky = False if chunky == None else bool(chunky)
fn = filename() if fn == None else fn
x, y = len(d_map[0]), len(d_map)
if chunky:
true_x, true_y = x*2, y*2
else:
true_x, true_y = x, y
img = Image.new("RGB",(true_x,true_y),(0,0,0))
lst = []
# Walls are black by default
c_wall = [r.randint(0,255), r.randint(0,255), r.randint(0,255)] if color else [0,0,0]
# Paths are white by default
c_space = [255-x for x in c_wall]
if chunky:
for line in d_map:
for _ in range(2):
for val in line:
for _ in range(2):
lst.append(tuple(c_wall) if val else tuple(c_space))
else:
for line in d_map:
for val in line:
lst.append(tuple(c_wall) if val else tuple(c_space))
img.putdata(lst)
if not os.path.exists("maps"):
os.makedirs("maps")
img.save('maps/{}.png'.format(fn))
print("Saved maps/{}.png".format(fn))
def filename():
hexes = ["0","1","2","3","4","5","6","7","8","9","a","b","c","d","e","f"]
fn = []
for _ in range(16):
fn.append(r.choice(hexes))
return "".join(fn)
def main(x=None, y=None, seed=None, d_lmt=None, a_lmt=None, reps=None, out=None, color=None, chunky=None):
# Initialize
x = 20 if x == None else int(x)
y = 20 if y == None else int(y)
seed = 45 if seed == None else int(seed)
d_lmt = 4 if d_lmt == None else int(d_lmt)
a_lmt = 4 if a_lmt == None else int(a_lmt)
reps = 2 if reps == None else int(reps)
out = False if out == None else bool(out)
color = False if color == None else bool(color)
chunky = False if chunky == None else bool(chunky)
my_map = createDungeon(x,y,seed)
fn = filename()
for _ in range(reps):
my_map = refineDungeon(my_map, d_lmt, a_lmt)
if out:
createImage(my_map, color, chunky)
else:
printDungeon(my_map)
def parseArgs(args):
flags = {
"--height" : 20,
"--width" : 20,
"--seed" : 45,
"--death" : 4,
"--birth" : 4,
"--reps" : 2,
"--out" : False,
"--color" : False,
"--chunky" : False,
}
for flag, default in flags.items():
if flag in args:
if flag == "--out":
flags["--out"] = True
elif flag == "--color":
flags["--color"] = True
elif flag == "--chunky":
flags["--chunky"] = True
else:
flags[flag] = args[args.index(flag) + 1]
return flags
if __name__ == "__main__":
flags = parseArgs(sys.argv)
main(flags["--width"],
flags["--height"],
flags["--seed"],
flags["--death"],
flags["--birth"],
flags["--reps"],
flags["--out"],
flags["--color"],
flags["--chunky"])