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