Source:Hack 1.0/hack.end.c
Below is the full text to hack.end.c from the source code of Hack 1.0. To link to a particular line, write [[Hack 1.0/hack.end.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. /* Copyright (c) Stichting Mathematisch Centrum, Amsterdam, 1984. */ 2. 3. #include "hack.h" 4. #include <stdio.h> 5. #include <signal.h> 6. #define Sprintf (void) sprintf 7. extern char plname[], pl_character[]; 8. extern char *itoa(), *ordin(), *eos(), *getlogin(); 9. 10. xchar maxdlevel = 1; 11. 12. done1() 13. { 14. (void) signal(SIGINT,SIG_IGN); 15. pline("Really quit?"); 16. if(readchar() != 'y') { 17. (void) signal(SIGINT,done1); 18. clrlin(); 19. (void) fflush(stdout); 20. if(multi > 0) nomul(0); 21. return(0); 22. } 23. done("quit"); 24. /* NOTREACHED */ 25. } 26. 27. int done_stopprint; 28. 29. done_intr(){ 30. done_stopprint++; 31. (void) signal(SIGINT,SIG_IGN); 32. } 33. 34. done_in_by(mtmp) register struct monst *mtmp; { 35. static char buf[BUFSZ]; 36. pline("You die ..."); 37. if(mtmp->data->mlet == ' '){ 38. Sprintf(buf, "the ghost of %s", (char *) mtmp->mextra); 39. killer = buf; 40. } else if(mtmp->mnamelth) { 41. Sprintf(buf, "%s called %s", 42. mtmp->data->mname, NAME(mtmp)); 43. killer = buf; 44. } else if(mtmp->minvis) { 45. Sprintf(buf, "invisible %s", mtmp->data->mname); 46. killer = buf; 47. } else killer = mtmp->data->mname; 48. done("died"); 49. } 50. 51. /* called with arg "died", "escaped", "quit", "choked", "panic" 52. or "starved" */ 53. /* Be careful not to call panic from here! */ 54. done(st1) 55. register char *st1; 56. { 57. 58. #ifdef WIZARD 59. if(wizard && *st1 == 'd'){ 60. u.ustr = u.ustrmax += 2; 61. u.uhp = u.uhpmax += 10; 62. if(uarm) uarm->spe++; 63. if(uwep) uwep->spe++; /* NB: uwep need not be a weapon! */ 64. u.uswldtim = 0; 65. pline("For some reason you are still alive."); 66. flags.move = 0; 67. if(multi > 0) multi = 0; else multi = -1; 68. flags.botl = 1; 69. return; 70. } 71. #endif WIZARD 72. (void) signal(SIGINT, done_intr); 73. if(*st1 == 'q' && u.uhp < 1){ 74. st1 = "died"; 75. killer = "quit while already on Charon's boat"; 76. } 77. if(*st1 == 's') killer = "starvation"; 78. paybill(); 79. clearlocks(); 80. if(index("cds", *st1)){ 81. savebones(); 82. outrip(); 83. } 84. settty((char *) 0); /* does a cls() */ 85. if(!done_stopprint) 86. printf("Goodbye %s %s...\n\n", pl_character, plname); 87. { long int tmp; 88. tmp = u.ugold - u.ugold0; 89. if(tmp < 0) tmp = 0; 90. if(*st1 == 'd') tmp -= tmp/10; 91. else killer = st1; 92. u.urexp += tmp; 93. } 94. if(*st1 == 'e') { 95. extern struct monst *mydogs; 96. register struct monst *mtmp = mydogs; 97. register struct obj *otmp; 98. register int i; 99. register unsigned worthlessct = 0; 100. 101. u.urexp += 50 * maxdlevel; 102. if(mtmp) { 103. if(!done_stopprint) printf("You"); 104. while(mtmp) { 105. if(!done_stopprint) 106. printf(" and %s", monnam(mtmp)); 107. u.urexp += mtmp->mhp; 108. mtmp = mtmp->nmon; 109. } 110. if(!done_stopprint) 111. printf("\nescaped from the dungeon with %lu points,\n", 112. u.urexp); 113. } else 114. if(!done_stopprint) 115. printf("You escaped from the dungeon with %lu points,\n", 116. u.urexp); 117. for(otmp = invent; otmp; otmp = otmp->nobj) { 118. if(otmp->olet == GEM_SYM){ 119. objects[otmp->otyp].oc_name_known = 1; 120. i = otmp->quan*objects[otmp->otyp].g_val; 121. if(i == 0) { 122. worthlessct += otmp->quan; 123. continue; 124. } 125. u.urexp += i; 126. if(!done_stopprint) 127. printf("\t%s (worth %d Zorkmids),\n", 128. doname(otmp), i); 129. } else if(otmp->olet == AMULET_SYM) { 130. otmp->known = 1; 131. i = (otmp->spe < 0) ? 2 : 5000; 132. u.urexp += i; 133. if(!done_stopprint) 134. printf("\t%s (worth %d Zorkmids),\n", 135. doname(otmp), i); 136. if(otmp->spe >= 0) u.urexp *= 2; 137. } 138. } 139. if(worthlessct) if(!done_stopprint) 140. printf("\t%d worthless piece%s of coloured glass,\n", 141. worthlessct, plur(worthlessct)); 142. killer=st1; 143. } else 144. if(!done_stopprint) 145. printf("You %s on dungeon level %d with %lu points,\n", 146. st1,dlevel,u.urexp); 147. if(!done_stopprint) 148. printf("and %lu piece%s of gold, after %lu move%s.\n", 149. u.ugold, (u.ugold == 1) ? "" : "s", 150. moves, (moves == 1) ? "" : "s"); 151. if(!done_stopprint) 152. printf("You were level %d with a maximum of %d hit points when you %s.\n", 153. u.ulevel, u.uhpmax, st1); 154. if(*st1 == 'e'){ 155. getret(); /* all those pieces of coloured glass ... */ 156. cls(); 157. } 158. #ifdef WIZARD 159. if(!wizard) 160. #endif WIZARD 161. topten(); 162. if(done_stopprint) printf("\n\n"); 163. exit(0); 164. } 165. 166. #define newttentry() (struct toptenentry *) alloc(sizeof(struct toptenentry)) 167. #define NAMSZ 8 168. #define DTHSZ 40 169. #define PERSMAX 1 170. #define POINTSMIN 1 /* must be > 0 */ 171. #define ENTRYMAX 100 /* must be >= 10 */ 172. struct toptenentry { 173. struct toptenentry *tt_next; 174. long int points; 175. int level,maxlvl,hp,maxhp; 176. char plchar; 177. char str[NAMSZ+1]; 178. char death[DTHSZ+1]; 179. } *tt_head; 180. 181. topten(){ 182. int rank, rank0 = -1, rank1 = 0; 183. int occ_cnt = PERSMAX; 184. register struct toptenentry *t0, *t1, *tprev; 185. char *recfile = "record"; 186. FILE *rfile; 187. register flg = 0; 188. 189. if(!(rfile = fopen(recfile,"r"))){ 190. puts("Cannot open record file!"); 191. return; 192. } 193. (void) putchar('\n'); 194. 195. /* create a new 'topten' entry */ 196. t0 = newttentry(); 197. t0->level = dlevel; 198. t0->maxlvl = maxdlevel; 199. t0->hp = u.uhp; 200. t0->maxhp = u.uhpmax; 201. t0->points = u.urexp; 202. t0->plchar = pl_character[0]; 203. (void) strncpy(t0->str, plname, NAMSZ); 204. (t0->str)[NAMSZ] = 0; 205. (void) strncpy(t0->death, killer, DTHSZ); 206. (t0->death)[DTHSZ] = 0; 207. 208. /* assure minimum number of points */ 209. if(t0->points < POINTSMIN) 210. t0->points = 0; 211. 212. t1 = tt_head = newttentry(); 213. tprev = 0; 214. /* rank0: -1 undefined, 0 not_on_list, n n_th on list */ 215. for(rank = 1; ; ) { 216. if(fscanf(rfile, "%d %d %d %d %ld %c %[^,],%[^\n]", 217. &t1->level, &t1->maxlvl, 218. &t1->hp, &t1->maxhp, &t1->points, 219. &t1->plchar, t1->str, t1->death) != 8 220. || t1->points < POINTSMIN) 221. t1->points = 0; 222. if(rank0 < 0 && t1->points < t0->points) { 223. rank0 = rank++; 224. if(tprev == 0) 225. tt_head = t0; 226. else 227. tprev->tt_next = t0; 228. t0->tt_next = t1; 229. occ_cnt--; 230. flg++; /* ask for a rewrite */ 231. } else 232. tprev = t1; 233. if(t1->points == 0) break; 234. if(strncmp(t1->str, t0->str, NAMSZ) == 0 && 235. t1->plchar == t0->plchar && --occ_cnt <= 0){ 236. if(rank0 < 0){ 237. rank0 = 0; 238. rank1 = rank; 239. printf("You didn't beat your previous score of %ld points.\n\n", 240. t1->points); 241. } 242. if(occ_cnt < 0){ 243. flg++; 244. continue; 245. } 246. } 247. if(rank <= ENTRYMAX){ 248. t1 = t1->tt_next = newttentry(); 249. rank++; 250. } 251. if(rank > ENTRYMAX){ 252. t1->points = 0; 253. break; 254. } 255. } 256. if(flg) { /* rewrite record file */ 257. (void) fclose(rfile); 258. if(!(rfile=fopen(recfile,"w"))){ 259. puts("Cannot write record file\n"); 260. return; 261. } 262. 263. if(!done_stopprint) if(rank0 > 0){ 264. if(rank0 <= 10) 265. puts("You made the top ten list!\n"); 266. else 267. printf("You reached the %d%s place on the top %d list.\n\n", 268. rank0, ordin(rank0), ENTRYMAX); 269. } 270. } 271. if(rank0 == 0) rank0 = rank1; 272. if(rank0 <= 0) rank0 = rank; 273. if(!done_stopprint) outheader(); 274. t1 = tt_head; 275. for(rank = 1; t1->points != 0; rank++, t1 = t1->tt_next) { 276. if(flg) fprintf(rfile,"%d %d %d %d %ld %c %s,%s\n", 277. t1->level, t1->maxlvl, 278. t1->hp, t1->maxhp, t1->points, 279. t1->plchar,t1->str,t1->death); 280. if(done_stopprint) continue; 281. if(rank > 5 && (rank < rank0 - 4 || rank > rank0 + 4)) 282. continue; 283. if(rank == rank0 - 4 && rank0 > 10) (void) putchar('\n'); 284. if(rank != rank0) 285. (void) outentry(rank, t1, 0); 286. else if(!rank1) 287. (void) outentry(rank, t1, 1); 288. else { 289. int t0lth = outentry(0, t0, -1); 290. int t1lth = outentry(rank, t1, t0lth); 291. if(t1lth > t0lth) t0lth = t1lth; 292. (void) outentry(0, t0, t0lth); 293. } 294. } 295. if(rank0 >= rank) 296. (void) outentry(0, t0, 1); 297. (void) fclose(rfile); 298. } 299. 300. outheader() { 301. char linebuf[BUFSZ]; 302. register char *bp; 303. (void) strcpy(linebuf, "Number Points Name"); 304. bp = eos(linebuf); 305. while(bp < linebuf + COLNO - 9) *bp++ = ' '; 306. (void) strcpy(bp, "Hp [max]"); 307. puts(linebuf); 308. } 309. 310. /* so>0: standout line; so=0: ordinary line; so<0: no output, return lth */ 311. int 312. outentry(rank,t1,so) register struct toptenentry *t1; { 313. boolean quit = FALSE, killed = FALSE, starv = FALSE; 314. char linebuf[BUFSZ]; 315. linebuf[0] = 0; 316. if(rank) Sprintf(eos(linebuf), "%3d", rank); 317. else Sprintf(eos(linebuf), " "); 318. Sprintf(eos(linebuf), " %6ld %8s", t1->points, t1->str); 319. if(t1->plchar == 'X') Sprintf(eos(linebuf), " "); 320. else Sprintf(eos(linebuf), "-%c ", t1->plchar); 321. if(!strcmp("escaped", t1->death)) 322. Sprintf(eos(linebuf), "escaped the dungeon [max level %d]", 323. t1->maxlvl); 324. else { 325. if(!strncmp(t1->death,"quit",4)) 326. Sprintf(eos(linebuf), "quit"), quit = TRUE; 327. else if(!strcmp(t1->death,"choked")) 328. Sprintf(eos(linebuf), "choked in his food"); 329. else if(!strncmp(t1->death,"starv",5)) 330. Sprintf(eos(linebuf), "starved to death"), starv = TRUE; 331. else Sprintf(eos(linebuf), "was killed"), killed = TRUE; 332. Sprintf(eos(linebuf), " on%s level %d", 333. (killed || starv) ? "" : " dungeon", t1->level); 334. if(t1->maxlvl != t1->level) 335. Sprintf(eos(linebuf), " [max %d]", t1->maxlvl); 336. if(quit && t1->death[4]) Sprintf(eos(linebuf), t1->death + 4); 337. } 338. if(killed) Sprintf(eos(linebuf), " by %s%s", 339. !strncmp(t1->death, "the ", 4) ? "" : 340. index(vowels,*t1->death) ? "an " : "a ", 341. t1->death); 342. Sprintf(eos(linebuf), "."); 343. if(t1->maxhp) { 344. register char *bp = eos(linebuf); 345. char hpbuf[10]; 346. int hppos; 347. Sprintf(hpbuf, (t1->hp > 0) ? itoa(t1->hp) : "-"); 348. hppos = COLNO - 7 - strlen(hpbuf); 349. if(bp <= linebuf + hppos) { 350. while(bp < linebuf + hppos) *bp++ = ' '; 351. (void) strcpy(bp, hpbuf); 352. Sprintf(eos(bp), " [%d]", t1->maxhp); 353. } 354. } 355. if(so == 0) puts(linebuf); 356. else if(so > 0) { 357. register char *bp = eos(linebuf); 358. if(so >= COLNO) so = COLNO-1; 359. while(bp < linebuf + so) *bp++ = ' '; 360. *bp = 0; 361. standoutbeg(); 362. fputs(linebuf,stdout); 363. standoutend(); 364. (void) putchar('\n'); 365. } 366. return(strlen(linebuf)); 367. } 368. 369. char * 370. itoa(a) int a; { 371. static char buf[12]; 372. Sprintf(buf,"%d",a); 373. return(buf); 374. } 375. 376. char * 377. ordin(n) int n; { 378. register int d = n%10; 379. return((d==0 || d>3 || n/10==1) ? "th" : (d==1) ? "st" : 380. (d==2) ? "nd" : "rd"); 381. } 382. 383. clearlocks(){ 384. register x; 385. (void) signal(SIGHUP,SIG_IGN); 386. for(x = 1; x <= maxdlevel; x++) { 387. glo(x); 388. (void) unlink(lock); /* not all levels need be present */ 389. } 390. (*index(lock,'.')) = 0; 391. (void) unlink(lock); 392. } 393. 394. #ifdef NOSAVEONHANGUP 395. hangup(){ 396. (void) signal(SIGINT,SIG_IGN); 397. clearlocks(); 398. exit(1); 399. } 400. #endif NOSAVEONHANGUP 401. 402. char * 403. eos(s) register char *s; { 404. while(*s) s++; 405. return(s); 406. } 407. 408. /* it is the callers responsibility to check that there is room for c */ 409. charcat(s,c) register char *s, c; { 410. while(*s) s++; 411. *s++ = c; 412. *s = 0; 413. } 414. 415. prscore(argc,argv) int argc; char **argv; { 416. extern char *hname; 417. char *player0; 418. char **players; 419. int playerct; 420. int rank; 421. register struct toptenentry *t1; 422. char *recfile = "record"; 423. FILE *rfile; 424. register flg = 0; 425. register int i; 426. 427. if(!(rfile = fopen(recfile,"r"))){ 428. puts("Cannot open record file!"); 429. return; 430. } 431. 432. if(argc > 1 && !strncmp(argv[1], "-s", 2)){ 433. if(!argv[1][2]){ 434. argc--; 435. argv++; 436. } else if(!argv[1][3] && index("CFKSTWX", argv[1][2])) { 437. argv[1]++; 438. argv[1][0] = '-'; 439. } else argv[1] += 2; 440. } 441. if(argc <= 1){ 442. player0 = getlogin(); 443. if(!player0) player0 = "player"; 444. playerct = 1; 445. players = &player0; 446. } else { 447. playerct = --argc; 448. players = ++argv; 449. } 450. putchar('\n'); 451. 452. t1 = tt_head = newttentry(); 453. for(rank = 1; ; rank++) { 454. if(fscanf(rfile, "%d %d %d %d %ld %c %[^,],%[^\n]", 455. &t1->level, &t1->maxlvl, 456. &t1->hp, &t1->maxhp, &t1->points, 457. &t1->plchar, t1->str, t1->death) != 8) 458. t1->points = 0; 459. if(t1->points == 0) break; 460. for(i = 0; i < playerct; i++){ 461. if(strcmp(players[i], "all") == 0 || 462. strncmp(t1->str, players[i], NAMSZ) == 0 || 463. (players[i][0] == '-' && 464. players[i][1] == t1->plchar && 465. players[i][2] == 0) || 466. (digit(players[i][0]) && rank <= atoi(players[i]))) 467. flg++; 468. } 469. t1 = t1->tt_next = newttentry(); 470. } 471. (void) fclose(rfile); 472. if(!flg) { 473. printf("Cannot find any entries for "); 474. if(playerct > 1) printf("any of "); 475. for(i=0; i<playerct; i++) 476. printf("%s%s", players[i], (i<playerct-1)?", ":".\n"); 477. printf("Call is: %s -s [playernames]\n", hname); 478. return; 479. } 480. 481. outheader(); 482. t1 = tt_head; 483. for(rank = 1; t1->points != 0; rank++, t1 = t1->tt_next) { 484. for(i = 0; i < playerct; i++){ 485. if(strcmp(players[i], "all") == 0 || 486. strncmp(t1->str, players[i], NAMSZ) == 0 || 487. (players[i][0] == '-' && 488. players[i][1] == t1->plchar && 489. players[i][2] == 0) || 490. (digit(players[i][0]) && rank <= atoi(players[i]))) 491. goto out; 492. } 493. continue; 494. out: 495. (void) outentry(rank, t1, 0); 496. } 497. }