-
Notifications
You must be signed in to change notification settings - Fork 1
Karel the Robot
Karel lives in a two-dimensional grid where (1, 1) is at the bottom left corner. Karel has a position and an orientation in the grid (north, east, south or west).
Each square of the grid may contain one or more beepers, or no beepers at all. Karel has a bag of beepers which may be empty or may contain many or even infinite beepers.
Karel can move one cell and turn left. Karel can put down a beeper or pick up a beeper. In addition, Karel is able to check state of the area around themselves.
Cells may be separated by walls. Karel cannot move through walls or off the edge of the world.
Karel has four actions:
void Move();
void TurnLeft();
void PutBeeper();
void PickBeeper();
Karel has several booleans for getting robot state:
bool FrontIsClear();
bool FrontIsBlocked();
bool LeftIsClear();
bool LeftIsBlocked();
bool RightIsClear();
bool RightIsBlocked();
bool HasBeepersInBag();
bool NoBeepersInBag();
bool BeepersPresent();
bool NoBeepersPresent();
bool FacingNorth();
bool NotFacingNorth();
bool FacingEast();
bool NotFacingEast();
bool FacingSouth();
bool NotFacingSouth();
bool FacingWest();
bool NotFacingWest();
This is functional programming: simply #include "cpputils/karel/karel.h"
and call the Karel functions in the global namespace.
#include "cpputils/karel/karel.h"
void TurnRight() {
TurnLeft();
TurnLeft();
TurnLeft();
}
void KarelProgram() {
while(FrontIsClear()) {
Move();
}
TurnRight();
Move();
TurnLeft();
Move();
PickBeeper();
TurnLeft();
TurnLeft();
while(FrontIsClear()) {
Move();
}
TurnRight();
Move();
TurnRight();
}
int main() {
LoadWorld("worlds/CollectNewspaperKarel.w");
KarelProgram();
Finish();
return 0;
}
Karel is an animated graphical program, so some a11y features are available to make it useful to more students: See https://github.com/ILXL/cpputils/wiki/Karel-Accessibility
Compile (from the directory containing cpputils) with:
clang++ -std=c++17 test.cc cpputils/karel/karel.cc cpputils/karel/src/robot.cc cpputils/graphics/image.cc -o main -lm -lX11 -lpthread
A few more flags are needed in Mac.
karel/src/robot.h
provides a Karel the Robot implementation in C++. Functions in karel/karel.h
are in the global namespace. Each function access the global instance of the Robot
class and calls methods on it.
The first time the Robot
global instance is accessed it will be created. This may happen in the LoadWorld()
function which loads from a file, but if that is not called first than a default empty 10x10 world will be loaded. After the world is loaded it cannot be re-loaded.
You can read about all the available global functions in the documentation in karel/karel.h
.
World files are the format used by Stanford 106A. Specifications:
-
Dimension
must be the first line, and is width x height.Dimension
is required. -
Wall
specifies a single with the cell and the side of the cell that has that wall, i.e.(3, 2) west
means there is a wall on the west side of cell x = 3, y = 2. You can have more than one wall in a cell, but each must be on its own row. -
Beeper
specifies one or more beepers with the cell and the beeper count, i.e.(4, 2) 3
means three beepers at x = 4, y = 2. -
Speed
is a multiplier, speeds near 0 are extremely slow and speeds can be much greater than 1. -
Karel
specifies the starting position and orientation of Karel.
Dimension: (7, 5)
Wall: (3, 2) west
Wall: (3, 2) south
Wall: (3, 3) west
Wall: (3, 4) west
Wall: (3, 5) south
Wall: (4, 2) south
Wall: (4, 5) south
Wall: (5, 2) south
Wall: (5, 5) south
Wall: (6, 2) west
Wall: (6, 4) west
Beeper: (6, 3) 1
Karel: (3, 4) east
Speed: 1.00
Instructors should call LoadWorld
before student code and Finish
after.
/**
* Loads a Karel world from a file.
* If this is not the first Karel function called a default world will be
* created instead and this will have no effect.
*/
void LoadWorld(std::string filename);
/**
* Completes a Karel program. Continues to show the image but will not
* do any more actions.
*/
void Finish();
Student code should be in another header (or cc) file which can be included in unit tests so that tests don't run against main.cc.
For example, main.cc:
#include "assignment.h"
int main() {
// LoadWorld should always be the first Karel function called or the Robot
// instance will initialize with a default world.
LoadWorld("worlds/karel.w");
// Optional: Configure a11y here.
// EnableCSVOutput();
// Execute student code. Recommend that KarelProgram is in a file
// assignment.h/assignment.cc which can be #included by unit tests for separate testing.
// Unit tests for Karel do not work on main().
KarelProgram();
Finish();
}
and assignment.h:
#include "cpputils/karel/karel.h"
void KarelProgram() {
// Student code
TurnLeft();
Move();
PickBeeper();
}
Example: see karel/src/test/karel_unittest.cc
Before each unit test you must re-set the global instance of the Robot
class as follows:
Robot& r = Robot::InitializeInstance("worlds/2x1.w", /* enable animations */ false,
/* force initialize */ true);
Disabling animations is helpful for headless testing and fast testing. You can use Robot::SaveWorldBmp
to generate images from unit tests if needed.
Unittest should not run over code that does world-loading setup or Finish(), i.e. should not run over code probably in main()
(per above example).
You can inspect the Robot
's position, orientation, beeper state, error state, and the state of each cell using the Robot
instance acquired from InitializeInstance
. For example,
// Re-initialize state at the beginning of each unit test.
Robot& r =
Robot::InitializeInstance("worlds/2x1.w", /* enable animations */ false,
/* force initialize */ true);
// World width and height.
ASSERT_EQ(2, r.GetWorldWidth());
ASSERT_EQ(1, r.GetWorldHeight());
// Number of beepers in a cell. Note that indexes are based on Karel's
// world where (1, 1) is the bottom left.
EXPECT_EQ(1, r.GetCell(2, 1).GetNumBeepers());
// Karel's position, orientation and beepers.
ASSERT_EQ(1, r.GetXPosition());
ASSERT_EQ(1, r.GetYPosition());
ASSERT_EQ(Orientation::kEast, r.GetOrientation());
ASSERT_EQ(1, r.GetNumBeepersInBag());
// Error state
EXPECT_EQ(RobotError::kNoError, r.GetError());
You can find error states in karel/src/error.h
, the Cell
class in karel/src/cell.h
, and the orientation enum in karel/src/orientation.h
.
All functions available for test are listed in karel/src/robot.h
under the heading "Methods for tests".