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