comparison urogue/magic.c @ 256:c495a4f288c6

Import UltraRogue from the Roguelike Restoration Project (r1490)
author John "Elwin" Edwards
date Tue, 31 Jan 2017 19:56:04 -0500
parents
children
comparison
equal deleted inserted replaced
253:d9badb9c0179 256:c495a4f288c6
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 }