image

COMPUTERS DON’T THINK. They aren’t capable of having any thoughts at all; they can only ever do what programmers tell them to do. You can, however, make computers look like they are thinking and making decisions by themselves. By programming your computer to “understand” what’s happening and giving it rules to “decide” what to do next, you can open a door to a lot of fun.

In this adventure, you are going to program a block friend who will follow you around, provided you don’t get too far away. You are also going to create a flying saucer that chases you until it can get above you and beam you aboard.

You learn how to make a block move and follow the path it decides is best, as well as how to use the Python random module to make it look as if the computer is thinking. You also create shapes using the MinecraftShape functions in the minecraftstuff module (which is included in your starter kit).

Your Block Friend

Minecraft can be a lonely world. But your player doesn’t have to be alone—you can create a block that will follow him around, talk to him and be his friend (see Figure 7-1).

image

FIGURE 7-1 Create a block friend to accompany your player on his Minecraft adventures.

To program a block friend you need to think like her! She will be happy if she’s near your player, so she will want to follow him around and try to sit next to him. She’ll stay happy as long as your player is close to her; if your player walks off, she will walk after him. If your player gets too far away, it will make the block friend sad and she will stop following him until he comes back and gives her a hug (by standing next to her).

The block friend program has two distinct parts:

  • The rules the block uses to decide what it should do next: This part of the program makes the block friend decide whether to move toward your player (the target) or stay still.
  • The code that moves the block toward a target: Once the block friend reaches her target, she uses the rules again to work out what to do next.

While the block friend is moving towards the target, she should be travelling “on top” of the land, not floating in the air or burrowing under the ground! You do this by using the function mc.getHeight(x,z)and passing it a horizontal position (x,z). It returns the vertical position (y) of the first block down from the sky that isn’t AIR.

Start by creating a new program for the block friend:

  1. Open IDLE, select File ⇒ New File to create a new program and save the file as BlockFriend.py in the MyAdventures folder.
  2. Import the minecraft, block, minecraftstuff, math and time modules:

    import mcpi.minecraft as minecraft
    import mcpi.block as block
    import mcpi.minecraftstuff as minecraftstuff
    import math
    import time

  3. The first thing you need to do is create a function to calculate the distance between two points. Later you use this function to work out how far the block friend is from your player:

    def distanceBetweenPoints(point1, point2):
    xd = point2.x - point1.x
    yd = point2.y - point1.y
    zd = point2.z - point1.z
    return math.sqrt((xd*xd) + (yd*yd) + (zd*zd))

  4. Now you need to decide how far away your player needs to be for the block friend to stop following him. Create a constant to store the distance that you consider to be “too far away”. I have chosen 15, meaning that when the block friend and the player are 15 blocks apart, the block friend stops following the player:

    TOO_FAR_AWAY = 15

  5. Create the Minecraft and MinecraftDrawing objects:

    mc = minecraft.Minecraft.create()
    mcdrawing = minecraftstuff.MinecraftDrawing(mc)

  6. Create a variable to store the block’s mood. For this adventure, the block is either happy or sad. Set it to "happy":

    blockMood = "happy"

  7. Create the block friend, a few blocks away from the player, by getting the player’s position, adding 5 to the x position and using the getHeight() function to find out the y position, so the block is sitting on top of the land:

    friend = mc.player.getTilePos()
    friend.x = friend.x + 5
    friend.y = mc.getHeight(friend.x, friend.z)
    mc.setBlock(friend.x, friend.y, friend.z,
    block.DIAMOND_BLOCK.id)
    mc.postToChat("<block> Hello friend")

  8. Create a target for the block friend. This is the position she will move towards. Initially, set the target as the block friend’s current position, this is so the block friend doesn’t try to move anywhere when the program starts:

    target = friend.clone()

  9. Start an infinite loop, so the program will run forever. (Note that all the code after this point is indented under this loop.)

    while True:

  10. Get the player’s position and calculate the distance between the player and the block friend using the distanceBetweenPoints() function:

    pos = mc.player.getTilePos()
    distance = distanceBetweenPoints(pos, friend)

  11. Apply the rules you want the block friend to use to work out what to do next. If it’s “happy”, tell it to compare the distance between the friend and the “too far away” constant. If the distance is less than the “too far away” constant, set the target to be the position of the player. If it’s greater than the “too far away” constant, change the block’s mood to “sad” (see Figure 7-2):

    if blockMood == "happy":
    if distance < TOO_FAR_AWAY:
    target = pos.clone()
    else:
    blockMood = "sad"
    mc.postToChat("<block> Come back. You are too far ↩
    away. I need a hug!")

  12. Indented inline with the if statement that checks if the block is "happy", you need to tell the program if the block friend is "sad", to wait until the player is within one block’s distance (a hug) before changing the block’s mood to "happy".

    elif blockMood == "sad":
    if distance <= 1:
    blockMood = "happy"
    mc.postToChat("<block> Awww thanks. Lets go.")

  13. Run your program to test that when you walk away from your block friend she changes from happy to sad and back to happy when you give her a hug.
image

FIGURE 7-2 The block friend is sad.

The block friend appears next to your player; if you walk too far away the friend asks you to come back.

Now that your block friend is talking to you to let you know how she feels, the next step is to update the program to make the block friend follow the player:

  1. The block friend only needs to move, if her position is not the same as her target (the player):

    if friend != target:

  2. Find all the blocks between the friend and her target by using the getLine() function in MinecraftDrawing:

    line = mcdrawing.getLine(
    friend.x, friend.y, friend.z,
    target.x, target.y, target.z)

    The getLine() function works in the same way as drawLine() (see Adventure 6). However, instead of drawing the line in blocks, it returns a list of points (x, y, z) that make a line between the two sets of x, y, z coordinates passed as parameters.

  3. Directly under the previous code, you need to tell your program to loop through all the blocks between the friend and the target, and move the block friend to the next block between the block friend and the player:

    for nextBlock in line[:-1]:
    mc.setBlock(friend.x, friend.y, friend.z, block.AIR.id)
    friend = nextBlock.clone()
    friend.y = mc.getHeight(friend.x, friend.z)
    mc.setBlock(friend.x, friend.y, friend.z,
    block.DIAMOND_BLOCK.id)
    time.sleep(0.25)
    target = friend.clone()

    When the for loop finishes, the block friend has reached her target, so set the target to be the block friend’s own current position. This way she won’t try to move again.

    The program moves the block friend by clearing her from her previous last position (which it does by setting the block to AIR), updating the block friend’s position to be the next block in the line, then re-creating the block friend in that position.

  4. Put in a small delay at the end of the infinite loop so the program asks for the player’s position once every 0.25 seconds:

    time.sleep(0.25)

  5. Run the program.

The block friend now follows the player until they get too far away from each other. When that happens, the block friend comes to a stop and your player has to go back and stand next to the block friend before she starts following again.

You can download the complete code for the block friend program from the Adventures in Minecraft companion website at www.wiley.com/go/adventuresinminecraft2e.

Using Random Numbers to Make Your Block Friend More Interesting

The problem with the block friend program you just created is that it is predictable; she's always going to do the same thing. After you’ve run the program only a couple of times, you’ll know exactly what she's going to do and when, so things are going to get boring very quickly. To really give your block friend a ‘mind', you need to give her an air of unpredictability.

By using random numbers, you can simulate unpredictability—in other words, make something look as if it’s acting unpredictably. You do this by making a program choose to do things based on a probability; for example, you might tell it to do a particular action 1 every 100 times. By adding more rules based on different odds, you can make the program much more difficult to predict. Before changing the block friend program to use random numbers, let’s explore the code to create random numbers and probability checks. You may remember random numbers being introduced in Adventure 3.

The Python random module contains the function random.randint(startNumber, endNumber) which is used to generate a random number between two specific numbers (startNumber, endNumber).

The following code prints a random number between 1 and 10 each time it is run. If you want to see the results, you should create a new Python program:

import random
randomNo = random.randint(1,10)
print(randomNo)

By adding an if statement to check when the random number is 10, you create a probability check that will be true approximately 1 time in every 10:

import random
if random.randint(1,10) == 10:
print("This happens about 1 time in 10")
else
print("This happens about 9 times out of 10")

If you were to run this program 100 times you would expect to see “This happens about 1 time in 10” printed about 10 times (see Figure 7-3), but you might only see it 9 or 11 times, or maybe even not at all. It's unpredictable!

image

FIGURE 7-3 Creating random numbers to give your block friend an air of unpredictability

If you use random numbers and a probability check in your block friend program, you can make it less predictable. You can even make the block friend “unfriend” your player!

Add some new rules to the block friend program so that if the block friend is “sad” there is a 1 in 100 chance she will decide she has had enough of waiting and will not follow your player if he comes back and gives her a hug:

  1. Open IDLE and open the BlockFriend.py program from the MyAdventures folder.
  2. Click File ⇒ Save As and save the file as BlockFriendRandom.py.
  3. Add the random module to the import statements at the top of the program (the code in bold):

    import mcpi.minecraft as minecraft
    import mcpi.block as block
    import mcpi.minecraftstuff as minecraftstuff
    import math
    import time
    import random

  4. Add a 1 in 100 random number test to change the block’s mood to "hadenough" when the block is "sad":

    elif blockMood == "sad":
    if distance <= 1:
    blockMood = "happy"
    mc.postToChat("<block> Awww thanks. Lets go.")
    if random.randint(1,100) == 100:
    blockMood = "hadenough"
    mc.postToChat("<block> Thats it. I have had ↩
              enough.")

  5. Run the program.

When your player gets too far away from the block friend, if you wait long enough (for a 1 in 100 chance to come true), the block friend decides she has had enough and ‘unfriends’ the player! Once that happens, the block friend says, “That’s it. I have had enough”, and will sit there forever.

Bigger Shapes

In the block friend program, you made one block move around and follow the player. But what if you wanted to make a lot of blocks move around? Or how about a shape made out of moving blocks, like a car or an alien spaceship?

This is where things become much more difficult, because you need to keep track of lots of blocks. Each time you want to make it move you would need to set all the blocks to AIR and then re-create the blocks in their new position. If there are a lot of blocks, the shape stops moving properly and slows to a crawl.

The minecraftstuff module contains functions called MinecraftShape, which has been written especially to create shapes and move them around. It does this by keeping track of all the blocks that make up a shape; when the shape is moved, it only changes the blocks that have changed rather than changing all of them.

To use MinecraftShape, you have to tell it what the shape looks like by creating a list of blocks that make up the shape. Each of the blocks in the shape has a position (x, y, z) and a block type.

Figure 7-4 shows a simple shape made up of seven blocks, together with the positions of the blocks. In this case, “position” isn’t the same as the position in Minecraft. You’ll see that the centre of the wooden horse is 0,0,0 and each block is relative to the centre, so the block to the right is 1,0,0.

image

FIGURE 7-4 Block positions of a wooden horse Minecraft shape

Now you’re going to create a program that uses MinecraftShape to create the wooden horse in Figure 7-4 and make it move:

  1. Open IDLE, and click File ⇒ New File to create a new program. Save the file as WoodenHorse.py in the MyAdventures folder.
  2. Import the minecraft, block, minecraftstuff and time modules:

    import mcpi.minecraft as minecraft
    import mcpi.block as block
    import mcpi.minecraftstuff as minecraftstuff
    import time

  3. Create the Minecraft object:

    mc = minecraft.Minecraft.create()

  4. Tell MinecraftShape where in the Minecraft world to create the wooden horse. Get the player’s position and add 1 to the z and y coordinates, so it isn’t directly on top of the player:

    horsePos = mc.player.getTilePos()
    horsePos.z = horsePos.z + 1
    horsePos.y = horsePos.y + 1

  5. Create the wooden horse by using MinecraftShape, passing the Minecraft object and the position where the shape should be created as parameters:

    horseShape = minecraftstuff.MinecraftShape(mc, horsePos)

  6. Set the blocks in the wooden horse:

    horseShape.setBlock(0,0,0,block.WOOD_PLANKS.id)
    horseShape.setBlock(-1,0,0,block.WOOD_PLANKS.id)
    horseShape.setBlock(1,0,0,block.WOOD_PLANKS.id)
    horseShape.setBlock(-1,-1,0,block.WOOD_PLANKS.id)
    horseShape.setBlock(1,-1,0,block.WOOD_PLANKS.id)
    horseShape.setBlock(1,1,0,block.WOOD_PLANKS.id)
    horseShape.setBlock(2,1,0,block.WOOD_PLANKS.id)

    The position of the blocks is the same as shown in Figure 7-4.

  7. Run the program. Voila! You should see a wooden horse appear next to the player.
  8. Modify the WoodenHorse.py program to make the horse move by adding the following code to the bottom of the program:

    for count in range(0,10):
    time.sleep(1)
    horseShape.moveBy(1,0,0)
    horseShape.clear()

    The moveBy(x,y,z) function tells the shape to “move by” the number of blocks in x, y, z. So in this example, the horseShape is moved by one block across (x). The clear() function removes the shape, setting all the blocks to AIR.

  9. Run the program and watch the wooden horse gallop!

You can download the complete code for the wooden horse from the Adventures in Minecraft companion website at www.wiley.com/go/adventuresinminecraft2e.

You’ll find shapes useful now, because you’re going to create an alien spaceship! Later, you use them again to create obstacles.

Alien Invasion

Aliens are about to invade Minecraft. A spaceship comes down from the sky directly above your player, who is in mortal danger—these aliens are not friendly and they won’t give up until they have completed their mission.

In the next program, you use MinecraftShape and the programming techniques you used in the block friend program to create an alien spaceship (see Figure 7-5) which hovers above the surface of the world, chasing your player, trying to get above him. And when it succeeds, it beams him onboard.

image

FIGURE 7-5 Create an alien spaceship to spice up your Minecraft game!

You create the alien spaceship using MinecraftShape, just like in the wooden horse program with each block in the shape having its own relative position and block type. Figure 7-6 shows the positions of the shape’s blocks from the side and from above.

image

FIGURE 7-6 Alien spaceship block positions

Like the block friend program, the code for the alien invasion is in two parts. The first part is the rules to decide what the spaceship does next; the second part is the code that moves the alien spaceship towards the player.

When the alien spaceship is chasing the player, it taunts him by posting messages (like “you can’t run forever”) to the chat. The messages are picked at random from a list of taunts (see Figure 7-7).

image

FIGURE 7-7 The alien spaceship gives chase.

The rules to decide what the alien spaceship does next is based on one of three modes:

  • Landing: When the program starts, this is the spaceship’s initial mode as the spaceship comes down from sky directly above the player.
  • Attack: As soon as the spaceship lands, it starts to attack, constantly chasing the player until it is directly above him, from where it will “beam” the player inside.
  • Mission accomplished: This mode is set after the player has been beamed inside the ship and the aliens are ready to return him to the ground. At this point the program finishes, and the player is beamed back.

Once the alien spaceship has captured the player, the program builds a dismal room in which to hold him and change his position to be inside it (see Figure 7-8). The aliens then post messages to the player before beaming him back by changing his position back to what it was and clearing the room.

image

FIGURE 7-8 Inside the alien spaceship

Use the following steps to create the alien invasion program:

  1. Open IDLE, click New ⇒ New File and save the file as AlienInvasion.py in the MyAdventures folder.
  2. Import the minecraft, block, minecraftstuff and time modules:

    import mcpi.minecraft as minecraft
    import mcpi.block as block
    import mcpi.minecraftstuff as minecraftstuff
    import time

  3. Create the distanceBetweenPoints() function:

    def distanceBetweenPoints(point1, point2):
    xd = point2.x - point1.x
    yd = point2.y - point1.y
    zd = point2.z - point1.z
    return math.sqrt((xd*xd) + (yd*yd) + (zd*zd))

  4. Create the constants for the program. HOVER_HEIGHT is the number of blocks the alien spaceship hovers over the player; ALIEN_TAUNTS is a list of the taunts that are posted to the chat while the aliens are chasing the player:

    HOVER_HEIGHT = 15
    ALIEN_TAUNTS = ["<aliens>You cannot run forever",
    "<aliens>Resistance is useless",
    "<aliens>We only want to be friends"]

    You can change the aliens’ taunts—see how creative you can be! Or add more if you like.

  5. Create the Minecraft and MinecraftDrawing objects:

    mc = minecraft.Minecraft.create()
    mcdrawing = minecraftstuff.MinecraftDrawing(mc)

  6. Set the aliens’ starting position and mode, which will be 50 blocks directly above the player and “landing”:

    alienPos = mc.player.getTilePos()
    alienPos.y = alienPos.y + 50
    mode = "landing"

  7. Create the alien spaceship using MinecraftShape (refer to Figure 7-6 for a reminder of how this is done):

    alienShape = minecraftstuff.MinecraftShape(mc, alienPos)

    alienShape.setBlock(-1,0,0,block.WOOL.id, 5)
    alienShape.setBlock(0,0,-1,block.WOOL.id, 5)
    alienShape.setBlock(1,0,0,block.WOOL.id, 5)
    alienShape.setBlock(0,0,1,block.WOOL.id, 5)
    alienShape.setBlock(0,-1,0,block.GLOWSTONE_BLOCK.id)
    alienShape.setBlock(0,1,0,block.GLOWSTONE_BLOCK.id)

  8. Create a while loop, which continues to loop while the mode is not "missionaccomplished" or, to put it another way, exits when the mode is "missionaccomplished":

    while mode != "missionaccomplished":

  9. Get the player’s position each time around the loop:

    playerPos = mc.player.getTilePos()

  10. The next section of code relates to the rules the program uses to decide what to do next—if the mode is "landing", set the alien target (where the alien spaceship travels to) to be above the player’s position and set the mode to "attack":

    if mode == "landing":
    mc.postToChat("<aliens> We do not come in peace - ↩
         please panic")
    alienTarget = playerPos.clone()
    alienTarget.y = alienTarget.y + HOVER_HEIGHT
    mode = "attack"

  11. Otherwise, if the mode is "attack", check to see whether the alien spaceship is above the player. If it is, beam him inside the ship and set the mode to "missionaccomplished". Otherwise, if the player has got away, set the alien target to be the player’s current position and post a taunt to the chat:

    elif mode == "attack":
    #check to see if the alien ship is above the player
    if alienPos.x == playerPos.x and alienPos.z == ↩
          playerPos.z:
    mc.postToChat("<aliens>We have you now!")

    #create a room
    mc.setBlocks(0,50,0,6,56,6,block.BEDROCK.id)
    mc.setBlocks(1,51,1,5,55,5,block.AIR.id)
    mc.setBlock(3,55,3,block.GLOWSTONE_BLOCK.id)

    #beam up player
    mc.player.setTilePos(3,51,5)
    time.sleep(10)
    mc.postToChat("<aliens>Not very interesting at all - ↩send it back")
    time.sleep(2)

    #send the player back to the original position
    mc.player.setTilePos(
    playerPos.x, playerPos.y, playerPos.z)

    #clear the room
    mc.setBlocks(0,50,0,6,56,6,block.AIR.id)
    mode = "missionaccomplished"

    else:
    #the player got away
    mc.postToChat(
    ALIEN_TAUNTS[random.randint(0,len(ALIEN_TAUNTS)-1)])
    alienTarget = playerPos.clone()
    alienTarget.y = alienTarget.y + HOVER_HEIGHT

    When the player is beamed aboard the spaceship, a room is built 50 blocks over the spawn position and the player’s position is set to be inside the room. (Just like Doctor Who’s Tardis, the inside is bigger than the outside!). Messages are then posted to the chat, before the player’s position is set to be back where he started and the room is cleared.

  12. If the position of the alien spaceship is not equal to the target (set in the rules above), move the alien spaceship to the target by typing this code into the end of the program, indented under the while loop:

    if alienPos != alienTarget:

    line = mcdrawing.getLine(
    alienPos.x, alienPos.y, alienPos.z,
    alienTarget.x, alienTarget.y, alienTarget.z)

    for nextBlock in line:
    alienShape.move(
    nextBlock.x, nextBlock.y, nextBlock.z)

    time.sleep(0.25)

    alienPos = alienTarget.clone()

  13. At this point the program returns to the top of the while loop. When the mode has been set to "missionaccomplished" and the while loop finishes, the last line of the program makes the alien spaceship disappear:

    alienShape.clear()

  14. Run the program and watch out for the aliens who come down from the sky directly above you.

You can download the complete code for the alien invasion from the Adventures in Minecraft companion website at www.wiley.com/go/adventuresinminecraft2e.

Further Adventures in Simulation

In this adventure you have used algorithms and rules to simulate a friend and an alien invasion—how about taking it further and simulating other things such as a flock of birds (or blocks), waves across the oceans in Minecraft or a complete cellular system such as Conway’s Game of Life made out of blocks.

To find out more about Conway’s Game of Life visit en.wikipedia.org/wiki/Conway's_Game_of_Life.

Quick Reference Table

Command

Description

import random

Imports the Python random module

random.randint(start, end)

Creates a random number between the start and end numbers

import minecraftstuff

Imports the minecraftstuff extensions module, which is included in the Starter Kit

mc.getHeight(x,z)

Gets the height (y coordinate) of the land (i.e. the first block down from the sky that isn’t AIR) for a horizontal position (x,z)

mcdrawing = minecraftstuff. ↩

MinecraftDrawing(mc)

Creates the MinecraftDrawing object

copyOfPosition = position.clone()

Creates a copy (clone) of a Minecraft position

mcdrawing.getLine(x1, y1, z1, x2, y2, z2)

Gets all the blocks in a line between two points

shape = minecraftstuff. ↩

MinecraftShape(mc, pos)

shape.setBlock(1,0,0,block.DIRT.id)

shape.setBlock(0,0,1,block.DIRT.id)

Creates a MinecraftShape

shape.moveBy(x,y,z)

Moves a MinecraftShape by the value in x,y,z

shape.move(x,y,z)

Moves a MinecraftShape to the position x,y,z

shape.clear()

Clears the MinecraftShape

shape.draw()

Draws the MinecraftShape

image

Achievement Unlocked: Abducted by your own artificial intelligence!

..................Content has been hidden....................

You can't read the all page of ebook, please click here login for view all page.
Reset
18.117.81.240