xref: /csrg-svn/games/hack/hack.end.c (revision 47700)
141234Sbostic /* Copyright (c) Stichting Mathematisch Centrum, Amsterdam, 1985. */
241234Sbostic /* hack.end.c - version 1.0.3 */
341234Sbostic 
441234Sbostic #include "hack.h"
541234Sbostic #include <stdio.h>
641234Sbostic #include <signal.h>
741234Sbostic #define	Sprintf	(void) sprintf
841234Sbostic extern char plname[], pl_character[];
941234Sbostic extern char *itoa(), *ordin(), *eos();
1041234Sbostic 
1141234Sbostic xchar maxdlevel = 1;
1241234Sbostic 
13*47700Sbostic void
done1()1441234Sbostic done1()
1541234Sbostic {
1641234Sbostic 	(void) signal(SIGINT,SIG_IGN);
1741234Sbostic 	pline("Really quit?");
1841234Sbostic 	if(readchar() != 'y') {
1941234Sbostic 		(void) signal(SIGINT,done1);
2041234Sbostic 		clrlin();
2141234Sbostic 		(void) fflush(stdout);
2241234Sbostic 		if(multi > 0) nomul(0);
23*47700Sbostic 		return;
2441234Sbostic 	}
2541234Sbostic 	done("quit");
2641234Sbostic 	/* NOTREACHED */
2741234Sbostic }
2841234Sbostic 
2941234Sbostic int done_stopprint;
3041234Sbostic int done_hup;
3141234Sbostic 
32*47700Sbostic void
done_intr()3341234Sbostic done_intr(){
3441234Sbostic 	done_stopprint++;
3541234Sbostic 	(void) signal(SIGINT, SIG_IGN);
3641234Sbostic 	(void) signal(SIGQUIT, SIG_IGN);
3741234Sbostic }
3841234Sbostic 
39*47700Sbostic void
done_hangup()4041234Sbostic done_hangup(){
4141234Sbostic 	done_hup++;
4241234Sbostic 	(void) signal(SIGHUP, SIG_IGN);
4341234Sbostic 	done_intr();
4441234Sbostic }
4541234Sbostic 
done_in_by(mtmp)4641234Sbostic done_in_by(mtmp) register struct monst *mtmp; {
4741234Sbostic static char buf[BUFSZ];
4841234Sbostic 	pline("You die ...");
4941234Sbostic 	if(mtmp->data->mlet == ' '){
5041234Sbostic 		Sprintf(buf, "the ghost of %s", (char *) mtmp->mextra);
5141234Sbostic 		killer = buf;
5241234Sbostic 	} else if(mtmp->mnamelth) {
5341234Sbostic 		Sprintf(buf, "%s called %s",
5441234Sbostic 			mtmp->data->mname, NAME(mtmp));
5541234Sbostic 		killer = buf;
5641234Sbostic 	} else if(mtmp->minvis) {
5741234Sbostic 		Sprintf(buf, "invisible %s", mtmp->data->mname);
5841234Sbostic 		killer = buf;
5941234Sbostic 	} else killer = mtmp->data->mname;
6041234Sbostic 	done("died");
6141234Sbostic }
6241234Sbostic 
6341234Sbostic /* called with arg "died", "drowned", "escaped", "quit", "choked", "panicked",
6441234Sbostic    "burned", "starved" or "tricked" */
6541234Sbostic /* Be careful not to call panic from here! */
done(st1)6641234Sbostic done(st1)
6741234Sbostic register char *st1;
6841234Sbostic {
6941234Sbostic 
7041234Sbostic #ifdef WIZARD
7141234Sbostic 	if(wizard && *st1 == 'd'){
7241234Sbostic 		u.uswldtim = 0;
7341234Sbostic 		if(u.uhpmax < 0) u.uhpmax = 100;	/* arbitrary */
7441234Sbostic 		u.uhp = u.uhpmax;
7541234Sbostic 		pline("For some reason you are still alive.");
7641234Sbostic 		flags.move = 0;
7741234Sbostic 		if(multi > 0) multi = 0; else multi = -1;
7841234Sbostic 		flags.botl = 1;
7941234Sbostic 		return;
8041234Sbostic 	}
8141234Sbostic #endif WIZARD
8241234Sbostic 	(void) signal(SIGINT, done_intr);
8341234Sbostic 	(void) signal(SIGQUIT, done_intr);
8441234Sbostic 	(void) signal(SIGHUP, done_hangup);
8541234Sbostic 	if(*st1 == 'q' && u.uhp < 1){
8641234Sbostic 		st1 = "died";
8741234Sbostic 		killer = "quit while already on Charon's boat";
8841234Sbostic 	}
8941234Sbostic 	if(*st1 == 's') killer = "starvation"; else
9041234Sbostic 	if(*st1 == 'd' && st1[1] == 'r') killer = "drowning"; else
9141234Sbostic 	if(*st1 == 'p') killer = "panic"; else
9241234Sbostic 	if(*st1 == 't') killer = "trickery"; else
9341234Sbostic 	if(!index("bcd", *st1)) killer = st1;
9441234Sbostic 	paybill();
9541234Sbostic 	clearlocks();
9641234Sbostic 	if(flags.toplin == 1) more();
9741234Sbostic 	if(index("bcds", *st1)){
9841234Sbostic #ifdef WIZARD
9941234Sbostic 	    if(!wizard)
10041234Sbostic #endif WIZARD
10141234Sbostic 		savebones();
10241234Sbostic 		if(!flags.notombstone)
10341234Sbostic 			outrip();
10441234Sbostic 	}
10541234Sbostic 	if(*st1 == 'c') killer = st1;		/* after outrip() */
10641234Sbostic 	settty((char *) 0);	/* does a clear_screen() */
10741234Sbostic 	if(!done_stopprint)
10841234Sbostic 		printf("Goodbye %s %s...\n\n", pl_character, plname);
10941234Sbostic 	{ long int tmp;
11041234Sbostic 	  tmp = u.ugold - u.ugold0;
11141234Sbostic 	  if(tmp < 0)
11241234Sbostic 		tmp = 0;
11341234Sbostic 	  if(*st1 == 'd' || *st1 == 'b')
11441234Sbostic 		tmp -= tmp/10;
11541234Sbostic 	  u.urexp += tmp;
11641234Sbostic 	  u.urexp += 50 * maxdlevel;
11741234Sbostic 	  if(maxdlevel > 20)
11841234Sbostic 		u.urexp += 1000*((maxdlevel > 30) ? 10 : maxdlevel - 20);
11941234Sbostic 	}
12041234Sbostic 	if(*st1 == 'e') {
12141234Sbostic 		extern struct monst *mydogs;
12241234Sbostic 		register struct monst *mtmp;
12341234Sbostic 		register struct obj *otmp;
12441234Sbostic 		register int i;
12541234Sbostic 		register unsigned worthlessct = 0;
12641234Sbostic 		boolean has_amulet = FALSE;
12741234Sbostic 
12841234Sbostic 		killer = st1;
12941234Sbostic 		keepdogs();
13041234Sbostic 		mtmp = mydogs;
13141234Sbostic 		if(mtmp) {
13241234Sbostic 			if(!done_stopprint) printf("You");
13341234Sbostic 			while(mtmp) {
13441234Sbostic 				if(!done_stopprint)
13541234Sbostic 					printf(" and %s", monnam(mtmp));
13641234Sbostic 				if(mtmp->mtame)
13741234Sbostic 					u.urexp += mtmp->mhp;
13841234Sbostic 				mtmp = mtmp->nmon;
13941234Sbostic 			}
14041234Sbostic 			if(!done_stopprint)
14141234Sbostic 		    printf("\nescaped from the dungeon with %ld points,\n",
14241234Sbostic 			u.urexp);
14341234Sbostic 		} else
14441234Sbostic 		if(!done_stopprint)
14541234Sbostic 		  printf("You escaped from the dungeon with %ld points,\n",
14641234Sbostic 		    u.urexp);
14741234Sbostic 		for(otmp = invent; otmp; otmp = otmp->nobj) {
14841234Sbostic 			if(otmp->olet == GEM_SYM){
14941234Sbostic 				objects[otmp->otyp].oc_name_known = 1;
15041234Sbostic 				i = otmp->quan*objects[otmp->otyp].g_val;
15141234Sbostic 				if(i == 0) {
15241234Sbostic 					worthlessct += otmp->quan;
15341234Sbostic 					continue;
15441234Sbostic 				}
15541234Sbostic 				u.urexp += i;
15641234Sbostic 				if(!done_stopprint)
15741234Sbostic 				  printf("\t%s (worth %d Zorkmids),\n",
15841234Sbostic 				    doname(otmp), i);
15941234Sbostic 			} else if(otmp->olet == AMULET_SYM) {
16041234Sbostic 				otmp->known = 1;
16141234Sbostic 				i = (otmp->spe < 0) ? 2 : 5000;
16241234Sbostic 				u.urexp += i;
16341234Sbostic 				if(!done_stopprint)
16441234Sbostic 				  printf("\t%s (worth %d Zorkmids),\n",
16541234Sbostic 				    doname(otmp), i);
16641234Sbostic 				if(otmp->spe >= 0) {
16741234Sbostic 					has_amulet = TRUE;
16841234Sbostic 					killer = "escaped (with amulet)";
16941234Sbostic 				}
17041234Sbostic 			}
17141234Sbostic 		}
17241234Sbostic 		if(worthlessct) if(!done_stopprint)
17341234Sbostic 		  printf("\t%u worthless piece%s of coloured glass,\n",
17441234Sbostic 		  worthlessct, plur(worthlessct));
17541234Sbostic 		if(has_amulet) u.urexp *= 2;
17641234Sbostic 	} else
17741234Sbostic 		if(!done_stopprint)
17841234Sbostic 		  printf("You %s on dungeon level %d with %ld points,\n",
17941234Sbostic 		    st1, dlevel, u.urexp);
18041234Sbostic 	if(!done_stopprint)
18141234Sbostic 	  printf("and %ld piece%s of gold, after %ld move%s.\n",
18241234Sbostic 	    u.ugold, plur(u.ugold), moves, plur(moves));
18341234Sbostic 	if(!done_stopprint)
18441234Sbostic   printf("You were level %u with a maximum of %d hit points when you %s.\n",
18541234Sbostic 	    u.ulevel, u.uhpmax, st1);
18641234Sbostic 	if(*st1 == 'e' && !done_stopprint){
18741234Sbostic 		getret();	/* all those pieces of coloured glass ... */
18841234Sbostic 		cls();
18941234Sbostic 	}
19041234Sbostic #ifdef WIZARD
19141234Sbostic 	if(!wizard)
19241234Sbostic #endif WIZARD
19341234Sbostic 		topten();
19441234Sbostic 	if(done_stopprint) printf("\n\n");
19541234Sbostic 	exit(0);
19641234Sbostic }
19741234Sbostic 
19841234Sbostic #define newttentry() (struct toptenentry *) alloc(sizeof(struct toptenentry))
19941234Sbostic #define	NAMSZ	8
20041234Sbostic #define	DTHSZ	40
20141234Sbostic #define	PERSMAX	1
20241234Sbostic #define	POINTSMIN	1	/* must be > 0 */
20341234Sbostic #define	ENTRYMAX	100	/* must be >= 10 */
20441234Sbostic #define	PERS_IS_UID		/* delete for PERSMAX per name; now per uid */
20541234Sbostic struct toptenentry {
20641234Sbostic 	struct toptenentry *tt_next;
20741234Sbostic 	long int points;
20841234Sbostic 	int level,maxlvl,hp,maxhp;
20941234Sbostic 	int uid;
21041234Sbostic 	char plchar;
21141234Sbostic 	char sex;
21241234Sbostic 	char name[NAMSZ+1];
21341234Sbostic 	char death[DTHSZ+1];
21441234Sbostic 	char date[7];		/* yymmdd */
21541234Sbostic } *tt_head;
21641234Sbostic 
topten()21741234Sbostic topten(){
21841234Sbostic 	int uid = getuid();
21941234Sbostic 	int rank, rank0 = -1, rank1 = 0;
22041234Sbostic 	int occ_cnt = PERSMAX;
22141234Sbostic 	register struct toptenentry *t0, *t1, *tprev;
22241234Sbostic 	char *recfile = RECORD;
22341234Sbostic 	char *reclock = "record_lock";
22441234Sbostic 	int sleepct = 300;
22541234Sbostic 	FILE *rfile;
22641234Sbostic 	register flg = 0;
22741234Sbostic 	extern char *getdate();
22841234Sbostic #define	HUP	if(!done_hup)
22941234Sbostic 	while(link(recfile, reclock) == -1) {
23041234Sbostic 		HUP perror(reclock);
23141234Sbostic 		if(!sleepct--) {
23241234Sbostic 			HUP puts("I give up. Sorry.");
23341234Sbostic 			HUP puts("Perhaps there is an old record_lock around?");
23441234Sbostic 			return;
23541234Sbostic 		}
23641234Sbostic 		HUP printf("Waiting for access to record file. (%d)\n",
23741234Sbostic 			sleepct);
23841234Sbostic 		HUP (void) fflush(stdout);
23941234Sbostic 		sleep(1);
24041234Sbostic 	}
24141234Sbostic 	if(!(rfile = fopen(recfile,"r"))){
24241234Sbostic 		HUP puts("Cannot open record file!");
24341234Sbostic 		goto unlock;
24441234Sbostic 	}
24541234Sbostic 	HUP (void) putchar('\n');
24641234Sbostic 
24741234Sbostic 	/* create a new 'topten' entry */
24841234Sbostic 	t0 = newttentry();
24941234Sbostic 	t0->level = dlevel;
25041234Sbostic 	t0->maxlvl = maxdlevel;
25141234Sbostic 	t0->hp = u.uhp;
25241234Sbostic 	t0->maxhp = u.uhpmax;
25341234Sbostic 	t0->points = u.urexp;
25441234Sbostic 	t0->plchar = pl_character[0];
25541234Sbostic 	t0->sex = (flags.female ? 'F' : 'M');
25641234Sbostic 	t0->uid = uid;
25741234Sbostic 	(void) strncpy(t0->name, plname, NAMSZ);
25841234Sbostic 	(t0->name)[NAMSZ] = 0;
25941234Sbostic 	(void) strncpy(t0->death, killer, DTHSZ);
26041234Sbostic 	(t0->death)[DTHSZ] = 0;
26141234Sbostic 	(void) strcpy(t0->date, getdate());
26241234Sbostic 
26341234Sbostic 	/* assure minimum number of points */
26441234Sbostic 	if(t0->points < POINTSMIN)
26541234Sbostic 		t0->points = 0;
26641234Sbostic 
26741234Sbostic 	t1 = tt_head = newttentry();
26841234Sbostic 	tprev = 0;
26941234Sbostic 	/* rank0: -1 undefined, 0 not_on_list, n n_th on list */
27041234Sbostic 	for(rank = 1; ; ) {
27141234Sbostic 	  if(fscanf(rfile, "%6s %d %d %d %d %d %ld %c%c %[^,],%[^\n]",
27241234Sbostic 		t1->date, &t1->uid,
27341234Sbostic 		&t1->level, &t1->maxlvl,
27441234Sbostic 		&t1->hp, &t1->maxhp, &t1->points,
27541234Sbostic 		&t1->plchar, &t1->sex, t1->name, t1->death) != 11
27641234Sbostic 	  || t1->points < POINTSMIN)
27741234Sbostic 			t1->points = 0;
27841234Sbostic 	  if(rank0 < 0 && t1->points < t0->points) {
27941234Sbostic 		rank0 = rank++;
28041234Sbostic 		if(tprev == 0)
28141234Sbostic 			tt_head = t0;
28241234Sbostic 		else
28341234Sbostic 			tprev->tt_next = t0;
28441234Sbostic 		t0->tt_next = t1;
28541234Sbostic 		occ_cnt--;
28641234Sbostic 		flg++;		/* ask for a rewrite */
28741234Sbostic 	  } else
28841234Sbostic 		tprev = t1;
28941234Sbostic 	  if(t1->points == 0) break;
29041234Sbostic 	  if(
29141234Sbostic #ifdef PERS_IS_UID
29241234Sbostic 	     t1->uid == t0->uid &&
29341234Sbostic #else
29441234Sbostic 	     strncmp(t1->name, t0->name, NAMSZ) == 0 &&
29541234Sbostic #endif PERS_IS_UID
29641234Sbostic 	     t1->plchar == t0->plchar && --occ_cnt <= 0){
29741234Sbostic 		if(rank0 < 0){
29841234Sbostic 			rank0 = 0;
29941234Sbostic 			rank1 = rank;
30041234Sbostic 	HUP printf("You didn't beat your previous score of %ld points.\n\n",
30141234Sbostic 				t1->points);
30241234Sbostic 		}
30341234Sbostic 		if(occ_cnt < 0){
30441234Sbostic 			flg++;
30541234Sbostic 			continue;
30641234Sbostic 		}
30741234Sbostic 	  }
30841234Sbostic 	  if(rank <= ENTRYMAX){
30941234Sbostic 	  	t1 = t1->tt_next = newttentry();
31041234Sbostic 	  	rank++;
31141234Sbostic 	  }
31241234Sbostic 	  if(rank > ENTRYMAX){
31341234Sbostic 		t1->points = 0;
31441234Sbostic 		break;
31541234Sbostic 	  }
31641234Sbostic 	}
31741234Sbostic 	if(flg) {	/* rewrite record file */
31841234Sbostic 		(void) fclose(rfile);
31941234Sbostic 		if(!(rfile = fopen(recfile,"w"))){
32041234Sbostic 			HUP puts("Cannot write record file\n");
32141234Sbostic 			goto unlock;
32241234Sbostic 		}
32341234Sbostic 
32441234Sbostic 		if(!done_stopprint) if(rank0 > 0){
32541234Sbostic 		    if(rank0 <= 10)
32641234Sbostic 			puts("You made the top ten list!\n");
32741234Sbostic 		    else
32841234Sbostic 		printf("You reached the %d%s place on the top %d list.\n\n",
32941234Sbostic 			rank0, ordin(rank0), ENTRYMAX);
33041234Sbostic 		}
33141234Sbostic 	}
33241234Sbostic 	if(rank0 == 0) rank0 = rank1;
33341234Sbostic 	if(rank0 <= 0) rank0 = rank;
33441234Sbostic 	if(!done_stopprint) outheader();
33541234Sbostic 	t1 = tt_head;
33641234Sbostic 	for(rank = 1; t1->points != 0; rank++, t1 = t1->tt_next) {
33741234Sbostic 	  if(flg) fprintf(rfile,"%6s %d %d %d %d %d %ld %c%c %s,%s\n",
33841234Sbostic 	    t1->date, t1->uid,
33941234Sbostic 	    t1->level, t1->maxlvl,
34041234Sbostic 	    t1->hp, t1->maxhp, t1->points,
34141234Sbostic 	    t1->plchar, t1->sex, t1->name, t1->death);
34241234Sbostic 	  if(done_stopprint) continue;
34341234Sbostic 	  if(rank > flags.end_top &&
34441234Sbostic 	    (rank < rank0-flags.end_around || rank > rank0+flags.end_around)
34541234Sbostic 	    && (!flags.end_own ||
34641234Sbostic #ifdef PERS_IS_UID
34741234Sbostic 				  t1->uid != t0->uid ))
34841234Sbostic #else
34941234Sbostic 				  strncmp(t1->name, t0->name, NAMSZ)))
35041234Sbostic #endif PERS_IS_UID
35141234Sbostic 	  	continue;
35241234Sbostic 	  if(rank == rank0-flags.end_around &&
35341234Sbostic 	     rank0 > flags.end_top+flags.end_around+1 &&
35441234Sbostic 	     !flags.end_own)
35541234Sbostic 		(void) putchar('\n');
35641234Sbostic 	  if(rank != rank0)
35741234Sbostic 		(void) outentry(rank, t1, 0);
35841234Sbostic 	  else if(!rank1)
35941234Sbostic 		(void) outentry(rank, t1, 1);
36041234Sbostic 	  else {
36141234Sbostic 		int t0lth = outentry(0, t0, -1);
36241234Sbostic 		int t1lth = outentry(rank, t1, t0lth);
36341234Sbostic 		if(t1lth > t0lth) t0lth = t1lth;
36441234Sbostic 		(void) outentry(0, t0, t0lth);
36541234Sbostic 	  }
36641234Sbostic 	}
36741234Sbostic 	if(rank0 >= rank) if(!done_stopprint)
36841234Sbostic 		(void) outentry(0, t0, 1);
36941234Sbostic 	(void) fclose(rfile);
37041234Sbostic unlock:
37141234Sbostic 	(void) unlink(reclock);
37241234Sbostic }
37341234Sbostic 
outheader()37441234Sbostic outheader() {
37541234Sbostic char linebuf[BUFSZ];
37641234Sbostic register char *bp;
37741234Sbostic 	(void) strcpy(linebuf, "Number Points  Name");
37841234Sbostic 	bp = eos(linebuf);
37941234Sbostic 	while(bp < linebuf + COLNO - 9) *bp++ = ' ';
38041234Sbostic 	(void) strcpy(bp, "Hp [max]");
38141234Sbostic 	puts(linebuf);
38241234Sbostic }
38341234Sbostic 
38441234Sbostic /* so>0: standout line; so=0: ordinary line; so<0: no output, return lth */
38541234Sbostic int
outentry(rank,t1,so)38641234Sbostic outentry(rank,t1,so) register struct toptenentry *t1; {
38741234Sbostic boolean quit = FALSE, killed = FALSE, starv = FALSE;
38841234Sbostic char linebuf[BUFSZ];
38941234Sbostic 	linebuf[0] = 0;
39041234Sbostic 	if(rank) Sprintf(eos(linebuf), "%3d", rank);
39141234Sbostic 		else Sprintf(eos(linebuf), "   ");
39241234Sbostic 	Sprintf(eos(linebuf), " %6ld %8s", t1->points, t1->name);
39341234Sbostic 	if(t1->plchar == 'X') Sprintf(eos(linebuf), " ");
39441234Sbostic 	else Sprintf(eos(linebuf), "-%c ", t1->plchar);
39541234Sbostic 	if(!strncmp("escaped", t1->death, 7)) {
39641234Sbostic 	  if(!strcmp(" (with amulet)", t1->death+7))
39741234Sbostic 	    Sprintf(eos(linebuf), "escaped the dungeon with amulet");
39841234Sbostic 	  else
39941234Sbostic 	    Sprintf(eos(linebuf), "escaped the dungeon [max level %d]",
40041234Sbostic 	      t1->maxlvl);
40141234Sbostic 	} else {
40241234Sbostic 	  if(!strncmp(t1->death,"quit",4)) {
40341234Sbostic 	    quit = TRUE;
40441234Sbostic 	    if(t1->maxhp < 3*t1->hp && t1->maxlvl < 4)
40541234Sbostic 	  	Sprintf(eos(linebuf), "cravenly gave up");
40641234Sbostic 	    else
40741234Sbostic 		Sprintf(eos(linebuf), "quit");
40841234Sbostic 	  }
40941234Sbostic 	  else if(!strcmp(t1->death,"choked"))
41041234Sbostic 	    Sprintf(eos(linebuf), "choked on %s food",
41141234Sbostic 		(t1->sex == 'F') ? "her" : "his");
41241234Sbostic 	  else if(!strncmp(t1->death,"starv",5))
41341234Sbostic 	    Sprintf(eos(linebuf), "starved to death"), starv = TRUE;
41441234Sbostic 	  else Sprintf(eos(linebuf), "was killed"), killed = TRUE;
41541234Sbostic 	  Sprintf(eos(linebuf), " on%s level %d",
41641234Sbostic 	    (killed || starv) ? "" : " dungeon", t1->level);
41741234Sbostic 	  if(t1->maxlvl != t1->level)
41841234Sbostic 	    Sprintf(eos(linebuf), " [max %d]", t1->maxlvl);
41941234Sbostic 	  if(quit && t1->death[4]) Sprintf(eos(linebuf), t1->death + 4);
42041234Sbostic 	}
42141234Sbostic 	if(killed) Sprintf(eos(linebuf), " by %s%s",
42241234Sbostic 	  (!strncmp(t1->death, "trick", 5) || !strncmp(t1->death, "the ", 4))
42341234Sbostic 		? "" :
42441234Sbostic 	  index(vowels,*t1->death) ? "an " : "a ",
42541234Sbostic 	  t1->death);
42641234Sbostic 	Sprintf(eos(linebuf), ".");
42741234Sbostic 	if(t1->maxhp) {
42841234Sbostic 	  register char *bp = eos(linebuf);
42941234Sbostic 	  char hpbuf[10];
43041234Sbostic 	  int hppos;
43141234Sbostic 	  Sprintf(hpbuf, (t1->hp > 0) ? itoa(t1->hp) : "-");
43241234Sbostic 	  hppos = COLNO - 7 - strlen(hpbuf);
43341234Sbostic 	  if(bp <= linebuf + hppos) {
43441234Sbostic 	    while(bp < linebuf + hppos) *bp++ = ' ';
43541234Sbostic 	    (void) strcpy(bp, hpbuf);
43641234Sbostic 	    Sprintf(eos(bp), " [%d]", t1->maxhp);
43741234Sbostic 	  }
43841234Sbostic 	}
43941234Sbostic 	if(so == 0) puts(linebuf);
44041234Sbostic 	else if(so > 0) {
44141234Sbostic 	  register char *bp = eos(linebuf);
44241234Sbostic 	  if(so >= COLNO) so = COLNO-1;
44341234Sbostic 	  while(bp < linebuf + so) *bp++ = ' ';
44441234Sbostic 	  *bp = 0;
44541234Sbostic 	  standoutbeg();
44641234Sbostic 	  fputs(linebuf,stdout);
44741234Sbostic 	  standoutend();
44841234Sbostic 	  (void) putchar('\n');
44941234Sbostic 	}
45041234Sbostic 	return(strlen(linebuf));
45141234Sbostic }
45241234Sbostic 
45341234Sbostic char *
itoa(a)45441234Sbostic itoa(a) int a; {
45541234Sbostic static char buf[12];
45641234Sbostic 	Sprintf(buf,"%d",a);
45741234Sbostic 	return(buf);
45841234Sbostic }
45941234Sbostic 
46041234Sbostic char *
ordin(n)46141234Sbostic ordin(n) int n; {
46241234Sbostic register int d = n%10;
46341234Sbostic 	return((d==0 || d>3 || n/10==1) ? "th" : (d==1) ? "st" :
46441234Sbostic 		(d==2) ? "nd" : "rd");
46541234Sbostic }
46641234Sbostic 
clearlocks()46741234Sbostic clearlocks(){
46841234Sbostic register x;
46941234Sbostic 	(void) signal(SIGHUP,SIG_IGN);
47041234Sbostic 	for(x = maxdlevel; x >= 0; x--) {
47141234Sbostic 		glo(x);
47241234Sbostic 		(void) unlink(lock);	/* not all levels need be present */
47341234Sbostic 	}
47441234Sbostic }
47541234Sbostic 
47641234Sbostic #ifdef NOSAVEONHANGUP
hangup()47741234Sbostic hangup()
47841234Sbostic {
47941234Sbostic 	(void) signal(SIGINT, SIG_IGN);
48041234Sbostic 	clearlocks();
48141234Sbostic 	exit(1);
48241234Sbostic }
48341234Sbostic #endif NOSAVEONHANGUP
48441234Sbostic 
48541234Sbostic char *
eos(s)48641234Sbostic eos(s)
48741234Sbostic register char *s;
48841234Sbostic {
48941234Sbostic 	while(*s) s++;
49041234Sbostic 	return(s);
49141234Sbostic }
49241234Sbostic 
49341234Sbostic /* it is the callers responsibility to check that there is room for c */
charcat(s,c)49441234Sbostic charcat(s,c) register char *s, c; {
49541234Sbostic 	while(*s) s++;
49641234Sbostic 	*s++ = c;
49741234Sbostic 	*s = 0;
49841234Sbostic }
49941234Sbostic 
50041234Sbostic /*
50141234Sbostic  * Called with args from main if argc >= 0. In this case, list scores as
50241234Sbostic  * requested. Otherwise, find scores for the current player (and list them
50341234Sbostic  * if argc == -1).
50441234Sbostic  */
prscore(argc,argv)50541234Sbostic prscore(argc,argv) int argc; char **argv; {
50641234Sbostic 	extern char *hname;
50741234Sbostic 	char **players;
50841234Sbostic 	int playerct;
50941234Sbostic 	int rank;
51041234Sbostic 	register struct toptenentry *t1, *t2;
51141234Sbostic 	char *recfile = RECORD;
51241234Sbostic 	FILE *rfile;
51341234Sbostic 	register flg = 0;
51441234Sbostic 	register int i;
51541234Sbostic #ifdef nonsense
51641234Sbostic 	long total_score = 0L;
51741234Sbostic 	char totchars[10];
51841234Sbostic 	int totcharct = 0;
51941234Sbostic #endif nonsense
52041234Sbostic 	int outflg = (argc >= -1);
52141234Sbostic #ifdef PERS_IS_UID
52241234Sbostic 	int uid = -1;
52341234Sbostic #else
52441234Sbostic 	char *player0;
52541234Sbostic #endif PERS_IS_UID
52641234Sbostic 
52741234Sbostic 	if(!(rfile = fopen(recfile,"r"))){
52841234Sbostic 		puts("Cannot open record file!");
52941234Sbostic 		return;
53041234Sbostic 	}
53141234Sbostic 
53241234Sbostic 	if(argc > 1 && !strncmp(argv[1], "-s", 2)){
53341234Sbostic 		if(!argv[1][2]){
53441234Sbostic 			argc--;
53541234Sbostic 			argv++;
53641234Sbostic 		} else if(!argv[1][3] && index("CFKSTWX", argv[1][2])) {
53741234Sbostic 			argv[1]++;
53841234Sbostic 			argv[1][0] = '-';
53941234Sbostic 		} else	argv[1] += 2;
54041234Sbostic 	}
54141234Sbostic 	if(argc <= 1){
54241234Sbostic #ifdef PERS_IS_UID
54341234Sbostic 		uid = getuid();
54441234Sbostic 		playerct = 0;
54541234Sbostic #else
54641234Sbostic 		player0 = plname;
54741234Sbostic 		if(!*player0)
54841234Sbostic 			player0 = "hackplayer";
54941234Sbostic 		playerct = 1;
55041234Sbostic 		players = &player0;
55141234Sbostic #endif PERS_IS_UID
55241234Sbostic 	} else {
55341234Sbostic 		playerct = --argc;
55441234Sbostic 		players = ++argv;
55541234Sbostic 	}
55641234Sbostic 	if(outflg) putchar('\n');
55741234Sbostic 
55841234Sbostic 	t1 = tt_head = newttentry();
55941234Sbostic 	for(rank = 1; ; rank++) {
56041234Sbostic 	  if(fscanf(rfile, "%6s %d %d %d %d %d %ld %c%c %[^,],%[^\n]",
56141234Sbostic 		t1->date, &t1->uid,
56241234Sbostic 		&t1->level, &t1->maxlvl,
56341234Sbostic 		&t1->hp, &t1->maxhp, &t1->points,
56441234Sbostic 		&t1->plchar, &t1->sex, t1->name, t1->death) != 11)
56541234Sbostic 			t1->points = 0;
56641234Sbostic 	  if(t1->points == 0) break;
56741234Sbostic #ifdef PERS_IS_UID
56841234Sbostic 	  if(!playerct && t1->uid == uid)
56941234Sbostic 		flg++;
57041234Sbostic 	  else
57141234Sbostic #endif PERS_IS_UID
57241234Sbostic 	  for(i = 0; i < playerct; i++){
57341234Sbostic 		if(strcmp(players[i], "all") == 0 ||
57441234Sbostic 		   strncmp(t1->name, players[i], NAMSZ) == 0 ||
57541234Sbostic 		  (players[i][0] == '-' &&
57641234Sbostic 		   players[i][1] == t1->plchar &&
57741234Sbostic 		   players[i][2] == 0) ||
57841234Sbostic 		  (digit(players[i][0]) && rank <= atoi(players[i])))
57941234Sbostic 			flg++;
58041234Sbostic 	  }
58141234Sbostic 	  t1 = t1->tt_next = newttentry();
58241234Sbostic 	}
58341234Sbostic 	(void) fclose(rfile);
58441234Sbostic 	if(!flg) {
58541234Sbostic 	    if(outflg) {
58641234Sbostic 		printf("Cannot find any entries for ");
58741234Sbostic 		if(playerct < 1) printf("you.\n");
58841234Sbostic 		else {
58941234Sbostic 		  if(playerct > 1) printf("any of ");
59041234Sbostic 		  for(i=0; i<playerct; i++)
59141234Sbostic 			printf("%s%s", players[i], (i<playerct-1)?", ":".\n");
59241234Sbostic 		  printf("Call is: %s -s [playernames]\n", hname);
59341234Sbostic 		}
59441234Sbostic 	    }
59541234Sbostic 	    return;
59641234Sbostic 	}
59741234Sbostic 
59841234Sbostic 	if(outflg) outheader();
59941234Sbostic 	t1 = tt_head;
60041234Sbostic 	for(rank = 1; t1->points != 0; rank++, t1 = t2) {
60141234Sbostic 		t2 = t1->tt_next;
60241234Sbostic #ifdef PERS_IS_UID
60341234Sbostic 		if(!playerct && t1->uid == uid)
60441234Sbostic 			goto outwithit;
60541234Sbostic 		else
60641234Sbostic #endif PERS_IS_UID
60741234Sbostic 		for(i = 0; i < playerct; i++){
60841234Sbostic 			if(strcmp(players[i], "all") == 0 ||
60941234Sbostic 			   strncmp(t1->name, players[i], NAMSZ) == 0 ||
61041234Sbostic 			  (players[i][0] == '-' &&
61141234Sbostic 			   players[i][1] == t1->plchar &&
61241234Sbostic 			   players[i][2] == 0) ||
61341234Sbostic 			  (digit(players[i][0]) && rank <= atoi(players[i]))){
61441234Sbostic 			outwithit:
61541234Sbostic 				if(outflg)
61641234Sbostic 				    (void) outentry(rank, t1, 0);
61741234Sbostic #ifdef nonsense
61841234Sbostic 				total_score += t1->points;
61941234Sbostic 				if(totcharct < sizeof(totchars)-1)
62041234Sbostic 				    totchars[totcharct++] = t1->plchar;
62141234Sbostic #endif nonsense
62241234Sbostic 				break;
62341234Sbostic 			}
62441234Sbostic 		}
62541234Sbostic 		free((char *) t1);
62641234Sbostic 	}
62741234Sbostic #ifdef nonsense
62841234Sbostic 	totchars[totcharct] = 0;
62941234Sbostic 
63041234Sbostic 	/* We would like to determine whether he is experienced. However,
63141234Sbostic 	   the information collected here only tells about the scores/roles
63241234Sbostic 	   that got into the topten (top 100?). We should maintain a
63341234Sbostic 	   .hacklog or something in his home directory. */
63441234Sbostic 	flags.beginner = (total_score < 6000);
63541234Sbostic 	for(i=0; i<6; i++)
63641234Sbostic 	    if(!index(totchars, "CFKSTWX"[i])) {
63741234Sbostic 		flags.beginner = 1;
63841234Sbostic 		if(!pl_character[0]) pl_character[0] = "CFKSTWX"[i];
63941234Sbostic 		break;
64041234Sbostic 	}
64141234Sbostic #endif nonsense
64241234Sbostic }
643