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.
My earlier change resulted in rejecting all commands entered after
a movement prefix key, rather than just ones that aren't supposed to
take any prefix.
This fixes that and also restores the ability to use 'm>' or 'm<' on
stairs to change levels without auto-pickup at the destination.
The wall of water goaded me into updating waterbody_name(). It's
mostly the same, aside from being moved from mkmaze.c to pager.c and
adding "{wall of|limitless} water" instead of plain "water" for WATER
terrain. I'm not very happy with "limitless" for the Plane of Water
because limits imposed by air bubbles are all over the place. "Wall
of water" might work ok for that level.
Water on Medusa's level is now described as "shallow sea" rather than
lame "water". The two unusual pools on the Samurai home level are
described as "pond" rather than previous "water" which replaced 3.6's
ridiculous "moat". When lava is hallucinated, it is described as
"molten <substance>" (yielding silly things like "molten yoghurt"),
rather than just "<substance>" to distinguish it from hallucinated
water. 'autodescribe' doesn't use waterbody_name() though.
Another gold dragon scales/mail issue, reported bu vultur-cadens:
reading a cursed scroll of light extinguishes carried light sources
except for wielded Sunsword and worn gold dragon scales/mail; there
was a special message for Sunsword (preventing the hero from being in
darkness) but no such message for gold dragon scales/mail. Replace
the special message with a more generic one applicable to both cases.
Also, implement the suggestion that cursed light degrade the amount
of light being emitted (which varies by bless/curse state) for those
two cases. Sunsword has a 75% chance to resist, gold dragon scales
25% chance. And add the inverse: blessed scroll of light might
increase the amount of light by improving their bless/curse state.
The resistance check applies here too and isn't inverted; Sunsword
is still fairly likely to resist.
Uncursed scroll of light, spell of light regardless of skill, zapped
or broken wand of light have so such effect.
Closes#666
... you will also get a message when a seen stinking cloud
or the one surrounding the hero dissipates.
Original feature comes from Fourk, but this version (with some
minor changes) comes from xnethack by copperwater <aosdict@gmail.com>
The extended command input prompt was behaving in an unintended way:
Typing #a<enter> executed #adjust. Spaces in the entry prevented matching
any command. No error message was given when no command was matched.
Fix all of those, so it behaves more like the tty.
Clean up the tty, curses, and X11 windowport code, so they don't use
the extcmdlist array directly, but query with extcmds_match
and extcmds_getentry.
When rest_on_space is On, assign same function as for #wait to the
<space> key. When Off, set that key to Null instead. Binding some
other command to <space> when rest_on_space is Off doesn't work but
I would classify that as something to be discouraged anyway.
Changes most of the special keys used in the main input loop
into extended commands:
- movement keys are now bound to extended commands, eg.
#movewest and so on.
- m-prefix is now #reqmenu extended command, still bound to
the 'm' key.
- run, rush, and fight are now extended commands, still bound
to the same keys as previously.
- nopickup and runnopickup keys are removed.
Nopickup was using 'm' key, the same as the m-prefix, so
allow #reqmenu to modify movement commands to disable pickup.
- multiple prefix commands are allowed. This lets user to
use #reqmenu, followed by #run, followed by movement to simulate
runnopickup behaviour. (If necessary, adding runnopickup back
as an extended command would be easy)
... instead of hard-coding them to 50. New allocated value is
(COLNO*ROWNO)/30, which is slightly higher (56), and that formula
seems to work for hypothetical larger maps too.
Wield a polearm and use 'f'ire to automatically hit with it,
if there's a single valid target.
With fireassist-option, will swapweapon to a polearm.
This only applies if quiver is empty and autoquiver is off.
Special abilities conferred by wearing dragon armor was implemented in
a somewhat half-assed fashion; extend it to 3/4-assed. Abilities came
from wearing dragon armor but not from being poly'd into a dragon or
for monsters that were wearing dragon armor or actually were dragons.
This covers much of that.
There are umpteen calls of 'resists_foo(mon)' and some are now
'resists_foo(mon) || defended(mon, AD_FOO)' but the second part ought
to be incorporated into update_mon_intrinics() so that the extra
'|| defended()' doesn't have to be spread all over the place and the
ones being put in now could/should be removed.
While testing, I noticed that a monster wielding Fire Brand did not
resist being hit by a wand of fire. This fixes that and should also
fix various comparable situations for other artifacts. But so far it
has only been done for zapping (and any other actions which use the
zapping code). Folding defended() checks into update_mon_intrinsics()
matters more than that probably sounds.
When testing the urgent message for having weapon be snagged by a
bullwhip, in between the occasional weapon grabs (which mention
flicking the bullwhip) I saw lots of regular attacks that said
"<mon> swings his bullwhip." That is accurate but seems odd, so
change it to "<mon> lashes his bullwhip." Do same for the hero.
While working on that, I discovered that monsters using a polearm
for a ranged attack always showed "<mon> thrusts <a polearm>" even
for ones that aren't defined as piercing so should be swung rather
that thrust. And they're allowed to do that when adjacent where
there isn't enough room to thrust or swing a long polearm. Now it's
"<mon> bashes with <a polearm>" in that situation.
When shortening/splitting wide lines I noticed that the save and
restore code for regions had a bunch of those and they could be
shortened by using an intermediate variable. Easier to read too.
Also, change several 'unsigned int' to just 'unsigned' as is used in
most of the rest of the code.
At one point I omitted a (genericptr_t) cast (which should no longer
be necessary...) and discovered that bwrite() wasn't declaring the
input buffer it never modifies as 'const'.
If you have a function named like that, and it goes and
changes the monster state, that's just wrong.
Move waking up the monster from the hit into separate function.
Teleporting a monster only updated the map. Give a message
so blind players can get the same information.
Making a monster invisible gives the same message, if you
cannot detect invisible.
Several other places where monsters teleported themselves
now also give the same message.
Reported by entrez: applying a bullwhip towards a medium or small
peaceful monster used to be an attack but that stopped working when
'safepet' was extended to peacefuls in order for the hero to be able
to swap places which those. Also, side-effects were different when
hero applied the whip from within a pit compared to when not in one.
This allows the hero trapped in a pit to try to snag furniture or a
boulder even when a small or medium is present, and escaping that
pit if successful. (It still snags big monsters in preference to
furniture/boulder at their location.) When no such non-monster
target is available, it attacks the monster if hostile or peaceful
but not when tame. When revealing a previously unseen monster it
prevents snagging that monster's wielded weapon because hero couldn't
possibly target the weapon in that situation.
This makes other changes, mostly dealing with finding and exposing
concealed monsters, which may introduce some new bugs.
Since I was already in the right place, implement snagging an item
off the floor while flying. It isn't necessary since a flyer can
pick things up off the floor directly, but there isn't any pressing
reason to disallow it. Supersedes the commit in pull request #632
by RojjaCebolla.
Closes#632
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.
We've had a few pull requests fixing format/argument mismatches
lately. I did't notice when PRINTF_F(format_index,first_arg_index)
attribute use and the checking gcc and clang do with it got removed,
but that was very useful. Putting it back triggers a whole bunch
of "format string is not literal" warnings, but that's because
'-Wformat-nonliteral' was explicitly added to the *.2020 hints.
Checking pline/You/&c arguments in the cases where the format is a
literal is more valuable than the complaints for sprintf being fed
a generated format, so reinstate PRINTF_F usage and turn off the
check for non-literal format strings.
Function the() wasn't supposed to be used for monsters because many
of the ones with capitalized names confuse it, but over time multiple
instances of the(mon_nam()) have crept into the code. Instead of
ripping those out, modify the() to handle that situation better.
Pull request #636 by entrez dealt with this with one extra line of
code, but could end up scanning all the names in mons[] repeatedly
if the("Capitalized string") gets called a lot. This uses a similar
one line fix but calls a whole new routine that scans through mons[]
once collecting all the relevant special case names. As a bonus,
it does the same for hallucinatory monster names which name_to_mon()
couldn't handle.
Fixes#626
Incorporate the functionality of the loadable DLL's (nhraykey.dll,
nhdefkey.dll, and nh340key.dll) into the consoletty.c code and
remove the dll building
Globs never rotted away but did become tainted after a relatively
short while, which seemed like a contradiction. Change them to never
be tainted but shrink by 1 unit of weight approximately every 25
turns. An ordinary glob (one that hasn't combined with any others)
starts out weighing 20 units, so it takes about 500 turns to vanish.
That's roughly twice as long as a corpse takes to rot away.
Shrinking globs give feedback when in hero's invent or in a container
in hero's inventory, but rarely (when going from an exact multiple
of 20 weight units; that is, from integral number of N globs to
N-1 + 19/20, or if weight reduction triggers an encumbrance change).
When a glob goes away completely, there is feedback for those two
circumstances and also for seeing the glob vanish from the floor.
I haven't touched how much nutrition eating a glob confers. I have
changed formatting of glob names to use "small", "medium", "large",
"very large" instead of "small", [no adjective], "large", &c. You
still need to have at least five globs coalesced together for the
adjective to become "medium", same amount as before.
I don't think EDITLEVEL needs to be modified but have incremented it
anyway to play things safe.
I thought there were more places that checked for "it" and substituted
"someone" or "something". Perhaps there are and I'm just not finding
them now. Anyway, this extends x_monnam() and adds some_mon_nam() and
Some_Monnam() to do that during monster name formatting instead of
having various bits of code try fix it up after the fact. The fixups
could be fooled by monsters given the name "it" or "It"; x_monnam()
won't be.
Reported by entrez, wielding something fragile (potion of acid
perhaps), and using F to smash it against iron bars called breaktest()
directly, then a second time indirectly through hero_breaks() via
hit_bars(). There is a random chance to resist breaking (99% for
artifacts, 1% for other items) so breaktest() might say that something
will break on the first call and that it will not break on the second
call, or vice versa. That could remove uwep from inventory then leave
it in limbo without destroying it, or destroy uwep without removing it
from inventory first triggering impossible "obfree: deleting worn obj".
Reported directly to devteam by entrez via email:
>
> I noticed some potential issues with (melting) ice:
>
> * Digging down into ice, or setting a land mine on the ice and
> triggering it, doesn't remove the melt_ice timeout, so it can result
> in a sequence like dig down -> pit fills with water -> freeze water
> -> freezing water tries to set melt_ice timeout -> duplicate timeout
> impossible. Or if you don't freeze the water again, melt_ice will
> run on a non-ice surface, which might at least produce strange
> messages.
>
> * Setting a land mine on ice: melting ice doesn't do anything with
> the trap, so there is still a land mine which you can trigger by
> flying over the water (the land mine's trigger is also still
> described as being 'in a pile of soil', despite being underwater at
> this point). Similar thing happens with bear traps.
>
> * Not really related to _melting_ ice, but an exploding land mine
> doesn't reset the typ from ICE to FLOOR (like normal digging does),
> so it will result in a square with a pit that is also an ice square,
> where the ice can melt under the pit and produce a combination
> pit/moat. If you then freeze the moat, the pit reappears on top of
> the ice.
Fix the vault repair issue that could lead to "wall_angle: unknown"
warning. Unlike shop repair, the original wall info isn't available
so this recreates it. The extra 'flags' field added yesterday could
be eliminated but this leaves it in place.
Fixes#606
for helm of opposite alignment.
Discovered and described by vultur-cadens.
The #adjust command can be used to split an object stack and if the
shop price of the two halves are different, the new stack will have
its obj->o_id modified to make the prices the same. That could be
used to tip off the player as to what the low bits of the next o_id
will be. Since no time passes, no intervening activity such as
random creation of a new monster can take place, so the player could
wish for something that depends on o_id with some degree of control.
Matters mainly for helms of opposite alignment intended to be used
by neutral characters since the player isn't supposed to be able to
control that. (Other items like T-shirt slogan text and candy bar
wrapper text had a similar issue but controlling those wouldn't have
had any tangible difference on play.)
The issue writeup suggested allowing the player to specify a helm's
alignment during a wish. That would defeat the purpose of having
o_id affect the helm's behavior in an arbitrary but repeatable way
so is rejected.
I implemented this fix before seeing a followup comment that suggests
using a more sophisticated decision than 'obj->o_id % N' for the
arbitrary effect. This just increments context.ident for the next
obj->o_id or mon->m_id by 1 or 2 instead of always by 1 and should
be adequate. It also has the side-effect that two consecutive wishes
for helm of opposite alignment won't necessary give one for each of
the two possible 'polarities', even with no intervening activity by
monsters, reinforcing the lack of player control.
Minor bonus fix: it moves the incrementing check for wrap-to-0 into
a single place instead of replicating that half a dozen times. Ones
that should have been there for shop billing and for objects loaded
from bones files were missing.
Fixes#596
The gas will expand from its chosen center point via breadth-first
search instead of hardcoding a diagonal shape. The search is performed
with a randomized list of directions, and has 50% chance of not spreading
to a space it otherwise would have spread to. This has the effect of fuzzing
the cloud edges in open areas, helping the clouds on, for instance,
the Plane of Fire not be big rhombuses.
Also some other code refactoring related to stinking clouds in read.c
This comes from xNetHack by copperwater <aosdict@gmail.com>
The walls for the mines, gehennom, knox, and sokoban had been
changed at the "tile"-level, with no awareness of the core game,
or non-tile interfaces.
- Expand the glyphs to include a set of walls for the main level
as well as each of those mentioned above.
Altars had been adjusted at the map_glyphinfo() level to substitute
some color variations on-the-fly for unaligned, chaotic, neutral,
lawful altars, and shrines. The tile interface had no awareness of
the feature.
- Expand the glyphs to include each of the altar variations that
had been implemented in the display code for tty-only. This required
the addition of four placeholder tiles in other.txt. Someone with
artistic skill will hopefully alter the additional tiles to better
reflect their intended purpose.
Explosions had unique tiles in the tile window port, and the display
code for tty tinkered with the colors, but the game had very little
awareness of the different types of explosions.
- Expand the glyphs to include each of the explosion types: dark,
noxious, muddy, wet, magical, fiery and frosty.
Pile-markers to represent a pile had been introduced at the
display-level, without little to no awareness by the core game.
- Expand the glyphs to include piletops, including objects,
bodys, and statues.
Recently male and female variations of tiles and monsters had been
had been introduced, but the mechanics had been mostly done at the
display-level through a marker flag. The window port interface then
had to increment the tile mapped to the glyph to get the female version
of the tile.
- Expand the glyphs to include the male and female versions of the
monsters, and their corresponding pet versions, ridden, detected
versions and statues of them.
Direct references to GLYPH_BODY_OFF and GLYPH_STATUE_OFF
in object_from_map() in pager.c were getting incomplete results.
- Add macros glyph_to_body_corpsenm(glyph) and
glyph_to_statue_corpsenm(glyph) macros for obtaining the corpsenm
value after passing the glyph_is_body() or glyph_is_statue() test.
Other relevant notes:
- The tile ordering in the win/share/*.txt tile files has been altered,
other.txt in particular.
- tilemap.c has had a lot of alterations to accommodate the expanded
glyphs. Output that is useful for troubleshooting will end up in
tilemappings.lst if OBTAIN_TILEMAP is defined during build.
It lists all of the glyphs and which tile it gets mapped to, and also
lists each tile and some of the references to it by various glyphs.
- An array glyphmap[MAXGLYPH] is now used. It has an entry for each
glyph, ordered by glyph, and once reset_glyphs(glyph) has been run, it
contains the mapped symindex, default color, glyphflags, and tile
index.
If USE_TILES is defined during build, the tile.c produced from the
tilemap utility populates the tileidx field of each array element with
a glyph-to-tile mapping for the glyph. Later on, when reset_glyphmap()
is run, the other fields of each element will get populated.
- The glyph-to-tile mapping is an added field available to a window
port via the glyphinfo struct passed in the documented interface. The
old glyph2tile[] array is gone. The various active window ports that
had been using glyph2tile[] have been updated to use the new interface
mechanism. Disclaimer: There may be some bug fixing or tidying
required in the window port code.
- reset_glyphmap() is called after config file options parsing
has finished, because some config file settings can impact the results
produced by reset_glyphmap().
- Everything that passes the glyph_is_cmap(glyph) test must
return a valid cmap value from glyph_to_cmap(glyph).
- An 'extern glyph_info glyphmap[MAX_GLYPH];' is inserted into the
top of only the files which need awareness of it, not inserted into
display.h. Presently, the only files that actually need to directly
reference the glyphmap[] array are display.c, o_init.c (for shuffling
the tiles), and the generated tile.c (if USE_TILES is defined).
- Added an MG_MALE glyphflag to complement the MG_FEMALE glyphflag.
- Provide an array for wall colorizations. reset_glyphmap() will draw
the colors from this array: int array wallcolors[sokoban_walls + 1];
The indices of the wallcolors array are main_walls (0), mines_walls
(1), gehennom_walls (2), knox_walls (3), and sokoban_walls (4).
In future, a config file option for adjusting the wall colors and/or
an 'O' option menu to do the same could be added. Right now, the
initializaton of the wallcolors[] array entries in display.c leaves the
walls at CLR_GRAY, matching the defsym color.
- Most of the display-level kludges for some of the on-the-fly
interface features have been removed from map_glyphinfo() as they
aren't needed any longer. These glyph expansions adhere more closely to
the original glyph mechanics of the game.
- Because the glyphs are re-ordered and expanded, an update to
editlevel will be required upon merge of these changes.
When using a menu to drop or put in items into a container,
allow putting in the item (or items) you picked up previously,
by selecting the 'P' entry from the item class menu
Inspired by the itemcat patch by Stanislav Traykov.
Invalidates saves and bones.
Reported and diagnosed by entrez:
"The <mon> yanks <two-handed weapon> from your corpses!"
It became unwielded and that triggered a perm_invent update and
such updates reformat entire inventory, so if that contains a dozen
or more items it will use all the obuf[] static buffers as least
once. In this case, the bullwhip code had plural of "hand" in one
of those buffers and by the time it delivered the message which
used that, the value had been clobbered.
As the diagnosis mentioned, it can be tricky to reproduce since
either &obuf[0] or &obuf[PREFIX] might be used and if the value
being clobbered didn't overlap, the effect wasn't noticeable.
Instead of fixing the bullwhip message, this changes inventory
display so that it should no longer churn through all the buffers.
It also adds a fixes entry for #K3401, which was already fixed for
3.7 but I hadn't been able to reproduce it for 3.6.x (which I now
blame on the PREFIX trickiness).
triggered by Grayswandir's hallucination resistance. If the game
is saved while hero is hallucinating but having that be suppressed
by wielding Grayswandir, is riding, and the steed is on an object,
then during restore the hero's location will be updated because
of the presence of the object but the attempt to display the hero
there is made before u.usteed has been restored and fails.
When discussing the recent commit that removed makedefs -o from the
build process, nhmall pointed out that a sanity check ensuring all
objects within one class add up to 1000 probability had been removed as
well. This requirement was a perennial thorn in the side for anyone
doing anything that touches object probabilities, because allocating
probability to something meant deciding what to take it away from,
without a good way to evenly distribute that across all the other
members of the object class.
I had gotten around this in xNetHack by removing the sanity check and
making mkobj() total up the probability within an object class and then
using that instead of 1000. This commit takes a similar approach, but
instead of inefficiently recalculating the sum every time mkobj() is
called, it instead computes it at the start of the game or when
restoring the save file and stores it in a global variable.
This fixes a slight bias problem with rings - they are all supposed to
be of equal probability, but there are 28 of them and 1000 is not evenly
divisible by that, so the old formula made the later rings slightly more
likely. Now instead of a 35/1000 or 36/1000 chance, they are all
uniformly 1/28. (Internally they have a oc_prob of 1 now, not 0).
Gems are also weird, because their oc_prob values change every level.
This ought to have still worked without a change, because the arcane
formula for assigning the probabilities would still end up with them
adding to 1000. But I added in code to reset the total gem probability
anyway; this may help make the formula less arcane in the future.
There is still a sanity check against object classes having a nonzero
number of objects but zero total probability, in which case an
impossible will be thrown and every member of the class will be given
equal probability. I also downgraded the "probtype error" panic in
mkobj() to an impossible because it has a reasonable failure case -
return the first item in that class.
The code has been assuming that time_t is some number of seconds.
That's valid for traditional Unix systems and for Posix compliant
systems but is not something guaranteed by the C standard. (We ran
into a long time ago when trying out an alternate way to calculate
phase of moon. That code made a similar assumption and broke one
of the ports.)
'ubirthday' also warrants being re-done but I've run out of energy.
even when protection from shape changers is in effect. I'm not sure
why mimicking other things doesn't trigger the same sanity check
warning. This fix works for the strange object case and I assume
that it doesn't break the more general case.
When investigating, I noticed that save and restore (even leaving
the level and then returning) causes cancelled shape changers to be
uncancelled. Treat being cancelled similarly to having to having
protection from shape changers in effect: shape changer is forced
to revert to its innate form and not allowed to change shape.
This evolves and hopefully eases the game-build requirements by
removing game-compile dependencies on any header files generated
by the makedefs utility, including:
date.h dependency and its inclusion is removed and comparable functionality
is produced at runtime via new file src/date.c.
pm.h dependency and its inclusion is removed and comparable functionality is
produced by moving the monster definitions from monst.c into new header
file called monsters.h and altering them slightly. The former pm.h header
file #define PM_ values are now replaced with appropriate emitted enum
entries during the compiler preprocessing.
onames.h dependency and its inclusion is removed and comparable functionality
is produced by moving the object definitions from objects.c into new header
file called objects.h and altering them slightly. The former onames.h header
file #define values are now replaced with appropriate emitted enum entries
during the compiler preprocessing.
artilist.h has been slightly altered, and the former onames.h artifact-related
header file #define ART_ values are now replaced with appropriate emitted enum
entries during the compiler preprocessing.
makedefs can still produce date.h (makedefs -v), pm.h (makedefs -p), and
onames.h (makedefs -o) for reference purposes. They won't be used during
the compiler.
The other uses for makedefs remain. They are used to prepare external
file content that the game utilizes, not prerequisite code for the
compile:
makedefs -d (database)
makedefs -r (rumors)
makedefs -h (oracles)
makedefs -s (epitaphs, engravings, bogusmons)
date.c
Pull the code for date/time stamping from mdlib.c into date.c.
Set date.o to be dependent on source files, header files, and .o files
so that date.o is rebuilt from date.c when any of those changes, thus
ensuring an accurate date/time stamp. It also includes git sha
functionality formerly done by makedefs writing #define directives
into include/date.h. For unix it passes the git info on
the compile line for date.c (via sys/unix/hints/linux.2020, macOS.2020)
nethack --dumpenums (optional, but on by default)
Allow developer to obtain some internal enum values from NetHack
without having to resort to an external utility such as
makedefs.
Uncomment #define NODUMPENUMS in config.h to disable this.
The updates to sys/windows/Makefile.gcc have not been tested yet.
..\src\explode.c(884): warning C4028: formal parameter 1 different from declaration
That one stems from commit 6b60618e0e.
Adjust the prototype in include/extern.h to match the function definition in
src/explode.c
Also, a recent update to the Microsoft Visual Studio 2019 causes the
compiler to complain while compiling a vendor c++ header (string) if
warning C4774 is enabled.
We force that warning to be enabled during the Makefile build, even though
it is not enabled by default.
Only do so in the Makefile.msc for c source files, and not for c++
(sys/share/cppregex.cpp).
See below for an example of the compiler complaint.
cppregex.cpp
C:\Program Files (x86)\Microsoft Visual
Studio\2017\Community\VC\Tools\MSVC\14.16.27023\include\string(530):
warning C4774: '_scprintf' : format string expected in argument 1 is
not a string literal
C:\Program Files (x86)\Microsoft Visual
Studio\2017\Community\VC\Tools\MSVC\14.16.27023\include\string(530):
note: e.g. instead of printf(name); use printf("%s", name); because
format specifiers in 'name' may pose a security issue
C:\Program Files (x86)\Microsoft Visual
Studio\2017\Community\VC\Tools\MSVC\14.16.27023\include\string(530):
note: consider using constexpr specifier for named string literals
C:\Program Files (x86)\Microsoft Visual
Studio\2017\Community\VC\Tools\MSVC\14.16.27023\include\string(583):
note: see reference to function template instantiation 'std::string
std::_Floating_to_string<float>(const char *,_Ty)' being compiled
with
[
_Ty=float
]