Source:NetHack 2.2a/topten.c
Revision as of 02:52, 4 March 2008 by Kernigh bot (talk | contribs) (NetHack 2.2a/topten.c moved to Source:NetHack 2.2a/topten.c: Robot: moved page)
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
Screenshots and source code from Hack are used under the CWI license.
1. /* SCCS Id: @(#)topten.c 2.1 87/09/28 2. /* Copyright (c) Stichting Mathematisch Centrum, Amsterdam, 1985. */ 3. 4. #include <stdio.h> 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)\n", 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('\n'); 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 %[^,],%[^\n]", 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.\n\n", 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\n"); 148. goto unlock; 149. } 150. 151. if(!done_stopprint) if(rank0 > 0){ 152. if(rank0 <= 10) 153. puts("You made the top ten list!\n"); 154. else 155. printf("You reached the %d%s place on the top %d list.\n\n", 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\n", 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('\n'); 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('\n'); 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('\n'); 382. 383. t1 = tt_head = newttentry(); 384. for(rank = 1; ; rank++) { 385. if(fscanf(rfile, "%6s %d %d %d %d %d %ld %c%c %[^,],%[^\n]", 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.\n"); 413. else { 414. if(playerct > 1) printf("any of "); 415. for(i=0; i<playerct; i++) 416. printf("%s%s", players[i], (i<playerct-1)?", ":".\n"); 417. printf("Call is: %s -s [playernames]\n", 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. }