Home | History | Annotate | Line # | Download | only in hack
hack.end.c revision 1.1
      1  1.1  cgd /* Copyright (c) Stichting Mathematisch Centrum, Amsterdam, 1985. */
      2  1.1  cgd /* hack.end.c - version 1.0.3 */
      3  1.1  cgd 
      4  1.1  cgd #include "hack.h"
      5  1.1  cgd #include <stdio.h>
      6  1.1  cgd #include <signal.h>
      7  1.1  cgd #define	Sprintf	(void) sprintf
      8  1.1  cgd extern char plname[], pl_character[];
      9  1.1  cgd extern char *itoa(), *ordin(), *eos();
     10  1.1  cgd 
     11  1.1  cgd xchar maxdlevel = 1;
     12  1.1  cgd 
     13  1.1  cgd void
     14  1.1  cgd done1()
     15  1.1  cgd {
     16  1.1  cgd 	(void) signal(SIGINT,SIG_IGN);
     17  1.1  cgd 	pline("Really quit?");
     18  1.1  cgd 	if(readchar() != 'y') {
     19  1.1  cgd 		(void) signal(SIGINT,done1);
     20  1.1  cgd 		clrlin();
     21  1.1  cgd 		(void) fflush(stdout);
     22  1.1  cgd 		if(multi > 0) nomul(0);
     23  1.1  cgd 		return;
     24  1.1  cgd 	}
     25  1.1  cgd 	done("quit");
     26  1.1  cgd 	/* NOTREACHED */
     27  1.1  cgd }
     28  1.1  cgd 
     29  1.1  cgd int done_stopprint;
     30  1.1  cgd int done_hup;
     31  1.1  cgd 
     32  1.1  cgd void
     33  1.1  cgd done_intr(){
     34  1.1  cgd 	done_stopprint++;
     35  1.1  cgd 	(void) signal(SIGINT, SIG_IGN);
     36  1.1  cgd 	(void) signal(SIGQUIT, SIG_IGN);
     37  1.1  cgd }
     38  1.1  cgd 
     39  1.1  cgd void
     40  1.1  cgd done_hangup(){
     41  1.1  cgd 	done_hup++;
     42  1.1  cgd 	(void) signal(SIGHUP, SIG_IGN);
     43  1.1  cgd 	done_intr();
     44  1.1  cgd }
     45  1.1  cgd 
     46  1.1  cgd done_in_by(mtmp) register struct monst *mtmp; {
     47  1.1  cgd static char buf[BUFSZ];
     48  1.1  cgd 	pline("You die ...");
     49  1.1  cgd 	if(mtmp->data->mlet == ' '){
     50  1.1  cgd 		Sprintf(buf, "the ghost of %s", (char *) mtmp->mextra);
     51  1.1  cgd 		killer = buf;
     52  1.1  cgd 	} else if(mtmp->mnamelth) {
     53  1.1  cgd 		Sprintf(buf, "%s called %s",
     54  1.1  cgd 			mtmp->data->mname, NAME(mtmp));
     55  1.1  cgd 		killer = buf;
     56  1.1  cgd 	} else if(mtmp->minvis) {
     57  1.1  cgd 		Sprintf(buf, "invisible %s", mtmp->data->mname);
     58  1.1  cgd 		killer = buf;
     59  1.1  cgd 	} else killer = mtmp->data->mname;
     60  1.1  cgd 	done("died");
     61  1.1  cgd }
     62  1.1  cgd 
     63  1.1  cgd /* called with arg "died", "drowned", "escaped", "quit", "choked", "panicked",
     64  1.1  cgd    "burned", "starved" or "tricked" */
     65  1.1  cgd /* Be careful not to call panic from here! */
     66  1.1  cgd done(st1)
     67  1.1  cgd register char *st1;
     68  1.1  cgd {
     69  1.1  cgd 
     70  1.1  cgd #ifdef WIZARD
     71  1.1  cgd 	if(wizard && *st1 == 'd'){
     72  1.1  cgd 		u.uswldtim = 0;
     73  1.1  cgd 		if(u.uhpmax < 0) u.uhpmax = 100;	/* arbitrary */
     74  1.1  cgd 		u.uhp = u.uhpmax;
     75  1.1  cgd 		pline("For some reason you are still alive.");
     76  1.1  cgd 		flags.move = 0;
     77  1.1  cgd 		if(multi > 0) multi = 0; else multi = -1;
     78  1.1  cgd 		flags.botl = 1;
     79  1.1  cgd 		return;
     80  1.1  cgd 	}
     81  1.1  cgd #endif WIZARD
     82  1.1  cgd 	(void) signal(SIGINT, done_intr);
     83  1.1  cgd 	(void) signal(SIGQUIT, done_intr);
     84  1.1  cgd 	(void) signal(SIGHUP, done_hangup);
     85  1.1  cgd 	if(*st1 == 'q' && u.uhp < 1){
     86  1.1  cgd 		st1 = "died";
     87  1.1  cgd 		killer = "quit while already on Charon's boat";
     88  1.1  cgd 	}
     89  1.1  cgd 	if(*st1 == 's') killer = "starvation"; else
     90  1.1  cgd 	if(*st1 == 'd' && st1[1] == 'r') killer = "drowning"; else
     91  1.1  cgd 	if(*st1 == 'p') killer = "panic"; else
     92  1.1  cgd 	if(*st1 == 't') killer = "trickery"; else
     93  1.1  cgd 	if(!index("bcd", *st1)) killer = st1;
     94  1.1  cgd 	paybill();
     95  1.1  cgd 	clearlocks();
     96  1.1  cgd 	if(flags.toplin == 1) more();
     97  1.1  cgd 	if(index("bcds", *st1)){
     98  1.1  cgd #ifdef WIZARD
     99  1.1  cgd 	    if(!wizard)
    100  1.1  cgd #endif WIZARD
    101  1.1  cgd 		savebones();
    102  1.1  cgd 		if(!flags.notombstone)
    103  1.1  cgd 			outrip();
    104  1.1  cgd 	}
    105  1.1  cgd 	if(*st1 == 'c') killer = st1;		/* after outrip() */
    106  1.1  cgd 	settty((char *) 0);	/* does a clear_screen() */
    107  1.1  cgd 	if(!done_stopprint)
    108  1.1  cgd 		printf("Goodbye %s %s...\n\n", pl_character, plname);
    109  1.1  cgd 	{ long int tmp;
    110  1.1  cgd 	  tmp = u.ugold - u.ugold0;
    111  1.1  cgd 	  if(tmp < 0)
    112  1.1  cgd 		tmp = 0;
    113  1.1  cgd 	  if(*st1 == 'd' || *st1 == 'b')
    114  1.1  cgd 		tmp -= tmp/10;
    115  1.1  cgd 	  u.urexp += tmp;
    116  1.1  cgd 	  u.urexp += 50 * maxdlevel;
    117  1.1  cgd 	  if(maxdlevel > 20)
    118  1.1  cgd 		u.urexp += 1000*((maxdlevel > 30) ? 10 : maxdlevel - 20);
    119  1.1  cgd 	}
    120  1.1  cgd 	if(*st1 == 'e') {
    121  1.1  cgd 		extern struct monst *mydogs;
    122  1.1  cgd 		register struct monst *mtmp;
    123  1.1  cgd 		register struct obj *otmp;
    124  1.1  cgd 		register int i;
    125  1.1  cgd 		register unsigned worthlessct = 0;
    126  1.1  cgd 		boolean has_amulet = FALSE;
    127  1.1  cgd 
    128  1.1  cgd 		killer = st1;
    129  1.1  cgd 		keepdogs();
    130  1.1  cgd 		mtmp = mydogs;
    131  1.1  cgd 		if(mtmp) {
    132  1.1  cgd 			if(!done_stopprint) printf("You");
    133  1.1  cgd 			while(mtmp) {
    134  1.1  cgd 				if(!done_stopprint)
    135  1.1  cgd 					printf(" and %s", monnam(mtmp));
    136  1.1  cgd 				if(mtmp->mtame)
    137  1.1  cgd 					u.urexp += mtmp->mhp;
    138  1.1  cgd 				mtmp = mtmp->nmon;
    139  1.1  cgd 			}
    140  1.1  cgd 			if(!done_stopprint)
    141  1.1  cgd 		    printf("\nescaped from the dungeon with %ld points,\n",
    142  1.1  cgd 			u.urexp);
    143  1.1  cgd 		} else
    144  1.1  cgd 		if(!done_stopprint)
    145  1.1  cgd 		  printf("You escaped from the dungeon with %ld points,\n",
    146  1.1  cgd 		    u.urexp);
    147  1.1  cgd 		for(otmp = invent; otmp; otmp = otmp->nobj) {
    148  1.1  cgd 			if(otmp->olet == GEM_SYM){
    149  1.1  cgd 				objects[otmp->otyp].oc_name_known = 1;
    150  1.1  cgd 				i = otmp->quan*objects[otmp->otyp].g_val;
    151  1.1  cgd 				if(i == 0) {
    152  1.1  cgd 					worthlessct += otmp->quan;
    153  1.1  cgd 					continue;
    154  1.1  cgd 				}
    155  1.1  cgd 				u.urexp += i;
    156  1.1  cgd 				if(!done_stopprint)
    157  1.1  cgd 				  printf("\t%s (worth %d Zorkmids),\n",
    158  1.1  cgd 				    doname(otmp), i);
    159  1.1  cgd 			} else if(otmp->olet == AMULET_SYM) {
    160  1.1  cgd 				otmp->known = 1;
    161  1.1  cgd 				i = (otmp->spe < 0) ? 2 : 5000;
    162  1.1  cgd 				u.urexp += i;
    163  1.1  cgd 				if(!done_stopprint)
    164  1.1  cgd 				  printf("\t%s (worth %d Zorkmids),\n",
    165  1.1  cgd 				    doname(otmp), i);
    166  1.1  cgd 				if(otmp->spe >= 0) {
    167  1.1  cgd 					has_amulet = TRUE;
    168  1.1  cgd 					killer = "escaped (with amulet)";
    169  1.1  cgd 				}
    170  1.1  cgd 			}
    171  1.1  cgd 		}
    172  1.1  cgd 		if(worthlessct) if(!done_stopprint)
    173  1.1  cgd 		  printf("\t%u worthless piece%s of coloured glass,\n",
    174  1.1  cgd 		  worthlessct, plur(worthlessct));
    175  1.1  cgd 		if(has_amulet) u.urexp *= 2;
    176  1.1  cgd 	} else
    177  1.1  cgd 		if(!done_stopprint)
    178  1.1  cgd 		  printf("You %s on dungeon level %d with %ld points,\n",
    179  1.1  cgd 		    st1, dlevel, u.urexp);
    180  1.1  cgd 	if(!done_stopprint)
    181  1.1  cgd 	  printf("and %ld piece%s of gold, after %ld move%s.\n",
    182  1.1  cgd 	    u.ugold, plur(u.ugold), moves, plur(moves));
    183  1.1  cgd 	if(!done_stopprint)
    184  1.1  cgd   printf("You were level %u with a maximum of %d hit points when you %s.\n",
    185  1.1  cgd 	    u.ulevel, u.uhpmax, st1);
    186  1.1  cgd 	if(*st1 == 'e' && !done_stopprint){
    187  1.1  cgd 		getret();	/* all those pieces of coloured glass ... */
    188  1.1  cgd 		cls();
    189  1.1  cgd 	}
    190  1.1  cgd #ifdef WIZARD
    191  1.1  cgd 	if(!wizard)
    192  1.1  cgd #endif WIZARD
    193  1.1  cgd 		topten();
    194  1.1  cgd 	if(done_stopprint) printf("\n\n");
    195  1.1  cgd 	exit(0);
    196  1.1  cgd }
    197  1.1  cgd 
    198  1.1  cgd #define newttentry() (struct toptenentry *) alloc(sizeof(struct toptenentry))
    199  1.1  cgd #define	NAMSZ	8
    200  1.1  cgd #define	DTHSZ	40
    201  1.1  cgd #define	PERSMAX	1
    202  1.1  cgd #define	POINTSMIN	1	/* must be > 0 */
    203  1.1  cgd #define	ENTRYMAX	100	/* must be >= 10 */
    204  1.1  cgd #define	PERS_IS_UID		/* delete for PERSMAX per name; now per uid */
    205  1.1  cgd struct toptenentry {
    206  1.1  cgd 	struct toptenentry *tt_next;
    207  1.1  cgd 	long int points;
    208  1.1  cgd 	int level,maxlvl,hp,maxhp;
    209  1.1  cgd 	int uid;
    210  1.1  cgd 	char plchar;
    211  1.1  cgd 	char sex;
    212  1.1  cgd 	char name[NAMSZ+1];
    213  1.1  cgd 	char death[DTHSZ+1];
    214  1.1  cgd 	char date[7];		/* yymmdd */
    215  1.1  cgd } *tt_head;
    216  1.1  cgd 
    217  1.1  cgd topten(){
    218  1.1  cgd 	int uid = getuid();
    219  1.1  cgd 	int rank, rank0 = -1, rank1 = 0;
    220  1.1  cgd 	int occ_cnt = PERSMAX;
    221  1.1  cgd 	register struct toptenentry *t0, *t1, *tprev;
    222  1.1  cgd 	char *recfile = RECORD;
    223  1.1  cgd 	char *reclock = "record_lock";
    224  1.1  cgd 	int sleepct = 300;
    225  1.1  cgd 	FILE *rfile;
    226  1.1  cgd 	register flg = 0;
    227  1.1  cgd 	extern char *getdate();
    228  1.1  cgd #define	HUP	if(!done_hup)
    229  1.1  cgd 	while(link(recfile, reclock) == -1) {
    230  1.1  cgd 		HUP perror(reclock);
    231  1.1  cgd 		if(!sleepct--) {
    232  1.1  cgd 			HUP puts("I give up. Sorry.");
    233  1.1  cgd 			HUP puts("Perhaps there is an old record_lock around?");
    234  1.1  cgd 			return;
    235  1.1  cgd 		}
    236  1.1  cgd 		HUP printf("Waiting for access to record file. (%d)\n",
    237  1.1  cgd 			sleepct);
    238  1.1  cgd 		HUP (void) fflush(stdout);
    239  1.1  cgd 		sleep(1);
    240  1.1  cgd 	}
    241  1.1  cgd 	if(!(rfile = fopen(recfile,"r"))){
    242  1.1  cgd 		HUP puts("Cannot open record file!");
    243  1.1  cgd 		goto unlock;
    244  1.1  cgd 	}
    245  1.1  cgd 	HUP (void) putchar('\n');
    246  1.1  cgd 
    247  1.1  cgd 	/* create a new 'topten' entry */
    248  1.1  cgd 	t0 = newttentry();
    249  1.1  cgd 	t0->level = dlevel;
    250  1.1  cgd 	t0->maxlvl = maxdlevel;
    251  1.1  cgd 	t0->hp = u.uhp;
    252  1.1  cgd 	t0->maxhp = u.uhpmax;
    253  1.1  cgd 	t0->points = u.urexp;
    254  1.1  cgd 	t0->plchar = pl_character[0];
    255  1.1  cgd 	t0->sex = (flags.female ? 'F' : 'M');
    256  1.1  cgd 	t0->uid = uid;
    257  1.1  cgd 	(void) strncpy(t0->name, plname, NAMSZ);
    258  1.1  cgd 	(t0->name)[NAMSZ] = 0;
    259  1.1  cgd 	(void) strncpy(t0->death, killer, DTHSZ);
    260  1.1  cgd 	(t0->death)[DTHSZ] = 0;
    261  1.1  cgd 	(void) strcpy(t0->date, getdate());
    262  1.1  cgd 
    263  1.1  cgd 	/* assure minimum number of points */
    264  1.1  cgd 	if(t0->points < POINTSMIN)
    265  1.1  cgd 		t0->points = 0;
    266  1.1  cgd 
    267  1.1  cgd 	t1 = tt_head = newttentry();
    268  1.1  cgd 	tprev = 0;
    269  1.1  cgd 	/* rank0: -1 undefined, 0 not_on_list, n n_th on list */
    270  1.1  cgd 	for(rank = 1; ; ) {
    271  1.1  cgd 	  if(fscanf(rfile, "%6s %d %d %d %d %d %ld %c%c %[^,],%[^\n]",
    272  1.1  cgd 		t1->date, &t1->uid,
    273  1.1  cgd 		&t1->level, &t1->maxlvl,
    274  1.1  cgd 		&t1->hp, &t1->maxhp, &t1->points,
    275  1.1  cgd 		&t1->plchar, &t1->sex, t1->name, t1->death) != 11
    276  1.1  cgd 	  || t1->points < POINTSMIN)
    277  1.1  cgd 			t1->points = 0;
    278  1.1  cgd 	  if(rank0 < 0 && t1->points < t0->points) {
    279  1.1  cgd 		rank0 = rank++;
    280  1.1  cgd 		if(tprev == 0)
    281  1.1  cgd 			tt_head = t0;
    282  1.1  cgd 		else
    283  1.1  cgd 			tprev->tt_next = t0;
    284  1.1  cgd 		t0->tt_next = t1;
    285  1.1  cgd 		occ_cnt--;
    286  1.1  cgd 		flg++;		/* ask for a rewrite */
    287  1.1  cgd 	  } else
    288  1.1  cgd 		tprev = t1;
    289  1.1  cgd 	  if(t1->points == 0) break;
    290  1.1  cgd 	  if(
    291  1.1  cgd #ifdef PERS_IS_UID
    292  1.1  cgd 	     t1->uid == t0->uid &&
    293  1.1  cgd #else
    294  1.1  cgd 	     strncmp(t1->name, t0->name, NAMSZ) == 0 &&
    295  1.1  cgd #endif PERS_IS_UID
    296  1.1  cgd 	     t1->plchar == t0->plchar && --occ_cnt <= 0){
    297  1.1  cgd 		if(rank0 < 0){
    298  1.1  cgd 			rank0 = 0;
    299  1.1  cgd 			rank1 = rank;
    300  1.1  cgd 	HUP printf("You didn't beat your previous score of %ld points.\n\n",
    301  1.1  cgd 				t1->points);
    302  1.1  cgd 		}
    303  1.1  cgd 		if(occ_cnt < 0){
    304  1.1  cgd 			flg++;
    305  1.1  cgd 			continue;
    306  1.1  cgd 		}
    307  1.1  cgd 	  }
    308  1.1  cgd 	  if(rank <= ENTRYMAX){
    309  1.1  cgd 	  	t1 = t1->tt_next = newttentry();
    310  1.1  cgd 	  	rank++;
    311  1.1  cgd 	  }
    312  1.1  cgd 	  if(rank > ENTRYMAX){
    313  1.1  cgd 		t1->points = 0;
    314  1.1  cgd 		break;
    315  1.1  cgd 	  }
    316  1.1  cgd 	}
    317  1.1  cgd 	if(flg) {	/* rewrite record file */
    318  1.1  cgd 		(void) fclose(rfile);
    319  1.1  cgd 		if(!(rfile = fopen(recfile,"w"))){
    320  1.1  cgd 			HUP puts("Cannot write record file\n");
    321  1.1  cgd 			goto unlock;
    322  1.1  cgd 		}
    323  1.1  cgd 
    324  1.1  cgd 		if(!done_stopprint) if(rank0 > 0){
    325  1.1  cgd 		    if(rank0 <= 10)
    326  1.1  cgd 			puts("You made the top ten list!\n");
    327  1.1  cgd 		    else
    328  1.1  cgd 		printf("You reached the %d%s place on the top %d list.\n\n",
    329  1.1  cgd 			rank0, ordin(rank0), ENTRYMAX);
    330  1.1  cgd 		}
    331  1.1  cgd 	}
    332  1.1  cgd 	if(rank0 == 0) rank0 = rank1;
    333  1.1  cgd 	if(rank0 <= 0) rank0 = rank;
    334  1.1  cgd 	if(!done_stopprint) outheader();
    335  1.1  cgd 	t1 = tt_head;
    336  1.1  cgd 	for(rank = 1; t1->points != 0; rank++, t1 = t1->tt_next) {
    337  1.1  cgd 	  if(flg) fprintf(rfile,"%6s %d %d %d %d %d %ld %c%c %s,%s\n",
    338  1.1  cgd 	    t1->date, t1->uid,
    339  1.1  cgd 	    t1->level, t1->maxlvl,
    340  1.1  cgd 	    t1->hp, t1->maxhp, t1->points,
    341  1.1  cgd 	    t1->plchar, t1->sex, t1->name, t1->death);
    342  1.1  cgd 	  if(done_stopprint) continue;
    343  1.1  cgd 	  if(rank > flags.end_top &&
    344  1.1  cgd 	    (rank < rank0-flags.end_around || rank > rank0+flags.end_around)
    345  1.1  cgd 	    && (!flags.end_own ||
    346  1.1  cgd #ifdef PERS_IS_UID
    347  1.1  cgd 				  t1->uid != t0->uid ))
    348  1.1  cgd #else
    349  1.1  cgd 				  strncmp(t1->name, t0->name, NAMSZ)))
    350  1.1  cgd #endif PERS_IS_UID
    351  1.1  cgd 	  	continue;
    352  1.1  cgd 	  if(rank == rank0-flags.end_around &&
    353  1.1  cgd 	     rank0 > flags.end_top+flags.end_around+1 &&
    354  1.1  cgd 	     !flags.end_own)
    355  1.1  cgd 		(void) putchar('\n');
    356  1.1  cgd 	  if(rank != rank0)
    357  1.1  cgd 		(void) outentry(rank, t1, 0);
    358  1.1  cgd 	  else if(!rank1)
    359  1.1  cgd 		(void) outentry(rank, t1, 1);
    360  1.1  cgd 	  else {
    361  1.1  cgd 		int t0lth = outentry(0, t0, -1);
    362  1.1  cgd 		int t1lth = outentry(rank, t1, t0lth);
    363  1.1  cgd 		if(t1lth > t0lth) t0lth = t1lth;
    364  1.1  cgd 		(void) outentry(0, t0, t0lth);
    365  1.1  cgd 	  }
    366  1.1  cgd 	}
    367  1.1  cgd 	if(rank0 >= rank) if(!done_stopprint)
    368  1.1  cgd 		(void) outentry(0, t0, 1);
    369  1.1  cgd 	(void) fclose(rfile);
    370  1.1  cgd unlock:
    371  1.1  cgd 	(void) unlink(reclock);
    372  1.1  cgd }
    373  1.1  cgd 
    374  1.1  cgd outheader() {
    375  1.1  cgd char linebuf[BUFSZ];
    376  1.1  cgd register char *bp;
    377  1.1  cgd 	(void) strcpy(linebuf, "Number Points  Name");
    378  1.1  cgd 	bp = eos(linebuf);
    379  1.1  cgd 	while(bp < linebuf + COLNO - 9) *bp++ = ' ';
    380  1.1  cgd 	(void) strcpy(bp, "Hp [max]");
    381  1.1  cgd 	puts(linebuf);
    382  1.1  cgd }
    383  1.1  cgd 
    384  1.1  cgd /* so>0: standout line; so=0: ordinary line; so<0: no output, return lth */
    385  1.1  cgd int
    386  1.1  cgd outentry(rank,t1,so) register struct toptenentry *t1; {
    387  1.1  cgd boolean quit = FALSE, killed = FALSE, starv = FALSE;
    388  1.1  cgd char linebuf[BUFSZ];
    389  1.1  cgd 	linebuf[0] = 0;
    390  1.1  cgd 	if(rank) Sprintf(eos(linebuf), "%3d", rank);
    391  1.1  cgd 		else Sprintf(eos(linebuf), "   ");
    392  1.1  cgd 	Sprintf(eos(linebuf), " %6ld %8s", t1->points, t1->name);
    393  1.1  cgd 	if(t1->plchar == 'X') Sprintf(eos(linebuf), " ");
    394  1.1  cgd 	else Sprintf(eos(linebuf), "-%c ", t1->plchar);
    395  1.1  cgd 	if(!strncmp("escaped", t1->death, 7)) {
    396  1.1  cgd 	  if(!strcmp(" (with amulet)", t1->death+7))
    397  1.1  cgd 	    Sprintf(eos(linebuf), "escaped the dungeon with amulet");
    398  1.1  cgd 	  else
    399  1.1  cgd 	    Sprintf(eos(linebuf), "escaped the dungeon [max level %d]",
    400  1.1  cgd 	      t1->maxlvl);
    401  1.1  cgd 	} else {
    402  1.1  cgd 	  if(!strncmp(t1->death,"quit",4)) {
    403  1.1  cgd 	    quit = TRUE;
    404  1.1  cgd 	    if(t1->maxhp < 3*t1->hp && t1->maxlvl < 4)
    405  1.1  cgd 	  	Sprintf(eos(linebuf), "cravenly gave up");
    406  1.1  cgd 	    else
    407  1.1  cgd 		Sprintf(eos(linebuf), "quit");
    408  1.1  cgd 	  }
    409  1.1  cgd 	  else if(!strcmp(t1->death,"choked"))
    410  1.1  cgd 	    Sprintf(eos(linebuf), "choked on %s food",
    411  1.1  cgd 		(t1->sex == 'F') ? "her" : "his");
    412  1.1  cgd 	  else if(!strncmp(t1->death,"starv",5))
    413  1.1  cgd 	    Sprintf(eos(linebuf), "starved to death"), starv = TRUE;
    414  1.1  cgd 	  else Sprintf(eos(linebuf), "was killed"), killed = TRUE;
    415  1.1  cgd 	  Sprintf(eos(linebuf), " on%s level %d",
    416  1.1  cgd 	    (killed || starv) ? "" : " dungeon", t1->level);
    417  1.1  cgd 	  if(t1->maxlvl != t1->level)
    418  1.1  cgd 	    Sprintf(eos(linebuf), " [max %d]", t1->maxlvl);
    419  1.1  cgd 	  if(quit && t1->death[4]) Sprintf(eos(linebuf), t1->death + 4);
    420  1.1  cgd 	}
    421  1.1  cgd 	if(killed) Sprintf(eos(linebuf), " by %s%s",
    422  1.1  cgd 	  (!strncmp(t1->death, "trick", 5) || !strncmp(t1->death, "the ", 4))
    423  1.1  cgd 		? "" :
    424  1.1  cgd 	  index(vowels,*t1->death) ? "an " : "a ",
    425  1.1  cgd 	  t1->death);
    426  1.1  cgd 	Sprintf(eos(linebuf), ".");
    427  1.1  cgd 	if(t1->maxhp) {
    428  1.1  cgd 	  register char *bp = eos(linebuf);
    429  1.1  cgd 	  char hpbuf[10];
    430  1.1  cgd 	  int hppos;
    431  1.1  cgd 	  Sprintf(hpbuf, (t1->hp > 0) ? itoa(t1->hp) : "-");
    432  1.1  cgd 	  hppos = COLNO - 7 - strlen(hpbuf);
    433  1.1  cgd 	  if(bp <= linebuf + hppos) {
    434  1.1  cgd 	    while(bp < linebuf + hppos) *bp++ = ' ';
    435  1.1  cgd 	    (void) strcpy(bp, hpbuf);
    436  1.1  cgd 	    Sprintf(eos(bp), " [%d]", t1->maxhp);
    437  1.1  cgd 	  }
    438  1.1  cgd 	}
    439  1.1  cgd 	if(so == 0) puts(linebuf);
    440  1.1  cgd 	else if(so > 0) {
    441  1.1  cgd 	  register char *bp = eos(linebuf);
    442  1.1  cgd 	  if(so >= COLNO) so = COLNO-1;
    443  1.1  cgd 	  while(bp < linebuf + so) *bp++ = ' ';
    444  1.1  cgd 	  *bp = 0;
    445  1.1  cgd 	  standoutbeg();
    446  1.1  cgd 	  fputs(linebuf,stdout);
    447  1.1  cgd 	  standoutend();
    448  1.1  cgd 	  (void) putchar('\n');
    449  1.1  cgd 	}
    450  1.1  cgd 	return(strlen(linebuf));
    451  1.1  cgd }
    452  1.1  cgd 
    453  1.1  cgd char *
    454  1.1  cgd itoa(a) int a; {
    455  1.1  cgd static char buf[12];
    456  1.1  cgd 	Sprintf(buf,"%d",a);
    457  1.1  cgd 	return(buf);
    458  1.1  cgd }
    459  1.1  cgd 
    460  1.1  cgd char *
    461  1.1  cgd ordin(n) int n; {
    462  1.1  cgd register int d = n%10;
    463  1.1  cgd 	return((d==0 || d>3 || n/10==1) ? "th" : (d==1) ? "st" :
    464  1.1  cgd 		(d==2) ? "nd" : "rd");
    465  1.1  cgd }
    466  1.1  cgd 
    467  1.1  cgd clearlocks(){
    468  1.1  cgd register x;
    469  1.1  cgd 	(void) signal(SIGHUP,SIG_IGN);
    470  1.1  cgd 	for(x = maxdlevel; x >= 0; x--) {
    471  1.1  cgd 		glo(x);
    472  1.1  cgd 		(void) unlink(lock);	/* not all levels need be present */
    473  1.1  cgd 	}
    474  1.1  cgd }
    475  1.1  cgd 
    476  1.1  cgd #ifdef NOSAVEONHANGUP
    477  1.1  cgd hangup()
    478  1.1  cgd {
    479  1.1  cgd 	(void) signal(SIGINT, SIG_IGN);
    480  1.1  cgd 	clearlocks();
    481  1.1  cgd 	exit(1);
    482  1.1  cgd }
    483  1.1  cgd #endif NOSAVEONHANGUP
    484  1.1  cgd 
    485  1.1  cgd char *
    486  1.1  cgd eos(s)
    487  1.1  cgd register char *s;
    488  1.1  cgd {
    489  1.1  cgd 	while(*s) s++;
    490  1.1  cgd 	return(s);
    491  1.1  cgd }
    492  1.1  cgd 
    493  1.1  cgd /* it is the callers responsibility to check that there is room for c */
    494  1.1  cgd charcat(s,c) register char *s, c; {
    495  1.1  cgd 	while(*s) s++;
    496  1.1  cgd 	*s++ = c;
    497  1.1  cgd 	*s = 0;
    498  1.1  cgd }
    499  1.1  cgd 
    500  1.1  cgd /*
    501  1.1  cgd  * Called with args from main if argc >= 0. In this case, list scores as
    502  1.1  cgd  * requested. Otherwise, find scores for the current player (and list them
    503  1.1  cgd  * if argc == -1).
    504  1.1  cgd  */
    505  1.1  cgd prscore(argc,argv) int argc; char **argv; {
    506  1.1  cgd 	extern char *hname;
    507  1.1  cgd 	char **players;
    508  1.1  cgd 	int playerct;
    509  1.1  cgd 	int rank;
    510  1.1  cgd 	register struct toptenentry *t1, *t2;
    511  1.1  cgd 	char *recfile = RECORD;
    512  1.1  cgd 	FILE *rfile;
    513  1.1  cgd 	register flg = 0;
    514  1.1  cgd 	register int i;
    515  1.1  cgd #ifdef nonsense
    516  1.1  cgd 	long total_score = 0L;
    517  1.1  cgd 	char totchars[10];
    518  1.1  cgd 	int totcharct = 0;
    519  1.1  cgd #endif nonsense
    520  1.1  cgd 	int outflg = (argc >= -1);
    521  1.1  cgd #ifdef PERS_IS_UID
    522  1.1  cgd 	int uid = -1;
    523  1.1  cgd #else
    524  1.1  cgd 	char *player0;
    525  1.1  cgd #endif PERS_IS_UID
    526  1.1  cgd 
    527  1.1  cgd 	if(!(rfile = fopen(recfile,"r"))){
    528  1.1  cgd 		puts("Cannot open record file!");
    529  1.1  cgd 		return;
    530  1.1  cgd 	}
    531  1.1  cgd 
    532  1.1  cgd 	if(argc > 1 && !strncmp(argv[1], "-s", 2)){
    533  1.1  cgd 		if(!argv[1][2]){
    534  1.1  cgd 			argc--;
    535  1.1  cgd 			argv++;
    536  1.1  cgd 		} else if(!argv[1][3] && index("CFKSTWX", argv[1][2])) {
    537  1.1  cgd 			argv[1]++;
    538  1.1  cgd 			argv[1][0] = '-';
    539  1.1  cgd 		} else	argv[1] += 2;
    540  1.1  cgd 	}
    541  1.1  cgd 	if(argc <= 1){
    542  1.1  cgd #ifdef PERS_IS_UID
    543  1.1  cgd 		uid = getuid();
    544  1.1  cgd 		playerct = 0;
    545  1.1  cgd #else
    546  1.1  cgd 		player0 = plname;
    547  1.1  cgd 		if(!*player0)
    548  1.1  cgd 			player0 = "hackplayer";
    549  1.1  cgd 		playerct = 1;
    550  1.1  cgd 		players = &player0;
    551  1.1  cgd #endif PERS_IS_UID
    552  1.1  cgd 	} else {
    553  1.1  cgd 		playerct = --argc;
    554  1.1  cgd 		players = ++argv;
    555  1.1  cgd 	}
    556  1.1  cgd 	if(outflg) putchar('\n');
    557  1.1  cgd 
    558  1.1  cgd 	t1 = tt_head = newttentry();
    559  1.1  cgd 	for(rank = 1; ; rank++) {
    560  1.1  cgd 	  if(fscanf(rfile, "%6s %d %d %d %d %d %ld %c%c %[^,],%[^\n]",
    561  1.1  cgd 		t1->date, &t1->uid,
    562  1.1  cgd 		&t1->level, &t1->maxlvl,
    563  1.1  cgd 		&t1->hp, &t1->maxhp, &t1->points,
    564  1.1  cgd 		&t1->plchar, &t1->sex, t1->name, t1->death) != 11)
    565  1.1  cgd 			t1->points = 0;
    566  1.1  cgd 	  if(t1->points == 0) break;
    567  1.1  cgd #ifdef PERS_IS_UID
    568  1.1  cgd 	  if(!playerct && t1->uid == uid)
    569  1.1  cgd 		flg++;
    570  1.1  cgd 	  else
    571  1.1  cgd #endif PERS_IS_UID
    572  1.1  cgd 	  for(i = 0; i < playerct; i++){
    573  1.1  cgd 		if(strcmp(players[i], "all") == 0 ||
    574  1.1  cgd 		   strncmp(t1->name, players[i], NAMSZ) == 0 ||
    575  1.1  cgd 		  (players[i][0] == '-' &&
    576  1.1  cgd 		   players[i][1] == t1->plchar &&
    577  1.1  cgd 		   players[i][2] == 0) ||
    578  1.1  cgd 		  (digit(players[i][0]) && rank <= atoi(players[i])))
    579  1.1  cgd 			flg++;
    580  1.1  cgd 	  }
    581  1.1  cgd 	  t1 = t1->tt_next = newttentry();
    582  1.1  cgd 	}
    583  1.1  cgd 	(void) fclose(rfile);
    584  1.1  cgd 	if(!flg) {
    585  1.1  cgd 	    if(outflg) {
    586  1.1  cgd 		printf("Cannot find any entries for ");
    587  1.1  cgd 		if(playerct < 1) printf("you.\n");
    588  1.1  cgd 		else {
    589  1.1  cgd 		  if(playerct > 1) printf("any of ");
    590  1.1  cgd 		  for(i=0; i<playerct; i++)
    591  1.1  cgd 			printf("%s%s", players[i], (i<playerct-1)?", ":".\n");
    592  1.1  cgd 		  printf("Call is: %s -s [playernames]\n", hname);
    593  1.1  cgd 		}
    594  1.1  cgd 	    }
    595  1.1  cgd 	    return;
    596  1.1  cgd 	}
    597  1.1  cgd 
    598  1.1  cgd 	if(outflg) outheader();
    599  1.1  cgd 	t1 = tt_head;
    600  1.1  cgd 	for(rank = 1; t1->points != 0; rank++, t1 = t2) {
    601  1.1  cgd 		t2 = t1->tt_next;
    602  1.1  cgd #ifdef PERS_IS_UID
    603  1.1  cgd 		if(!playerct && t1->uid == uid)
    604  1.1  cgd 			goto outwithit;
    605  1.1  cgd 		else
    606  1.1  cgd #endif PERS_IS_UID
    607  1.1  cgd 		for(i = 0; i < playerct; i++){
    608  1.1  cgd 			if(strcmp(players[i], "all") == 0 ||
    609  1.1  cgd 			   strncmp(t1->name, players[i], NAMSZ) == 0 ||
    610  1.1  cgd 			  (players[i][0] == '-' &&
    611  1.1  cgd 			   players[i][1] == t1->plchar &&
    612  1.1  cgd 			   players[i][2] == 0) ||
    613  1.1  cgd 			  (digit(players[i][0]) && rank <= atoi(players[i]))){
    614  1.1  cgd 			outwithit:
    615  1.1  cgd 				if(outflg)
    616  1.1  cgd 				    (void) outentry(rank, t1, 0);
    617  1.1  cgd #ifdef nonsense
    618  1.1  cgd 				total_score += t1->points;
    619  1.1  cgd 				if(totcharct < sizeof(totchars)-1)
    620  1.1  cgd 				    totchars[totcharct++] = t1->plchar;
    621  1.1  cgd #endif nonsense
    622  1.1  cgd 				break;
    623  1.1  cgd 			}
    624  1.1  cgd 		}
    625  1.1  cgd 		free((char *) t1);
    626  1.1  cgd 	}
    627  1.1  cgd #ifdef nonsense
    628  1.1  cgd 	totchars[totcharct] = 0;
    629  1.1  cgd 
    630  1.1  cgd 	/* We would like to determine whether he is experienced. However,
    631  1.1  cgd 	   the information collected here only tells about the scores/roles
    632  1.1  cgd 	   that got into the topten (top 100?). We should maintain a
    633  1.1  cgd 	   .hacklog or something in his home directory. */
    634  1.1  cgd 	flags.beginner = (total_score < 6000);
    635  1.1  cgd 	for(i=0; i<6; i++)
    636  1.1  cgd 	    if(!index(totchars, "CFKSTWX"[i])) {
    637  1.1  cgd 		flags.beginner = 1;
    638  1.1  cgd 		if(!pl_character[0]) pl_character[0] = "CFKSTWX"[i];
    639  1.1  cgd 		break;
    640  1.1  cgd 	}
    641  1.1  cgd #endif nonsense
    642  1.1  cgd }
    643