Source:NetHack 3.2.0/worn.c

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

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  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*/