Using packages
[Agent practical 5 of 9]
We'll now build an example of agent communication into our model. This is the final major element of our model behaviour. After this, we'll work on the user interface and getting data into our model.
As an example of agent communication, our Nibblers are going to check that an area they are moving into doesn't have any agents already near it. There are two components to this: firstly, we have to get all the agents knowing about all the other agents so they can query each other. Secondly, we need to implement the actual behaviour. We'll start with the former.
We now have our Nibblers in an ArrayList in Model.java. What we need is for each agent, as it is created, to get a copy of the ArrayList of all Nibblers. As we've seen with the Environment object, the simplest way to do this is by passing the ArrayList into the Nibbler constructor when the Nibblers are made:
private ArrayList <Agent> agents = new ArrayList <Agent>();
private Environment world = new Environment();
public Model() {
for (int i = 0; i < numberOfAgents; i++) {
agents.add(new Nibbler(world, agent)); // Pass in agent list as well as world.
}
This might seem a little crazy, as when the first few Nibblers are created, the later Nibblers won't yet be in the list, but remember that
the label agents
isn't pointing at the individual contents of the ArrayList, but the ArrayList itself, which has been
created at this stage. Later, in Nibbler, we'll be able to get hold of the ArrayList, and by that time it will be filled up.
Make the adjustment to your Model.java code, as above, and then adjust your Nibbler class so it picks up the ArrayList and
stores it in the superclass as an instance variable in the same way as the Environment object. You'll need to
import java.util.*;
in any class that uses the ArrayList.
Keep the
name agents
as the name of the object within your Animal.java. Remember that in both Nibbler.java and Animal.java you're dealing with the same
constructor that grabs the Environment, not making a second constructor just to deal with the ArrayList. Calling the superclass constructor with two variables is
just as simple as doing: super(worldIn,agentsIn)
.
In addition, note that the labels in the constructors should use angle brackets as well to keep the constraint on the object:
public Nibbler (Environment worldIn, ArrayList<Agent> agentsIn) {
There's no specific reason for storing the ArrayList in "Animal" rather than "Nibbler" -- it's just easier to copy what you did for the Environment object. That said, a list of other Agents is probably so common that having it in the more generic superclass probably makes sense.
Once you've got that working, each agent now has a list of all the other agents (and, weirdly, itself). It can use this to communicate with other agents by running through the list calling their methods (and filtering out itself).
We'll now go on to implement a communication behaviour.