Source:NetHack 3.3.0/rumors.c

Below is the full text to rumors.c from the source code of NetHack 3.3.0. To link to a particular line, write [[NetHack 3.3.0/rumors.c#line123 ]], for example.

Warning! This is the source code from an old release. For the latest release, see Source code

1.   /*	SCCS Id: @(#)rumors.c	3.3	96/04/20	*/ 2.   /* Copyright (c) Stichting Mathematisch Centrum, Amsterdam, 1985. */ 3.    /* NetHack may be freely redistributed. See license for details. */ 4.     5.    #include "hack.h"  6.    #include "lev.h"  7.    #include "dlb.h"  8. 9.   /*	[note: this comment is fairly old, but still accurate for 3.1] 10.   * Rumors have been entirely rewritten to speed up the access. This is 11. * essential when working from floppies. Using fseek the way that's done 12.   * here means rumors following longer rumors are output more often than those 13.   * following shorter rumors. Also, you may see the same rumor more than once 14.   * in a particular game (although the odds are highly against it), but 15.   * this also happens with real fortune cookies. -dgk 16.   */  17.    18.   /*	3.1  19.    * The rumors file consists of a "do not edit" line, a hexadecimal number 20.   * giving the number of bytes of useful/true rumors, followed by those 21.   * true rumors (one per line), followed by the useless/false/misleading/cute 22.   * rumors (also one per line). Number of bytes of untrue rumors is derived 23.   * via fseek(EOF)+ftell. 24.   *  25.    * The oracles file consists of a "do not edit" comment, a decimal count N  26. * and set of N+1 hexadecimal fseek offsets, followed by N multiple-line 27.   * records, separated by "---" lines. The first oracle is a special case, 28.   * and placed there by 'makedefs'. 29.   */  30.    31.   STATIC_DCL void FDECL(init_rumors, (dlb *)); 32.  STATIC_DCL void FDECL(init_oracles, (dlb *)); 33.   34.   static long true_rumor_start,  true_rumor_size,  true_rumor_end, 35.  	    false_rumor_start, false_rumor_size, false_rumor_end; 36.  static int oracle_flg = 0;  /* -1=>don't use, 0=>need init, 1=>init done */ 37.  static unsigned oracle_cnt = 0; 38.  static long *oracle_loc = 0; 39.   40.   STATIC_OVL void 41.  init_rumors(fp) 42.  dlb *fp; 43.  {  44.   	char line[BUFSZ]; 45.   46.   	(void) dlb_fgets(line, sizeof line, fp); /* skip "don't edit" comment */ 47.  	(void) dlb_fgets(line, sizeof line, fp); 48.  	if (sscanf(line, "%6lx\n", &true_rumor_size) == 1 &&  49.   	    true_rumor_size > 0L) { 50.  	    (void) dlb_fseek(fp, 0L, SEEK_CUR); 51.  	    true_rumor_start  = dlb_ftell(fp); 52.  	    true_rumor_end    = true_rumor_start + true_rumor_size; 53.  	    (void) dlb_fseek(fp, 0L, SEEK_END); 54.  	    false_rumor_end   = dlb_ftell(fp); 55.  	    false_rumor_start = true_rumor_end;	/* ok, so it's redundant... */ 56.   	    false_rumor_size  = false_rumor_end - false_rumor_start; 57.  	} else 58.  	    true_rumor_size = -1L;	/* init failed */ 59.  }  60.    61.   char * 62.  getrumor(truth, rumor_buf) 63.  int truth; /* 1=true, -1=false, 0=either */ 64.  char *rumor_buf; 65.  {  66.   	dlb	*rumors; 67.  	long tidbit, beginning; 68.  	char	*endp, line[BUFSZ], xbuf[BUFSZ]; 69.   70.   	rumor_buf[0] = '\0'; 71.  	if (true_rumor_size < 0L)	/* we couldn't open RUMORFILE */ 72.  		return rumor_buf; 73.   74.   	rumors = dlb_fopen(RUMORFILE, "r"); 75.   76.   	if (rumors) { 77.  		if (true_rumor_size == 0L) {	/* if this is 1st outrumor */ 78.  		    init_rumors(rumors); 79.  		    if (true_rumor_size < 0L) {	/* init failed */ 80.  			Sprintf(rumor_buf, "Error reading \"%.80s\".",  81.   				RUMORFILE); 82.  			return rumor_buf; 83.  		    }  84.   		}  85.   		/*  86.   		 *	input:      1    0   -1 87.  		 *	 rn2 \ +1  2=T  1=T  0=F 88.  		 *	 adj./ +0  1=T  0=F -1=F 89.  		 */  90.   		switch (truth += rn2(2)) { 91.  		  case  2:	/*(might let a bogus input arg sneak thru)*/ 92.  		  case  1:  beginning = true_rumor_start; 93.  			    tidbit = Rand % true_rumor_size; 94.  			break; 95.  		  case  0:	/* once here, 0 => false rather than "either"*/ 96.  		  case -1:  beginning = false_rumor_start; 97.  			    tidbit = Rand % false_rumor_size; 98.  			break; 99.  		  default: 100. 			    impossible("strange truth value for rumor"); 101. 			return strcpy(rumor_buf, "Oops..."); 102. 		}  103.  		(void) dlb_fseek(rumors, beginning + tidbit, SEEK_SET); 104. 		(void) dlb_fgets(line, sizeof line, rumors); 105. 		if (!dlb_fgets(line, sizeof line, rumors) ||  106.  		    (truth > 0 && dlb_ftell(rumors) > true_rumor_end)) { 107. 			/* reached end of rumors -- go back to beginning */ 108. 			(void) dlb_fseek(rumors, beginning, SEEK_SET); 109. 			(void) dlb_fgets(line, sizeof line, rumors); 110. 		}  111.  		if ((endp = index(line, '\n')) != 0) *endp = 0; 112. 		Strcat(rumor_buf, xcrypt(line, xbuf)); 113. 		(void) dlb_fclose(rumors); 114. 		exercise(A_WIS, (truth > 0)); 115. 	} else { 116. 		pline("Can't open rumors file!"); 117. 		true_rumor_size = -1;	/* don't try to open it again */ 118. 	}  119.  	return rumor_buf; 120. }  121.   122.  void 123. outrumor(truth, mechanism) 124. int truth; /* 1=true, -1=false, 0=either */ 125. int mechanism; 126. {  127.  	static const char fortune_msg[] = 128. 		"This cookie has a scrap of paper inside."; 129. 	const char *line; 130. 	char buf[BUFSZ]; 131. 	boolean reading = (mechanism == BY_COOKIE ||  132.  			   mechanism == BY_PAPER); 133.  134.  	if (reading && Blind) { 135. 		if (mechanism == BY_COOKIE) 136. 			pline(fortune_msg); 137. 		pline("What a pity that you cannot read it!"); 138. 		return; 139. 	}  140.  	line = getrumor(truth, buf); 141. 	if (!*line) 142. 		line = "NetHack rumors file closed for renovation."; 143. 	switch (mechanism) { 144. 	    case BY_ORACLE: 145. 	 	/* Oracle delivers the rumor */ 146. 		pline("True to her word, the Oracle %ssays: ",  147.  		  (!rn2(4) ? "offhandedly " : (!rn2(3) ? "casually " : 148.  		  (rn2(2) ? "nonchalantly " : "")))); 149. 		verbalize("%s", line); 150. 		exercise(A_WIS, TRUE); 151. 		return; 152. 	    case BY_COOKIE: 153. 		pline(fortune_msg); 154. 		/* FALLTHRU */ 155. 	    case BY_PAPER: 156. 		pline("It reads:"); 157. 		break; 158. 	}  159.  	pline("%s", line); 160. }  161.   162.  STATIC_OVL void 163. init_oracles(fp) 164. dlb *fp; 165. {  166.  	register int i;  167. char line[BUFSZ]; 168. 	int cnt = 0; 169.  170.  	/* this assumes we're only called once */ 171. 	(void) dlb_fgets(line, sizeof line, fp); /* skip "don't edit" comment*/ 172. 	(void) dlb_fgets(line, sizeof line, fp); 173. 	if (sscanf(line, "%5d\n", &cnt) == 1 && cnt > 0) { 174. 	    oracle_cnt = (unsigned) cnt; 175. 	    oracle_loc = (long *) alloc((unsigned)cnt * sizeof (long)); 176. 	    for (i = 0; i < cnt; i++) { 177. 		(void) dlb_fgets(line, sizeof line, fp); 178. 		(void) sscanf(line, "%5lx\n", &oracle_loc[i]); 179. 	    }  180.  	}  181.  	return; 182. }  183.   184.  void 185. save_oracles(fd, mode) 186. int fd, mode; 187. {  188.  	if (perform_bwrite(mode)) { 189. 	    bwrite(fd, (genericptr_t) &oracle_cnt, sizeof oracle_cnt); 190. 	    if (oracle_cnt) 191. 		bwrite(fd, (genericptr_t)oracle_loc, oracle_cnt*sizeof (long)); 192. 	}  193.  	if (release_data(mode)) { 194. 	    if (oracle_cnt) { 195. 		free((genericptr_t)oracle_loc); 196. 		oracle_loc = 0,  oracle_cnt = 0,  oracle_flg = 0; 197. 	    }  198.  	}  199.  }  200.   201.  void 202. restore_oracles(fd) 203. int fd; 204. {  205.  	mread(fd, (genericptr_t) &oracle_cnt, sizeof oracle_cnt); 206. 	if (oracle_cnt) { 207. 	    oracle_loc = (long *) alloc(oracle_cnt * sizeof (long)); 208. 	    mread(fd, (genericptr_t) oracle_loc, oracle_cnt * sizeof (long)); 209. 	    oracle_flg = 1;	/* no need to call init_oracles */ 210. 	}  211.  }  212.   213.  void 214. outoracle(special, delphi) 215. boolean special; 216. boolean delphi; 217. {  218.  	char	line[COLNO]; 219. 	char	*endp; 220. 	dlb	*oracles; 221. 	int oracle_idx; 222. 	char xbuf[BUFSZ]; 223.  224.  	if(oracle_flg < 0 ||			/* couldn't open ORACLEFILE */  225.  	   (oracle_flg > 0 && oracle_cnt == 0))	/* oracles already exhausted */ 226. 		return; 227.  228.  	oracles = dlb_fopen(ORACLEFILE, "r"); 229.  230.  	if (oracles) { 231. 		winid tmpwin; 232. 		if (oracle_flg == 0) {	/* if this is the first outoracle */ 233. 			init_oracles(oracles); 234. 			oracle_flg = 1; 235. 			if (oracle_cnt == 0) return; 236. 		}  237.  		/* oracle_loc[0] is the special oracle;		*/ 238. 		/* oracle_loc[1..oracle_cnt-1] are normal ones	*/ 239. 		if (oracle_cnt <= 1 && !special) return;  /*(shouldn't happen)*/ 240. 		oracle_idx = special ? 0 : rnd((int) oracle_cnt - 1); 241. 		(void) dlb_fseek(oracles, oracle_loc[oracle_idx], SEEK_SET); 242. 		if (!special) oracle_loc[oracle_idx] = oracle_loc[--oracle_cnt]; 243.  244.  		tmpwin = create_nhwindow(NHW_TEXT); 245. 		if (delphi) 246. 		    putstr(tmpwin, 0, special ?  247.  		          "The Oracle scornfully takes all your money and says:" :  248.  		          "The Oracle meditates for a moment and then intones:"); 249. 		else 250. 		    putstr(tmpwin, 0, "The message reads:"); 251. 		putstr(tmpwin, 0, ""); 252.  253.  		while(dlb_fgets(line, COLNO, oracles) && strcmp(line,"---\n")) { 254. 			if ((endp = index(line, '\n')) != 0) *endp = 0; 255. 			putstr(tmpwin, 0, xcrypt(line, xbuf)); 256. 		}  257.  		display_nhwindow(tmpwin, TRUE); 258. 		destroy_nhwindow(tmpwin); 259. 		(void) dlb_fclose(oracles); 260. 	} else { 261. 		pline("Can't open oracles file!"); 262. 		oracle_flg = -1;	/* don't try to open it again */ 263. 	}  264.  }  265.   266.  int 267. doconsult(oracl) 268. register struct monst *oracl; 269. {  270.  	int u_pay, minor_cost = 50, major_cost = 500 + 50 * u.ulevel; 271. 	int add_xpts; 272. 	char qbuf[QBUFSZ]; 273.  274.  	multi = 0; 275.  276.  	if (!oracl) { 277. 		pline("There is no one here to consult."); 278. 		return 0; 279. 	} else if (!oracl->mpeaceful) { 280. 		pline("%s is in no mood for consultations.", Monnam(oracl)); 281. 		return 0; 282. 	} else if (!u.ugold) { 283. 		You("have no money."); 284. 		return 0; 285. 	}  286.   287.  	Sprintf(qbuf,  288.  		"\"Wilt thou settle for a minor consultation?\" (%d zorkmids)",  289.  		minor_cost); 290. 	switch (ynq(qbuf)) { 291. 	    default: 292. 	    case 'q': 293. 		return 0; 294. 	    case 'y': 295. 		if (u.ugold < (long)minor_cost) { 296. 		    You("don't even have enough money for that!"); 297. 		    return 0; 298. 		}  299.  		u_pay = minor_cost; 300. 		break; 301. 	    case 'n': 302. 		if (u.ugold <= (long)minor_cost ||	/* don't even ask */  303.  		    (oracle_cnt == 1 || oracle_flg < 0)) return 0; 304. 		Sprintf(qbuf,  305.  			"\"Then dost thou desire a major one?\" (%d zorkmids)",  306.  			major_cost); 307. 		if (yn(qbuf) != 'y') return 0; 308. 		u_pay = (u.ugold < (long)major_cost ? (int)u.ugold  309.  						    : major_cost); 310. 		break; 311. 	}  312.  	u.ugold -= (long)u_pay; 313. 	oracl->mgold += (long)u_pay; 314. 	flags.botl = 1; 315. 	add_xpts = 0;	/* first oracle of each type gives experience points */ 316. 	if (u_pay == minor_cost) { 317. 		outrumor(1, BY_ORACLE); 318. 		if (!u.uevent.minor_oracle) 319. 		    add_xpts = u_pay / (u.uevent.major_oracle ? 25 : 10); 320. 		    /* 5 pts if very 1st, or 2 pts if major already done */ 321. 		u.uevent.minor_oracle = TRUE; 322. 	} else { 323. 		boolean cheapskate = u_pay < major_cost; 324. 		outoracle(cheapskate, TRUE); 325. 		if (!cheapskate && !u.uevent.major_oracle) 326. 		    add_xpts = u_pay / (u.uevent.minor_oracle ? 25 : 10); 327. 		    /* ~100 pts if very 1st, ~40 pts if minor already done */ 328. 		u.uevent.major_oracle = TRUE; 329. 		exercise(A_WIS, !cheapskate); 330. 	}  331.  	if (add_xpts) { 332. 		more_experienced(add_xpts, u_pay/50); 333. 		newexplevel; 334. 	}  335.  	return 1; 336. }  337.   338.  /*rumors.c*/