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

1.   /* Copyright (c) Stichting Mathematisch Centrum, Amsterdam, 1984. */ 2.     3.    #include "hack.h"  4.    #include   5.    #include   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; ipoints != 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.  }