Home | History | Annotate | Line # | Download | only in larn
scores.c revision 1.6
      1  1.3  mycroft #ifndef lint
      2  1.6      mrg static char rcsid[] = "$NetBSD: scores.c,v 1.6 1996/05/22 00:36:14 mrg Exp $";
      3  1.3  mycroft #endif /* not lint */
      4  1.3  mycroft 
      5  1.1      cgd /* scores.c			 Larn is copyrighted 1986 by Noah Morgan.
      6  1.1      cgd  *
      7  1.1      cgd  *	Functions in this file are:
      8  1.1      cgd  *
      9  1.1      cgd  *	readboard() 	Function to read in the scoreboard into a static buffer
     10  1.1      cgd  *	writeboard()	Function to write the scoreboard from readboard()'s buffer
     11  1.1      cgd  *	makeboard() 	Function to create a new scoreboard (wipe out old one)
     12  1.1      cgd  *	hashewon()	 Function to return 1 if player has won a game before, else 0
     13  1.1      cgd  *	long paytaxes(x)	 Function to pay taxes if any are due
     14  1.1      cgd  *	winshou()		Subroutine to print out the winning scoreboard
     15  1.1      cgd  *	shou(x)			Subroutine to print out the non-winners scoreboard
     16  1.1      cgd  *	showscores()		Function to show the scoreboard on the terminal
     17  1.1      cgd  *	showallscores()	Function to show scores and the iven lists that go with them
     18  1.1      cgd  *	sortboard()		Function to sort the scoreboard
     19  1.1      cgd  *	newscore(score, whoo, whyded, winner) 	Function to add entry to scoreboard
     20  1.1      cgd  *	new1sub(score,i,whoo,taxes) 		  Subroutine to put player into a
     21  1.1      cgd  *	new2sub(score,i,whoo,whyded)	 	  Subroutine to put player into a
     22  1.1      cgd  *	died(x) 	Subroutine to record who played larn, and what the score was
     23  1.1      cgd  *	diedsub(x) Subroutine to print out a line showing player when he is killed
     24  1.1      cgd  *	diedlog() 	Subroutine to read a log file and print it out in ascii format
     25  1.1      cgd  *	getplid(name)		Function to get players id # from id file
     26  1.1      cgd  *
     27  1.1      cgd  */
     28  1.1      cgd #include <sys/types.h>
     29  1.1      cgd #include <sys/times.h>
     30  1.1      cgd #include <sys/stat.h>
     31  1.1      cgd #include "header.h"
     32  1.5      cgd #include <string.h>
     33  1.1      cgd 
     34  1.1      cgd struct scofmt			/*	This is the structure for the scoreboard 		*/
     35  1.1      cgd 	{
     36  1.1      cgd 	long score;			/* the score of the player 							*/
     37  1.1      cgd 	long suid;			/* the user id number of the player 				*/
     38  1.1      cgd 	short what;			/* the number of the monster that killed player 	*/
     39  1.1      cgd 	short level;		/* the level player was on when he died 			*/
     40  1.1      cgd 	short hardlev;		/* the level of difficulty player played at 		*/
     41  1.1      cgd 	short order;		/* the relative ordering place of this entry 		*/
     42  1.1      cgd 	char who[40];		/* the name of the character 						*/
     43  1.1      cgd 	char sciv[26][2];	/* this is the inventory list of the character 		*/
     44  1.1      cgd 	};
     45  1.1      cgd struct wscofmt			/* This is the structure for the winning scoreboard */
     46  1.1      cgd 	{
     47  1.1      cgd 	long score;			/* the score of the player 							*/
     48  1.1      cgd 	long timeused;		/* the time used in mobuls to win the game 			*/
     49  1.1      cgd 	long taxes;			/* taxes he owes to LRS 							*/
     50  1.1      cgd 	long suid;			/* the user id number of the player 				*/
     51  1.1      cgd 	short hardlev;		/* the level of difficulty player played at 		*/
     52  1.1      cgd 	short order;		/* the relative ordering place of this entry 		*/
     53  1.1      cgd 	char who[40];		/* the name of the character 						*/
     54  1.1      cgd 	};
     55  1.1      cgd 
     56  1.1      cgd struct log_fmt			/* 102 bytes struct for the log file 				*/
     57  1.1      cgd 	{
     58  1.1      cgd 	long score;			/* the players score 								*/
     59  1.5      cgd 	time_t diedtime;	/* time when game was over 							*/
     60  1.1      cgd 	short cavelev;		/* level in caves 									*/
     61  1.1      cgd 	short diff;			/* difficulty player played at 						*/
     62  1.1      cgd #ifdef EXTRA
     63  1.1      cgd 	long elapsedtime;	/* real time of game in seconds 					*/
     64  1.1      cgd 	long bytout;		/* bytes input and output 							*/
     65  1.1      cgd 	long bytin;
     66  1.1      cgd 	long moves;			/* number of moves made by player 					*/
     67  1.1      cgd 	short ac;			/* armor class of player 							*/
     68  1.1      cgd 	short hp,hpmax;		/* players hitpoints 								*/
     69  1.1      cgd 	short cputime;		/* cpu time needed in seconds 						*/
     70  1.1      cgd 	short killed,spused;/* monsters killed and spells cast 					*/
     71  1.1      cgd 	short usage;		/* usage of the cpu in % 							*/
     72  1.1      cgd 	short lev;			/* player level 									*/
     73  1.1      cgd #endif
     74  1.1      cgd 	char who[12];		/* player name 										*/
     75  1.1      cgd 	char what[46];		/* what happened to player 							*/
     76  1.1      cgd 	};
     77  1.1      cgd 
     78  1.1      cgd static struct scofmt sco[SCORESIZE];	/* the structure for the scoreboard  */
     79  1.1      cgd static struct wscofmt winr[SCORESIZE];	/* struct for the winning scoreboard */
     80  1.1      cgd static struct log_fmt logg;				/* structure for the log file 		 */
     81  1.1      cgd static char *whydead[] = {
     82  1.1      cgd 	"quit", "suspended", "self - annihilated", "shot by an arrow",
     83  1.1      cgd 	"hit by a dart", "fell into a pit", "fell into a bottomless pit",
     84  1.1      cgd 	"a winner", "trapped in solid rock", "killed by a missing save file",
     85  1.1      cgd 	"killed by an old save file", "caught by the greedy cheater checker trap",
     86  1.1      cgd 	"killed by a protected save file","killed his family and committed suicide",
     87  1.1      cgd 	"erased by a wayward finger", "fell through a bottomless trap door",
     88  1.1      cgd 	"fell through a trap door", "drank some poisonous water",
     89  1.1      cgd 	"fried by an electric shock", "slipped on a volcano shaft",
     90  1.1      cgd 	"killed by a stupid act of frustration", "attacked by a revolting demon",
     91  1.1      cgd 	"hit by his own magic", "demolished by an unseen attacker",
     92  1.1      cgd 	"fell into the dreadful sleep", "killed by an exploding chest",
     93  1.1      cgd /*26*/	"killed by a missing maze data file", "annihilated in a sphere",
     94  1.1      cgd 	"died a post mortem death","wasted by a malloc() failure"
     95  1.1      cgd 	};
     96  1.1      cgd 
     97  1.1      cgd /*
     98  1.1      cgd  *	readboard() 	Function to read in the scoreboard into a static buffer
     99  1.1      cgd  *
    100  1.1      cgd  *	returns -1 if unable to read in the scoreboard, returns 0 if all is OK
    101  1.1      cgd  */
    102  1.1      cgd readboard()
    103  1.1      cgd 	{
    104  1.6      mrg 	int i;
    105  1.6      mrg 
    106  1.6      mrg 	seteuid(euid);
    107  1.6      mrg 	i = lopen(scorefile);
    108  1.6      mrg 	seteuid(uid);
    109  1.6      mrg 	if (i<0)
    110  1.1      cgd 	  { lprcat("Can't read scoreboard\n"); lflush(); return(-1); }
    111  1.1      cgd 	lrfill((char*)sco,sizeof(sco));		lrfill((char*)winr,sizeof(winr));
    112  1.1      cgd 	lrclose();  lcreat((char*)0);  return(0);
    113  1.1      cgd 	}
    114  1.1      cgd 
    115  1.1      cgd /*
    116  1.1      cgd  *	writeboard()	Function to write the scoreboard from readboard()'s buffer
    117  1.1      cgd  *
    118  1.1      cgd  *	returns -1 if unable to write the scoreboard, returns 0 if all is OK
    119  1.1      cgd  */
    120  1.1      cgd writeboard()
    121  1.1      cgd 	{
    122  1.6      mrg 	int i;
    123  1.6      mrg 
    124  1.1      cgd 	set_score_output();
    125  1.6      mrg 	seteuid(euid);
    126  1.6      mrg 	i = lcreat(scorefile);
    127  1.6      mrg 	seteuid(uid);
    128  1.6      mrg 	if (i<0)
    129  1.1      cgd 	  { lprcat("Can't write scoreboard\n"); lflush(); return(-1); }
    130  1.1      cgd 	lwrite((char*)sco,sizeof(sco));		lwrite((char*)winr,sizeof(winr));
    131  1.1      cgd 	lwclose();  lcreat((char*)0);  return(0);
    132  1.1      cgd 	}
    133  1.1      cgd 
    134  1.1      cgd /*
    135  1.1      cgd  *	makeboard() 		Function to create a new scoreboard (wipe out old one)
    136  1.1      cgd  *
    137  1.1      cgd  *	returns -1 if unable to write the scoreboard, returns 0 if all is OK
    138  1.1      cgd  */
    139  1.1      cgd makeboard()
    140  1.1      cgd 	{
    141  1.1      cgd 	register int i;
    142  1.1      cgd 	for (i=0; i<SCORESIZE; i++)
    143  1.1      cgd 		{
    144  1.1      cgd 		winr[i].taxes = winr[i].score = sco[i].score = 0;
    145  1.1      cgd 		winr[i].order = sco[i].order = i;
    146  1.1      cgd 		}
    147  1.1      cgd 	if (writeboard()) return(-1);
    148  1.6      mrg 	seteuid(euid);
    149  1.1      cgd 	chmod(scorefile,0660);
    150  1.6      mrg 	seteuid(uid);
    151  1.1      cgd 	return(0);
    152  1.1      cgd 	}
    153  1.1      cgd 
    154  1.1      cgd /*
    155  1.1      cgd  *	hashewon()	 Function to return 1 if player has won a game before, else 0
    156  1.1      cgd  *
    157  1.1      cgd  *	This function also sets c[HARDGAME] to appropriate value -- 0 if not a
    158  1.1      cgd  *	winner, otherwise the next level of difficulty listed in the winners
    159  1.1      cgd  *	scoreboard.  This function also sets outstanding_taxes to the value in
    160  1.1      cgd  *	the winners scoreboard.
    161  1.1      cgd  */
    162  1.1      cgd hashewon()
    163  1.1      cgd 	{
    164  1.1      cgd 	register int i;
    165  1.1      cgd 	c[HARDGAME] = 0;
    166  1.1      cgd 	if (readboard() < 0) return(0);	/* can't find scoreboard */
    167  1.1      cgd 	for (i=0; i<SCORESIZE; i++)	/* search through winners scoreboard */
    168  1.1      cgd 	   if (winr[i].suid == userid)
    169  1.1      cgd 		  if (winr[i].score > 0)
    170  1.1      cgd 			{
    171  1.1      cgd 			c[HARDGAME]=winr[i].hardlev+1;  outstanding_taxes=winr[i].taxes;
    172  1.1      cgd 			return(1);
    173  1.1      cgd 			}
    174  1.1      cgd 	return(0);
    175  1.1      cgd 	}
    176  1.1      cgd 
    177  1.1      cgd /*
    178  1.1      cgd  *	long paytaxes(x)		 Function to pay taxes if any are due
    179  1.1      cgd  *
    180  1.1      cgd  *	Enter with the amount (in gp) to pay on the taxes.
    181  1.1      cgd  *	Returns amount actually paid.
    182  1.1      cgd  */
    183  1.1      cgd long paytaxes(x)
    184  1.1      cgd 	long x;
    185  1.1      cgd 	{
    186  1.1      cgd 	register int i;
    187  1.1      cgd 	register long amt;
    188  1.1      cgd 	if (x<0) return(0L);
    189  1.1      cgd 	if (readboard()<0) return(0L);
    190  1.1      cgd 	for (i=0; i<SCORESIZE; i++)
    191  1.1      cgd 		if (winr[i].suid == userid)	/* look for players winning entry */
    192  1.1      cgd 			if (winr[i].score>0) /* search for a winning entry for the player */
    193  1.1      cgd 				{
    194  1.1      cgd 				amt = winr[i].taxes;
    195  1.1      cgd 				if (x < amt) amt=x;		/* don't overpay taxes (Ughhhhh) */
    196  1.1      cgd 				winr[i].taxes -= amt;
    197  1.1      cgd 				outstanding_taxes -= amt;
    198  1.1      cgd 				if (writeboard()<0) return(0);
    199  1.1      cgd 				return(amt);
    200  1.1      cgd 				}
    201  1.1      cgd 	return(0L);	/* couldn't find user on winning scoreboard */
    202  1.1      cgd 	}
    203  1.1      cgd 
    204  1.1      cgd /*
    205  1.1      cgd  *	winshou()		Subroutine to print out the winning scoreboard
    206  1.1      cgd  *
    207  1.1      cgd  *	Returns the number of players on scoreboard that were shown
    208  1.1      cgd  */
    209  1.1      cgd winshou()
    210  1.1      cgd 	{
    211  1.1      cgd 	register struct wscofmt *p;
    212  1.1      cgd 	register int i,j,count;
    213  1.1      cgd 	for (count=j=i=0; i<SCORESIZE; i++) /* is there anyone on the scoreboard? */
    214  1.1      cgd 		if (winr[i].score != 0)
    215  1.1      cgd 			{ j++; break; }
    216  1.1      cgd 	if (j)
    217  1.1      cgd 		{
    218  1.1      cgd 		lprcat("\n  Score    Difficulty   Time Needed   Larn Winners List\n");
    219  1.1      cgd 
    220  1.1      cgd 		for (i=0; i<SCORESIZE; i++)	/* this loop is needed to print out the */
    221  1.1      cgd 		  for (j=0; j<SCORESIZE; j++) /* winners in order */
    222  1.1      cgd 			{
    223  1.1      cgd 			p = &winr[j];	/* pointer to the scoreboard entry */
    224  1.1      cgd 			if (p->order == i)
    225  1.1      cgd 				{
    226  1.1      cgd 				if (p->score)
    227  1.1      cgd 					{
    228  1.1      cgd 					count++;
    229  1.1      cgd 					lprintf("%10d     %2d      %5d Mobuls   %s \n",
    230  1.1      cgd 					(long)p->score,(long)p->hardlev,(long)p->timeused,p->who);
    231  1.1      cgd 					}
    232  1.1      cgd 				break;
    233  1.1      cgd 				}
    234  1.1      cgd 			}
    235  1.1      cgd 		}
    236  1.1      cgd 	return(count);	/* return number of people on scoreboard */
    237  1.1      cgd 	}
    238  1.1      cgd 
    239  1.1      cgd /*
    240  1.1      cgd  *	shou(x)			Subroutine to print out the non-winners scoreboard
    241  1.1      cgd  *		int x;
    242  1.1      cgd  *
    243  1.1      cgd  *	Enter with 0 to list the scores, enter with 1 to list inventories too
    244  1.1      cgd  *	Returns the number of players on scoreboard that were shown
    245  1.1      cgd  */
    246  1.1      cgd shou(x)
    247  1.1      cgd 	int x;
    248  1.1      cgd 	{
    249  1.1      cgd 	register int i,j,n,k;
    250  1.1      cgd 	int count;
    251  1.1      cgd 	for (count=j=i=0; i<SCORESIZE; i++)	/* is the scoreboard empty? */
    252  1.1      cgd 		if (sco[i].score!= 0)
    253  1.1      cgd 			{ j++; break; }
    254  1.1      cgd 	if (j)
    255  1.1      cgd 		{
    256  1.1      cgd 		lprcat("\n   Score   Difficulty   Larn Visitor Log\n");
    257  1.1      cgd 		for (i=0; i<SCORESIZE; i++) /* be sure to print them out in order */
    258  1.1      cgd 		  for (j=0; j<SCORESIZE; j++)
    259  1.1      cgd 			if (sco[j].order == i)
    260  1.1      cgd 				{
    261  1.1      cgd 				if (sco[j].score)
    262  1.1      cgd 					{
    263  1.1      cgd 					count++;
    264  1.1      cgd 					lprintf("%10d     %2d       %s ",
    265  1.1      cgd 						(long)sco[j].score,(long)sco[j].hardlev,sco[j].who);
    266  1.1      cgd 					if (sco[j].what < 256) lprintf("killed by a %s",monster[sco[j].what].name);
    267  1.1      cgd 						else lprintf("%s",whydead[sco[j].what - 256]);
    268  1.1      cgd 					if (x != 263) lprintf(" on %s",levelname[sco[j].level]);
    269  1.1      cgd 					if (x)
    270  1.1      cgd 						{
    271  1.1      cgd 						for (n=0; n<26; n++) { iven[n]=sco[j].sciv[n][0]; ivenarg[n]=sco[j].sciv[n][1]; }
    272  1.1      cgd 						for (k=1; k<99; k++)
    273  1.1      cgd 						  for (n=0; n<26; n++)
    274  1.1      cgd 							if (k==iven[n])  { srcount=0; show3(n); }
    275  1.1      cgd 						lprcat("\n\n");
    276  1.1      cgd 						}
    277  1.1      cgd 					else lprc('\n');
    278  1.1      cgd 					}
    279  1.1      cgd 				j=SCORESIZE;
    280  1.1      cgd 				}
    281  1.1      cgd 		}
    282  1.1      cgd 	return(count);	/* return the number of players just shown */
    283  1.1      cgd 	}
    284  1.1      cgd 
    285  1.1      cgd /*
    286  1.1      cgd  *	showscores()		Function to show the scoreboard on the terminal
    287  1.1      cgd  *
    288  1.1      cgd  *	Returns nothing of value
    289  1.1      cgd  */
    290  1.1      cgd static char esb[] = "The scoreboard is empty.\n";
    291  1.1      cgd showscores()
    292  1.1      cgd 	{
    293  1.1      cgd 	register int i,j;
    294  1.1      cgd 	lflush();  lcreat((char*)0);  if (readboard()<0) return;
    295  1.1      cgd 	i=winshou();	j=shou(0);
    296  1.1      cgd 	if (i+j == 0) lprcat(esb); else lprc('\n');
    297  1.1      cgd 	lflush();
    298  1.1      cgd 	}
    299  1.1      cgd 
    300  1.1      cgd /*
    301  1.1      cgd  *	showallscores()	Function to show scores and the iven lists that go with them
    302  1.1      cgd  *
    303  1.1      cgd  *	Returns nothing of value
    304  1.1      cgd  */
    305  1.1      cgd showallscores()
    306  1.1      cgd 	{
    307  1.1      cgd 	register int i,j;
    308  1.1      cgd 	lflush();  lcreat((char*)0);  if (readboard()<0) return;
    309  1.1      cgd 	c[WEAR] = c[WIELD] = c[SHIELD] = -1;  /* not wielding or wearing anything */
    310  1.2  mycroft 	for (i=0; i<MAXPOTION; i++) potionname[i]=potionhide[i];
    311  1.2  mycroft 	for (i=0; i<MAXSCROLL; i++) scrollname[i]=scrollhide[i];
    312  1.1      cgd 	i=winshou();  j=shou(1);
    313  1.1      cgd 	if (i+j==0) lprcat(esb); else lprc('\n');
    314  1.1      cgd 	lflush();
    315  1.1      cgd 	}
    316  1.1      cgd 
    317  1.1      cgd /*
    318  1.1      cgd  *	sortboard()		Function to sort the scoreboard
    319  1.1      cgd  *
    320  1.1      cgd  *	Returns 0 if no sorting done, else returns 1
    321  1.1      cgd  */
    322  1.1      cgd sortboard()
    323  1.1      cgd 	{
    324  1.1      cgd 	register int i,j,pos;
    325  1.1      cgd 	long jdat;
    326  1.1      cgd 	for (i=0; i<SCORESIZE; i++) sco[i].order = winr[i].order = -1;
    327  1.1      cgd 	pos=0;  while (pos < SCORESIZE)
    328  1.1      cgd 		{
    329  1.1      cgd 		jdat=0;
    330  1.1      cgd 		for (i=0; i<SCORESIZE; i++)
    331  1.1      cgd 			if ((sco[i].order < 0) && (sco[i].score >= jdat))
    332  1.1      cgd 				{ j=i;  jdat=sco[i].score; }
    333  1.1      cgd 		sco[j].order = pos++;
    334  1.1      cgd 		}
    335  1.1      cgd 	pos=0;  while (pos < SCORESIZE)
    336  1.1      cgd 		{
    337  1.1      cgd 		jdat=0;
    338  1.1      cgd 		for (i=0; i<SCORESIZE; i++)
    339  1.1      cgd 			if ((winr[i].order < 0) && (winr[i].score >= jdat))
    340  1.1      cgd 				{ j=i;  jdat=winr[i].score; }
    341  1.1      cgd 		winr[j].order = pos++;
    342  1.1      cgd 		}
    343  1.1      cgd 	return(1);
    344  1.1      cgd 	}
    345  1.1      cgd 
    346  1.1      cgd /*
    347  1.1      cgd  *	newscore(score, whoo, whyded, winner) 	Function to add entry to scoreboard
    348  1.1      cgd  *		int score, winner, whyded;
    349  1.1      cgd  *		char *whoo;
    350  1.1      cgd  *
    351  1.1      cgd  *	Enter with the total score in gp in score,  players name in whoo,
    352  1.1      cgd  *		died() reason # in whyded, and TRUE/FALSE in winner if a winner
    353  1.1      cgd  *	ex.		newscore(1000, "player 1", 32, 0);
    354  1.1      cgd  */
    355  1.1      cgd newscore(score, whoo, whyded, winner)
    356  1.1      cgd 	long score;
    357  1.1      cgd 	int winner, whyded;
    358  1.1      cgd 	char *whoo;
    359  1.1      cgd 	{
    360  1.1      cgd 	register int i;
    361  1.1      cgd 	long taxes;
    362  1.1      cgd 	if (readboard() < 0) return; 	/*	do the scoreboard	*/
    363  1.1      cgd 	/* if a winner then delete all non-winning scores */
    364  1.1      cgd 	if (cheat) winner=0;	/* if he cheated, don't let him win */
    365  1.1      cgd 	if (winner)
    366  1.1      cgd 		{
    367  1.1      cgd 		for (i=0; i<SCORESIZE; i++) if (sco[i].suid == userid) sco[i].score=0;
    368  1.1      cgd 		taxes = score*TAXRATE;
    369  1.1      cgd 		score += 100000*c[HARDGAME];	/* bonus for winning */
    370  1.1      cgd 	/* if he has a slot on the winning scoreboard update it if greater score */
    371  1.1      cgd 		for (i=0; i<SCORESIZE; i++) if (winr[i].suid == userid)
    372  1.1      cgd 				{ new1sub(score,i,whoo,taxes); return; }
    373  1.1      cgd 	/* he had no entry. look for last entry and see if he has a greater score */
    374  1.1      cgd 		for (i=0; i<SCORESIZE; i++) if (winr[i].order == SCORESIZE-1)
    375  1.1      cgd 				{ new1sub(score,i,whoo,taxes); return; }
    376  1.1      cgd 		}
    377  1.1      cgd 	else if (!cheat) /* for not winning scoreboard */
    378  1.1      cgd 		{
    379  1.1      cgd 	/* if he has a slot on the scoreboard update it if greater score */
    380  1.1      cgd 		for (i=0; i<SCORESIZE; i++) if (sco[i].suid == userid)
    381  1.1      cgd 				{ new2sub(score,i,whoo,whyded); return; }
    382  1.1      cgd 	/* he had no entry. look for last entry and see if he has a greater score */
    383  1.1      cgd 		for (i=0; i<SCORESIZE; i++) if (sco[i].order == SCORESIZE-1)
    384  1.1      cgd 				{ new2sub(score,i,whoo,whyded); return; }
    385  1.1      cgd 		}
    386  1.1      cgd 	}
    387  1.1      cgd 
    388  1.1      cgd /*
    389  1.1      cgd  *	new1sub(score,i,whoo,taxes) 	  Subroutine to put player into a
    390  1.1      cgd  *		int score,i,whyded,taxes;		  winning scoreboard entry if his score
    391  1.1      cgd  *		char *whoo; 					  is high enough
    392  1.1      cgd  *
    393  1.1      cgd  *	Enter with the total score in gp in score,  players name in whoo,
    394  1.1      cgd  *		died() reason # in whyded, and TRUE/FALSE in winner if a winner
    395  1.1      cgd  *		slot in scoreboard in i, and the tax bill in taxes.
    396  1.1      cgd  *	Returns nothing of value
    397  1.1      cgd  */
    398  1.1      cgd new1sub(score,i,whoo,taxes)
    399  1.1      cgd 	long score,taxes;
    400  1.1      cgd 	int i;
    401  1.1      cgd 	char *whoo;
    402  1.1      cgd 	{
    403  1.1      cgd 	register struct wscofmt *p;
    404  1.1      cgd 	p = &winr[i];
    405  1.1      cgd 	p->taxes += taxes;
    406  1.1      cgd 	if ((score >= p->score) || (c[HARDGAME] > p->hardlev))
    407  1.1      cgd 		{
    408  1.1      cgd 		strcpy(p->who,whoo);  		p->score=score;
    409  1.1      cgd 		p->hardlev=c[HARDGAME];		p->suid=userid;
    410  1.1      cgd 		p->timeused=gtime/100;
    411  1.1      cgd 		}
    412  1.1      cgd 	}
    413  1.1      cgd 
    414  1.1      cgd /*
    415  1.1      cgd  *	new2sub(score,i,whoo,whyded)	 	  Subroutine to put player into a
    416  1.1      cgd  *		int score,i,whyded,taxes;		  non-winning scoreboard entry if his
    417  1.1      cgd  *		char *whoo; 					  score is high enough
    418  1.1      cgd  *
    419  1.1      cgd  *	Enter with the total score in gp in score,  players name in whoo,
    420  1.1      cgd  *		died() reason # in whyded, and slot in scoreboard in i.
    421  1.1      cgd  *	Returns nothing of value
    422  1.1      cgd  */
    423  1.1      cgd new2sub(score,i,whoo,whyded)
    424  1.1      cgd 	long score;
    425  1.1      cgd 	int i,whyded;
    426  1.1      cgd 	char *whoo;
    427  1.1      cgd 	{
    428  1.1      cgd 	register int j;
    429  1.1      cgd 	register struct scofmt *p;
    430  1.1      cgd 	p = &sco[i];
    431  1.1      cgd 	if ((score >= p->score) || (c[HARDGAME] > p->hardlev))
    432  1.1      cgd 		{
    433  1.1      cgd 		strcpy(p->who,whoo);  p->score=score;
    434  1.1      cgd 		p->what=whyded;       p->hardlev=c[HARDGAME];
    435  1.1      cgd 		p->suid=userid;		  p->level=level;
    436  1.1      cgd 		for (j=0; j<26; j++)
    437  1.1      cgd 			{ p->sciv[j][0]=iven[j]; p->sciv[j][1]=ivenarg[j]; }
    438  1.1      cgd 		}
    439  1.1      cgd 	}
    440  1.1      cgd 
    441  1.1      cgd /*
    442  1.1      cgd  *	died(x) 	Subroutine to record who played larn, and what the score was
    443  1.1      cgd  *		int x;
    444  1.1      cgd  *
    445  1.1      cgd  *	if x < 0 then don't show scores
    446  1.1      cgd  *	died() never returns! (unless c[LIFEPROT] and a reincarnatable death!)
    447  1.1      cgd  *
    448  1.1      cgd  *		< 256	killed by the monster number
    449  1.1      cgd  *		256		quit
    450  1.1      cgd  *		257		suspended
    451  1.1      cgd  *		258		self - annihilated
    452  1.1      cgd  *		259		shot by an arrow
    453  1.1      cgd  *		260		hit by a dart
    454  1.1      cgd  *		261		fell into a pit
    455  1.1      cgd  *		262		fell into a bottomless pit
    456  1.1      cgd  *		263		a winner
    457  1.1      cgd  *		264		trapped in solid rock
    458  1.1      cgd  *		265		killed by a missing save file
    459  1.1      cgd  *		266		killed by an old save file
    460  1.1      cgd  *		267		caught by the greedy cheater checker trap
    461  1.1      cgd  *		268		killed by a protected save file
    462  1.1      cgd  *		269		killed his family and killed himself
    463  1.1      cgd  *		270		erased by a wayward finger
    464  1.1      cgd  *		271		fell through a bottomless trap door
    465  1.1      cgd  *		272		fell through a trap door
    466  1.1      cgd  *		273		drank some poisonous water
    467  1.1      cgd  *		274		fried by an electric shock
    468  1.1      cgd  *		275		slipped on a volcano shaft
    469  1.1      cgd  *		276		killed by a stupid act of frustration
    470  1.1      cgd  *		277		attacked by a revolting demon
    471  1.1      cgd  *		278		hit by his own magic
    472  1.1      cgd  *		279		demolished by an unseen attacker
    473  1.1      cgd  *		280		fell into the dreadful sleep
    474  1.1      cgd  *		281		killed by an exploding chest
    475  1.1      cgd  *		282		killed by a missing maze data file
    476  1.1      cgd  *		283		killed by a sphere of annihilation
    477  1.1      cgd  *		284		died a post mortem death
    478  1.1      cgd  *		285		malloc() failure
    479  1.1      cgd  *		300		quick quit -- don't put on scoreboard
    480  1.1      cgd  */
    481  1.1      cgd 
    482  1.1      cgd static int scorerror;
    483  1.1      cgd died(x)
    484  1.1      cgd 	int x;
    485  1.1      cgd 	{
    486  1.1      cgd 	register int f,win;
    487  1.1      cgd 	char ch,*mod;
    488  1.5      cgd 	time_t zzz;
    489  1.5      cgd 	long i;
    490  1.1      cgd 	struct tms cputime;
    491  1.1      cgd 	if (c[LIFEPROT]>0) /* if life protection */
    492  1.1      cgd 		{
    493  1.1      cgd 		switch((x>0) ? x : -x)
    494  1.1      cgd 			{
    495  1.1      cgd 			case 256: case 257: case 262: case 263: case 265: case 266:
    496  1.1      cgd 			case 267: case 268: case 269: case 271: case 282: case 284:
    497  1.1      cgd 			case 285: case 300:  goto invalid; /* can't be saved */
    498  1.1      cgd 			};
    499  1.1      cgd 		--c[LIFEPROT]; c[HP]=1; --c[CONSTITUTION];
    500  1.1      cgd 		cursors(); lprcat("\nYou feel wiiieeeeerrrrrd all over! "); beep();
    501  1.1      cgd 		lflush();  sleep(4);
    502  1.1      cgd 		return; /* only case where died() returns */
    503  1.1      cgd 		}
    504  1.1      cgd invalid:
    505  1.1      cgd 	clearvt100();  lflush();  f=0;
    506  1.1      cgd 	if (ckpflag) unlink(ckpfile);	/* remove checkpoint file if used */
    507  1.1      cgd 	if (x<0) { f++; x = -x; }	/* if we are not to display the scores */
    508  1.1      cgd 	if ((x == 300) || (x == 257))  exit();	/* for quick exit or saved game */
    509  1.1      cgd 	if (x == 263)  win = 1;  else  win = 0;
    510  1.1      cgd 	c[GOLD] += c[BANKACCOUNT];   c[BANKACCOUNT] = 0;
    511  1.1      cgd 		/*	now enter the player at the end of the scoreboard */
    512  1.1      cgd 	newscore(c[GOLD], logname, x, win);
    513  1.1      cgd 	diedsub(x);	/* print out the score line */  lflush();
    514  1.1      cgd 
    515  1.1      cgd 	set_score_output();
    516  1.1      cgd 	if ((wizard == 0) && (c[GOLD] > 0)) 	/*	wizards can't score		*/
    517  1.1      cgd 		{
    518  1.1      cgd #ifndef NOLOG
    519  1.1      cgd 		if (lappend(logfile)<0)  /* append to file */
    520  1.1      cgd 			{
    521  1.1      cgd 			if (lcreat(logfile)<0) /* and can't create new log file */
    522  1.1      cgd 		    	{
    523  1.1      cgd 				lcreat((char*)0);
    524  1.1      cgd 				lprcat("\nCan't open record file:  I can't post your score.\n");
    525  1.1      cgd 				sncbr();  resetscroll();  lflush();  exit();
    526  1.1      cgd 				}
    527  1.6      mrg 			seteuid(euid);
    528  1.1      cgd 			chmod(logfile,0660);
    529  1.6      mrg 			seteuid(uid);
    530  1.1      cgd 			}
    531  1.1      cgd 		strcpy(logg.who,loginname);
    532  1.1      cgd 		logg.score = c[GOLD];		logg.diff = c[HARDGAME];
    533  1.1      cgd 		if (x < 256)
    534  1.1      cgd 			{
    535  1.1      cgd 			ch = *monster[x].name;
    536  1.1      cgd 			if (ch=='a' || ch=='e' || ch=='i' || ch=='o' || ch=='u')
    537  1.1      cgd 				mod="an";  else mod="a";
    538  1.1      cgd 			sprintf(logg.what,"killed by %s %s",mod,monster[x].name);
    539  1.1      cgd 			}
    540  1.1      cgd 		else sprintf(logg.what,"%s",whydead[x - 256]);
    541  1.1      cgd 		logg.cavelev=level;
    542  1.1      cgd 		time(&zzz);	  /* get cpu time -- write out score info */
    543  1.1      cgd 		logg.diedtime=zzz;
    544  1.1      cgd #ifdef EXTRA
    545  1.1      cgd 		times(&cputime);  /* get cpu time -- write out score info */
    546  1.1      cgd 		logg.cputime = i = (cputime.tms_utime + cputime.tms_stime)/60 + c[CPUTIME];
    547  1.1      cgd 		logg.lev=c[LEVEL];			logg.ac=c[AC];
    548  1.1      cgd 		logg.hpmax=c[HPMAX];		logg.hp=c[HP];
    549  1.1      cgd 		logg.elapsedtime=(zzz-initialtime+59)/60;
    550  1.1      cgd 		logg.usage=(10000*i)/(zzz-initialtime);
    551  1.1      cgd 		logg.bytin=c[BYTESIN];		logg.bytout=c[BYTESOUT];
    552  1.1      cgd 		logg.moves=c[MOVESMADE];	logg.spused=c[SPELLSCAST];
    553  1.1      cgd 		logg.killed=c[MONSTKILLED];
    554  1.1      cgd #endif
    555  1.1      cgd 		lwrite((char*)&logg,sizeof(struct log_fmt));	 lwclose();
    556  1.1      cgd #endif NOLOG
    557  1.1      cgd 
    558  1.1      cgd /*	now for the scoreboard maintenance -- not for a suspended game 	*/
    559  1.1      cgd 		if (x != 257)
    560  1.1      cgd 			{
    561  1.1      cgd 			if (sortboard())  scorerror = writeboard();
    562  1.1      cgd 			}
    563  1.1      cgd 		}
    564  1.1      cgd 	if ((x==256) || (x==257) || (f != 0)) exit();
    565  1.1      cgd 	if (scorerror == 0) showscores();	/* if we updated the scoreboard */
    566  1.1      cgd 	if (x == 263) mailbill();		exit();
    567  1.1      cgd 	}
    568  1.1      cgd 
    569  1.1      cgd /*
    570  1.1      cgd  *	diedsub(x) Subroutine to print out the line showing the player when he is killed
    571  1.1      cgd  *		int x;
    572  1.1      cgd  */
    573  1.1      cgd diedsub(x)
    574  1.1      cgd int x;
    575  1.1      cgd 	{
    576  1.1      cgd 	register char ch,*mod;
    577  1.1      cgd 	lprintf("Score: %d, Diff: %d,  %s ",(long)c[GOLD],(long)c[HARDGAME],logname);
    578  1.1      cgd 	if (x < 256)
    579  1.1      cgd 		{
    580  1.1      cgd 		ch = *monster[x].name;
    581  1.1      cgd 		if (ch=='a' || ch=='e' || ch=='i' || ch=='o' || ch=='u')
    582  1.1      cgd 			mod="an";  else mod="a";
    583  1.1      cgd 		lprintf("killed by %s %s",mod,monster[x].name);
    584  1.1      cgd 		}
    585  1.1      cgd 	else lprintf("%s",whydead[x - 256]);
    586  1.1      cgd 	if (x != 263) lprintf(" on %s\n",levelname[level]);  else lprc('\n');
    587  1.1      cgd 	}
    588  1.1      cgd 
    589  1.1      cgd /*
    590  1.1      cgd  *	diedlog() 	Subroutine to read a log file and print it out in ascii format
    591  1.1      cgd  */
    592  1.1      cgd diedlog()
    593  1.1      cgd 	{
    594  1.1      cgd 	register int n;
    595  1.1      cgd 	register char *p;
    596  1.1      cgd 	struct stat stbuf;
    597  1.1      cgd 	lcreat((char*)0);
    598  1.1      cgd 	if (lopen(logfile)<0)
    599  1.1      cgd 		{
    600  1.1      cgd 		lprintf("Can't locate log file <%s>\n",logfile);
    601  1.1      cgd 		return;
    602  1.1      cgd 		}
    603  1.1      cgd 	if (fstat(fd,&stbuf) < 0)
    604  1.1      cgd 		{
    605  1.1      cgd 		lprintf("Can't  stat log file <%s>\n",logfile);
    606  1.1      cgd 		return;
    607  1.1      cgd 		}
    608  1.1      cgd 	for (n=stbuf.st_size/sizeof(struct log_fmt); n>0; --n)
    609  1.1      cgd 		{
    610  1.1      cgd 		lrfill((char*)&logg,sizeof(struct log_fmt));
    611  1.1      cgd 		p = ctime(&logg.diedtime); p[16]='\n'; p[17]=0;
    612  1.1      cgd 		lprintf("Score: %d, Diff: %d,  %s %s on %d at %s",(long)(logg.score),(long)(logg.diff),logg.who,logg.what,(long)(logg.cavelev),p+4);
    613  1.1      cgd #ifdef EXTRA
    614  1.1      cgd 		if (logg.moves<=0) logg.moves=1;
    615  1.1      cgd 		lprintf("  Experience Level: %d,  AC: %d,  HP: %d/%d,  Elapsed Time: %d minutes\n",(long)(logg.lev),(long)(logg.ac),(long)(logg.hp),(long)(logg.hpmax),(long)(logg.elapsedtime));
    616  1.1      cgd 		lprintf("  CPU time used: %d seconds,  Machine usage: %d.%02d%%\n",(long)(logg.cputime),(long)(logg.usage/100),(long)(logg.usage%100));
    617  1.1      cgd 		lprintf("  BYTES in: %d, out: %d, moves: %d, deaths: %d, spells cast: %d\n",(long)(logg.bytin),(long)(logg.bytout),(long)(logg.moves),(long)(logg.killed),(long)(logg.spused));
    618  1.1      cgd 		lprintf("  out bytes per move: %d,  time per move: %d ms\n",(long)(logg.bytout/logg.moves),(long)((logg.cputime*1000)/logg.moves));
    619  1.1      cgd #endif
    620  1.1      cgd 		}
    621  1.1      cgd 		lflush();  lrclose();  return;
    622  1.1      cgd 	}
    623  1.1      cgd 
    624  1.1      cgd #ifndef UIDSCORE
    625  1.1      cgd /*
    626  1.1      cgd  *	getplid(name)		Function to get players id # from id file
    627  1.1      cgd  *
    628  1.1      cgd  *	Enter with the name of the players character in name.
    629  1.1      cgd  *	Returns the id # of the players character, or -1 if failure.
    630  1.1      cgd  *	This routine will try to find the name in the id file, if its not there,
    631  1.1      cgd  *	it will try to make a new entry in the file.  Only returns -1 if can't
    632  1.1      cgd  *	find him in the file, and can't make a new entry in the file.
    633  1.1      cgd  *	Format of playerids file:
    634  1.1      cgd  *			Id # in ascii     \n     character name     \n
    635  1.1      cgd  */
    636  1.1      cgd static int havepid= -1;	/* playerid # if previously done */
    637  1.1      cgd getplid(nam)
    638  1.1      cgd 	char *nam;
    639  1.1      cgd 	{
    640  1.1      cgd 	int fd7,high=999,no;
    641  1.1      cgd 	register char *p,*p2;
    642  1.1      cgd 	char name[80];
    643  1.1      cgd 	if (havepid != -1) return(havepid);	/* already did it */
    644  1.1      cgd 	lflush();	/* flush any pending I/O */
    645  1.1      cgd 	sprintf(name,"%s\n",nam);	/* append a \n to name */
    646  1.1      cgd 	if (lopen(playerids) < 0)	/* no file, make it */
    647  1.1      cgd 		{
    648  1.1      cgd 		if ((fd7=creat(playerids,0666)) < 0)  return(-1); /* can't make it */
    649  1.1      cgd 		close(fd7);  goto addone;	/* now append new playerid record to file */
    650  1.1      cgd 		}
    651  1.1      cgd 	for (;;)	/* now search for the name in the player id file */
    652  1.1      cgd 		{
    653  1.1      cgd 		p = lgetl();  if (p==NULL) break;	/* EOF? */
    654  1.1      cgd 		no = atoi(p);	/* the id # */
    655  1.1      cgd 		p2= lgetl();  if (p2==NULL) break;	/* EOF? */
    656  1.1      cgd 		if (no>high) high=no;	/* accumulate highest id # */
    657  1.1      cgd 		if (strcmp(p2,name)==0)	/* we found him */
    658  1.1      cgd 			{
    659  1.1      cgd 			return(no);	/* his id number */
    660  1.1      cgd 			}
    661  1.1      cgd 		}
    662  1.1      cgd 	lrclose();
    663  1.1      cgd 	/* if we get here, we didn't find him in the file -- put him there */
    664  1.1      cgd addone:
    665  1.1      cgd 	if (lappend(playerids) < 0) return(-1);	/* can't open file for append */
    666  1.1      cgd 	lprintf("%d\n%s",(long)++high,name);  /* new id # and name */
    667  1.1      cgd 	lwclose();
    668  1.1      cgd 	lcreat((char*)0);	/* re-open terminal channel */
    669  1.1      cgd 	return(high);
    670  1.1      cgd 	}
    671  1.1      cgd #endif UIDSCORE
    672  1.1      cgd 
    673