Merge branch 'NetHack-3.7' into twitch-interact

This commit is contained in:
2026-04-23 20:37:34 -07:00
22 changed files with 270 additions and 142 deletions

View File

@@ -803,26 +803,151 @@ start: MACgraphics
S_pool: \xe0 S_pool: \xe0
finish finish
# When using Unicode glyphs, care must be taken with how terminals
# render them and how completely fonts cover them.
#
# Depending on the font, terminal, and operating system, unsupported
# glyphs may be replaced by placeholder symbols (e.g. <20> U+FFFD
# replacement character or □ U+25A1 white square), omitted entirely, or
# substituted from fallback fonts. Such fallback can introduce visual
# inconsistencies due to differences in style, metrics, or alignment.
#
# Support for glyphs defined in the Windows Glyph List 4
# (https://en.wikipedia.org/wiki/WGL4) is generally good across common
# fonts and platforms. Beyond that baseline, coverage becomes less
# predictable and should be evaluated case by case.
#
# Emoji support often is problematic, and wide glyphs occupy two display
# columns, which NetHack does not support.
#
# Symset Enhanced1 should be considered the conservative Unicode symset,
# while Enhanced2 (and any future symsets) may make use of more advanced
# Unicode features.
start: Enhanced1 start: Enhanced1
Description: Enhanced with Unicode glyphs and 24-bit color Description: Enhanced with Unicode glyphs and 24-bit color
Restrictions: primary Restrictions: primary
Handling: UTF8 Handling: UTF8
S_vwall: U+2502 # BOX DRAWINGS LIGHT VERTICAL S_corr: U+2591 # ░ LIGHT SHADE
S_hwall: U+2500 # BOX DRAWINGS LIGHT HORIZONTAL S_engrcorr: U+2591 # ░ LIGHT SHADE
S_tlcorn: U+250c # BOX DRAWINGS LIGHT DOWN AND RIGHT S_litcorr: U+2592 # ▒ MEDIUM SHADE
S_trcorn: U+2510 # BOX DRAWINGS LIGHT DOWN AND LEFT S_vwall: U+2502 # │ BOX DRAWINGS LIGHT VERTICAL
S_blcorn: U+2514 # BOX DRAWINGS LIGHT UP AND RIGHT S_hwall: U+2500 # BOX DRAWINGS LIGHT HORIZONTAL
S_brcorn: U+2518 # BOX DRAWINGS LIGHT UP AND LEFT S_tlcorn: U+250c # BOX DRAWINGS LIGHT DOWN AND RIGHT
S_crwall: U+253c # BOX DRAWINGS LIGHT VERTICAL AND HORIZONTAL S_trcorn: U+2510 # BOX DRAWINGS LIGHT DOWN AND LEFT
S_tuwall: U+2534 # BOX DRAWINGS LIGHT UP AND HORIZONTAL S_blcorn: U+2514 # BOX DRAWINGS LIGHT UP AND RIGHT
S_tdwall: U+252c # BOX DRAWINGS LIGHT DOWN AND HORIZONTAL S_brcorn: U+2518 # BOX DRAWINGS LIGHT UP AND LEFT
S_tlwall: U+2524 # BOX DRAWINGS LIGHT VERTICAL AND LEFT S_crwall: U+253c # BOX DRAWINGS LIGHT VERTICAL AND HORIZONTAL
S_trwall: U+251c # BOX DRAWINGS LIGHT VERTICAL AND RIGHT S_tuwall: U+2534 # BOX DRAWINGS LIGHT UP AND HORIZONTAL
S_tdwall: U+252c # ┬ BOX DRAWINGS LIGHT DOWN AND HORIZONTAL
S_tlwall: U+2524 # ┤ BOX DRAWINGS LIGHT VERTICAL AND LEFT
S_trwall: U+251c # ├ BOX DRAWINGS LIGHT VERTICAL AND RIGHT
S_ndoor: U+00b7 # · MIDDLE DOT
S_vodoor: U+2592 # ▒ MEDIUM SHADE
S_hodoor: U+2592 # ▒ MEDIUM SHADE
S_bars: U+2261 # ≡ IDENTICAL TO
S_tree: U+03a8 # Ψ GREEK CAPITAL LETTER PSI
S_room: U+00b7 # · MIDDLE DOT
S_engroom: U+03BE # ξ Greek Small Letter Xi
S_darkroom: U+00b7 # · MIDDLE DOT
S_upladder: U+2264 # ≤ LESS-THAN OR EQUAL TO
S_dnladder: U+2265 # ≥ GREATER-THAN OR EQUAL TO
S_altar: U+03A9 # Ω GREEK CAPITAL LETTER OMEGA
S_grave: U+2020 # † DAGGER
G_fountain: U+2320/0-150-255 # ⌠ TOP HALF INTEGRAL
S_pool: U+224b # ≋ TRIPLE TILDE
S_ice: U+00b7 # · MIDDLE DOT
S_lava: U+224b # ≋ TRIPLE TILDE
S_lavawall: U+2248 # ≈ ALMOST EQUAL TO
S_vodbridge: U+00b7 # · MIDDLE DOT
S_hodbridge: U+00b7 # · MIDDLE DOT
S_water: U+2248 # ≈ ALMOST EQUAL TO
S_web: U+00A4 # ¤ CURRENCY SIGN
S_vbeam: U+2502 # │ BOX DRAWINGS LIGHT VERTICAL
S_hbeam: U+2500 # ─ BOX DRAWINGS LIGHT HORIZONTAL
S_sw_tc: U+2594 # ▔ UPPER ONE EIGHTH BLOCK
S_sw_ml: U+258f # ▏ LEFT ONE EIGHTH BLOCK
S_sw_mr: U+2595 # ▕ RIGHT ONE EIGHTH BLOCK
S_sw_bc: U+2581 # LOWER ONE EIGHTH BLOCK
S_expl_tc: U+2594 # ▔ UPPER ONE EIGHTH BLOCK
S_expl_ml: U+258f # ▏ LEFT ONE EIGHTH BLOCK
S_expl_mr: U+2595 # ▕ RIGHT ONE EIGHTH BLOCK
S_expl_bc: U+2581 # LOWER ONE EIGHTH BLOCK
G_vwall_sokoban: U+2502/blue # │ BOX DRAWINGS LIGHT VERTICAL
G_hwall_sokoban: U+2500/blue # ─ BOX DRAWINGS LIGHT HORIZONTAL
G_tlcorn_sokoban: U+250c/blue # ┌ BOX DRAWINGS LIGHT DOWN AND RIGHT
G_trcorn_sokoban: U+2510/blue # ┐ BOX DRAWINGS LIGHT DOWN AND LEFT
G_blcorn_sokoban: U+2514/blue # └ BOX DRAWINGS LIGHT UP AND RIGHT
G_brcorn_sokoban: U+2518/blue # ┘ BOX DRAWINGS LIGHT UP AND LEFT
G_crwall_sokoban: U+253C/blue # ┼ BOX DRAWINGS LIGHT VERTICAL AND HORIZONTAL
G_tuwall_sokoban: U+2534/blue # ┴ BOX DRAWINGS LIGHT UP AND HORIZONTAL
G_tdwall_sokoban: U+252C/blue # ┬ BOX DRAWINGS LIGHT DOWN AND HORIZONTAL
G_tlwall_sokoban: U+2524/blue # ┤ BOX DRAWINGS LIGHT VERTICAL AND LEFT
G_trwall_sokoban: U+251C/blue # ├ BOX DRAWINGS LIGHT VERTICAL AND RIGHT
G_vwall_gehennom: U+2502/red # │ BOX DRAWINGS LIGHT VERTICAL
G_hwall_gehennom: U+2500/red # ─ BOX DRAWINGS LIGHT HORIZONTAL
G_tlcorn_gehennom: U+250c/red # ┌ BOX DRAWINGS LIGHT DOWN AND RIGHT
G_trcorn_gehennom: U+2510/red # ┐ BOX DRAWINGS LIGHT DOWN AND LEFT
G_blcorn_gehennom: U+2514/red # └ BOX DRAWINGS LIGHT UP AND RIGHT
G_brcorn_gehennom: U+2518/red # ┘ BOX DRAWINGS LIGHT UP AND LEFT
G_crwall_gehennom: U+253C/red # ┼ BOX DRAWINGS LIGHT VERTICAL AND HORIZONTAL
G_tuwall_gehennom: U+2534/red # ┴ BOX DRAWINGS LIGHT UP AND HORIZONTAL
G_tdwall_gehennom: U+252C/red # ┬ BOX DRAWINGS LIGHT DOWN AND HORIZONTAL
G_tlwall_gehennom: U+2524/red # ┤ BOX DRAWINGS LIGHT VERTICAL AND LEFT
G_trwall_gehennom: U+251C/red # ├ BOX DRAWINGS LIGHT VERTICAL AND RIGHT
G_vwall_knox: U+2502/150-75-0 # │ BOX DRAWINGS LIGHT VERTICAL
G_hwall_knox: U+2500/150-75-0 # ─ BOX DRAWINGS LIGHT HORIZONTAL
G_tlcorn_knox: U+250c/150-75-0 # ┌ BOX DRAWINGS LIGHT DOWN AND RIGHT
G_trcorn_knox: U+2510/150-75-0 # ┐ BOX DRAWINGS LIGHT DOWN AND LEFT
G_blcorn_knox: U+2514/150-75-0 # └ BOX DRAWINGS LIGHT UP AND RIGHT
G_brcorn_knox: U+2518/150-75-0 # ┘ BOX DRAWINGS LIGHT UP AND LEFT
G_crwall_knox: U+253C/150-75-0 # ┼ BOX DRAWINGS LIGHT VERTICAL AND HORIZONTAL
G_tuwall_knox: U+2534/150-75-0 # ┴ BOX DRAWINGS LIGHT UP AND HORIZONTAL
G_tdwall_knox: U+252C/150-75-0 # ┬ BOX DRAWINGS LIGHT DOWN AND HORIZONTAL
G_tlwall_knox: U+2524/150-75-0 # ┤ BOX DRAWINGS LIGHT VERTICAL AND LEFT
G_trwall_knox: U+251C/150-75-0 # ├ BOX DRAWINGS LIGHT VERTICAL AND RIGHT
G_vwall_mines: U+2502/113-126-142 # │ BOX DRAWINGS LIGHT VERTICAL
G_hwall_mines: U+2500/113-126-142 # ─ BOX DRAWINGS LIGHT HORIZONTAL
G_tlcorn_mines: U+250c/113-126-142 # ┌ BOX DRAWINGS LIGHT DOWN AND RIGHT
G_trcorn_mines: U+2510/113-126-142 # ┐ BOX DRAWINGS LIGHT DOWN AND LEFT
G_blcorn_mines: U+2514/113-126-142 # └ BOX DRAWINGS LIGHT UP AND RIGHT
G_brcorn_mines: U+2518/113-126-142 # ┘ BOX DRAWINGS LIGHT UP AND LEFT
G_crwall_mines: U+253C/113-126-142 # ┼ BOX DRAWINGS LIGHT VERTICAL AND HORIZONTAL
G_tuwall_mines: U+2534/113-126-142 # ┴ BOX DRAWINGS LIGHT UP AND HORIZONTAL
G_tdwall_mines: U+252C/113-126-142 # ┬ BOX DRAWINGS LIGHT DOWN AND HORIZONTAL
G_tlwall_mines: U+2524/113-126-142 # ┤ BOX DRAWINGS LIGHT VERTICAL AND LEFT
G_trwall_mines: U+251C/113-126-142 # ├ BOX DRAWINGS LIGHT VERTICAL AND RIGHT
finish
start: Enhanced2
# contributed in GitHub pull request 1503 by abcbarryn.
# This has double line wall symbols.
Description: Enhanced with more Unicode glyphs and 24-bit color
Restrictions: primary
Handling: UTF8
S_corr: U+2591
S_litcorr: U+2592
S_engrcorr: U+2591
S_amulet: U+2299 # ☉
S_cloud: U+2601 # ☁
S_vwall: U+2551 # ║ BOX DRAWINGS DOUBLE VERTICAL
S_hwall: U+2550 # ═ BOX DRAWINGS DOUBLE HORIZONTAL
S_tlcorn: U+2554 # ╔ BOX DRAWINGS DOUBLE DOWN AND RIGHT
S_trcorn: U+2557 # ╗ BOX DRAWINGS DOUBLE DOWN AND LEFT
S_blcorn: U+255a # ╚ BOX DRAWINGS DOUBLE UP AND RIGHT
S_brcorn: U+255d # ╝ BOX DRAWINGS DOUBLE UP AND LEFT
S_crwall: U+256c # ╬ BOX DRAWINGS DOUBLE VERTICAL AND HORIZONTAL
S_tuwall: U+2569 # ╩ BOX DRAWINGS DOUBLE UP AND HORIZONTAL
S_tdwall: U+2566 # ╦ BOX DRAWINGS DOUBLE DOWN AND HORIZONTAL
S_tlwall: U+2563 # ╣ BOX DRAWINGS DOUBLE VERTICAL AND LEFT
S_trwall: U+2560 # ╠ BOX DRAWINGS DOUBLE VERTICAL AND RIGHT
S_ndoor: U+00b7 # MIDDLE DOT S_ndoor: U+00b7 # MIDDLE DOT
S_vodoor: U+2592 # MEDIUM SHADE S_vodoor: U+2592 # MEDIUM SHADE
S_hodoor: U+2592 # MEDIUM SHADE S_hodoor: U+2592 # MEDIUM SHADE
S_bars: U+2261 # IDENTICAL TO # S_bars: U+2261 # IDENTICAL TO
S_tree: U+03a8 # GREEK CAPITAL LETTER PSI S_bars: U+2980 #
# S_tree: U+03a8 # GREEK CAPITAL LETTER PSI
# S_tree: U+1F332 # 🌲
S_tree: U+2660 # ♠
S_room: U+00b7 # MIDDLE DOT S_room: U+00b7 # MIDDLE DOT
S_engroom: U+03BE # Greek Small Letter Xi S_engroom: U+03BE # Greek Small Letter Xi
S_darkroom: U+00b7 # MIDDLE DOT S_darkroom: U+00b7 # MIDDLE DOT
@@ -833,6 +958,7 @@ start: Enhanced1
G_fountain: U+2320/0-150-255 # TOP HALF INTEGRAL G_fountain: U+2320/0-150-255 # TOP HALF INTEGRAL
S_pool: U+224b # TRIPLE TILDE S_pool: U+224b # TRIPLE TILDE
S_ice: U+00b7 # MIDDLE DOT S_ice: U+00b7 # MIDDLE DOT
# S_ice: U+2744 # ❄️
S_lava: U+224b # TRIPLE TILDE S_lava: U+224b # TRIPLE TILDE
S_lavawall: U+2248 # ALMOST EQUAL TO S_lavawall: U+2248 # ALMOST EQUAL TO
S_vodbridge: U+00b7 # MIDDLE DOT S_vodbridge: U+00b7 # MIDDLE DOT

View File

@@ -1,4 +1,4 @@
NHDT-Branch: NetHack-3.7 $:$NHDT-Revision: 1.1614 $ $NHDT-Date: 1769342601 2026/01/25 04:03:21 $ NHDT-Branch: NetHack-3.7 $:$NHDT-Revision: 1.1649 $ $NHDT-Date: 1777000050 2026/04/23 19:07:30 $
General Fixes and Modified Features General Fixes and Modified Features
----------------------------------- -----------------------------------
@@ -1598,6 +1598,10 @@ prevent selecting all options in #optionsfull menu
shapeshifters change shape less shapeshifters change shape less
rolling boulder traps aren't removed when stepped on and move boulders rolling boulder traps aren't removed when stepped on and move boulders
pushed onto them pushed onto them
when starting a new game as a monk, newsym(0,0) was being called (adjabil ->
postadjabil -> see_monsters when initializing See_invisible as hero
became level 1; seen 'monster' was the hero who hadn't been placed
on the map yet)
Fixes to 3.7.0-x General Problems Exposed Via git Repository Fixes to 3.7.0-x General Problems Exposed Via git Repository
@@ -2203,7 +2207,7 @@ mounted hero was able to deliver joust hits when trapped
timer sanity check for melting ice gave false complaint about non-ice for timer sanity check for melting ice gave false complaint about non-ice for
frozen moat under open drawbridge frozen moat under open drawbridge
mhitm_ad_phys() was not applying Half_physical_damage when hero was target mhitm_ad_phys() was not applying Half_physical_damage when hero was target
callers of thitu() were not applyibg Half_physical_damage either callers of thitu() were not applying Half_physical_damage either
throwing crystal plate mail or helm of brilliance up against the ceiling could throwing crystal plate mail or helm of brilliance up against the ceiling could
result in the item being cracked and then vanishing result in the item being cracked and then vanishing
yn_function (used all over the place) sometimes triggered an impossible() yn_function (used all over the place) sometimes triggered an impossible()

View File

@@ -510,6 +510,7 @@ extern void destroy_drawbridge(coordxy, coordxy);
/* ### decl.c ### */ /* ### decl.c ### */
extern void program_state_init(void);
extern void decl_globals_init(void); extern void decl_globals_init(void);
extern void sa_victual(volatile struct victual_info *); extern void sa_victual(volatile struct victual_info *);

View File

@@ -19,7 +19,7 @@ enum wp_ids { wp_tty = 1, wp_X11, wp_Qt, wp_mswin, wp_curses,
#ifdef OUTDATED_STUFF #ifdef OUTDATED_STUFF
wp_mac, wp_Gem, wp_Gnome, wp_mac, wp_Gem, wp_Gnome,
#endif #endif
wp_trace // XXX do we need this? should chainin/out get an id? TBD wp_trace // XXX do we need this? should chainin/out get an id? TBD
}; };
/* NB: this MUST match chain_procs below */ /* NB: this MUST match chain_procs below */

View File

@@ -32,6 +32,7 @@ staticfn void interrupt_multi(const char *);
void void
early_init(int argc USED_FOR_CRASHREPORT, char *argv[] USED_FOR_CRASHREPORT) early_init(int argc USED_FOR_CRASHREPORT, char *argv[] USED_FOR_CRASHREPORT)
{ {
program_state_init();
#ifdef CRASHREPORT #ifdef CRASHREPORT
/* Do this as early as possible, but let ports do other things first. */ /* Do this as early as possible, but let ports do other things first. */
crashreport_init(argc, argv); crashreport_init(argc, argv);

View File

@@ -1,4 +1,4 @@
/* NetHack 3.7 attrib.c $NHDT-Date: 1754979443 2025/08/11 22:17:23 $ $NHDT-Branch: NetHack-3.7 $:$NHDT-Revision: 1.134 $ */ /* NetHack 3.7 attrib.c $NHDT-Date: 1777000050 2026/04/23 19:07:30 $ $NHDT-Branch: NetHack-3.7 $:$NHDT-Revision: 1.137 $ */
/* Copyright 1988, 1989, 1990, 1992, M. Stephenson */ /* Copyright 1988, 1989, 1990, 1992, M. Stephenson */
/* NetHack may be freely redistributed. See license for details. */ /* NetHack may be freely redistributed. See license for details. */
@@ -107,7 +107,7 @@ static const struct innate {
staticfn void exerper(void); staticfn void exerper(void);
staticfn int rnd_attr(void); staticfn int rnd_attr(void);
staticfn int init_attr_role_redist(int, boolean); staticfn int init_attr_role_redist(int, boolean);
staticfn void postadjabil(long *); staticfn void postadjabil(long *) NONNULLARG1;
staticfn const struct innate *role_abil(int); staticfn const struct innate *role_abil(int);
staticfn const struct innate *check_innate_abil(long *, long); staticfn const struct innate *check_innate_abil(long *, long);
staticfn int innately(long *); staticfn int innately(long *);
@@ -779,7 +779,7 @@ staticfn
void void
postadjabil(long *ability) postadjabil(long *ability)
{ {
if (!ability) if (!u.ulevel) /* initializing hero; don't attempt screen update yet */
return; return;
if (ability == &(HWarning) || ability == &(HSee_invisible)) if (ability == &(HWarning) || ability == &(HSee_invisible))
see_monsters(); see_monsters();

View File

@@ -1063,6 +1063,12 @@ const struct const_globals cg = {
} \ } \
} while(0); } while(0);
void
program_state_init(void)
{
program_state = init_program_state;
}
void void
decl_globals_init(void) decl_globals_init(void)
{ {
@@ -1114,7 +1120,6 @@ decl_globals_init(void)
svu = init_svu; svu = init_svu;
svx = init_svx; svx = init_svx;
svy = init_svy; svy = init_svy;
program_state = init_program_state;
gv.valuables[0].list = gg.gems; gv.valuables[0].list = gg.gems;
gv.valuables[0].size = SIZE(gg.gems); gv.valuables[0].size = SIZE(gg.gems);

View File

@@ -1,4 +1,4 @@
/* NetHack 3.7 display.c $NHDT-Date: 1745114235 2025/04/19 17:57:15 $ $NHDT-Branch: NetHack-3.7 $:$NHDT-Revision: 1.260 $ */ /* NetHack 3.7 display.c $NHDT-Date: 1777000050 2026/04/23 19:07:30 $ $NHDT-Branch: NetHack-3.7 $:$NHDT-Revision: 1.263 $ */
/* Copyright (c) Dean Luick, with acknowledgements to Kevin Darcy */ /* Copyright (c) Dean Luick, with acknowledgements to Kevin Darcy */
/* and Dave Cohrs, 1990. */ /* and Dave Cohrs, 1990. */
/* NetHack may be freely redistributed. See license for details. */ /* NetHack may be freely redistributed. See license for details. */
@@ -753,10 +753,9 @@ feel_location(coordxy x, coordxy y)
/* replicate safeguards used by newsym(); might not be required here */ /* replicate safeguards used by newsym(); might not be required here */
if (_suppress_map_output()) if (_suppress_map_output())
return; return;
if (!isok(x, y)) if (!isok(x, y))
return; return;
lev = &(levl[x][y]); lev = &levl[x][y];
/* If hero's memory of an invisible monster is accurate, we want to keep /* If hero's memory of an invisible monster is accurate, we want to keep
* him from detecting the same monster over and over again on each turn. * him from detecting the same monster over and over again on each turn.
* We must return (so we don't erase the monster). (We must also, in the * We must return (so we don't erase the monster). (We must also, in the
@@ -917,15 +916,24 @@ feel_location(coordxy x, coordxy y)
void void
newsym(coordxy x, coordxy y) newsym(coordxy x, coordxy y)
{ {
struct rm *lev;
struct engr *ep;
struct monst *mon; struct monst *mon;
int see_it; int see_it;
boolean worm_tail; boolean worm_tail;
struct rm *lev = &(levl[x][y]);
struct engr *ep;
/* don't try to produce map output when level is in a state of flux */ /* don't try to produce map output when level is in a state of flux */
if (_suppress_map_output()) if (_suppress_map_output())
return; return;
/* should never happen; same error handling as u_on_newpos() */
if (!isok(x, y)) {
void (*errfunc)(const char *, ...) PRINTF_F_PTR(1, 2);
errfunc = (x < 0 || y < 0 || x > COLNO - 1 || y > ROWNO - 1) ? panic
: impossible; /* misuse of column 0 is less severe */
(*errfunc)("newsym: attempting screen update for <%d,%d>", x, y);
return;
}
/* only permit updating the hero when swallowed */ /* only permit updating the hero when swallowed */
if (u.uswallow) { if (u.uswallow) {
@@ -939,6 +947,7 @@ newsym(coordxy x, coordxy y)
if (!(is_pool_or_lava(x, y) || is_ice(x, y)) || !next2u(x, y)) if (!(is_pool_or_lava(x, y) || is_ice(x, y)) || !next2u(x, y))
return; return;
} }
lev = &levl[x][y];
/* Can physically see the location. */ /* Can physically see the location. */
if (cansee(x, y)) { if (cansee(x, y)) {

View File

@@ -182,6 +182,11 @@ early_options(int *argc_p, char ***argv_p, char **hackdir_p)
char **argv, *arg, *origarg; char **argv, *arg, *origarg;
int argc, oldargc, ndx = 0, consumed = 0; int argc, oldargc, ndx = 0, consumed = 0;
#ifdef ENHANCED_SYMBOLS
if (argcheck(*argc_p, *argv_p, ARG_DUMPGLYPHIDS) == 2)
opt_terminate();
#endif
config_error_init(FALSE, "command line", FALSE); config_error_init(FALSE, "command line", FALSE);
/* treat "nethack ?" as a request for usage info; due to shell /* treat "nethack ?" as a request for usage info; due to shell
@@ -711,7 +716,7 @@ dump_enums(void)
objclass_classes_enum, objclass_classes_enum,
objclass_syms_enum, objclass_syms_enum,
arti_enum, arti_enum,
mcastu_enum, mcastu_enum,
NUM_ENUM_DUMPS NUM_ENUM_DUMPS
}; };
@@ -743,7 +748,7 @@ dump_enums(void)
objclass_classes_dump, objclass_classes_dump,
objclass_syms_dump, objclass_syms_dump,
arti_enum_dump, arti_enum_dump,
mcastu_enum_dump, mcastu_enum_dump,
}; };
static const struct de_params { static const struct de_params {

View File

@@ -4251,12 +4251,12 @@ saving_grace(int dmg)
impossible("saving_grace check for negative damage? (%d)", dmg); impossible("saving_grace check for negative damage? (%d)", dmg);
return 0; return 0;
} }
#if 0 /* saving grace _does_ protect hero during own actions */
if (!svc.context.mon_moving) { if (!svc.context.mon_moving) {
/* saving grace doesn't protect you from your own actions */ /* saving grace doesn't protect you from your own actions */
return dmg; return dmg;
} }
#endif
if (dmg < u.uhp || u.uhp <= 0) { if (dmg < u.uhp || u.uhp <= 0) {
/* no need for saving grace */ /* no need for saving grace */
return dmg; return dmg;

View File

@@ -1,4 +1,4 @@
/* NetHack 3.7 insight.c $NHDT-Date: 1737384766 2025/01/20 06:52:46 $ $NHDT-Branch: NetHack-3.7 $:$NHDT-Revision: 1.128 $ */ /* NetHack 3.7 insight.c $NHDT-Date: 1777004419 2026/04/23 20:20:19 $ $NHDT-Branch: NetHack-3.7 $:$NHDT-Revision: 1.134 $ */
/* Copyright (c) Stichting Mathematisch Centrum, Amsterdam, 1985. */ /* Copyright (c) Stichting Mathematisch Centrum, Amsterdam, 1985. */
/* NetHack may be freely redistributed. See license for details. */ /* NetHack may be freely redistributed. See license for details. */
@@ -16,13 +16,14 @@
staticfn void enlght_out(const char *); staticfn void enlght_out(const char *);
staticfn void enlght_line(const char *, const char *, const char *, staticfn void enlght_line(const char *, const char *, const char *,
const char *); const char *);
staticfn char *enlght_combatinc(const char *, int, int, char *); staticfn char *enlght_combatinc(const char *, int, int, char *);
staticfn void enlght_halfdmg(int, int); staticfn void enlght_halfdmg(int, int);
staticfn boolean walking_on_water(void); staticfn boolean walking_on_water(void);
staticfn boolean cause_known(int); staticfn boolean cause_known(int);
staticfn char *attrval(int, int, char *); staticfn char *attrval(int, int, char *);
staticfn char *fmt_elapsed_time(char *, int); staticfn char *fmt_elapsed_time(char *, int);
staticfn char *N_times(long, char *) NONNULL NONNULLARG2;
staticfn void background_enlightenment(int, int); staticfn void background_enlightenment(int, int);
staticfn void basics_enlightenment(int, int); staticfn void basics_enlightenment(int, int);
staticfn void characteristics_enlightenment(int, int); staticfn void characteristics_enlightenment(int, int);
@@ -356,6 +357,28 @@ fmt_elapsed_time(char *outbuf, int final)
return outbuf; return outbuf;
} }
/* "once" vs "twice" vs "17 times", used in several places */
staticfn char *
N_times(long n, char *outbuf)
{
switch (n) {
case 0:
default:
Sprintf(outbuf, "%ld times", n);
break;
case 1:
Strcpy(outbuf, "once");
break;
case 2:
Strcpy(outbuf, "twice");
break;
case 3:
Strcpy(outbuf, "thrice");
break;
}
return outbuf;
}
void void
enlightenment( enlightenment(
int mode, /* BASICENLIGHTENMENT | MAGICENLIGHTENMENT (| both) */ int mode, /* BASICENLIGHTENMENT | MAGICENLIGHTENMENT (| both) */
@@ -1972,23 +1995,10 @@ attributes_enlightenment(
buf[0] = '\0'; buf[0] = '\0';
if (final < 2) { /* still in progress, or quit/escaped/ascended */ if (final < 2) { /* still in progress, or quit/escaped/ascended */
p = "survived after being killed "; p = "survived after being killed ";
switch (u.umortality) { if (!u.umortality)
case 0:
p = !final ? (char *) 0 : "survived"; p = !final ? (char *) 0 : "survived";
break; else
case 1: (void) N_times((long) u.umortality, buf);
Strcpy(buf, "once");
break;
case 2:
Strcpy(buf, "twice");
break;
case 3:
Strcpy(buf, "thrice");
break;
default:
Sprintf(buf, "%d times", u.umortality);
break;
}
} else { /* game ended in character's death */ } else { /* game ended in character's death */
p = "are dead"; p = "are dead";
switch (u.umortality) { switch (u.umortality) {
@@ -2093,13 +2103,26 @@ doconduct(void)
void void
show_conduct(int final) show_conduct(int final)
{ {
char buf[BUFSZ]; char buf[BUFSZ], bufN[40];
int ngenocided; int ngenocided;
/* Create the conduct window */ /* Create the conduct window */
ge.en_win = create_nhwindow(NHW_MENU); ge.en_win = create_nhwindow(NHW_MENU);
putstr(ge.en_win, 0, "Voluntary challenges:"); putstr(ge.en_win, 0, "Voluntary challenges:");
/* rerolling; "You <this or that>" is about the character, rerolling
is about the player so phrase it differently;
also, always use past tense since the chance to do something with it
is gone by time player can issue #conduct command or see disclosure */
if (!u.uroleplay.reroll)
Strcpy(buf, " Character rerolling was not enabled.");
else if (!u.uroleplay.numrerolls)
Strcpy(buf, " Your character was not rerolled.");
else
Sprintf(buf, " Your character was rerolled %s.",
N_times(u.uroleplay.numrerolls, bufN));
enlght_out(buf);
if (u.uroleplay.blind) if (u.uroleplay.blind)
you_have_been("blind from birth"); you_have_been("blind from birth");
if (u.uroleplay.deaf) if (u.uroleplay.deaf)
@@ -2109,12 +2132,6 @@ show_conduct(int final)
if (u.uroleplay.pauper) if (u.uroleplay.pauper)
enl_msg(You_, gi.invent ? "started" : "are", "started out", enl_msg(You_, gi.invent ? "started" : "are", "started out",
" without possessions", ""); " without possessions", "");
if (u.uroleplay.reroll) {
Sprintf(buf, "rerolled your character %ld time%s",
u.uroleplay.numrerolls, plur(u.uroleplay.numrerolls));
you_have_X(buf);
}
/* nudist is far more than a subset of possessionless, and a much /* nudist is far more than a subset of possessionless, and a much
more impressive accomplishment, but showing "started out without more impressive accomplishment, but showing "started out without
possessions" before "faithfully nudist" looks more logical */ possessions" before "faithfully nudist" looks more logical */
@@ -2214,25 +2231,13 @@ show_conduct(int final)
if (sokoban_in_play()) { if (sokoban_in_play()) {
const char *presentverb = "have violated", *pastverb = "violated"; const char *presentverb = "have violated", *pastverb = "violated";
Strcpy(buf, " the special Sokoban rules "); if (!u.uconduct.sokocheat) {
switch (u.uconduct.sokocheat) {
case 0L:
presentverb = "have not violated"; presentverb = "have not violated";
pastverb = "did not violate"; pastverb = "did not violate";
Strcpy(buf, " any of the special Sokoban rules"); Strcpy(buf, " any of the special Sokoban rules");
break; } else {
case 1L: Strcpy(buf, " the special Sokoban rules ");
Strcat(buf, "once"); Strcat(buf, N_times(u.uconduct.sokocheat, bufN));
break;
case 2L:
Strcat(buf, "twice");
break;
case 3L:
Strcat(buf, "thrice");
break;
default:
Sprintf(eos(buf), "%ld times", u.uconduct.sokocheat);
break;
} }
enl_msg(You_, presentverb, pastverb, buf, ""); enl_msg(You_, presentverb, pastverb, buf, "");
} }
@@ -2899,19 +2904,9 @@ list_vanquished(char defquery, boolean ask)
Sprintf(buf, "%s%s", Sprintf(buf, "%s%s",
!type_is_pname(&mons[i]) ? "the " : "", !type_is_pname(&mons[i]) ? "the " : "",
mons[i].pmnames[NEUTRAL]); mons[i].pmnames[NEUTRAL]);
if (nkilled > 1) { if (nkilled > 1)
switch (nkilled) { Sprintf(eos(buf), " (%s)",
case 2: N_times((long) nkilled, buftoo));
Sprintf(eos(buf), " (twice)");
break;
case 3:
Sprintf(eos(buf), " (thrice)");
break;
default:
Sprintf(eos(buf), " (%d times)", nkilled);
break;
}
}
was_uniq = TRUE; was_uniq = TRUE;
} else { } else {
if (uniq_header && was_uniq) { if (uniq_header && was_uniq) {

View File

@@ -737,6 +737,8 @@ m_throw(
hitv += 8 + singleobj->spe; hitv += 8 + singleobj->spe;
if (dam < 1) if (dam < 1)
dam = 1; dam = 1;
if (singleobj->otyp != ACID_VENOM)
dam = Maybe_Half_Phys(dam);
hitu = thitu(hitv, dam, &singleobj, (char *) 0); hitu = thitu(hitv, dam, &singleobj, (char *) 0);
} }
} }
@@ -1233,7 +1235,7 @@ thrwmu(struct monst *mtmp)
if (dam < 1) if (dam < 1)
dam = 1; dam = 1;
(void) thitu(hitv, dam, &otmp, (char *) 0); (void) thitu(hitv, Maybe_Half_Phys(dam), &otmp, (char *) 0);
stop_occupation(); stop_occupation();
return; return;
} else if ((arw = autoreturn_weapon(otmp)) != 0 && !mwelded(otmp)) { } else if ((arw = autoreturn_weapon(otmp)) != 0 && !mwelded(otmp)) {

View File

@@ -7368,7 +7368,8 @@ initoptions_finish(void)
#ifdef ENHANCED_SYMBOLS #ifdef ENHANCED_SYMBOLS
if (glyphid_cache_status()) if (glyphid_cache_status())
free_glyphid_cache(); free_glyphid_cache();
apply_customizations(gc.currentgraphics, do_custom_symbols); apply_customizations(gc.currentgraphics,
do_custom_symbols | do_custom_colors);
#endif #endif
go.opt_initial = FALSE; go.opt_initial = FALSE;
return; return;
@@ -8697,8 +8698,8 @@ doset_simple_menu(void)
int int
doset_simple(void) doset_simple(void)
{ {
int pickedone = 0, int pickedone = 0;
opt_crt_flags = docrtNocls; boolean flush = FALSE;
if (iflags.menu_requested) { if (iflags.menu_requested) {
/* doset() checks for 'm' and calls doset_simple(); clear the /* doset() checks for 'm' and calls doset_simple(); clear the
@@ -8713,40 +8714,13 @@ doset_simple(void)
give_opt_msg = FALSE; give_opt_msg = FALSE;
do { do {
pickedone = doset_simple_menu(); pickedone = doset_simple_menu();
flush = go.opt_need_redraw;
/* some option choices warrant immediate updating beyond the reset_needed_visuals();
option value itself */ if (flush) {
if (go.opt_need_glyph_reset) {
reset_glyphmap(gm_optionchange);
}
if (go.opt_need_redraw) {
check_gold_symbol();
reglyph_darkroom();
if (go.opt_symset_changed)
opt_crt_flags &= ~docrtRefresh;
docrt_flags(opt_crt_flags);
flush_screen(1); flush_screen(1);
flush = FALSE;
} }
if (go.opt_need_promptstyle)
adjust_menu_promptstyle(WIN_INVEN, &iflags.menu_headings);
if (go.opt_update_basic_palette) {
#ifdef CHANGE_COLOR
change_palette();
#endif
go.opt_update_basic_palette = FALSE;
}
if (go.opt_reset_customcolors || go.opt_reset_customsymbols) {
if (go.opt_reset_customcolors)
reset_customcolors();
if (go.opt_reset_customsymbols)
reset_customsymbols();
docrt_flags(opt_crt_flags);
}
/* status may need updating if terminal is tall enough that
doset_simple menu doesn't cover up status or wide enough for
curses to honor player's choice of align_status:Right|Left */
if (disp.botl || disp.botlx)
bot();
} while (pickedone > 0); } while (pickedone > 0);
give_opt_msg = TRUE; give_opt_msg = TRUE;
return ECMD_OK; return ECMD_OK;

View File

@@ -638,14 +638,14 @@ parse_sym_line(char *buf, int which_set)
#ifdef ENHANCED_SYMBOLS #ifdef ENHANCED_SYMBOLS
} else { } else {
if (gc.chosen_symset_start) { if (gc.chosen_symset_start) {
glyphrep_to_custom_map_entries(buf, &glyph); (void) glyphrep_to_custom_map_entries(buf, &glyph);
} }
#endif #endif
} }
} }
} else if (gc.chosen_symset_start) { } else if (gc.chosen_symset_start) {
/* glyph, not symbol */ /* glyph, not symbol */
glyphrep_to_custom_map_entries(buf, &glyph); (void) glyphrep_to_custom_map_entries(buf, &glyph);
} }
#ifndef ENHANCED_SYMBOLS #ifndef ENHANCED_SYMBOLS
nhUse(glyph); nhUse(glyph);

View File

@@ -14,7 +14,7 @@ CCFLAGS = -g
#If you want to force use of one particular set of compilers, do it #If you want to force use of one particular set of compilers, do it
#here, ahead of the detection, so that the detection will match your #here, ahead of the detection, so that the detection will match your
#choice and set variables CCISCLANG, GCCGTEQ, CLANGPPGTEQ9 etc. #choice and set variables CCISCLANG, CCISGCC, GCCGTEQ, CLANGPPGTEQ9 etc.
#accordingly. #accordingly.
# #
#CC= gcc #CC= gcc
@@ -41,7 +41,7 @@ endif
# If you want to override the compiler detection just carried out # If you want to override the compiler detection just carried out
# uncomment one of the following pairs. Note, however, that # uncomment one of the following pairs. Note, however, that
# doing this after the detection above will likely result in # doing this after the detection above will likely result in
# mismatched variable values for CCISCLANG, GCCGTEQ, CLANGPPGTEQ9 etc. # mismatched variable values for CCISCLANG, CCISGCC, GCCGTEQ, CLANGPPGTEQ9 etc.
# #
#CC= gcc #CC= gcc
#CXX= g++ -std-gnu++11 #CXX= g++ -std-gnu++11
@@ -72,8 +72,17 @@ CFLAGS+=-Wstrict-prototypes
CFLAGS+=-Wnonnull CFLAGS+=-Wnonnull
#detection of clang vs gcc #detection of clang vs gcc
CCISCLANG := $(shell echo `$(CC) --version` | grep clang) CCTEST := $(shell echo `$(CC) --version` | grep clang)
ifeq "$(CCISCLANG)" "" ifneq "$(CCTEST)" ""
CCISCLANG=1
CCISGCC=
else
CCISCLANG=
CCISGCC=1
endif
#$(info CCISCLANG=$(CCISCLANG), CCISGCC=$(CCISGCC))
ifeq "$(CCISGCC)" "1"
# gcc-specific follows # gcc-specific follows
CXX=g++ -std=gnu++11 CXX=g++ -std=gnu++11
# get the version of gcc # get the version of gcc
@@ -95,8 +104,8 @@ CFLAGS+=-Wimplicit-fallthrough
#endif #endif
# end of gcc-specific # end of gcc-specific
else # gcc or clang? else # gcc or clang?
CXX=clang++ -std=gnu++11
# clang-specific follows # clang-specific follows
CXX=clang++ -std=gnu++11
CLANGGTEQ12 := $(shell expr `$(CC) -dumpversion | cut -f1 -d.` \>= 12) CLANGGTEQ12 := $(shell expr `$(CC) -dumpversion | cut -f1 -d.` \>= 12)
CLANGGTEQ14 := $(shell expr `$(CC) -dumpversion | cut -f1 -d.` \>= 14) CLANGGTEQ14 := $(shell expr `$(CC) -dumpversion | cut -f1 -d.` \>= 14)
CLANGGTEQ21 := $(shell expr `$(CC) -dumpversion | cut -f1 -d.` \>= 21) CLANGGTEQ21 := $(shell expr `$(CC) -dumpversion | cut -f1 -d.` \>= 21)

View File

@@ -415,7 +415,7 @@ endif
SYSCFLAGS=-DLUA_USE_LINUX SYSCFLAGS=-DLUA_USE_LINUX
ifdef GITSUBMODULES ifdef GITSUBMODULES
LUAFLAGS=CC='$(CC)' SYSCFLAGS='$(SYSCFLAGS)' LUAFLAGS=CC='$(CC)' SYSCFLAGS='$(SYSCFLAGS)'
ifneq "$(CCISCLANG)" "" ifeq "$(CCISCLANG)" "1"
# clang # clang
LUAFLAGS +=CWARNGCC='' LUAFLAGS +=CWARNGCC=''
endif # clang endif # clang

View File

@@ -338,7 +338,7 @@ endif # WANT_LIBNH
# this needs to be passed via make rather than defined in unixconf.h # this needs to be passed via make rather than defined in unixconf.h
ifdef GITSUBMODULES ifdef GITSUBMODULES
LUAFLAGS=CC='$(CC)' MYCFLAGS=' -DLUA_USE_MACOSX' LUAFLAGS=CC='$(CC)' MYCFLAGS=' -DLUA_USE_MACOSX'
ifneq "$(CCISCLANG)" "" ifeq "$(CCISCLANG)" "1"
# clang # clang
LUAFLAGS +=CWARNGCC='' LUAFLAGS +=CWARNGCC=''
endif # clang endif # clang

View File

@@ -123,10 +123,6 @@ main(int argc, char *argv[])
dir = nh_getenv("HACKDIR"); dir = nh_getenv("HACKDIR");
#endif /* CHDIR */ #endif /* CHDIR */
program_state.early_options = 1; program_state.early_options = 1;
#ifdef ENHANCED_SYMBOLS
if (argcheck(argc, argv, ARG_DUMPGLYPHIDS) == 2)
exit(EXIT_SUCCESS);
#endif
/* handle -dalthackdir, -s <score stuff>, --version, --showpaths */ /* handle -dalthackdir, -s <score stuff>, --version, --showpaths */
early_options(&argc, &argv, &dir); early_options(&argc, &argv, &dir);
program_state.early_options = 0; program_state.early_options = 0;

View File

@@ -139,8 +139,6 @@ GIT_AVAILABLE = N
# if next line is commented out, full compiler command lines will be output # if next line is commented out, full compiler command lines will be output
Q=@ Q=@
SKIP_NETHACKW = N
!IFNDEF LUA_VERSION !IFNDEF LUA_VERSION
LUAVER=5.4.8 LUAVER=5.4.8
!ELSE !ELSE

View File

@@ -870,7 +870,7 @@ back_buffer_flip(void)
do_anything |= do_wide_content; do_anything |= do_wide_content;
} else { } else {
#endif #endif
if (back->utf8str && front->utf8str if (back->utf8str[0] && front->utf8str[0]
&& strcmp((const char *) back->utf8str, && strcmp((const char *) back->utf8str,
(const char *) front->utf8str)) (const char *) front->utf8str))
do_anything |= do_utf8_content; do_anything |= do_utf8_content;

View File

@@ -167,12 +167,6 @@ MAIN(int argc, char *argv[])
/* setting iflags.colorcount has to be after early_init() /* setting iflags.colorcount has to be after early_init()
* because it zeros out all of iflags */ * because it zeros out all of iflags */
hwnd = GetDesktopWindow(); hwnd = GetDesktopWindow();
hdc = GetDC(hwnd);
if (hdc) {
bpp = GetDeviceCaps(hdc, BITSPIXEL);
iflags.colorcount = (bpp >= 16) ? 16777216 : (bpp >= 8) ? 256 : 16;
ReleaseDC(hwnd, hdc);
}
#ifdef _MSC_VER #ifdef _MSC_VER
#ifdef DEBUG #ifdef DEBUG
@@ -201,6 +195,15 @@ _CrtSetReportFile(_CRT_ASSERT, _CRTDBG_FILE_STDERR);*/
#ifndef MSWIN_GRAPHICS #ifndef MSWIN_GRAPHICS
early_init(argc, argv); /* already in WinMain for MSWIN_GRAPHICS */ early_init(argc, argv); /* already in WinMain for MSWIN_GRAPHICS */
#endif #endif
/* this must be done after early_init() because early_init()
sets iflags to zero */
hdc = GetDC(hwnd);
if (hdc) {
bpp = GetDeviceCaps(hdc, BITSPIXEL);
iflags.colorcount = (bpp >= 16) ? 16777216 : (bpp >= 8) ? 256 : 16;
ReleaseDC(hwnd, hdc);
}
gh.hname = "NetHack"; /* used for syntax messages */ gh.hname = "NetHack"; /* used for syntax messages */
set_default_prefix_locations( set_default_prefix_locations(
argv[0]); /* must be re-done after initoptions_init() argv[0]); /* must be re-done after initoptions_init()
@@ -223,7 +226,7 @@ _CrtSetReportFile(_CRT_ASSERT, _CRTDBG_FILE_STDERR);*/
#ifdef EARLY_CONFIGFILE_PASS #ifdef EARLY_CONFIGFILE_PASS
rcfile_interface_options(); rcfile_interface_options();
if (gc.chosen_windowtype && *gc.chosen_windowtype) if (*gc.chosen_windowtype)
windowtype = gc.chosen_windowtype; windowtype = gc.chosen_windowtype;
#endif #endif