abstract
| - Below is the full text to topten.c from the source code of NetHack 2.3e. To link to a particular line, write [[NetHack 2.3e/topten.c#line123]], for example. Warning! This is the source code from an old release. For the latest release, see Source code 1. /* SCCS Id: @(#)topten.c 2.3 88/02/01 2. /* Copyright (c) Stichting Mathematisch Centrum, Amsterdam, 1985. */ 3. 4. #include 5. #include "hack.h" 6. #ifdef GENIX 7. #define void int /* jhn - mod to prevent compiler from bombing */ 8. #endif 9. 10. #define Sprintf (void) sprintf 11. extern char plname[], pl_character[]; 12. #ifndef MSC /* set by the Microsoft "C" compiler */ 13. extern char *itoa(); 14. #endif 15. extern char *ordin(), *eos(); 16. extern int done_hup, done_stopprint; 17. 18. #define newttentry() (struct toptenentry *) alloc(sizeof(struct toptenentry)) 19. #define NAMSZ 10 20. #define DTHSZ 60 21. #define PERSMAX 3 /* entries per name/uid per char. allowed */ 22. #define POINTSMIN 1 /* must be > 0 */ 23. #define ENTRYMAX 100 /* must be >= 10 */ 24. #ifndef MSDOS 25. #define PERS_IS_UID /* delete for PERSMAX per name; now per uid */ 26. #endif 27. struct toptenentry { 28. struct toptenentry *tt_next; 29. long int points; 30. int level,maxlvl,hp,maxhp; 31. int uid; 32. char plchar; 33. char sex; 34. char name[NAMSZ+1]; 35. char death[DTHSZ+1]; 36. char date[7]; /* yymmdd */ 37. } *tt_head; 38. 39. topten(){ 40. int uid = getuid(); 41. int rank, rank0 = -1, rank1 = 0; 42. int occ_cnt = PERSMAX; 43. register struct toptenentry *t0, *t1, *tprev; 44. char *recfile = RECORD; 45. #ifdef UNIX 46. char *reclock = "record_lock"; 47. #endif 48. int sleepct = 300; 49. FILE *rfile; 50. register flg = 0; 51. extern char *getdate(); 52. #ifdef LOGFILE 53. char *lgfile = LOGFILE; 54. FILE *lfile; 55. char *loglock = "logfile_lock"; 56. int sleeplgct = 30; 57. #endif 58. 59. #ifndef DGK 60. #define HUP if(!done_hup) 61. #else 62. #define HUP 63. #endif 64. 65. #ifdef UNIX 66. while(link(recfile, reclock) == -1) { 67. HUP perror(reclock); 68. if(!sleepct--) { 69. HUP puts("I give up. Sorry."); 70. HUP puts("Perhaps there is an old record_lock around?"); 71. return; 72. } 73. HUP printf("Waiting for access to record file. (%d)
", 74. sleepct); 75. HUP (void) fflush(stdout); 76. sleep(1); 77. } 78. #endif 79. if(!(rfile = fopen(recfile,"r"))){ 80. HUP puts("Cannot open record file!"); 81. goto unlock; 82. } 83. HUP (void) putchar('
'); 84. 85. /* create a new 'topten' entry */ 86. t0 = newttentry(); 87. t0->level = dlevel; 88. t0->maxlvl = maxdlevel; 89. t0->hp = u.uhp; 90. t0->maxhp = u.uhpmax; 91. t0->points = u.urexp; 92. t0->plchar = pl_character[0]; 93. t0->sex = (flags.female ? 'F' : 'M'); 94. t0->uid = uid; 95. (void) strncpy(t0->name, plname, NAMSZ); 96. (t0->name)[NAMSZ] = 0; 97. (void) strncpy(t0->death, killer, DTHSZ); 98. (t0->death)[DTHSZ] = 0; 99. (void) strcpy(t0->date, getdate()); 100. 101. /* assure minimum number of points */ 102. if(t0->points < POINTSMIN) 103. t0->points = 0; 104. #ifdef LOGFILE /* used for debugging (who dies of what, where) */ 105. while(link(lgfile, loglock) == -1) { 106. HUP perror(loglock); 107. if(!sleeplgct--) { 108. HUP puts("I give up. Sorry."); 109. HUP puts("Perhaps there is an old logfile_lock around?"); 110. goto lgend; 111. } 112. HUP printf("Waiting for access to log file. (%d)
", 113. sleeplgct); 114. HUP (void) fflush(stdout); 115. sleep(1); 116. } 117. if(!(lfile = fopen(lgfile,"a"))){ 118. HUP puts("Cannot open log file!"); 119. goto lgend; 120. } 121. fprintf(lfile,"%6s %d %d %d %d %d %ld %c%c %s,%s
", 122. t0->date, t0->uid, 123. t0->level, t0->maxlvl, 124. t0->hp, t0->maxhp, t0->points, 125. t0->plchar, t0->sex, t0->name, t0->death); 126. fclose(lfile); 127. (void) unlink(loglock); 128. lgend:; 129. #endif 130. 131. t1 = tt_head = newttentry(); 132. tprev = 0; 133. /* rank0: -1 undefined, 0 not_on_list, n n_th on list */ 134. for(rank = 1; ; ) { 135. if(fscanf(rfile, "%6s %d %d %d %d %d %ld %c%c %[^,],%[^
]", 136. t1->date, &t1->uid, 137. &t1->level, &t1->maxlvl, 138. &t1->hp, &t1->maxhp, &t1->points, 139. &t1->plchar, &t1->sex, t1->name, t1->death) != 11 140. || t1->points < POINTSMIN) 141. t1->points = 0; 142. if(rank0 < 0 && t1->points < t0->points) { 143. rank0 = rank++; 144. if(tprev == 0) 145. tt_head = t0; 146. else 147. tprev->tt_next = t0; 148. t0->tt_next = t1; 149. occ_cnt--; 150. flg++; /* ask for a rewrite */ 151. } else 152. tprev = t1; 153. if(t1->points == 0) break; 154. if( 155. #ifdef PERS_IS_UID 156. t1->uid == t0->uid && 157. #else 158. strncmp(t1->name, t0->name, NAMSZ) == 0 && 159. #endif 160. t1->plchar == t0->plchar && --occ_cnt <= 0){ 161. if(rank0 < 0){ 162. rank0 = 0; 163. rank1 = rank; 164. HUP printf("You didn't beat your previous score of %ld points.
", 165. t1->points); 166. } 167. if(occ_cnt < 0){ 168. flg++; 169. continue; 170. } 171. } 172. if(rank <= ENTRYMAX){ 173. t1 = t1->tt_next = newttentry(); 174. rank++; 175. } 176. if(rank > ENTRYMAX){ 177. t1->points = 0; 178. break; 179. } 180. } 181. if(flg) { /* rewrite record file */ 182. (void) fclose(rfile); 183. if(!(rfile = fopen(recfile,"w"))){ 184. HUP puts("Cannot write record file
"); 185. goto unlock; 186. } 187. 188. if(!done_stopprint) if(rank0 > 0){ 189. if(rank0 <= 10) 190. puts("You made the top ten list!
"); 191. else 192. printf("You reached the %d%s place on the top %d list.
", 193. rank0, ordin(rank0), ENTRYMAX); 194. } 195. } 196. if(rank0 == 0) rank0 = rank1; 197. if(rank0 <= 0) rank0 = rank; 198. if(!done_stopprint) outheader(); 199. t1 = tt_head; 200. for(rank = 1; t1->points != 0; rank++, t1 = t1->tt_next) { 201. if(flg) fprintf(rfile,"%6s %d %d %d %d %d %ld %c%c %s,%s
", 202. t1->date, t1->uid, 203. t1->level, t1->maxlvl, 204. t1->hp, t1->maxhp, t1->points, 205. t1->plchar, t1->sex, t1->name, t1->death); 206. if(done_stopprint) continue; 207. if(rank > flags.end_top && 208. (rank < rank0-flags.end_around || rank > rank0+flags.end_around) 209. && (!flags.end_own || 210. #ifdef PERS_IS_UID 211. t1->uid != t0->uid 212. #else 213. strncmp(t1->name, t0->name, NAMSZ) 214. #endif 215. )) continue; 216. if(rank == rank0-flags.end_around && 217. rank0 > flags.end_top+flags.end_around+1 && 218. !flags.end_own) 219. (void) putchar('
'); 220. if(rank != rank0) 221. (void) outentry(rank, t1, 0); 222. else if(!rank1) 223. (void) outentry(rank, t1, 1); 224. else { 225. int t0lth = outentry(0, t0, -1); 226. int t1lth = outentry(rank, t1, t0lth); 227. if(t1lth > t0lth) t0lth = t1lth; 228. (void) outentry(0, t0, t0lth); 229. } 230. } 231. if(rank0 >= rank) if(!done_stopprint) 232. (void) outentry(0, t0, 1); 233. (void) fclose(rfile); 234. unlock: ; 235. #ifdef UNIX 236. (void) unlink(reclock); 237. #endif 238. } 239. 240. outheader() { 241. char linebuf[BUFSZ]; 242. register char *bp; 243. #ifdef KJSMODS 244. (void) strcpy(linebuf, " No Points Name"); 245. #else 246. (void) strcpy(linebuf, "Number Points Name"); 247. #endif 248. bp = eos(linebuf); 249. while(bp < linebuf + COLNO - 9) *bp++ = ' '; 250. (void) strcpy(bp, "Hp [max]"); 251. puts(linebuf); 252. } 253. 254. /* so>0: standout line; so=0: ordinary line; so<0: no output, return lth */ 255. int 256. outentry(rank,t1,so) register struct toptenentry *t1; { 257. boolean quit = FALSE, killed = FALSE, starv = FALSE; 258. char linebuf[BUFSZ]; 259. linebuf[0] = 0; 260. if(rank) Sprintf(eos(linebuf), "%3d", rank); 261. else Sprintf(eos(linebuf), " "); 262. #ifdef KJSMODS 263. Sprintf(eos(linebuf), " %7ld %10s", t1->points, t1->name); 264. #else 265. # ifdef DGKMOD 266. Sprintf(eos(linebuf), " %6ld %10s", t1->points, t1->name); 267. # else 268. Sprintf(eos(linebuf), " %6ld %8s", t1->points, t1->name); 269. # endif 270. #endif 271. if(t1->plchar == 'X') Sprintf(eos(linebuf), " "); 272. else Sprintf(eos(linebuf), "-%c ", t1->plchar); 273. if(!strncmp("escaped", t1->death, 7)) { 274. if(!strcmp(" (with amulet)", t1->death+7)) 275. Sprintf(eos(linebuf), "escaped the dungeon with amulet"); 276. else 277. Sprintf(eos(linebuf), "escaped the dungeon [max level %d]", 278. t1->maxlvl); 279. } else { 280. if(!strncmp(t1->death,"quit",4)) { 281. quit = TRUE; 282. #ifndef KJSMODS 283. if(t1->maxhp < 3*t1->hp && t1->maxlvl < 4) 284. Sprintf(eos(linebuf), "cravenly gave up"); 285. else 286. #endif 287. Sprintf(eos(linebuf), "quit"); 288. } 289. else if(!strcmp(t1->death,"choked")) 290. Sprintf(eos(linebuf), "choked on %s food", 291. (t1->sex == 'F') ? "her" : "his"); 292. else if(!strncmp(t1->death,"starv",5)) 293. Sprintf(eos(linebuf), "starved to death"), starv = TRUE; 294. else Sprintf(eos(linebuf), ", killed"), killed = TRUE; 295. Sprintf(eos(linebuf), " on%s level %d", 296. (killed || starv) ? "" : " dungeon", t1->level); 297. if(t1->maxlvl != t1->level) 298. Sprintf(eos(linebuf), " [max %d]", t1->maxlvl); 299. if(quit && t1->death[4]) Sprintf(eos(linebuf), t1->death + 4); 300. } 301. if(killed) Sprintf(eos(linebuf), " by %s%s", 302. (!strncmp(t1->death, "trick", 5) || !strncmp(t1->death, "the ", 4)) 303. ? "" : 304. index(vowels,*t1->death) ? "an " : "a ", 305. t1->death); 306. Sprintf(eos(linebuf), "."); 307. if(t1->maxhp) { 308. register char *bp = eos(linebuf); 309. char hpbuf[10]; 310. int hppos; 311. #ifdef KJSMODS 312. int lngr = strlen(linebuf); 313. #endif 314. Sprintf(hpbuf, (t1->hp > 0) ? itoa(t1->hp) : "-"); 315. hppos = COLNO - 7 - strlen(hpbuf); 316. #ifdef KJSMODS 317. if (lngr >= hppos) hppos = (2*COLNO) - 7 - strlen(hpbuf); 318. #endif 319. if(bp <= linebuf + hppos) { 320. /* pad any necessary blanks to the hit point entry */ 321. while(bp < linebuf + hppos) *bp++ = ' '; 322. (void) strcpy(bp, hpbuf); 323. Sprintf(eos(bp), " [%d]", t1->maxhp); 324. } 325. } 326. if(so == 0) puts(linebuf); 327. else if(so > 0) { 328. register char *bp = eos(linebuf); 329. if(so >= COLNO) so = COLNO-1; 330. while(bp < linebuf + so) *bp++ = ' '; 331. *bp = 0; 332. standoutbeg(); 333. fputs(linebuf,stdout); 334. standoutend(); 335. (void) putchar('
'); 336. } 337. return(strlen(linebuf)); 338. } 339. 340. char * 341. itoa(a) int a; { 342. static char buf[12]; 343. Sprintf(buf,"%d",a); 344. return(buf); 345. } 346. 347. char * 348. ordin(n) int n; { 349. register int d = n%10; 350. return((d==0 || d>3 || n/10==1) ? "th" : (d==1) ? "st" : 351. (d==2) ? "nd" : "rd"); 352. } 353. 354. char * 355. eos(s) 356. register char *s; 357. { 358. while(*s) s++; 359. return(s); 360. } 361. 362. /* 363. * Called with args from main if argc >= 0. In this case, list scores as 364. * requested. Otherwise, find scores for the current player (and list them 365. * if argc == -1). 366. */ 367. prscore(argc,argv) int argc; char **argv; { 368. extern char *hname; 369. char **players; 370. int playerct; 371. int rank; 372. register struct toptenentry *t1, *t2; 373. char *recfile = RECORD; 374. FILE *rfile; 375. register flg = 0; 376. register int i; 377. #ifdef nonsense 378. long total_score = 0L; 379. char totchars[10]; 380. int totcharct = 0; 381. #endif 382. int outflg = (argc >= -1); 383. #ifdef PERS_IS_UID 384. int uid = -1; 385. #else 386. char *player0; 387. #endif 388. 389. if(!(rfile = fopen(recfile,"r"))){ 390. puts("Cannot open record file!"); 391. return; 392. } 393. 394. if(argc > 1 && !strncmp(argv[1], "-s", 2)){ 395. if(!argv[1][2]){ 396. argc--; 397. argv++; 398. } else if(!argv[1][3] && index("CFKSTWX", argv[1][2])) { 399. argv[1]++; 400. argv[1][0] = '-'; 401. } else argv[1] += 2; 402. } 403. if(argc <= 1){ 404. #ifdef PERS_IS_UID 405. uid = getuid(); 406. playerct = 0; 407. #else 408. player0 = plname; 409. if(!*player0) 410. player0 = "hackplayer"; 411. playerct = 1; 412. players = &player0; 413. #endif 414. } else { 415. playerct = --argc; 416. players = ++argv; 417. } 418. if(outflg) putchar('
'); 419. 420. t1 = tt_head = newttentry(); 421. for(rank = 1; ; rank++) { 422. if(fscanf(rfile, "%6s %d %d %d %d %d %ld %c%c %[^,],%[^
]", 423. t1->date, &t1->uid, 424. &t1->level, &t1->maxlvl, 425. &t1->hp, &t1->maxhp, &t1->points, 426. &t1->plchar, &t1->sex, t1->name, t1->death) != 11) 427. t1->points = 0; 428. if(t1->points == 0) break; 429. #ifdef PERS_IS_UID 430. if(!playerct && t1->uid == uid) 431. flg++; 432. else 433. #endif 434. for(i = 0; i < playerct; i++){ 435. if(strcmp(players[i], "all") == 0 || 436. strncmp(t1->name, players[i], NAMSZ) == 0 || 437. (players[i][0] == '-' && 438. players[i][1] == t1->plchar && 439. players[i][2] == 0) || 440. (digit(players[i][0]) && rank <= atoi(players[i]))) 441. flg++; 442. } 443. t1 = t1->tt_next = newttentry(); 444. } 445. (void) fclose(rfile); 446. if(!flg) { 447. if(outflg) { 448. printf("Cannot find any entries for "); 449. if(playerct < 1) printf("you.
"); 450. else { 451. if(playerct > 1) printf("any of "); 454. printf("Call is: %s -s [playernames]
", hname); 455. } 456. } 457. return; 458. } 459. 460. if(outflg) outheader(); 461. t1 = tt_head; 462. for(rank = 1; t1->points != 0; rank++, t1 = t2) { 463. t2 = t1->tt_next; 464. #ifdef PERS_IS_UID 465. if(!playerct && t1->uid == uid) 466. goto outwithit; 467. else 468. #endif 469. for(i = 0; i < playerct; i++){ 470. if(strcmp(players[i], "all") == 0 || 471. strncmp(t1->name, players[i], NAMSZ) == 0 || 472. (players[i][0] == '-' && 473. players[i][1] == t1->plchar && 474. players[i][2] == 0) || 475. (digit(players[i][0]) && rank <= atoi(players[i]))){ 476. outwithit: 477. if(outflg) 478. (void) outentry(rank, t1, 0); 479. #ifdef nonsense 480. total_score += t1->points; 481. if(totcharct < sizeof(totchars)-1) 482. totchars[totcharct++] = t1->plchar; 483. #endif 484. break; 485. } 486. } 487. free((char *) t1); 488. } 489. #ifdef nonsense 490. totchars[totcharct] = 0; 491. 492. /* We would like to determine whether he is experienced. However, 493. the information collected here only tells about the scores/roles 494. that got into the topten (top 100?). We should maintain a 495. .hacklog or something in his home directory. */ 496. flags.beginner = (total_score < 6000); 497. for(i=0; i<6; i++) 498. if(!index(totchars, "CFKSTWX"[i])) { 499. flags.beginner = 1; 500. if(!pl_character[0]) pl_character[0] = "CFKSTWX"[i]; 501. break; 502. } 503. #endif /* nonsense /**/ 504. }
|