#include "wand_head.h"

#if	MSDOS | AMIGA	/* M001	*/
#define	LOCK
#define	UNLOCK
#else
#define LOCK while((lock = creat(LOCKPATH,0)) < 0)
#define UNLOCK (void) unlink(LOCKPATH)
#endif

#define ENTRIES 15

#if	MSDOS | AMIGA	/* M001 */
#define	 getuid()	0
#else
extern int getuid();
#endif

extern int saved_game;  /* prevent recording of hiscore if  */
			/* NO_RESTORED_GAME_HISCORES is #def'd */

typedef struct
    {
    char howdead[25];
    char name[20];
    int  score;
    int  level;
    int  uid;
    } score_entry;

#ifdef	LINT_ARGS	/* M001	*/
void show_scores(score_entry *,int );
int readtable(score_entry *);
#else
void show_scores();
int readtable();
#endif

void show_scores(table,num)
score_entry *table;
int         num;
{
int tot = num;

/* only show the top ten */
if (num > 10) num = tot = 10;

addstr("\nNo. Score Level           Names                 How they died\n");
addstr("=============================================================================\n");
while(num > 0)
    {
    char buffer[80];
    num--;
    sprintf(buffer,"%2d %5d %3d      %-20s     killed by %-s\n",(tot - num),table->score,table->level,table->name,table->howdead);
    addstr(buffer);
    table++;
    }
addstr("\n");
}

int readtable(table_ptr)
score_entry *table_ptr;
{
FILE *fp;
int  numread;
if((fp = fopen(HISCOREPATH,R_BIN)) == NULL)
    {
    numread = 0;
    }
else
    {
    numread = fread( VOIDSTAR table_ptr, sizeof(score_entry), ENTRIES, fp);
    fclose(fp);
    }
return numread;
}

int  savescore(howdead,score,level,name)
char *howdead, *name;
int  score,level;
{
score_entry table[ENTRIES + 2],
	    *table_ptr = table,new_entry,temp_entry;
int  numread,index = 1, numsaved, lock, already = 0, output_value = 1,
     user_id;
FILE *fp;
#ifdef NO_RESTORED_GAME_HISCORES
if(saved_game) {
	addstr("No hiscores recorded from restored games.\n");
        addstr("\nWanderer (C) 1988  S.Shipway.\n\n");
	return 1;
}
#endif
user_id = getuid();
strncpy(new_entry.howdead,howdead,25);
new_entry.howdead[24] = '\0';	/* M002 strncpy does not null terminate */
strncpy(new_entry.name,name,20);
new_entry.name[19] = '\0';	/* M002 strncpy does not null terminate */
new_entry.score = score;
new_entry.level = level;
new_entry.uid = user_id;
LOCK;
numread = readtable(table_ptr);
if (numread > 0)
    if(table[numread-1].score > 99999)     /* stop system errors messing it up*/
        {
        numread--;
        addstr("Erasing spurious entry in table.\n");
        }
if(score == 0)
    {
    show_scores(table,numread);
    UNLOCK;
    return 0;
    }
if (numread > 0)
    {
    numread++; /* scan through until correct insertion point */
    /* pass table entries with higher scores */
    while((table_ptr->score > score)&&(index < numread))
	{
#ifdef	COMPARE_BY_NAME
#define	SAMEUSER(p)	(strcmp((p)->name, name) == 0)
#else
#define	SAMEUSER(p)	((p)->uid == user_id)
#endif
	if(SAMEUSER(table_ptr))
	    {
	    already = 1;
	    break;
	    }
	table_ptr++;
	index++;
	}
    /* pass table entries with equal score but higher or equal level */
    while((table_ptr->level>=level)&&(index<numread)&&(table_ptr->score==score))
	{
	if(SAMEUSER(table_ptr))
	    {
	    already = 1;
	    break;
	    }
	table_ptr++;
	index++;
	}
    /* if already found: done */
    if(already == 1)
	{
	numread--;
	show_scores(table,numread);
	UNLOCK;
	return numread;
	}
    /* shift down score list */
    while(index < numread)
	{
	/* swap *table_ptr and new_entry */
	temp_entry = *table_ptr;
	*table_ptr = new_entry;
	new_entry = temp_entry;
	if(SAMEUSER(&new_entry))
	    {
	    already = 1;
	    numread--; /* an older entry found */
	    break;
	    }
	table_ptr++;
	index++;
	}
    /* if all shifted without finding an older entry */
    if(already==0)
	*table_ptr = new_entry;
    }
else
    {
    addstr("\nCreating new hiscore table.\n\n");
    *table_ptr = new_entry;
    numread++;
    }
numread = ( (numread > ENTRIES) ? ENTRIES : numread );
if ((fp = fopen(HISCOREPATH,W_BIN)) == NULL)
    {
    UNLOCK;
    return 0;
    }
table_ptr = table;
numsaved = fwrite( VOIDSTAR table_ptr, sizeof(score_entry), numread, fp);
chmod(HISCOREPATH,0666);
if(numsaved < numread)
    {
    output_value = 0;
    }
fclose(fp);
UNLOCK;
show_scores(table,numsaved);
return output_value;
}

void delete_entry(num)
int num;
{
score_entry table[ENTRIES + 22],
	    *table_ptr = table;
int  numread,index = 1, numsaved, lock, output_value = 1;
FILE *fp;
LOCK;
numread = readtable(table_ptr);
if (numread == 0) {
    addstr("Missing or unreadable hiscore table.\n\n");
    UNLOCK;
    exit(1);
}
if (num > numread) {
    addstr("Invalid entry, choose again\n");
    UNLOCK;
    return;
}
while(index < num)
    {
    index++;
    table_ptr++;
    }
while(index < numread)
    {
    index++;
    *table_ptr = *(table_ptr+1);
    table_ptr++;
    }
numread--;
fp = fopen(HISCOREPATH,W_BIN);
table_ptr = table;
numsaved = fwrite( VOIDSTAR table_ptr, sizeof(score_entry), numread, fp);
chmod(HISCOREPATH,0666);
if(numsaved < numread)
    {
    output_value = 0;
    }
fclose(fp);
UNLOCK;
show_scores(table,numsaved);
}

erase_scores()
{
int erasenum,numread,index = 0;
char correct[20],c,buffer[20];
score_entry table[ENTRIES + 2],
	    *table_ptr = table;
addstr("Please enter password:");
while((c = getchar()) != '\n' && index <19) {
    correct[index++] = c;
    }
correct[index] = 0;
if(strcmp(correct,MASTERPASSWORD))
    {
    addstr("\nFoo, charlatan!\n");
    return 0;
    }
numread = readtable(table_ptr);
show_scores(table,numread);
addstr("\n");
for(;;)
{
addstr("Number to erase (0 to exit): ");
gets(buffer);
erasenum = atoi(buffer);
addstr("\n");
if(erasenum == 0)
    break;
delete_entry(erasenum);
addstr("\n");
}
addstr("Byee!\n");
}
