#endif /* else !MAC */
#endif /* else !AMIGA */
+/*
+ * For files where entries are selected by seeking to a random position,
+ * skipping to newline, and then using the next line, lines that follow
+ * long ones are more likely to be selected than average and lines that
+ * follow short ones are less likely to be selected than average.
+ * We make selection be more evenly distributed by padding the shortest
+ * lines, at the cost of making the data files bigger. The larger these
+ * values are, the more uniform the selection will become but the more
+ * space will be needed for data used for something which is relatively
+ * inconsequential to actual game play. A value of 0 would suppress the
+ * padding because every line is already at least that long.
+ */
+#define PAD_RUMORS_TO 60u /* also used for epitaphs and engravings */
+#define PAD_BOGONS_TO 20u /* hallucinatory monsters */
+
static const char
*Dont_Edit_Code =
"/* This source file is generated by 'makedefs'. Do not edit. */\n",
*Dont_Edit_Data =
"#\tThis data file is generated by 'makedefs'. Do not edit. \n",
*Reference_file =
- "/* This file is generated by 'makedefs' for reference purposes only. */\n"
- "/* It is no longer used in the NetHack build. */\n";
+ "/* This file is generated by 'makedefs' for reference purposes only. */\n"
+ "/* It is no longer used in the NetHack build. */\n";
static struct version_info version;
static FILE *getfp(const char *, const char *, const char *, int);
static void do_ext_makedefs(int, char **);
static char *xcrypt(const char *);
+static char *padline(char *, unsigned);
static unsigned long read_rumors_file(const char *, int *,
- long *, unsigned long);
-static void do_rnd_access_file(const char *, const char *);
+ long *, unsigned long, unsigned);
+static void do_rnd_access_file(const char *, const char *, unsigned);
static boolean d_filter(char *);
static boolean h_filter(char *);
static void opt_out_words(char *, int *);
*/
do_rnd_access_file(EPITAPHFILE,
/* default epitaph: parody of the default engraving */
- "No matter where I went, here I am.");
+ "No matter where I went, here I am.",
+ PAD_RUMORS_TO);
do_rnd_access_file(ENGRAVEFILE,
/* default engraving: popularized by "The Adventures of
Buckaroo Bonzai Across the 8th Dimenstion" but predates
that 1984 movie; some attribute it to Confucius */
- "No matter where you go, there you are.");
+ "No matter where you go, there you are.",
+ PAD_RUMORS_TO);
do_rnd_access_file(BOGUSMONFILE,
/* default bogusmon: iconic monster that isn't in nethack */
- "grue");
+ "grue", PAD_BOGONS_TO);
break;
case 'h':
case 'H':
return buf;
}
-#define PAD_RUMORS_TO 60
+static char *
+padline(char *line, unsigned padlength)
+{
+ /*
+ * Rumor selection is accomplished by seeking to a random
+ * position in the file, advancing to newline, and taking
+ * the next line. Therefore, rumors which follow long-line
+ * rumors are most likely to be chosen and rumors which
+ * follow short-line rumors are least likely to be chosen.
+ * We ameliorate the latter by padding the shortest lines,
+ * increasing the chance of the random seek landing in them.
+ *
+ * Random epitaphs, engravings, and hallucinatory monster
+ * names are in the same boat.
+ */
+ char *endp;
+ unsigned len = (unsigned) strlen(line); /* includes newline */
+
+ if (len <= padlength) {
+ endp = index(line, '\n');
+
+ /* this is only safe because fgetline() overallocates */
+ while (len++ < padlength) {
+ *endp++ = '_';
+ }
+ *endp++ = '\n';
+ *endp = '\0';
+ }
+ return line;
+}
+
/* common code for do_rumors(). Return 0 on error. */
static unsigned long
-read_rumors_file(const char* file_ext, int* rumor_count,
- long* rumor_size, unsigned long old_rumor_offset)
+read_rumors_file(
+ const char *file_ext,
+ int *rumor_count,
+ long *rumor_size,
+ unsigned long old_rumor_offset,
+ unsigned padlength)
{
char infile[MAXFNAMELEN];
char *line;
/* copy the rumors */
while ((line = fgetline(ifp)) != 0) {
-#ifdef PAD_RUMORS_TO
- /* rumor selection is accomplished by seeking to a random
- position in the file, advancing to newline, and taking
- the next line; therefore, rumors which follow long-line
- rumors are most likely to be chosen and rumors which
- follow short-line rumors are least likely to be chosen;
- we ameliorate the latter by padding the shortest lines,
- increasing the chance of the random seek landing in them */
- int len = (int) strlen(line);
-
- if (len <= PAD_RUMORS_TO) {
- char *base = index(line, '\n');
- /* this is only safe because fgetline() overallocates */
- while (len++ < PAD_RUMORS_TO) {
- *base++ = '_';
- }
- *base++ = '\n';
- *base = '\0';
- }
-#endif
+ (void) padline(line, padlength); /* make shortest lines be longer */
+
(*rumor_count)++;
#if 0
/*[if we forced binary output, this would be sufficient]*/
}
static void
-do_rnd_access_file(const char* fname, const char* deflt_content)
+do_rnd_access_file(
+ const char *fname,
+ const char *deflt_content,
+ unsigned padlength)
{
char *line, buf[BUFSZ];
exit(EXIT_FAILURE);
}
Fprintf(ofp, "%s", Dont_Edit_Data);
- /* lines from the file include trailing newline so make sure that the
- default one does too */
- if (!index(deflt_content, '\n'))
- deflt_content = strcat(strcpy(buf, deflt_content), "\n");
/* write out the default content entry unconditionally instead of
waiting to see whether there are no regular output lines; if it
matches a regular entry (bogusmon "grue"), that entry will become
more likely to be picked than normal but it's nothing to worry about */
- (void) fputs(xcrypt(deflt_content), ofp);
+ Strcpy(buf, deflt_content);
+ if (!index(buf, '\n')) /* lines from the file include trailing newline +*/
+ Strcat(buf, "\n"); /* so make sure that the default one does too */
+ (void) fputs(xcrypt(padline(buf, padlength)), ofp);
tfp = getfp(DATA_TEMPLATE, "grep.tmp", WRTMODE, FLG_TEMPFILE);
grep0(ifp, tfp, FLG_TEMPFILE);
ifp = getfp(DATA_TEMPLATE, "grep.tmp", RDTMODE, 0);
#endif
while ((line = fgetline(ifp)) != 0) {
- if (line[0] != '#' && line[0] != '\n')
+ if (line[0] != '#' && line[0] != '\n') {
+ (void) padline(line, padlength);
(void) fputs(xcrypt(line), ofp);
+ }
free((genericptr_t) line);
}
Fclose(ifp);
/* record the current position; true rumors will start here */
true_rumor_offset = ftell(tfp);
- false_rumor_offset = read_rumors_file(
- ".tru", &true_rumor_count, &true_rumor_size, true_rumor_offset);
+ false_rumor_offset = read_rumors_file(".tru", &true_rumor_count,
+ &true_rumor_size, true_rumor_offset,
+ PAD_RUMORS_TO);
if (!false_rumor_offset)
goto rumors_failure;
eof_offset = read_rumors_file(".fal", &false_rumor_count,
- &false_rumor_size, false_rumor_offset);
+ &false_rumor_size, false_rumor_offset,
+ PAD_RUMORS_TO);
if (!eof_offset)
goto rumors_failure;