Wikihack
Advertisement

Below is the full text to worn.c from the source code of NetHack 3.2.0. To link to a particular line, write [[NetHack 3.2.0/worn.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: @(#)worn.c	3.2	96/03/28	*/
2.    /* Copyright (c) Stichting Mathematisch Centrum, Amsterdam, 1985. */
3.    /* NetHack may be freely redistributed.  See license for details. */
4.    
5.    #include "hack.h"
6.    
7.    static void FDECL(m_lose_armor, (struct monst *,struct obj *));
8.    
9.    const struct worn {
10.   	long w_mask;
11.   	struct obj **w_obj;
12.   } worn[] = {
13.   	{ W_ARM, &uarm },
14.   	{ W_ARMC, &uarmc },
15.   	{ W_ARMH, &uarmh },
16.   	{ W_ARMS, &uarms },
17.   	{ W_ARMG, &uarmg },
18.   	{ W_ARMF, &uarmf },
19.   #ifdef TOURIST
20.   	{ W_ARMU, &uarmu },
21.   #endif
22.   	{ W_RINGL, &uleft },
23.   	{ W_RINGR, &uright },
24.   	{ W_WEP, &uwep },
25.   	{ W_AMUL, &uamul },
26.   	{ W_TOOL, &ublindf },
27.   	{ W_BALL, &uball },
28.   	{ W_CHAIN, &uchain },
29.   	{ 0, 0 }
30.   };
31.   
32.   /* this only allows for one blocking item per property;
33.      to be general, we'd need a separate uprops[].i_blocked
34.      field rather than just a single bit in uprops[].p_flgs */
35.   #define w_blocks(otmp)	\
36.   		((otmp->otyp == MUMMY_WRAPPING) ? INVIS :	\
37.   		 (otmp->otyp == CORNUTHAUM && !Role_is('W')) ? CLAIRVOYANT : 0)
38.   		/* note: monsters don't have clairvoyance, so your role
39.   		   has no significant effect on their use of w_blocks() */
40.   
41.   void
42.   setworn(obj, mask)
43.   register struct obj *obj;
44.   long mask;
45.   {
46.   	register const struct worn *wp;
47.   	register struct obj *oobj;
48.   	register int p;
49.   
50.   	if ((mask & (W_ARM|I_SPECIAL)) == (W_ARM|I_SPECIAL)) {
51.   	    /* restoring saved game; no properties are conferred via skin */
52.   	    uskin = obj;
53.   	 /* assert( !uarm ); */
54.   	} else {
55.   	    for(wp = worn; wp->w_mask; wp++) if(wp->w_mask & mask) {
56.   		oobj = *(wp->w_obj);
57.   		if(oobj && !(oobj->owornmask & wp->w_mask))
58.   			impossible("Setworn: mask = %ld.", wp->w_mask);
59.   		if(oobj) {
60.   		    oobj->owornmask &= ~wp->w_mask;
61.   		    /* leave as "x = x <op> y", here and below, for broken
62.   		     * compilers */
63.   		    p = objects[oobj->otyp].oc_oprop;
64.   		    u.uprops[p].p_flgs = u.uprops[p].p_flgs & ~wp->w_mask;
65.   		    if (oobj->oartifact) set_artifact_intrinsic(oobj, 0, mask);
66.   		    if ((p = w_blocks(oobj)) != 0)
67.   			u.uprops[p].p_flgs &= ~I_BLOCKED;
68.   		}
69.   		*(wp->w_obj) = obj;
70.   		if(obj) {
71.   		    obj->owornmask |= wp->w_mask;
72.   		/* prevent getting intrinsics from wielding potions, etc... */
73.   		/* wp_mask should be same as mask at this point */
74.   		    if(obj->oclass == WEAPON_CLASS || mask != W_WEP) {
75.   			p = objects[obj->otyp].oc_oprop;
76.   			u.uprops[p].p_flgs = u.uprops[p].p_flgs | wp->w_mask;
77.   		    }
78.   		    if (obj->oartifact) set_artifact_intrinsic(obj, 1, mask);
79.   		    if ((p = w_blocks(obj)) != 0)
80.   			u.uprops[p].p_flgs |= I_BLOCKED;
81.   		}
82.   	    }
83.   	}
84.   	update_inventory();
85.   }
86.   
87.   /* called e.g. when obj is destroyed */
88.   void
89.   setnotworn(obj)
90.   register struct obj *obj;
91.   {
92.   	register const struct worn *wp;
93.   	register int p;
94.   
95.   	if (!obj) return;
96.   	for(wp = worn; wp->w_mask; wp++)
97.   		if(obj == *(wp->w_obj)) {
98.   			*(wp->w_obj) = 0;
99.   			p = objects[obj->otyp].oc_oprop;
100.  			u.uprops[p].p_flgs = u.uprops[p].p_flgs & ~wp->w_mask;
101.  			obj->owornmask &= ~wp->w_mask;
102.  			if (obj->oartifact)
103.  			    set_artifact_intrinsic(obj, 0, wp->w_mask);
104.  			if ((p = w_blocks(obj)) != 0)
105.  			    u.uprops[p].p_flgs &= ~I_BLOCKED;
106.  		}
107.  	update_inventory();
108.  }
109.  
110.  void
111.  mon_set_minvis(mon)
112.  struct monst *mon;
113.  {
114.  	mon->perminvis = 1;
115.  	if (!mon->invis_blkd) {
116.  	    mon->minvis = 1;
117.  	    newsym(mon->mx, mon->my);		/* make it disappear */
118.  	    if (mon->wormno) see_wsegs(mon);	/* and any tail too */
119.  	}
120.  }
121.  
122.  /* armor put on or taken off; might be magical variety */
123.  void
124.  update_mon_intrinsics(mon, obj, on)
125.  struct monst *mon;
126.  struct obj *obj;
127.  boolean on;
128.  {
129.  	int unseen = !canseemon(mon);
130.  
131.  	switch (objects[obj->otyp].oc_oprop) {
132.  	 case INVIS:
133.  	    mon->minvis = on ? !mon->invis_blkd : mon->perminvis;
134.  	    break;
135.  	 default:
136.  	    break;
137.  	}
138.  	switch (w_blocks(obj)) {
139.  	 case INVIS:
140.  	    mon->invis_blkd = on ? 1 : 0;
141.  	    mon->minvis = on ? 0 : mon->perminvis;
142.  	    break;
143.  	 default:
144.  	    break;
145.  	}
146.  
147.  	/* if couldn't see it but now can, or vice versa, update display */
148.  	if (unseen ^ !canseemon(mon))
149.  	    newsym(mon->mx, mon->my);
150.  }
151.  
152.  int
153.  find_mac(mon)
154.  register struct monst *mon;
155.  {
156.  	register struct obj *obj;
157.  	int base = mon->data->ac;
158.  	long mwflags = mon->misc_worn_check;
159.  
160.  	for (obj = mon->minvent; obj; obj = obj->nobj) {
161.  	    if (obj->owornmask & mwflags)
162.  		base -= ARM_BONUS(obj);
163.  		/* since ARM_BONUS is positive, subtracting it increases AC */
164.  	}
165.  	return base;
166.  }
167.  
168.  /* weapons are handled separately; rings and eyewear aren't used by monsters */
169.  #define m_might_wear(O) ((O)->oclass == ARMOR_CLASS ||	\
170.  			 (O)->oclass == AMULET_CLASS)
171.  
172.  /* Wear first object of that type it finds, and never switch unless it
173.   * has none at all.  This means that monsters with leather armor never
174.   * switch to plate mail, but it also avoids the overhead of either having 8
175.   * struct obj *s for every monster in the game, or of doing multiple inventory
176.   * searches each round using which_armor().
177.   *
178.   * We'll let monsters put on shirts and/or suits under worn cloaks, but
179.   * not shirts under worn suits.  This is somewhat arbitrary, but it's
180.   * too tedious to have them remove and later replace outer garments,
181.   * and preventing suits under cloaks makes it a little bit too easy for
182.   * players to influence what gets worn.  Putting on a shirt underneath
183.   * already worn body armor is too obviously buggy...
184.   */
185.  void
186.  m_dowear(mon, creation)
187.  register struct monst *mon;
188.  boolean creation;
189.  {
190.  	register struct obj *obj;
191.  
192.  	/* Note the restrictions here are the same as in dowear in do_wear.c
193.  	 * except for the additional restriction on intelligence.  (Players
194.  	 * are always intelligent, even if polymorphed).
195.  	 */
196.  	if (verysmall(mon->data) || nohands(mon->data) || is_animal(mon->data))
197.  		return;
198.  	/* give mummies a chance to wear their wrappings */
199.  	if (mindless(mon->data) && (mon->data->mlet != S_MUMMY || !creation))
200.  		return;
201.  
202.  	for(obj = mon->minvent; obj; obj = obj->nobj) {
203.  		long flag;
204.  		int m_delay = 0;
205.  
206.  		/* if already worn or never wearable, skip it right away */
207.  		if (obj->owornmask || !m_might_wear(obj)) continue;
208.  
209.  		if (obj->oclass == AMULET_CLASS) {
210.  			if (obj->otyp != AMULET_OF_LIFE_SAVING &&
211.  			    obj->otyp != AMULET_OF_REFLECTION)
212.  				continue;
213.  			flag = W_AMUL;
214.  #ifdef TOURIST
215.  		} else if (is_shirt(obj)) {
216.  			if (cantweararm(mon->data) ||
217.  			    /* can't put on shirt if already wearing suit */
218.  			    (mon->misc_worn_check & W_ARM))
219.  				continue;
220.  			flag = W_ARMU;
221.  			m_delay = (mon->misc_worn_check & W_ARMC) ? 2 : 0;
222.  #endif
223.  		} else if (is_cloak(obj)) {
224.  			/* treating small as a special case allows
225.  			   hobbits, gnomes, and kobolds to wear cloaks */
226.  			if (cantweararm(mon->data) &&
227.  			    mon->data->msize != MZ_SMALL)
228.  				continue;
229.  			flag = W_ARMC;
230.  		} else if (is_helmet(obj)) {
231.  			flag = W_ARMH;
232.  		} else if (is_shield(obj)) {
233.  			if (MON_WEP(mon) && bimanual(MON_WEP(mon)))
234.  				continue;
235.  			flag = W_ARMS;
236.  		} else if (is_gloves(obj)) {
237.  			if (MON_WEP(mon) && MON_WEP(mon)->cursed)
238.  				continue;
239.  			flag = W_ARMG;
240.  		} else if (is_boots(obj)) {
241.  			if (slithy(mon->data) || mon->data->mlet == S_CENTAUR)
242.  				continue;
243.  			flag = W_ARMF;
244.  		} else if (obj->oclass == ARMOR_CLASS) {
245.  			if (cantweararm(mon->data))
246.  				continue;
247.  			flag = W_ARM;
248.  			m_delay = (mon->misc_worn_check & W_ARMC) ? 2 : 0;
249.  		} else
250.  			continue;		/* shouldn't be possible */
251.  
252.  		if (mon->misc_worn_check & flag) continue;
253.  			/* already wearing one */
254.  		if (!creation && canseemon(mon)) {
255.  			pline("%s puts on %s.", Monnam(mon),
256.  						distant_name(obj, doname));
257.  			m_delay += objects[obj->otyp].oc_delay;
258.  			mon->mfrozen = m_delay;
259.  			if (mon->mfrozen) mon->mcanmove = 0;
260.  		}
261.  		mon->misc_worn_check |= flag;
262.  		obj->owornmask |= flag;
263.  		update_mon_intrinsics(mon, obj, TRUE);
264.  		if (mon->mfrozen) break;		/* now busy */
265.  	}
266.  }
267.  
268.  struct obj *
269.  which_armor(mon, flag)
270.  struct monst *mon;
271.  long flag;
272.  {
273.  	register struct obj *obj;
274.  
275.  	for(obj = mon->minvent; obj; obj = obj->nobj)
276.  		if (obj->owornmask & flag) return obj;
277.  	return((struct obj *)0);
278.  }
279.  
280.  /* remove an item of armor and then drop it */
281.  static void
282.  m_lose_armor(mon, obj)
283.  struct monst *mon;
284.  struct obj *obj;
285.  {
286.  	mon->misc_worn_check &= ~obj->owornmask;
287.  	obj->owornmask = 0L;
288.  	update_mon_intrinsics(mon, obj, FALSE);
289.  
290.  	obj_extract_self(obj);
291.  	place_object(obj, mon->mx, mon->my);
292.  	/* call stackobj() if we ever drop anything that can merge */
293.  	newsym(mon->mx, mon->my);
294.  }
295.  
296.  void
297.  mon_break_armor(mon)
298.  struct monst *mon;
299.  {
300.  	register struct obj *otmp;
301.  	struct permonst *mdat = mon->data;
302.  	boolean vis = cansee(mon->mx, mon->my);
303.  	const char *pronoun = him[pronoun_gender(mon)],
304.  			*ppronoun = his[pronoun_gender(mon)];
305.  
306.  	if (breakarm(mdat)) {
307.  	    if ((otmp = which_armor(mon, W_ARM)) != 0) {
308.  		if (vis)
309.  		    pline("%s breaks out of %s armor!", Monnam(mon), ppronoun);
310.  		else
311.  		    You_hear("a cracking sound.");
312.  		m_useup(mon, otmp);
313.  	    }
314.  	    if ((otmp = which_armor(mon, W_ARMC)) != 0) {
315.  		if (otmp->oartifact) {
316.  		    if (vis)
317.  			pline("%s cloak falls off!", s_suffix(Monnam(mon)));
318.  		    m_lose_armor(mon, otmp);
319.  		} else {
320.  		    if (vis)
321.  			pline("%s cloak tears apart!", s_suffix(Monnam(mon)));
322.  		    else
323.  			You_hear("a ripping sound.");
324.  		    m_useup(mon, otmp);
325.  		}
326.  	    }
327.  #ifdef TOURIST
328.  	    if ((otmp = which_armor(mon, W_ARMU)) != 0) {
329.  		if (vis)
330.  		    pline("%s shirt rips to shreds!", s_suffix(Monnam(mon)));
331.  		else
332.  		    You_hear("a ripping sound.");
333.  		m_useup(mon, otmp);
334.  	    }
335.  #endif
336.  	} else if (sliparm(mdat)) {
337.  	    if ((otmp = which_armor(mon, W_ARM)) != 0) {
338.  		if (vis)
339.  		    pline("%s armor falls around %s!",
340.  			         s_suffix(Monnam(mon)), pronoun);
341.  		else
342.  		    You_hear("a thud.");
343.  		m_lose_armor(mon, otmp);
344.  	    }
345.  	    if ((otmp = which_armor(mon, W_ARMC)) != 0) {
346.  		if (vis)
347.  		    if (is_whirly(mon->data))
348.  			pline("%s cloak falls, unsupported!",
349.  			             s_suffix(Monnam(mon)));
350.  		    else
351.  			pline("%s shrinks out of %s cloak!", Monnam(mon),
352.  								ppronoun);
353.  		m_lose_armor(mon, otmp);
354.  	    }
355.  #ifdef TOURIST
356.  	    if ((otmp = which_armor(mon, W_ARMU)) != 0) {
357.  		if (vis)
358.  		    if (sliparm(mon->data))
359.  			pline("%s seeps right through %s shirt!",
360.  					Monnam(mon), ppronoun);
361.  		    else
362.  			pline("%s becomes much too small for %s shirt!",
363.  					Monnam(mon), ppronoun);
364.  		m_lose_armor(mon, otmp);
365.  	    }
366.  #endif
367.  	}
368.  	if (nohands(mdat) || verysmall(mdat)) {
369.  	    if ((otmp = which_armor(mon, W_ARMG)) != 0) {
370.  		if (vis)
371.  		    pline("%s drops %s gloves%s!", Monnam(mon), ppronoun,
372.  					MON_WEP(mon) ? " and weapon" : "");
373.  		possibly_unwield(mon);
374.  		m_lose_armor(mon, otmp);
375.  	    }
376.  	    if ((otmp = which_armor(mon, W_ARMS)) != 0) {
377.  		if (vis)
378.  		    pline("%s can no longer hold %s shield!", Monnam(mon),
379.  								ppronoun);
380.  		else
381.  		    You_hear("a clank.");
382.  		m_lose_armor(mon, otmp);
383.  	    }
384.  	    if ((otmp = which_armor(mon, W_ARMH)) != 0) {
385.  		if (vis)
386.  		    pline("%s helmet falls to the %s!",
387.  			  s_suffix(Monnam(mon)), surface(mon->mx, mon->my));
388.  		else
389.  		    You_hear("a clank.");
390.  		m_lose_armor(mon, otmp);
391.  	    }
392.  	}
393.  	if (nohands(mdat) || verysmall(mdat) || slithy(mdat) ||
394.  	    mdat->mlet == S_CENTAUR) {
395.  	    if ((otmp = which_armor(mon, W_ARMF)) != 0) {
396.  		if (vis) {
397.  		    if (is_whirly(mon->data))
398.  			pline("%s boots fall away!",
399.  			               s_suffix(Monnam(mon)));
400.  		    else pline("%s boots %s off %s feet!",
401.  			s_suffix(Monnam(mon)),
402.  			verysmall(mdat) ? "slide" : "are pushed", ppronoun);
403.  		}
404.  		m_lose_armor(mon, otmp);
405.  	    }
406.  	}
407.  }
408.  
409.  /*worn.c*/
Advertisement