#!/usr/bin/python2
import numpy
from numpy.random import randint as rand
import sys
def tile():
tiles=[1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,
1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,2,
1,1,1,1,1,2,1,1,1,1,1,1,1,1,1,1,1,2,1,1,1,1,10]
return str(tiles[rand(len(tiles))])
def block20(txt=True):
if txt:
return "5,5,5,5,5,5,5,5,5,5,5,5,5,5,5,5,5,5,5,5,";
else:
return [5,5,5,5,5,5,5,5,5,5,5,5,5,5,5,5,5,5,5,5];
def generate_maze(width=81, height=51, complexity=.75, density=.75):
"""Generate a maze using a maze generation algorithm."""
# Only odd shapes
shape = ((height // 2) * 2 + 1, (width // 2) * 2 + 1)
# Adjust complexity and density relative to maze size
complexity = int(complexity * (5 * (shape[0] + shape[1]))) # Number of components
density = int(density * ((shape[0] // 2) * (shape[1] // 2))) # Size of components
# Build actual maze
Z = numpy.zeros(shape, dtype=int)
# Fill borders
Z[0, :] = Z[-1, :] = 1
Z[:, 0] = Z[:, -1] = 1
# Make aisles
for i in range(density):
x, y = rand(0, shape[1] // 2) * 2, rand(0, shape[0] // 2) * 2 # Pick a random position
Z[y, x] = 1
for j in range(complexity):
neighbours = []
if x > 1: neighbours.append((y, x - 2))
if x < shape[1] - 2: neighbours.append((y, x + 2))
if y > 1: neighbours.append((y - 2, x))
if y < shape[0] - 2: neighbours.append((y + 2, x))
if len(neighbours):
y_, x_ = neighbours[rand(0, len(neighbours) - 1)]
if Z[y_, x_] == 0:
Z[y_, x_] = 1
Z[y_ + (y - y_) // 2, x_ + (x - x_) // 2] = 1
x, y = x_, y_
return Z
# Receive arguments from commandline
try:
MaxMazes = int(sys.argv[1])
x = int(sys.argv[2])
y = int(sys.argv[3])
ry = int(y)
except IndexError:
print("Usage: ./maze.py <number of mazes> <width> <height>")
print("")
print("Creates random mazes. Must strip final comma and automap. Reorder.")
exit(0)
# Base class
class dlist(list):
def __setitem__(self, index, value):
size = len(self)
if index >= size:
self.extend(0 for _ in range(size, index + 1))
list.__setitem__(self, index, value)
def MakeMaze(maze):
TRUEMAZE=[]
xc=yc=1 # Cursors
# Setup TRUEMAZE
i=0
while i < (y+1):
# Three instances per Y
TRUEMAZE.append(dlist())
TRUEMAZE.append(dlist())
TRUEMAZE.append(dlist())
i+=1
# Build TRUEMAZE
for row in maze:
for r in row:
r=str(r)
#print "(%d, %d) = %s" % (xc, yc, r)
TRUEMAZE[max(0, yc-1)][max(0, xc-1)]=int(r.replace('1', '5').replace('0', tile()))
TRUEMAZE[max(0, yc-1)][max(0, xc)]=int(r.replace('1', '5').replace('0', tile()))
TRUEMAZE[max(0, yc-1)][max(0, xc+1)]=int(r.replace('1', '5').replace('0', tile()))
TRUEMAZE[max(0, yc)][max(0, xc-1)]=int(r.replace('1', '5').replace('0', tile()))
TRUEMAZE[max(0, yc)][max(0, xc)]=int(r.replace('1', '5').replace('0', tile()))
TRUEMAZE[max(0, yc)][max(0, xc+1)]=int(r.replace('1', '5').replace('0', tile()))
TRUEMAZE[max(0, yc+1)][max(0, xc-1)]=int(r.replace('1', '5').replace('0', tile()))
TRUEMAZE[max(0, yc+1)][max(0, xc)]=int(r.replace('1', '5').replace('0', tile()))
TRUEMAZE[max(0, yc+1)][max(0, xc+1)]=int(r.replace('1', '5').replace('0', tile()))
xc+=3
xc=1
yc+=3
return TRUEMAZE
def BuildLayer(LayerName, w, h, LayerData, invisible=False):
if invisible:
inv=' visible="0"'
else:
inv=""
return("""
<layer name="%s" width="%d" height="%d"%s>
<data encoding="csv">
%s
</data>
</layer>""" % (LayerName, w, h, inv, LayerData))
# Begin
print "Begin!"
MazeID=0
while MazeID < MaxMazes:
MazeID+=1
y=ry+0
print("Building Maze %02d/%02d!" % (MazeID, MaxMazes))
maze=generate_maze(x, y)
print(repr(maze))
TRUEMAZE=MakeMaze(maze)
width=len(TRUEMAZE[1])
name="mz%03d_%02d%02d.tmx" % (MazeID, x, y)
f=open(name, "w");
print("open // %s" % name)
# Generate Margins
MZLINE=str(TRUEMAZE[0]).replace('[','').replace(']','').replace(' ','').replace("10", "5").replace("1", "5").replace("2", "5")+","
MARGIN=""
i=0
while i < 20:
i+=1
MARGIN+=block20()+MZLINE+block20()+"\n"
# Create the maze string
MAZEDATA=""
MAZEDATA+=MARGIN
# Fill maze data
for line in TRUEMAZE:
if line != []:
MAZEDATA+=block20()
MAZEDATA+=(str(line).replace('[','').replace(']','').replace(' ',''))
MAZEDATA+=","+block20()+"\n"
# Clean MAZEDATA properly
MAZEDATA+=MARGIN
MAZEDATA=MAZEDATA[:-2]+"\n"
#MAZEMPTY=MAZEDATA.replace("10", "1").replace("2", "1").replace("5", "0")
MAZEMPTY=MAZEDATA.replace("10", "0").replace("1", "0").replace("2", "0").replace("5", "0")[:-1]
# Margin fix
width+=40
height=((y+1)*3)+40
y+=40
# Write the TMX file
f.write("""<?xml version="1.0" encoding="UTF-8"?>
<map version="1.0" tiledversion="1.0.3" orientation="orthogonal" renderorder="right-down" width="%d" height="%d" tilewidth="32" tileheight="32" nextobjectid="1">
<properties>
<property name="AutomappingRadius" value="1"/>
<property name="DeleteTiles" value="true"/>
</properties>
<tileset firstgid="1" name="set_cave" tilewidth="32" tileheight="32" tilecount="64" columns="8">
<image source="../Rules/tilesets/set_cave.png" width="256" height="256"/>
</tileset>
""" % (width, height))
# Build set layer
f.write(BuildLayer("set", width, height, MAZEDATA))
# Build the other tile layers
f.write(BuildLayer("Ground", width, height, MAZEMPTY))
f.write(BuildLayer("Fringe", width, height, MAZEMPTY))
f.write(BuildLayer("Over", width, height, MAZEMPTY))
# Build the other invisible layers
f.write(BuildLayer("Collision", width, height, MAZEMPTY, True))
f.write(BuildLayer("Heights", width, height, MAZEMPTY, True))
# Close the mapfile
f.write(""" <objectgroup name="Objects"/>
</map>""")
# And, we're done
f.close()