/* $Log:	sysdefaults.c,v $
 * Revision 1.3  92/03/19  21:34:34  terence
 * Added UDP mods (version 0.2, 3/17/92)
 * 
 * Revision 1.2  92/03/11  15:56:51  terence
 * added UDP mods
 *  */

/* sysdefaults.c
 * 
 * This code is pretty hacked up, but it works fine.
 */
#include <stdio.h>
#include <math.h>
#include <sys/types.h>
#include <sys/stat.h>
#include "defs.h"
#include INC_STRINGS
#include "struct.h"
#include "data.h"
#include "copyright2.h"

static struct stat oldstat;

void shipdefs();

readsysdefaults()
{
    int i,j;
    FILE *f;
    char buf[200];
    char *s;

    /* Setup defaults. */
    for (i=0; i<MAXPLANETS; i++) {
	startplanets[i]=0;
    }
    startplanets[0]=startplanets[10]=startplanets[20]=startplanets[30]=1;
    for (i=0; i<NUM_TYPES; i++) {
	shipsallowed[i]=1;
    }
    for (i=0; i<WP_MAX; i++) {
	weaponsallowed[i]=1;
    }
/* Clear ship type sent field, in case the .sysdef change changed ship defs */
    for (i=0;i<NUM_TYPES;i++) {
	sent_ship[i] = 0;
    }

    testtime= -1;
    topgun=0; /* added 12/9/90 TC */
    newturn=0; /* added 1/20/91 TC */
    hiddenenemy=1;
    binconfirm=0;
    plkills=2;
    sbrank=3;
    chaosmode=0;
    tournplayers=5;
    udpAllowed=1;		/* UDP */
    top_armies = 30;            /* added 11/27/93 ATH */
    planet_move = 0;		/* added 9/28/92 NBT */
    wrap_galaxy = 0;		/* added 6/28/95 JRP */
    pingpong_plasma = 0;	/* added 7/6/95 JRP */
#ifdef MINES
    mines = 0;			/* added 8/3/95 JRP */
#endif
#ifdef SB_TRANSWARP
    twarpMode = 0;
    twarpSpeed = 60;
#endif
    start_robot = NO_ROBOT;
    strcpy(Motd,N_MOTD);

    getshipdefaults();

    f=fopen(SysDef_File, "r");
    if (f==NULL) {
	ERROR(1,("No system defaults file!\n"));
        return;
    }
    stat(SysDef_File, &oldstat);

    while (fgets(buf, 199, f)!=NULL) {
	if (buf[0] == '#') continue; /* a comment */
	s=INDEX(buf, '=');
	if (s==NULL) continue;
	*s='\0';
	s++;
	
	if (strcmp(buf,"CLUE")==0) {		/* NBT added */
	    clue = atoi(s);
	}
        else if (strcmp(buf,"CLUERANK")==0) {
            cluerank = atoi(s);
        }
	else if (strcmp(buf, "HUNTERKILLER")==0) {	/* NBT added */
	    killer = atoi(s);
	}
	else if (strcmp(buf, "RESETGALAXY")==0) {
	    resetgalaxy = atoi(s);
	}
#ifdef CHECKMESG
	else if (strcmp(buf, "CHECKMESG")==0) {		/* NBT added */
	    checkmessage = atoi(s);
	}
	else if (strcmp(buf, "LOGALL")==0) {		/* NBT added */
	    logall = atoi(s);
	}
	else if (strcmp(buf, "LOGGOD")==0) {		/* NBT added */
	    loggod = atoi(s);
	}
      else if (strcmp(buf, "EVENTLOG")==0) {          /* 007 added */
          eventlog = atoi(s);
      }
#endif
	else if (strcmp(buf, "DOOSHER")==0) {		/* NBT added */
	    doosher = atoi(s);
	}
	else if (strcmp(buf, "CHECKSCUM")==0) {		/* NBT added */
	    check_scum = atoi(s);
	}
	else if (strcmp(buf, "WHYMESS")==0) {		/* NBT added */
#ifdef CHAIN_REACTION
	    whymess = atoi(s);
#endif
	}
	else if (strcmp(buf,"MAX_POP")==0) {
	    max_pop = atoi(s);
	}
	else if (strcmp(buf,"SHOWSYSDEF")==0) {
	    show_sysdef = atoi(s);
	}
	else if (strcmp(buf, "PLANET_MOVE")==0) {
	    planet_move=atoi(s);
        }
        else if (strcmp(buf, "WRAP_GALAXY")==0) {
       	    wrap_galaxy=atoi(s);
	}
#ifdef MINES
        else if (strcmp(buf, "STARBASE_MINES")==0) {
       	    mines=atoi(s);
	}
#endif
	else if (strcmp(buf, "PINGPONG_PLASMA")==0) {
	    pingpong_plasma=atoi(s);
	}
	else if (strcmp(buf, "MAX_CHAOS_BASES")==0) {
	    max_chaos_bases=atoi(s);
	}
	else if (strcmp(buf, "TOURN")==0) {
	    tournplayers=atoi(s);
	    if (tournplayers==0) tournplayers=5;
	} 
	else if (strcmp(buf, "SHIPS")==0) {
	    for (i=0; i<NUM_TYPES; i++) {
		shipsallowed[i]=0;
	    }
	    readstrings("SHIPS", s, shiptypes, shipsallowed, NUM_TYPES);
	} 
	else if (strcmp(buf, "WEAPONS")==0) {
	    for (i=0; i<WP_MAX; i++) {
		weaponsallowed[i]=0;
	    }
	    readstrings("WEAPONS", s, weapontypes, weaponsallowed, WP_MAX);
	} 
	else if (strcmp(buf, "PLKILLS")==0) {
	    plkills=atoi(s);
	} 
	else if (strcmp(buf, "SBRANK")==0) {
	    sbrank=atoi(s);
	} 
	else if (strcmp(buf, "CHAOS")==0) {
	    chaosmode=atoi(s);
	} 
#ifdef SNAKEPATROL
	else if (strcmp(buf, "SNAKEPATROL")==0) {
	    snakepatrol=atoi(s);
	}
#endif
	else if (strncmp(buf, "NODIAG", 6)==0) {
            nodiag=atoi(s);
	} 
	else if (strcmp(buf, "TOPGUN")==0) { /* change 12/9/90 TC */
	    topgun=atoi(s);
	} 
	else if (strcmp(buf, "NEWTURN")==0) { /* change 1/20/91 TC */
	    newturn=atoi(s);
	} 
	else if (strcmp(buf, "HIDDEN")==0) {
	    hiddenenemy=atoi(s);
	} 
	else if (strcmp(buf, "LOADCHECK")==0) {
	    loadcheck=atoi(s);
	} 
	else if (strcmp(buf, "MAXLOAD")==0) {
	    maxload=atoi(s);
	} 
	else if (strcmp(buf, "PLANETS")==0) {
	    for (i=0; i<MAXPLANETS; i++) {
		startplanets[i]=0;
	    }
	    readstrings("PLANETS", s, planettypes, startplanets, MAXPLANETS);
	} 
	else if (strcmp(buf, "CONFIRM")==0) {
	    binconfirm=atoi(s);
	} 
	else if (strcmp(buf, "UDP")==0) {             /* UDP */
	    udpAllowed=atoi(s);
        } 
	else if (strcmp(buf, "SURRSTART")==0) {
	    surrenderStart=atoi(s);
	}
	else if (strcmp(buf, "PING_FREQ")==0) {
#ifdef PING
            ping_freq = atoi(s);
            if(ping_freq <= 0) ping_freq = 1;
#endif /*PING*/
        } 
	else if (strcmp(buf, "PING_ILOSS_INTERVAL")==0) {
#ifdef PING
            ping_iloss_interval = atoi(s);
            if(ping_iloss_interval <= 0)
               ping_iloss_interval = 1;
#endif /*PING*/
        } 
	else if (strcmp(buf, "PING_GHOSTBUST")==0) {
#ifdef PING
            ping_allow_ghostbust = atoi(s);
#endif /*PING*/
        } 
	else if (strcmp(buf, "PING_GHOSTBUST_INTERVAL")==0) {
#ifdef PING
            ping_ghostbust_interval = atoi(s);
            if(ping_ghostbust_interval <= 0)
               ping_ghostbust_interval = 1;
#endif /*PING*/
	} 
	else if (strcmp(buf, "TRANSWARP")==0) {
#ifdef SB_TRANSWARP
	    twarpMode = atoi(s);
#endif /*SB_TRANSWARP*/
	} 
	else if (strcmp(buf, "WARPSPEED")==0) {
#ifdef SB_TRANSWARP
	    twarpSpeed = atoi(s);
#endif /*SB_TRANSWARP*/
	}
	else if (strcmp(buf, "VECTOR")==0) {
	    vectortorps = atoi(s);
	}
	else if (strcmp(buf, "START_ARMIES")==0) {
	    top_armies = atoi(s);
	}
	else if (strcmp(buf, "ERROR_LEVEL")==0) {
	    errorlevel = atoi(s);
	}
/* Added 1/9/94 by Steve Sheldon - Load shipvals from .sysdef */
	else if (strcmp (buf, "SHIP") == 0) { /* if ship being entered */
	        shipdefs (atoi(s),f);
	}
	else if (strcmp(buf, "BASEPRACTICE")==0) {
#ifdef BASEPRACTICE
	    if (atoi(s)) { 
		binconfirm=0;      /* allow robots to join */
		sbrank=0;          /* no SB restriction */
		check_scum=0;
		start_robot=BASEP_ROBOT;
	    }
#endif
	}
        else if (strcmp(buf, "ROBOTHOST")==0) {
#ifdef BASEPRACTICE
            sscanf(s,"%s",robot_host);
#endif
	}
	else if (strcmp(buf, "HOCKEY")==0) {
	     if (atoi(s)) start_robot=PUCK_ROBOT;
	}
	else if (strcmp(buf, "INL")==0) {
	     if (atoi(s)) {
		start_robot=INL_ROBOT;
	     }
	}
/* 
  These are used by Mars for a dogfight server.
  They should not be used in any other part of the server. jn
*/
	else if (strcmp(buf, "DOGFIGHT") == 0) {
#ifdef DOGFIGHT
	     if (atoi(s)) start_robot=MARS_ROBOT;
#endif
	}
	else if (strcmp(buf, "CONTESTSIZE") == 0) {
#ifdef DOGFIGHT
	    contestsize=atoi(s);
#endif /* DOGFIGHT */
	} 
	else if (strcmp(buf, "NUMMATCH") == 0) {
#ifdef DOGFIGHT
	    nummatch=atoi(s);
#endif /* DOGFIGHT */
	} 
	else if (strcmp(buf, "SAVE_DOG_STAT") == 0) {
#ifdef DOGFIGHT
	    dogcounts=atoi(s);
#endif /* DOGFIGHT */
	} 
	else if (strcmp(buf, "MOTD") == 0) {
	    sscanf(s,"%s",Motd);
	}
	else {
	    ERROR(2,("System default %s unknown\n", buf));
	}
    }
    /* Make sure every team can start at some planet! */
    for (i=0; i<4; i++) { 
	for (j=0; j<10; j++) {
	    if (startplanets[i*10+j]) goto foundone;
	}
	ERROR(1,("No starting planets specified for team %d\n", i));
	startplanets[i*10]=1;
foundone: ;
    }

    fclose(f);
}

readstrings(type, string, keys, array, max)
char *type;
char *string;
char **keys;
int *array;
int max;
{
    int i;

    while (*string!='\0') { 
	while (*string=='\n' || *string==' ' || *string==',' || *string=='\t') string++;
	if (*string=='\0') break;
	for (i=0; i<max; i++) {
	    if (strncmp(keys[i], string, strlen(keys[i]))==0) {
		string+=strlen(keys[i]);
		array[i]=1;
		break;
	    }
	}
	if (i==max) {
	    ERROR(1,("%s type %s unknown!\n", type, string));
	    string++;
	}
    }
}

/* This function will update all of the defaults if the default file 
 * changed.  It is called often, and assuming the OS caches the file
 * inode info well, this isn't a problem.
 */
int
update_sys_defaults()
{
    struct stat newstat;

    if (stat(SysDef_File, &newstat)==0) {
	if (newstat.st_ino != oldstat.st_ino ||
	    newstat.st_mtime != oldstat.st_mtime) {
	    readsysdefaults();
	    return(1);
	}
    }
    return(0);
}


/*------------------------------------------------------------------------

 Stolen direct from the Paradise 2.2.6 server code 
 This code is used to load shipvals from the .sysdef

 Added 1/9/94 by Steve Sheldon
-------------------------------------------------------------------------*/

/*--------------------------------SHIPDEFS---------------------------------*/
/*    This function gets all of the field values for a ship.  Each line of
input for the ship fields has a single ship field on it.    The name of the
ship field is followed by the value to place in that field.    The function
stops when it encounters a line with "end" on it.     It places the values
into the shipvals so that the next time getship is called, the new values
will be used.    */

void shipdefs (set,f)
    int set;
    FILE *f;					/* file to load from */
{
    struct ship *currship = NULL;
    char buf[256];				/* to get a string from file */
    char field_name[64];			/* to get name of field */
    char value[256];				/* to get name */
    char sdesig[64];				/* to get ship letters */
    int len;					/* hold len of read in string */
    int i;					/* looping var */
    int offset;					/* offset into ship structure */

    while (1) {					/* loop until break */
	if (0 == fgets (buf, sizeof (buf), f))	/* get a string of input */
	    return;				/* if end of file then break */
	if (buf[0]=='!' || buf[0]=='#')
	    continue;				/* skip line with ! or # */
	len = strlen (buf);
	if (buf[len - 1] == '\n') 		/* blast trailing newline */
	    buf[--len] = 0;
	if (strncmp (buf, "END", 3) == 0) {	/* if end of ship then break */
	    return;
	}
	if (shipvals == 0)
	    continue;

	/* get field name and value */
	sscanf (buf, "%s %s %s", sdesig, field_name, value);

	if (!set) continue;

	for (i = 0; i < NUM_TYPES; i++) {
	    if (strcasecmp(sdesig,shiptypes[i])==0) 
		currship = shipvals + i;	
	}
	if (!currship) {
		ERROR(1,("Unknown ship type (%s)\n",sdesig));
		return;
	}

	for (i = 0; ship_fields[i].name; i++) {	/* loop through field names */
	    if (strcasecmp (field_name, ship_fields[i].name) == 0) /* found field?*/
	    break;
	}
	if (ship_fields[i].name == 0) {		/* if we did not find name */
	    fprintf (stderr, "invalid field name in ship %s description `%s'(5d)\n",
	           sdesig,field_name,i);
	    continue;				/* print error, get next */
	}

	offset = ship_fields[i].offset;		/* get offset into struct */
	switch (ship_fields[i].type) {		/* parse the right type */
	case FT_CHAR:
	    sscanf (value, "%c", offset + (char *) currship);
	    break;
	case FT_SHORT:
	    sscanf (value, "%hi", offset + (char *) currship);
	    break;
	case FT_INT:
	    sscanf (value, "%i", offset + (char *) currship);
	    break;
	case FT_LONG:
	    sscanf (value, "%li", offset + (char *) currship);
	    break;
	case FT_FLOAT:
	    sscanf (value, "%f", offset + (char *) currship);
	    break;
	case FT_STRING:
	    sscanf (value, "%s", offset + (char *) currship);
	    break;
	default:
	    fprintf (stderr, "Internal error, unknown field type %d\n",
	           ship_fields[i].type);
	}
    }
  }
