/*  agtread.h-- Header for all AGiliTy files.             */
/* Copyright 1996,97  Robert Masenten                     */
/*                                                        */
/* This is part of the source for both AGiliTy: the (Mostly) Universal */
/*       AGT Interpreter and for the Magx adventure game compiler.    */

/*
    This is the master header file for all of the AGT stuff.
      It includes the global variables, the data types, etc.
      (everything that is read in from the game file).
    Variables not read in from the game file but used internally
      by the AGiliTy interpreter are declared in uagt.h.
    Magx specific things are in comp.h.
    This file also contains most of the configuration information
      including the platform-dependent #define statements 
*/


/* Default to PLAIN platform */
/* At the moment, you can replace this with LINUX, HPUX, AMIGA,     */
/*   MSDOS, SUN, or NEXT; some of these may require the correct os_... */
/*   file to work                                                   */
/*   (In particular, AMIGA requires David Kinder's os_amiga.c file) */
/* The actual platform specific defines don't start until a few     */
/*   lines down, past the #includes and the definition of global    */
#ifndef PLAIN 
#define PLAIN
#endif

/* Headers used by by all of the modules or by this header file */
#include <stdlib.h>
#include <stdio.h>
#include <string.h>

#ifdef __MSDOS__  /* This works under Borland C, at least */
#define MSDOS
#endif

/* ------------------------------------------------------------------- */
/* PLATFORM SPECIFIC DEFINITIONS, ETC. */
/*  See agility.doc or porting.txt for more information. */
/* Things you can currently define: */
/*    fix_ascii: 1=translate IBM character set, 0=don't */
/*    NEED_STR_CMP: define if strcasecmp() not defined on your system */
/*    NEED_STRN_CMP: define if strncasecmp() not defined on your system */
/*    HAVE_STRDUP: define if strdup() exists on your system */
/*    REPLACE_GETFILE: define if you replace the default get_user_file(). */
/*    REPLACE_MENU if you replace agt_menu().                 */
/*    REPLACE_MAIN: define if you replace the default main(). */
/*  (replacements should be defined in the relevant os_<platform>.c file) */
/*    DA1,DA2,...DA6,DSS,pTTL: file name extensions for the various AGT 
            files */
/*   HAVE_SLEEP if your platform has the sleep() function */
/*   BUFF_SIZE is the maximum size of the buffer to use when reading
       in files. Regardless, it will be made no bigger than the file 
       being read in and no smaller than the record size; thus setting
       it to 0 will cause the smallest buffer to always be used and
       setting this to 1MB will in practice always use a buffer the
       sizs of the file. It defaults to 32K */
/*   CBUF_SIZE is the maximum size of the buffer used for reading in 
       the Master's Edition DA6 files; the size of the buffer in bytes
       is twice this value (since an individual token is two bytes long). */
/*   DOHASH to use a hash table for dictionary searches; the only 
       reason not to have this would be memory */
/*   HASHBITS determines the size of the hash table: (2^HASHBITS)*sizeof(word);
       the hash table must be at least as large as the dictionary.
       In practice this means HASHBITS should be at least 12;
       this is the current default. */
/*   MAXSTRUC The maximum size (in chars) which a single data structure can
       be on this platform. This defaults to 1MB (i.e. no limit for 
       practical purposes). In practice I know of no game files that
       require any structures bigger than about 30K.  */
/*   LOWMEM Define this if you are low on memory. At the moment this
       only saves a few K.*/
/*   PORTSTR Is the string describing this particular port.
        e.g. #define PORTSTR "OrfDOS Port by R.J. Wright" */ 
/*   UNIX_IO  if you have Unix-like low level file I/O functions.
       (MS-DOS, for example, does). This speeds up the reading
       of the large game data files on some platforms. If this is 
       defined, READFLAG, WRITEFLAG, and FILE_PERM also need to
       be defined. (Giving the flags needed for opening a file for
       reading or writing, and the file permissions to be given to newly
       created files. */  
/*   OPEN_AS_TEXT  Define to cause text files to be opened as text files. */
/*   PREFIX_EXT  Add filename extensions at the beginning of the name, 
       rather than at the end. */
/* ------------------------------------------------------------------- */

/* force16 is used purely for debugging purposes, to make sure that
   everything works okay even with 16-bit ints */
/* #define force16 */

#define DOHASH

/* This works with Borland C; I don't know about other DOS C compilers  */
#ifdef MSDOS
#define FAR far
#define strcasecmp(s1,s2) stricmp(s1,s2)
#define fnamecmp strcasecmp   /* Case insensitive file name comparison */
#define NEED_STRN_CMP
#define fix_ascii 0  /* DON'T translate IBM character set */
#define HAVE_SLEEP
#define BUFF_SIZE (16*1024L)
#define CBUF_SIZE (20000L)
#define MAXSTRUC (64L*1024L)  /* DOS 64K Limit */
#define FAST_FIXSIGN
#define PORTSTR "DOS Version"
#define UNIX_IO
#define READFLAG (O_RDONLY | O_BINARY)
#define WRITEFLAG (O_WRONLY | O_BINARY | O_CREAT | O_TRUNC)
#define FILE_PERM (S_IWRITE | S_IREAD)
#undef PLAIN
#endif


 
#ifdef LINUX
#define LINUX_COLOR
#define fix_ascii 1  
#define HAVE_TPARAM
#define UNIX
#define HAVE_STRDUP
#define BUFF_SIZE (1024L*1024L) 
#define MAXSTRUC (4*1024L*1024L) /* If we're asking for over 4 MB, something
				  is wrong. */
#define CBUF_SIZE (20000L)
#define FAST_FIXSIGN
#define PORTSTR "Linux Version"
#undef PLAIN
#endif


/* The following configuration was contributed by Alexander Lehmann */
/* It was originally written for 0.3, but it should work for later */
/* versions as well. */ 
#ifdef HPUX
#define HAVE_TPARAM
#define UNIX
#define HAVE_STRDUP
#define BUFF_SIZE (1024L*1024L)
#define MAXSTRUCT (1024L*1024L)
#define CBUF_SIZE (20000L)
#define FAST_FIXSIGN
#define PORTSTR "HP-UX Version"
#undef PLAIN
#endif


#ifdef SUN
#define NO_TERMCAP_H
#define UNIX
#define BUFF_SIZE (1024L*1024L)
#define MAXSTRUC (1024L*1024L) 
#define CBUF_SIZE (20000L)  
#define PORTSTR "UNIX Version"
#undef PLAIN
#endif

/* This can presumably be tweaked to support various flavors of BSD */
#ifdef NEXT
#define NO_TERMCAP_H
#define UNIX
#define BSD_TERM
#define BUFF_SIZE (1024L*1024L)
#define MAXSTRUC (1024L*1024L) 
#define CBUF_SIZE (20000L)  
#define PORTSTR "NEXT/BSD Version"
#define _POSIX_SOURCE
#include <time.h>
#include <sys/types.h>
#undef PLAIN
#endif


/* From David Kinder's port; you'll also need his os_amiga.c file  */
#ifdef AMIGA  
#define NEED_STR_CMP
#define NEED_STRN_CMP
#undef HAVE_STRDUP
#define REPLACE_GETFILE
#define FAST_FIXSIGN
#define BUFF_SIZE (256L*1024L)
#define CBUF_SIZE (20000L)
#define UNIX_IO
#define PORTSTR "Amiga Version by David Kinder"
#define READFLAG O_RDONLY
#define WRITEFLAG (O_WRONLY|O_CREAT|O_TRUNC)  
#define FILE_PERM 0
#undef PLAIN
#endif


/* PLAIN should always come last, giving everyone else a chance
 to #undef it. */
#ifdef PLAIN  /* This should work if nothing else does */
#define NEED_STR_CMP
#define NEED_STRN_CMP
#define BUFF_SIZE 0    
#define CBUF_SIZE (5000L)
#define MAXSTRUC (32L*1024L) /* IIRC, 32K is the minimum required by
				the ANSI standard */
#define PORTSTR "Pure ANSI C version"
#endif


/* __GNUC__ */


/* ------------------------------------------------------------------- */
/* DEFAULTS FOR "PLATFORM SPECIFIC" DEFINES */
/* ------------------------------------------------------------------- */

#ifdef __POSIX__
#ifndef UNIX
#define UNIX
#endif
#endif

#ifdef UNIX
#define HAVE_SLEEP
#define UNIX_IO
#define READFLAG O_RDONLY
#define WRITEFLAG (O_WRONLY|O_CREAT|O_TRUNC)
#define FILE_PERM (S_IRUSR | S_IWUSR | S_IRGRP | S_IROTH)
#include <unistd.h>
#endif

#ifdef __STRICT_ANSI__
#define NEED_STR_CMP
#define NEED_STRN_CMP
#undef HAVE_STRDUP
#endif

#ifndef fix_ascii
#define fix_ascii 1  /* Translate IBM character set by default */
#endif

#ifndef BUFF_SIZE
#ifdef LOWMEM
#define BUFF_SIZE 0   /* i.e. unbuffered */
#else
#define BUFF_SIZE (32L*1024L)  /* 32K */
#endif
#endif /* BUFF_SIZE */

#ifndef MAXSTRUC
#define MAXSTRUC (1024L*1024L)
#endif

#ifndef HASHBITS
#ifdef LOWMEM
#define HASHBITS 12   /* 4K entries */
#else
#define HASHBITS 12   /* 4K entries in hash table */
#endif  
#endif /* HASHBITS */
 
#ifndef FAR
#define FAR   /* Define FAR to be blank */
#endif 

#ifndef fnamecmp   /* Used to compare filenames */
#define fnamecmp strcmp
#endif

#ifndef fnamencmp  /* Also used to compare filenames */
#define fnamencmp strncmp
#endif

/* ---------------------------------------------------------------------- */
/* FILENAME EXTENSIONS 						          */
/* These are the various filename extensions for the different data files.*/
/* ---------------------------------------------------------------------- */

/* The following are only used by the interpreter, agtout, and agt2agx */
#ifndef DA1
#define DA1 ".da1"   /* General info (text file) */
#define DA2 ".da2"   /* Rooms */
#define DA3 ".da3"   /* Items */
#define DA4 ".da4"   /* Creatures */
#define DA5 ".da5"   /* Commands, headers */
#define DA6 ".da6"   /* Commands, code (Master's Ed only) */
#define DSS ".d$$"   /* Description strings */
#define pHNT ".hnt"  /* Popup hint file; not used yet. */
#define pOPT ".opt"  /* Interface specification file */
#endif

/* The following are only used by the compiler */
#ifndef pAGT
#define pAGT ".agt"
#define pDAT ".dat"
#define pMSG ".msg"
#define pCMD ".cmd"
#define pSTD ".std"
#define AGTpSTD "agt.std"  /* Default error message file */
#endif

/* The following are used by both the interpreter and the compiler */
#ifndef pAGX
#define pAGX ".agx"  /* Extension for new Adventure Game eXecutable format */
#define pTTL ".ttl"  /* Title file */
#define pINS ".ins"  /* Instruction file */
#define pVOC ".voc"  /* Menu vocabulary file */
#define pCFG ".cfg"  /* Game configuration file */
#define pEXT "."  /* Separator between extension and base of filename */
#endif


#ifndef pSAV
#define pSAV ".sav"  /* Extension for save files */
#endif
#ifndef pSCR
#define pSCR ".scr"  /* Script file */
#endif
#ifndef pLOG
#define pLOG ".log"  /* LOG/REPLAY file */
#endif



/* ------------------------------------------------------------------- */
/* This is a preprocessor trick to ensure that space is only allocated
   for global variables once.  'global' should only be defined in one
   source file; for all of the other modules, it will be converted to
   extern by the following lines */ 
/* ------------------------------------------------------------------- */
#ifndef global    /* Don't touch this */
#define global extern
#define global_defined_agtread
#endif


/* ------------------------------------------------------------------- */
/* DEFINITIONS OF SPECIAL DATA TYPES 				       */
/* These should by platform-independent.                               */
/* ------------------------------------------------------------------- */

#ifdef force16  /* This is for debugging purposes */   
#define int short int
#endif

/* General data types */
typedef unsigned char uchar;
typedef signed char schar;
typedef short integer;  /* Should be a 16+-bit signed numeric type */
                        /* For technical reasons, it must be big enough to
			   hold a value of type word (see below) */
typedef unsigned long int32;  /* Should be a 32+-bit unsigned numeric type */
typedef unsigned long uint32;
typedef uchar bool;

#define WORD_LENG 25

/* Game-specific data type */
typedef char tline[81]; /* Both of these must include terminating null */
typedef char words[WORD_LENG]; /* ...23 in classic, 16 in master's */
typedef short word;     /* A pointer into the dictionary */
typedef short slist; /* Index into synlist marking beginning of this 
			synonym list.  [SYNCNT] 
			list of word pointers -- eg synonyms */
typedef char *descr_line; /* This is the type used to return descriptions.
			     They are actually returned as an array of
			     pointers to char, one for each line.
			     It is NULL terminated. */
typedef char *filename;  /* Datatype used for picture, sound, etc. names*/






/* ------------------------------------------------------------------- */
/* GLOBAL FLAGS                                                        */
/* Many of the following should be made into command line options      */
/* ------------------------------------------------------------------- */

/* #define AGT_16BIT */ /* Force interpreter to use 16-bit qunatities */
/* #define DUMP_VLIST  */ /* Dump out the verb list info */
/* #define USE_CMD_INDEX */  /* Read in metacommand index data for objects */


#define SS_GRAIN 1024  /* Granularity of size request for static string
			  array (to avoid calling rrealloc too often) */
#define SYN_GRAIN 32 /* Granularity of requests for synonym array; this
			   is in units of sizeof(word) */
#define MAX_BADTOK 10  /* How many bad tokens to report before giving
			  up */



/* The following are defaults that can be overridden from the command line */
/* The real variable has the name without the "def_"  */

#define def_DIAG 0   /* Print out diagnostic data? */
#define def_interp_arg 1  /* Decipher arguments to opcodes? */
#define def_debug_da1 0  /* used to analyse .DA1 files */
#define def_RAW_CMD_OUT 0  /*Print CMDs out raw, undecoded; sometimes useful
			when trying to understand new gamefile version */ 
#define def_ERR_LEVEL 2    /* Level of error reporting. */
                   /* 0== almost none */
                   /* 1== Report possibly serious conditions */
		   /* 2== Report any fall from perfection */







/* ------------------------------------------------------------------- */
/* DEFINES OF GLOBAL PARAMETERS                                        */
/* ------------------------------------------------------------------- */

#define FORMAT_CODE 0xFF  /* Character used for special formatting codes:
			     --in 1.8x games, it designates bold
			     --in AGX+ games, it will prefix format codes
			     --otherwise it designates black (replacing
			     0, which has obvious problems) */
#define LAST_TEXTCODE 8  /* Last ascii code to be used for text attributes */



#define MAX_PIX 32
#define MAX_FLAG_NOUN 32



#define OLD_VERB 59    /* Number of built in verbs in original interpreters-- 
			  this number includes ANY, which is verb 0. */
#define DIR_ADDR_CODE (OLD_VERB+17)  /* Verb ID used for direct address */
#define AUX_VERB 18    /* Additional verbs supported by the interpreter */
#define BASE_VERB (OLD_VERB+AUX_VERB)  /* Total number of built-in verbs */
#define DUMB_VERB (DVERB+MAX_SUB)  /* Number of dummy verbs and subroutines */
#define TOTAL_VERB (BASE_VERB+DUMB_VERB)  /* Total count of verbs */


#define MAX_TOKEN_ID 250   /* Upper limit on legal (raw) token values
			      read from AGT files. Doesn't need to be exact. */

/* The following numbers refer to the ideal code we are translating into,
   not the parameters for the actual data file we're reading. */
#define MAX_COND 123     /* Last condition token id */
#define START_ACT 1000  /* First action code */
#define PREWIN_ACT 1132  /* Last action code before WinGame */
#define WIN_ACT 2000    /* Value of WinGame opcode */
#define END_ACT (WIN_ACT+2)  /* Lowest command-terminating action code */
#define MAX_ACT (WIN_ACT+4)  /* Highest action code */


/* 
   None of these are used any more, but I leave them here for reference
   #define MAX_ROOM 300
   #define MAX_NOUN 300
   #define MAX_CREAT 200
   #define MAX_CMD 1500
   #define MAX_QUEST 100
   #define MAX_MSG 1000
   #define MAX_PICT 250
   #define ABS_MAX_REC_CMD 34
   #define MAX_OBJ (MAX_ROOM+MAX_NOUN+MAX_CREAT)
   #define SYNCNT 15    
*/



/* --------------------------------------------------------------------- */
/* DATA STRUCTURE DEFINITIONS                                            */
/*                                                                       */
/* All of the internal data structures used to store the contents of the */
/*   game file                                                           */
/* --------------------------------------------------------------------- */

/* First, pointers to game descriptions */
/*    start and size may be measured in units of characters or in units */
/*    of tline  */
typedef struct { 
  long start;
  long size;
} descr_ptr;


/* Entries in the opcode tables:  the name of the opcode, the number of
   arguments, and the types of those arguments */
typedef struct {
  char *opcode;
  integer argnum;
  integer arg1,arg2;
} opdef;  /* Opcode table entry */



/* This is the data type for opcode correction entries */
/*   These are used to translate the opcodes from the various versions */
/*   to a uniform internal format. */
/*   The actual translation tables built with this are in agtdata.c */
typedef struct {
  integer old,new;  /* Old and new values. */
} cmd_fix_rec;

typedef const cmd_fix_rec *fix_array;


/* ROOMS */
typedef struct {
  char *name;  /* [31] */
  int32 flag_noun_bits,PIX_bits;  /* Master's Ed. only */
  slist replacing_word;  /* List of words to be replaced */
  word replace_word;   /* Word that does replacing */
  word autoverb;     /* Verb automatically executed on entry to room */
  integer path[13];
  integer key;
  integer contents;   /* Used internally by the interpreter; not read in
			 from the game file */
  integer points;
  integer light;  /* Object that lights room; 0=none needed, 1=any */
  integer pict,initdesc;
  bool seen, locked_door;
  bool end, win, killplayer;
} room_rec;


/* NOUNS */
typedef struct {
  char *shortdesc; /* tline */
  char *position; /* 23 characters in position for classic ed, 31 for ME */
  slist syns;   /* List of synonyms */
  word name, adj;
  word related_name;  /* Word that should appear on menu when this noun
			  is in scope */
  word pos_prep, pos_name;   /* Used internally by the interpreter */
                       /* pos_prep==-1 means use noun.position */
  integer nearby_noun; /* Noun this noun is behind */
  integer num_shots;
  integer points;
  integer weight, size;
  integer key;
  integer initdesc,pict;
  integer location;    /* 1=carried, 1000=worn */
  integer contents, next;   /* Used internally by the interpreter; not read in
		     from the game file */
  bool scope;   /* Used internally by the interpreter */
  uchar sing_plur;
  bool something_pos_near_noun;  /* Anybody behind us? */
  bool has_syns;
  bool pushable, pullable, turnable, playable, readable;
  bool on, closable, open, lockable, locked, edible, wearable;
  bool drinkable, poisonous, movable, light;
  bool shootable;
  bool win;
} noun_rec;


/* CREATURES */
typedef struct {
  char *shortdesc; /* tline */
  slist syns;
  word name;
  word adj;
  integer location;
  integer contents, next;   /* Used internally by the interpreter; not read in
			       from the game file */
  integer weapon;  /* Killed by this */
  integer points;
  integer counter;  /* How many times has player been nasty to it? */
  integer threshold, timethresh, timecounter;
  integer pict,initdesc;
  bool scope; /* Used internally by the interpreter */
  bool has_syns;
  bool groupmemb;
  bool hostile;
  uchar gender;
} creat_rec;


/*  Metacommand headers and a pointer to the actual sequence of tokens
    to execute if the metacommand is run. */
typedef struct {  
  integer actor;  /* Contains the actor object number;
		       1==self(no explicit actor) 2=anybody 
		       It is multiplied by negative one for redirected
		       commands */
  word verbcmd, nouncmd, objcmd, prep;  /* prep only in ME games */
  word noun_adj, obj_adj;  /* Adjectives for noun and obj; not
			      supported in original AGT games */
  integer *data; /* MaxSizeCommand */
  integer cmdsize; /* Number of commands */
/*  integer ptr; */ /* In ME games-- see below for replacement */
} cmd_rec;


/* FRS=file record size; these are the sizes to be allocated to the buffer
   used to read in the various records from the files; they should be at
   least as big as the worst case scenario. */
#define FRS_ROOM 220
#define FRS_NOUN 310
#define FRS_CREAT 240
#define FRS_CMD 150


/* This is the record used to hold menu information for verbs */
typedef struct {  /*verb menu entry */
  word verb; /* Verb word */
  word prep; /* Associated preposition */
  short objnum; /* Number of objects */
} verbentry_rec;



/* The following data structure is used to store info on fields of a struct 
   that may need to be read from/written to a file. */
/* They are used by both the AGX and the Savefile routines */
/* They should be organized in ftype==0 terminated arrays,
   in the order they occur in the file (the file is assumed to have 
   no padding, so we don't need file offsets: they can be computed) */
/* The following is used for both global variables and fields in
   structures. For global variables, ptr is set to point at the variable
   and offset is 0. For fields, offset is set to the offset of the field
   in the structure and ptr is set internally */
typedef struct {
  int ftype; /* Type in file */
  int dtype; /* Data type of field in memory; often ignored */
  void *ptr;   /* Pointer to variable */
  size_t offset; /* Offset of field in structure */ 
} file_info;





/* ------------------------------------------------------------------- */
/* GLOBAL VARIABLES                                                    */
/* ------------------------------------------------------------------- */

/* ------------------------------------------------------------------- */
/* Flags used internally by the interpreter and reading routines */

global uchar DIAG, interp_arg, debug_da1, RAW_CMD_OUT;
global int ERR_LEVEL;

global bool agx_file;  /* Are we reading an AGX file? */
global bool have_opt;      /* Do we have an OPT file? */
global bool skip_descr; /* Causes read_filerec() to skip over description
			   pointers without actually reading them in.
			   Used to support RESTORE for multi-part games
			   such as Klaustrophobia */
global bool no_auxsyn; /* Prevents building of auxsyn and preplist 
		  synonym lists; used by agt2agx. */



/* ------------------------------------------------------------------- */
/* Flags reflecting game version and configuration */

global bool have_meta; /* Do we have any metacommands? */
global bool debug_mode, freeze_mode, milltime_mode, bold_mode;
global uchar score_mode, statusmode;
global bool intro_first;
global bool box_title;
global bool mars_fix;
global bool fix_ascii_flag;  /* Translate IBM characters? 
			       Defaults to fix_ascii #define'd above */
global bool dbg_nomsg;  /* Causes printing of <msg> arguments by
			   debug disassembler to be supressed */

global bool irun_mode;  /* If true, all messages will be in 1st person */
global bool verboseflag;


/*   The following are AGT 'purity' flags; they turn off features of */
/* my interpreter that are not fully consistent with the original AGT. */
/* They are defined in agtdata.c (see also uagt.h and agil.c for */
/* interpreter-specific flags)  */
/* Anything added here should also be correctly initialized in agt2agx */

extern bool PURE_ANSWER, PURE_TIME, PURE_ROOMTITLE;
extern bool PURE_AND, PURE_METAVERB;
extern bool PURE_SYN, PURE_NOUN, PURE_ADJ;
extern bool PURE_DUMMY, PURE_SUBNAME, PURE_PROSUB;
extern bool PURE_HOSTILE, PURE_GETHOSTILE;
extern bool PURE_DISAMBIG, PURE_ALL, PURE_OBJ_DESC;




/* ------------------------------------------------------------------- */
/*  Variables containing limits and counts of objects  */

global integer FLAG_NUM, CNT_NUM, VAR_NUM;  /* (255, 50, 50) */
global integer MAX_USTR;  /* Maximum number of user strings (25)  */
global integer MAX_SUB;   /* Number of subroutines (15) */
global integer DVERB;     /* Number of real dummy_verbs (50) */
global integer NUM_ERR;  /* For ME is 185 */

global integer maxroom, maxnoun, maxcreat;
global long MaxQuestion;
global integer first_room, first_noun, first_creat, last_obj;
global long last_message, last_cmd;
global long numglobal; /* Number of global nouns */
global long maxpict, maxpix, maxfont, maxsong;

global integer exitmsg_base; /* Number added to messages used as 
			 "illegal direction" messages */

/* ------------------------------------------------------------------- */
/*   Miscellaneous other variables read in from the game file */

global integer start_room, treas_room, ressurect_room, max_lives;
global long max_score;
global integer start_time, delta_time;

/* ver contains the size of the game, aver indicates its version */
/*  See the #define's below for details */
global int ver,aver;  /* ver: 0=unknown, 1=small, 2=big, 4=masters1.5 */
global long game_sig; /* 2-byte quantity used to identify game files */
                   /* (It's declared long to avoid overflow problems when
		      computing it) */
global int vm_size;  /* Size of verb menu */ 



/* ------------------------------------------------------------------- */
/*  Miscellaneous Game Data Structures */

/* All of the following are allocated dynamically */
global room_rec *room; /* [MAX_ROOM]; */
global creat_rec *creature; /* [MAX_CREAT]; */
global noun_rec *noun; /* [MAX_NOUN]; */
global cmd_rec *command;

global tline *userstr; /*[MAX_USTR];*/
global word FAR *sub_name;  /* [MAX_SUB] Dictionary id's of all subroutines */

/* Verb information */
global verbentry_rec *verbinfo; /* Verb information */
global short *verbptr,*verbend; /* [TOTAL_VERB] */
global slist FAR *synlist;  /* [MAX_VERBS+1];*/

global word FAR flag_noun[MAX_FLAG_NOUN],*globalnoun;
global word FAR pix_name[MAX_PIX];
global filename *pictlist,*pixlist,*fontlist,*songlist;

global uchar opt_data[14];  /* Contents of OPT file. For the format of this
			       block, see the comments to read_opt() in
			       agtread.c */

/* These are built by reinit_dict */

global slist FAR *auxsyn; /* [TOTAL_VERB]  Built-in synonym list */
global slist FAR *preplist;  /* [TOTAL_VERB] */
global uchar FAR *verbflag;  /* [TOTAL_VERB]  Verb flags; see below */





/* ------------------------------------------------------------------- */
/*  Description Pointers   */


global descr_ptr intro_ptr;
global descr_ptr title_ptr, ins_ptr; /* Only defined if agx_file is true */
global descr_ptr *err_ptr; /* [NUM_ERR];*/

global descr_ptr *msg_ptr; /* [MAX_MSG];*/
global descr_ptr *help_ptr, *room_ptr, *special_ptr; /*[ROOM] */
global descr_ptr *noun_ptr, *text_ptr, *turn_ptr, /* [NOUN] */
            *push_ptr, *pull_ptr, *play_ptr;
global descr_ptr *talk_ptr, *ask_ptr, *creat_ptr; /* [CREAT] */

global descr_ptr *quest_ptr, *ans_ptr; /* [MAX_QUEST] */
global tline *question, *answer; /* [MAX_QUEST] */



/* ------------------------------------------------------------------------ */
/* Dynamically allocated data blocks (which are pointed to from elsewhere)  */

global char **dict;  /* dict[n] points to the nth dictionary word */
global long dp;  /* Dictionary pointer: number of words in dict */

#define DICT_GRAN 1024  /* Granularity of dictstr size requests 
			   must be at least 4. */
global char *dictstr;  /* Pointer to memory block containing dict words */
global long dictstrptr, dictstrsize;
   /* dictstrptr points to the first unused byte in dictstr.
      dictstrsize points to the end of the space currently allocated for
         dictstr.
   */

global char *static_str; /*Static string space */
global long strptr; /* Pointer to end of used space in above */
global long ss_size; /* Current size of static string space */

global word *syntbl;  /* Synonym list space */
global slist synptr; /* Points to end of used space */
global long syntbl_size; /* Long so we can catch overflows */


/* ------------------------------------------------------------------------ */
/*  Data structures used internally by agtread.c   */

/*The following are all set to NULL after agtread finishes. */
global long *cmd_ptr; /* ME only;Points to cmd start locs in gamefile.*/
global long *room_name,*noun_sdesc,*noun_pos,*creat_sdesc;
global long *t_pictlist, *t_pixlist, *t_songlist, *t_fontlist;

/* These are only used by agtout (to allow the AGT reading routines to 
   pass back the count of nouns inside the given object) */
global integer *room_inside, *noun_inside, *creat_inside;
   
/* This is used to translate ASCII codes */
global uchar fixchar[256];

global bool text_file;  /* Set if we are currently opening a binary file. */
#ifdef OPEN_AS_TEXT
global bool open_as_binary;  /* Open text files as binary, anyhow. */
#endif
/* ------------------------------------------------------------------ */
/* SYMBOLIC CONSTANTS: VERSION CODES                                  */
/*   These are the values stored in the variable 'aver'.              */
/* ------------------------------------------------------------------ */

#define AGT10 1     /* SPA */
#define AGT118 2    /* TAMORET, PORK II  */
#define AGT12  3   /* SOS,... */ 
#define AGTCOS 4   /* COSMOS and SOGGY: enhanced versions of 1.3x */
#define AGT135 5   /* By far the most common version; includes practically
		      every version of Classic AGT from 1.19 to 1.7 */
#define AGT182 6 
#define AGT183A 7
#define AGT183 8
#define AGT15 9    /* HOTEL */
#define AGT15F 10  /* MDTHIEF */
#define AGT15P 11  /* PORK */
#define AGTME10 12  /* CLIFF2, ELF20  */
#define AGTME15 13    /* WOK */
#define AGTME155 14 /* TJA */
#define AGTME16 15 /* also includes v1.56 */
#define AGX00 16   /* Tenative */

#define AGTMAST AGTME16
#define AGTCLASS AGT15F  /* Dividing line between master's ed and classic */
#define AGT18 AGT182  /* Defines lowest 1.8x version */
#define AGT18MAX AGT183 /* Defines the highest 1.8x version */
#define AGTSTD AGT135  /* "Default" version of AGT */



/* ------------------------------------------------------------------ */
/* SYMBOLIC CONSTANTS: ARGUMENT TYPES                                 */
/*   These are used to encode the argument types of metacommands for  */
/*   opcode tables.                                                   */
/* ------------------------------------------------------------------ */

#define AGT_UNK 0     /* Unknown argument type */

/* The following can all mix and match in various ways and so are
   put together as powers of two. */
#define AGT_NONE 1  /* 0 is allowed */
#define AGT_SELF 2  /* 1 is allowed */
#define AGT_WORN 4  /* 1000 is allowed */
#define AGT_ROOM 8  /* A room # is allowed */
#define AGT_ITEM 16 /* An item # is allowed */
#define AGT_CREAT 32  /* A creature # is allowed */

/* AGT_VAR is special, since it is always combined with another type--
   the type that the variable is expected to be */
#define AGT_VAR 64

/* The rest of the values are always distinct; they never mix and so
   they can be given simple consecutive indices */
#define AGT_NUM 128
#define AGT_FLAG 129
#define AGT_QUEST 130   /* Question */
#define AGT_MSG 131     /* Message */
#define AGT_STR 132    /* String */
#define AGT_CNT 133  /* Counter */
#define AGT_DIR 134   /* Direction */
#define AGT_SUB 135   /* Subroutine */
#define AGT_PIC 136    /* Picture */
#define AGT_PIX 137   /* Room picture */
#define AGT_FONT 138
#define AGT_SONG 139
#define AGT_ROOMFLAG 140
#define AGT_TIME 141
#define AGT_ERR 142

/* These last two may not occur as operand types */
#define AGT_EXIT 143  /* Valid values for an exit: room, msg+msgbase, 0 */
#define AGT_GENFLAG 144 /* PIX or Room Flag; used internally by compiler */

#define AGT_DEFINE 256

/* ------------------------------------------------------------------ */
/* Verb flags for verbflag[]; these should be powers of 2 */

#define VERB_TAKEOBJ 1  
#define VERB_META 2
#define VERB_MULTI 4  /* Can the verb take mulitple objects? */
#define VERB_GLOBAL 8  /* Does the verb have global scope? */

/* ------------------------------------------------------------------ */
/* SYMBOLIC CONSTANTS: FILE DATA TYPES                                */
/*   Data type specifiers for file i/o routines                       */
/*   The FT_* constants specify file data types                       */
/*   The DT_* constants specify internal data types                   */
/* ------------------------------------------------------------------ */

#define FT_COUNT 17 /* Number of file data types */

#define FT_END 0  /* End of list of fields/variables in file */
#define FT_INT16 1   /* DT_SHORT */
#define FT_UINT16 2  /* DT_LONG */
#define FT_INT32 3   /* DT_LONG */
#define FT_UINT32 4   
#define FT_BYTE 5   /* aka uchar; DT_UCHAR */
#define FT_VERSION 6 /* Game version */
#define FT_BOOL 7   /* DT_BOOL. Adjacent booleans are packed */
#define FT_DESCPTR 8  /* DT_DESCPTR */
#define FT_STR 9  /* Integer pointer into static string array */
#define FT_SLIST 10 /* Synonym list index */
#define FT_WORD FT_INT16 /* Index into dictionary */
#define FT_PATHARRAY 11 /* 13 integers in an array of directions */
#define FT_CMDPTR 12   /* Pointer into command block */
#define FT_DICTPTR 13  /* Pointer into dictionary text */
#define FT_TLINE 14    /* TextLine */
#define FT_CHAR 15     /* Characters. */
#define FT_CFG 16      /* Configuration byte; 0=false, 1=true, 
			  2=none (don't change) */


#define DT_DEFAULT 0  /* Default internal type for <ftype> */
#define DT_LONG 1
#define DT_DESCPTR 2 /* Description pointer, which are treated specially */
#define DT_CMDPTR 3  /* Command block pointer, also treated specially */

/* This is the end marker for the file definitions used by the file I/O
   routines */
#define endrec {FT_END,0,NULL,0}





/* ------------------------------------------------------------------- */
/* FUNCTION PROTOTYPES AND INITIALIZED TABLES                          */
/* ------------------------------------------------------------------- */

/* ------------------------------------------------------------------- */
/* In AGTDATA.C                                                        */
/* This module contains the major initialized data structures and      */
/*  routines to manipulate game data structures, in particular the     */
/*  game's dictionary 						       */
/* ------------------------------------------------------------------- */

void init_dict(void); /* 1=set of verblist, 0=don't */
void build_verblist(void);  /* Creates verblist */
void reinit_dict(void);
void free_dict(void);
word search_dict(const char*);
word add_dict(const char*);

int verb_code(word);
void addsyn(word);

const opdef *get_opdef(integer op);
char *objname(int i);
void sort_cmd(void);

void agtwarn(const char*,int elev);
void agtnwarn(const char*,int,int elev);

#ifdef ZIP
#define fatal agil_fatal
#endif
void fatal(const char*);


descr_line *read_descr(long start,long size);
void free_descr(descr_line *p);
bool open_ins_file(char *fname,bool report_error);
char *read_ins_line(void); /* Reuses buffer, so return value should be copied
			  if it needs to be used past the next call to
			  read_ins_line or close_ins_file */
void close_ins_file(void);
void read_config(FILE *cfgfile, bool lastpass);

extern const char trans_ibm[];

/* Tables of opcodes */  
extern const opdef cond_def[], act_def[], end_def[], illegal_def;

global words *verblist; /* List of prexisting words, intialized by init_dict */
extern const fix_array FIX_LIST[];
extern const char *exitname[13];
extern const char *verstr[], *averstr[];
extern const char *version_str,*portstr;


/* ------------------------------------------------------------------- */
/* In AGTREAD.C                                                        */
/* Routines to read in AGT data files                                  */
/* ------------------------------------------------------------------- */

void open_descr(char*);  
void close_descr(void);
descr_line *agt_read_descr(long start,long len);
void readagt(char *gamename,bool diag);
void free_all_agtread(void); /* Cleans up everything allocated in agtread
			      should only be called at the very end of
			      the program */
descr_line *read_ttl(char *fname); /* This returns the title. The return string
				      must be freed with free_ttl() and not
				      with free_descr */
void free_ttl(descr_line *title);


/* ------------------------------------------------------------------- */
/* In AGXFILE.C                                         	       */
/*   Routines to read and write AGX files  			       */
/* ------------------------------------------------------------------- */

int read_agx(char *gamename, bool diag);
descr_line *agx_read_descr(long start,long size);
void agx_close_descr(void);

/* The following are in the order they should be called */
void agx_create(char *gamename);
void write_descr(descr_ptr *dp,descr_line *txt);
void agx_write(void);
void agx_wclose(void);
void agx_wabort(void);

/* ------------------------------------------------------------------- */
/*  In AUXFILE.C                                                       */
/*    Routines to read VOC, OPT, CFG, TTL, INS, etc. files             */
/* ------------------------------------------------------------------- */
void read_opt(char *fname);
void read_config(FILE *cfgfile, bool lastpass);
bool parse_config_line(char *s, bool lastpass);

descr_line *read_ttl(char *fname);
void free_ttl(descr_line *title);

void read_voc(char *fname);
void init_verbrec(void);
void add_verbrec(char *verbline,bool addnew); /* addnew should be 0 */
void finish_verbrec(void);


descr_line *read_ins(char *gamename);
void free_ins(descr_line *instr);
bool open_ins_file(char *fname,bool report_error);
char *read_ins_line(void);
void close_ins_file(void);

void build_fixchar(void);

/* ------------------------------------------------------------------- */
/* In or used by AGTDBG.C           				       */
/*   Routines to disassemble metacommands (used by the interpreter for */
/*   tracing and by agtout to produce the metacommand output).         */
/* ------------------------------------------------------------------- */

global bool *dbgflagptr;
global long *dbgvarptr;
global short  *dbgcntptr;

void debugout(const char *s);
int argout(int dtype, int dval, int optype);

/* ------------------------------------------------------------------- */
/* In INTERFACE.C, AGIL.C and/or AGILSTUB.C                            */
/*   agilstub.c provides minimal versions of these routines for use by */
/*   programs other than the interpreter       			       */
/* ------------------------------------------------------------------- */

void writeln(const char *s);
void writestr(const char *s);
void agil_option(int optnum,char *optstr[], bool setflag, bool lastpass);
void close_interface(void);


/* ------------------------------------------------------------------- */
/* In RMEM.C 							       */
/*   Low-level utilites, including memory allocation, string manip.,   */
/*   and buffered file I/O.					       */
/* ------------------------------------------------------------------- */

global uchar trans_ascii[256];  /* Table to translate ascii values read
				   in from file */

void build_trans_ascii(void); /* Set up the above table. */

void rprintf(const char *fmt, ...); /* General output routine, mainly used
				       for diagnostics. There can be a newline
				       at the end, but there shouldn't be
				       one in the middle of the string */



/* Memory management variables and routines */

global bool rm_trap; /* Trap memory allocation failures? */
global bool rm_acct; /* Turn on rmem accounting, to locate memory leaks */
global long rfree_cnt, ralloc_cnt; /* # of allocs/frees since acct turned on */
global long rm_size, rm_freesize; /* These hold worst case values */

long get_rm_size(void);   /* These get the current values */
long get_rm_freesize(void);
void *rmalloc(long size);
void r_free(void *p);
#define rfree(p) (r_free(p),p=NULL) /* Traps errors & catch memory leaks */
void *rrealloc(void *p,long size);
char *rstrdup(const char *s);


/* String utilities */

char *concdup(const char *s1,const char *s2); /* Concacate and duplicate */

#ifdef NEED_STR_CMP
int strcasecmp(const char *s1,const char *s2);
#endif
#ifdef NEED_STRN_CMP
int strncasecmp(const char *s1,const char *s2,size_t n);
#endif


/* The fixsign.. routines put together unsigned bytes to form signed ints */

#ifndef FAST_FIXSIGN
short fixsign16(uchar n1,uchar n2);
long fixsign32(uchar n1,uchar n2,uchar n3,uchar n4);
#else 
#define fixsign16(u1,u2) ( (u1) | ((u2)<<8) )
#define fixsign32(u1,u2,u3,u4)  ( ((long)u1) | (((long)u2)<<8) | \
				 (((long)u3)<<16) | (((long)u4)<<24) )
#endif


/* Miscellaneous */
long rangefix(long n);

/* File name manipulation routines */
char *make_fname(char *fname, char *ext);  /* Copy fname and add ext */
char *remake_fname(char *fname, char *ext); /* Realloc fname to add ext */
bool check_fname(char *fname, char *ext); /* Does fname have extension? */
char *trunc_fname(char *fname, char *ext); 
  /* Truncate extension of fname, copying if any changes are made */

/* File routines */
long file_size(FILE *f); /* Size of an open binary file */
FILE *openfile(char *fname,char *ext,char *err,bool ferr);
char *readln(FILE *f, char *buff, int n); /* Read a line from a 'text' file */

/* (None of the following routines are at all reentrant) */
long buffopen(char *fname,char *ext,int minbuffsize,char *rectype,int recnum);
       /* Open file for our buffered routines and make it our current file;
	  returns the record size. Prints out error message on failure 
	  rectype="noun","room",etc.; recnum=expected # of objects in file */
uchar *buffread(long index);
    /* seek to index*recsize, read buff_rsize bytes, return pointer to a 
       buffer with them. */
void buffclose(void); /* Close the current file */

void bw_open(char *fname, char *ext); /* Open buffered file for writing */
void bw_close(void); /* Close buffered file */
void bw_abort(void); /* Close and delete buffered file */

/* "Universal" file routines */
extern const size_t ft_leng[FT_COUNT];  /* File lengths of the data types */
long compute_recsize(file_info *recinfo);
void *read_recblock(void *base,int ftype,int numrec, long offset,
		    long blocksize);
     /* Only works for FT_BYTE, FT_SLIST, FT_WORD, FT_DICTTEXT, FT_INT16 */
void *read_recarray(void *base, int eltsize, int numelts,
		   file_info *field_info, char *rectype,
		   long file_offset,long file_blocksize);
void read_globalrec(file_info *global_info, char *rectype,
		    long file_offset, long file_blocksize);

long write_recarray(void *base, int eltsize, int numelts, 
		    file_info *field_info, long file_offset);
long write_globalrec(file_info *global_info, long file_offset);
long write_recblock(void *base,int ftype,int numrec, long offset);

void set_internal_buffer(void *p);
/* Causes all of the above routines to write to the block of memory pointed 
   at by p instead of to a file */

#ifdef PROFILE_SUPPORT
/* These are functions to do quick-and-dirty timing of routines;
   I added them to check the performance of the AGX code. 
   They aren't likely to work on anything other than a *nix box */
void resetwatch(void);
void startwatch(void);
char *stopwatch(void);
char *timestring(void);
#define runwatch(cmd) do{resetwatch();cmd;printf("%s\n",stopwatch());}while(0)
#else
#define runwatch(cmd) cmd
#endif


#ifdef global_defined_agtread
#undef global
#undef global_defined_agtread
#endif

