Levels

The development has reached this point:

The Entity class depending on the Grid class

Now we want to add a Level class. A level object reads in data from a level file, and acts as a driver for all the non-graphics aspects of the game.

Which way round should the dependencies go? Should Entity depend on Level, or vice versa? It seems natural to make the Level class into a controller, telling the entities when to act:

The Level class as a framework class depending
on the Entity and Grid classes

On the other hand, entity classes are presumably custom classes defined for a specific game, whereas the Level class could usefully be part of the framework. A framework class should not depend on a custom class, so maybe we should rethink.

The approach taken here is to define a Cell class as a base class for custom entity classes, to have it be a framework class, and to allow the Level class to control cells:

The Entity and Level classes
depend on Cell which depends on Grid

Besides looking after the grid, one of the things a level object needs to do is to keep track of global variables such as a score. But to keep the Level class general, it should be the entities which change the global variables, according to their game-specific details. A generic class State can be separated off from the Level class to handle state variables.

Similarly, a level object needs to keep track of a queue of entities, to control what order they act in. And again, to keep Level general, it should be entities which queue themselves up. A generic Queue class can be separated out. That leads us to a picture like this:

he Entity and Level classes,
depend on Cell, which depends on Grid, State and Queue

Two aspects of the wanderer game are a little unusual. First, instead of an entity such as an arrow moving autonomously, it moves by triggering the space in front of it. This allows entities to act as stationary booby traps, only starting to move when the player or another entity moves nearby. The other unusual aspect is that the original program used recursion to deal with the way in which one event triggers another.

For example, if you move near two objects, say an arrow and a boulder, and set them going, the entire flight of the arrow and everything it triggers, happens before the boulder moves. In other words, the program is doing a depth-first search for things to do. It is more normal to keep a queue of things to do, and to use it to give a more concurrent, breadth-first physics.

The reconstruction uses a double ended queue, and allows entities to be added at either end. By adding entities at the start instead of the end, the original game is reproduced as accurately as possible.

There is one more thing a level needs to be able to do. That is to create entities of different types, according to the data from a level file. Entities may also need to spawn other entities. The creation of new entities is something that can only be carried out when full knowledge of all the custom entity classes is known. So a custom factory object of some kind will need to be passed to the level, and an interface or base class will need to be provided for it, accessible both by the level object and entities. Let's give the name Hatchery for such a factory interface and add it to the diagram:

The Entity and Level classes,
depend on Cell, which depends on Grid, State, Queue and Hatchery

This is a reasonable design for the model. The way custom classes are intended to be designed is something like this:

A Program class, which depends on various entity
classes, which depends on the Entity base class

There may be many specific entity classes, all inheriting from the Entity class. Each entity interacts with other entities, but only knows that they have class Entity, nothing more specific, to avoid dependencies between the classes. A Program class knows about all the various entity classes, and can provide a factory for them.