A-maze-in Python

In this post  for the Naas-Sallins Coder Dojo we are going to look at writing a program which will draw a maze. We will then use that code as a map to allow us to build a maze in our minecraft-clone world. So code for a maze is tricky but luckly for us someone has already written some.

The Rosetta Code website is really cool and it attempts to show solutions to common problems in as many different computer programming languages as possible.

from random import shuffle, randrange

def make_maze(w = 16, h = 8):
	vis = [[0] * w + [1] for _ in range(h)] + [[1] * (w + 1)]
	ver = [["|  "] * w + ['|'] for _ in range(h)] + [[]]
	hor = [["+--"] * w + ['+'] for _ in range(h + 1)]

	def walk(x, y):
		vis[y][x] = 1

		d = [(x - 1, y), (x, y + 1), (x + 1, y), (x, y - 1)]
		shuffle(d)
		for (xx, yy) in d:
			if vis[yy][xx]: continue
			if xx == x: hor[max(y, yy)][x] = "+  "
			if yy == y: ver[y][max(x, xx)] = "   "
			walk(xx, yy)

	walk(randrange(w), randrange(h))
	for (a, b) in zip(hor, ver):
		print(''.join(a + ['\n'] + b))

make_maze()

So as you can see its pretty complicated but if we run this piece of code we should get something like

+--+--+--+--+--+--+--+--+--+--+--+--+--+--+--+--+
|        |     |     |                    |     |
+  +  +  +  +  +  +  +  +--+--+--+--+--+  +--+  +
|  |  |     |  |  |     |     |        |        |
+--+  +--+--+  +  +--+--+--+  +  +--+  +--+--+  +
|     |     |  |  |  |        |     |  |        |
+  +--+  +--+  +  +  +  +  +  +--+  +  +  +--+--+
|  |           |  |     |  |     |  |     |     |
+  +--+  +--+--+  +  +--+  +--+--+  +--+--+  +  +
|     |  |        |     |           |        |  |
+--+  +  +  +--+--+--+  +--+--+--+--+--+--+--+  +
|     |  |  |        |        |           |     |
+  +--+--+  +--+--+  +--+--+  +--+  +--+  +  +  +
|        |        |        |        |     |  |  |
+  +--+  +--+--+--+  +  +--+--+--+--+  +--+  +  +
|     |              |                       |  |
+--+--+--+--+--+--+--+--+--+--+--+--+--+--+--+--+

Our aim now is to take our main.py from our earlier minecraft clone and integerate this maze code into it. We will replace the section of code that sets up the initial landscape with our maze generation code. Step one is to make a new folder called dojomaze and copy your main.py and texture.png file to it. So if we look at the main.py we are going to change our def _initialize function to insert our maze code

def _initialize(self):
    """ Initialize the world by placing all the blocks."""

    n = 21 # make the world small enough
    s = 1 # step size
    y = 0 # initial y height
    for x in xrange(-n, n + 1, s):
        for z in xrange(-n, n + 1, s):
            # create a layer stone everywhere.
            self.add_block((x, y - 3, z), STONE, immediate=False)
            if x in (-n, n) or z in (-n, n):
                # create outer walls.
                for dy in xrange(-2, 3):
                    self.add_block((x, y + dy, z), STONE, immediate=False)
    ##---now put our maze on top-------------------------------------------------------------------
    def make_maze(w = 13, h = 19):
        vis = [[0] * w + [1] for _ in range(h)] + [[1] * (w + 1)]
        ver = [["| "] * w + ['|'] for _ in range(h)] + [[]]
        hor = [["+--"] * w + ['+'] for _ in range(h + 1)]

        def walk(x, y):
            vis[y][x] = 1
            d = [(x - 1, y), (x, y + 1), (x + 1, y), (x, y - 1)]
            random.shuffle(d)
            for (xx, yy) in d:
                if vis[yy][xx]: continue
                if xx == x: hor[max(y, yy)][x] = "+ "
                if yy == y: ver[y][max(x, xx)] = " "
                walk(xx, yy)

        walk(random.randrange(w), random.randrange(h))
        for (a, b) in zip(hor, ver):
            #--build up our map line by line
            self.mazemap = self.mazemap + (''.join(a+ ['\n'] +b + ['\n']))

make_maze()

myrows = self.mazemap.split('\n')
#--start in the corner of our would
x = -20
z = -20
for i in myrows: #for each line in our map
    z +=1
    x = -20
    for j in i: #go through each position on the current line
        x +=1
        if j != " ": #if the map is not blank in this position build a wall 3 high
            position = (x, -0, z)
            self.add_block(position,GRASS, immediate=False)
            position = (x, -1, z)
            self.add_block(position,STONE, immediate=False)
            position = (x, -2, z)
            self.add_block(position,STONE, immediate=False)
 #place treasure - our texture is adjusted to have a treasure block in it
 self.treasureposition = (18, -2, 18)
 self.add_block(self.treasureposition,TREASURE, immediate=False)

I have put these changes along with the new textures in this zip file which you can download. Have a look and we can go through the code at the next session. If you run the code you should end up with something like

Untitled

The object of the game is to navigate the maze and find the treasure. The aim of this post was just to demonstrate how we could adapt the code that we had in order to end up with something new.