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