home *** CD-ROM | disk | FTP | other *** search
/ Source Code 1994 March / Source_Code_CD-ROM_Walnut_Creek_March_1994.iso / compsrcs / games / volume16 / nethck31 / part56 < prev    next >
Encoding:
Internet Message Format  |  1993-02-03  |  58.3 KB

  1. Path: uunet!news.tek.com!master!saab!billr
  2. From: billr@saab.CNA.TEK.COM (Bill Randle)
  3. Newsgroups: comp.sources.games
  4. Subject: v16i064:  nethack31 - display oriented dungeons & dragons (Ver. 3.1), Part56/108
  5. Message-ID: <4367@master.CNA.TEK.COM>
  6. Date: 1 Feb 93 19:44:00 GMT
  7. Sender: news@master.CNA.TEK.COM
  8. Lines: 2197
  9. Approved: billr@saab.CNA.TEK.COM
  10. Xref: uunet comp.sources.games:1614
  11.  
  12. Submitted-by: izchak@linc.cis.upenn.edu (Izchak Miller)
  13. Posting-number: Volume 16, Issue 64
  14. Archive-name: nethack31/Part56
  15. Supersedes: nethack3p9: Volume 10, Issue 46-102
  16. Environment: Amiga, Atari, Mac, MS-DOS, OS2, Unix, VMS, X11
  17.  
  18.  
  19.  
  20. #! /bin/sh
  21. # This is a shell archive.  Remove anything before this line, then unpack
  22. # it by saving it into a file and typing "sh file".  To overwrite existing
  23. # files, type "sh file -c".  You can also feed this as standard input via
  24. # unshar, or by typing "sh <file", e.g..  If this archive is complete, you
  25. # will see the following message at the end:
  26. #        "End of archive 56 (of 108)."
  27. # Contents:  include/wintype.h src/lock.c src/mhitu.c1
  28. # Wrapped by billr@saab on Wed Jan 27 16:09:08 1993
  29. PATH=/bin:/usr/bin:/usr/ucb ; export PATH
  30. if test -f 'include/wintype.h' -a "${1}" != "-c" ; then 
  31.   echo shar: Will not clobber existing file \"'include/wintype.h'\"
  32. else
  33. echo shar: Extracting \"'include/wintype.h'\" \(753 characters\)
  34. sed "s/^X//" >'include/wintype.h' <<'END_OF_FILE'
  35. X/*    SCCS Id: @(#)wintype.h    3.1    91/07/03    */
  36. X/* Copyright (c) David Cohrs, 1991                  */
  37. X/* NetHack may be freely redistributed.  See license for details. */
  38. X
  39. X#ifndef WINTYPE_H
  40. X#define WINTYPE_H
  41. X
  42. X/* window types */
  43. X/* any additional port specific types should be defined in win*.h */
  44. X#define NHW_MESSAGE 1
  45. X#define NHW_STATUS  2
  46. X#define NHW_MAP     3
  47. X#define NHW_MENU    4
  48. X#define NHW_TEXT    5
  49. X
  50. X/* attribute types for putstr; the same as the ANSI value, for convenience */
  51. X#define ATR_NONE    0
  52. X#define ATR_BOLD    1
  53. X#define ATR_DIM     2
  54. X#define ATR_ULINE   4
  55. X#define ATR_BLINK   5
  56. X#define ATR_INVERSE 7
  57. X
  58. X/* nh_poskey() modifier types */
  59. X#define CLICK_1     1
  60. X#define CLICK_2        2
  61. X
  62. X/* invalid winid */
  63. X#define WIN_ERR ((winid) -1)
  64. X
  65. X#endif /* WINTYPE_H */
  66. END_OF_FILE
  67. if test 753 -ne `wc -c <'include/wintype.h'`; then
  68.     echo shar: \"'include/wintype.h'\" unpacked with wrong size!
  69. fi
  70. # end of 'include/wintype.h'
  71. fi
  72. if test -f 'src/lock.c' -a "${1}" != "-c" ; then 
  73.   echo shar: Will not clobber existing file \"'src/lock.c'\"
  74. else
  75. echo shar: Extracting \"'src/lock.c'\" \(19813 characters\)
  76. sed "s/^X//" >'src/lock.c' <<'END_OF_FILE'
  77. X/*    SCCS Id: @(#)lock.c    3.1    92/09/02
  78. X/* Copyright (c) Stichting Mathematisch Centrum, Amsterdam, 1985. */
  79. X/* NetHack may be freely redistributed.  See license for details. */
  80. X
  81. X#include    "hack.h"
  82. X
  83. X#define CONTAINER_BITS 0    /* box options not [yet?] implemented */
  84. X
  85. XSTATIC_PTR int NDECL(picklock);
  86. XSTATIC_PTR int NDECL(forcelock);
  87. X
  88. XSTATIC_VAR struct xlock_s {
  89. X    int    door_or_box, picktyp;
  90. X    struct rm  *door;
  91. X    struct obj *box;
  92. X    int chance, usedtime;
  93. X} NEARDATA xlock;
  94. X
  95. X#ifdef OVLB
  96. X
  97. Xstatic boolean FDECL(obstructed,(int,int));
  98. Xstatic void FDECL(chest_shatter_msg, (struct obj *));
  99. X
  100. Xboolean
  101. Xpicking_at(x, y)
  102. Xint x, y;
  103. X{
  104. X    return((occupation == picklock) && 
  105. X           xlock.door_or_box && (xlock.door == &levl[x][y])); 
  106. X}
  107. X
  108. XSTATIC_PTR
  109. Xint
  110. Xpicklock()    /* try to open/close a lock */
  111. X{
  112. X
  113. X    if(!xlock.door_or_box) {    /* box */
  114. X
  115. X        if((xlock.box->ox != u.ux) || (xlock.box->oy != u.uy)) {
  116. X        return((xlock.usedtime = 0));        /* you or it moved */
  117. X        }
  118. X    } else {        /* door */
  119. X        if(xlock.door != &(levl[u.ux+u.dx][u.uy+u.dy])) {
  120. X        return((xlock.usedtime = 0));        /* you moved */
  121. X        }
  122. X        switch (xlock.door->doormask) {
  123. X        case D_NODOOR:
  124. X            pline("This doorway has no door.");
  125. X            return((xlock.usedtime = 0));
  126. X        case D_ISOPEN:
  127. X            pline("Picking the lock of an open door is pointless.");
  128. X            return((xlock.usedtime = 0));
  129. X        case D_BROKEN:
  130. X            pline("This door is broken.");
  131. X            return((xlock.usedtime = 0));
  132. X        }
  133. X    }
  134. X
  135. X    if(xlock.usedtime++ >= 50
  136. X#ifdef POLYSELF
  137. X       || nohands(uasmon)
  138. X#endif
  139. X       ) {
  140. X        You("give up your attempt to %s the lock.",
  141. X          (xlock.door_or_box ? !(xlock.door->doormask & D_LOCKED) :
  142. X           !xlock.box->olocked) ? "lock" :
  143. X          ((xlock.picktyp == LOCK_PICK) ? "pick" : "open" ));
  144. X
  145. X        exercise(A_DEX, TRUE);    /* even if you don't succeed */
  146. X        return((xlock.usedtime = 0));
  147. X    }
  148. X
  149. X    if(rn2(100) > xlock.chance) return(1);        /* still busy */
  150. X
  151. X    if(xlock.door_or_box) {
  152. X        You("succeed in %sing the lock.",
  153. X          !(xlock.door->doormask & D_LOCKED) ? "lock" :
  154. X          ((xlock.picktyp == LOCK_PICK) ? "pick" : "open" ));
  155. X        if(xlock.door->doormask & D_TRAPPED) {
  156. X            b_trapped("door");
  157. X            xlock.door->doormask = D_NODOOR;
  158. X            unblock_point(u.ux+u.dx, u.uy+u.dy);
  159. X            newsym(u.ux+u.dx, u.uy+u.dy);
  160. X        } else if(xlock.door->doormask == D_LOCKED)
  161. X        xlock.door->doormask = D_CLOSED;
  162. X        else xlock.door->doormask = D_LOCKED;
  163. X    } else {
  164. X        You("succeed in %sing the lock.",
  165. X          (!xlock.box->olocked) ? "lock" :
  166. X          (xlock.picktyp == LOCK_PICK) ? "pick" : "open" );
  167. X        xlock.box->olocked = !xlock.box->olocked;
  168. X        if(xlock.box->otrapped)    
  169. X        (void) chest_trap(xlock.box, FINGER, FALSE);
  170. X    }
  171. X    exercise(A_DEX, TRUE);
  172. X    return((xlock.usedtime = 0));
  173. X}
  174. X
  175. XSTATIC_PTR
  176. Xint
  177. Xforcelock()    /* try to force a locked chest */
  178. X{
  179. X
  180. X    register struct obj *otmp, *otmp2;
  181. X
  182. X    if((xlock.box->ox != u.ux) || (xlock.box->oy != u.uy))
  183. X        return((xlock.usedtime = 0));        /* you or it moved */
  184. X
  185. X    if(xlock.usedtime++ >= 50 || !uwep
  186. X#ifdef POLYSELF
  187. X       || nohands(uasmon)
  188. X#endif
  189. X       ) {
  190. X        You("give up your attempt to force the lock.");
  191. X        if(xlock.usedtime >= 50)        /* you made the effort */
  192. X          exercise((xlock.picktyp) ? A_DEX : A_STR, TRUE);
  193. X        return((xlock.usedtime = 0));
  194. X    }
  195. X
  196. X    if(xlock.picktyp) {    /* blade */
  197. X
  198. X        if(rn2(1000-(int)uwep->spe) > (992-(int)uwep->oeroded*10) && 
  199. X           !uwep->cursed) {
  200. X        /* for a +0 weapon, probability that it survives an unsuccessful
  201. X         * attempt to force the lock is (.992)^50 = .67
  202. X         */
  203. X        pline("%sour %s broke!",
  204. X              (uwep->quan > 1L) ? "One of y" : "Y", xname(uwep));
  205. X        useup(uwep);
  206. X        You("give up your attempt to force the lock.");
  207. X        exercise(A_DEX, TRUE);
  208. X        return((xlock.usedtime = 0));
  209. X        }
  210. X    } else            /* blunt */
  211. X        wake_nearby();    /* due to hammering on the container */
  212. X
  213. X    if(rn2(100) > xlock.chance) return(1);        /* still busy */
  214. X
  215. X    You("succeed in forcing the lock.");
  216. X    xlock.box->olocked = 0;
  217. X    xlock.box->obroken = 1;
  218. X    if(!xlock.picktyp && !rn2(3)) {
  219. X        register struct monst *shkp;
  220. X        long loss = 0L;
  221. X
  222. X#ifdef GCC_WARN
  223. X        shkp = (struct monst *) 0;
  224. X#endif
  225. X
  226. X        if(*u.ushops) shkp = shop_keeper(*u.ushops);
  227. X
  228. X        pline("In fact, you've totally destroyed %s.",
  229. X          the(xname(xlock.box)));
  230. X
  231. X        /* Put the contents on ground at the hero's feet. */
  232. X        for (otmp = xlock.box->cobj; otmp; otmp = otmp2) {
  233. X        otmp2 = otmp->nobj;
  234. X        if(!rn2(3) || otmp->oclass == POTION_CLASS) {
  235. X            chest_shatter_msg(otmp);
  236. X            if(*u.ushops && costly_spot(u.ux, u.uy))
  237. X                loss += stolen_value(otmp, u.ux, u.uy,
  238. X                         (boolean)shkp->mpeaceful, TRUE);
  239. X            if (otmp->quan == 1L) {
  240. X            obfree(otmp, (struct obj *) 0);
  241. X            continue;
  242. X            }
  243. X            useup(otmp);
  244. X        }
  245. X        place_object(otmp,u.ux,u.uy);
  246. X        otmp->nobj = fobj;
  247. X        fobj = otmp;
  248. X        stackobj(otmp);
  249. X        }
  250. X        xlock.box->cobj = (struct obj *) 0;    /* no contents */
  251. X        if(*u.ushops && costly_spot(u.ux, u.uy))
  252. X        loss += stolen_value(otmp, u.ux, u.uy,
  253. X                         (boolean)shkp->mpeaceful, TRUE);
  254. X        if(loss) You("owe %ld zorkmids for objects destroyed.", loss);
  255. X        delobj(xlock.box);
  256. X    }
  257. X    exercise((xlock.picktyp) ? A_DEX : A_STR, TRUE);
  258. X    return((xlock.usedtime = 0));
  259. X}
  260. X
  261. X#endif /* OVLB */
  262. X#ifdef OVL0
  263. X
  264. Xvoid
  265. Xreset_pick() { xlock.usedtime = 0; }
  266. X
  267. X#endif /* OVL0 */
  268. X#ifdef OVLB
  269. X
  270. Xint
  271. Xpick_lock(pick) /* pick a lock with a given object */
  272. X    register struct    obj    *pick;
  273. X{
  274. X    register int x, y, picktyp, c, ch;
  275. X    register struct rm    *door;
  276. X    register struct obj    *otmp;
  277. X    char qbuf[QBUFSZ];
  278. X
  279. X#ifdef GCC_WARN
  280. X    ch = 0;        /* GCC myopia */
  281. X#endif
  282. X    picktyp = pick->otyp;
  283. X    if(xlock.usedtime && picktyp == xlock.picktyp) {
  284. X
  285. X        You("resume your attempt to %s the lock.",
  286. X          (xlock.door_or_box ? !(xlock.door->doormask & D_LOCKED) :
  287. X           !xlock.box->olocked) ? "lock" :
  288. X          ((xlock.picktyp == LOCK_PICK) ? "pick" : "open" ));
  289. X
  290. X        set_occupation(picklock,
  291. X               (picktyp == LOCK_PICK) ? "picking the lock" :
  292. X                            "opening the lock",  0);
  293. X        return(1);
  294. X    }
  295. X
  296. X#ifdef POLYSELF
  297. X    if(nohands(uasmon)) {
  298. X        You("can't hold a %s - you have no hands!", xname(pick));
  299. X        return(0);
  300. X    }
  301. X#endif
  302. X    if((picktyp != LOCK_PICK &&
  303. X#ifdef TOURIST
  304. X        picktyp != CREDIT_CARD &&
  305. X#endif
  306. X        picktyp != SKELETON_KEY)) {
  307. X        impossible("picking lock with object %d?", picktyp);
  308. X        return(0);
  309. X    }
  310. X    if(!getdir(NULL)) return(0);
  311. X
  312. X    x = u.ux + u.dx;
  313. X    y = u.uy + u.dy;
  314. X    if((x == u.ux) && (y == u.uy)) { /* pick the lock on a container */
  315. X        c = 'n';            /* in case there are no boxes here */
  316. X        for(otmp = level.objects[x][y]; otmp; otmp = otmp->nexthere)
  317. X        if (Is_box(otmp)) {
  318. X            const char *verb;
  319. X            boolean it = 0;
  320. X#if CONTAINER_BITS
  321. X            if (!otmp->oclosed) {    /* it's open */
  322. X            pline("There is %s here.", doname(otmp));
  323. X            continue;
  324. X            }
  325. X            if (!otmp->lknown) verb = "work";
  326. X            else
  327. X#endif
  328. X             if (otmp->obroken) verb = "fix";
  329. X            else if (!otmp->olocked) verb = "lock", it = 1;
  330. X            else if (picktyp != LOCK_PICK) verb = "unlock", it = 1;
  331. X            else verb = "pick";
  332. X            Sprintf(qbuf, "There is %s here, %s %s?",
  333. X                doname(otmp), verb, it ? "it" : "its lock");
  334. X
  335. X            c = ynq(qbuf);
  336. X            if(c == 'q') return(0);
  337. X            if(c == 'n') continue;
  338. X
  339. X#if CONTAINER_BITS
  340. X            otmp->lknown = 1;
  341. X#endif
  342. X            if (otmp->obroken) {
  343. X            You("can't fix its broken lock with %s.", doname(pick));
  344. X            return 0;
  345. X            }
  346. X#ifdef TOURIST
  347. X            else if (picktyp == CREDIT_CARD && !otmp->olocked) {
  348. X            /* credit cards are only good for unlocking */
  349. X            You("can't do that with %s.", doname(pick));
  350. X            return 0;
  351. X            }
  352. X#endif
  353. X            switch(picktyp) {
  354. X#ifdef TOURIST
  355. X            case CREDIT_CARD:
  356. X                ch = ACURR(A_DEX)+(20*(pl_character[0] == 'R'));
  357. X                break;
  358. X#endif
  359. X            case LOCK_PICK:
  360. X                ch = 4*ACURR(A_DEX)+(25*(pl_character[0] == 'R'));
  361. X                break;
  362. X            case SKELETON_KEY:
  363. X                ch = 75 + ACURR(A_DEX);
  364. X                break;
  365. X            default:    ch = 0;
  366. X            }
  367. X            if(otmp->cursed) ch /= 2;
  368. X
  369. X            xlock.door_or_box = 0;
  370. X            xlock.picktyp = picktyp;
  371. X            xlock.box = otmp;
  372. X            break;
  373. X        }
  374. X        if(c != 'y')
  375. X        return(0);        /* decided against all boxes */
  376. X    } else {            /* pick the lock in a door */
  377. X        struct monst *mtmp;
  378. X
  379. X        door = &levl[x][y];
  380. X        if ((mtmp = m_at(x, y)) && canseemon(mtmp)
  381. X            && mtmp->m_ap_type != M_AP_FURNITURE
  382. X            && mtmp->m_ap_type != M_AP_OBJECT) {
  383. X#ifdef TOURIST
  384. X        if (picktyp == CREDIT_CARD &&
  385. X            (mtmp->isshk || mtmp->data == &mons[PM_ORACLE]))
  386. X            verbalize("No checks, no credit, no problem.");
  387. X        else
  388. X#endif
  389. X            pline("I don't think %s would appreciate that.", mon_nam(mtmp));
  390. X        return(0);
  391. X        }
  392. X        if(!IS_DOOR(door->typ)) {
  393. X        if (is_drawbridge_wall(x,y) >= 0)
  394. X            You("%s no lock on the drawbridge.",
  395. X                Blind ? "feel" : "see");
  396. X        else
  397. X            You("%s no door there.",
  398. X                Blind ? "feel" : "see");
  399. X        return(0);
  400. X        }
  401. X        switch (door->doormask) {
  402. X        case D_NODOOR:
  403. X            pline("This doorway has no door.");
  404. X            return(0);
  405. X        case D_ISOPEN:
  406. X            pline("Picking the lock of an open door is pointless.");
  407. X            return(0);
  408. X        case D_BROKEN:
  409. X            pline("This door is broken.");
  410. X            return(0);
  411. X        default:
  412. X#ifdef TOURIST
  413. X            /* credit cards are only good for unlocking */
  414. X            if(picktyp == CREDIT_CARD && !(door->doormask & D_LOCKED)) {
  415. X            You("can't lock a door with a credit card.");
  416. X            return(0);
  417. X            }
  418. X#endif
  419. X
  420. X            Sprintf(qbuf,"%sock it?",
  421. X            (door->doormask & D_LOCKED) ? "Unl" : "L" );
  422. X
  423. X            c = yn(qbuf);
  424. X            if(c == 'n') return(0);
  425. X
  426. X            switch(picktyp) {
  427. X#ifdef TOURIST
  428. X            case CREDIT_CARD:
  429. X                ch = 2*ACURR(A_DEX)+(20*(pl_character[0] == 'R'));
  430. X                break;
  431. X#endif
  432. X            case LOCK_PICK:
  433. X                ch = 3*ACURR(A_DEX)+(30*(pl_character[0] == 'R'));
  434. X                break;
  435. X            case SKELETON_KEY:
  436. X                ch = 70 + ACURR(A_DEX);
  437. X                break;
  438. X            default:    ch = 0;
  439. X            }
  440. X            xlock.door_or_box = 1;
  441. X            xlock.door = door;
  442. X        }
  443. X    }
  444. X    flags.move = 0;
  445. X    xlock.chance = ch;
  446. X    xlock.picktyp = picktyp;
  447. X    xlock.usedtime = 0;
  448. X    set_occupation(picklock,
  449. X               (picktyp == LOCK_PICK) ? "picking the lock" :
  450. X                        "opening the lock",  0);
  451. X    return(1);
  452. X}
  453. X
  454. Xint
  455. Xdoforce()        /* try to force a chest with your weapon */
  456. X{
  457. X    register struct obj *otmp;
  458. X    register int c, picktyp;
  459. X    char qbuf[QBUFSZ];
  460. X
  461. X    if(!uwep ||    /* proper type test */
  462. X       (uwep->oclass != WEAPON_CLASS && uwep->oclass != ROCK_CLASS &&
  463. X                        uwep->otyp != PICK_AXE) ||
  464. X       (uwep->otyp < BOOMERANG) ||
  465. X       (uwep->otyp > AKLYS && uwep->oclass != ROCK_CLASS &&
  466. X                        uwep->otyp != PICK_AXE)
  467. X#ifdef KOPS
  468. X       || uwep->otyp == RUBBER_HOSE
  469. X#endif
  470. X      ) {
  471. X        You("can't force anything without a %sweapon.",
  472. X          (uwep) ? "proper " : "");
  473. X        return(0);
  474. X    }
  475. X
  476. X    picktyp = is_blade(uwep);
  477. X    if(xlock.usedtime && xlock.box && picktyp == xlock.picktyp) {
  478. X        You("resume your attempt to force the lock.");
  479. X        set_occupation(forcelock, "forcing the lock", 0);
  480. X        return(1);
  481. X    }
  482. X
  483. X    /* A lock is made only for the honest man, the thief will break it. */
  484. X    xlock.box = (struct obj *)0;
  485. X    for(otmp = level.objects[u.ux][u.uy]; otmp; otmp = otmp->nexthere)
  486. X        if(Is_box(otmp)) {
  487. X#if CONTAINER_BITS
  488. X        if (!otmp->oclosed) {    /* it's open */
  489. X            pline("There is %s here.", doname(otmp));
  490. X            continue;
  491. X        }
  492. X        if (otmp->obroken || (otmp->lknown && !otmp->olocked)) {
  493. X#else
  494. X        if (otmp->obroken || !otmp->olocked) {
  495. X#endif
  496. X            pline("There is %s here, but its lock is already %s.",
  497. X              doname(otmp), otmp->obroken ? "broken" : "unlocked");
  498. X            continue;
  499. X        }
  500. X        Sprintf(qbuf,"There is %s here, force its lock?", doname(otmp));
  501. X
  502. X        c = ynq(qbuf);
  503. X        if(c == 'q') return(0);
  504. X        if(c == 'n') continue;
  505. X
  506. X#if CONTAINER_BITS
  507. X        if (!otmp->olocked) {    /* lock-status wasn't known */
  508. X            pline("Well what'd'ya know?  It's already unlocked.");
  509. X            otmp->lknown = 1;
  510. X            return 0;
  511. X        }
  512. X#endif
  513. X        if(picktyp)
  514. X            You("force your %s into a crack and pry.", xname(uwep));
  515. X        else
  516. X            You("start bashing it with your %s.", xname(uwep));
  517. X        xlock.box = otmp;
  518. X        xlock.chance = objects[otmp->otyp].oc_wldam * 2;
  519. X        xlock.picktyp = picktyp;
  520. X        xlock.usedtime = 0;
  521. X        break;
  522. X        }
  523. X
  524. X    if(xlock.box)    set_occupation(forcelock, "forcing the lock", 0);
  525. X    else        You("decide not to force the issue.");
  526. X    return(1);
  527. X}
  528. X
  529. Xint
  530. Xdoopen()        /* try to open a door */
  531. X{
  532. X    register int x, y;
  533. X    register struct rm *door;
  534. X    struct monst *mtmp;
  535. X
  536. X    if (u.utrap && u.utraptype == TT_PIT) {
  537. X        You("can't reach over the edge of the pit.");
  538. X        return 0;
  539. X    }
  540. X
  541. X    if(!getdir(NULL)) return(0);
  542. X
  543. X    x = u.ux + u.dx;
  544. X    y = u.uy + u.dy;
  545. X    if((x == u.ux) && (y == u.uy)) return(0);
  546. X
  547. X    if ((mtmp = m_at(x,y))                &&
  548. X        mtmp->m_ap_type == M_AP_FURNITURE    &&
  549. X        (mtmp->mappearance == S_hcdoor ||
  550. X            mtmp->mappearance == S_vcdoor)    &&
  551. X        !Protection_from_shape_changers)     {
  552. X
  553. X        stumble_onto_mimic(mtmp);
  554. X        return(1);
  555. X    }
  556. X
  557. X    door = &levl[x][y];
  558. X
  559. X    if(!IS_DOOR(door->typ)) {
  560. X        if (is_db_wall(x,y)) {
  561. X            pline("There is no obvious way to open the drawbridge.");
  562. X            return(0);
  563. X        }
  564. X        You("%s no door there.",
  565. X                Blind ? "feel" : "see");
  566. X        return(0);
  567. X    }
  568. X
  569. X    if(!(door->doormask & D_CLOSED)) {
  570. X      switch(door->doormask) {
  571. X         case D_BROKEN: pline("This door is broken."); break;
  572. X         case D_NODOOR: pline("This doorway has no door."); break;
  573. X         case D_ISOPEN: pline("This door is already open."); break;
  574. X         default:        pline("This door is locked."); break;
  575. X      }
  576. X      return(0);
  577. X    }
  578. X
  579. X#ifdef POLYSELF
  580. X    if(verysmall(uasmon)) {
  581. X        pline("You're too small to pull the door open.");
  582. X        return(0);
  583. X    }
  584. X#endif
  585. X    /* door is known to be CLOSED */
  586. X    if (rnl(20) < (ACURRSTR+ACURR(A_DEX)+ACURR(A_CON))/3) {
  587. X        pline("The door opens.");
  588. X        if(door->doormask & D_TRAPPED) {
  589. X        b_trapped("door");
  590. X        door->doormask = D_NODOOR;
  591. X        } else
  592. X        door->doormask = D_ISOPEN;
  593. X        if (Blind)
  594. X        feel_location(x,y);    /* the hero knows she opened it  */
  595. X        else
  596. X        newsym(x,y);
  597. X        unblock_point(x,y);        /* vision: new see through there */
  598. X    } else {
  599. X        exercise(A_STR, TRUE);
  600. X        pline("The door resists!");
  601. X    }
  602. X
  603. X    return(1);
  604. X}
  605. X
  606. Xstatic
  607. Xboolean
  608. Xobstructed(x,y)
  609. Xregister int x, y;
  610. X{
  611. X    register struct monst *mtmp = m_at(x, y);
  612. X
  613. X    if(mtmp && mtmp->m_ap_type != M_AP_FURNITURE) {
  614. X        if (mtmp->m_ap_type == M_AP_OBJECT) goto objhere;
  615. X        pline("%s stands in the way!", Blind ?
  616. X            "Some creature" : Monnam(mtmp));
  617. X        return(TRUE);
  618. X    }
  619. X    if (OBJ_AT(x, y)) {
  620. Xobjhere:    pline("Something's in the way.");
  621. X        return(TRUE);
  622. X    }
  623. X    return(FALSE);
  624. X}
  625. X
  626. Xint
  627. Xdoclose()        /* try to close a door */
  628. X{
  629. X    register int x, y;
  630. X    register struct rm *door;
  631. X    struct monst *mtmp;
  632. X
  633. X    if (u.utrap && u.utraptype == TT_PIT) {
  634. X        You("can't reach over the edge of the pit.");
  635. X        return 0;
  636. X    }
  637. X
  638. X    if(!getdir(NULL)) return(0);
  639. X
  640. X    x = u.ux + u.dx;
  641. X    y = u.uy + u.dy;
  642. X    if((x == u.ux) && (y == u.uy)) {
  643. X        You("are in the way!");
  644. X        return(1);
  645. X    }
  646. X
  647. X    if ((mtmp = m_at(x,y))                &&
  648. X        mtmp->m_ap_type == M_AP_FURNITURE    && 
  649. X        (mtmp->mappearance == S_hcdoor ||
  650. X            mtmp->mappearance == S_vcdoor)    &&
  651. X        !Protection_from_shape_changers)     {
  652. X
  653. X        stumble_onto_mimic(mtmp);
  654. X        return(1);
  655. X    }
  656. X
  657. X    door = &levl[x][y];
  658. X
  659. X    if(!IS_DOOR(door->typ)) {
  660. X        if (door->typ == DRAWBRIDGE_DOWN)
  661. X            pline("There is no obvious way to close the drawbridge.");
  662. X        else
  663. X            You("%s no door there.",
  664. X                Blind ? "feel" : "see");
  665. X        return(0);
  666. X    }
  667. X
  668. X    if(door->doormask == D_NODOOR) {
  669. X        pline("This doorway has no door.");
  670. X        return(0);
  671. X    }
  672. X
  673. X    if(obstructed(x, y)) return(0);
  674. X
  675. X    if(door->doormask == D_BROKEN) {
  676. X        pline("This door is broken.");
  677. X        return(0);
  678. X    }
  679. X
  680. X    if(door->doormask & (D_CLOSED | D_LOCKED)) {
  681. X        pline("This door is already closed.");
  682. X        return(0);
  683. X    }
  684. X
  685. X    if(door->doormask == D_ISOPEN) {
  686. X#ifdef POLYSELF
  687. X        if(verysmall(uasmon)) {
  688. X         pline("You're too small to push the door closed.");
  689. X         return(0);
  690. X         }
  691. X#endif
  692. X        if (rn2(25) < (ACURRSTR+ACURR(A_DEX)+ACURR(A_CON))/3) {
  693. X        pline("The door closes.");
  694. X        door->doormask = D_CLOSED;
  695. X        if (Blind)
  696. X            feel_location(x,y);    /* the hero knows she closed it */
  697. X        else
  698. X            newsym(x,y);
  699. X        block_point(x,y);    /* vision:  no longer see there */
  700. X        }
  701. X        else {
  702. X            exercise(A_STR, TRUE);
  703. X            pline("The door resists!");
  704. X        }
  705. X    }
  706. X
  707. X    return(1);
  708. X}
  709. X
  710. Xboolean            /* box obj was hit with spell effect otmp */
  711. Xboxlock(obj, otmp)    /* returns true if something happened */
  712. Xregister struct obj *obj, *otmp;    /* obj *is* a box */
  713. X{
  714. X    register boolean res = 0;
  715. X
  716. X    switch(otmp->otyp) {
  717. X    case WAN_LOCKING:
  718. X    case SPE_WIZARD_LOCK:
  719. X        if (!obj->olocked) {    /* lock it; fix if broken */
  720. X        pline("Klunk!");
  721. X#if CONTAINER_BITS
  722. X        obj->lknown = 0;
  723. X        obj->oclosed = 1;
  724. X#endif
  725. X        obj->olocked = 1;
  726. X        obj->obroken = 0;
  727. X        res = 1;
  728. X        } /* else already closed and locked */
  729. X        break;
  730. X    case WAN_OPENING:
  731. X    case SPE_KNOCK:
  732. X        if (obj->olocked) {        /* unlock; couldn't be broken */
  733. X        pline("Klick!");
  734. X#if CONTAINER_BITS
  735. X        obj->lknown = 0;
  736. X#endif
  737. X        obj->olocked = 0;
  738. X        res = 1;
  739. X        } else            /* silently fix if broken */
  740. X        obj->obroken = 0;
  741. X#if CONTAINER_BITS
  742. X        obj->oclosed = 0;        /* now open, unconditionally */
  743. X#endif
  744. X        break;
  745. X    }
  746. X    return res;
  747. X}
  748. X
  749. Xboolean            /* Door/secret door was hit with spell effect otmp */
  750. Xdoorlock(otmp,x,y)    /* returns true if something happened */
  751. Xregister struct obj *otmp;
  752. Xint x, y;
  753. X{
  754. X    register struct rm *door = &levl[x][y];
  755. X    boolean res = 1;
  756. X    const char *msg = NULL;
  757. X
  758. X    if (door->typ == SDOOR) {
  759. X        if (otmp->otyp == WAN_OPENING || otmp->otyp == SPE_KNOCK) {
  760. X        door->typ = DOOR;
  761. X        door->doormask = D_CLOSED | (door->doormask & D_TRAPPED);
  762. X        if (cansee(x,y)) pline("A section of the wall opens up!");
  763. X        newsym(x,y);
  764. X        return(1);
  765. X        } else
  766. X        return(0);
  767. X    }
  768. X
  769. X    switch(otmp->otyp) {
  770. X    case WAN_LOCKING:
  771. X    case SPE_WIZARD_LOCK:
  772. X        if (obstructed(x,y)) return 0;
  773. X        switch (door->doormask & ~D_TRAPPED) {
  774. X        case D_CLOSED:
  775. X        msg = "The door locks!";
  776. X        break;
  777. X        case D_ISOPEN:
  778. X        msg = "The door swings shut, and locks!";
  779. X        break;
  780. X        case D_BROKEN:
  781. X        msg = "The broken door reassembles and locks!";
  782. X        break;
  783. X        case D_NODOOR:
  784. X        msg =
  785. X        "A cloud of dust springs up and assembles itself into a door!";
  786. X        break;
  787. X        default:
  788. X        res = 0;
  789. X        break;
  790. X        }
  791. X        block_point(x, y);
  792. X        door->doormask = D_LOCKED | (door->doormask & D_TRAPPED);
  793. X        newsym(x,y);
  794. X        break;
  795. X    case WAN_OPENING:
  796. X    case SPE_KNOCK:
  797. X        if (door->doormask & D_LOCKED) {
  798. X        msg = "The door unlocks!";
  799. X        door->doormask = D_CLOSED | (door->doormask & D_TRAPPED);
  800. X        } else res = 0;
  801. X        break;
  802. X    case WAN_STRIKING:
  803. X    case SPE_FORCE_BOLT:
  804. X        if (door->doormask & (D_LOCKED | D_CLOSED)) {
  805. X        if (door->doormask & D_TRAPPED) {
  806. X            if (MON_AT(x, y))
  807. X            (void) mb_trapped(m_at(x,y));
  808. X            else if (flags.verbose) {
  809. X            if (cansee(x,y))
  810. X                pline("KABOOM!!  You see a door explode.");
  811. X            else if (flags.soundok)
  812. X                You("hear a distant explosion.");
  813. X            }
  814. X            door->doormask = D_NODOOR;
  815. X            unblock_point(x,y);
  816. X            newsym(x,y);
  817. X            break;
  818. X        }
  819. X        door->doormask = D_BROKEN;
  820. X        if (flags.verbose) {
  821. X            if (cansee(x,y))
  822. X            pline("The door crashes open!");
  823. X            else if (flags.soundok)
  824. X            You("hear a crashing sound.");
  825. X        }
  826. X        unblock_point(x,y);
  827. X        newsym(x,y);
  828. X        } else res = 0;
  829. X        break;
  830. X    default: impossible("magic (%d) attempted on door.", otmp->otyp);
  831. X        break;
  832. X    }
  833. X    if (msg && cansee(x,y)) pline(msg);
  834. X    return res;
  835. X}
  836. X
  837. Xstatic void
  838. Xchest_shatter_msg(otmp)
  839. Xstruct obj *otmp;
  840. X{
  841. X    const char *disposition, *article = (otmp->quan > 1L) ? "A" : "The";
  842. X    char *thing;
  843. X    long save_Blinded;
  844. X
  845. X    if (otmp->oclass == POTION_CLASS) {
  846. X        You("%s a flask shatter!", Blind ? "hear" : "see");
  847. X        potionbreathe(otmp);
  848. X        return;
  849. X    }
  850. X    /* We have functions for distant and singular names, but not one */
  851. X    /* which does _both_... */
  852. X    save_Blinded = Blinded;
  853. X    Blinded = 1;
  854. X    thing = singular(otmp, xname);
  855. X    Blinded = save_Blinded;
  856. X    switch (objects[otmp->otyp].oc_material) {
  857. X    case PAPER:    disposition = "is torn to shreds";
  858. X        break;
  859. X    case WAX:    disposition = "is crushed";
  860. X        break;
  861. X    case VEGGY:    disposition = "is pulped";
  862. X        break;
  863. X    case FLESH:    disposition = "is mashed";
  864. X        break;
  865. X    case GLASS:    disposition = "shatters";
  866. X        break;
  867. X    case WOOD:    disposition = "splinters to fragments";
  868. X        break;
  869. X    default:    disposition = "is destroyed";
  870. X        break;
  871. X    }
  872. X    pline("%s %s %s!", article, thing, disposition);
  873. X}
  874. X
  875. X#endif /* OVLB */
  876. X
  877. X/*lock.c*/
  878. END_OF_FILE
  879. if test 19813 -ne `wc -c <'src/lock.c'`; then
  880.     echo shar: \"'src/lock.c'\" unpacked with wrong size!
  881. fi
  882. # end of 'src/lock.c'
  883. fi
  884. if test -f 'src/mhitu.c1' -a "${1}" != "-c" ; then 
  885.   echo shar: Will not clobber existing file \"'src/mhitu.c1'\"
  886. else
  887. echo shar: Extracting \"'src/mhitu.c1'\" \(33906 characters\)
  888. sed "s/^X//" >'src/mhitu.c1' <<'END_OF_FILE'
  889. X/*    SCCS Id: @(#)mhitu.c    3.1    92/12/10    */
  890. X/* Copyright (c) Stichting Mathematisch Centrum, Amsterdam, 1985. */
  891. X/* NetHack may be freely redistributed.  See license for details. */
  892. X
  893. X#include "hack.h"
  894. X#include "artifact.h"
  895. X
  896. XSTATIC_VAR struct obj NEARDATA *otmp;
  897. X
  898. X#ifdef POLYSELF
  899. XSTATIC_DCL void FDECL(urustm, (struct monst *, struct obj *));
  900. X# ifdef OVL1
  901. Xstatic int FDECL(passiveum, (struct permonst *,struct monst *,struct attack *));
  902. X# endif /* OVL1 */
  903. X#endif /* POLYSELF */
  904. X
  905. X#ifdef OVLB
  906. X# ifdef SEDUCE
  907. Xstatic void FDECL(mayberem, (struct obj *, const char *));
  908. X# endif
  909. X#endif /* OVLB */
  910. X
  911. XSTATIC_DCL boolean FDECL(diseasemu, (struct permonst *));
  912. XSTATIC_DCL int FDECL(hitmu, (struct monst *,struct attack *));
  913. XSTATIC_DCL int FDECL(gulpmu, (struct monst *,struct attack *));
  914. XSTATIC_DCL int FDECL(explmu, (struct monst *,struct attack *,BOOLEAN_P));
  915. XSTATIC_DCL int FDECL(gazemu, (struct monst *,struct attack *));
  916. XSTATIC_DCL void FDECL(missmu,(struct monst *,BOOLEAN_P,struct attack *));
  917. XSTATIC_DCL void FDECL(mswings,(struct monst *,struct obj *));
  918. XSTATIC_DCL void FDECL(wildmiss,(struct monst *));
  919. X
  920. XSTATIC_DCL void FDECL(hurtarmor,(struct permonst *,int));
  921. XSTATIC_DCL void FDECL(hitmsg,(struct monst *,struct attack *));
  922. X
  923. X/* See comment in mhitm.c.  If we use this a lot it probably should be */
  924. X/* changed to a parameter to mhitu. */
  925. Xstatic int dieroll;
  926. X
  927. X#ifdef OVL1
  928. X
  929. X
  930. XSTATIC_OVL void
  931. Xhitmsg(mtmp, mattk)
  932. Xregister struct monst *mtmp;
  933. Xregister struct attack *mattk;
  934. X{
  935. X    int compat;
  936. X
  937. X    /* Note: if opposite gender, "seductively" */
  938. X    /* If same gender, "engagingly" for nymph, normal msg for others */
  939. X    if((compat = could_seduce(mtmp, &youmonst, mattk))
  940. X            && !mtmp->mcan && !mtmp->mspec_used) {
  941. X            pline("%s %s you %s.", Monnam(mtmp),
  942. X            Blind ? "talks to" : "smiles at",
  943. X            compat == 2 ? "engagingly" : "seductively");
  944. X    } else
  945. X        switch (mattk->aatyp) {
  946. X        case AT_BITE:
  947. X            pline("%s bites!", Monnam(mtmp));
  948. X            break;
  949. X        case AT_KICK:
  950. X#ifdef POLYSELF
  951. X            pline("%s kicks%c", Monnam(mtmp), thick_skinned(uasmon) ? '.' : '!');
  952. X#else
  953. X            pline("%s kicks!", Monnam(mtmp));
  954. X#endif
  955. X            break;
  956. X        case AT_STNG:
  957. X            pline("%s stings!", Monnam(mtmp));
  958. X            break;
  959. X        case AT_BUTT:
  960. X            pline("%s butts!", Monnam(mtmp));
  961. X            break;
  962. X        case AT_TUCH:
  963. X            pline("%s touches you!", Monnam(mtmp));
  964. X            break;
  965. X        case AT_TENT:
  966. X            pline("%s tentacles suck you!", 
  967. X                        s_suffix(Monnam(mtmp)));
  968. X            break;
  969. X        case AT_EXPL:
  970. X            pline("%s explodes!", Monnam(mtmp));
  971. X            break;
  972. X        default:
  973. X            pline("%s hits!", Monnam(mtmp));
  974. X        }
  975. X}
  976. X
  977. XSTATIC_OVL void
  978. Xmissmu(mtmp, nearmiss, mattk)        /* monster missed you */
  979. Xregister struct monst *mtmp;
  980. Xregister boolean nearmiss;
  981. Xregister struct attack *mattk;
  982. X{
  983. X    if(could_seduce(mtmp, &youmonst, mattk) && !mtmp->mcan)
  984. X        pline("%s pretends to be friendly.", Monnam(mtmp));
  985. X    else {
  986. X        if (!flags.verbose || !nearmiss)
  987. X        pline("%s misses.", Monnam(mtmp));
  988. X        else
  989. X        pline("%s just misses!", Monnam(mtmp));
  990. X    }
  991. X}
  992. X
  993. XSTATIC_OVL void
  994. Xmswings(mtmp, otemp)        /* monster swings obj */
  995. Xregister struct monst *mtmp;
  996. Xregister struct obj *otemp;
  997. X{
  998. X    if (!flags.verbose || Blind || !mon_visible(mtmp) ||
  999. X        otemp->oclass != WEAPON_CLASS) return;
  1000. X    pline("%s %s %s %s.", Monnam(mtmp),
  1001. X          ((otemp->otyp >= SPEAR &&
  1002. X            otemp->otyp <= LANCE) ||
  1003. X           (otemp->otyp >= PARTISAN &&
  1004. X            otemp->otyp <= SPETUM) ||
  1005. X           otemp->otyp == TRIDENT) ? "thrusts" : "swings",
  1006. X          !humanoid(mtmp->data) ? "its" : mtmp->female ? "her" : "his",
  1007. X          xname(otemp));
  1008. X}
  1009. X
  1010. X#endif /* OVL1 */
  1011. X#ifdef OVLB
  1012. X
  1013. XSTATIC_OVL void
  1014. Xwildmiss(mtmp)        /* monster attacked your displaced image */
  1015. X    register struct monst *mtmp;
  1016. X{
  1017. X    int compat;
  1018. X
  1019. X    if (!flags.verbose) return;
  1020. X    if (!cansee(mtmp->mx, mtmp->my)) return;
  1021. X        /* maybe it's attacking an image around the corner? */
  1022. X
  1023. X    compat = could_seduce(mtmp, &youmonst, (struct attack *)0);
  1024. X        /* we really want to have the attack here to pass --
  1025. X         * the previous code checked whether mtmp was a nymph,
  1026. X         * which was not correct either since the attack type of
  1027. X         * succubi/incubi varies with SEDUCE
  1028. X         */
  1029. X
  1030. X    if(Invis && !perceives(mtmp->data)) {
  1031. X        if(compat)
  1032. X        pline("%s tries to touch you and misses!", Monnam(mtmp));
  1033. X        else
  1034. X        switch(rn2(3)) {
  1035. X        case 0: pline("%s %s wildly and misses!", Monnam(mtmp),
  1036. X                  nolimbs(mtmp->data) ? "lunges" : "swings");
  1037. X            break;
  1038. X        case 1: pline("%s attacks a spot beside you.", Monnam(mtmp));
  1039. X            break;
  1040. X        case 2: pline("%s strikes at %s!", Monnam(mtmp),
  1041. X                Underwater ? "empty water" : "thin air");
  1042. X            break;
  1043. X        default:pline("%s %s wildly!", Monnam(mtmp),
  1044. X                  nolimbs(mtmp->data) ? "lunges" : "swings");
  1045. X            break;
  1046. X        }
  1047. X    }
  1048. X    else if(Displaced) {
  1049. X        if(compat)
  1050. X        pline("%s smiles %s at your %sdisplaced image...",
  1051. X            Monnam(mtmp),
  1052. X            compat == 2 ? "engagingly" : "seductively",
  1053. X            Invis ? "invisible " : "");
  1054. X        else
  1055. X        pline("%s strikes at your %sdisplaced image and misses you!",
  1056. X            /* Note: if you're both invisible and displaced,
  1057. X             * only monsters which see invisible will attack your
  1058. X             * displaced image, since the displaced image is also
  1059. X             * invisible.
  1060. X             */
  1061. X            Monnam(mtmp),
  1062. X            Invis ? "invisible " : "");
  1063. X    }
  1064. X    /* monsters may miss especially on water level where
  1065. X       bubbles shake the player here and there */
  1066. X    else if(Underwater) {
  1067. X        if(compat)
  1068. X        pline("%s reaches towards your distorted image.",Monnam(mtmp));
  1069. X        else
  1070. X        pline("%s is fooled by water reflections and misses!",Monnam(mtmp));
  1071. X    }
  1072. X    else impossible("%s attacks you without knowing your location?",
  1073. X        Monnam(mtmp));
  1074. X}
  1075. X
  1076. Xvoid
  1077. Xexpels(mtmp, mdat, message)
  1078. Xregister struct monst *mtmp;
  1079. Xregister struct permonst *mdat; /* if mtmp is polymorphed, mdat != mtmp->data */
  1080. Xboolean message;
  1081. X{
  1082. X    if (message) 
  1083. X        if (is_animal(mdat)) 
  1084. X            You("get regurgitated!");
  1085. X        else {
  1086. X            char blast[40];
  1087. X            register int i;
  1088. X
  1089. X            blast[0] = '\0';
  1090. X            for(i = 0; i < NATTK; i++)
  1091. X                if(mdat->mattk[i].aatyp == AT_ENGL) 
  1092. X                    break;
  1093. X            if (mdat->mattk[i].aatyp != AT_ENGL)
  1094. X                  impossible("Swallower has no engulfing attack?"); 
  1095. X            else {
  1096. X                if (is_whirly(mdat)) {
  1097. X                    switch (mdat->mattk[i].adtyp) {
  1098. X                        case AD_ELEC:
  1099. X                            Strcpy(blast, 
  1100. X                              " in a shower of sparks");
  1101. X                            break;
  1102. X                        case AD_COLD:
  1103. X                            Strcpy(blast, 
  1104. X                            " in a blast of frost");
  1105. X                            break;
  1106. X                    }
  1107. X                } else
  1108. X                    Strcpy(blast, " with a squelch");
  1109. X                You("get expelled from %s%s!", 
  1110. X                    mon_nam(mtmp), blast);
  1111. X            }
  1112. X        }
  1113. X    unstuck(mtmp);    /* ball&chain returned in unstuck() */
  1114. X    mnexto(mtmp);
  1115. X    newsym(u.ux,u.uy);
  1116. X    spoteffects();
  1117. X    /* to cover for a case where mtmp is not in a next square */
  1118. X    if(um_dist(mtmp->mx,mtmp->my,1))
  1119. X        pline("Brrooaa...  You land hard at some distance.");
  1120. X}
  1121. X
  1122. X#endif /* OVLB */
  1123. X#ifdef OVL0
  1124. X
  1125. X/*
  1126. X * mattacku: monster attacks you
  1127. X *    returns 1 if monster dies (e.g. "yellow light"), 0 otherwise
  1128. X *    Note: if you're displaced or invisible the monster might attack the
  1129. X *        wrong position...
  1130. X *    Assumption: it's attacking you or an empty square; if there's another
  1131. X *        monster which it attacks by mistake, the caller had better
  1132. X *        take care of it...
  1133. X */
  1134. Xint
  1135. Xmattacku(mtmp)
  1136. X    register struct monst *mtmp;
  1137. X{
  1138. X    struct    attack    *mattk;
  1139. X    int    i, j, tmp, sum[NATTK];
  1140. X    struct    permonst *mdat = mtmp->data;
  1141. X    boolean ranged = (distu(mtmp->mx, mtmp->my) > 3);
  1142. X        /* Is it near you?  Affects your actions */
  1143. X    boolean range2 = !monnear(mtmp, mtmp->mux, mtmp->muy);
  1144. X        /* Does it think it's near you?  Affects its actions */
  1145. X    boolean foundyou = (mtmp->mux==u.ux && mtmp->muy==u.uy);
  1146. X        /* Is it attacking you or your image? */
  1147. X    boolean youseeit = canseemon(mtmp);
  1148. X        /* Might be attacking your image around the corner, or
  1149. X         * invisible, or you might be blind....
  1150. X         */
  1151. X
  1152. X    if(!ranged) nomul(0);
  1153. X    if(mtmp->mhp <= 0 || (Underwater && !is_swimmer(mtmp->data)))
  1154. X        return(0);
  1155. X
  1156. X    /* If swallowed, can only be affected by u.ustuck */
  1157. X    if(u.uswallow) {
  1158. X        if(mtmp != u.ustuck)
  1159. X        return(0);
  1160. X        u.ustuck->mux = u.ux;
  1161. X        u.ustuck->muy = u.uy;
  1162. X        range2 = 0;
  1163. X        foundyou = 1;
  1164. X        if(u.uinvulnerable) return (0); /* stomachs can't hurt you! */
  1165. X        /* This is not impossible! */
  1166. X        /* If the swallowing monster changes into a monster
  1167. X         * that is not capable of swallowing you, you get
  1168. X         * regurgitated - dgk
  1169. X         *
  1170. X         * This code is obsolete: newcham() will handle this contingency 
  1171. X         * as soon as it occurs in the course of a round. - kcd
  1172. X         *
  1173. X         * for(i = 0; i < NATTK; i++)
  1174. X         *     if(mdat->mattk[i].aatyp == AT_ENGL) goto doattack;
  1175. X         *
  1176. X         * You("get regurgitated!");
  1177. X         * regurgitates(mtmp);
  1178. X             * return(0);
  1179. X         */
  1180. X    }
  1181. X/* doattack:        use commented out above */
  1182. X#ifdef POLYSELF
  1183. X    if (u.uundetected && !range2 && foundyou && !u.uswallow) {
  1184. X        u.uundetected = 0;
  1185. X        if (is_hider(uasmon)) {
  1186. X            coord cc; /* maybe we need a unexto() function? */
  1187. X
  1188. X            You("fall from the ceiling!");
  1189. X            if (enexto(&cc, u.ux, u.uy, &playermon)) {
  1190. X            remove_monster(mtmp->mx, mtmp->my);
  1191. X            newsym(mtmp->mx,mtmp->my);
  1192. X            place_monster(mtmp, u.ux, u.uy);
  1193. X            if(mtmp->wormno) worm_move(mtmp);
  1194. X            teleds(cc.x, cc.y);
  1195. X            set_apparxy(mtmp);
  1196. X            newsym(u.ux,u.uy);
  1197. X            } else {
  1198. X            pline("%s is killed by a falling %s (you)!",
  1199. X                        Monnam(mtmp), uasmon->mname);
  1200. X            killed(mtmp);
  1201. X            newsym(u.ux,u.uy);
  1202. X            return(0);
  1203. X            }
  1204. X            if (u.usym != S_PIERCER)
  1205. X            return(0);    /* trappers don't attack */
  1206. X#ifdef MUSE
  1207. X            if (which_armor(mtmp, WORN_HELMET)) {
  1208. X#else
  1209. X            if (is_mercenary(mtmp->data) && m_carrying(mtmp,HELMET)) {
  1210. X#endif
  1211. X            Your("blow glances off %s helmet.", 
  1212. X                           s_suffix(mon_nam(mtmp)));
  1213. X            } else {
  1214. X            if (3 + find_mac(mtmp) <= rnd(20)) {
  1215. X                pline("%s is hit by a falling piercer (you)!",
  1216. X                                Monnam(mtmp));
  1217. X                if ((mtmp->mhp -= d(3,6)) < 1)
  1218. X                killed(mtmp);
  1219. X            } else
  1220. X              pline("%s is almost hit by a falling piercer (you)!",
  1221. X                                Monnam(mtmp));
  1222. X            }
  1223. X        } else {
  1224. X            if (!youseeit)
  1225. X            pline("It tries to move where you are hiding.");
  1226. X            else {
  1227. X            /* Ugly kludge for eggs.  The message is phrased so as
  1228. X             * to be directed at the monster, not the player,
  1229. X             * which makes "laid by you" wrong.  For the
  1230. X             * parallelism to work, we can't rephrase it, so we
  1231. X             * zap the "laid by you" momentarily instead.
  1232. X             */
  1233. X            struct obj *obj = level.objects[u.ux][u.uy];
  1234. X
  1235. X            if (obj) {
  1236. X                int save_spe = obj->spe;
  1237. X                if (obj->otyp == EGG) obj->spe = 0;
  1238. X         pline("Wait, %s!  There's a %s named %s hiding under %s!",
  1239. X                mtmp->mnamelth ? (const char *)NAME(mtmp)
  1240. X                           : mtmp->data->mname,
  1241. X                uasmon->mname, plname,
  1242. X                doname(level.objects[u.ux][u.uy]));
  1243. X                obj->spe = save_spe;
  1244. X            } else
  1245. X                impossible("hiding under nothing?");
  1246. X            }
  1247. X            newsym(u.ux,u.uy);
  1248. X        }
  1249. X        return(0);
  1250. X    }
  1251. X    if (u.usym == S_MIMIC_DEF && !range2 && foundyou && !u.uswallow) {
  1252. X        if (!youseeit) pline("It gets stuck on you.");
  1253. X            else pline("Wait, %s!  That's a %s named %s!",
  1254. X            mtmp->mnamelth ? (const char *)NAME(mtmp) : mtmp->data->mname,
  1255. X            uasmon->mname, plname);
  1256. X        u.ustuck = mtmp;
  1257. X        u.usym = S_MIMIC;
  1258. X        newsym(u.ux,u.uy);
  1259. X        return(0);
  1260. X    }
  1261. X#endif
  1262. X/*    Work out the armor class differential    */
  1263. X    tmp = u.uac + 10;        /* tmp ~= 0 - 20 */
  1264. X/*    give people with Ac < -9 at least some vulnerability */
  1265. X/*    negative AC gives an actual AC of somewhere from -1 to the AC */
  1266. X    if (tmp < 10) tmp = 10 - rnd(10-tmp);
  1267. X    tmp += mtmp->m_lev;
  1268. X    if(multi < 0) tmp += 4;
  1269. X    if((Invis && !perceives(mdat)) || !mtmp->mcansee)
  1270. X        tmp -= 2;
  1271. X    if(mtmp->mtrapped) tmp -= 2;
  1272. X    if(tmp <= 0) tmp = 1;
  1273. X
  1274. X    /* make eels visible the moment they hit/miss us */
  1275. X    if(mdat->mlet == S_EEL && mtmp->minvis && cansee(mtmp->mx,mtmp->my)) {
  1276. X        mtmp->minvis = 0;
  1277. X        newsym(mtmp->mx,mtmp->my);
  1278. X    }
  1279. X
  1280. X/*    Special demon handling code */
  1281. X    if(!mtmp->cham && is_demon(mdat) && !range2
  1282. X       && mtmp->data != &mons[PM_BALROG]
  1283. X       && mtmp->data != &mons[PM_SUCCUBUS]
  1284. X       && mtmp->data != &mons[PM_INCUBUS])
  1285. X        if(!mtmp->mcan && !rn2(13))    msummon(mdat);
  1286. X
  1287. X/*    Special lycanthrope handling code */
  1288. X    if(!mtmp->cham && is_were(mdat) && !range2) {
  1289. X
  1290. X        if(is_human(mdat)) {
  1291. X        if(!rn2(5 - (night() * 2)) && !mtmp->mcan) new_were(mtmp);
  1292. X        } else if(!rn2(30) && !mtmp->mcan) new_were(mtmp);
  1293. X
  1294. X        if(!rn2(10) && !mtmp->mcan) {
  1295. X        if(youseeit) {
  1296. X            pline("%s summons help!",youseeit ?
  1297. X                Monnam(mtmp) : "It");
  1298. X        } else
  1299. X            You("feel hemmed in.");
  1300. X        /* Technically wrong; we really should check if you can see the
  1301. X         * help, but close enough...
  1302. X         */
  1303. X        if (!were_summon(mdat,FALSE) && youseeit)
  1304. X            pline("But none comes.");
  1305. X        }
  1306. X    }
  1307. X
  1308. X    if(u.uinvulnerable) {
  1309. X        /* monster's won't attack you */
  1310. X        if(mtmp == u.ustuck)
  1311. X        pline("%s loosens its grip slightly.", Monnam(mtmp));
  1312. X        else if(!range2) {
  1313. X        if(youseeit)
  1314. X            pline("%s starts to attack you, but pulls back.",
  1315. X              Monnam(mtmp));
  1316. X        else
  1317. X            You("feel something move nearby.");
  1318. X        }
  1319. X        return (0);
  1320. X    }
  1321. X#ifdef MUSE
  1322. X    /* Unlike defensive stuff, don't let them use item _and_ attack. */
  1323. X    /* Exception:  Medusa; her gaze is automatic.  (We actually kludge
  1324. X     * by permitting a full attack sequence, not just a gaze attack.)
  1325. X     */
  1326. X    if(find_offensive(mtmp)) {
  1327. X        int foo = use_offensive(mtmp);
  1328. X
  1329. X        if (mtmp->data != &mons[PM_MEDUSA] && foo != 0) return(foo==1);
  1330. X    }
  1331. X#endif
  1332. X
  1333. X    for(i = 0; i < NATTK; i++) {
  1334. X
  1335. X        sum[i] = 0;
  1336. X        mattk = &(mdat->mattk[i]);
  1337. X        if (u.uswallow && (mattk->aatyp != AT_ENGL))
  1338. X        continue;
  1339. X        switch(mattk->aatyp) {
  1340. X        case AT_CLAW:    /* "hand to hand" attacks */
  1341. X        case AT_KICK:
  1342. X        case AT_BITE:
  1343. X        case AT_STNG:
  1344. X        case AT_TUCH:
  1345. X        case AT_BUTT:
  1346. X        case AT_TENT:
  1347. X            if(!range2) {
  1348. X                if (foundyou) {
  1349. X                if(tmp > (j = rnd(20+i))) {
  1350. X#ifdef POLYSELF
  1351. X                    if (mattk->aatyp != AT_KICK ||
  1352. X                        !thick_skinned(uasmon))
  1353. X#endif
  1354. X                    sum[i] = hitmu(mtmp, mattk);
  1355. X                } else
  1356. X                    missmu(mtmp, (tmp == j), mattk);
  1357. X                } else
  1358. X                wildmiss(mtmp);
  1359. X            }
  1360. X            break;
  1361. X
  1362. X        case AT_HUGS:    /* automatic if prev two attacks succeed */
  1363. X            /* Note: if displaced, prev attacks never succeeded */
  1364. X            if((!range2 && i>=2 && sum[i-1] && sum[i-2])
  1365. X                            || mtmp == u.ustuck)
  1366. X                sum[i]= hitmu(mtmp, mattk);
  1367. X            break;
  1368. X
  1369. X        case AT_GAZE:    /* can affect you either ranged or not */
  1370. X            if (youseeit)
  1371. X                /* not displaced around a corner so not visible */
  1372. X                sum[i] = gazemu(mtmp, mattk);
  1373. X            /* if gazemu returns, the player isn't dead.
  1374. X             * can't put this in gazemu() because youseeit might
  1375. X             * not be set
  1376. X             */
  1377. X            if(Reflecting && m_canseeu(mtmp) &&
  1378. X               !mtmp->mcan && mtmp->data == &mons[PM_MEDUSA]) {
  1379. X                if(!Blind) {
  1380. X                if(Reflecting & W_AMUL)
  1381. X                    makeknown(AMULET_OF_REFLECTION);
  1382. X                else
  1383. X                    makeknown(SHIELD_OF_REFLECTION);
  1384. X                pline("%s gaze is reflected by your %s.",
  1385. X                      s_suffix(Monnam(mtmp)),
  1386. X                      (Reflecting & W_AMUL) ?
  1387. X                      "medallion" : "shield");
  1388. X                pline("%s is turned to stone!", Monnam(mtmp));
  1389. X                }
  1390. X                stoned = TRUE;
  1391. X                killed(mtmp);
  1392. X                sum[i] = 2;
  1393. X            }
  1394. X            break;
  1395. X
  1396. X        case AT_EXPL:    /* automatic hit if next to, and aimed at you */
  1397. X            if(!range2) sum[i] = explmu(mtmp, mattk, foundyou);
  1398. X            break;
  1399. X
  1400. X        case AT_ENGL:
  1401. X            if (!range2) {
  1402. X                if(foundyou) {
  1403. X                if(u.uswallow || tmp > (j = rnd(20+i))) {
  1404. X                    /* Force swallowing monster to be
  1405. X                     * displayed even when player is
  1406. X                     * moving away */
  1407. X                    flush_screen(1);
  1408. X                    sum[i] = gulpmu(mtmp, mattk);
  1409. X                } else {
  1410. X                    missmu(mtmp, (tmp == j), mattk);
  1411. X                }
  1412. X                           } else if (is_animal(mtmp->data))
  1413. X                    pline("%s gulps some air!", youseeit ?
  1414. X                          Monnam(mtmp) : "It");
  1415. X                  else
  1416. X                    if (youseeit)
  1417. X                     pline("%s lunges forward and recoils!",
  1418. X                           Monnam(mtmp));
  1419. X                    else
  1420. X                        You("hear a %s nearby.", 
  1421. X                            is_whirly(mtmp->data)? 
  1422. X                            "rushing noise" : 
  1423. X                            "splat");
  1424. X            }
  1425. X            break;
  1426. X        case AT_BREA:
  1427. X            if(range2) sum[i] = breamu(mtmp, mattk);
  1428. X            /* Note: breamu takes care of displacement */
  1429. X            break;
  1430. X        case AT_SPIT:
  1431. X            if(range2) sum[i] = spitmu(mtmp, mattk);
  1432. X            /* Note: spitmu takes care of displacement */
  1433. X            break;
  1434. X        case AT_WEAP:
  1435. X            if(range2) {
  1436. X#ifdef REINCARNATION
  1437. X                if (!Is_rogue_level(&u.uz))
  1438. X#endif
  1439. X                    thrwmu(mtmp);
  1440. X            } else {
  1441. X#ifdef MUSE
  1442. X                /* Rare but not impossible.  Normally the monster
  1443. X                 * wields when 2 spaces away, but it can be
  1444. X                 * teleported or whatever....
  1445. X                 */
  1446. X                if (mtmp->weapon_check == NEED_WEAPON || !MON_WEP(mtmp)) {
  1447. X                mtmp->weapon_check = NEED_HTH_WEAPON;
  1448. X                /* mon_wield_item resets weapon_check as appropriate */
  1449. X                if (mon_wield_item(mtmp) != 0) break;
  1450. X                }
  1451. X#endif
  1452. X                if (foundyou) {
  1453. X                set_uasmon();
  1454. X#ifdef MUSE
  1455. X                otmp = MON_WEP(mtmp);
  1456. X#else
  1457. X                otmp = select_hwep(mtmp);
  1458. X#endif
  1459. X                if(otmp) {
  1460. X                    tmp += hitval(otmp, uasmon);
  1461. X                    mswings(mtmp, otmp);
  1462. X                }
  1463. X                if(tmp > (j = dieroll = rnd(20+i)))
  1464. X                    sum[i] = hitmu(mtmp, mattk);
  1465. X                else
  1466. X                    missmu(mtmp, (tmp == j), mattk);
  1467. X                } else
  1468. X                wildmiss(mtmp);
  1469. X            }
  1470. X            break;
  1471. X        case AT_MAGC:
  1472. X            if (range2)
  1473. X                sum[i] = buzzmu(mtmp, mattk);
  1474. X            else
  1475. X                if (foundyou)
  1476. X                sum[i] = castmu(mtmp, mattk);
  1477. X                else
  1478. X                pline("%s casts a spell at thin air!",
  1479. X                    youseeit ? Monnam(mtmp) : "It");
  1480. X                /* Not totally right since castmu allows other
  1481. X                 * spells, such as the monster healing itself,
  1482. X                 * that should work even when not next to you--
  1483. X                 * but the previous code was just as wrong.
  1484. X                 * --KAA
  1485. X                 */
  1486. X            break;
  1487. X
  1488. X        default:        /* no attack */
  1489. X            break;
  1490. X        }
  1491. X        if(flags.botl) bot();
  1492. X        if(sum[i] == 2)  return(1);      /* attacker dead */
  1493. X        if(sum[i] == 3) break;  /* attacker teleported, no more attacks */
  1494. X        /* sum[i] == 1: successful attack */
  1495. X        /* sum[i] == 0: unsuccessful attack */
  1496. X    }
  1497. X    return(0);
  1498. X}
  1499. X
  1500. X#endif /* OVL0 */
  1501. X#ifdef OVLB
  1502. X
  1503. X/*
  1504. X * helper function for some compilers that have trouble with hitmu
  1505. X */
  1506. X
  1507. XSTATIC_OVL void
  1508. Xhurtarmor(mdat, attk)
  1509. Xstruct permonst *mdat;
  1510. Xint attk;
  1511. X{
  1512. X    boolean getbronze, rusting;
  1513. X    int    hurt;
  1514. X
  1515. X    rusting = (attk == AD_RUST);
  1516. X    if (rusting) {
  1517. X        hurt = 1;
  1518. X        getbronze = (mdat == &mons[PM_BLACK_PUDDING] &&
  1519. X                 uarm && is_corrodeable(uarm));
  1520. X    }
  1521. X    else {
  1522. X        hurt=2;
  1523. X        getbronze = FALSE;
  1524. X    }
  1525. X    /* What the following code does: it keeps looping until it
  1526. X     * finds a target for the rust monster.
  1527. X     * Head, feet, etc... not covered by metal, or covered by
  1528. X     * rusty metal, are not targets.  However, your body always
  1529. X     * is, no matter what covers it.
  1530. X     */
  1531. X    while (1) {
  1532. X        switch(rn2(5)) {
  1533. X        case 0:
  1534. X        if (!rust_dmg(uarmh, rusting ? "helmet" : "leather helmet",
  1535. X                     hurt, FALSE))
  1536. X            continue;
  1537. X        break;
  1538. X        case 1:
  1539. X        if (uarmc) break;
  1540. X        /* Note the difference between break and continue;
  1541. X         * break means it was hit and didn't rust; continue
  1542. X         * means it wasn't a target and though it didn't rust
  1543. X         * something else did.
  1544. X         */
  1545. X        if (getbronze)
  1546. X            (void)rust_dmg(uarm, "bronze armor", 3, TRUE);
  1547. X        else if (uarm)
  1548. X            (void)rust_dmg(uarm, xname(uarm), hurt, TRUE);
  1549. X        break;
  1550. X        case 2:
  1551. X        if (!rust_dmg(uarms, rusting ? "shield" : "wooden shield",
  1552. X                     hurt, FALSE))
  1553. X            continue;
  1554. X        break;
  1555. X        case 3:
  1556. X        if (!rust_dmg(uarmg, rusting ? "metal gauntlets" : "gloves",
  1557. X                     hurt, FALSE))
  1558. X            continue;
  1559. X        break;
  1560. X        case 4:
  1561. X        if (!rust_dmg(uarmf, rusting ? "metal boots" : "boots",
  1562. X                     hurt, FALSE))
  1563. X            continue;
  1564. X        break;
  1565. X        }
  1566. X        break; /* Out of while loop */
  1567. X    }
  1568. X}
  1569. X
  1570. X#endif /* OVLB */
  1571. X#ifdef OVL1
  1572. X
  1573. XSTATIC_OVL boolean
  1574. Xdiseasemu(mdat)
  1575. Xstruct permonst *mdat;
  1576. X{
  1577. X    if (defends(AD_DISE,uwep)
  1578. X#ifdef POLYSELF
  1579. X            || u.usym == S_FUNGUS
  1580. X#endif
  1581. X                        ) {
  1582. X        You("feel a slight illness.");
  1583. X        return FALSE;
  1584. X    } else {
  1585. X        if (!Sick) You("feel very sick.");
  1586. X        exercise(A_CON, FALSE);
  1587. X        make_sick(Sick + (long)rn1(25-ACURR(A_CON),15),FALSE);
  1588. X        u.usick_cause = mdat->mname;
  1589. X        return TRUE;
  1590. X    }
  1591. X}
  1592. X
  1593. X/*
  1594. X * hitmu: monster hits you
  1595. X *      returns 2 if monster dies (e.g. "yellow light"), 1 otherwise
  1596. X *      3 if the monster lives but teleported/paralyzed, so it can't keep
  1597. X *           attacking you
  1598. X */
  1599. XSTATIC_OVL int
  1600. Xhitmu(mtmp, mattk)
  1601. X    register struct monst *mtmp;
  1602. X    register struct attack  *mattk;
  1603. X{
  1604. X    register struct permonst *mdat = mtmp->data;
  1605. X    register int ctmp, ptmp;
  1606. X    int dmg, armpro;
  1607. X    char     buf[BUFSZ];
  1608. X#ifdef POLYSELF
  1609. X    struct permonst *olduasmon = uasmon;
  1610. X    int res;
  1611. X#endif
  1612. X
  1613. X/*    If the monster is undetected & hits you.  You should know where
  1614. X *    the attack came from.
  1615. X */
  1616. X    if(mtmp->mundetected && hides_under(mdat)) {
  1617. X        mtmp->mundetected = 0;
  1618. X        if(!(Blind ? Telepat : (HTelepat & (WORN_HELMET|WORN_AMUL)))) {
  1619. X        register struct obj *obj;
  1620. X
  1621. X        if(OBJ_AT(mtmp->mx, mtmp->my)) {
  1622. X            if((obj = level.objects[mtmp->mx][mtmp->my]) != 0)
  1623. X            pline("%s was hidden under %s!",
  1624. X                  Amonnam(mtmp), doname(obj));
  1625. X        }
  1626. X        newsym(mtmp->mx, mtmp->my);
  1627. X        }
  1628. X    }
  1629. X
  1630. X/*    First determine the base damage done */
  1631. X    dmg = d((int)mattk->damn, (int)mattk->damd);
  1632. X    if(is_undead(mdat) && midnight())
  1633. X        dmg += d((int)mattk->damn, (int)mattk->damd); /* extra damage */
  1634. X
  1635. X/*    Next a cancellation factor    */
  1636. X/*    Use ctmp when the cancellation factor takes into account certain
  1637. X *    armor's special magic protection.  Otherwise just use !mtmp->mcan.
  1638. X */
  1639. X    armpro = 0;
  1640. X    if (uarm && armpro < objects[uarm->otyp].a_can)
  1641. X        armpro = objects[uarm->otyp].a_can;
  1642. X    if (uarmc && armpro < objects[uarmc->otyp].a_can)
  1643. X        armpro = objects[uarmc->otyp].a_can;
  1644. X    ctmp = !mtmp->mcan && ((rn2(3) >= armpro) || !rn2(50));
  1645. X
  1646. X/*    Now, adjust damages via resistances or specific attacks */
  1647. X    switch(mattk->adtyp) {
  1648. X        case AD_PHYS:
  1649. X        if(mattk->aatyp == AT_HUGS
  1650. X#ifdef POLYSELF
  1651. X                       && !sticks(uasmon)
  1652. X#endif
  1653. X                                ) {
  1654. X            if(!u.ustuck && rn2(2)) {
  1655. X            u.ustuck = mtmp;
  1656. X            pline("%s grabs you!", Monnam(mtmp));
  1657. X            } else if(u.ustuck == mtmp) {
  1658. X                exercise(A_STR, FALSE);
  1659. X            You("are being %s.",
  1660. X                  (mtmp->data == &mons[PM_ROPE_GOLEM])
  1661. X                  ? "choked" : "crushed");
  1662. X            }
  1663. X        } else {              /* hand to hand weapon */
  1664. X            if(mattk->aatyp == AT_WEAP && otmp) {
  1665. X            dmg += dmgval(otmp, uasmon);
  1666. X            if (dmg <= 0) dmg = 1;
  1667. X            if (!(otmp->oartifact &&
  1668. X                artifact_hit(mtmp, &youmonst, otmp, &dmg,dieroll)))
  1669. X                 hitmsg(mtmp, mattk);
  1670. X#ifdef POLYSELF
  1671. X            if (u.mh > 1 && u.mh > ((u.uac>0) ? dmg : dmg+u.uac) &&
  1672. X                    (u.umonnum==PM_BLACK_PUDDING
  1673. X                    || u.umonnum==PM_BROWN_PUDDING)) {
  1674. X                /* This redundancy necessary because you have to
  1675. X                 * take the damage _before_ being cloned.
  1676. X                 */
  1677. X                if (u.uac < 0) dmg += u.uac;
  1678. X                if (dmg < 1) dmg = 1;
  1679. X                if (dmg > 1) exercise(A_STR, FALSE);
  1680. X                u.mh -= dmg;
  1681. X                flags.botl = 1;
  1682. X                dmg = 0;
  1683. X                if(cloneu())
  1684. X                You("divide as %s hits you!",mon_nam(mtmp));
  1685. X            }
  1686. X            urustm(mtmp, otmp);
  1687. X#endif
  1688. X            } else
  1689. X            hitmsg(mtmp, mattk);
  1690. X        }
  1691. X        break;
  1692. X        case AD_DISE:
  1693. X        hitmsg(mtmp, mattk);
  1694. X        if (!diseasemu(mdat)) dmg = 0;
  1695. X        break;
  1696. X        case AD_FIRE:
  1697. X        hitmsg(mtmp, mattk);
  1698. X        if(ctmp) {
  1699. X            pline("You're on fire!");
  1700. X            if (Fire_resistance) {
  1701. X            pline("The fire doesn't feel hot!");
  1702. X            dmg = 0;
  1703. X            }
  1704. X            if((int) mtmp->m_lev > rn2(20))
  1705. X            destroy_item(SCROLL_CLASS, AD_FIRE);
  1706. X            if((int) mtmp->m_lev > rn2(20))
  1707. X            destroy_item(POTION_CLASS, AD_FIRE);
  1708. X            if((int) mtmp->m_lev > rn2(25))
  1709. X            destroy_item(SPBOOK_CLASS, AD_FIRE);
  1710. X        } else dmg = 0;
  1711. X        break;
  1712. X        case AD_COLD:
  1713. X        hitmsg(mtmp, mattk);
  1714. X        if(ctmp) {
  1715. X            pline("You're covered in frost!");
  1716. X            if (Cold_resistance) {
  1717. X            pline("The frost doesn't seem cold!");
  1718. X            dmg = 0;
  1719. X            }
  1720. X            if((int) mtmp->m_lev > rn2(20))
  1721. X            destroy_item(POTION_CLASS, AD_COLD);
  1722. X        } else dmg = 0;
  1723. X        break;
  1724. X        case AD_ELEC:
  1725. X        hitmsg(mtmp, mattk);
  1726. X        if(ctmp) {
  1727. X            You("get zapped!");
  1728. X            if (Shock_resistance) {
  1729. X            pline("The zap doesn't shock you!");
  1730. X            dmg = 0;
  1731. X            }
  1732. X            if((int) mtmp->m_lev > rn2(20))
  1733. X            destroy_item(WAND_CLASS, AD_ELEC);
  1734. X            if((int) mtmp->m_lev > rn2(20))
  1735. X            destroy_item(RING_CLASS, AD_ELEC);
  1736. X        } else dmg = 0;
  1737. X        break;
  1738. X        case AD_SLEE:
  1739. X        hitmsg(mtmp, mattk);
  1740. X        if(ctmp && multi >= 0 && !rn2(5)) {
  1741. X            if (Sleep_resistance) break;
  1742. X            nomul(-rnd(10));
  1743. X            u.usleep = 1;
  1744. X            nomovemsg = "You wake up.";
  1745. X            if (Blind)    You("are put to sleep!");
  1746. X            else    You("are put to sleep by %s!",mon_nam(mtmp));
  1747. X        }
  1748. X        break;
  1749. X        case AD_DRST:
  1750. X        ptmp = A_STR;
  1751. X        goto dopois;
  1752. X        case AD_DRDX:
  1753. X        ptmp = A_DEX;
  1754. X        goto dopois;
  1755. X        case AD_DRCO:
  1756. X        ptmp = A_CON;
  1757. Xdopois:
  1758. X        hitmsg(mtmp, mattk);
  1759. X        if(ctmp && !rn2(8)) {
  1760. X            Sprintf(buf, "%s %s",
  1761. X                !(canseemon(mtmp) || sensemon(mtmp)) ? "Its" :
  1762. X                Hallucination ? s_suffix(rndmonnam()) : 
  1763. X                                s_suffix(mdat->mname),
  1764. X                (mattk->aatyp == AT_BITE) ? "bite" : "sting");
  1765. X            poisoned(buf, ptmp, mdat->mname, 30);
  1766. X        }
  1767. X        break;
  1768. X        case AD_DRIN:
  1769. X        hitmsg(mtmp, mattk);
  1770. X        if (defends(AD_DRIN, uwep)
  1771. X#ifdef POLYSELF
  1772. X                    || !has_head(uasmon)
  1773. X#endif
  1774. X                                ) {
  1775. X            You("don't seem harmed.");
  1776. X            break;
  1777. X        }
  1778. X        if (uarmh && rn2(8)) {
  1779. X            Your("helmet blocks the attack to your head.");
  1780. X            break;
  1781. X        }
  1782. X        if (Half_physical_damage) dmg = (dmg+1) / 2;
  1783. X        losehp(dmg, mon_nam(mtmp), KILLED_BY_AN);
  1784. X        Your("brain is eaten!");
  1785. X        /* No such thing as mindless players... */
  1786. X        if (ABASE(A_INT) <= ATTRMIN(A_INT)) {
  1787. X            int lifesaved = 0;
  1788. X            while(1) {
  1789. X            if (lifesaved)
  1790. X                pline("Unfortunately your brain is still gone.");
  1791. X            else
  1792. X                Your("last thought fades away.");
  1793. X            killer = "brainlessness";
  1794. X            killer_format = KILLED_BY;
  1795. X            done(DIED);
  1796. X            lifesaved = 1;
  1797. X#ifdef WIZARD
  1798. X            if (wizard) break;
  1799. X#endif
  1800. X            }
  1801. X        }
  1802. X        (void) adjattrib(A_INT, -rnd(2), FALSE);
  1803. X        exercise(A_WIS, FALSE);
  1804. X        break;
  1805. X        case AD_PLYS:
  1806. X        hitmsg(mtmp, mattk);
  1807. X        if(ctmp && multi >= 0 && !rn2(3)) {
  1808. X            if (Blind)    You("are frozen!");
  1809. X            else    You("are frozen by %s!", mon_nam(mtmp));
  1810. X            nomul(-rnd(10));
  1811. X            exercise(A_DEX, FALSE);
  1812. X        }
  1813. X        break;
  1814. X        case AD_DRLI:
  1815. X        hitmsg(mtmp, mattk);
  1816. X        if (ctmp && !rn2(3)
  1817. X#ifdef POLYSELF
  1818. X            && !resists_drli(uasmon)
  1819. X#endif
  1820. X            && !defends(AD_DRLI, uwep)
  1821. X            ) losexp();
  1822. X        break;
  1823. X        case AD_LEGS:
  1824. X        { register long side = rn2(2) ? RIGHT_SIDE : LEFT_SIDE;
  1825. X          if (mtmp->mcan) {
  1826. X            pline("%s nuzzles against your %s %s!", Monnam(mtmp),
  1827. X              (side == RIGHT_SIDE) ? "right" : "left",
  1828. X              body_part(LEG));
  1829. X          } else {
  1830. X            if (uarmf) {
  1831. X            pline("%s scratches your %s boot!", Monnam(mtmp),
  1832. X                (side == RIGHT_SIDE) ? "right" : "left");
  1833. X            break;
  1834. X            }
  1835. X            pline("%s pricks your %s %s!", Monnam(mtmp),
  1836. X              (side == RIGHT_SIDE) ? "right" : "left",
  1837. X              body_part(LEG));
  1838. X            set_wounded_legs(side, rnd(60-ACURR(A_DEX)));
  1839. X            exercise(A_STR, FALSE);
  1840. X            exercise(A_DEX, FALSE);
  1841. X          }
  1842. X          break;
  1843. X        }
  1844. X        case AD_STON:    /* at present only a cockatrice */
  1845. X        hitmsg(mtmp, mattk);
  1846. X        if(!rn2(3) && !Stoned) {
  1847. X            if (mtmp->mcan) {
  1848. X            if (flags.soundok)
  1849. X                You("hear a cough from %s!", mon_nam(mtmp));
  1850. X            } else {
  1851. X            if (flags.soundok)
  1852. X                You("hear %s hissing!", s_suffix(mon_nam(mtmp)));
  1853. X            if((!rn2(10) ||
  1854. X                (flags.moonphase == NEW_MOON && !have_lizard()))
  1855. X#ifdef POLYSELF
  1856. X                && !resists_ston(uasmon)
  1857. X                && !(poly_when_stoned(uasmon) &&
  1858. X                 polymon(PM_STONE_GOLEM))
  1859. X#endif
  1860. X                ) {
  1861. X                Stoned = 5;
  1862. X                return(1);
  1863. X                /* You("turn to stone..."); */
  1864. X                /* done_in_by(mtmp); */
  1865. X            }
  1866. X            }
  1867. X        }
  1868. X        break;
  1869. X        case AD_STCK:
  1870. X        hitmsg(mtmp, mattk);
  1871. X        if(ctmp && !u.ustuck
  1872. X#ifdef POLYSELF
  1873. X                     && !sticks(uasmon)
  1874. X#endif
  1875. X                            ) u.ustuck = mtmp;
  1876. X        break;
  1877. X        case AD_WRAP:
  1878. X        if(ctmp
  1879. X#ifdef POLYSELF
  1880. X            && !sticks(uasmon)
  1881. X#endif
  1882. X                      ) {
  1883. X            if(!u.ustuck && !rn2(10)) {
  1884. X            pline("%s swings itself around you!", Monnam(mtmp));
  1885. X            u.ustuck = mtmp;
  1886. X            } else if(u.ustuck == mtmp) {
  1887. X            if (is_pool(mtmp->mx,mtmp->my)
  1888. X#ifdef POLYSELF
  1889. X                && !is_swimmer(uasmon)
  1890. X#endif
  1891. X                && !Magical_breathing
  1892. X               ) {
  1893. X                pline("%s drowns you....", Monnam(mtmp));
  1894. X                done(DROWNING);
  1895. X            } else if(mattk->aatyp == AT_HUGS)
  1896. X                You("are being crushed.");
  1897. X            } else {
  1898. X            dmg = 0;
  1899. X            if(flags.verbose)
  1900. X                pline("%s brushes against your %s.", Monnam(mtmp),
  1901. X                   body_part(LEG));
  1902. X            }
  1903. X        } else dmg = 0;
  1904. X        break;
  1905. X        case AD_WERE:
  1906. X        hitmsg(mtmp, mattk);
  1907. X#ifdef POLYSELF
  1908. X        if (ctmp && !rn2(4) && u.ulycn == -1
  1909. X            && !Protection_from_shape_changers
  1910. X            && !defends(AD_WERE,uwep)) {
  1911. X            You("feel feverish.");
  1912. X            exercise(A_CON, FALSE);
  1913. X            u.ulycn = monsndx(mdat);
  1914. X        }
  1915. X#endif
  1916. X        break;
  1917. X        case AD_SGLD:
  1918. X        hitmsg(mtmp, mattk);
  1919. X#ifdef POLYSELF
  1920. X        if (u.usym == mdat->mlet) break;
  1921. X#endif
  1922. X        if(!mtmp->mcan) stealgold(mtmp);
  1923. X        break;
  1924. X
  1925. X        case AD_SITM:    /* for now these are the same */
  1926. X        case AD_SEDU:
  1927. X#ifdef POLYSELF
  1928. X        if (dmgtype(uasmon, AD_SEDU)
  1929. X#  ifdef SEDUCE
  1930. X            || dmgtype(uasmon, AD_SSEX)
  1931. X#  endif
  1932. X                        ) {
  1933. X            if (mtmp->minvent)
  1934. X    pline("%s brags about the goods some dungeon explorer provided.",
  1935. X    Monnam(mtmp));
  1936. X            else
  1937. X    pline("%s makes some remarks about how difficult theft is lately.",
  1938. X    Monnam(mtmp));
  1939. X            rloc(mtmp);
  1940. X            return 3;
  1941. X        } else
  1942. X#endif
  1943. X        if(mtmp->mcan) {
  1944. X            if (!Blind) {
  1945. X            pline("%s tries to %s you, but you seem %s.",
  1946. X                Adjmonnam(mtmp, "plain"),
  1947. X                flags.female ? "charm" : "seduce",
  1948. X                flags.female ? "unaffected" : "uninterested");
  1949. X            }
  1950. X            if(rn2(3)) {
  1951. X            rloc(mtmp);
  1952. X            return 3;
  1953. X            }
  1954. X        } else {
  1955. X            switch (steal(mtmp)) {
  1956. X              case -1:
  1957. X            return 2;
  1958. X              case 0:
  1959. X            break;
  1960. X              default:
  1961. X            rloc(mtmp);
  1962. X            mtmp->mflee = 1;
  1963. X            return 3;
  1964. X            }
  1965. X        }
  1966. X        break;
  1967. X#ifdef SEDUCE
  1968. X        case AD_SSEX:
  1969. X        if(could_seduce(mtmp, &youmonst, mattk) == 1
  1970. X            && !mtmp->mcan)
  1971. X            if (doseduce(mtmp))
  1972. X            return 3;
  1973. X        break;
  1974. X#endif
  1975. X        case AD_SAMU:
  1976. X        hitmsg(mtmp, mattk);
  1977. X        /* when the Wiz hits, 1/20 steals the amulet */
  1978. X        if (!u.uhave.amulet) break;
  1979. X        if (!rn2(20)) stealamulet(mtmp);
  1980. X        break;
  1981. X
  1982. X        case AD_TLPT:
  1983. X        hitmsg(mtmp, mattk);
  1984. X        if(ctmp) {
  1985. X            if(flags.verbose)
  1986. X            Your("position suddenly seems very uncertain!");
  1987. X            tele();
  1988. X        }
  1989. X        break;
  1990. X        case AD_RUST:
  1991. X        hitmsg(mtmp, mattk);
  1992. X        if (mtmp->mcan) break;
  1993. X#if defined(POLYSELF)
  1994. X        if (u.umonnum == PM_IRON_GOLEM) {
  1995. X            You("rust!");
  1996. X            rehumanize();
  1997. X            break;
  1998. X        }
  1999. X#endif
  2000. X        hurtarmor(mdat, AD_RUST);
  2001. X        break;
  2002. X        case AD_DCAY:
  2003. X        hitmsg(mtmp, mattk);
  2004. X        if (mtmp->mcan) break;
  2005. X#if defined(POLYSELF)
  2006. X        if (u.umonnum == PM_WOOD_GOLEM ||
  2007. X            u.umonnum == PM_LEATHER_GOLEM) {
  2008. X            You("rot!");
  2009. X            rehumanize();
  2010. X            break;
  2011. X        }
  2012. X#endif
  2013. X        hurtarmor(mdat, AD_DCAY);
  2014. X        break;
  2015. X        case AD_HEAL:
  2016. X        if(!uwep
  2017. X#ifdef TOURIST
  2018. X           && !uarmu
  2019. X#endif
  2020. X           && !uarm && !uarmh && !uarms && !uarmg && !uarmc && !uarmf) {
  2021. X            pline("%s hits!  (I hope you don't mind.)", Monnam(mtmp));
  2022. X#ifdef POLYSELF
  2023. X            if (u.mtimedone) {
  2024. X                u.mh += rnd(7);
  2025. X                if(!rn2(7)) u.mhmax++;
  2026. X                if(u.mh > u.mhmax) u.mh = u.mhmax;
  2027. X                if(u.mh == u.mhmax && !rn2(50)) mongone(mtmp);
  2028. X            } else {
  2029. X#endif
  2030. X                u.uhp += rnd(7);
  2031. X                if(!rn2(7)) u.uhpmax++;
  2032. X                if(u.uhp > u.uhpmax) u.uhp = u.uhpmax;
  2033. X                if(u.uhp == u.uhpmax && !rn2(50)) mongone(mtmp);
  2034. X#ifdef POLYSELF
  2035. X            }
  2036. X#endif
  2037. X                exercise(A_STR, TRUE);
  2038. X                exercise(A_CON, TRUE);
  2039. X            flags.botl = 1;
  2040. X            if(!rn2(50)) rloc(mtmp);
  2041. X            dmg = 0;
  2042. X        } else
  2043. X            if(pl_character[0] == 'H') {
  2044. X                if (flags.soundok && !(moves % 5))
  2045. X                verbalize("Doc, I can't help you unless you cooperate.");
  2046. X                dmg = 0;
  2047. X            } else hitmsg(mtmp, mattk);
  2048. X        break;
  2049. X        case AD_CURS:
  2050. X        hitmsg(mtmp, mattk);
  2051. X        if(!night() && mdat == &mons[PM_GREMLIN]) break;
  2052. X        if(!mtmp->mcan && !rn2(10)) {
  2053. X            if (flags.soundok)
  2054. X            if (Blind) You("hear laughter.");
  2055. X            else       pline("%s chuckles.", Monnam(mtmp));
  2056. X#ifdef POLYSELF
  2057. X            if (u.umonnum == PM_CLAY_GOLEM) {
  2058. X            pline("Some writing vanishes from your head!");
  2059. X            rehumanize();
  2060. X            break;
  2061. X            }
  2062. X#endif
  2063. X            attrcurse();
  2064. X        }
  2065. X        break;
  2066. X        case AD_STUN:
  2067. X        hitmsg(mtmp, mattk);
  2068. X        if(!mtmp->mcan && !rn2(4)) {
  2069. X            make_stunned(HStun + dmg, TRUE);
  2070. X            dmg /= 2;
  2071. X        }
  2072. X        break;
  2073. X        case AD_ACID:
  2074. X        hitmsg(mtmp, mattk);
  2075. X        if(!mtmp->mcan && !rn2(3))
  2076. X#ifdef POLYSELF
  2077. X            if (resists_acid(uasmon)) {
  2078. X            pline("You're covered in acid, but it seems harmless.");
  2079. X            dmg = 0;
  2080. X            } else
  2081. X#endif
  2082. X              {
  2083. X            pline("You're covered in acid!    It burns!");
  2084. X            exercise(A_STR, FALSE);
  2085. X              }
  2086. X        else        dmg = 0;
  2087. X        break;
  2088. X        case AD_SLOW:
  2089. X        hitmsg(mtmp, mattk);
  2090. X        if(!ctmp && (Fast & (INTRINSIC|TIMEOUT)) &&
  2091. X                    !defends(AD_SLOW, uwep) && !rn2(4)) {
  2092. X            Fast &= ~(INTRINSIC|TIMEOUT);
  2093. X            You("feel yourself slowing down.");
  2094. X            exercise(A_DEX, FALSE);
  2095. X        }
  2096. X        break;
  2097. X        case AD_DREN:
  2098. X        hitmsg(mtmp, mattk);
  2099. X        if(!ctmp && !rn2(4)) drain_en(dmg);
  2100. X        dmg = 0;
  2101. X        break;
  2102. X        case AD_CONF:
  2103. X        hitmsg(mtmp, mattk);
  2104. X        if(!mtmp->mcan && !rn2(4) && !mtmp->mspec_used) {
  2105. X            mtmp->mspec_used = mtmp->mspec_used + (dmg + rn2(6));
  2106. X            if(Confusion)
  2107. X             You("are getting even more confused.");
  2108. X            else You("are getting confused.");
  2109. X            make_confused(HConfusion + dmg, FALSE);
  2110. X        }
  2111. X        /* fall through to next case */
  2112. X        case AD_DETH:
  2113. X        pline("%s reaches out with its deadly touch.", Monnam(mtmp));
  2114. X#ifdef POLYSELF
  2115. X        if (is_undead(uasmon)) {
  2116. X            /* Still does normal damage */
  2117. X            pline("Was that the touch of death?");
  2118. X            break;
  2119. X        }
  2120. X#endif
  2121. X        if(!Antimagic && rn2(20) > 16)  {
  2122. X            killer_format = KILLED_BY_AN;
  2123. X            killer = "touch of death";
  2124. X            done(DIED);
  2125. X        } else {
  2126. X            if(!rn2(5)) {
  2127. X            if(Antimagic) shieldeff(u.ux, u.uy);
  2128. X            pline("Lucky for you, it didn't work!");
  2129. X            dmg = 0;
  2130. X            } else You("feel your life force draining away...");
  2131. X        }
  2132. X        break;
  2133. X        case AD_PEST:
  2134. X        pline("%s reaches out, and you feel fever and chills.",
  2135. X            Monnam(mtmp));
  2136. X        (void) diseasemu(mdat); /* plus the normal damage */
  2137. X        break;
  2138. X        case AD_FAMN:
  2139. X        pline("%s reaches out, and your body shrivels.",
  2140. X            Monnam(mtmp));
  2141. X        exercise(A_CON, FALSE);
  2142. X        morehungry(rn1(40,40));
  2143. X        /* plus the normal damage */
  2144. X        break;
  2145. X        default:    dmg = 0;
  2146. X            break;
  2147. X    }
  2148. X    if(u.uhp < 1) done_in_by(mtmp);
  2149. X
  2150. X/*    Negative armor class reduces damage done instead of fully protecting
  2151. X *    against hits.
  2152. X */
  2153. X    if (dmg && u.uac < 0) {
  2154. X        dmg -= rnd(-u.uac);
  2155. X        if (dmg < 1) dmg = 1;
  2156. X    }
  2157. X
  2158. X    if(dmg) {
  2159. X        if(Half_physical_damage)
  2160. X        dmg = (dmg+1) / 2;
  2161. X#ifdef MULDGN
  2162. X        else if(pl_character[0] == 'P' && uwep && is_quest_artifact(uwep)
  2163. X            && is_undead(mtmp->data))
  2164. X        dmg = (dmg+1) / 2;
  2165. X#endif
  2166. X        mdamageu(mtmp, dmg);
  2167. X    }
  2168. X
  2169. X#ifdef POLYSELF
  2170. X    res = passiveum(olduasmon, mtmp, mattk);
  2171. X    stop_occupation();
  2172. X    return res;
  2173. X#else
  2174. X    stop_occupation();
  2175. X    return 1;
  2176. X#endif
  2177. X}
  2178. X
  2179. X#endif /* OVL1 */
  2180. END_OF_FILE
  2181. if test 33906 -ne `wc -c <'src/mhitu.c1'`; then
  2182.     echo shar: \"'src/mhitu.c1'\" unpacked with wrong size!
  2183. fi
  2184. # end of 'src/mhitu.c1'
  2185. fi
  2186. echo shar: End of archive 56 \(of 108\).
  2187. cp /dev/null ark56isdone
  2188. MISSING=""
  2189. for I in 1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 \
  2190. 21 22 23 24 25 26 27 28 29 30 31 32 33 34 35 36 37 38 39 40 \
  2191. 41 42 43 44 45 46 47 48 49 50 51 52 53 54 55 56 57 58 59 60 \
  2192. 61 62 63 64 65 66 67 68 69 70 71 72 73 74 75 76 77 78 79 80 \
  2193. 81 82 83 84 85 86 87 88 89 90 91 92 93 94 95 96 97 98 99 100 \
  2194. 101 102 103 104 105 106 107 108 ; do
  2195.     if test ! -f ark${I}isdone ; then
  2196.     MISSING="${MISSING} ${I}"
  2197.     fi
  2198. done
  2199. if test "${MISSING}" = "" ; then
  2200.     echo You have unpacked all 108 archives.
  2201.     echo "Now execute 'rebuild.sh'"
  2202.     rm -f ark10[0-8]isdone ark[1-9]isdone ark[1-9][0-9]isdone
  2203. else
  2204.     echo You still need to unpack the following archives:
  2205.     echo "        " ${MISSING}
  2206. fi
  2207. ##  End of shell archive.
  2208. exit 0
  2209.