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

  1. /*    SCCS Id: @(#)explode.c 3.1    93/05/15    */
  2. /*    Copyright (C) 1990 by Ken Arromdee */
  3. /* NetHack may be freely redistributed.  See license for details. */
  4.  
  5. #include "hack.h"
  6.  
  7. /* Note: Arrays are column first, while the screen is row first */
  8. static int expl[3][3] = {
  9.     { S_explode1, S_explode4, S_explode7 },
  10.     { S_explode2, S_explode5, S_explode8 },
  11.     { S_explode3, S_explode6, S_explode9 }
  12. };
  13.  
  14. /* Note: I had to choose one of three possible kinds of "type" when writing
  15.  * this function: a wand type (like in zap.c), an adtyp, or an object type.
  16.  * Wand types get complex because they must be converted to adtyps for
  17.  * determining such things as fire resistance.  Adtyps get complex in that
  18.  * they don't supply enough information--was it a player or a monster that
  19.  * did it, and with a wand, spell, or breath weapon?  Object types share both
  20.  * these disadvantages....
  21.  */
  22. void
  23. explode(x, y, type, dam, olet)
  24. int x, y;
  25. int type; /* the same as in zap.c */
  26. int dam;
  27. char olet;
  28. {
  29.     int i, j, k;
  30.     boolean starting = 1;
  31.     boolean visible, any_shield;
  32.     int uhurt = 0; /* 0=unhurt, 1=items damaged, 2=you and items damaged */
  33.     const char *str;
  34.     int idamres, idamnonres;
  35.     struct monst *mtmp;
  36.     uchar adtyp;
  37.     int explmask[3][3];
  38.         /* 0=normal explosion, 1=do shieldeff, 2=do nothing */
  39.     boolean shopdamage = FALSE;
  40.  
  41.     switch(abs(type) % 10) {
  42.         default: impossible("explosion base type %d?", type); return;
  43.  
  44.         case 1: str = (olet == SCROLL_CLASS ? "tower of flame" : "fireball"); adtyp = AD_FIRE; break;
  45.         /* case 3: str = "ball of cold"; adtyp = AD_COLD; break; */
  46.         /* case 5: str = "ball lightning"; adtyp = AD_ELEC; break; */
  47.         /* case 7: str = "acid ball"; adtyp = AD_ACID; break; */
  48.     }
  49.  
  50.     any_shield = visible = FALSE;
  51.     for(i=0; i<3; i++) for(j=0; j<3; j++) {
  52.         if (!isok(i+x-1, j+y-1)) {
  53.             explmask[i][j] = 2;
  54.             continue;
  55.         }
  56.         if (i+x-1 == u.ux && j+y-1 == u.uy) {
  57.             switch(adtyp) {
  58.             case AD_FIRE:
  59.                 explmask[i][j] = Fire_resistance ? 1 : 0;
  60.                 break;
  61.             /* case AD_COLD: */
  62.             /* case AD_ELEC: */
  63.             /* case AD_DISN: */
  64.             /* case AD_ACID: */
  65.             default:
  66.                 impossible("explosion type %d?", adtyp);
  67.                 explmask[i][j] = 0;
  68.                 break;
  69.             }
  70.         }
  71.         /* can be both you and mtmp if you're swallowed */
  72.         if ((mtmp = m_at(i+x-1, j+y-1)) != 0) {
  73.             switch(adtyp) {
  74.             case AD_FIRE:
  75.                 explmask[i][j] = resists_fire(mtmp->data)
  76.                     ? 1 : 0;
  77.                 break;
  78.             /* case AD_COLD: */
  79.             /* case AD_ELEC: */
  80.             /* case AD_DISN: */
  81.             /* case AD_ACID: */
  82.             default:
  83.                 impossible("explosion type %d?", adtyp);
  84.                 explmask[i][j] = 0;
  85.                 break;
  86.             }
  87.         } else if (i+x-1 != u.ux || j+y-1 != u.uy)
  88.             explmask[i][j] = 0;
  89.  
  90.         if (cansee(i+x-1, j+y-1)) visible = TRUE;
  91.         if (explmask[i][j] == 1) any_shield = TRUE;
  92.     }
  93.  
  94.     if (visible) {
  95.         /* Start the explosion */
  96.         for(i=0; i<3; i++) for(j=0; j<3; j++) {
  97.             if (explmask[i][j] == 2) continue;
  98.             tmp_at(starting ? DISP_BEAM : DISP_CHANGE,
  99.                         cmap_to_glyph(expl[i][j]));
  100.             tmp_at(i+x-1, j+y-1);
  101.             starting = 0;
  102.         }
  103.         curs_on_u();    /* will flush screen and output */
  104.  
  105.         if (any_shield) {    /* simulate a shield effect */
  106.             for (k = 0; k < SHIELD_COUNT; k++) {
  107.             for(i=0; i<3; i++) for(j=0; j<3; j++) {
  108.                 if (explmask[i][j] == 1)
  109.                 /*
  110.                  * Bypass tmp_at() and send the shield glyphs
  111.                  * directly to the buffered screen.  tmp_at()
  112.                  * will clean up the location for us later.
  113.                  */
  114.                 show_glyph(i+x-1, j+y-1,
  115.                     cmap_to_glyph(shield_static[k]));
  116.             }
  117.             curs_on_u();    /* will flush screen and output */
  118.             delay_output();
  119.             }
  120.  
  121.             /* Cover last shield glyph with blast symbol. */
  122.             for(i=0; i<3; i++) for(j=0; j<3; j++) {
  123.             if (explmask[i][j] == 1)
  124.                 show_glyph(i+x-1,j+y-1,cmap_to_glyph(expl[i][j]));
  125.             }
  126.  
  127.         } else {        /* delay a little bit. */
  128.             delay_output();
  129.             delay_output();
  130.         }
  131.  
  132.     } else You("hear a blast.");
  133.  
  134.  
  135.     for(i=0; i<3; i++) for(j=0; j<3; j++) {
  136.         if (explmask[i][j] == 2) continue;
  137.         if (i+x-1 == u.ux && j+y-1 == u.uy)
  138.             uhurt = (explmask[i][j] == 1) ? 1 : 2;
  139.         idamres = idamnonres = 0;
  140.         (void)zap_over_floor((xchar)(i+x-1), (xchar)(j+y-1),
  141.                      type, &shopdamage);
  142.  
  143.         mtmp = m_at(i+x-1, j+y-1);
  144.         if (!mtmp) continue;
  145.         if (u.uswallow && mtmp == u.ustuck) {
  146.             if (is_animal(u.ustuck->data))
  147.                 pline("%s gets heartburn!",
  148.                       Monnam(u.ustuck));
  149.             else
  150.                 pline("%s gets slightly toasted!",
  151.                       Monnam(u.ustuck));
  152.         } else
  153.         pline("%s is caught in the %s!",
  154.             cansee(i+x-1, j+y-1) ? Monnam(mtmp) : "It", str);
  155.  
  156.         idamres += destroy_mitem(mtmp, SCROLL_CLASS, (int) adtyp);
  157.         idamres += destroy_mitem(mtmp, SPBOOK_CLASS, (int) adtyp);
  158.         /* Fire resistance protects monsters from burning scrolls, */
  159.         /* but not from exploding potions. */
  160.         idamnonres += destroy_mitem(mtmp, POTION_CLASS, (int) adtyp);
  161. /*
  162.         idamnonres += destroy_mitem(mtmp, WAND_CLASS, (int) adtyp);
  163.         idamnonres += destroy_mitem(mtmp, RING_CLASS, (int) adtyp);
  164. */
  165.         if (explmask[i][j] == 1) {
  166.             golemeffects(mtmp, (int) adtyp, dam + idamres);
  167.             mtmp->mhp -= idamnonres;
  168.         } else {
  169.         /* call resist with 0 and do damage manually so 1) we can
  170.          * get out the message before doing the damage, and 2) we can
  171.          * call mondied, not killed, if it's not your blast
  172.          */
  173.             int mdam = dam;
  174.  
  175.             if (resist(mtmp, olet, 0, FALSE)) {
  176.                 pline("%s resists the magical blast!",
  177.                     cansee(i+x-1,j+y-1) ? Monnam(mtmp)
  178.                     : "It");
  179.                 mdam = dam/2;
  180.             }
  181.             if (mtmp == u.ustuck)
  182.                 mdam *= 2;
  183.             if (resists_cold(mtmp->data) /* && adtyp == AD_FIRE */)
  184.                 mdam *= 2;
  185.             mtmp->mhp -= mdam;
  186.             mtmp->mhp -= (idamres + idamnonres);
  187.         }
  188.         if (mtmp->mhp <= 0) {
  189.             if (type >= 0) killed(mtmp);
  190.             else mondied(mtmp);
  191.         }
  192.     }
  193.  
  194.     if (visible) tmp_at(DISP_END, 0); /* clear the explosion */
  195.  
  196.     /* Do your injury last */
  197.     if (uhurt) {
  198.             if (type >= 0 && flags.verbose && olet != SCROLL_CLASS)
  199.             You("are caught in the %s!", str);
  200.         if (uhurt == 2) u.uhp -= dam;
  201.         if (u.uhp <= 0) {
  202.             char buf[BUFSZ];
  203.  
  204.             if (type >= 0 && olet != SCROLL_CLASS) {
  205.                 killer_format = NO_KILLER_PREFIX;
  206.                 Sprintf(buf, "caught %sself in %s own %s.",
  207.                     him[flags.female], his[flags.female], str);
  208.             } else {
  209.                 killer_format = KILLED_BY;
  210.                 Strcpy(buf, str);
  211.             }
  212.             killer = buf;
  213.             /* done(adtyp == AD_FIRE ? BURNING : DIED); */
  214.             done(BURNING);
  215.         }
  216.         exercise(A_STR, FALSE);
  217. #if defined(POLYSELF)
  218.         ugolemeffects((int) adtyp, dam);
  219. #endif
  220.         destroy_item(SCROLL_CLASS, (int) adtyp);
  221.         destroy_item(SPBOOK_CLASS, (int) adtyp);
  222.         destroy_item(POTION_CLASS, (int) adtyp);
  223. /*
  224.         destroy_item(RING_CLASS, (int) adtyp);
  225.         destroy_item(WAND_CLASS, (int) adtyp);
  226. */
  227.     }
  228.     if (shopdamage) {
  229.         pay_for_damage("burn away");
  230. /* (only if we ever add non-fire balls)
  231.         pay_for_damage(adtyp == AD_FIRE ? "burn away" :
  232.                    adtyp == AD_COLD ? "shatter" :
  233.                    adtyp == AD_DISN ? "disintegrate" : "destroy");
  234. */
  235.     }
  236. }
  237.  
  238. /*explode.c*/
  239.