home *** CD-ROM | disk | FTP | other *** search
/ OS/2 Shareware BBS: 10 Tools / 10-Tools.zip / HACKSRC.ZIP / FIGHT.C < prev    next >
C/C++ Source or Header  |  1985-10-16  |  10KB  |  383 lines

  1. /* Copyright (c) Stichting Mathematisch Centrum, Amsterdam, 1985. */
  2. /* fight.c - version 1.0.3 */
  3.  
  4. #include    <stdio.h>
  5. #include    "hack.h"
  6. extern struct permonst li_dog, dog, la_dog;
  7. extern char *exclam(), *xname();
  8. extern struct obj *mkobj_at();
  9.  
  10. static boolean far_noise;
  11. static long noisetime;
  12.  
  13. /* hitmm returns 0 (miss), 1 (hit), or 2 (kill) */
  14. hitmm(magr,mdef) register struct monst *magr,*mdef; {
  15. register struct permonst *pa = magr->data, *pd = mdef->data;
  16. int hit;
  17. schar tmp;
  18. boolean vis;
  19.     if(index("Eauy", pa->mlet)) return(0);
  20.     if(magr->mfroz) return(0);        /* riv05!a3 */
  21.     tmp = pd->ac + pa->mlevel;
  22.     if(mdef->mconf || mdef->mfroz || mdef->msleep){
  23.         tmp += 4;
  24.         if(mdef->msleep) mdef->msleep = 0;
  25.     }
  26.     hit = (tmp > rnd(20));
  27.     if(hit) mdef->msleep = 0;
  28.     vis = (cansee(magr->mx,magr->my) && cansee(mdef->mx,mdef->my));
  29.     if(vis){
  30.         char buf[BUFSZ];
  31.         if(mdef->mimic) seemimic(mdef);
  32.         if(magr->mimic) seemimic(magr);
  33.         (void) sprintf(buf,"%s %s", Monnam(magr),
  34.             hit ? "hits" : "misses");
  35.         pline("%s %s.", buf, monnam(mdef));
  36.     } else {
  37.         boolean far = (dist(magr->mx, magr->my) > 15);
  38.         if(far != far_noise || moves-noisetime > 10) {
  39.             far_noise = far;
  40.             noisetime = moves;
  41.             pline("You hear some noises%s.",
  42.                 far ? " in the distance" : "");
  43.         }
  44.     }
  45.     if(hit){
  46.         if(magr->data->mlet == 'c' && !magr->cham) {
  47.             magr->mhpmax += 3;
  48.             if(vis) pline("%s is turned to stone!", Monnam(mdef));
  49.             else if(mdef->mtame)
  50.      pline("You have a peculiarly sad feeling for a moment, then it passes.");
  51.             monstone(mdef);
  52.             hit = 2;
  53.         } else
  54.         if((mdef->mhp -= d(pa->damn,pa->damd)) < 1) {
  55.             magr->mhpmax += 1 + rn2(pd->mlevel+1);
  56.             if(magr->mtame && magr->mhpmax > 8*pa->mlevel){
  57.                 if(pa == &li_dog) magr->data = pa = &dog;
  58.                 else if(pa == &dog) magr->data = pa = &la_dog;
  59.             }
  60.             if(vis) pline("%s is killed!", Monnam(mdef));
  61.             else if(mdef->mtame)
  62.         pline("You have a sad feeling for a moment, then it passes.");
  63.             mondied(mdef);
  64.             hit = 2;
  65.         }
  66.     }
  67.     return(hit);
  68. }
  69.  
  70. /* drop (perhaps) a cadaver and remove monster */
  71. mondied(mdef) register struct monst *mdef; {
  72. register struct permonst *pd = mdef->data;
  73.         if(letter(pd->mlet) && rn2(3)){
  74.             (void) mkobj_at(pd->mlet,mdef->mx,mdef->my);
  75.             if(cansee(mdef->mx,mdef->my)){
  76.                 unpmon(mdef);
  77.                 atl(mdef->mx,mdef->my,fobj->olet);
  78.             }
  79.             stackobj(fobj);
  80.         }
  81.         mondead(mdef);
  82. }
  83.  
  84. /* drop a rock and remove monster */
  85. monstone(mdef) register struct monst *mdef; {
  86.     extern char mlarge[];
  87.     if(index(mlarge, mdef->data->mlet))
  88.         mksobj_at(ENORMOUS_ROCK, mdef->mx, mdef->my);
  89.     else
  90.         mksobj_at(ROCK, mdef->mx, mdef->my);
  91.     if(cansee(mdef->mx, mdef->my)){
  92.         unpmon(mdef);
  93.         atl(mdef->mx,mdef->my,fobj->olet);
  94.     }
  95.     mondead(mdef);
  96. }
  97.         
  98.  
  99. fightm(mtmp) register struct monst *mtmp; {
  100. register struct monst *mon;
  101.     for(mon = fmon; mon; mon = mon->nmon) if(mon != mtmp) {
  102.         if(DIST(mon->mx,mon->my,mtmp->mx,mtmp->my) < 3)
  103.             if(rn2(4))
  104.             return(hitmm(mtmp,mon));
  105.     }
  106.     return(-1);
  107. }
  108.  
  109. /* u is hit by sth, but not a monster */
  110. thitu(tlev,dam,name)
  111. register tlev,dam;
  112. register char *name;
  113. {
  114. char buf[BUFSZ];
  115.     setan(name,buf);
  116.     if(u.uac + tlev <= rnd(20)) {
  117.         if(Blind) pline("It misses.");
  118.         else pline("You are almost hit by %s!", buf);
  119.         return(0);
  120.     } else {
  121.         if(Blind) pline("You are hit!");
  122.         else pline("You are hit by %s!", buf);
  123.         losehp(dam,name);
  124.         return(1);
  125.     }
  126. }
  127.  
  128. char mlarge[] = "bCDdegIlmnoPSsTUwY',&";
  129.  
  130. boolean
  131. hmon(mon,obj,thrown)    /* return TRUE if mon still alive */
  132. register struct monst *mon;
  133. register struct obj *obj;
  134. register thrown;
  135. {
  136.     register tmp;
  137.     boolean hittxt = FALSE;
  138.  
  139.     if(!obj){
  140.         tmp = rnd(2);    /* attack with bare hands */
  141.         if(mon->data->mlet == 'c' && !uarmg){
  142.             pline("You hit the cockatrice with your bare hands.");
  143.             pline("You turn to stone ...");
  144.             done_in_by(mon);
  145.         }
  146.     } else if(obj->olet == WEAPON_SYM || obj->otyp == PICK_AXE) {
  147.         if(obj == uwep && (obj->otyp > SPEAR || obj->otyp < BOOMERANG))
  148.         tmp = rnd(2);
  149.         else {
  150.         if(index(mlarge, mon->data->mlet)) {
  151.             tmp = rnd(objects[obj->otyp].wldam);
  152.             if(obj->otyp == TWO_HANDED_SWORD) tmp += d(2,6);
  153.             else if(obj->otyp == FLAIL) tmp += rnd(4);
  154.         } else {
  155.             tmp = rnd(objects[obj->otyp].wsdam);
  156.         }
  157.         tmp += obj->spe;
  158.         if(!thrown && obj == uwep && obj->otyp == BOOMERANG
  159.          && !rn2(3)){
  160.           pline("As you hit %s, the boomerang breaks into splinters.",
  161.                 monnam(mon));
  162.             freeinv(obj);
  163.             setworn((struct obj *) 0, obj->owornmask);
  164.             obfree(obj, (struct obj *) 0);
  165.             tmp++;
  166.         }
  167.         }
  168.         if(mon->data->mlet == 'O' && obj->otyp == TWO_HANDED_SWORD &&
  169.         !strcmp(ONAME(obj), "Orcrist"))
  170.         tmp += rnd(10);
  171.     } else    switch(obj->otyp) {
  172.         case HEAVY_IRON_BALL:
  173.             tmp = rnd(25); break;
  174.         case EXPENSIVE_CAMERA:
  175.     pline("You succeed in destroying your camera. Congratulations!");
  176.             freeinv(obj);
  177.             if(obj->owornmask)
  178.                 setworn((struct obj *) 0, obj->owornmask);
  179.             obfree(obj, (struct obj *) 0);
  180.             return(TRUE);
  181.         case DEAD_COCKATRICE:
  182.             pline("You hit %s with the cockatrice corpse.",
  183.                 monnam(mon));
  184.             if(mon->data->mlet == 'c') {
  185.                 tmp = 1;
  186.                 hittxt = TRUE;
  187.                 break;
  188.             }
  189.             pline("%s is turned to stone!", Monnam(mon));
  190.             killed(mon);
  191.             return(FALSE);
  192.         case CLOVE_OF_GARLIC:        /* no effect against demons */
  193.             if(index(UNDEAD, mon->data->mlet))
  194.                 mon->mflee = 1;
  195.             tmp = 1;
  196.             break;
  197.         default:
  198.             /* non-weapons can damage because of their weight */
  199.             /* (but not too much) */
  200.             tmp = obj->owt/10;
  201.             if(tmp < 1) tmp = 1;
  202.             else tmp = rnd(tmp);
  203.             if(tmp > 6) tmp = 6;
  204.         }
  205.  
  206.     /****** NOTE: perhaps obj is undefined!! (if !thrown && BOOMERANG) */
  207.  
  208.     tmp += u.udaminc + dbon();
  209.     if(u.uswallow) {
  210.         if((tmp -= u.uswldtim) <= 0) {
  211.             pline("Your arms are no longer able to hit.");
  212.             return(TRUE);
  213.         }
  214.     }
  215.     if(tmp < 1) tmp = 1;
  216.     mon->mhp -= tmp;
  217.     if(mon->mhp < 1) {
  218.         killed(mon);
  219.         return(FALSE);
  220.     }
  221.     if(mon->mtame && (!mon->mflee || mon->mfleetim)) {
  222.         mon->mflee = 1;            /* Rick Richardson */
  223.         mon->mfleetim += 10*rnd(tmp);
  224.     }
  225.  
  226.     if(!hittxt) {
  227.         if(thrown)
  228.             /* this assumes that we cannot throw plural things */
  229.             hit( xname(obj)  /* or: objects[obj->otyp].oc_name */,
  230.                 mon, exclam(tmp) );
  231.         else if(Blind)
  232.             pline("You hit it.");
  233.         else
  234.             pline("You hit %s%s", monnam(mon), exclam(tmp));
  235.     }
  236.  
  237.     if(u.umconf && !thrown) {
  238.         if(!Blind) {
  239.             pline("Your hands stop glowing blue.");
  240.             if(!mon->mfroz && !mon->msleep)
  241.                 pline("%s appears confused.",Monnam(mon));
  242.         }
  243.         mon->mconf = 1;
  244.         u.umconf = 0;
  245.     }
  246.     return(TRUE);    /* mon still alive */
  247. }
  248.  
  249. /* try to attack; return FALSE if monster evaded */
  250. /* u.dx and u.dy must be set */
  251. attack(mtmp)
  252. register struct monst *mtmp;
  253. {
  254.     schar tmp;
  255.     boolean malive = TRUE;
  256.     register struct permonst *mdat;
  257.     mdat = mtmp->data;
  258.  
  259.     u_wipe_engr(3);   /* andrew@orca: prevent unlimited pick-axe attacks */
  260.  
  261.     if(mdat->mlet == 'L' && !mtmp->mfroz && !mtmp->msleep &&
  262.        !mtmp->mconf && mtmp->mcansee && !rn2(7) &&
  263.        (m_move(mtmp, 0) == 2 /* he died */ || /* he moved: */
  264.         mtmp->mx != u.ux+u.dx || mtmp->my != u.uy+u.dy))
  265.         return(FALSE);
  266.  
  267. #ifdef DGK
  268.     /* This section of code provides protection against accidentally
  269.      * hitting peaceful (like '@') and tame (like 'd') monsters.
  270.      * There is protection only if you're not blind or confused. -dgk
  271.      */
  272.     if ((mtmp->mpeaceful || mtmp->mtame) && !Confusion)
  273.         if ((!Blind && (!mtmp->minvis || See_invisible))
  274.             || (Blind && Telepat)) {
  275.             (void) fflush(stdin);
  276.             pline("Really attack?");
  277.             (void) fflush(stdout);
  278.             if (readchar() != 'y') return(TRUE);
  279.         }
  280. #endif DGK
  281.     if(mtmp->mimic){
  282.         if(!u.ustuck && !mtmp->mflee) u.ustuck = mtmp;
  283. #ifdef DGK
  284.         if (levl[u.ux+u.dx][u.uy+u.dy].scrsym == symbol.door)
  285.             pline("The door actually was a Mimic.");
  286.         else if (levl[u.ux+u.dx][u.uy+u.dy].scrsym == '$')
  287.             pline("The chest was a Mimic!");
  288.         else
  289.             pline("Wait! That's a Mimic!");
  290. #else
  291.         switch(levl[u.ux+u.dx][u.uy+u.dy].scrsym){
  292.         case '+':
  293.             pline("The door actually was a Mimic.");
  294.             break;
  295.         case '$':
  296.             pline("The chest was a Mimic!");
  297.             break;
  298.         default:
  299.             pline("Wait! That's a Mimic!");
  300.         }
  301. #endif DGK
  302.         wakeup(mtmp);    /* clears mtmp->mimic */
  303.         return(TRUE);
  304.     }
  305.  
  306.     wakeup(mtmp);
  307.  
  308.     if(mtmp->mhide && mtmp->mundetected){
  309.         register struct obj *obj;
  310.  
  311.         mtmp->mundetected = 0;
  312.         if((obj = o_at(mtmp->mx,mtmp->my)) && !Blind)
  313.             pline("Wait! There's a %s hiding under %s!",
  314.                 mdat->mname, doname(obj));
  315.         return(TRUE);
  316.     }
  317.  
  318.     tmp = u.uluck + u.ulevel + mdat->ac + abon();
  319.     if(uwep) {
  320.         if(uwep->olet == WEAPON_SYM || uwep->otyp == PICK_AXE)
  321.             tmp += uwep->spe;
  322.         if(uwep->otyp == TWO_HANDED_SWORD) tmp -= 1;
  323.         else if(uwep->otyp == DAGGER) tmp += 2;
  324.         else if(uwep->otyp == CRYSKNIFE) tmp += 3;
  325.         else if(uwep->otyp == SPEAR &&
  326.             index("XDne", mdat->mlet)) tmp += 2;
  327.     }
  328.     if(mtmp->msleep) {
  329.         mtmp->msleep = 0;
  330.         tmp += 2;
  331.     }
  332.     if(mtmp->mfroz) {
  333.         tmp += 4;
  334.         if(!rn2(10)) mtmp->mfroz = 0;
  335.     }
  336.     if(mtmp->mflee) tmp += 2;
  337.     if(u.utrap) tmp -= 3;
  338.  
  339.     /* with a lot of luggage, your agility diminishes */
  340.     tmp -= (inv_weight() + 40)/20;
  341.  
  342.     if(tmp <= rnd(20) && !u.uswallow){
  343.         if(Blind) pline("You miss it.");
  344.         else pline("You miss %s.",monnam(mtmp));
  345.     } else {
  346.         /* we hit the monster; be careful: it might die! */
  347.  
  348.         if((malive = hmon(mtmp,uwep,0)) == TRUE) {
  349.         /* monster still alive */
  350.             if(!rn2(25) && mtmp->mhp < mtmp->mhpmax/2) {
  351.                 mtmp->mflee = 1;
  352.                 if(!rn2(3)) mtmp->mfleetim = rnd(100);
  353.                 if(u.ustuck == mtmp && !u.uswallow)
  354.                     u.ustuck = 0;
  355.             }
  356. #ifndef NOWORM
  357.             if(mtmp->wormno)
  358.                 cutworm(mtmp, u.ux+u.dx, u.uy+u.dy,
  359.                     uwep ? uwep->otyp : 0);
  360. #endif NOWORM
  361.         }
  362.         if(mdat->mlet == 'a') {
  363.             if(rn2(2)) {
  364.                 pline("You are splashed by the blob's acid!");
  365.                 losehp_m(rnd(6), mtmp);
  366.                 if(!rn2(30)) corrode_armor();
  367.             }
  368.             if(!rn2(6)) corrode_weapon();
  369.         }
  370.     }
  371.     if(malive && mdat->mlet == 'E' && canseemon(mtmp)
  372.        && !mtmp->mcan && rn2(3)) {
  373.         if(mtmp->mcansee) {
  374.           pline("You are frozen by the floating eye's gaze!");
  375.           nomul((u.ulevel > 6 || rn2(4)) ? rn1(20,-21) : -200);
  376.         } else {
  377.           pline("The blinded floating eye cannot defend itself.");
  378.           if(!rn2(500)) if((int)u.uluck > LUCKMIN) u.uluck--;
  379.         }
  380.     }
  381.     return(TRUE);
  382. }
  383.