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