[BACK]Return to magic.c CVS log [TXT][DIR] Up to [contributed] / early-roguelike / urogue

Annotation of early-roguelike/urogue/magic.c, Revision 1.1

1.1     ! rubenllo    1: /*
        !             2:     magic.c - This file contains functions for casting magic spells
        !             3:
        !             4:     UltraRogue: The Ultimate Adventure in the Dungeons of Doom
        !             5:     Copyright (C) 1986, 1992, 1993, 1995 Herb Chong
        !             6:     All rights reserved.
        !             7:
        !             8:     Based on "Advanced Rogue"
        !             9:     Copyright (C) 1984, 1985 Michael Morgan, Ken Dalka
        !            10:     All rights reserved.
        !            11:
        !            12:     Based on "Rogue: Exploring the Dungeons of Doom"
        !            13:     Copyright (C) 1980, 1981 Michael Toy, Ken Arnold and Glenn Wichman
        !            14:     All rights reserved.
        !            15:
        !            16:     See the file LICENSE.TXT for full copyright and licensing information.
        !            17: */
        !            18:
        !            19: #include <stdlib.h>
        !            20: #include <string.h>
        !            21: #include <ctype.h>
        !            22: #include "rogue.h"
        !            23:
        !            24: /*
        !            25:          Cost for each level of spells level:
        !            26: */
        !            27:
        !            28: static const int spell_cost[] = {1, 5, 17, 29, 53, 91, 159, 247, 396};
        !            29:
        !            30: static struct spells monst_spells[] =
        !            31: {
        !            32:     {5, S_SELFTELEP, SCR_MAGIC},
        !            33:     {4, P_HEALING, POT_MAGIC | _TWO_},
        !            34:     {3, P_REGENERATE, POT_MAGIC},
        !            35:     {2, P_HEALING, POT_MAGIC},
        !            36:     {4, P_HASTE, POT_MAGIC},
        !            37:     {2, P_SEEINVIS, POT_MAGIC},
        !            38:     {3, P_SHERO, POT_MAGIC},
        !            39:     {5, P_PHASE, POT_MAGIC},
        !            40:     {4, P_INVIS, POT_MAGIC},
        !            41:     {4, WS_CANCEL, ZAP_MAGIC},
        !            42:
        !            43:     /* In reverse order of damage ability */
        !            44:     {6, WS_ELECT, ZAP_MAGIC | _TWO_},
        !            45:     {6, WS_FIRE, ZAP_MAGIC | _TWO_},
        !            46:     {6, WS_COLD, ZAP_MAGIC | _TWO_},
        !            47:     {6, WS_MISSILE, ZAP_MAGIC | _TWO_},
        !            48:     {5, WS_ELECT, ZAP_MAGIC},
        !            49:     {5, WS_FIRE, ZAP_MAGIC},
        !            50:     {5, WS_COLD, ZAP_MAGIC},
        !            51:     {4, WS_ELECT, ZAP_MAGIC | ISCURSED},
        !            52:     {4, WS_FIRE, ZAP_MAGIC | ISCURSED},
        !            53:     {4, WS_COLD, ZAP_MAGIC | ISCURSED},
        !            54:     {3, WS_MISSILE, ZAP_MAGIC},
        !            55:     {1, WS_MISSILE, ZAP_MAGIC | ISCURSED},
        !            56:
        !            57:     {-1, -1, 0}
        !            58: };
        !            59:
        !            60: /*
        !            61:     Spells that a player can cast Non-mus only know ISKNOW spells until found
        !            62:     in the dungeon. Special classes know their spells one level lower, and
        !            63:     blessed one above.
        !            64: */
        !            65:
        !            66: static struct spells player_spells[] =
        !            67: {
        !            68:     {1, WS_KNOCK, ZAP_MAGIC | ISKNOW},
        !            69:     {1, S_SUMFAMILIAR, SCR_MAGIC | SP_DRUID | SP_MAGIC | SP_CLERIC, SP_ILLUSION },
        !            70:     {1, S_GFIND, SCR_MAGIC | ISKNOW},
        !            71:     {1, P_MONSTDET, POT_MAGIC | ISKNOW | SP_DRUID},
        !            72:     {1, P_TREASDET, POT_MAGIC | ISKNOW | SP_MAGIC},
        !            73:     {1, S_FOODDET, SCR_MAGIC | ISKNOW | SP_CLERIC},
        !            74:     {1, S_LIGHT, SCR_MAGIC | ISKNOW | SP_ILLUSION},
        !            75:
        !            76:     {2, WS_CLOSE, ZAP_MAGIC | ISKNOW},
        !            77:     {2, S_IDENTIFY, SCR_MAGIC | ISKNOW},
        !            78:     {2, WS_HIT, ZAP_MAGIC | ISKNOW | SP_PRAYER},
        !            79:     {2, P_SHIELD, POT_MAGIC | ISKNOW | SP_MAGIC},
        !            80:     {2, P_COLDRESIST, POT_MAGIC | SP_WIZARD},
        !            81:     {2, P_SEEINVIS, POT_MAGIC | SP_ILLUSION},
        !            82:     {2, S_CONFUSE, SCR_MAGIC | SP_CLERIC},
        !            83:     {2, P_SMELL, POT_MAGIC | SP_DRUID},
        !            84:     {2, WS_MISSILE, ZAP_MAGIC | SP_MAGIC},
        !            85:     {2, P_HEAR, POT_MAGIC},
        !            86:
        !            87:     {3, P_CLEAR, POT_MAGIC | ISKNOW},
        !            88:     {3, P_HEALING, POT_MAGIC | ISKNOW | SP_PRAYER},
        !            89:     {3, S_CURING, SCR_MAGIC | ISKNOW | SP_PRAYER},
        !            90:     {3, WS_MONSTELEP, ZAP_MAGIC | SP_MAGIC},
        !            91:     {3, WS_CANCEL, ZAP_MAGIC | SP_WIZARD},
        !            92:     {3, S_SELFTELEP, SCR_MAGIC | SP_WIZARD},
        !            93:     {3, P_FIRERESIST, POT_MAGIC | SP_WIZARD | SP_DRUID},
        !            94:     {3, S_MAP, SCR_MAGIC | SP_ILLUSION | SP_DRUID},
        !            95:     {3, S_REMOVECURSE, SCR_MAGIC | SP_PRAYER},
        !            96:     {3, S_HOLD, SCR_MAGIC | SP_CLERIC},
        !            97:     {3, S_SLEEP, SCR_MAGIC | SP_DRUID},
        !            98:     {3, P_HASOXYGEN, POT_MAGIC | SP_DRUID},
        !            99:     {3, WS_XENOHEALING, ZAP_MAGIC | SP_DRUID},
        !           100:     {3, P_RESTORE, POT_MAGIC},
        !           101:
        !           102:     {4, S_MSHIELD, SCR_MAGIC | ISKNOW | SP_ILLUSION},
        !           103:     {4, P_INVIS, POT_MAGIC | SP_ILLUSION},
        !           104:     {4, S_REFLECT, SCR_MAGIC | SP_ILLUSION},
        !           105:     {4, P_TRUESEE, POT_MAGIC | SP_ILLUSION},
        !           106:     {4, P_REGENERATE, POT_MAGIC | SP_CLERIC},
        !           107:     {4, WS_DRAIN, ZAP_MAGIC | SP_CLERIC},
        !           108:     {4, P_HASTE, POT_MAGIC | SP_ILLUSION | SP_CLERIC},
        !           109:     {4, P_LEVITATION, POT_MAGIC | SP_WIZARD | SP_DRUID},
        !           110:     {4, WS_WEB, ZAP_MAGIC | SP_MAGIC},
        !           111:     {4, P_PHASE, POT_MAGIC},
        !           112:
        !           113:     {5, P_SHERO, POT_MAGIC | ISKNOW},
        !           114:     {5, S_PETRIFY, SCR_MAGIC | SP_MAGIC},
        !           115:     {5, S_SCARE, SCR_MAGIC | _TWO_ | SP_PRAYER},
        !           116:     {5, WS_COLD, ZAP_MAGIC | SP_DRUID},
        !           117:     {5, WS_FIRE, ZAP_MAGIC | SP_CLERIC},
        !           118:     {5, WS_ELECT, ZAP_MAGIC | SP_WIZARD},
        !           119:     {5, WS_ANTIMATTER, ZAP_MAGIC | SP_ILLUSION},
        !           120:     {5, S_ELECTRIFY, SCR_MAGIC | SP_ILLUSION},
        !           121:
        !           122:     {6, WS_DISINTEGRATE, ZAP_MAGIC | ISKNOW},
        !           123:     {6, S_OWNERSHIP, SCR_MAGIC | SP_ALL},
        !           124:
        !           125:     {7, S_ENCHANT, SCR_MAGIC | SP_MAGIC},
        !           126:
        !           127:     {-1, -1, 0}
        !           128: };
        !           129:
        !           130: /*
        !           131:     incant()
        !           132:        Cast a spell
        !           133: */
        !           134:
        !           135: void
        !           136: incant(struct thing *caster, coord dir)
        !           137: {
        !           138:     int i;
        !           139:     struct stats    *curp;
        !           140:     struct stats    *maxp;
        !           141:     int is_player = (caster == &player);
        !           142:     int points_casters;
        !           143:     char    *casters_name = (on(player, ISBLIND)) ? "it" :
        !           144:             monsters[caster->t_index].m_name;
        !           145:     struct spells   *sp;
        !           146:     char *cast_name;                      /* = spell_name(sp)           */
        !           147:     char *spell_type;                     /* spell or prayer            */
        !           148:     int   casting_cost;                   /* from spell_cost[]          */
        !           149:     int   spell_roll;                     /* sucess/fail 1D100 die roll */
        !           150:     int   fumble_chance;                  /* Spell fumble chance        */
        !           151:     int   num_fumbles = 0;                /* for fumble_spell()         */
        !           152:     int   bless_or_curse = ISNORMAL;      /* blessed or cursed?         */
        !           153:     int   message_flags = CAST_NORMAL;    /* which message to print out */
        !           154:     int   class_casters;                  /* For determining ISKNOW     */
        !           155:     int   stat_casters;                   /* s_intel or s_wisdom        */
        !           156:     int   level_casters;                  /* spellcasting level         */
        !           157:     char  buf[2 * LINELEN];
        !           158:     struct spells sorted_spells[MAX_SPELLS];
        !           159:     char  spellbuf[2 * LINELEN];
        !           160:     char  spellbuf2[2 * LINELEN];
        !           161:
        !           162:     curp = &(caster->t_stats);
        !           163:     maxp = &(caster->maxstats);
        !           164:     points_casters = curp->s_power;
        !           165:
        !           166:     if (points_casters <= 0)
        !           167:     {
        !           168:         if (is_player)
        !           169:             msg("You don't have any spell points.");
        !           170:
        !           171:         return;
        !           172:     }
        !           173:
        !           174:     /*
        !           175:      * Paladins, Rangers, ringwearers, and monsters cast at 4 levels
        !           176:      * below. Other non-specialists at 8 below
        !           177:     */
        !           178:
        !           179:     level_casters = curp->s_lvl;
        !           180:
        !           181:     switch (caster->t_ctype)
        !           182:     {
        !           183:         case C_PALADIN:
        !           184:             level_casters -= 4;
        !           185:             /* fallthrough */
        !           186:         case C_CLERIC:
        !           187:             class_casters = SP_CLERIC;
        !           188:             stat_casters = curp->s_wisdom;
        !           189:             break;
        !           190:         case C_RANGER:
        !           191:             level_casters -= 4;
        !           192:             /* fallthrough */
        !           193:         case C_DRUID:
        !           194:             class_casters = SP_DRUID;
        !           195:             stat_casters = curp->s_wisdom;
        !           196:             break;
        !           197:         case C_MAGICIAN:
        !           198:             class_casters = SP_WIZARD;
        !           199:             stat_casters = curp->s_intel;
        !           200:             break;
        !           201:         case C_ILLUSION:
        !           202:             class_casters = SP_ILLUSION;
        !           203:             stat_casters = curp->s_intel;
        !           204:             break;
        !           205:         case C_MONSTER:
        !           206:             if (off(*caster, ISUNIQUE))
        !           207:                 level_casters -= 4;
        !           208:             class_casters = 0x0;
        !           209:             stat_casters = curp->s_intel;
        !           210:             break;
        !           211:
        !           212:         default:
        !           213:             if (is_wearing(R_WIZARD))
        !           214:             {
        !           215:                 level_casters -= 4;
        !           216:                 class_casters = (rnd(4) ? SP_WIZARD : SP_ILLUSION);
        !           217:                 stat_casters = curp->s_intel;
        !           218:             }
        !           219:             else if (is_wearing(R_PIETY))
        !           220:             {
        !           221:                 level_casters -= 4;
        !           222:                 class_casters = (rnd(4) ? SP_CLERIC : SP_DRUID);
        !           223:                 stat_casters = curp->s_wisdom;
        !           224:             }
        !           225:             else
        !           226:             {
        !           227:                 level_casters -= 8;
        !           228:                 class_casters = 0x0;
        !           229:                 stat_casters = (rnd(2) ? curp->s_wisdom : curp->s_intel);
        !           230:             }
        !           231:     }
        !           232:
        !           233:     /* Bug - What about when WIS == INT? */
        !           234:
        !           235:     spell_type = (stat_casters == curp->s_intel) ? "spell" : "prayer";
        !           236:
        !           237:     if (!is_player && (sp = pick_monster_spell(caster)) == NULL)
        !           238:             return;
        !           239:     else if (is_player)
        !           240:     {
        !           241:         int num_spells = -1;    /* num of spells cheap enough */
        !           242:
        !           243:         sorted_spells[0].sp_cost = -1;
        !           244:
        !           245:         for (sp = player_spells; sp->sp_level != -1; sp++)
        !           246:         {
        !           247:             if (sp->sp_flags & class_casters)  /* Does class know spell? */
        !           248:             {
        !           249:                 int rnd_number = rnd(2 * sp->sp_level) - sp->sp_level;
        !           250:
        !           251:                 /* Knows normal spell one level below others */
        !           252:
        !           253:                 casting_cost = spell_cost[sp->sp_level - 1] + rnd_number;
        !           254:
        !           255:                 if (points_casters >= casting_cost)
        !           256:                 {
        !           257:                     sorted_spells[++num_spells] = *sp;
        !           258:                     sorted_spells[num_spells].sp_cost = casting_cost;
        !           259:                     sorted_spells[num_spells].sp_level = sp->sp_level - 1;
        !           260:                 }
        !           261:
        !           262:                 /* Knows blessed spell one level above others */
        !           263:
        !           264:                 casting_cost = spell_cost[sp->sp_level + 1] + rnd_number;
        !           265:
        !           266:                 if (points_casters >= casting_cost)
        !           267:                 {
        !           268:                     sorted_spells[++num_spells] = *sp;
        !           269:                     sorted_spells[num_spells].sp_level = sp->sp_level + 1;
        !           270:                     sorted_spells[num_spells].sp_cost = casting_cost;
        !           271:                     sorted_spells[num_spells].sp_flags |= ISBLESSED;
        !           272:                 }
        !           273:             } /* If class doesn't know spell, see if its a ISKNOW */
        !           274:             else if (sp->sp_flags & ISKNOW)
        !           275:             {
        !           276:                 int rnd_number = rnd(4 * sp->sp_level) - sp->sp_level;
        !           277:
        !           278:                 casting_cost = spell_cost[sp->sp_level] + rnd_number;
        !           279:
        !           280:                 if (points_casters >= casting_cost)
        !           281:                 {
        !           282:                     sorted_spells[++num_spells] = *sp;
        !           283:                     sorted_spells[num_spells].sp_cost = casting_cost;
        !           284:                 }
        !           285:             }
        !           286:             /* else this spell is unknown */
        !           287:         }
        !           288:
        !           289:         if (sorted_spells[0].sp_cost == -1)
        !           290:         {
        !           291:             msg("You don't have enough %s points.", spell_type);
        !           292:             after = FALSE;
        !           293:             return;
        !           294:         }
        !           295:
        !           296:         qsort(sorted_spells,num_spells + 1,sizeof(struct spells),sort_spells);
        !           297:
        !           298:         do         /* Prompt for spells */
        !           299:         {
        !           300:             struct spells   *which_spell = NULL;
        !           301:
        !           302:             buf[0] = '\0';
        !           303:             msg("");/* Get rid of --More-- */
        !           304:             msg("Which %s are you casting [%d points left] (* for list)? ",
        !           305:                 spell_type, points_casters);
        !           306:
        !           307:             switch(get_string(buf, cw))
        !           308:             {
        !           309:                 case NORM:  break;
        !           310:                 case QUIT:  return; /* ESC - lose turn */
        !           311:                 default:    continue;
        !           312:             }
        !           313:
        !           314:             if (buf[0] == '*')    /* print list */
        !           315:             {
        !           316:                 add_line("Cost  Abbreviation    Full Name");
        !           317:
        !           318:                 for (i = 0; i <= num_spells; i++)
        !           319:                 {
        !           320:                     sp = &sorted_spells[i];
        !           321:                     sprintf(buf, "[%3d] %-12s\t%s",
        !           322:                         sp->sp_cost, spell_abrev(sp,spellbuf2),
        !           323:                         spell_name(sp,spellbuf));
        !           324:                     add_line(buf);
        !           325:                 }
        !           326:                 end_line();
        !           327:                 sp = NULL;
        !           328:                 continue;
        !           329:             }
        !           330:
        !           331:             if (isupper(buf[0])) /* Uppercase Abbreviation */
        !           332:             {
        !           333:                 for (i = 0; i <= num_spells; i++)
        !           334:                 {
        !           335:                     sp = &sorted_spells[i];
        !           336:
        !           337:                     if ((strcmp(spell_abrev(sp,spellbuf2), buf) == 0))
        !           338:                     {
        !           339:                         which_spell = sp;
        !           340:                         break;
        !           341:                     }
        !           342:                 }
        !           343:             }
        !           344:             else /* Full Spell Name */
        !           345:             {
        !           346:                 for (i = 0; i <= num_spells; i++)
        !           347:                 {
        !           348:                     sp = &sorted_spells[i];
        !           349:
        !           350:                     if ((strcmp(spell_name(sp,spellbuf), buf) == 0))
        !           351:                     {
        !           352:                         which_spell = sp;
        !           353:                         break;
        !           354:                     }
        !           355:                 }
        !           356:             }
        !           357:
        !           358:             sp = which_spell;
        !           359:         }
        !           360:         while (sp == NULL);
        !           361:     }
        !           362:
        !           363:     /* Common monster and player code */
        !           364:
        !           365:     cast_name = spell_name(sp,spellbuf);
        !           366:
        !           367:     fumble_chance = (10 * sp->sp_level / 4 - 10 * level_casters / 13) * 5;
        !           368:
        !           369:     if (cur_weapon != NULL && wield_ok(caster, cur_weapon, FALSE) == FALSE)
        !           370:     {
        !           371:         switch (caster->t_ctype)
        !           372:         {
        !           373:             case C_MAGICIAN:
        !           374:             case C_ILLUSION:
        !           375:                 msg("You should have both hands free.");
        !           376:                 fumble_chance += rnd(level_casters) * 5;
        !           377:                 break;
        !           378:
        !           379:             case C_CLERIC:
        !           380:             case C_DRUID:
        !           381:             case C_PALADIN:
        !           382:                 msg("Your god looks askance at the weapon you wield.");
        !           383:                 fumble_chance += rnd(level_casters) * 5;
        !           384:                 break;
        !           385:
        !           386:             default:
        !           387:                 break;
        !           388:         }
        !           389:     }
        !           390:
        !           391:     if (fumble_chance >= MAX_FUMBLE_CHANCE)
        !           392:         fumble_chance = MAX_FUMBLE_CHANCE;
        !           393:     else if (fumble_chance <= MIN_FUMBLE_CHANCE + sp->sp_level)
        !           394:         fumble_chance = MIN_FUMBLE_CHANCE + sp->sp_level;
        !           395:
        !           396:     if (fumble_chance > (30 + rnd(50)))
        !           397:     {
        !           398:         if (is_player)
        !           399:         {
        !           400:             int  answer;
        !           401:
        !           402:             msg("Are you sure you want to try for that hard a %s? [n]",
        !           403:                 spell_type);
        !           404:
        !           405:             answer = readchar();
        !           406:
        !           407:             if (tolower(answer) != 'y')
        !           408:             {
        !           409:                 after = FALSE;
        !           410:                 return;
        !           411:             }
        !           412:             else
        !           413:                 msg("Here goes...");
        !           414:         }
        !           415:         else  /* Only if the monster is desperate */
        !           416:         {
        !           417:             if (curp->s_hpt > maxp->s_hpt / 2)
        !           418:                 return;
        !           419:         }
        !           420:     }
        !           421:
        !           422:        /* casting costs food energy */
        !           423:
        !           424:        food_left -= sp->sp_cost;
        !           425:
        !           426:     spell_roll = rnd(100);
        !           427:
        !           428:     debug("%s(%d) cast '%s' fumble %%%d (rolled %d) ",
        !           429:           monsters[caster->t_index].m_name, curp->s_power, cast_name,
        !           430:           fumble_chance, spell_roll);
        !           431:
        !           432:     caster->t_rest_hpt = caster->t_rest_pow = 0;
        !           433:
        !           434:     if (!is_player)    /* Stop running. */
        !           435:     {
        !           436:         running = FALSE;
        !           437:         msg("The %s is casting '%s'.", casters_name, cast_name);
        !           438:     }
        !           439:
        !           440:     /* The Crown of Might insures that your spells never fumble */
        !           441:
        !           442:     if (spell_roll < fumble_chance)
        !           443:     {
        !           444:         if (is_carrying(TR_CROWN))
        !           445:             message_flags |= CAST_CROWN;
        !           446:         else
        !           447:         {
        !           448:             message_flags |= CAST_CURSED;
        !           449:
        !           450:             curp->s_power -= min(curp->s_power,
        !           451:                 (2 * sp->sp_cost)); /* 2x cost */
        !           452:             num_fumbles = rnd(((fumble_chance - spell_roll) / 10)
        !           453:                  + 1) + rnd(sp->sp_level) + rnd(curp->s_lvl);
        !           454:             num_fumbles = min(10, max(0, num_fumbles));
        !           455:
        !           456:             if (num_fumbles >= 6 && rnd(1) == 0)
        !           457:                 bless_or_curse = ISCURSED;
        !           458:             else if (num_fumbles < 4)
        !           459:             {
        !           460:                 if (is_player)
        !           461:                     msg("Your %s fails.", spell_type);
        !           462:                 return;
        !           463:             }
        !           464:         }
        !           465:     }
        !           466:     else if (spell_roll > MAX_FUMBLE_CHANCE)
        !           467:     {
        !           468:         if (is_player)
        !           469:         {
        !           470:             message_flags |= CAST_BLESSED;
        !           471:             pstats.s_exp += 3 * sp->sp_cost * curp->s_lvl;
        !           472:             check_level();
        !           473:         }
        !           474:
        !           475:         maxp->s_power += sp->sp_cost;
        !           476:         bless_or_curse = ISBLESSED;
        !           477:     }
        !           478:     else
        !           479:     {
        !           480:         if (is_player) /* extra exp for sucessful spells */
        !           481:         {
        !           482:             if (player.t_ctype == C_MAGICIAN || player.t_ctype == C_ILLUSION)
        !           483:             {
        !           484:                 pstats.s_exp += sp->sp_cost * curp->s_lvl;
        !           485:                 check_level();
        !           486:             }
        !           487:         }
        !           488:
        !           489:         bless_or_curse = sp->sp_flags & ISBLESSED;
        !           490:         curp->s_power -= sp->sp_cost;
        !           491:     }
        !           492:
        !           493:     /* The Sceptre of Might blesses all your spells */
        !           494:
        !           495:     if (is_player && ((bless_or_curse & ISBLESSED) == 0) &&
        !           496:         is_carrying(TR_SCEPTRE))
        !           497:     {
        !           498:         message_flags |= CAST_SEPTRE;
        !           499:         bless_or_curse = ISBLESSED;
        !           500:     }
        !           501:
        !           502:     if (sp->sp_flags & POT_MAGIC)
        !           503:         quaff(caster, sp->sp_which, bless_or_curse);
        !           504:     else if (sp->sp_flags & SCR_MAGIC)
        !           505:             read_scroll(caster, sp->sp_which, bless_or_curse);
        !           506:     else if (sp->sp_flags & ZAP_MAGIC)
        !           507:     {
        !           508:         if (is_player)
        !           509:         {
        !           510:             do     /* Must pick a direction */
        !           511:             {
        !           512:                 msg("Which direction?");
        !           513:             }
        !           514:             while (get_dir() == FALSE);
        !           515:         }
        !           516:         else
        !           517:         {
        !           518:             delta.x = dir.x;
        !           519:             delta.y = dir.y;
        !           520:         }
        !           521:         do_zap(caster, sp->sp_which, bless_or_curse);
        !           522:     }
        !           523:     else
        !           524:         msg("What a strange %s!", spell_type);
        !           525:
        !           526:     /*
        !           527:      * Print messages and take fumbles *after* spell has gone off. This
        !           528:      * makes ENCHANT, etc more dangerous
        !           529:     */
        !           530:
        !           531:     if (is_player)
        !           532:     {
        !           533:         if (message_flags & CAST_SEPTRE)
        !           534:             msg("The Sceptre enhanced your %s.", spell_type);
        !           535:         if (message_flags & CAST_CROWN)
        !           536:             msg("The Crown wordlessly corrected your %s.",
        !           537:                 spell_type);
        !           538:
        !           539:         switch (message_flags & 0x1)
        !           540:         {
        !           541:             case CAST_CURSED:
        !           542:                 msg("You botched your '%s' %s.", cast_name,
        !           543:                     spell_type);
        !           544:                 fumble_spell(caster, num_fumbles);
        !           545:                 break;
        !           546:             case CAST_NORMAL:
        !           547:                 msg("You sucessfully cast your '%s' %s.",
        !           548:                     cast_name, spell_type);
        !           549:                 break;
        !           550:
        !           551:             case CAST_BLESSED:
        !           552:                 msg("Your '%s' %s went superbly.", cast_name,
        !           553:                     spell_type);
        !           554:                 break;
        !           555:         }
        !           556:     }
        !           557: }
        !           558:
        !           559: /*
        !           560:     spell_name()
        !           561:         returns pointer to spell name
        !           562: */
        !           563:
        !           564: char *
        !           565: spell_name(struct spells *sp, char *buf)
        !           566: {
        !           567:     if (buf == NULL)
        !           568:         return("UltraRogue Bug #105");
        !           569:
        !           570:     if (sp->sp_flags & POT_MAGIC)
        !           571:         strcpy(buf, p_magic[sp->sp_which].mi_name);
        !           572:     else if (sp->sp_flags & SCR_MAGIC)
        !           573:         strcpy(buf, s_magic[sp->sp_which].mi_name);
        !           574:     else if (sp->sp_flags & ZAP_MAGIC)
        !           575:         strcpy(buf, ws_magic[sp->sp_which].mi_name);
        !           576:     else
        !           577:         strcpy(buf, "unknown spell type");
        !           578:
        !           579:     if (sp->sp_flags & ISBLESSED)
        !           580:         strcat(buf, " 2");
        !           581:
        !           582:     return(buf);
        !           583: }
        !           584:
        !           585: /*
        !           586:     spell_abrev()
        !           587:         returns pointer to capital letter spell abbreviation
        !           588: */
        !           589:
        !           590: char *
        !           591: spell_abrev(struct spells *sp, char *buf)
        !           592: {
        !           593:     if (buf == NULL)
        !           594:          return("UltraRogue Bug #106");
        !           595:
        !           596:     if (sp->sp_flags & POT_MAGIC)
        !           597:         strcpy(buf, p_magic[sp->sp_which].mi_abrev);
        !           598:     else if (sp->sp_flags & SCR_MAGIC)
        !           599:         strcpy(buf, s_magic[sp->sp_which].mi_abrev);
        !           600:     else if (sp->sp_flags & ZAP_MAGIC)
        !           601:         strcpy(buf, ws_magic[sp->sp_which].mi_abrev);
        !           602:     else
        !           603:         strcpy(buf, "?????");
        !           604:
        !           605:     if (sp->sp_flags & ISBLESSED)
        !           606:         strcat(buf, " 2");
        !           607:
        !           608:     return(buf);
        !           609: }
        !           610:
        !           611: /*
        !           612:     fumble_spell()
        !           613:         he blew it.  Make him pay
        !           614: */
        !           615:
        !           616: void
        !           617: fumble_spell(struct thing *caster, int num_fumbles)
        !           618: {
        !           619:     struct stats    *curp = &(caster->t_stats);
        !           620:     struct stats    *maxp = &(caster->maxstats);
        !           621:     int    is_player = (caster == &player);
        !           622:
        !           623:     debug("Taking %d fumbles.", num_fumbles);
        !           624:
        !           625:     switch (num_fumbles)
        !           626:     {
        !           627:         case 10: /* Lose ability */
        !           628:             if (rnd(5) == 0)
        !           629:                 quaff(caster, P_GAINABIL, ISCURSED);
        !           630:             break;
        !           631:
        !           632:         case 9: /* Lose max spell points */
        !           633:
        !           634:             if (rnd(4) == 0)
        !           635:             {
        !           636:                 maxp->s_power -= rnd(10);
        !           637:
        !           638:                 if (maxp->s_power <= 5)
        !           639:                     maxp->s_power = 5;
        !           640:             }
        !           641:             break;
        !           642:
        !           643:         case 8: /* Lose all current spell points */
        !           644:
        !           645:             if (rnd(3) == 0)
        !           646:                 curp->s_power = 0;
        !           647:             else
        !           648:                 curp->s_power /= 2;
        !           649:             break;
        !           650:
        !           651:         case 7: /* Freeze */
        !           652:
        !           653:             if (rnd(2) == 0)
        !           654:             {
        !           655:                 if (is_player)
        !           656:                     no_command++;
        !           657:                 else
        !           658:                     caster->t_no_move++;
        !           659:             }
        !           660:             break;
        !           661:
        !           662:         case 6: /* Cast a cursed spell - see below */
        !           663:             break;
        !           664:
        !           665:         case 5: /* Become dazed and confused */
        !           666:
        !           667:             if (rnd(5) == 0)
        !           668:                 quaff(caster, P_CLEAR, ISCURSED);
        !           669:             break;
        !           670:
        !           671:         case 4: /* Lose hit points */
        !           672:
        !           673:             if (is_player)
        !           674:                 feel_message();
        !           675:             if ((curp->s_hpt -= rnd(10)) <= 0)
        !           676:             {
        !           677:                 if (is_player)
        !           678:                     death(D_SPELLFUMBLE);
        !           679:                 else
        !           680:                     killed(caster, find_mons(caster->t_pos.y, caster->t_pos.x),
        !           681:                        NOMESSAGE, NOPOINTS);
        !           682:                 return;
        !           683:             }
        !           684:             break;
        !           685:
        !           686:         case 3: /* Spell fails */
        !           687:             break;
        !           688:
        !           689:         case 2: /* Freeze */
        !           690:
        !           691:             if (is_player)
        !           692:                 no_command++;
        !           693:             else
        !           694:                 caster->t_no_move++;
        !           695:
        !           696:             break;
        !           697:
        !           698:         default:
        !           699:         case 1: /* Take double spell points - handled in incant() */
        !           700:             break;
        !           701:     }
        !           702: }
        !           703:
        !           704: /*
        !           705:     learn_new_spells()
        !           706:         go through player_spells and ISKNOW identified potions,
        !           707:         scrolls, and sticks
        !           708: */
        !           709:
        !           710: void
        !           711: learn_new_spells(void)
        !           712: {
        !           713:     struct spells   *sp;
        !           714:     int kludge = 0;
        !           715:     char spellbuf[2*LINELEN];
        !           716:
        !           717:     for (sp = player_spells; sp->sp_level != -1; sp++)
        !           718:     {
        !           719:         if (sp->sp_flags & POT_MAGIC)
        !           720:             kludge = TYP_POTION;
        !           721:         else if (sp->sp_flags & SCR_MAGIC)
        !           722:             kludge = TYP_SCROLL;
        !           723:         else if (sp->sp_flags & ZAP_MAGIC)
        !           724:             kludge = TYP_STICK;
        !           725:
        !           726:         if (know_items[kludge][sp->sp_which])
        !           727:         {
        !           728:             if ((sp->sp_flags & ISKNOW) == FALSE)
        !           729:                 debug("Learned new spell '%s'", spell_name(sp,spellbuf));
        !           730:             sp->sp_flags |= ISKNOW;
        !           731:         }
        !           732:     }
        !           733: }
        !           734:
        !           735: /*
        !           736:     pick_monster_spell()
        !           737:         decide which spell from monst_spells will be cast
        !           738:         returns pointer to spell in monst_spells
        !           739: */
        !           740:
        !           741: struct spells *
        !           742: pick_monster_spell(struct thing *caster)
        !           743: {
        !           744:     struct spells   *sp = NULL;
        !           745:     struct stats    *curp = &(caster->t_stats);
        !           746:     int points_casters = curp->s_power;
        !           747:
        !           748:     /* Discover castable spells */
        !           749:
        !           750:     for (sp = monst_spells; sp->sp_level != -1; sp++)
        !           751:     {
        !           752:         int rnd_number = rnd(2 * sp->sp_level) - sp->sp_level;
        !           753:         int casting_cost = spell_cost[sp->sp_level] + rnd_number;
        !           754:
        !           755:         if (points_casters >= casting_cost)
        !           756:             sp->sp_flags |= ISKNOW;
        !           757:     }
        !           758:
        !           759:     /* Decide which spell to cast */
        !           760:
        !           761:     if (curp->s_hpt < rnd(caster->maxstats.s_hpt))  /* think defense */
        !           762:     {
        !           763:         int i;
        !           764:         static const int run_or_heal[NUM_RUN] =
        !           765:             { M_SELFTELEP, M_HLNG2, M_HLNG, M_REGENERATE };
        !           766:
        !           767:         for (i = 0; i < NUM_RUN; i++)
        !           768:         {
        !           769:             sp = &monst_spells[run_or_heal[i]];
        !           770:
        !           771:             if ((sp->sp_flags & ISKNOW) && rnd(1))
        !           772:                 return(sp);
        !           773:         }
        !           774:     }
        !           775:
        !           776:     if (on(*caster, ISSLOW))   /* cancel a slow */
        !           777:     {
        !           778:         sp = &monst_spells[M_HASTE];
        !           779:
        !           780:         if (sp->sp_flags & ISKNOW)
        !           781:             return (sp);
        !           782:     }
        !           783:
        !           784:     if (on(*caster, ISFLEE))   /* stop running away */
        !           785:     {
        !           786:         sp = &monst_spells[M_SHERO];
        !           787:
        !           788:         if (sp->sp_flags & ISKNOW)
        !           789:             return (sp);
        !           790:     }
        !           791:
        !           792:     if (on(player, ISINVIS) || on(player, ISDISGUISE))
        !           793:     {
        !           794:         if (off(*caster, CANSEE))  /* look for him */
        !           795:         {
        !           796:             sp = &monst_spells[M_SEEINVIS];
        !           797:
        !           798:             if (sp->sp_flags & ISKNOW)
        !           799:                 return (sp);
        !           800:         }
        !           801:         else if (off(*caster, ISINVIS))    /* go invisible */
        !           802:         {
        !           803:             sp = &monst_spells[M_INVIS];
        !           804:
        !           805:             if (sp->sp_flags & ISKNOW)
        !           806:                 return (sp);
        !           807:         }
        !           808:     }
        !           809:
        !           810:     if (on(player, CANINWALL) && (off(*caster, CANINWALL)) &&
        !           811:        (rnd(5) == 0))
        !           812:     {
        !           813:         sp = &monst_spells[M_PHASE];
        !           814:
        !           815:         if (sp->sp_flags & ISKNOW)
        !           816:             return (sp);
        !           817:     }
        !           818:
        !           819:     if (rnd(5) == 0 && has_defensive_spell(player))
        !           820:     {
        !           821:         sp = &monst_spells[M_CANCEL];
        !           822:
        !           823:         if (sp->sp_flags & ISKNOW)
        !           824:             return (sp);
        !           825:     }
        !           826:
        !           827:     /* Cast an offensive spell */
        !           828:
        !           829:     for (sp = &monst_spells[M_OFFENSE]; sp->sp_level != 1; sp++)
        !           830:     {
        !           831:         if ((rnd(3) == 0) && (sp->sp_flags & ISKNOW))
        !           832:             return (sp);
        !           833:
        !           834:         if ((rnd(3) == 0) && (sp->sp_flags & ISKNOW))
        !           835:         {
        !           836:             if (sp->sp_which != WS_MISSILE &&
        !           837:                 DISTANCE(caster->t_pos, hero) > BOLT_LENGTH)
        !           838:                 continue;
        !           839:             else
        !           840:                 return(sp);
        !           841:         }
        !           842:     }
        !           843:
        !           844:     return(NULL);
        !           845: }
        !           846:
        !           847: /*
        !           848:     sort_spells()
        !           849:        called by qsort()
        !           850: */
        !           851:
        !           852: int
        !           853: sort_spells(const void *a, const void *b)
        !           854: {
        !           855:     struct spells *sp1, *sp2;
        !           856:     int diff;
        !           857:     char  spellbuf[2 * LINELEN];
        !           858:     char  spellbuf2[2 * LINELEN];
        !           859:
        !           860:     union /* hack to prevent 'lint' from complaining */
        !           861:     {
        !           862:         struct spells *s;
        !           863:         const void          *vptr;
        !           864:     } s1,s2;
        !           865:
        !           866:     s1.vptr = a;
        !           867:     s2.vptr = b;
        !           868:
        !           869:     sp1 = s1.s;
        !           870:     sp2 = s2.s;
        !           871:
        !           872:     diff = sp1->sp_cost - sp2->sp_cost;
        !           873:
        !           874:     if (diff != 0)
        !           875:         return(diff);
        !           876:     else
        !           877:         return(strcmp(spell_name(sp1,spellbuf), spell_name(sp1,spellbuf2)));
        !           878: }

CVSweb