Learn How to Think with Karel the Robot. Chapter 6. Custom Commands
Chapter 6
Custom Commands
In this chapter you will learn:
- How to split complex problems into simpler ones which are easier to solve.
- How to define custom commands using the keyword def.
- How to use the optional return statement.
- The Second Maze Algorithm of robotics.
- That the shortest program may not always be the most efficient one.
- How to define new commands locally within the body of other commands.
6.1. Why are custom commands useful?
Today, Karel needs to collect 25 computer chips which form five stars:
The following program will solve the task, but it would not get you hired as a software engineer.
Look at it first, and then we will explain what is wrong with it:
2 go
3left
4go
5
6repeat 4
7 get
8 go
9 right
10 go
11 left
12 left
13go
14get
15go
16
17right
18repeat 6
19 go
20left
21
22repeat 4
23 get
24 go
25 right
26 go
27 left
28 left
29go
30get
31go
32
33left
34repeat 8
35 go
36right
37
38repeat 4
39 get
40 go
41 right
42 go
43 left
44 left
45go
46get
47go
48
49right
50repeat 10
51 go
52left
53
54repeat 4
55 get
56 go
57 right
58 go
59 left
60 left
61go
62get
63go
64
65left
66repeat 6
67 go
68right
69
70repeat 4
71 get
72 go
73 right
74 go
75 left
76 left
77go
78get
79go
80
81right
82repeat 8
83 go
The problem with this program is that it contains a 10-line section which was copied and pasted
five times:
This is the section of the code which actually collects the pattern of five chips.
Copying and pasting code makes the program not only long and cumbersome to work with, but also extremely prone to mistakes. Imagine that the pattern of the chips changes:
Then the above code would have to be redone at five different places (!) Since programmers are only human, they are likely to make mistakes. And changing the same code at five different places makes the likelihood of making a mistake extremely high.
6.2. Defining a custom command star
The correct approach is to define a new command for the repeated functionality. Let’s call it
star:
2def star
3 repeat 4
4 get
5 go
6 right
7 go
8 left
9 left
10 go
11 get
12 go
Notice that custom commands are defined using the keyword def which is followed by the name of the new command. Then, indented, comes the body of the command. The following image shows where Karel should be when the command star is executed, and then the robot’s position after the command finishes:

6.3. Assembling the solution of the main task
Recall that the main task is to collect all 25 chips:
But how can the custom command star be used to solve it, when Karel is far away from the first star of chips?
The answer is - before executing the command star, we will program Karel to get there! In order to stand on the first chip of the first star, the robot needs to make four steps forward, turn left, and make one more step:
go
left
go
After executing this initial code, Karel is ready to execute the command star for the first
time.
Next, in order to get ready for collecting the second star of chips, Karel needs to turn right, make 6 steps forward, and turn left:
repeat 6
go
left
After executing this code, he is ready:
Now you should able to figure out the rest! Write down the commands Karel needs to
get ready to collect the third, fourth, and fifth stars of chips. The final program is as
follows:
2def star
3 repeat 4
4 get
5 go
6 right
7 go
8 left
9 left
10 go
11 get
12 go
13
14# Main program:
15# Collect the 1st star:
16repeat 4
17 go
18left
19go
20star
21# Collect the 2nd star:
22right
23repeat 6
24 go
25left
26star
27# Collect the 3rd star:
28left
29repeat 8
30 go
31right
32star
33# Collect the 4th star:
34right
35repeat 10
36 go
37left
38star
39# Collect the 5th star:
40left
41repeat 6
42 go
43right
44star
45# Finish at the home square:
46right
47repeat 8
48 go

6.4. Collecting water bottles
Today Karel faces another complex task - to collect 27 water bottles which are stored in three crates:
As you already know, it would not be a good idea to go ahead and start writing code right away.
Let’s think about it first, and figure out a suitable subtask which is easier to solve than the main
task.
Here is a good candidate for such a subtask. Let’s call the new command get9:
This time, let’s work like an experienced software engineer, and solve the main task first. We
know that the subtask is a routine thing to do, so we can leave it for later. The main program is
below. Step through it in your mind to verify that it is correct!
2# Get to the 1st crate:
3go
4# Collect the 1st crate:
5get9
6# Collect the 2nd crate:
7get9
8# Get to the 3rd crate:
9left
10repeat 5
11 go
12right
13# Collect the 3rd crate:
14get9
15# Make one last step home:
16go
This was a piece of cake - which tells us that the subtask was chosen really well! It remains to write the body of the new command get9. But you know what? We can still simplify it by splitting it into three smaller subtasks, where one subtask will be to just collect a row of three water bottles. Let’s call the new command get3:
Karel’s position before and after executing the command get3 (on the left, one water bottle is beneath Karel).
The following code will do it:
And now, the new command get9 is easy to write:
2def get9
3 get3
4 right
5 go
6 right
7 get3
8 left
9 go
10 left
11 get3
12 go
Finally, let’s put everything together and write the solution program for the main task. The
program will consist of two custom commands and a main program:
2def get3
3 repeat 2
4 get
5 go
6 get
7
8# Collect 9 water bottles:
9def get9
10 get3
11 right
12 go
13 right
14 get3
15 left
16 go
17 left
18 get3
19 go
20
21# Main program:
22# Get to the 1st crate:
23go
24# Collect the 1st crate:
25get9
26# Collect the 2nd crate:
27get9
28# Get to the 3rd crate:
29left
30repeat 5
31 go
32right
33# Collect the 3rd crate:
34get9
35# Make one last step home:
36go
6.5. The optional return statement
Every custom command can (but does not have to) contain one or more return statements. The
return statement terminates and exits the custom command. For example, the command get3
from the previous section could be written as follows:

6.6. Arcade game
Karel’s next task is to pass through the entire maze, collecting all gold nuggets and gems:
This is a complex task, so why don’t we solve a simpler subtask first. It will be much easier to just pass through one floor, left to right, collect all nuggets and gems, and if not at home, then find the opening to the next floor up. Let’s call the new command floor:
As before, first let’s solve the main task assuming that we already have the command floor.
The new command will be easy to define later:
2repeat 12
3 # Pass through one floor:
4 floor
5 # If not at home, get ready at the left end of the new floor:
6 if not home
7 left
8 while not wall
9 go
10 repeat 2
11 right
And here is the new command floor:
2def floor
3 repeat 14
4 if gem or nugget
5 get
6 go
7 if gem or nugget
8 get
9 # If not home, find the opening up:
10 if not home
11 left
12 while wall
13 left
14 go
15 right
16 go
By putting the pieces together, we obtain the final solution program:
2def floor
3 repeat 14
4 if gem or nugget
5 get
6 go
7 if gem or nugget
8 get
9 # If not home, find the opening up:
10 if not home
11 left
12 while wall
13 left
14 go
15 right
16 go
17
18# Main program:
19repeat 12
20 # Pass through one floor:
21 floor
22 # If not at home, get ready at the left end of the new floor:
23 if not home
24 left
25 while not wall
26 go
27 repeat 2
28 right

6.7. Second Maze Algorithm (SMA)
You already know the First Maze Algorithm of robotics which allows Karel (or any other robot) to pass through unknown mazes. The Second Maze Algorithm (SMA) allows robots to follow an arbitrary winding wall or a line on the ground. Imagine that Karel is in the jungle, and he has to follow a winding line of tree branches to his home square. He stands next to the line which is on his left-hand side:
The Second Maze Algorithm of robotics will guide Karel safely to his home square:
2: Turn left.
3: While there is a wall in front of you, keep turning right.
4: Make one step forward.
It can be translated to the following code:
Let’s have a closer look at how the algorithm works! At the beginning, the line goes straight forward:
On line 2, Karel will turn left:
The while loop on line 3 will do one cycle, and so Karel will turn right once:
Finally, on line 5, he will make one step forward:
OK, that worked! After two more steps forward, Karel will arrive at a right turn:
On line 2, he will turn left:
Then, the while loop on line 3 will do two cycles:
And finally, Karel will make one step forward on line 5:
After this, the robot will make another right turn and two steps forward. Then the situation becomes more interesting because there is no wall on his left. BTW, this case is why the algorithm begins with a left turn, in case you were puzzled about it:
So, on line 2 Karel will turn left:
The body of the while loop will be skipped because there is no wall in front of the robot, and he will just make one step forward on line 5:
Now the situation repeats itself because there is no wall on Karel’s left. Hence, on line 2 he turns left:
Because there is no wall in front of him, the body of the while loop will be skipped again, and on line 5 he will make one step forward:
Woo-hoo, almost there! After a few more steps and one more right turn, Karel arrives at a left turn:
On line 2 he turns left:
Since there is a wall in front of him, the while loop will make him turn right once:
And on line 5 he makes one step forward:
You already know this situation - Karel does not have a wall on his left. On line 2 he turns left:
Then, because there is no wall in front of the robot, the body of the while loop is skipped, and Karel just makes one step forward:
6.8. Right-handed version of the SMA
Like the First Maze Algorithm, also the Second Maze Algorithm has a right-handed version. It is useful when Karel needs to follow a wall or line which is on his right:
The algorithm is symmetric to the SMA (just switch "left" to "right" and vice versa):
2: Turn right.
3: While there is a wall in front of you, keep turning left.
4: Make one step forward.
Here is the corresponding code:
6.9. Rock climbing
Today, Karel will climb some rocks! His task is to collect all the beepers and enter his home square. The shape of the rock is random, and so is the number and positions of the beepers on it:
This task is perfect for the Second Maze Algorithm (right-handed version). Just executing
Program 6.14 will make Karel follow the contour of the rock ("climb on the rock") and get to his
home square. So, the only change we need to make, is to check for a beeper after each step the
robot makes:
6.10. Program length vs. efficiency
You already know that a well thought-out program usually is shorter and more elegant than a
program which was written hastily. However, program length is not the only thing that matters.
Even more important is efficiency.
In this section we will show you that the shortest program may not always be the most efficient one.
Today, Karel is collecting pearls in the ocean:
This task is perfect for the Second Maze Algorithm (right-handed version) - Karel just needs to follow the wall on his right-hand side, and it will lead him to his home square. The solution program is practically the same as Program 6.15, the only difference being that the robot is looking for pearls instead of beepers:
This program needs 503 operations to collect all pearls and get Karel home. Save this number for a future comparison!
Next, let’s solve the task differently. We will write a new command column for the robot to collect all pearls in the column above him, and get ready below the next column. Then, the main program will just loop over all columns:
2def column
3 while not wall
4 go
5 if pearl
6 get
7 left
8 left
9 while not wall
10 go
11 right
12 go
13 right
14
15# Main program:
16repeat 14
17 column
18repeat 7
19 go
As you can see, this program is longer than the previous one - it has 16 lines of code as opposed
to 7. However, it provides a solution which is much more efficient. It collectc all pearls and gets
the robot home with only 242 operations!
6.11. Writing monolithic code vs. using custom commands
Sometimes it is not obvious whether one will gain anything by introducing a custom command. For illustration, let’s return to the five stars of chips from Section 6.1 (page 490), but now the stars will form a regular repeating pattern. The task is the same - collect all the chips!
The code can be written as one monolithic piece, without defining any custom commands:
2repeat 5 # loop over stars
3 repeat 4 # collect one star
4 get
5 go
6 right
7 go
8 left
9 left
10 go
11 get
12 go
13 right # move to the next star or home square
14 repeat 3
15 if not home
16 go
17 left
This code is very dense, but it does not contradict any good programming practices - there is no part which would be copied and pasted at multiple different places in the program (as it was in the original task in Section 6.1). The comments make it readable, so it is a good code.
Now let’s solve the same task using the custom command star from Section 6.1. And
moreover, we will define another new command next for the robot to move to the next star or to
the home square:
2def star
3 repeat 4
4 get
5 go
6 right
7 go
8 left
9 left
10 go
11 get
12 go
13
14# Move to the next star or home square:
15def next
16 right
17 repeat 3
18 if not home
19 go
20 left
21
22# Main program:
23go
24repeat 5
25 star
26 next
The latter program had 21 lines (not counting empty lines and comments) while the former only
had 17. This is not a huge difference. On the other hand, the latter program is so well readable
that the main program does not need any comments - it is completely self-explanatory.
Readability matters. If we had to pick up our favorite, then the slightly longer but much more
readable program would definitely be our choice.
6.12. Defining commands inside other commands
It is possible in Karel to define commands within the body of other commands. This feature was implemented for conceptual compatibility with Python. Its usefulness becomes clear in large, complex programs where it helps keep code better organized.
For illustration, let’s return to Section 6.4 (page 516) where Karel was collecting water bottles
from three crates. The solution Program 6.8 defined new commands get3 and get9.
Notably, the command get3 was only used within the body of the command get9
and nowhere else. Therefore, it can be defined locally in the body of the command
get9:
2def get9
3
4 # Collect three water bottles
5 def get3
6 repeat 2
7 get
8 go
9 get
10
11 # Main body of the command:
12 get3
13 right
14 go
15 right
16 get3
17 left
18 go
19 left
20 get3
21 go
22
23# Main program:
24# Get to the 1st crate:
25go
26# Collect the 1st crate:
27get9
28# Collect the 2nd crate:
29get9
30# Get to the 3rd crate:
31left
32repeat 5
33 go
34right
35# Collect the 3rd crate:
36get9
37# Make one last step home:
38go

If we tried to call the command get3 outside the body of the command get9, the program would crash with an error message. In larger programs, limiting the validity of commands helps improve code structure.
6.13. Create your own Karel language!
Being able to define your own commands is powerful. If you like, you can now create your own
language for Karel, adding all the commands which you were missing! For example, the
Karel language does not have a command to turn around 180 degrees, so let’s add
it:
With this new command in hand, many algorithms become simpler to implement, such as the
First Maze Algorithm:
Speaking of the First Maze Algorithm, why don’t we just define a new command move to move
one step forward in the maze:
Then, passing through an unknown maze becomes extremely simple:
Now let’s change the subject. If your native language is different from English, you can make
Karel speak your language! For example, "get" is "ukuthola" in Zulu:
6.14. Review questions
Friendly reminder - for every question either none, one, or several answers may be correct.
QUESTION 6.1. Is copying and pasting code a bad thing?
- A
- No because the length of the program grows more quickly.
- B
- Yes because the program becomes prone to mistakes.
- C
- No because the program will run faster.
- D
- No because this makes programming easier.
QUESTION 6.2. Is it a good idea to split complex tasks into simpler ones?
- A
- No because it is a loss of time.
- B
- No because it’s more work.
- C
- Yes because the simpler tasks are easier to solve.
- D
- No because an experienced programmer just solves the whole task at once.
QUESTION 6.3. When does one need to identify repeating patterns?
- A
- When working with repeat loops.
- B
- When working with while loops.
- C
- When working with custom commands.
- D
- When debugging programs.
QUESTION 6.5. What keyword does Karel use to terminate and exit custom commands?
- A
- end
- B
- terminate
- C
- exit
- D
- return
QUESTION 6.6. Can custom commands define other custom commands in their body?
- A
- Yes.
- B
- No.
- C
- Only if the locally-defined command is a one-liner.
- D
- Only if the locally-defined command does not contain a return statement.
QUESTION 6.7. Can custom commands define other custom commands in their body?
- A
- Yes.
- B
- No.
- C
- Only if the locally-defined command is a one-liner.
- D
- Only if the locally-defined command does not contain a return statement.
QUESTION 6.8. What is the purpose of the Second Maze Algorithm (SMA)?
- A
- To pass through a maze without loops and dead ends.
- B
- To pass through a maze without forsk, loops and dead ends.
- C
- To follow an arbitrary winding wall or line on the ground.
- D
- To find a way out of an arbitrary maze.
QUESTION 6.9. The left-handed version of the SMA assumes that
- A
- Karel stands next to a wall, and the wall is on his left.
- B
- Karel stands next to a wall, and the wall is on his right.
- C
- Karel faces the wall.
- D
- Karel stands with his back turned to the wall.
QUESTION 6.10. What of the following actions represent one operation in the Karel language?
- A
- Karel makes one step forward.
- B
- Karel turns around 180 degrees.
- C
- Karel places an object on the ground.
- D
- Karel walks from one side of the maze to the opposite one.
QUESTION 6.11. When is a program efficient?
- A
- When it has as few lines as possible.
- B
- When it is carefully thought-out.
- C
- When it uses nested loops and conditions.
- D
- When it solves the given task using as few operations as possible.
Table of Contents
- About
- 1. Introduction
- 2. Basic Commands
- 3. Counting Loop
- 4. Conditions
- 5. Conditional Loop
- 6. Custom Commands
- 7. Variables
- 8. Functions
- 9. Text Strings
- 10. Testing Your Programs
- 11. Boolean Values, Variables, Expressions, and Functions
- 12. Randomness and Probability
- 13. Lists
- 14. Recursion
- 15. Advanced Applications
- Appendix A. Karel App in NCLab
- Appendix B. Self-Paced Karel Course in NCLab