IT’S WHEN YOU can start to process large amounts of data that computer programming gets really exciting. Your program then becomes a set of rules that govern how that data is read, processed and visually represented—the data becomes the really important part.
In this adventure, you first look at how to create text files that define mazes. The mazes will then be automatically built in the Minecraft world for you and your friends to solve; you'll wonder how such a small Python program can build something so big in the Minecraft world.
You are then going to develop this simple idea into a complete virtual 3D scanning and printing facility called the duplicator room. Anything you build inside the duplicator room can be saved to a file, recalled later and teleported to any location in your Minecraft world, and even loaded into Minecraft worlds on other computers! You will be able to build your own library of objects and build them in Minecraft so quickly that your friends will all want duplicating machines of their own!
Computer programs are generally quite unintelligent—they repeatedly follow instructions that you give them. If you don’t change any input to your program, it will do exactly the same thing every time you run it. The Minecraft programs you have been making have been quite interactive because they change what they do depending on what happens in the game world, which is the input to the program.
Another interesting way to make computer programs do different things every time you run them is to store the input data in a text file and have the computer read that file when it starts. You can then create any number of text files and even have a menu so you can choose which file to open depending on what you want to do with the program. This is called a data-driven program because it is mostly the data in the external text file that defines what the program does.
If you think about it, many of the programs you already use on your computer use data files. The word processor you use to type up your homework stores your homework in a data file; when you take a photo with a digital camera it is stored in a data file; and your image editor program reads that photo from the data file. Even Minecraft uses data files behind the scenes for tasks like saving and loading the world, and for the texture packs used to build all of the different blocks in the world from. Using data files with a program is a much more flexible way of working because it means that the program can be used for lots of different things without forcing you, the user, to modify the program every time you want it to do something slightly different. You can also share those data files with your friends, if they have the same programs as you.
Your first step in writing a data-driven program is to learn how to use Python to open and read text files from the computer filing system.
To learn how to open and read text files, you are going to write a simple hint-giver program. This program reads a file you have prepared of useful Minecraft hints and tips and displays one of the hints on the Minecraft chat at random intervals. You’re going to need a text file with tips in it, so your first task is to create this file. You can create this file in the normal Python editor, just like you do with your Python programs.
Start up Minecraft, IDLE, and if you are working on a PC or a Mac, start up the server, too. You should have had a bit of practice with starting everything by now, but refer to Adventure 1 if you need any reminders.
tips.txt
.Build yourself a house before the mobs come and get you
Use flowing water to fill underwater channels
Build up with sand then knock out the bottom block
Use both first-person and third-person views
Double tap space bar to fly into the sky
MyAdventures
folder. You don’t run this file, as it is not a Python program but a text file you’re going to tell your Python program to use.Now you have a data file with tips in it—in other words, input data—it’s time to write the program that processes that input data. This program read a random tip from the file and display it after a random interval on the Minecraft chat. Then, while you are playing your game, helpful tips will pop up on the chat.
tipChat.py
.import mcpi.minecraft as minecraft
import time
import random
mc = minecraft.Minecraft.create()
FILENAME = "tips.txt"
f = open(FILENAME, "r")
tips
. Remember that you have already used lists in Adventure 4 (magic bridge builder):
tips = f.readlines()
f.close()
while True:
time.sleep(random.randint(3,7))
tips
list and display it on the chat. You need to use the strip()
function to strip out unwanted newline characters. You’ll be looking at newline characters later on, so don’t worry too much about understanding this for now.
msg = random.choice(tips)
mc.postToChat(msg.strip())
Save and run your program. What happens? As you walk around the Minecraft world and play your game, every so often a tip pops up on the chat, just like in Figure 5-1. Note how the Minecraft chat builds up messages on the screen, and gradually they disappear over time.
Now that you know how to make your programs read from data files, you are ready to get a bit more adventurous. You know from earlier adventures that it is easy to place blocks in the Minecraft world. What if you could build blocks using lists of blocks stored in a data file? That’s exactly what you are going to do here: You are going to build a complete 3D maze in Minecraft, where the maze data is stored in an external file! But first, you need to decide how the maze data will be represented inside the file.
The mazes that you design are 3D because they are built in the Minecraft 3D world, but really they are just 2D mazes built out of 3D blocks—there is only one layer to your maze. This means that the data file needs to store x and z data for each block in the maze, so it is rectangular.
You need to decide how blocks themselves are represented in the data file. You use walls and air. To keep things simple, use a 1 to represent a wall and a 0 to represent air. You can always change the block types inside your Python program that are used for walls later.
For this program, you use a special type of text file called a CSV file, to represent your mazes as files in your computer’s filing system.
CSV is a very simple and widely used format. Here is a sample of a CSV file that stores part of a table from a database with details about Minecraft gamer characters. In this CSV file, the first row (or line) in the file has the names of the fields, and all other lines have data separated by commas:
Name,Handle,Speciality
David,w_geek,Coding in Python
Roma,physics_gurl,Designing big buildings
Ryan,mr_teck,Minecraft robots
Craig,rrrrrrrr,TNT expert
This CSV file has one header row, which has three field names called Name
, Handle
and Speciality
. There are four data rows, each with three fields of data.
For your maze data file, you don’t need a header row because each column in the table represents the same type of data; that is, it stores a number 0 for a space and a number 1 for a wall. You can download this sample maze file from the companion website, but here it is if you want to type it in:
maze1.csv
. Make sure you save this file in your MyAdventures
folder.1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1
0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,1
1,1,1,1,1,1,1,1,1,0,1,0,1,1,0,1
1,0,0,1,0,0,0,0,1,0,1,0,1,0,0,1
1,1,0,1,0,1,1,0,0,0,0,0,1,0,1,1
1,1,0,1,0,1,1,1,1,1,1,1,1,0,1,1
1,1,0,0,0,1,1,1,1,1,0,0,0,0,1,1
1,1,1,1,1,1,0,0,0,0,0,1,1,1,1,1
1,0,0,0,0,1,0,0,0,0,0,0,0,0,0,1
1,0,1,1,1,1,0,0,0,0,0,1,1,1,1,1
1,0,0,0,0,0,0,0,0,0,0,0,0,0,0,1
1,0,1,1,1,1,1,1,1,1,0,1,1,1,1,1
1,0,1,0,0,0,0,0,0,1,0,0,0,0,0,1
1,0,1,0,1,1,1,1,0,1,1,1,1,1,0,1
1,0,0,0,0,0,0,0,0,1,0,0,0,0,0,1
1,1,1,1,1,1,1,1,1,1,0,1,1,1,1,1
Now that you have a data file describing your maze, the final step is to write the Python program that reads data from this file and builds the maze in Minecraft using blocks.
csvBuild.py
.import mcpi.minecraft as minecraft
import mcpi.block as block
mc = minecraft.Minecraft.create()
GAP
constant is the block type that is used in the spaces. This is normally air, but you could experiment with different block types to make the maze interesting. The WALL
constant is the block type that the walls of the maze are built with, so choose this carefully as some block types won’t work very well as walls. The FLOOR
constant is used to build the layer that the maze stands on:
GAP = block.AIR.id
WALL = block.GOLD_BLOCK.id
FLOOR = block.GRASS.id
FILENAME
constant is used so that it is easy for you to change the filename later to read in different maze files:
FILENAME = "maze1.csv"
f = open(FILENAME, "r")
pos = mc.player.getTilePos()
ORIGIN_X = pos.x+1
ORIGIN_Y = pos.y
ORIGIN_Z = pos.z+1
z = ORIGIN_Z
readlines()
function does. The for
loop is actually looping through every line in the file, one by one. Each time round the loop, the line
variable holds the next line that has been read from the file:
for line in f.readlines():
split()
function does. Remember that all of the lines that are part of the body of the for
loop have to be indented one level:
data = line.split(",")
for
loop. This is called a nested loop, because one loop is nested inside another. Your program has to reset the x coordinate at the start of every new row of the maze, so this has to be done outside of the for
loop that draws a whole row:
x = ORIGIN_X
for cell in data:
if
/else
statement chooses whether to build a gap or a wall, based on the number just read back from the CSV file. A 0 builds a gap, and anything else builds a wall. Make sure your indentation is correct here: The if
statement is indented twice because it is part of the for cell in data
loop, which is part of the for line in f.readlines()
loop. The b
variable here is useful as it makes the program a bit smaller and simpler. (Try rewriting this part without using the b
variable to see what I mean!)
if cell == "0":
b = GAP
else:
b = WALL
mc.setBlock(x, ORIGIN_Y, z, b)
mc.setBlock(x, ORIGIN_Y+1, z, b)
mc.setBlock(x, ORIGIN_Y-1, z, FLOOR)
for cell
loop. This must be indented so that it lines up with the previous mc.setBlock()
as it is still part of the body of the for cell in data
loop.
x = x + 1
for line in f.readlines()
loop).
z = z + 1
Save your program and double-check that all the indentation is correct. If the indentation is wrong, the program doesn't work correctly, and you get some very strange-shaped mazes!
Run your program and a fantastic (and quite hard to solve) maze will be built in front of you. Walk around the maze and see if you can solve it without breaking down any walls or flying. Figure 5-2 shows what the maze looks like from ground level.
If you get stuck, you can always cheat a bit and fly into the sky to get a 3D bird’s-eye view of the maze, as shown in Figure 5-3.
Building mazes is great fun, but there is so much more you can do with data files now that you know the basics! Why stop at building with only two block types on a single layer? You are now going to use your maze program as the basis of your very own 3D printer and 3D scanner that will duplicate trees, houses—in fact, anything you can build in Minecraft—and “print” them all around the Minecraft world at the touch of a button! This is a block builder really, but I like to call this a 3D printer because of the way you can sometimes see the blocks building up row at a time, just like how a computer printer prints onto a piece of paper row at a time, or how a 3D printing machine builds up structures a layer at a time.
You’re getting quite good at building programs now, and each new program you build is larger than the last one. Just like in the previous adventure, where you built your program out of functions, you are going to build this program up in steps.
In your maze program, data was stored in a CSV file, where each line in the file represents a line of blocks inside the Minecraft world. Each column inside that line (separated by commas) corresponds to one block in that line of blocks. This is a 2D structure because it stores a block for each x and z coordinate of a rectangle region. The mazes you have built here are really only 2D mazes, as they only have one layer. They are just built inside the 3D Minecraft world by using 3D blocks.
To build 3D shapes, you need to build up in the y dimension too. If you think of a 3D object as just multiple layers or slices, then your 3D program is not all that different from your maze program. All you need to do for a cube that is 5 by 5 by 5 blocks in size is to store five layers of information.
There is a problem with this. Your Python program doesn't know how many lines to expect until it has processed the whole file. It could assume a certain size, but it would be nice to design a flexible CSV file format that can work with any size of object.
To solve this problem, you add some metadata in the first line of the file that describes the size of the object.
You are now going to create a sample object that is a tiny 3D cave so that you can test the 3D printing capabilities of your program. You can download this sample object as shown in Figure 5-4 from the companion Wiley website by downloading the CodeFiles.zip file, or just type it in here like you did with your maze.
object1.csv
.5,5,5
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
0,0,0,0,1
0,0,0,0,1
0,0,0,0,1
1,1,1,1,1
Save your file, but don’t run it—you can’t run it as it is not a Python program but a data file that will be used by the program you are now going to write.
Now that you have written your test data, it is time to write the 3D printer program that builds the hollow cave inside the Minecraft world. This program is very similar to your maze program, but this one has three nested loops: one loop for each of the x, y and z dimensions.
print3D.py
.import mcpi.minecraft as minecraft
import mcpi.block as block
mc = minecraft.Minecraft.create()
FILENAME = "object1.csv"
print3D()
function. You reuse this function later on in the final project, so make sure you name it correctly:
def print3D(filename, originx, originy, originz):
f = open(filename, "r")
lines = f.readlines()
split()
function. Then store those three numbers into the variables sizex
, sizey
and sizez
. You have to use the int()
function here because when you read lines from a file they come in as strings, but you need them to be numbers so you can calculate with them later:
coords = lines[0].split(",")
sizex = int(coords[0])
sizey = int(coords[1])
sizez = int(coords[2])
lineidx
variable to remember the index of the line in the lines[]
list that you are processing. Because your program scans through the lines
list reading out data for different layers of the 3D object, you can’t use this as the loop control variable:
lineidx = 1
for
loop scans through each of the vertical layers of the data read in from the file. The first few lines of the file are for the layer that is built at the lowest y layer. You can put a postToChat
here so that the progress of the printing process is visible inside Minecraft:
for y in range(sizey):
mc.postToChat(str(y))
lineidx
variable. Remember that these blank lines are only in the file so that it is easier for people to read it, but your program has to skip over them.
lineidx = lineidx + 1
for
loop that reads out the next line in the file and splits it whenever there is a comma. Be careful of the indentation here; the for
has to be indented two levels (one for the function and one for the for y
loop) and the code inside this for x
loop needs to be indented three levels.
for x in range(sizex):
line = lines[lineidx]
lineidx = lineidx + 1
data = line.split(",")
for
loop that scans through each of the blocks in the line just read and builds them inside Minecraft. The for z
loop is indented three levels and the body of the loop is indented four times, so take very special care of the indentation; otherwise you'll end up with some very strange-shaped objects!
for z in range(sizez):
blockid = int(data[z])
mc.setBlock(originx+x, originy+y, originz+z, ↩
blockid)
print3D()
function to print your 3D object just to the side of where you're standing:
pos = mc.player.getTilePos()
print3D(FILENAME, pos.x+1, pos.y, pos.z+1)
Save your program and run it to see what happens! Run around to different locations inside Minecraft and run the program. Every time you run the program, a hollow stone cave should be built just near your player! Figure 5-5 shows how easy it is to build lots of stone caves very quickly.
Your 3D printer is already very powerful. You can create a big library of CSV files for different objects you want to build, and then, whenever you need to, just run your print3D.py
program with a different FILENAME
constant to stamp the object all over your Minecraft world.
However, building larger and more complex objects becomes very difficult if you have to enter all the numbers into the CSV file by hand. Minecraft itself is the best program for building complex objects—so, what if you could use Minecraft to create these CSV data files for you? Here, you are going to run up to a tree and hug it, and then make an identical copy of the tree so you can duplicate it all over the Minecraft world. Fortunately, 3D scanning works a bit like 3D printing in reverse, so this not quite as hard as you might think.
scan3D.py
.import mcpi.minecraft as minecraft
import mcpi.block as block
mc = minecraft.Minecraft.create()
FILENAME = "tree.csv"
SIZEX = 5
SIZEY = 5
SIZEZ = 5
scan3D()
function. You use this function in a later program, so make sure it is named correctly:
def scan3D(filename, originx, originy, originz):
"w"
file mode inside the open()
function:
f = open(filename, "w")
"
"
at the end of the line is and why you need it.
f.write(str(SIZEX) + "," + str(SIZEY) + ","
+ str(SIZEZ) + "
")
for y in range(SIZEY):
f.write("
")
for x in range(SIZEX):
line = ""
for z in range(SIZEZ):
blockid = mc.getBlock(originx+x,
originy+y,
originz+z)
if line != "":
line = line + ","
line = line + str(blockid)
f.write(line + "
")
f.close()
scan3D()
function to scan that whole space to your CSV file.
pos = mc.player.getTilePos()
scan3D(FILENAME, pos.x-(SIZEX/2), pos.y, pos.z-(SIZEZ/2))
Save your program. Double-check that all your indentation is correct before you run it.
Now run up to a tree and hug it (stand as close as you can to its trunk), and run your scan3D.py
program. What happens?
Did anything happen at all? Remember that this program scans an object to a CSV file, so you have to look at the CSV file tree.csv
which is in the MyAdventures
folder, to see what numbers have been stored in it. Open the file tree.csv
by choosing File ⇒ Open from the editor window and choosing All Files in the file type drop-down menu. Figure 5-6 shows a section of the tree.csv
file that I captured after hugging a tree on my computer! Because the scanning space is quite small, you might regularly get only half a tree scanned, but you can always change the SIZE
constants to scan a bigger area.
You now have all the building blocks of programs you need in order to design and build your own 3D duplicating machine that will be envy of all your friends. With it, you will be able to jump into the Minecraft world and make a magic duplicating room materialise, in which you can build any object you like. You can then save these objects to files, load them into the room to edit them or magically duplicate them all over the Minecraft world. Finally, you can escape from the world and make the duplicating room vanish completely, leaving no traces of your magic behind you.
Just like in some of the earlier adventures, you are going to use your existing programs and stitch them together into a much bigger program. Because this program has a number of features, you are going to add a menu system to it so it is easy to control.
The first thing to do is to write the framework of the program that makes it all hang together. You start with some dummy functions that just print their name when you call them, and gradually fill in their detail using your existing functions from other programs. You may remember that this is the same way you built up your treasure hunt game in Adventure 4.
duplicator.py
.import mcpi.minecraft as minecraft
import mcpi.block as block
import glob
import time
import random
mc = minecraft.Minecraft.create()
SIZEX = 10
SIZEY = 10
SIZEZ = 10
roomx = 1
roomy = 1
roomz = 1
def buildRoom(x, y, z):
print("buildRoom")
def demolishRoom():
print("demolishRoom")
def cleanRoom():
print("cleanRoom")
def listFiles():
print("listFiles")
def scan3D(filename, originx, originy, originz):
print("scan3D")
def print3D(filename, originx, originy, originz):
print("print3D")
def menu():
print("menu")
time.sleep(1)
return random.randint(1,7)
anotherGo
variable is used:
anotherGo = True
while anotherGo:
choice = menu()
if choice == 1:
pos = mc.player.getTilePos()
buildRoom(pos.x, pos.y, pos.z)
elif choice == 2:
listFiles()
elif choice == 3:
filename = input("filename?")
scan3D(filename, roomx+1, roomy+1, roomz+1)
elif choice == 4:
filename = input("filename?")
print3D(filename, roomx+1, roomy+1, roomz+1)
elif choice == 5:
scan3D("scantemp", roomx+1, roomy+1, roomz+1)
pos = mc.player.getTilePos()
print3D("scantemp", pos.x+1, pos.y, pos.z+1)
elif choice == 6:
cleanRoom()
elif choice == 7:
demolishRoom()
elif choice == 8:
anotherGo = False
Save your test program and run it. What happens? Figure 5-7 shows what happened when I ran this program on my computer. You can see that the program is telling you what it is doing—it is choosing a random item from the menu, and then it is using the function that handles that menu option. As each function at the moment in your program only prints its name, that is all that you see. You see a different sequence of words on your screen to those in Figure 5-7 because the menu()
function chooses a random choice each time it is used.
A menu system is a very useful feature to add to your programs if they have lots of options for you to choose from. This menu system prints all the available options and then loops around, waiting for you to enter a number in the correct range. If you enter a number that is out of range, it just prints the menu again to give you another try.
Modify the menu function and replace it with the following (make sure that you get the indentation correct):
def menu():
while True:
print("DUPLICATOR MENU")
print(" 1. BUILD the duplicator room")
print(" 2. LIST files")
print(" 3. SCAN from duplicator room to file")
print(" 4. LOAD from file into duplicator room")
print(" 5. PRINT from duplicator room to player.pos")
print(" 6. CLEAN the duplicator room")
print(" 7. DEMOLISH the duplicator room")
print(" 8. QUIT")
choice = int(input("please choose: "))
if choice < 1 or choice > 8:
print("Sorry, please choose a number between 1 and 8")
else:
return choice
Save the program and run it. What does your program do differently from the one with the dummy menu? Figure 5-8 shows what the real menu looks like.
The duplicator room is going to be built out of glass, and it has a missing front on it so that your player can easily climb into it and create and delete blocks.
Replace the buildRoom()
function with the following code. Be careful of the long lines that use setBlocks()
, but note that I have not used the ↩ arrow here, because Python allows you to split these across multiple lines (see Digging into the Code for an explanation of why you can sometimes split lines and sometimes cannot):
def buildRoom(x, y, z):
global roomx, roomy, roomz
roomx = x
roomy = y
roomz = z
mc.setBlocks(roomx, roomy, roomz,
roomx+SIZEX+1, roomy+SIZEY+1, roomz+SIZEZ+1,
block.GLASS.id)
mc.setBlocks(roomx+1, roomy+1, roomz,
roomx+SIZEX, roomy+SIZEY, roomz+SIZEZ,
block.AIR.id)
Save your program and test it again. Test option 1 on the menu to make sure that you can build the duplicator room. Run to another location in the Minecraft world and choose option 1 again to see what happens! Figure 5-9 shows the duplicator room after it has just been built.
When you have run your duplicator program many times, you probably end up with lots of old duplicator rooms built all over the Minecraft world. Only the latest one that you have created is actually a working room, and after some time your world fills up so much that you won’t know which room is the right one! To solve this problem, you're adding a feature to your program that demolishes the duplicator room so that your Minecraft world doesn’t get cluttered with all these old rooms!
Demolishing the duplicator room is just like using your clearSpace.py
program from Adventure 3. All you need to know is the outer coordinates of the room. Because the room is one block bigger all around the outside of the duplicating space defined by SIZEX
, SIZEY
and SIZEZ
, this is quite simple to do with a little bit of maths.
Modify the demolishRoom()
function to look like this.
def demolishRoom():
mc.setBlocks(roomx, roomy, roomz,
roomx+SIZEX+1, roomy+SIZEY+1, roomz+SIZEZ+1,
block.AIR.id)
Save your program and run it again. Now it’s easy to build or demolish your duplicator room. Just use option 1 on your menu to build it and option 7 to demolish it.
You have written this part of the program before, in your scan3D.py
program, so you can use that with some small modifications.
scan3D()
function with the following code. This code is almost identical to the scan3D.py
program, but the line in bold has been added to make it show the progress of the scanning on the Minecraft chat. Scanning a big room can take a long time, so it is nice to have some indication of how far through the process your program has got. You can use copy and paste to bring in the code from your earlier program to save some typing time here:
def scan3D(filename, originx, originy, originz):
f = open(filename, "w")
f.write(str(SIZEX) + "," + str(SIZEY) + "," + ↩
str(SIZEZ) + "
")
for y in range(SIZEY):
mc.postToChat("scan:" + str(y))
f.write("
")
for x in range(SIZEX):
line = ""
for z in range(SIZEZ):
blockid = mc.getBlock(originx+x, originy+y, ↩
originz+z)
if line != "":
line = line + ","
line = line + str(blockid)
f.write(line + "
")
f.close()
AIR
blocks as well.Fancy a spring clean? Sometimes it is useful to have a fresh start and just clear the room. You could do this by demolishing the room and rebuilding it, but it’s really easy to add a clean feature, as it is only the coordinates that differ from the demolishRoom()
function.
cleanRoom()
function so that it looks like the following code. Note how the start coordinates are all bigger than the edge of the room, and the end coordinates are not as far over as in the demolishRoom()
function. This way, it clears the inner space of the room without destroying its walls:
def cleanRoom():
mc.setBlocks(roomx+1, roomy+1, roomz+1,
roomx+SIZEX, roomy+SIZEY, roomz+SIZEZ, block.AIR.id)
Printing (duplicating) the object that is in the room is really easy, because you have already written the print3D.py
program that does this, and it is identical. Here it is again so you can see it all in one place:
def print3D(filename, originx, originy, originz):
f = open(filename, "r")
lines = f.readlines()
coords = lines[0].split(",")
sizex = int(coords[0])
sizey = int(coords[1])
sizez = int(coords[2])
lineidx = 1
for y in range(sizey):
mc.postToChat("print:" + str(y))
lineidx = lineidx + 1
for x in range(sizex):
line = lines[lineidx]
lineidx = lineidx + 1
data = line.split(",")
for z in range(sizez):
blockid = int(data[z])
mc.setBlock(originx+x, originy+y, originz+z, ↩
blockid)
Save the program and run it again. Test that you can build something in the room, run to somewhere in the Minecraft world and then choose option 5 from the menu. The contents of the room are scanned then printed just to the side of where your player is standing. You should be able to run to anywhere in the Minecraft world and duplicate your objects many times. Try duplicating objects in the sky and under water to see what happens! Figure 5-11 shows the results of running this program.
Your last task is to write a useful little function that lists all the files in your filing system that are CSV files. You could just use the File Manager, but it is nice to add this feature to your program so that you have everything you need in one place:
listFiles()
function to use the glob.glob()
function to read in a list of all files and print them. See Digging into the Code for an explanation of how this works.
def listFiles():
print("
FILES:")
files = glob.glob("*.csv")
for filename in files:
print(filename)
print("
")
Quick Reference Table | |
Command |
Description |
f = open("data.txt", "r") tips = f.readlines() f.close() for t in tips: print(t) |
Reading lines from a file |
f = open("scores.txt", "w") f.write("Victoria:26000 ") f.write("Amanda:10000 ") f.write("Ria:32768 ") f.close() |
Writing lines to a file |
import glob names = glob.glob("*.csv") for n in names: print(n) |
Getting a list of matching filenames |
a = " hello " a = a.strip() print(a) |
Stripping unwanted white space from strings |
In this adventure, you learnt how to read from and write to data files. This opens up endless opportunities for saving and restoring parts of the Minecraft world, and even bringing in large amounts of real-world data from other sources, such as websites. You built your own 3D mazes with lots of winding tunnels and dead ends, and finished by building a fully functional 3D scanner and printer, complete with a full menu system. This technique of writing a menu system is useful for many other programs, too!
There are many sources of “live data” on the Internet. One data source that I found when researching for this book was the Nottingham City Council car park data here: http://data.nottinghamtravelwise.org.uk/parking.xml
. This data is updated every five minutes and tracks cars as they enter and exit the car parks. I have written a Python program and put it on my github page that processes this data and prints out useful information here: https://github.com/whaleygeek/pyparsers
. See if you can use this to write a Minecraft game that builds car parks with cars in them, inside your Minecraft world. Your game could be a car-parking challenge where you have to run around the Minecraft world and try to find a spare parking space in a limited time!
Everything you ever wanted to know about 3D mazes is explained in detail on this fantastic web page: http://www.astrolog.org/labyrnth/algrithm.htm
. This page includes lots of example multilayer 3D mazes that are stored in normal text files. Look through the site and see if you can find a file for a multi-layer maze, and modify your maze program to use the techniques you learned with your 3D duplicating machine to build a huge multilayered maze. You might even experiment with some of the suggestions on this website to write a Python program that automatically generates mazes for you!
Achievement Unlocked: Shattering the laws of physics and magically materialising and dematerialising huge objects all over the Minecraft world at the push of a button.