This is the second of a series of changes related to save/restore.
No EDITLEVEL bump has been included, because although the code
is changed extensively by this, the content of the savefiles have
not been changed.
Push the use of the structlevel bwrite() and mread() function use
out of the core and into sfstruct.c. This is groundwork for upcoming
changes.
In the core, replace the bwrite() and mread() calls with the
use of type-specific savefile output (Sfo) and savefile
input (Sfi) macros. The macros are defined in a new header file
savefile.h, which also contains the prototypes for the sfo_* and
sfi_* functions that the macros ultimately expand to. The functions
themselves are in src/sfbase.c.
On C99, each Sfo or Sfi macro expansion refers directly to the
corresponding type-specific sfo_* or sfi_* function.
If C23 or later is is use, the majority (all but 3 types) of the
macros refer to a single _Generic output routine sfo(nhfp, dt, tag),
and a single _Generic input routine sfi(nhfp, dt, tag), which handles
the dispatch of the type-specific underlying functions. This was
somewhat experimental, but turned out to be practical because the
compiler would gripe if the type for a variable was not included in
the _Generic when passed as an argument, so it could be fixed.
This alters the savefile verication process by having a common set
return values for the related functions such as uptodate(),
check_version(), etc. The new return values return more information
about savefile incompatibilities, beyond failure/sucess. The
additional information will be useful for an upcoming addition.
The expanded return values are:
SF_UPTODATE (0) everything matched and looks good
SF_OUTDATED (1) savefile is outdated
SF_CRITICAL_BYTE_COUNT_MISMATCH (2) critical size count mismatch
SF_DM_IL32LLP64_ON_ILP32LL64 (3) Windows x64 savefile on x86
SF_DM_I32LP64_ON_ILP32LL64 (4) Unix 64 savefile on x86
SF_DM_ILP32LL64_ON_I32LP64 (5) x86 savefile on Unix 64
SF_DM_ILP32LL64_ON_IL32LLP64 (6) x86 savefile on Windows x64
SF_DM_I32LP64_ON_IL32LLP64 (7) Unix 64 savefile on Windows x64
SF_DM_IL32LLP64_ON_I32LP64 (8) Windows x64 savefile on Unix 64
SF_DM_MISMATCH (9) some other mismatch
The callers in the core have been adjusted to deal with the expanded
return values.
Other miscellaneous inclusions:
- go.oracle_loc -> svo.oracle_loc.
- add a bit (1UL << 30) to called SFCTOOL_BIT as groundwork
for changes to follow.
1571 lines
55 KiB
C
1571 lines
55 KiB
C
/* NetHack 3.7 hack.h $NHDT-Date: 1736530208 2025/01/10 09:30:08 $ $NHDT-Branch: NetHack-3.7 $:$NHDT-Revision: 1.266 $ */
|
|
/* Copyright (c) Stichting Mathematisch Centrum, Amsterdam, 1985. */
|
|
/*-Copyright (c) Pasi Kallinen, 2017. */
|
|
/* NetHack may be freely redistributed. See license for details. */
|
|
|
|
#ifndef HACK_H
|
|
#define HACK_H
|
|
|
|
#ifndef CONFIG_H
|
|
#include "config.h"
|
|
#endif
|
|
#include "lint.h"
|
|
|
|
#include "align.h"
|
|
#include "weight.h"
|
|
#include "dungeon.h"
|
|
#include "stairs.h"
|
|
#include "objclass.h"
|
|
#include "wintype.h"
|
|
#include "flag.h"
|
|
#include "rect.h"
|
|
#include "sym.h"
|
|
#include "trap.h"
|
|
#include "youprop.h"
|
|
#include "display.h"
|
|
|
|
#include "botl.h"
|
|
#include "context.h"
|
|
#include "engrave.h"
|
|
#include "mkroom.h"
|
|
#include "obj.h"
|
|
#include "quest.h"
|
|
#include "region.h"
|
|
#include "rm.h"
|
|
#include "selvar.h"
|
|
#include "sndprocs.h"
|
|
#include "spell.h"
|
|
#include "sys.h"
|
|
#include "timeout.h"
|
|
#include "winprocs.h"
|
|
#include "wintype.h"
|
|
#include "vision.h"
|
|
#include "you.h"
|
|
|
|
#define TELL 1
|
|
#define NOTELL 0
|
|
#define ON 1
|
|
#define OFF 0
|
|
#define BOLT_LIM 8 /* from this distance ranged attacks will be made */
|
|
#define DUMMY { 0 } /* array initializer, letting [1..N-1] default */
|
|
#define DEF_NOTHING ' ' /* default symbol for NOTHING and UNEXPLORED */
|
|
|
|
/* Macros for how a rumor was delivered in outrumor() */
|
|
#define BY_ORACLE 0
|
|
#define BY_COOKIE 1
|
|
#define BY_PAPER 2
|
|
#define BY_OTHER 9
|
|
|
|
/* bitmask flags for corpse_xname();
|
|
PFX_THE takes precedence over ARTICLE, NO_PFX takes precedence over both */
|
|
#define CXN_NORMAL 0 /* no special handling */
|
|
#define CXN_SINGULAR 1 /* override quantity if greater than 1 */
|
|
#define CXN_NO_PFX 2 /* suppress "the" from "the Unique Monst */
|
|
#define CXN_PFX_THE 4 /* prefix with "the " (unless pname) */
|
|
#define CXN_ARTICLE 8 /* include a/an/the prefix */
|
|
#define CXN_NOCORPSE 16 /* suppress " corpse" suffix */
|
|
|
|
/* number of turns it takes for vault guard to show up */
|
|
#define VAULT_GUARD_TIME 30
|
|
|
|
/* sellobj_state() states */
|
|
#define SELL_NORMAL (0)
|
|
#define SELL_DELIBERATE (1)
|
|
#define SELL_DONTSELL (2)
|
|
|
|
#define SHOP_DOOR_COST 400L /* cost of a destroyed shop door */
|
|
#define SHOP_BARS_COST 300L /* cost of iron bars */
|
|
#define SHOP_HOLE_COST 200L /* cost of making hole/trapdoor */
|
|
#define SHOP_WALL_COST 200L /* cost of destroying a wall */
|
|
#define SHOP_WALL_DMG (10L * ACURRSTR) /* damaging a wall */
|
|
#define SHOP_PIT_COST 100L /* cost of making a pit */
|
|
#define SHOP_WEB_COST 30L /* cost of removing a web */
|
|
|
|
/* flags for look_here() */
|
|
#define LOOKHERE_NOFLAGS 0U
|
|
#define LOOKHERE_PICKED_SOME 1U
|
|
#define LOOKHERE_SKIP_DFEATURE 2U
|
|
|
|
/* max size of a windowtype option */
|
|
#define WINTYPELEN 16
|
|
|
|
/* str_or_len from sp_lev.h */
|
|
typedef union str_or_len {
|
|
char *str;
|
|
int len;
|
|
} Str_or_Len;
|
|
|
|
enum artifacts_nums {
|
|
#define ARTI_ENUM
|
|
#include "artilist.h"
|
|
#undef ARTI_ENUM
|
|
AFTER_LAST_ARTIFACT
|
|
};
|
|
|
|
enum misc_arti_nums {
|
|
NROFARTIFACTS = (AFTER_LAST_ARTIFACT - 1)
|
|
};
|
|
|
|
/* related to breadcrumb struct */
|
|
enum bcargs {override_restriction = -1};
|
|
|
|
struct breadcrumbs {
|
|
const char *funcnm;
|
|
int linenum;
|
|
boolean in_effect;
|
|
};
|
|
|
|
/* types of calls to bhit() */
|
|
enum bhit_call_types {
|
|
ZAPPED_WAND = 0,
|
|
THROWN_WEAPON = 1,
|
|
THROWN_TETHERED_WEAPON = 2,
|
|
KICKED_WEAPON = 3,
|
|
FLASHED_LIGHT = 4,
|
|
INVIS_BEAM = 5
|
|
};
|
|
|
|
/* Macros for messages referring to hands, eyes, feet, etc... */
|
|
enum bodypart_types {
|
|
NO_PART = -1,
|
|
ARM = 0,
|
|
EYE = 1,
|
|
FACE = 2,
|
|
FINGER = 3,
|
|
FINGERTIP = 4,
|
|
FOOT = 5,
|
|
HAND = 6,
|
|
HANDED = 7,
|
|
HEAD = 8,
|
|
LEG = 9,
|
|
LIGHT_HEADED = 10,
|
|
NECK = 11,
|
|
SPINE = 12,
|
|
TOE = 13,
|
|
HAIR = 14,
|
|
BLOOD = 15,
|
|
LUNG = 16,
|
|
NOSE = 17,
|
|
STOMACH = 18
|
|
};
|
|
|
|
#define MAX_BMASK 4
|
|
|
|
struct bubble {
|
|
coordxy x, y; /* coordinates of the upper left corner */
|
|
schar dx, dy; /* the general direction of the bubble's movement */
|
|
uchar bm[MAX_BMASK + 2]; /* bubble bit mask */
|
|
struct bubble *prev, *next; /* need to traverse the list up and down */
|
|
struct container *cons;
|
|
};
|
|
|
|
enum bubble_contains_types {
|
|
CONS_OBJ = 0,
|
|
CONS_MON,
|
|
CONS_HERO,
|
|
CONS_TRAP
|
|
};
|
|
|
|
/*
|
|
* Rudimentary command queue.
|
|
* Allows the code to put keys and extended commands into the queue,
|
|
* and they're executed just as if the user did them. Time passes
|
|
* normally when doing queued actions. The queue will get cleared
|
|
* if hero is interrupted.
|
|
*/
|
|
enum cmdq_cmdtypes {
|
|
CMDQ_KEY = 0, /* a literal character, cmdq_add_key() */
|
|
CMDQ_EXTCMD, /* extended command, cmdq_add_ec() */
|
|
CMDQ_DIR, /* direction, cmdq_add_dir() */
|
|
CMDQ_USER_INPUT, /* placeholder for user input, cmdq_add_userinput() */
|
|
CMDQ_INT, /* integer value, cmdq_add_int() */
|
|
};
|
|
|
|
struct _cmd_queue {
|
|
int typ;
|
|
char key;
|
|
schar dirx, diry, dirz;
|
|
int intval;
|
|
const struct ext_func_tab *ec_entry;
|
|
struct _cmd_queue *next;
|
|
};
|
|
|
|
enum {
|
|
CQ_CANNED = 0, /* internal canned sequence */
|
|
CQ_REPEAT, /* user-inputted, if gi.in_doagain, replayed */
|
|
NUM_CQS
|
|
};
|
|
|
|
typedef long cmdcount_nht; /* Command counts */
|
|
|
|
|
|
/* special key functions */
|
|
enum nh_keyfunc {
|
|
NHKF_ESC = 0,
|
|
|
|
NHKF_GETDIR_SELF,
|
|
NHKF_GETDIR_SELF2,
|
|
NHKF_GETDIR_HELP,
|
|
NHKF_GETDIR_MOUSE, /* simulated click for #therecmdmenu; use '_' as
|
|
* direction to initiate, then getpos() finishing
|
|
* with ',' (left click) or '.' (right click) */
|
|
NHKF_COUNT,
|
|
NHKF_GETPOS_SELF,
|
|
NHKF_GETPOS_PICK,
|
|
NHKF_GETPOS_PICK_Q, /* quick */
|
|
NHKF_GETPOS_PICK_O, /* once */
|
|
NHKF_GETPOS_PICK_V, /* verbose */
|
|
NHKF_GETPOS_SHOWVALID,
|
|
NHKF_GETPOS_AUTODESC,
|
|
NHKF_GETPOS_MON_NEXT,
|
|
NHKF_GETPOS_MON_PREV,
|
|
NHKF_GETPOS_OBJ_NEXT,
|
|
NHKF_GETPOS_OBJ_PREV,
|
|
NHKF_GETPOS_DOOR_NEXT,
|
|
NHKF_GETPOS_DOOR_PREV,
|
|
NHKF_GETPOS_UNEX_NEXT,
|
|
NHKF_GETPOS_UNEX_PREV,
|
|
NHKF_GETPOS_INTERESTING_NEXT,
|
|
NHKF_GETPOS_INTERESTING_PREV,
|
|
NHKF_GETPOS_VALID_NEXT,
|
|
NHKF_GETPOS_VALID_PREV,
|
|
NHKF_GETPOS_HELP,
|
|
NHKF_GETPOS_MENU,
|
|
NHKF_GETPOS_LIMITVIEW,
|
|
NHKF_GETPOS_MOVESKIP,
|
|
|
|
NUM_NHKF
|
|
};
|
|
|
|
/* commands[] is used to directly access cmdlist[] instead of looping
|
|
through it to find the entry for a given input character;
|
|
move_X is the character used for moving one step in direction X;
|
|
alphadirchars corresponds to old sdir,
|
|
dirchars corresponds to ``iflags.num_pad ? ndir : sdir'';
|
|
pcHack_compat and phone_layout only matter when num_pad is on,
|
|
swap_yz only matters when it's off */
|
|
struct cmd {
|
|
unsigned serialno; /* incremented after each update */
|
|
boolean num_pad; /* same as iflags.num_pad except during updates */
|
|
boolean pcHack_compat; /* for numpad: affects 5, M-5, and M-0 */
|
|
boolean phone_layout; /* inverted keypad: 1,2,3 above, 7,8,9 below */
|
|
boolean swap_yz; /* QWERTZ keyboards; use z to move NW, y to zap */
|
|
const char *dirchars; /* current movement/direction characters */
|
|
const char *alphadirchars; /* same as dirchars if !numpad */
|
|
const struct ext_func_tab *commands[256]; /* indexed by input character */
|
|
const struct ext_func_tab *mousebtn[NUM_MOUSE_BUTTONS];
|
|
char spkeys[NUM_NHKF];
|
|
char extcmd_char; /* key that starts an extended command ('#') */
|
|
};
|
|
|
|
struct c_color_names {
|
|
const char *const c_black, *const c_amber, *const c_golden,
|
|
*const c_light_blue, *const c_red, *const c_green, *const c_silver,
|
|
*const c_blue, *const c_purple, *const c_white, *const c_orange;
|
|
};
|
|
|
|
struct c_common_strings {
|
|
const char *const c_nothing_happens, *const c_nothing_seems_to_happen,
|
|
*const c_thats_enough_tries, *const c_silly_thing_to,
|
|
*const c_shudder_for_moment, *const c_something, *const c_Something,
|
|
*const c_You_can_move_again, *const c_Never_mind,
|
|
*const c_vision_clears, *const c_the_your[2], *const c_fakename[2];
|
|
};
|
|
|
|
struct container {
|
|
struct container *next;
|
|
coordxy x, y;
|
|
short what;
|
|
genericptr_t list;
|
|
};
|
|
|
|
/* alteration types--keep in synch with costly_alteration(mkobj.c) */
|
|
enum cost_alteration_types {
|
|
COST_CANCEL = 0, /* standard cancellation */
|
|
COST_DRAIN = 1, /* drain life upon an object */
|
|
COST_UNCHRG = 2, /* cursed charging */
|
|
COST_UNBLSS = 3, /* unbless (devalues holy water) */
|
|
COST_UNCURS = 4, /* uncurse (devalues unholy water) */
|
|
COST_DECHNT = 5, /* disenchant weapons or armor */
|
|
COST_DEGRD = 6, /* removal of rustproofing, dulling via engraving */
|
|
COST_DILUTE = 7, /* potion dilution */
|
|
COST_ERASE = 8, /* scroll or spellbook blanking */
|
|
COST_BURN = 9, /* dipped into flaming oil */
|
|
COST_NUTRLZ = 10, /* neutralized via unicorn horn */
|
|
COST_DSTROY = 11, /* wand breaking (bill first, useup later) */
|
|
COST_SPLAT = 12, /* cream pie to own face (ditto) */
|
|
COST_BITE = 13, /* start eating food */
|
|
COST_OPEN = 14, /* open tin */
|
|
COST_BRKLCK = 15, /* break box/chest's lock */
|
|
COST_RUST = 16, /* rust damage */
|
|
COST_ROT = 17, /* rotting attack */
|
|
COST_CORRODE = 18, /* acid damage */
|
|
COST_CRACK = 19, /* damage to crystal armor */
|
|
};
|
|
|
|
/* used by unpaid_cost(shk.h) */
|
|
enum unpaid_cost_flags {
|
|
COST_NOCONTENTS = 0,
|
|
COST_CONTENTS = 1,
|
|
COST_SINGLEOBJ = 2,
|
|
};
|
|
|
|
/* read.c, create_particular() & create_particular_parse() */
|
|
struct _create_particular_data {
|
|
int quan;
|
|
int which;
|
|
int fem; /* -1, MALE, FEMALE, NEUTRAL */
|
|
int genderconf; /* conflicting gender */
|
|
char monclass;
|
|
boolean randmonst;
|
|
boolean maketame, makepeaceful, makehostile;
|
|
boolean sleeping, saddled, invisible, hidden;
|
|
};
|
|
|
|
/* dig_check() results */
|
|
|
|
enum digcheck_result {
|
|
DIGCHECK_PASSED = 1,
|
|
DIGCHECK_PASSED_DESTROY_TRAP = 2,
|
|
DIGCHECK_PASSED_PITONLY = 3,
|
|
DIGCHECK_FAILED = 4,
|
|
DIGCHECK_FAIL_ONSTAIRS = DIGCHECK_FAILED,
|
|
DIGCHECK_FAIL_ONLADDER,
|
|
DIGCHECK_FAIL_THRONE,
|
|
DIGCHECK_FAIL_ALTAR,
|
|
DIGCHECK_FAIL_AIRLEVEL,
|
|
DIGCHECK_FAIL_WATERLEVEL,
|
|
DIGCHECK_FAIL_TOOHARD,
|
|
DIGCHECK_FAIL_UNDESTROYABLETRAP,
|
|
DIGCHECK_FAIL_CANTDIG,
|
|
DIGCHECK_FAIL_BOULDER,
|
|
DIGCHECK_FAIL_OBJ_POOL_OR_TRAP
|
|
};
|
|
|
|
|
|
/* Dismount: causes for why you are no longer riding */
|
|
enum dismount_types {
|
|
DISMOUNT_GENERIC = 0,
|
|
DISMOUNT_FELL = 1,
|
|
DISMOUNT_THROWN = 2,
|
|
DISMOUNT_KNOCKED = 3, /* hero hit for knockback effect */
|
|
DISMOUNT_POLY = 4,
|
|
DISMOUNT_ENGULFED = 5,
|
|
DISMOUNT_BONES = 6,
|
|
DISMOUNT_BYCHOICE = 7
|
|
};
|
|
|
|
struct dgn_topology { /* special dungeon levels for speed */
|
|
d_level d_oracle_level;
|
|
d_level d_bigroom_level; /* unused */
|
|
d_level d_rogue_level;
|
|
d_level d_medusa_level;
|
|
d_level d_stronghold_level;
|
|
d_level d_valley_level;
|
|
d_level d_wiz1_level;
|
|
d_level d_wiz2_level;
|
|
d_level d_wiz3_level;
|
|
d_level d_juiblex_level;
|
|
d_level d_orcus_level;
|
|
d_level d_baalzebub_level; /* unused */
|
|
d_level d_asmodeus_level; /* unused */
|
|
d_level d_portal_level; /* only in goto_level() [do.c] */
|
|
d_level d_sanctum_level;
|
|
d_level d_earth_level;
|
|
d_level d_water_level;
|
|
d_level d_fire_level;
|
|
d_level d_air_level;
|
|
d_level d_astral_level;
|
|
xint16 d_tower_dnum;
|
|
xint16 d_sokoban_dnum;
|
|
xint16 d_mines_dnum, d_quest_dnum;
|
|
xint16 d_tutorial_dnum;
|
|
d_level d_qstart_level, d_qlocate_level, d_nemesis_level;
|
|
d_level d_knox_level;
|
|
d_level d_mineend_level;
|
|
d_level d_sokoend_level;
|
|
};
|
|
|
|
/* macros for accessing the dungeon levels by their old names */
|
|
/* clang-format off */
|
|
#define oracle_level (svd.dungeon_topology.d_oracle_level)
|
|
#define bigroom_level (svd.dungeon_topology.d_bigroom_level)
|
|
#define rogue_level (svd.dungeon_topology.d_rogue_level)
|
|
#define medusa_level (svd.dungeon_topology.d_medusa_level)
|
|
#define stronghold_level (svd.dungeon_topology.d_stronghold_level)
|
|
#define valley_level (svd.dungeon_topology.d_valley_level)
|
|
#define wiz1_level (svd.dungeon_topology.d_wiz1_level)
|
|
#define wiz2_level (svd.dungeon_topology.d_wiz2_level)
|
|
#define wiz3_level (svd.dungeon_topology.d_wiz3_level)
|
|
#define juiblex_level (svd.dungeon_topology.d_juiblex_level)
|
|
#define orcus_level (svd.dungeon_topology.d_orcus_level)
|
|
#define baalzebub_level (svd.dungeon_topology.d_baalzebub_level)
|
|
#define asmodeus_level (svd.dungeon_topology.d_asmodeus_level)
|
|
#define portal_level (svd.dungeon_topology.d_portal_level)
|
|
#define sanctum_level (svd.dungeon_topology.d_sanctum_level)
|
|
#define earth_level (svd.dungeon_topology.d_earth_level)
|
|
#define water_level (svd.dungeon_topology.d_water_level)
|
|
#define fire_level (svd.dungeon_topology.d_fire_level)
|
|
#define air_level (svd.dungeon_topology.d_air_level)
|
|
#define astral_level (svd.dungeon_topology.d_astral_level)
|
|
#define tower_dnum (svd.dungeon_topology.d_tower_dnum)
|
|
#define sokoban_dnum (svd.dungeon_topology.d_sokoban_dnum)
|
|
#define mines_dnum (svd.dungeon_topology.d_mines_dnum)
|
|
#define quest_dnum (svd.dungeon_topology.d_quest_dnum)
|
|
#define tutorial_dnum (svd.dungeon_topology.d_tutorial_dnum)
|
|
#define qstart_level (svd.dungeon_topology.d_qstart_level)
|
|
#define qlocate_level (svd.dungeon_topology.d_qlocate_level)
|
|
#define nemesis_level (svd.dungeon_topology.d_nemesis_level)
|
|
#define knox_level (svd.dungeon_topology.d_knox_level)
|
|
#define mineend_level (svd.dungeon_topology.d_mineend_level)
|
|
#define sokoend_level (svd.dungeon_topology.d_sokoend_level)
|
|
/* clang-format on */
|
|
|
|
#define dunlev_reached(x) (svd.dungeons[(x)->dnum].dunlev_ureached)
|
|
#define MAXLINFO (MAXDUNGEON * MAXLEVEL)
|
|
|
|
enum lua_theme_group {
|
|
all_themes = 1, /* for end of game */
|
|
most_themes = 2, /* for entering endgame */
|
|
tut_themes = 3, /* for leaving tutorial */
|
|
};
|
|
|
|
enum earlyarg {
|
|
ARG_DEBUG, ARG_VERSION, ARG_SHOWPATHS
|
|
#ifndef NODUMPENUMS
|
|
, ARG_DUMPENUMS
|
|
#endif
|
|
, ARG_DUMPGLYPHIDS
|
|
, ARG_DUMPMONGEN
|
|
, ARG_DUMPWEIGHTS
|
|
#ifdef WIN32
|
|
, ARG_WINDOWS
|
|
#endif
|
|
#if defined(CRASHREPORT)
|
|
, ARG_BIDSHOW
|
|
#endif
|
|
};
|
|
|
|
struct early_opt {
|
|
enum earlyarg e;
|
|
const char *name;
|
|
int minlength;
|
|
boolean valallowed;
|
|
};
|
|
|
|
/* symbolic names for capacity levels */
|
|
enum encumbrance_types {
|
|
UNENCUMBERED = 0,
|
|
SLT_ENCUMBER = 1, /* Burdened */
|
|
MOD_ENCUMBER = 2, /* Stressed */
|
|
HVY_ENCUMBER = 3, /* Strained */
|
|
EXT_ENCUMBER = 4, /* Overtaxed */
|
|
OVERLOADED = 5 /* Overloaded */
|
|
};
|
|
|
|
struct entity {
|
|
struct monst *emon; /* youmonst for the player */
|
|
struct permonst *edata; /* must be non-zero for record to be valid */
|
|
int ex, ey;
|
|
};
|
|
|
|
struct enum_dump {
|
|
int val;
|
|
const char *nm;
|
|
};
|
|
|
|
/*
|
|
* This is the way the game ends. If these are rearranged, the arrays
|
|
* in end.c and topten.c will need to be changed. Some parts of the
|
|
* code assume that PANICKED separates the deaths from the non-deaths.
|
|
*/
|
|
enum game_end_types {
|
|
DIED = 0,
|
|
CHOKING = 1,
|
|
POISONING = 2,
|
|
STARVING = 3,
|
|
DROWNING = 4,
|
|
BURNING = 5,
|
|
DISSOLVED = 6,
|
|
CRUSHING = 7,
|
|
STONING = 8,
|
|
TURNED_SLIME = 9,
|
|
GENOCIDED = 10,
|
|
PANICKED = 11,
|
|
TRICKED = 12,
|
|
QUIT = 13,
|
|
ESCAPED = 14,
|
|
ASCENDED = 15
|
|
};
|
|
|
|
/* game events log */
|
|
struct gamelog_line {
|
|
long turn; /* turn when this happened */
|
|
long flags; /* LL_foo flags */
|
|
char *text;
|
|
struct gamelog_line *next;
|
|
};
|
|
|
|
|
|
/* values returned from getobj() callback functions */
|
|
enum getobj_callback_returns {
|
|
/* generally invalid - can't be used for this purpose. will give a "silly
|
|
* thing" message if the player tries to pick it, unless a more specific
|
|
* failure message is in getobj itself - e.g. "You cannot foo gold". */
|
|
GETOBJ_EXCLUDE = -3,
|
|
/* invalid because it is not in inventory; used when the hands/self
|
|
* possibility is queried and the player passed up something on the
|
|
* floor before getobj. */
|
|
GETOBJ_EXCLUDE_NONINVENT = -2,
|
|
/* invalid because it is an inaccessible or unwanted piece of gear, but
|
|
* pseudo-valid for the purposes of allowing the player to select it and
|
|
* getobj to return it if there is a prompt instead of getting "silly
|
|
* thing", in order for the getobj caller to present a specific failure
|
|
* message. Other than that, the only thing this does differently from
|
|
* GETOBJ_EXCLUDE is that it inserts an "else" in "You don't have anything
|
|
* else to foo". */
|
|
GETOBJ_EXCLUDE_INACCESS = -1,
|
|
/* invalid for purposes of not showing a prompt if nothing is valid but
|
|
* pseudo-valid for selecting - identical to GETOBJ_EXCLUDE_INACCESS but
|
|
* without the "else" in "You don't have anything else to foo". */
|
|
GETOBJ_EXCLUDE_SELECTABLE = 0,
|
|
/* valid - invlet not presented in the summary or the ? menu as a
|
|
* recommendation, but is selectable if the player enters it anyway.
|
|
* Used for objects that are actually valid but unimportantly so, such
|
|
* as shirts for reading. */
|
|
GETOBJ_DOWNPLAY = 1,
|
|
/* valid - will be shown in summary and ? menu */
|
|
GETOBJ_SUGGEST = 2,
|
|
};
|
|
|
|
/* getpos() return values */
|
|
enum getpos_retval {
|
|
LOOK_TRADITIONAL = 0, /* '.' -- ask about "more info?" */
|
|
LOOK_QUICK = 1, /* ',' -- skip "more info?" */
|
|
LOOK_ONCE = 2, /* ';' -- skip and stop looping */
|
|
LOOK_VERBOSE = 3 /* ':' -- show more info w/o asking */
|
|
};
|
|
|
|
struct h2o_ctx {
|
|
int dkn_boom, unk_boom; /* track dknown, !dknown separately */
|
|
boolean ctx_valid;
|
|
};
|
|
|
|
/* attack mode for hmon() */
|
|
enum hmon_atkmode_types {
|
|
HMON_MELEE = 0, /* hand-to-hand */
|
|
HMON_THROWN = 1, /* normal ranged (or spitting while poly'd) */
|
|
HMON_KICKED = 2, /* alternate ranged */
|
|
HMON_APPLIED = 3, /* polearm, treated as ranged */
|
|
HMON_DRAGGED = 4 /* attached iron ball, pulled into mon */
|
|
};
|
|
|
|
/* hunger states - see hu_stat in eat.c */
|
|
enum hunger_state_types {
|
|
SATIATED = 0,
|
|
NOT_HUNGRY = 1,
|
|
HUNGRY = 2,
|
|
WEAK = 3,
|
|
FAINTING = 4,
|
|
FAINTED = 5,
|
|
STARVED = 6
|
|
};
|
|
|
|
/* inventory counts (slots in tty parlance)
|
|
* a...zA..Z invlet_basic (52)
|
|
* $a...zA..Z# 2 special additions
|
|
*/
|
|
enum inventory_counts {
|
|
invlet_basic = 52,
|
|
invlet_gold = 1,
|
|
invlet_overflow = 1,
|
|
invlet_max = invlet_basic + invlet_gold + invlet_overflow,
|
|
/* 2023/11/30 invlet_max is not yet used anywhere */
|
|
};
|
|
|
|
struct kinfo {
|
|
struct kinfo *next; /* chain of delayed killers */
|
|
int id; /* uprop keys to ID a delayed killer */
|
|
int format; /* one of the killer formats */
|
|
#define KILLED_BY_AN 0
|
|
#define KILLED_BY 1
|
|
#define NO_KILLER_PREFIX 2
|
|
char name[BUFSZ]; /* actual killer name */
|
|
};
|
|
|
|
struct launchplace {
|
|
struct obj *obj;
|
|
coordxy x, y;
|
|
};
|
|
|
|
/* light source */
|
|
typedef struct ls_t {
|
|
struct ls_t *next;
|
|
coordxy x, y; /* source's position */
|
|
short range; /* source's current range */
|
|
short flags;
|
|
short type; /* type of light source */
|
|
anything id; /* source's identifier */
|
|
} light_source;
|
|
|
|
struct menucoloring {
|
|
struct nhregex *match;
|
|
char *origstr;
|
|
int color, attr;
|
|
struct menucoloring *next;
|
|
};
|
|
|
|
enum movemodes {
|
|
MV_ANY = -1,
|
|
MV_WALK,
|
|
MV_RUN,
|
|
MV_RUSH,
|
|
|
|
N_MOVEMODES
|
|
};
|
|
|
|
enum movementdirs {
|
|
DIR_ERR = -1,
|
|
DIR_W,
|
|
DIR_NW,
|
|
DIR_N,
|
|
DIR_NE,
|
|
DIR_E,
|
|
DIR_SE,
|
|
DIR_S,
|
|
DIR_SW,
|
|
DIR_DOWN,
|
|
DIR_UP,
|
|
|
|
N_DIRS_Z
|
|
};
|
|
/* N_DIRS_Z, minus up & down */
|
|
#define N_DIRS (N_DIRS_Z - 2)
|
|
/* direction adjustments */
|
|
#define DIR_180(dir) (((dir) + 4) % N_DIRS)
|
|
#define DIR_LEFT(dir) (((dir) + 7) % N_DIRS)
|
|
#define DIR_RIGHT(dir) (((dir) + 1) % N_DIRS)
|
|
#define DIR_LEFT2(dir) (((dir) + 6) % N_DIRS)
|
|
#define DIR_RIGHT2(dir) (((dir) + 2) % N_DIRS)
|
|
#define DIR_CLAMP(dir) (((dir) + N_DIRS) % N_DIRS)
|
|
|
|
struct multishot {
|
|
int n, i;
|
|
short o;
|
|
boolean s;
|
|
};
|
|
|
|
struct musable {
|
|
struct obj *offensive;
|
|
struct obj *defensive;
|
|
struct obj *misc;
|
|
int has_offense, has_defense, has_misc;
|
|
/* =0, no capability; otherwise, different numbers.
|
|
* If it's an object, the object is also set (it's 0 otherwise).
|
|
*/
|
|
};
|
|
|
|
struct mvitals {
|
|
uchar born;
|
|
uchar died;
|
|
uchar mvflags;
|
|
Bitfield(seen_close, 1);
|
|
};
|
|
|
|
|
|
/* Lua callback functions */
|
|
enum nhcore_calls {
|
|
NHCORE_START_NEW_GAME = 0,
|
|
NHCORE_RESTORE_OLD_GAME,
|
|
NHCORE_MOVELOOP_TURN,
|
|
NHCORE_GAME_EXIT,
|
|
NHCORE_GETPOS_TIP,
|
|
NHCORE_ENTER_TUTORIAL,
|
|
NHCORE_LEAVE_TUTORIAL,
|
|
|
|
NUM_NHCORE_CALLS
|
|
};
|
|
|
|
/* Lua callbacks. TODO: Merge with NHCORE */
|
|
enum nhcb_calls {
|
|
NHCB_CMD_BEFORE = 0,
|
|
NHCB_LVL_ENTER,
|
|
NHCB_LVL_LEAVE,
|
|
NHCB_END_TURN,
|
|
|
|
NUM_NHCB
|
|
};
|
|
|
|
/*
|
|
* option setting restrictions
|
|
*/
|
|
|
|
enum optset_restrictions {
|
|
set_in_sysconf = 0, /* system config file option only */
|
|
set_in_config = 1, /* config file option only */
|
|
set_viaprog = 2, /* may be set via extern program, not seen in game */
|
|
set_gameview = 3, /* may be set via extern program, displayed in game */
|
|
set_in_game = 4, /* may be set via extern program or set in the game */
|
|
set_wizonly = 5, /* may be set in the game if wizmode */
|
|
set_wiznofuz = 6, /* wizard-mode only, but not by fuzzer */
|
|
set_hidden = 7 /* placeholder for prefixed entries, never show it */
|
|
};
|
|
#define SET__IS_VALUE_VALID(s) ((s < set_in_sysconf) || (s > set_wiznofuz))
|
|
|
|
struct plinemsg_type {
|
|
xint16 msgtype; /* one of MSGTYP_foo */
|
|
struct nhregex *regex;
|
|
char *pattern;
|
|
struct plinemsg_type *next;
|
|
};
|
|
|
|
#define MSGTYP_NORMAL 0
|
|
#define MSGTYP_NOREP 1
|
|
#define MSGTYP_NOSHOW 2
|
|
#define MSGTYP_STOP 3
|
|
/* bitmask for callers of hide_unhide_msgtypes() */
|
|
#define MSGTYP_MASK_REP_SHOW ((1 << MSGTYP_NOREP) | (1 << MSGTYP_NOSHOW))
|
|
|
|
/* polyself flags */
|
|
enum polyself_flags {
|
|
POLY_NOFLAGS = 0x00,
|
|
POLY_CONTROLLED = 0x01,
|
|
POLY_MONSTER = 0x02,
|
|
POLY_REVERT = 0x04,
|
|
POLY_LOW_CTRL = 0x08
|
|
};
|
|
|
|
struct repo { /* repossession context */
|
|
struct monst *shopkeeper;
|
|
coord location;
|
|
};
|
|
|
|
struct restore_info {
|
|
const char *name;
|
|
int mread_flags;
|
|
};
|
|
|
|
enum restore_stages {
|
|
REST_GSTATE = 1, /* restoring game state + first pass of current level */
|
|
REST_LEVELS = 2, /* restoring remainder of dungeon */
|
|
REST_CURRENT_LEVEL = 3, /* final pass of restoring current level */
|
|
};
|
|
|
|
struct rogueroom {
|
|
coordxy rlx, rly;
|
|
coordxy dx, dy;
|
|
boolean real;
|
|
uchar doortable;
|
|
int nroom; /* Only meaningful for "real" rooms */
|
|
};
|
|
|
|
#define NUM_ROLES (13)
|
|
struct role_filter {
|
|
boolean roles[NUM_ROLES + 1];
|
|
short mask;
|
|
};
|
|
#define NUM_RACES (5)
|
|
|
|
struct selectionvar {
|
|
int wid, hei;
|
|
boolean bounds_dirty;
|
|
NhRect bounds; /* use selection_getbounds() */
|
|
char *map;
|
|
};
|
|
|
|
/* structure for 'program_state'; not saved and restored */
|
|
struct sinfo {
|
|
int gameover; /* self explanatory? */
|
|
int stopprint; /* inhibit further end of game disclosure */
|
|
#ifdef HANGUPHANDLING
|
|
volatile int done_hup; /* SIGHUP or moral equivalent received
|
|
* -- no more screen output */
|
|
int preserve_locks; /* don't remove level files prior to exit */
|
|
#endif
|
|
int something_worth_saving; /* in case of panic */
|
|
int panicking; /* `panic' is in progress */
|
|
int exiting; /* an exit handler is executing */
|
|
int saving; /* creating a save file */
|
|
int restoring; /* reloading a save file */
|
|
int freeingdata; /* in saveobjchn(), mode FREEING */
|
|
int in_getlev; /* in getlev() */
|
|
int in_moveloop; /* normal gameplay in progress */
|
|
int in_impossible; /* reporting a warning */
|
|
int in_docrt; /* in docrt(): redrawing the whole screen */
|
|
int in_self_recover; /* processing orphaned level files */
|
|
int in_checkpoint; /* saving insurance checkpoint */
|
|
int in_parseoptions; /* in parseoptions */
|
|
int in_role_selection; /* role/race/&c selection menus in progress */
|
|
int in_getlin; /* inside interface getlin routine */
|
|
int in_sanity_check; /* for impossible() during sanity checking */
|
|
int config_error_ready; /* config_error_add is ready, available */
|
|
int beyond_savefile_load; /* set when past savefile loading */
|
|
#ifdef PANICLOG
|
|
int in_paniclog; /* writing a panicloc entry */
|
|
#endif
|
|
int wizkit_wishing; /* starting wizard mode game w/ WIZKIT file */
|
|
/* input_state: used in the core for the 'altmeta' option to process ESC;
|
|
used in the curses interface to avoid arrow keys when user is doing
|
|
something other than entering a command or direction and in the Qt
|
|
interface to suppress menu commands in similar conditions;
|
|
readchar() always resets it to 'otherInp' prior to returning */
|
|
int input_state; /* whether next key pressed will be entering a command */
|
|
#ifdef TTY_GRAPHICS
|
|
/* resize_pending only matters when handling a SIGWINCH signal for tty;
|
|
getting_char is used along with that and also separately for UNIX;
|
|
we minimize #if conditionals for them to avoid unnecessary clutter */
|
|
volatile int resize_pending; /* set by signal handler */
|
|
volatile int getting_char; /* referenced during signal handling */
|
|
#endif
|
|
};
|
|
|
|
/* value of program_state.input_state, significant during readchar();
|
|
get_count() expects digits then a command so sets it to commandInp */
|
|
enum InputState {
|
|
otherInp = 0, /* 'other' */
|
|
commandInp = 1, /* readchar() */
|
|
getposInp = 2, /* getpos() */
|
|
getdirInp = 3, /* getdir() */
|
|
};
|
|
|
|
/* sortloot() return type; needed before extern.h */
|
|
struct sortloot_item {
|
|
struct obj *obj;
|
|
char *str; /* result of loot_xname(obj) in some cases, otherwise null */
|
|
/* these need to be signed; 'indx' should be big enough to hold a count
|
|
of the largest pile of items, the others fit within char */
|
|
int indx; /* index into original list (used as tie-breaker) */
|
|
int8 orderclass; /* order rather than object class; 0 => not yet init'd */
|
|
int8 subclass; /* subclass for some classes */
|
|
int8 disco; /* discovery status */
|
|
int8 inuse; /* 0: not in-use or not sorting by inuse_only;
|
|
* 1: lit candle/lamp or attached leash; 2: worn armor;
|
|
* 3: wielded weapon (including uswapwep and uquiver);
|
|
* 4: worn accessory (amulet, rings, blindfold). */
|
|
};
|
|
typedef struct sortloot_item Loot;
|
|
|
|
typedef struct strbuf {
|
|
int len;
|
|
char *str;
|
|
char buf[256];
|
|
} strbuf_t;
|
|
|
|
enum stoning_checks {
|
|
st_gloves = 0x1, /* wearing gloves? */
|
|
st_corpse = 0x2, /* is it a corpse obj? */
|
|
st_petrifies = 0x4, /* does the corpse petrify on touch? */
|
|
st_resists = 0x8, /* do you have stoning resistance? */
|
|
st_all = (st_gloves | st_corpse | st_petrifies | st_resists)
|
|
};
|
|
|
|
struct throw_and_return_weapon {
|
|
short otyp;
|
|
int range;
|
|
Bitfield(tethered, 1);
|
|
};
|
|
|
|
struct trapinfo {
|
|
struct obj *tobj;
|
|
coordxy tx, ty;
|
|
int time_needed;
|
|
boolean force_bungle;
|
|
};
|
|
|
|
/* values for rtype are defined in dungeon.h */
|
|
/* lev_region from sp_lev.h */
|
|
typedef struct {
|
|
struct {
|
|
coordxy x1, y1, x2, y2;
|
|
} inarea;
|
|
struct {
|
|
coordxy x1, y1, x2, y2;
|
|
} delarea;
|
|
boolean in_islev, del_islev;
|
|
coordxy rtype, padding;
|
|
Str_or_Len rname;
|
|
} lev_region;
|
|
|
|
/* Flags for controlling uptodate */
|
|
#define UTD_CHECKSIZES 0x01
|
|
#define UTD_CHECKFIELDCOUNTS 0x02
|
|
#define UTD_SKIP_SANITY1 0x04
|
|
#define UTD_SKIP_SAVEFILEINFO 0x08
|
|
#define UTD_WITHOUT_WAITSYNCH_PERFILE 0x10
|
|
#define UTD_QUIETLY 0x20
|
|
|
|
/* Values for savefile status */
|
|
#define SF_UPTODATE 0
|
|
#define SF_OUTDATED 1
|
|
#define SF_CRITICAL_BYTE_COUNT_MISMATCH 2
|
|
#define SF_DM_IL32LLP64_ON_ILP32LL64 3 /* Wind x64 savefile on x86 */
|
|
#define SF_DM_I32LP64_ON_ILP32LL64 4 /* Unix 64 savefile on x86 */
|
|
#define SF_DM_ILP32LL64_ON_I32LP64 5 /* x86 savefile on Unix 64 */
|
|
#define SF_DM_ILP32LL64_ON_IL32LLP64 6 /* x86 savefile on Wind x64 */
|
|
#define SF_DM_I32LP64_ON_IL32LLP64 7 /* Unix 64 savefile on Wind x64 */
|
|
#define SF_DM_IL32LLP64_ON_I32LP64 8 /* Wind x64 savefile on Unix 64 */
|
|
#define SF_DM_MISMATCH 9 /* generic savefile byte mismatch */
|
|
|
|
#define ENTITIES 2
|
|
struct valuable_data {
|
|
long count;
|
|
int typ;
|
|
};
|
|
|
|
struct val_list {
|
|
struct valuable_data *list;
|
|
int size;
|
|
};
|
|
|
|
enum vanq_order_modes {
|
|
VANQ_MLVL_MNDX = 0, /* t - traditional: by monster level */
|
|
VANQ_MSTR_MNDX, /* d - by difficulty rating */
|
|
VANQ_ALPHA_SEP, /* a - alphabetical, first uniques, then ordinary */
|
|
VANQ_ALPHA_MIX, /* A - alpha with uniques and ordinary intermixed */
|
|
VANQ_MCLS_HTOL, /* C - by class, high to low within class */
|
|
VANQ_MCLS_LTOH, /* c - by class, low to high within class */
|
|
VANQ_COUNT_H_L, /* n - by count, high to low */
|
|
VANQ_COUNT_L_H, /* z - by count, low to high */
|
|
|
|
NUM_VANQ_ORDER_MODES
|
|
};
|
|
|
|
struct autopickup_exception {
|
|
struct nhregex *regex;
|
|
char *pattern;
|
|
boolean grab;
|
|
struct autopickup_exception *next;
|
|
};
|
|
|
|
/* at most one of `door' and `box' should be non-null at any given time */
|
|
struct xlock_s {
|
|
struct rm *door;
|
|
struct obj *box;
|
|
int picktyp, /* key|pick|card for unlock, sharp vs blunt for #force */
|
|
chance, usedtime;
|
|
boolean magic_key;
|
|
};
|
|
|
|
#define MAX_BMASK 4
|
|
|
|
/* NetHack ftypes */
|
|
#define NHF_LEVELFILE 1
|
|
#define NHF_SAVEFILE 2
|
|
#define NHF_BONESFILE 3
|
|
/* modes */
|
|
#define READING 0x0
|
|
#define COUNTING 0x1
|
|
#define WRITING 0x2
|
|
#define FREEING 0x4
|
|
#define CONVERTING 0x08
|
|
#define UNCONVERTING 0x10
|
|
#if 0
|
|
/* operations of the various saveXXXchn & co. routines */
|
|
#define perform_bwrite(nhfp) ((nhfp)->mode & (COUNTING | WRITING))
|
|
#define release_data(nhfp) ((nhfp)->mode & FREEING)
|
|
#endif
|
|
|
|
/* operations of the various saveXXXchn & co. routines */
|
|
#define update_file(nhfp) ((nhfp)->mode & (COUNTING | WRITING))
|
|
#define release_data(nhfp) ((nhfp)->mode & FREEING)
|
|
|
|
enum saveformats {
|
|
invalid = 0,
|
|
historical = 1, /* entire struct, binary, as-is */
|
|
cnvascii = 2, /* each field, ascii text */
|
|
NUM_SAVEFORMATS
|
|
};
|
|
|
|
/* Content types for fieldlevel files */
|
|
struct fieldlevel_content {
|
|
boolean deflt; /* individual fields */
|
|
boolean binary; /* binary rather than text */
|
|
};
|
|
|
|
struct nh_file {
|
|
int fd; /* for traditional structlevel binary writes */
|
|
int mode; /* holds READING, WRITING, or FREEING modes */
|
|
int ftype; /* NHF_LEVELFILE, NHF_SAVEFILE, or NHF_BONESFILE */
|
|
int fnidx; /* index of procs for fieldlevel saves */
|
|
long count; /* holds current line count for default style file,
|
|
field count for binary style */
|
|
boolean structlevel; /* traditional structure binary saves */
|
|
boolean fieldlevel; /* fieldlevel saves each field individually */
|
|
boolean addinfo; /* if set, some additional context info from core */
|
|
boolean eof; /* place to mark eof reached */
|
|
boolean bendian; /* set to true if executing on big-endian machine */
|
|
FILE *fpdef; /* file pointer for fieldlevel default style */
|
|
FILE *fpdefmap; /* file pointer mapfile for def format */
|
|
FILE *fplog; /* file pointer logfile */
|
|
FILE *fpdebug; /* file pointer debug info */
|
|
struct fieldlevel_content style;
|
|
struct nh_file *nhfpconvert;
|
|
};
|
|
|
|
typedef struct nh_file NHFILE;
|
|
|
|
/* Monster name articles */
|
|
#define ARTICLE_NONE 0
|
|
#define ARTICLE_THE 1
|
|
#define ARTICLE_A 2
|
|
#define ARTICLE_YOUR 3
|
|
|
|
/* x_monnam() monster name suppress masks */
|
|
#define SUPPRESS_IT 0x01
|
|
#define SUPPRESS_INVISIBLE 0x02
|
|
#define SUPPRESS_HALLUCINATION 0x04
|
|
#define SUPPRESS_SADDLE 0x08
|
|
#define SUPPRESS_MAPPEARANCE 0x10
|
|
#define EXACT_NAME 0x1F
|
|
#define SUPPRESS_NAME 0x20
|
|
#define AUGMENT_IT 0x40 /* use "someone" or "something" instead of "it" */
|
|
|
|
/* pline (et al) for a single string argument (suppress compiler warning) */
|
|
#define pline1(cstr) pline("%s", cstr)
|
|
#define Your1(cstr) Your("%s", cstr)
|
|
#define You1(cstr) You("%s", cstr)
|
|
#define verbalize1(cstr) verbalize("%s", cstr)
|
|
#define You_hear1(cstr) You_hear("%s", cstr)
|
|
#define Sprintf1(buf, cstr) Sprintf(buf, "%s", cstr)
|
|
#define panic1(cstr) panic("%s", cstr)
|
|
|
|
/* Some systems want to use full pathnames for some subsets of file names,
|
|
* rather than assuming that they're all in the current directory. This
|
|
* provides all the subclasses that seem reasonable, and sets up for all
|
|
* prefixes being null. Port code can set those that it wants.
|
|
*/
|
|
#define HACKPREFIX 0 /* shared, RO */
|
|
#define LEVELPREFIX 1 /* per-user, RW */
|
|
#define SAVEPREFIX 2 /* per-user, RW */
|
|
#define BONESPREFIX 3 /* shared, RW */
|
|
#define DATAPREFIX 4 /* dungeon/dlb; must match value in dlb.c */
|
|
#define SCOREPREFIX 5 /* shared, RW */
|
|
#define LOCKPREFIX 6 /* shared, RW */
|
|
#define SYSCONFPREFIX 7 /* shared, RO */
|
|
#define CONFIGPREFIX 8
|
|
#define TROUBLEPREFIX 9 /* shared or per-user, RW (append-only) */
|
|
#define PREFIX_COUNT 10
|
|
/* used in files.c; xxconf.h can override if needed */
|
|
#ifndef FQN_MAX_FILENAME
|
|
#define FQN_MAX_FILENAME 512
|
|
#endif
|
|
|
|
#if defined(NOCWD_ASSUMPTIONS) || defined(VAR_PLAYGROUND)
|
|
/* the bare-bones stuff is unconditional above to simplify coding; for
|
|
* ports that actually use prefixes, add some more localized things
|
|
*/
|
|
#define PREFIXES_IN_USE
|
|
#endif
|
|
|
|
/* from options.c */
|
|
#define MAX_MENU_MAPPED_CMDS 32 /* some number */
|
|
|
|
/* player selection constants */
|
|
#define BP_ALIGN 0
|
|
#define BP_GEND 1
|
|
#define BP_RACE 2
|
|
#define BP_ROLE 3
|
|
#define NUM_BP 4
|
|
|
|
/* some array sizes for 'g?' */
|
|
#define WIZKIT_MAX 128
|
|
#define CVT_BUF_SIZE 64
|
|
|
|
#define LUA_VER_BUFSIZ 20
|
|
#define LUA_COPYRIGHT_BUFSIZ 120
|
|
|
|
/* Symbol offsets */
|
|
#define SYM_OFF_P (0)
|
|
#define SYM_OFF_O (SYM_OFF_P + MAXPCHARS) /* MAXPCHARS from sym.h */
|
|
#define SYM_OFF_M (SYM_OFF_O + MAXOCLASSES) /* MAXOCLASSES from objclass.h */
|
|
#define SYM_OFF_W (SYM_OFF_M + MAXMCLASSES) /* MAXMCLASSES from sym.h*/
|
|
#define SYM_OFF_X (SYM_OFF_W + WARNCOUNT)
|
|
#define SYM_MAX (SYM_OFF_X + MAXOTHER)
|
|
|
|
/* The UNDEFINED macros are used to initialize variables whose
|
|
initialized value is not relied upon.
|
|
UNDEFINED_VALUE: used to initialize any scalar type except pointers.
|
|
UNDEFINED_VALUES: used to initialize any non scalar type without pointers.
|
|
UNDEFINED_PTR: can be used only on pointer types. */
|
|
#define UNDEFINED_VALUE 0
|
|
#define UNDEFINED_VALUES { 0 }
|
|
#define UNDEFINED_PTR NULL
|
|
|
|
/* The UNDEFINED_ROLE macro is used to initialize Role variables */
|
|
#define UNDEFINED_ROLE \
|
|
{ \
|
|
/* role name, set of rank names */ \
|
|
{ NULL, NULL }, { { NULL, NULL } }, \
|
|
/* strings: pantheon deity names */ \
|
|
NULL, NULL, NULL, \
|
|
/* file code, quest home+goal names */ \
|
|
NULL, NULL, NULL, \
|
|
/* indices: base mon type, pet */ \
|
|
NON_PM, NON_PM, \
|
|
/* quest leader, guardians, nemesis */ \
|
|
NON_PM, NON_PM, NON_PM, \
|
|
/* quest enemy types (index, symbol) */ \
|
|
NON_PM, NON_PM, '\0', '\0', \
|
|
/* quest artifact object index */ \
|
|
STRANGE_OBJECT, \
|
|
/* Bitmasks */ \
|
|
0, \
|
|
/* Attributes */ \
|
|
{0}, {0}, {0}, {0}, 0, 0, \
|
|
/* spell statistics */ \
|
|
0, 0, 0, 0, 0, 0, 0 }
|
|
|
|
/* The UNDEFINED_RACE macro is used to initialize Race variables */
|
|
#define UNDEFINED_RACE \
|
|
{ \
|
|
/* strings */ \
|
|
NULL, NULL, NULL, NULL, { NULL, NULL }, \
|
|
/* Indices: base race, mummy, zombie */ \
|
|
NON_PM, NON_PM, NON_PM, \
|
|
/* Bitmasks */ \
|
|
0, 0, 0, 0, \
|
|
/* Characteristic limits */ \
|
|
{0}, {0}, \
|
|
/* Level change HP and Pw adjustments */ \
|
|
{0}, {0} \
|
|
}
|
|
|
|
#define MATCH_WARN_OF_MON(mon) \
|
|
(Warn_of_mon \
|
|
&& ((svc.context.warntype.obj & (mon)->data->mflags2) != 0 \
|
|
|| (svc.context.warntype.polyd & (mon)->data->mflags2) != 0 \
|
|
|| (svc.context.warntype.species \
|
|
&& (svc.context.warntype.species == (mon)->data))))
|
|
|
|
typedef uint32_t mmflags_nht; /* makemon MM_ flags */
|
|
|
|
|
|
/* flags to control makemon(); goodpos() uses some plus has some of its own*/
|
|
#define NO_MM_FLAGS 0x00000000L /* use this rather than plain 0 */
|
|
#define NO_MINVENT 0x00000001L /* suppress minvent when creating mon */
|
|
#define MM_NOWAIT 0x00000002L /* don't set STRAT_WAITMASK flags */
|
|
#define MM_NOCOUNTBIRTH 0x00000004L /* don't incr born count (for revival) */
|
|
#define MM_IGNOREWATER 0x00000008L /* ignore water when positioning */
|
|
#define MM_ADJACENTOK 0x00000010L /* ok to use adjacent coordinates */
|
|
#define MM_ANGRY 0x00000020L /* monster is created angry */
|
|
#define MM_NONAME 0x00000040L /* monster is not christened */
|
|
#define MM_EGD 0x00000080L /* add egd structure */
|
|
#define MM_EPRI 0x00000100L /* add epri structure */
|
|
#define MM_ESHK 0x00000200L /* add eshk structure */
|
|
#define MM_EMIN 0x00000400L /* add emin structure */
|
|
#define MM_EDOG 0x00000800L /* add edog structure */
|
|
#define MM_ASLEEP 0x00001000L /* monsters should be generated asleep */
|
|
#define MM_NOGRP 0x00002000L /* suppress creation of monster groups */
|
|
#define MM_NOTAIL 0x00004000L /* if a long worm, don't give it a tail */
|
|
#define MM_MALE 0x00008000L /* male variation */
|
|
#define MM_FEMALE 0x00010000L /* female variation */
|
|
#define MM_NOMSG 0x00020000L /* no appear message */
|
|
#define MM_NOEXCLAM 0x00040000L /* more sedate "<mon> appears."
|
|
* mesg for ^G */
|
|
#define MM_IGNORELAVA 0x00080000L /* ignore lava when positioning */
|
|
#define MM_MINVIS 0x00100000L /* for ^G/create_particular */
|
|
/* if more MM_ flag masks are added, skip or renumber the GP_ one(s) */
|
|
#define GP_ALLOW_XY 0x00200000L /* [actually used by enexto() to decide
|
|
* whether to make an extra call to
|
|
* goodpos()] */
|
|
#define GP_ALLOW_U 0x00400000L /* don't reject hero's location */
|
|
#define GP_CHECKSCARY 0x00800000L /* check monster for onscary() */
|
|
#define GP_AVOID_MONPOS 0x01000000L /* don't accept existing mon location */
|
|
/* 25 bits used */
|
|
|
|
/* flags for mhidden_description() (pager.c; used for mimics and hiders) */
|
|
#define MHID_PREFIX 1 /* include ", mimicking " prefix */
|
|
#define MHID_ARTICLE 2 /* include "a " or "an " after prefix */
|
|
#define MHID_ALTMON 4 /* if mimicking a monster, include that */
|
|
#define MHID_REGION 8 /* include region when mon is in one */
|
|
|
|
/* flags for that_is_a_mimic() */
|
|
#define MIM_REVEAL 1 /* seemimic() */
|
|
#define MIM_OMIT_WAIT 2 /* strip beginning from "Wait! That is a <foo>" */
|
|
|
|
/* flags for make_corpse() and mkcorpstat(); 0..7 are recorded in obj->spe */
|
|
#define CORPSTAT_NONE 0x00
|
|
#define CORPSTAT_GENDER 0x03 /* 0x01 | 0x02 */
|
|
#define CORPSTAT_HISTORIC 0x04 /* historic statue; not used for corpse */
|
|
#define CORPSTAT_SPE_VAL 0x07 /* 0x03 | 0x04 */
|
|
#define CORPSTAT_INIT 0x08 /* pass init flag to mkcorpstat */
|
|
#define CORPSTAT_BURIED 0x10 /* bury the corpse or statue */
|
|
/* note: gender flags have different values from those used for monsters
|
|
so that 0 can be unspecified/random instead of male */
|
|
#define CORPSTAT_RANDOM 0
|
|
#define CORPSTAT_FEMALE 1
|
|
#define CORPSTAT_MALE 2
|
|
#define CORPSTAT_NEUTER 3
|
|
|
|
/* flag bits for collect_coords(); combining ring_pairs with unshuffled
|
|
makes no sense--if both are specified unshuffled takes precedence */
|
|
#define CC_NO_FLAGS 0x00 /* skip center, collect in distinct rings and
|
|
* shuffle each ring, ignore monster occupants */
|
|
#define CC_INCL_CENTER 0x01 /* include center point as ring #0 */
|
|
#define CC_UNSHUFFLED 0x02 /* don't shuffle the rings */
|
|
#define CC_RING_PAIRS 0x04 /* shuffle w/ odd and next even rings together */
|
|
#define CC_SKIP_MONS 0x08 /* skip locations occupied by monsters */
|
|
#define CC_SKIP_INACCS 0x10 /* skip !ZAP_POS: reject rock and wall locations
|
|
* but allow pools, unlike !ACCESSIBLE */
|
|
|
|
/* flags for decide_to_shift() */
|
|
#define SHIFT_SEENMSG 0x01 /* put out a message if in sight */
|
|
#define SHIFT_MSG 0x02 /* always put out a message */
|
|
|
|
/* m_poisongas_ok() return values */
|
|
#define M_POISONGAS_BAD 0 /* poison gas is bad */
|
|
#define M_POISONGAS_MINOR 1 /* poison gas is ok, maybe causes coughing */
|
|
#define M_POISONGAS_OK 2 /* ignores poison gas completely */
|
|
|
|
/* flags for deliver_obj_to_mon */
|
|
#define DF_NONE 0x00
|
|
#define DF_RANDOM 0x01
|
|
#define DF_ALL 0x04
|
|
|
|
/* special mhpmax value when loading bones monster to flag as extinct or
|
|
* genocided */
|
|
#define DEFUNCT_MONSTER (-100)
|
|
|
|
/* macro form of adjustments of physical damage based on Half_physical_damage.
|
|
* Can be used on-the-fly with the 1st parameter to losehp() if you don't
|
|
* need to retain the dmg value beyond that call scope.
|
|
* Take care to ensure it doesn't get used more than once in other instances.
|
|
*/
|
|
#define Maybe_Half_Phys(dmg) \
|
|
((Half_physical_damage) ? (((dmg) + 1) / 2) : (dmg))
|
|
|
|
/* flags for special ggetobj status returns */
|
|
#define ALL_FINISHED 0x01 /* called routine already finished the job */
|
|
|
|
/* flags to control query_objlist() */
|
|
#define BY_NEXTHERE 0x0001 /* follow objlist by nexthere field */
|
|
#define INCLUDE_VENOM 0x0002 /* include venom objects if present */
|
|
#define AUTOSELECT_SINGLE 0x0004 /* if only 1 object, don't ask */
|
|
#define USE_INVLET 0x0008 /* use object's invlet */
|
|
#define INVORDER_SORT 0x0010 /* sort objects by packorder */
|
|
#define SIGNAL_NOMENU 0x0020 /* return -1 rather than 0 if none allowed */
|
|
#define SIGNAL_ESCAPE 0x0040 /* return -2 rather than 0 for ESC */
|
|
#define FEEL_COCKATRICE 0x0080 /* engage cockatrice checks and react */
|
|
#define INCLUDE_HERO 0x0100 /* show hero among engulfer's inventory */
|
|
|
|
/* Flags to control query_category() */
|
|
/* BY_NEXTHERE and INCLUDE_VENOM are used by query_category() too, so
|
|
skip 0x0001 and 0x0002 */
|
|
#define UNPAID_TYPES 0x0004
|
|
#define GOLD_TYPES 0x0008
|
|
#define WORN_TYPES 0x0010
|
|
#define ALL_TYPES 0x0020
|
|
#define BILLED_TYPES 0x0040
|
|
#define CHOOSE_ALL 0x0080
|
|
#define BUC_BLESSED 0x0100
|
|
#define BUC_CURSED 0x0200
|
|
#define BUC_UNCURSED 0x0400
|
|
#define BUC_UNKNOWN 0x0800
|
|
#define JUSTPICKED 0x1000
|
|
#define BUC_ALLBKNOWN (BUC_BLESSED | BUC_CURSED | BUC_UNCURSED)
|
|
#define BUCX_TYPES (BUC_ALLBKNOWN | BUC_UNKNOWN)
|
|
#define ALL_TYPES_SELECTED -2
|
|
|
|
/* Flags for oname(), artifact_exists(), artifact_origin() */
|
|
#define ONAME_NO_FLAGS 0U /* none of the below; they apply to artifacts */
|
|
/* 0x0001U is reserved for 'exists' */
|
|
/* flags indicating where an artifact came from */
|
|
#define ONAME_VIA_NAMING 0x0002U /* oname() is being called by do_oname();
|
|
* only matters if creating Sting|Orcrist */
|
|
#define ONAME_WISH 0x0004U /* created via wish */
|
|
#define ONAME_GIFT 0x0008U /* created as a divine reward after #offer or
|
|
* special #pray result of being crowned */
|
|
#define ONAME_VIA_DIP 0x0010U /* created Excalibur in a fountain */
|
|
#define ONAME_LEVEL_DEF 0x0020U /* placed by a special level's definition */
|
|
#define ONAME_BONES 0x0040U /* object came from bones; in its original
|
|
* game it had one of the other bits but we
|
|
* don't care which one */
|
|
#define ONAME_RANDOM 0x0080U /* something created an artifact randomly
|
|
* with mk_artifact() (mksboj or mk_player)
|
|
* or m_initweap() (lawful Angel) */
|
|
/* flag controlling potential livelog event of finding an artifact */
|
|
#define ONAME_KNOW_ARTI 0x0100U /* hero is already aware of this artifact */
|
|
/* flag for suppressing perm_invent update when name gets assigned */
|
|
#define ONAME_SKIP_INVUPD 0x0200U /* don't call update_inventory() */
|
|
|
|
/* Flags to control find_mid() and whereis_mon() */
|
|
#define FM_FMON 0x01 /* search the fmon chain */
|
|
#define FM_MIGRATE 0x02 /* search the migrating monster chain */
|
|
#define FM_MYDOGS 0x04 /* search gm.mydogs */
|
|
#define FM_YOU 0x08 /* check for gy.youmonst */
|
|
#define FM_EVERYWHERE (FM_YOU | FM_FMON | FM_MIGRATE | FM_MYDOGS)
|
|
|
|
/* Flags to control pick_[race,role,gend,align] routines in role.c */
|
|
#define PICK_RANDOM 0
|
|
#define PICK_RIGID 1
|
|
|
|
/* Flags to control dotrap() and mintrap() in trap.c */
|
|
#define NO_TRAP_FLAGS 0x00U
|
|
#define FORCETRAP 0x01U /* triggering not left to chance */
|
|
#define NOWEBMSG 0x02U /* suppress stumble into web message */
|
|
#define FORCEBUNGLE 0x04U /* adjustments appropriate for bungling */
|
|
#define RECURSIVETRAP 0x08U /* trap changed into another type this same turn */
|
|
#define TOOKPLUNGE 0x10U /* used '>' to enter pit below you */
|
|
#define VIASITTING 0x20U /* #sit while at trap location (affects message) */
|
|
#define FAILEDUNTRAP 0x40U /* trap activated by failed untrap attempt */
|
|
#define HURTLING 0x80U /* monster is hurtling through air */
|
|
|
|
/* Flags to control test_move in hack.c */
|
|
#define DO_MOVE 0 /* really doing the move */
|
|
#define TEST_MOVE 1 /* test a normal move (move there next) */
|
|
#define TEST_TRAV 2 /* test a future travel location */
|
|
#define TEST_TRAP 3 /* check if a future travel loc is a trap */
|
|
|
|
/* m_move return values */
|
|
#define MMOVE_NOTHING 0
|
|
#define MMOVE_MOVED 1 /* monster moved */
|
|
#define MMOVE_DIED 2 /* monster died */
|
|
#define MMOVE_DONE 3 /* monster used up all actions */
|
|
#define MMOVE_NOMOVES 4 /* monster has no valid locations to move to */
|
|
|
|
/*** some utility macros ***/
|
|
#define y_n(query) yn_function(query, ynchars, 'n', TRUE)
|
|
#define ynq(query) yn_function(query, ynqchars, 'q', TRUE)
|
|
#define ynaq(query) yn_function(query, ynaqchars, 'y', TRUE)
|
|
#define nyaq(query) yn_function(query, ynaqchars, 'n', TRUE)
|
|
#define nyNaq(query) yn_function(query, ynNaqchars, 'n', TRUE)
|
|
#define ynNaq(query) yn_function(query, ynNaqchars, 'y', TRUE)
|
|
/* YN() is same as y_n() except doesn't save the response in do-again buffer */
|
|
#define YN(query) yn_function(query, ynchars, 'n', FALSE)
|
|
|
|
/* Macros for scatter */
|
|
#define VIS_EFFECTS 0x01 /* display visual effects */
|
|
#define MAY_HITMON 0x02 /* objects may hit monsters */
|
|
#define MAY_HITYOU 0x04 /* objects may hit you */
|
|
#define MAY_HIT (MAY_HITMON | MAY_HITYOU)
|
|
#define MAY_DESTROY 0x08 /* objects may be destroyed at random */
|
|
#define MAY_FRACTURE 0x10 /* boulders & statues may fracture */
|
|
|
|
/* Macros for launching objects */
|
|
#define ROLL 0x01 /* the object is rolling */
|
|
#define FLING 0x02 /* the object is flying thru the air */
|
|
#define LAUNCH_UNSEEN 0x40 /* hero neither caused nor saw it */
|
|
#define LAUNCH_KNOWN 0x80 /* the hero caused this by explicit action */
|
|
|
|
/* enlightenment control flags */
|
|
#define BASICENLIGHTENMENT 1 /* show mundane stuff */
|
|
#define MAGICENLIGHTENMENT 2 /* show intrinsics and such */
|
|
#define ENL_GAMEINPROGRESS 0
|
|
#define ENL_GAMEOVERALIVE 1 /* ascension, escape, quit, trickery */
|
|
#define ENL_GAMEOVERDEAD 2
|
|
|
|
/* control flags for sortloot() */
|
|
#define SORTLOOT_PACK 0x01
|
|
#define SORTLOOT_INVLET 0x02
|
|
#define SORTLOOT_LOOT 0x04
|
|
#define SORTLOOT_INUSE 0x08 /* for inventory, in-use items first */
|
|
#define SORTLOOT_PETRIFY 0x20 /* override filter func for c-trice corpses */
|
|
|
|
/* flags for xkilled() [note: meaning of first bit used to be reversed,
|
|
1 to give message and 0 to suppress] */
|
|
#define XKILL_GIVEMSG 0
|
|
#define XKILL_NOMSG 1
|
|
#define XKILL_NOCORPSE 2
|
|
#define XKILL_NOCONDUCT 4
|
|
|
|
/* pline_flags; mask values for custompline()'s first argument */
|
|
/* #define PLINE_ORDINARY 0 */
|
|
#define PLINE_NOREPEAT 1
|
|
#define OVERRIDE_MSGTYPE 2
|
|
#define SUPPRESS_HISTORY 4
|
|
#define URGENT_MESSAGE 8
|
|
#define PLINE_VERBALIZE 16
|
|
#define PLINE_SPEECH 32
|
|
#define NO_CURS_ON_U 64
|
|
|
|
/* get_count flags */
|
|
#define GC_NOFLAGS 0
|
|
#define GC_SAVEHIST 1 /* save "Count: 123" in message history */
|
|
#define GC_CONDHIST 2 /* save "Count: N" in message history unless the
|
|
* first digit is passed in and N matches it */
|
|
#define GC_ECHOFIRST 4 /* echo "Count: 1" even when there's only one digit */
|
|
|
|
/* rloc() flags */
|
|
#define RLOC_NONE 0x00
|
|
#define RLOC_ERR 0x01 /* allow impossible() if no rloc */
|
|
#define RLOC_MSG 0x02 /* show vanish/appear msg */
|
|
#define RLOC_NOMSG 0x04 /* prevent appear msg, even for STRAT_APPEARMSG */
|
|
|
|
/* indices for some special tin types */
|
|
#define ROTTEN_TIN 0
|
|
#define HOMEMADE_TIN 1
|
|
#define SPINACH_TIN (-1)
|
|
#define RANDOM_TIN (-2)
|
|
#define HEALTHY_TIN (-3)
|
|
|
|
/* Corpse aging */
|
|
#define TAINT_AGE (50L) /* age when corpses go bad */
|
|
#define TROLL_REVIVE_CHANCE 37 /* 1/37 chance for 50 turns ~ 75% chance */
|
|
#define ROT_AGE (250L) /* age when corpses rot away */
|
|
|
|
/* Some misc definitions */
|
|
#define POTION_OCCUPANT_CHANCE(n) (13 + 2 * (n))
|
|
#define WAND_BACKFIRE_CHANCE 100
|
|
#define WAND_WREST_CHANCE 121
|
|
#define BALL_IN_MON (u.uswallow && uball && uball->where == OBJ_FREE)
|
|
#define CHAIN_IN_MON (u.uswallow && uchain && uchain->where == OBJ_FREE)
|
|
#define NODIAG(monnum) ((monnum) == PM_GRID_BUG)
|
|
|
|
/* Flags to control menus */
|
|
#define MENUTYPELEN sizeof("traditional ")
|
|
#define MENU_TRADITIONAL 0
|
|
#define MENU_COMBINATION 1
|
|
#define MENU_FULL 2
|
|
#define MENU_PARTIAL 3
|
|
|
|
/* flags to control teleds() */
|
|
#define TELEDS_NO_FLAGS 0
|
|
#define TELEDS_ALLOW_DRAG 1
|
|
#define TELEDS_TELEPORT 2
|
|
|
|
/* flags for mktrap() */
|
|
#define MKTRAP_NOFLAGS 0x0U
|
|
#define MKTRAP_SEEN 0x1U /* trap is seen */
|
|
#define MKTRAP_MAZEFLAG 0x2U /* choose random coords instead of room */
|
|
#define MKTRAP_NOSPIDERONWEB 0x4U /* web will not generate a spider */
|
|
#define MKTRAP_NOVICTIM 0x8U /* no victim corpse or items on it */
|
|
|
|
#define MON_POLE_DIST 5 /* How far monsters can use pole-weapons */
|
|
#define PET_MISSILE_RANGE2 36 /* Square of distance within which pets shoot */
|
|
|
|
/* flags passed to getobj() to control how it responds to player input */
|
|
#define GETOBJ_NOFLAGS 0x0
|
|
#define GETOBJ_ALLOWCNT 0x1 /* is a count allowed with this command? */
|
|
#define GETOBJ_PROMPT 0x2 /* should it force a prompt for input? (prevents
|
|
* it exiting early with "You don't have anything
|
|
* to foo" if nothing in inventory is valid) */
|
|
|
|
/* flags for hero_breaks() and hits_bars(); BRK_KNOWN* let callers who have
|
|
already called breaktest() prevent it from being called again since it
|
|
has a random factor which makes it be non-deterministic */
|
|
#define BRK_BY_HERO 0x01
|
|
#define BRK_FROM_INV 0x02
|
|
#define BRK_KNOWN2BREAK 0x04
|
|
#define BRK_KNOWN2NOTBREAK 0x08
|
|
#define BRK_KNOWN_OUTCOME (BRK_KNOWN2BREAK | BRK_KNOWN2NOTBREAK)
|
|
#define BRK_MELEE 0x10
|
|
|
|
/* extended command return values */
|
|
#define ECMD_OK 0x00 /* cmd done successfully */
|
|
#define ECMD_TIME 0x01 /* cmd took time, uses up a turn */
|
|
#define ECMD_CANCEL 0x02 /* cmd canceled by user */
|
|
#define ECMD_FAIL 0x04 /* cmd failed to finish, maybe with a yafm */
|
|
|
|
/* flags for newcham() */
|
|
#define NO_NC_FLAGS 0U
|
|
#define NC_SHOW_MSG 0x01U
|
|
#define NC_VIA_WAND_OR_SPELL 0x02U
|
|
|
|
/* Constant passed to explode() for gas spores because gas spores are weird.
|
|
* Specifically, this is an exception to whole "explode() uses dobuzz types"
|
|
* system (the range -1 to -9 isn't used by it, for some reason), where this
|
|
* is effectively an extra dobuzz type, and some zap.c code needs to be aware
|
|
* of it. */
|
|
#define PHYS_EXPL_TYPE -1
|
|
|
|
/* macros for dobuzz() type */
|
|
#define BZ_VALID_ADTYP(adtyp) ((adtyp) >= AD_MAGM && (adtyp) <= AD_SPC2)
|
|
|
|
#define BZ_OFS_AD(adtyp) (abs((adtyp) - AD_MAGM) % 10)
|
|
#define BZ_OFS_WAN(otyp) (abs((otyp) - WAN_MAGIC_MISSILE) % 10)
|
|
#define BZ_OFS_SPE(otyp) (abs((otyp) - SPE_MAGIC_MISSILE) % 10)
|
|
/* hero shooting a wand */
|
|
#define BZ_U_WAND(bztyp) (0 + (bztyp)) /* 0..9 */
|
|
/* hero casting a spell */
|
|
#define BZ_U_SPELL(bztyp) (10 + (bztyp)) /* 10..19 */
|
|
/* hero breathing as a monster */
|
|
#define BZ_U_BREATH(bztyp) (20 + (bztyp)) /* 20..29 */
|
|
/* monster casting a spell */
|
|
#define BZ_M_SPELL(bztyp) (-10 - (bztyp)) /* -19..-10 */
|
|
/* monster breathing */
|
|
#define BZ_M_BREATH(bztyp) (-20 - (bztyp)) /* -29..-20 */
|
|
/* monster shooting a wand; note: not -9 to -0 because -0 is ambiguous */
|
|
#define BZ_M_WAND(bztyp) (-30 - (bztyp)) /* -39..-30 */
|
|
|
|
/* pick a random entry from array */
|
|
#define ROLL_FROM(array) array[rn2(SIZE(array))]
|
|
/* array with terminator variation */
|
|
/* #define ROLL_FROMT(array) array[rn2(SIZE(array) - 1)] */
|
|
|
|
/* validate index of array */
|
|
#define IndexOk(idx, array) \
|
|
((idx) >= 0 && (idx) < SIZE(array))
|
|
/* array with terminator variation */
|
|
#define IndexOkT(idx, array) \
|
|
((idx) >= 0 && (idx) < (SIZE(array) - 1))
|
|
|
|
#define FEATURE_NOTICE_VER(major, minor, patch) \
|
|
(((unsigned long) major << 24) | ((unsigned long) minor << 16) \
|
|
| ((unsigned long) patch << 8) | ((unsigned long) 0))
|
|
|
|
#define FEATURE_NOTICE_VER_MAJ (flags.suppress_alert >> 24)
|
|
#define FEATURE_NOTICE_VER_MIN \
|
|
(((unsigned long) (0x0000000000FF0000L & flags.suppress_alert)) >> 16)
|
|
#define FEATURE_NOTICE_VER_PATCH \
|
|
(((unsigned long) (0x000000000000FF00L & flags.suppress_alert)) >> 8)
|
|
|
|
#ifndef max
|
|
#define max(a, b) ((a) > (b) ? (a) : (b))
|
|
#endif
|
|
#ifndef min
|
|
#define min(x, y) ((x) < (y) ? (x) : (y))
|
|
#endif
|
|
#define plur(x) (((x) == 1) ? "" : "s")
|
|
|
|
/* Cast to int, but limit value to range. */
|
|
#define LIMIT_TO_RANGE_INT(lo, hi, var) \
|
|
((int) ((var) < (lo) ? (lo) : (var) > (hi) ? (hi) : (var)))
|
|
|
|
#define ARM_BONUS(obj) \
|
|
(objects[(obj)->otyp].a_ac + (obj)->spe \
|
|
- min((int) greatest_erosion(obj), objects[(obj)->otyp].a_ac))
|
|
|
|
#define makeknown(x) discover_object((x), TRUE, TRUE)
|
|
#define distu(xx, yy) dist2((coordxy) (xx), (coordxy) (yy), u.ux, u.uy)
|
|
#define mdistu(mon) distu((mon)->mx, (mon)->my)
|
|
#define onlineu(xx, yy) online2((coordxy)(xx), (coordxy)(yy), u.ux, u.uy)
|
|
|
|
#define rn1(x, y) (rn2(x) + (y))
|
|
|
|
/* negative armor class is randomly weakened to prevent invulnerability */
|
|
#define AC_VALUE(AC) ((AC) >= 0 ? (AC) : -rnd(-(AC)))
|
|
|
|
#if defined(MICRO) && !defined(__DJGPP__)
|
|
#define getuid() 1
|
|
#define getlogin() ((char *) 0)
|
|
#endif /* MICRO */
|
|
|
|
/* These may have been defined to platform-specific values in *conf.h
|
|
* or on the compiler command line from a hints file or Makefile */
|
|
|
|
#ifndef QSORTCALLBACK
|
|
#define QSORTCALLBACK
|
|
#endif
|
|
|
|
#ifndef SIG_RET_TYPE
|
|
#define SIG_RET_TYPE void (*)(int)
|
|
#endif
|
|
|
|
#define DEVTEAM_EMAIL "devteam@nethack.org"
|
|
#define DEVTEAM_URL "https://www.nethack.org/"
|
|
|
|
#if !defined(CROSSCOMPILE) || defined(CROSSCOMPILE_TARGET)
|
|
#include "nhlua.h"
|
|
#endif
|
|
|
|
#if !defined(RECOVER_C)
|
|
|
|
#include "extern.h"
|
|
#include "savefile.h"
|
|
#include "decl.h"
|
|
|
|
#endif /* RECOVER_C */
|
|
|
|
#endif /* HACK_H */
|
|
|