The Builder & Relative Coordinates
Meet a faster block-placer, learn the tilde, and combine everything from Lessons 1 and 2.
How can choosing a smarter tool let your code do the same job in far fewer lines?
By the end of this lesson, I will...
- Explain how the Builder is different from the Agent.
- Read and write relative coordinates using the
~(tilde) operator. - Use
builder.move,builder.turn, andbuilder.trace_pathto draw a shape. - Make the same program more efficient by moving
trace_pathoutside the inner loop. - Use
builder.mark()andbuilder.line()to draw long lines in one step. - Combine loops (Lesson 2) with the Builder to build a wall or repeating structure.
What you already know
Today's lesson builds on everything from Lessons 1 and 2. Here's the toolkit you bring in:
player.on_chat) start your code.~.STEP 1 Warm-up: Meet the Builder
You've spent two lessons with the Agent — a visible character you can watch walk around the world. The Agent is great for learning because you can see what your code did.
Today you'll meet the Builder. The Builder does similar work but with three big differences:
| Agent | Builder | |
|---|---|---|
| Visible? | Yes — you can see it. | No — it's invisible while working. |
| Speed | Slow — walks one block at a time. | Fast — can teleport and stamp lines. |
| Inventory | Needs set_item first. | No inventory needed — just say which block. |
| Best for | Learning, debugging, watching what code does. | Big builds, walls, lines, structures. |
Today's Vocabulary
~ meaning "offset from here."mark to where the Builder is now.STEP 2 Open MakeCode (Python Only)
You should already be in your fresh flat world from Lesson 0. If not, go back and complete Lesson 0 first.
- In Minecraft, press C to open Code Builder.
- Choose MakeCode.
- Click New Project and name it
Lesson 3 - Builder. - Click Code options, then select Python Only, then click Create.
STEP 3 Relative Coordinates with ~
Minecraft has two ways to describe a position. Absolute coordinates use exact world numbers (like X = 200, Y = 64, Z = -57). Relative coordinates use the tilde character ~ and mean "offset from where the player is standing."
| Position | What it means |
|---|---|
pos(~0, ~0, ~0) | Exactly where the player is standing right now. |
pos(~5, ~0, ~0) | 5 blocks east of the player (X axis). |
pos(~0, ~3, ~0) | 3 blocks up from the player (Y axis). |
pos(~0, ~0, ~5) | 5 blocks south of the player (Z axis). |
pos(~-2, ~0, ~0) | 2 blocks west of the player (negative direction). |
~), your program only works at one specific spot in the world. With ~, the same program works wherever the player is standing. Relative coordinates make your code portable.
You'll see pos(~0, ~0, ~0) a lot in this lesson. It just means "start here."
RECAP First, the Agent Way (from Lesson 2)
You already know how to make a 5×5 square outline with the Agent. Here it is one more time so we have something to compare with:
def on_chat():
agent.set_item(STONE, 64, 1)
for side in range(4):
for step in range(5):
agent.move(FORWARD, 1)
agent.destroy(DOWN)
agent.place(DOWN)
agent.turn(LEFT_TURN)
player.on_chat("agent_square", on_chat)
If you want to feel the difference, paste this in and run it with the chat command agent_square. You'll watch the Agent walk every block, one at a time. It works — but you'll see why the Builder is appealing.
STEP 5 Builder Version 1: Just Like the Agent
Here is the same 5×5 square — but written with the Builder. Look carefully at the differences.
def on_chat():
# Start fresh: warp the Builder to the player. This resets where the
# Builder is so the program produces the same result no matter what ran before.
builder.teleport_to(pos(~0, ~0, ~0))
for side in range(4):
for step in range(5):
builder.move(FORWARD, 1)
builder.trace_path(STONE)
builder.turn(TurnDirection.LEFT)
player.on_chat("build1", on_chat)
What changed
builder.teleport_to(pos(~0, ~0, ~0))— warp the Builder to where the player is standing. This is a one-line replacement for "summon and position the Agent."builder.move(FORWARD, 1)— same idea asagent.move, but for the Builder.builder.trace_path(STONE)— stamps a stone block on the Builder's path. Noset_item, nodestroy, no inventory worries.builder.turn(TurnDirection.LEFT)— same idea asagent.turn(LEFT_TURN), but the constant name is different. (Don't ask me why — it just is.)
Predict: how is the result different from the Agent version? How does the experience of running it differ?
The result is the same: a 5×5 stone outline. The experience is very different — you won't see anything walking around the world. The square just appears. The Builder is invisible.
/tp ~ ~ ~10, and press Enter to jump 10 blocks south. Now there's open ground in front of the Builder and you'll have a clear view of what it does.
Run it with the chat command build1 and watch the square pop into existence.
STEP 6 Builder Version 2: One Trace at the End
The Builder has a trick the Agent doesn't have. You can walk the whole path first, then call trace_path once at the very end. The Builder remembers every step it took and stamps the blocks along the whole route.
def on_chat():
# Start fresh: warp to the player so this function stands alone.
builder.teleport_to(pos(~0, ~0, ~0))
for side in range(4):
for step in range(5):
builder.move(FORWARD, 1)
builder.turn(TurnDirection.LEFT)
builder.trace_path(STONE)
player.on_chat("build2", on_chat)
What changed (and why it's better)
trace_path(STONE)moved outside the inner loop — it's the last line of the function.- The Builder walks the entire square path first, then trace_path stamps all the stone in one operation.
- Result is identical to Version 1, but the program does its work in one big stamp instead of 20 small ones.
/tp ~ ~ ~10, and press Enter. Standing 10 blocks back lets you see the entire square at once. Then run the chat command build2.
STEP 7 Builder Version 3: mark() and line()
For straight lines the Builder has a faster trick still: mark a spot, teleport somewhere else, and draw a line between them.
def on_chat():
# Start fresh: warp to the player so this function stands alone.
builder.teleport_to(pos(~0, ~0, ~0))
builder.mark()
builder.teleport_to(pos(~100, ~0, ~0))
builder.line(STONE)
player.on_chat("long_line", on_chat)
How this works
teleport_to(pos(~0, ~0, ~0))— place the Builder at the player's spot.mark()— remember this position.teleport_to(pos(~100, ~0, ~0))— warp 100 blocks east.line(STONE)— fill every block between the mark and here with stone.
Predict: how many stone blocks will appear, and how long does the program take to run?
Roughly 100 stone blocks stretching east from where you stand — and the whole thing happens almost instantly. You did the work of a 100-iteration loop in 4 lines of code.
trace_path— you walked a curvy path and want to stamp blocks along the route.mark()+line()— you want a straight line between two points. Way faster than walking.agent.move + place— you want to see the work happen for debugging or for fun.
/tp ~ ~ ~10, and press Enter. The line will run alongside you instead of into you. Then run long_line.
STEP 8 Combining Loops with mark() and line()
Now bring the two pieces together. We use a loop (from Lesson 2) to repeat a mark/line pair. Each iteration draws one row, and after drawing we step the Builder up by 1. Result: a wall.
def on_chat():
# Start fresh: warp to the player so this function stands alone.
builder.teleport_to(pos(~0, ~0, ~0))
for layer in range(5):
builder.mark()
builder.move(FORWARD, 10)
builder.line(STONE)
builder.move(BACK, 10)
builder.move(UP, 1)
player.on_chat("wall", on_chat)
Reading this nested idea
- The loop runs 5 times — one per layer of the wall.
- Each iteration: mark the spot, walk forward 10, draw a stone line back to the mark.
- Then walk back to the start of this row (so the next mark begins lined up).
- Move up 1 block to start the next layer.
- Total: a wall 10 blocks long, 5 blocks tall.
Predict: if you change range(5) to range(15), what changes? What if you change FORWARD, 10 to FORWARD, 30?
range(15) → the wall becomes 15 blocks tall instead of 5. Same length, more height.
FORWARD, 30 (and BACK, 30) → the wall becomes 30 blocks long. Same height, much longer.
/tp ~ ~ ~10, and press Enter. You'll be 10 blocks south of where the wall builds, with a clean view of the whole thing.
Run it as wall and look at what just appeared. Try the changes from the prediction prompt and watch the wall scale up.
CHALLENGE Build Something Big
Create an original Builder program that uses at least one loop and either mark()+line() or trace_path(). Pick a challenge below — or invent your own.
Minimum requirements
- Your program starts with a chat command.
- Your program uses at least one
forloop. - Your program uses the Builder — not the Agent.
- Your program uses at least one of:
trace_path,mark()+line(). - Your program uses relative coordinates (
~) at least once. - Your build covers a footprint of at least 10×10 blocks, or stands at least 8 blocks tall.
Stretch goals
- Build a filled rectangle floor (not just an outline) using nested loops and
mark()+line(). - Use multiple block types — alternate stone and glass to make a checker or stripe pattern.
- Add an opening (door or window) by skipping certain iterations with an
ifstatement. - Add
#comments above each section to explain what it does.
SUBMIT Turn In Your Work
Submit three items to the Schoology assignment:
- Screenshot of your code in the MakeCode editor. Your loop and your Builder commands must be visible.
- Screenshot of the result in Minecraft — the structure or pattern your Builder created.
- Short written reflection. Answer all four in 1–2 sentences each:
- What did your program build, and which Builder commands did you use?
- Where in your code did you use
~(relative coordinates)? Why is that useful? - Compare: how would this same build look if you wrote it with the Agent? Faster or slower? Why?
- Describe one bug or surprise you ran into and what fixed it.
When You're Done
- Trade computers and run a classmate's program.
- Look up
builder.fillin the MakeCode docs — it fills a solid box between two marked corners in one call. - Try building a hollow cube using
mark()+line()for each edge. - Re-write your Lesson 2 challenge using the Builder. How much shorter does the code get?