home *** CD-ROM | disk | FTP | other *** search
/ Usenet 1994 October / usenetsourcesnewsgroupsinfomagicoctober1994disk2.iso / games / volume3 / nethack2.2 / part13 / spell.c < prev    next >
C/C++ Source or Header  |  1987-12-02  |  10KB  |  445 lines

  1. /*    SCCS Id: @(#)spell.c    2.1    87/10/07
  2.  */
  3.  
  4. #include "hack.h"
  5. #ifdef SPELLS
  6. extern char *nomovemsg;
  7.  
  8. doxcribe() {
  9.     register struct obj *book;
  10.     struct     obj    *getobj();
  11.     register boolean confused = (Confusion != 0);
  12.     register boolean oops;
  13.     register schar     delay;
  14.     register int   booktype;
  15.     register int     i;
  16.  
  17.     book = getobj("+", "transcribe");
  18.     if(!book) return(0);
  19.  
  20.     if(Blind) {
  21.         pline("Being blind, you cannot read the mystic runes.");
  22.         useup(book);        /* well, if you are stupid... */
  23.         return(0);
  24.     }
  25.  
  26.     if(confused) {
  27.         pline("Being confused, you cannot grasp the meaning of this tome.");
  28.         useup(book);        /* and more stupidity... */
  29.         return(0);
  30.     }
  31.     booktype = book->otyp;
  32.     oops = !rn2(u.ulevel - objects[booktype].spl_lev + 7);
  33.     switch(booktype)  {
  34.  
  35. /* level 1 spells */
  36.     case SPE_HEALING:
  37.     case SPE_DETECT_MONSTERS:
  38.     case SPE_FORCE_BOLT:
  39.     case SPE_LIGHT:
  40.     case SPE_SLEEP:
  41. /* level 2 spells */
  42.     case SPE_MAGIC_MISSILE:
  43.     case SPE_CONFUSE_MONSTER:
  44.     case SPE_SLOW_MONSTER:
  45.     case SPE_CURE_BLINDNESS:
  46.     case SPE_CREATE_MONSTER:
  47.     case SPE_DETECT_FOOD:
  48.         delay = -objects[booktype].oc_delay;
  49.         break;
  50. /* level 3 spells */
  51.     case SPE_HASTE_SELF:
  52.     case SPE_CAUSE_FEAR:
  53.     case SPE_CURE_SICKNESS:
  54.     case SPE_DETECT_UNSEEN:
  55.     case SPE_EXTRA_HEALING:
  56.     case SPE_CHARM_MONSTER:
  57. /* level 4 spells */
  58.     case SPE_LEVITATION:
  59.     case SPE_RESTORE_STRENGTH:
  60.     case SPE_INVISIBILITY:
  61.     case SPE_FIREBALL:
  62.     case SPE_DETECT_TREASURE:
  63.         delay = -(objects[booktype].spl_lev - 1) * objects[booktype].oc_delay;
  64.         break;
  65. /* level 5 spells */
  66.     case SPE_REMOVE_CURSE:
  67.     case SPE_MAGIC_MAPPING:
  68.     case SPE_CONE_OF_COLD:
  69.     case SPE_IDENTIFY:
  70.     case SPE_DIG:
  71. /* level 6 spells */
  72.     case SPE_TURN_UNDEAD:
  73.     case SPE_POLYMORPH:
  74.     case SPE_CREATE_FAMILIAR:
  75.     case SPE_TELEPORT_AWAY:
  76.         delay = -objects[booktype].spl_lev * objects[booktype].oc_delay;
  77.         break;
  78. /* level 7 spells */
  79.     case SPE_CANCELLATION:
  80.     case SPE_FINGER_OF_DEATH:
  81.     case SPE_GENOCIDE:
  82.         delay = -8 * objects[booktype].oc_delay;
  83.         break;
  84. /* impossible */
  85.     default:
  86.         impossible("Unknown spell-book, %d;", booktype);
  87.         return(0);
  88.     }
  89.  
  90.     pline("You begin to transcribe the spell.");
  91.     if(oops || book->cursed)  {
  92.         cursed_book(objects[booktype].spl_lev);
  93.         nomul(delay);            /* study time */
  94.     } else  {
  95.         nomul(delay);            /* study time */
  96.         for(i = 0; i < MAXSPELL; i++)  {
  97.             if(spl_book[i].sp_id == booktype)  {
  98. #ifdef HARD
  99.             nomovemsg = "You make that spell more legible.";
  100.             spl_book[i].sp_uses += rn1(3,8-spl_book[i].sp_lev);
  101. #else            
  102.             nomovemsg = "Oh, you already know that one!";
  103. #endif
  104.             useup(book);
  105.             return(1);
  106.             } else if (spl_book[i].sp_id == NO_SPELL)  {
  107.             spl_book[i].sp_id = booktype;
  108.             spl_book[i].sp_lev = objects[booktype].spl_lev;
  109.             spl_book[i].sp_flags = objects[booktype].bits;
  110. #ifdef HARD
  111.             /* spells have 2 .. 10-level uses. */
  112.             /* ie 2 or 3 uses w/ most potent */
  113.             spl_book[i].sp_uses = rn1(3,8-spl_book[i].sp_lev);
  114. #endif
  115.             nomovemsg = "You add the spell to your books.";
  116.             objects[booktype].oc_name_known = 1;
  117.             useup(book);
  118.             return(1);
  119.             }
  120.         }
  121.         impossible("Too many spells in spellbook!");
  122.     }
  123.     useup(book);
  124.     return(1);
  125. }
  126.  
  127. cursed_book(level)
  128.     register int    level;
  129. {
  130.     switch(rn2(level)) {
  131.     case 0:
  132.         pline("You feel a wrenching sensation.");
  133.         tele();        /* teleport him */
  134.         break;
  135.     case 1:
  136.         pline("You feel threatened.");
  137.         aggravate();
  138.         break;
  139.     case 2:
  140.         if(!Blind)    pline("A cloud of darkness falls upon you.");
  141.         Blinded += rn1(100,250);
  142.         seeoff(0);
  143.         break;
  144.     case 3:
  145.         if (u.ugold <= 0)  {
  146.             pline("You feel a strange sensation.");
  147.         } else {
  148.             pline("You notice you have no gold!");
  149.             u.ugold = 0;
  150.             flags.botl = 1;
  151.         }
  152.         break;
  153.     case 4:
  154.         pline("These runes were just too much to comprehend.");
  155.         HConfusion += rn1(7,16);
  156.         break;
  157.     case 5:
  158.         pline("The book was coated with contact poison!");
  159.         if(Poison_resistance) {
  160.             losestr(rn1(1,2));
  161.             losehp(rnd(6), "contact poison");
  162.         } else {
  163.             losestr(rn1(4,3));
  164.             losehp(rnd(10), "contact poison");
  165.         }
  166.         break;
  167.     case 6:
  168.         pline("As you read the book, it explodes in your face!");
  169.         losehp (2*rnd(10)+5, "exploding rune");
  170.         break;
  171.     default:
  172.         rndcurse();
  173.         break;
  174.     }
  175.     return(0);
  176. }
  177.  
  178. docast()
  179. {
  180.     register int     spell, energy, damage;
  181.     register boolean confused = (Confusion != 0);
  182.     register struct  obj    *pseudo;
  183.     struct     obj     *mksobj();
  184.  
  185.     spell = getspell();
  186.     if (!spell) return(0);
  187.     else  {
  188. #ifdef HARD
  189.         /* note that turning to the page decrements the # of uses,  */
  190.         /* even if the mage does not have enough food/energy to use */
  191.         /* the spell */
  192.         switch (spelluses(spell)) {
  193.         case 0:
  194.             pline ("That page is too faint to read at the moment.");
  195.             return(0);
  196.         case 1:
  197.             pline ("You can barely make out the runes on this page.");
  198.             break;
  199.         case 2:
  200.             pline ("This spell is starting to look well used.");
  201.             break;
  202.         default:
  203.             break;
  204.         }
  205.         decrnuses(spell);
  206. #endif        
  207.         energy = spellev(spell);
  208. #ifdef BVH
  209.         if (has_amulet()) {
  210.  
  211.             pline("You feel the amulet draining your energy away.");
  212.             energy *= rnd(6);
  213.         }
  214. #endif
  215.         if(energy > u.uen)  {
  216.             pline("You are too weak to cast that spell.");
  217.             return(0);
  218.         } else  if ((u.uhunger <= 100) || (u.ustr < 6))  {
  219.             pline("You miss the strength for that spell.");
  220.             return(0);
  221.         } else    {
  222.             morehungry(energy * 10);
  223.             u.uen -= energy;
  224.         }
  225.         flags.botl = 1;
  226.     }
  227. #ifdef HARD
  228.     if (confused ||
  229.         (rn2(10) + (int)(u.ulevel + u.uluck) - 3*spellev(spell)) < 0) {
  230.  
  231.         if (Hallucination)
  232.             pline("Far out... a light show!");
  233.         else    pline("The air around you crackles as you goof up.");
  234.         return(0);
  235.     }
  236. #endif
  237.  
  238. /*    pseudo is a temporary "false" object containing the spell stats. */
  239.     pseudo = mksobj(spellid(spell));
  240.     pseudo->quan = 20;            /* do not let useup get it */
  241.     switch(pseudo->otyp)  {
  242.  
  243. /* These spells are all duplicates of wand effects */
  244.     case SPE_FORCE_BOLT:
  245.     case SPE_SLEEP:
  246.     case SPE_MAGIC_MISSILE:
  247.     case SPE_SLOW_MONSTER:
  248.     case SPE_FIREBALL:
  249.     case SPE_CONE_OF_COLD:
  250.     case SPE_DIG:
  251.     case SPE_TURN_UNDEAD:
  252.     case SPE_POLYMORPH:
  253.     case SPE_TELEPORT_AWAY:
  254.     case SPE_CANCELLATION:
  255.     case SPE_FINGER_OF_DEATH:
  256.     case SPE_LIGHT:
  257.     case SPE_DETECT_UNSEEN:
  258.         if (!(objects[pseudo->otyp].bits & NODIR)) {
  259.             getdir(1);
  260.             if(!u.dx && !u.dy && !u.dz && (u.ulevel > 8)) {
  261.                 if((damage = zapyourself(pseudo)))
  262.                 losehp(damage, "self-inflicted injury");
  263.             } else    weffects(pseudo);
  264.         } else weffects(pseudo);
  265.         break;
  266. /* These are all duplicates of scroll effects */
  267.     case SPE_CONFUSE_MONSTER:
  268.     case SPE_DETECT_FOOD:
  269.     case SPE_CAUSE_FEAR:
  270.     case SPE_CHARM_MONSTER:
  271.     case SPE_REMOVE_CURSE:
  272.     case SPE_MAGIC_MAPPING:
  273.     case SPE_CREATE_MONSTER:
  274.     case SPE_IDENTIFY:
  275.     case SPE_GENOCIDE:
  276.         seffects(pseudo);
  277.         break;
  278.     case SPE_HASTE_SELF:
  279.     case SPE_DETECT_TREASURE:
  280.     case SPE_DETECT_MONSTERS:
  281.     case SPE_LEVITATION:
  282.     case SPE_RESTORE_STRENGTH:
  283.     case SPE_INVISIBILITY:
  284.         peffects(pseudo);
  285.         break;
  286.     case SPE_HEALING:
  287.         pline("You feel a bit better.");
  288.         healup(rnd(8), 0, 0, 0);
  289.         break;
  290.     case SPE_CURE_BLINDNESS:
  291.         healup(0, 0, 0, 1);
  292.         break;
  293.     case SPE_CURE_SICKNESS:
  294.         pline("You are no longer ill.");
  295.         healup(0, 0, 1, 0);
  296.         break;
  297.     case SPE_EXTRA_HEALING:
  298.         pline("You feel a fair bit better.");
  299.         healup(d(2,8), 1, 0, 0);
  300.         break;
  301.     case SPE_CREATE_FAMILIAR:
  302.         {    register struct monst *mtmp;
  303.             struct   monst  *makedog();
  304.  
  305.             mtmp = makedog();
  306.             if(mtmp) {
  307.                 /* make it into something else */
  308.                 (void) newcham(mtmp, &mons[dlevel+14+rn2(CMNUM-14-dlevel)]);
  309.                 if(confused)
  310.                     mtmp->mtame = mtmp->mpeaceful = 0;
  311.             }
  312.         }
  313.         break;
  314.     default:
  315.         impossible("Unknown spell %d attempted.", spell);
  316.         obfree(pseudo, (struct obj *)0);
  317.         return(0);
  318.     }
  319.     obfree(pseudo, (struct obj *)0);    /* now, get rid of it */
  320.     return(1);
  321. }
  322.  
  323. getspell()  {
  324.  
  325.     register int    max, ilet, i;
  326.     char     lets[BUFSZ], buf[BUFSZ];
  327.  
  328.     if (spl_book[0].sp_id == NO_SPELL)  {
  329.  
  330.         pline("You don't know any spells right now.");
  331.         return(0);
  332.     } else  {
  333.  
  334.         for(max = 1; (max < MAXSPELL) && (spl_book[max].sp_id != NO_SPELL); max++);
  335.         if (max >= MAXSPELL)  {
  336.  
  337.         impossible("Too many spells memorized.");
  338.         return(0);
  339.         }
  340.  
  341.         for(i = 0; (i < max) && (i < 26); buf[++i] = 0)  buf[i] = 'a' + i;
  342.         for(i = 26; (i < max) && (i < 52); buf[++i] = 0) buf[i] = 'A' + i - 26;
  343.  
  344.         if (max == 1)  strcpy(lets, "a");
  345.         else if (max < 27)  sprintf(lets, "a-%c", 'a' + max - 1);
  346.         else if (max == 27)  sprintf(lets, "a-z A");
  347.         else sprintf(lets, "a-z A-%c", 'A' + max - 27);
  348.         for(;;)  {
  349.  
  350.         pline("Cast which spell [%s ?]: ", lets);
  351.         if ((ilet = readchar()) == '?')  {
  352.             dovspell();
  353.             continue;
  354.         } else if ((ilet == '\033')||(ilet == '\n')||(ilet == ' '))
  355.             return(0);
  356.         else for(i = 0; buf[i] != 0; i++)  if(ilet == buf[i])  return(++i);
  357.         pline("You don't know that spell.");
  358.         }
  359.     }
  360. }
  361.  
  362. losespells() {
  363.     register boolean confused = (Confusion != 0);
  364.     register int     n, nzap, i;
  365.  
  366.     for(n = 0;(spl_book[n].sp_id != NO_SPELL) && (n < MAXSPELL); n++);
  367.     if (!n) return;
  368.     if (n < MAXSPELL) {
  369.         nzap = rnd(n);
  370.         if (nzap < n) nzap += confused;
  371.         for (i = 0; i < nzap; i++) spl_book[n-i-1].sp_id = NO_SPELL;
  372.     } else impossible("Too many spells in spellbook!");
  373.     return;
  374. }
  375.  
  376. dovspell() {
  377.  
  378.     register int max, i, side;
  379.     char     buf[BUFSZ],
  380.          *spellname();
  381.  
  382.     if (spl_book[0].sp_id == NO_SPELL)  {
  383.  
  384.         pline("You don't know any spells right now.");
  385.         return(0);
  386.     } else  {
  387.  
  388.         for(max = 1; (max < MAXSPELL) && (spl_book[max].sp_id != NO_SPELL); max++);
  389.         if (max >= MAXSPELL)  {
  390.  
  391.         impossible("Too many spells memorized.");
  392.         return(0);
  393.         }
  394.     }
  395.     set_pager(0);
  396.     side = (max + 1) / 2;
  397.     if(page_line("Currently known spells:") || page_line(""))  goto quit;
  398.  
  399.     for(i = 1; i <= side; i++) {
  400.  
  401.         if((i < side) || !(max % 2))  {
  402.  
  403.             (void) sprintf(buf, "%c - (%d) %22s          %c - (%d) %22s",
  404.                    spellet(i), spellev(i), spellname(i),
  405.                    spellet(i + side), spellev(i + side), spellname(i + side));
  406.         } else {
  407.  
  408.             (void) sprintf(buf, "%c - (%d) %22s", spellet(i), spellev(i), spellname(i));
  409.         }
  410.         if(page_line(buf)) goto quit;
  411.     }
  412.  
  413.     set_pager(1);
  414.     return(0);
  415. quit:
  416.     set_pager(2);
  417.     return(0);
  418. }
  419.  
  420. spellet(spl)  {
  421.  
  422.     if (spl < 27)    return('a' + spl - 1);
  423.     else        return('A' + spl - 27);
  424. }
  425.  
  426. spellev(spl)  {
  427.  
  428.     return(spl_book[spl-1].sp_lev);
  429. }
  430.  
  431. char *
  432. spellname(spl)  {
  433.  
  434.     return(objects[spl_book[spl-1].sp_id].oc_name);
  435. }
  436.  
  437. spellid(spl)  {        return(spl_book[spl-1].sp_id);        }
  438.  
  439. #ifdef HARD
  440. spelluses(spell) {    return(spl_book[spell-1].sp_uses);    }
  441. decrnuses(spell) {    spl_book[spell-1].sp_uses--;        }
  442. #endif
  443.  
  444. #endif /* SPELLS /**/
  445.