The magazine of the Melbourne PC User Group

Karel and Company — More Robots
Trevor Gosbell
 
 

Trevor Gosbell presents Part 3 of his very popular and easy to follow “Programming with Karel”

Welcome to part three of Programming with Karel. In this episode we will start controlling more than one robot and have a look at how robot names work. But first I'll make a comment.

Just Making A Comment Here

Now that we're getting familiar with how the robot world works, let's start to do things in a more orderly fashion. Listing 1 is a solution to the double-decker squares problem from the previous article (see Figure 1).

There is a new part of the syntax introduced here - the double slash '//' that marks a "comment". In Java anything from a double slash '//' to the end of the line is simply ignored by the compiler. Remember that computer program source code is mainly for people to read, so the double slash allows you to make free-form remarks in the code to help make a program easier to understand. A helpful feature of BlueJ is that comments appear in a different colour, so it's easy to tell what's comment and what's code. Handy, isn't it?

But Listing 1 is a bit disappointing after our last instalment where we gave so much attention to removing unnecessary repetition. Now that we need to move the robot into position for the second square we end up with more repetition! Really, this is most annoying.

It's time to get some teamwork going.
 



Figure 1.

Listing 1.

import kareltherobot.*;

public class Example03 implements RobotTask
{
 public void task()
 {
  World.reset();
  World.setTrace(false);
  World.setVisible(true);

  // make a new robot
  SquareMaker karel = new
   SquareMaker(1, 2, East, 8);

  // make the first square
  karel.move();
  karel.makeSquare();

  // move into position
  // for the next square
  karel.turnLeft();
  karel.turnLeft();
  karel.turnLeft();
  karel.move();
  karel.turnLeft();
  karel.turnLeft();
  karel.turnLeft();

  // start the second square
  karel.makeSquare();
  karel.move();
 }
}

Fun with dick and jane

Listing 2 shows a team of two robots making the two squares. The first,
jane, starts at the corner of 1st and 3rd, makes a square then moves aside one space. The other, dick, starts at 5th and 3rd but otherwise does the same job as jane. That's all there is to making multiple robots. Knowing this, you could now make as many robots as you like simply by thinking up a unique name and calling new SquareMaker(); for each one.

Listing 2.

import kareltherobot.*;

public class Example03 implements RobotTask
{
 public void task()
 {
  World.reset();
  World.setTrace(false);
  World.setVisible(true);

  // make a new SquareMaker
  SquareMaker jane = new
   SquareMaker(1, 3, East, 4);

  // jane makes the first square
  jane.makeSquare();
  jane.move();

  // make another new SquareMaker
  SquareMaker dick = new
   SquareMaker(5, 3, East, 4);

  // dick makes the second square
  dick.makeSquare();
  dick.move();
 }
}


And here we learn the first new thing about robot names - you can call your robots practically anything. In fact, the name of a robot doesn't need to be a real name or even a real word. There are a few simple rules about robot names, but for the moment we'll just use ordinary human names.

Reduce, reuse, recycle

There is something else you need to know about robot names. Unlike your name which is yours to keep, robot names are more like stick-on labels that can be transferred between robots as required. Listing 3 will help to illustrate.

Listing 3.

import kareltherobot.*;

public class Example03 implements RobotTask
{
 public void task()
 {
  World.reset();
  World.setTrace(false);
  World.setVisible(true);

  // make a name called jane
  SquareMaker jane = null;

  // make a SquareMaker robot
  // and call it jane
  jane = new SquareMaker(1, 3, East, 4);

  // jane makes the first square
  jane.makeSquare();
  jane.move();

  // make another SquareMaker
  // and call it jane also
  jane = new SquareMaker(5, 3, East, 4);

  // the new robot, also called
  // jane, makes the second square
  jane.makeSquare();
  jane.move();
 }
}


Notice some subtle differences. Firstly, we make
jane as a SquareMaker-style name, but we don't give it a SquareMaker robot straight away:

// make a name called jane
SquareMaker jane = null;


Use the word null to show that jane isn't a name for anything in particular (yet).

Next we use the name
jane to refer to something - a brand new SquareMaker robot:

// make a SquareMaker robot
// and call it jane
jane = new SquareMaker(1, 3, East, 4);


See the difference? In previous examples we did both steps on one line, that is make a name and give that name to a new robot. Something like this:

SquareMaker jane = new SquareMaker(1, 3, East, 4);

Then it's all the same as before until we get to the second robot - and dick doesn't make an appearance:

// make another SquareMaker
// and call it jane also
jane = new SquareMaker(5, 3, East, 4);


It looks like jane can do it all alone. But note carefully: although the name is the same, there are still two separate robots here.

Beer and Robots

Have you ever been to a crowded party or BBQ where there's heaps of people you don't know? Or worse, heaps of people you do know but can't remember their names? In these circumstances, I use my old fallback: "Mate". As in, "Mate, can you pass me a beer?" It's not a bad strategy - I don't need to know the real name of the man by the fridge because "Mate" does the job quite nicely. It doesn't even need to be the same person. If I come back later and there's someone different by the fridge, "Mate, can you pass me a beer?" will still work!

A very similar thing is happening with our robots, except the question is
jane.makeSquare();. Just like getting a beer at a BBQ, it doesn't matter that the second time we ask the question jane refers to a different robot.

Beer drinking may be the perfect pastime, but in this case it doesn't make a perfect metaphor: When I go back to the fridge a third time, the man who gave me my first beer has returned. I can repeat "Mate, can you pass me a beer?" and (provided that he's not getting sick of me), he'll pass me another beer. But with the robots, once I've used the name jane to refer to the second robot, I can't use it to refer to the first robot anymore. I can't go back to the first robot and say jane.makeSquare(); because jane now refers to the second robot. In fact, once I've moved the name jane onto the second robot I can no longer refer to the first robot at all. Figure 2 shows how the name jane refers to different things as the program progresses.



Figure 2.

Cup-and-Ball

In fact, that last statement is not entirely true - it is possible to refer to the first robot again, provided that it still has a name. Let's have a look at how robot names can be swapped around. The following explanation will make more sense if you compile Listing 4 and watch it carefully while it runs.

Listing 4.

import kareltherobot.*;

public class Example03 implements RobotTask
{
 public void task()
 {
  World.reset();
  World.setTrace(false);
  World.setVisible(true);

  // make two new robot names
  SquareMaker jane = null;
  SquareMaker dick = null;

  // make robot 1
  // and call it jane
  jane = new SquareMaker(1, 3, East, 4);

  // make dick refer to robot 1
  dick = jane;

  // dick makes the first square
  dick.makeSquare();

  // make robot 2
  // and call it jane
  jane = new SquareMaker(5, 3, East, 4);

  // use jane to make
  // the second square
  jane.makeSquare();
  jane.move();
  jane.move();

  // make jane refer
  // to robot 1 again
  jane = dick;

  // use jane to tell
  // robot 1 what to do
  jane.move();
  jane.move();
 }
}

This time we start out with two unallocated robot names, jane and dick. As in the previous example, we make a new robot and use the jane name to refer to it.

Then we get to

dick = jane;

By now you've probably got used to the idea that the equals sign is used to give a name (on the left) to a robot (on the right). Although there are robot names on both sides, this line works in exactly the same way - it gives the name on the left (dick) to the robot on the right. And the robot on the right is the same robot to which the label jane is given - the one that is facing east at the corner of 1st and 3rd, holding four beepers. This line makes both labels -
jane and dick - point to the same robot.

We prove that both names refer to the one robot in the next line, where we tell dick to make the square - and it does just that.

 

Then we make a new robot and give it the name jane. The situation now is that jane refers to the second robot while dick still refers to the first robot. So the next three instructions to jane are carried out on the second robot:

jane.makeSquare();
jane.move();
jane.move();


This is exactly what we want to happen.

Following the discussion above about

dick = jane;

we can confidently predict the result of

jane = dick;

This time the robot name on the left is jane and that name is being given to the robot on the right - the robot refered to by dick, that is the first robot. So jane and dick are both labels for the same robot again. Knowing this, we are sure that the last two instructions

jane.move();
jane.move();


act on the first robot, not the second.

If you've been able to follow this cup-and-ball routine, you'll notice that the second robot no longer has a name allocated to it, so it can't be recovered and referred to again (see Figure 3). So the key point here is: if you need to send instructions to a robot then it must have at least one name left that refers to it.

A Task for You

In Listing 4, when we gave the command
jane = dick; we transferred the name jane from robot 2 back to robot 1, leaving robot 2 without a name and beyond reach. Can you think of a way of swapping the robots that jane and dick refer to without leaving any robots "orphaned"? In other words, start with jane referring to robot 1 and dick referring to robot 2 but end with jane referring to robot 2 and dick referring to robot 1.



Figure 3.

Wrap up

In this episode we have covered the following points:

  • how to make and control several robots at once.
  • robots can have more than one name.
  • a robot name can only refer to one robot at a time.
  • it is possible to make a robot name refer to different robots at different times.
  • it is not possible to give instructions to a robot that doesn't have at least one name.
Next Time

In the next episode we will branch out beyond boring squares and start to work with other shapes.

Reprinted from the December 2003 issue of PC Update, the magazine of Melbourne PC User Group, Australia

[ About Melbourne PC User Group ]