Source:NetHack 3.4.3/src/topten.c
Revision as of 15:20, 4 March 2008 by Kernigh bot (talk | contribs) (Topten.c moved to Source:Topten.c: Robot: moved page)
Below is the full text to src/topten.c from NetHack 3.4.3. To link to a particular line, write [[topten.c#line123]], for example.
Contents
Top of file
1. /* SCCS Id: @(#)topten.c 3.4 2000/01/21 */ 2. /* Copyright (c) Stichting Mathematisch Centrum, Amsterdam, 1985. */ 3. /* NetHack may be freely redistributed. See license for details. */ 4.
The NetHack General Public License applies to screenshots, source code and other content from NetHack.
This content was modified from the original NetHack source code distribution (by splitting up NetHack content between wiki pages, and possibly further editing). See the page history for a list of who changed it, and on what dates.
5. #include "hack.h" 6. #include "dlb.h" 7. #ifdef SHORT_FILENAMES 8. #include "patchlev.h" 9. #else 10. #include "patchlevel.h" 11. #endif 12. 13. #ifdef VMS 14. /* We don't want to rewrite the whole file, because that entails */ 15. /* creating a new version which requires that the old one be deletable. */ 16. # define UPDATE_RECORD_IN_PLACE 17. #endif 18. 19. /* 20. * Updating in place can leave junk at the end of the file in some 21. * circumstances (if it shrinks and the O.S. doesn't have a straightforward 22. * way to truncate it). The trailing junk is harmless and the code 23. * which reads the scores will ignore it. 24. */ 25. #ifdef UPDATE_RECORD_IN_PLACE 26. static long final_fpos; 27. #endif 28. 29. #define done_stopprint program_state.stopprint 30. 31. #define newttentry() (struct toptenentry *) alloc(sizeof(struct toptenentry)) 32. #define dealloc_ttentry(ttent) free((genericptr_t) (ttent)) 33. #define NAMSZ 10 34. #define DTHSZ 100 35. #define ROLESZ 3 36. #define PERSMAX 3 /* entries per name/uid per char. allowed */ 37. #define POINTSMIN 1 /* must be > 0 */ 38. #define ENTRYMAX 100 /* must be >= 10 */ 39. 40. #if !defined(MICRO) && !defined(MAC) && !defined(WIN32) 41. #define PERS_IS_UID /* delete for PERSMAX per name; now per uid */ 42. #endif 43. struct toptenentry { 44. struct toptenentry *tt_next; 45. #ifdef UPDATE_RECORD_IN_PLACE 46. long fpos; 47. #endif 48. long points; 49. int deathdnum, deathlev; 50. int maxlvl, hp, maxhp, deaths; 51. int ver_major, ver_minor, patchlevel; 52. long deathdate, birthdate; 53. int uid; 54. char plrole[ROLESZ+1]; 55. char plrace[ROLESZ+1]; 56. char plgend[ROLESZ+1]; 57. char plalign[ROLESZ+1]; 58. char name[NAMSZ+1]; 59. char death[DTHSZ+1]; 60. } *tt_head; 61. 62. STATIC_DCL void FDECL(topten_print, (const char *)); 63. STATIC_DCL void FDECL(topten_print_bold, (const char *)); 64. STATIC_DCL xchar FDECL(observable_depth, (d_level *)); 65. STATIC_DCL void NDECL(outheader); 66. STATIC_DCL void FDECL(outentry, (int,struct toptenentry *,BOOLEAN_P)); 67. STATIC_DCL void FDECL(readentry, (FILE *,struct toptenentry *)); 68. STATIC_DCL void FDECL(writeentry, (FILE *,struct toptenentry *)); 69. STATIC_DCL void FDECL(free_ttlist, (struct toptenentry *)); 70. STATIC_DCL int FDECL(classmon, (char *,BOOLEAN_P)); 71. STATIC_DCL int FDECL(score_wanted, 72. (BOOLEAN_P, int,struct toptenentry *,int,const char **,int)); 73. #ifdef NO_SCAN_BRACK 74. STATIC_DCL void FDECL(nsb_mung_line,(char*)); 75. STATIC_DCL void FDECL(nsb_unmung_line,(char*)); 76. #endif 77.
topten_print
78. /* must fit with end.c; used in rip.c */ 79. NEARDATA const char * const killed_by_prefix[] = { 80. "killed by ", "choked on ", "poisoned by ", "died of ", "drowned in ", 81. "burned by ", "dissolved in ", "crushed to death by ", "petrified by ", 82. "turned to slime by ", "killed by ", "", "", "", "", "" 83. }; 84. 85. static winid toptenwin = WIN_ERR; 86. 87. STATIC_OVL void 88. topten_print(x) 89. const char *x; 90. { 91. if (toptenwin == WIN_ERR) 92. raw_print(x); 93. else 94. putstr(toptenwin, ATR_NONE, x); 95. } 96.
topten_print_bold
97. STATIC_OVL void 98. topten_print_bold(x) 99. const char *x; 100. { 101. if (toptenwin == WIN_ERR) 102. raw_print_bold(x); 103. else 104. putstr(toptenwin, ATR_BOLD, x); 105. } 106.
observable_depth
107. STATIC_OVL xchar 108. observable_depth(lev) 109. d_level *lev; 110. { 111. #if 0 /* if we ever randomize the order of the elemental planes, we 112. must use a constant external representation in the record file */ 113. if (In_endgame(lev)) { 114. if (Is_astralevel(lev)) return -5; 115. else if (Is_waterlevel(lev)) return -4; 116. else if (Is_firelevel(lev)) return -3; 117. else if (Is_airlevel(lev)) return -2; 118. else if (Is_earthlevel(lev)) return -1; 119. else return 0; /* ? */ 120. } else 121. #endif 122. return depth(lev); 123. } 124.
readentry
125. STATIC_OVL void 126. readentry(rfile,tt) 127. FILE *rfile; 128. struct toptenentry *tt; 129. { 130. #ifdef NO_SCAN_BRACK /* Version_ Pts DgnLevs_ Hp___ Died__Born id */ 131. static const char fmt[] = "%d %d %d %ld %d %d %d %d %d %d %ld %ld %d%*c"; 132. static const char fmt32[] = "%c%c %s %s%*c"; 133. static const char fmt33[] = "%s %s %s %s %s %s%*c"; 134. #else 135. static const char fmt[] = "%d.%d.%d %ld %d %d %d %d %d %d %ld %ld %d "; 136. static const char fmt32[] = "%c%c %[^,],%[^\n]%*c"; 137. static const char fmt33[] = "%s %s %s %s %[^,],%[^\n]%*c"; 138. #endif 139. 140. #ifdef UPDATE_RECORD_IN_PLACE 141. /* note: fscanf() below must read the record's terminating newline */ 142. final_fpos = tt->fpos = ftell(rfile); 143. #endif 144. #define TTFIELDS 13 145. if(fscanf(rfile, fmt, 146. &tt->ver_major, &tt->ver_minor, &tt->patchlevel, 147. &tt->points, &tt->deathdnum, &tt->deathlev, 148. &tt->maxlvl, &tt->hp, &tt->maxhp, &tt->deaths, 149. &tt->deathdate, &tt->birthdate, 150. &tt->uid) != TTFIELDS) 151. #undef TTFIELDS 152. tt->points = 0; 153. else { 154. /* Check for backwards compatibility */ 155. if (tt->ver_major < 3 || 156. (tt->ver_major == 3 && tt->ver_minor < 3)) { 157. int i; 158. 159. if (fscanf(rfile, fmt32, 160. tt->plrole, tt->plgend, 161. tt->name, tt->death) != 4) 162. tt->points = 0; 163. tt->plrole[1] = '\0'; 164. if ((i = str2role(tt->plrole)) >= 0) 165. Strcpy(tt->plrole, roles[i].filecode); 166. Strcpy(tt->plrace, "?"); 167. Strcpy(tt->plgend, (tt->plgend[0] == 'M') ? "Mal" : "Fem"); 168. Strcpy(tt->plalign, "?"); 169. } else if (fscanf(rfile, fmt33, 170. tt->plrole, tt->plrace, tt->plgend, 171. tt->plalign, tt->name, tt->death) != 6) 172. tt->points = 0; 173. #ifdef NO_SCAN_BRACK 174. if(tt->points > 0) { 175. nsb_unmung_line(tt->name); 176. nsb_unmung_line(tt->death); 177. } 178. #endif 179. } 180. 181. /* check old score entries for Y2K problem and fix whenever found */ 182. if (tt->points > 0) { 183. if (tt->birthdate < 19000000L) tt->birthdate += 19000000L; 184. if (tt->deathdate < 19000000L) tt->deathdate += 19000000L; 185. } 186. } 187.
writeentry
188. STATIC_OVL void 189. writeentry(rfile,tt) 190. FILE *rfile; 191. struct toptenentry *tt; 192. { 193. #ifdef NO_SCAN_BRACK 194. nsb_mung_line(tt->name); 195. nsb_mung_line(tt->death); 196. /* Version_ Pts DgnLevs_ Hp___ Died__Born id */ 197. (void) fprintf(rfile,"%d %d %d %ld %d %d %d %d %d %d %ld %ld %d ", 198. #else 199. (void) fprintf(rfile,"%d.%d.%d %ld %d %d %d %d %d %d %ld %ld %d ", 200. #endif 201. tt->ver_major, tt->ver_minor, tt->patchlevel, 202. tt->points, tt->deathdnum, tt->deathlev, 203. tt->maxlvl, tt->hp, tt->maxhp, tt->deaths, 204. tt->deathdate, tt->birthdate, tt->uid); 205. if (tt->ver_major < 3 || 206. (tt->ver_major == 3 && tt->ver_minor < 3)) 207. #ifdef NO_SCAN_BRACK 208. (void) fprintf(rfile,"%c%c %s %s\n", 209. #else 210. (void) fprintf(rfile,"%c%c %s,%s\n", 211. #endif 212. tt->plrole[0], tt->plgend[0], 213. onlyspace(tt->name) ? "_" : tt->name, tt->death); 214. else 215. #ifdef NO_SCAN_BRACK 216. (void) fprintf(rfile,"%s %s %s %s %s %s\n", 217. #else 218. (void) fprintf(rfile,"%s %s %s %s %s,%s\n", 219. #endif 220. tt->plrole, tt->plrace, tt->plgend, tt->plalign, 221. onlyspace(tt->name) ? "_" : tt->name, tt->death); 222. 223. #ifdef NO_SCAN_BRACK 224. nsb_unmung_line(tt->name); 225. nsb_unmung_line(tt->death); 226. #endif 227. } 228.
free_ttlist
229. STATIC_OVL void 230. free_ttlist(tt) 231. struct toptenentry *tt; 232. { 233. struct toptenentry *ttnext; 234. 235. while (tt->points > 0) { 236. ttnext = tt->tt_next; 237. dealloc_ttentry(tt); 238. tt = ttnext; 239. } 240. dealloc_ttentry(tt); 241. } 242.
topten
243. void 244. topten(how) 245. int how; 246. { 247. int uid = getuid(); 248. int rank, rank0 = -1, rank1 = 0; 249. int occ_cnt = PERSMAX; 250. register struct toptenentry *t0, *tprev; 251. struct toptenentry *t1; 252. FILE *rfile; 253. register int flg = 0; 254. boolean t0_used; 255. #ifdef LOGFILE 256. FILE *lfile; 257. #endif /* LOGFILE */ 258. 259. /* Under DICE 3.0, this crashes the system consistently, apparently due to 260. * corruption of *rfile somewhere. Until I figure this out, just cut out 261. * topten support entirely - at least then the game exits cleanly. --AC 262. */ 263. #ifdef _DCC 264. return; 265. #endif 266. 267. /* If we are in the midst of a panic, cut out topten entirely. 268. * topten uses alloc() several times, which will lead to 269. * problems if the panic was the result of an alloc() failure. 270. */ 271. if (program_state.panicking) 272. return; 273. 274. if (flags.toptenwin) { 275. toptenwin = create_nhwindow(NHW_TEXT); 276. } 277. 278. #if defined(UNIX) || defined(VMS) || defined(__EMX__) 279. #define HUP if (!program_state.done_hup) 280. #else 281. #define HUP 282. #endif 283. 284. #ifdef TOS 285. restore_colors(); /* make sure the screen is black on white */ 286. #endif 287. /* create a new 'topten' entry */ 288. t0_used = FALSE; 289. t0 = newttentry(); 290. /* deepest_lev_reached() is in terms of depth(), and reporting the 291. * deepest level reached in the dungeon death occurred in doesn't 292. * seem right, so we have to report the death level in depth() terms 293. * as well (which also seems reasonable since that's all the player 294. * sees on the screen anyway) 295. */ 296. t0->ver_major = VERSION_MAJOR; 297. t0->ver_minor = VERSION_MINOR; 298. t0->patchlevel = PATCHLEVEL; 299. t0->points = u.urexp; 300. t0->deathdnum = u.uz.dnum; 301. t0->deathlev = observable_depth(&u.uz); 302. t0->maxlvl = deepest_lev_reached(TRUE); 303. t0->hp = u.uhp; 304. t0->maxhp = u.uhpmax; 305. t0->deaths = u.umortality; 306. t0->uid = uid; 307. (void) strncpy(t0->plrole, urole.filecode, ROLESZ); 308. t0->plrole[ROLESZ] = '\0'; 309. (void) strncpy(t0->plrace, urace.filecode, ROLESZ); 310. t0->plrace[ROLESZ] = '\0'; 311. (void) strncpy(t0->plgend, genders[flags.female].filecode, ROLESZ); 312. t0->plgend[ROLESZ] = '\0'; 313. (void) strncpy(t0->plalign, aligns[1-u.ualign.type].filecode, ROLESZ); 314. t0->plalign[ROLESZ] = '\0'; 315. (void) strncpy(t0->name, plname, NAMSZ); 316. t0->name[NAMSZ] = '\0'; 317. t0->death[0] = '\0'; 318. switch (killer_format) { 319. default: impossible("bad killer format?"); 320. case KILLED_BY_AN: 321. Strcat(t0->death, killed_by_prefix[how]); 322. (void) strncat(t0->death, an(killer), 323. DTHSZ-strlen(t0->death)); 324. break; 325. case KILLED_BY: 326. Strcat(t0->death, killed_by_prefix[how]); 327. (void) strncat(t0->death, killer, 328. DTHSZ-strlen(t0->death)); 329. break; 330. case NO_KILLER_PREFIX: 331. (void) strncat(t0->death, killer, DTHSZ); 332. break; 333. } 334. t0->birthdate = yyyymmdd(u.ubirthday); 335. t0->deathdate = yyyymmdd((time_t)0L); 336. t0->tt_next = 0; 337. #ifdef UPDATE_RECORD_IN_PLACE 338. t0->fpos = -1L; 339. #endif 340. 341. #ifdef LOGFILE /* used for debugging (who dies of what, where) */ 342. if (lock_file(LOGFILE, SCOREPREFIX, 10)) { 343. if(!(lfile = fopen_datafile(LOGFILE, "a", SCOREPREFIX))) { 344. HUP raw_print("Cannot open log file!"); 345. } else { 346. writeentry(lfile, t0); 347. (void) fclose(lfile); 348. } 349. unlock_file(LOGFILE); 350. } 351. #endif /* LOGFILE */ 352. 353. if (wizard || discover) { 354. if (how != PANICKED) HUP { 355. char pbuf[BUFSZ]; 356. topten_print(""); 357. Sprintf(pbuf, 358. "Since you were in %s mode, the score list will not be checked.", 359. wizard ? "wizard" : "discover"); 360. topten_print(pbuf); 361. } 362. goto showwin; 363. } 364. 365. if (!lock_file(RECORD, SCOREPREFIX, 60)) 366. goto destroywin; 367. 368. #ifdef UPDATE_RECORD_IN_PLACE 369. rfile = fopen_datafile(RECORD, "r+", SCOREPREFIX); 370. #else 371. rfile = fopen_datafile(RECORD, "r", SCOREPREFIX); 372. #endif 373. 374. if (!rfile) { 375. HUP raw_print("Cannot open record file!"); 376. unlock_file(RECORD); 377. goto destroywin; 378. } 379. 380. HUP topten_print(""); 381. 382. /* assure minimum number of points */ 383. if(t0->points < POINTSMIN) t0->points = 0; 384. 385. t1 = tt_head = newttentry(); 386. tprev = 0; 387. /* rank0: -1 undefined, 0 not_on_list, n n_th on list */ 388. for(rank = 1; ; ) { 389. readentry(rfile, t1); 390. if (t1->points < POINTSMIN) t1->points = 0; 391. if(rank0 < 0 && t1->points < t0->points) { 392. rank0 = rank++; 393. if(tprev == 0) 394. tt_head = t0; 395. else 396. tprev->tt_next = t0; 397. t0->tt_next = t1; 398. #ifdef UPDATE_RECORD_IN_PLACE 399. t0->fpos = t1->fpos; /* insert here */ 400. #endif 401. t0_used = TRUE; 402. occ_cnt--; 403. flg++; /* ask for a rewrite */ 404. } else tprev = t1; 405. 406. if(t1->points == 0) break; 407. if( 408. #ifdef PERS_IS_UID 409. t1->uid == t0->uid && 410. #else 411. strncmp(t1->name, t0->name, NAMSZ) == 0 && 412. #endif 413. !strncmp(t1->plrole, t0->plrole, ROLESZ) && 414. --occ_cnt <= 0) { 415. if(rank0 < 0) { 416. rank0 = 0; 417. rank1 = rank; 418. HUP { 419. char pbuf[BUFSZ]; 420. Sprintf(pbuf, 421. "You didn't beat your previous score of %ld points.", 422. t1->points); 423. topten_print(pbuf); 424. topten_print(""); 425. } 426. } 427. if(occ_cnt < 0) { 428. flg++; 429. continue; 430. } 431. } 432. if(rank <= ENTRYMAX) { 433. t1->tt_next = newttentry(); 434. t1 = t1->tt_next; 435. rank++; 436. } 437. if(rank > ENTRYMAX) { 438. t1->points = 0; 439. break; 440. } 441. } 442. if(flg) { /* rewrite record file */ 443. #ifdef UPDATE_RECORD_IN_PLACE 444. (void) fseek(rfile, (t0->fpos >= 0 ? 445. t0->fpos : final_fpos), SEEK_SET); 446. #else 447. (void) fclose(rfile); 448. if(!(rfile = fopen_datafile(RECORD, "w", SCOREPREFIX))){ 449. HUP raw_print("Cannot write record file"); 450. unlock_file(RECORD); 451. free_ttlist(tt_head); 452. goto destroywin; 453. } 454. #endif /* UPDATE_RECORD_IN_PLACE */ 455. if(!done_stopprint) if(rank0 > 0){ 456. if(rank0 <= 10) 457. topten_print("You made the top ten list!"); 458. else { 459. char pbuf[BUFSZ]; 460. Sprintf(pbuf, 461. "You reached the %d%s place on the top %d list.", 462. rank0, ordin(rank0), ENTRYMAX); 463. topten_print(pbuf); 464. } 465. topten_print(""); 466. } 467. } 468. if(rank0 == 0) rank0 = rank1; 469. if(rank0 <= 0) rank0 = rank; 470. if(!done_stopprint) outheader(); 471. t1 = tt_head; 472. for(rank = 1; t1->points != 0; rank++, t1 = t1->tt_next) { 473. if(flg 474. #ifdef UPDATE_RECORD_IN_PLACE 475. && rank >= rank0 476. #endif 477. ) writeentry(rfile, t1); 478. if (done_stopprint) continue; 479. if (rank > flags.end_top && 480. (rank < rank0 - flags.end_around || 481. rank > rank0 + flags.end_around) && 482. (!flags.end_own || 483. #ifdef PERS_IS_UID 484. t1->uid != t0->uid 485. #else 486. strncmp(t1->name, t0->name, NAMSZ) 487. #endif 488. )) continue; 489. if (rank == rank0 - flags.end_around && 490. rank0 > flags.end_top + flags.end_around + 1 && 491. !flags.end_own) 492. topten_print(""); 493. if(rank != rank0) 494. outentry(rank, t1, FALSE); 495. else if(!rank1) 496. outentry(rank, t1, TRUE); 497. else { 498. outentry(rank, t1, TRUE); 499. outentry(0, t0, TRUE); 500. } 501. } 502. if(rank0 >= rank) if(!done_stopprint) 503. outentry(0, t0, TRUE); 504. #ifdef UPDATE_RECORD_IN_PLACE 505. if (flg) { 506. # ifdef TRUNCATE_FILE 507. /* if a reasonable way to truncate a file exists, use it */ 508. truncate_file(rfile); 509. # else 510. /* use sentinel record rather than relying on truncation */ 511. t1->points = 0L; /* terminates file when read back in */ 512. t1->ver_major = t1->ver_minor = t1->patchlevel = 0; 513. t1->uid = t1->deathdnum = t1->deathlev = 0; 514. t1->maxlvl = t1->hp = t1->maxhp = t1->deaths = 0; 515. t1->plrole[0] = t1->plrace[0] = t1->plgend[0] = t1->plalign[0] = '-'; 516. t1->plrole[1] = t1->plrace[1] = t1->plgend[1] = t1->plalign[1] = 0; 517. t1->birthdate = t1->deathdate = yyyymmdd((time_t)0L); 518. Strcpy(t1->name, "@"); 519. Strcpy(t1->death, "<eod>\n"); 520. writeentry(rfile, t1); 521. (void) fflush(rfile); 522. # endif /* TRUNCATE_FILE */ 523. } 524. #endif /* UPDATE_RECORD_IN_PLACE */ 525. (void) fclose(rfile); 526. unlock_file(RECORD); 527. free_ttlist(tt_head); 528. 529. showwin: 530. if (flags.toptenwin && !done_stopprint) display_nhwindow(toptenwin, 1); 531. destroywin: 532. if (!t0_used) dealloc_ttentry(t0); 533. if (flags.toptenwin) { 534. destroy_nhwindow(toptenwin); 535. toptenwin=WIN_ERR; 536. } 537. } 538.
outheader
539. STATIC_OVL void 540. outheader() 541. { 542. char linebuf[BUFSZ]; 543. register char *bp; 544. 545. Strcpy(linebuf, " No Points Name"); 546. bp = eos(linebuf); 547. while(bp < linebuf + COLNO - 9) *bp++ = ' '; 548. Strcpy(bp, "Hp [max]"); 549. topten_print(linebuf); 550. } 551.
outentry
552. /* so>0: standout line; so=0: ordinary line */ 553. STATIC_OVL void 554. outentry(rank, t1, so) 555. struct toptenentry *t1; 556. int rank; 557. boolean so; 558. { 559. boolean second_line = TRUE; 560. char linebuf[BUFSZ]; 561. char *bp, hpbuf[24], linebuf3[BUFSZ]; 562. int hppos, lngr; 563. 564. 565. linebuf[0] = '\0'; 566. if (rank) Sprintf(eos(linebuf), "%3d", rank); 567. else Strcat(linebuf, " "); 568. 569. Sprintf(eos(linebuf), " %10ld %.10s", t1->points, t1->name); 570. Sprintf(eos(linebuf), "-%s", t1->plrole); 571. if (t1->plrace[0] != '?') 572. Sprintf(eos(linebuf), "-%s", t1->plrace); 573. /* Printing of gender and alignment is intentional. It has been 574. * part of the NetHack Geek Code, and illustrates a proper way to 575. * specify a character from the command line. 576. */ 577. Sprintf(eos(linebuf), "-%s", t1->plgend); 578. if (t1->plalign[0] != '?') 579. Sprintf(eos(linebuf), "-%s ", t1->plalign); 580. else 581. Strcat(linebuf, " "); 582. if (!strncmp("escaped", t1->death, 7)) { 583. Sprintf(eos(linebuf), "escaped the dungeon %s[max level %d]", 584. !strncmp(" (", t1->death + 7, 2) ? t1->death + 7 + 2 : "", 585. t1->maxlvl); 586. /* fixup for closing paren in "escaped... with...Amulet)[max..." */ 587. if ((bp = index(linebuf, ')')) != 0) 588. *bp = (t1->deathdnum == astral_level.dnum) ? '\0' : ' '; 589. second_line = FALSE; 590. } else if (!strncmp("ascended", t1->death, 8)) { 591. Sprintf(eos(linebuf), "ascended to demigod%s-hood", 592. (t1->plgend[0] == 'F') ? "dess" : ""); 593. second_line = FALSE; 594. } else { 595. if (!strncmp(t1->death, "quit", 4)) { 596. Strcat(linebuf, "quit"); 597. second_line = FALSE; 598. } else if (!strncmp(t1->death, "died of st", 10)) { 599. Strcat(linebuf, "starved to death"); 600. second_line = FALSE; 601. } else if (!strncmp(t1->death, "choked", 6)) { 602. Sprintf(eos(linebuf), "choked on h%s food", 603. (t1->plgend[0] == 'F') ? "er" : "is"); 604. } else if (!strncmp(t1->death, "poisoned", 8)) { 605. Strcat(linebuf, "was poisoned"); 606. } else if (!strncmp(t1->death, "crushed", 7)) { 607. Strcat(linebuf, "was crushed to death"); 608. } else if (!strncmp(t1->death, "petrified by ", 13)) { 609. Strcat(linebuf, "turned to stone"); 610. } else Strcat(linebuf, "died"); 611. 612. if (t1->deathdnum == astral_level.dnum) { 613. const char *arg, *fmt = " on the Plane of %s"; 614. 615. switch (t1->deathlev) { 616. case -5: 617. fmt = " on the %s Plane"; 618. arg = "Astral"; break; 619. case -4: 620. arg = "Water"; break; 621. case -3: 622. arg = "Fire"; break; 623. case -2: 624. arg = "Air"; break; 625. case -1: 626. arg = "Earth"; break; 627. default: 628. arg = "Void"; break; 629. } 630. Sprintf(eos(linebuf), fmt, arg); 631. } else { 632. Sprintf(eos(linebuf), " in %s", dungeons[t1->deathdnum].dname); 633. if (t1->deathdnum != knox_level.dnum) 634. Sprintf(eos(linebuf), " on level %d", t1->deathlev); 635. if (t1->deathlev != t1->maxlvl) 636. Sprintf(eos(linebuf), " [max %d]", t1->maxlvl); 637. } 638. 639. /* kludge for "quit while already on Charon's boat" */ 640. if (!strncmp(t1->death, "quit ", 5)) 641. Strcat(linebuf, t1->death + 4); 642. } 643. Strcat(linebuf, "."); 644. 645. /* Quit, starved, ascended, and escaped contain no second line */ 646. if (second_line) 647. Sprintf(eos(linebuf), " %c%s.", highc(*(t1->death)), t1->death+1); 648. 649. lngr = (int)strlen(linebuf); 650. if (t1->hp <= 0) hpbuf[0] = '-', hpbuf[1] = '\0'; 651. else Sprintf(hpbuf, "%d", t1->hp); 652. /* beginning of hp column after padding (not actually padded yet) */ 653. hppos = COLNO - (sizeof(" Hp [max]")-1); /* sizeof(str) includes \0 */ 654. while (lngr >= hppos) { 655. for(bp = eos(linebuf); 656. !(*bp == ' ' && (bp-linebuf < hppos)); 657. bp--) 658. ; 659. /* special case: if about to wrap in the middle of maximum 660. dungeon depth reached, wrap in front of it instead */ 661. if (bp > linebuf + 5 && !strncmp(bp - 5, " [max", 5)) bp -= 5; 662. Strcpy(linebuf3, bp+1); 663. *bp = 0; 664. if (so) { 665. while (bp < linebuf + (COLNO-1)) *bp++ = ' '; 666. *bp = 0; 667. topten_print_bold(linebuf); 668. } else 669. topten_print(linebuf); 670. Sprintf(linebuf, "%15s %s", "", linebuf3); 671. lngr = strlen(linebuf); 672. } 673. /* beginning of hp column not including padding */ 674. hppos = COLNO - 7 - (int)strlen(hpbuf); 675. bp = eos(linebuf); 676. 677. if (bp <= linebuf + hppos) { 678. /* pad any necessary blanks to the hit point entry */ 679. while (bp < linebuf + hppos) *bp++ = ' '; 680. Strcpy(bp, hpbuf); 681. Sprintf(eos(bp), " %s[%d]", 682. (t1->maxhp < 10) ? " " : (t1->maxhp < 100) ? " " : "", 683. t1->maxhp); 684. } 685. 686. if (so) { 687. bp = eos(linebuf); 688. if (so >= COLNO) so = COLNO-1; 689. while (bp < linebuf + so) *bp++ = ' '; 690. *bp = 0; 691. topten_print_bold(linebuf); 692. } else 693. topten_print(linebuf); 694. } 695.
score_wanted
696. STATIC_OVL int 697. score_wanted(current_ver, rank, t1, playerct, players, uid) 698. boolean current_ver; 699. int rank; 700. struct toptenentry *t1; 701. int playerct; 702. const char **players; 703. int uid; 704. { 705. int i; 706. 707. if (current_ver && (t1->ver_major != VERSION_MAJOR || 708. t1->ver_minor != VERSION_MINOR || 709. t1->patchlevel != PATCHLEVEL)) 710. return 0; 711. 712. #ifdef PERS_IS_UID 713. if (!playerct && t1->uid == uid) 714. return 1; 715. #endif 716. 717. for (i = 0; i < playerct; i++) { 718. if (players[i][0] == '-' && index("pr", players[i][1]) && 719. players[i][2] == 0 && i + 1 < playerct) { 720. char *arg = (char *)players[i + 1]; 721. if ((players[i][1] == 'p' && 722. str2role(arg) == str2role(t1->plrole)) || 723. (players[i][1] == 'r' && 724. str2race(arg) == str2race(t1->plrace))) 725. return 1; 726. i++; 727. } else if (strcmp(players[i], "all") == 0 || 728. strncmp(t1->name, players[i], NAMSZ) == 0 || 729. (players[i][0] == '-' && 730. players[i][1] == t1->plrole[0] && 731. players[i][2] == 0) || 732. (digit(players[i][0]) && rank <= atoi(players[i]))) 733. return 1; 734. } 735. return 0; 736. } 737.
prscore
738. /* 739. * print selected parts of score list. 740. * argc >= 2, with argv[0] untrustworthy (directory names, et al.), 741. * and argv[1] starting with "-s". 742. */ 743. void 744. prscore(argc,argv) 745. int argc; 746. char **argv; 747. { 748. const char **players; 749. int playerct, rank; 750. boolean current_ver = TRUE, init_done = FALSE; 751. register struct toptenentry *t1; 752. FILE *rfile; 753. boolean match_found = FALSE; 754. register int i; 755. char pbuf[BUFSZ]; 756. int uid = -1; 757. #ifndef PERS_IS_UID 758. const char *player0; 759. #endif 760. 761. if (argc < 2 || strncmp(argv[1], "-s", 2)) { 762. raw_printf("prscore: bad arguments (%d)", argc); 763. return; 764. } 765. 766. rfile = fopen_datafile(RECORD, "r", SCOREPREFIX); 767. if (!rfile) { 768. raw_print("Cannot open record file!"); 769. return; 770. } 771. 772. #ifdef AMIGA 773. { 774. extern winid amii_rawprwin; 775. init_nhwindows(&argc, argv); 776. amii_rawprwin = create_nhwindow(NHW_TEXT); 777. } 778. #endif 779. 780. /* If the score list isn't after a game, we never went through 781. * initialization. */ 782. if (wiz1_level.dlevel == 0) { 783. dlb_init(); 784. init_dungeons(); 785. init_done = TRUE; 786. } 787. 788. if (!argv[1][2]){ /* plain "-s" */ 789. argc--; 790. argv++; 791. } else argv[1] += 2; 792. 793. if (argc > 1 && !strcmp(argv[1], "-v")) { 794. current_ver = FALSE; 795. argc--; 796. argv++; 797. } 798. 799. if (argc <= 1) { 800. #ifdef PERS_IS_UID 801. uid = getuid(); 802. playerct = 0; 803. players = (const char **)0; 804. #else 805. player0 = plname; 806. if (!*player0) 807. # ifdef AMIGA 808. player0 = "all"; /* single user system */ 809. # else 810. player0 = "hackplayer"; 811. # endif 812. playerct = 1; 813. players = &player0; 814. #endif 815. } else { 816. playerct = --argc; 817. players = (const char **)++argv; 818. } 819. raw_print(""); 820. 821. t1 = tt_head = newttentry(); 822. for (rank = 1; ; rank++) { 823. readentry(rfile, t1); 824. if (t1->points == 0) break; 825. if (!match_found && 826. score_wanted(current_ver, rank, t1, playerct, players, uid)) 827. match_found = TRUE; 828. t1->tt_next = newttentry(); 829. t1 = t1->tt_next; 830. } 831. 832. (void) fclose(rfile); 833. if (init_done) { 834. free_dungeons(); 835. dlb_cleanup(); 836. } 837. 838. if (match_found) { 839. outheader(); 840. t1 = tt_head; 841. for (rank = 1; t1->points != 0; rank++, t1 = t1->tt_next) { 842. if (score_wanted(current_ver, rank, t1, playerct, players, uid)) 843. (void) outentry(rank, t1, 0); 844. } 845. } else { 846. Sprintf(pbuf, "Cannot find any %sentries for ", 847. current_ver ? "current " : ""); 848. if (playerct < 1) Strcat(pbuf, "you."); 849. else { 850. if (playerct > 1) Strcat(pbuf, "any of "); 851. for (i = 0; i < playerct; i++) { 852. /* stop printing players if there are too many to fit */ 853. if (strlen(pbuf) + strlen(players[i]) + 2 >= BUFSZ) { 854. if (strlen(pbuf) < BUFSZ-4) Strcat(pbuf, "..."); 855. else Strcpy(pbuf+strlen(pbuf)-4, "..."); 856. break; 857. } 858. Strcat(pbuf, players[i]); 859. if (i < playerct-1) { 860. if (players[i][0] == '-' && 861. index("pr", players[i][1]) && players[i][2] == 0) 862. Strcat(pbuf, " "); 863. else Strcat(pbuf, ":"); 864. } 865. } 866. } 867. raw_print(pbuf); 868. raw_printf("Usage: %s -s [-v] <playertypes> [maxrank] [playernames]", 869. 870. hname); 871. raw_printf("Player types are: [-p role] [-r race]"); 872. } 873. free_ttlist(tt_head); 874. #ifdef AMIGA 875. { 876. extern winid amii_rawprwin; 877. display_nhwindow(amii_rawprwin, 1); 878. destroy_nhwindow(amii_rawprwin); 879. amii_rawprwin = WIN_ERR; 880. } 881. #endif 882. } 883.
classmon
884. STATIC_OVL int 885. classmon(plch, fem) 886. char *plch; 887. boolean fem; 888. { 889. int i; 890. 891. /* Look for this role in the role table */ 892. for (i = 0; roles[i].name.m; i++) 893. if (!strncmp(plch, roles[i].filecode, ROLESZ)) { 894. if (fem && roles[i].femalenum != NON_PM) 895. return roles[i].femalenum; 896. else if (roles[i].malenum != NON_PM) 897. return roles[i].malenum; 898. else 899. return PM_HUMAN; 900. } 901. /* this might be from a 3.2.x score for former Elf class */ 902. if (!strcmp(plch, "E")) return PM_RANGER; 903. 904. impossible("What weird role is this? (%s)", plch); 905. return (PM_HUMAN_MUMMY); 906. } 907.
tt_oname
908. /* 909. * Get a random player name and class from the high score list, 910. * and attach them to an object (for statues or morgue corpses). 911. */ 912. struct obj * 913. tt_oname(otmp) 914. struct obj *otmp; 915. { 916. int rank; 917. register int i; 918. register struct toptenentry *tt; 919. FILE *rfile; 920. struct toptenentry tt_buf; 921. 922. if (!otmp) return((struct obj *) 0); 923. 924. rfile = fopen_datafile(RECORD, "r", SCOREPREFIX); 925. if (!rfile) { 926. impossible("Cannot open record file!"); 927. return (struct obj *)0; 928. } 929. 930. tt = &tt_buf; 931. rank = rnd(10); 932. pickentry: 933. for(i = rank; i; i--) { 934. readentry(rfile, tt); 935. if(tt->points == 0) break; 936. } 937. 938. if(tt->points == 0) { 939. if(rank > 1) { 940. rank = 1; 941. rewind(rfile); 942. goto pickentry; 943. } 944. otmp = (struct obj *) 0; 945. } else { 946. /* reset timer in case corpse started out as lizard or troll */ 947. if (otmp->otyp == CORPSE) obj_stop_timers(otmp); 948. otmp->corpsenm = classmon(tt->plrole, (tt->plgend[0] == 'F')); 949. otmp->owt = weight(otmp); 950. otmp = oname(otmp, tt->name); 951. if (otmp->otyp == CORPSE) start_corpse_timeout(otmp); 952. } 953. 954. (void) fclose(rfile); 955. return otmp; 956. } 957.
nsb_mung_line
958. #ifdef NO_SCAN_BRACK 959. /* Lattice scanf isn't up to reading the scorefile. What */ 960. /* follows deals with that; I admit it's ugly. (KL) */ 961. /* Now generally available (KL) */ 962. STATIC_OVL void 963. nsb_mung_line(p) 964. char *p; 965. { 966. while ((p = index(p, ' ')) != 0) *p = '|'; 967. } 968.
nsb_unmung_line
969. STATIC_OVL void 970. nsb_unmung_line(p) 971. char *p; 972. { 973. while ((p = index(p, '|')) != 0) *p = ' '; 974. } 975. #endif /* NO_SCAN_BRACK */ 976. 977. /*topten.c*/