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