/* $Id: GameObject.h,v 1.19 1996/10/12 13:23:24 swetland Exp $
**
** The World, Ship, StarSystem, and GameObject classes
**
** Copyright 1996, Brian J. Swetland <swetland@uiuc.edu> and ACM@UIUC.
** Free for non-commercial use.  Share and Enjoy!
*/
#ifndef _GAME_OBJECT_H
#define _GAME_OBJECT_H

/*

 #    #    ##    #####   #    #     #    #    #   ####      This file is a
 #    #   #  #   #    #  ##   #     #    ##   #  #    #     mess.  Proceed
 #    #  #    #  #    #  # #  #     #    # #  #  #          at your own risk.
 # ## #  ######  #####   #  # #     #    #  # #  #  ###
 ##  ##  #    #  #   #   #   ##     #    #   ##  #    #     Everything you 
 #    #  #    #  #    #  #    #     #    #    #   ####      need to know is
                                                            documented
                                                            elsewhere
                                                            
 Many functions below are used internally by the game engine and are
 NOT for client use.  It is strongly suggest that you do not use these
 functions.  While it is not possible to cheat this way, you can
 severly confuse your client's game state -- this will not be to your
 benefit.

 You have been warned.

 Abandon All Hope, Ye Who Would Enter Here...
                                                            
                                                            */
#include "Socket.h"
#include "Message.h"
#include "Types.h"
#include "Loader.h"

class AI;
class Ship;
class Star;
class Enemy;
class Client;
class Server;

#define GAME_LENGTH 300

#define WARP_COST 20
#define FLAG_COST 25

#define WORLDMAX 128
#define MAXNEIGHBORS 100

#define INFINITE 3335828

#define UNKNOWN 4004

#define fHYPER       0x01
#define fDESTROYED   0x02
#define fHASFLAG     0x04


class World
{
    Star *starL[WORLDMAX];
    Ship *shipL[WORLDMAX];
    Enemy *enemyL[WORLDMAX];
    int star_count, enemy_count, ship_count;
    Star *home;
    
  public:
        /* INTERNAL USE BY GAME ENGINE -- DO NOT USE */
    World(void);
    void SetHomeBase(Star *h) {home=h;};
    
    void AddStarX(int id, int x, int y,
                  int flags, int ccount, lCnxn *list);
    void AddShip(Ship *);
    void AddStar(Star *);
    void AddEnemy(Enemy *);
    void ClearMsgs(void);
    void SendMsgs(MessageSocket *ms);

        /* THESE ARE OKAY TO USE */
    Star *HomeBase(void)   { return home; };
    int ShipCount(void)    { return ship_count; };
    int StarCount(void)    { return star_count; };
    int EnemyCount(void)   { return enemy_count; };
    Ship *ShipN(int num)   { return num >= ship_count ?
                                 (Ship*) NULL : shipL[num]; };
    Star *StarN(int num)   { return num >= star_count ?
                                 (Star *) NULL : starL[num]; };
    Enemy *EnemyN(int num) { return num >= enemy_count ?
                                 (Enemy *) NULL : enemyL[num]; };
};

class TeamSuper
{
    friend Client;
    Word id, year;
    World *world;    
   
public:
        /* THESE ARE OKAY TO USE */
    Word Year(void)         { return year; };
    World *TheWorld(void)   { return world; };
    Word ID(void)           { return id; };

    virtual char *Name(void) = 0;
    virtual void NewShip(Ship *ship);
    virtual void GameBegin(Word players);
     
    virtual void Turn(void);
    virtual void TurnBegin(void);
    virtual void TurnEnd(void);
};


class GameObject 
{
    Word owner;
    Word id;

public:
        /* INTERNAL USE BY GAME ENGINE -- DO NOT USE */
    GameObject();
    GameObject(Word id0);
    GameObject(Word id0, Word own0);
    Word SetOwner(Word o) { owner = o; };
    
        /* THESE ARE OKAY TO USE */
    Word ID(void)         { return id; };
    Word Owner(void)      { return owner; };
};


class Star : public GameObject
{
    friend class Server;
    
    Word x,y;
    Byte flagcount; /* -1 if unseen */

    int count; /* number of neighbors in hyperspace */
    Star *neighbor[MAXNEIGHBORS];
    int cost[MAXNEIGHBORS];
    int seen;
    
  public:
        /* INTERNAL USE BY GAME ENGINE -- DO NOT USE */
    Star(int id) : GameObject(id) { return; };
    Message *ToMessage(void);
     
    void SetStar(int x0, int y0, int f, int c, Star *nl[], int *cl);
    void SetFlags(int f);

        /* THESE ARE OKAY TO USE*/
    int HasFlags(void)       { return flagcount; }; 
    int CostTo(Star *star);
    int NeighborCount(void)  { return count; };
    Star *Neighbor(int n)    { return n >= count ?
                                   (Star *) NULL : neighbor[n]; };
};


class Enemy : public GameObject
{
    Word power;
    
    Byte flags;
    Star *star, *hyperstar;
    Word lastseen;
    
  public:
        /* INTERNAL USE BY GAME ENGINE -- DO NOT USE */
    Enemy(Word id) : GameObject(id) { return; };
    SetEnemy(Byte f0, Star *s, Star *h, Word l, Word p)
        { flags = f0; star = s; lastseen = l; hyperstar = h; power = p; };    
            
        /* THESE ARE OKAY */
    int HasFlag(void) { return flags & fHASFLAG; };
    int Destroyed(void) { return flags & fDESTROYED; };
    Star *Hyperspace(void) { return hyperstar; };

    Star *AtStar(void) { return star; };
    int LastSeen(void) { return lastseen; };
    int Power(void) { return power; };
};


class Ship : public GameObject
{
    friend TeamSuper;
    friend Server;
    TeamSuper *team;

    Word power;
    Word shields;
    Word weapons;
    Word engines;
    Word transport;
    
    Star *star;
    Byte flags;
    Word eta;  /* 0 = at star */
    AI *ai;

    Message *actionmsg;
    Message *configmsg;

  public:
        /* INTERNAL USE BY GAME ENGINE -- DO NOT USE */
    Ship(Word id, Word own);
    
    Ship(Word id, TeamSuper *t);
    
    void SetShip(Word p, Word s, Word w, Word e, Word t,
                 Byte f, Star *st, Word eta0);
    void SetShields(Word s) { shields = s; };
    Message *ToMessage(int isenemy, Word year, Star *hyper = NULL);
    void ClearMsgs(void) { actionmsg = NULL; configmsg = NULL;};
    void SendMsgs(MessageSocket *ms);

        /* THESE ARE OKAY TO USE */
    void AttachAI(AI *new_ai);
    int HasFlag(void)   { return flags & fHASFLAG; };
    int Destroyed(void) { return flags & fDESTROYED; };
    Star *AtStar(void)  { return star; };

    int ETA(void)       { return eta; };
    
    int Power(void)     { return power; };
    int Shields(void)   { return shields; };
    int Weapons(void)   { return weapons; };
    int Engines(void)   { return engines; };
    int Transport(void) { return transport; };

        /* Calling these outside of Team::Turn() is inadvisable */
    int Configure(Word shields, Word weapons, Word engines, Word transport);
    void ActionHyperspace(Star *star);
    void ActionAttack(Enemy *ship);
    void ActionPickupFlag(void);
    void ActionDropFlag(void);
};

class AI
{
  protected:  
    Ship *ship;
    World *world;
    TeamSuper *team;
  public:
        /* INTERNAL USE BY GAME ENGINE -- DO NOT USE */
    void Configure(Ship *ship1, World *world1, TeamSuper *team1)
        { ship = ship1; world = world1; team = team1; };
    
        /* THESE ARE OKAY */
    virtual void Turn(int year) { return; };
};

#endif /* _GAME_OBJECT_H */

