1 /* $NetBSD: hack.end.c,v 1.9 2008/01/28 06:55:41 dholland 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.9 2008/01/28 06:55:41 dholland 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 __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 __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 > (int)flags.end_top && 452 (rank < rank0 - (int)flags.end_around || rank > rank0 + (int)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 - (int)flags.end_around && 461 rank0 > (int)flags.end_top + (int)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, gotkilled = FALSE, starv = FALSE; 503 char linebuf[BUFSZ]; 504 505 linebuf[0] = 0; 506 if (rank) 507 Sprintf(eos(linebuf), "%3d", rank); 508 else 509 Sprintf(eos(linebuf), " "); 510 Sprintf(eos(linebuf), " %6ld %8s", t1->points, t1->name); 511 if (t1->plchar == 'X') 512 Sprintf(eos(linebuf), " "); 513 else 514 Sprintf(eos(linebuf), "-%c ", t1->plchar); 515 if (!strncmp("escaped", t1->death, 7)) { 516 if (!strcmp(" (with amulet)", t1->death + 7)) 517 Sprintf(eos(linebuf), "escaped the dungeon with amulet"); 518 else 519 Sprintf(eos(linebuf), "escaped the dungeon [max level %d]", 520 t1->maxlvl); 521 } else { 522 if (!strncmp(t1->death, "quit", 4)) { 523 quit = TRUE; 524 if (t1->maxhp < 3 * t1->hp && t1->maxlvl < 4) 525 Sprintf(eos(linebuf), "cravenly gave up"); 526 else 527 Sprintf(eos(linebuf), "quit"); 528 } else if (!strcmp(t1->death, "choked")) 529 Sprintf(eos(linebuf), "choked on %s food", 530 (t1->sex == 'F') ? "her" : "his"); 531 else if (!strncmp(t1->death, "starv", 5)) 532 Sprintf(eos(linebuf), "starved to death"), starv = TRUE; 533 else 534 Sprintf(eos(linebuf), "was killed"), gotkilled = TRUE; 535 Sprintf(eos(linebuf), " on%s level %d", 536 (gotkilled || starv) ? "" : " dungeon", t1->level); 537 if (t1->maxlvl != t1->level) 538 Sprintf(eos(linebuf), " [max %d]", t1->maxlvl); 539 if (quit && t1->death[4]) 540 Sprintf(eos(linebuf), t1->death + 4); 541 } 542 if (gotkilled) 543 Sprintf(eos(linebuf), " by %s%s", 544 (!strncmp(t1->death, "trick", 5) || !strncmp(t1->death, "the ", 4)) 545 ? "" : 546 strchr(vowels, *t1->death) ? "an " : "a ", 547 t1->death); 548 Sprintf(eos(linebuf), "."); 549 if (t1->maxhp) { 550 char *bp = eos(linebuf); 551 char hpbuf[10]; 552 int hppos; 553 Sprintf(hpbuf, (t1->hp > 0) ? itoa(t1->hp) : "-"); 554 hppos = COLNO - 7 - strlen(hpbuf); 555 if (bp <= linebuf + hppos) { 556 while (bp < linebuf + hppos) 557 *bp++ = ' '; 558 (void) strcpy(bp, hpbuf); 559 Sprintf(eos(bp), " [%d]", t1->maxhp); 560 } 561 } 562 if (so == 0) 563 puts(linebuf); 564 else if (so > 0) { 565 char *bp = eos(linebuf); 566 if (so >= COLNO) 567 so = COLNO - 1; 568 while (bp < linebuf + so) 569 *bp++ = ' '; 570 *bp = 0; 571 standoutbeg(); 572 fputs(linebuf, stdout); 573 standoutend(); 574 (void) putchar('\n'); 575 } 576 return (strlen(linebuf)); 577 } 578 579 char * 580 itoa(a) 581 int a; 582 { 583 static char buf[12]; 584 Sprintf(buf, "%d", a); 585 return (buf); 586 } 587 588 const char * 589 ordin(n) 590 int n; 591 { 592 int dg = n % 10; 593 594 return ((dg == 0 || dg > 3 || n / 10 == 1) ? "th" : (dg == 1) ? "st" : 595 (dg == 2) ? "nd" : "rd"); 596 } 597 598 void 599 clearlocks() 600 { 601 int x; 602 (void) signal(SIGHUP, SIG_IGN); 603 for (x = maxdlevel; x >= 0; x--) { 604 glo(x); 605 (void) unlink(lock); /* not all levels need be present */ 606 } 607 } 608 609 #ifdef NOSAVEONHANGUP 610 /*ARGSUSED*/ 611 void 612 hangup(n) 613 int n; 614 { 615 (void) signal(SIGINT, SIG_IGN); 616 clearlocks(); 617 exit(1); 618 } 619 #endif /* NOSAVEONHANGUP */ 620 621 char * 622 eos(s) 623 char *s; 624 { 625 while (*s) 626 s++; 627 return (s); 628 } 629 630 /* it is the callers responsibility to check that there is room for c */ 631 void 632 charcat(s, c) 633 char *s, c; 634 { 635 while (*s) 636 s++; 637 *s++ = c; 638 *s = 0; 639 } 640 641 /* 642 * Called with args from main if argc >= 0. In this case, list scores as 643 * requested. Otherwise, find scores for the current player (and list them 644 * if argc == -1). 645 */ 646 void 647 prscore(argc, argv) 648 int argc; 649 char **argv; 650 { 651 char **players = NULL; 652 int playerct; 653 int rank; 654 struct toptenentry *t1, *t2; 655 const char *recfile = RECORD; 656 FILE *rfile; 657 int flg = 0; 658 int i; 659 #ifdef nonsense 660 long total_score = 0L; 661 char totchars[10]; 662 int totcharct = 0; 663 #endif /* nonsense */ 664 int outflg = (argc >= -1); 665 #ifdef PERS_IS_UID 666 int uid = -1; 667 #else 668 char *player0; 669 #endif /* PERS_IS_UID */ 670 671 if (!(rfile = fopen(recfile, "r"))) { 672 puts("Cannot open record file!"); 673 return; 674 } 675 if (argc > 1 && !strncmp(argv[1], "-s", 2)) { 676 if (!argv[1][2]) { 677 argc--; 678 argv++; 679 } else if (!argv[1][3] && strchr("CFKSTWX", argv[1][2])) { 680 argv[1]++; 681 argv[1][0] = '-'; 682 } else 683 argv[1] += 2; 684 } 685 if (argc <= 1) { 686 #ifdef PERS_IS_UID 687 uid = getuid(); 688 playerct = 0; 689 #else 690 player0 = plname; 691 if (!*player0) 692 player0 = "hackplayer"; 693 playerct = 1; 694 players = &player0; 695 #endif /* PERS_IS_UID */ 696 } else { 697 playerct = --argc; 698 players = ++argv; 699 } 700 if (outflg) 701 putchar('\n'); 702 703 t1 = tt_head = newttentry(); 704 for (rank = 1;; rank++) { 705 if (fscanf(rfile, "%6s %d %d %d %d %d %ld %c%c %[^,],%[^\n]", 706 t1->date, &t1->uid, 707 &t1->level, &t1->maxlvl, 708 &t1->hp, &t1->maxhp, &t1->points, 709 &t1->plchar, &t1->sex, t1->name, t1->death) != 11) 710 t1->points = 0; 711 if (t1->points == 0) 712 break; 713 #ifdef PERS_IS_UID 714 if (!playerct && t1->uid == uid) 715 flg++; 716 else 717 #endif /* PERS_IS_UID */ 718 for (i = 0; i < playerct; i++) { 719 if (strcmp(players[i], "all") == 0 || 720 strncmp(t1->name, players[i], NAMSZ) == 0 || 721 (players[i][0] == '-' && 722 players[i][1] == t1->plchar && 723 players[i][2] == 0) || 724 (digit(players[i][0]) && rank <= atoi(players[i]))) 725 flg++; 726 } 727 t1 = t1->tt_next = newttentry(); 728 } 729 (void) fclose(rfile); 730 if (!flg) { 731 if (outflg) { 732 printf("Cannot find any entries for "); 733 if (playerct < 1) 734 printf("you.\n"); 735 else { 736 if (playerct > 1) 737 printf("any of "); 738 for (i = 0; i < playerct; i++) 739 printf("%s%s", players[i], (i < playerct - 1) ? ", " : ".\n"); 740 printf("Call is: %s -s [playernames]\n", hname); 741 } 742 } 743 return; 744 } 745 if (outflg) 746 outheader(); 747 t1 = tt_head; 748 for (rank = 1; t1->points != 0; rank++, t1 = t2) { 749 t2 = t1->tt_next; 750 #ifdef PERS_IS_UID 751 if (!playerct && t1->uid == uid) 752 goto outwithit; 753 else 754 #endif /* PERS_IS_UID */ 755 for (i = 0; i < playerct; i++) { 756 if (strcmp(players[i], "all") == 0 || 757 strncmp(t1->name, players[i], NAMSZ) == 0 || 758 (players[i][0] == '-' && 759 players[i][1] == t1->plchar && 760 players[i][2] == 0) || 761 (digit(players[i][0]) && rank <= atoi(players[i]))) { 762 outwithit: 763 if (outflg) 764 (void) outentry(rank, t1, 0); 765 #ifdef nonsense 766 total_score += t1->points; 767 if (totcharct < sizeof(totchars) - 1) 768 totchars[totcharct++] = t1->plchar; 769 #endif /* nonsense */ 770 break; 771 } 772 } 773 free((char *) t1); 774 } 775 #ifdef nonsense 776 totchars[totcharct] = 0; 777 778 /* 779 * We would like to determine whether he is experienced. However, the 780 * information collected here only tells about the scores/roles that 781 * got into the topten (top 100?). We should maintain a .hacklog or 782 * something in his home directory. 783 */ 784 flags.beginner = (total_score < 6000); 785 for (i = 0; i < 6; i++) 786 if (!strchr(totchars, "CFKSTWX"[i])) { 787 flags.beginner = 1; 788 if (!pl_character[0]) 789 pl_character[0] = "CFKSTWX"[i]; 790 break; 791 } 792 #endif /* nonsense */ 793 } 794