A RePast Tutorial by John T. Murphy, University of Arizona & Arizona State University (contact)

Agents on the Move

So far our simulation doesn't include the agents moving from point to point. It will take a bit of coding to get them to do this. One reason why it will be so complicated is that we have decreed already that only one agent can be in a given cell at a time. This means we will have to accommodate in our code for the possibility of a collision between agents- this is fine, because in the end we will use this as an important part of the simulation.

We need several elements to make our agents move:

  1. Agents must have a 'direction' variable. Actually we will use two variables, that will either be -1,0, or 1, and will represent the agent's proposed change in position in the x and y directions. We will not permit both of those to be zero, so that all agents will move. We will also initialize these when the agent is created.
  2. A method in the space object that actually moves the agent. The agent will tell it where it currently is and where it wants to go; the space object will check to see if there's already an agent in the destination spot and if so will return 'false', indicating that the move did not occur. If the move did occur, the space object will re-set the agent's position variables and update its own space object, and the agent will move.
  3. We react to a collision by having the agent reset its x and y velocity variables, so that it changes direction.

In the code below, we name the x and y velocity variables vX and vY. We create a method that resets these randomly, which we then call in the constructor.

CarryDropModel

// CarryDropModel
package demo;

import java.awt.Color;
import java.util.ArrayList;

import uchicago.src.sim.engine.BasicAction;
import uchicago.src.sim.engine.Schedule;
import uchicago.src.sim.engine.SimInit;
import uchicago.src.sim.engine.SimModelImpl;
import uchicago.src.sim.gui.DisplaySurface;
import uchicago.src.sim.gui.ColorMap;
import uchicago.src.sim.gui.Object2DDisplay;
import uchicago.src.sim.gui.Value2DDisplay;
import uchicago.src.sim.util.SimUtilities;

public class CarryDropModel extends SimModelImpl {
  // Default Values
  private static final int NUMAGENTS = 100;
  private static final int WORLDXSIZE = 40;
  private static final int WORLDYSIZE = 40;
  private static final int TOTALMONEY = 1000;
  private static final int AGENT_MIN_LIFESPAN = 30;
  private static final int AGENT_MAX_LIFESPAN = 50;

  private int numAgents = NUMAGENTS;
  private int worldXSize = WORLDXSIZE;
  private int worldYSize = WORLDYSIZE;
  private int money = TOTALMONEY;
  private int agentMinLifespan = AGENT_MIN_LIFESPAN;
  private int agentMaxLifespan = AGENT_MAX_LIFESPAN;

  private Schedule schedule;

  private CarryDropSpace cdSpace;

  private ArrayList agentList;

  private DisplaySurface displaySurf;

  public String getName(){
    return "Carry And Drop";
  }

  public void setup(){
    System.out.println("Running setup");
    cdSpace = null;
    agentList = new ArrayList();
    schedule = new Schedule(1);

    if (displaySurf != null){
      displaySurf.dispose();
    }
    displaySurf = null;

    displaySurf = new DisplaySurface(this, "Carry Drop Model Window 1");

    registerDisplaySurface("Carry Drop Model Window 1", displaySurf);
  }

  public void begin(){
    buildModel();
    buildSchedule();
    buildDisplay();

    displaySurf.display();
  }

  public void buildModel(){
    System.out.println("Running BuildModel");
    cdSpace = new CarryDropSpace(worldXSize, worldYSize);
    cdSpace.spreadMoney(money);

    for(int i = 0; i < numAgents; i++){
      addNewAgent();
    }
    for(int i = 0; i < agentList.size(); i++){
      CarryDropAgent cda = (CarryDropAgent)agentList.get(i);
      cda.report();
    }
  }

  public void buildSchedule(){
    System.out.println("Running BuildSchedule");

    class CarryDropStep extends BasicAction {
      public void execute() {
        SimUtilities.shuffle(agentList);
        for(int i =0; i < agentList.size(); i++){
          CarryDropAgent cda = (CarryDropAgent)agentList.get(i);
          cda.step();
        }

        int deadAgents = reapDeadAgents();
        for(int i =0; i < deadAgents; i++){
          addNewAgent();
        }

        displaySurf.updateDisplay();
      }
    }

    schedule.scheduleActionBeginning(0, new CarryDropStep());

    class CarryDropCountLiving extends BasicAction {
      public void execute(){
        countLivingAgents();
      }
    }

    schedule.scheduleActionAtInterval(10, new CarryDropCountLiving());

  }

  public void buildDisplay(){
    System.out.println("Running BuildDisplay");

    ColorMap map = new ColorMap();

    for(int i = 1; i<16; i++){
      map.mapColor(i, new Color((int)(i * 8 + 127), 0, 0));
    }
    map.mapColor(0, Color.white);

    Value2DDisplay displayMoney =
        new Value2DDisplay(cdSpace.getCurrentMoneySpace(), map);

    Object2DDisplay displayAgents = new Object2DDisplay(cdSpace.getCurrentAgentSpace());
    displayAgents.setObjectList(agentList);

    displaySurf.addDisplayable(displayMoney, "Money");
    displaySurf.addDisplayable(displayAgents, "Agents");

  }

  private void addNewAgent(){
    CarryDropAgent a = new CarryDropAgent(agentMinLifespan, agentMaxLifespan);
    agentList.add(a);
    cdSpace.addAgent(a);
  }

  private int reapDeadAgents(){
    int count = 0;
    for(int i = (agentList.size() - 1); i >= 0 ; i--){
      CarryDropAgent cda = (CarryDropAgent)agentList.get(i);
      if(cda.getStepsToLive() < 1){
        cdSpace.removeAgentAt(cda.getX(), cda.getY());
        cdSpace.spreadMoney(cda.getMoney());
        agentList.remove(i);
        count++;
      }
    }
    return count;
  }

  private int countLivingAgents(){
    int livingAgents = 0;
    for(int i = 0; i < agentList.size(); i++){
      CarryDropAgent cda = (CarryDropAgent)agentList.get(i);
      if(cda.getStepsToLive() > 0) livingAgents++;
    }
    System.out.println("Number of living agents is: " + livingAgents);

    return livingAgents;
  }

  public Schedule getSchedule(){
    return schedule;
  }

  public String[] getInitParam(){
    String[] initParams = { "NumAgents", "WorldXSize", "WorldYSize", "Money", "AgentMinLifespan", "AgentMaxLifespan"};
    return initParams;
  }

  public int getNumAgents(){
    return numAgents;
  }

  public void setNumAgents(int na){
    numAgents = na;
  }

  public int getWorldXSize(){
    return worldXSize;
  }

  public void setWorldXSize(int wxs){
    worldXSize = wxs;
  }

  public int getWorldYSize(){
    return worldYSize;
  }

  public void setWorldYSize(int wys){
    worldYSize = wys;
  }

  public int getMoney() {
    return money;
  }

  public void setMoney(int i) {
    money = i;
  }

  public int getAgentMaxLifespan() {
    return agentMaxLifespan;
  }

  public int getAgentMinLifespan() {
    return agentMinLifespan;
  }

  public void setAgentMaxLifespan(int i) {
    agentMaxLifespan = i;
  }

  public void setAgentMinLifespan(int i) {
    agentMinLifespan = i;
  }

  public static void main(String[] args) {
    SimInit init = new SimInit();
    CarryDropModel model = new CarryDropModel();
    init.loadModel(model, "", false);
  }

}

CarryDropAgent

// CarryDropAgent
package demo;

import java.awt.Color;

import uchicago.src.sim.gui.Drawable;
import uchicago.src.sim.gui.SimGraphics;
import uchicago.src.sim.space.Object2DGrid;

public class CarryDropAgent implements Drawable{
  private int x;
  private int y;
  private int vX;
  private int vY;
  private int money;
  private int stepsToLive;
  private static int IDNumber = 0;
  private int ID;
  private CarryDropSpace cdSpace;

  public CarryDropAgent(int minLifespan, int maxLifespan){
    x = -1;
    y = -1;
    money = 0;
    setVxVy();
    stepsToLive =
        (int)((Math.random() * (maxLifespan - minLifespan)) + minLifespan);
    IDNumber++;
    ID = IDNumber;
  }

  private void setVxVy(){
    vX = 0;
    vY = 0;
    while((vX == 0) && ( vY == 0)){
      vX = (int)Math.floor(Math.random() * 3) - 1;
      vY = (int)Math.floor(Math.random() * 3) - 1;
    }
  }

  public void setXY(int newX, int newY){
    x = newX;
    y = newY;
  }

  public void setCarryDropSpace(CarryDropSpace cds){
    cdSpace = cds;
  }

  public String getID(){
    return "A-" + ID;
  }

  public int getMoney(){
    return money;
  }

  public int getStepsToLive(){
    return stepsToLive;
  }

  public void report(){
    System.out.println(getID() +
                       " at " +
                       x + ", " + y +
                       " has " +
                       getMoney() + " dollars" +
                       " and " +
                       getStepsToLive() + " steps to live.");
  }

  public int getX(){
    return x;
  }

  public int getY(){
    return y;
  }

  public void draw(SimGraphics G){
    if(stepsToLive > 10)
      G.drawFastRoundRect(Color.green);
    else
      G.drawFastRoundRect(Color.blue);
  }

  public void step(){
    int newX = x + vX;
    int newY = y + vY;

    Object2DGrid grid = cdSpace.getCurrentAgentSpace();
    newX = (newX + grid.getSizeX()) % grid.getSizeX();
    newY = (newY + grid.getSizeY()) % grid.getSizeY();

    if(tryMove(newX, newY)){
      money += cdSpace.takeMoneyAt(x, y);
    }
    else{
      setVxVy();
    }
    stepsToLive--;
  }

  private boolean tryMove(int newX, int newY){
    return cdSpace.moveAgentAt(x, y, newX, newY);
  }
}

CarryDropSpace

// CarryDropSpace
package demo;

import uchicago.src.sim.space.Object2DGrid;


public class CarryDropSpace {
private Object2DGrid moneySpace;
private Object2DGrid agentSpace;

  public CarryDropSpace(int xSize, int ySize){
    moneySpace = new Object2DGrid(xSize, ySize);
    agentSpace = new Object2DGrid(xSize, ySize);

    for(int i = 0; i < xSize; i++){
      for(int j = 0; j < ySize; j++){
        moneySpace.putObjectAt(i,j,new Integer(0));
      }
    }
  }

  public void spreadMoney(int money){
    // Randomly place money in moneySpace
    for(int i = 0; i < money; i++){

      // Choose coordinates
      int x = (int)(Math.random()*(moneySpace.getSizeX()));
      int y = (int)(Math.random()*(moneySpace.getSizeY()));

      // Get the value of the object at those coordinates
      int currentValue = getMoneyAt(x, y);
      // Replace the Integer object with another one with the new value
      moneySpace.putObjectAt(x,y,new Integer(currentValue + 1));
    }
  }

  public int getMoneyAt(int x, int y){
    int i;
    if(moneySpace.getObjectAt(x,y)!= null){
      i = ((Integer)moneySpace.getObjectAt(x,y)).intValue();
    }
    else{
      i = 0;
    }
    return i;
  }

  public Object2DGrid getCurrentMoneySpace(){
    return moneySpace;
  }

  public Object2DGrid getCurrentAgentSpace(){
    return agentSpace;
  }

  public boolean isCellOccupied(int x, int y){
    boolean retVal = false;
    if(agentSpace.getObjectAt(x, y)!=null) retVal = true;
    return retVal;
  }

  public boolean addAgent(CarryDropAgent agent){
    boolean retVal = false;
    int count = 0;
    int countLimit = 10 * agentSpace.getSizeX() * agentSpace.getSizeY();

    while((retVal==false) && (count < countLimit)){
      int x = (int)(Math.random()*(agentSpace.getSizeX()));
      int y = (int)(Math.random()*(agentSpace.getSizeY()));
      if(isCellOccupied(x,y) == false){
        agentSpace.putObjectAt(x,y,agent);
        agent.setXY(x,y);
        agent.setCarryDropSpace(this);
        retVal = true;
      }
      count++;
    }

    return retVal;
  }

  public void removeAgentAt(int x, int y){
    agentSpace.putObjectAt(x, y, null);
  }

  public int takeMoneyAt(int x, int y){
    int money = getMoneyAt(x, y);
    moneySpace.putObjectAt(x, y, new Integer(0));
    return money;
  }

  public boolean moveAgentAt(int x, int y, int newX, int newY){
    boolean retVal = false;
    if(!isCellOccupied(newX, newY)){
      CarryDropAgent cda = (CarryDropAgent)agentSpace.getObjectAt(x, y);
      removeAgentAt(x,y);
      cda.setXY(newX, newY);
      agentSpace.putObjectAt(newX, newY, cda);
      retVal = true;
    }
    return retVal;
  }

}

This code is quite satisfying- we now have agents moving across the landscape. We need only add one more element to complete the model itself.

Previous: Agents Get Money

Next: Money changing hands

Go to Table of Contents


A RePast Tutorial by John T. Murphy, University of Arizona & Arizona State University (contact)