]> granicus.if.org Git - nethack/commitdiff
more thorough rumor processing (trunk only)
authornethack.rankin <nethack.rankin>
Sat, 6 May 2006 04:55:57 +0000 (04:55 +0000)
committernethack.rankin <nethack.rankin>
Sat, 6 May 2006 04:55:57 +0000 (04:55 +0000)
     To fix the gibberish rumor observed by at least a couple of players on
Windows (where if rumors.tru had <cr><lf> line ends and DLB was defined,
makedefs built a file that caused nethack to end up in the wrong place when
it reached EOF and tried to jump back to the first false rumor), change
the way that makedefs builds the rumors file.  It now will collect more
information about the true and false rumors.  Instead of one hex value on
the second line, there are nine values (three groups of three).

1,2,3;4,5,6;7,8,9

1 = number of true rumors; not previously collected and not currently used
2 = size in bytes for all true rumors (in decimal, as is #1)
3 = offset to first true rumor (in hexadecimal; not previously collected)
4,5,6 = same as 1,2,3 but for the false rumors section
7,8 = always 0 (imaginary third section has no entries, no size)
9 = offset to end-of-file (could be used for sanity checks; currently isn't)

Adding #2 with #3 yields #6; adding #5 with #6 yields #9.  The old format's
lone entry was the same as the new format's #6.  #2, #3, and #5 are values
which nethack was previously calculating on the fly after opening the file.

     This also extends rumor_check() a little bit (displays the last rumor
for both sections in addition to the first), but I think it can probably
now be demoted to ``#if 0'' and removed from the extended commands list.

src/rumors.c
util/makedefs.c

index 6e78a90c8b5c7e6c37f462353bc2b1a04f5727b5..0bca828da139ba2de0aeb326a028c82dcc832025 100644 (file)
@@ -1,4 +1,4 @@
-/*     SCCS Id: @(#)rumors.c   3.5     1996/04/20      */
+/*     SCCS Id: @(#)rumors.c   3.5     2006/05/05      */
 /* Copyright (c) Stichting Mathematisch Centrum, Amsterdam, 1985. */
 /* NetHack may be freely redistributed.  See license for details. */
 
  * this also happens with real fortune cookies.  -dgk
  */
 
-/*     3.1
+/*     3.5
+ * The rumors file consists of a "do not edit" line, then a line containing
+ * three sets of three counts (first two in decimal, third in hexadecimal).
+ * The first set has the number of true rumors, the count in bytes for all
+ * true rumors, and the file offset to the first one.  The second set has
+ * the same group of numbers for the false rumors.  The third set has 0 for
+ * count, 0 for size, and the file offset for end-of-file.  The offset of
+ * the first true rumor plus the size of the true rumors matches the offset
+ * of the first false rumor.  Likewise, the offset of the first false rumor
+ * plus the size of the false rumors matches the offset for end-of-file.
+ */
+
+/*     3.1     [now obsolete for rumors but still accurate for oracles]
  * The rumors file consists of a "do not edit" line, a hexadecimal number
  * giving the number of bytes of useful/true rumors, followed by those
  * true rumors (one per line), followed by the useless/false/misleading/cute
@@ -41,21 +53,26 @@ STATIC_OVL void
 init_rumors(fp)
 dlb *fp;
 {
+       static const char rumors_header[] = "%d,%ld,%lx;%d,%ld,%lx;0,0,%lx\n";
+       int true_count, false_count;    /* in file but not used here */
+       long eof_offset;
        char line[BUFSZ];
 
        (void) dlb_fgets(line, sizeof line, fp); /* skip "don't edit" comment */
        (void) dlb_fgets(line, sizeof line, fp);
-       if (sscanf(line, "%6lx\n", &true_rumor_size) == 1 &&
-           true_rumor_size > 0L) {
-           (void) dlb_fseek(fp, 0L, SEEK_CUR);
-           true_rumor_start  = dlb_ftell(fp);
-           true_rumor_end    = true_rumor_start + true_rumor_size;
-           (void) dlb_fseek(fp, 0L, SEEK_END);
-           false_rumor_end   = dlb_ftell(fp);
-           false_rumor_start = true_rumor_end; /* ok, so it's redundant... */
-           false_rumor_size  = false_rumor_end - false_rumor_start;
-       } else
+       if (sscanf(line, rumors_header,
+                  &true_count, &true_rumor_size, &true_rumor_start,
+                  &false_count, &false_rumor_size, &false_rumor_start,
+                  &eof_offset) == 7 &&
+           true_rumor_size > 0L && false_rumor_size > 0L) {
+           true_rumor_end  = true_rumor_start + true_rumor_size;
+        /* assert( true_rumor_end == false_rumor_start ); */
+           false_rumor_end = false_rumor_start + false_rumor_size;
+        /* assert( false_rumor_end == eof_offset ); */
+       } else {
            true_rumor_size = -1L;      /* init failed */
+           (void) dlb_fclose(fp);
+       }
 }
 
 /* exclude_cookie is a hack used because we sometimes want to get rumors in a
@@ -145,8 +162,11 @@ rumor_check()
        winid tmpwin;
        char *endp, line[BUFSZ], xbuf[BUFSZ], rumor_buf[BUFSZ];
 
-       if (true_rumor_size < 0L)       /* we couldn't open RUMORFILE */
+       if (true_rumor_size < 0L) {     /* we couldn't open RUMORFILE */
+ no_rumors:
+               pline("rumors not accessible.");
                return;
+       }
 
        rumors = dlb_fopen(RUMORFILE, "r");
 
@@ -155,8 +175,7 @@ rumor_check()
                rumor_buf[0] = '\0';
                if (true_rumor_size == 0L) {    /* if this is 1st outrumor() */
                    init_rumors(rumors);
-                   if (true_rumor_size < 0L)   /* init failed */
-                       return;
+                   if (true_rumor_size < 0L) goto no_rumors; /* init failed */
                }
                tmpwin = create_nhwindow(NHW_TEXT);
 
@@ -193,6 +212,13 @@ rumor_check()
                Sprintf(rumor_buf, "T %06ld %s", ftell_rumor_start,
                        xcrypt(line, xbuf));
                putstr(tmpwin, 0, rumor_buf);
+               /* find last true rumor */
+               while (dlb_fgets(line, sizeof line, rumors) &&
+                       dlb_ftell(rumors) < true_rumor_end)
+                   continue;
+               if ((endp = index(line, '\n')) != 0) *endp = 0;
+               Sprintf(rumor_buf, "  %6s %s", "", xcrypt(line, xbuf));
+               putstr(tmpwin, 0, rumor_buf);
 
                rumor_buf[0] = '\0';
                (void) dlb_fseek(rumors, false_rumor_start, SEEK_SET);
@@ -202,6 +228,13 @@ rumor_check()
                Sprintf(rumor_buf, "F %06ld %s", ftell_rumor_start,
                        xcrypt(line, xbuf));
                putstr(tmpwin, 0, rumor_buf);
+               /* find last false rumor */
+               while (dlb_fgets(line, sizeof line, rumors) &&
+                       dlb_ftell(rumors) < false_rumor_end)
+                   continue;
+               if ((endp = index(line, '\n')) != 0) *endp = 0;
+               Sprintf(rumor_buf, "  %6s %s", "", xcrypt(line, xbuf));
+               putstr(tmpwin, 0, rumor_buf);
 
                (void) dlb_fclose(rumors);
                display_nhwindow(tmpwin, TRUE);
index c3b0ea451c4b0d7d7372a26ea3ac0b160bb3321a..c1d131e8affb914af8731d4406febf6201b6cd28 100644 (file)
@@ -1,4 +1,4 @@
-/*     SCCS Id: @(#)makedefs.c 3.5     2005/01/04      */
+/*     SCCS Id: @(#)makedefs.c 3.5     2006/05/05      */
 /* Copyright (c) Stichting Mathematisch Centrum, Amsterdam, 1985. */
 /* Copyright (c) M. Stephenson, 1990, 1991.                      */
 /* Copyright (c) Dean Luick, 1990.                               */
@@ -347,84 +347,110 @@ const char *str;
 void
 do_rumors()
 {
-       char    infile[60];
-       long    true_rumor_size;
+       static const char rumors_header[] =
+                       "%s%04d,%06ld,%06lx;%04d,%06ld,%06lx;0,0,%06lx\n";
+       char    infile[60], tempfile[60];
+       int     true_rumor_count, false_rumor_count;
+       long    true_rumor_size, false_rumor_size,
+               true_rumor_offset, false_rumor_offset, eof_offset;
 
+       Sprintf(tempfile, DATA_TEMPLATE, "rumors.tmp");
        filename[0]='\0';
 #ifdef FILE_PREFIX
-       Strcat(filename,file_prefix);
+       Strcat(filename, file_prefix);
 #endif
        Sprintf(eos(filename), DATA_TEMPLATE, RUMOR_FILE);
-       if (!(ofp = fopen(filename,
-#ifdef WIN32
-                                   WRBMODE
-#else
-                                   WRTMODE
-#endif
-                                          ))) {
+       if (!(ofp = fopen(filename, WRTMODE))) {
                perror(filename);
                exit(EXIT_FAILURE);
        }
-       Fprintf(ofp,Dont_Edit_Data);
+       if (!(tfp = fopen(tempfile, WRTMODE))) {
+               perror(tempfile);
+               Fclose(ofp);
+               exit(EXIT_FAILURE);
+       }
+
+       true_rumor_count = false_rumor_count = 0;
+       true_rumor_size = false_rumor_size = 0L;
+       true_rumor_offset = false_rumor_offset = eof_offset = 0L;
+
+       /* output a dummy header record; we'll replace it in final output */
+       Fprintf(tfp, rumors_header, Dont_Edit_Data, 
+               true_rumor_count, true_rumor_size, true_rumor_offset,
+               false_rumor_count, false_rumor_size, false_rumor_offset,
+               eof_offset);
+       /* record the current position; true rumors will start here */
+       true_rumor_offset = ftell(tfp);
 
        Sprintf(infile, DATA_IN_TEMPLATE, RUMOR_FILE);
        Strcat(infile, ".tru");
-       if (!(ifp = fopen(infile,
-#ifdef WIN32
-                                   RDBMODE
-#else
-                                   RDTMODE
-#endif
-                                          ))) {
+       if (!(ifp = fopen(infile, RDTMODE))) {
                perror(infile);
-               Fclose(ofp);
-               Unlink(filename);       /* kill empty output file */
-               exit(EXIT_FAILURE);
+               goto rumors_failure;
        }
 
-       /* get size of true rumors file */
-#ifndef VMS
-       (void) fseek(ifp, 0L, SEEK_END);
-       true_rumor_size = ftell(ifp);
-#else
-       /* seek+tell is only valid for stream format files; since rumors.%%%
-          might be in record format, count the actual data bytes instead.
-        */
-       true_rumor_size = 0;
-       while (fgets(in_line, sizeof in_line, ifp) != 0)
+       /* copy the true rumors */
+       while (fgets(in_line, sizeof in_line, ifp) != 0) {
+               true_rumor_count++;
                true_rumor_size += strlen(in_line);     /* includes newline */
-#endif /* VMS */
-       Fprintf(ofp,"%06lx\n", true_rumor_size);
-       (void) fseek(ifp, 0L, SEEK_SET);
-
-       /* copy true rumors */
-       while (fgets(in_line, sizeof in_line, ifp) != 0)
-               (void) fputs(xcrypt(in_line), ofp);
-
-       Fclose(ifp);
+               (void) fputs(xcrypt(in_line), tfp);
+       }
+       /* record the current position; false rumors will start here */
+       false_rumor_offset = ftell(tfp);
+       Fclose(ifp);            /* all done with rumors.tru */
 
+       /* process rumors.fal */
        Sprintf(infile, DATA_IN_TEMPLATE, RUMOR_FILE);
        Strcat(infile, ".fal");
-       if (!(ifp = fopen(infile,
-#ifdef WIN32
-                                 RDBMODE
-#else
-                                 RDTMODE
-#endif
-                                        ))) {
+       if (!(ifp = fopen(infile, RDTMODE))) {
                perror(infile);
-               Fclose(ofp);
-               Unlink(filename);       /* kill incomplete output file */
-               exit(EXIT_FAILURE);
+               goto rumors_failure;
        }
 
        /* copy false rumors */
-       while (fgets(in_line, sizeof in_line, ifp) != 0)
-               (void) fputs(xcrypt(in_line), ofp);
+       while (fgets(in_line, sizeof in_line, ifp) != 0) {
+               false_rumor_count++;
+               false_rumor_size += strlen(in_line);    /* includes newline */
+               (void) fputs(xcrypt(in_line), tfp);
+       }
+       /* record the current position; EOF available for sanity check */
+       eof_offset = ftell(tfp);
+       Fclose(ifp);            /* all done with rumors.fal */
 
-       Fclose(ifp);
+       /* get ready to transfer the contents of temp file to output file */
+       Sprintf(in_line, "rewind of \"%s\"", tempfile);
+       if (rewind(tfp) != 0) {
+               perror(in_line);
+               goto rumors_failure;
+       }
+
+       /* output the header record */
+       Fprintf(ofp, rumors_header, Dont_Edit_Data, 
+               true_rumor_count, true_rumor_size, true_rumor_offset,
+               false_rumor_count, false_rumor_size, false_rumor_offset,
+               eof_offset);
+       /* skip the temp file's dummy header */
+       if (!fgets(in_line, sizeof in_line, tfp) ||     /* "Don't Edit" */
+           !fgets(in_line, sizeof in_line, tfp)) {     /* count,size,offset */
+               perror(tempfile);
+               goto rumors_failure;
+       }
+       /* copy the rest of the temp file into the final output file */
+       while (fgets(in_line, sizeof in_line, tfp) != 0) {
+               (void) fputs(in_line, ofp);
+       }
+       /* all done; delete temp file */
+       Fclose(tfp);
+       Unlink(tempfile);
        Fclose(ofp);
        return;
+
+ rumors_failure:
+       Fclose(ofp);
+       Unlink(filename);       /* kill empty or incomplete output file */
+       Fclose(tfp);
+       Unlink(tempfile);       /* and temporary file */
+       exit(EXIT_FAILURE);
 }
 
 /*