* candy bar wrapper index;
* scroll of mail (normal==0, bones or wishing==1, written==2);
* splash of venom (normal==0, wishing==1);
- * gender for corpses and statues (0..3, CORPSTAT_GENDER),
- * historic flag (4, CORPSTAT_HISTORIC) for statues */
+ * gender for corpses, statues, and figurines (0..3,
+ * CORPSTAT_GENDER),
+ * historic flag for statues (4, CORPSTAT_HISTORIC) */
char oclass; /* object class */
char invlet; /* designation in inventory */
char oartifact; /* artifact array index */
int chance, trycnt = 100;
do {
- if (otmp) { /* figurine; otherwise spell */
- int mndx = otmp->corpsenm;
+ long mmflags;
+ int cgend, mndx;
+ if (otmp) { /* figurine; otherwise spell */
+ mndx = otmp->corpsenm;
pm = &mons[mndx];
/* activating a figurine provides one way to exceed the
maximum number of the target critter created--unless
}
}
- mtmp = makemon(pm, x, y, MM_EDOG | MM_IGNOREWATER | NO_MINVENT);
+ mmflags = MM_EDOG | MM_IGNOREWATER | NO_MINVENT;
+ cgend = otmp ? (otmp->spe & CORPSTAT_GENDER) : 0;
+ mmflags |= ((cgend == CORPSTAT_FEMALE) ? MM_FEMALE
+ : (cgend == CORPSTAT_MALE) ? MM_MALE : 0L);
+
+ mtmp = makemon(pm, x, y, mmflags);
if (otmp && !mtmp) { /* monster was genocided or square occupied */
if (!quietly)
pline_The("figurine writhes and then shatters into pieces!");
register int mntmp = NON_PM;
register char *s, *str, *term;
char buf[BUFSZ];
- int len, slen, mgend, matchgend = NEUTRAL;
+ int len, slen, mgend, matchgend = -1;
boolean exact_match = FALSE;
if (remainder_p)
*remainder_p = (const char *) 0;
- if (gender_name_var)
- *gender_name_var = matchgend; /* NEUTRAL */
str = strcpy(buf, in_str);
mntmp = title_to_mon(str, (int *) 0, &len);
if (len && remainder_p)
*remainder_p = in_str + (&str[len] - buf);
- if (gender_name_var)
- *gender_name_var = matchgend;
+ if (gender_name_var && matchgend != -1) {
+ /* don't override with neuter if caller has already specified male
+ or female and we've matched the neuter name */
+ if (*gender_name_var == -1 || matchgend != NEUTRAL)
+ *gender_name_var = matchgend;
+ }
return mntmp;
}
if (typ == FIGURINE && omndx != NON_PM) {
char anbuf[10]; /* [4] would be enough: 'a','n',' ','\0' */
- const char *pm_name = mons[omndx].pmnames[NEUTRAL];
+ const char *pm_name = obj_pmname(obj);
Sprintf(eos(buf), " of %s%s", just_an(anbuf, pm_name), pm_name);
} else if (is_wet_towel(obj)) {
= d->looted /* wizard mode fountain/sink/throne/tree and grave */
= d->real = d->fake = 0; /* Amulet */
d->tvariety = RANDOM_TIN;
- d->mgend = NEUTRAL;
+ d->mgend = -1; /* not specified, aka random */
d->mntmp = NON_PM;
d->contents = UNDEFINED;
d->oclass = 0;
(void) memset(d->fruitbuf, '\0', sizeof d->globbuf);
}
+/* return 1 if d->bp is empty or contains only various qualifiers like
+ "blessed", "rustproof", and so on, or 0 if anything else is present */
static int
readobjnam_preparse(struct _readobjnam_data *d)
{
+ char *save_bp = 0;
+ int more_l = 0, res = 1;
+
for (;;) {
register int l;
if (!d->bp || !*d->bp)
- return 1;
+ break;
+
if (!strncmpi(d->bp, "an ", l = 3) || !strncmpi(d->bp, "a ", l = 2)) {
d->cnt = 1;
} else if (!strncmpi(d->bp, "the ", l = 4)) {
d->fake = 1, d->real = 0;
/* ['real' isn't actually needed (unless we someday add
"real gem" for random non-glass, non-stone)] */
- } else
+ } else if (!strncmpi(d->bp, "female ", l = 7)) {
+ d->mgend = FEMALE;
+ /* if after "corpse/statue/figurine of", remove from string */
+ if (save_bp)
+ strsubst(d->bp, "female ", ""), l = 0;
+ } else if (!strncmpi(d->bp, "male ", l = 5)) {
+ d->mgend = MALE;
+ if (save_bp)
+ strsubst(d->bp, "male ", ""), l = 0;
+ } else if (!strncmpi(d->bp, "neuter ", l = 7)) {
+ d->mgend = NEUTRAL;
+ if (save_bp)
+ strsubst(d->bp, "neuter ", ""), l = 0;
+
+ /*
+ * Corpse/statue/figurine gender hack: in order to accept
+ * "statue of a female gnome ruler" for gnome queen we need
+ * to recognize and skip over "statue of [a ]". Otherwise
+ * we would only accept "female gnome ruler statue" and the
+ * viable but silly "female statue of a gnome ruler".
+ */
+ } else if ((!strncmpi(d->bp, "corpse ", l = 7)
+ || !strncmpi(d->bp, "statue ", l = 7)
+ || !strncmpi(d->bp, "figurine ", l = 9))
+ && !strncmpi(d->bp + l, "of ", more_l = 3)) {
+ save_bp = d->bp; /* we'll backtrack to here later */
+ l += more_l, more_l = 0;
+ if (!strncmpi(d->bp + l, "a ", more_l = 2)
+ || !strncmpi(d->bp + l, "an ", more_l = 3)
+ || !strncmpi(d->bp + l, "the ", more_l = 4))
+ l += more_l;
+ res = 0;
+ } else {
+ res = 0;
break;
+ }
d->bp += l;
}
- return 0;
+ if (save_bp)
+ d->bp = save_bp;
+ return res;
}
static void
case IRON_CHAIN:
break;
case STATUE: /* otmp->cobj already done in mksobj() */
+ case FIGURINE:
case CORPSE: {
struct permonst *P = (d.mntmp >= LOW_PM) ? &mons[d.mntmp] : 0;