OSDN Git Service

fix comment-out
[jnethack/source.git] / src / rumors.c
1 /* NetHack 3.6  rumors.c        $NHDT-Date: 1446713640 2015/11/05 08:54:00 $  $NHDT-Branch: master $:$NHDT-Revision: 1.27 $ */
2 /* Copyright (c) Stichting Mathematisch Centrum, Amsterdam, 1985. */
3 /* NetHack may be freely redistributed.  See license for details. */
4
5 /* JNetHack Copyright */
6 /* (c) Issei Numata, Naoki Hamada, Shigehiro Miyashita, 1994-2000  */
7 /* For 3.4-, Copyright (c) SHIRAKATA Kentaro, 2002-2016            */
8 /* JNetHack may be freely redistributed.  See license for details. */
9
10 #include "hack.h"
11 #include "lev.h"
12 #include "dlb.h"
13
14 /*      [note: this comment is fairly old, but still accurate for 3.1]
15  * Rumors have been entirely rewritten to speed up the access.  This is
16  * essential when working from floppies.  Using fseek() the way that's done
17  * here means rumors following longer rumors are output more often than those
18  * following shorter rumors.  Also, you may see the same rumor more than once
19  * in a particular game (although the odds are highly against it), but
20  * this also happens with real fortune cookies.  -dgk
21  */
22
23 /*      3.6
24  * The rumors file consists of a "do not edit" line, then a line containing
25  * three sets of three counts (first two in decimal, third in hexadecimal).
26  * The first set has the number of true rumors, the count in bytes for all
27  * true rumors, and the file offset to the first one.  The second set has
28  * the same group of numbers for the false rumors.  The third set has 0 for
29  * count, 0 for size, and the file offset for end-of-file.  The offset of
30  * the first true rumor plus the size of the true rumors matches the offset
31  * of the first false rumor.  Likewise, the offset of the first false rumor
32  * plus the size of the false rumors matches the offset for end-of-file.
33  */
34
35 /*      3.1     [now obsolete for rumors but still accurate for oracles]
36  * The rumors file consists of a "do not edit" line, a hexadecimal number
37  * giving the number of bytes of useful/true rumors, followed by those
38  * true rumors (one per line), followed by the useless/false/misleading/cute
39  * rumors (also one per line).  Number of bytes of untrue rumors is derived
40  * via fseek(EOF)+ftell().
41  *
42  * The oracles file consists of a "do not edit" comment, a decimal count N
43  * and set of N+1 hexadecimal fseek offsets, followed by N multiple-line
44  * records, separated by "---" lines.  The first oracle is a special case,
45  * and placed there by 'makedefs'.
46  */
47
48 STATIC_DCL void FDECL(init_rumors, (dlb *));
49 STATIC_DCL void FDECL(init_oracles, (dlb *));
50
51 /* rumor size variables are signed so that value -1 can be used as a flag */
52 static long true_rumor_size = 0L, false_rumor_size;
53 /* rumor start offsets are unsigned because they're handled via %lx format */
54 static unsigned long true_rumor_start, false_rumor_start;
55 /* rumor end offsets are signed because they're compared with [dlb_]ftell() */
56 static long true_rumor_end, false_rumor_end;
57 /* oracles are handled differently from rumors... */
58 static int oracle_flg = 0; /* -1=>don't use, 0=>need init, 1=>init done */
59 static unsigned oracle_cnt = 0;
60 static unsigned long *oracle_loc = 0;
61
62 STATIC_OVL void
63 init_rumors(fp)
64 dlb *fp;
65 {
66     static const char rumors_header[] = "%d,%ld,%lx;%d,%ld,%lx;0,0,%lx\n";
67     int true_count, false_count; /* in file but not used here */
68     unsigned long eof_offset;
69     char line[BUFSZ];
70
71     (void) dlb_fgets(line, sizeof line, fp); /* skip "don't edit" comment */
72     (void) dlb_fgets(line, sizeof line, fp);
73     if (sscanf(line, rumors_header, &true_count, &true_rumor_size,
74                &true_rumor_start, &false_count, &false_rumor_size,
75                &false_rumor_start, &eof_offset) == 7
76         && true_rumor_size > 0L
77         && false_rumor_size > 0L) {
78         true_rumor_end = (long) true_rumor_start + true_rumor_size;
79         /* assert( true_rumor_end == false_rumor_start ); */
80         false_rumor_end = (long) false_rumor_start + false_rumor_size;
81         /* assert( false_rumor_end == eof_offset ); */
82     } else {
83         true_rumor_size = -1L; /* init failed */
84         (void) dlb_fclose(fp);
85     }
86 }
87
88 /* exclude_cookie is a hack used because we sometimes want to get rumors in a
89  * context where messages such as "You swallowed the fortune!" that refer to
90  * cookies should not appear.  This has no effect for true rumors since none
91  * of them contain such references anyway.
92  */
93 char *
94 getrumor(truth, rumor_buf, exclude_cookie)
95 int truth; /* 1=true, -1=false, 0=either */
96 char *rumor_buf;
97 boolean exclude_cookie;
98 {
99     dlb *rumors;
100     long tidbit, beginning;
101     char *endp, line[BUFSZ], xbuf[BUFSZ];
102
103     rumor_buf[0] = '\0';
104     if (true_rumor_size < 0L) /* we couldn't open RUMORFILE */
105         return rumor_buf;
106
107     rumors = dlb_fopen(RUMORFILE, "r");
108
109     if (rumors) {
110         int count = 0;
111         int adjtruth;
112
113         do {
114             rumor_buf[0] = '\0';
115             if (true_rumor_size == 0L) { /* if this is 1st outrumor() */
116                 init_rumors(rumors);
117                 if (true_rumor_size < 0L) { /* init failed */
118                     Sprintf(rumor_buf, "Error reading \"%.80s\".", RUMORFILE);
119                     return rumor_buf;
120                 }
121             }
122             /*
123              *  input:      1    0   -1
124              *   rn2 \ +1  2=T  1=T  0=F
125              *   adj./ +0  1=T  0=F -1=F
126              */
127             switch (adjtruth = truth + rn2(2)) {
128             case 2: /*(might let a bogus input arg sneak thru)*/
129             case 1:
130                 beginning = (long) true_rumor_start;
131                 tidbit = Rand() % true_rumor_size;
132                 break;
133             case 0: /* once here, 0 => false rather than "either"*/
134             case -1:
135                 beginning = (long) false_rumor_start;
136                 tidbit = Rand() % false_rumor_size;
137                 break;
138             default:
139                 impossible("strange truth value for rumor");
140                 return strcpy(rumor_buf, "Oops...");
141             }
142             (void) dlb_fseek(rumors, beginning + tidbit, SEEK_SET);
143             (void) dlb_fgets(line, sizeof line, rumors);
144             if (!dlb_fgets(line, sizeof line, rumors)
145                 || (adjtruth > 0 && dlb_ftell(rumors) > true_rumor_end)) {
146                 /* reached end of rumors -- go back to beginning */
147                 (void) dlb_fseek(rumors, beginning, SEEK_SET);
148                 (void) dlb_fgets(line, sizeof line, rumors);
149             }
150             if ((endp = index(line, '\n')) != 0)
151                 *endp = 0;
152             Strcat(rumor_buf, xcrypt(line, xbuf));
153         } while (
154             count++ < 50 && exclude_cookie
155 #if 0 /*JP*/
156             && (strstri(rumor_buf, "fortune") || strstri(rumor_buf, "pity")));
157 #else
158             && (strstri(rumor_buf, "\90è") || strstri(rumor_buf, "\82È\82ñ\82Ä\82±\82Æ\82¾")));
159 #endif
160         (void) dlb_fclose(rumors);
161         if (count >= 50)
162             impossible("Can't find non-cookie rumor?");
163         else if (!in_mklev) /* avoid exercizing wisdom for graffiti */
164             exercise(A_WIS, (adjtruth > 0));
165     } else {
166 /*JP
167         pline("Can't open rumors file!");
168 */
169         pline("rumors\83t\83@\83C\83\8b\82ª\8aJ\82¯\82È\82¢\81I");
170         true_rumor_size = -1; /* don't try to open it again */
171     }
172 /* this is safe either way, so do it always since we can't get the definition
173  * out of makedefs.c
174  */
175 #define PAD_RUMORS_TO
176 #ifdef PAD_RUMORS_TO
177     /* remove padding */
178     {
179         char *x = eos(rumor_buf) - 1;
180
181         while (x > rumor_buf && *x == '_')
182             x--;
183         *++x = '\n';
184         *x = '\0';
185     }
186 #endif
187     return rumor_buf;
188 }
189
190 /*
191  * test that the true/false rumor boundaries are valid.
192  */
193 void
194 rumor_check()
195 {
196     dlb *rumors;
197     winid tmpwin;
198     char *endp, line[BUFSZ], xbuf[BUFSZ], rumor_buf[BUFSZ];
199
200     if (true_rumor_size < 0L) { /* we couldn't open RUMORFILE */
201     no_rumors:
202         pline("rumors not accessible.");
203         return;
204     }
205
206     rumors = dlb_fopen(RUMORFILE, "r");
207
208     if (rumors) {
209         long ftell_rumor_start = 0L;
210
211         rumor_buf[0] = '\0';
212         if (true_rumor_size == 0L) { /* if this is 1st outrumor() */
213             init_rumors(rumors);
214             if (true_rumor_size < 0L)
215                 goto no_rumors; /* init failed */
216         }
217         tmpwin = create_nhwindow(NHW_TEXT);
218
219         /*
220          * reveal the values.
221          */
222
223         Sprintf(
224             rumor_buf,
225             "T start=%06ld (%06lx), end=%06ld (%06lx), size=%06ld (%06lx)",
226             (long) true_rumor_start, true_rumor_start, true_rumor_end,
227             (unsigned long) true_rumor_end, true_rumor_size,
228             (unsigned long) true_rumor_size);
229         putstr(tmpwin, 0, rumor_buf);
230
231         Sprintf(
232             rumor_buf,
233             "F start=%06ld (%06lx), end=%06ld (%06lx), size=%06ld (%06lx)",
234             (long) false_rumor_start, false_rumor_start, false_rumor_end,
235             (unsigned long) false_rumor_end, false_rumor_size,
236             (unsigned long) false_rumor_size);
237         putstr(tmpwin, 0, rumor_buf);
238
239         /*
240          * check the first rumor (start of true rumors) by
241          * skipping the first two lines.
242          *
243          * Then seek to the start of the false rumors (based on
244          * the value read in rumors, and display it.
245          */
246         rumor_buf[0] = '\0';
247         (void) dlb_fseek(rumors, (long) true_rumor_start, SEEK_SET);
248         ftell_rumor_start = dlb_ftell(rumors);
249         (void) dlb_fgets(line, sizeof line, rumors);
250         if ((endp = index(line, '\n')) != 0)
251             *endp = 0;
252         Sprintf(rumor_buf, "T %06ld %s", ftell_rumor_start,
253                 xcrypt(line, xbuf));
254         putstr(tmpwin, 0, rumor_buf);
255         /* find last true rumor */
256         while (dlb_fgets(line, sizeof line, rumors)
257                && dlb_ftell(rumors) < true_rumor_end)
258             continue;
259         if ((endp = index(line, '\n')) != 0)
260             *endp = 0;
261         Sprintf(rumor_buf, "  %6s %s", "", xcrypt(line, xbuf));
262         putstr(tmpwin, 0, rumor_buf);
263
264         rumor_buf[0] = '\0';
265         (void) dlb_fseek(rumors, (long) false_rumor_start, SEEK_SET);
266         ftell_rumor_start = dlb_ftell(rumors);
267         (void) dlb_fgets(line, sizeof line, rumors);
268         if ((endp = index(line, '\n')) != 0)
269             *endp = 0;
270         Sprintf(rumor_buf, "F %06ld %s", ftell_rumor_start,
271                 xcrypt(line, xbuf));
272         putstr(tmpwin, 0, rumor_buf);
273         /* find last false rumor */
274         while (dlb_fgets(line, sizeof line, rumors)
275                && dlb_ftell(rumors) < false_rumor_end)
276             continue;
277         if ((endp = index(line, '\n')) != 0)
278             *endp = 0;
279         Sprintf(rumor_buf, "  %6s %s", "", xcrypt(line, xbuf));
280         putstr(tmpwin, 0, rumor_buf);
281
282         (void) dlb_fclose(rumors);
283         display_nhwindow(tmpwin, TRUE);
284         destroy_nhwindow(tmpwin);
285     } else {
286         impossible("Can't open rumors file!");
287         true_rumor_size = -1; /* don't try to open it again */
288     }
289 }
290
291 /* Gets a random line of text from file 'fname', and returns it. */
292 char *
293 get_rnd_text(fname, buf)
294 const char *fname;
295 char *buf;
296 {
297     dlb *fh;
298
299     buf[0] = '\0';
300
301     fh = dlb_fopen(fname, "r");
302
303     if (fh) {
304         /* TODO: cache sizetxt, starttxt, endtxt. maybe cache file contents?
305          */
306         long sizetxt = 0, starttxt = 0, endtxt = 0, tidbit = 0;
307         char *endp, line[BUFSZ], xbuf[BUFSZ];
308         (void) dlb_fgets(line, sizeof line,
309                          fh); /* skip "don't edit" comment */
310
311         (void) dlb_fseek(fh, 0L, SEEK_CUR);
312         starttxt = dlb_ftell(fh);
313         (void) dlb_fseek(fh, 0L, SEEK_END);
314         endtxt = dlb_ftell(fh);
315         sizetxt = endtxt - starttxt;
316         tidbit = Rand() % sizetxt;
317
318         (void) dlb_fseek(fh, starttxt + tidbit, SEEK_SET);
319         (void) dlb_fgets(line, sizeof line, fh);
320         if (!dlb_fgets(line, sizeof line, fh)) {
321             (void) dlb_fseek(fh, starttxt, SEEK_SET);
322             (void) dlb_fgets(line, sizeof line, fh);
323         }
324         if ((endp = index(line, '\n')) != 0)
325             *endp = 0;
326         Strcat(buf, xcrypt(line, xbuf));
327         (void) dlb_fclose(fh);
328     } else
329         impossible("Can't open file %s!", fname);
330     return buf;
331 }
332
333 void
334 outrumor(truth, mechanism)
335 int truth; /* 1=true, -1=false, 0=either */
336 int mechanism;
337 {
338     static const char fortune_msg[] =
339 /*JP
340         "This cookie has a scrap of paper inside.";
341 */
342         "\82±\82Ì\83N\83b\83L\81[\82É\82Í\8e\86\90Ø\82ª\93ü\82Á\82Ä\82¢\82é\81D";
343     const char *line;
344     char buf[BUFSZ];
345     boolean reading = (mechanism == BY_COOKIE || mechanism == BY_PAPER);
346
347     if (reading) {
348         /* deal with various things that prevent reading */
349         if (is_fainted() && mechanism == BY_COOKIE)
350             return;
351         else if (Blind) {
352             if (mechanism == BY_COOKIE)
353                 pline(fortune_msg);
354 /*JP
355             pline("What a pity that you cannot read it!");
356 */
357             pline("\82»\82ê\82ð\93Ç\82ß\82È\82¢\82È\82ñ\82Ä\8bC\82Ì\93Å\82È\81I");
358             return;
359         }
360     }
361     line = getrumor(truth, buf, reading ? FALSE : TRUE);
362     if (!*line)
363 /*JP
364         line = "NetHack rumors file closed for renovation.";
365 */
366         line = "\89\\82Ì\90^\91\8a\82Í\8dü\90V\82Ì\82½\82ß\8bx\8a§\82µ\82Ä\82¢\82é\81D";
367     switch (mechanism) {
368     case BY_ORACLE:
369         /* Oracle delivers the rumor */
370 #if 0 /*JP*/
371         pline("True to her word, the Oracle %ssays: ",
372               (!rn2(4) ? "offhandedly "
373                        : (!rn2(3) ? "casually "
374                                   : (rn2(2) ? "nonchalantly " : ""))));
375 #else
376         pline("\96ñ\91©\82Ç\82¨\82è\82É\81C\8c«\8eÒ\82Í%s\8fq\82×\82½:",
377               (!rn2(4) ? "\96³\91¢\8dì\82É"
378                        : (!rn2(3) ? "\89½\8bC\82È\82­"
379                                   : (rn2(2) ? "\96³\93Ú\92\85\82É" : ""))));
380 #endif
381         verbalize1(line);
382         /* [WIS exercized by getrumor()] */
383         return;
384     case BY_COOKIE:
385         pline(fortune_msg);
386     /* FALLTHRU */
387     case BY_PAPER:
388 /*JP
389         pline("It reads:");
390 */
391         pline("\82»\82ê\82ð\93Ç\82ñ\82¾:");
392         break;
393     }
394     pline1(line);
395 }
396
397 STATIC_OVL void
398 init_oracles(fp)
399 dlb *fp;
400 {
401     register int i;
402     char line[BUFSZ];
403     int cnt = 0;
404
405     /* this assumes we're only called once */
406     (void) dlb_fgets(line, sizeof line, fp); /* skip "don't edit" comment*/
407     (void) dlb_fgets(line, sizeof line, fp);
408     if (sscanf(line, "%5d\n", &cnt) == 1 && cnt > 0) {
409         oracle_cnt = (unsigned) cnt;
410         oracle_loc = (unsigned long *) alloc((unsigned) cnt * sizeof(long));
411         for (i = 0; i < cnt; i++) {
412             (void) dlb_fgets(line, sizeof line, fp);
413             (void) sscanf(line, "%5lx\n", &oracle_loc[i]);
414         }
415     }
416     return;
417 }
418
419 void
420 save_oracles(fd, mode)
421 int fd, mode;
422 {
423     if (perform_bwrite(mode)) {
424         bwrite(fd, (genericptr_t) &oracle_cnt, sizeof oracle_cnt);
425         if (oracle_cnt)
426             bwrite(fd, (genericptr_t) oracle_loc, oracle_cnt * sizeof(long));
427     }
428     if (release_data(mode)) {
429         if (oracle_cnt) {
430             free((genericptr_t) oracle_loc);
431             oracle_loc = 0, oracle_cnt = 0, oracle_flg = 0;
432         }
433     }
434 }
435
436 void
437 restore_oracles(fd)
438 int fd;
439 {
440     mread(fd, (genericptr_t) &oracle_cnt, sizeof oracle_cnt);
441     if (oracle_cnt) {
442         oracle_loc = (unsigned long *) alloc(oracle_cnt * sizeof(long));
443         mread(fd, (genericptr_t) oracle_loc, oracle_cnt * sizeof(long));
444         oracle_flg = 1; /* no need to call init_oracles() */
445     }
446 }
447
448 void
449 outoracle(special, delphi)
450 boolean special;
451 boolean delphi;
452 {
453     char line[COLNO];
454     char *endp;
455     dlb *oracles;
456     int oracle_idx;
457     char xbuf[BUFSZ];
458
459     /* early return if we couldn't open ORACLEFILE on previous attempt,
460        or if all the oracularities are already exhausted */
461     if (oracle_flg < 0 || (oracle_flg > 0 && oracle_cnt == 0))
462         return;
463
464     oracles = dlb_fopen(ORACLEFILE, "r");
465
466     if (oracles) {
467         winid tmpwin;
468         if (oracle_flg == 0) { /* if this is the first outoracle() */
469             init_oracles(oracles);
470             oracle_flg = 1;
471             if (oracle_cnt == 0)
472                 return;
473         }
474         /* oracle_loc[0] is the special oracle;
475            oracle_loc[1..oracle_cnt-1] are normal ones */
476         if (oracle_cnt <= 1 && !special)
477             return; /*(shouldn't happen)*/
478         oracle_idx = special ? 0 : rnd((int) oracle_cnt - 1);
479         (void) dlb_fseek(oracles, (long) oracle_loc[oracle_idx], SEEK_SET);
480         if (!special) /* move offset of very last one into this slot */
481             oracle_loc[oracle_idx] = oracle_loc[--oracle_cnt];
482
483         tmpwin = create_nhwindow(NHW_TEXT);
484         if (delphi)
485             putstr(tmpwin, 0,
486                    special
487 /*JP
488                      ? "The Oracle scornfully takes all your money and says:"
489 */
490                      ? "\8c«\8eÒ\82Í\8cy\95Ì\82µ\82½\82æ\82¤\82É\82 \82È\82½\82Ì\91S\82Ä\82Ì\82¨\8bà\82ð\8eó\82¯\82Æ\82è\81C\8fq\82×\82½\81F"
491 /*JP
492                      : "The Oracle meditates for a moment and then intones:");
493 */
494                      : "\8c«\8eÒ\82Í\82µ\82Î\82ç\82­\96»\91z\82µ\81C\89Ì\82¤\82æ\82¤\82É\98b\82µ\82½\81F");
495         else
496 /*JP
497             putstr(tmpwin, 0, "The message reads:");
498 */
499             putstr(tmpwin, 0, "\83\81\83b\83Z\81[\83W:");
500         putstr(tmpwin, 0, "");
501
502         while (dlb_fgets(line, COLNO, oracles) && strcmp(line, "---\n")) {
503             if ((endp = index(line, '\n')) != 0)
504                 *endp = 0;
505             putstr(tmpwin, 0, xcrypt(line, xbuf));
506         }
507         display_nhwindow(tmpwin, TRUE);
508         destroy_nhwindow(tmpwin);
509         (void) dlb_fclose(oracles);
510     } else {
511 /*JP
512         pline("Can't open oracles file!");
513 */
514         pline("oracles\83t\83@\83C\83\8b\82ð\8aJ\82¯\82È\82¢\81I");
515         oracle_flg = -1; /* don't try to open it again */
516     }
517 }
518
519 int
520 doconsult(oracl)
521 struct monst *oracl;
522 {
523     long umoney;
524     int u_pay, minor_cost = 50, major_cost = 500 + 50 * u.ulevel;
525     int add_xpts;
526     char qbuf[QBUFSZ];
527
528     multi = 0;
529     umoney = money_cnt(invent);
530
531     if (!oracl) {
532 /*JP
533         There("is no one here to consult.");
534 */
535         pline("\82±\82±\82É\82Í\90_\91õ\82ð\8fq\82×\82é\90l\82Í\82¢\82È\82¢\81D");
536         return 0;
537     } else if (!oracl->mpeaceful) {
538 /*JP
539         pline("%s is in no mood for consultations.", Monnam(oracl));
540 */
541         pline("\8c«\8eÒ\82Í\90_\91õ\82ð\8d\90\82°\82Ä\82­\82ê\82é\95µ\88Í\8bC\82Å\82Í\82È\82¢\81D");
542         return 0;
543     } else if (!umoney) {
544 /*JP
545         You("have no money.");
546 */
547         You("\82¨\8bà\82ª\82È\82¢\81D");
548         return 0;
549     }
550
551 /*JP
552     Sprintf(qbuf, "\"Wilt thou settle for a minor consultation?\" (%d %s)",
553 */
554     Sprintf(qbuf, "\81u\93ð\81C\92á\88Ê\82Ì\90_\91õ\82ð\8eó\82¯\82é\82©\81H\81v(%d%s)",
555             minor_cost, currency((long) minor_cost));
556     switch (ynq(qbuf)) {
557     default:
558     case 'q':
559         return 0;
560     case 'y':
561         if (umoney < (long) minor_cost) {
562 /*JP
563             You("don't even have enough money for that!");
564 */
565             You("\82±\82ê\82É\95¥\82¦\82é\82¾\82¯\82Ì\82¨\8bà\82·\82ç\8e\9d\82Á\82Ä\82¢\82È\82¢\81I");
566             return 0;
567         }
568         u_pay = minor_cost;
569         break;
570     case 'n':
571         if (umoney <= (long) minor_cost /* don't even ask */
572             || (oracle_cnt == 1 || oracle_flg < 0))
573             return 0;
574 /*JP
575         Sprintf(qbuf, "\"Then dost thou desire a major one?\" (%d %s)",
576 */
577         Sprintf(qbuf, "\81u\82È\82ç\82Î\93ð\81C\8d\82\88Ê\82Ì\90_\91õ\82ð\8eó\82¯\82é\82©\81H\81v(%d%s)",
578                 major_cost, currency((long) major_cost));
579         if (yn(qbuf) != 'y')
580             return 0;
581         u_pay = (umoney < (long) major_cost) ? (int) umoney : major_cost;
582         break;
583     }
584     money2mon(oracl, (long) u_pay);
585     context.botl = 1;
586     add_xpts = 0; /* first oracle of each type gives experience points */
587     if (u_pay == minor_cost) {
588         outrumor(1, BY_ORACLE);
589         if (!u.uevent.minor_oracle)
590             add_xpts = u_pay / (u.uevent.major_oracle ? 25 : 10);
591         /* 5 pts if very 1st, or 2 pts if major already done */
592         u.uevent.minor_oracle = TRUE;
593     } else {
594         boolean cheapskate = u_pay < major_cost;
595
596         outoracle(cheapskate, TRUE);
597         if (!cheapskate && !u.uevent.major_oracle)
598             add_xpts = u_pay / (u.uevent.minor_oracle ? 25 : 10);
599         /* ~100 pts if very 1st, ~40 pts if minor already done */
600         u.uevent.major_oracle = TRUE;
601         exercise(A_WIS, !cheapskate);
602     }
603     if (add_xpts) {
604         more_experienced(add_xpts, u_pay / 50);
605         newexplevel();
606     }
607     return 1;
608 }
609
610 /*rumors.c*/