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.

Python Minecraft II – Hello World

So in this post  for the Naas-Sallins Coder Dojo we are going to look at writing a program which will allow us to alter the state of the python minecraft world which we looked at in the last post. The first thing we need to do is amend the saveModule.py file in our pymc folder to allow for the two new blocks we added. If we look at lines 9 and 11 we have the following

        self.coordDictSave = { str(main.GRASS):'GRASS', str(main.SAND):'SAND', str(main.BRICK):'BRICK', str(main.STONE):'STONE' }

        self.coordDictLoad = { 'GRASS':main.GRASS, 'SAND':main.SAND, 'BRICK':main.BRICK, 'STONE':main.STONE }

we can see the structure of the save and load lines. We don’t really need to know everything the code does to guess that we can extend it to add our 2 blocks DOJO & DOJO2 so we get

        self.coordDictSave = { str(main.GRASS):'GRASS', str(main.SAND):'SAND', str(main.BRICK):'BRICK', str(main.STONE):'STONE',str(main.DOJO):'DOJO',str(main.DOJO2):'DOJO2' }

        self.coordDictLoad = { 'GRASS':main.GRASS, 'SAND':main.SAND, 'BRICK':main.BRICK, 'STONE':main.STONE, 'DOJO':main.DOJO, 'DOJO2':main.DOJO2 }

Now when we run our main.py program we can save the world by pressing F5. This creates a file called savegame.sav in our pymc folder.

This file has the following structure.

[-8, -3, 21]=>STONE
[52, -2, -39]=>GRASS
[66, -2, 19]=>GRASS

each line in the file represents the coordinates and texture of every block in our world. We can think of these numbers as the x, y and z of our world, where x is length, y is height and z is depth. Once we know the structure of our save file it gives the opportunity to write code to change the file and the world itself.

Our first step is to make a copy of the save file which we will call savegame.bak, this is so that we can start with a default state as we test our code. In our pymc folder create and edit a new file called world.py and add the following code

import shutil

shutil.copyfile('savegame.bak','savegame.sav')
world=open('savegame.sav','a')
world.close()

In this snippet we import the shutil library which allows us to perform operations on files on our computer. Our next line simply copies our default world state from our backup savegame.bak to savegame.sav . We then show how to open and close that file. The ‘a’ in the open statement says that we are going to open the file for append, which just means that we are going to add on to the end of the file.

Next we are going to alter our world by adding lines to the savegame.sav file. In this example we are going to create a large ‘hello world’ message in blocks. So we are going to create a function which will draw each letter.


def do_h(startx,starth,starty,texture):
    """ draw the letter H """
    myletter = []
    myletter.append("[%d,%d,%d]=>%s\n" % (startx,starth,starty,texture))
    myletter.append("[%d,%d,%d]=>%s\n" % (startx,starth+1,starty,texture))
    myletter.append("[%d,%d,%d]=>%s\n" % (startx,starth+2,starty,texture))
    myletter.append("[%d,%d,%d]=>%s\n" % (startx,starth+3,starty,texture))
    myletter.append("[%d,%d,%d]=>%s\n" % (startx,starth+4,starty,texture))
    myletter.append("[%d,%d,%d]=>%s\n" % (startx+1,starth+2,starty,texture))
    myletter.append("[%d,%d,%d]=>%s\n" % (startx+2,starth+2,starty,texture))
    myletter.append("[%d,%d,%d]=>%s\n" % (startx+3,starth,starty,texture))
    myletter.append("[%d,%d,%d]=>%s\n" % (startx+3,starth+1,starty,texture))
    myletter.append("[%d,%d,%d]=>%s\n" % (startx+3,starth+2,starty,texture))
    myletter.append("[%d,%d,%d]=>%s\n" % (startx+3,starth+3,starty,texture))
    myletter.append("[%d,%d,%d]=>%s\n" % (startx+3,starth+4,starty,texture))
    return(myletter)

This function is different than the ones we had in earlier posts, if we look at the first line we can see that we have some values in between the brackets after our name do_h. These values are called parameters and they represent the variables that we want this function to do its work on. In this case they are startx, starth, starty, texture which represent the beginning coordinates of the first block we want to place in our world along with the texture we want to use. After that we create a new list called myletter and then begin to create the lines which will draw our letter H. We do this by adding onto the beginning position of our first block. For example if we want to add a block on top of our first (which will be part of our first leg of the letter H) we have

startx,starth+1,starty,texture

so you can see that all we are changing  is the height of the block by one in comparison to the first. To explain the rest of the line, mylist.append simply means that we add onto our list. The next bit

("[%d,%d,%d]=>%s\n" % (startx+3,starth+4,starty,texture))

says to replace the placeholders (%d for digits and %s for words) with the following variables. Really all this is saying is that we want to create a line that will have the same structure as our savegame.sav file. In general our function creates a list of the lines we want to add to our file given a start position and texture. In order to actually add this letter H to our world we need to call the function so our code becomes

import shutil
def do_h(startx,starth,starty,texture):
    """ draw the letter H """
    myletter = []
    myletter.append("[%d,%d,%d]=>%s\n" % (startx,starth,starty,texture))
    myletter.append("[%d,%d,%d]=>%s\n" % (startx,starth+1,starty,texture))
    myletter.append("[%d,%d,%d]=>%s\n" % (startx,starth+2,starty,texture))
    myletter.append("[%d,%d,%d]=>%s\n" % (startx,starth+3,starty,texture))
    myletter.append("[%d,%d,%d]=>%s\n" % (startx,starth+4,starty,texture))
    myletter.append("[%d,%d,%d]=>%s\n" % (startx+1,starth+2,starty,texture))
    myletter.append("[%d,%d,%d]=>%s\n" % (startx+2,starth+2,starty,texture))
    myletter.append("[%d,%d,%d]=>%s\n" % (startx+3,starth,starty,texture))
    myletter.append("[%d,%d,%d]=>%s\n" % (startx+3,starth+1,starty,texture))
    myletter.append("[%d,%d,%d]=>%s\n" % (startx+3,starth+2,starty,texture))
    myletter.append("[%d,%d,%d]=>%s\n" % (startx+3,starth+3,starty,texture))
    myletter.append("[%d,%d,%d]=>%s\n" % (startx+3,starth+4,starty,texture))
    return(myletter)

shutil.copyfile('savegame.bak','savegame.sav')
world=open('savegame.sav','a')

nextletter = do_h(20,4,-8,'DOJO2')
for i in nextletter:
    world.write(i)

world.close()

Here we can see that in order to create our H we call the function do_h and send it our values for startx, starty, startz and texture. The values passed to our function when we call it need to be in the format and order that our function expects in order for it to work. By changing these values we can alter where the letter will be placed in our world.   The variable next letter takes on the value returned by our function and we then loop through that list writing the details to our world file. If we run this program we will then be able to see our floating letter when we run our world using main.py. All that is required to spell out Hello World is to define a function for each letter and then call it with the correct starting coordinates.
helloworld

Its a fair bit to take in but once you get the hang of it you can create all sorts of objects by code alone. The full Hello world code is below. Note how once we have defined the letter, we only need to change the coordinates to position it somewhere else.

import shutil

def do_e(startx,starth,starty,texture):
    """ draw the letter E """
    myletter = []
    myletter.append("[%d,%d,%d]=>%s\n" % (startx,starth,starty,texture))
    myletter.append("[%d,%d,%d]=>%s\n" % (startx,starth+1,starty,texture))
    myletter.append("[%d,%d,%d]=>%s\n" % (startx,starth+2,starty,texture))
    myletter.append("[%d,%d,%d]=>%s\n" % (startx,starth+3,starty,texture))
    myletter.append("[%d,%d,%d]=>%s\n" % (startx,starth+4,starty,texture))
    myletter.append("[%d,%d,%d]=>%s\n" % (startx+1,starth+2,starty,texture))
    myletter.append("[%d,%d,%d]=>%s\n" % (startx+2,starth+2,starty,texture))
    myletter.append("[%d,%d,%d]=>%s\n" % (startx+1,starth,starty,texture))
    myletter.append("[%d,%d,%d]=>%s\n" % (startx+2,starth,starty,texture))
    myletter.append("[%d,%d,%d]=>%s\n" % (startx+1,starth+4,starty,texture))
    myletter.append("[%d,%d,%d]=>%s\n" % (startx+2,starth+4,starty,texture))
    return(myletter)
def do_h(startx,starth,starty,texture):
    """ draw the letter H """
    myletter = []
    myletter.append("[%d,%d,%d]=>%s\n" % (startx,starth,starty,texture))
    myletter.append("[%d,%d,%d]=>%s\n" % (startx,starth+1,starty,texture))
    myletter.append("[%d,%d,%d]=>%s\n" % (startx,starth+2,starty,texture))
    myletter.append("[%d,%d,%d]=>%s\n" % (startx,starth+3,starty,texture))
    myletter.append("[%d,%d,%d]=>%s\n" % (startx,starth+4,starty,texture))
    myletter.append("[%d,%d,%d]=>%s\n" % (startx+1,starth+2,starty,texture))
    myletter.append("[%d,%d,%d]=>%s\n" % (startx+2,starth+2,starty,texture))
    myletter.append("[%d,%d,%d]=>%s\n" % (startx+3,starth,starty,texture))
    myletter.append("[%d,%d,%d]=>%s\n" % (startx+3,starth+1,starty,texture))
    myletter.append("[%d,%d,%d]=>%s\n" % (startx+3,starth+2,starty,texture))
    myletter.append("[%d,%d,%d]=>%s\n" % (startx+3,starth+3,starty,texture))
    myletter.append("[%d,%d,%d]=>%s\n" % (startx+3,starth+4,starty,texture))
    return(myletter)
def do_l(startx,starth,starty,texture):
    """ draw the letter L """
    myletter = []
    myletter.append("[%d,%d,%d]=>%s\n" % (startx,starth,starty,texture))
    myletter.append("[%d,%d,%d]=>%s\n" % (startx,starth+1,starty,texture))
    myletter.append("[%d,%d,%d]=>%s\n" % (startx,starth+2,starty,texture))
    myletter.append("[%d,%d,%d]=>%s\n" % (startx,starth+3,starty,texture))
    myletter.append("[%d,%d,%d]=>%s\n" % (startx,starth+4,starty,texture))
    myletter.append("[%d,%d,%d]=>%s\n" % (startx+1,starth,starty,texture))
    myletter.append("[%d,%d,%d]=>%s\n" % (startx+2,starth,starty,texture))
    return(myletter)
def do_o(startx,starth,starty,texture):
    """ draw the letter O """
    myletter = []
    myletter.append("[%d,%d,%d]=>%s\n" % (startx,starth,starty,texture))
    myletter.append("[%d,%d,%d]=>%s\n" % (startx,starth+1,starty,texture))
    myletter.append("[%d,%d,%d]=>%s\n" % (startx,starth+2,starty,texture))
    myletter.append("[%d,%d,%d]=>%s\n" % (startx,starth+3,starty,texture))
    myletter.append("[%d,%d,%d]=>%s\n" % (startx,starth+4,starty,texture))
    myletter.append("[%d,%d,%d]=>%s\n" % (startx+1,starth,starty,texture))
    myletter.append("[%d,%d,%d]=>%s\n" % (startx+2,starth,starty,texture))
    myletter.append("[%d,%d,%d]=>%s\n" % (startx+1,starth+4,starty,texture))
    myletter.append("[%d,%d,%d]=>%s\n" % (startx+2,starth+4,starty,texture))
    myletter.append("[%d,%d,%d]=>%s\n" % (startx+3,starth,starty,texture))
    myletter.append("[%d,%d,%d]=>%s\n" % (startx+3,starth+1,starty,texture))
    myletter.append("[%d,%d,%d]=>%s\n" % (startx+3,starth+2,starty,texture))
    myletter.append("[%d,%d,%d]=>%s\n" % (startx+3,starth+3,starty,texture))
    myletter.append("[%d,%d,%d]=>%s\n" % (startx+3,starth+4,starty,texture))
    return(myletter)
def do_w(startx,starth,starty,texture):
    """ draw the letter W """
    myletter = []
    myletter.append("[%d,%d,%d]=>%s\n" % (startx+1,starth,starty,texture))
    myletter.append("[%d,%d,%d]=>%s\n" % (startx+3,starth,starty,texture))
    myletter.append("[%d,%d,%d]=>%s\n" % (startx,starth+1,starty,texture))
    myletter.append("[%d,%d,%d]=>%s\n" % (startx+2,starth+1,starty,texture))
    myletter.append("[%d,%d,%d]=>%s\n" % (startx+4,starth+1,starty,texture))
    myletter.append("[%d,%d,%d]=>%s\n" % (startx,starth+2,starty,texture))
    myletter.append("[%d,%d,%d]=>%s\n" % (startx+2,starth+2,starty,texture))
    myletter.append("[%d,%d,%d]=>%s\n" % (startx+4,starth+2,starty,texture))
    myletter.append("[%d,%d,%d]=>%s\n" % (startx,starth+3,starty,texture))
    myletter.append("[%d,%d,%d]=>%s\n" % (startx+2,starth+3,starty,texture))
    myletter.append("[%d,%d,%d]=>%s\n" % (startx+4,starth+3,starty,texture))
    myletter.append("[%d,%d,%d]=>%s\n" % (startx,starth+4,starty,texture))
    myletter.append("[%d,%d,%d]=>%s\n" % (startx+4,starth+4,starty,texture))
    return(myletter)
def do_r(startx,starth,starty,texture):
    """ draw the letter R """
    myletter = []
    myletter.append("[%d,%d,%d]=>%s\n" % (startx,starth,starty,texture))
    myletter.append("[%d,%d,%d]=>%s\n" % (startx,starth+1,starty,texture))
    myletter.append("[%d,%d,%d]=>%s\n" % (startx,starth+2,starty,texture))
    myletter.append("[%d,%d,%d]=>%s\n" % (startx,starth+3,starty,texture))
    myletter.append("[%d,%d,%d]=>%s\n" % (startx,starth+4,starty,texture))
    myletter.append("[%d,%d,%d]=>%s\n" % (startx+1,starth+4,starty,texture))
    myletter.append("[%d,%d,%d]=>%s\n" % (startx+2,starth+4,starty,texture))
    myletter.append("[%d,%d,%d]=>%s\n" % (startx+3,starth+3,starty,texture))
    myletter.append("[%d,%d,%d]=>%s\n" % (startx+2,starth+2,starty,texture))
    myletter.append("[%d,%d,%d]=>%s\n" % (startx+1,starth+2,starty,texture))
    myletter.append("[%d,%d,%d]=>%s\n" % (startx+3,starth+1,starty,texture))
    myletter.append("[%d,%d,%d]=>%s\n" % (startx+3,starth,starty,texture))
    return(myletter)
def do_d(startx,starth,starty,texture):
    """ draw the letter O """
    myletter = []
    myletter.append("[%d,%d,%d]=>%s\n" % (startx,starth,starty,texture))
    myletter.append("[%d,%d,%d]=>%s\n" % (startx,starth+1,starty,texture))
    myletter.append("[%d,%d,%d]=>%s\n" % (startx,starth+2,starty,texture))
    myletter.append("[%d,%d,%d]=>%s\n" % (startx,starth+3,starty,texture))
    myletter.append("[%d,%d,%d]=>%s\n" % (startx,starth+4,starty,texture))
    myletter.append("[%d,%d,%d]=>%s\n" % (startx+1,starth,starty,texture))
    myletter.append("[%d,%d,%d]=>%s\n" % (startx+2,starth,starty,texture))
    myletter.append("[%d,%d,%d]=>%s\n" % (startx+1,starth+4,starty,texture))
    myletter.append("[%d,%d,%d]=>%s\n" % (startx+2,starth+4,starty,texture))
    #myletter.append("[%d,%d,%d]=>%s\n" % (startx+3,starth,starty,texture))
    myletter.append("[%d,%d,%d]=>%s\n" % (startx+3,starth+1,starty,texture))
    myletter.append("[%d,%d,%d]=>%s\n" % (startx+3,starth+2,starty,texture))
    myletter.append("[%d,%d,%d]=>%s\n" % (startx+3,starth+3,starty,texture))
    return(myletter)

shutil.copyfile('savegame.bak','savegame.sav')
world=open('savegame.sav','a')

nextletter = do_h(20,4,-8,'DOJO2')
for i in nextletter:
    world.write(i)
nextletter = do_e(25,4,-8,'DOJO2')
for i in nextletter:
    world.write(i)
nextletter = do_l(29,4,-8,'DOJO2')
for i in nextletter:
    world.write(i)
nextletter = do_l(33,4,-8,'DOJO2')
for i in nextletter:
    world.write(i)
nextletter = do_o(37,4,-8,'DOJO2')
for i in nextletter:
    world.write(i)
nextletter = do_w(43,4,-8,'DOJO2')
for i in nextletter:
    world.write(i)
nextletter = do_o(49,4,-8,'DOJO2')
for i in nextletter:
    world.write(i)
nextletter = do_r(54,4,-8,'DOJO2')
for i in nextletter:
    world.write(i)
nextletter = do_l(59,4,-8,'DOJO2')
for i in nextletter:
    world.write(i)
nextletter = do_d(63,4,-8,'DOJO2')
for i in nextletter:
    world.write(i)
world.close()

 

Simple Python Minecraft Clone

This is the latest in a series for the Naas-Sallins Coder Dojo about using the Python programming language. This time we are going to look at taking the source code for a simple Python minecraft clone by Michael Fogleman and making some amendments.

Our First step is getting the pyglet graphic library installed. Michael has some instructions on his page but in general on the command line type [to get to the command line on windows press the windows key and r and then type cmd before pressing enter]

pip install pyglet

This will download and install the library for you, if you run into trouble try these tips or wait until the next dojo session and I will try to help out.

Once you have pyglet installed the next step is to get the python code we are going to play with. We are going to use a fork of the original project by another github user (bison) which contains some code to save the state of the world and then reload it. So download this zip file and extract its contents to a new folder, call that folder something like pymc. Our folder should contain the following files

LICENSE
main.py
README.md
saveModule.py
texture.png

So step one is to check that everything works by running main.py. You can do this from the command line by changing to your pymc folder and typing python main.py or by loading the file into the pythonwin editor and clicking run. If you get something like

basicworld

then congrats, everything is working as it should! Play instructions are below.

 Moving

– W: forward
– S: back
– A: strafe left
– D: strafe right
– Mouse: look around
– Space: jump
– Tab: toggle flying mode

Building

– Selecting type of block to create:
– 1: brick
– 2: grass
– 3: sand
– Mouse left-click: remove block
– Mouse right-click: create block

Quitting

– ESC: release mouse, then close window

Okay so next we are going to learn how to add our own blocks which involves firstly editing the image file texture.png and then editing the main.py file to allow for the new blocks that we are going to add. To start copy texture.png to a new file called texture2.png then open this in an image editor like mspaint. You should see

textureblank

we are going to edit the two squares shown. For example with mspaint I changed them to

textureedit

which is the coderdojo logo and a badly hand drawn one! Don’t worry you can come back to this as often as you like.

So now we need to edit the main.py code to allow for these new blocks. Open the file in your editor and have a quick look at it.  Don’t panic! We have 845 lines of code but we only need to change a few of them.

Lets start by telling the program to use our new texture2.png. In your editor search for texture.png (ctrl+f in pythonwin), it is on line 55. Change this to read

TEXTURE_PATH = 'texture2.png'

Just below that we have 4 lines which tell the program which section of texture2.png to use for the top bottom and side of each block. Our 2 blocks will use the same texture for all sides so lets add our two lines for these blocks which I’m calling DOJO and DOJO2

GRASS = tex_coords((1, 0), (0, 1), (0, 0))
SAND = tex_coords((1, 1), (1, 1), (1, 1))
BRICK = tex_coords((2, 0), (2, 0), (2, 0))
STONE = tex_coords((2, 1), (2, 1), (2, 1))
DOJO = tex_coords((3, 1), (3, 1), (3, 1))
DOJO2 = tex_coords((3, 0), (3, 0), (3, 0))

In order to be able to place these blocks we need to add them to the inventory of blocks so that when a player presses 4 or 5 it changes the block to place to DOJO or DOJO2. If we have a look through our code or search for inventory we find on line 455

        # A list of blocks the player can place. Hit num keys to cycle.
        self.inventory = [BRICK, GRASS, SAND]

Here we can see a comment telling what the code does and then our list of textures. Lets edit this to

        # A list of blocks the player can place. Hit num keys to cycle.
        self.inventory = [BRICK, GRASS, SAND, DOJO, DOJO2]

If we run this new main.py we should be able to place our new blocks by pressing 4 or 5
newblockworld

Python Vs Scratch II

This is the third post in a series for the Naas-Sallins Coder Dojo about using the Python programming language.  This time we are going to have a look at how we break up a program into small sections which perform particular tasks and how we connect those sections together. We are going to use our lotto example from the last time

""" Lotto number generator for dojo"""
import random
balls = [1,2,3,4,5,6,7,8,9,10,11,12,13,14,15,16,17,18,19,20,21,22,23,24,25,26,27,28,29,30,31,32,33,34,35,36,37,38,39,40,41,42,43,44,45]
picks = random.sample(balls,6)
print picks

but we are going to extend it so that we ask our user to enter their 6 numbers and then use our random number selection code to simulate the lotto draw. We will keep going until the draw matches our numbers and then we will tell the user how many goes it took.

So we are going to introduce the concept of a function which is a small chunk of code that we use to do a particular thing.  An equivalent is a block which is available in Scratch 2 and BYOB/SNAP. We start off by defining its name and then we write the code that we want the function to perform. An example makes more sense so amending our code above to put it in a function we get

def draw_random():
picks = random.sample(balls,6)
    return(picks)

now anytime we want to use the code in the function we just call it by using its name draw_random(). For example if we want to print out two sets of numbers our program would look like this

import random
def draw_random():
    """get 6 randoms from the pot"""
    picks = random.sample(balls,6)
    return(picks)

balls = [1,2,3,4,5,6,7,8,9,10,11,12,13,14,15,16,17,18,19,20,21,22,23,24,25,26,27,28,29,30,31,32,33,34,35,36,37,38,39,40,41,42,43,44,45]

print draw_random()
print draw_random()

So whats important to get from this is the structure of a function, we give it a name and then all the code that is part of the function is indented and when its finished it returns a value to the code that called the function. In this case it returns our list of 6 numbers to the print statement which displays the value returned. Our output would be something like

[2, 7, 19, 24, 28, 40]
[7, 18, 24, 31, 39, 45]

Now we want to get the user to enter the numbers they want to pick. In scratch we might have something like

scratchask6

where we ask the user for a number and add that number to our list.

In python we can do this as follows

for repeat in range(6):
    answer = raw_input("enter a number between 1 and 45")
    selection.append(int(answer))

Here we are saying that we want to do something 6 times,
that we will make the variable answer equal to whatever the user enters
and then we add the answer to our list called selection (we actually convert answer to an integer number with the int(answer) part so make sure the user entered a number)

Now if we put together what we have and pop the code to get user input into a function we can come up with the following program

""" Lotto number generator 2 for dojo"""
import random

def draw_random():
    """get 6 randoms from the pot"""
    picks = random.sample(balls,6)
    picks.sort()
    return(picks)

def get_selection():
    """get 6 numbers from the user"""
    selection = []
    for i in range(6):
        number = raw_input('Enter a number ')
        selection.append(int(number))
    selection.sort()
    print "You Picked"
    print selection
    return(selection)

balls = [1,2,3,4,5,6,7,8,9,10,11,12,13,14,15,16,17,18,19,20,21,22,23,24,25,26,27,28,29,30,31,32,33,34,35,36,37,38,39,40,41,42,43,44,45]
count = 0
myselection = get_selection()
while True:
    draw = draw_random()
    count += 1
    if draw == myselection:
        print "You won on draw"
        print count
        print "The number of years it would have taken for your numbers to come up is"
        print count/104 #--2 draws per week
        break

So lets go through this to see what we are doing. Our first function draw_random is the same as above except for the line picks.sort() which takes our list and sorts it in ascending order. We do this to make it easier to compare out list of random numbers with our list of picked numbers. Our second function get_selection is where we get the 6 numbers from the user, again we sort our list before we return it.

Our main section of code starts when we make our list containing the 45 balls and then make a variable called count which we set to zero. The next line myselection = get_selection() is where we call the get_selection function and myselection gets the value of the list returned. Next we start a loop with the while True: statement. This is similar to

scratchmain

a forever loop in Scratch. We call our draw_random function and it returns a list of 6 random numbers to draw. After that we add one to our variable count and then check if our 6 random numbers are equal to the 6 numbers that the user picked. If they are we tell the user how many times we picked the random numbers before they matched and how many years it would have taken to do that in the real bi-weekly lotto draw. If they didn’t match then we tray again until they do.

The main thing to take away from this is the general structure of our python program. It is worth typing the commands into the python editor as you get the hang of the python syntax. Also if you are running on an older computer be prepared for your program to run for a while. As usual don’t worry if you get stuck or have problems, I will give you a hand at the next dojo session but it is worth giving this or a similar sized program a try so you can get the hang of python and how it works.

Python Vs Scratch

This is the second post in a series for the Naas-Sallins Coder Dojo about using the Python programming language. What I want to talk about here is how a more traditional programming language like Python compares with Scratch, by having a quick look at what they have in common and whats different.

In Scratch we are used to the different coloured sections which contain the various commands.

scratchlibraryThese commands are grouped together by the type of function they perform so we can see that all the commands to move a sprite are in the motion section. In Python we have the concept of libraries which we can import into our program to allow us to do particular things. For example we might import urllib2 to enable us to open a webpage. Again don’t worry about the details of this now, we will cover this as we go along.

Now in Scratch we are used to dragging our various commands for a sprite onto our scripts tab and putting them together to get the desired output. In Python however we need to type each command into our editor and we need to understand that how we layout those commands will change how our program runs. In Python the layout of the code matters more than in most other traditional programming languages since Python uses indentation to group statements together. Let me show you what I mean.

In Scratch we might have scratchifblock so we can see that if our variable x is equal to one we will move ten steps and than the sprite will say “this is an if block in Scratch”. We can see that the orange if-then includes the two other statements.

To do something similar in a Python program we would do something like this

if x ==1:
    currentpos = currentpos + 1
    print "if block in Python"

So what is important here is not the syntax of the Python commands but the fact that the two lines we want to run if the value of x are equal to one must be indented so that Python knows that they are all part of the same condition that needs to be run when the value of x is one. Some other languages enclose all the commands to be run when a condition is true in {} brackets but in Python its how the lines of code are indented that controls this.

Okay so that’s enough talk, how about some real code. Lets make a program to select 6 lotto numbers from 1 to 45 inclusive. If we were doing this in scratch we might do something like

scratchlottoWhich would give us 6 random numbers but wouldn’t check if we had the same number twice.

Now to try this in Python we need to start our editor so we can type in our commands so search for and run pythonwin.exe. It is a free editor that comes with Activestate Python which allows us to access the help documentation,  as well as enter and run our code.

Okay so the first thing we are going to do is set up our pot of 45 balls to choose from, in this case we are going to use a list. A list in Python is pretty much the same as our list from Scratch so we enter the following.

balls = [1,2,3,4,5,6,7,8,9,10,11,12,13,14,15,16,17,18,19,20,21,22,23,24,25,26,27,28,29,30,31,32,33,34,35,36,37,38,39,40,41,42,43,44,45]

Here we set out list called balls to all the numbers from 1 to 45 inclusive, note the use of the [ ] square brackets to denote a list. Now we need the code that will pick our 6 balls at random from the 45. Finding the right information can be tricky but the we can search for that information both in the help files and by using Google.

Click on Help-Python Manuals and enter random in the search tab, If you select the first result you should get all the details of the functions built into the random library. As you can see it is a bit complicated and as you gain more experience you will be able to understand this but for the moment trust me when I say (a bit of example code will make it clearer) that the bit we want is

random.sample(population, k)

Return a k length list of unique elements chosen from the population sequence. Used for random sampling without replacement.”

Step one is to tell Python that we want to use the random library by using the import command

import random

then we need to use the random.sample command in our code so our full program becomes

""" Lotto number generator for dojo"""
import random
balls = [1,2,3,4,5,6,7,8,9,10,11,12,13,14,15,16,17,18,19,20,21,22,23,24,25,26,27,28,29,30,31,32,33,34,35,36,37,38,39,40,41,42,43,44,45]
picks = random.sample(balls,6)
print picks

Here we have

A comment describing the program

Our import statement so we can use the methods associated with random

Our setup of the pot by putting the numbers 1 to 45 in a list called balls

Our selection of a set of picks by getting a sample of 6 items at random from the list called balls

Our print statement which displays the 6 random items from the list.

When you run the code hopefully you should get something like [32, 3, 38, 12, 25, 5]

Again, don’t worry if you didn’t get everything/anything just let me know where you got stuck and we will give you a hand at the next dojo session.

Getting Started with Python

So this is the first post in a short series for the Naas-Sallins Coder Dojo about using the Python programming language. It is aimed at the people who have got pretty familiar with scratch and are looking to try something new. There are a ton of python resources on the web and I will list some of these later.

 

Step 1. Get Python

unless you are on Linux chances are that you will need to install python. At the moment python has 2 major versions 2.7 and 3.3 which have some real differences. I recommend for our purposes that you download and install the 2.7 version for your operating system from ActiveState as it comes bundled with some good help files an editor and documentation. If your install asks if you want to let python through your firewall select yes since we will use this feature later.

Step 2. Hello World

Okay so now lets check that python is installed correctly.  It’s pretty much a standard to do ‘Hello World’ when starting any new programming language. The idea is to confirm that you have everything installed correctly by writing the code to print out the message ‘Hello World’.  If you are on windows and have a start menu try running the Python Interactive shell from the ActiveState Group or you can type python from a command shell.

 

You should get something like this

ActivePython 2.7.5.6 (ActiveState Software Inc.) based on
Python 2.7.5 (#65, Mar 30 2005, 09:33:37 [MSC v.1310 32 bit (Intel)] on
win32
Type “help”, “copyright”, “credits” or “license” for more information.
>>>

You can use the Python shell to interactively run Python code, so in our case at the >>> prompt type

print “Hello World”

If you get

Hello World

congrats you have python installed! If something went wrong along the way don’t worry, I will give you a hand at the next dojo session.