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