int eroded, eroded2, erodeproof, locked, unlocked, broken, real, fake;
int halfeaten, mntmp, contents;
int islit, unlabeled, ishistoric, isdiluted, trapped;
+ int doorless, open, closed, looted;
int tmp, tinv, tvariety, mgend;
int wetness, gsize;
int ftype;
static boolean wishymatch(const char *, const char *, boolean);
static short rnd_otyp_by_wpnskill(schar);
static short rnd_otyp_by_namedesc(const char *, char, int);
-static struct obj *wizterrainwish(char *, char *, int, int);
+static struct obj *wizterrainwish(struct _readobjnam_data *);
static void readobjnam_init(char *, struct _readobjnam_data *);
static int readobjnam_preparse(struct _readobjnam_data *);
static void readobjnam_parse_charges(struct _readobjnam_data *);
struct fruit *
fruit_from_name(
const char *fname,
- boolean exact, /* False => prefix or exact match, True = exact match only */
+ boolean exact, /* False: prefix or exact match, True: exact match only */
int *highest_fid) /* optional output; only valid if 'fname' isn't found */
{
struct fruit *f, *tentativef;
break;
}
if (obj->otyp == CANDELABRUM_OF_INVOCATION) {
- Sprintf(eos(bp), " (%d of 7 candle%s%s)", obj->spe, plur(obj->spe),
+ Sprintf(eos(bp), " (%d of 7 candle%s%s)",
+ obj->spe, plur(obj->spe),
!obj->lamplit ? " attached" : ", lit");
break;
} else if (obj->otyp == OIL_LAMP || obj->otyp == MAGIC_LAMP
static boolean
badman(
const char *basestr,
- boolean to_plural) /* true => makeplural, false => makesingular */
+ boolean to_plural) /* True: makeplural, False: makesingular */
{
/* these are all the prefixes for *man that don't have a *men plural */
static const char *no_men[] = {
rnd_otyp_by_namedesc(
const char *name,
char oclass,
- int xtra_prob) /* to force 0% random generation items to also be considered */
+ int xtra_prob) /* add to item's chance of being chosen; non-zero causes
+ * 0% random generation items to also be considered */
{
int i, n = 0;
short validobjs[NUM_OBJECTS];
/* in wizard mode, readobjnam() can accept wishes for traps and terrain */
static struct obj *
-wizterrainwish(char* bp, char* p, int locked, int trapped)
+wizterrainwish(struct _readobjnam_data *d)
{
struct rm *lev;
boolean madeterrain = FALSE, badterrain = FALSE, didblock;
int trap, oldtyp, x = u.ux, y = u.uy;
+ char *bp = d->bp, *p = d->p;
for (trap = NO_TRAP + 1; trap < TRAPNUM; trap++) {
struct trap *t;
if (!BSTRCMPI(bp, p - 8, "fountain")) {
lev->typ = FOUNTAIN;
g.level.flags.nfountains++;
- lev->looted = 0; /* overlays 'flags' */
+ lev->looted = d->looted ? F_LOOTED : 0; /* overlays 'flags' */
lev->blessedftn = !strncmpi(bp, "magic ", 6);
pline("A %sfountain.", lev->blessedftn ? "magic " : "");
madeterrain = TRUE;
} else if (!BSTRCMPI(bp, p - 6, "throne")) {
lev->typ = THRONE;
- lev->looted = 0; /* overlays 'flags' */
+ lev->looted = d->looted ? T_LOOTED : 0; /* overlays 'flags' */
pline("A throne.");
madeterrain = TRUE;
} else if (!BSTRCMPI(bp, p - 4, "sink")) {
lev->typ = SINK;
g.level.flags.nsinks++;
- lev->looted = 0; /* overlays 'flags' */
+ lev->looted = d->looted ? (S_LPUDDING | S_LDWASHER | S_LRING) : 0;
pline("A sink.");
madeterrain = TRUE;
make_grave(x, y, (char *) 0);
if (IS_GRAVE(lev->typ)) {
lev->looted = 0; /* overlays 'flags' */
- lev->disturbed = !strncmpi(bp, "disturbed ", 10);
+ lev->disturbed = d->looted ? 1 : 0;
pline("A %sgrave.", lev->disturbed ? "disturbed " : "");
madeterrain = TRUE;
} else {
- pline("Can't place a grave here");
+ pline("Can't place a grave here.");
badterrain = TRUE;
}
} else if (!BSTRCMPI(bp, p - 4, "tree")) {
lev->typ = TREE;
- lev->looted = 0; /* overlays 'flags' */
+ lev->looted = d->looted ? (TREE_LOOTED | TREE_SWARM) : 0;
pline("A tree.");
madeterrain = TRUE;
} else if (!BSTRCMPI(bp, p - 4, "bars")) {
lev->flags = 0;
pline("A cloud.");
madeterrain = TRUE;
- } else if (!BSTRCMPI(bp, p - 11, "secret door")) {
+ } else if (!BSTRCMPI(bp, p - 4, "door")
+ || (d->doorless && !BSTRCMPI(bp, p - 7, "doorway"))) {
+ char dbuf[40];
+ unsigned old_wall_info;
+ boolean secret = !BSTRCMPI(bp, p - 11, "secret door");
+
/* require door or wall so that the 'horizontal' flag will
- already have the correct value (it will matter once the
- secret door is discovered and becomes a regular door);
- player might choose to put SDOOR on top of existing SDOOR
- to control its trapped state; iron bars are surrogate walls */
+ already have the correct value; player might choose to put
+ DOOR on top of existing DOOR or SDOOR on top of existing SDOOR
+ to control its trapped state; iron bars are surrogate walls;
+ a previously dug wall looks like corridor but is actually a
+ doorless doorway so will be acceptable here */
if (lev->typ == DOOR || lev->typ == SDOOR
|| (IS_WALL(lev->typ) && lev->typ != DBWALL)
|| lev->typ == IRONBARS) {
- lev->typ = SDOOR;
+ /* remember previous wall info [is this right for iron bars?] */
+ old_wall_info = (lev->typ != DOOR) ? lev->wall_info : 0;
+ /* set the new terrain type */
+ lev->typ = secret ? SDOOR : DOOR;
lev->wall_info = 0; /* overlays 'flags' */
/* lev->horizontal stays as-is */
- /* no special handling for rogue level is necessary;
- exposing a secret door there yields a doorless doorway */
-#if 0 /*
- * Can't do this; secret doors want both doormask and
- * wall_info but those both overload rm.flags which makes
- * D_CLOSED conflict with WM_MASK. However, converting
- * secret door to regular door sets D_CLOSED iff D_LOCKED
- * isn't specified so the alternate code suffices.
- */
- lev->doormask = locked ? D_LOCKED : D_CLOSED;
-#else
- /* cvt_sdoor_to_door() will change D_NODOOR to D_CLOSED */
- lev->doormask = locked ? D_LOCKED : D_NODOOR;
-#endif
- if (trapped)
+ if (Is_rogue_level(&u.uz)) {
+ /* all doors on the rogue level are doorless; locking magic
+ there converts them into walls rather than closed doors */
+ d->doorless = 1;
+ d->locked = d->closed = d->open = d->broken = 0;
+ }
+ /* if not locked, secret doors are implicitly closed but
+ mustn't be set that way explicitly because they use both
+ doormask and wall_info which both overload rm[x][y].flags
+ (CLOSED overlaps wall_info bits, LOCKED and TRAPPED don't);
+ conversion from SDOOR to DOOR changes NODOOR to CLOSED */
+ lev->doormask = d->locked ? D_LOCKED
+ : (d->doorless || secret) ? D_NODOOR
+ : d->open ? D_ISOPEN
+ : d->broken ? D_BROKEN
+ : D_CLOSED;
+ /* SDOOR uses wall_info, restore relevant bits.
+ * FIXME? if we're changing a regular door into a secret door,
+ * old_wall_info bits will be 0 instead of being set properly.
+ * Probably only matters if player uses Passes_walls and a wish
+ * to turn a T- or cross-wall into a door, losing wall info,
+ * and then another wish to turn that door into a secret door. */
+ if (secret)
+ lev->wall_info |= (old_wall_info & WM_MASK);
+ /* set up trapped flag; open door states aren't eligible */
+ if (d->trapped == 2 /* 2: wish includes explicit "untrapped" */
+ || (!secret && ((lev->doormask & (D_LOCKED | D_CLOSED)) == 0)))
+ d->trapped = 0;
+ if (d->trapped)
lev->doormask |= D_TRAPPED;
- pline("Secret door.");
+ /* feedback */
+ dbuf[0] = '\0';
+ /* locked state and trapped flag can augment secret doors; other
+ states apply to normal doors only (see above about 'closed') */
+ if (lev->doormask & D_TRAPPED)
+ Strcat(dbuf, "trapped ");
+ if (lev->doormask & D_LOCKED)
+ Strcat(dbuf, "locked ");
+ if (lev->typ == SDOOR) {
+ Strcat(dbuf, "secret door");
+ } else {
+ /* these should be mutually exclusive but we describe them
+ as if they're independent to maybe catch future bugs... */
+ if (lev->doormask & D_CLOSED)
+ Strcat(dbuf, "closed ");
+ if (lev->doormask & D_ISOPEN)
+ Strcat(dbuf, "open ");
+ if (lev->doormask & D_BROKEN)
+ Strcat(dbuf, "broken ");
+ if ((lev->doormask & ~D_TRAPPED) == D_NODOOR)
+ Strcat(dbuf, "doorless doorway");
+ else
+ Strcat(dbuf, "door");
+ }
+ pline("%s.", upstart(an(dbuf)));
madeterrain = TRUE;
} else {
- pline("Secret door requires door or wall location.");
+ Strcpy(dbuf, secret ? "secret door" : "door");
+ pline("%s requires door or wall location.", upstart(dbuf));
badterrain = TRUE;
}
+ } else if (!BSTRCMPI(bp, p - 4, "wall")
+ && (bp == p - 4 || p[-4] == ' ')) {
+ pline("Wishing for walls is not implemented.");
+ badterrain = TRUE;
} else if (!BSTRCMPI(bp, p - 15, "secret corridor")) {
if (lev->typ == CORR) {
lev->typ = SCORR;
d->very = d->rechrg = d->blessed = d->uncursed = d->iscursed
= d->ispoisoned = d->isgreased = d->eroded = d->eroded2
= d->erodeproof = d->halfeaten = d->islit = d->unlabeled
- = d->ishistoric = d->isdiluted = d->trapped = d->locked
- = d->unlocked = d->broken = d->real = d->fake = 0;
+ = d->ishistoric = d->isdiluted /* statues, potions */
+ /* box/chest and wizard mode door */
+ = d->trapped = d->locked = d->unlocked = d->broken
+ = d->open = d->closed = d->doorless /* wizard mode door */
+ = d->looted /* wizard mode fountain/sink/throne/tree and grave */
+ = d->real = d->fake = 0; /* Amulet */
d->tvariety = RANDOM_TIN;
d->mgend = MALE;
d->mntmp = NON_PM;
d->trapped = 1;
} else if (!strncmpi(d->bp, "untrapped ", l = 10)) {
d->trapped = 2; /* not trapped */
- /* locked, unlocked, broken: box/chest lock states */
+ /* locked, unlocked, broken: box/chest lock states, also door states;
+ open, closed, doorless: additional door states */
} else if (!strncmpi(d->bp, "locked ", l = 7)) {
- d->locked = 1, d->unlocked = d->broken = 0;
+ d->locked = d->closed = 1,
+ d->unlocked = d->broken = d->open = d->doorless = 0;
} else if (!strncmpi(d->bp, "unlocked ", l = 9)) {
- d->unlocked = 1, d->locked = d->broken = 0;
+ d->unlocked = d->closed = 1,
+ d->locked = d->broken = d->open = d->doorless = 0;
} else if (!strncmpi(d->bp, "broken ", l = 7)) {
- d->broken = 1, d->locked = d->unlocked = 0;
+ d->broken = 1,
+ d->locked = d->unlocked = d->open = d->closed
+ = d->doorless = 0;
+ } else if (!strncmpi(d->bp, "open ", l = 5)) {
+ d->open = 1,
+ d->closed = d->locked = d->broken = d->doorless = 0;
+ } else if (!strncmpi(d->bp, "closed ", l = 7)) {
+ d->closed = 1,
+ d->open = d->locked = d->broken = d->doorless = 0;
+ } else if (!strncmpi(d->bp, "doorless ", l = 9)) {
+ d->doorless = 1,
+ d->open = d->closed = d->locked = d->unlocked = d->broken = 0;
+ /* looted: fountain/sink/throne/tree; disturbed: grave */
+ } else if (!strncmpi(d->bp, "looted ", l = 7)
+ /* overload disturbed grave with looted fountain here
+ even though they're separate in struct rm */
+ || !strncmpi(d->bp, "disturbed ", l = 10)) {
+ d->looted = 1;
} else if (!strncmpi(d->bp, "greased ", l = 8)) {
d->isgreased = 1;
} else if (!strncmpi(d->bp, "very ", l = 5)) {
d->p = (char *) 0;
/* check for "glob", "<foo> glob", and "glob of <foo>" */
if (!strcmpi(d->bp, "glob") || !BSTRCMPI(d->bp, d->bp + i - 5, " glob")
- || !strcmpi(d->bp, "globs") || !BSTRCMPI(d->bp, d->bp + i - 6, " globs")
+ || !strcmpi(d->bp, "globs")
+ || !BSTRCMPI(d->bp, d->bp + i - 6, " globs")
|| (d->p = strstri(d->bp, "glob of ")) != 0
|| (d->p = strstri(d->bp, "globs of ")) != 0) {
d->mntmp = name_to_mon(!d->p ? d->bp
if (*d->bp == ' ') {
d->bp++;
} else if (!strncmpi(d->bp, "s ", 2)
- || (d->bp > d->origbp && !strncmpi(d->bp - 1, "s' ", 3))) {
+ || (d->bp > d->origbp
+ && !strncmpi(d->bp - 1, "s' ", 3))) {
d->bp += 2;
} else if (!strncmpi(d->bp, "es ", 3)
|| !strncmpi(d->bp, "'s ", 3)) {
d->bp += 3;
- } else if (!*d->bp && !d->actualn && !d->dn && !d->un && !d->oclass) {
+ } else if (!*d->bp && !d->actualn && !d->dn && !d->un
+ && !d->oclass) {
/* no referent; they don't really mean a monster type */
d->bp = obp;
d->mntmp = NON_PM;
* " object", but " trap" is suggested--to either the trap
* name or the object name.
*/
- if (wizard && (!strncmpi(d->bp, "bear", 4) || !strncmpi(d->bp, "land", 4))) {
+ if (wizard && (!strncmpi(d->bp, "bear", 4)
+ || !strncmpi(d->bp, "land", 4))) {
boolean beartrap = (lowc(*d->bp) == 'b');
char *zp = d->bp + 4; /* skip "bear"/"land" */
return 2; /*goto typfnd;*/
}
- if (!BSTRCMPI(d->bp, d->p - 6, " stone") || !BSTRCMPI(d->bp, d->p - 4, " gem")) {
+ if (!BSTRCMPI(d->bp, d->p - 6, " stone")
+ || !BSTRCMPI(d->bp, d->p - 4, " gem")) {
d->p[!strcmpi(d->p - 4, " gem") ? -4 : -6] = '\0';
d->oclass = GEM_CLASS;
d->dn = d->actualn = d->bp;
return 1; /*goto srch;*/
} else if (!strcmpi(d->bp, "looking glass")) {
; /* avoid false hit on "* glass" */
- } else if (!BSTRCMPI(d->bp, d->p - 6, " glass") || !strcmpi(d->bp, "glass")) {
+ } else if (!BSTRCMPI(d->bp, d->p - 6, " glass")
+ || !strcmpi(d->bp, "glass")) {
register char *s = d->bp;
/* treat "broken glass" as a non-existent item; since "broken" is
}
}
- if (((d->typ = rnd_otyp_by_namedesc(d->actualn, d->oclass, 1)) != STRANGE_OBJECT)
+ if (((d->typ = rnd_otyp_by_namedesc(d->actualn, d->oclass, 1))
+ != STRANGE_OBJECT)
|| (d->dn != d->actualn
- && (d->typ = rnd_otyp_by_namedesc(d->dn, d->oclass, 1)) != STRANGE_OBJECT)
- || ((d->typ = rnd_otyp_by_namedesc(d->un, d->oclass, 1)) != STRANGE_OBJECT)
+ && ((d->typ = rnd_otyp_by_namedesc(d->dn, d->oclass, 1))
+ != STRANGE_OBJECT))
+ || ((d->typ = rnd_otyp_by_namedesc(d->un, d->oclass, 1))
+ != STRANGE_OBJECT)
|| (d->origbp != d->actualn
&& ((d->typ = rnd_otyp_by_namedesc(d->origbp, d->oclass, 1))
!= STRANGE_OBJECT)))
wiztrap:
if (wizard && !g.program_state.wizkit_wishing) {
/* [inline code moved to separate routine to unclutter readobjnam] */
- if ((d.otmp = wizterrainwish(d.bp, d.p, d.locked, d.trapped)) != 0)
+ if ((d.otmp = wizterrainwish(&d)) != 0)
return d.otmp;
}