Part 2 of the GridWorld case study uses some features we haven’t seen
yet, so you will get a preview now and more details later.
As a re-
minder, you can find the documentation for the GridWorld classes at http:
//www.greenteapress.com/thinkapjava/javadoc/gridworld/.
When
you
install
GridWorld,
you
should
have
a
folder
named
projects/boxBug, which contains BoxBug.java, BoxBugRunner.java and
BoxBug.gif.
Copy these files into your working folder and import them into
your development environment.
There are instructions here that
might help:
http://www.collegeboard.com/prod_downloads/student/
testing/ap/compsci_a/ap07_gridworld_installation_guide.pdf.
Here is the code from BoxBugRunner.java:
import info.gridworld.actor.ActorWorld;
import info.gridworld.grid.Location;
import java.awt.Color;
public class BoxBugRunner {
public static void main(String[] args) {
ActorWorld world = new ActorWorld();
BoxBug alice = new BoxBug(6);
124
Chapter 10. GridWorld: Part 2
alice.setColor(Color.ORANGE);
BoxBug bob = new BoxBug(3);
world.add(new Location(7, 8), alice);
world.add(new Location(5, 5), bob);
world.show();
}
}
Everything here should be familiar, with the possible exception of Location,
which is part of GridWorld, and similar to java.awt.Point.
BoxBug.java contains the class definition for BoxBug.
public class BoxBug extends Bug {
private int steps;
private int sideLength;
public BoxBug(int length) {
steps = 0;
sideLength = length;
}
}
The first line says that this class extends Bug, which means that a BoxBug is
a kind of Bug.
The next two lines are instance variables. Every Bug has variables named
sideLength, which determines the size of the box it draws, and steps, which
keeps track of how many steps the Bug has taken.
The next line defines a constructor, which is a special method that initial-
izes the instance variables. When you create a Bug by invoking new, Java
invokes this constructor.
The parameter of the constructor is the side length.
Bug behavior is controlled by the act method. Here is the act method for
BoxBug:
public void act() {
if (steps < sideLength && canMove()) {
move();
10.1. Termites
125
steps++;
}
else {
turn();
turn();
steps = 0;
}
}
If the BoxBug can move, and has not taken the required number of steps, it
moves and increments steps.
If it hits a wall or completes one side of the box, it turns 90 degrees to the
right and resets steps to 0.
Run the program and see what it does. Did you get the behavior you ex-
pected?
Exercise 10.1. Now you know enough to do the exercises in the Student
Manual, Part 2. Go do them, and then come back for more fun.
10.1
Termites
I wrote a class called Termite that extends Bug and adds the ability to
interact with flowers.
To run it, download these files and import them into your development en-
vironment:
http://thinkapjava.com/code/Termite.java
http://thinkapjava.com/code/Termite.gif
http://thinkapjava.com/code/TermiteRunner.java
Because Termite extends Bug, all Bug methods also work on Termites. But
Termites have additional methods that Bugs don’t have.
/**
* Returns true if the termite has a flower.
*/
public boolean hasFlower();
126
Chapter 10. GridWorld: Part 2
/**
* Returns true if the termite is facing a flower.
*/
public boolean seeFlower();
/**
* Creates a flower unless the termite already has one.
*/
public void createFlower();
/**
* Drops the flower in the termites current location.
*
* Note: only one Actor can occupy a grid cell, so the effect of
* dropping a flower is delayed until the termite moves.
*/
public void dropFlower();
/**
* Throws the flower into the location the termite is facing.
*
*/
public void throwFlower();
/**
* Picks up the flower the termite is facing, if there is one,
* and if the termite doesn✬t already have a flower.
*/
public void pickUpFlower();
For some methods Bug provides one definition and Termite provides another.
In that case, the Termite method overrides the Bug method.
For example, Bug.canMove returns true if there is a flower in the next loca-
tion, so Bugs can trample Flowers. Termite.canMove returns false if there
is any object in the next location, so Termite behavior is different.
As another example, Termites have a version of turn that takes an integer
number of degrees as a parameter. Finally, Termites have randomTurn, which
10.1. Termites
127
turns left or right 45 degrees at random.
Here is the code from TermiteRunner.java:
public class TermiteRunner
{
public static void main(String[] args)
{
ActorWorld world = new ActorWorld();
makeFlowers(world, 20);
Termite alice = new Termite();
world.add(alice);
Termite bob = new Termite();
bob.setColor(Color.blue);
world.add(bob);
world.show();
}
public static void makeFlowers(ActorWorld world, int n) {
for (int i=0; i<n; i++) {
world.add(new EternalFlower());
}
}
}
Everything here should be familiar. TermiteRunner creates an ActorWorld
with 20 EternalFlowers and two Termites.
An EternalFlower is a Flower that overrides act so the flowers don’t get
darker.
class EternalFlower extends Flower {
public void act() {}
}
If you run TermiteRunner.java you should see two termites moving at ran-
dom among the flowers.
128
Chapter 10. GridWorld: Part 2
MyTermite.java demonstrates the methods that interact with flowers. Here
is the class definition:
public class MyTermite extends Termite {
public void act() {
if (getGrid() == null)
return;
if (seeFlower()) {
pickUpFlower();
}
if (hasFlower()) {
dropFlower();
}
if (canMove()) {
move();
}
randomTurn();
}
}
MyTermite extends Termite and overrides act. If MyTermite sees a flower,
it picks it up. If it has a flower, it drops it.
Exercise 10.2. The purpose of this exercise is to explore the behavior of
Termites that interact with flowers.
Modify TermiteRunner.java to create MyTermites instead of Termites.
Then run it again. MyTermites should move around at random, moving the
flowers around. The total number of flowers should stay the same (including
the ones MyTermites are holding).
In Termites, Turtles and Traffic Jams, Mitchell Resnick describes a simple
model of termite behavior:
❼ If you see a flower, pick it up. Unless you already have a flower; in
that case, drop the one you have.
❼ Move forward, if you can.
10.2. Langton’s Termite
129
❼ Turn left or right at random.
Modify MyTermite.java to implement this model. What effect do you think
this change will have on the behavior of MyTermites?
Try it out. Again, the total number of flowers does not change, but over time
the flowers accumulate in a small number of piles, often just one.
This behavior is an an emergent property, which you can read about at
http: // en. wikipedia. org/ wiki/ Emergence . MyTermites follow sim-
ple rules using only small-scale information, but the result is large-scale or-
ganization.
Experiment with different rules and see what effect they have on the system.
Small changes can have unpredicable results!
10.2
Langton’s Termite
Langton’s Ant is a simple model of ant behavior that displays surprisingly
complex behavior. The Ant lives on a grid like GridWorld where each cell is
either white or black. The Ant moves according to these rules:
❼ If the Ant is on a white cell, it turns to the right, makes the cell black,
and moves forward.
❼ If the Ant is on a black cell, it turns to the left, makes the cell white,
and moves forward.
Because the rules are simple, you might expect the Ant to do something
simple like make a square or repeat a simple pattern. But starting on a grid
with all white cells, the Ant makes more than 10,000 steps in a seemingly
random pattern before it settles into a repeating loop of 104 steps.
You can read more about Langton’s Ant at http://en.wikipedia.org/
wiki/Langton_ant.
It is not easy to implement Langton’s Ant in GridWorld because we can’t
set the color of the cells. As an alternative, we can use Flowers to mark
130
Chapter 10. GridWorld: Part 2
cells, but we can’t have an Ant and a Flower in the same cell, so we can’t
implement the Ant rules exactly.
Instead we’ll create what I’ll call a LangtonTermite, which uses seeFlower
to check whether there is a flower in the next cell, pickUpFlower to pick it
up, and throwFlower to put a flower in the next cell. You might want to
read the code for these methods to be sure you know what they do.
Exercise 10.3.
1. Make a copy of Termite.java called LangtonTermite
and a copy of TermiteRunner.java called LangtonRunner.java. Mod-
ify them so the class definitions have the same name as the files, and
so LangtonRunner creates a LangtonTermite.
2. If you create a file named LangtonTermite.gif, GridWorld uses
it to represent your Termite.
You can download excellent pictures
of
insects
from
http: // www. cksinfo. com/ animals/ insects/
realisticdrawings/ index. html . To convert them to GIF format,
you can use an application like ImageMagick.
3. Modify act to implement rules similar to Langton’s Ant. Experiment
with different rules, and with both 45 and 90 degree turns. Find rules
that run the maximum number of steps before the Termite starts to
loop.
4. To give your Termite enough room, you can make the grid bigger or
switch to an UnboundedGrid.
5. Create more than one LangtonTermite and see how they interact.