dsynth - Make dummy /usr/packages directory for pkg compatibility
[dragonfly.git] / games / hack / hack.end.c
blobb9ad8185bc22bd0ee0f50ce255410cfb825cd98e
1 /* $NetBSD: hack.end.c,v 1.19 2020/02/07 22:04:02 fox Exp $ */
3 /*
4 * Copyright (c) 1985, Stichting Centrum voor Wiskunde en Informatica,
5 * Amsterdam
6 * All rights reserved.
8 * Redistribution and use in source and binary forms, with or without
9 * modification, are permitted provided that the following conditions are
10 * met:
12 * - Redistributions of source code must retain the above copyright notice,
13 * this list of conditions and the following disclaimer.
15 * - Redistributions in binary form must reproduce the above copyright
16 * notice, this list of conditions and the following disclaimer in the
17 * documentation and/or other materials provided with the distribution.
19 * - Neither the name of the Stichting Centrum voor Wiskunde en
20 * Informatica, nor the names of its contributors may be used to endorse or
21 * promote products derived from this software without specific prior
22 * written permission.
24 * THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS
25 * IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED
26 * TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A
27 * PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT OWNER
28 * OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL,
29 * EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO,
30 * PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR
31 * PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF
32 * LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING
33 * NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS
34 * SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
38 * Copyright (c) 1982 Jay Fenlason <hack@gnu.org>
39 * All rights reserved.
41 * Redistribution and use in source and binary forms, with or without
42 * modification, are permitted provided that the following conditions
43 * are met:
44 * 1. Redistributions of source code must retain the above copyright
45 * notice, this list of conditions and the following disclaimer.
46 * 2. Redistributions in binary form must reproduce the above copyright
47 * notice, this list of conditions and the following disclaimer in the
48 * documentation and/or other materials provided with the distribution.
49 * 3. The name of the author may not be used to endorse or promote products
50 * derived from this software without specific prior written permission.
52 * THIS SOFTWARE IS PROVIDED ``AS IS'' AND ANY EXPRESS OR IMPLIED WARRANTIES,
53 * INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY
54 * AND FITNESS FOR A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL
55 * THE AUTHOR BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL,
56 * EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO,
57 * PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS;
58 * OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY,
59 * WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR
60 * OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF
61 * ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
64 #include <signal.h>
65 #include <unistd.h>
66 #include <stdlib.h>
67 #include "hack.h"
68 #include "extern.h"
69 #define Snprintf (void) snprintf
71 xchar maxdlevel = 1;
73 struct toptenentry;
75 static void topten(void);
76 static void outheader(void);
77 static int outentry(int, struct toptenentry *, int);
78 static char *itoa(int);
79 static const char *ordin(int);
81 int
82 dodone(void)
84 done1(0);
85 return 0;
89 /*ARGSUSED*/
90 void
91 done1(int n __unused)
93 (void) signal(SIGINT, SIG_IGN);
94 pline("Really quit?");
95 if (readchar() != 'y') {
96 (void) signal(SIGINT, done1);
97 clrlin();
98 (void) fflush(stdout);
99 if (multi > 0)
100 nomul(0);
101 return;
103 done("quit");
104 /* NOTREACHED */
107 static int done_stopprint;
108 static int done_hup;
110 /*ARGSUSED*/
111 static void
112 done_intr(int n __unused)
114 done_stopprint++;
115 (void) signal(SIGINT, SIG_IGN);
116 (void) signal(SIGQUIT, SIG_IGN);
119 static void
120 done_hangup(int n)
122 done_hup++;
123 (void) signal(SIGHUP, SIG_IGN);
124 done_intr(n);
127 void
128 done_in_by(struct monst *mtmp)
130 static char buf[BUFSZ];
131 pline("You die ...");
132 if (mtmp->data->mlet == ' ') {
133 Snprintf(buf, sizeof(buf),
134 "the ghost of %s", (char *) mtmp->mextra);
135 killer = buf;
136 } else if (mtmp->mnamelth) {
137 Snprintf(buf, sizeof(buf), "%s called %s",
138 mtmp->data->mname, NAME(mtmp));
139 killer = buf;
140 } else if (mtmp->minvis) {
141 Snprintf(buf, sizeof(buf), "invisible %s", mtmp->data->mname);
142 killer = buf;
143 } else
144 killer = mtmp->data->mname;
145 done("died");
149 * called with arg "died", "drowned", "escaped", "quit", "choked",
150 * "panicked", "burned", "starved" or "tricked"
152 /* Be careful not to call panic from here! */
153 void
154 done(const char *st1)
157 #ifdef WIZARD
158 if (wizard && *st1 == 'd') {
159 u.uswldtim = 0;
160 if (u.uhpmax < 0)
161 u.uhpmax = 100; /* arbitrary */
162 u.uhp = u.uhpmax;
163 pline("For some reason you are still alive.");
164 flags.move = 0;
165 if (multi > 0)
166 multi = 0;
167 else
168 multi = -1;
169 flags.botl = 1;
170 return;
172 #endif /* WIZARD */
173 (void) signal(SIGINT, done_intr);
174 (void) signal(SIGQUIT, done_intr);
175 (void) signal(SIGHUP, done_hangup);
176 if (*st1 == 'q' && u.uhp < 1) {
177 st1 = "died";
178 killer = "quit while already on Charon's boat";
180 if (*st1 == 's')
181 killer = "starvation";
182 else if (*st1 == 'd' && st1[1] == 'r')
183 killer = "drowning";
184 else if (*st1 == 'p')
185 killer = "panic";
186 else if (*st1 == 't')
187 killer = "trickery";
188 else if (!strchr("bcd", *st1))
189 killer = st1;
190 paybill();
191 clearlocks();
192 if (flags.toplin == 1)
193 more();
194 if (strchr("bcds", *st1)) {
195 #ifdef WIZARD
196 if (!wizard)
197 #endif /* WIZARD */
198 savebones();
199 if (!flags.notombstone)
200 outrip();
202 if (*st1 == 'c')
203 killer = st1; /* after outrip() */
204 settty(NULL); /* does a clear_screen() */
205 if (!done_stopprint)
206 printf("Goodbye %s %s...\n\n", pl_character, plname);
208 long int tmp;
209 tmp = u.ugold - u.ugold0;
210 if (tmp < 0)
211 tmp = 0;
212 if (*st1 == 'd' || *st1 == 'b')
213 tmp -= tmp / 10;
214 u.urexp += tmp;
215 u.urexp += 50 * maxdlevel;
216 if (maxdlevel > 20)
217 u.urexp += 1000 * ((maxdlevel > 30) ? 10 : maxdlevel - 20);
219 if (*st1 == 'e') {
220 struct monst *mtmp;
221 struct obj *otmp;
222 int i;
223 unsigned worthlessct = 0;
224 boolean has_amulet = FALSE;
226 killer = st1;
227 keepdogs();
228 mtmp = mydogs;
229 if (mtmp) {
230 if (!done_stopprint)
231 printf("You");
232 while (mtmp) {
233 if (!done_stopprint)
234 printf(" and %s", monnam(mtmp));
235 if (mtmp->mtame)
236 u.urexp += mtmp->mhp;
237 mtmp = mtmp->nmon;
239 if (!done_stopprint)
240 printf("\nescaped from the dungeon with %ld points,\n",
241 u.urexp);
242 } else if (!done_stopprint)
243 printf("You escaped from the dungeon with %ld points,\n",
244 u.urexp);
245 for (otmp = invent; otmp; otmp = otmp->nobj) {
246 if (otmp->olet == GEM_SYM) {
247 objects[otmp->otyp].oc_name_known = 1;
248 i = otmp->quan * objects[otmp->otyp].g_val;
249 if (i == 0) {
250 worthlessct += otmp->quan;
251 continue;
253 u.urexp += i;
254 if (!done_stopprint)
255 printf("\t%s (worth %d Zorkmids),\n",
256 doname(otmp), i);
257 } else if (otmp->olet == AMULET_SYM) {
258 otmp->known = 1;
259 i = (otmp->spe < 0) ? 2 : 5000;
260 u.urexp += i;
261 if (!done_stopprint)
262 printf("\t%s (worth %d Zorkmids),\n",
263 doname(otmp), i);
264 if (otmp->spe >= 0) {
265 has_amulet = TRUE;
266 killer = "escaped (with amulet)";
270 if (worthlessct)
271 if (!done_stopprint)
272 printf("\t%u worthless piece%s of coloured glass,\n",
273 worthlessct, plur(worthlessct));
274 if (has_amulet)
275 u.urexp *= 2;
276 } else if (!done_stopprint)
277 printf("You %s on dungeon level %d with %ld points,\n",
278 st1, dlevel, u.urexp);
279 if (!done_stopprint)
280 printf("and %ld piece%s of gold, after %ld move%s.\n",
281 u.ugold, plur(u.ugold), moves, plur(moves));
282 if (!done_stopprint)
283 printf("You were level %u with a maximum of %d hit points when you %s.\n",
284 u.ulevel, u.uhpmax, st1);
285 if (*st1 == 'e' && !done_stopprint) {
286 getret(); /* all those pieces of coloured glass ... */
287 cls();
289 #ifdef WIZARD
290 if (!wizard)
291 #endif /* WIZARD */
292 topten();
293 if (done_stopprint)
294 printf("\n\n");
295 exit(0);
298 #define newttentry() ((struct toptenentry *) alloc(sizeof(struct toptenentry)))
299 #define NAMSZ 8
300 #define DTHSZ 40
301 #define PERSMAX 1
302 #define POINTSMIN 1 /* must be > 0 */
303 #define ENTRYMAX 100 /* must be >= 10 */
304 #define PERS_IS_UID /* delete for PERSMAX per name; now per uid */
305 struct toptenentry {
306 struct toptenentry *tt_next;
307 long int points;
308 int level, maxlvl, hp, maxhp;
309 int uid;
310 char plchar;
311 char sex;
312 char name[NAMSZ + 1];
313 char death[DTHSZ + 1];
314 char date[7];/* yymmdd */
317 static struct toptenentry *tt_head;
319 static void
320 topten(void)
322 int uid = getuid();
323 int rank, rank0 = -1, rank1 = 0;
324 int occ_cnt = PERSMAX;
325 struct toptenentry *t0, *t1, *tprev;
326 const char *recfile = RECORD;
327 const char *reclock = "record_lock";
328 int sleepct = 300;
329 FILE *rfile;
330 int flg = 0;
331 #define HUP if(!done_hup)
332 while (link(recfile, reclock) == -1) {
333 HUP perror(reclock);
334 if (!sleepct--) {
335 HUP puts("I give up. Sorry.");
336 HUP puts("Perhaps there is an old record_lock around?");
337 return;
339 HUP printf("Waiting for access to record file. (%d)\n",
340 sleepct);
341 HUP(void) fflush(stdout);
342 sleep(1);
344 if (!(rfile = fopen(recfile, "r"))) {
345 HUP puts("Cannot open record file!");
346 goto unlock;
348 HUP(void) putchar('\n');
350 /* create a new 'topten' entry */
351 t0 = newttentry();
352 t0->level = dlevel;
353 t0->maxlvl = maxdlevel;
354 t0->hp = u.uhp;
355 t0->maxhp = u.uhpmax;
356 t0->points = u.urexp;
357 t0->plchar = pl_character[0];
358 t0->sex = (flags.female ? 'F' : 'M');
359 t0->uid = uid;
360 (void) strncpy(t0->name, plname, NAMSZ);
361 (t0->name)[NAMSZ] = 0;
362 (void) strncpy(t0->death, killer, DTHSZ);
363 (t0->death)[DTHSZ] = 0;
364 (void) strcpy(t0->date, getdatestr());
366 /* assure minimum number of points */
367 if (t0->points < POINTSMIN)
368 t0->points = 0;
370 t1 = tt_head = newttentry();
371 tprev = 0;
372 /* rank0: -1 undefined, 0 not_on_list, n n_th on list */
373 for (rank = 1;;) {
374 if (fscanf(rfile, "%6s %d %d %d %d %d %ld %c%c %[^,],%[^\n]",
375 t1->date, &t1->uid,
376 &t1->level, &t1->maxlvl,
377 &t1->hp, &t1->maxhp, &t1->points,
378 &t1->plchar, &t1->sex, t1->name, t1->death) != 11
379 || t1->points < POINTSMIN)
380 t1->points = 0;
381 if (rank0 < 0 && t1->points < t0->points) {
382 rank0 = rank++;
383 if (tprev == 0)
384 tt_head = t0;
385 else
386 tprev->tt_next = t0;
387 t0->tt_next = t1;
388 occ_cnt--;
389 flg++; /* ask for a rewrite */
390 } else
391 tprev = t1;
392 if (t1->points == 0)
393 break;
394 if (
395 #ifdef PERS_IS_UID
396 t1->uid == t0->uid &&
397 #else
398 strncmp(t1->name, t0->name, NAMSZ) == 0 &&
399 #endif /* PERS_IS_UID */
400 t1->plchar == t0->plchar && --occ_cnt <= 0) {
401 if (rank0 < 0) {
402 rank0 = 0;
403 rank1 = rank;
404 HUP printf("You didn't beat your previous score of %ld points.\n\n",
405 t1->points);
407 if (occ_cnt < 0) {
408 flg++;
409 continue;
412 if (rank <= ENTRYMAX) {
413 t1 = t1->tt_next = newttentry();
414 rank++;
416 if (rank > ENTRYMAX) {
417 t1->points = 0;
418 break;
421 if (flg) { /* rewrite record file */
422 (void) fclose(rfile);
423 if (!(rfile = fopen(recfile, "w"))) {
424 HUP puts("Cannot write record file\n");
425 goto unlock;
427 if (!done_stopprint)
428 if (rank0 > 0) {
429 if (rank0 <= 10)
430 puts("You made the top ten list!\n");
431 else
432 printf("You reached the %d%s place on the top %d list.\n\n",
433 rank0, ordin(rank0), ENTRYMAX);
436 if (rank0 == 0)
437 rank0 = rank1;
438 if (rank0 <= 0)
439 rank0 = rank;
440 if (!done_stopprint)
441 outheader();
442 t1 = tt_head;
443 for (rank = 1; t1->points != 0; rank++, t1 = t1->tt_next) {
444 if (flg)
445 fprintf(rfile, "%6s %d %d %d %d %d %ld %c%c %s,%s\n",
446 t1->date, t1->uid,
447 t1->level, t1->maxlvl,
448 t1->hp, t1->maxhp, t1->points,
449 t1->plchar, t1->sex, t1->name, t1->death);
450 if (done_stopprint)
451 continue;
452 if (rank > (int)flags.end_top &&
453 (rank < rank0 - (int)flags.end_around || rank > rank0 + (int)flags.end_around)
454 && (!flags.end_own ||
455 #ifdef PERS_IS_UID
456 t1->uid != t0->uid))
457 #else
458 strncmp(t1->name, t0->name, NAMSZ)))
459 #endif /* PERS_IS_UID */
460 continue;
461 if (rank == rank0 - (int)flags.end_around &&
462 rank0 > (int)flags.end_top + (int)flags.end_around + 1 &&
463 !flags.end_own)
464 (void) putchar('\n');
465 if (rank != rank0)
466 (void) outentry(rank, t1, 0);
467 else if (!rank1)
468 (void) outentry(rank, t1, 1);
469 else {
470 int t0lth = outentry(0, t0, -1);
471 int t1lth = outentry(rank, t1, t0lth);
472 if (t1lth > t0lth)
473 t0lth = t1lth;
474 (void) outentry(0, t0, t0lth);
477 if (rank0 >= rank)
478 if (!done_stopprint)
479 (void) outentry(0, t0, 1);
480 (void) fclose(rfile);
481 free(t0);
482 unlock:
483 (void) unlink(reclock);
486 static void
487 outheader(void)
489 char linebuf[BUFSZ];
490 char *bp;
491 (void) strcpy(linebuf, "Number Points Name");
492 bp = eos(linebuf);
493 while (bp < linebuf + COLNO - 9)
494 *bp++ = ' ';
495 (void) strcpy(bp, "Hp [max]");
496 puts(linebuf);
499 /* so>0: standout line; so=0: ordinary line; so<0: no output, return length */
500 static int
501 outentry(int rank, struct toptenentry *t1, int so)
503 boolean quit = FALSE, gotkilled = FALSE, starv = FALSE;
504 char linebuf[BUFSZ];
505 size_t pos;
507 linebuf[0] = '\0';
508 pos = 0;
510 if (rank)
511 Snprintf(linebuf+pos, sizeof(linebuf)-pos, "%3d", rank);
512 else
513 Snprintf(linebuf+pos, sizeof(linebuf)-pos, " ");
514 pos = strlen(linebuf);
516 Snprintf(linebuf+pos, sizeof(linebuf)-pos, " %6ld %8s",
517 t1->points, t1->name);
518 pos = strlen(linebuf);
520 if (t1->plchar == 'X')
521 Snprintf(linebuf+pos, sizeof(linebuf)-pos, " ");
522 else
523 Snprintf(linebuf+pos, sizeof(linebuf)-pos, "-%c ", t1->plchar);
524 pos = strlen(linebuf);
526 if (!strncmp("escaped", t1->death, 7)) {
527 if (!strcmp(" (with amulet)", t1->death + 7))
528 Snprintf(linebuf+pos, sizeof(linebuf)-pos,
529 "escaped the dungeon with amulet");
530 else
531 Snprintf(linebuf+pos, sizeof(linebuf)-pos,
532 "escaped the dungeon [max level %d]",
533 t1->maxlvl);
534 pos = strlen(linebuf);
535 } else {
536 if (!strncmp(t1->death, "quit", 4)) {
537 quit = TRUE;
538 if (t1->maxhp < 3 * t1->hp && t1->maxlvl < 4)
539 Snprintf(linebuf+pos, sizeof(linebuf)-pos,
540 "cravenly gave up");
541 else
542 Snprintf(linebuf+pos, sizeof(linebuf)-pos,
543 "quit");
544 } else if (!strcmp(t1->death, "choked")) {
545 Snprintf(linebuf+pos, sizeof(linebuf)-pos,
546 "choked on %s food",
547 (t1->sex == 'F') ? "her" : "his");
548 } else if (!strncmp(t1->death, "starv", 5)) {
549 Snprintf(linebuf+pos, sizeof(linebuf)-pos,
550 "starved to death");
551 starv = TRUE;
552 } else {
553 Snprintf(linebuf+pos, sizeof(linebuf)-pos,
554 "was killed");
555 gotkilled = TRUE;
557 pos = strlen(linebuf);
559 Snprintf(linebuf+pos, sizeof(linebuf)-pos, " on%s level %d",
560 (gotkilled || starv) ? "" : " dungeon", t1->level);
561 pos = strlen(linebuf);
563 if (t1->maxlvl != t1->level)
564 Snprintf(linebuf+pos, sizeof(linebuf)-pos,
565 " [max %d]", t1->maxlvl);
566 pos = strlen(linebuf);
568 if (quit && t1->death[4])
569 Snprintf(linebuf+pos, sizeof(linebuf)-pos,
570 "%s", t1->death + 4);
571 pos = strlen(linebuf);
573 if (gotkilled) {
574 Snprintf(linebuf+pos, sizeof(linebuf)-pos, " by %s%s",
575 (!strncmp(t1->death, "trick", 5) || !strncmp(t1->death, "the ", 4))
576 ? "" :
577 strchr(vowels, *t1->death) ? "an " : "a ",
578 t1->death);
579 pos = strlen(linebuf);
581 strlcat(linebuf, ".", sizeof(linebuf));
582 pos = strlen(linebuf);
583 if (t1->maxhp) {
584 char hpbuf[10];
585 unsigned hppos;
587 strlcpy(hpbuf, (t1->hp > 0) ? itoa(t1->hp) : "-", sizeof(hpbuf));
588 hppos = COLNO - 7 - strlen(hpbuf);
589 if (pos <= hppos) {
590 while (pos < hppos)
591 linebuf[pos++] = ' ';
592 (void) strlcpy(linebuf+pos, hpbuf, sizeof(linebuf)-pos);
593 pos = strlen(linebuf);
594 Snprintf(linebuf+pos, sizeof(linebuf)-pos,
595 " [%d]", t1->maxhp);
596 pos = strlen(linebuf);
599 if (so == 0)
600 puts(linebuf);
601 else if (so > 0) {
602 if (so >= COLNO)
603 so = COLNO - 1;
604 while (pos < (unsigned)so)
605 linebuf[pos++] = ' ';
606 linebuf[pos] = '\0';
607 standoutbeg();
608 fputs(linebuf, stdout);
609 standoutend();
610 (void) putchar('\n');
612 return /*(strlen(linebuf))*/ pos;
615 static char *
616 itoa(int a)
618 static char buf[12];
619 Snprintf(buf, sizeof(buf), "%d", a);
620 return (buf);
623 static const char *
624 ordin(int n)
626 int dg = n % 10;
628 return ((dg == 0 || dg > 3 || n / 10 == 1) ? "th" : (dg == 1) ? "st" :
629 (dg == 2) ? "nd" : "rd");
632 void
633 clearlocks(void)
635 int x;
636 (void) signal(SIGHUP, SIG_IGN);
637 for (x = maxdlevel; x >= 0; x--) {
638 glo(x);
639 (void) unlink(lock); /* not all levels need be present */
643 #ifdef NOSAVEONHANGUP
644 /*ARGSUSED*/
645 void
646 hang_up(int n __unused)
648 (void) signal(SIGINT, SIG_IGN);
649 clearlocks();
650 exit(1);
652 #endif /* NOSAVEONHANGUP */
654 char *
655 eos(char *s)
657 while (*s)
658 s++;
659 return (s);
662 /* it is the callers responsibility to check that there is room for c */
663 void
664 charcat(char *s, int c)
666 while (*s)
667 s++;
668 *s++ = c;
669 *s = 0;
673 * Called with args from main if argc >= 0. In this case, list scores as
674 * requested. Otherwise, find scores for the current player (and list them
675 * if argc == -1).
677 void
678 prscore(int argc, char **argv)
680 char **players = NULL;
681 int playerct;
682 int rank;
683 struct toptenentry *t1, *t2;
684 const char *recfile = RECORD;
685 FILE *rfile;
686 int flg = 0;
687 int i;
688 #ifdef nonsense
689 long total_score = 0L;
690 char totchars[10];
691 int totcharct = 0;
692 #endif /* nonsense */
693 int outflg = (argc >= -1);
694 #ifdef PERS_IS_UID
695 int uid = -1;
696 #else
697 char *player0;
698 #endif /* PERS_IS_UID */
700 if (!(rfile = fopen(recfile, "r"))) {
701 puts("Cannot open record file!");
702 return;
704 if (argc > 1 && !strncmp(argv[1], "-s", 2)) {
705 if (!argv[1][2]) {
706 argc--;
707 argv++;
708 } else if (!argv[1][3] && strchr("CFKSTWX", argv[1][2])) {
709 argv[1]++;
710 argv[1][0] = '-';
711 } else
712 argv[1] += 2;
714 if (argc <= 1) {
715 #ifdef PERS_IS_UID
716 uid = getuid();
717 playerct = 0;
718 #else
719 player0 = plname;
720 if (!*player0)
721 player0 = "hackplayer";
722 playerct = 1;
723 players = &player0;
724 #endif /* PERS_IS_UID */
725 } else {
726 playerct = --argc;
727 players = ++argv;
729 if (outflg)
730 putchar('\n');
732 t1 = tt_head = newttentry();
733 for (rank = 1;; rank++) {
734 if (fscanf(rfile, "%6s %d %d %d %d %d %ld %c%c %[^,],%[^\n]",
735 t1->date, &t1->uid,
736 &t1->level, &t1->maxlvl,
737 &t1->hp, &t1->maxhp, &t1->points,
738 &t1->plchar, &t1->sex, t1->name, t1->death) != 11)
739 t1->points = 0;
740 if (t1->points == 0)
741 break;
742 #ifdef PERS_IS_UID
743 if (!playerct && t1->uid == uid)
744 flg++;
745 else
746 #endif /* PERS_IS_UID */
747 for (i = 0; i < playerct; i++) {
748 if (strcmp(players[i], "all") == 0 ||
749 strncmp(t1->name, players[i], NAMSZ) == 0 ||
750 (players[i][0] == '-' &&
751 players[i][1] == t1->plchar &&
752 players[i][2] == 0) ||
753 (digit(players[i][0]) && rank <= atoi(players[i])))
754 flg++;
756 t1 = t1->tt_next = newttentry();
758 (void) fclose(rfile);
759 if (!flg) {
760 if (outflg) {
761 printf("Cannot find any entries for ");
762 if (playerct < 1)
763 printf("you.\n");
764 else {
765 if (playerct > 1)
766 printf("any of ");
767 for (i = 0; i < playerct; i++)
768 printf("%s%s", players[i], (i < playerct - 1) ? ", " : ".\n");
769 printf("Call is: %s -s [playernames]\n", hname);
772 return;
774 if (outflg)
775 outheader();
776 t1 = tt_head;
777 for (rank = 1; t1->points != 0; rank++, t1 = t2) {
778 t2 = t1->tt_next;
779 #ifdef PERS_IS_UID
780 if (!playerct && t1->uid == uid)
781 goto outwithit;
782 else
783 #endif /* PERS_IS_UID */
784 for (i = 0; i < playerct; i++) {
785 if (strcmp(players[i], "all") == 0 ||
786 strncmp(t1->name, players[i], NAMSZ) == 0 ||
787 (players[i][0] == '-' &&
788 players[i][1] == t1->plchar &&
789 players[i][2] == 0) ||
790 (digit(players[i][0]) && rank <= atoi(players[i]))) {
791 outwithit:
792 if (outflg)
793 (void) outentry(rank, t1, 0);
794 #ifdef nonsense
795 total_score += t1->points;
796 if (totcharct < sizeof(totchars) - 1)
797 totchars[totcharct++] = t1->plchar;
798 #endif /* nonsense */
799 break;
802 free(t1);
804 #ifdef nonsense
805 totchars[totcharct] = 0;
808 * We would like to determine whether he is experienced. However, the
809 * information collected here only tells about the scores/roles that
810 * got into the topten (top 100?). We should maintain a .hacklog or
811 * something in his home directory.
813 flags.beginner = (total_score < 6000);
814 for (i = 0; i < 6; i++)
815 if (!strchr(totchars, "CFKSTWX"[i])) {
816 flags.beginner = 1;
817 if (!pl_character[0])
818 pl_character[0] = "CFKSTWX"[i];
819 break;
821 #endif /* nonsense */