/*

NOTES FOR LATER:

   Note: during the update_game() function (see game.h), interact_sprites()
   should be called *before* update_sprites(). There are two reasons for
   this:

   1. An interact proc can set a flag in a sprite, triggering an action in
      the same frame; that action can then be handled by the update proc.

   2. The update proc, responsible for collision detection with the tile map,
      will have the last word. While this arrangement allows sprites to
      overlap for a frame before a collision is detected, it prevents sprites
      from overlapping with the tile map, which would be a more serious
      problem.


*/


#ifndef INCLUDED_GAME_H
#define INCLUDED_GAME_H

#include "level.h"
#include "tilemap.h"
#include "sprite.h"
#include "player.h"


typedef struct OUTPUTDEV {

 struct OUTPUTDEV *next; /* Linked list of devices */

 unsigned int x, y, w, h;   /* Area of the screen on to which to draw.
                      These coordinates are resolution-independent;
                      the screen is considered to be sized 65536 x 65536
                      for these purposes.
                   */

 PLAYER *player;   /* The player owning the camera, status for overlay, etc */

} OUTPUTDEV;


typedef struct GAME {

	TILEMAP *map;
	SPRITE *sprite; /* Linked list of sprites */
	PLAYER *player; /* Linked list of players */

	OUTPUTDEV *output; /* Where the game will be drawn */

} GAME;

struct PLAYER *player_won;
extern int game_start_time;
extern int game_is_draw;
extern int game_draw_time;
extern int game_has_started;


/* GAME *initialise_game(LEVEL *level, OUTPUTDEV *output)
 *  Initialises a game from the specified level. Set 'output' to the
 *  default device you'd like the game to be drawn into (may be the screen,
 *  or a backbuffer, or a subbitmap even). See create_output_dev() for
 *  details.
 *  Returns NULL on failure.
 */
GAME *initialise_game(LEVEL *level, OUTPUTDEV *output, PLAYER *players);


/* int add_player_to_game(GAME *game, PLAYER *player)
 *  Adds a player to the game. The player must already have been initialized.
 *  This will attach the player's sprite to the game. Returs 0 on success.
 */
int add_player_to_game(LEVEL *level, GAME *game, PLAYER *player);


/* void remove_player_to_game(GAME *game, PLAYER *player)
 *  Removes a player from the game. The player's structure will not be modified.
 *  This function will also remove the player's sprite from the game.
 *  Neither the player's memory, nor its sprite will be freed.
 */
void remove_player_from_game(GAME *game, PLAYER *player);

/* int is_player_in_game(GAME *game, PLAYER *player)
 * returns TRUE if the player is in 'game'. Player's status
 * (dead, outside map, etc) is irrelevant.
 */
int is_player_in_game(GAME *game, PLAYER *player);  

/* void shut_down_game(GAME *game)
 *  Call when the game has ended. This function will free all memory attached
 *  to 'game' that was created by initialize_game() or update_game().
 *  Players and sprites are not free'd, but the linked list is reset.
 *  Output devices, with their associtaed bitmaps, are also destroyed
 *  (except if bitmap == screen).
 */
void shut_down_game(GAME *game);


/* int update_game(GAME *game)
 *  Update the game logic. This will be called at 100 Hz on average. It should update
 *  all the physics (positions, collision detection), and the status of players.
 *  Returns 1 on game end.
 */
int update_game(void *data);

/* void draw_game(GAME *game)
 *  This function will draw the game in the specified bitmap.
 *  The rendering will be done for every output device in the
 *  list. The polygons are transformed and clipped accoding to
 *  the output dev's camera, then rasterized on the output bitmap.
 *  This function will also draw the overlay (player stats), and
 *  game state texts (such as "Game Over").
 */
void draw_game(void *data);

/* OUTPUTDEV *create_output_device(BITMAP *bitmap, PLAYER *player);
 *  Creates a device to output to. It also links in the player for
 *  displaying his stats. The bitmap can be a video bitmap, memory bitmap
 *  or subbitmap thereof. Returns a pointer to an output device, or NULL
 *  on error.
 */
OUTPUTDEV *create_output_device(int x, int y, int w, int h, PLAYER *player);


/* int add_output_device(GAME *game, OUTPUTDEV *device)
 *  Adds an output device to the game. Returns 0 on success.
 */
int add_output_device(GAME *game, OUTPUTDEV *device);

void destroy_output_device(OUTPUTDEV *dev);
void destroy_output_devices(OUTPUTDEV *dev);

extern int chosen_level;


/* mkc_play_game() is used in m_game.h. mkc_test_zig() is used in m_option.h.
   While mkc_play_game() should use the player allocation set up by the game
   menu (m_game.h), mkc_test_zig() should set up a game between four Zig AI
   players.
*/
int mkc_play_game(void);
int mkc_test_zig(void);

#endif /* INCLUDED_GAME_H */
