## Posted By

goldenratio on 08/11/09

# random dungeon generator

/ Published in: Python

`import mathimport randomimport pygamefrom random import randintfrom GameObjects import Vector class DungeonGenerator(object): 	def __init__(self, rows, cols, num_features, num_specials): # number of rooms too		def rcell():			return (randint(0, cols - 1), randint(0, rows - 1))		def rcellin(rect):			return ( (randint(rect.x,rect.x+rect.width-1), randint(rect.y,rect.y+rect.height-1)) )		def cell(pos):			return self.level[pos[1]][pos[0]]		def setcell(pos, val):			self.level[pos[1]][pos[0]] = val		def feature(pos, size):			return pygame.Rect(pos[0], pos[1], size, size)		def canbuild(feature):			# make sure it's not outside the screen			if feature.x < 0 or feature.y < 0:				return False			if feature.x + feature.width > cols:				return False			if feature.y + feature.height > rows:				return False			# make sure it doesn't cross another feature			# for x in range(feature.width):			# 	for y in range(feature.height):			# 		if cell((x,y)) == 1:			# 			return False			return True		def build(rect):			cur = pygame.Rect(rect)			for x in range(rect.width):				for y in range(rect.height):					setcell((cur.x, cur.y), 1) # space					cur.top += 1				cur.left += 1				cur.top = rect.top		def connect(start, end):			v = Vector.from_points((start.x, start.y), (end.x, end.y))			cur = feature((start.x,start.y), 1)			if random.getrandbits(1) == 0:				for x in range(int(math.fabs(v.x))): # total number of steps in x direction					setcell(cur, 1)					cur.x += 1 if v.x > 0 else -1				for y in range(int(math.fabs(v.y))):					setcell(cur, 1)					cur.y += 1 if v.y > 0 else -1			else:				for y in range(int(math.fabs(v.y))):					setcell(cur, 1)					cur.y += 1 if v.y > 0 else -1				for x in range(int(math.fabs(v.x))): # total number of steps in x direction					setcell(cur, 1)					cur.x += 1 if v.x > 0 else -1 		# create multidimensional array of ints:			# 0 = cannot walk			# 1 = can walk			# 2 = start			# 3 = exit			# 4 = item		zeros = [0] * cols;		self.level = [zeros[:] for x in range(rows)]		del zeros 		# place "features"		features = []		farthest = []		highest_mag = 0		for x in range(num_features):			# pick random feature			f = feature(rcell(), randint(2, 6))			# see if we can build it			while not canbuild(f):				# if not, pick another random feature				f = feature(rcell(), randint(2, 6))			# build it			build(f)			# check for farthest features			for f2 in features:				# calc magnitude between new feature and all old ones				mag = Vector.from_points( (f.x, f.y), (f2.x, f2.y) ).magnitude()				if mag > highest_mag:					highest_mag = mag					farthest = [f, f2]			# append to list of built features			features.append(f) 		# connect "features" together		last_feature = feature(( features[0].x, features[0].y ), 1)		for f in features:			connect(last_feature, f)			last_feature = feature((f.x,f.y),1)		del last_feature 		# place start and end points		start, end = farthest[0], farthest[1]		setcell(rcellin(start), 2)		setcell(rcellin(end), 3) 		# place special points		for x in range(num_specials):			f = random.choice(features)			spec = rcellin(f)			while cell(spec) != 1: # open space				f = random.choice(features)				spec = rcellin(f)			setcell(spec, 4) 		del features`