Search
Google
 

Karel J. Robot





A preprocessor that translates a simplified Java-syntax into 100% pure Java code. The simplifications are penned by Joseph Bergin et al. in their manuscript Karel J. Robot. This work was used in the basic course "Basics of Computer Science I" winter 2001 and winter 2002 at Darmstadt University of Technology.

Contents

Introduction

Karel J. Robot is an interesting approach for teaching object oriented programming using Java. The manuscript is by Joseph Bergin, Mark Stehlik, Jim Roberts and Richard Pattis. For details on Karel J. please refer to the manuscript.

The manuscript uses some simplifications which I will describe later. Joseph Bergin also offers a runtime environment for programming robots as described in Karel J. Though you have to use pure Java then and can't take advantage of the simplifications. My work is mainly a preprocessor which translates the simplifications into pure Java.

After using the first version of my preprocessor and Mr. Bergin's runtime environment for the "Introduction to Computer Science" lecture at the "Darmstadt University of Technology", we found some shortcommings which I tried to fix in a second version of the preprocessor. I also wrote a new runtime environment whose premier advantage is its small interface. We only used Karel J. as an introduction into Java, so we essentially used the first chapters. My new r. e. only offers the most basic functionality which is actually all we used. I also wrote a new r. e. to solve some problems we had with the graphic interface. A third cause for rewriting it is that we assigned exercises using Karel J. The new runtime environment will offer the correctors some help.

News

  • A new version of the Simulator is available for download (afternoon Sep. 16. 2002) - KarelSim.jar - KarelRT.jar - KarelRTsrc.zip - sample.task
  • Added the clone method to ur_Robot
  • Now all constructors of robots have the signature (street, avenue, direction, beepers)
  • Now you can use non-absolute paths for the source files in the commandline
  • Fixed the frontIsClear() method to return false if the robot faces the edge of the world (i.e. west of the first avenue or south of the first street)
  • I forgot to mention that I compiled the classes using the jdk 1.4. This means you also have to use the virtual mashine of the jdk 1.4 to run the simulator. I will work on this but it will take a while until a version for earlier jdk releases is available.
  • Now you can change the World implementation to be used via the commandline. There is a new commandline option available: -worldimpl <fully qualified classname>.
  • I added a manifest to the KarelSim.jar file. Now you can start the simulator by java -jar KarelSim.jar your.task, but only the current directory and KarelSim.jar will be in the classpath then. If you want to add other directories or archives, you still have to use java -classpath KarelSim.jar;inst;%CLASSPATH% Simulator your.task
  • Updated the sample.task file to use the right constructor (see above), too.
  • Standard directory for instrumented and compiled files is now the current directory. If you want to use another one, be sure to have it in your classpath.
  • There still might be a problem in the file finding mechanism. If the simulator looks for a class and finds a file which is named like the file, it stops looking any further. If this file doesn't really contain the searched class (which is possible if you don't use public classes) it might be a problem.
  • I reprogrammed the file finding mechsanism. Now the "Karel"-Constructor is not added if a the super class has a constructor with four ints as parameters but if it is a direct or indirect subtype of ur_Robot. Also if you didn't explicitely imported the "keareltherobot" package, the simulator didn't work. That should be fixed now.
  • There was an error in the commandline I gave as example to start the Simulator. The right one is: java -classpath KarelSim.jar;inst;%CLASSPATH% Simulator your.task.
  • I added the Robot class which is part of the original core by Mr. Bergin.

Features

The new preprocessor now parses the denoted file and all files containing depending classes. It does that in similar ways as javac. You can only have one public class per file (in that case the file also must have the same name as the class), but you can have as many non-public classes per file as you like and they can have any name you like. That might, though, cause problems finding some types (it might be that my way of finding types is not always correct). The simplest way of success is that you only have one class per file and name the file the same as the class. The preprocessor finds files with the extensions ".java" and ".task".

How it works

The Proprocessor makes several changes:

  • Aadd "import kareltherobot.*;" to all files.
  • Add kareltherobot.Directions to the implemented interfaces of all classes.
  • If the superclass of a class has a constructor like (int, int, int, int) this constructor is added, calling the super constructor. This is because in the manuscript subtyping is explained without constructors. And as every robot needs this kind of constructor it is simply added if it isn't there. (at the moment, this is buggy. consider: A extends ur_Robot, B extends A. Then B wouldn't get the constructor ... I will fix this soon).
  • Every method without visibility modifiers is set to be public. Otherwise, if the method is inherited and was originally public, javac would say, that it is redefined with weaker access rights.
  • The new loop-statement of the Karel J. language is replaced by a for-statement. Variables of the form "_i" + some counter are used so be careful not to use identifiers like this yourself.
  • The task-declaration of the Karel J. language is used to create a class. It is called KarelTask and the clock of the task declaration becomes the body of its main method. This class is public and it is added to the file containing the task. So don't put a task into a file containing a public class (I might change this, though). If a class KarelTask already exists within the classpath it might cause some confusion. If you encounter problems like changes you made don't appear, please look for KarelTask.java or KarelTask.class files and delete them.

How to use it

To use the preprocessor, you have to download this jar-archive. It contains the Preprocessor and the runtime environment (which can also be downloaded separately). To start the simulator type the following: java -classpath KarelSim.jar;inst;%CLASSPATH% Simulator your.task. This will cause the preprocessor to do its modifications to all necessary files, write the changed files into directory "dist", compile them and run the task in an empty world. You can use the following commandline parameters:
-delay <milliseconds>The delay between robot movements in milliseconds
-instdir <path>The directory to temporarily output instrumented files
-world <file>The name of the world file to be loaded at startup
-streets <number>The number of streets to be visible
-avenues <number>The number of avenues to be visible
-d <path>The directory where to place generated class files
-sourcepath <path>Specify where to find input source files
-worldimpl <classname>The World implementation to be used
For you to get started, I prepared a sample Karel J. .task file. The directory in which the instrumented files (i.e. the generated java files) are put, must exist and must be included in the classpath (the default "inst"). If the -d argument is used, the specified directory must also be within the classpath. I will not make the source code of the simulator publicly available, as I am using a framework, I am developing myself, for the preprocessor. This framework is not yet ready to be published. You can download the source of the runtime environment though.

The runtime is very similar to the one by Mr. Bergin. Actually it should be the same except for the missing parts and a few extensions that are merely optional to use. I also put the classes in the same package which is for downwards-compatibility reasons. I intend that the programs we used last year can simply run using the new r. e. and that the original r. e. can be used with my new simulator. For documetation on the api I will add a JavaDoc generated docu soon. You can also refer to the the Karel J. pages which also include a JavaDoc documention.

The main difference between both implementations is the World. In my implementation World has most of the static methods the original one has, but it just delegates them to an instance of a World-object which also can be accessed using World.getWorld(). It is a singleton and therefor only one instance per virtual machine exists. Because World is really an object for me, other implementations of World can be used. Actually two already exist. World is only offers the functionality for keeping book about walls, beepers and robots. The GUIWorld offers a graphical interface for presenting the world. The protected method "registerWorld()" is used by subclasses of World to set themselves as the World-Object. This should be done within the static initializer to load a World implmentation by using 'Class.forName( "WorldImplementation" );' just like for JDBC drivers. I will add some documentation on World implementation later. For now please refer to the source code of the r. e. The simulator automatically selects "GUIWorld".

Error messages

Where possible, my simulator mimics or uses javac or java behaviour. There are three types of errors: syntax errors, semantic errors and runtime errors. Syntax and semantic errors appear during compiletime. The error messages have the following format: filename:line,column:message. Where filename is given as url (using the simulator) and denotes the file within which the error occurred, line and column name the position within this file. As my simulator parses the code itself, the syntax errors appear during parsetime of the simulator. That means, the simulator doesn't generate original javac error messages for them. the error messages then name the token the parser found and a list of tokens that were expected to find. After transforming the code, it is printed into the specified directory and compiled using javac. The error messages generated by javac are translated by the parser. I.e. the original source file and the original position of the error are printed out. If an error occurred within code that was generated by the simulator error in generated code is printed as errormessage followed by the filename and position where the error occurred. This doesn't denote the original file but the generated one. Javac also prints the line within which the error occurred in the error message. This code sample is taken from the generated file so it might look different from the respective line in the original code. The runtime errors (or exceptions) are not especially handled by the simulator and thus the sourcecode positions given in runtime error messages always name the position within the generated file.

As mentioned before, we don't want that the students use arrays. Also, as Karel J. introduces the loop statement, the for statement should not be used in Karel J. programs. Also the '&&' and '||' operators don't exist in the Karel J. language. So my simulator warns if it encounters any of those language constructs.

Customization

The graphic of my new runtime, also is completely based on .gif images. So it can be completely customized. The images are within the jar archive. This is simply a zip archive within which you can replace the .gif files. The graphic routine seperates the world into rectangles which represent the crosroads the robots move on. The images are always stretched to fit exactly into such rectangles. You can use a transparent color. I suggest, you use images of the same resolution and. The robot and beepers should not fill the image and be centered. You need to put your customized images back into the jar archive for the simulator to find them. If you think your images are nice, please send them to me, I'll publish them on this page.

Unfortunately using .gif images introduced a new probley, I was not yet able to solve. The images are loaded asynchronously and thus it may happen that an image is not displayed the first time it should be.

Contact

I am still in the testing phase, but also I have some ideas of funtionality I'd like to add. So if you tried this program and encountered problems or have ideas yourself what is missing, please let me know. Also if you miss something in this docu, please tell me. If you are interested in the simulator please check this page regularly as it will (hopefully) change a lot within the next time.