Files
nethack/include/sp_lev.h
copperwater 2d4f9893ad Enable more ways to specify monster inventory in special levels
This originated with a bug in NerfHack in which the developer specified
an inventory for a quest nemesis, but neglected to include the Bell of
Opening in it. Since monsters' inventory contents from makemon() were
tossed out completely, this caused a situation where the Bell was
deleted and the game was unwinnable. The first part of this change is
guarding against that by adding mdrop_special_objs before discarding the
inventory. This does create a possibility where if the programmer *does*
specify a nemesis get the Bell item in their inventory, while neglecting
to remove its special case generation in makemon.c, it would generate
twice - but two Bells is better than none.

Working on that fix led me to think about a limitation of the current
sp_lev.c behavior. You could either have a monster generate with its
species-typical inventory by not specifying an inventory for it, or you
could have it generate with custom inventory but then have to use that
to clumsily reproduce the normal inventory's complex chances and
conditionals in mongets(). So the remainder of this commit implements
another flag for des.monster(), keep_default_invent, that allows for
more flexibility in two ways:

1. When des.monster() contains an inventory function and
   keep_default_invent is true, the monster will retain everything it
   gets from makemon() and the objects in the inventory function are in
   ADDITION to those. This is useful for augmenting a monster's default
   kit with something to make them more threatening, or just more loot.
2. When des.monster contains no inventory function and
   keep_default_invent is false, the monster will get NO inventory even
   if its species is normally supposed to. I'm not sure where exactly
   this would be used, but it doesn't hurt to have it available.

When keep_default_invent is not specified at all, the behavior remains
the same as it is now - if inventory is provided, default items are
discarded, and if not, they are kept.
2025-01-02 08:07:50 +02:00

208 lines
5.1 KiB
C

/* 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. */
#ifndef SP_LEV_H
#define SP_LEV_H
/* wall directions */
#define W_RANDOM -1
#define W_NORTH 1
#define W_SOUTH 2
#define W_EAST 4
#define W_WEST 8
#define W_ANY (W_NORTH | W_SOUTH | W_EAST | W_WEST)
/* MAP limits */
#define MAP_X_LIM 76
#define MAP_Y_LIM 21
/* Per level flags */
#define NOTELEPORT 0x00000001L
#define HARDFLOOR 0x00000002L
#define NOMMAP 0x00000004L
#define SHORTSIGHTED 0x00000008L
#define ARBOREAL 0x00000010L
#define MAZELEVEL 0x00000020L
#define PREMAPPED 0x00000040L /* premapped level & sokoban rules */
#define SHROUD 0x00000080L
#define GRAVEYARD 0x00000100L
#define ICEDPOOLS 0x00000200L /* for ice locations: ICED_POOL vs ICED_MOAT \
*/
#define SOLIDIFY 0x00000400L /* outer areas are nondiggable & nonpasswall */
#define CORRMAZE 0x00000800L /* for maze levels only */
#define CHECK_INACCESSIBLES 0x00001000L /* check for inaccessible areas and
generate ways to escape from them */
/* different level layout initializers */
enum lvlinit_types {
LVLINIT_NONE = 0,
LVLINIT_SOLIDFILL,
LVLINIT_MAZEGRID,
LVLINIT_MAZE,
LVLINIT_MINES,
LVLINIT_ROGUE,
LVLINIT_SWAMP
};
/* max. nested depth of subrooms */
#define MAX_NESTED_ROOMS 5
/* When creating objects, we need to know whether
* it's a container and/or contents.
*/
#define SP_OBJ_CONTENT 0x1
#define SP_OBJ_CONTAINER 0x2
/* SPO_FILTER types */
#define SPOFILTER_PERCENT 0
#define SPOFILTER_SELECTION 1
#define SPOFILTER_MAPCHAR 2
/* gradient filter types */
#define SEL_GRADIENT_RADIAL 0
#define SEL_GRADIENT_SQUARE 1
#define SP_COORD_IS_RANDOM 0x01000000L
/* Humidity flags for get_location() and friends, used with
* SP_COORD_PACK_RANDOM() */
#define DRY 0x01
#define WET 0x02
#define HOT 0x04
#define SOLID 0x08
#define ANY_LOC 0x10 /* even outside the level */
#define NO_LOC_WARN 0x20 /* no complaints and set x & y to -1, if no loc */
#define SPACELOC 0x40 /* like DRY, but accepts furniture too */
/* has_invent flags */
#define NO_INVENT 0 /* monster doesn't get any invent */
#define CUSTOM_INVENT 0x01 /* monster gets items specified in lua */
#define DEFAULT_INVENT 0x02 /* monster gets items from makemon() */
#define SP_COORD_X(l) (l & 0xff)
#define SP_COORD_Y(l) ((l >> 16) & 0xff)
#define SP_COORD_PACK(x, y) (((x) & 0xff) + (((y) & 0xff) << 16))
#define SP_COORD_PACK_RANDOM(f) (SP_COORD_IS_RANDOM | (f))
struct sp_coder {
int premapped;
boolean solidify;
struct mkroom *croom;
int room_stack;
struct mkroom *tmproomlist[MAX_NESTED_ROOMS + 1];
boolean failed_room[MAX_NESTED_ROOMS + 1];
int n_subroom;
boolean lvl_is_joined;
boolean check_inaccessibles;
int allow_flips;
};
/*
* Structures manipulated by the special levels loader & compiler
*/
#define packed_coord long
typedef uint32_t getloc_flags_t;
typedef struct {
xint16 is_random;
getloc_flags_t getloc_flags;
int x, y;
} unpacked_coord;
typedef struct {
xint16 init_style; /* one of LVLINIT_foo */
long flags;
schar filling;
boolean init_present, padding;
char fg, bg;
boolean smoothed, joined;
xint16 lit, walled;
boolean icedpools;
int corrwid, wallthick;
boolean rm_deadends;
} lev_init;
typedef struct {
xint16 wall, pos, secret, mask;
} room_door;
typedef struct {
packed_coord coord;
coordxy x, y;
xint16 type;
boolean spider_on_web;
boolean seen;
boolean novictim;
} spltrap;
typedef struct {
Str_or_Len name, appear_as;
short id;
unsigned int sp_amask; /* splev amask */
packed_coord coord;
coordxy x, y;
xint16 class, appear;
schar peaceful, asleep;
short female, invis, cancelled, revived, avenge, fleeing, blinded,
paralyzed, stunned, confused, waiting;
long seentraps;
short has_invent;
mmflags_nht mm_flags; /* makemon flags */
} monster;
typedef struct {
Str_or_Len name;
int corpsenm;
short id, spe;
packed_coord coord;
coordxy x, y;
xint16 class, containment;
schar curse_state;
int quan;
short buried;
short lit;
short eroded, locked, trapped, tknown, recharged, invis, greased, broken,
achievement;
} object;
typedef struct {
packed_coord coord;
coordxy x, y;
unsigned int sp_amask; /* splev amask */
xint16 shrine;
} altar;
typedef struct {
coordxy x1, y1, x2, y2;
xint16 rtype, rlit, rirreg;
} region;
typedef struct {
xint16 ter, tlit;
} terrain;
typedef struct {
struct {
xint16 room;
xint16 wall;
xint16 door;
} src, dest;
} corridor;
typedef struct _room {
Str_or_Len name;
Str_or_Len parent;
coordxy x, y;
xint16 w, h;
xint16 xalign, yalign;
xint16 rtype, chance, rlit, needfill;
boolean joined;
} room;
struct mapfragment {
int wid, hei;
char *data;
};
#endif /* SP_LEV_H */