get_rnd_text() for rumors and other stuff

Solve the uneven distribution situation that has been present for
picking random rumors for a long time and for random engravings,
epitaphs, and hallucinatory monster names since 3.6.0.  This relies
on the previous partial solution where short lines have been padded
to a longer length.  When that length is N and random seek lands in
a long line of length L, retry if the position is in the first L-N
characters.  Put differently, it if takes more than N characters to
reach the next newline, reject that random seek and try again.  This
effectively makes long lines behave as if they had the same length
of N as the short lines have been padded to and when all lines are
the same length, all entries have the same chance to be chosen.
This commit is contained in:
PatR
2021-11-27 12:23:01 -08:00
parent 629c2c4094
commit 03476a7c78
7 changed files with 50 additions and 32 deletions

View File

@@ -104,21 +104,6 @@ static const char SCCS_Id[] UNUSED = "@(#)makedefs.c\t3.7\t2020/01/18";
#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",
@@ -329,16 +314,16 @@ do_makedefs(char *options)
do_rnd_access_file(EPITAPHFILE,
/* default epitaph: parody of the default engraving */
"No matter where I went, here I am.",
PAD_RUMORS_TO);
MD_PAD_RUMORS); /* '_RUMORS' is correct here */
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.",
PAD_RUMORS_TO);
MD_PAD_RUMORS); /* '_RUMORS' used here too */
do_rnd_access_file(BOGUSMONFILE,
/* default bogusmon: iconic monster that isn't in nethack */
"grue", PAD_BOGONS_TO);
"grue", MD_PAD_BOGONS);
break;
case 'h':
case 'H':
@@ -896,6 +881,8 @@ padline(char *line, unsigned padlength)
* 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.
* The core's get_rnd_text() handles long lines in a way
* that results in even selection distribution.
*
* Random epitaphs, engravings, and hallucinatory monster
* names are in the same boat.
@@ -1059,13 +1046,13 @@ do_rumors(void)
false_rumor_offset = read_rumors_file(".tru", &true_rumor_count,
&true_rumor_size, true_rumor_offset,
PAD_RUMORS_TO);
MD_PAD_RUMORS);
if (!false_rumor_offset)
goto rumors_failure;
eof_offset = read_rumors_file(".fal", &false_rumor_count,
&false_rumor_size, false_rumor_offset,
PAD_RUMORS_TO);
MD_PAD_RUMORS);
if (!eof_offset)
goto rumors_failure;