<조건>
-CA(Cellular Automata)를 이용하여 동굴형태의 던전맵을 생성.
-0세대(랜덤생성맵) Wall의 생성 비율은 45%, 5세대까지 Loop.
-경계면도 Rule 적용.
-Rule은 B5678/S45678
-Moore neighborhood 검색방식.
<결과 예제: 40x20 크기로 5세대까지 Loop>
<소스코드>
# -*- coding: utf-8 -*-
#
# cave_map_generator.py
#
# http://codememo.tistory.com
#
# # - Wall / Space - Empty, CA Rule - B5678/S45678
#
import sys
import os
import random
class Map:
wall_ratio = 45
def __init__(self, column, row):
self.column, self.row = column, row
self.wall, self.empty = 0, 0
self.map = [["#"] * self.row for m in range(self.column)]
self.new_map = [["#"] * self.row for m in range(self.column)]
for column in range(self.column):
for row in range(self.row):
if (0< row < self.row - 1) and (0 < column < self.column - 1):
if (random.random() * 100) < self.wall_ratio:
self.map[column][row] = "#"
else:
self.map[column][row] = " "
self.new_map[column][row] = " "
print("0 Generation")
self.result()
def generate(self, count):
for i in range(1, count + 1):
for column in range(1, self.column - 1):
for row in range(1, self.row -1):
self.check(column, row)
print("%d Generation" % (i))
self.map = self.new_map
self.result()
self.new_map = [["#"] * self.row for m in range(self.column)]
for m in range(1, self.column - 1):
for n in range(1, self.row - 1):
self.new_map[m][n] = " "
def check(self, column, row):
neighborhood_empty, neighborhood_wall = 0, 0
for m in range(-1, 2):
for n in range(-1, 2):
if m != 0 or n != 0:
if self.map[column + m][row + n] == "#":
neighborhood_wall += 1
elif self.map[column + m][row + n] == " ":
neighborhood_empty += 1
if ((self.map[column][row] == "#" and neighborhood_wall >= 4) or
(self.map[column][row] == " " and neighborhood_wall >= 5)):
self.new_map[column][row] = "#"
else:
self.new_map[column][row] = " "
def result(self):
dungeon = ""
self.wall, self.empty = 0, 0
for column in range(self.column):
for row in range(self.row):
dungeon += self.map[column][row]
if self.map[column][row] == "#":
self.wall += 1
else:
self.empty += 1
if column < (self.column - 1):
dungeon += "\n"
print("Wall : %d Empty: %d" % (self.wall, self.empty))
print(dungeon)
def main():
map = Map(20, 40)
map.generate(5)
sys.exit()
if __name__ == "__main__":
main()
<참고>
http://www.roguebasin.com/index.php?title=Cellular_Automata_Method_for_Generating_Random_Cave-Like_Levels