# Learning to program with Minecraft

#### Let's Get Fracking!

"Hello World!" programs are dumb, so you're going to dive right in and make a game within Minecraft – call it Treasure Hunt. The aim of the game is to find (and demolish!) a diamond block that has been hidden (buried) somewhere in the Minecraft world. Every 10 seconds, the program will post "Colder!" or "Warmer!" to the chat screen, depending on whether you are farther from or closer to the hidden block than the last time you checked (see the game program in Listing 1).

Listing 1

treasureHunt.py

```01 import random, math, time
02
03 import mcpi.block as block
04 import mcpi.minecraft as minecraft
05 mc=minecraft.Minecraft.create()
06
07 v_height=0
08
09 while v_height <= 0:
10     (tx, tz)=(random.randint(-125,125), random.randint(-125,125))
11     v_height=mc.getHeight(tx, tz)
12
13 mc.setBlock(tx, v_height-2, tz, block.DIAMOND_BLOCK)
14
15 vdistance = math.sqrt(math.pow(mc.player.getTilePos().x-tx, 2) + math.pow(mc.player.getTilePos().z-tz, 2))
16
17 while mc.getBlock(tx, v_height-2, tz)!=0:
18
19     vnewdistance=math.sqrt(math.pow(mc.player.getTilePos().x-tx,2)+ math.pow(mc.player.getTilePos().z-tz, 2))
20
21     if vnewdistance == 0: mc.postToChat("Dig!")
22     elif vdistance > vnewdistance: mc.postToChat("Warmer!")
23     elif vdistance < vnewdistance: mc.postToChat("Colder!")
24     else: mc.postToChat("Move!")
25
26     vdistance=vnewdistance
27
28     time.sleep(10)
29
30 mc.postToChat("Treasure found... And destroyed!")
31 mc.postToChat("Congratulations!")```

Line 1 loads several standard Python modules you'll need later on. With the `random` module, you'll pick a place to hide the treasure; `math` comes with methods like `sqrt` (square root) and `pow` (power) that you'll need to calculate the distance from the player to the treasure. Finally, you'll need `time` to post messages every 10 seconds.

Lines 3 and 4 import Minecraft-specific modules. The `block` module allows you to manipulate blocks, and the `minecraft` module allows you to know the player's position, to print messages to the chat window, and so forth.

Line 5 creates a connection to the running Minecraft server. Lines 3 to 5 will be pretty standard in all the Minecraft programs you write.

After loading all the necessary modules, the first thing you have to do is hide the treasure. The Pi version of Minecraft is 256 blocks wide on the x axis and 256 blocks deep on the z axis. Position (0,0) is the center of the grid. The y axis is up/down. I haven't been able to find the upper limit for the y axis, but 0 is sea level, which will be important later.

To keep things safe, the program will place the treasure within a square area that has 251 squares on a side (line 10). Even though you're avoiding the extreme edges (Minecraft Pi sometimes crashes when you play too close to the limits of the world), you still have a playing field of 63,001 blocks, and the treasure can be anywhere  … or almost. To avoid burying the treasure under the sea (because that would be evil), you check to make sure the highest point of the chosen location is above sea level (lines 9 to 11) with `getHeight()`, which is part of the Minecraft API.

So that the diamond is not immediately visible, you push it two layers under the surface (line 13). The `setBlock` method used in this instruction is part of the Minecraft API (Table 2) and takes the x, y, z position of the block you want to modify, plus the type of block you want to transform it into. For a full list of the types of blocks you can use, check out the Minecraft: Pi Edition wiki [5].

Tabelle 2

Minecraft API Methods

Method

Arguments

Returns

Description

Minecraft Class: mc.[method]

`getBlock`

x, y, z

blockId: int

Get the block ID at the named coordinates

`getBlockWithData`

x, y, z

vec3: obj

Get a block object at named coordinates

`getBlocks`

x0, y0, z0, x1, y1, z1

[int]

Get block IDs in cuboid between two coordinates

`setBlock`

x, y, z, id, [state]

Sets a block at coordinates; optional argument state is between 0 and 15

`setBlocks`

x0, y0, z0, x1, y1, z1, id, [state]

Sets blocks between two sets of coordinates; optional argument state is between 0 and 15

`getHeight`

x,z

int

Returns the highest block at a point

`getPlayerEntityIds`

[int]

Returns the IDs of all players connected to the game

`saveCheckpoint`

Saves the current state of the game

`restoreCheckpoint`

Restores the game to the latest saved state

`postToChat`

message: str

Posts a message to the chat

`setting`

key, stat: bol

Changes the settings of the world; key values: world_immutable, nametags_visible

Player Class: mc.player.[method]

`getPos`

x, y, z

vec3: obj

Returns the player's position as an object with floats

`setPos`

x, y, z

Sets the player's position using floats

`getTilePos`

x, y, z

vec3: obj

Returns the player's position as an object with integers

`setTilePos`

x, y, z

Sets the player's position using integers

`setting`

key, stat: bol

Changes the player's settings; key value: autojump

Events Class: mc.events.[method]

`clearAll`

Clears all events from buffer

`pollBlockHits`

[vec3: obj]

Returns an array of block hits; block hits created with sword right-click

Camera Class: mc.camera.[method]

`setNormal`

[entityID]

Sets the camera to normal for a list of player entities

`setFixed`

Sets the camera to fixed

`setFollow`

[entityId]

Sets the camera to follow for a list of player entities

`setPos`

x, y, z

Sets the camera position to coordinates

Entity Class: mc.entity.[method]

`getPos`

id: int

vec3: obj

Gets the position of the entity as floats

`setPos`

entityId:int, x, y, z

Sets the position of the entity

`getTilePos`

entityId: int

vec3: obj

Returns the position of an entity as a vector with integers

`setTilePos`

entityId:int, x, y, z

Sets the position of an entity with integers

`setting`

entityId: int, key, stat: bol

Changes the entity's settings; key value: autojump

An unexpected effect of the code as described is that the diamond is not only underground but can also be hidden under a tree. Because this adds a little more challenge to the game, I decided to leave it as is.

#### Minesweep

Before entering the main loop of the game, you first measure the distance from the point at which the player starts to the diamond stash (line 15). Note that the distance to the treasure is as the crow flies. Vertical distance is not taken into account. The coordinates of the treasure are stored in `tx` and `ty`, and you can determine player position by using the `player.getTilePos()` Minecraft method. This method returns a vector with three attributes: `x`, `y` and `z`. So, you can find out the x component of your player's coordinates by calling:

`mc.player.getTilePos().x`

Just change the trailing `x`, for `y` or `z` to get the corresponding components of the player's coordinates. This, by the way, is called dot notation.

You will have learned from geometry that the way to calculate a distance between two points (your player and the diamond) on a grid is by using the Pythagorean theorem (Figure 2). The difference between `mc.player.getTilePos().x` and `tx` is the length of one of the legs of a right triangle and the difference between `mc.player.getTilePos().z` and `tz` is the length of the other leg. The hypotenuse of your imaginary triangle is the distance between the two points: In Python, that calculation looks like line 15.

Figure 2: Using the Pythagorean theorem, you can calculate the distance from the player to the diamond.

The aim of the game is to locate and destroy the diamond, so now you create a loop that uses the Minecraft method `getBlock()` to check the content of the diamond's location (line 17). As soon as the location contains air (i.e., `0`, which is the numeric value for a block of type `AIR` [5]), the diamond has been destroyed and the loop will exit. Meanwhile, you must check the player position every 10 seconds to see if it is any closer to or farther from the treasure (lines 21-24).

If the distance is 0 (i.e., the player has arrived at the correct location), the program uses the `postToChat()` Minecraft method to show a Dig! message in the chat window. If the distance has decreased since the last time you checked, you post Warmer! (Figure 3); if it has increased (i.e., the player has moved farther away from the goal), you'll post Colder!. If the distance hasn't changed, you can assume the player hasn't moved and you post the incentive Move!.

Figure 3: Messages in the chat window guide the player toward the treasure.

The new distance becomes the old distance (line 26), then the program waits for 10 seconds (line 28) for the player to move, and the cycle starts again.

As soon as the player locates (Figure 4) and destroys the diamond, the loop exits, and the program congratulates the player (Figure 5) and ends.

Figure 4: You found the treasure. Now smash it to bits!
Figure 5: The program congratulates you on your successful quest.

Express-Checkout as PDF

Pages: 6

Price \$2.95
(incl. VAT)

SINGLE ISSUES

SUBSCRIPTIONS

TABLET & SMARTPHONE APPS

UK / Australia

## Related content

• Using the Raspberry Pi as a Minecraft server

Minecraft has millions of devoted fans worldwide, and players who organize a communal game with friends and acquaintances achieve an entirely new gaming experience. The Raspberry Pi is an excellent replacement for the Minecraft server.

• Don't Use a Hammer

When you first start building, you probably learn how to use one device and one programming language. Then comes the day you design a project that your toolset either can't solve or forces you to jump through too many hoops to get the outcome you desire. That's the day you start looking at new devices and languages to solve your problem. Having an arsenal of tools at your disposal makes solving problems easier.