Bolo

From WinBolo

(Difference between revisions)
Jump to: navigation, search
Line 1: Line 1:
The bolo directory contains the backend code for simulating a game world.
The bolo directory contains the backend code for simulating a game world.
 +
 +
[[#screen.c]] is the main entry point for client applications to talk to the backend.
 +
 +
The backend is not threadsafe and access to any functions should be syncronized.
== Design ==
== Design ==
Line 15: Line 19:
The ADT concept as well as ''New()'' and ''Dispose()'' macro's for ADT memory management come from Geoff Whales book - Data Structures and Abstraction Using C.
The ADT concept as well as ''New()'' and ''Dispose()'' macro's for ADT memory management come from Geoff Whales book - Data Structures and Abstraction Using C.
 +
 +
 +
== Client vs Server ==
 +
 +
The backend has code that provides processing for a single player game and game server as well as a dumber client. This is handled by the function ''threadsGetContext();'' which returns TRUE if it is a server performing the action or FALSE if it is a client. Note that a single player game will return FALSE. Single player games need to be able to use some of the server logic to work to work correctly. So the backend will typically contain.
 +
<pre>
 +
if (threadsGetContext() == TRUE || netGetType() == netSingle) {
 +
</pre>
 +
 +
The reason these two tests can not be simplified into threadsGetContext() function is they are also used to determine which structures are passed to the modules. Single player games use the client structures memory addresses.
 +
Line 20: Line 35:
=== backend.c ===
=== backend.c ===
 +
 +
Backend.c primary purpose is to switch between server and client functions based upon the current threads game context. In doing so it implements some of the functions of backend.h. For example the backend function ''screenGetNumNeutralBases();'' is implemented:
 +
 +
<pre>
 +
/*********************************************************
 +
*NAME:          screenGetNumNeutralBases
 +
*AUTHOR:        John Morrison
 +
*CREATION DATE: 21/2/99
 +
*LAST MODIFIED: 21/2/99
 +
*PURPOSE:
 +
* Returns the number of neutral bases
 +
*
 +
*ARGUMENTS:
 +
*
 +
*********************************************************/
 +
BYTE screenGetNumNeutralBases(void) {
 +
  if (threadsGetContext() == FALSE) {
 +
    return clientGetNumNeutralBases();
 +
  }
 +
  return serverCoreGetNumNeutralBases();
 +
}
 +
</pre>
 +
 +
The reason for this switching module is because of WinBolo's development history. The very first versions were built as a single player clone. The backend functions all started with screen*(); When the game became networkable (around WIP release 8) (todo full version history) the [[server]] functions were created using the prefix of serverCore*(); Any backend code that needed to access screen*(); functions could be added into the servercore file. The problem arose when trying to merge the server and client applications into the one binary.
 +
 +
The result was the API (function names) remained screen*(); but backend.c would switch between client*(); and serverCore*(); depending upon thread context.
 +
 +
This could be simplified by creating a game world structure that contains references to each of the ADT memory locations and having a single function to return the correct ADT rather then switching per ADT.
 +
 +
== screen.c ==
 +
 +
screen.c is the main entry point to the backend for clients. Overview of key functions:
 +
 +
<pre>/*********************************************************
 +
*NAME:          screenLoadMap
 +
*AUTHOR:        John Morrison
 +
*CREATION DATE: 29/10/98
 +
*LAST MODIFIED: 30/01/02
 +
*PURPOSE:
 +
*  Loads a map. Returns if it was sucessful reading the
 +
*  map or not.
 +
*
 +
*ARGUMENTS:
 +
* fileName - File name and path to map to open
 +
*  game - The game type-Open/tournament/strict tournament
 +
*  hiddenMines - Are hidden mines allowed
 +
*  srtDelay    - Game start delay (50th second increments)
 +
*  gmeLen      - Length of the game (in 50ths)
 +
*                (-1 =unlimited)
 +
*  playerName  - Name of the player
 +
*  wantFree    - Should we free the backend after loading
 +
*                Usually TRUE if you only want to check
 +
*                if a map is valid
 +
*********************************************************/
 +
bool screenLoadMap(char *fileName, gameType game, bool hiddenMines, long srtDelay, long gmeLen, char *playerName, bool wantFree);</pre>
 +
 +
Sets up a single player game by loading a map.
 +
 +
<pre>void screenDestroy();</pre>
 +
Called to shutdown the game simulation and free all memory.
 +
 +
<pre>/*********************************************************
 +
*NAME:          screenGameTick
 +
*AUTHOR:        John Morrison
 +
*AUTHOR:        John Morrison
 +
*CREATION DATE: 29/10/98
 +
*LAST MODIFIED: 4/1/00
 +
*PURPOSE:
 +
*  This function is called whenever a game tick occurs,
 +
*
 +
*ARGUMENTS:
 +
* tb        - The combinations of tank buttons being
 +
*            pressed
 +
* tankShoot - Is the fire key being pressed?
 +
* isBrain  - TRUE if a brain is running. Other
 +
*            parameters are ignored.
 +
*********************************************************/
 +
void screenGameTick(tankButton tb, bool tankShoot, bool isBrain);</pre>
 +
 +
The main simulation loop. Must be called every 20ms. Frontends must repeatedly call if it falls behind processing.

Revision as of 14:01, 1 December 2008

The bolo directory contains the backend code for simulating a game world.

#screen.c is the main entry point for client applications to talk to the backend.

The backend is not threadsafe and access to any functions should be syncronized.

Contents

Design

Although WinBolo is not written in C++ the backend has object orientated principles for managing the game world. This is due to the use of abstract data types within each module. (Note not all modules) For instance here is a list of some of pillbox functions:

void pillsCreate(pillboxes *value);
void pillsDestroy(pillboxes *value);
void pillsSetNumPills(pillboxes *value, BYTE numPills);
BYTE pillsGetNumPills(pillboxes *value);
void pillsSetPill(pillboxes *value, pillbox *item, BYTE pillNum);
bool pillsExistPos(pillboxes *value, BYTE xValue, BYTE yValue);
void pillsUpdate(pillboxes *value, map *mp, bases *bs, tank *tnk, shells *shs);

The ADT concept as well as New() and Dispose() macro's for ADT memory management come from Geoff Whales book - Data Structures and Abstraction Using C.


Client vs Server

The backend has code that provides processing for a single player game and game server as well as a dumber client. This is handled by the function threadsGetContext(); which returns TRUE if it is a server performing the action or FALSE if it is a client. Note that a single player game will return FALSE. Single player games need to be able to use some of the server logic to work to work correctly. So the backend will typically contain.

if (threadsGetContext() == TRUE || netGetType() == netSingle) {

The reason these two tests can not be simplified into threadsGetContext() function is they are also used to determine which structures are passed to the modules. Single player games use the client structures memory addresses.


Files

backend.c

Backend.c primary purpose is to switch between server and client functions based upon the current threads game context. In doing so it implements some of the functions of backend.h. For example the backend function screenGetNumNeutralBases(); is implemented:

/*********************************************************
*NAME:          screenGetNumNeutralBases
*AUTHOR:        John Morrison
*CREATION DATE: 21/2/99
*LAST MODIFIED: 21/2/99
*PURPOSE:
* Returns the number of neutral bases
*
*ARGUMENTS:
*
*********************************************************/
BYTE screenGetNumNeutralBases(void) {
  if (threadsGetContext() == FALSE) {
    return clientGetNumNeutralBases();
  }
  return serverCoreGetNumNeutralBases();
}

The reason for this switching module is because of WinBolo's development history. The very first versions were built as a single player clone. The backend functions all started with screen*(); When the game became networkable (around WIP release 8) (todo full version history) the server functions were created using the prefix of serverCore*(); Any backend code that needed to access screen*(); functions could be added into the servercore file. The problem arose when trying to merge the server and client applications into the one binary.

The result was the API (function names) remained screen*(); but backend.c would switch between client*(); and serverCore*(); depending upon thread context.

This could be simplified by creating a game world structure that contains references to each of the ADT memory locations and having a single function to return the correct ADT rather then switching per ADT.

screen.c

screen.c is the main entry point to the backend for clients. Overview of key functions:

/*********************************************************
*NAME:          screenLoadMap
*AUTHOR:        John Morrison
*CREATION DATE: 29/10/98
*LAST MODIFIED: 30/01/02
*PURPOSE:
*  Loads a map. Returns if it was sucessful reading the
*  map or not.
*
*ARGUMENTS:
* fileName - File name and path to map to open
*  game - The game type-Open/tournament/strict tournament
*  hiddenMines - Are hidden mines allowed
*  srtDelay    - Game start delay (50th second increments)
*  gmeLen      - Length of the game (in 50ths)
*                (-1 =unlimited)
*  playerName  - Name of the player
*  wantFree    - Should we free the backend after loading
*                Usually TRUE if you only want to check
*                if a map is valid
*********************************************************/
bool screenLoadMap(char *fileName, gameType game, bool hiddenMines, long srtDelay, long gmeLen, char *playerName, bool wantFree);

Sets up a single player game by loading a map.

void screenDestroy();

Called to shutdown the game simulation and free all memory.

/*********************************************************
*NAME:          screenGameTick
*AUTHOR:        John Morrison
*AUTHOR:        John Morrison
*CREATION DATE: 29/10/98
*LAST MODIFIED: 4/1/00
*PURPOSE:
*  This function is called whenever a game tick occurs,
*
*ARGUMENTS:
* tb        - The combinations of tank buttons being
*             pressed
* tankShoot - Is the fire key being pressed?
* isBrain   - TRUE if a brain is running. Other
*             parameters are ignored.
*********************************************************/
void screenGameTick(tankButton tb, bool tankShoot, bool isBrain);

The main simulation loop. Must be called every 20ms. Frontends must repeatedly call if it falls behind processing.

Personal tools