Annotation of early-roguelike/urogue/magic.c, Revision 1.1.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