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.
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()