If 'autounlock' is set to test a chest for traps, skip "check for
traps?" when tknown is set; go directly to "disarm trap?" if the
chest is trapped, skip that too if it isn't.
If wand of probing hits a chest, set the tknown bit.
Issue reported by ostrosablin: having Kick enabled as one of the
values for the 'autounlock' option succeeded it prompting "kick it?"
when walking into a locked closed door, but answering "yes" behaved
the same as answering "no".
There's bound to be a better way of fixing this, but this works.
Fixes#1360
After finding a trap on a chest or a large box, remember it
as trapped: "You see here a trapped large box."
Randomly generated chests and boxes can be obviously trapped.
Allow defining obviously trapped containers via lua.
Invalidates saves and bones.
The g? structs had a mix of variables that were written to
the savefile, and those that were not.
For better clarity and to distinguish those that end up in
the savefile, relocate some g? variables that get written
directly to the savefile into different structs.
This updates EDITLEVEL, although technically it probably
didn't need to, since savefile contents are not changing.
Details:
gb.bases -> svb.bases
gb.bbubbles -> svb.bbubbles
gb.branches -> svb.branches
gc.context -> svc.context
gd.disco -> svd.disco
gd.dndest -> svd.dndest
gd.doors -> svd.doors
gd.doors_alloc -> svd.doors_alloc
gd.dungeon_topology -> svd.dungeon_topology
gd.dungeons -> svd.dungeons
ge.exclusion_zones -> sve.exclusion_zones
gh.hackpid -> svh.hackpid
gi.inv_pos -> svi.inv_pos
gk.killer -> svk.killer
gl.lastseentyp -> svl.lastseentyp
gl.level -> svl.level
gl.level_info -> svl.level_info
gm.mapseenchn -> svm.mapseenchn
gm.moves -> svm.moves
gm.mvitals -> svm.mvitals
gn.n_dgns -> svn.n_dgns
gn.n_regions -> svn.n_regions
gn.nroom -> svn.nroom
go.oracle_cnt -> svo.oracle_cnt
gp.pl_character -> svp.pl_character
gp.pl_fruit -> svp.pl_fruit
gp.plname -> svp.plname
gp.program_state -> svp.program_state
gq.quest_status -> svq.quest_status
gr.rooms -> svr.rooms
gs.sp_levchn -> svs.sp_levchn
gs.spl_book -> svs.spl_book
gt.timer_id -> svt.timer_id
gt.tune -> svt.tune
gu.updest -> svu.updest
gx.xmax -> svx.xmax
gx.xmin -> svx.xmin
gy.ymax -> svy.ymax
gy.ymin -> svy.ymin
Related note:
There are some pointer variables that are heads of chains that were not
moved from 'g?' to 'sv?', because they are not actually written to the
savefile directly, but the objects/monst/trap/lightsource/timer in the
chains they point to are. That can be changed, if desired.
Examples: gi.invent, gm.migrating_objs, gb.billobjs, gm.migrating_mons,
gf.ftrap, gl.light_base, gt.timer_base
A fairly recent change to improve the message given when hero isn't
able to force a locked chest due to type of weapon or weapons being
wielded had one of the text substitutions backwards. If wielding 1
dart, it gave
|You can't force anything with those weapon.
and if wielding more than 1,
|You can't force anything with that weapons.
Failed #force due to wielding wrong implement didn't phrase things
well if current weapon was a stack.
Plus some reformatting split out from a forthcoming #engrave patch.
In 3.6.2 parts of the wakeup code were merged together, and this
caused pets consider any noise made by the hero - such as hitting
iron bars or digging - as whistling for them to come to the hero.
Change it to only consider actual whistling and ringing a bell.
Adds a new boolean option, accessiblemsg. If on, some game messages
are prefixed with direction or location information, for example:
(west): The newt bites!
(northwest): You find a hidden door.
I added the info to the most common messages, but several are
still missing it.
Update several places where lazy lastseentyp[] might be an issue.
I think it isn't updated in a timely fashion when newsym() shows
a spot covered by an object or trap, but didn't manage to find any
cases where that caused a problem. This is more in the nature of
a precaution.
When testing water-vault chests, I kept getting
|Klick! Klick!
when zapping them with a wand of opening. This had me scratching my
head for a while, but it seems to have been caused by partially adding
a sound effect. pline("Klick!") became duplicated and presumeably one
of the two was intended to be edited into a sound-effect call but got
overlooked.
Sound_effect(se_klick,) doesn't make any sound though.
I was working on this at the time 3.6.0 was released and set it aside
until later. Later has finally arrived. Redo the Blind, Blinded,
Blindfolded,&c macros to make more complete use of intrinsic property
handling. Blinded was being treated as a number which could be added
to or subtracted from; now that has to be done via TIMEOUT mask
because it has FROMOUTSIDE (OPTIONS:blind) and FROMFORM (poly'd into
!haseyes() form) bits included. Object definitions for blindfold and
towel now specify the BLINDED property; overriding blindness via the
Eyes of the Overworld is accomplished via props[BLINDED].blocked.
Code generated for the scores of Blind and !Blind tests throughout
the program should be smaller.
One bug that has been fixed is that putting on the Eyes of the
Overworld cured permanent blindness (from OPTIONS:blind). The
u.uroleplay.blind flag was cleared and stayed so after taking them
off. Putting the Eyes on still breaks blind-from-birth conduct but
now blindness will resume when they are removed.
This was untested at the time it was set aside and is only lightly
tested now. A large number of the changes here are just to switch
from Blinded to BlindedTimeout for current timed value and to call
set_itimeout() for setting a new value.
If standing at the location of a closed door while having Passes_walls
ability, attemping to open that door with 'o' reported "you don't find
anything here to loot".
Using 'o' to loot for direction ./>/< is intentional but it ignored
the possibility of there also being a closed door present. When the
latter applies, only switch from open to loot for direction '>' so
that '.' (and '<') will open the door. Doesn't matter for creatures
that can ooze under a closed door--trying to use 'o' gets rejected for
them because they lack hands.
Also allow hero in Passes_walls form to use 'c' when at open door spot.
(For creatures that ooze under doors, 'c' is rejected just like 'o'.)
Unrelated: fix a typo in a recently added comment.
sound_verbal(char *text, int32_t gender, int32_t tone, int32_t vol,
int32_t moreinfo);
-- NetHack will call this function when it wants to pass text of
spoken language by a character or creature within the game.
-- text is a transcript of what has been spoken.
-- gender indicates MALE or FEMALE sounding voice.
-- tone indicates the tone of the voice.
-- vol is the volume (1% - 100%) for the sound.
-- moreinfo is used to provide additional information to the soundlib.
-- there may be some accessibility uses for this function.
It may be useful for accessibility purposes too.
A preliminary implementation has been attempted for macsound to test
the interface on macOS. No tinkering of the voices has been done.
Use of the test implementation requires the following at build time with make.
WANT_SPEECH=1
That needs to be included on the make command line to enable the test code,
otherwise just the interface update is compiled in.
I don't know for certain when AVSpeechSynthesizer went into macOS, but older versions
likely don't support it, and would just leave off the WANT_SPEECH=1.
If built with WANT_SPEECH=1, the 'voices' NetHack option needs to be enabled.
It was a bit strange, when I first started up the test, to hear Asidonhopo,
the shopkeeper, talking to me as I entered his shop and interacted with him.
Trying to open a location where a pet was removed the glyph
and showed the underlying terrain glyph instead.
Just use newsym - it'll use feel_location when Blind.
Insert the calls to trigger a number of potential soundeffects
into the core.
If no additional soundlib support is integrated into the
build, then the Soundeffect macro (sndprocs.h) expands to nothing:
[#define Soundeffect(seid, vol)
]
If, however, at least one additional soundlib support is integrated
into the build, then the Soundeffect macro gets defined as this
in sndprocs.h:
[#define Soundeffect(seid, vol) \
do { \
if (!Deaf && soundprocs.sound_soundeffect \
&& ((soundprocs.sndcap & SNDCAP_SOUNDEFFECTS) != 0)) \
(*soundprocs.sound_soundeffect)(emptystr, (seid), (vol)); \
} while(0)
]
That macro definition checks for the hero not being Deaf; it checks
to ensure that the active soundlib interface has a non-null
sound_soundeffect() function pointer; and it checks to ensure
that the active soundlib interface has declared that it supports
soundeffects by setting the SNDCAP_SOUNDEFFECTS bit in its sndcap
entry. That just means that the interface routines are prepared to
accept and deal with the calls from the core, whether or not it
actually produces the desired soundeffect.
A number of C compiler suites have a math.h library that includes a yn()
function name that conflicts with NetHack's yn() macro:
"The y0(), y1(), and yn() functions are Bessel functions of the second kind,
for orders 0, 1, and n, respectively. The argument x must be positive. The
argument n should be greater than or equal to zero. If n is less than zero,
there will be a negative exponent in the result."
At one point, isaac64.h included math.h, although that has since been removed.
Some libraries used in NetHack (Qt for one) do include math.h and that required
build work-arounds to avoid the conflict.
Rename the NetHack macro from yn() to y_n() and avoid the math.h conflict
altogether, eliminating the need for that particular work-around.
The consolidation of global variables from scattered source
files into decl.c and declared in decl.h was begun in 3.7.0.
Their placement in common files was done for centralized
initialization and potential re-initialization during a
"play again" scenario.
It wasn't really necessary for all of them to be housed in a
single huge structure to meet the "play again" requirement,
and the single huge structure has been a little unwieldy when
it comes to maintenance.
Following this commit, instead of one single extremely large structure
named 'g' to house all of the relocated global variables, they
are distributed into several ga through gz.
To make things easy for the developer, each variable is placed
into the struct corresponding to the starting letter of the variable.
That way, no lookup is required in order to know which struct houses
a particular variable, it is a simple match to the starting letter
for all the centralized global variables.
A global variable named 'amulets', would be found in ga.
ga.amulets
^ ^
A global varable named 'move', would be found in gm.
gm.moves
^ ^
A global variable named 'val_for_n_or_more' would be found in gv.
gv.val_for_n_or_more
^ ^
A global variable named 'youmonst' would be found in gy.
gy.youmonst
^ ^
Year old issue from copperwater: 'open' directed at a non-door told
player that there isn't a door and took no time unless character was
blind and learned what type of terrain it is, applying a key gave
the same message but used a turn and didn't update map to reflect any
terrain discovery.
Attempting to open an adjacent door or applying a key to one while in
a pit had a similar issue: they produced the same "you can't reach
it from here" but had different time vs no-time outcome.
There may be other actions in the same situation.
Closes#581
The pull request included some changes that were neither accidental nor
unintentional, so only a subset of the changes from pull request #869
submitted by klorpa were manually applied.
behaviour -> behavior
speach -> speech
knowlege -> knowledge
incrments -> increments
stethscope -> stethoscope
staiway -> stairway
arifact -> artifact
extracing -> extracting
The uses of "iff" were left alone.
Close#869
This replaces the old pushq/saveq arrays (which were used to save
the keys pressed by the user for repeating a previous command)
with a new command queue. This means there's no hard-coded limit
to the saved keys, and it can repeat extended commands which are
not bound to any key.
Using #loot while in a pit allows looting containers in that pit.
Using open and specifying the hero's spot when not in a pit allows
looting containers at hero's spot. But using open while in a pit
complained about not being able to reach out of the pit before player
had a chance to give hero's spot at the place of interest, so did not
allow looting any container there.
Get a target spot before rejecting use of 'open' while in a pit.
The alternate prompt might be tty-centric.
One of the drivers of this change was that screen coordinates require a
type that can hold values greater than 127. Parameters to the window
port routines require a large type in order to be able to have values
a fair bit larger than COLNO and ROWNO passed to them, particularly for
their use to the right of the map window.
This splits the uses of xchar into 3 different situations, and adjusts
their type and size:
xchar
|
-----------------------
| | |
coordxy xint16 xint8
coordxy: Actual x or y coordinates for various things (moved to 16-bits).
xint16: Same data size as coordxy, but for non-coordinate use (16-bits).
xint8: There are only a few use cases initially, where it was very
plain to see that the variable could remain as 8-bits, rather
than be bumped to 16-bits. There are probably more such cases
that could be changed after additional review.
Note: This first changed all xchar variables to coordxy. Some were
reviewed and got changed to xint16 or xint8 when it became apparent that
their usage was not for coordinates.
This increments EDITLEVEL in patchlevel.h
Switch to using a macro invocation Verbos(n, s) in place of the
flags.verbose checks.
Provide the mechanics for individual suppression of any of the
existing messages that were considered verbose.
Mechanics only - this code update does not provide any means of
setting the suppression bits.
iflags.verbose = 0
is still a master suppression of all the verbose messages.
iflags.verbose = 1
turns on the verbose messages only for those whose suppression
bit is 0 (not set).
Implement 'untrap' as an 'autounlock' action. Quite a bit more work
than anticipated. The new documentation is rather clumsy; too many
if-this and if-not-that clauses have intruded.
I'll be astonished if all the return values are correct....
[A couple of places were checking for (rx != 0 && ry != 0) to decide
whether they were performating an autounlock action at <rx,ry> but
that erroneously excludes the top line of the map if the current
level extends that far. Just check rx for zero/non-zero.]
This gives the player more control over what autounlock does. It is
now a compound option rather than a boolean, and takes values of
autounlock:none
!autounlock or noautounlock (shortcuts for none)
autounlock:untrap + apply-key + kick + force (spaces are optional
or can be used instead of plus-signs, but can't mix "foo bar+quux")
autounlock (without a value, shortcut for autounlock:apply-key).
Default is autounlock:apply-key.
Untrap isn't implemented (feel free to jump in) so is suppressed from
the 'O' command's new sub-menu for autounlock. It's parsed and
accepted from .nethackrc but won't accomplish anything.
[Just musing: it should be feasible to kick in direction '.' to break
open a container or #force to an adjacent spot to break open a door.
If that was done, autounlock:kick+force (or more likely autounlock:
apply-key+kick+force when lacking a key) would resort to force if hero
couldn't kick due to wounded legs or riding.
This changes struct flags so increments EDITLEVEL again.
This includes pull requests #750 from entrez and #751 from FIQ but was
entered from scratch rather than using use their commits.
Closes#750Closes#751
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.
djgpp cross-compiler was griping about several.
This also removes these lines from sys/unix/hints/include/compiler.370.
CFLAGS+=-Wno-format-nonliteral
CCXXFLAGS+=-Wno-format-nonliteral
-Wformat-nonliteral should not be incompatible with the printf
argument-checking capabilities on literal format strings and there
shouldn't be any new warnings created.
-- &< --
artifact.c: In function 'artifact_hit':
artifact.c:1309:23: warning: format not a string literal, argument types not checked [-Wformat-nonliteral]
1309 | mon_nam(mdef));
| ^~~~~~~
artifact.c:1328:17: warning: format not a string literal, argument types not checked [-Wformat-nonliteral]
1328 | pline(behead_msg[rn2(SIZE(behead_msg))], wepdesc, "you");
| ^~~~~
ball.c: In function 'drop_ball':
ball.c:896:17: warning: format not a string literal, argument types not checked [-Wformat-nonliteral]
896 | pline(pullmsg, "pit");
| ^~~~~
ball.c:899:17: warning: format not a string literal, argument types not checked [-Wformat-nonliteral]
899 | pline(pullmsg, "web");
| ^~~~~
ball.c:904:17: warning: format not a string literal, argument types not checked [-Wformat-nonliteral]
904 | pline(pullmsg, hliquid("lava"));
| ^~~~~
ball.c:908:17: warning: format not a string literal, argument types not checked [-Wformat-nonliteral]
908 | pline(pullmsg, "bear trap");
| ^~~~~
dig.c: In function 'liquid_flow':
dig.c:747:9: warning: format not a string literal, argument types not checked [-Wformat-nonliteral]
747 | pline(fillmsg, hliquid(typ == LAVAPOOL ? "lava" : "water"));
| ^~~~~
fountain.c: In function 'floating_above':
fountain.c:28:5: warning: format not a string literal, argument types not checked [-Wformat-nonliteral]
28 | You(umsg, what);
| ^~~
invent.c: In function 'hold_another_object':
invent.c:1018:17: warning: format not a string literal, argument types not checked [-Wformat-nonliteral]
1018 | pline(drop_fmt, drop_arg);
| ^~~~~
invent.c:1073:9: warning: format not a string literal, argument types not checked [-Wformat-nonliteral]
1073 | pline(drop_fmt, drop_arg);
| ^~~~~
invent.c: In function 'silly_thing':
invent.c:1811:9: warning: format not a string literal, argument types not checked [-Wformat-nonliteral]
1811 | pline(silly_thing_to, word);
| ^~~~~
lock.c: In function 'pick_lock':
lock.c:375:19: warning: format not a string literal, argument types not checked [-Wformat-nonliteral]
375 | pline(no_longer, "hold the", what);
| ^~~~~~~~~
lock.c:379:19: warning: format not a string literal, argument types not checked [-Wformat-nonliteral]
379 | pline(no_longer, "reach the", "lock");
| ^~~~~~~~~
lock.c: In function 'pick_lock':
lock.c:375:19: warning: format not a string literal, argument types not checked [-Wformat-nonliteral]
375 | pline(no_longer, "hold the", what);
| ^~~~~~~~~
lock.c:379:19: warning: format not a string literal, argument types not checked [-Wformat-nonliteral]
379 | pline(no_longer, "reach the", "lock");
| ^~~~~~~~~
mcastu.c: In function 'cast_cleric_spell':
mcastu.c:670:13: warning: format not a string literal, argument types not checked [-Wformat-nonliteral]
670 | pline(fmt, Monnam(mtmp), what);
| ^~~~~
mhitu.c: In function 'hitmsg':
mhitu.c:68:13: warning: format not a string literal, argument types not checked [-Wformat-nonliteral]
68 | pline(pfmt, Monst_name);
| ^~~~~
mkobj.c: In function 'insane_object':
mkobj.c:2848:20: warning: format not a string literal, argument types not checked [-Wformat-nonliteral]
2848 | impossible(altfmt, mesg, fmt_ptr((genericptr_t) obj), where_name(obj),
| ^~~~~~
mkobj.c:2852:20: warning: format not a string literal, argument types not checked [-Wformat-nonliteral]
2852 | objnm);
| ^~~~~
mon.c: In function 'mon_givit':
mon.c:1469:9: warning: format not a string literal, argument types not checked [-Wformat-nonliteral]
1469 | pline(msg, Monnam(mtmp));
| ^~~~~
mon.c: In function 'mondead':
mon.c:2485:33: warning: format not a string literal, argument types not checked [-Wformat-nonliteral]
2485 | | SUPPRESS_INVISIBLE), FALSE));
| ^
muse.c: In function 'mon_reflects':
muse.c:2438:13: warning: format not a string literal, argument types not checked [-Wformat-nonliteral]
2438 | pline(str, s_suffix(mon_nam(mon)), "shield");
| ^~~~~
muse.c:2445:13: warning: format not a string literal, argument types not checked [-Wformat-nonliteral]
2445 | pline(str, s_suffix(mon_nam(mon)), "weapon");
| ^~~~~
muse.c:2450:13: warning: format not a string literal, argument types not checked [-Wformat-nonliteral]
2450 | pline(str, s_suffix(mon_nam(mon)), "amulet");
| ^~~~~
muse.c:2458:13: warning: format not a string literal, argument types not checked [-Wformat-nonliteral]
2458 | pline(str, s_suffix(mon_nam(mon)), "armor");
| ^~~~~
muse.c:2464:13: warning: format not a string literal, argument types not checked [-Wformat-nonliteral]
2464 | pline(str, s_suffix(mon_nam(mon)), "scales");
| ^~~~~
muse.c: In function 'ureflects':
muse.c:2476:13: warning: format not a string literal, argument types not checked [-Wformat-nonliteral]
2476 | pline(fmt, str, "shield");
| ^~~~~
muse.c:2483:13: warning: format not a string literal, argument types not checked [-Wformat-nonliteral]
2483 | pline(fmt, str, "weapon");
| ^~~~~
muse.c:2487:13: warning: format not a string literal, argument types not checked [-Wformat-nonliteral]
2487 | pline(fmt, str, "medallion");
| ^~~~~
muse.c:2493:13: warning: format not a string literal, argument types not checked [-Wformat-nonliteral]
2493 | pline(fmt, str, uskin ? "luster" : "armor");
| ^~~~~
muse.c:2497:13: warning: format not a string literal, argument types not checked [-Wformat-nonliteral]
2497 | pline(fmt, str, "scales");
| ^~~~~
polyself.c: In function 'polyman':
polyself.c:201:5: warning: format not a string literal, argument types not checked [-Wformat-nonliteral]
201 | urgent_pline(fmt, arg);
| ^~~~~~~~~~~~
potion.c: In function 'make_hallucinated':
potion.c:423:13: warning: format not a string literal, argument types not checked [-Wformat-nonliteral]
423 | pline(message, verb);
| ^~~~~
potion.c: In function 'peffect_gain_level':
potion.c:1033:17: warning: format not a string literal, argument types not checked [-Wformat-nonliteral]
1033 | You(riseup, ceiling(u.ux, u.uy));
| ^~~
potion.c:1044:21: warning: format not a string literal, argument types not checked [-Wformat-nonliteral]
1044 | You(riseup, ceiling(u.ux, u.uy));
| ^~~
priest.c: In function 'intemple':
priest.c:487:17: warning: format not a string literal, argument types not checked [-Wformat-nonliteral]
487 | You(msg1, msg2);
| ^~~
read.c: In function 'doread':
read.c:522:9: warning: format not a string literal, argument types not checked [-Wformat-nonliteral]
522 | pline(silly_thing_to, "read");
| ^~~~~
shk.c: In function 'shk_names_obj':
shk.c:2576:15: warning: format not a string literal, argument types not checked [-Wformat-nonliteral]
2576 | pline(fmtbuf, obj_name, (obj->quan > 1L) ? "them" : "it", amt,
| ^~~~~~
shk.c:2579:9: warning: format not a string literal, argument types not checked [-Wformat-nonliteral]
2579 | You(fmt, obj_name, amt, plur(amt), arg);
| ^~~
shk.c: In function 'shk_chat':
shk.c:4506:13: warning: format not a string literal, argument types not checked [-Wformat-nonliteral]
4506 | pline(Izchak_speaks[rn2(SIZE(Izchak_speaks))], shkname(shkp));
| ^~~~~
shk.c: In function 'check_unpaid_usage':
shk.c:4633:9: warning: format not a string literal, argument types not checked [-Wformat-nonliteral]
4633 | verbalize(fmt, arg1, arg2, tmp, currency(tmp));
| ^~~~~~~~~
sounds.c: In function 'dosounds':
sounds.c:66:21: warning: format not a string literal, argument types not checked [-Wformat-nonliteral]
66 | pline(throne_msg[2], uhis());
| ^~~~~
sounds.c:259:17: warning: format not a string literal, argument types not checked [-Wformat-nonliteral]
259 | You_hear(msg, halu_gname(EPRI(mtmp)->shralign));
| ^~~~~~~~
timeout.c: In function 'choke_dialogue':
timeout.c:269:26: warning: format not a string literal, argument types not checked [-Wformat-nonliteral]
269 | body_part(NECK));
| ^~~~~~~~~
timeout.c:274:17: warning: format not a string literal, argument types not checked [-Wformat-nonliteral]
274 | urgent_pline(str, hcolor(NH_BLUE));
| ^~~~~~~~~~~~
timeout.c: In function 'levitation_dialogue':
timeout.c:339:26: warning: format not a string literal, argument types not checked [-Wformat-nonliteral]
339 | danger ? surface(u.ux, u.uy) : "air");
| ^~~~~~
timeout.c: In function 'slime_dialogue':
timeout.c:379:34: warning: format not a string literal, argument types not checked [-Wformat-nonliteral]
379 | urgent_pline(buf, hcolor(NH_GREEN));
| ^~~
timeout.c:381:30: warning: format not a string literal, argument types not checked [-Wformat-nonliteral]
381 | urgent_pline(buf, an(Hallucination ? rndmonnam(NULL)
| ^~~
uhitm.c: In function 'hmon_hitmon':
uhitm.c:1398:9: warning: format not a string literal, argument types not checked [-Wformat-nonliteral]
1398 | pline(fmt, whom);
| ^~~~~
uhitm.c:1421:9: warning: format not a string literal, argument types not checked [-Wformat-nonliteral]
1421 | pline(fmt, whom);
| ^~~~~
uhitm.c: In function 'stumble_onto_mimic':
uhitm.c:5301:9: warning: format not a string literal, argument types not checked [-Wformat-nonliteral]
5301 | pline(fmt, what);
| ^~~~~
../win/tty/wintty.c: In function 'tty_clear_nhwindow':
../win/tty/wintty.c:1649:15: warning: format not a string literal, argument types not checked [-Wformat-nonliteral]
1649 | panic(winpanicstr, window);
| ^~~~~~~~~~~
../win/tty/wintty.c: In function 'tty_display_nhwindow':
../win/tty/wintty.c:2339:15: warning: format not a string literal, argument types not checked [-Wformat-nonliteral]
2339 | panic(winpanicstr, window);
| ^~~~~~~~~~~
../win/tty/wintty.c: In function 'tty_dismiss_nhwindow':
../win/tty/wintty.c:2432:15: warning: format not a string literal, argument types not checked [-Wformat-nonliteral]
2432 | panic(winpanicstr, window);
| ^~~~~~~~~~~
../win/tty/wintty.c: In function 'tty_destroy_nhwindow':
../win/tty/wintty.c:2477:15: warning: format not a string literal, argument types not checked [-Wformat-nonliteral]
2477 | panic(winpanicstr, window);
| ^~~~~~~~~~~
../win/tty/wintty.c: In function 'tty_curs':
../win/tty/wintty.c:2503:15: warning: format not a string literal, argument types not checked [-Wformat-nonliteral]
2503 | panic(winpanicstr, window);
| ^~~~~~~~~~~
../win/tty/wintty.c: In function 'tty_putsym':
../win/tty/wintty.c:2599:15: warning: format not a string literal, argument types not checked [-Wformat-nonliteral]
2599 | panic(winpanicstr, window);
| ^~~~~~~~~~~
../win/tty/wintty.c: In function 'tty_add_menu':
../win/tty/wintty.c:2967:15: warning: format not a string literal, argument types not checked [-Wformat-nonliteral]
2967 | panic(winpanicstr, window);
| ^~~~~~~~~~~
../win/tty/wintty.c: In function 'tty_end_menu':
../win/tty/wintty.c:3032:15: warning: format not a string literal, argument types not checked [-Wformat-nonliteral]
3032 | panic(winpanicstr, window);
| ^~~~~~~~~~~
../win/tty/wintty.c: In function 'tty_select_menu':
../win/tty/wintty.c:3140:15: warning: format not a string literal, argument types not checked [-Wformat-nonliteral]
3140 | panic(winpanicstr, window);
| ^~~~~~~~~~~
Instead of returning ECMD_OK, the commands now return ECMD_CANCEL
when user declined to pick a direction or an object to act on.
Note that this can be ORed with ECMD_TIME, if the command still
took a turn.
For now this has no gameplay meaning.
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.
It's redundant with g.moves, so there is no more need for it.
Way, way back, it looks like g.moves and g.monstermoves can and did
desync, where g.moves would track the amount of moves the player had
gotten (and would therefore increase faster if the player were hasted)
and g.monstermoves would track the amount of monster move cycles, aka
turns. But this has not been the case for a long time, and they both
increment together in the same location in allmain.c. There are no
longer any cases where they will not be the same value.
This is a save-breaking change because it changes struct
instance_globals, but I have not updated the editlevel in this commit.
Apply visibility fixups for monsters triggering door trap
explosions or digging through doors similar to the monster-opens-
door-handling from a couple of days. Again, the issue is that
hero/player can see a closed door in situations where they can't
see an open one, and messages about the door being opened or
destroyed need to take that into account when seeing a closed
door go away.
Not as thoroughly tested as monster just opening closed door.
Use ansimpleoname() instead of doname() to describe the key or
lock pick or credit card when reporting "You can't fix a chest's
broken lock with a <foo>." doname() includes BUC status when
known and feedback mentioning a particular bless/curse state on
the tool that can't be used to fix the lock suggests that some
other bless/curse state might be viable.
Apply makes a touch_artifact check on the tool being applied, but
autounlock would pick an unlocking tool to use without doing that.
Noticed while fixing that: autounlock took no time.
Since picking an artifact unlocking tool might now blast the hero,
change the tool selection. First choice: any key except another
role's quest artifact; second: any lock-pick except another role's
quest artifact; third: any credit card except another role's quest
artifact; fourth, fifth, sixth: other roles' quest artifact key,
lock-pick, or credit card. The fifth category (artifact lock-picks)
is empty. Rogues will pick non-cursed Master Key over any other
key (special case for first choice). Tourists will pick a key or
a lock-pick over their PYEC (first and second choices over third).
Some new code was using 3.4.3 era formatting (operators at end of
first half of a continued line rather than at start of second half).
Also a few cases of 'g.' prefix making lines be too wide. I imagine
there will be a lot more of these over time.