Source:NetHack 3.1.0/rumors.c

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