Source:NetHack 3.2.0/worn.c
(Redirected from NetHack 3.2.0/worn.c)
Jump to navigation
Jump to search
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.
This content was modified from the original NetHack source code distribution (by splitting up NetHack content between wiki pages, and possibly further editing). See the page history for a list of who changed it, and on what dates.
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*/