--------------------------------------
How to implement a new Game in TripleA
--------------------------------------


1. Read the TripleA documentation
---------------------------------

Before you start developing a new game you should get a general idea
about how the TripleA engine works. There are a few documentation
files that come with the TripleA download (they are located in the
"doc" folder in the main directory). For our purposes, the "Engine
code overview" is especially interesting. It explains the basic
concepts we will be dealing with when making a game.


2. Setting Up the game XML and creating required classes
--------------------------------------------------------

2.1 Create the XML:
  The first thing we have to do is writing an XML file, that describes
  our game and provides some meta data to the engine. It has to satisfy
  a specific schema that is defined by the "game.dtd" file in the
  "data\games\strategy\engine\xml" directory found in the source
  download. As an example, see the provided "othello.xml" file, which
  describes the game Othello. The file also explains the meaning of the
  individual elements via inline comments. Among other things, you will
  have to specify the class names of your game loader class and your
  delegate classes in the XML. The following steps explain what these
  classes should look like.

2.2 Create the loader class:
  Create a new class that extends the TripleA class
  "games.strategy.grid.GridGame" and implements the interface
  "games.strategy.engine.framework.IGameLoader". Let Eclipse add method
  stubs for all unimplemented methods.

  2.2.1 Implement getServerPlayerTypes():
    This method should return an array of strings describing the names
    of different game players, i.e. "human player", "ai1", "ai2", ...
    For now just return an array with one entry called "human player"
    or something like that. You can add different AIs to the list later

  2.2.2 Implement createPlayers(...):
    This method receives a mapping of player names to player types as a
    parameter and should create and return IGamePlayer instances based
    on that mapping. The key strings represent the different player
    names for the game (for example "Black", "White", ...), the value
    strings represent the respective game players ("human", "ai1", ..).
    Iterate over all entries and check if the player type equals the
    string you added in 2.2.1, if it does create a new instance of
    "games.strategy.grid.player.GridGamePlayer" with name and type as
    parameters and add it to the set that you return (you can use a
    HashSet for that).

  2.2.3 Implement getGridMapDataClass():
    This method defines the class that describes the data we want to
    store for our game map. For now we will just use the class
    "games.strategy.grid.ui.GridMapData".
    Just return "GridMapData.class". If you want to store some
    additional data, you can later replace this class with an extension
    of it.

  Leave the other methods of this class as they are for now.
  Don't forget to set this as your new loader class in the XML file.

2.3 Create the delegate classes:
  Delegates define your games logic and mechanics. Each delegate class
  represents one step of a turn in your game. For example in a complex
  strategy game there could be a delegate class for movement, another
  for trading, for battle, and so on. There are delegates which execute
  plays done by players or AIs, but there can also be delegates which
  don't require any user interaction and alter the game data on their
  own. For example you could imagine a game where a delegate
  automatically removes a random unit after both players have taken
  their turn.
  For this tutorial we will create one delegate class to interpret
  players' moves and change the game data accordingly, and another
  delegate that checks if a player wins at the end of their turn.

  2.3.1 Create the play delegate class:
    Create a new class that extends "AbstractDelegate" from the
    "games.strategy.common.delegate" package and implements the
    interface "IGridPlayDelegate" from the
    "games.strategy.grid.delegate.remote" package. Let Eclipse add
    stubs for all unimplemented methods. We will refer to this class as
    our play delegate.

  2.3.2 Create the end turn delegate class:
    Create another class that extends "AbstractDelegate", but this time
    we don't implement the "IGridPlayDelegate" interface. Add stubs for
    all unimplemented methods. We will refer to this class as the end
    turn delegate.

  2.3.3 Define the delegates and game sequence in the XML file:
    Define your delegates and game sequence in the "gamePlay" element
    of your XML file. For examples on what this should look like, see
    "othello.xml" or the "Engine Code Overview" in the TripleA doc.

2.4 Put the XML in the right directory:
  Make sure your XML contains all required elements and that they are
  in the right order.
  For the engine to find your XML file, it has to be placed in a
  specific folder structure. In the "maps" folder in your TripleA home
  directory, create a new folder called "my_game" or something like
  that, within that folder create a new folder called "games" and put
  the XML file there. If you installed TripleA with the Windows
  installer, you can use the "triplea\maps" folder in your user
  directory as an alternative.
  If you run your project now you should be able to select your game
  from the "Choose Game" menu. Try starting a new local game, you
  should see your specified players and be able to select a player type
  for them (the one you added in 2.2.1). After clicking play you should
  receive an error message because the UI can't be created yet. To fix
  this we have to create a few more classes.

2.5 Create classes for the UI:
  
  2.5.1 Create the map panel class:
    Create a new class that extends the "GridMapPanel" class in the
    "games.strategy.grid.ui" package. Let Eclipse add method stubs for
    all unimplemented methods and create a default constructor.
    In your loader class, return this class in the method
    "getGridMapPanelClass()".

  2.5.2 Create a Menu class:
    Create a new class that extends "GridGameMenu<GridGameFrame>", both
    classes from the "games.strategy.grid.ui" package. Add a default
    constructor and the unimplemented method.
    In the loader class, return this class in the method
    "getGridTableMenuClass()".

If you run your game now, the context for our user interface should be
created correctly and the errors from earlier should be gone. The next
step is to use this context to actually draw our game board and handle
user input.


3. User Interface
-----------------

3.1 Specify tile dimensions in loader:
  In the loader class, override the methods
  getSquareWidth(), getSquareHeight() and getBevelSize().
  These methods specify the size of the tiles of your game board. The
  engine will use these values to automatically create Polygon
  objects to be drawn later. Just return some constant values (~50)

3.2 Draw the board and game pieces:
  Drawing is done in the paintComponentMiddleLayer() method in your
  map panel class. It receives a Graphics2D object as a parameter.
  If you are not familiar with the java.awt.Graphics2D class, you can
  look up its documentation online.
  To receive the automatically created polygons from the engine, use
  "m_mapData.getTerritoryPolygons(m_gameData.getMap())"
  It returns a mapping of all territories to their respective polygons.
  Using the Graphics2D methods, draw the polygons in any way you like.
  You can also use information about the territories if you like, for
  example to paint territories with different owners in different
  colors. If you run the game now you should be able to see the game
  board.
  The next step is to draw the game pieces or units. The member
  variable "m_images" is a mapping from territories to Image objects
  for units located on that territory. You can just draw them using the
  drawImage(...) method of the Graphics2D class. To find out the right
  position and size for the images you can use the getBounds() method
  of the respective polygon.
  Assuming you have specified some starting positions for units in the
  XML, you should now be able to see the units on the board when you
  run the game.

3.3 Handling user input:
  You might have noticed that so far, any time you click the game board
  an exception is thrown. To fix this we need to implement the methods
  isValidPlay(...) and getCapturesForPlay(...).
  isValidPlay should return an error string if the play it receives as
  a parameter is not legal for the current game state.
  getCapturesForPlay should return a collection of all territories that
  change owners if the specified play is performed.
  Since we will most likely also need methods like this in our
  delegates, it is advisable to write some static methods somewhere to
  do these checks, so we don't have to write the same code twice.
  If the game you want to make uses drag&drop-style input (i.e. moving
  pieces from one tile to another, like in chess), you can  leave the
  rest of the user input to the superclasses and move on to writing the
  delegates.
  If you want user input other than drag&drop, you have to override the
  MouseListener methods, manually create a play and forward it to your
  play delegate. For an example on how this can be done, see the
  implementation of the game "Go" that comes with TripleA
  (games.strategy.grid.go.ui.GoMapPanel.java).
  If you want to use input from the keyboard, you can also override the
  method doKeyListenerEvents(...) in your map panel class.


4. Defining game mechanics with delegates
----------------------------------------

Now it's time to implement the delegate classes (we already created
them in step 2.3)

4.1 Implement the play delegate:
  
  4.1.1 Implement delegateCurrentlyRequiresUserInput():
    This method defines whether or not a delegate should wait for user
    input. In this example you can just return true, but in a more
    complex game the return value could be dynamic (for example return
    true unless a player has no units left and can't move)
  4.1.2 Implement getRemoteType():
    Just return "IGridPlayDelegate.class".
  4.1.3 Implement signalStatus(...):
    This method is used to send status strings about the current state
    of the game to the delegate. To display these messages, we can use
    the display channel broadcaster. It gives us access to all displays
    running our game, also on remote machines. Call the method
    "m_bridge.getDisplayChannelBroadcaster()". It returns an IDisplay
    object which we cast to IGridGameDisplay. On this object, call the
    method "setStatus" with the status as a parameter.
  4.1.4 Implement play(...):
    Finally, this is where we define our delegates behaviour. The
    method receives a play from the user interface or an AI player. The
    delegate's job is to change the game data based on that play. For
    example in a chess game the delegate would have to move a game
    piece, check if there is an enemy game piece in the new position
    and if there is, remove it. It can also return an error if the move
    is illegal, for example when moving a king into check.

    4.1.4.1 The history writer:
       One of TripleA's features is to display the history of the game,
       i.e. the board states of all previous turns. We just have to
       tell the engine when to start a new history event. To do this we
       use the HistoryWriter, which we obtain by calling
       "m_bridge.getHistoryWriter()". We then call its "startEvent"
       method with a string that describes the current play (you can
       use play.toString() for this).
    4.1.4.2 Making changes:
       For network transparency reasons, delegates can not change game
       data directly but have to use the "addChange" method of the
       delegate bridge ("this.m_bridge"). It takes a Change object as
       a parameter which we create using the "ChangeFactory" class. It
       provides various static methods to create different kind of
       changes to the game data (for example moveUnits, changeOwner,
       and so on). Multiple Change objects can also be encapsulated
       into one using the "CompositeChange" class.
    4.1.4.3 Illegal moves:
       If the delegate decides a move is not legal for the current game
       state it can return an error message describing what's wrong
       with the play, otherwise it returns null. Note that the error
       should be returned before making any changes or starting a new
       history event.
  4.1.5 Override start():
    The start method is called by the engine when a delegate is run.
    Other than the play method, it does not wait for user input, so if
    you want to make some changes before the player gets a chance to
    make his move, this is the place to put them.
    You can also give instructions and information to the player using
    the setStatus method.
    When overriding this method it's important to call "super.start()"
    before you do anything else.

After implementing the play delegate, you should be able to start your
game and play it. However, the game will never end because we haven't
implemented a game over yet. This is why we have the end turn delegate.

4.2 Implement the end turn delegate:
  If the game sequence in our XML is defined correctly, this delegate
  should run after each player's turn. Here we check the state of the
  game after the play delegate's changes and decide if the game should
  end and signal this to the engine.
   
  4.2.1 Implement delegateCurrentlyRequiresUserInput():
    Since this delegate never requires user input, just return false.
  4.2.2 Implement getRemoteType():
    This time we don't implement an IRemote interface, so we can just
    return null.
  4.2.3 Override start():
    Other than the play delegate, this one does not need a play method,
    so this is the only method that gets called by the engine. Don't
    forget to call super.start() first, then check for a game over.
    To end the game do the following steps

    4.2.3.1 Create a new history event:
      We want to add the end of the game to the history, so start a new
      history event with some game over text.
    4.2.3.2 Notifying the displays:
      Use the display channel broadcaster to display to the user that
      the game is over (with the setStatus method). After that call the
      display's setGameOver method.
    4.2.3.3 Notifying the delegate bridge
      Finally we tell the engine to stop the game sequence and to not
      run any further delegates after this one.
      To do this, call "m_bridge.stopGameSequence()"