-/* NetHack 3.6 mondata.c $NHDT-Date: 1446604115 2015/11/04 02:28:35 $ $NHDT-Branch: master $:$NHDT-Revision: 1.58 $ */
+/* NetHack 3.6 mondata.c $NHDT-Date: 1550525093 2019/02/18 21:24:53 $ $NHDT-Branch: NetHack-3.6.2-beta01 $:$NHDT-Revision: 1.72 $ */
/* Copyright (c) Stichting Mathematisch Centrum, Amsterdam, 1985. */
+/*-Copyright (c) Robert Patrick Rankin, 2011. */
/* NetHack may be freely redistributed. See license for details. */
/* JNetHack Copyright */
/* (c) Issei Numata, Naoki Hamada, Shigehiro Miyashita, 1994-2000 */
-/* For 3.4-, Copyright (c) SHIRAKATA Kentaro, 2002-2016 */
+/* For 3.4-, Copyright (c) SHIRAKATA Kentaro, 2002-2019 */
/* JNetHack may be freely redistributed. See license for details. */
#include "hack.h"
-
-/* These routines provide basic data for any type of monster. */
+/*
+ * These routines provide basic data for any type of monster.
+ */
/* set up an individual monster's base type (initial creation, shapechange) */
void
-set_mon_data(mon, ptr, flag)
+set_mon_data(mon, ptr)
struct monst *mon;
struct permonst *ptr;
-int flag;
{
- mon->data = ptr;
- if (flag == -1)
- return; /* "don't care" */
+ int new_speed, old_speed = mon->data ? mon->data->mmove : 0;
- if (flag == 1)
- mon->mintrinsics |= (ptr->mresists & 0x00FF);
- else
- mon->mintrinsics = (ptr->mresists & 0x00FF);
+ mon->data = ptr;
+ mon->mnum = (short) monsndx(ptr);
+
+ if (mon->movement) { /* used to adjust poly'd hero as well as monsters */
+ new_speed = ptr->mmove;
+ /* prorate unused movement if new form is slower so that
+ it doesn't get extra moves leftover from previous form;
+ if new form is faster, leave unused movement as is */
+ if (new_speed < old_speed) {
+ /*
+ * Some static analysis warns that this might divide by 0
+ mon->movement = new_speed * mon->movement / old_speed;
+ * so add a redundant test to suppress that.
+ */
+ mon->movement *= new_speed;
+ if (old_speed > 0) /* old > new and new >= 0, so always True */
+ mon->movement /= old_speed;
+ }
+ }
return;
}
if (check_visor) {
o = (mdef == &youmonst) ? invent : mdef->minvent;
for (; o; o = o->nobj)
-#if 0 /*JP*/
+#if 0 /*JP:T*/
if ((o->owornmask & W_ARMH)
&& (s = OBJ_DESCR(objects[o->otyp])) != (char *) 0
&& !strcmp(s, "visored helmet"))
|| (ptr->mlet == S_IMP && ptr != &mons[PM_TENGU]));
}
+/* True if specific monster is especially affected by light-emitting weapons */
+boolean
+mon_hates_light(mon)
+struct monst *mon;
+{
+ return (boolean) (hates_light(mon->data));
+}
+
/* True iff the type of monster pass through iron bars */
boolean
passes_bars(mptr)
/* returns True if monster can blow (whistle, etc) */
boolean
can_blow(mtmp)
-register struct monst *mtmp;
+struct monst *mtmp;
{
if ((is_silent(mtmp->data) || mtmp->data->msound == MS_BUZZ)
&& (breathless(mtmp->data) || verysmall(mtmp->data)
return TRUE;
}
+/* for casting spells and reading scrolls while blind */
+boolean
+can_chant(mtmp)
+struct monst *mtmp;
+{
+ if ((mtmp == &youmonst && Strangled)
+ || is_silent(mtmp->data) || !has_head(mtmp->data)
+ || mtmp->data->msound == MS_BUZZ || mtmp->data->msound == MS_BURBLE)
+ return FALSE;
+ return TRUE;
+}
+
/* True if mon is vulnerable to strangulation */
boolean
can_be_strangled(mon)
/* Outdated names */
{ "invisible stalker", PM_STALKER },
{ "high-elf", PM_ELVENKING }, /* PM_HIGH_ELF is obsolete */
+ /* other misspellings or incorrect words */
+ { "wood-elf", PM_WOODLAND_ELF },
+ { "wood elf", PM_WOODLAND_ELF },
+ { "woodland nymph", PM_WOOD_NYMPH },
{ "halfling", PM_HOBBIT }, /* potential guess for polyself */
- /* Hyphenated names */
+ { "genie", PM_DJINNI }, /* potential guess for ^G/#wizgenesis */
+ /* Hyphenated names -- it would be nice to handle these via
+ fuzzymatch() but it isn't able to ignore trailing stuff */
{ "ki rin", PM_KI_RIN },
{ "uruk hai", PM_URUK_HAI },
{ "orc captain", PM_ORC_CAPTAIN },
{ "lurkers above", PM_LURKER_ABOVE },
{ "cavemen", PM_CAVEMAN },
{ "cavewomen", PM_CAVEWOMAN },
+ { "watchmen", PM_WATCHMAN },
{ "djinn", PM_DJINNI },
{ "mumakil", PM_MUMAK },
{ "erinyes", PM_ERINYS },
}
for (len = 0, i = LOW_PM; i < NUMMONS; i++) {
- register int m_i_len = strlen(mons[i].mname);
+ register int m_i_len = (int) strlen(mons[i].mname);
if (m_i_len > len && !strncmpi(mons[i].mname, str, m_i_len)) {
if (m_i_len == slen) {
- return i; /* exact match */
+ mntmp = i;
+ break; /* exact match */
} else if (slen > m_i_len
#if 0 /*JP*/
&& (str[m_i_len] == ' '
{ 0, NON_PM }
};
const char *p, *x;
- int i;
+ int i, len;
if (mndx_p)
*mndx_p = NON_PM; /* haven't [yet] matched a specific type */
return i;
} else {
/* multiple characters */
+ if (!strcmpi(in_str, "long")) /* not enough to match "long worm" */
+ return 0; /* avoid false whole-word match with "long worm tail" */
in_str = makesingular(in_str);
/* check for special cases */
for (i = 0; falsematch[i]; i++)
return mons[i].mlet;
}
/* check monster class descriptions */
+ len = (int) strlen(in_str);
for (i = 1; i < MAXMCLASSES; i++) {
x = def_monsyms[i].explain;
- if ((p = strstri(x, in_str)) != 0 && (p == x || *(p - 1) == ' '))
+ if ((p = strstri(x, in_str)) != 0 && (p == x || *(p - 1) == ' ')
+ && ((int) strlen(p) >= len
+ && (p[len] == '\0' || p[len] == ' ')))
return i;
}
- /* check individual species names; not as thorough as mon_to_name()
- but our caller can call that directly if desired */
- for (i = LOW_PM; i < NUMMONS; i++) {
- x = mons[i].mname;
- if ((p = strstri(x, in_str)) != 0
- && (p == x || *(p - 1) == ' ')) {
- if (mndx_p)
- *mndx_p = i;
- return mons[i].mlet;
- }
+ /* check individual species names */
+ i = name_to_mon(in_str);
+ if (i != NON_PM) {
+ if (mndx_p)
+ *mndx_p = i;
+ return mons[i].mlet;
}
}
return 0;
/* Like gender(), but lower animals and such are still "it".
This is the one we want to use when printing messages. */
int
-pronoun_gender(mtmp)
+pronoun_gender(mtmp, override_vis)
register struct monst *mtmp;
+boolean override_vis; /* if True then 'no it' unless neuter */
{
- if (is_neuter(mtmp->data) || !canspotmon(mtmp))
+ if (!override_vis && !canspotmon(mtmp))
+ return 2;
+ if (is_neuter(mtmp->data))
return 2;
return (humanoid(mtmp->data) || (mtmp->data->geno & G_UNIQ)
|| type_is_pname(mtmp->data)) ? (int) mtmp->female : 2;
return montype;
}
+/* determine whether two permonst indices are part of the same progression;
+ existence of progressions with more than one step makes it a bit tricky */
+boolean
+big_little_match(montyp1, montyp2)
+int montyp1, montyp2;
+{
+ int l, b;
+
+ /* simplest case: both are same pm */
+ if (montyp1 == montyp2)
+ return TRUE;
+ /* assume it isn't possible to grow from one class letter to another */
+ if (mons[montyp1].mlet != mons[montyp2].mlet)
+ return FALSE;
+ /* check whether montyp1 can grow up into montyp2 */
+ for (l = montyp1; (b = little_to_big(l)) != l; l = b)
+ if (b == montyp2)
+ return TRUE;
+ /* check whether montyp2 can grow up into montyp1 */
+ for (l = montyp2; (b = little_to_big(l)) != l; l = b)
+ if (b == montyp1)
+ return TRUE;
+ /* neither grows up to become the other; no match */
+ return FALSE;
+}
+
/*
* Return the permonst ptr for the race of the monster.
* Returns correct pointer for non-polymorphed and polymorphed
/*JP
static const char *flys[4] = { "fly", "Fly", "flutter", "Flutter" };
*/
-static const char *flys[4] = { "\94ò\82Ô", "\94ò\82Ô", "\82Í\82½\82ß\82", "\82Í\82½\82ß\82" };
+static const char *flys[4] = { "\94ò\82Ô", "\94ò\82Ô", "\82¨\82Ì\82Ì\82", "\82¨\82Ì\82Ì\82" };
/*JP
static const char *flyl[4] = { "fly", "Fly", "stagger", "Stagger" };
*/
/*JP
static const char *ooze[4] = { "ooze", "Ooze", "tremble", "Tremble" };
*/
-static const char *ooze[4] = { "\82É\82¶\82Ý\8fo\82é", "\82É\82¶\82Ý\8fo\82é", "\90k\82¦\82é", "\90k\82¦\82é" };
+static const char *ooze[4] = { "\82É\82¶\82Ý\8fo\82é", "\82É\82¶\82Ý\8fo\82é", "\90g\90k\82¢\82·\82é", "\90g\90k\82¢\82·\82é" };
/*JP
static const char *immobile[4] = { "wiggle", "Wiggle", "pulsate", "Pulsate" };
*/
-static const char *immobile[4] = { "\90k\82¦\82é", "\90k\82¦\82é", "\90k\82¦\82é", "\90k\82¦\82é" };
+static const char *immobile[4] = { "\93®\82", "\93®\82", "\90k\82¦\82é", "\90k\82¦\82é" };
/*JP
static const char *crawl[4] = { "crawl", "Crawl", "falter", "Falter" };
*/
: def);
}
+/*JP:
+ * \81u\82æ\82ë\82ß\82\81v\82ð\89ö\95¨\82Ì\8eí\97Þ\82É\82æ\82Á\82Ä\95Ï\82¦\82é\81B
+ * \8e©\95ª\82É\91Î\82µ\82Ä\8eg\82¤\8fê\8d\87\82É\82Í\8aù\82É\81u\82\82ç\82\82ç\82·\82é\81v\82ª\8eg\82í\82ê\82Ä\82¢\82é\82Ì\82Å\81A
+ * \95Ï\89»\82µ\82Ä\82¢\82Ä\82à\82»\82Ì\82Ü\82Ü\82É\82·\82é\81B
+ * \91\8a\8eè\82É\91Î\82µ\82Ä\8eg\82¤\8fê\8d\87\82Í\81u\82\82ç\82\82ç\82·\82é\81v\82Í\95s\8e©\91R\82È\82Ì\82Å\82±\82ê\82ð\8eg\82¤\81B
+ */
const char *
stagger(ptr, def)
const struct permonst *ptr;