home *** CD-ROM | disk | FTP | other *** search
/ Celestin Apprentice 2 / Apprentice-Release2.iso / Source Code / C / Games / NetHack 3.1.3 / source / src / mthrowu.c < prev    next >
Encoding:
C/C++ Source or Header  |  1993-08-01  |  15.0 KB  |  592 lines  |  [TEXT/R*ch]

  1. /*    SCCS Id: @(#)mthrowu.c    3.1    93/02/14    */
  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_DCL void FDECL(drop_throw,(struct obj *,BOOLEAN_P,int,int));
  8. #ifndef MUSE
  9. STATIC_DCL void FDECL(m_throw,(struct monst *,int,int,int,int,int,struct obj *));
  10. #endif
  11.  
  12. #define URETREATING(x,y) (distmin(u.ux,u.uy,x,y) > distmin(u.ux0,u.uy0,x,y))
  13.  
  14. boolean FDECL(lined_up, (struct monst *));
  15.  
  16. #ifndef OVLB
  17.  
  18. STATIC_DCL const char *breathwep[];
  19.  
  20. #else /* OVLB */
  21.  
  22. /*
  23.  * Keep consistent with breath weapons in zap.c, and AD_* in monattk.h.
  24.  */
  25. STATIC_OVL NEARDATA const char *breathwep[] = {
  26.                 "fragments",
  27.                 "fire",
  28.                 "frost",
  29.                 "sleep gas",
  30.                 "death",
  31.                 "lightning",
  32.                 "poison gas",
  33.                 "acid",
  34.                 "strange breath #8",
  35.                 "strange breath #9"
  36. };
  37.  
  38. int
  39. thitu(tlev, dam, obj, name)    /* u is hit by sth, but not a monster */
  40.     register int tlev, dam;
  41.     struct obj *obj;
  42.     register const char *name;
  43. {
  44.     const char *onm = (obj && obj_is_pname(obj)) ? the(name) : an(name);
  45.     boolean is_acid = (obj && obj->otyp == ACID_VENOM);
  46.  
  47.     if(u.uac + tlev <= rnd(20)) {
  48.         if(Blind || !flags.verbose) pline("It misses.");
  49.         else You("are almost hit by %s!", onm);
  50.         return(0);
  51.     } else {
  52.         if(Blind || !flags.verbose) You("are hit!");
  53.         else You("are hit by %s!", onm);
  54. #ifdef POLYSELF
  55.         if (obj && objects[obj->otyp].oc_material == SILVER
  56.                 && hates_silver(uasmon)) {
  57.             dam += rnd(20);
  58.             pline("The silver sears your flesh!");
  59.             exercise(A_CON, FALSE);
  60.         }
  61.         if (is_acid && resists_acid(uasmon))
  62.             pline("It doesn't seem to hurt you.");
  63.         else {
  64. #endif
  65.             if (is_acid) pline("It burns!");
  66.             if (Half_physical_damage) dam = (dam+1) / 2;
  67.             losehp(dam, name, (obj && obj_is_pname(obj)) ?
  68.                    KILLED_BY : KILLED_BY_AN);
  69.             exercise(A_STR, FALSE);
  70. #ifdef POLYSELF
  71.         }
  72. #endif
  73.         return(1);
  74.     }
  75. }
  76.  
  77. /* Be sure this corresponds with what happens to player-thrown objects in
  78.  * dothrow.c (for consistency). --KAA
  79.  */
  80.  
  81. STATIC_OVL void
  82. drop_throw(obj, ohit, x, y)
  83. register struct obj *obj;
  84. boolean ohit;
  85. int x,y;
  86. {
  87.     int create;
  88.     struct monst *mtmp;
  89.     struct trap *t;
  90.  
  91.     if (obj->otyp == CREAM_PIE || obj->oclass == VENOM_CLASS)
  92.         create = 0;
  93.     else if (ohit &&
  94.          ((obj->otyp >= ARROW && obj->otyp <= SHURIKEN) ||
  95.           obj->otyp == ROCK))
  96.         create = !rn2(3);
  97.     else create = 1;
  98.  
  99.     if (create && !((mtmp = m_at(x, y)) && (mtmp->mtrapped) && 
  100.             (t = t_at(x, y)) && ((t->ttyp == PIT) || 
  101.             (t->ttyp == SPIKED_PIT)))) {
  102.         if (!flooreffects(obj,x,y,"fall")) { /* don't double-dip on damage */
  103.         place_object(obj, x, y);
  104.         obj->nobj = fobj;
  105.         fobj = obj;
  106.         stackobj(fobj);
  107.         }
  108.     } else obfree(obj, (struct obj*) 0);
  109. }
  110.  
  111. #endif /* OVLB */
  112. #ifdef OVL1
  113.  
  114. #ifndef MUSE
  115. STATIC_OVL
  116. #endif
  117. void
  118. m_throw(mon, x, y, dx, dy, range, obj)
  119.     register struct monst *mon;
  120.     register int x,y,dx,dy,range;        /* direction and range */
  121.     register struct obj *obj;
  122. {
  123.     register struct monst *mtmp;
  124.     struct obj *singleobj;
  125.     char sym = obj->oclass;
  126.     int damage;
  127.     int hitu, blindinc=0;
  128.  
  129.     bhitpos.x = x;
  130.     bhitpos.y = y;
  131.  
  132.     singleobj = splitobj(obj, obj->quan - 1L);
  133.     /* splitobj leaves the new object in the chain (i.e. the monster's
  134.      * inventory).  Remove it.  We can do this in 1 line, but it's highly
  135.      * dependent on the fact that we know splitobj() places it immediately
  136.      * after obj.
  137.      */
  138.     obj->nobj = singleobj->nobj;
  139.     /* Get rid of object.  This cannot be done later on; what if the
  140.      * player dies before then, leaving the monster with 0 daggers?
  141.      * (This caused the infamous 2^32-1 orcish dagger bug).
  142.      */
  143.     if (!obj->quan) {
  144.         if(obj->oclass == VENOM_CLASS) {
  145.         /* venom is not in the monster's inventory chain */
  146.         dealloc_obj(obj);
  147.         } else {
  148. #ifdef MUSE
  149.         /* not possibly_unwield, which checks the object's */
  150.         /* location, not its existence */
  151.         if (MON_WEP(mon) == obj) {
  152.             obj->owornmask &= ~W_WEP;
  153.             MON_NOWEP(mon);
  154.         }
  155. #endif
  156.         m_useup(mon, obj);
  157.         }
  158.     }
  159. #ifdef MUSE
  160.     singleobj->owornmask = 0; /* threw one of multiple weapons in hand? */
  161. #endif
  162.  
  163.     if (singleobj->cursed && (dx || dy) && !rn2(7)) {
  164.         if(canseemon(mon) && flags.verbose) {
  165.         if((singleobj->oclass == WEAPON_CLASS ||
  166.                         singleobj->oclass == GEM_CLASS)
  167.            && objects[singleobj->otyp].w_propellor)
  168.             pline("%s misfires!", Monnam(mon));
  169.         else
  170.             pline("%s slips as %s throws it!",
  171.               The(xname(singleobj)), mon_nam(mon));
  172.         }
  173.         dx = rn2(3)-1;
  174.         dy = rn2(3)-1;
  175.         /* pre-check validity of new direction */
  176.         if((!dx && !dy)
  177.            || !isok(bhitpos.x+dx,bhitpos.y+dy)
  178.            /* missile hits the wall */
  179.            || IS_WALL(levl[bhitpos.x+dx][bhitpos.y+dy].typ)
  180.            || levl[bhitpos.x+dx][bhitpos.y+dy].typ == SDOOR
  181.            || levl[bhitpos.x+dx][bhitpos.y+dy].typ == SCORR) {
  182.         drop_throw(singleobj, 0, bhitpos.x, bhitpos.y);
  183.         return;
  184.         }
  185.     }
  186.  
  187.     /* Note: drop_throw may destroy singleobj.  Since obj must be destroyed
  188.      * early to avoid the dagger bug, anyone who modifies this code should
  189.      * be careful not to use either one after it's been freed.
  190.      */
  191.     if (sym) tmp_at(DISP_FLASH, obj_to_glyph(singleobj));
  192.     while(range-- > 0) { /* Actually the loop is always exited by break */
  193.         boolean vis;
  194.  
  195.         bhitpos.x += dx;
  196.         bhitpos.y += dy;
  197.         vis = cansee(bhitpos.x, bhitpos.y);
  198.         if(MON_AT(bhitpos.x, bhitpos.y)) {
  199.             boolean ismimic;
  200.  
  201.             mtmp = m_at(bhitpos.x,bhitpos.y);
  202.             ismimic = mtmp->m_ap_type &&
  203.             mtmp->m_ap_type != M_AP_MONSTER;
  204.  
  205.             /* don't use distance/size modifiers since target was u */
  206.             if(find_mac(mtmp) + 8 + singleobj->spe <= rnd(20)) {
  207.             if (!ismimic) {
  208.                 if (!vis) pline("It is missed.");
  209.                 else miss(distant_name(singleobj,xname), mtmp);
  210.             }
  211.             if (!range) { /* Last position; object drops */
  212.                 drop_throw(singleobj, 0, mtmp->mx, mtmp->my);
  213.                 break;
  214.             }
  215. #ifdef MUSE
  216.             } else if (singleobj->oclass == POTION_CLASS) {
  217.             if (ismimic) seemimic(mtmp);
  218.             if (vis) singleobj->dknown = 1;
  219.             potionhit(mtmp, singleobj);
  220.             break;
  221. #endif
  222.             } else {
  223.             damage = dmgval(singleobj, mtmp->data);
  224.             if (damage < 1) damage = 1;
  225.             if (singleobj->otyp==ACID_VENOM && resists_acid(mtmp->data))
  226.                 damage = 0;
  227.             if (ismimic) seemimic(mtmp);
  228.             if (!vis) pline("It is hit%s", exclam(damage));
  229.             else hit(distant_name(singleobj,xname),
  230.                             mtmp,exclam(damage));
  231.             if (singleobj->opoisoned) {
  232.                 if (resists_poison(mtmp->data)) {
  233.                 if (vis)
  234.                   pline("The poison doesn't seem to affect %s.",
  235.                                 mon_nam(mtmp));
  236.                 } else {
  237.                 if (rn2(30)) damage += rnd(6);
  238.                 else {
  239.                     if (vis)
  240.                     pline("The poison was deadly...");
  241.                     damage = mtmp->mhp;
  242.                 }
  243.                 }
  244.             }
  245.             if (objects[singleobj->otyp].oc_material == SILVER
  246.                 && hates_silver(mtmp->data)) {
  247.                 if (vis) pline("The silver sears %s's flesh!",
  248.                 mon_nam(mtmp));
  249.                 else pline("Its flesh is seared!");
  250.             }
  251.             if (singleobj->otyp==ACID_VENOM && cansee(mtmp->mx,mtmp->my)){
  252.                 if (resists_acid(mtmp->data)) {
  253.                 pline("%s is unaffected.", vis ? Monnam(mtmp)
  254.                     : "It");
  255.                 damage = 0;
  256.                 } else if (vis)
  257.                 pline("The acid burns %s!", mon_nam(mtmp));
  258.                 else pline("It is burned!");
  259.             }
  260.             mtmp->mhp -= damage;
  261.             if(mtmp->mhp < 1) {
  262.                 pline("%s is %s!", vis ? Monnam(mtmp) : "It",
  263.                    (is_demon(mtmp->data) || 
  264.                     is_undead(mtmp->data) || !vis) ?
  265.                  "destroyed" : "killed");
  266.                 mondied(mtmp);
  267.             }
  268.  
  269.             if(((singleobj->otyp == CREAM_PIE) ||
  270.                 (singleobj->otyp == BLINDING_VENOM))
  271.                && haseyes(mtmp->data)) {
  272.                 if (vis)
  273.                 pline("%s is blinded by %s.",
  274.                       Monnam(mtmp), the(xname(singleobj)));
  275.                 if(mtmp->msleep) mtmp->msleep = 0;
  276.                 mtmp->mcansee = 0;
  277.                 {
  278.                 register unsigned rnd_tmp = rnd(25) + 20;
  279.                 if((mtmp->mblinded + rnd_tmp) > 127)
  280.                     mtmp->mblinded = 127;
  281.                 else mtmp->mblinded += rnd_tmp;
  282.                 }
  283.             }
  284.             drop_throw(singleobj, 1, bhitpos.x, bhitpos.y);
  285.             break;
  286.             }
  287.         }
  288.         if (bhitpos.x == u.ux && bhitpos.y == u.uy) {
  289.             if (multi) nomul(0);
  290.  
  291. #ifdef MUSE
  292.             if (singleobj->oclass == POTION_CLASS) {
  293.                 if (!Blind) singleobj->dknown = 1;
  294.                 potionhit(&youmonst, singleobj);
  295.                 break;
  296.             }
  297. #endif
  298.             switch(singleobj->otyp) {
  299.                 int dam, hitv;
  300.                 case CREAM_PIE:
  301.                 case BLINDING_VENOM:
  302.                 hitu = thitu(8, 0, singleobj, xname(singleobj));
  303.                 break;
  304.                 default:
  305.                 dam = dmgval(singleobj, uasmon);
  306.                 hitv = 3 - distmin(u.ux,u.uy, mon->mx,mon->my);
  307.                 if (hitv < -4) hitv = -4;
  308.                 if (is_elf(mon->data) &&
  309.                     objects[singleobj->otyp].w_propellor
  310.                                 == WP_BOW) {
  311.                     hitv++;
  312. #ifdef MUSE
  313.                     if (MON_WEP(mon) &&
  314.                     MON_WEP(mon)->otyp == ELVEN_BOW)
  315.                     hitv++;
  316. #endif
  317.                     if(singleobj->otyp == ELVEN_ARROW) dam++;
  318.                 }
  319. #ifdef POLYSELF
  320.                 if (bigmonst(uasmon)) hitv++;
  321. #endif
  322.                 hitv += 8+singleobj->spe;
  323.  
  324.                 if (dam < 1) dam = 1;
  325.                 hitu = thitu(hitv, dam,
  326.                     singleobj, xname(singleobj));
  327.             }
  328.             if (hitu && singleobj->opoisoned)
  329.                 /* it's safe to call xname twice because it's the
  330.                    same object both times... */
  331.                 poisoned(xname(singleobj), A_STR, xname(singleobj), 10);
  332.             if(hitu && (singleobj->otyp == CREAM_PIE ||
  333.                      singleobj->otyp == BLINDING_VENOM)) {
  334.                 blindinc = rnd(25);
  335.                 if(singleobj->otyp == CREAM_PIE) {
  336.                 if(!Blind) pline("Yecch!  You've been creamed.");
  337.                 else    pline("There's something sticky all over your %s.", body_part(FACE));
  338.                 } else {    /* venom in the eyes */
  339.                 if(Blindfolded) /* nothing */ ;
  340.                 else if(!Blind) pline("The venom blinds you.");
  341.                 else    Your("%s sting.",
  342.                     makeplural(body_part(EYE)));
  343.                 }
  344.             }
  345.             stop_occupation();
  346.             if (hitu || !range) {
  347.                 drop_throw(singleobj, hitu, u.ux, u.uy);
  348.                 break;
  349.             }
  350.         } else if (!range    /* reached end of path */
  351.             /* missile hits edge of screen */
  352.             || !isok(bhitpos.x+dx,bhitpos.y+dy)
  353.             /* missile hits the wall */
  354.             || IS_WALL(levl[bhitpos.x+dx][bhitpos.y+dy].typ)
  355.             || levl[bhitpos.x+dx][bhitpos.y+dy].typ == SDOOR
  356.             || levl[bhitpos.x+dx][bhitpos.y+dy].typ == SCORR
  357. #ifdef SINKS
  358.             /* Thrown objects "sink" */
  359.             || IS_SINK(levl[bhitpos.x][bhitpos.y].typ)
  360. #endif
  361.                                 ) {
  362.             drop_throw(singleobj, 0, bhitpos.x, bhitpos.y);
  363.             break;
  364.         }
  365.         tmp_at(bhitpos.x, bhitpos.y);
  366.         delay_output();
  367.     }
  368.     tmp_at(bhitpos.x, bhitpos.y);
  369.     delay_output();
  370.     tmp_at(DISP_END, 0);
  371.     /* blindfold keeps substances out of your eyes */
  372.     if (blindinc && !Blindfolded) {
  373.         u.ucreamed += blindinc;
  374.         make_blinded(Blinded + blindinc,FALSE);
  375.     }
  376. }
  377.  
  378. #endif /* OVL1 */
  379. #ifdef OVLB
  380.  
  381. /* Remove an item from the monster's inventory.
  382.  */
  383. void
  384. m_useup(mon, obj)
  385. struct monst *mon;
  386. struct obj *obj;
  387. {
  388.     struct obj *otmp, *prev;
  389.  
  390.     if (obj->quan > 1L) {
  391.         obj->quan--;
  392.         return;
  393.     }
  394.     prev = ((struct obj *) 0);
  395.     for (otmp = mon->minvent; otmp; otmp = otmp->nobj) {
  396.         if (otmp == obj) {
  397.             if (prev)
  398.                 prev->nobj = obj->nobj;
  399.             else
  400.                 mon->minvent = obj->nobj;
  401.             dealloc_obj(obj);
  402.             break;
  403.         }
  404.         prev = otmp;
  405.     }
  406. #ifdef MUSE
  407.     possibly_unwield(mon);
  408. #endif
  409. }
  410.  
  411. #endif /* OVLB */
  412. #ifdef OVL1
  413.  
  414. void
  415. thrwmu(mtmp)    /* monster throws item at you */
  416. register struct monst *mtmp;
  417. {
  418.     struct obj *otmp;
  419.     register xchar x, y;
  420.  
  421.     if(lined_up(mtmp)) {
  422. #ifdef MUSE
  423.         if (mtmp->weapon_check == NEED_WEAPON || !MON_WEP(mtmp)) {
  424.         mtmp->weapon_check = NEED_RANGED_WEAPON;
  425.         /* mon_wield_item resets weapon_check as appropriate */
  426.         if(mon_wield_item(mtmp) != 0) return;
  427.         }
  428. #endif
  429.         if((otmp = select_rwep(mtmp))) {
  430.         /* If you are coming toward the monster, the monster
  431.          * should try to soften you up with missiles.  If you are
  432.          * going away, you are probably hurt or running.  Give
  433.          * chase, but if you are getting too far away, throw.
  434.          */
  435.         x = mtmp->mx;
  436.         y = mtmp->my;
  437.         if(!URETREATING(x,y) ||
  438.            !rn2(BOLT_LIM-distmin(x,y,mtmp->mux,mtmp->muy)))
  439.         {
  440.             const char *verb = "throws";
  441.  
  442.             if (otmp->otyp == ARROW
  443.             || otmp->otyp == ELVEN_ARROW
  444.             || otmp->otyp == ORCISH_ARROW
  445.             || otmp->otyp == CROSSBOW_BOLT) verb = "shoots";
  446.             if (canseemon(mtmp)) {
  447.             pline("%s %s %s!", Monnam(mtmp), verb,
  448.                   obj_is_pname(otmp) ?
  449.                   the(singular(otmp, xname)) :
  450.                   an(singular(otmp, xname)));
  451.             }
  452.             m_throw(mtmp, mtmp->mx, mtmp->my, sgn(tbx), sgn(tby), 
  453.             distmin(mtmp->mx,mtmp->my,mtmp->mux,mtmp->muy), otmp);
  454.             nomul(0);
  455.             return;
  456.         }
  457.         }
  458.     }
  459. }
  460.  
  461. #endif /* OVL1 */
  462. #ifdef OVLB
  463.  
  464. int
  465. spitmu(mtmp, mattk)        /* monster spits substance at you */
  466. register struct monst *mtmp;
  467. register struct attack *mattk;
  468. {
  469.     register struct obj *otmp;
  470.  
  471.     if(mtmp->mcan) {
  472.  
  473.         if(flags.soundok)
  474.         pline("A dry rattle comes from %s throat", 
  475.                               s_suffix(mon_nam(mtmp)));
  476.         return 0;
  477.     }
  478.     if(lined_up(mtmp)) {
  479.         switch (mattk->adtyp) {
  480.             case AD_BLND:
  481.             case AD_DRST:
  482.             otmp = mksobj(BLINDING_VENOM, TRUE, FALSE);
  483.             break;
  484.             default:
  485.             impossible("bad attack type in spitmu");
  486.                 /* fall through */
  487.             case AD_ACID:
  488.             otmp = mksobj(ACID_VENOM, TRUE, FALSE);
  489.             break;
  490.         }
  491.         if(!rn2(BOLT_LIM-distmin(mtmp->mx,mtmp->my,mtmp->mux,mtmp->muy))) {
  492.             if (canseemon(mtmp))
  493.             pline("%s spits venom!", Monnam(mtmp));
  494.             m_throw(mtmp, mtmp->mx, mtmp->my, sgn(tbx), sgn(tby), 
  495.             distmin(mtmp->mx,mtmp->my,mtmp->mux,mtmp->muy), otmp);
  496.             nomul(0);
  497.             return 0;
  498.         }
  499.     }
  500.     return 0;
  501. }
  502.  
  503. #endif /* OVLB */
  504. #ifdef OVL1
  505.  
  506. int
  507. breamu(mtmp, mattk)            /* monster breathes at you (ranged) */
  508.     register struct monst *mtmp;
  509.     register struct attack  *mattk;
  510. {
  511.     /* if new breath types are added, change AD_ACID to max type */
  512.     int typ = (mattk->adtyp == AD_RBRE) ? rnd(AD_ACID) : mattk->adtyp ;
  513.  
  514.     if(lined_up(mtmp)) {
  515.  
  516.         if(mtmp->mcan) {
  517.         if(flags.soundok) {
  518.             if(canseemon(mtmp))
  519.             pline("%s coughs.", Monnam(mtmp));
  520.             else
  521.             You("hear a cough.");
  522.         }
  523.         return(0);
  524.         }
  525.         if(!mtmp->mspec_used && rn2(3)) {
  526.  
  527.         if((typ >= AD_MAGM) && (typ <= AD_ACID)) {
  528.  
  529.             if(canseemon(mtmp))
  530.             pline("%s breathes %s!", Monnam(mtmp),
  531.                   breathwep[typ-1]);
  532.             buzz((int) (-20 - (typ-1)), (int)mattk->damn,
  533.              mtmp->mx, mtmp->my, sgn(tbx), sgn(tby));
  534.             nomul(0);
  535.             /* breath runs out sometimes. Also, give monster some
  536.              * cunning; don't breath if the player fell asleep.
  537.              */
  538.             if(!rn2(3))
  539.             mtmp->mspec_used = 10+rn2(20);
  540.             if(typ == AD_SLEE && !Sleep_resistance)
  541.             mtmp->mspec_used += rnd(20);
  542.         } else impossible("Breath weapon %d used", typ-1);
  543.         }
  544.     }
  545.     return(1);
  546. }
  547.  
  548. boolean
  549. linedup(ax, ay, bx, by)
  550. register xchar ax, ay, bx, by;
  551. {
  552.     tbx = ax - bx;    /* These two values are set for use */
  553.     tby = ay - by;    /* after successful return.        */
  554.  
  555.     if((!tbx || !tby || abs(tbx) == abs(tby)) /* straight line or diagonal */
  556.        && distmin(tbx, tby, 0, 0) < BOLT_LIM) {
  557.  
  558.         if(ax == u.ux && ay == u.uy) return((boolean)(couldsee(bx,by)));
  559.         else if(clear_path(ax,ay,bx,by)) return TRUE;
  560.     }
  561.     return FALSE;
  562. }
  563.  
  564. boolean
  565. lined_up(mtmp)        /* is mtmp in position to use ranged attack? */
  566.     register struct monst *mtmp;
  567. {
  568.     return(linedup(mtmp->mux,mtmp->muy,mtmp->mx,mtmp->my));
  569. }
  570.  
  571. #endif /* OVL1 */
  572. #ifdef OVL0
  573.  
  574. /* Check if a monster is carrying a particular item.
  575.  */
  576. struct obj *
  577. m_carrying(mtmp, type)
  578. struct monst *mtmp;
  579. int type;
  580. {
  581.     register struct obj *otmp;
  582.  
  583.     for(otmp = mtmp->minvent; otmp; otmp = otmp->nobj)
  584.         if(otmp->otyp == type)
  585.             return(otmp);
  586.     return((struct obj *) 0);
  587. }
  588.  
  589. #endif /* OVL0 */
  590.  
  591. /*mthrowu.c*/
  592.