Entities

The development has reached this point, leaving out some details:

The Entity class depends on Level which
depends on Grid

The next question is whether or not an entity should know its own coordinates in the grid. The problem is that it involves duplicate data. The (x,y) coordinates stored in the entity object, and the actual position of the object in the grid, need to be kept consistent with each other. It is easy to imagine a lot of code like this:

grid.move(this, Right);
x++;

The first line tells the grid to move the entity to a new cell, and the second updates the entity's coordinates to match. The danger of inconsistency is very real, and increases enormously as the number of code fragments like the one above increases. Any problems can be very tough to debug.

One approach is for an entity not to know its own coordinates. Only the grid knows, and can therefore carefully keep them consistent. Several variations on this theme are possible, but two problems inevitably arise. The first is that the resulting system can't be described as simple or natural. The second is that, although most things that an entity wants to do can be done with directions, e.g. "move right" or "find the entity to the right" and so on, occasionally actual coordinates come into play, e.g a long-distance teleport, or a monster which chases the player.

Entities have already been split across two classes, Cell as a generic base class and Entity for custom details. So a good approach is for a Cell to know here it is, but not an Entity. The Cell class might look like this:

class Cell {
    private Grid<Cell> grid;
    private int x, y;
    int x() { return x; }
    int y() { return y; }
...
}

An object of the Cell class knows its own coordinates, but the class consists of a relatively small amount of stable code, so that consistency can be kept under control. The coordinates are private, and so the Entity class only has read access to them. That encapsulates the coordinate consistency problem inside the Cell class.

The Cell class shown above has a weakness. The grid field has class Grid<Cell>. So, when an entity finds a neighbouring entity in the grid, it only knows that the neighbour has type Cell, not Entity (unless it cheats by using casting, for example). While this isn't a disaster, it is worth making the framework class Cell a bit more sophisticated, to ease the implementation of game-specific custom classes, like this:

public class Cell<E extends Cell<E>>
    private Grid<E> grid;
    private int x, y;
    int x() { return x; }
    int y() { return y; }
...
}

The Cell class is given a parameter E, which will later be filled in by the Entity class. Then entities will be able to access other entities using variables of class Entity. The E parameter (which will end up referring to the Entity class) must be a class which extends Cell. In fact, it must extend Cell<E>, which leads to the strangely cyclic but correct class declaration class Cell<E extends Cell<E>>.

Implementing the Cell class is a bit tricky. For example, suppose there is a method to move this entity to the coordinates of another entity:

void move(E to) {
    ...
    x = to.x;
    y = to.y;
}

This fails because to.x and to.y are not accessible. The to variable has class E whereas the x and y fields are private to the Cell class. However, any object of class E automatically has class Cell<E> because of the class declaration, so the problem can be fixed without casts or compiler warnings:

void move(E e) {
    ...
    Cell<E> c = e;
    x = c.x;
    y = c.y;
}

There is another problem. Suppose there is a method:

void wake() {
    grid.wake(x, y, this);
}

This fails because the variable this has type Cell<E> instead of type E. All objects of type Cell<E> are actually going to be of type E, but the compiler doesn't know that. A cast (E)this is needed, but it causes a warning. However, a single tiny method can be defined with the warning suppressed:

@SuppressWarnings("unchecked")
private E thisE() { return (E)this; }