Large diffs are not rendered by default.

@@ -105,7 +105,7 @@ opt_##a,
&flags.autodig)
NHOPTB(autoopen, 0, opt_out, set_in_game, On, Yes, No, No, NoAlias,
&flags.autoopen)
NHOPTB(autopickup, 0, opt_out, set_in_game, On, Yes, No, No, NoAlias,
NHOPTB(autopickup, 0, opt_out, set_in_game, Off, Yes, No, No, NoAlias,
&flags.pickup)
NHOPTO("autopickup exceptions", o_autopickup_exceptions, BUFSZ, opt_in,
set_in_game, No, Yes, No, NoAlias, "edit autopickup exceptions")
@@ -172,6 +172,8 @@ opt_##a,
&iflags.extmenu)
NHOPTB(female, 0, opt_in, set_in_config, Off, Yes, No, No, "male",
&flags.female)
NHOPTB(fireassist, 0, opt_out, set_in_game, On, Yes, No, No, NoAlias,
&iflags.fireassist)
NHOPTB(fixinv, 0, opt_out, set_in_game, On, Yes, No, No, NoAlias,
&flags.invlet_constant)
NHOPTC(font_map, 40, opt_in, set_gameview, Yes, Yes, Yes, No, NoAlias,
@@ -8,7 +8,7 @@

/* xNetHack 6.1 */
#define VERSION_MAJOR 6
#define VERSION_MINOR 2
#define VERSION_MINOR 3
/*
* PATCHLEVEL is updated for each release.
*/
@@ -36,9 +36,10 @@
#define DEBUG
#endif

#define COPYRIGHT_BANNER_A "xNetHack 6.2, Copyright 2021, based on NetHack, Copyright 1985-2021"
#define COPYRIGHT_BANNER_A "xNetHack, Copyright 2021, based on NetHack, Copyright 1985-2021"
#define COPYRIGHT_BANNER_B "by Stichting Mathematisch Centrum and M. Stephenson."
/* COPYRIGHT_BANNER_C is generated by makedefs into date.h */
/* nomakedefs.copyright_banner_c is generated at runtime */
#define COPYRIGHT_BANNER_C nomakedefs.copyright_banner_c
#define COPYRIGHT_BANNER_D " See license for details."

/*
@@ -66,6 +66,13 @@ struct permonst {

extern NEARDATA struct permonst mons[]; /* the master list of monster types */

enum monnums {
#define MONS_ENUM
#include "monsters.h"
#undef MONS_ENUM
NUMMONS
};

#define VERY_SLOW 3
#define SLOW_SPEED 9
#define NORMAL_SPEED 12 /* movement rates */
@@ -82,4 +89,5 @@ extern NEARDATA struct permonst mons[]; /* the master list of monster types */
#define pmname(pm,g) ((((g) == MALE || (g) == FEMALE) && (pm)->pmnames[g]) \
? (pm)->pmnames[g] : (pm)->pmnames[NEUTRAL])
#endif

#endif /* PERMONST_H */
@@ -109,213 +109,13 @@ enum levl_typ_types {
#define IS_SOFT(typ) ((typ) == AIR || (typ) == CLOUD || IS_POOL(typ))

/*
* The screen symbols may be the default or defined at game startup time.
* See drawing.c for defaults.
* Note: {ibm|dec|curses}_graphics[] arrays (also in drawing.c) must be kept in
* synch.
* Note: secret doors (SDOOR) want to use both rm.doormask and
* rm.wall_info but those both overload rm.flags. SDOOR only
* has 2 states (closed or locked). However, it can't specify
* D_CLOSED due to that conflicting with WM_MASK (below). When
* a secret door is revealed, the door gets set to D_CLOSED iff
* it isn't set to D_LOCKED (see cvt_sdoor_to_door() in detect.c).
*/

/* begin dungeon characters */
enum screen_symbols {
S_stone = 0,
S_vwall = 1,
S_hwall = 2,
S_tlcorn = 3,
S_trcorn = 4,
S_blcorn = 5,
S_brcorn = 6,
S_crwall = 7,
S_tuwall = 8,
S_tdwall = 9,
S_tlwall = 10,
S_trwall = 11,
S_ndoor = 12,
S_vodoor = 13,
S_hodoor = 14,
S_vcdoor = 15, /* closed door, vertical wall */
S_hcdoor = 16, /* closed door, horizontal wall */
S_bars = 17, /* KMH -- iron bars */
S_tree = 18, /* KMH */
S_room = 19,
S_darkroom = 20,
S_corr = 21,
S_litcorr = 22,
S_upstair = 23,
S_dnstair = 24,
S_upladder = 25,
S_dnladder = 26,
S_altar = 27,
S_grave = 28,
S_throne = 29,
S_sink = 30,
S_fountain = 31,
S_pool = 32,
S_ice = 33,
S_grass = 34,
S_lava = 35,
S_vodbridge = 36,
S_hodbridge = 37,
S_vcdbridge = 38, /* closed drawbridge, vertical wall */
S_hcdbridge = 39, /* closed drawbridge, horizontal wall */
S_air = 40,
S_cloud = 41,
S_water = 42,
S_engraving = 43,

/* end dungeon characters, begin traps */

S_arrow_trap = 44,
S_dart_trap = 45,
S_falling_rock_trap = 46,
S_squeaky_board = 47,
S_bear_trap = 48,
S_land_mine = 49,
S_rolling_boulder_trap = 50,
S_sleeping_gas_trap = 51,
S_rust_trap = 52,
S_fire_trap = 53,
S_pit = 54,
S_spiked_pit = 55,
S_hole = 56,
S_trap_door = 57,
S_teleportation_trap = 58,
S_level_teleporter = 59,
S_magic_portal = 60,
S_web = 61,
S_statue_trap = 62,
S_magic_trap = 63,
S_anti_magic_trap = 64,
S_polymorph_trap = 65,
S_vibrating_square = 66, /* for display rather than any trap effect */

/* end traps, begin special effects */

S_vbeam = 67, /* The 4 zap beam symbols. Do NOT separate. */
S_hbeam = 68, /* To change order or add, see function */
S_lslant = 69, /* zapdir_to_glyph() in display.c. */
S_rslant = 70,
S_digbeam = 71, /* dig beam symbol */
S_flashbeam = 72, /* camera flash symbol */
S_boomleft = 73, /* thrown boomerang, open left, e.g ')' */
S_boomright = 74, /* thrown boomerang, open right, e.g. '(' */
S_ss1 = 75, /* 4 magic shield ("resistance sparkle") glyphs */
S_ss2 = 76,
S_ss3 = 77,
S_ss4 = 78,
S_poisoncloud = 79,
S_goodpos = 80, /* valid position for targeting via getpos() */

/* The 8 swallow symbols. Do NOT separate. To change order or add, */
/* see the function swallow_to_glyph() in display.c. */
S_sw_tl = 81, /* swallow top left [1] */
S_sw_tc = 82, /* swallow top center [2] Order: */
S_sw_tr = 83, /* swallow top right [3] */
S_sw_ml = 84, /* swallow middle left [4] 1 2 3 */
S_sw_mr = 85, /* swallow middle right [6] 4 5 6 */
S_sw_bl = 86, /* swallow bottom left [7] 7 8 9 */
S_sw_bc = 87, /* swallow bottom center [8] */
S_sw_br = 88, /* swallow bottom right [9] */

S_explode1 = 89, /* explosion top left */
S_explode2 = 90, /* explosion top center */
S_explode3 = 91, /* explosion top right Ex. */
S_explode4 = 92, /* explosion middle left */
S_explode5 = 93, /* explosion middle center /-\ */
S_explode6 = 94, /* explosion middle right |@| */
S_explode7 = 95, /* explosion bottom left \-/ */
S_explode8 = 96, /* explosion bottom center */
S_explode9 = 97, /* explosion bottom right */

/* end effects */

MAXPCHARS = 98 /* maximum number of mapped characters */
};

#define MAXDCHARS (S_water - S_stone + 1) /* mapped dungeon characters */
#define MAXTCHARS (S_vibrating_square - S_arrow_trap + 1) /* trap chars */
#define MAXECHARS (S_explode9 - S_vbeam + 1) /* mapped effects characters */
#define MAXEXPCHARS 9 /* number of explosion characters */

#define DARKROOMSYM (S_darkroom)

#define is_cmap_trap(i) ((i) >= S_arrow_trap && (i) <= S_polymorph_trap)
#define is_cmap_drawbridge(i) ((i) >= S_vodbridge && (i) <= S_hcdbridge)
#define is_cmap_door(i) ((i) >= S_vodoor && (i) <= S_hcdoor)
#define is_cmap_wall(i) ((i) >= S_stone && (i) <= S_trwall)
#define is_cmap_room(i) ((i) >= S_room && (i) <= S_darkroom)
#define is_cmap_corr(i) ((i) >= S_corr && (i) <= S_litcorr)
#define is_cmap_furniture(i) ((i) >= S_upstair && (i) <= S_fountain)
#define is_cmap_water(i) ((i) == S_pool || (i) == S_water)
#define is_cmap_lava(i) ((i) == S_lava)
#define is_cmap_stairs(i) ((i) == S_upstair || (i) == S_dnstair || \
(i) == S_upladder || (i) == S_dnladder)


struct symdef {
uchar sym;
const char *explanation;
#ifdef TEXTCOLOR
uchar color;
#endif
};

struct symparse {
unsigned range;
#define SYM_CONTROL 1 /* start/finish markers */
#define SYM_PCHAR 2 /* index into showsyms */
#define SYM_OC 3 /* index into oc_syms */
#define SYM_MON 4 /* index into monsyms */
#define SYM_OTH 5 /* misc */
int idx;
const char *name;
};

/* misc symbol definitions */
#define SYM_NOTHING 0
#define SYM_UNEXPLORED 1
#define SYM_BOULDER 2
#define SYM_INVISIBLE 3
#define SYM_PET_OVERRIDE 4
#define SYM_HERO_OVERRIDE 5
#define MAXOTHER 6

/* linked list of symsets and their characteristics */
struct symsetentry {
struct symsetentry *next; /* next in list */
char *name; /* ptr to symset name */
char *desc; /* ptr to description */
int idx; /* an index value */
int handling; /* known handlers value */
Bitfield(nocolor, 1); /* don't use color if set */
Bitfield(primary, 1); /* restricted for use as primary set */
Bitfield(explicitly, 1); /* explicit symset set */
/* 4 free bits */
};

/*
* Graphics sets for display symbols
*/
#define DEFAULT_GRAPHICS 0 /* regular characters: '-', '+', &c */
#define PRIMARY 0 /* primary graphics set */
#define NUM_GRAPHICS 1

/*
* special symbol set handling types ( for invoking callbacks, etc.)
* Must match the order of the known_handlers strings
* in drawing.c
*/
#define H_UNK 0
#define H_IBM 1
#define H_DEC 2
#define H_CURS 3
#define H_MAC 4 /* obsolete; needed so that the listing of available
* symsets by 'O' can skip it for !MAC_GRAPHICS_ENV */

extern const struct symdef defsyms[MAXPCHARS]; /* defaults */
#define WARNCOUNT 6 /* number of different warning levels */
extern const struct symdef def_warnsyms[WARNCOUNT];
#define SYMHANDLING(ht) (g.symset[g.currentgraphics].handling == (ht))

/*
* The possible states of doors - lowest 2 bits of doormask
*
@@ -1,4 +1,4 @@
/* NetHack 3.7 sp_lev.h $NHDT-Date: 1599434249 2020/09/06 23:17:29 $ $NHDT-Branch: NetHack-3.7 $:$NHDT-Revision: 1.39 $ */
/* NetHack 3.7 sp_lev.h $NHDT-Date: 1622361649 2021/05/30 08:00:49 $ $NHDT-Branch: NetHack-3.7 $:$NHDT-Revision: 1.47 $ */
/* Copyright (c) 1989 by Jean-Christophe Collet */
/* NetHack may be freely redistributed. See license for details. */

@@ -150,6 +150,7 @@ typedef struct {
paralyzed, stunned, confused, dead, waiting;
long seentraps;
short has_invent;
long mm_flags; /* makemon flags */
} monster;

typedef struct {
@@ -205,11 +206,14 @@ struct mapfragment {
char *data;
};

#define CAN_OVERWRITE_TERRAIN(ttyp) \
(iflags.debug_overwrite_stairs || !((ttyp) == LADDER || (ttyp) == STAIRS))

#define SET_TYPLIT(x, y, ttyp, llit) \
{ \
do { \
if ((x) >= 1 && (y) >= 0 && (x) < COLNO && (y) < ROWNO) { \
if ((ttyp) < MAX_TYPE && levl[(x)][(y)].typ != STAIRS \
&& levl[(x)][(y)].typ != LADDER) \
if ((ttyp) < MAX_TYPE \
&& CAN_OVERWRITE_TERRAIN(levl[(x)][(y)].typ)) \
levl[(x)][(y)].typ = (ttyp); \
if ((ttyp) == LAVAPOOL) \
levl[(x)][(y)].lit = 1; \
@@ -220,6 +224,6 @@ struct mapfragment {
levl[(x)][(y)].lit = (llit); \
} \
} \
}
} while (0)

#endif /* SP_LEV_H */
@@ -0,0 +1,139 @@
/* NetHack 3.7 sym.h */
/* Copyright (c) 2016 by Pasi Kallinen */
/* NetHack may be freely redistributed. See license for details. */

#ifndef SYM_H
#define SYM_H

/*
* Default characters for monsters.
*/
/* clang-format off */
enum mon_defchars {
#define MONSYMS_DEFCHAR_ENUM
#include "defsym.h"
#undef MONSYMS_DEFCHAR_ENUM
};
/* clang-format on */

enum mon_syms {
#define MONSYMS_S_ENUM
#include "defsym.h"
#undef MONSYMS_S_ENUM

MAXMCLASSES /* number of monster classes */
};

#ifndef MAKEDEFS_C

/* Default characters for dungeon surroundings and furniture */
enum screen_symbols {
#define PCHAR_S_ENUM
#include "defsym.h"
#undef PCHAR_S_ENUM
MAXPCHARS
};

struct symdef {
uchar sym;
const char *explanation;
#ifdef TEXTCOLOR
uchar color;
#endif
};

enum symparse_range {
SYM_CONTROL = 1, /* start/finish markers */
SYM_PCHAR = 2, /* index into showsyms */
SYM_OC = 3, /* index into oc_syms */
SYM_MON = 4, /* index into monsyms */
SYM_OTH = 5 /* misc */
};

struct symparse {
unsigned range;
int idx;
const char *name;
};

/* linked list of symsets and their characteristics */
struct symsetentry {
struct symsetentry *next; /* next in list */
char *name; /* ptr to symset name */
char *desc; /* ptr to description */
int idx; /* an index value */
int handling; /* known handlers value */
Bitfield(nocolor, 1); /* don't use color if set */
Bitfield(primary, 1); /* restricted for use as primary set */
Bitfield(rogue, 1); /* restricted for use as rogue lev set */
Bitfield(explicitly, 1); /* explicit symset set */
/* 4 free bits */
};

/*
*
*/

#define MAXDCHARS (S_water - S_stone + 1) /* mapped dungeon characters */
#define MAXTCHARS (S_vibrating_square - S_arrow_trap + 1) /* trap chars */
#define MAXECHARS (S_explode9 - S_vbeam + 1) /* mapped effects characters */
#define MAXEXPCHARS 9 /* number of explosion characters */

#define DARKROOMSYM (S_darkroom)

#define is_cmap_trap(i) ((i) >= S_arrow_trap && (i) <= S_polymorph_trap)
#define is_cmap_drawbridge(i) ((i) >= S_vodbridge && (i) <= S_hcdbridge)
#define is_cmap_door(i) ((i) >= S_vodoor && (i) <= S_hcdoor)
#define is_cmap_wall(i) ((i) >= S_stone && (i) <= S_trwall)
#define is_cmap_room(i) ((i) >= S_room && (i) <= S_darkroom)
#define is_cmap_corr(i) ((i) >= S_corr && (i) <= S_litcorr)
#define is_cmap_furniture(i) ((i) >= S_upstair && (i) <= S_fountain)
#define is_cmap_water(i) ((i) == S_pool || (i) == S_water)
#define is_cmap_lava(i) ((i) == S_lava)
#define is_cmap_stairs(i) ((i) == S_upstair || (i) == S_dnstair || \
(i) == S_upladder || (i) == S_dnladder)

/* misc symbol definitions */
enum misc_symbols {
SYM_NOTHING = 0,
SYM_UNEXPLORED = 1,
SYM_BOULDER = 2,
SYM_INVISIBLE = 3,
SYM_PET_OVERRIDE = 4,
SYM_HERO_OVERRIDE = 5,
MAXOTHER
};

/*
* Graphics sets for display symbols
*/
#define DEFAULT_GRAPHICS 0 /* regular characters: '-', '+', &c */
enum graphics_sets {
PRIMARY = 0, /* primary graphics set */
ROGUESET = 1, /* rogue graphics set */
NUM_GRAPHICS
};

/*
* special symbol set handling types ( for invoking callbacks, etc.)
* Must match the order of the known_handlers strings
* in drawing.c
*/

enum symset_handling_types {
H_UNK = 0,
H_IBM = 1,
H_DEC = 2,
H_CURS = 3,
H_MAC = 4 /* obsolete; needed so that the listing of available
* symsets by 'O' can skip it for !MAC_GRAPHICS_ENV */
};

extern const struct symdef defsyms[MAXPCHARS]; /* defaults */
#define WARNCOUNT 6 /* number of different warning levels */
extern const struct symdef def_warnsyms[WARNCOUNT];
#define SYMHANDLING(ht) (g.symset[g.currentgraphics].handling == (ht))

#endif /* !MAKEDEFS_C */
#endif /* SYM_H */

@@ -91,13 +91,13 @@ E int srandom(unsigned int);
#endif
#endif
#else
#if defined(MACOSX)
#if defined(MACOS)
E long lrand48(void);
E void srand48(long);
#else
extern long lrand48(void);
extern void srand48(long);
#endif /* MACOSX */
#endif /* MACOS */
#endif /* BSD || ULTRIX || RANDOM */

#if !defined(BSD) || defined(ultrix)
@@ -117,7 +117,7 @@
*/
/* #define TIMED_DELAY */ /* usleep() */
#endif
#if defined(MACOSX) && !defined(TIMED_DELAY)
#if defined(MACOS) && !defined(TIMED_DELAY)
#define TIMED_DELAY
#endif

@@ -335,7 +335,7 @@
/* the high quality random number routines */
#ifndef USE_ISAAC64
# if defined(BSD) || defined(LINUX) || defined(ULTRIX) || defined(CYGWIN32) \
|| defined(RANDOM) || defined(MACOSX)
|| defined(RANDOM) || defined(MACOS)
# define Rand() random()
# else
# define Rand() lrand48()
@@ -392,7 +392,7 @@
#endif /* LINUX */
#endif /* GNOME_GRAPHICS */

#if defined(MACOSX) && !defined(LIBNH)
#if defined(MACOS) && !defined(LIBNH)
# define RUNTIME_PASTEBUF_SUPPORT
#endif

@@ -405,7 +405,7 @@
#ifdef LINUX
# define DEV_RANDOM "/dev/urandom"
#else
# if defined(BSD) || defined(MACOSX)
# if defined(BSD) || defined(MACOS)
# define DEV_RANDOM "/dev/random"
# endif
#endif
@@ -68,6 +68,7 @@
#define STDC_Pragma_AVAILABLE

#elif defined(_MSC_VER)
#if _MSC_VER > 1916
#define DISABLE_WARNING_UNREACHABLE_CODE \
_Pragma("warning( push )") \
_Pragma("warning( disable : 4702 )")
@@ -81,6 +82,21 @@
#define RESTORE_WARNING_FORMAT_NONLITERAL _Pragma("warning( pop )")
#define RESTORE_WARNINGS _Pragma("warning( pop )")
#define STDC_Pragma_AVAILABLE
#else /* Visual Studio prior to 2019 below */
#define DISABLE_WARNING_UNREACHABLE_CODE \
__pragma(warning(push)) \
__pragma(warning(disable:4702))
#define DISABLE_WARNING_FORMAT_NONLITERAL \
__pragma(warning(push)) \
__pragma(warning(disable:4774))
#define DISABLE_WARNING_CONDEXPR_IS_CONSTANT \
__pragma(warning(push)) \
__pragma(warning(disable:4127))
#define RESTORE_WARNING_CONDEXPR_IS_CONSTANT __pragma(warning(pop))
#define RESTORE_WARNING_FORMAT_NONLITERAL __pragma(warning(pop))
#define RESTORE_WARNINGS __pragma(warning(pop))
#define STDC_Pragma_AVAILABLE
#endif /* vs2019 or vs2017 */

#endif /* various compiler detections */
#endif /* ACTIVATE_WARNING_PRAGMAS */
@@ -12,6 +12,8 @@ extern int orig_cursor; /* Preserve initial cursor state */
extern WINDOW *base_term; /* underlying terminal window */
extern boolean counting; /* Count window is active */
extern WINDOW *mapwin, *statuswin, *messagewin; /* Main windows */
extern WINDOW *activemenu; /* curses window for menu requesting a
* count; affects count_window refresh */

#define TEXTCOLOR /* Allow color */
#define NHW_END 19
@@ -160,7 +162,7 @@ extern void curses_prehousekeeping(void);
extern void curses_posthousekeeping(void);
extern void curses_view_file(const char *filename, boolean must_exist);
extern void curses_rtrim(char *str);
extern int curses_get_count(int first_digit);
extern long curses_get_count(int first_digit);
extern int curses_convert_attr(int attr);
extern int curses_read_attrs(const char *attrs);
extern char *curses_fmt_attrs(char *);
@@ -1,9 +1,9 @@
/* NetHack 3.7 ntconf.h $NHDT-Date: 1596498552 2020/08/03 23:49:12 $ $NHDT-Branch: NetHack-3.7 $:$NHDT-Revision: 1.89 $ */
/* NetHack 3.7 windconf.h $NHDT-Date: 1596498552 2020/08/03 23:49:12 $ $NHDT-Branch: NetHack-3.7 $:$NHDT-Revision: 1.89 $ */
/* Copyright (c) NetHack PC Development Team 1993, 1994. */
/* NetHack may be freely redistributed. See license for details. */

#ifndef NTCONF_H
#define NTCONF_H
#ifndef WINDCONF_H
#define WINDCONF_H

/* #define SHELL */ /* nt use of pcsys routines caused a hang */

@@ -45,7 +45,9 @@
/* #define SHORT_FILENAMES */ /* All NT filesystems support long names now
*/

#ifdef DLB
#define VERSION_IN_DLB_FILENAME /* Append version digits to nhdat */
#endif

#ifdef MICRO
#undef MICRO /* never define this! */
@@ -213,7 +215,7 @@ extern void interject(int);
#define C(c) (0x1f & (c))
#endif

#if defined(DLB)
#if defined(DLB) || defined(_MSC_VER)
#define FILENAME_CMP stricmp /* case insensitive */
#endif

@@ -223,7 +225,7 @@ extern const char *alllevels, *allbones;
#define getuid() 1
#define getlogin() ((char *) 0)
extern void win32_abort(void);
extern void nttty_preference_update(const char *);
extern void consoletty_preference_update(const char *);
extern void toggle_mouse_support(void);
extern void map_subkeyvalue(char *);
#if defined(WIN32CON)
@@ -273,7 +275,7 @@ extern int set_win32_option(const char *, const char *);
extern int alternative_palette(char *);
#endif

#define nethack_enter(argc, argv) nethack_enter_winnt()
#define nethack_enter(argc, argv) nethack_enter_windows()
extern void nethack_exit(int) NORETURN;
extern boolean file_exists(const char *);
extern boolean file_newer(const char *, const char *);
@@ -290,4 +292,4 @@ extern void nt_assert_failed(const char *, const char *, int);
#define nhassert(expression) (void)((!!(expression)) || \
(nt_assert_failed(#expression, __FILE__, __LINE__), 0))

#endif /* NTCONF_H */
#endif /* WINDCONF_H */
@@ -8,7 +8,6 @@
#include "prop.h"
#include "permonst.h"
#include "mondata.h"
#include "pm.h"

/* KMH, intrinsics patch.
* Reorganized and rewritten for >32-bit properties.
@@ -3,7 +3,7 @@ matrix:
include:
- name: linux-xenial-gcc-win-all
os: linux
env: HINTS=linux.2020 LUA_VERSION=5.4.2
env: HINTS=linux.2020 LUA_VERSION=5.4.3
compiler: gcc
addons:
apt:
@@ -21,7 +21,7 @@ matrix:
- make LUA_VERSION=$LUA_VERSION WANT_WIN_ALL=1 QT_SELECT=5 MOC=moc install
- name: linux-bionic-gcc-win-all
os: linux
env: HINTS=linux.2020 LUA_VERSION=5.4.2
env: HINTS=linux.2020 LUA_VERSION=5.4.3
dist: bionic
compiler: gcc
addons:
@@ -40,7 +40,7 @@ matrix:
- make LUA_VERSION=$LUA_VERSION WANT_WIN_ALL=1 QT_SELECT=5 MOC=moc install
- name: linux-focal-clang-win-all
os: linux
env: HINTS=linux.2020 LUA_VERSION=5.4.2
env: HINTS=linux.2020 LUA_VERSION=5.4.3
dist: focal
compiler: clang
addons:
@@ -59,7 +59,7 @@ matrix:
- make LUA_VERSION=$LUA_VERSION WANT_WIN_ALL=1 QT_SELECT=5 MOC=moc install
- name: linux-xenial-gcc-nocommon
os: linux
env: HINTS=linux.2020 LUA_VERSION=5.4.2
env: HINTS=linux.2020 LUA_VERSION=5.4.3
dist: xenial
compiler: gcc
script:
@@ -70,7 +70,7 @@ matrix:
- make install
- name: linux-focal-gcc9-win-all
os: linux
env: HINTS=linux.2020 LUA_VERSION=5.4.2
env: HINTS=linux.2020 LUA_VERSION=5.4.3
dist: focal
compiler: gcc
addons:
@@ -91,7 +91,7 @@ matrix:
- make LUA_VERSION=$LUA_VERSION WANT_WIN_ALL=1 QT_SELECT=5 MOC=moc install
- name: linux-xenial-gcc-minimal
os: linux
env: HINTS=linux-minimal LUA_VERSION=5.4.2
env: HINTS=linux-minimal LUA_VERSION=5.4.3
compiler: gcc
script: |
cd sys/unix/ && sh setup.sh hints/$HINTS && cd ../../
@@ -129,16 +129,16 @@ matrix:
script:
- export ADD_CURSES=Y
- export PDCURSES_TOP=../lib/pdcurses
- export LUA_VERSION=5.4.2
- sh sys/winnt/travis-gcc.sh
- export LUA_VERSION=5.4.3
- sh sys/windows/travis-gcc.sh
- test -d "lib/lua-$LUA_VERSION/src" || exit 0
- test -d "lib/pdcurses" || exit 0
- cd src
- cp ../sys/winnt/Makefile.gcc ./Makefile
- cp ../sys/windows/Makefile.gcc ./Makefile
- mingw32-make LUA_VERSION=$LUA_VERSION install
- name: msdos-linux-focal-djgpp-crosscompile
os: linux
env: HINTS=linux.2020 LUA_VERSION=5.4.2
env: HINTS=linux.2020 LUA_VERSION=5.4.3
dist: focal
compiler: gcc
script:
@@ -180,7 +180,7 @@ extern char hackdir[];
#define getlogin() ((char *) 0)
extern void win32_abort(void);
#ifdef WIN32CON
extern void nttty_preference_update(const char *);
extern void consoletty_preference_update(const char *);
extern void toggle_mouse_support(void);
#endif

@@ -24,7 +24,7 @@ DOC = ..\doc # NetHack documentation files
UTIL = ..\util # Utility source
SRC = ..\src # Main source
SSYS = ..\sys\share # Shared system files
NTSYS = ..\sys\winnt # NT Win32 specific files
NTSYS = ..\sys\windows # NT Win32 specific files
TTY = ..\win\tty # window port files (tty)
WIN32 = ..\win\win32 # window port files (WINCE)
WSHR = ..\win\share # Tile support files
@@ -77,7 +77,7 @@ LEVCFLAGS= -c -nologo -DWINVER=0x0400 -DWIN32 -D_WIN32 \
$(CC) $(CFLAGSU) -Fo$@ $<

#==========================================
# Rules for files in sys\winnt
# Rules for files in sys\windows
#==========================================

{$(NTSYS)}.c{$(OBJ)}.o:
@@ -175,7 +175,7 @@ CONFIG_H = $(INCL)\config.h $(INCL)\config1.h $(INCL)\tradstdc.h \
$(INCL)\system.h $(INCL)\unixconf.h $(INCL)\os2conf.h \
$(INCL)\micro.h $(INCL)\pcconf.h $(INCL)\tosconf.h \
$(INCL)\amiconf.h $(INCL)\macconf.h $(INCL)\beconf.h \
$(INCL)\ntconf.h $(INCL)\wceconf.h
$(INCL)\windconf.h $(INCL)\wceconf.h

HACK_H = $(INCL)\hack.h $(CONFIG_H) $(INCL)\align.h \
$(INCL)\dungeon.h $(INCL)\monsym.h $(INCL)\mkroom.h \
@@ -495,10 +495,10 @@ $(DAT)\dungeon: $(UTIL)\makedefs.exe $(DAT)\dungeon.def
# NT dependencies
#
#
#$(O)nttty.o: $(HACK_H) $(TILE_H) $(INCL)\win32api.h $(NTSYS)\nttty.c
# $(CC) $(CFLAGSU) -I$(WSHR) -Fo$@ $(NTSYS)\nttty.c
#$(O)winnt.o: $(HACK_H) $(INCL)\win32api.h $(NTSYS)\winnt.c
# $(CC) $(CFLAGSU) -Fo$@ $(NTSYS)\winnt.c
#$(O)consoletty.o: $(HACK_H) $(TILE_H) $(INCL)\win32api.h $(NTSYS)\consoletty.c
# $(CC) $(CFLAGSU) -I$(WSHR) -Fo$@ $(NTSYS)\consoletty.c
#$(O)windsys.o: $(HACK_H) $(INCL)\win32api.h $(NTSYS)\windsys.c
# $(CC) $(CFLAGSU) -Fo$@ $(NTSYS)\windsys.c
#$(O)ntsound.o: $(HACK_H) $(NTSYS)\ntsound.c
# $(CC) $(CFLAGSU) -Fo$@ $(NTSYS)\ntsound.c

@@ -12,4 +12,4 @@ graphicschk
nhdat
o
nhdat*

date.nmk

Large diffs are not rendered by default.

@@ -1,4 +1,4 @@
/* NetHack 3.7 apply.c $NHDT-Date: 1621387861 2021/05/19 01:31:01 $ $NHDT-Branch: NetHack-3.7 $:$NHDT-Revision: 1.344 $ */
/* NetHack 3.7 apply.c $NHDT-Date: 1629242800 2021/08/17 23:26:40 $ $NHDT-Branch: NetHack-3.7 $:$NHDT-Revision: 1.347 $ */
/* Copyright (c) Stichting Mathematisch Centrum, Amsterdam, 1985. */
/*-Copyright (c) Robert Patrick Rankin, 2012. */
/* NetHack may be freely redistributed. See license for details. */
@@ -299,7 +299,7 @@ its_dead(int rx, int ry, int *resp, struct obj *stethoscope)
humanoid(mptr) ? "person" : "creature");
what = buf;
} else {
what = pmname(mptr, NEUTRAL);
what = obj_pmname(statue);
if (!type_is_pname(mptr))
what = The(what);
}
@@ -704,6 +704,13 @@ use_leash(struct obj *obj)
pline("%s has no extremities the leash would fit.",
Monnam(mtmp));
} else if (!leashable(mtmp)) {
char lmonbuf[BUFSZ];
char *lmonnam = l_monnam(mtmp);

if (cc.x != mtmp->mx || cc.y != mtmp->my) {
Sprintf(lmonbuf, "%s tail", s_suffix(lmonnam));
lmonnam = lmonbuf;
}
pline("The leash won't fit onto %s.",
spotmon ? y_monnam(mtmp) : l_monnam(mtmp));
} else {
@@ -2083,6 +2090,7 @@ static void
use_tinning_kit(struct obj *obj)
{
struct obj *corpse, *can;
struct permonst *mptr;

/* This takes only 1 move. If this is to be changed to take many
* moves, we've got to deal with decaying corpses...
@@ -2097,29 +2105,28 @@ use_tinning_kit(struct obj *obj)
You("cannot tin %s which is partly eaten.", something);
return;
}
if (touch_petrifies(&mons[corpse->corpsenm]) && !Stone_resistance
&& !uarmg) {
mptr = &mons[corpse->corpsenm];
if (touch_petrifies(mptr) && !Stone_resistance && !uarmg) {
char kbuf[BUFSZ];
const char *corpse_name = an(cxname(corpse));

if (poly_when_stoned(g.youmonst.data))
You("tin %s without wearing gloves.",
an(mons[corpse->corpsenm].pmnames[NEUTRAL]));
else {
if (poly_when_stoned(g.youmonst.data)) {
You("tin %s without wearing gloves.", corpse_name);
} else {
pline("Tinning %s without wearing gloves is a fatal mistake...",
an(mons[corpse->corpsenm].pmnames[NEUTRAL]));
Sprintf(kbuf, "trying to tin %s without gloves",
an(mons[corpse->corpsenm].pmnames[NEUTRAL]));
corpse_name);
Sprintf(kbuf, "trying to tin %s without gloves", corpse_name);
}
instapetrify(kbuf);
}
if (is_rider(&mons[corpse->corpsenm])) {
if (is_rider(mptr)) {
if (revive_corpse(corpse, FALSE))
verbalize("Yes... But War does not preserve its enemies...");
else
pline_The("corpse evades your grasp.");
return;
}
if (mons[corpse->corpsenm].cnutrit == 0) {
if (mptr->cnutrit == 0) {
pline("That's too insubstantial to tin.");
return;
}
@@ -2305,10 +2312,10 @@ fig_transform(anything *arg, long timeout)
char monnambuf[BUFSZ], carriedby[BUFSZ];

if (!figurine) {
debugpline0("null figurine in fig_transform()");
impossible("null figurine in fig_transform()");
return;
}
silent = (timeout != g.monstermoves); /* happened while away */
silent = (timeout != g.moves); /* happened while away */
okay_spot = get_obj_location(figurine, &cc.x, &cc.y, 0);
if (figurine->where == OBJ_INVENT || figurine->where == OBJ_MINVENT)
okay_spot = enexto(&cc, cc.x, cc.y, &mons[figurine->corpsenm]);
@@ -3210,10 +3217,18 @@ use_whip(struct obj *obj)
&& polymon(PM_STONE_GOLEM, POLYMON_ALL_MSGS))) {
char kbuf[BUFSZ];

Sprintf(kbuf, "%s corpse",
an(mons[otmp->corpsenm].pmnames[NEUTRAL]));
Strcpy(kbuf, (otmp->quan == 1L) ? an(onambuf)
: onambuf);
pline("Snatching %s is a fatal mistake.", kbuf);
/* corpse probably has a rot timer but is now
OBJ_FREE; end of game cleanup will panic if
it isn't part of current level; plus it would
be missing from bones, so put it on the floor */
place_object(otmp, u.ux, u.uy); /* but don't stack */

instapetrify(kbuf);
/* life-saved; free the corpse again */
obj_extract_self(otmp);
}
(void) hold_another_object(otmp, "You drop %s!",
doname(otmp), (const char *) 0);
@@ -3874,7 +3889,7 @@ do_break_wand(struct obj *obj)
zapsetup();

/* this makes it hit us last, so that we can see the action first */
for (i = 0; i <= 8; i++) {
for (i = 0; i <= N_DIRS; i++) {
g.bhitpos.x = x = obj->ox + xdir[i];
g.bhitpos.y = y = obj->oy + ydir[i];
if (!isok(x, y))
@@ -1560,7 +1560,7 @@ arti_invoke(struct obj *obj)

if (oart->inv_prop > LAST_PROP) {
/* It's a special power, not "just" a property */
if (obj->age > g.monstermoves) {
if (obj->age > g.moves) {
/* the artifact is tired :-) */
You_feel("that %s %s ignoring you.", the(xname(obj)),
otense(obj, "are"));
@@ -1570,7 +1570,7 @@ arti_invoke(struct obj *obj)
return 1;
}
}
obj->age = g.monstermoves + rnz(100);
obj->age = g.moves + rnz(100);

switch (oart->inv_prop) {
case TAMING: {
@@ -1800,7 +1800,7 @@ arti_invoke(struct obj *obj)
iprop = u.uprops[oart->inv_prop].intrinsic;
boolean on = (eprop & W_ARTI) != 0; /* true if prop just set */

if (on && obj->age > g.monstermoves) {
if (on && obj->age > g.moves) {
/* the artifact is tired :-) */
u.uprops[oart->inv_prop].extrinsic ^= W_ARTI;
You_feel("that %s %s ignoring you.", the(xname(obj)),
@@ -1813,7 +1813,7 @@ arti_invoke(struct obj *obj)
} else if (!on) {
/* when turning off property, determine downtime */
/* arbitrary for now until we can tune this -dlc */
obj->age = g.monstermoves + rnz(100);
obj->age = g.moves + rnz(100);
}

if ((eprop & ~W_ARTI) || iprop) {
@@ -1886,6 +1886,13 @@ finesse_ahriman(struct obj *obj)
boolean
artifact_light(struct obj *obj)
{
/* not artifacts but treat them as if they were because they emit
light without burning */
if (obj && (Is_dragon_armor(obj)
&& Dragon_armor_to_scales(obj) == GOLD_DRAGON_SCALES)
&& (obj->owornmask & (W_ARM | W_ARMC)) != 0L)
return TRUE;

return (boolean) (get_artifact(obj) && obj->oartifact == ART_SUNSWORD);
}

@@ -1,4 +1,4 @@
/* NetHack 3.7 attrib.c $NHDT-Date: 1596498149 2020/08/03 23:42:29 $ $NHDT-Branch: NetHack-3.7 $:$NHDT-Revision: 1.75 $ */
/* NetHack 3.7 attrib.c $NHDT-Date: 1626312521 2021/07/15 01:28:41 $ $NHDT-Branch: NetHack-3.7 $:$NHDT-Revision: 1.79 $ */
/* Copyright 1988, 1989, 1990, 1992, M. Stephenson */
/* NetHack may be freely redistributed. See license for details. */

@@ -677,7 +677,7 @@ redist_attr(void)
if (ABASE(i) < ATTRMIN(i))
ABASE(i) = ATTRMIN(i);
}
(void) encumber_msg();
/* (void) encumber_msg(); -- caller needs to do this */
}

static
@@ -309,10 +309,10 @@ drop_upon_death(struct monst *mtmp, /* monster if hero turned into one (other th
if (!mtmp || is_undead(mtmp->data))
obj_no_longer_held(otmp);

otmp->owornmask = 0L;
/* lamps don't go out when dropped */
if ((cont || artifact_light(otmp)) && obj_is_burning(otmp))
end_burn(otmp, TRUE); /* smother in statue */
otmp->owornmask = 0L;

/* undo any armor weight reduction if it was worn */
otmp->owt = weight(otmp);
@@ -60,6 +60,9 @@ do_statusline1(void)
register char *nb;
register int i, j;

if (suppress_map_output())
return strcpy(newbot1, "");

Strcpy(newbot1, g.plname);
if ('a' <= newbot1[0] && newbot1[0] <= 'z')
newbot1[0] += 'A' - 'a';
@@ -115,6 +118,9 @@ do_statusline2(void)
int hp, hpmax, cap;
long money;

if (suppress_map_output())
return strcpy(newbot2, "");

/*
* Various min(x,9999)'s are to avoid having excessive values
* violate the field width assumptions in botl.h and should not
@@ -247,9 +253,10 @@ do_statusline2(void)
void
bot(void)
{
/* dosave() flags completion by setting u.uhp to -1 */
/* dosave() flags completion by setting u.uhp to -1; supprss_map_output()
covers program_state.restoring and is used for status as well as map */
if (u.uhp != -1 && g.youmonst.data && iflags.status_updates
&& !g.program_state.saving && !g.program_state.restoring) {
&& !g.program_state.saving && !suppress_map_output()) {
if (VIA_WINDOWPORT()) {
bot_via_windowport();
} else {
@@ -262,11 +269,18 @@ bot(void)
g.context.botl = g.context.botlx = iflags.time_botl = FALSE;
}

/* special purpose status update: move counter ('time' status) only */
void
timebot(void)
{
/* we're called when iflags.time_botl is set and general g.context.botl
is clear; iflags.time_botl gets set whenever g.moves changes value
so there's no benefit in tracking previous value to decide whether
to skip update; suppress_map_output() handles program_state.restoring
and program_state.done_hup (tty hangup => no further output at all)
and we use it for maybe skipping status as well as for the map */
if (flags.time && iflags.status_updates
&& !g.program_state.saving && !g.program_state.restoring) {
&& !g.program_state.saving && !suppress_map_output()) {
if (VIA_WINDOWPORT()) {
stat_update_time();
} else {
@@ -888,13 +902,13 @@ bot_via_windowport(void)
#endif
}
}
condtests[bl_blind].test = (Blind);
condtests[bl_blind].test = (Blind) ? TRUE : FALSE;
condtests[bl_conf].test = (Confusion) ? TRUE : FALSE;
condtests[bl_deaf].test = (Deaf);
condtests[bl_fly].test = (Flying);
condtests[bl_glowhands].test = (u.umconf);
condtests[bl_hallu].test = (Hallucination);
condtests[bl_lev].test = (Levitation);
condtests[bl_deaf].test = (Deaf) ? TRUE : FALSE;
condtests[bl_fly].test = (Flying) ? TRUE : FALSE;
condtests[bl_glowhands].test = (u.umconf) ? TRUE : FALSE;
condtests[bl_hallu].test = (Hallucination) ? TRUE : FALSE;
condtests[bl_lev].test = (Levitation) ? TRUE : FALSE;
condtests[bl_ride].test = (u.usteed) ? TRUE : FALSE;
condtests[bl_slime].test = (Slimed) ? TRUE : FALSE;
condtests[bl_stone].test = (Stoned) ? TRUE : FALSE;
@@ -906,7 +920,7 @@ bot_via_windowport(void)
test_if_enabled(bl_bareh) = (!uarmg && !uwep);
test_if_enabled(bl_icy) = (levl[u.ux][u.uy].typ == ICE);
test_if_enabled(bl_slippery) = (Glib) ? TRUE : FALSE;
test_if_enabled(bl_woundedl) = (Wounded_legs);
test_if_enabled(bl_woundedl) = (Wounded_legs) ? TRUE : FALSE;

if (g.multi < 0) {
cond_cache_prepA();
@@ -3612,9 +3626,11 @@ status_hilite_menu_add(int origfld)
goto choose_field;
return FALSE;
}
Sprintf(colorqry, "Choose a color for conditions %s:",
Snprintf(colorqry, sizeof(colorqry),
"Choose a color for conditions %s:",
conditionbitmask2str(cond));
Sprintf(attrqry, "Choose attribute for conditions %s:",
Snprintf(attrqry, sizeof(attrqry),
"Choose attribute for conditions %s:",
conditionbitmask2str(cond));
} else if (behavior == BL_TH_TEXTMATCH) {
char qry_buf[BUFSZ];
576 src/cmd.c

Large diffs are not rendered by default.

@@ -0,0 +1,144 @@
/* NetHack 3.7 date.c $NHDT-Date: 1608933420 2020/12/25 21:57:00 $ $NHDT-Branch: NetHack-3.7 $:$NHDT-Revision: 1.17 $ */
/* Copyright (c) Michael Allison, 2021. */
/* NetHack may be freely redistributed. See license for details. */

#include "config.h"

/* these are in extern.h but we don't include hack.h */
void populate_nomakedefs(struct version_info *);
void free_nomakedefs(void);

#define Snprintf(str, size, ...) \
nh_snprintf(__func__, __LINE__, str, size, __VA_ARGS__)
extern void nh_snprintf(const char *func, int line, char *str, size_t size,
const char *fmt, ...);
extern char *mdlib_version_string(char *, const char *);
extern char *version_id_string(char *, int, const char *);
extern char *bannerc_string(char *, int, const char *);
extern int case_insensitive_comp(const char *, const char *);

struct nomakedefs_s nomakedefs = {
/* https://groups.google.com/forum/#!original/
comp.sources.games/91SfKYg_xzI/dGnR3JnspFkJ */
"Tue, 28-Jul-87 13:18:57 EDT",
"Version 1.0, built Jul 28 13:18:57 1987.",
(const char *) 0, /* git_sha */
(const char *) 0, /* git_branch */
"1.0.0-0",
"NetHack Version 1.0.0-0 - last build Tue Jul 28 13:18:57 1987.",
0x01010000UL,
0x00000000UL,
0x00000000UL,
0x00000000UL,
0x00000000UL,
0x00000000UL,
554476737UL,
};

#if defined(__DATE__) && defined(__TIME__)

#define extract_field(t,s,n,z) \
do { \
for (i = 0; i < n; ++i) \
t[i] = s[i + z]; \
t[i] = '\0'; \
} while (0)

void
populate_nomakedefs(struct version_info *version)
{
int i;
char tmpbuf1[BUFSZ], tmpbuf2[BUFSZ], *strp;
const char *mth[] = {
"Jan", "Feb", "Mar", "Apr", "May", "Jun",
"Jul", "Aug", "Sep", "Oct", "Nov", "Dec"};
struct tm t = {0};
time_t timeresult;
/*
* In a cross-compiled environment, you can't execute
* the target binaries during the build, so we can't
* use makedefs to write the values of the build
* date and time to a file for retrieval. Not for
* information meaningful to the target execution
* environment.
*
* How can we capture the build date/time of the target
* binaries in such a situation? We need to rely on the
* cross-compiler itself to do it for us during the
* cross-compile.
*
* To that end, we are going to make use of the
* following pre-defined preprocessor macros for this:
* gcc, msvc, clang __DATE__ "Feb 12 1996"
* gcc, msvc, clang __TIME__ "23:59:01"
*
*/
/* if (sizeof __DATE__ + sizeof __TIME__ + sizeof "123" <
sizeof tmpbuf1) */
Snprintf(tmpbuf1, sizeof tmpbuf1, "%s %s", __DATE__, __TIME__);
/* "Feb 12 1996 23:59:01"
01234567890123456789 */
if ((int) strlen(tmpbuf1) == 20) {
extract_field(tmpbuf2, tmpbuf1, 4, 7); /* year */
t.tm_year = atoi(tmpbuf2) - 1900;
extract_field(tmpbuf2, tmpbuf1, 3, 0); /* mon */
for (i = 0; i < SIZE(mth); ++i)
if (!case_insensitive_comp(tmpbuf2, mth[i])) {
t.tm_mon = i;
break;
}
extract_field(tmpbuf2, tmpbuf1, 2, 4); /* mday */
strp = tmpbuf2;
if (*strp == ' ')
strp++;
t.tm_mday = atoi(strp);
extract_field(tmpbuf2, tmpbuf1, 2, 12); /* hour */
t.tm_hour = atoi(tmpbuf2);
extract_field(tmpbuf2, tmpbuf1, 2, 15); /* min */
t.tm_min = atoi(tmpbuf2);
extract_field(tmpbuf2, tmpbuf1, 2, 18); /* sec */
t.tm_sec = atoi(tmpbuf2);
timeresult = mktime(&t);
nomakedefs.build_time = (unsigned long) timeresult;
nomakedefs.build_date = strdup(tmpbuf1);
}

nomakedefs.version_number = version->incarnation;
nomakedefs.version_features = version->feature_set;
#ifdef MD_IGNORED_FEATURES
nomakedefs.ignored_features = MD_IGNORED_FEATURES;
#endif
nomakedefs.version_sanity1 = version->entity_count;
nomakedefs.version_sanity2 = version->struct_sizes1;
nomakedefs.version_sanity3 = version->struct_sizes2;
nomakedefs.version_string = strdup(mdlib_version_string(tmpbuf2, "."));
nomakedefs.version_id = strdup(version_id_string(tmpbuf2, sizeof tmpbuf2,
nomakedefs.build_date));
nomakedefs.copyright_banner_c = strdup(bannerc_string(
tmpbuf2, sizeof tmpbuf2,
nomakedefs.build_date));
#ifdef NETHACK_GIT_SHA
nomakedefs.git_sha = strdup(NETHACK_GIT_SHA);
#endif
#ifdef NETHACK_GIT_BRANCH
nomakedefs.git_branch = strdup(NETHACK_GIT_BRANCH);
#endif
}

void
free_nomakedefs(void)
{
if (nomakedefs.build_date)
free((genericptr_t) nomakedefs.build_date);
if (nomakedefs.version_string)
free((genericptr_t) nomakedefs.version_string);
if (nomakedefs.version_id)
free((genericptr_t) nomakedefs.version_id);
if (nomakedefs.copyright_banner_c)
free((genericptr_t) nomakedefs.copyright_banner_c);
}

#endif /* __DATE__ && __TIME__ */


/*date.c*/
@@ -15,10 +15,13 @@ NEARDATA long yn_number = 0L;

const char disclosure_options[] = "iavgco";

/* x/y/z deltas for the 10 movement directions (8 compass pts, 2 up/down) */
const schar xdir[10] = { -1, -1, 0, 1, 1, 1, 0, -1, 0, 0 };
const schar ydir[10] = { 0, -1, -1, -1, 0, 1, 1, 1, 0, 0 };
const schar zdir[10] = { 0, 0, 0, 0, 0, 0, 0, 0, 1, -1 };
/* x/y/z deltas for the 10 movement directions (8 compass pts, 2 down/up) */
const schar xdir[N_DIRS_Z] = { -1, -1, 0, 1, 1, 1, 0, -1, 0, 0 };
const schar ydir[N_DIRS_Z] = { 0, -1, -1, -1, 0, 1, 1, 1, 0, 0 };
const schar zdir[N_DIRS_Z] = { 0, 0, 0, 0, 0, 0, 0, 0, 1, -1 };
/* redordered directions, cardinals first */
const schar dirs_ord[N_DIRS] =
{ DIR_W, DIR_N, DIR_E, DIR_S, DIR_NW, DIR_NE, DIR_SE, DIR_SW };

NEARDATA struct flag flags;
NEARDATA boolean has_strong_rngseed = FALSE;
@@ -200,6 +203,9 @@ const struct Race urace_init_data = {
};

const struct instance_globals g_init = {

NULL, /* command_queue */

/* apply.c */
0, /* jumping_is_magic */
-1, /* polearm_range_min */
@@ -312,7 +318,6 @@ const struct instance_globals g_init = {
NULL, /* subrooms */
UNDEFINED_VALUES, /* level */
1, /* moves */
1, /* monstermoves */
0, /* wailmsg */
NULL, /* migrating_objs */
NULL, /* billobjs */
@@ -511,6 +516,7 @@ const struct instance_globals g_init = {

/* o_init.c */
DUMMY, /* disco */
DUMMY, /* oclass_prob_totals */

/* objname.c */
0, /* distantname */
@@ -1846,6 +1846,8 @@ sokoban_detect(void)
for (y = 0; y < ROWNO; y++) {
levl[x][y].seenv = SVALL;
levl[x][y].waslit = TRUE;
if (levl[x][y].typ == SDOOR)
levl[x][y].wall_info = 0; /* see rm.h for explanation */
map_background(x, y, 1);
if ((obj = sobj_at(BOULDER, x, y)) != 0)
map_object(obj, 1);
@@ -629,6 +629,8 @@ digactualhole(int x, int y, struct monst *madeby, int ttyp)
You("dig a pit in the %s.", surface_type);
if (shopdoor)
pay_for_damage("ruin", FALSE);
else
add_damage(x, y, madeby_u ? SHOP_PIT_COST : 0L);
} else if (!madeby_obj && canseemon(madeby)) {
pline("%s digs a pit in the %s.", Monnam(madeby), surface_type);
} else if (cansee(x, y) && flags.verbose) {
@@ -981,10 +983,11 @@ dig_up_grave(coord *cc)
int
use_pick_axe(struct obj *obj)
{
const char *sdp, *verb;
const char *verb;
char *dsp, dirsyms[12], qbuf[BUFSZ];
boolean ispick;
int rx, ry, downok, res = 0;
int dir;

/* Check tool */
if (obj != uwep) {
@@ -1007,13 +1010,19 @@ use_pick_axe(struct obj *obj)
/* construct list of directions to show player for likely choices */
downok = !!can_reach_floor(FALSE);
dsp = dirsyms;
for (sdp = g.Cmd.dirchars; *sdp; ++sdp) {
for (dir = 0; dir < N_DIRS_Z; dir++) {
char dirch;
if (dir == DIR_DOWN)
dirch = cmd_from_func(dodown);
else if (dir == DIR_UP)
dirch = cmd_from_func(doup);
else
dirch = g.Cmd.move[dir];
/* filter out useless directions */
if (u.uswallow) {
; /* all directions are viable when swallowed */
} else if (movecmd(*sdp)) {
/* normal direction, within plane of the level map;
movecmd() sets u.dx, u.dy, u.dz and returns !u.dz */
} else if (movecmd(dirch, MV_WALK)) {
/* normal direction, within plane of the level map */
if (!dxdy_moveok())
continue; /* handle NODIAG */
rx = u.ux + u.dx;
@@ -1030,7 +1039,7 @@ use_pick_axe(struct obj *obj)
continue;
}
/* include this direction */
*dsp++ = *sdp;
*dsp++ = dirch;
}
*dsp = 0;
Sprintf(qbuf, "In what direction do you want to %s? [%s]", verb, dirsyms);
@@ -1129,15 +1138,10 @@ use_pick_axe2(struct obj *obj)
&& (trap_with_u = t_at(u.ux, u.uy))
&& is_pit(trap->ttyp)
&& !conjoined_pits(trap, trap_with_u, FALSE)) {
int idx;
int idx = xytod(u.dx, u.dy);

for (idx = 0; idx < 8; idx++) {
if (xdir[idx] == u.dx && ydir[idx] == u.dy)
break;
}
/* idx is valid if < 8 */
if (idx < 8) {
int adjidx = (idx + 4) % 8;
if (idx != DIR_ERR) {
int adjidx = DIR_180(idx);

trap_with_u->conjoined |= (1 << idx);
trap->conjoined |= (1 << adjidx);
@@ -1232,8 +1236,10 @@ use_pick_axe2(struct obj *obj)
assign_level(&g.context.digging.level, &u.uz);
g.context.digging.effort = 0;
You("start %s downward.", verbing);
if (*u.ushops)
if (*u.ushops) {
shopdig(0);
add_damage(u.ux, u.uy, SHOP_PIT_COST);
}
} else
You("continue %s downward.", verbing);
g.did_dig_msg = FALSE;
@@ -1494,11 +1500,7 @@ zap_dig(void)
if (u.utrap && u.utraptype == TT_PIT
&& (trap_with_u = t_at(u.ux, u.uy))) {
pitdig = TRUE;
for (diridx = 0; diridx < 8; diridx++) {
if (xdir[diridx] == u.dx && ydir[diridx] == u.dy)
break;
/* diridx is valid if < 8 */
}
diridx = xytod(u.dx, u.dy);
}
digdepth = rn1(18, 8);
tmp_at(DISP_BEAM, cmap_to_glyph(S_digbeam));
@@ -1512,10 +1514,12 @@ zap_dig(void)
if (pitdig) { /* we are already in a pit if this is true */
coord cc;
struct trap *adjpit = t_at(zx, zy);
if ((diridx < 8) && !conjoined_pits(adjpit, trap_with_u, FALSE)) {

if ((diridx != DIR_ERR) && !conjoined_pits(adjpit, trap_with_u, FALSE)) {
digdepth = 0; /* limited to the adjacent location only */
if (!(adjpit && is_pit(adjpit->ttyp))) {
char buf[BUFSZ];

cc.x = zx;
cc.y = zy;
if (!adj_pit_checks(&cc, buf)) {
@@ -1527,9 +1531,9 @@ zap_dig(void)
adjpit = t_at(zx, zy);
}
}
if (adjpit
&& is_pit(adjpit->ttyp)) {
int adjidx = (diridx + 4) % 8;
if (adjpit && is_pit(adjpit->ttyp)) {
int adjidx = DIR_180(diridx);

trap_with_u->conjoined |= (1 << diridx);
adjpit->conjoined |= (1 << adjidx);
flow_x = zx;
@@ -1751,7 +1755,7 @@ pit_flow(struct trap *trap, schar filltyp)
(t.tx == u.ux && t.ty == u.uy)
? "Suddenly %s flows in from the adjacent pit!"
: (char *) 0);
for (idx = 0; idx < 8; ++idx) {
for (idx = 0; idx < N_DIRS; ++idx) {
if (t.conjoined & (1 << idx)) {
int x, y;
struct trap *t2;
@@ -1764,7 +1768,7 @@ pit_flow(struct trap *trap, schar filltyp)
* called deltrap() which cleaned up the
* conjoined fields on both pits.
*/
if (t2 && (t2->conjoined & (1 << ((idx + 4) % 8))))
if (t2 && (t2->conjoined & (1 << DIR_180(idx))))
#endif
/* recursion */
pit_flow(t2, filltyp);
@@ -534,6 +534,20 @@ warning_of(struct monst *mon)
return wl;
}

/* map or status window might not be ready for output during level creation
or game restoration (something like u.usteed which affects display of
the hero and also a status condition might not be set up yet) */
boolean
suppress_map_output(void)
{
if (g.in_mklev || g.program_state.restoring)
return TRUE;
#ifdef HANGUPHANDLING
if (g.program_state.done_hup)
return TRUE;
#endif
return FALSE;
}

/*
* feel_newsym()
@@ -567,6 +581,10 @@ feel_location(xchar x, xchar y)
struct obj *boulder;
register struct monst *mon;

/* replicate safeguards used by newsym(); might not be required here */
if (suppress_map_output())
return;

if (!isok(x, y))
return;
lev = &(levl[x][y]);
@@ -724,12 +742,9 @@ newsym(register int x, register int y)
boolean worm_tail;
register struct rm *lev = &(levl[x][y]);

if (g.in_mklev)
/* don't try to produce map output when level is in a state of flux */
if (suppress_map_output())
return;
#ifdef HANGUPHANDLING
if (g.program_state.done_hup)
return;
#endif

/* only permit updating the hero when swallowed */
if (u.uswallow) {
@@ -1810,6 +1825,7 @@ back_to_defsym(xchar x, xchar y, boolean show_engravings)
{
int idx;
struct rm *ptr = &(levl[x][y]);
struct stairway *sway;

/* aos: most types of terrain shouldn't have engravings override their
* usual symbol. Only boring ones should do that. */
@@ -1871,10 +1887,18 @@ back_to_defsym(xchar x, xchar y, boolean show_engravings)
idx = S_pool;
break;
case STAIRS:
idx = (ptr->ladder & LA_DOWN) ? S_dnstair : S_upstair;
sway = stairway_at(x, y);
if (known_branch_stairs(sway))
idx = (ptr->ladder & LA_DOWN) ? S_brdnstair : S_brupstair;
else
idx = (ptr->ladder & LA_DOWN) ? S_dnstair : S_upstair;
break;
case LADDER:
idx = (ptr->ladder & LA_DOWN) ? S_dnladder : S_upladder;
sway = stairway_at(x, y);
if (known_branch_stairs(sway))
idx = (ptr->ladder & LA_DOWN) ? S_brdnladder : S_brupladder;
else
idx = (ptr->ladder & LA_DOWN) ? S_dnladder : S_upladder;
break;
case FOUNTAIN:
idx = S_fountain;
@@ -2204,7 +2228,7 @@ map_glyphinfo(xchar x, xchar y, int glyph,
special |= MG_STATUE;
if (is_objpile(x,y))
special |= MG_OBJPILE;
if (obj && (obj->spe & STATUE_FEMALE))
if (obj && (obj->spe & CORPSTAT_GENDER) == CORPSTAT_FEMALE)
special |= MG_FEMALE;
} else if ((offset = (glyph - GLYPH_WARNING_OFF)) >= 0) { /* warn flash */
idx = offset + SYM_OFF_W;
100 src/do.c
@@ -1,4 +1,4 @@
/* NetHack 3.7 do.c $NHDT-Date: 1619919402 2021/05/02 01:36:42 $ $NHDT-Branch: NetHack-3.7 $:$NHDT-Revision: 1.267 $ */
/* NetHack 3.7 do.c $NHDT-Date: 1627516694 2021/07/28 23:58:14 $ $NHDT-Branch: NetHack-3.7 $:$NHDT-Revision: 1.270 $ */
/* Copyright (c) Stichting Mathematisch Centrum, Amsterdam, 1985. */
/*-Copyright (c) Derek S. Ray, 2015. */
/* NetHack may be freely redistributed. See license for details. */
@@ -50,6 +50,8 @@ boulder_hits_pool(struct obj *otmp, int rx, int ry, boolean pushing)
const char *what = waterbody_name(rx, ry);
schar ltyp = levl[rx][ry].typ;
int chance = rn2(10); /* water: 90%; lava: 10% */
struct monst *mtmp;

fills_up = lava ? chance == 0 : chance != 0;

if (fills_up) {
@@ -61,6 +63,9 @@ boulder_hits_pool(struct obj *otmp, int rx, int ry, boolean pushing)
} else
levl[rx][ry].typ = ROOM, levl[rx][ry].flags = 0;

if ((mtmp = m_at(rx, ry)) != 0)
mondied(mtmp);

if (ttmp)
(void) delfloortrap(ttmp);
bury_objs(rx, ry);
@@ -128,19 +133,23 @@ flooreffects(struct obj *obj, int x, int y, const char *verb)
struct trap *t;
struct monst *mtmp;
struct obj *otmp;
coord save_bhitpos;
boolean tseen;
int ttyp = NO_TRAP;
int ttyp = NO_TRAP, res = FALSE;

if (obj->where != OBJ_FREE)
panic("flooreffects: obj not free");

/* make sure things like water_damage() have no pointers to follow */
obj->nobj = obj->nexthere = (struct obj *) 0;
/* erode_obj() needs this (called from water_damage() or lava_damage()) */
/* erode_obj() (called from water_damage() or lava_damage()) needs
bhitpos, but that was screwing up wand zapping that called us from
rloco(), so we now restore bhitpos before we return */
save_bhitpos = g.bhitpos;
g.bhitpos.x = x, g.bhitpos.y = y;

if (obj->otyp == BOULDER && boulder_hits_pool(obj, x, y, FALSE)) {
return TRUE;
res = TRUE;
} else if (obj->otyp == BOULDER && (t = t_at(x, y)) != 0
&& (is_pit(t->ttyp) || is_hole(t->ttyp))) {
ttyp = t->ttyp;
@@ -180,7 +189,7 @@ flooreffects(struct obj *obj, int x, int y, const char *verb)
(void) hmon(mtmp, obj, HMON_THROWN, dieroll);
}
if (!DEADMONSTER(mtmp) && !is_whirly(mtmp->data))
return FALSE; /* still alive */
res = FALSE; /* still alive, boulder still intact */
}
mtmp->mtrapped = 0;
} else {
@@ -211,15 +220,15 @@ flooreffects(struct obj *obj, int x, int y, const char *verb)
* Note: trap might have gone away via ((hmon -> killed -> xkilled)
* || mondied) -> mondead -> m_detach -> fill_pit.
*/
deletedwithboulder:
deletedwithboulder:
if ((t = t_at(x, y)) != 0)
deltrap(t);
useupf(obj, 1L);
bury_objs(x, y);
newsym(x, y);
return TRUE;
res = TRUE;
} else if (is_lava(x, y)) {
return lava_damage(obj, x, y);
res = lava_damage(obj, x, y);
} else if (is_pool(x, y)) {
/* Reasonably bulky objects (arbitrary) splash when dropped.
* If you're floating above the water even small things make
@@ -236,17 +245,20 @@ flooreffects(struct obj *obj, int x, int y, const char *verb)
map_background(x, y, 0);
newsym(x, y);
}
return water_damage(obj, NULL, FALSE) == ER_DESTROYED;
res = water_damage(obj, NULL, FALSE) == ER_DESTROYED;
} else if (u.ux == x && u.uy == y && (t = t_at(x, y)) != 0
&& (uteetering_at_seen_pit(t) || uescaped_shaft(t))) {
if (Blind && !Deaf)
You_hear("%s tumble downwards.", the(xname(obj)));
else
pline("%s %s into %s %s.", The(xname(obj)),
otense(obj, "tumble"), the_your[t->madeby_u],
is_pit(t->ttyp) ? "pit" : "hole");
if (is_hole(t->ttyp) && ship_object(obj, x, y, FALSE))
return TRUE;
if (is_pit(t->ttyp)) {
if (Blind && !Deaf)
You_hear("%s tumble downwards.", the(xname(obj)));
else
pline("%s into %s pit.", Tobjnam(obj, "tumble"),
the_your[t->madeby_u]);
} else if (ship_object(obj, x, y, FALSE)) {
/* ship_object will print an appropriate "the item falls
* through the hole" message, so no need to do it here. */
res = TRUE;
}
} else if (obj->globby) {
/* Globby things like puddings might stick together */
while (obj && (otmp = obj_nexto_xy(obj, x, y, TRUE)) != 0) {
@@ -255,9 +267,11 @@ flooreffects(struct obj *obj, int x, int y, const char *verb)
* obj to null. */
(void) obj_meld(&obj, &otmp);
}
return (boolean) !obj;
res = (boolean) !obj;
}
return FALSE;

g.bhitpos = save_bhitpos;
return res;
}

/* obj is an object dropped on an altar */
@@ -1002,8 +1016,8 @@ dodown(void)
for (obj = g.invent; obj; obj = obj->nobj) {
if (obj->oartifact
&& artifact_has_invprop(obj, LEVITATION)) {
if (obj->age < g.monstermoves)
obj->age = g.monstermoves;
if (obj->age < g.moves)
obj->age = g.moves;
obj->age += rnz(100);
}
}
@@ -1276,7 +1290,11 @@ u_collide_m(struct monst *mtmp)
DISABLE_WARNING_FORMAT_NONLITERAL

void
goto_level(d_level *newlevel, boolean at_stairs, boolean falling, boolean portal)
goto_level(
d_level *newlevel, /* destination */
boolean at_stairs, /* True if arriving via stairs/ladder */
boolean falling, /* when fallling to level, objects might tag along */
boolean portal) /* True if arriving via magic portal */
{
int l_idx, save_mode;
NHFILE *nhfp;
@@ -1500,9 +1518,10 @@ goto_level(d_level *newlevel, boolean at_stairs, boolean falling, boolean portal
} else if (at_stairs && !In_endgame(&u.uz)) {
if (up) {
stairway *stway = stairway_find_from(&u.uz0, g.at_ladder);
if (stway)
if (stway) {
u_on_newpos(stway->sx, stway->sy);
else if (newdungeon)
stway->u_traversed = TRUE;
} else if (newdungeon)
u_on_sstairs(1);
else
u_on_dnstairs();
@@ -1517,9 +1536,10 @@ goto_level(d_level *newlevel, boolean at_stairs, boolean falling, boolean portal
g.at_ladder ? "ladder" : "stairs");
} else { /* down */
stairway *stway = stairway_find_from(&u.uz0, g.at_ladder);
if (stway)
if (stway) {
u_on_newpos(stway->sx, stway->sy);
else if (newdungeon)
stway->u_traversed = TRUE;
} else if (newdungeon)
u_on_sstairs(0);
else
u_on_upstairs();
@@ -1812,6 +1832,7 @@ revive_corpse(struct obj *corpse, boolean moldy)
char cname[BUFSZ];
struct obj *container = (struct obj *) 0;
int container_where = 0;
boolean is_zomb = (mons[corpse->corpsenm].mlet == S_ZOMBIE);

where = corpse->where;
is_uwep = (corpse == uwep);
@@ -1912,6 +1933,21 @@ revive_corpse(struct obj *corpse, boolean moldy)
}
break;
}
case OBJ_BURIED:
if (is_zomb) {
maketrap(mtmp->mx, mtmp->my, PIT);
if (cansee(mtmp->mx, mtmp->my)) {
struct trap *ttmp;

ttmp = t_at(mtmp->mx, mtmp->my);
ttmp->tseen = TRUE;
pline("%s claws itself out of the ground!", Amonnam(mtmp));
newsym(mtmp->mx, mtmp->my);
} else if (distu(mtmp->mx, mtmp->my) < 5*5)
You_hear("scratching noises.");
break;
}
/*FALLTHRU*/
default:
/* we should be able to handle the other cases... */
impossible("revive_corpse: lost corpse @ %d", where);
@@ -1958,13 +1994,15 @@ revive_mon(anything *arg, long timeout UNUSED)
action = REVIVE_MON;
when = rider_revival_time(body, TRUE);
} else { /* rot this corpse away */
You_feel("%sless hassled.", is_rider(mptr) ? "much " : "");
if (!obj_has_timer(body, ROT_CORPSE))
You_feel("%sless hassled.", is_rider(mptr) ? "much " : "");
action = ROT_CORPSE;
when = (long) d(5, 50) - (g.monstermoves - body->age);
when = (long) d(5, 50) - (g.moves - body->age);
if (when < 1L)
when = 1L;
}
(void) start_timer(when, TIMER_OBJECT, action, arg);
if (!obj_has_timer(body, action))
(void) start_timer(when, TIMER_OBJECT, action, arg);
}
}

@@ -2010,7 +2048,7 @@ moldy_corpse(anything *arg, long timeout UNUSED)

if (already_fungus || bad_spot || no_eligible || munching) {
/* set to rot away normally */
start_timer(250L - (g.monstermoves - peek_at_iced_corpse_age(body)),
start_timer(250L - (g.moves - peek_at_iced_corpse_age(body)),
TIMER_OBJECT, ROT_CORPSE, arg);
return;
}
@@ -2052,7 +2090,7 @@ moldy_corpse(anything *arg, long timeout UNUSED)
if (old_oname)
ONAME(body) = old_oname;
body->owt = weight(body);
start_timer(250L - (g.monstermoves - peek_at_iced_corpse_age(body)),
start_timer(250L - (g.moves - peek_at_iced_corpse_age(body)),
TIMER_OBJECT, ROT_CORPSE, arg);
}
}
@@ -1,4 +1,4 @@
/* NetHack 3.7 do_name.c $NHDT-Date: 1614818323 2021/03/04 00:38:43 $ $NHDT-Branch: NetHack-3.7 $:$NHDT-Revision: 1.198 $ */
/* NetHack 3.7 do_name.c $NHDT-Date: 1625885761 2021/07/10 02:56:01 $ $NHDT-Branch: NetHack-3.7 $:$NHDT-Revision: 1.213 $ */
/* Copyright (c) Stichting Mathematisch Centrum, Amsterdam, 1985. */
/*-Copyright (c) Pasi Kallinen, 2018. */
/* NetHack may be freely redistributed. See license for details. */
@@ -17,6 +17,7 @@ static void gloc_filter_done(void);
static boolean gather_locs_interesting(int, int, int);
static void gather_locs(coord **, int *, int);
static void auto_describe(int, int);
static void truncate_to_map(int *, int *, schar, schar);
static void do_mgivenname(void);
static boolean alreadynamed(struct monst *, char *, char *);
static void do_oname(struct obj *);
@@ -107,15 +108,23 @@ getpos_help(boolean force, const char *goal)
char sbuf[BUFSZ];
boolean doing_what_is;
winid tmpwin = create_nhwindow(NHW_MENU);
int runkey = iflags.num_pad ? NHKF_RUN2 : NHKF_RUN;
int rushkey = iflags.num_pad ? NHKF_RUSH2 : NHKF_RUSH;

Sprintf(sbuf,
"Use '%c', '%c', '%c', '%c' to move the cursor to %s.", /* hjkl */
g.Cmd.move_W, g.Cmd.move_S, g.Cmd.move_N, g.Cmd.move_E, goal);
"Use '%s', '%s', '%s', '%s' to move the cursor to %s.", /* hjkl */
visctrl(g.Cmd.move[DIR_W]), visctrl(g.Cmd.move[DIR_S]),
visctrl(g.Cmd.move[DIR_N]), visctrl(g.Cmd.move[DIR_E]), goal);
putstr(tmpwin, 0, sbuf);
Sprintf(sbuf,
"Use 'H', 'J', 'K', 'L' to fast-move the cursor, %s.",
"Use '%s', '%s', '%s', '%s' to fast-move the cursor, %s.",
visctrl(g.Cmd.run[DIR_W]), visctrl(g.Cmd.run[DIR_S]),
visctrl(g.Cmd.run[DIR_N]), visctrl(g.Cmd.run[DIR_E]),
fastmovemode[iflags.getloc_moveskip]);
putstr(tmpwin, 0, sbuf);
Sprintf(sbuf, "(or prefix normal move with '%s' or '%s' to fast-move)",
visctrl(g.Cmd.spkeys[runkey]), visctrl(g.Cmd.spkeys[rushkey]));
putstr(tmpwin, 0, sbuf);
putstr(tmpwin, 0, "Or enter a background symbol (ex. '<').");
Sprintf(sbuf, "Use '%s' to move the cursor on yourself.",
visctrl(g.Cmd.spkeys[NHKF_GETPOS_SELF]));
@@ -622,6 +631,29 @@ getpos_menu(coord *ccp, int gloc)
return (pick_cnt > 0);
}

/* add dx,dy to cx,cy, truncating at map edges */
static void
truncate_to_map(int *cx, int *cy, schar dx, schar dy)
{
/* diagonal moves complicate this... */
if (*cx + dx < 1) {
dy -= sgn(dy) * (1 - (*cx + dx));
dx = 1 - *cx; /* so that (cx+dx == 1) */
} else if (*cx + dx > COLNO - 1) {
dy += sgn(dy) * ((COLNO - 1) - (*cx + dx));
dx = (COLNO - 1) - *cx;
}
if (*cy + dy < 0) {
dx -= sgn(dx) * (0 - (*cy + dy));
dy = 0 - *cy; /* so that (cy+dy == 0) */
} else if (*cy + dy > ROWNO - 1) {
dx += sgn(dx) * ((ROWNO - 1) - (*cy + dy));
dy = (ROWNO - 1) - *cy;
}
*cx += dx;
*cy += dy;
}

int
getpos(coord *ccp, boolean force, const char *goal)
{
@@ -659,6 +691,11 @@ getpos(coord *ccp, boolean force, const char *goal)
coord *garr[NUM_GLOCS] = DUMMY;
int gcount[NUM_GLOCS] = DUMMY;
int gidx[NUM_GLOCS] = DUMMY;
schar udx = u.dx, udy = u.dy, udz = u.dz;
int dx, dy;
boolean rushrun = FALSE;
int runkey = iflags.num_pad ? NHKF_RUN2 : NHKF_RUN;
int rushkey = iflags.num_pad ? NHKF_RUSH2 : NHKF_RUSH;

for (i = 0; i < SIZE(pick_chars_def); i++)
pick_chars[i] = g.Cmd.spkeys[pick_chars_def[i].nhkf];
@@ -695,7 +732,10 @@ getpos(coord *ccp, boolean force, const char *goal)
auto_describe(cx, cy);
}

c = nh_poskey(&tx, &ty, &sidx);
rushrun = FALSE;

g.program_state.getting_a_command = 1;
c = readchar_poskey(&tx, &ty, &sidx);

if (hilite_state) {
(*getpos_hilitefunc)(2);
@@ -713,6 +753,10 @@ getpos(coord *ccp, boolean force, const char *goal)
result = -1;
break;
}
if (c == g.Cmd.spkeys[runkey] || c == g.Cmd.spkeys[rushkey]) {
c = readchar_poskey(&tx, &ty, &sidx);
rushrun = TRUE;
}
if (c == 0) {
if (!isok(tx, ty))
continue;
@@ -725,55 +769,35 @@ getpos(coord *ccp, boolean force, const char *goal)
/* '.' => 0, ',' => 1, ';' => 2, ':' => 3 */
result = pick_chars_def[(int) (cp - pick_chars)].ret;
break;
}
for (i = 0; i < 8; i++) {
int dx, dy;

if (g.Cmd.dirchars[i] == c) {
/* a normal movement letter or digit */
dx = xdir[i];
dy = ydir[i];
} else if (g.Cmd.alphadirchars[i] == lowc((char) c)
|| (g.Cmd.num_pad && g.Cmd.dirchars[i] == (c & 0177))) {
/* a shifted movement letter or Meta-digit */
if (iflags.getloc_moveskip) {
/* skip same glyphs */
int glyph = glyph_at(cx, cy);

dx = xdir[i];
dy = ydir[i];
while (isok(cx + dx, cy + dy)
&& glyph == glyph_at(cx + dx, cy + dy)
&& isok(cx + dx + xdir[i], cy + dy + ydir[i])
&& glyph == glyph_at(cx + dx + xdir[i],
cy + dy + ydir[i])) {
dx += xdir[i];
dy += ydir[i];
}
} else {
dx = 8 * xdir[i];
dy = 8 * ydir[i];
}
} else
continue;
} else if (movecmd(c, MV_WALK)) {
if (rushrun)
goto do_rushrun;
dx = u.dx;
dy = u.dy;
truncate_to_map(&cx, &cy, dx, dy);
goto nxtc;
} else if (movecmd(c, MV_RUSH) || movecmd(c, MV_RUN)) {
do_rushrun:
if (iflags.getloc_moveskip) {
/* skip same glyphs */
int glyph = glyph_at(cx, cy);

dx = u.dx;
dy = u.dy;
while (isok(cx + dx, cy + dy)
&& glyph == glyph_at(cx + dx, cy + dy)
&& isok(cx + dx + xdir[i], cy + dy + ydir[i])
&& glyph == glyph_at(cx + dx + xdir[i],
cy + dy + ydir[i])) {
dx += u.dx;
dy += u.dy;

/* truncate at map edge; diagonal moves complicate this... */
if (cx + dx < 1) {
dy -= sgn(dy) * (1 - (cx + dx));
dx = 1 - cx; /* so that (cx+dx == 1) */
} else if (cx + dx > COLNO - 1) {
dy += sgn(dy) * ((COLNO - 1) - (cx + dx));
dx = (COLNO - 1) - cx;
}
if (cy + dy < 0) {
dx -= sgn(dx) * (0 - (cy + dy));
dy = 0 - cy; /* so that (cy+dy == 0) */
} else if (cy + dy > ROWNO - 1) {
dx += sgn(dx) * ((ROWNO - 1) - (cy + dy));
dy = (ROWNO - 1) - cy;
}
} else {
dx = 8 * u.dx;
dy = 8 * u.dy;
}
cx += dx;
cy += dy;
truncate_to_map(&cx, &cy, dx, dy);
goto nxtc;
}

@@ -884,7 +908,12 @@ getpos(coord *ccp, boolean force, const char *goal)
|| glyph_to_cmap(k) == S_corr
|| glyph_to_cmap(k) == S_litcorr)
continue;
if (c == defsyms[sidx].sym || c == (int) g.showsyms[sidx])
if (c == defsyms[sidx].sym
|| c == (int) g.showsyms[sidx]
/* have '^' match webs and vibrating square or any
other trap that uses something other than '^' */
|| (c == '^' && (is_cmap_trap(sidx)
|| sidx == S_vibrating_square)))
matching[sidx] = (char) ++k;
}
if (k) {
@@ -943,7 +972,8 @@ getpos(coord *ccp, boolean force, const char *goal)
Strcpy(note, "aborted");
else /* hjkl */
Sprintf(note, "use '%c', '%c', '%c', '%c' or '%s'",
g.Cmd.move_W, g.Cmd.move_S, g.Cmd.move_N, g.Cmd.move_E,
g.Cmd.move[DIR_W], g.Cmd.move[DIR_S],
g.Cmd.move[DIR_N], g.Cmd.move[DIR_E],
visctrl(g.Cmd.spkeys[NHKF_GETPOS_PICK]));
pline("Unknown direction: '%s' (%s).", visctrl((char) c),
note);
@@ -979,6 +1009,7 @@ getpos(coord *ccp, boolean force, const char *goal)
free((genericptr_t) garr[i]);
getpos_hilitefunc = (void (*)(int)) 0;
getpos_getvalid = (boolean (*)(int, int)) 0;
u.dx = udx, u.dy = udy, u.dz = udz;
return result;
}

@@ -1750,14 +1781,19 @@ rndghostname(void)
* options works, since those are special cases.
*/
char *
x_monnam(register struct monst *mtmp, int article,
const char *adjective, int suppress, boolean called)
x_monnam(
struct monst *mtmp,
int article,
const char *adjective,
int suppress,
boolean called)
{
char *buf = nextmbuf();
struct permonst *mdat = mtmp->data;
const char *pm_name = pmname(mdat, Mgender(mtmp));
const char *pm_name = mon_pmname(mtmp);
boolean do_hallu, do_invis, do_it, do_saddle, do_name;
boolean name_at_start, has_adjectives;
boolean name_at_start, has_adjectives,
falseCap = (*pm_name != lowc(*pm_name));
char *bp;

if (g.program_state.gameover)
@@ -1793,7 +1829,7 @@ x_monnam(register struct monst *mtmp, int article,
EHalluc_resistance = 1L;
if (!do_invis)
mtmp->minvis = 0;
name = priestname(mtmp, priestnambuf);
name = priestname(mtmp, article, priestnambuf);
EHalluc_resistance = save_prop;
mtmp->minvis = save_invis;
if (article == ARTICLE_NONE && !strncmp(name, "the ", 4))
@@ -1896,11 +1932,21 @@ x_monnam(register struct monst *mtmp, int article,
article = ARTICLE_THE;
else
article = ARTICLE_NONE;
} else if ((mdat->geno & G_UNIQ) && article == ARTICLE_A) {
} else if ((mdat->geno & G_UNIQ) != 0 && article == ARTICLE_A) {
article = ARTICLE_THE;
}

{
if (article == ARTICLE_A && falseCap && !name_at_start) {
char buf2[BUFSZ], buf3[BUFSZ];

/* some type names like "Archon", "Green-elf", and "Uruk-hai" fool
an() because of the capitalization and would result in "the " */
Strcpy(buf3, buf);
*buf3 = lowc(*buf3);
(void) just_an(buf2, buf3);
Strcat(buf2, buf);
return strcpy(buf, buf2);
} else {
char buf2[BUFSZ];

switch (article) {
@@ -2141,7 +2187,7 @@ minimal_monnam(struct monst *mon, boolean ckloc)
} else {
Sprintf(outbuf, "%s%s <%d,%d>",
mon->mtame ? "tame " : mon->mpeaceful ? "peaceful " : "",
pmname(mon->data, Mgender(mon)), mon->mx, mon->my);
mon_pmname(mon), mon->mx, mon->my);
if (mon->cham != NON_PM)
Sprintf(eos(outbuf), "{%s}",
pmname(&mons[mon->cham], Mgender(mon)));
@@ -2167,13 +2213,48 @@ Mgender(struct monst *mtmp)
const char *
pmname(struct permonst *pm, int mgender)
{
if ((mgender >= MALE && mgender < NUM_MGENDERS) && pm->pmnames[mgender])
return pm->pmnames[mgender];
else
return pm->pmnames[NEUTRAL];
if (mgender < MALE || mgender >= NUM_MGENDERS || !pm->pmnames[mgender])
mgender = NEUTRAL;
return pm->pmnames[mgender];
}
#endif /* PMNAME_MACROS */

/* mons[]->pmname for a monster */
const char *
mon_pmname(struct monst *mon)
{
/* for neuter, mon->data->pmnames[MALE] will be Null and use [NEUTRAL] */
return pmname(mon->data, mon->female ? FEMALE : MALE);
}

/* mons[]->pmname for a corpse or statue or figurine */
const char *
obj_pmname(struct obj *obj)
{
#if 0 /* ignore saved montraits even when they're available; they determine
* what a corpse would revive as if resurrected (human corpse from
* slain vampire revives as vampire rather than as human, for example)
* and don't necessarily reflect the state of the corpse itself */
if (has_omonst(obj)) {
struct monst *m = OMONST(obj);

/* obj->oextra->omonst->data is Null but ...->mnum is set */
if (m->mnum >= LOW_PM)
return pmname(&mons[m->mnum], m->female ? FEMALE : MALE);
}
#endif
if ((obj->otyp == CORPSE || obj->otyp == STATUE || obj->otyp == FIGURINE)
&& obj->corpsenm >= LOW_PM) {
int cgend = (obj->spe & CORPSTAT_GENDER),
mgend = ((cgend == CORPSTAT_MALE) ? MALE
: (cgend == CORPSTAT_FEMALE) ? FEMALE
: NEUTRAL);

return pmname(&mons[obj->corpsenm], mgend);
}
return "two-legged glorkum-seeker";
}

/* fake monsters used to be in a hard-coded array, now in a data file
* The which parameter is passed along to get_rnd_text and represents the line
* of BOGUSMONFILE to return. Specify -1 for a random one. */
@@ -2440,6 +2521,10 @@ lookup_novel(const char *lookname, int *idx)
lookname = "Sourcery"; /* [4] */
else if (!strcmpi(lookname, "Masquerade"))
lookname = "Maskerade"; /* [17] */
else if (!strcmpi(The(lookname), "The Amazing Maurice"))
lookname = "The Amazing Maurice and His Educated Rodents"; /* [27] */
else if (!strcmpi(lookname, "Thud"))
lookname = "Thud!"; /* [33] */

for (k = 0; k < SIZE(sir_Terry_novels); ++k) {
if (!strcmpi(lookname, sir_Terry_novels[k])
@@ -48,6 +48,7 @@ static int remove_ok(struct obj *);
static int wear_ok(struct obj *);
static int takeoff_ok(struct obj *);
static int wornmask_to_bodypart(int);
static void toggle_armor_light(struct obj *, boolean);

/* plural "fingers" or optionally "gloves" */
const char *
@@ -370,6 +371,7 @@ Cloak_on(void)
}
if (uarmc) /* no known instance of !uarmc here but play it safe */
uarmc->known = 1; /* cloak's +/- evident because of status line AC */
toggle_armor_light(uarmc, TRUE);
return 0;
}

@@ -379,6 +381,7 @@ Cloak_off(void)
struct obj *otmp = uarmc;
int otyp = otmp->otyp;
long oldprop = u.uprops[objects[otyp].oc_oprop].extrinsic & ~WORN_CLOAK;
boolean was_arti_light = otmp && otmp->lamplit && artifact_light(otmp);

if (Is_dragon_scales(uarmc)) {
/* all scales are handled the same in this function */
@@ -427,6 +430,8 @@ Cloak_off(void)
default:
impossible(unknown_type, c_cloak, otyp);
}
if (was_arti_light)
toggle_armor_light(otmp, FALSE);
return 0;
}

@@ -760,22 +765,26 @@ Armor_on(void)
{
cursed_gear_welds(uarm);

/*
* No suits require special handling. Special properties conferred by
* suits are set up as intrinsics (actually 'extrinsics') by setworn()
* which is called by armor_or_accessory_on() before Armor_on().
*/
if (uarm) /* no known instances of !uarm here but play it safe */
uarm->known = 1; /* suit's +/- evident because of status line AC */
if (!uarm) /* no known instances of !uarm here but play it safe */
return 0;
uarm->known = 1; /* suit's +/- evident because of status line AC */
toggle_armor_light(uarm, TRUE);

return 0;
}

int
Armor_off(void)
{
struct obj *otmp = uarm;
boolean was_arti_light = otmp && otmp->lamplit && artifact_light(otmp);

g.context.takeoff.mask &= ~W_ARM;
setworn((struct obj *) 0, W_ARM);
g.context.takeoff.cancelled_don = FALSE;

if (was_arti_light)
toggle_armor_light(otmp, FALSE);
return 0;
}

@@ -788,9 +797,18 @@ Armor_off(void)
int
Armor_gone(void)
{
struct obj *otmp = uarm;
boolean was_arti_light = otmp && otmp->lamplit && artifact_light(otmp);

g.context.takeoff.mask &= ~W_ARM;
setnotworn(uarm);
g.context.takeoff.cancelled_don = FALSE;

if (was_arti_light && !artifact_light(otmp)) {
end_burn(otmp, FALSE);
if (!Blind)
pline("%s shining.", Tobjnam(otmp, "stop"));
}
return 0;
}

@@ -2366,11 +2384,13 @@ glibr(void)
otmp = uleft;
Ring_off(uleft);
dropx(otmp);
cmdq_clear();
}
if (rightfall) {
otmp = uright;
Ring_off(uright);
dropx(otmp);
cmdq_clear();
}
}

@@ -2391,6 +2411,7 @@ glibr(void)
xfl++;
wastwoweap = TRUE;
setuswapwep((struct obj *) 0); /* clears u.twoweap */
cmdq_clear();
if (canletgo(otmp, ""))
dropx(otmp);
}
@@ -2426,6 +2447,7 @@ glibr(void)
/* xfl++; */
otmp->quan = savequan;
setuwep((struct obj *) 0);
cmdq_clear();
if (canletgo(otmp, ""))
dropx(otmp);
}
@@ -2919,6 +2941,10 @@ destroy_arm(register struct obj *atmp, boolean choose)
} else if (DESTROY_ARM(uarm)) {
if (donning(otmp))
cancel_don();
/* for gold DSM, we don't want Armor_gone() to report that it
stops shining _after_ we've been told that it is destroyed */
if (otmp->lamplit)
end_burn(otmp, FALSE);
Your("armor turns to dust and falls to the %s!", surface(u.ux, u.uy));
(void) Armor_gone();
useup(otmp);
@@ -3137,4 +3163,28 @@ takeoff_ok(struct obj *obj)
return equip_ok(obj, TRUE, FALSE);
}

/* hero is putting on or taking off obj, which may do something light-related
* unifies code for cloak and body armor code paths since gold dragon scales are
* worn in cloak slot and gold-scaled armor is worn in armor slot*/
static void
toggle_armor_light(struct obj *armor, boolean on)
{
if (on) {
if (artifact_light(armor) && !armor->lamplit) {
begin_burn(armor, FALSE);
if (!Blind)
pline("%s %s to shine %s!",
Yname2(armor), otense(armor, "begin"),
arti_light_description(armor));
}
}
else {
if (!artifact_light(armor)) {
end_burn(armor, FALSE);
if (!Blind)
pline("%s shining.", Tobjnam(armor, "stop"));
}
}
}

/*do_wear.c*/
@@ -41,7 +41,7 @@ initedog(struct monst *mtmp)
EDOG(mtmp)->dropdist = 10000;
EDOG(mtmp)->apport = ACURR(A_CHA);
EDOG(mtmp)->whistletime = 0;
EDOG(mtmp)->hungrytime = 1000 + g.monstermoves;
EDOG(mtmp)->hungrytime = 1000 + g.moves;
EDOG(mtmp)->ogoal.x = -1; /* force error if used before set */
EDOG(mtmp)->ogoal.y = -1;
EDOG(mtmp)->abuse = 0;
@@ -71,9 +71,11 @@ make_familiar(struct obj *otmp, xchar x, xchar y, boolean quietly)
int chance, trycnt = 100;

do {
if (otmp) { /* figurine; otherwise spell */
int mndx = otmp->corpsenm;
long mmflags;
int cgend, mndx;

if (otmp) { /* figurine; otherwise spell */
mndx = otmp->corpsenm;
pm = &mons[mndx];
/* activating a figurine provides one way to exceed the
maximum number of the target critter created--unless
@@ -97,7 +99,12 @@ make_familiar(struct obj *otmp, xchar x, xchar y, boolean quietly)
}
}

mtmp = makemon(pm, x, y, MM_EDOG | MM_IGNOREWATER | NO_MINVENT);
mmflags = MM_EDOG | MM_IGNOREWATER | NO_MINVENT;
cgend = otmp ? (otmp->spe & CORPSTAT_GENDER) : 0;
mmflags |= ((cgend == CORPSTAT_FEMALE) ? MM_FEMALE
: (cgend == CORPSTAT_MALE) ? MM_MALE : 0L);

mtmp = makemon(pm, x, y, mmflags);
if (otmp && !mtmp) { /* monster was genocided or square occupied */
if (!quietly)
pline_The("figurine writhes and then shatters into pieces!");
@@ -209,7 +216,7 @@ update_mlstmv(void)
for (mon = fmon; mon; mon = mon->nmon) {
if (DEADMONSTER(mon))
continue;
mon->mlstmv = g.monstermoves;
mon->mlstmv = g.moves;
}
}

@@ -356,12 +363,12 @@ mon_arrive(struct monst *mtmp, boolean with_you)
* specify its final destination.
*/

if (mtmp->mlstmv < g.monstermoves - 1L) {
if (mtmp->mlstmv < g.moves - 1L) {
/* heal monster for time spent in limbo */
long nmv = g.monstermoves - 1L - mtmp->mlstmv;
long nmv = g.moves - 1L - mtmp->mlstmv;

mon_catchup_elapsed_time(mtmp, nmv);
mtmp->mlstmv = g.monstermoves - 1L;
mtmp->mlstmv = g.moves - 1L;

/* let monster move a bit on new level (see placement code below) */
wander = (xchar) min(nmv, 8);
@@ -563,8 +570,8 @@ mon_catchup_elapsed_time(struct monst *mtmp,
&& (carnivorous(mtmp->data) || herbivorous(mtmp->data))) {
struct edog *edog = EDOG(mtmp);

if ((g.monstermoves > edog->hungrytime + 500 && mtmp->mhp < 3)
|| (g.monstermoves > edog->hungrytime + 750))
if ((g.moves > edog->hungrytime + 500 && mtmp->mhp < 3)
|| (g.moves > edog->hungrytime + 750))
mtmp->mtame = mtmp->mpeaceful = 0;
}

@@ -689,7 +696,7 @@ keepdogs(boolean pets_only, /* true for ascension or final escape */
relmon(mtmp, &g.mydogs); /* move it from map to g.mydogs */
mtmp->mx = mtmp->my = 0; /* avoid mnexto()/MON_AT() problem */
mtmp->wormno = num_segs;
mtmp->mlstmv = g.monstermoves;
mtmp->mlstmv = g.moves;
} else if (mtmp->iswiz) {
/* we want to be able to find him when his next resurrection
chance comes up, but have him resume his present location
@@ -751,7 +758,7 @@ migrate_to_level(struct monst *mtmp,
if (In_W_tower(mtmp->mx, mtmp->my, &u.uz))
xyflags |= 2;
mtmp->wormno = num_segs;
mtmp->mlstmv = g.monstermoves;
mtmp->mlstmv = g.moves;
mtmp->mtrack[2].x = u.uz.dnum; /* migrating from this dungeon */
mtmp->mtrack[2].y = u.uz.dlevel; /* migrating from this dungeon level */
mtmp->mtrack[1].x = cc ? cc->x : mtmp->mx;
@@ -807,7 +814,7 @@ dogfood(struct monst *mon, struct obj *obj)
when starving; they never eat stone-to-flesh'd meat */
if (mptr == &mons[PM_GHOUL]) {
if (obj->otyp == CORPSE)
return (peek_at_iced_corpse_age(obj) + 50L <= g.monstermoves
return (peek_at_iced_corpse_age(obj) + 50L <= g.moves
&& fptr != &mons[PM_LIZARD]
&& fptr != &mons[PM_LICHEN])
? DOGFOOD
@@ -829,7 +836,7 @@ dogfood(struct monst *mon, struct obj *obj)
case EGG:
return carni ? CADAVER : MANFOOD;
case CORPSE:
if ((peek_at_iced_corpse_age(obj) + 50L <= g.monstermoves
if ((peek_at_iced_corpse_age(obj) + 50L <= g.moves
&& obj->corpsenm != PM_LIZARD && obj->corpsenm != PM_LICHEN
&& mptr->mlet != S_FUNGUS)
|| (acidic(fptr) && !resists_acid(mon))
@@ -945,7 +952,7 @@ tamedog(struct monst *mtmp, struct obj *obj, boolean pacify_only)
if (mtmp->mcanmove && !mtmp->mconf && !mtmp->meating
&& ((tasty = dogfood(mtmp, obj)) == DOGFOOD
|| (tasty <= ACCFOOD
&& EDOG(mtmp)->hungrytime <= g.monstermoves))) {
&& EDOG(mtmp)->hungrytime <= g.moves))) {
/* pet will "catch" and eat this thrown food */
if (canseemon(mtmp)) {
boolean big_corpse =
@@ -1068,8 +1075,8 @@ wary_dog(struct monst *mtmp, boolean was_dead)
edog->killed_by_u = 0;
edog->abuse = 0;
edog->ogoal.x = edog->ogoal.y = -1;
if (was_dead || edog->hungrytime < g.monstermoves + 500L)
edog->hungrytime = g.monstermoves + 500L;
if (was_dead || edog->hungrytime < g.moves + 500L)
edog->hungrytime = g.moves + 500L;
if (was_dead) {
edog->droptime = 0L;
edog->dropdist = 10000;
@@ -214,8 +214,8 @@ dog_eat(struct monst *mtmp,
char objnambuf[BUFSZ];

objnambuf[0] = '\0';
if (edog->hungrytime < g.monstermoves)
edog->hungrytime = g.monstermoves;
if (edog->hungrytime < g.moves)
edog->hungrytime = g.moves;
nutrit = dog_nutrition(mtmp, obj);

deadmimic = (obj->otyp == CORPSE && (obj->corpsenm == PM_SMALL_MIMIC
@@ -296,7 +296,7 @@ dog_eat(struct monst *mtmp,
#ifdef LINT
edog->apport = 0;
#else
edog->apport += (int) (200L / ((long) edog->dropdist + g.monstermoves
edog->apport += (int) (200L / ((long) edog->dropdist + g.moves
- edog->droptime));
#endif
if (mtmp->data == &mons[PM_RUST_MONSTER] && obj->oerodeproof) {
@@ -362,9 +362,9 @@ dog_eat(struct monst *mtmp,
static boolean
dog_hunger(struct monst *mtmp, struct edog *edog)
{
if (g.monstermoves > edog->hungrytime + 500) {
if (g.moves > edog->hungrytime + 500) {
if (!carnivorous(mtmp->data) && !herbivorous(mtmp->data)) {
edog->hungrytime = g.monstermoves + 500;
edog->hungrytime = g.moves + 500;
/* but not too high; it might polymorph */
} else if (!edog->mhpmax_penalty) {
/* starving pets are limited in healing */
@@ -383,7 +383,7 @@ dog_hunger(struct monst *mtmp, struct edog *edog)
else
You_feel("worried about %s.", y_monnam(mtmp));
stop_occupation();
} else if (g.monstermoves > edog->hungrytime + 750
} else if (g.moves > edog->hungrytime + 750
|| DEADMONSTER(mtmp)) {
dog_died:
if (mtmp->mleashed && mtmp != u.usteed)
@@ -426,7 +426,7 @@ dog_invent(struct monst *mtmp, struct edog *edog, int udist)
if (edog->apport > 1)
edog->apport--;
edog->dropdist = udist; /* hpscdi!jon */
edog->droptime = g.monstermoves;
edog->droptime = g.moves;
}
} else {
if ((obj = g.level.objects[omx][omy]) != 0
@@ -441,7 +441,7 @@ dog_invent(struct monst *mtmp, struct edog *edog, int udist)
/* starving pet is more aggressive about eating */
|| (edog->mhpmax_penalty && edible == ACCFOOD))
&& could_reach_item(mtmp, obj->ox, obj->oy)
&& edog->hungrytime < g.monstermoves + DOG_SATIATED)
&& edog->hungrytime < g.moves + DOG_SATIATED)
return dog_eat(mtmp, obj, omx, omy, FALSE);

carryamt = can_carry(mtmp, obj);
@@ -534,8 +534,8 @@ dog_goal(register struct monst *mtmp, struct edog *edog,
|| !can_reach_location(mtmp, mtmp->mx, mtmp->my, nx, ny))
continue;
if (otyp < MANFOOD
&& (otyp < ACCFOOD || edog->hungrytime <= g.monstermoves)
&& edog->hungrytime < g.monstermoves + DOG_SATIATED) {
&& (otyp < ACCFOOD || edog->hungrytime <= g.moves)
&& edog->hungrytime < g.moves + DOG_SATIATED) {
if (otyp < g.gtyp || DDIST(nx, ny) < DDIST(g.gx, g.gy)) {
g.gx = nx;
g.gy = ny;
@@ -557,7 +557,7 @@ dog_goal(register struct monst *mtmp, struct edog *edog,

/* follow player if appropriate */
if (g.gtyp == UNDEF || (g.gtyp != DOGFOOD && g.gtyp != APPORT
&& g.monstermoves < edog->hungrytime)) {
&& g.moves < edog->hungrytime)) {
g.gx = u.ux;
g.gy = u.uy;
if (after && udist <= 4 && g.gx == u.ux && g.gy == u.uy)
@@ -917,7 +917,7 @@ dog_move(register struct monst *mtmp,
else if (j == 1)
goto newdogpos; /* eating something */

whappr = (g.monstermoves - edog->whistletime < 5);
whappr = (g.moves - edog->whistletime < 5);
} else
whappr = 0;

@@ -1031,7 +1031,7 @@ dog_move(register struct monst *mtmp,
return 2;

if ((mstatus & MM_HIT) && !(mstatus & MM_DEF_DIED) && rn2(4)
&& mtmp2->mlstmv != g.monstermoves
&& mtmp2->mlstmv != g.moves
&& !onscary(mtmp->mx, mtmp->my, mtmp2)
/* monnear check needed: long worms hit on tail */
&& monnear(mtmp2, mtmp->mx, mtmp->my)) {
@@ -1083,9 +1083,8 @@ dog_move(register struct monst *mtmp,
if (obj->cursed) {
cursemsg[i] = TRUE;
} else if ((otyp = dogfood(mtmp, obj)) < MANFOOD
&& (otyp < ACCFOOD
|| edog->hungrytime <= g.monstermoves)
&& edog->hungrytime < g.monstermoves + DOG_SATIATED) {
&& (otyp < ACCFOOD || edog->hungrytime <= g.moves)
&& edog->hungrytime < g.moves + DOG_SATIATED) {
/* Note: our dog likes the food so much that he
* might eat it even when it conceals a cursed object */
nix = nx;
@@ -1141,7 +1140,7 @@ dog_move(register struct monst *mtmp,
if (!mtmp->isminion) {
struct edog *dog = EDOG(mtmp);

hungry = (g.monstermoves > (dog->hungrytime + 300));
hungry = (g.moves > (dog->hungrytime + 300));
}

/* Identify the best target in a straight line from the pet;
@@ -1270,12 +1269,12 @@ dog_move(register struct monst *mtmp,
goto dognext;

i = xytod(nx, ny);
for (j = (i + 7) % 8; j < (i + 1) % 8; j++) {
for (j = DIR_LEFT(i); j < DIR_RIGHT(i); j++) {
dtoxy(&cc, j);
if (goodpos(cc.x, cc.y, mtmp, 0))
goto dognext;
}
for (j = (i + 6) % 8; j < (i + 2) % 8; j++) {
for (j = DIR_LEFT2(i); j < DIR_RIGHT2(i); j++) {
dtoxy(&cc, j);
if (goodpos(cc.x, cc.y, mtmp, 0))
goto dognext;
@@ -1380,7 +1379,7 @@ finish_meating(struct monst *mtmp)
mtmp->meating = 0;
if (M_AP_TYPE(mtmp) && mtmp->mappearance && mtmp->cham == NON_PM) {
/* was eating a mimic and now appearance needs resetting */
mtmp->m_ap_type = 0;
mtmp->m_ap_type = M_AP_NOTHING;
mtmp->mappearance = 0;
newsym(mtmp->mx, mtmp->my);
}
@@ -1,4 +1,4 @@
/* NetHack 3.7 dokick.c $NHDT-Date: 1608673689 2020/12/22 21:48:09 $ $NHDT-Branch: NetHack-3.7 $:$NHDT-Revision: 1.162 $ */
/* NetHack 3.7 dokick.c $NHDT-Date: 1625963851 2021/07/11 00:37:31 $ $NHDT-Branch: NetHack-3.7 $:$NHDT-Revision: 1.167 $ */
/* Copyright (c) Izchak Miller, Mike Stephenson, Steve Linhart, 1989. */
/* NetHack may be freely redistributed. See license for details. */

@@ -665,9 +665,10 @@ really_kick_object(xchar x, xchar y)
"send coins flying in all directions",
};

pline("Thwwpingg!");
if (!Deaf)
pline1("Thwwpingg!");
You("%s!", flyingcoinmsg[rn2(SIZE(flyingcoinmsg))]);
(void) scatter(x, y, rn2(3) + 1, VIS_EFFECTS | MAY_HIT,
(void) scatter(x, y, rnd(3), VIS_EFFECTS | MAY_HIT,
g.kickedobj);
newsym(x, y);
return 1;
@@ -713,7 +714,7 @@ really_kick_object(xchar x, xchar y)
if (costly && (!costly_spot(g.bhitpos.x, g.bhitpos.y)
|| *in_rooms(x, y, SHOPBASE) != bhitroom)) {
if (isgold)
costly_gold(x, y, g.kickedobj->quan);
costly_gold(x, y, g.kickedobj->quan, FALSE);
else
(void) stolen_value(g.kickedobj, x, y, (boolean) shkp->mpeaceful,
FALSE);
@@ -11,6 +11,7 @@ static int throw_obj(struct obj *, int);
static boolean ok_to_throw(int *);
static int throw_ok(struct obj *);
static void autoquiver(void);
static struct obj *find_launcher(struct obj *);
static int gem_accept(struct monst *, struct obj *);
static void tmiss(struct obj *, struct monst *, boolean);
static int throw_gold(struct obj *);
@@ -407,6 +408,23 @@ autoquiver(void)
return;
}

/* look through hero inventory for launcher matching ammo,
avoiding known cursed items. Returns NULL if no match. */
static struct obj *
find_launcher(struct obj *ammo)
{
struct obj *otmp;

if (!ammo)
return (struct obj *)0;

for (otmp = g.invent; otmp; otmp = otmp->nobj)
if (ammo_and_launcher(ammo, otmp) && !(otmp->cursed && otmp->bknown))
return otmp;

return (struct obj *)0;
}

/* f command -- fire: throw from the quiver */
int
dofire(void)
@@ -471,6 +489,28 @@ dofire(void)
}
}

if (uquiver && iflags.fireassist) {
struct obj *olauncher;

/* Try to find a launcher */
if (ammo_and_launcher(uquiver, uwep)) {
/* Do nothing, already wielding a launcher */
} else if (ammo_and_launcher(uquiver, uswapwep)) {
/* swap weapons and retry fire */
cmdq_add_ec(doswapweapon);
cmdq_add_ec(dofire);
return 0;
} else if ((olauncher = find_launcher(obj)) != 0) {
/* wield launcher, retry fire */
if (uwep && !flags.pushweapon)
cmdq_add_ec(doswapweapon);
cmdq_add_ec(dowield);
cmdq_add_key(olauncher->invlet);
cmdq_add_ec(dofire);
return 0;
}
}

return obj ? throw_obj(obj, shotlimit) : 0;
}