Skip to content

Starting example

Ondřej Šebek edited this page Mar 24, 2020 · 4 revisions

Starting example

We will create a simple script, that will help Karel find a treasure hidden in a wall of a rectangle room.

This is the starting map:

####$###
#......#
#......#
#..>...#
#......#
########

Setup

First you will need Python3 and a terminal1.

Now you can use commands in the terminal. Lets start by downloading the Karel package:

pip3 install karel_robot

Now you will need to store the map if you don't have it already2:

cd ~/Desktop     # go to a directory you can find
nano window.txt  # save the above map to a text file, use your favorite text editor

Program

Create a Python text file (treasure.py) and at the top of it load Karel:

from karel_robot.run import *

You can save the file and run it with Python from command line:

python treasure.py                # open an empty infinite map
python treasure.py -m window.txt  # open the map from file if you are in the same directory

example1

Small step for Karel

Great, Karel does not move though. Let's fix that! Edit the file like this:

from karel_robot.run import *

move()

Run with the map again and Karel should have moved one step. Now we march him to the wall:

from karel_robot.run import *

while not front_is_blocked():
    move()

We use another function called front_is_blocked and Python while loop and logical not. What they do should be self-explanatory, but lets run the script again, to make it obvious:

while_not_blocked

Huge leap for Machines

Now that we are facing wall we will go around and wont stop until we find the treasure:

from karel_robot.run import *

while not front_is_blocked():
    move()

while not front_is_treasure():
    turn_left()
    move()
    turn_right()

Now if the treasure was in the wall in front of Karel, he would have found it! Sadly there are corners in a room and Karel got stuck there:

corner_stuck

Look before you leap

Python comes to the rescue with if construction. That is exactly what we need and we can simply turn when we get in a corner:

from karel_robot.run import *

while not front_is_blocked():
    move()

while not front_is_treasure():
    turn_left()
    if front_is_blocked():
        turn_left()
    move()
    turn_right()

message("Found it!", paused=True)

Running the script now should finally get Karel to the treasure.

found_it

Find every possible treasure

If you watched at Karel carefully you might have noticed he gets a little faster in the corner. The problem is he is too fast! There might have been a treasure and he would have missed it.

This is called... wait for it... a corner case! Turns out there are at least 3 problems with the code. Take a moment to think about them and then click the solution:

Solution
  1. When treasure is in the corner, then Karel goes around in a loop.
  2. When Karel starts next to a wall or even treasure, he can go a full loop if he looks the other way.
  3. If the room is only one tile, Karel will crash into a wall and die.

You can check out these maps named 0*_window.km in the world directory.

We should really do something about the third problem!

from karel_robot.run import *

while not front_is_blocked():
    move()

while not front_is_treasure():
    turn_left()
    if front_is_blocked():
        turn_left()
    else:
        move()
    turn_right()

message("Found it!", paused=True)

Hah! Turns out we only needed to add an else case. This solves both the first and the third problem. The second one is left as an exercise to the reader. 😝

Takeaway

With these simple building blocks, you can already solve many of Karel's problems. However after solving a few, you may find that some parts are repeated over and over again. Python solves this by letting us write functions:

from karel_robot.run import *

def go_to_wall():
    while not front_is_blocked():
        move()

def go_around_until(stop_condition):
    while not stop_condition():
        turn_left()
        if front_is_blocked():
            turn_left()
        else:
            move()
        turn_right()


# This executes the previous only if the script is run directly,
# but you can import it in others and only use the functions
if __name__ == "__main__":
    go_to_wall()
    go_around_until(front_is_treasure)
    message("Found it!", paused=True)

This is pretty magical. Do no think too hard about how the script knows who he is or how the function takes another function. 😉

Go and write some code

If you want to solve some simple Karel problems, there is a list on next page:

For an extra level of fun, you can solve them in Karel's own language!

Credits

The example is adapted from a paper3 on cooperative education in CS1. It is inspiring a quite easy to read.


1: If you don't use terminal, good tutorial can be easily found online, for example at uw.edu.

2: For later tutorials it would be best to clone this project and use the maps and programs provided here. 😉

3: https://dl.acm.org/doi/abs/10.1145/2492686