#ifndef GAME_H
#define GAME_H

#define SCREEN_WIDTH 480
#define SCREEN_HEIGHT 272
#define TILE_WIDTH 20
#define TILE_HEIGHT 20
#define MAX_TILES 128 * 128

enum Sfx { S_DOORLOCKED, S_DOOROPENS, S_POWERUP, S_SPECIAL, S_GAMEOVER, S_LEVELCOMPLETE, S_LEVELSTART, MAX_SFX };
enum Song { MUS_INTRO, MUS_EVEN, MUS_ODD, MUS_MENU, MAX_MUSIC };

enum FontId { FONT_SMALL, FONT_HEADLINE, FONT_BODY, FONT_BODYHIGHLIGHT, FONT_MESSAGE, FONT_SMALLHIGHLIGHT };

enum TileType { MAP_FLOOR, MAP_WALL, MAP_DOOR, MAP_ITEM, MAP_DESK,MAP_EXIT, MAP_CHARACTER };

#define TILEF_ANIMATED 0x01			// There is cycling animation automatically
#define TILEF_FOURVIEW_BELOW 0x02	// There are up, down, left and right views
#define TILEF_OSCILLATE 0x04		// Animate 1 2 3 4 4 3 2 1 1 2 3 4 ...

#define TILEF_NPCSPAWNER 0x100

struct Tile {
	char *name;
	int id;
	int flags;		// See TILEF_ above
	enum TileType type;
	int x,y,w,h;	// Where on the sprite sheet it is
	int cx,cy;		// Where the center (or reference point) of the tile is
	int frames;		// Count of the number of frames
	int animDelay;	// How long between tile flips
	int spawnDelay;	// How often a new character is spawned.
};
extern struct Tile playerTileDir[4*4];
#define TUP 0
#define TDOWN 1
#define TRIGHT 2
#define TLEFT 3
extern struct Tile tileset[32];
extern int tilesetCount;
extern struct Tile avatar[16];
extern struct Tile buttontile[4];
extern struct Tile pointtile[5];

#define MAPF_BOTTLE 1	// hidden bottle
#define MAPF_KEY 2		// hidden key
#define MAPF_CANDY 4	// hidden candy
#define MAPF_SPECIAL 8	// different on each level

#define TX(x) (1+22*x)
#define TY(y) (1+22*y)

struct Map {
	struct Tile *tile;
	int flags;
	int animatedTimer;
	int spawnTimer;
	int frame;
};

struct Message {
	struct Message *next;
	unsigned long color;	// Background rectangle.
	struct Tile *tile;		// Optional icon for this dialog
	int x,y,w,h;			// Background message
	int mx,my;				// Message x/y anchor
	enum FontId fontId;
	char *message;
	int teletypeTimer;	// To have the message be typed on screen.
	int teletypePos;
	int teletypeDelay;	// How long the timer should be.
	int animatedTimer;	// For the Tile.
	int frame;			// For the Tile.
	int timeToLiveTimer;	// For the whole message.
};

enum CharacterType { CHAR_PLAYER, CHAR_NPC, CHAR_POINTS, CHAR_ALCOHOL, CHAR_CHAIR, CHAR_DESK, CHAR_CABINET };

struct Comment {
	int points;
	const char *comment;
};
extern struct Comment newgame_comment[];
extern const int newgame_commentCount;

#define MAXDELTA 65536
struct Character {
	struct Character *next;	// The next character in a linked list
	enum CharacterType type;
	const char *name;
	const char *comment;
	int commentPoints;
	struct Tile *tile;
	int x,y;		// Position in pixels
	int fx,fy;		// Fractional position /65536 (MAXDELTA)
	int animatedTimer;
	int dx,dy;		// Direction x,y in fixed point /65536
	int walkTimer;	// How long until the next direction decision
	int tx,ty;		// Target x,y
	int frame;		// Current view
	unsigned char *path;	// The total path to lead to tx,ty.
};

struct HighScore {
	char name[16];
	int score;
	int level;
};

enum GameMode { GAME_INTRO, GAME_PLAY, GAME_PAUSE, GAME_SUMMARY, GAME_NEWHIGH, 
	GAME_HIGHSCORE, GAME_EXTRAS, GAME_PLAYINTRO, GAME_SUBWAY,
	GAME_CREDITS, GAME_RULES, GAME_RULESPAUSE, GAME_EDITOR, 
	GAME_EDITOR_PLACE, GAME_EDITOR_SAVE, GAME_EDITOR_LOAD, GAME_QUIT };

struct Game {
	enum GameMode mode;
	int mapWidth,mapHeight;
	int viewTop,viewLeft;
	struct Map *map;
	int itemCount;
	struct Character *player;
	int keys;	// How many passcards the player had collected.
	struct Character *firstCharacter;
	struct Message *firstMessage;
	int characterCount;
	int health;
	int healthTimer;
	int newHealthTimer;
	int score;
	int newScoreTimer;
	int lives;
	int level;
	int menuitem;
	int menuitemCount;
	int menuTimer;
	struct HighScore highscore[16];
	char name[32];
};

#define NEWSCOREDUR 1000
#define NEWHEALTHDUR 1000

#define DRINKFACTOR 256

struct DrinkParticle;

struct DrinkRestraint {
	struct DrinkRestrain *next;
	void (*retraint)(struct DrinkParticle *particle);
};

struct DrinkParticle {
	struct DrinkParticle *next;		// to enumerate all items
	struct DrinkParticle *gridNext;	// list of neighbours in the grid
	int x,y;	// position /DRINKFACTOR
	int vx,vy;	// velocity
	int ax,ay;	// acceleration
	int fx,fy;	// force
	int mass;
	int radius;
	int lastgridx,lastgridy;
	struct DrinkRestraint *restraint;
};

enum ParticleDir { PD_UP, PD_LEFT, PD_DOWN, PD_RIGHT };

void initGame();
void newGame();
int loadLevel();
int newhigh();
void setMode(enum GameMode mode);
struct Character *newCharacter(enum CharacterType type,struct Tile *tile,int x,int y);
void saveHighScore();

#include "main.h"
#include "draw.h"
#include "event.h"
#include "update.h"
#include "subway.h"

#endif
