Karel

A Robot Interpreter

Edition 0.4.0, for karel version 0.4

25 July 2000

Tom Mitchell
tmitchel@users.sourceforge.net


Table of Contents


Introduction

Learning to Program

My first college computer class, in the fall of 1982, used Karel the Robot as the introduction to programming in Pascal. I found it an entertaining and useful introduction to structured programming. While structured programming has fallen out of favor in deference to object oriented programming, I still think this can be a useful introduction to computer programming. And I think that children are entertained by the idea of instructing a robot to perform a task, and then watching the robot actually follow the instructions.

Karel

This document is light on the details of the Karel language. The definitive reference is Richard Pattis' Karel The Robot: A Gentle Introduction to The Art of Programming(1). What this document attempts to describe is the Karel simulator, which loads and executes Karel programs.

There are three user interfaces that come with the Karel package: text, curses, and gtk. The text interface prints out a line whenever Karel moves or turns. This is useful for debugging and regression testing, but not very useful to a user. The curses interface allows users to run Karel programs on a terminal, no windowing system required. The gtk interface can be used on systems that have the X Window system and the GTK development headers and libraries.

The architecture of the Karel package is such that developers can build their own user interfaces using virtually any toolkit they desire. All they need is a C interface to interact with the Karel engine. Karel was written this way to avoid being tied to any particular GUI toolkit. The choice of GUI toolkits is largely personal preference; I set the goal of being relatively toolkit independent. I expect it to be possible to build user interfaces to the Karel environment in Qt, Motif/Lesstif, Athena, Tcl/Tk, Java, perl, guile, or any other system that has a C callout mechanism.

How to use this manual

This manual is divided into 2 sections, a User's Guide and a Programmer's Guide. If you want to write Karel programs and run them, you'll want to read the User's Guide. If you want to extend the Karel environment, or you are curious about the inner workings of the environment, you will find the Programmer's Guide helpful.

Acknowledgements

Thanks go to Richard Pattis wrote Karel the Robot, upon which this program is based. Richard was kind to give me his permission to distribute this simulator. Without his book, this program could never have been written.

Thanks also go to Jan Miksovsky, who wrote a Karel simulator in the mid 1980's. I found that program in early 2000, dusted it off, and it ran. I then modified the program to be more modular, and object-oriented (as much as one can in C). I was able to locate Jan on the internet (it pays to have a unique last name, I guess) and he was gracious enough to give me his permission to modify his original work and distribute it. Not much remains of Jan's code, but the concepts behind the simulator, and particularly the engine that builds and executes a Karel program, are Jan's, and I probably couldn't have written this system without his lead to follow.

Don Dietrick and Bill Mackiewicz both served as early beta testers. I am indebted to them for their patience in dealing with a half-baked glob of software, and sparse documentation. They dutifully did the compile-make-repeat loop in order to test out the latest I had to offer.

Karel User's Guide

Invoking the Karel Simulator

A Karel simulator is a program that ties the Karel execution engine to a user interface. The execution engine is responsible for running the karel program and moving Karel around his world. The user interface is responsible for displaying the state of the world and the robot to the user. The karel distribution comes with two such simulators: a terminal based interface and an X Window System based interface.

Invoking in a terminal

karelc is a simulator written with the curses user interface. To run the samples/maze.k Karel program in the karelc simulator:

curses/karelc -p samples/maze.k -w samples/maze1.wld

Invoking under X Windows

karelg is a simulator written with an X Window System GTK user interface. To run the samples/maze.k Karel program in the karelg simulator:

gtk/karelg -p samples/maze.k -w samples/maze1.wld

The X Window System front end is based on the Gimp ToolKit. The choice of X toolkits is largely personal preference. GTK was chosen because of its LGPL license. The core of the Karel Simulator, the execution engine, is independent of any user interface. It should be easy to create a new user interface for Karel with a different X toolkit. This was one of the goals for the Karel Architecture.

Defining Karel's World

Overview

Karel's world has intersections, walls, and beepers. The programs the Karel executes are independent of the world he moves around in. You can execute the same program in multiple worlds, or multiple programs in the same world.

Karel's world is defined in a file which is loaded by a Karel simulator. The world file is a simple text file containing commands that define the size of the world, the position of walls and beepers, and Karel's starting position.

General Rules

Each line in the file describes a part of Karel's world. We'll look at each in turn, but first there are some general rules for the world file.

Reference

World num_streets num_avenues
World 5 5

The World command defines a world that is 5 avenues wide by 5 streets high.

Beepers street avenue number
Beepers 3 3 1

The beeper command places a number of beepers on an intersection. In this case, one beeper would be placed on the intersection {3, 3}

Robot street avenue direction num_beepers
Robot 4 3 1 0

The robot starting position is defined with the Robot command. In this example, the robot starts at {4, 3}, facing North (1), with zero beepers in his beeper bag.

Wall street avenue direction
Wall 2 2 1

The Wall command places a wall section in Karel's world. Each wall section is one block long. Walls can either be north or west of an intersection (1 or 4 respectively). In this example, a horizontal wall is placed directly north of the intersection {2, 2}.

Example

Here is a sample world file:

World 5 5
Beepers 3 3 1
Robot 4 3 1 0
Wall 2 2 1
Wall 3 2 1
Wall 1 1 4
Wall 2 1 4
Wall 2 2 4
Wall 3 1 4
Wall 3 2 4
Wall 3 3 4
Wall 4 1 4
Wall 4 2 4
Wall 4 3 4
Wall 4 4 4

The resulting world, in the curses interface, looks like this:

  - - - - -
 |+ + + + +|

 |+ + + +|+|

 |+ + *|+|+|
    - -
 |+ +|+|+|+|

 |+|+|+|+|+|
 ----------

Writing Karel Programs

The definitive source of Karel information is Richard Pattis' book Karel the Robot: A Gentle Introduction to The Art of Programming. This section is intended to be a brief overview of the language in order to get started using Karel.

A Simple Program

This is the simplest correct Karel program. All valid Karel programs must minimally have these 5 lines.

BEGINNING-OF-PROGRAM
  BEGINNING-OF-EXECUTION
    turnoff
  END-OF-EXECUTION
END-OF-PROGRAM

This program does nothing but turn Karel off. It is a good sample because it concisely shows the structure of a valid Karel program.

Sample Karel Program 2

By adding calls to the move and turnleft primitives, this program causes Karel to walk a square, returning to his starting point. Note that in this version of Karel, the '{' and '}' are used for comments, just like Pascal.

{ A simple karel program to walk in a square to the left }

BEGINNING-OF-PROGRAM
  BEGINNING-OF-EXECUTION
    move;
    turnleft;
    move;
    turnleft;
    move;
    turnleft;
    move;
    turnleft;
    turnoff
  END-OF-EXECUTION
END-OF-PROGRAM

Turning Right

The Karel language has a turnleft primitive, but lacks a turnright primitive. One of the first instructions a new Karel programmer does is define the turnright instruction for Karel. As the old adage goes, "two wrongs don't make a right, but three lefts do".

The following example demonstrates how to define a new instruction for Karel out of the existing primitives. This example will cause Karel to walk in a square to the right, instead of the left as in the previous example.

{ A simple karel program to walk in a square to the right }

BEGINNING-OF-PROGRAM

  DEFINE-NEW-INSTRUCTION turnright AS
    ITERATE 3 TIMES
      turnleft;

  BEGINNING-OF-EXECUTION
    move;
    turnright;
    move;
    turnright;
    move;
    turnright;
    move;
    turnright;
    turnoff
  END-OF-EXECUTION

END-OF-PROGRAM

Solving a Maze

Programs can be constructed for Karel that will allow him to find a beeper by navigating through a maze. This sample program has Karel follow walls looking for openings until he locates a beeper. You can find this program in the distribution in file `samples/maze.k'.

{ karel follows the right wall until a beeper is found}

BEGINNING-OF-PROGRAM
  DEFINE-NEW-INSTRUCTION turnright AS
    ITERATE 3 TIMES
      turnleft;

  BEGINNING-OF-EXECUTION
    WHILE not-next-to-a-beeper DO
      BEGIN
        IF right-is-clear
          THEN turnright
          ELSE
            WHILE front-is-blocked DO
              turnleft;
        move
      END;
    turnoff
  END-OF-EXECUTION
END-OF-PROGRAM

Karel Language Reference

Primitives

Built-in: move
Move Karel one intersection forward.

Built-in: turnleft
Pivots Karel 90 degrees left.

Built-in: pickbeeper
Take a beeper from the current intersection and put it in the beeper bag.

Built-in: putbeeper
Take a beeper from the beeper bag and put it at the current intersection.

Built-in: turnoff
Turn Karel off.

Tests

Test: front-is-clear
True if there is no wall directly in front of Karel. False if there is.

Test: front-is-blocked
True if there is a wall directly in front of Karel. False otherwise.

Test: left-is-clear
True if there is no wall immediately to Karel's left. False if there is.

Test: left-is-blocked
True if there is a wall immediately to Karel's left. False otherwise.

Test: right-is-clear
True if there is no wall immediately to Karel's right. False if there is.

Test: right-is-blocked
True if there is a wall immediately to Karel's right. False otherwise.

Test: next-to-a-beeper
True if Karel is standing at an intersection that has a beeper. False otherwise.

Test: not-next-to-a-beeper
True if there is not beeper at the current intersection. False if there is a beeper at the current intersection.

Test: facing-north
True if Karel is facing north. False otherwise.

Test: not-facing-north
True if Karel is not facing north. False if he is facing north.

Test: facing-south
True if Karel is facing south. False otherwise.

Test: not-facing-south
True if Karel is not facing south. False if he is facing south.

Test: facing-east
True if Karel is facing east. False otherwise.

Test: not-facing-east
True if Karel is not facing east. False if he is facing east.

Test: facing-west
True if Karel is facing west. False otherwise.

Test: not-facing-west
True if Karel is not facing west. False if he is facing west.

Test: any-beepers-in-beeper-bag
True if there is at least one beeper in Karel's beeper bag. False if the beeper bag is empty.

Test: no-beepers-in-beeper-bag
True if Karel's beeper bag is empty. False if there is at least one beeper in the beeper bag.

Control Structures

BEGINNING-OF-PROGRAM
  <definitions>
    BEGINNING-OF-EXECUTION
      <stmt>;
      <stmt>;
      <stmt>;
      ...
    END-OF-EXECUTION
END-OF-PROGRAM
  BEGIN
    <stmt>;
    <stmt>;
    <stmt>;
    ...
  END;

  IF <test>
    THEN <stmt>
    [ ELSE <stmt> ]

  ITERATE <positive-integer> TIMES
    <stmt>

  WHILE <test> DO
    <stmt>

Defining Procedures

  DEFINE-NEW-INSTRUCTION <name> AS
    <stmt>

Karel Programmer's Guide

The Karel Simulator Architecture

Building applications

Extending Karel

API Reference

Error API

You can override the default error handling routines by defining replacements and including them in the link command prior to libkarel. Each error handler is defined separately, so it is possible to redefine one, and use the default behavior of the other two.

Error Handler: void ktr_err_nomem (size_t size)
Library function that is invoked when the Karel engine cannot allocate memory.

Error Handler: void ktr_err_fatal (char * format, ...)
Library function that is invoked when the Karel engine has a fatal error. The default implementation prints the arguments ala fprintf(stderr, format, ...) and exits the program.

Error Handler: void ktr_err_parse (char * format, ...)
Library function that is invoked when the Karel parser has an error. The default implementation prints the arguments ala fprintf(stderr, format, ...) and exits the program.

Memory API

You can override the default memory management routines by defining replacements and including them in the link command prior to libkarel. If you do decide to override the memory management routines, they must all be redefined. It is not possible to redefine some memory management routines and not others.

The default implementation uses the standard C library calls calloc, malloc, free, and realloc.

Memory Management: void * ktr_calloc (size_t nmemb, size_t size)
Allocates an array of nmemb elements, each of size bytes. Returns a pointer to the allocated memory, or NULL if the allocation failed.

Memory Management: void * ktr_malloc (size_t size)
Allocates size bytes. Returns a pointer to the allocated memory, or NULL if the allocaiton failed.

Memory Management: void ktr_free (void *ptr);
Frees memory previously allocated by ktr_calloc, ktr_malloc, or ktr_realloc.

Memory Management: void * ktr_realloc (void *ptr, size_t size);
Attempts to resize the memory block pointed to by ptr. If ptr is NULL, the call is equivalent to malloc(size). If size is equal to zero, the call is equivalent to free(ptr). Unless ptr is NULL, it must have been allocated by a previous call to ktr_calloc or ktr_malloc. Returns a pointer to the new block of memory. If the allocation fails, NULL is returned and the original block of memory is untouched.

Robot API

Robot: ktr_robot_t
The robot data type.

Robot: ktr_robot_t * ktr_robot_create (ktr_world_t *world, int street, int avenue, ktr_direction_t dir, int n_beepers)
Creates a new robot that lives in world. The starting position is given as (street, avenue), facing direction dir. The robot starts with n_beepers in his beeper bag.

Robot: void ktr_robot_set_move_callback (ktr_robot_t *r, ktr_robot_move_callback_t cb)
Establishes the function to invoke whenever karel moves.

Robot: void ktr_robot_set_turn_callback (ktr_robot_t *r, ktr_robot_turn_callback_t cb)
Establishes the function to invoke whenever karel turns.

Robot: void ktr_robot_get_pos (ktr_robot_t *r, int *street, int *avenue);
Sets street and avenue to the coordinates of the given robot's (r) current intersection.

Robot: char * ktr_robot_dir_to_string (ktr_direction_t dir);
Converts the given direction (dir) to a string for printing the robot's current direction.

World API

World: ktr_world_t
The world data type.

World: ktr_world_t * ktr_world_create (int n_streets, int n_avenues)
Creates a new world of size n_streets by n_avenues.

World: ktr_world_t * ktr_world_read (FILE *in_file)
Reads a world description from the open file in_file. The file should be opened with a call to fopen(). Returns a newly allocated world matching the description found in the file, or NULL if there is an error reading the file.

World: void ktr_world_add_ew_wall (ktr_world_t *w, int north_of_street, int at_avenue, int length_to_east)
Adds an east-west wall immediately north of north_of_street, starting at at_avenue, and extending length_to_east blocks to the east.

World: void ktr_world_add_ns_wall (ktr_world_t *w, int at_street, int east_of_avenue, int length_to_north)
Adds a north-south wall immediately east of east_of_avenue, starting at at_street, and extending length_to_north blocks to the north.

World: int ktr_world_check_ew_wall (ktr_world_t *w, int north_of_street, int at_avenue)
Returns 1 if there is an east-west wall immediately north of street north_of_street at avenue at_avenue. Returns 0 otherwise.

World: int ktr_world_check_ns_wall (ktr_world_t *w, int at_street, int east_of_avenue)
Returns 1 if there is an north-south wall immediately east of avenue east_of_avenue at street at_street. Returns 0 otherwise.

World: int ktr_world_check_beeper (ktr_world_t *w, int street, int avenue)
Returns 1 if there is a beeper at intersection (street,avenue). Returns 0 otherwise.

World: int ktr_world_pick_beeper (ktr_world_t *w, int street, int avenue)
Decrements the number of beepers at intersection (street,avenue). Returns 0 if a beeper was successfully picked. Returns -1 if there were no beepers to pick up.

World: int ktr_world_put_beeper (ktr_world_t *w, int street, int avenue)
Increments the number of beepers at intersection (street,avenue). Returns 0.

Engine API

Engine: ktr_engine_t * ktr_load_program (FILE *in_file);
Loads the karel program in the open file in_file. The file should be opened with a call to fopen(). Returns the resulting engine. Errors are presently undetected. This obviously needs work!

Index

Jump to: a - f - k - l - m - n - p - r - t - { - }

a

  • any-beepers-in-beeper-bag
  • f

  • facing-east
  • facing-north
  • facing-south
  • facing-west
  • front-is-blocked
  • front-is-clear
  • k

  • ktr_calloc
  • ktr_err_fatal
  • ktr_err_nomem
  • ktr_err_parse
  • ktr_free
  • ktr_load_program
  • ktr_malloc
  • ktr_realloc
  • ktr_robot_create
  • ktr_robot_dir_to_string
  • ktr_robot_get_pos
  • ktr_robot_set_move_callback
  • ktr_robot_set_turn_callback
  • ktr_world_add_ew_wall
  • ktr_world_add_ns_wall
  • ktr_world_check_beeper
  • ktr_world_check_ew_wall
  • ktr_world_check_ns_wall
  • ktr_world_create
  • ktr_world_pick_beeper
  • ktr_world_put_beeper
  • ktr_world_read
  • l

  • left-is-blocked
  • left-is-clear
  • m

  • Miksovsky, Jan
  • move
  • n

  • next-to-a-beeper
  • no-beepers-in-beeper-bag
  • not-facing-east
  • not-facing-north
  • not-facing-south
  • not-facing-west
  • not-next-to-a-beeper
  • p

  • Pattis, Richard
  • pickbeeper
  • putbeeper
  • r

  • right-is-blocked
  • right-is-clear
  • t

  • turnleft
  • turnoff
  • {

  • { comment character
  • }

  • } comment character

  • Footnotes

    (1)

    Pattis, Richard E., Jim Roberts, and Mark Stehlik. Karel the Robot: A Gentle Introduction to The Art of Programming. New York: Wiley, 1995. ISBN: 0471597252


    This document was generated on 27 July 2000 using texi2html 1.56k.