/* Interface between game parameters and the rest of Xconq.
   Copyright (C) 1992-1996, 1998-2000 Stanley T. Shebs.

Xconq is free software; you can redistribute it and/or modify
it under the terms of the GNU General Public License as published by
the Free Software Foundation; either version 2, or (at your option)
any later version.  See the file COPYING.  */

/* This file defines the structures that are filled in with type info,
   one for each type, plus the declarations for all functions and variables. */

/* Numbers guaranteed to be invalid types in each category.  Should be
   careful that these don't overflow anything. */

#define NONUTYPE (MAXUTYPES)
#define NONMTYPE (MAXMTYPES)
#define NONTTYPE (MAXTTYPES)
#define NONATYPE (MAXATYPES)

/* Indices for each category of types. */

typedef enum {
  UTYP = 0,
  MTYP = 1,
  TTYP = 2,
  ATYP = 3
} Typetype;

/* The four roles for terrain. */

enum terrain_subtype {
    cellsubtype = 0,
    bordersubtype = 1,
    connectionsubtype = 2,
    coatingsubtype = 3
};

/* Ultimate limits on values in properties. */

#define PROPLO -32768
#define PROPHI 32767

/* Ultimate limits on values in tables. */

#define TABLO -32768
#define TABHI 32767

#define TABINT 0
#define TABDICE 1

/* Ultimate limits on values of globals. */

#define VARLO -2000000000
#define VARHI 2000000000

/* Used in advances code. */

#define DONE (-1)

#define NOUSER (-1)

#define NOADVANCE (-1)

#define NOUNIT (-1)

#include "lisp.h"

/* This is the structure representing info about a property
   of a type, such as a unit type's maximum speed. */

typedef struct propertydefn {
    char *name;
    int (*intgetter)(int);
    char *(*strgetter)(int);
    Obj *(*objgetter)(int);
    short offset;
    char *doc;
    short dflt;
    char *dfltstr;
    short lo, hi;
} PropertyDefn;

/* This is the structure with info about a table. */

typedef struct tabledefn {
    char *name;			/* name of the table */
    int (*getter)(int, int);	/* accessor function */
    char *doc;			/* documentation string */
    short **table;		/* pointer to table itself */
    short dflt;			/* default value of entries */
    short lo, hi;		/* bounds of table value */
    char index1, index2;	/* type of row and column indices */
    char valtype;		/* type of data in table */
} TableDefn;

/* This is the structure with info about a global variable. */

typedef struct vardefn {
    char *name;			/* name of the global */
    int   (*intgetter)(void);	/* accessor if integer type */
    char *(*strgetter)(void);	/* accessor if string type */
    Obj  *(*objgetter)(void);	/* accessor if object type */
    void (*intsetter)(int);	/* setter if integer type */
    void (*strsetter)(char *);  /* setter if string type */
    void (*objsetter)(Obj *);	/* setter if object type */
    char *doc;			/* documentation string */
    int dflt;			/* default value if integer type */
    char *dfltstr;		/* default value if string type */
    void (*dfltfn)(void);	/* default value if object type */
    int lo, hi;			/* bounds of integer value */
} VarDefn;

extern short numutypes;
extern short nummtypes;
extern short numttypes;
extern short numatypes;

typedef struct utype {

#undef  DEF_UPROP_I
#define DEF_UPROP_I(name,fname,doc,SLOT,lo,dflt,hi)  \
    short SLOT;
#undef  DEF_UPROP_S
#define DEF_UPROP_S(name,fname,doc,SLOT,dflt)  \
    char *SLOT;
#undef  DEF_UPROP_L
#define DEF_UPROP_L(name,fname,doc,SLOT)  \
    Obj *SLOT;

#include "utype.def"

} Utype;

/* Definition of material types. */

typedef struct mtype {

#undef  DEF_MPROP_I
#define DEF_MPROP_I(name,fname,doc,SLOT,lo,dflt,hi)  \
    short SLOT;
#undef  DEF_MPROP_S
#define DEF_MPROP_S(name,fname,doc,SLOT,dflt)  \
    char *SLOT;
#undef  DEF_MPROP_L
#define DEF_MPROP_L(name,fname,doc,SLOT)  \
    Obj *SLOT;

#include "mtype.def"

} Mtype;

/* Definition of terrain types. */

typedef struct ttype {

#undef  DEF_TPROP_I
#define DEF_TPROP_I(name,fname,doc,SLOT,lo,dflt,hi)  \
    short SLOT;
#undef  DEF_TPROP_S
#define DEF_TPROP_S(name,fname,doc,SLOT,dflt)  \
    char *SLOT;
#undef  DEF_TPROP_L
#define DEF_TPROP_L(name,fname,doc,SLOT)  \
    Obj *SLOT;

#include "ttype.def"

} Ttype;

/* Definition of advance types. */

typedef struct atype {

#undef  DEF_APROP_I
#define DEF_APROP_I(name,fname,doc,SLOT,lo,dflt,hi)  \
    short SLOT;
#undef  DEF_APROP_S
#define DEF_APROP_S(name,fname,doc,SLOT,dflt)  \
    char *SLOT;
#undef  DEF_APROP_L
#define DEF_APROP_L(name,fname,doc,SLOT)  \
    Obj *SLOT;

#include "atype.def"

} Atype;

/* The global data. */

typedef struct a_globals {

#undef  DEF_VAR_I
#define DEF_VAR_I(name,fname,setfname,doc,VAR,lo,dflt,hi)  \
    int VAR;
#undef  DEF_VAR_S
#define DEF_VAR_S(name,fname,setfname,doc,VAR,dflt)  \
    char *VAR;
#undef  DEF_VAR_L
#define DEF_VAR_L(name,fname,setfname,doc,VAR,dflt)  \
    Obj *VAR;

#include "gvar.def"

} Globals;

/* Declarations of the functions accessing and setting type properties. */

#undef  DEF_UPROP_I
#define DEF_UPROP_I(name,FNAME,doc,slot,lo,dflt,hi)  int FNAME(int u);
#undef  DEF_UPROP_S
#define DEF_UPROP_S(name,FNAME,doc,slot,dflt)  char *FNAME(int u);
#undef  DEF_UPROP_L
#define DEF_UPROP_L(name,FNAME,doc,slot)  Obj *FNAME(int u);

#include "utype.def"

#undef  DEF_MPROP_I
#define DEF_MPROP_I(name,FNAME,doc,slot,lo,dflt,hi)  int FNAME(int m);
#undef  DEF_MPROP_S
#define DEF_MPROP_S(name,FNAME,doc,slot,dflt)  char *FNAME(int m);
#undef  DEF_MPROP_L
#define DEF_MPROP_L(name,FNAME,doc,slot)  Obj *FNAME(int m);

#include "mtype.def"

#undef  DEF_TPROP_I
#define DEF_TPROP_I(name,FNAME,doc,slot,lo,dflt,hi)  int FNAME(int t);
#undef  DEF_TPROP_S
#define DEF_TPROP_S(name,FNAME,doc,slot,dflt)  char *FNAME(int t);
#undef  DEF_TPROP_L
#define DEF_TPROP_L(name,FNAME,doc,slot)  Obj *FNAME(int t);

#include "ttype.def"

#undef  DEF_APROP_I
#define DEF_APROP_I(name,FNAME,doc,slot,lo,dflt,hi)  int FNAME(int a);
#undef  DEF_APROP_S
#define DEF_APROP_S(name,FNAME,doc,slot,dflt)  char *FNAME(int a);
#undef  DEF_APROP_L
#define DEF_APROP_L(name,FNAME,doc,slot)  Obj *FNAME(int a);

#include "atype.def"

#undef  DEF_VAR_I
#define DEF_VAR_I(str,FNAME,SETFNAME,doc,var,lo,dflt,hi)  \
  int FNAME(void);  \
  void SETFNAME(int val);
#undef  DEF_VAR_S
#define DEF_VAR_S(str,FNAME,SETFNAME,doc,var,dflt)  \
  char *FNAME(void);  \
  void SETFNAME(char *val);
#undef  DEF_VAR_L
#define DEF_VAR_L(str,FNAME,SETFNAME,doc,var,dflt)  \
  Obj *FNAME(void);  \
  void SETFNAME(Obj *val);

#include "gvar.def"

/* Declarations of table accessor functions and the globals
   for constant and filled-in tables. */

#undef  DEF_UU_TABLE
#define DEF_UU_TABLE(name,FNAME,doc,TABLE,CNST,lo,dflt,hi,valtype)  \
  int FNAME(int u1, int u2);  \
  extern short *TABLE, CNST;

#undef  DEF_UM_TABLE
#define DEF_UM_TABLE(name,FNAME,doc,TABLE,CNST,lo,dflt,hi,valtype)  \
  int FNAME(int u, int m);  \
  extern short *TABLE, CNST;

#undef  DEF_UT_TABLE
#define DEF_UT_TABLE(name,FNAME,doc,TABLE,CNST,lo,dflt,hi,valtype)  \
  int FNAME(int u, int t);  \
  extern short *TABLE, CNST;

#undef  DEF_TM_TABLE
#define DEF_TM_TABLE(name,FNAME,doc,TABLE,CNST,lo,dflt,hi,valtype)  \
  int FNAME(int t, int m);  \
  extern short *TABLE, CNST;

#undef  DEF_TT_TABLE
#define DEF_TT_TABLE(name,FNAME,doc,TABLE,CNST,lo,dflt,hi,valtype)  \
  int FNAME(int t1, int t2);  \
  extern short *TABLE, CNST;

#undef  DEF_MM_TABLE
#define DEF_MM_TABLE(name,FNAME,doc,TABLE,CNST,lo,dflt,hi,valtype)  \
  int FNAME(int m1, int m2);  \
  extern short *TABLE, CNST;

#undef  DEF_UA_TABLE
#define DEF_UA_TABLE(name,FNAME,doc,TABLE,CNST,lo,dflt,hi,valtype)  \
  int FNAME(int u, int a);  \
  extern short *TABLE, CNST;

#undef  DEF_AM_TABLE
#define DEF_AM_TABLE(name,FNAME,doc,TABLE,CNST,lo,dflt,hi,valtype)  \
  int FNAME(int a, int m);  \
  extern short *TABLE, CNST;

#undef  DEF_AA_TABLE
#define DEF_AA_TABLE(name,FNAME,doc,TABLE,CNST,lo,dflt,hi,valtype)  \
  int FNAME(int a1, int a2);  \
  extern short *TABLE, CNST;

#include "table.def"

/* Declarations of the globals description structures. */

extern Globals globals;

extern Utype *utypes;

extern Mtype *mtypes;

extern Ttype *ttypes;

extern Atype *atypes;

extern PropertyDefn utypedefns[];

extern PropertyDefn mtypedefns[];

extern PropertyDefn ttypedefns[];

extern PropertyDefn atypedefns[];

extern TableDefn tabledefns[];

extern VarDefn vardefns[];

/* Macros for iterating over types. */

#define for_all_unit_types(v)      for (v = 0; v < numutypes; ++v)

#define for_all_material_types(v)  for (v = 0; v < nummtypes; ++v)

#define for_all_terrain_types(v)   for (v = 0; v < numttypes; ++v)

#define for_all_advance_types(v)   for (v = 0; v < numatypes; ++v)

/* Iterate over border and connection types by using a cached array
   linking each type to the next. */

#define for_all_border_types(t)  \
  for ((t) = first_bord_type; (t) >= 0; (t) = next_bord_type[(t)])

#define for_all_connection_types(t)  \
  for ((t) = first_conn_type; (t) >= 0; (t) = next_conn_type[(t)])

/* Macros encapsulating things about units. */

#define checku(x) if ((x) < 0 || (x) >= numutypes) utype_error(x);

#define checkm(x) if ((x) < 0 || (x) >= nummtypes) mtype_error(x);

#define checkt(x) if ((x) < 0 || (x) >= numttypes) ttype_error(x);

#define checka(x) if ((x) < 0 || (x) >= numatypes) atype_error(x);

/* Fix eventually. */

/* (should say u_... or ..._type ?) */

#define actor(u) (u_acp(u) > 0)

#define mobile(u) (u_speed(u) > 0)

#define u_hp(u) (u_hp_max(u))

#define could_be_on(u,t)  \
  ((ut_capacity_x(u, t) > 0 || ut_size(u, t) <= t_capacity(t)))

#define could_live_on(u,t)  \
   (could_be_on(u, t) && !ut_vanishes_on(u, t) && !ut_wrecks_on(u, t))

#define could_carry(u1,u2)  \
  (uu_capacity_x(u1, u2) > 0 || uu_size(u2, u1) <= u_capacity(u1))

#define could_create(u1,u2) (uu_acp_to_create(u1, u2) > 0)

#define could_repair(u1, u2) (uu_repair(u1, u2) > 0)

/* These need actual units rather than types. */

#define impassable(u, x, y) (!could_be_on((u)->type, terrain_at((x), (y))))

#define isbase(u) (u_is_base((u)->type))

#define base_builder(u) (u_is_base_builder((u)->type))

#define istransport(u) (u_is_transport((u)->type))

#define t_is_cell(t) (t_subtype(t) == cellsubtype)

#define t_is_border(t) (t_subtype(t) == bordersubtype)

#define t_is_connection(t) (t_subtype(t) == connectionsubtype)

#define t_is_coating(t) (t_subtype(t) == coatingsubtype)

#define is_unit_type(u) ((u) >= 0 && (u) < numutypes)

#define is_material_type(m) ((m) >= 0 && (m) < nummtypes)

#define is_terrain_type(t) ((t) >= 0 && (t) < numttypes)

#define is_advance_type(a) ((a) >= 0 && (a) < numatypes)

extern short canaddutype;
extern short canaddmtype;
extern short canaddttype;
extern short canaddatype;

extern short tmputype;
extern short tmpmtype;
extern short tmpttype;
extern short tmpatype;

extern short first_bord_type;
extern short *next_bord_type;
extern short first_conn_type;
extern short *next_conn_type;

extern void utype_error(int u);
extern void mtype_error(int m);
extern void ttype_error(int t);
extern void atype_error(int s);

extern void init_types(void);
extern void init_globals(void);
extern void default_unit_type(int x);
extern void default_material_type(int x);
extern void default_terrain_type(int x);
extern void default_advance_type(int x);

extern void allocate_table(int tbl, int reset);
extern int numtypes_from_index_type(int x);
extern char *index_type_name(int x);

extern void set_g_synth_methods_default(void);
