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