Python script to generate simple "dungeon maps"
Vous ne pouvez pas sélectionner plus de 25 sujets Les noms de sujets doivent commencer par une lettre ou un nombre, peuvent contenir des tirets ('-') et peuvent comporter jusqu'à 35 caractères.

procgen.py 4.6KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170
  1. import random as r
  2. import sys, os
  3. from PIL import Image
  4. def createDungeon(x=None, y=None, seed=None):
  5. """ Initializes an x by y grid.
  6. x is width, y is height
  7. seed is the chance that a given cell will be "live" and should be an integer between 1-99.
  8. If True is equivalent to "wall", then higher seeds make more walls.
  9. """
  10. x = 10 if x == None else int(x)
  11. y = 10 if y == None else int(y)
  12. seed = 45 if seed == None else int(seed)
  13. new_map = []
  14. for j in range(y):
  15. new_row = []
  16. for i in range(x):
  17. new_row.append(True if r.randint(1,99) <= seed else False)
  18. new_map.append(new_row)
  19. return new_map
  20. def refineDungeon(d_map, d_lmt=None, a_lmt=None):
  21. """ Refines the grid.
  22. """
  23. d_lmt = 4 if d_lmt == None else int(d_lmt)
  24. a_lmt = 4 if a_lmt == None else int(a_lmt)
  25. new_map = []
  26. for j in range(len(d_map)):
  27. new_line = []
  28. for i in range(len(d_map[j])):
  29. x, y = i, j
  30. n_count = countAliveNeighbors(d_map, x, y)
  31. if d_map[y][x]:
  32. # It's a wall.
  33. if n_count < d_lmt:
  34. # It has too few wall neighbors, so kill it.
  35. new_line.append(False)
  36. else:
  37. # It has enough wall neighbors, so keep it.
  38. new_line.append(True)
  39. else:
  40. # It's a path.
  41. if n_count > a_lmt:
  42. # It has too many wall neighbors, so it becomes a wall.
  43. new_line.append(True)
  44. else:
  45. # It's not too crowded, so it stays a path.
  46. new_line.append(False)
  47. new_map.append(new_line)
  48. return new_map
  49. def countAliveNeighbors(d_map, x, y):
  50. count = 0
  51. for j in range(-1,2):
  52. for i in range(-1,2):
  53. n_x, n_y = x+i, y+j
  54. if i == 0 and j == 0:
  55. continue
  56. if n_x < 0 or n_x >= len(d_map[j]) or n_y == 0 or n_y >= len(d_map):
  57. # The target cell is at the edge of the map and this neighbor is off the edge.
  58. # So we make this neighbor count as a wall.
  59. count += 1
  60. #pass
  61. elif d_map[n_y][n_x]:
  62. # This neighbor is on the map and is a wall.
  63. count += 1
  64. return count
  65. def printDungeon(d_map, wall=None, path=None):
  66. wall = "II" if wall == None else wall
  67. path = " " if path == None else path
  68. for line in d_map:
  69. print("".join([wall if x else path for x in line]))
  70. print()
  71. def createImage(d_map, color=None, chunky=None, fn=None):
  72. color = False if color == None else bool(color)
  73. chunky = False if chunky == None else bool(chunky)
  74. fn = filename() if fn == None else fn
  75. x, y = len(d_map[0]), len(d_map)
  76. if chunky:
  77. true_x, true_y = x*2, y*2
  78. else:
  79. true_x, true_y = x, y
  80. img = Image.new("RGB",(true_x,true_y),(0,0,0))
  81. lst = []
  82. # Walls are black by default
  83. c_wall = [r.randint(0,255), r.randint(0,255), r.randint(0,255)] if color else [0,0,0]
  84. # Paths are white by default
  85. c_space = [255-x for x in c_wall]
  86. if chunky:
  87. for line in d_map:
  88. for _ in range(2):
  89. for val in line:
  90. for _ in range(2):
  91. lst.append(tuple(c_wall) if val else tuple(c_space))
  92. else:
  93. for line in d_map:
  94. for val in line:
  95. lst.append(tuple(c_wall) if val else tuple(c_space))
  96. img.putdata(lst)
  97. if not os.path.exists("maps"):
  98. os.makedirs("maps")
  99. img.save('maps/{}.png'.format(fn))
  100. print("Saved maps/{}.png".format(fn))
  101. def filename():
  102. hexes = ["0","1","2","3","4","5","6","7","8","9","a","b","c","d","e","f"]
  103. fn = []
  104. for _ in range(16):
  105. fn.append(r.choice(hexes))
  106. return "".join(fn)
  107. def main(x=None, y=None, seed=None, d_lmt=None, a_lmt=None, reps=None, out=None, color=None, chunky=None):
  108. # Initialize
  109. x = 20 if x == None else int(x)
  110. y = 20 if y == None else int(y)
  111. seed = 45 if seed == None else int(seed)
  112. d_lmt = 4 if d_lmt == None else int(d_lmt)
  113. a_lmt = 4 if a_lmt == None else int(a_lmt)
  114. reps = 2 if reps == None else int(reps)
  115. out = False if out == None else bool(out)
  116. color = False if color == None else bool(color)
  117. chunky = False if chunky == None else bool(chunky)
  118. my_map = createDungeon(x,y,seed)
  119. fn = filename()
  120. for _ in range(reps):
  121. my_map = refineDungeon(my_map, d_lmt, a_lmt)
  122. if out:
  123. createImage(my_map, color, chunky)
  124. else:
  125. printDungeon(my_map)
  126. def parseArgs(args):
  127. flags = {
  128. "--height" : 20,
  129. "--width" : 20,
  130. "--seed" : 45,
  131. "--death" : 4,
  132. "--birth" : 4,
  133. "--reps" : 2,
  134. "--out" : False,
  135. "--color" : False,
  136. "--chunky" : False,
  137. }
  138. for flag, default in flags.items():
  139. if flag in args:
  140. if flag == "--out":
  141. flags["--out"] = True
  142. elif flag == "--color":
  143. flags["--color"] = True
  144. elif flag == "--chunky":
  145. flags["--chunky"] = True
  146. else:
  147. flags[flag] = args[args.index(flag) + 1]
  148. return flags
  149. if __name__ == "__main__":
  150. flags = parseArgs(sys.argv)
  151. main(flags["--width"],
  152. flags["--height"],
  153. flags["--seed"],
  154. flags["--death"],
  155. flags["--birth"],
  156. flags["--reps"],
  157. flags["--out"],
  158. flags["--color"],
  159. flags["--chunky"])