trycall() is a short docall() wrapper that is a no-op if the item is
already identified or the player has called the object type already. For
some reason, many calls to docall() did those same exact checks
beforehand.
This commit eliminates that redundancy by converting those calls into
trycall(), which is now made extern rather than local to do.c. No
behavior should be changed by this commit; I've checked that none of the
affected places could take a different code path now that the
oc_name_known and oc_uname checks are removed.
Remove the conduct-specific aspect of receiving spells as prayer boon.
Anyone now has a 25% chance of having the spell directly implanted
into their head, not just characters who have maintained illiterate
conduct. It can now also restore a forgotten spell or refresh one
that is nearly forgotten. It still tries to choose a spell which
isn't already known (new: or was known but has been forgotten) but if
it picks one that is known and doesn't need refreshing, a redundant
book will be given, same as the behavior in earlier versions.
The chance for receiving a blank spellbook is higher when that item
is undiscovered. When given as a prayer reward, make it become
discovered even if hero doesn't read it so that it will be less likely
to be given again. There's a 1% chance for that auto-discovery to
happen with other bestowed books. Unlike blank boots, having the book
be discovered doesn't lessen their chance of being repeat gifts.
Minor bug fix: for a spell implanted from scratch, the book remains
unknown. That's ok; it's actually more interesting than discovering
a book you haven't seen yet. But after acquiring and reading the book
you could get "you know <spell> quite well already" and the book would
stay undiscovered even though you were just told what spell it's for.
Ensure the first spell - if any - given to the hero in initial
inventory is level 1 - otherwise you can end up with a situation
where the hero knows level 3 spells, but won't have enough power
to cast them.
If the hero starts out with a spell, ensure enough power (5)
to cast that level 1 spell.
Log game events, such as entering a new dungeon level, breaking
a conduct, or killing a unique monster, in a new "Major events"
chronicle. The entries record the turn when the event happened.
The log can be viewed with #chronicle -command, and the entries
also show up in the end-of-game dump, if that is available.
This feature is on by default, but can be disabled by
defining NO_CHRONICLE compile-time option.
This also contains "live logging", writing the events as they
happen into a single livelog-file. This is mostly useful for
public servers. The livelog is off by default, and must be
compiled in with LIVELOG, and then turned on in sysconf.
Mostly this a version of livelogging from the Hardfought server,
with some changes.
If you want to declare a pointer which the address pointed to is constant,
you should declare it as like `static const char *const var = "...";`.
This commit supplies missing `const` and prevents some programming
error in the future.
Instead of returning 0 or 1, we'll now use ECMD_OK or ECMD_TURN.
These have the same meaning as the hardcoded numbers; ECMD_TURN
means the command uses a turn.
In future, could add eg. a flag denoting "user cancelled command"
or "command failed", and should clear eg. the cmdq.
Mostly this was simply replacing return values with the defines
in the extended commands, so hopefully I didn't break anything.
If attempting to cast a spell without having enough power, you get
|You don't have enough energy to cast that spell.
Recently that was augmented to
|You don't have enough energy to cast that spell yet.
if your current power is at maximum and not enough. Augment again to
|You don't have enough energy to cast that spell anymore.
if current power is at maximum and that maximum is less than the peak
value it once had and that peak value would have been enough.
If the hero is at full energy but still lacks enough to cast a chosen
spell, say "you don't have enough energy yet" instead of just "you
don't have enough energy."
Revisit a 3.6.1 fix. When the hero is occupied reading a spellbook
and something causes it to become cursed without interrupting (post-
Wizard harassment's malignant aura), always stop reading instead of
just when the book's bknown flag is already set.
Whitelist all the verified existing triggers:
makedefs.c: In function ‘name_file’
attrib.c: one compiler balks at a ? b : c for fmtstring
cmd.c: In function ‘extcmd_via_menu’
cmd.c: In function ‘wiz_levltyp_legend’
do.c: In function ‘goto_level’
do_name.c: In function ‘coord_desc’
dungeon.c: In function ‘overview_stats’
eat.c: one compiler balks at a ? b : c for fmtstring
end.c: one compiler balks at a ? b : c for fmtstring
engrave.c: In function ‘engr_stats’
hack:c one compiler balks at a ? b : c for fmtstring
hacklib.c: one compiler balks at a ? b : c for fmtstring
insight.c: one compiler balks at a ? b : c for fmtstring
invent.c: In function ‘let_to_name’
light.c: In function ‘light_stats’
mhitm.c: In function ‘missmm’
options.c: In function ‘handler_symset’
options.c: In function ‘basic_menu_colors’
options.c: In function ‘optfn_o_autopickup_exceptions’
options.c: In function ‘optfn_o_menu_colors’
options.c: In function ‘optfn_o_message_types’
options.c: In function ‘optfn_o_status_cond’
options.c: In function ‘optfn_o_status_hilites’
options.c: In function ‘doset’
options.c: In function ‘doset_add_menu’
options.c: In function ‘show_menu_controls’
options.c: In function ‘handle_add_list_remove’
pager.c: In function ‘do_supplemental_info’
pager.c: In function ‘dohelp’
region.c: In function ‘region_stats’
rumors.c: sscanf usage
sounds.c: In function ‘domonnoise’
spell.c: In function ‘dospellmenu’
timeout.c: In function ‘timer_stats’
topten.c: In function ‘outentry’, fscanf, sscanf, fprintf usage
windows.c: In function ‘genl_status_update’
zap.c: one compiler balks at a ? b : c for fmtstring
win/curses/cursstat.c: In function ‘curses_status_update’
win/tty/wintty.c: In function ‘tty_status_update’
win/win32/mswproc.c: In function ‘mswin_status_update’
at self when blind. Spell targetting would let player pick
hero's own spot but casting would reject it when blind because
hero didn't sense any monster there. The player wanted to cast
skilled fireball at self to cure being turned into slime but
wasn't allowed. (Targetting an adjacent spot would work for
fireball, but is only feasible when telepathy reveals a monster
there.)
While testing the one-line fix, I noticed that the message line
(tty) showed stale data (autodescribe info for target spot) as
the fireball I cast (when not blind) bounced around the vicinity.
Normally that's cleared when a message is issued or the when the
next command is requested, but skilled fireball causes multiple
explosion animations before either of those situations.
Gcc 9 has become more vocal with sprintf buffer overflow
checking. Remove these sprintf warnings by changing the
offending calls to a snprintf wrapper that will explicitly
check the result.
further adjustments to the window port interface to pass a pointer
to a glyph_info struct which describes not just the glyph number
itself, but also the ttychar, the color, the glyphflags, and the
symset index.
This affects two existing window port calls that get passed glyphs
and does the parameter consistently for both of them using the
glyph_info struct pointer:
print_glyph()
add_menu().
The recently added glyphmod parameter is now unnecessary and has been
removed.
Tell the player the spell casting letter when learning a new spell:
|You add "knock" to your repertoire, as 'e'.
Comparable to "k - ring mail" when picking up a suit of ring mail
puts it into inventory slot k.
Aimed at fixing the problem where the player knows they're going to
forget a spell in a few thousand turns, so they go back and get the
book... only to find out that they "know it quite well already", and
need to wait an indeterminate amount of time until they are on the verge
of forgetting it (< 2000 turns) before the book will let them read it
again.
This commit simply removes that 2000 turn limit, so the player can fully
restore their memory at any time with the spellbook. Naturally, this
still consumes a read charge, so the book won't ultimately last as long
if you keep rereading it early.
If you do have more than 2000 turns left, the game will prompt you to
confirm that you do want to refresh your memory anyway. As before,
rereading with fewer turns will not prompt.
After writing the log message for the bell change, I decided to
test the Book and found some issues:
1) reading it while blind discovered the book's type but wasn't
marking the book object as if it had become seen (dknown);
2) reading it while blind gave sighted feedback if it was cursed;
3) reading (blind or not) when either of the other two invocation
tools are cursed referred to those as "artifacts" even though
they aren't artifacts; the discoveries list describes them as
"unique items" but that makes for a clumsy message--use "relics"
instead.
Instead of forgetting maps and objects, make amnesia forget skills.
Forgetting maps and objects could be circumvented with taking notes,
or by using an external tool to remember the forgotten levels.
Forgetting skills allows the player to optionally go down another
skill path, if they trained the wrong weapon in the early game.
Amnesia still forgets spells.
As a replacement for the deja vu messages when entering a forgotten
level, those messages will now indicate a ghost with your own name
existing on the level, given only when the level is entered for
the first time.
These changes based on fiqhack, with some adjustments.
Provide a way to communicate additional behaviors and/or appearances
desired from NetHack window port menus.
This is foundation work for changes to follow at a future date.
Introduce eight achievements that can be attained by more players.
Entered Gnomish Mines - self explanatory
Entered Mine Town - the town portion, not just the level
Entered a shop - any tended shop on any level
Entered a temple - likewise for temple
Consulted the Oracle - bought at least one major or minor oracle
Read a Discworld Novel - read at least one passage
Entered Sokoban - like mines
Entered the Big Room - not always possible since not always present
The novel and bigroom ones aren't always achieveable since novels are
only guaranteed if a book or scroll shop gets created and bigroom is
only guaranteed in wizard mode. No one ever claimed that every
possible achievement can be attained in a single game. (If one for
entering the Fort Ludios level--or perhaps entering the Fort itself--
eventually gets add, that won't be possible in every game either.)
The mine town one probably needs some tweaking. Two of the town's
seven variants have no town boundary (despite a rectangular area of
pre-defined map) and at present simply arriving on either of those
levels is enough to be credited with the entered-town achievement.
Bump EDITLEVEL because u.uachieved[] has increased in size. This
time it has been expanded to the maximum that xlogfile's bitmask of
achievements can handle, enough for up to 9 more achievements without
another EDITLEVEL increment.
Instead of an assortment of bits, assign numeric indices to the
potential achievements and keep an array of those in the order they
were attained. So disclosure might show the same subset occurring
differently in different games depending on the player's actions.
The encoded field in xlogfile doesn't care about that and remains
the same.
Modifies 'struct u', so EDITLEVEL has been incremented and existing
save files are invalidated.
groundwork only - window port interface change
This changes the last parameter for add_menu() from a boolean
to an unsigned int, to allow additional itemflags in future
beyond just the "preselected" that the original boolean offered.
There shouldn't be any functionality changes with this groundwork-only
change, and if there are it is unintentional and should be reported.
Fixes#172
Casting teleport-away via ^T used different requirements for energy,
strength, and hunger than casting it via 'Z'. The strength and hunger
requirements were more stringent, the energy one more lenient. When
it rejected a cast attempt due to any of those, it used up the move,
but 'Z' didn't.
When testing my fix, I wanted an easier way than a debugger to control
how ^T interacts with wizard mode, so finally got around to a first
cut at being able to invoke it via wizard mode but not override those
energy/strength/hunger requirements. It uses the 'm' prefix to ask
for a menu. 'm^T' gives four options about how to teleport. (There
are other permutations which aren't handled.)
Also noticed while testing: ^T wouldn't attempt to cast teleport-away
if you didn't know the corresponding spellbook. 'Z' will attempt that
because it is possible to forget a book and still know its spell.
Fixes#109
Spells of healing and extra healing cast at monsters were handling
monster blindness differently from other forms of healing. (Potions
also work differently when drunk by monsters but I haven't changed
that since it seems to be intentional.)
Hero:
potion of healing cures blindness if blessed; spell of healing
cast at skilled or better now behaves likewise;
potion of extra healing cures blindness if not cursed; spell of
extra healing is inherently not cursed and already behaved
likewise;
potion of full healing always cures blindness even if cursed.
Monsters quaffing potions:
plain healing cures blindness if not cursed;
extra healing and full healing always cure blindess.
Hero casting healing spell at monster:
plain healing behaves like the hero plain healing case: cures
blindness as if blessed when cast at skilled or expert level;
this is a change in hehavior--it used to cure timed blindness
even if unskilled and not cure 'permanent' blindness at all;
extra healing cast by hero is inherently not cursed so always
cures blindness.
Reading a scroll while blind is permitted if you know its label, but
message is "as you pronounce the words, the scroll vanishes" unless
you are poly'd into a form which can't make sounds, in which case you
"cogitate" rather than "pronouce". Switch to the cogitate variant if
you are suffering from strangulation.
Casting spells didn't even have the distinction; you could cast them
without regard to speech capability. Check for that. Unlike with
scrolls, now you can't cast if you can't speak (or grunt or bark or
whatever) instead of having a variant description of the action, so
this is a bigger change.