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 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 118 done2(void) 119 { 120 done1(0); 121 return(0); 122 } 123 124 int done_stopprint; 125 int done_hup; 126 127 void 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 136 done_hangup(int notused) 137 { 138 done_hup++; 139 (void) signal(SIGHUP, SIG_IGN); 140 done_intr(notused); 141 } 142 143 void 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 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 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 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 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 * 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 * 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 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 * 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 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 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