Here's some diagrams to get the ball rolling ...
Preliminary Diagrams showing the interface components
GE = Game Engine
GED = Game Engine Driver (custom made for each GE interface)
UBE = United Bot Engine
P = Plugin (supplies a bot component or related service)
Code:
|GE-1| <-> |GED-1| <-> |UBE| <-> [P-1, P-2 ... P-m]
|GE-2| <-> |GED-2| <-> |
:
|GE-n| <-> |GED n| <-> |
Code:
|P-1| <-> |P-API <-> UBE <-> GED-API| <-> [GED] <-> [GE]
|P-2| <-> |
:
|P-m| <-> |
Here are my rambling thoughts for discussion ...
The UB Engine should only provide a standard set of basic services which allow a bot to be constructed out of various "plugins".
Plugins provide the high level functions, such as combat behaviour and navigation.
Each plugin will use the services provided through the standard P-API (plugin API).
Plugins may communicate with each other, but only through the P-API.
The UBE may communicate with GED's but only through the standard GED-API (Game Engine Driver API).
For maximum flexibility we can allow plugins to directly call GED functions. This way certain game specific functions can be made available that otherwise would not be availble through the UB Engine API. Of course, using non standard function calls leads to driver dependant code which is not 100% portable to other game engines.
Plugins and GED's can replace some of the UBE functions with alternate versions providing "virtual function" capabilities.
Plugins and GED's can also "hook" or "chain" onto some of the UBE functions.
Some of the UBE services will provide status information about each bot, as well as the game environment.
Other UBE services will have to be defined.
The UBE may issue event messages to plugins as a means to trigger events, such as "round start", "team selection", etc.
A sticky problem to solve will be in how to share data between the UBE and the plugins. We don't want a duplication of effort across plugins, for example where each plugin keeps its own duplicate list of bots and associated data.
If data structures are to be shared across plugins, then how is this done? There's more than one way to do this, but some methods are more suitable than others.
How do plugins communicate with each other? Message passing is usually a good method of communications. Messages can be used as event triggers which simplifies the need for constant polling (only the message queue needs to be polled in a generic way).
Function "hooks" can work well as event triggers.
Changes to messages can be made without modifying API's.
more discussion ...