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