Fandom

Wikihack

Source:NetHack 3.3.0/mondata.c

2,034pages on
this wiki
Add New Page
Talk0

Ad blocker interference detected!


Wikia is a free-to-use site that makes money from advertising. We have a modified experience for viewers using ad blockers

Wikia is not accessible if you’ve made further modifications. Remove the custom ad blocker rule(s) and the page will load as expected.

Below is the full text to mondata.c from the source code of NetHack 3.3.0. To link to a particular line, write [[NetHack 3.3.0/mondata.c#line123]], for example.

Warning! This is the source code from an old release. For the latest release, see Source code

The NetHack General Public License applies to screenshots, source code and other content from NetHack.
1.    /*	SCCS Id: @(#)mondata.c	3.3	99/09/15	*/
2.    /* Copyright (c) Stichting Mathematisch Centrum, Amsterdam, 1985. */
3.    /* NetHack may be freely redistributed.  See license for details. */
4.    
5.    #include "hack.h"
6.    #include "eshk.h"
7.    #include "epri.h"
8.    
9.    /*	These routines provide basic data for any type of monster. */
10.   
11.   #ifdef OVLB
12.   
13.   void
14.   set_mon_data(mon, ptr, flag)
15.   struct monst *mon;
16.   struct permonst *ptr;
17.   int flag;
18.   {
19.       mon->data = ptr;
20.       if (flag == -1) return;		/* "don't care" */
21.   
22.       if (flag == 1)
23.   	mon->mintrinsics |= (ptr->mresists & 0x00FF);
24.       else
25.   	mon->mintrinsics = (ptr->mresists & 0x00FF);
26.       return;
27.   }
28.   
29.   #endif /* OVLB */
30.   #ifdef OVL0
31.   
32.   boolean
33.   attacktype(ptr, atyp)
34.   	register struct	permonst	*ptr;
35.   	register int atyp;
36.   {
37.   	int	i;
38.   
39.   	for(i = 0; i < NATTK; i++)
40.   	    if(ptr->mattk[i].aatyp == atyp) return(TRUE);
41.   
42.   	return(FALSE);
43.   }
44.   
45.   #endif /* OVL0 */
46.   #ifdef OVLB
47.   
48.   boolean
49.   poly_when_stoned(ptr)
50.       struct permonst *ptr;
51.   {
52.       return((boolean)(is_golem(ptr) && ptr != &mons[PM_STONE_GOLEM] &&
53.   	    !(mvitals[PM_STONE_GOLEM].mvflags & G_GENOD)));
54.   	    /* allow G_EXTINCT */
55.   }
56.   
57.   boolean
58.   resists_drli(mon)	/* returns TRUE if monster is drain-life resistant */
59.   struct monst *mon;
60.   {
61.   	struct permonst *ptr = mon->data;
62.   	struct obj *wep = ((mon == &youmonst) ? uwep : MON_WEP(mon));
63.   
64.   	return (boolean)(is_undead(ptr) || is_demon(ptr) || is_were(ptr) ||
65.   			 ptr == &mons[PM_DEATH] ||
66.   			 (wep && wep->oartifact && defends(AD_DRLI, wep)));
67.   }
68.   
69.   boolean
70.   resists_magm(mon)	/* TRUE if monster is magic-missile resistant */
71.   struct monst *mon;
72.   {
73.   	struct permonst *ptr = mon->data;
74.   	struct obj *o;
75.   
76.   	/* as of 3.2.0:  gray dragons, Angels, Oracle, Yeenoghu */
77.   	if (dmgtype(ptr, AD_MAGM) || ptr == &mons[PM_BABY_GRAY_DRAGON] ||
78.   		dmgtype(ptr, AD_RBRE))	/* Chromatic Dragon */
79.   	    return TRUE;
80.   	/* check for magic resistance granted by wielded weapon */
81.   	o = (mon == &youmonst) ? uwep : MON_WEP(mon);
82.   	if (o && o->oartifact && defends(AD_MAGM, o))
83.   	    return TRUE;
84.   	/* check for magic resistance granted by worn or carried items */
85.   	for (o = mon->minvent; o; o = o->nobj)
86.   	    if ((o->owornmask && objects[o->otyp].oc_oprop == ANTIMAGIC) ||
87.   		    (o->oartifact && protects(AD_MAGM, o)))
88.   		return TRUE;
89.   	return FALSE;
90.   }
91.   
92.   /* TRUE iff monster is resistant to light-induced blindness */
93.   boolean
94.   resists_blnd(mon)
95.   struct monst *mon;
96.   {
97.   	struct permonst *ptr = mon->data;
98.   	boolean is_you = (mon == &youmonst);
99.   	struct obj *o;
100.  
101.  	if (is_you ? (Blind || u.usleep) :
102.  		(mon->mblinded || !mon->mcansee || !haseyes(ptr) ||
103.  		    /* BUG: temporary sleep sets mfrozen, but since
104.  			    paralysis does too, we can't check it */
105.  		    mon->msleeping))
106.  	    return TRUE;
107.  	/* AD_BLND => yellow light, dust vortex, ki-rin (?), Archon */
108.  	if (dmgtype(ptr, AD_BLND) && !attacktype(ptr, AT_SPIT))
109.  	    return TRUE;
110.  	o = is_you ? uwep : MON_WEP(mon);
111.  	if (o && o->oartifact && defends(AD_BLND, o))
112.  	    return TRUE;
113.  	o = is_you ? invent : mon->minvent;
114.  	for ( ; o; o = o->nobj)
115.  	    if ((o->owornmask && objects[o->otyp].oc_oprop == BLINDED) ||
116.  		    (o->oartifact && protects(AD_BLND, o)))
117.  		return TRUE;
118.  	return FALSE;
119.  }
120.  
121.  #endif /* OVLB */
122.  #ifdef OVL0
123.  
124.  boolean
125.  ranged_attk(ptr)	/* returns TRUE if monster can attack at range */
126.  struct permonst *ptr;
127.  {
128.  	register int i, atyp;
129.  	long atk_mask = (1L << AT_BREA) | (1L << AT_SPIT) | (1L << AT_GAZE);
130.  
131.  	/* was: (attacktype(ptr, AT_BREA) || attacktype(ptr, AT_WEAP) ||
132.  		attacktype(ptr, AT_SPIT) || attacktype(ptr, AT_GAZE) ||
133.  		attacktype(ptr, AT_MAGC));
134.  	   but that's too slow -dlc
135.  	 */
136.  	for (i = 0; i < NATTK; i++) {
137.  	    atyp = ptr->mattk[i].aatyp;
138.  	    if (atyp >= AT_WEAP) return TRUE;
139.  	 /* assert(atyp < 32); */
140.  	    if ((atk_mask & (1L << atyp)) != 0L) return TRUE;
141.  	}
142.  
143.  	return FALSE;
144.  }
145.  
146.  boolean
147.  hates_silver(ptr)
148.  register struct permonst *ptr;
149.  /* returns TRUE if monster is especially affected by silver weapons */
150.  {
151.  	return((boolean)(is_were(ptr) || ptr->mlet==S_VAMPIRE || is_demon(ptr) ||
152.  		ptr == &mons[PM_SHADE] ||
153.  		(ptr->mlet==S_IMP && ptr != &mons[PM_TENGU])));
154.  }
155.  
156.  #endif /* OVL0 */
157.  #ifdef OVL1
158.  
159.  boolean
160.  can_track(ptr)		/* returns TRUE if monster can track well */
161.  	register struct permonst *ptr;
162.  {
163.  	if (uwep && uwep->oartifact == ART_EXCALIBUR)
164.  		return TRUE;
165.  	else
166.  		return((boolean)haseyes(ptr));
167.  }
168.  
169.  #endif /* OVL1 */
170.  #ifdef OVLB
171.  
172.  boolean
173.  sliparm(ptr)	/* creature will slide out of armor */
174.  	register struct permonst *ptr;
175.  {
176.  	return((boolean)(is_whirly(ptr) || ptr->msize <= MZ_SMALL ||
177.  			 noncorporeal(ptr)));
178.  }
179.  
180.  boolean
181.  breakarm(ptr)	/* creature will break out of armor */
182.  	register struct permonst *ptr;
183.  {
184.  	return ((bigmonst(ptr) || (ptr->msize > MZ_SMALL && !humanoid(ptr)) ||
185.  		/* special cases of humanoids that cannot wear body armor */
186.  		ptr == &mons[PM_MARILITH] || ptr == &mons[PM_WINGED_GARGOYLE])
187.  	      && !sliparm(ptr));
188.  }
189.  #endif /* OVLB */
190.  #ifdef OVL1
191.  
192.  boolean
193.  sticks(ptr)	/* creature sticks other creatures it hits */
194.  	register struct permonst *ptr;
195.  {
196.  	return((boolean)(dmgtype(ptr,AD_STCK) || dmgtype(ptr,AD_WRAP) ||
197.  		attacktype(ptr,AT_HUGS)));
198.  }
199.  
200.  boolean
201.  dmgtype(ptr, dtyp)
202.  	register struct	permonst	*ptr;
203.  	register int dtyp;
204.  {
205.  	int	i;
206.  
207.  	for(i = 0; i < NATTK; i++)
208.  	    if(ptr->mattk[i].adtyp == dtyp) return TRUE;
209.  
210.  	return FALSE;
211.  }
212.  
213.  /* returns the maximum damage a defender can do to the attacker via
214.   * a passive defense */
215.  int
216.  max_passive_dmg(mdef, magr)
217.      register struct monst *mdef, *magr;
218.  {
219.      int	i, dmg = 0;
220.      uchar adtyp;
221.  
222.      for(i = 0; i < NATTK; i++)
223.  	if(mdef->data->mattk[i].aatyp == AT_NONE) {
224.  	    adtyp = mdef->data->mattk[i].adtyp;
225.  	    if ((adtyp == AD_ACID && !resists_acid(magr)) ||
226.  		    (adtyp == AD_COLD && !resists_cold(magr)) ||
227.  		    (adtyp == AD_FIRE && !resists_fire(magr)) ||
228.  		    (adtyp == AD_ELEC && !resists_elec(magr))) {
229.  		dmg = mdef->data->mattk[i].damn;
230.  		if(!dmg) dmg = mdef->data->mlevel+1;
231.  		dmg *= mdef->data->mattk[i].damd;
232.  	    } else dmg = 0;
233.  
234.  	    return dmg;
235.  	}
236.      return 0;
237.  }
238.  
239.  #endif /* OVL1 */
240.  #ifdef OVL0
241.  
242.  int
243.  monsndx(ptr)		/* return an index into the mons array */
244.  	struct	permonst	*ptr;
245.  {
246.  	register int	i;
247.  
248.  	i = (int)(ptr - &mons[0]);
249.  	if (i < LOW_PM || i >= NUMMONS) {
250.  		/* ought to switch this to use `fmt_ptr' */
251.  	    panic("monsndx - could not index monster (%lx)",
252.  		  (unsigned long)ptr);
253.  	    return FALSE;		/* will not get here */
254.  	}
255.  
256.  	return(i);
257.  }
258.  
259.  #endif /* OVL0 */
260.  #ifdef OVL1
261.  
262.  
263.  int
264.  name_to_mon(in_str)
265.  const char *in_str;
266.  {
267.  	/* Be careful.  We must check the entire string in case it was
268.  	 * something such as "ettin zombie corpse".  The calling routine
269.  	 * doesn't know about the "corpse" until the monster name has
270.  	 * already been taken off the front, so we have to be able to
271.  	 * read the name with extraneous stuff such as "corpse" stuck on
272.  	 * the end.
273.  	 * This causes a problem for names which prefix other names such
274.  	 * as "ettin" on "ettin zombie".  In this case we want the _longest_
275.  	 * name which exists.
276.  	 * This also permits plurals created by adding suffixes such as 's'
277.  	 * or 'es'.  Other plurals must still be handled explicitly.
278.  	 */
279.  	register int i;
280.  	register int mntmp = NON_PM;
281.  	register char *s, *str, *term;
282.  	char buf[BUFSZ];
283.  	int len, slen;
284.  
285.  	str = strcpy(buf, in_str);
286.  
287.  	if (!strncmp(str, "a ", 2)) str += 2;
288.  	else if (!strncmp(str, "an ", 3)) str += 3;
289.  
290.  	slen = strlen(str);
291.  	term = str + slen;
292.  
293.  	if ((s = strstri(str, "vortices")) != 0)
294.  	    Strcpy(s+4, "ex");
295.  	/* be careful with "ies"; "priest", "zombies" */
296.  	else if (slen > 3 && !strcmpi(term-3, "ies") &&
297.  		    (slen < 7 || strcmpi(term-7, "zombies")))
298.  	    Strcpy(term-3, "y");
299.  	/* luckily no monster names end in fe or ve with ves plurals */
300.  	else if (slen > 3 && !strcmpi(term-3, "ves"))
301.  	    Strcpy(term-3, "f");
302.  
303.  	slen = strlen(str); /* length possibly needs recomputing */
304.  
305.      {
306.  	static const struct alt_spl { const char* name; short pm_val; }
307.  	    names[] = {
308.  	    /* Alternate spellings */
309.  		{ "grey dragon",	PM_GRAY_DRAGON },
310.  		{ "baby grey dragon",	PM_BABY_GRAY_DRAGON },
311.  		{ "grey unicorn",	PM_GRAY_UNICORN },
312.  		{ "grey ooze",		PM_GRAY_OOZE },
313.  		{ "gray-elf",		PM_GREY_ELF },
314.  	    /* Hyphenated names */
315.  		{ "ki rin",		PM_KI_RIN },
316.  		{ "uruk hai",		PM_URUK_HAI },
317.  		{ "orc captain",	PM_ORC_CAPTAIN },
318.  		{ "woodland elf",	PM_WOODLAND_ELF },
319.  		{ "green elf",		PM_GREEN_ELF },
320.  		{ "grey elf",		PM_GREY_ELF },
321.  		{ "gray elf",		PM_GREY_ELF },
322.  		{ "elf lord",		PM_ELF_LORD },
323.  #if 0	/* OBSOLETE */
324.  		{ "high elf",		PM_HIGH_ELF },
325.  #endif
326.  		{ "olog hai",		PM_OLOG_HAI },
327.  		{ "arch lich",		PM_ARCH_LICH },
328.  	    /* Some irregular plurals */
329.  		{ "incubi",		PM_INCUBUS },
330.  		{ "succubi",		PM_SUCCUBUS },
331.  		{ "violet fungi",	PM_VIOLET_FUNGUS },
332.  		{ "homunculi",		PM_HOMUNCULUS },
333.  		{ "baluchitheria",	PM_BALUCHITHERIUM },
334.  		{ "lurkers above",	PM_LURKER_ABOVE },
335.  		{ "cavemen",		PM_CAVEMAN },
336.  		{ "cavewomen",		PM_CAVEWOMAN },
337.  		{ "djinn",		PM_DJINNI },
338.  		{ "mumakil",		PM_MUMAK },
339.  		{ "erinyes",		PM_ERINYS },
340.  	    /* falsely caught by -ves check above */
341.  		{ "master of thief",	PM_MASTER_OF_THIEVES },
342.  	    /* end of list */
343.  		{ 0, 0 }
344.  	};
345.  	register const struct alt_spl *namep;
346.  
347.  	for (namep = names; namep->name; namep++)
348.  	    if (!strncmpi(str, namep->name, (int)strlen(namep->name)))
349.  		return namep->pm_val;
350.      }
351.  
352.  	for (len = 0, i = LOW_PM; i < NUMMONS; i++) {
353.  	    register int m_i_len = strlen(mons[i].mname);
354.  	    if (m_i_len > len && !strncmpi(mons[i].mname, str, m_i_len)) {
355.  		if (m_i_len == slen) return i;	/* exact match */
356.  		else if (slen > m_i_len &&
357.  			(str[m_i_len] == ' ' ||
358.  			 !strcmpi(&str[m_i_len], "s") ||
359.  			 !strncmpi(&str[m_i_len], "s ", 2) ||
360.  			 !strcmpi(&str[m_i_len], "es") ||
361.  			 !strncmpi(&str[m_i_len], "es ", 3))) {
362.  		    mntmp = i;
363.  		    len = m_i_len;
364.  		}
365.  	    }
366.  	}
367.  	if (mntmp == NON_PM) mntmp = title_to_mon(str, (int *)0, (int *)0);
368.  	return mntmp;
369.  }
370.  
371.  #endif /* OVL1 */
372.  #ifdef OVLB
373.  
374.  boolean
375.  webmaker(ptr)   /* creature can spin a web */
376.  	register struct permonst *ptr;
377.  {
378.  	return((boolean)(ptr->mlet == S_SPIDER && ptr != &mons[PM_SCORPION]));
379.  }
380.  
381.  #endif /* OVLB */
382.  #ifdef OVL2
383.  
384.  /* returns 3 values (0=male, 1=female, 2=none) */
385.  int
386.  gender(mtmp)
387.  register struct monst *mtmp;
388.  {
389.  	if (is_neuter(mtmp->data)) return 2;
390.  	return mtmp->female;
391.  }
392.  
393.  /* Like gender(), but lower animals and such are still "it". */
394.  /* This is the one we want to use when printing messages. */
395.  int
396.  pronoun_gender(mtmp)
397.  register struct monst *mtmp;
398.  {
399.  	if (!canspotmon(mtmp) || !humanoid(mtmp->data))
400.  		return 2;
401.  	return mtmp->female;
402.  }
403.  
404.  #endif /* OVL2 */
405.  #ifdef OVLB
406.  
407.  boolean
408.  levl_follower(mtmp)
409.  register struct monst *mtmp;
410.  {
411.  	return((boolean)(mtmp->mtame || (mtmp->data->mflags2 & M2_STALK) || is_fshk(mtmp)
412.  		|| (mtmp->iswiz && !mon_has_amulet(mtmp))));
413.  }
414.  
415.  static const short grownups[][2] = {
416.  	{PM_CHICKATRICE, PM_COCKATRICE},
417.  	{PM_LITTLE_DOG, PM_DOG}, {PM_DOG, PM_LARGE_DOG},
418.  	{PM_HELL_HOUND_PUP, PM_HELL_HOUND},
419.  	{PM_WINTER_WOLF_CUB, PM_WINTER_WOLF},
420.  	{PM_KITTEN, PM_HOUSECAT}, {PM_HOUSECAT, PM_LARGE_CAT},
421.  	{PM_PONY, PM_HORSE}, {PM_HORSE, PM_WARHORSE},
422.  	{PM_KOBOLD, PM_LARGE_KOBOLD}, {PM_LARGE_KOBOLD, PM_KOBOLD_LORD},
423.  	{PM_GNOME, PM_GNOME_LORD}, {PM_GNOME_LORD, PM_GNOME_KING},
424.  	{PM_DWARF, PM_DWARF_LORD}, {PM_DWARF_LORD, PM_DWARF_KING},
425.  	{PM_OGRE, PM_OGRE_LORD}, {PM_OGRE_LORD, PM_OGRE_KING},
426.  	{PM_ELF, PM_ELF_LORD}, {PM_WOODLAND_ELF, PM_ELF_LORD},
427.  	{PM_GREEN_ELF, PM_ELF_LORD}, {PM_GREY_ELF, PM_ELF_LORD},
428.  	{PM_ELF_LORD, PM_ELVENKING},
429.  	{PM_LICH, PM_DEMILICH}, {PM_DEMILICH, PM_MASTER_LICH},
430.  	{PM_MASTER_LICH, PM_ARCH_LICH},
431.  	{PM_VAMPIRE, PM_VAMPIRE_LORD}, {PM_BAT, PM_GIANT_BAT},
432.  	{PM_BABY_GRAY_DRAGON, PM_GRAY_DRAGON},
433.  	{PM_BABY_SILVER_DRAGON, PM_SILVER_DRAGON},        
434.  #if 0	/* DEFERRED */
435.  	{PM_BABY_SHIMMERING_DRAGON, PM_SHIMMERING_DRAGON},
436.  #endif
437.  	{PM_BABY_RED_DRAGON, PM_RED_DRAGON},
438.  	{PM_BABY_WHITE_DRAGON, PM_WHITE_DRAGON},
439.  	{PM_BABY_ORANGE_DRAGON, PM_ORANGE_DRAGON},
440.  	{PM_BABY_BLACK_DRAGON, PM_BLACK_DRAGON},
441.  	{PM_BABY_BLUE_DRAGON, PM_BLUE_DRAGON},
442.  	{PM_BABY_GREEN_DRAGON, PM_GREEN_DRAGON},
443.  	{PM_BABY_YELLOW_DRAGON, PM_YELLOW_DRAGON},
444.  	{PM_RED_NAGA_HATCHLING, PM_RED_NAGA},
445.  	{PM_BLACK_NAGA_HATCHLING, PM_BLACK_NAGA},
446.  	{PM_GOLDEN_NAGA_HATCHLING, PM_GOLDEN_NAGA},
447.  	{PM_GUARDIAN_NAGA_HATCHLING, PM_GUARDIAN_NAGA},
448.  	{PM_SMALL_MIMIC, PM_LARGE_MIMIC}, {PM_LARGE_MIMIC, PM_GIANT_MIMIC},
449.  	{PM_BABY_LONG_WORM, PM_LONG_WORM},
450.  	{PM_BABY_PURPLE_WORM, PM_PURPLE_WORM},
451.  	{PM_BABY_CROCODILE, PM_CROCODILE},
452.  	{PM_SOLDIER, PM_SERGEANT},
453.  	{PM_SERGEANT, PM_LIEUTENANT},
454.  	{PM_LIEUTENANT, PM_CAPTAIN},
455.  	{PM_WATCHMAN, PM_WATCH_CAPTAIN},
456.  	{PM_ALIGNED_PRIEST, PM_HIGH_PRIEST},
457.  	{PM_STUDENT, PM_ARCHEOLOGIST},
458.  	{PM_ATTENDANT, PM_HEALER},
459.  	{PM_PAGE, PM_KNIGHT},
460.  	{PM_ACOLYTE, PM_PRIEST},
461.  	{PM_APPRENTICE, PM_WIZARD},
462.  #ifdef KOPS
463.  	{PM_KEYSTONE_KOP, PM_KOP_SERGEANT},
464.  	{PM_KOP_SERGEANT, PM_KOP_LIEUTENANT},
465.  	{PM_KOP_LIEUTENANT, PM_KOP_KAPTAIN},
466.  #endif
467.  	{NON_PM,NON_PM}
468.  };
469.  
470.  int
471.  little_to_big(montype)
472.  int montype;
473.  {
474.  #ifndef AIXPS2_BUG
475.  	register int i;
476.  	
477.  	for (i = 0; grownups[i][0] >= LOW_PM; i++)
478.  		if(montype == grownups[i][0]) return grownups[i][1];
479.  	return montype;
480.  #else
481.  /* AIX PS/2 C-compiler 1.1.1 optimizer does not like the above for loop,
482.   * and causes segmentation faults at runtime.  (The problem does not
483.   * occur if -O is not used.)
484.   * lehtonen@cs.Helsinki.FI (Tapio Lehtonen) 28031990
485.   */
486.  	int i;
487.  	int monvalue;
488.  
489.  	monvalue = montype;
490.  	for (i = 0; grownups[i][0] >= LOW_PM; i++)
491.  		if(montype == grownups[i][0]) monvalue = grownups[i][1];
492.  
493.  	return monvalue;
494.  #endif
495.  }
496.  
497.  int
498.  big_to_little(montype)
499.  int montype;
500.  {
501.  	register int i;
502.  	
503.  	for (i = 0; grownups[i][0] >= LOW_PM; i++)
504.  		if(montype == grownups[i][1]) return grownups[i][0];
505.  	return montype;
506.  }
507.  
508.  static const char *levitate[2]	= { "float", "Float" };
509.  static const char *fly[2]	= { "fly", "Fly" };
510.  static const char *slither[2]	= { "slither", "Slither" };
511.  static const char *ooze[2]	= { "ooze", "Ooze" };
512.  static const char *crawl[2]	= { "crawl", "Crawl" };
513.  
514.  const char *
515.  locomotion(ptr, def)
516.  const struct permonst *ptr;
517.  const char *def;
518.  {
519.  	int capitalize = (*def == highc(*def));
520.  
521.  	return (
522.  		is_floater(ptr) ? levitate[capitalize] :
523.  		is_flyer(ptr)   ? fly[capitalize] :
524.  		slithy(ptr)     ? slither[capitalize] :
525.  		amorphous(ptr)  ? ooze[capitalize] :
526.  		nolimbs(ptr)    ? crawl[capitalize] :
527.  		def
528.  	       );
529.  
530.  }
531.  
532.  #endif /* OVLB */
533.  
534.  /*mondata.c*/

Also on Fandom

Random Wiki