Wikijunior:Raspberry Pi/Minecraft Dungeon Maze

Raspberry Pi Minecraft Dungeon Maze

Tutorial by Steve Martin and Andrew Oakley

Public Domain 17 May 2018 www.cotswoldjam.org

To start Minecraft, click the Pi menu - Games - Minecraft Pi

Click Start Game then click an existing game or click Create New

Tab ↹ key to switch between the Minecraft world and the normal mouse on the desktop. The Tab ↹ key is to the left of the letter Q.

Esc for the game menu.

Controls
Mouse to look0 to select the sword
WSAD to moveE to reassign blocks 0–9
Space to jumpSpace twice to fly
Left-click to destroy a blockSpace twice again to stop flying
Right-click to create a blockSpace once while flying to go up
19 to select a type of block⇧ Shift while flying to go down

To code with Minecraft, leave Minecraft running. Press the Tab ↹ key to release the mouse from the game, so you can use the mouse on the desktop.

Click Pi menu - Programming - Python3 (IDLE) File menu - Open - python/minecraft-dungeon/myDungeon.py

from Dungeon import Dungeon
dungeon = Dungeon()
entrance = dungeon.create()
room1 = dungeon.newRoom(entrance, "N")

Run the program with Run menu - Run module. You should see a staircase down to a room.

Add more rooms to the program, for example:

room1 = dungeon.newRoom(entrance, "N")
hallway = dungeon.newRoom(room1, "N")
bedroom = dungeon.newRoom(hallway, "W")
lounge = dungeon.newRoom(hallway, "E")

Make a maze!

Files edit

Cjam-minecraft-dungeon.pdf edit

The original PDF for this tutorial is on Wikimedia Commons: Cjam-minecraft-dungeon.pdf

Dungeon.py edit

from mcpi.minecraft import Minecraft
from mcpi import block
import DungeonError

class Dungeon:
    _mc = Minecraft.create()
    _rooms = {}
    _MIN_X = -10
    _MIN_Y = -42
    _MIN_Z = -80
    _MAX_X = 120
    _MAX_Y = -12
    _MAX_Z = 80
    _ROOM_WIDTH = 10
    _ROOM_LENGTH = 10
    _ROOM_HEIGHT = 4

    ###########################################################
    #
    # Construct a room with the given dimensions. Place torches
    # around the walls, optionally put a random piece of
    # treasure in the room.
    #
    ###########################################################
    def MakeRoom(self, x1, y1, z1, x2, y2, z2):
        # Plot the room itself
        self._mc.setBlocks(x1, y1, z1, x2, y2, z2, block.AIR.id)

        # Determine height of torch
        th = min([y1, y2]) + 2

        # Place torches along each wall.
        for i in range(x1+1, x2-1):
            if i % 6 == 0 and (self._mc.getBlock(i, th, z1-1) != block.AIR):
                self._mc.setBlock(i, th, z1, block.TORCH)
            if i % 6 == 0 and (self._mc.getBlock(i, th, z2+1) != block.AIR):
                self._mc.setBlock(i, th, z2, block.TORCH)
        for i in range(z1+1, z2-1):
            if i % 6 == 0 and (self._mc.getBlock(x1-1, th, i) != block.AIR):
                self._mc.setBlock(x1, th, i, block.TORCH)
            if i % 6 == 0 and (self._mc.getBlock(x2+1, th, i) != block.AIR):
                self._mc.setBlock(x2, th, i, block.TORCH)


    ###########################################################
    #
    # Construct a flight of steps going downwards. The steps
    # must go through water so must include walls and ceiling.
    #
    ############################################################
    def MakeSteps(self, x, y, z, l):
        for step in range(l+1):
            # Floor steps
            self._mc.setBlock(x+step, y-step, z-1, block.STAIRS_COBBLESTONE.id, 1)
            self._mc.setBlock(x+step, y-step, z, block.STAIRS_COBBLESTONE.id, 1)
            self._mc.setBlock(x+step, y-step, z+1, block.STAIRS_COBBLESTONE.id, 1)
            # Ceiling steps
            self._mc.setBlock(x+step, y-step+4, z-1, block.STAIRS_COBBLESTONE.id, 4)
            self._mc.setBlock(x+step, y-step+4, z, block.STAIRS_COBBLESTONE.id, 4)
            self._mc.setBlock(x+step, y-step+4, z+1, block.STAIRS_COBBLESTONE.id, 4)
            # Sidewalls
            self._mc.setBlocks(x+step, y-step, z-2, x+step, y-step+self._ROOM_HEIGHT, z-2, block.STONE)
            self._mc.setBlocks(x+step, y-step, z+2, x+step, y-step+self._ROOM_HEIGHT, z+2, block.STONE)
            # Ensure that nothing is in the void.
            self._mc.setBlocks(x+step, y-step+1, z-1, x+step, y-step+3, z+1, block.AIR)

    ###########################################################
    #
    # Construct a flight of steps going downwards to join rooms.
    #
    ############################################################
    def StepsDown(self, x, y, z):
        print(y)
        if (y == -12):
            fs = x+3
        else:
            fs = x+2
        self._mc.setBlocks(fs, y, z-1, x+self._ROOM_HEIGHT+2, y, z-1, block.FENCE)
        self._mc.setBlocks(fs, y, z+1, x+self._ROOM_HEIGHT+2, y, z+1, block.FENCE)
        #  self._mc.setBlocks(x+self._ROOM_HEIGHT+4, y, z-1, x+self._ROOM_HEIGHT+4, y, z+1, block.FENCE)
        for step in range(1, self._ROOM_HEIGHT+3):
            # Floor steps
            self._mc.setBlock(x+step, y-step, z, block.STAIRS_COBBLESTONE.id, 1)
            # Space to walk
            self._mc.setBlocks(x+step+1, y-step, z, x+step+3, y-step, z, block.AIR)

    ############################################################
    #
    # Construct a new room.
    #
    ############################################################
    def newRoom(self, start, direction):
        handle = len(self._rooms)
        if direction.upper() not in ["N", "S", "E", "W", "U", "D"]:
            raise DungeonError.DirectionError("Direction must be: \"N\", \"S\", \"E\", \"W\", \"U\" or \"D\"")
        else:
            if start not in self._rooms:
                raise DungeonError.RoomError("Unknown room: " + str(start))
            else:
                x, y, z = self._rooms[start]
                if (direction.upper() == "N"):
                    x += self._ROOM_LENGTH+2
                elif (direction.upper() == "S"):
                    x -= self._ROOM_LENGTH+2
                elif (direction.upper() == "E"):
                    z += self._ROOM_WIDTH+2
                elif (direction.upper() == "W"):
                    z -= self._ROOM_WIDTH+2
                elif (direction.upper() == "U"):
                    y += self._ROOM_HEIGHT+2
                else:
                    y -= self._ROOM_HEIGHT+2
                if (x > self._MAX_X-self._ROOM_LENGTH
                 or x < self._MIN_X
                 or z < self._MIN_Z
                 or x > self._MAX_Z-self._ROOM_WIDTH
                 or y > self._MAX_Y
                 or y < self._MIN_Y):
                    raise DungeonError.RoomError("Not enough space in direction \"" + direction + "\" from room " + str(start))
                else:
                    if (self._mc.getBlock(x+1, y, z+2) == block.AIR.id):
                        raise DungeonError.RoomError("There is already a room in direction \"" + direction + "\" from room " + str(start))
                    else:
                        self.MakeRoom(x, y, z, x+self._ROOM_LENGTH, y+self._ROOM_HEIGHT, z+self._ROOM_WIDTH)
                        self._rooms[handle] = [x, y, z]
                        # Create the ajoining corridore or steps
                        if (direction.upper() == "N"):
                            self._mc.setBlocks(x-2, y, z+self._ROOM_WIDTH/2, x, y+1, z+self._ROOM_WIDTH/2, block.AIR)
                        elif (direction.upper() == "S"):
                            self._mc.setBlocks(x+self._ROOM_LENGTH, y, z+self._ROOM_WIDTH/2, x+self._ROOM_LENGTH+2, y+1, z+self._ROOM_WIDTH/2, block.AIR)
                        elif (direction.upper() == "E"):
                            self._mc.setBlocks(x+self._ROOM_LENGTH/2, y, z-2, x+self._ROOM_LENGTH/2, y+1, z, block.AIR)
                        elif (direction.upper() == "W"):
                            self._mc.setBlocks(x+self._ROOM_LENGTH/2, y, z+self._ROOM_WIDTH, x+self._ROOM_LENGTH/2, y+1, z+self._ROOM_WIDTH+2, block.AIR)
                        elif (direction.upper() == "U"):
                            self.StepsDown(x+1, y, z+2)
                        else:
                            self.StepsDown(x+1, y+self._ROOM_HEIGHT+2, z+2)
        return handle


    def __init__(self):
        # Create a large underwater block of stone for the dungeon.
        self._mc.setBlocks(self._MIN_X, -4, self._MIN_Z, self._MAX_X, self._MIN_Y, self._MAX_Z, block.STONE)
        self._mc.setBlocks(self._MIN_X-2, 0, self._MIN_Z-2, self._MAX_X+2, -3, self._MAX_Z+2, block.WATER_STATIONARY)
        self._mc.setBlocks(self._MIN_X-4, 0, self._MIN_Z-4, self._MAX_X+4, 30, self._MAX_Z+4, block.AIR)

        # Create external plinth for player to stand on
        self._mc.setBlocks(-6, 0, -5, 0, -3, 5, block.STONE)


    def create(self):
        # Create a dungeon as the start point
        self.MakeRoom(10, -12, -5, 20, -8, 5)
        self._rooms[0] = [10, -12, -5]

        # Place some steps down into the dungeon.
        self.MakeSteps(1, 0, 0, 12)

        # Put the player near the dungeon entrance.
        self._mc.player.setPos(-2, 1, 0)
        self._mc.setting("world_immutable", True)
        return 0

DungeonError.py edit

class DirectionError(Exception):
    def __init__(self, value):
        self.value = value

    def __str__(self):
        return repr(self.value)

class RoomError(Exception):
    def __init__(self, value):
        self.value = value

    def __str__(self):
        return repr(self.value)

myDungeon.py edit

#!/usr/bin/env python3
from Dungeon import Dungeon

dungeon = Dungeon()
entrance = dungeon.create()
room1 = dungeon.newRoom(entrance, "N")

# Create more rooms by adding more "dungeon.newRoom(room, direction)"
# like the line above. "room" must be a room that you've already created.
# "direction" must be one of:
#    "N" - North
#    "S" - South
#    "E" - East
#    "W" - West
#    "U" - Up (above)
#    "D" - Down (below)
# Create one or two more rooms, then explore your dungeon to make sure
# that it is as you expect, then create more rooms.

TestDungeon.py edit

#!/usr/bin/env python3
from Dungeon import Dungeon

dungeon = Dungeon()
hallway = dungeon.create()
d1 = dungeon.newRoom(hallway, "D")
d2 = dungeon.newRoom(d1, "D")
d3 = dungeon.newRoom(d2, "D")
d4 = dungeon.newRoom(d3, "D")
d5 = dungeon.newRoom(d4, "D")
bedroom = dungeon.newRoom(hallway, "N")
bedroom2 = dungeon.newRoom(hallway, "W")
bedroom3 = dungeon.newRoom(bedroom, "E")
bedroom4 = dungeon.newRoom(bedroom3, "D")
room5 = dungeon.newRoom(bedroom4, "N")
room6 = dungeon.newRoom(room5, "W")
room7 = dungeon.newRoom(room6, "U")