<조건>

-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

+ Recent posts