Source:NetHack 3.2.0/rumors.c

Below is the full text to rumors.c from the source code of NetHack 3.2.0. To link to a particular line, write [[NetHack 3.2.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.2	95/08/04	*/ 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 "dlb.h"  7. 8.   /*	[note: this comment is fairly old, but still accurate for 3.1] 9.    * Rumors have been entirely rewritten to speed up the access. This is 10. * essential when working from floppies. Using fseek the way that's done 11.   * here means rumors following longer rumors are output more often than those 12.   * following shorter rumors. Also, you may see the same rumor more than once 13.   * in a particular game (although the odds are highly against it), but 14.   * this also happens with real fortune cookies. -dgk 15.   */  16.    17.   /*	3.1  18.    * The rumors file consists of a "do not edit" line, a hexadecimal number 19.   * giving the number of bytes of useful/true rumors, followed by those 20.   * true rumors (one per line), followed by the useless/false/misleading/cute 21.   * rumors (also one per line). Number of bytes of untrue rumors is derived 22.   * via fseek(EOF)+ftell. 23.   *  24.    * The oracles file consists of a "do not edit" comment, a decimal count N  25. * and set of N+1 hexadecimal fseek offsets, followed by N multiple-line 26.   * records, separated by "---" lines. The first oracle is a special case, 27.   * and placed there by 'makedefs'. 28.   */  29.    30.   static void FDECL(init_rumors, (dlb *)); 31.  static void FDECL(init_oracles, (dlb *)); 32.  static void FDECL(outoracle, (BOOLEAN_P)); 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 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, cookie) 124. int truth; /* 1=true, -1=false, 0=either */ 125. boolean cookie; 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.  132.  	if (cookie && Blind) { 133. 		pline(fortune_msg); 134. 		pline("What a pity that you cannot read it!"); 135. 		return; 136. 	}  137.  	line = getrumor(truth, buf); 138. 	if (!*line) 139. 		line = "NetHack rumors file closed for renovation."; 140. 	if (cookie) { 141. 		pline(fortune_msg); 142. 		pline("It reads:"); 143. 		pline("%s", line); 144. 	} else {	/* if the Oracle is the only alternative */ 145. 		pline("True to her word, the Oracle %ssays: ",  146.  		(!rn2(4) ? "offhandedly " : (!rn2(3) ? "casually " : 147.  		(rn2(2) ? "nonchalantly " : "")))); 148. 		verbalize("%s", line); 149. 		exercise(A_WIS, TRUE); 150. 	}  151.  }  152.   153.  static void 154. init_oracles(fp) 155. dlb *fp; 156. {  157.  	register int i;  158. char line[BUFSZ]; 159. 	int cnt = 0; 160.  161.  	/* this assumes we're only called once */ 162. 	(void) dlb_fgets(line, sizeof line, fp); /* skip "don't edit" comment*/ 163. 	(void) dlb_fgets(line, sizeof line, fp); 164. 	if (sscanf(line, "%5d\n", &cnt) == 1 && cnt > 0) { 165. 	    oracle_cnt = (unsigned) cnt; 166. 	    oracle_loc = (long *) alloc((unsigned)cnt * sizeof (long)); 167. 	    for (i = 0; i < cnt; i++) { 168. 		(void) dlb_fgets(line, sizeof line, fp); 169. 		(void) sscanf(line, "%5lx\n", &oracle_loc[i]); 170. 	    }  171.  	}  172.  	return; 173. }  174.   175.  void 176. save_oracles(fd) 177. int fd; 178. {  179.  	bwrite(fd, (genericptr_t) &oracle_cnt, sizeof oracle_cnt); 180. 	if (oracle_cnt) 181. 	    bwrite(fd, (genericptr_t) oracle_loc, oracle_cnt * sizeof (long)); 182. }  183.   184.  void 185. restore_oracles(fd) 186. int fd; 187. {  188.  	mread(fd, (genericptr_t) &oracle_cnt, sizeof oracle_cnt); 189. 	if (oracle_cnt) { 190. 	    oracle_loc = (long *) alloc(oracle_cnt * sizeof (long)); 191. 	    mread(fd, (genericptr_t) oracle_loc, oracle_cnt * sizeof (long)); 192. 	    oracle_flg = 1;	/* no need to call init_oracles */ 193. 	}  194.  }  195.   196.  static void 197. outoracle(special) 198. boolean special; 199. {  200.  	char	line[COLNO]; 201. 	char	*endp; 202. 	dlb	*oracles; 203. 	int oracle_idx; 204. 	char xbuf[BUFSZ]; 205.  206.  	if(oracle_flg < 0 ||			/* couldn't open ORACLEFILE */  207.  	   (oracle_flg > 0 && oracle_cnt == 0))	/* oracles already exhausted */ 208. 		return; 209.  210.  	oracles = dlb_fopen(ORACLEFILE, "r"); 211.  212.  	if (oracles) { 213. 		winid tmpwin; 214. 		if (oracle_flg == 0) {	/* if this is the first outoracle */ 215. 			init_oracles(oracles); 216. 			oracle_flg = 1; 217. 			if (oracle_cnt == 0) return; 218. 		}  219.  		/* oracle_loc[0] is the special oracle;		*/ 220. 		/* oracle_loc[1..oracle_cnt-1] are normal ones	*/ 221. 		if (oracle_cnt <= 1 && !special) return;  /*(shouldn't happen)*/ 222. 		oracle_idx = special ? 0 : rnd((int) oracle_cnt - 1); 223. 		(void) dlb_fseek(oracles, oracle_loc[oracle_idx], SEEK_SET); 224. 		if (!special) oracle_loc[oracle_idx] = oracle_loc[--oracle_cnt]; 225.  226.  		tmpwin = create_nhwindow(NHW_TEXT); 227. 		putstr(tmpwin, 0, special ?  228.  		      "The Oracle scornfully takes all your money and says:" :  229.  		      "The Oracle meditates for a moment and then intones:"); 230. 		putstr(tmpwin, 0, ""); 231.  232.  		while(dlb_fgets(line, COLNO, oracles) && strcmp(line,"---\n")) { 233. 			if ((endp = index(line, '\n')) != 0) *endp = 0; 234. 			putstr(tmpwin, 0, xcrypt(line, xbuf)); 235. 		}  236.  		display_nhwindow(tmpwin, TRUE); 237. 		destroy_nhwindow(tmpwin); 238. 		(void) dlb_fclose(oracles); 239. 	} else { 240. 		pline("Can't open oracles file!"); 241. 		oracle_flg = -1;	/* don't try to open it again */ 242. 	}  243.  }  244.   245.  int 246. doconsult(oracl) 247. register struct monst *oracl; 248. {  249.  	int u_pay, minor_cost = 50, major_cost = 500 + 50 * u.ulevel; 250. 	int add_xpts; 251. 	char qbuf[QBUFSZ]; 252.  253.  	multi = 0; 254.  255.  	if (!oracl) { 256. 		pline("There is no one here to consult."); 257. 		return 0; 258. 	} else if (!oracl->mpeaceful) { 259. 		pline("%s is in no mood for consultations.", Monnam(oracl)); 260. 		return 0; 261. 	} else if (!u.ugold) { 262. 		You("have no money."); 263. 		return 0; 264. 	}  265.   266.  	Sprintf(qbuf,  267.  		"\"Wilt thou settle for a minor consultation?\" (%d zorkmids)",  268.  		minor_cost); 269. 	switch (ynq(qbuf)) { 270. 	    default: 271. 	    case 'q': 272. 		return 0; 273. 	    case 'y': 274. 		if (u.ugold < (long)minor_cost) { 275. 		    You("don't even have enough money for that!"); 276. 		    return 0; 277. 		}  278.  		u_pay = minor_cost; 279. 		break; 280. 	    case 'n': 281. 		if (u.ugold <= (long)minor_cost ||	/* don't even ask */  282.  		    (oracle_cnt == 1 || oracle_flg < 0)) return 0; 283. 		Sprintf(qbuf,  284.  			"\"Then dost thou desire a major one?\" (%d zorkmids)",  285.  			major_cost); 286. 		if (yn(qbuf) != 'y') return 0; 287. 		u_pay = (u.ugold < (long)major_cost ? (int)u.ugold  288.  						    : major_cost); 289. 		break; 290. 	}  291.  	u.ugold -= (long)u_pay; 292. 	oracl->mgold += (long)u_pay; 293. 	flags.botl = 1; 294. 	add_xpts = 0;	/* first oracle of each type gives experience points */ 295. 	if (u_pay == minor_cost) { 296. 		outrumor(1, FALSE); 297. 		if (!u.uevent.minor_oracle) 298. 		    add_xpts = u_pay / (u.uevent.major_oracle ? 25 : 10); 299. 		    /* 5 pts if very 1st, or 2 pts if major already done */ 300. 		u.uevent.minor_oracle = TRUE; 301. 	} else { 302. 		boolean cheapskate = u_pay < major_cost; 303. 		outoracle(cheapskate); 304. 		if (!cheapskate && !u.uevent.major_oracle) 305. 		    add_xpts = u_pay / (u.uevent.minor_oracle ? 25 : 10); 306. 		    /* ~100 pts if very 1st, ~40 pts if minor already done */ 307. 		u.uevent.major_oracle = TRUE; 308. 		exercise(A_WIS, !cheapskate); 309. 	}  310.  	if (add_xpts) { 311. 		more_experienced(add_xpts, u_pay/50); 312. 		newexplevel; 313. 	}  314.  	return 1; 315. }  316.   317.  /*rumors.c*/