Files
nethack/include/you.h
Pasi Kallinen e645c0b4bb Allow starting game as pauper, without any inventory
And also without spells, skills, or preidentified items.
This also implies nudist.

Breaks saves and bones.
2024-08-29 20:51:13 +03:00

556 lines
24 KiB
C

/* NetHack 3.7 you.h $NHDT-Date: 1702349061 2023/12/12 02:44:21 $ $NHDT-Branch: NetHack-3.7 $:$NHDT-Revision: 1.75 $ */
/* Copyright (c) Stichting Mathematisch Centrum, Amsterdam, 1985. */
/*-Copyright (c) Robert Patrick Rankin, 2016. */
/* NetHack may be freely redistributed. See license for details. */
#ifndef YOU_H
#define YOU_H
#include "attrib.h"
#include "monst.h"
#ifndef PROP_H
#include "prop.h" /* (needed here for util/makedefs.c) */
#endif
#include "skills.h"
/*** Substructures ***/
struct RoleName {
const char *m; /* name when character is male */
const char *f; /* when female; null if same as male */
};
struct RoleAdvance {
/* "fix" is the fixed amount, "rnd" is the random amount */
xint16 infix, inrnd; /* at character initialization */
xint16 lofix, lornd; /* gained per level < gu.urole.xlev */
xint16 hifix, hirnd; /* gained per level >= gu.urole.xlev */
};
struct u_have {
Bitfield(amulet, 1); /* carrying Amulet */
Bitfield(bell, 1); /* carrying Bell */
Bitfield(book, 1); /* carrying Book */
Bitfield(menorah, 1); /* carrying Candelabrum */
Bitfield(questart, 1); /* carrying the Quest Artifact */
Bitfield(unused, 3);
};
struct u_event {
Bitfield(minor_oracle, 1); /* received at least 1 cheap oracle */
Bitfield(major_oracle, 1); /* " expensive oracle */
Bitfield(read_tribute, 1); /* read a passage from a novel */
Bitfield(qcalled, 1); /* called by Quest leader to do task */
Bitfield(qexpelled, 1); /* expelled from the Quest dungeon */
Bitfield(qcompleted, 1); /* successfully completed Quest task */
Bitfield(uheard_tune, 2); /* 1=know about, 2=heard passtune, 3=bridge has
* been destroyed so tune has become useless */
Bitfield(uopened_dbridge, 1); /* opened the drawbridge */
Bitfield(invoked, 1); /* invoked Gate to the Sanctum level */
Bitfield(gehennom_entered, 1); /* entered Gehennom via Valley */
Bitfield(uhand_of_elbereth, 2); /* became Hand of Elbereth */
Bitfield(udemigod, 1); /* killed the wiz */
Bitfield(uvibrated, 1); /* stepped on "vibrating square" */
Bitfield(ascended, 1); /* has offered the Amulet */
};
/*
* Achievements: milestones reached during the current game.
* Numerical order of these matters because they've been encoded in
* a bitmask in xlogfile. Reordering would break decoding that.
* Aside from that, the number isn't significant--they're recorded
* and eventually disclosed in the order achieved.
*
* Since xlogfile could be post-processed by unknown tools, we should
* limit these to 31 total (it's possible that 32-bit signed longs are
* the best such tools can offer). Eventually that is likely to need
* to change, probably by giving xlogfile an achieve2 field rather
* than by assuming that 64-bit longs are viable or by squeezing in a
* 32nd entry by switching to unsigned long.
*/
enum achivements {
ACH_BELL = 1, /* acquired Bell of Opening */
ACH_HELL = 2, /* entered Gehennom */
ACH_CNDL = 3, /* acquired Candelabrum of Invocation */
ACH_BOOK = 4, /* acquired Book of the Dead */
ACH_INVK = 5, /* performed invocation to gain access to Sanctum */
ACH_AMUL = 6, /* acquired The Amulet */
ACH_ENDG = 7, /* entered end game */
ACH_ASTR = 8, /* entered Astral Plane */
ACH_UWIN = 9, /* ascended */
ACH_MINE_PRIZE = 10, /* acquired Mines' End luckstone */
ACH_SOKO_PRIZE = 11, /* acquired Sokoban bag or amulet */
ACH_MEDU = 12, /* killed Medusa */
ACH_BLND = 13, /* hero was always blond, no, blind */
ACH_NUDE = 14, /* hero never wore armor */
/* 1 through 14 were present in 3.6.x; the rest are newer; first,
some easier ones so less skilled players can have achievements */
ACH_MINE = 15, /* entered Gnomish Mines */
ACH_TOWN = 16, /* reached Minetown */
ACH_SHOP = 17, /* entered a shop */
ACH_TMPL = 18, /* entered a temple */
ACH_ORCL = 19, /* consulted the Oracle */
ACH_NOVL = 20, /* read at least one passage from a Discworld novel */
ACH_SOKO = 21, /* entered Sokoban */
ACH_BGRM = 22, /* entered Bigroom (not guaranteed to be in every dgn) */
/* role's rank titles, beyond first (#0 at level one, not an achievement);
23..30 are negated if hero is female at the time new rank is gained
so that disclosing them can use the gender which applied at the time */
ACH_RNK1 = 23, ACH_RNK2 = 24, ACH_RNK3 = 25, ACH_RNK4 = 26,
ACH_RNK5 = 27, ACH_RNK6 = 28, ACH_RNK7 = 29, ACH_RNK8 = 30,
ACH_TUNE = 31, /* discovered the castle drawbridge's open/close tune */
N_ACH = 32 /* allocate room for 31 plus a slot for 0 terminator */
};
/*
* Other potential achievements to track (this comment briefly resided
* in encodeachieve(topten.c) and has been revised since moving here:
* AC <= 0, AC <= -10, AC <= -20 (stop there; lower is better but
* not something to encourage with achievements),
* got quest summons,
* entered quest branch,
* chatted with leader,
* entered second or lower quest level (implies leader gave the Ok),
* entered last quest level,
* defeated nemesis (not same as acquiring Bell or artifact),
* completed quest (formally, by bringing artifact to leader),
* entered rogue level,
* entered Fort Ludios level/branch (not guaranteed to be achievable),
* entered Medusa level,
* entered castle level,
* obtained castle wand (handle similarly to mines and sokoban prizes),
* passed Valley level (entered-Gehennom already covers Valley itself),
* [assorted demon lairs?],
* entered Vlad's tower branch,
* defeated Vlad (not same as acquiring Candelabrum),
* entered Wizard's tower area within relevant level,
* defeated Wizard,
* found vibrating square,
* entered sanctum level (maybe not; too close to performed-invocation),
* [defeated Famine, defeated Pestilence, defeated Death]
*/
struct u_realtime {
long realtime; /* accumulated playing time in seconds */
time_t start_timing; /* time game was started or restored or 'realtime'
was last updated (savegamestate for checkpoint) */
time_t finish_time; /* end of 'realtime' interval: time of save or
end of game; used for topten/logfile/xlogfile */
};
/* KMH, conduct --
* These are voluntary challenges. Each field denotes the number of
* times a challenge has been violated.
*/
struct u_conduct { /* number of times... */
long unvegetarian; /* eaten any animal */
long unvegan; /* ... or any animal byproduct */
long food; /* ... or any comestible */
long gnostic; /* used prayer, priest, or altar */
long weaphit; /* hit a monster with a weapon */
long killer; /* killed a monster yourself */
long literate; /* read something (other than BotD) */
long polypiles; /* polymorphed an object */
long polyselfs; /* transformed yourself */
long wishes; /* used a wish */
long wisharti; /* wished for an artifact */
long sokocheat; /* violated special 'rules' in Sokoban */
long pets; /* obtained a pet */
/* genocides already listed at end of game */
};
struct u_roleplay {
boolean blind; /* permanently blind */
boolean nudist; /* has not worn any armor, ever */
boolean deaf; /* permanently deaf */
boolean pauper; /* no starting inventory */
long numbones; /* # of bones files loaded */
};
/*** Unified structure containing role information ***/
struct Role {
/*** Strings that name various things ***/
struct RoleName name; /* the role's name (from u_init.c) */
struct RoleName rank[9]; /* names for experience levels (from botl.c) */
const char *lgod, *ngod, *cgod; /* god names (from pray.c) */
const char *filecode; /* abbreviation for use in file names */
const char *homebase; /* quest leader's location (from questpgr.c) */
const char *intermed; /* quest intermediate goal (from questpgr.c) */
/*** Indices of important monsters and objects ***/
short mnum, /* index (PM_) of role (botl.c) */
petnum, /* PM_ of preferred pet (NON_PM == random) */
ldrnum, /* PM_ of quest leader (questpgr.c) */
guardnum, /* PM_ of quest guardians (questpgr.c) */
neminum, /* PM_ of quest nemesis (questpgr.c) */
enemy1num, /* specific quest enemies (NON_PM == random) */
enemy2num;
char enemy1sym, /* quest enemies by class (S_) */
enemy2sym;
short questarti; /* index (ART_) of quest artifact (questpgr.c) */
/*** Bitmasks ***/
short allow; /* bit mask of allowed variations */
#define ROLE_RACEMASK 0x0ff8 /* allowable races */
#define ROLE_GENDMASK 0xf000 /* allowable genders */
#define ROLE_MALE 0x1000
#define ROLE_FEMALE 0x2000
#define ROLE_NEUTER 0x4000
#define ROLE_ALIGNMASK AM_MASK /* allowable alignments */
#define ROLE_LAWFUL AM_LAWFUL
#define ROLE_NEUTRAL AM_NEUTRAL
#define ROLE_CHAOTIC AM_CHAOTIC
/*** Attributes (from attrib.c and exper.c) ***/
xint16 attrbase[A_MAX]; /* lowest initial attributes */
xint16 attrdist[A_MAX]; /* distribution of initial attributes */
struct RoleAdvance hpadv; /* hit point advancement */
struct RoleAdvance enadv; /* energy advancement */
xint16 xlev; /* cutoff experience level */
xint16 initrecord; /* initial alignment record */
/*** Spell statistics (from spell.c) ***/
int spelbase; /* base spellcasting penalty */
int spelheal; /* penalty (-bonus) for healing spells */
int spelshld; /* penalty for wearing any shield */
int spelarmr; /* penalty for wearing metal armour */
int spelstat; /* which stat (A_) is used */
int spelspec; /* spell (SPE_) the class excels at */
int spelsbon; /* penalty (-bonus) for that spell */
/*** Properties in variable-length arrays ***/
/* intrinsics (see attrib.c) */
/* initial inventory (see u_init.c) */
/* skills (see u_init.c) */
/*** Don't forget to add... ***/
/* quest leader, guardians, nemesis (monst.c) */
/* quest artifact (artilist.h) */
/* quest dungeon definition (dat/Xyz.dat) */
/* quest text (dat/quest.txt) */
/* dictionary entries (dat/data.bas) */
};
extern const struct Role roles[]; /* table of available roles */
#define Role_if(X) (gu.urole.mnum == (X))
#define Role_switch (gu.urole.mnum)
/* used during initialization for race, gender, and alignment
as well as for character class */
#define ROLE_NONE (-1)
#define ROLE_RANDOM (-2)
/*** Unified structure specifying race information ***/
struct Race {
/*** Strings that name various things ***/
const char *noun; /* noun ("human", "elf") */
const char *adj; /* adjective ("human", "elven") */
const char *coll; /* collective ("humanity", "elvenkind") */
const char *filecode; /* code for filenames */
struct RoleName individual; /* individual as a noun ("man", "elf") */
/*** Indices of important monsters and objects ***/
short mnum, /* PM_ as a monster */
mummynum, /* PM_ as a mummy */
zombienum; /* PM_ as a zombie */
/*** Bitmasks ***/
short allow; /* bit mask of allowed variations */
short selfmask, /* your own race's bit mask */
lovemask, /* bit mask of always peaceful */
hatemask; /* bit mask of always hostile */
/*** Attributes ***/
xint16 attrmin[A_MAX]; /* minimum allowable attribute */
xint16 attrmax[A_MAX]; /* maximum allowable attribute */
struct RoleAdvance hpadv; /* hit point advancement */
struct RoleAdvance enadv; /* energy advancement */
#if 0 /* DEFERRED */
int nv_range; /* night vision range */
int xray_range; /* X-ray vision range */
#endif
/*** Properties in variable-length arrays ***/
/* intrinsics (see attrib.c) */
/*** Don't forget to add... ***/
/* quest leader, guardians, nemesis (monst.c) */
/* quest dungeon definition (dat/Xyz.dat) */
/* quest text (dat/quest.txt) */
/* dictionary entries (dat/data.bas) */
};
extern const struct Race races[]; /* Table of available races */
#define Race_if(X) (gu.urace.mnum == (X))
#define Race_switch (gu.urace.mnum)
/*** Unified structure specifying gender information ***/
struct Gender {
const char *adj; /* male/female/neuter */
const char *he; /* he/she/it */
const char *him; /* him/her/it */
const char *his; /* his/her/its */
const char *filecode; /* file code */
short allow; /* equivalent ROLE_ mask */
};
#define ROLE_GENDERS 2 /* number of permitted player genders
increment to 3 if you allow neuter roles */
extern const struct Gender genders[]; /* table of available genders */
/* pronouns for the hero */
#define uhe() (genders[flags.female ? 1 : 0].he)
#define uhim() (genders[flags.female ? 1 : 0].him)
#define uhis() (genders[flags.female ? 1 : 0].his)
/* pronoun_gender() flag masks */
#define PRONOUN_NORMAL 0 /* none of the below */
#define PRONOUN_NO_IT 1
#define PRONOUN_HALLU 2
/* corresponding pronouns for monsters; yields "it" when mtmp can't be seen */
#define mhe(mtmp) (genders[pronoun_gender(mtmp, PRONOUN_HALLU)].he)
#define mhim(mtmp) (genders[pronoun_gender(mtmp, PRONOUN_HALLU)].him)
#define mhis(mtmp) (genders[pronoun_gender(mtmp, PRONOUN_HALLU)].his)
/* override "it" if reason is lack of visibility rather than neuter species */
#define noit_mhe(mtmp) \
(genders[pronoun_gender(mtmp, (PRONOUN_NO_IT | PRONOUN_HALLU))].he)
#define noit_mhim(mtmp) \
(genders[pronoun_gender(mtmp, (PRONOUN_NO_IT | PRONOUN_HALLU))].him)
#define noit_mhis(mtmp) \
(genders[pronoun_gender(mtmp, (PRONOUN_NO_IT | PRONOUN_HALLU))].his)
/*** Unified structure specifying alignment information ***/
struct Align {
const char *noun; /* law/balance/chaos */
const char *adj; /* lawful/neutral/chaotic */
const char *filecode; /* file code */
short allow; /* equivalent ROLE_ mask */
aligntyp value; /* equivalent A_ value */
};
#define ROLE_ALIGNS 3 /* number of permitted player alignments */
extern const struct Align aligns[]; /* table of available alignments */
enum utraptypes {
TT_NONE = 0,
TT_BEARTRAP = 1,
TT_PIT = 2,
TT_WEB = 3,
TT_LAVA = 4,
TT_INFLOOR = 5,
TT_BURIEDBALL = 6
};
enum utotypes {
UTOTYPE_NONE = 0x00,
UTOTYPE_ATSTAIRS = 0x01,
UTOTYPE_FALLING = 0x02,
UTOTYPE_PORTAL = 0x04,
UTOTYPE_RMPORTAL = 0x10, /* remove portal */
UTOTYPE_DEFERRED = 0x20 /* deferred_goto */
};
/*** Information about the player ***/
struct you {
coordxy ux, uy; /* current map coordinates */
int dx, dy, dz; /* x,y,z deltas; direction of move (or zap or ... )
* usually +1 or 0 or -1 */
coordxy tx, ty; /* destination of travel */
coordxy ux0, uy0; /* previous ux,uy */
d_level uz, uz0; /* your level on this and the previous turn */
d_level utolev; /* level monster teleported you to, or uz */
uchar utotype; /* bitmask of goto_level() flags for utolev */
d_level ucamefrom; /* level where you came from; used for tutorial */
boolean umoved; /* changed map location (post-move) */
int last_str_turn; /* 0: none, 1: half turn, 2: full turn
* +: turn right, -: turn left */
int ulevel; /* 1 to MAXULEV (30) */
int ulevelmax; /* highest level, but might go down (to throttle
* lost level recovery via blessed full healing) */
int ulevelpeak; /* really highest level reached; never does down */
unsigned utrap; /* trap timeout */
unsigned utraptype; /* defined if utrap nonzero. one of utraptypes */
char urooms[5]; /* rooms (roomno + 3) occupied now */
char urooms0[5]; /* ditto, for previous position */
char uentered[5]; /* rooms (roomno + 3) entered this turn */
char ushops[5]; /* shop rooms (roomno + 3) occupied now */
char ushops0[5]; /* ditto, for previous position */
char ushops_entered[5]; /* ditto, shops entered this turn */
char ushops_left[5]; /* ditto, shops exited this turn */
int uhunger; /* refd only in eat.c and shk.c (also insight.c) */
unsigned uhs; /* hunger state - see eat.c */
struct prop uprops[LAST_PROP + 1];
unsigned umconf;
Bitfield(usick_type, 2);
#define SICK_VOMITABLE 0x01
#define SICK_NONVOMITABLE 0x02
#define SICK_ALL 0x03
/* These ranges can never be more than MAX_RANGE (vision.h). */
int nv_range; /* current night vision range */
int xray_range; /* current xray vision range */
int unblind_telepat_range;
/*
* These variables are valid globally only when punished and blind.
*/
#define BC_BALL 0x01 /* bit mask for ball in 'bc_felt' below */
#define BC_CHAIN 0x02 /* bit mask for chain in 'bc_felt' below */
int bglyph; /* glyph under the ball */
int cglyph; /* glyph under the chain */
int bc_order; /* ball & chain order [see bc_order() in ball.c] */
int bc_felt; /* mask for ball/chain being felt */
int umonster; /* hero's "real" monster num */
int umonnum; /* current monster number */
int mh, mhmax, /* current and max hit points when polyd */
mtimedone; /* no. of turns until polymorph times out */
struct attribs macurr, /* for monster attribs */
mamax; /* for monster attribs */
int ulycn; /* lycanthrope type */
unsigned ucreamed;
unsigned uswldtim; /* time you have been swallowed */
Bitfield(uswallow, 1); /* true if swallowed */
Bitfield(uinwater, 1); /* if you're currently in water (only
underwater possible currently) */
Bitfield(uundetected, 1); /* if you're a hiding monster/piercer */
Bitfield(mfemale, 1); /* saved human value of flags.female */
Bitfield(uinvulnerable, 1); /* you're invulnerable (praying) */
Bitfield(uburied, 1); /* you're buried */
Bitfield(uedibility, 1); /* blessed food detect; sense unsafe food */
Bitfield(usaving_grace, 1); /* prevents death once */
Bitfield(uhandedness, 1); /* There is no advantage for either handedness.
The distinction is only for flavor variation
and for use in messages. */
#define RIGHT_HANDED 0x00
#define LEFT_HANDED 0x01
unsigned udg_cnt; /* how long you have been demigod */
struct u_event uevent; /* certain events have happened */
struct u_have uhave; /* you're carrying special objects */
struct u_conduct uconduct; /* KMH, conduct */
struct u_roleplay uroleplay;
struct attribs acurr, /* your current attributes (eg. str)*/
aexe, /* for gain/loss via "exercise" */
abon, /* your bonus attributes (eg. str) */
amax, /* your max attributes (eg. str) */
atemp, /* used for temporary loss/gain */
atime; /* used for loss/gain countdown */
align ualign; /* character alignment */
#define CONVERT 2
#define A_ORIGINAL 1
#define A_CURRENT 0
aligntyp ualignbase[CONVERT]; /* for ualign conversion record */
schar uluck, moreluck; /* luck and luck bonus */
/* default u.uluck is 0 except on special days (full moon: +1, Fri 13: -1,
both: 0); equilibrium for luck timeout is changed to those values,
but Luck max and min stay at 10+3 and -10-3 even on those days */
#define Luck (u.uluck + u.moreluck)
#define LUCKADD 3 /* value of u.moreluck when carrying luck stone;
* +3 when blessed or uncursed, -3 when cursed */
#define LUCKMAX 10 /* maximum value of u.uluck */
#define LUCKMIN (-10) /* minimum value of u.uluck */
schar uhitinc;
schar udaminc;
schar uac;
#define AC_MAX 99 /* abs(u.uac) <= 99; likewise for monster AC */
uchar uspellprot; /* protection by SPE_PROTECTION */
uchar usptime; /* #moves until uspellprot-- */
uchar uspmtime; /* #moves between uspellprot-- */
int uhp, uhpmax, /* hit points, aka health */
uhppeak; /* highest value of uhpmax so far */
int uen, uenmax, /* magical energy, aka spell power */
uenpeak; /* highest value of uenmax so far */
xint16 uhpinc[MAXULEV], /* increases to uhpmax for each level gain */
ueninc[MAXULEV]; /* increases to uenmax for each level gain */
int ugangr; /* if the gods are angry at you */
int ugifts; /* number of artifacts bestowed */
int ublessed, ublesscnt; /* blessing/duration from #pray */
long umoney0;
long uspare1;
long uexp, urexp; /* exper pts for gaining levels and for score */
long ucleansed; /* to record moves when player was cleansed */
long usleep; /* sleeping; monstermove you last started */
int uinvault;
struct monst *ustuck; /* engulfer or grabber, maybe grabbee if Upolyd */
struct monst *usteed; /* mount when riding */
unsigned ustuck_mid; /* u.ustuck->m_id, used during save/restore */
unsigned usteed_mid; /* u.usteed->m_id, used during save/restore */
long ugallop; /* turns steed will run after being kicked */
int urideturns; /* time spent riding, for skill advancement */
int umortality; /* how many times you died */
int ugrave_arise; /* you die and become something aside from a ghost */
int weapon_slots; /* unused skill slots */
int skills_advanced; /* # of advances made so far */
xint16 skill_record[P_SKILL_LIMIT]; /* skill advancements */
struct skills weapon_skills[P_NUM_SKILLS];
boolean twoweap; /* KMH -- Using two-weapon combat */
short mcham; /* vampire mndx if shapeshifted to bat/cloud */
short umovement; /* instead of youmonst.movement */
schar uachieved[N_ACH]; /* list of achievements in the order attained */
}; /* end of `struct you' */
/* _hitmon_data: Info for when hero hits a monster */
/* The basic reason we need all these booleans is that we don't want
* a "hit" message when a monster dies, so we have to know how much
* damage it did _before_ outputting a hit message, but any messages
* associated with the damage don't come out until _after_ outputting
* a hit message.
*
* More complications: first_weapon_hit() should be called before
* xkilled() in order to have the gamelog messages in the right order.
* So it can't be deferred until end of known_hitum() as was originally
* done.
*/
struct _hitmon_data {
int dmg; /* damage */
int thrown;
int twohits; /* 0: 1 of 1; 1: 1 of 2; 2: 2 of 2 */
int dieroll;
struct permonst *mdat;
boolean use_weapon_skill;
boolean train_weapon_skill;
int barehand_silver_rings;
boolean silvermsg;
boolean silverobj;
boolean lightobj;
int material;
int jousting;
boolean hittxt;
boolean get_dmg_bonus;
boolean unarmed;
boolean hand_to_hand;
boolean ispoisoned;
boolean unpoisonmsg;
boolean needpoismsg;
boolean poiskilled;
boolean already_killed;
boolean destroyed;
boolean dryit;
boolean doreturn;
boolean retval;
char saved_oname[BUFSZ];
};
#define Upolyd (u.umonnum != u.umonster)
#define Ugender ((Upolyd ? u.mfemale : flags.female) ? 1 : 0)
/* point px,py is adjacent to (or same location as) hero */
#define next2u(px,py) (distu((px),(py)) <= 2)
/* is monster on top of or next to hero? */
#define m_next2u(m) (distu((m)->mx,(m)->my) <= 2)
/* hero at (x,y)? */
#define u_at(x,y) ((x) == u.ux && (y) == u.uy)
#define URIGHTY (u.uhandedness == RIGHT_HANDED)
#define ULEFTY (u.uhandedness == LEFT_HANDED)
#define RING_ON_PRIMARY (ULEFTY ? uleft : uright)
#define RING_ON_SECONDARY (ULEFTY ? uright : uleft)
#endif /* YOU_H */