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