Testing concepts and sketches

Mocks and testing

The immediate priority is to reconsider the structure of the AI components, and to ensure that it is testable. This means that we need to define clear seams between the components.

The following sketch is simply divided into two cases, with extreme abstraction. On the LHS is the 'normal' case where the game is being played, and the RHS is the case where we are testing.

All that's happening here is that we've identified two seams at the top level, which isolates the AI from the game and the neo4j database.

For the purposes of testing, we must assume that the neo4j database and the game core work as expected, and focus tests on the AI module. To achieve this, we will create a 'mock' of the game which we set up and tear down as required for testing. This mock will return some value or action that we define. We will also build an equivalent for the embedded database.

When we create a test, the calls to these mocks will use the API and the mock will, given some data, always return the correct result or action. This way, we are testing that the AI module has an expected set of data from the game and we can examine whether it acts on it correctly.

Configuration and testing

Although unit tests will allow us to ensure the functional aspects of the AI work correctly, there is a huge amount of human interperetation required when we evaluate the actual intelligence of the AI. The tuning mode concept is to allow us to mode directly tune the AI and observe its behaviour.

Using spring configuration, we are able to define our java objects with an xml file. The constructors of the java objects are called with whatever parameters we define, and they are kept in a special heap area which is the spring context. This gives us the ability, combined with effective object-oriented design allows us to change a great deal of behaviour without ever recompiling the code.

An example of this would be two iterators, one which returns the next number from some distribution, and an iterator which returns a random number from that distribution. Provided they are descended from the same distributionIterator class, we can easily use one or the other by changing the spring file.

Although this is more useful that I have probably illustrated for the creation of java objects, we need a more responsive approach to tuning the AI. We want to test the results of certain config changes on a turn-by-turn basis to increase development speed. To achieve this, a test-mode tuning mechanism is suggested. A very basic sketch is below.

We can see that the normal flow would be to launch the AI module (from the game core) in some way, and at this point we use the basic overall spring configuration. The AI module is created and is now 'plugged into' the game.

In tuning mode, the AI will additionally read from the tuning file (for example) every turn, refreshing the parameters we change. When tuning mode is off, these parameters will be read during the spring configuration stage and kept constant for the game (this allows modders to configure the AI but not tune it every turn).

Now we have the ability to increase the development speed of certain parameters and algorithms by tuning them quickly.

Returning from stasis

Due to real-world constraints, I've been off-project for some time. It's been nice to go over the project notes and wiki pages, and for there to be enough information there to get me up to speed pretty quickly. The break has been good to abstract me away from implementation and consider robustness in the design.

A key part of the picture at the moment is to communication between the game and the AI. Several releases are planned for the AI, and being able to swap them in and out from the core game will be essential. Initial thoughts for the communication object would be:

  • A set of source nodes to move from
  • Each has a set of neighbours
  • A set of numbers relating to the transfer of forces from source to each neighbour
  • A list of additional actions, i.e. optional stuff
  • Time taken for move
  • In the case of game reporting to AI, the actual board state at beginning of AI turn (this is beacuse of the random combat element and (deliberate) imperfect predictive ability of AI).

There's a bit of implementation - level stuff that should be done sooner than later, and although there will be no immediate gain in functionality, will improve maintainablility and reduce technical debt.

  • Make the AI spring configurable
  • Introduce logging for both trace (all info) and stats (aggregate info, reduce log trawling for known areas of interest)

After those steps, I'll start looking at getting ARCHIE-3 to simply move some ships independent of context or board state. Once I have a series of valid moves, I can consider how to model the game in a predictive context.

I'm thinking that, given a particular course of action, we can create a new map per turn and have a number of maps in the database that have resulted from some predicted set of events. How exactly this will work is the subject of the modelling exercise.

Some placeholder tile models

I've been busy modelling up some placeholder 3d art the last couple of days so I can build the new 3d version of the gameboard. It was some 35 unique tile placeholders in all. Now I have think I have everything to start building the next iteration of the game! Here's a gallery of some of the tiles all imported into Unity.

Finding and maintaining a game's focus

It sure has been a long time between posts eh! Part of that is due to Hyperspace Empires being in a bit of design purgatory of late. In a nutshell, I decided to scrap about a month's worth of work on the metagame that I had begun surrounding the core game with. The reasons I abandoned the metagame were numerous:

  • The metagame drastically increased the scope of the game and thus the time taken to finish it became intractably long.
  • The design became too complicated and unwieldy and the design started to get sloppy.
  • The metagame took focus away from the elevator pitch of the game: "the coffeebreak 4x". The meaning of the game and thus the message was being obscured.
  • I still haven't made the core of the game fun and playable yet. In essence I was concentrating on what I thought I needed to have in the game to make it more 'marketable' rather then concentrating on the core gameplay experience. Ironically by concentrating on this metagame I was diluting the marketing message of the game.

So I've cut back the project to the core essentials, the core gameplay ideas and will see where that takes me. It feels very liberating and I feel like a big weight has been lifted from my shoulders. I think this is a sign I had started to loose my way but am now back on the path. The other sign is more design ideas are flowing.