Role selection is insanely complex. I had to use a debugger to force
the relevant routine to be executed.
The analysis was correct: it could use rn2(14) to pick a role (valid
values 0 through 12) and randomly getting 13 would lead to a crash.
The terminating element of roles[] passes all the ok_role(), ok_race(),
etc tests. Explicitly exclude that element when collecting the roles
to choose from.
Implement the request that a wielded+thrown aklys be given the same
inventory letter when it returns and is caught and rewielded, even for
the !fixinv setting where inventory letters don't stick. Works for
Valkyrie-thrown Mjollnir and returning (ie, didn't hit) boomerangs as
well as for aklys.
I'm not sure how useful this really is, because on the rare occasions
that it either doesn't return or fails to be caught, it won't be given
the same letter when subsequently picked up. So the player who relies
on it will still be vulnerable to using the wrong letter next time a
throw is attempted. But at least picking it up explicitly displays
the new inventory letter, unlike catching it upon return.
Change a couple of messages. When speed/haste-self times out:
"you feel yourself slowing down" -> "you feel yourself slow down"
because the former was too close to the turn-to-stone countdown and
the loss of speed is immediate rather than gradual.
The vomiting countdown causes confusion and stun; vary the messages
for those if already confused or stunned:
"you feel slightly confused" -> "you feel slightly more confused";
"you can't seem to think straight" -> "you can't think straight".
Separate out the reformatting from other changes I'm working on
for X11 "fancy status". Splits a few wide lines but mostly just
switches to the X11 idiom of combining
XSetArg(arglist[argcount], ...);
argcount++;
onto one line:
XSetArg(arglist[argcount], ...); argcount++;
Instead of having the demon lair levels unconditionally no-teleport,
grant demon lords and princes the ability to suppress teleportation
in Gehennom on the level they are on.
combine boolean and compound options into a single allopt[] array for
processing in options.c.
move the definitions of the options into new include/optlist.h file which
uses a set of macros to define them appropriately.
during compile of options.c each option described in include/optlist.h:
1. automatically results in a function prototype for an optfn called
optfn_xxxx (xxxx is the option name).
2. automatically results in an opt_xxxx enum value for referencing
its index throughout options.c (xxxx is the option name).
3. is used to initialize an element of the allopt[] array at index
opt_xxxx (xxxx is the option name) based on the settings in the
NHOPTB, NHOPTC, NHOPTP macros. Those macros only live during the
compilation of include/optlist.h.
each optfn_xxxx() function can be called with a req id of: do_init, do_set,
get_val or do_handler.
req do_init is called from options_init, and if initialization or memory
allocation or other initialization for that particular option is needed,
it can be done in response to the init req.
req do_set is called from parseoptions() for each option it encounters
and the optfn_xxxx() function is expected to react and set the option
based on the string values that parseoptions() passes to it.
req get_val expects each optfn_xxxx() function to write the current
option value into the buffer it is passed.
req do_handler is called during doset() operations in response to player
selections most likely from the 'O' option-setting menu, but only if the
option is identified as having do_handler support in the allopts[]
'has_handler' boolean flag. Not every optfn_xxxx() does.
function special_handling() is eliminated. It's code has been redistributed
to individual handler functions for the option or purpose that they serve.
moved reglyph_darkroom() function from options.c to display.c
A recent change has resulted in complaints about 'sel' not being
used in
struct selectionvar *sel = l_selection_check(L, 1);
struct selectionvar *ret;
int p = (int) luaL_checkinteger(L, 2);
lua_pop(L, 1);
(void) l_selection_clone(L);
ret = l_selection_check(L, 1);
selection_filter_percent(ret, p);
This preserves the semantics of that code while getting rid of the
warning, but I have no idea whether it makes any sense.
Give wizard mode player control over how a level gets transposed by
prompting for the desired outcome.
Refreshing the screen showed that remembered, no longer in view wall
corners and T walls were shown with their old orientation instead of
being transposed along with the level. This fixes that, but does so
by adding a chunk of code that will be irrelevant for normal play.
Eliminate the cache that was supporting rndmonst() and pick a random
monster in a single pass through mons[] via "weighted reservoir
sampling", a term I'm not familiar with.
It had a couple of bugs: if the first monster examined happened to
be given a weighting of 0, rn2() would divide by 0. I didn't try
to figure out how to trigger that. But the second one was easy to
trigger: if all eligible monsters were extinct or genocided, it
would issue a warning even though the situation isn't impossible.
Aside from fixing those, the rest is mostly as-is. I included a bit
of formatting in decl.c, moved some declarations to not require C99,
and changed a couple of macros to not hide and duplicate a call to
level_difficulty().
Fixes#286