CS 231 Project 3

Agents on a Landscape

This week we'll continue to experiment with 2D agent-based simulations. You will also use the linked-list class from lab to maintain a list of agents in a Landscape.

Here are the links to the API's for the most recent versions of Java:


You can copy over your Cell.java and Landscape.java files from project 2. We'll be modifying, and in some cases simplifying them.

In general, a Landscape will no longer be a discrete thing with cells. Instead, each Cell will keep track of its own location, and that location will be a continous -- that is, a floating point -- value. The Landscape will use the LinkedList class to keep track of agents on the Landscape.


  1. Simplify the Cell class so that it keeps track of only its location, and does so with two double fields: x and y. The Cell class should have only the following functions.
    • public Cell(double x0, double y0) - constructor that takes an x and y location.
    • public double getX() - returns the x location as a double.
    • public int getCol() - returns the x location as the nearest integer.
    • public double getY() - returns the y location as a double
    • public int getRow() - returns the y location as the nearest integer.
    • public String toString() - returns a string containing a single period.
    • public void updateState(ArrayList<Cell> neighbors) - this function will update the Cell's state and status, but leave it blank for now.
    • Create a test main function. Feel free to use the following.
    • public static void main(String argv[]) {
      	Cell cell1 = new Cell(4.4, 3.6 );
      	Cell cell2 = new Cell(2.1, 4.5 );
      	System.out.printf( "cell1: %.2f %.2f %d %d\n", 
      	cell1.getX(), cell1.getY(), 
      	cell1.getCol(), cell1.getRow() );
      	System.out.printf( "cell2: %.2f %.2f %d %d\n", 
      	cell2.getX(), cell2.getY(), 
      	cell2.getCol(), cell2.getRow() );
  2. Update your Landscape class so that in contains fields for the width and height (in pixels) and a LinkedList of Cell objects. The Landscape should implement the following methods.
    • public Landscape(int rows, int cols) - initialize the three fields.
    • public void reset() - clear the Landscape of agents.
    • public void getRows() - return the height of the Landscape.
    • public void getCols() - return the width of the Landscape.
    • public void addAgent( Cell a ) - add the agent a to the Landscape.
    • public ArrayList<Cell> getAgents() - returns an ArrayList of the Cells on the Landscape.
    • public String toString() - returns a string representing the Landscape. You may want to, first, create an ArrayList (or a regular 2D array) of String objects that are all initially a single space, with a carriage return at the end of each row. Then go through your agents and ask each one for its row and column index. After making sure they are within the boundaries of the Landscape, update the appropriate String in the grid or array using the Cell's toString function. At the end, concatenate all of the Strings in the grid or ArrayList and return it.
    • public ArrayList<Cell> getNeighbors(double x0, double y0, double radius) - return a list of the Cells within radius radius of the location x0, y0.
    • public void advance() - get a shuffled list of Cells and then go through each one and call its updateState method.
    • Use the following test function to test if you can create a Landscape.
      public static void main(String argv[]) {
      	int rows = 30;
      	int cols = 70;
      	int N = 300;
      	Landscape scape = new Landscape(rows, cols);
      	Random gen = new Random();
      	System.out.println( "Landscape:\n" + scape );
      	for(int i=0;i<N;i++) {
      		scape.addAgent( new Cell( 
      		                gen.nextFloat() * cols, 
      		                gen.nextFloat() * rows );
      	System.out.println( "\nLandscape:\n" + scape );
  3. Now go back to the Cell class and write the updateState method. It should implement the following rules.
    If the cell has more than 3 neighbors, then 
        the cell should move +/- 5 with a 1% chance.
        the cell should move +/- 5

    Note that the Cell's motion should be a continuous value between +5 and -5 in both X and Y. You can use the Random class's nextFloat or nextDouble method to get a random floating point value between 0 and 1.0.

  4. Then add the following to the end of the Landscape main method.

    for(int i=0;i<10;i++) {
    	System.out.printf("Iteration %d:\n", i);
    	System.out.println( scape );

    Run Landscape and see if you get clumping behavior.

  5. Create a new class Cell2 that extends Cell.

    public class Cell2 extends Cell

    The new class should have an integer field category and implement or override the following methods.

    • public Cell2(double x0, double y0, int cat) - call the parent constructor and set the category.
    • public int getCategory() - return the category value.
    • public String toString() - return a single character string indicating the category.
    • public void updateState(ArrayList<Cell> neighbors) - implement the following rule.
      Identify how many neighbors have the same category as this cell and how many have a different category than this cell.
      If there are more of the same category as this cell
         move +/- 5 with a 1% chance
         move +/- 5 
  6. Change your Landscape main test function to create Cell2 agents instead of Cell agents in the main test function. Better yet, design a system where which type of Cell is created is determined by a command line argument. Give the Cell2 agents the category 0 or 1, then run the simulation again.
  7. Make a new Simulation class that can do the following.
    1. Run either type of simulation
    2. Control how many iterations the simulation will run
    3. Control how often the simulation gets printed to the command line
    4. Control the width and height of the Landscape
    5. Control the number of agents on the Landscape
  8. Create one other type of agent that extends the Cell class and has a different update rule. Show simulations for it. Explain what individual behavior you are trying to model with your new agent type. [Example: the original Cell class is modeling a preference for clumping, while the second Cell class is modeling the impact on group behavior of subtle individual preferences.]


  1. See if you can mix and match different agent types and write about what happens.
  2. Try out additional Cell subclasses with different update rules.
  3. Experiment with the effects of modifying some of the update rules. These should be compare and contrast. Try to avoid comparing simulations where more than one thing has been changed.
  4. Use command line arguments to control simulation parameters.
  5. See if you can figure out how to make pictures of your Simulation. You may try to look at the pgm or ppm format.


Make your writeup for the project a wiki page in your personal space. If you have questions about making a wiki page, stop by my office or ask in lab.

Your writeup should have a simple format.

Once you have written up your assignment, give the page the label:


You can give any page a label when you're editing it using the label field at the bottom of the page.

Do not put code on your writeup page or anywhere it can be publicly accessed. To hand in code, put it in your folder on the Courses fileserver. Create a directory for each project inside the private folder inside your username folder.