Home | History | Annotate | Line # | Download | only in hack
hack.end.c revision 1.4
      1 /*	$NetBSD: hack.end.c,v 1.4 1997/10/19 16:57:55 christos 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.4 1997/10/19 16:57:55 christos 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;
     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;
     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 	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 	char           *recfile = RECORD;
    269 	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(rank, t1, so)
    443 	struct toptenentry *t1;
    444 {
    445 	boolean         quit = FALSE, killed = FALSE, starv = FALSE;
    446 	char            linebuf[BUFSZ];
    447 	linebuf[0] = 0;
    448 	if (rank)
    449 		Sprintf(eos(linebuf), "%3d", rank);
    450 	else
    451 		Sprintf(eos(linebuf), "   ");
    452 	Sprintf(eos(linebuf), " %6ld %8s", t1->points, t1->name);
    453 	if (t1->plchar == 'X')
    454 		Sprintf(eos(linebuf), " ");
    455 	else
    456 		Sprintf(eos(linebuf), "-%c ", t1->plchar);
    457 	if (!strncmp("escaped", t1->death, 7)) {
    458 		if (!strcmp(" (with amulet)", t1->death + 7))
    459 			Sprintf(eos(linebuf), "escaped the dungeon with amulet");
    460 		else
    461 			Sprintf(eos(linebuf), "escaped the dungeon [max level %d]",
    462 				t1->maxlvl);
    463 	} else {
    464 		if (!strncmp(t1->death, "quit", 4)) {
    465 			quit = TRUE;
    466 			if (t1->maxhp < 3 * t1->hp && t1->maxlvl < 4)
    467 				Sprintf(eos(linebuf), "cravenly gave up");
    468 			else
    469 				Sprintf(eos(linebuf), "quit");
    470 		} else if (!strcmp(t1->death, "choked"))
    471 			Sprintf(eos(linebuf), "choked on %s food",
    472 				(t1->sex == 'F') ? "her" : "his");
    473 		else if (!strncmp(t1->death, "starv", 5))
    474 			Sprintf(eos(linebuf), "starved to death"), starv = TRUE;
    475 		else
    476 			Sprintf(eos(linebuf), "was killed"), killed = TRUE;
    477 		Sprintf(eos(linebuf), " on%s level %d",
    478 			(killed || starv) ? "" : " dungeon", t1->level);
    479 		if (t1->maxlvl != t1->level)
    480 			Sprintf(eos(linebuf), " [max %d]", t1->maxlvl);
    481 		if (quit && t1->death[4])
    482 			Sprintf(eos(linebuf), t1->death + 4);
    483 	}
    484 	if (killed)
    485 		Sprintf(eos(linebuf), " by %s%s",
    486 			(!strncmp(t1->death, "trick", 5) || !strncmp(t1->death, "the ", 4))
    487 			? "" :
    488 			strchr(vowels, *t1->death) ? "an " : "a ",
    489 			t1->death);
    490 	Sprintf(eos(linebuf), ".");
    491 	if (t1->maxhp) {
    492 		char           *bp = eos(linebuf);
    493 		char            hpbuf[10];
    494 		int             hppos;
    495 		Sprintf(hpbuf, (t1->hp > 0) ? itoa(t1->hp) : "-");
    496 		hppos = COLNO - 7 - strlen(hpbuf);
    497 		if (bp <= linebuf + hppos) {
    498 			while (bp < linebuf + hppos)
    499 				*bp++ = ' ';
    500 			(void) strcpy(bp, hpbuf);
    501 			Sprintf(eos(bp), " [%d]", t1->maxhp);
    502 		}
    503 	}
    504 	if (so == 0)
    505 		puts(linebuf);
    506 	else if (so > 0) {
    507 		char           *bp = eos(linebuf);
    508 		if (so >= COLNO)
    509 			so = COLNO - 1;
    510 		while (bp < linebuf + so)
    511 			*bp++ = ' ';
    512 		*bp = 0;
    513 		standoutbeg();
    514 		fputs(linebuf, stdout);
    515 		standoutend();
    516 		(void) putchar('\n');
    517 	}
    518 	return (strlen(linebuf));
    519 }
    520 
    521 char           *
    522 itoa(a)
    523 	int             a;
    524 {
    525 	static char     buf[12];
    526 	Sprintf(buf, "%d", a);
    527 	return (buf);
    528 }
    529 
    530 char           *
    531 ordin(n)
    532 	int             n;
    533 {
    534 	int             d = n % 10;
    535 	return ((d == 0 || d > 3 || n / 10 == 1) ? "th" : (d == 1) ? "st" :
    536 		(d == 2) ? "nd" : "rd");
    537 }
    538 
    539 void
    540 clearlocks()
    541 {
    542 	int x;
    543 	(void) signal(SIGHUP, SIG_IGN);
    544 	for (x = maxdlevel; x >= 0; x--) {
    545 		glo(x);
    546 		(void) unlink(lock);	/* not all levels need be present */
    547 	}
    548 }
    549 
    550 #ifdef NOSAVEONHANGUP
    551 /*ARGSUSED*/
    552 void
    553 hangup(n)
    554 	int n;
    555 {
    556 	(void) signal(SIGINT, SIG_IGN);
    557 	clearlocks();
    558 	exit(1);
    559 }
    560 #endif	/* NOSAVEONHANGUP */
    561 
    562 char           *
    563 eos(s)
    564 	char           *s;
    565 {
    566 	while (*s)
    567 		s++;
    568 	return (s);
    569 }
    570 
    571 /* it is the callers responsibility to check that there is room for c */
    572 void
    573 charcat(s, c)
    574 	char           *s, c;
    575 {
    576 	while (*s)
    577 		s++;
    578 	*s++ = c;
    579 	*s = 0;
    580 }
    581 
    582 /*
    583  * Called with args from main if argc >= 0. In this case, list scores as
    584  * requested. Otherwise, find scores for the current player (and list them
    585  * if argc == -1).
    586  */
    587 void
    588 prscore(argc, argv)
    589 	int             argc;
    590 	char          **argv;
    591 {
    592 	char          **players = NULL;
    593 	int             playerct;
    594 	int             rank;
    595 	struct toptenentry *t1, *t2;
    596 	char           *recfile = RECORD;
    597 	FILE           *rfile;
    598 	int		flg = 0;
    599 	int             i;
    600 #ifdef nonsense
    601 	long            total_score = 0L;
    602 	char            totchars[10];
    603 	int             totcharct = 0;
    604 #endif	/* nonsense */
    605 	int             outflg = (argc >= -1);
    606 #ifdef PERS_IS_UID
    607 	int             uid = -1;
    608 #else
    609 	char           *player0;
    610 #endif	/* PERS_IS_UID */
    611 
    612 	if (!(rfile = fopen(recfile, "r"))) {
    613 		puts("Cannot open record file!");
    614 		return;
    615 	}
    616 	if (argc > 1 && !strncmp(argv[1], "-s", 2)) {
    617 		if (!argv[1][2]) {
    618 			argc--;
    619 			argv++;
    620 		} else if (!argv[1][3] && strchr("CFKSTWX", argv[1][2])) {
    621 			argv[1]++;
    622 			argv[1][0] = '-';
    623 		} else
    624 			argv[1] += 2;
    625 	}
    626 	if (argc <= 1) {
    627 #ifdef PERS_IS_UID
    628 		uid = getuid();
    629 		playerct = 0;
    630 #else
    631 		player0 = plname;
    632 		if (!*player0)
    633 			player0 = "hackplayer";
    634 		playerct = 1;
    635 		players = &player0;
    636 #endif	/* PERS_IS_UID */
    637 	} else {
    638 		playerct = --argc;
    639 		players = ++argv;
    640 	}
    641 	if (outflg)
    642 		putchar('\n');
    643 
    644 	t1 = tt_head = newttentry();
    645 	for (rank = 1;; rank++) {
    646 		if (fscanf(rfile, "%6s %d %d %d %d %d %ld %c%c %[^,],%[^\n]",
    647 			   t1->date, &t1->uid,
    648 			   &t1->level, &t1->maxlvl,
    649 			   &t1->hp, &t1->maxhp, &t1->points,
    650 			   &t1->plchar, &t1->sex, t1->name, t1->death) != 11)
    651 			t1->points = 0;
    652 		if (t1->points == 0)
    653 			break;
    654 #ifdef PERS_IS_UID
    655 		if (!playerct && t1->uid == uid)
    656 			flg++;
    657 		else
    658 #endif	/* PERS_IS_UID */
    659 			for (i = 0; i < playerct; i++) {
    660 				if (strcmp(players[i], "all") == 0 ||
    661 				strncmp(t1->name, players[i], NAMSZ) == 0 ||
    662 				    (players[i][0] == '-' &&
    663 				     players[i][1] == t1->plchar &&
    664 				     players[i][2] == 0) ||
    665 				    (digit(players[i][0]) && rank <= atoi(players[i])))
    666 					flg++;
    667 			}
    668 		t1 = t1->tt_next = newttentry();
    669 	}
    670 	(void) fclose(rfile);
    671 	if (!flg) {
    672 		if (outflg) {
    673 			printf("Cannot find any entries for ");
    674 			if (playerct < 1)
    675 				printf("you.\n");
    676 			else {
    677 				if (playerct > 1)
    678 					printf("any of ");
    679 				for (i = 0; i < playerct; i++)
    680 					printf("%s%s", players[i], (i < playerct - 1) ? ", " : ".\n");
    681 				printf("Call is: %s -s [playernames]\n", hname);
    682 			}
    683 		}
    684 		return;
    685 	}
    686 	if (outflg)
    687 		outheader();
    688 	t1 = tt_head;
    689 	for (rank = 1; t1->points != 0; rank++, t1 = t2) {
    690 		t2 = t1->tt_next;
    691 #ifdef PERS_IS_UID
    692 		if (!playerct && t1->uid == uid)
    693 			goto outwithit;
    694 		else
    695 #endif	/* PERS_IS_UID */
    696 			for (i = 0; i < playerct; i++) {
    697 				if (strcmp(players[i], "all") == 0 ||
    698 				strncmp(t1->name, players[i], NAMSZ) == 0 ||
    699 				    (players[i][0] == '-' &&
    700 				     players[i][1] == t1->plchar &&
    701 				     players[i][2] == 0) ||
    702 				    (digit(players[i][0]) && rank <= atoi(players[i]))) {
    703 			outwithit:
    704 					if (outflg)
    705 						(void) outentry(rank, t1, 0);
    706 #ifdef nonsense
    707 					total_score += t1->points;
    708 					if (totcharct < sizeof(totchars) - 1)
    709 						totchars[totcharct++] = t1->plchar;
    710 #endif	/* nonsense */
    711 					break;
    712 				}
    713 			}
    714 		free((char *) t1);
    715 	}
    716 #ifdef nonsense
    717 	totchars[totcharct] = 0;
    718 
    719 	/*
    720 	 * We would like to determine whether he is experienced. However, the
    721 	 * information collected here only tells about the scores/roles that
    722 	 * got into the topten (top 100?). We should maintain a .hacklog or
    723 	 * something in his home directory.
    724 	 */
    725 	flags.beginner = (total_score < 6000);
    726 	for (i = 0; i < 6; i++)
    727 		if (!strchr(totchars, "CFKSTWX"[i])) {
    728 			flags.beginner = 1;
    729 			if (!pl_character[0])
    730 				pl_character[0] = "CFKSTWX"[i];
    731 			break;
    732 		}
    733 #endif	/* nonsense */
    734 }
    735