Wikihack
Advertisement

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

Top of file[]

1.    /*	SCCS Id: @(#)rumors.c	3.4	1996/04/20	*/
2.    /* Copyright (c) Stichting Mathematisch Centrum, Amsterdam, 1985. */
3.    /* NetHack may be freely redistributed.  See license for details. */
4.    
The NetHack General Public License applies to screenshots, source code and other content from NetHack.
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.   

init_rumors[]

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.   

getrumor[]

61.   /* exclude_cookie is a hack used because we sometimes want to get rumors in a
62.    * context where messages such as "You swallowed the fortune!" that refer to
63.    * cookies should not appear.  This has no effect for true rumors since none
64.    * of them contain such references anyway.
65.    */
66.   char *
67.   getrumor(truth, rumor_buf, exclude_cookie)
68.   int truth; /* 1=true, -1=false, 0=either */
69.   char *rumor_buf;
70.   boolean exclude_cookie; 
71.   {
72.   	dlb	*rumors;
73.   	long tidbit, beginning;
74.   	char	*endp, line[BUFSZ], xbuf[BUFSZ];
75.   
76.   	rumor_buf[0] = '\0';
77.   	if (true_rumor_size < 0L)	/* we couldn't open RUMORFILE */
78.   		return rumor_buf;
79.   
80.   	rumors = dlb_fopen(RUMORFILE, "r");
81.   
82.   	if (rumors) {
83.   	    int count = 0;
84.   	    int adjtruth;
85.   
86.   	    do {
87.   		rumor_buf[0] = '\0';
88.   		if (true_rumor_size == 0L) {	/* if this is 1st outrumor() */
89.   		    init_rumors(rumors);
90.   		    if (true_rumor_size < 0L) {	/* init failed */
91.   			Sprintf(rumor_buf, "Error reading \"%.80s\".",
92.   				RUMORFILE);
93.   			return rumor_buf;
94.   		    }
95.   		}
96.   		/*
97.   		 *	input:      1    0   -1
98.   		 *	 rn2 \ +1  2=T  1=T  0=F
99.   		 *	 adj./ +0  1=T  0=F -1=F
100.  		 */
101.  		switch (adjtruth = truth + rn2(2)) {
102.  		  case  2:	/*(might let a bogus input arg sneak thru)*/
103.  		  case  1:  beginning = true_rumor_start;
104.  			    tidbit = Rand() % true_rumor_size;
105.  			break;
106.  		  case  0:	/* once here, 0 => false rather than "either"*/
107.  		  case -1:  beginning = false_rumor_start;
108.  			    tidbit = Rand() % false_rumor_size;
109.  			break;
110.  		  default:
111.  			    impossible("strange truth value for rumor");
112.  			return strcpy(rumor_buf, "Oops...");
113.  		}
114.  		(void) dlb_fseek(rumors, beginning + tidbit, SEEK_SET);
115.  		(void) dlb_fgets(line, sizeof line, rumors);
116.  		if (!dlb_fgets(line, sizeof line, rumors) ||
117.  		    (adjtruth > 0 && dlb_ftell(rumors) > true_rumor_end)) {
118.  			/* reached end of rumors -- go back to beginning */
119.  			(void) dlb_fseek(rumors, beginning, SEEK_SET);
120.  			(void) dlb_fgets(line, sizeof line, rumors);
121.  		}
122.  		if ((endp = index(line, '\n')) != 0) *endp = 0;
123.  		Strcat(rumor_buf, xcrypt(line, xbuf));
124.  	    } while(count++ < 50 && exclude_cookie && (strstri(rumor_buf, "fortune") || strstri(rumor_buf, "pity")));
125.  	    (void) dlb_fclose(rumors);
126.  	    if (count >= 50)
127.  		impossible("Can't find non-cookie rumor?");
128.  	    else
129.  		exercise(A_WIS, (adjtruth > 0));
130.  	} else {
131.  		pline("Can't open rumors file!");
132.  		true_rumor_size = -1;	/* don't try to open it again */
133.  	}
134.  	return rumor_buf;
135.  }
136.  

outrumor[]

137.  void
138.  outrumor(truth, mechanism)
139.  int truth; /* 1=true, -1=false, 0=either */
140.  int mechanism;
141.  {
142.  	static const char fortune_msg[] =
143.  		"This cookie has a scrap of paper inside.";
144.  	const char *line;
145.  	char buf[BUFSZ];
146.  	boolean reading = (mechanism == BY_COOKIE ||
147.  			   mechanism == BY_PAPER);
148.  
149.  	if (reading) {
150.  	    /* deal with various things that prevent reading */
151.  	    if (is_fainted() && mechanism == BY_COOKIE)
152.  	    	return;
153.  	    else if (Blind) {
154.  		if (mechanism == BY_COOKIE)
155.  			pline(fortune_msg);
156.  		pline("What a pity that you cannot read it!");
157.  	    	return;
158.  	    }
159.  	}
160.  	line = getrumor(truth, buf, reading ? FALSE : TRUE);
161.  	if (!*line)
162.  		line = "NetHack rumors file closed for renovation.";
163.  	switch (mechanism) {
164.  	    case BY_ORACLE:
165.  	 	/* Oracle delivers the rumor */
166.  		pline("True to her word, the Oracle %ssays: ",
167.  		  (!rn2(4) ? "offhandedly " : (!rn2(3) ? "casually " :
168.  		  (rn2(2) ? "nonchalantly " : ""))));
169.  		verbalize("%s", line);
170.  		exercise(A_WIS, TRUE);
171.  		return;
172.  	    case BY_COOKIE:
173.  		pline(fortune_msg);
174.  		/* FALLTHRU */
175.  	    case BY_PAPER:
176.  		pline("It reads:");
177.  		break;
178.  	}
179.  	pline("%s", line);
180.  }
181.  

init_oracles[]

182.  STATIC_OVL void
183.  init_oracles(fp)
184.  dlb *fp;
185.  {
186.  	register int i;
187.  	char line[BUFSZ];
188.  	int cnt = 0;
189.  
190.  	/* this assumes we're only called once */
191.  	(void) dlb_fgets(line, sizeof line, fp); /* skip "don't edit" comment*/
192.  	(void) dlb_fgets(line, sizeof line, fp);
193.  	if (sscanf(line, "%5d\n", &cnt) == 1 && cnt > 0) {
194.  	    oracle_cnt = (unsigned) cnt;
195.  	    oracle_loc = (long *) alloc((unsigned)cnt * sizeof (long));
196.  	    for (i = 0; i < cnt; i++) {
197.  		(void) dlb_fgets(line, sizeof line, fp);
198.  		(void) sscanf(line, "%5lx\n", &oracle_loc[i]);
199.  	    }
200.  	}
201.  	return;
202.  }
203.  

save_oracles[]

204.  void
205.  save_oracles(fd, mode)
206.  int fd, mode;
207.  {
208.  	if (perform_bwrite(mode)) {
209.  	    bwrite(fd, (genericptr_t) &oracle_cnt, sizeof oracle_cnt);
210.  	    if (oracle_cnt)
211.  		bwrite(fd, (genericptr_t)oracle_loc, oracle_cnt*sizeof (long));
212.  	}
213.  	if (release_data(mode)) {
214.  	    if (oracle_cnt) {
215.  		free((genericptr_t)oracle_loc);
216.  		oracle_loc = 0,  oracle_cnt = 0,  oracle_flg = 0;
217.  	    }
218.  	}
219.  }
220.  

restore_oracles[]

221.  void
222.  restore_oracles(fd)
223.  int fd;
224.  {
225.  	mread(fd, (genericptr_t) &oracle_cnt, sizeof oracle_cnt);
226.  	if (oracle_cnt) {
227.  	    oracle_loc = (long *) alloc(oracle_cnt * sizeof (long));
228.  	    mread(fd, (genericptr_t) oracle_loc, oracle_cnt * sizeof (long));
229.  	    oracle_flg = 1;	/* no need to call init_oracles() */
230.  	}
231.  }
232.  

outoracle[]

233.  void
234.  outoracle(special, delphi)
235.  boolean special;
236.  boolean delphi;
237.  {
238.  	char	line[COLNO];
239.  	char	*endp;
240.  	dlb	*oracles;
241.  	int oracle_idx;
242.  	char xbuf[BUFSZ];
243.  
244.  	if(oracle_flg < 0 ||			/* couldn't open ORACLEFILE */
245.  	   (oracle_flg > 0 && oracle_cnt == 0))	/* oracles already exhausted */
246.  		return;
247.  
248.  	oracles = dlb_fopen(ORACLEFILE, "r");
249.  
250.  	if (oracles) {
251.  		winid tmpwin;
252.  		if (oracle_flg == 0) {	/* if this is the first outoracle() */
253.  			init_oracles(oracles);
254.  			oracle_flg = 1;
255.  			if (oracle_cnt == 0) return;
256.  		}
257.  		/* oracle_loc[0] is the special oracle;		*/
258.  		/* oracle_loc[1..oracle_cnt-1] are normal ones	*/
259.  		if (oracle_cnt <= 1 && !special) return;  /*(shouldn't happen)*/
260.  		oracle_idx = special ? 0 : rnd((int) oracle_cnt - 1);
261.  		(void) dlb_fseek(oracles, oracle_loc[oracle_idx], SEEK_SET);
262.  		if (!special) oracle_loc[oracle_idx] = oracle_loc[--oracle_cnt];
263.  
264.  		tmpwin = create_nhwindow(NHW_TEXT);
265.  		if (delphi)
266.  		    putstr(tmpwin, 0, special ?
267.  		          "The Oracle scornfully takes all your money and says:" :
268.  		          "The Oracle meditates for a moment and then intones:");
269.  		else
270.  		    putstr(tmpwin, 0, "The message reads:");
271.  		putstr(tmpwin, 0, "");
272.  
273.  		while(dlb_fgets(line, COLNO, oracles) && strcmp(line,"---\n")) {
274.  			if ((endp = index(line, '\n')) != 0) *endp = 0;
275.  			putstr(tmpwin, 0, xcrypt(line, xbuf));
276.  		}
277.  		display_nhwindow(tmpwin, TRUE);
278.  		destroy_nhwindow(tmpwin);
279.  		(void) dlb_fclose(oracles);
280.  	} else {
281.  		pline("Can't open oracles file!");
282.  		oracle_flg = -1;	/* don't try to open it again */
283.  	}
284.  }
285.  

doconsult[]

This function is called when, and only when, #chatting to the Oracle.

286.  int
287.  doconsult(oracl)
288.  register struct monst *oracl;
289.  {
290.  #ifdef GOLDOBJ
291.          long umoney = money_cnt(invent);
292.  #endif
293.  	int u_pay, minor_cost = 50, major_cost = 500 + 50 * u.ulevel;
294.  	int add_xpts;
295.  	char qbuf[QBUFSZ];
296.  
297.  	multi = 0;
298.  
299.  	if (!oracl) {
300.  		There("is no one here to consult.");
301.  		return 0;
302.  	} else if (!oracl->mpeaceful) {
303.  		pline("%s is in no mood for consultations.", Monnam(oracl));
304.  		return 0;
305.  #ifndef GOLDOBJ
306.  	} else if (!u.ugold) {
307.  #else
308.  	} else if (!umoney) {
309.  #endif
310.  		You("have no money.");
311.  		return 0;
312.  	}
313.  
314.  	Sprintf(qbuf,
315.  		"\"Wilt thou settle for a minor consultation?\" (%d %s)",
316.  		minor_cost, currency((long)minor_cost));
317.  	switch (ynq(qbuf)) {
318.  	    default:
319.  	    case 'q':
320.  		return 0;
321.  	    case 'y':
322.  #ifndef GOLDOBJ
323.  		if (u.ugold < (long)minor_cost) {
324.  #else
325.  		if (umoney < (long)minor_cost) {
326.  #endif
327.  		    You("don't even have enough money for that!");
328.  		    return 0;
329.  		}
330.  		u_pay = minor_cost;
331.  		break;
332.  	    case 'n':
333.  #ifndef GOLDOBJ
334.  		if (u.ugold <= (long)minor_cost ||	/* don't even ask */
335.  #else
336.  		if (umoney <= (long)minor_cost ||	/* don't even ask */
337.  #endif
338.  		    (oracle_cnt == 1 || oracle_flg < 0)) return 0;
339.  		Sprintf(qbuf,
340.  			"\"Then dost thou desire a major one?\" (%d %s)",
341.  			major_cost, currency((long)major_cost));
342.  		if (yn(qbuf) != 'y') return 0;
343.  #ifndef GOLDOBJ
344.  		u_pay = (u.ugold < (long)major_cost ? (int)u.ugold
345.  						    : major_cost);
346.  #else
347.  		u_pay = (umoney < (long)major_cost ? (int)umoney
348.  						    : major_cost);
349.  #endif
350.  		break;
351.  	}
352.  #ifndef GOLDOBJ
353.  	u.ugold -= (long)u_pay;
354.  	oracl->mgold += (long)u_pay;
355.  #else
356.          money2mon(oracl, (long)u_pay);
357.  #endif
358.  	flags.botl = 1;
359.  	add_xpts = 0;	/* first oracle of each type gives experience points */
360.  	if (u_pay == minor_cost) {
361.  		outrumor(1, BY_ORACLE);
362.  		if (!u.uevent.minor_oracle)
363.  		    add_xpts = u_pay / (u.uevent.major_oracle ? 25 : 10);
364.  		    /* 5 pts if very 1st, or 2 pts if major already done */
365.  		u.uevent.minor_oracle = TRUE;
366.  	} else {
367.  		boolean cheapskate = u_pay < major_cost;
368.  		outoracle(cheapskate, TRUE);
369.  		if (!cheapskate && !u.uevent.major_oracle)
370.  		    add_xpts = u_pay / (u.uevent.minor_oracle ? 25 : 10);
371.  		    /* ~100 pts if very 1st, ~40 pts if minor already done */

This comment is true only for a level 10 character, hence the "~".

372.  		u.uevent.major_oracle = TRUE;
373.  		exercise(A_WIS, !cheapskate);
374.  	}
375.  	if (add_xpts) {
376.  		more_experienced(add_xpts, u_pay/50);

The more_experienced function controls the score increase as well as the experience point gain.

377.  		newexplevel();
378.  	}
379.  	return 1;
380.  }
381.  
382.  /*rumors.c*/
Advertisement