Using packages
[Agent practical 5 of 9]


We'll now expand what we've done to utilise a neighbourhood.

To do this, we'll utilise a nice little class distributed with Java, java.awt.Polygon (API docs). This class represents a closed polygon defined in a coordinate space, and has a useful little method called contains() which takes in an x,y coordinate and tells you if it is inside the polygon or not. To use it, all we have to do is construct a java.awt.Polygon object around our proposed point and then query each agent for their x and y coordinates to see if they fall in the Polygon. We'll then have identified if they fall within a neighbourhood around our prospective new location.

The constructor for java.awt.Polygon takes in an array of x-coordinates, and array of y-coordinates, and a number of coordinates to use. The polygon is automatically closed between the first and last point. You need to think through in detail what kind of shape you want to use for your neighbourhood, depending on its size and the datasets it is being compared against. Here, we're going to use a hexagonal neighbourhood, just because its better than a square. With a bit more effort, you could construct something more like a circle, but this isn't necessary here.

To be honest, thinking through the maths is a bit of a faff, so we're going to give you the code. You can find it in this copy of the Animal class:

Check this is compatible with your code, and then either download it to your directory for this practical, or cut and paste the new code into your Animal class.

Note a few things about this. Firstly, there are three new instance variables, set to private to this class only:

private int neighbourhoodRadius = 5;
private int opp = (int)Math.abs((Math.sin(Math.toRadians(30.0)) * (double)neighbourhoodRadius));
private int adj = (int)Math.abs((Math.cos(Math.toRadians(30.0)) * (double)neighbourhoodRadius));

These utilise the static trigonometry methods built into the Math class to calculate some key lengths for building of hexagon. Note also that these take radians, rather than degrees.

Secondly, note that the class imports java.awt.* so we can get hold of the Polygon class.

Finally, note that getNeighbourhood is polymorphic. There's a version that generates the neighbourhood around the current agent location, and another that takes in specific coordinates. Note that the former simply pass the current x and y to the latter. This isn't an uncommon way of doing polymorphism -- there's no point in doubling-up code unnecessarily. We won't use the version for the current neighbourhood at the moment, but it is there if we need it later.


So, how do we use our new method, which is inherited into Nibbler? Well, here's our take on the locationSuitable method, but feel free to adapt to match your own:

private boolean locationSuitable(int x, int y) {

   for (Agent agent: agents) {
      if ((getNeighbourhood(x,y).contains(agent.getX(), agent.getY()) == true) && (agent != this)) {
         return false;
      }
   }

   return true;

}


Get this, or its equivalent, working, and we're done for this practical.

Go on to the last page for a summary of where we're at.