Advertisement
jonksar

CA Cave Gen

Apr 29th, 2016
74
0
Never
Not a member of Pastebin yet? Sign Up, it unlocks many cool features!
Python 3.76 KB | None | 0 0
  1. import PIL
  2. import random
  3. import array
  4. import itertools
  5.  
  6. class PearsonHash:
  7.     def __init__(self, seed=None):
  8.         if seed != None:
  9.             assert seed in range(256), "seed must be integer between 0 and 255"
  10.             self.seed = seed
  11.         else:
  12.             self.seed = random.randint(0, 255)
  13.         self.permut = list(range(256))
  14.         random.shuffle(self.permut)
  15.  
  16.     def __call__(self, array):
  17.         h = self.seed
  18.         for value in array:
  19.             h = self.permut[h ^ value]
  20.         return h
  21.  
  22. def ZCurve(x, y, n):
  23.         i = 0
  24.         assert ((n & (n - 1)) == 0) and n != 0, "n must be power of 2"
  25.         for j in range(n):
  26.             i |= (x & 1) << (2 * j)
  27.             x >>= 1
  28.             i |= (y & 1) << (2 * j + 1)
  29.             y >>= 1
  30.         return i
  31.  
  32. class Random2dNoise:
  33.     def __init__(self, size):
  34.         self.phash = PearsonHash()
  35.         self.size = size
  36.  
  37.     def __call__(self, x, y):
  38.         assert x < self.size and y < self.size, "x, y out of bounds"
  39.         tmp = array.array('B', [0] * 4)
  40.         z = ZCurve(x, y, self.size)
  41.         for k in range(4):
  42.             tmp[k] = (z >> (8 * k)) & 255
  43.         return self.phash(tmp)
  44.  
  45. class CellularAutomaton:
  46.     def __init__(self, size, percent_filled=0.55, rng_seed=random.randint(0, 255)):
  47.         random.seed(rng_seed)
  48.         self.array = [[int(random.random() < percent_filled) for _ in range(size)] for _ in range(size)]
  49.         self.size = size
  50.         self.percent_filled = percent_filled
  51.         self.rng_seed = rng_seed
  52.  
  53.     def iteration(self, rule1=4, rule2=5):
  54.         res = [[0 for _ in range(self.size)] for _ in range(self.size)]
  55.         for x, y in itertools.product(range(self.size), repeat=2):
  56.             neighbours = []
  57.             for dx, dy in itertools.product([-1, 0, 1], repeat=2):
  58.                 if dx == 0 and dy == 0: continue
  59.                 else:
  60.                     try: neighbours.append(self.array[y + dy][x+dx])
  61.                     except IndexError: pass
  62.  
  63.             if self.array[y][x] == 1:
  64.                 if sum(neighbours) < rule1:
  65.                     res[y][x] = 1
  66.                 else:
  67.                     res[y][x] = 0
  68.  
  69.             elif self.array[y][x] == 0:
  70.                 if sum(neighbours) < rule2:
  71.                     res[y][x] = 1
  72.                 else:
  73.                     res[y][x] = 0
  74.  
  75.         self.array = res
  76.  
  77. class Map:
  78.     def __init__(self, size=32, chunksize=16):
  79.         """
  80.       :int size: specifying map size for both axes
  81.       :int chunksize: number of blocks in every chunk
  82.       :call: map_chunk at (x_i, y_i)
  83.       """
  84.  
  85.         self.size = size
  86.         self.chunksize = chunksize
  87.         self.seed_gen = Random2dNoise(size=size)  # generator for random seeds at map indexes
  88.  
  89.     def __call__(self, x, y):
  90.         seed = self.seed_gen(x, y)
  91.         percent_filled = lambda: 0.51 # placeholder for a more random function
  92.         ca = CellularAutomaton(size=self.chunksize, percent_filled=percent_filled(), rng_seed=seed)
  93.         for i in range(7):
  94.             ca.iteration()
  95.  
  96.         return ca
  97.  
  98. s = 126
  99. map1 = Map(chunksize=s)
  100. maparray = map1(10, 10).array
  101. f = lambda x: ' ' if x == 0 else '#'
  102. def fill(data, pos):
  103.     stack = [pos]
  104.     xSize, ySize = len(data[0]), len(data)
  105.     temp = [[0 for i in range(xSize)] for j in range(ySize)]
  106.  
  107.     while stack: # is not empty
  108.         (x, y), *stack = stack
  109.  
  110.         if data[y][x] == 1:
  111.             data[y][x] = 2
  112.             if x > 0: stack.append((x - 1, y))
  113.             if x < (xSize - 1): stack.append((x + 1, y))
  114.             if y > 0: stack.append((x, y - 1))
  115.             if y < (ySize - 1): stack.append((x, y + 1))
  116.  
  117. print('\n'.join(''.join([f(maparray[y][x]) for x in range(len(maparray[0]))]) for y in range(len(maparray))))
Advertisement
Add Comment
Please, Sign In to add comment
Advertisement