change attendant (healer quest) monster from lawful to neutral
quit is not longer bound to M-q
change default value of autopickup to off and color to on
+resurrected corpse of mon could end up with different gender from original mon
Fixes to 3.7.0-x Problems that Were Exposed Via git Repository
causing hero to hit head on ceiling
enlightenment/disclosure when wielding two weapons with two-weap skill higher
than secondary weapon's skill had "with" duplicated in the feedback
+corpse of monster with gender specific names (king vs queen and so forth)
+ was always described by the neutral name (ruler and such)
curses: 'msg_window' option wasn't functional for curses unless the binary
also included tty support
* to make an extra call to goodpos()] */
#define GP_ALLOW_U 0x080000L /* don't reject hero's location */
-/* flags for make_corpse() and mkcorpstat() */
-#define CORPSTAT_NONE 0x00
-#define CORPSTAT_INIT 0x01 /* pass init flag to mkcorpstat */
-#define CORPSTAT_BURIED 0x02 /* bury the corpse or statue */
+/* 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
/* flags for decide_to_shift() */
#define SHIFT_SEENMSG 0x01 /* put out a message if in sight */
* candy bar wrapper index;
* scroll of mail (normal==0, bones or wishing==1, written==2);
* splash of venom (normal==0, wishing==1);
- * historic flag and gender for statues */
-#define STATUE_HISTORIC 0x01
-#define STATUE_MALE 0x02
-#define STATUE_FEMALE 0x04
+ * gender for corpses and statues (0..3, CORPSTAT_GENDER),
+ * historic flag (4, CORPSTAT_HISTORIC) for statues */
char oclass; /* object class */
char invlet; /* designation in inventory */
char oartifact; /* artifact array index */
special |= MG_STATUE;
if (is_objpile(x,y))
special |= MG_OBJPILE;
- if ((obj = sobj_at(STATUE, x, y)) && (obj->spe & STATUE_FEMALE))
+ if ((obj = sobj_at(STATUE, x, y)) != 0
+ && (obj->spe & CORPSTAT_GENDER) == CORPSTAT_FEMALE)
special |= MG_FEMALE;
} else if ((offset = (glyph - GLYPH_WARNING_OFF)) >= 0) { /* warn flash */
idx = offset + SYM_OFF_W;
} else {
otmp = mksobj_at(objtype, x, y, init, FALSE);
}
- otmp->norevive = g.mkcorpstat_norevive;
+ /* record gender and 'historic statue' in overloaded enchantment field */
+ otmp->spe = (corpstatflags & CORPSTAT_SPE_VAL);
+ otmp->norevive = g.mkcorpstat_norevive; /* via envrmt rather than flags */
/* when 'mtmp' is non-null save the monster's details with the
corpse or statue; it will also force the 'ptr' override below */
never returns Null */
struct obj *
mk_named_object(
-int objtype, /* CORPSE or STATUE */
-struct permonst *ptr,
-int x, int y,
-const char *nm)
+ int objtype, /* CORPSE or STATUE */
+ struct permonst *ptr,
+ int x, int y,
+ const char *nm)
{
struct obj *otmp;
unsigned corpstatflags = (objtype != STATUE) ? CORPSTAT_INIT
* etc....
*/
static struct obj *
-make_corpse(register struct monst* mtmp, unsigned int corpseflags)
+make_corpse(struct monst *mtmp, unsigned int corpseflags)
{
register struct permonst *mdat = mtmp->data;
int num;
unsigned corpstatflags = corpseflags;
boolean burythem = ((corpstatflags & CORPSTAT_BURIED) != 0);
+ if (mtmp->female)
+ corpstatflags |= CORPSTAT_FEMALE;
+ else if (!is_neuter(mtmp->data))
+ corpstatflags |= CORPSTAT_MALE;
+
switch (mndx) {
case PM_GRAY_DRAGON:
case PM_SILVER_DRAGON:
break;
case PM_STONE_GOLEM:
corpstatflags &= ~CORPSTAT_INIT;
- obj =
- mkcorpstat(STATUE, (struct monst *) 0, mdat, x, y, corpstatflags);
+ obj = mkcorpstat(STATUE, (struct monst *) 0, mdat, x, y,
+ corpstatflags);
break;
case PM_WOOD_GOLEM:
num = d(2, 4);
/* figure out what type of monster a user-supplied string is specifying;
ingore anything past the monster name */
int
-name_to_mon(const char *in_str, int * gender_name_var)
+name_to_mon(const char *in_str, int *gender_name_var)
{
return name_to_monplus(in_str, (const char **) 0, gender_name_var);
}
if (remainder_p)
*remainder_p = (const char *) 0;
+ if (gender_name_var)
+ *gender_name_var = 0;
str = strcpy(buf, in_str);
{ "master of assassin", PM_MASTER_ASSASSIN, NEUTRAL },
/* Outdated names */
{ "invisible stalker", PM_STALKER, NEUTRAL },
- { "high-elf", PM_ELVEN_MONARCH, NEUTRAL }, /* PM_HIGH_ELF is obsolete */
+ { "high-elf", PM_ELVEN_MONARCH, NEUTRAL }, /* PM_HIGH_ELF is
+ * obsolete */
/* other misspellings or incorrect words */
{ "wood-elf", PM_WOODLAND_ELF, NEUTRAL },
{ "wood elf", PM_WOODLAND_ELF, NEUTRAL },
{ "woodland nymph", PM_WOOD_NYMPH, NEUTRAL },
- { "halfling", PM_HOBBIT, NEUTRAL }, /* potential guess for polyself */
- { "genie", PM_DJINNI, NEUTRAL }, /* potential guess for ^G/#wizgenesis */
+ { "halfling", PM_HOBBIT, NEUTRAL }, /* potential guess for
+ * polyself */
+ { "genie", PM_DJINNI, NEUTRAL }, /* potential guess for
+ * ^G/#wizgenesis */
/* prefix used to workaround duplicate monster names for
monsters with alternate forms */
{ "human wererat", PM_HUMAN_WERERAT, NEUTRAL },
nhl_add_table_entry_int(L, "quan", obj->quan);
nhl_add_table_entry_int(L, "spe", obj->spe);
- if (obj->otyp == STATUE) {
- nhl_add_table_entry_int(L, "historic", (obj->spe & STATUE_HISTORIC));
- nhl_add_table_entry_int(L, "statue_male", (obj->spe & STATUE_MALE));
- nhl_add_table_entry_int(L, "statue_female", (obj->spe & STATUE_FEMALE));
+ if (obj->otyp == STATUE)
+ nhl_add_table_entry_int(L, "historic",
+ (obj->spe & CORPSTAT_HISTORIC) != 0);
+ if (obj->otyp == CORPSE || obj->otyp == STATUE) {
+ nhl_add_table_entry_int(L, "male",
+ (obj->spe & CORPSTAT_MALE) != 0);
+ nhl_add_table_entry_int(L, "female",
+ (obj->spe & CORPSTAT_FEMALE) != 0);
}
nhl_add_table_entry_char(L, "oclass",
case ROCK_CLASS:
if (typ == STATUE && omndx != NON_PM) {
char anbuf[10];
- int mgend = (obj->spe & STATUE_FEMALE) ? FEMALE : MALE;
+ int mgend = (((obj->spe & CORPSTAT_GENDER) == CORPSTAT_FEMALE)
+ ? FEMALE : MALE);
Sprintf(buf, "%s%s of %s%s",
- (Role_if(PM_ARCHEOLOGIST) && (obj->spe & STATUE_HISTORIC))
- ? "historic "
- : "",
+ (Role_if(PM_ARCHEOLOGIST)
+ && (obj->spe & CORPSTAT_HISTORIC)) ? "historic " : "",
actualn,
- type_is_pname(&mons[omndx])
- ? ""
- : the_unique_pm(&mons[omndx])
- ? "the "
- : just_an(anbuf, pmname(&mons[omndx], mgend)),
+ type_is_pname(&mons[omndx]) ? ""
+ : the_unique_pm(&mons[omndx]) ? "the "
+ : just_an(anbuf, pmname(&mons[omndx], mgend)),
pmname(&mons[omndx], mgend));
} else
Strcpy(buf, actualn);
/* avoid "aligned priest"; it just exposes internal details */
mnam = "priest";
} else {
- mnam = mons[omndx].pmnames[NEUTRAL];
+ int cspe = (otmp->spe & CORPSTAT_GENDER),
+ mgend = (cspe == CORPSTAT_FEMALE) ? FEMALE
+ : (cspe == CORPSTAT_MALE) ? MALE
+ : NEUTRAL;
+
+ mnam = pmname(&mons[omndx], mgend);
if (the_unique_pm(&mons[omndx]) || type_is_pname(&mons[omndx])) {
mnam = s_suffix(mnam);
possessive = TRUE;
= d->looted /* wizard mode fountain/sink/throne/tree and grave */
= d->real = d->fake = 0; /* Amulet */
d->tvariety = RANDOM_TIN;
- d->mgend = MALE;
+ d->mgend = NEUTRAL;
d->mntmp = NON_PM;
d->contents = UNDEFINED;
d->oclass = 0;
d->typ = TIN;
return 2; /*goto typfnd;*/
} else if ((d->p = strstri(d->bp, " of ")) != 0
- && (d->mntmp = name_to_mon(d->p + 4,
- &d->mgend)) >= LOW_PM)
+ && ((d->mntmp = name_to_mon(d->p + 4, &d->mgend))
+ >= LOW_PM))
*d->p = 0;
}
}
const char *rest = 0;
if (d->mntmp < LOW_PM && strlen(d->bp) > 2
- && (d->mntmp = name_to_monplus(d->bp, &rest,
- &d->mgend)) >= LOW_PM) {
+ && ((d->mntmp = name_to_monplus(d->bp, &rest, &d->mgend))
+ >= LOW_PM)) {
char *obp = d->bp;
/* 'rest' is a pointer past the matching portion; if that was
case HEAVY_IRON_BALL:
case IRON_CHAIN:
break;
- case STATUE:
- /* otmp->cobj already done in mksobj() */
- if (d.mgend)
- d.otmp->spe |= STATUE_FEMALE;
+ case STATUE: /* otmp->cobj already done in mksobj() */
+ case CORPSE: {
+ struct permonst *P = (d.mntmp >= LOW_PM) ? &mons[d.mntmp] : 0;
+
+ d.otmp->spe = !P ? CORPSTAT_RANDOM
+ /* if neuter, force neuter regardless of wish request */
+ : is_neuter(P) ? CORPSTAT_NEUTER
+ /* not neuter, honor wish unless it conflicts */
+ : (d.mgend == FEMALE && !is_male(P)) ? CORPSTAT_FEMALE
+ : (d.mgend == MALE && !is_female(P)) ? CORPSTAT_MALE
+ /* unspecified or wish conflicts */
+ : CORPSTAT_RANDOM;
break;
+ };
#ifdef MAIL_STRUCTURES
/* scroll of mail: 0: delivered in-game via external event (or randomly
for fake mail); 1: from bones or wishing; 2: written with marker */
d.otmp->corpsenm = d.mntmp;
if (Has_contents(d.otmp) && verysmall(&mons[d.mntmp]))
delete_contents(d.otmp); /* no spellbook */
- d.otmp->spe |= d.ishistoric ? STATUE_HISTORIC : 0;
+ d.otmp->spe |= d.ishistoric ? CORPSTAT_HISTORIC : 0;
break;
case SCALE_MAIL:
/* Dragon mail - depends on the order of objects & dragons. */
block_point(x, y);
}
+ mtmp->female = m->female;
if (m->peaceful >= 0) {
mtmp->mpeaceful = m->peaceful;
/* changed mpeaceful again; have to reset malign */
}
if (m->seentraps)
mtmp->mtrapseen = m->seentraps;
- if (m->female)
- mtmp->female = 1;
if (m->cancelled)
mtmp->mcan = 1;
if (m->revived)
|| tmpobj.id == CORPSE || tmpobj.id == TIN
|| tmpobj.id == FIGURINE) {
struct permonst *pm = NULL;
- int i, lflags = 0;
+ int i;
char *montype = get_table_str_opt(L, "montype", NULL);
if (montype) {
if (strlen(montype) == 1
&& def_char_to_monclass(*montype) != MAXMCLASSES) {
- pm = mkclass(def_char_to_monclass(*montype), G_NOGEN|G_IGNORE);
+ pm = mkclass(def_char_to_monclass(*montype),
+ G_NOGEN | G_IGNORE);
} else {
for (i = LOW_PM; i < NUMMONS; i++)
if (!strcmpi(mons[i].pmnames[NEUTRAL], montype)
|| (mons[i].pmnames[MALE] != 0
- && !strcmpi(mons[i].pmnames[MALE], montype))
+ && !strcmpi(mons[i].pmnames[MALE], montype))
|| (mons[i].pmnames[FEMALE] != 0
- && !strcmpi(mons[i].pmnames[FEMALE], montype))) {
+ && !strcmpi(mons[i].pmnames[FEMALE], montype))) {
pm = &mons[i];
break;
}
else
nhl_error(L, "Unknown montype");
}
- if (tmpobj.id == STATUE) {
+ if (tmpobj.id == STATUE || tmpobj.id == CORPSE) {
+ int lflags = 0;
+
if (get_table_boolean_opt(L, "historic", 0))
- lflags |= STATUE_HISTORIC;
+ lflags |= CORPSTAT_HISTORIC;
if (get_table_boolean_opt(L, "male", 0))
- lflags |= STATUE_MALE;
+ lflags |= CORPSTAT_MALE;
if (get_table_boolean_opt(L, "female", 0))
- lflags |= STATUE_FEMALE;
+ lflags |= CORPSTAT_FEMALE;
tmpobj.spe = lflags;
} else if (tmpobj.id == EGG) {
tmpobj.spe = get_table_boolean_opt(L, "laid_by_you", 0) ? 1 : 0;
+ } else {
+ tmpobj.spe = 0;
}
}
tmproom.chance = get_table_int_opt(L, "chance", 100);
tmproom.rlit = get_table_int_opt(L, "lit", -1);
/* theme rooms default to unfilled */
- tmproom.needfill = get_table_int_opt(L, "filled", g.in_mk_themerooms ? 0 : 1);
+ tmproom.needfill = get_table_int_opt(L, "filled",
+ g.in_mk_themerooms ? 0 : 1);
tmproom.joined = get_table_boolean_opt(L, "joined", TRUE);
if (!g.coder->failed_room[g.coder->n_subroom - 1]) {
get_table_xy_or_coord(L, &x, &y);
tmptrap.type = get_table_traptype_opt(L, "type", -1);
- tmptrap.spider_on_web
- = get_table_boolean_opt(L, "spider_on_web", 1);
+ tmptrap.spider_on_web = get_table_boolean_opt(L, "spider_on_web", 1);
}
if (tmptrap.type == NO_TRAP)
struct obj *item;
coord cc;
boolean historic = (Role_if(PM_ARCHEOLOGIST)
- && (statue->spe & STATUE_HISTORIC) != 0),
+ && (statue->spe & CORPSTAT_HISTORIC) != 0),
golem_xform = FALSE, use_saved_traits;
const char *comes_to_life;
char statuename[BUFSZ], tmpbuf[BUFSZ];
be NON_PM; otherwise, set form to match the statue */
if (mon && mon->cham >= LOW_PM)
(void) newcham(mon, mptr, FALSE, FALSE);
- } else
+ } else {
mon = makemon(mptr, x, y, (cause == ANIMATE_SPELL)
? (NO_MINVENT | MM_ADJACENTOK)
: NO_MINVENT);
+ }
+ /* a non-montraits() statue might specify gender */
+ if ((statue->spe & CORPSTAT_MALE) != 0)
+ mon->female = 0;
+ else if ((statue->spe & CORPSTAT_FEMALE) != 0)
+ mon->female = 1;
}
if (!mon) {
return (struct monst *) 0;
}
- /* a non-montraits() statue might specify gender */
- if (statue->spe & STATUE_MALE)
- mon->female = FALSE;
- else if (statue->spe & STATUE_FEMALE)
- mon->female = TRUE;
/* if statue has been named, give same name to the monster */
if (has_oname(statue) && !unique_corpstat(mon->data))
mon = christen_monst(mon, ONAME(statue));
if (!mtmp)
return (struct monst *) 0;
+ /* if we didn't use montraits, corpse might specify mon's gender */
+ if (!has_omonst(corpse)) {
+ int cspe = (corpse->spe & CORPSTAT_GENDER);
+
+ if (cspe == CORPSTAT_MALE)
+ mtmp->female = 0;
+ else if (cspe == CORPSTAT_FEMALE)
+ mtmp->female = 1;
+ }
+
/* hiders shouldn't already be re-hidden when they revive */
if (mtmp->mundetected) {
mtmp->mundetected = 0;
obj_extract_self(item);
place_object(item, obj->ox, obj->oy);
}
- if (by_you && Role_if(PM_ARCHEOLOGIST) && (obj->spe & STATUE_HISTORIC)) {
+ if (by_you && Role_if(PM_ARCHEOLOGIST)
+ && (obj->spe & CORPSTAT_HISTORIC)) {
You_feel("guilty about damaging such a historic statue.");
adjalign(-1);
}