1 /* omega copyright (C) by Laurence Raphael Brothers, 1987,1988,1989 */
2 /* spell.c */
3 /* functions having to do with spellcasting */
4 
5 #include "glob.h"
6 
7 
s_wish()8 void s_wish()
9 {
10   if (random_range(100) > Player.iq+Player.pow+Player.level) {
11     mprint("Your concentration is flawed!");
12     mprint("The spell energy backfires!");
13     p_damage(random_range(Spells[S_WISH].powerdrain),
14 	     UNSTOPPABLE,
15 	     "a backfired wish spell");
16   }
17   else {
18     wish(0);
19     if (Spells[S_WISH].known) {
20       mprint("The power of the spell is too much for you to withstand!");
21       mprint("All memory of the spell is expunged from your brain.");
22       Spells[S_WISH].known = FALSE;
23     }
24   }
25 }
26 
s_firebolt()27 void s_firebolt()
28 {
29   int x=Player.x,y=Player.y;
30   setspot(&x,&y);
31   fbolt(Player.x,Player.y,x,y,Player.dex*2+Player.level,Player.level*10+10);
32 }
33 
s_missile()34 void s_missile()
35 {
36   int x=Player.x,y=Player.y;
37   setspot(&x,&y);
38   nbolt(Player.x,Player.y,x,y,Player.dex*2+Player.level,Player.level*3+3);
39 }
40 
s_teleport()41 void s_teleport()
42 {
43   p_teleport(0);
44 }
45 
s_disrupt()46 void s_disrupt()
47 {
48   int x=Player.x,y=Player.y;
49   setspot(&x,&y);
50   disrupt(x,y,Player.level*10+25);
51 }
52 
53 
s_disintegrate()54 void s_disintegrate()
55 {
56   int x=Player.x,y=Player.y;
57   setspot(&x,&y);
58   disintegrate(x,y);
59 }
60 
61 
s_sleep()62 void s_sleep()
63 {
64   sleep_monster(0);
65 }
66 
s_heal()67 void s_heal()
68 {
69   heal(3);
70 }
71 
s_dispel()72 void s_dispel()
73 {
74   dispel((Player.level+Player.maxpow)/10);
75 }
76 
s_breathe()77 void s_breathe()
78 {
79   breathe(0);
80 }
81 
s_invisible()82 void s_invisible()
83 {
84   invisible(0);
85 }
86 
87 
s_warp()88 void s_warp()
89 {
90   warp(1);
91 }
92 
s_enchant()93 void s_enchant()
94 {
95   enchant(1);
96 }
97 
98 
s_bless()99 void s_bless()
100 {
101   bless(0);
102 }
103 
104 
s_restore()105 void s_restore()
106 {
107   recover_stat(0);
108 }
109 
110 
s_cure()111 void s_cure()
112 {
113   cure(0);
114 }
115 
116 
s_truesight()117 void s_truesight()
118 {
119   truesight(0);
120 }
121 
122 
s_hellfire()123 void s_hellfire()
124 {
125   int x=Player.x,y=Player.y;
126   setspot(&x,&y);
127   hellfire(x,y,0);
128 }
129 
130 
s_knowledge()131 void s_knowledge()
132 {
133   knowledge(0);
134 }
135 
136 
s_hero()137 void s_hero()
138 {
139   hero(0);
140 }
141 
142 /* spell takes longer and longer to work deeper into dungeon */
s_return()143 void s_return()
144 {
145   mprint("You hear a whine as your spell begins to charge up.");
146   Player.status[RETURNING] =
147     ((Current_Environment == Current_Dungeon) ? difficulty() : 1);
148 }
149 
s_desecrate()150 void s_desecrate()
151 {
152   sanctify(-1);
153 }
154 
155 
s_haste()156 void s_haste()
157 {
158   haste(0);
159 }
160 
161 
s_summon()162 void s_summon()
163 {
164   summon(0,-1);
165 }
166 
167 
s_sanctuary()168 void s_sanctuary()
169 {
170   sanctuary();
171 }
172 
s_sanctify()173 void s_sanctify()
174 {
175   sanctify(1);
176 }
177 
178 
s_accuracy()179 void s_accuracy()
180 {
181   accuracy(0);
182 }
183 
s_fear()184 void s_fear()
185 {
186   int x = Player.x,y=Player.y;
187   setspot(&x,&y);
188   inflict_fear(x,y);
189 }
190 
191 
192 /* Has all kinds of effects in different circumstances.
193    Eventually will be more interesting */
s_ritual()194 void s_ritual()
195 {
196   pob symbol;
197   int i,roomno;
198   int x,y;
199 
200   mprint("You begin your ritual....");
201   mprint("You enter a deep trance. Time Passes...");
202   setgamestatus(SKIP_PLAYER);
203   time_clock(FALSE);
204   setgamestatus(SKIP_PLAYER);
205   time_clock(FALSE);
206   setgamestatus(SKIP_PLAYER);
207   time_clock(FALSE);
208   setgamestatus(SKIP_PLAYER);
209   time_clock(FALSE);
210   setgamestatus(SKIP_PLAYER);
211   time_clock(FALSE);
212   if (RitualHour == hour())
213     mprint("Your mental fatigue prevents from completing the ritual!");
214   else if (random_range(100) > Player.iq+Player.pow+Player.level)
215     mprint("Your concentration was broken -- the ritual fails!");
216   else {
217     mprint("You charge the ritual with magical energy and focus your will.");
218     mprint("Time Passes...");
219     setgamestatus(SKIP_PLAYER);
220     time_clock(FALSE);
221     setgamestatus(SKIP_PLAYER);
222     time_clock(FALSE);
223     setgamestatus(SKIP_PLAYER);
224     time_clock(FALSE);
225     setgamestatus(SKIP_PLAYER);
226     time_clock(FALSE);
227     setgamestatus(SKIP_PLAYER);
228     time_clock(FALSE);
229     RitualHour = hour();
230     /* set of random conditions for different ritual effects */
231     if (Current_Environment == E_CITY) {
232       mprint("Flowing waves of mystical light congeal all around you.");
233       mprint("'Like wow, man! Colors!'");
234       mprint("Appreciative citizens throw you spare change.");
235       Player.cash +=random_range(50);
236     }
237     else if ((roomno=Level->site[Player.x][Player.y].roomnumber) >= 0) {
238       if (RitualRoom == roomno)
239 	mprint("For some reason the ritual doesn't work this time...");
240       else {
241 	RitualRoom = roomno;
242 	switch (RitualRoom) {
243 	case ROOMBASE+9: /* ransacked treasure chamber */
244 	  mprint("Your spell sets off frenetic growth all around you!");
245 	  for(i=0;i<8;i++){
246 	    Level->site[Player.x+Dirs[0][i]][Player.y+Dirs[1][i]].locchar =
247 	      HEDGE;
248 	    Level->site[Player.x+Dirs[0][i]][Player.y+Dirs[1][i]].p_locf =
249 	      L_TRIFID;
250 	    lset(Player.x+Dirs[0][i], Player.y+Dirs[1][i], CHANGED);
251 	  }
252 	  break;
253 	case ROOMBASE+13: /* harem */
254 	case ROOMBASE+22: /* boudoir */
255 	  mprint("A secret panel opens next to the bed....");
256 	  if (random_range(2))
257 	    summon(0,INCUBUS); /* succubus/incubus */
258 	  else summon(0,SATYR); /* satyr/nymph */
259 	  break;
260 	case ROOMBASE+26: /*shrine to high magic */
261 	  mprint("A storm of mana coaelesces around you.");
262 	  mprint("You are buffeted by bursts of random magic.");
263 	  p_damage(random_range(Player.pow),UNSTOPPABLE,"high magic");
264 	  mprint("Continue ritual? Could be dangerous.... [yn] ");
265 	  if (ynq()=='y') s_wish();
266 	  else mprint("The mana fades away to nothingness.");
267 	  x = Player.x;
268 	  y = Player.y;
269 	  while (x >= 0 && Level->site[x - 1][y].roomnumber == ROOMBASE+26)
270 	    x--;
271 	  while (y >= 0 && Level->site[x][y - 1].roomnumber == ROOMBASE+26)
272 	    y--;
273 	  for (i = 0; Level->site[x][y].roomnumber == ROOMBASE+26;) {
274 	    Level->site[x][y].roomnumber = RS_ZORCH;
275 	    x++;
276 	    i++;
277 	    if (Level->site[x][y].roomnumber != ROOMBASE+26) {
278 	      x -= i;
279 	      i = 0;
280 	      y++;
281 	    }
282 	  }
283 	  lset(Player.x, Player.y, CHANGED);
284 	  break;
285 	case ROOMBASE+27: /* magician's lab */
286 	  mprint("Your magical activity sets off a latent spell in the lab!");
287 	  cast_spell(random_range(NUMSPELLS));
288 	  break;
289 	case ROOMBASE+28: /* pentagram room */
290 	  mprint("A smoky form begins to coalesce....");
291 	  summon(-1,-1);
292 	  mprint("Fortunately, it seems confined to the pentagram.");
293 	  m_status_reset(Level->mlist->m,MOBILE);
294 	  break;
295 	case ROOMBASE+29: /* blue omega room */
296 	  mprint("The Lords of Destiny look upon you....");
297 	  if (Player.level > 10) {
298 	    mprint("A curtain of blue flames leaps up from the omega.");
299 	    morewait();
300 	    l_adept();
301 	  }
302 	  else {
303 	    if (Player.patron == DESTINY) {
304 	      mprint("Your patrons take pity on you.");
305 	      if ((Player.rank[PRIESTHOOD]<SPRIEST) &&
306 		  (! find_item(&symbol,ARTIFACTID+19,-1))) {
307 		symbol = ((pob) checkmalloc(sizeof(objtype)));
308 		*symbol = Objects[ARTIFACTID+19];
309 		symbol->known = 2;
310 		symbol->charge = 17;
311 		gain_item(symbol);
312 		mprint("You feel uplifted.");
313 	      }
314 	      else gain_experience(min(1000,Player.xp));
315 	    }
316 	    else if (random_range(3)==1) {
317 	      mprint("You feel Fated.");
318 	      gain_experience(Player.level*Player.level*10);
319 	      Player.hp = max(Player.hp, Player.maxhp);
320 	    }
321 	    else if (random_range(2)) {
322 	      mprint("You feel Doomed.");
323 	      Player.hp = 1;
324 	      Player.mana = 0;
325 	      Player.xp = 0;
326 	    }
327 	    else mprint("The Lords of Destiny laugh at you!");
328 	  }
329 	  break;
330 	default:
331 	  mprint("Well, not much effect. Chalk it up to experience.");
332 	  gain_experience(Player.level*5);
333 	  break;
334 	}
335       }
336     }
337     else {
338       if (RitualRoom == Level->site[Player.x][Player.y].roomnumber)
339 	mprint("The ritual fails for some unexplainable reason.");
340       else {
341 	mprint("The ritual seems to be generating some spell effect.");
342 	RitualRoom = Level->site[Player.x][Player.y].roomnumber;
343 	switch (RitualRoom) {
344 	case RS_WALLSPACE:
345 	  shadowform();
346 	  break;
347 	case RS_CORRIDOR:
348 	  haste(0);
349 	  break;
350 	case RS_PONDS:
351 	  breathe(0);
352 	  break;
353 	case RS_ADEPT:
354 	  hero(1);
355 	  break;
356 	default:
357 	  mprint("The ritual doesn't seem to produce any tangible results...");
358 	  gain_experience(Player.level*6);
359 	}
360       }
361     }
362   }
363 }
364 
365 
366 
s_apport()367 void s_apport()
368 {
369   apport(0);
370 }
371 
s_shadowform()372 void s_shadowform()
373 {
374   shadowform();
375 }
376 
s_alert()377 void s_alert()
378 {
379   alert(0);
380 }
381 
s_regenerate()382 void s_regenerate()
383 {
384   regenerate(0);
385 }
386 
s_clairvoyance()387 void s_clairvoyance()
388 {
389   clairvoyance(10);
390 }
391 
s_drain()392 void s_drain()
393 {
394   drain(0);
395 }
396 
s_levitate()397 void s_levitate()
398 {
399   levitate(0);
400 }
401 
s_polymorph()402 void s_polymorph()
403 {
404   polymorph(0);
405 }
406 
407 
408 /* lball spell */
s_lball()409 void s_lball()
410 {
411   int x=Player.x,y=Player.y;
412   setspot(&x,&y);
413   lball(Player.x,Player.y,x,y,Player.level*10+10);
414 }
415 
s_identify()416 void s_identify()
417 {
418   identify(0);
419 }
420 
s_objdet()421 void s_objdet()
422 {
423   objdet(1);
424 }
425 
s_mondet()426 void s_mondet()
427 {
428   mondet(1);
429 }
430 
431 
432 /* select a spell to cast */
getspell()433 int getspell()
434 {
435   int spell= ABORT - 1;
436 
437   do {
438     mprint("Cast Spell: [type spell abbrev, ?, or ESCAPE]: ");
439     spell = spellparse();
440   } while (spell < ABORT);
441   return(spell);
442 }
443 
444 
spellid(id)445 char *spellid(id)
446 int id;
447 {
448   switch(id) {
449     case S_MON_DET:return("monster detection");
450     case S_OBJ_DET:return("object detection");
451     case S_IDENTIFY:return("identification");
452     case S_FIREBOLT:return("firebolt");
453     case S_LBALL:return("ball lightning");
454     case S_SLEEP:return("sleep");
455     case S_DISRUPT:return("disrupt");
456     case S_DISINTEGRATE:return("disintegrate");
457     case S_TELEPORT:return("teleport");
458     case S_MISSILE:return("magic missile");
459     case S_HEAL:return("healing");
460     case S_DISPEL:return("dispelling");
461     case S_BREATHE:return("breathing");
462     case S_INVISIBLE:return("invisibility");
463     case S_WARP:return("the warp");
464     case S_ENCHANT:return("enchantment");
465     case S_BLESS:return("blessing");
466     case S_RESTORE:return("restoration");
467     case S_CURE:return("curing");
468     case S_TRUESIGHT:return("true sight");
469     case S_HELLFIRE:return("hellfire");
470     case S_KNOWLEDGE:return("self knowledge");
471     case S_HERO:return("heroism");
472     case S_RETURN:return("return");
473     case S_DESECRATE:return("desecration");
474     case S_HASTE:return("haste");
475     case S_SUMMON:return("summoning");
476     case S_SANCTUARY:return("sanctuary");
477     case S_ACCURACY:return("accuracy");
478     case S_RITUAL:return("ritual magic");
479     case S_APPORT:return("apportation");
480     case S_SHADOWFORM:return("shadow form");
481     case S_ALERT:return("alertness");
482     case S_REGENERATE:return("regeneration");
483     case S_SANCTIFY:return("sanctification");
484     case S_CLAIRVOYANCE:return("clairvoyance");
485     case S_DRAIN:return("energy drain");
486     case S_LEVITATE:return("levitate");
487     case S_POLYMORPH:return("polymorph");
488     case S_FEAR:return("fear");
489     case S_WISH:return("wishing");
490     default:return("???");
491   }
492 }
493 
494 
495 
initspells()496 void initspells()
497 {
498   int i;
499 
500   for (i=0; i<NUMSPELLS; i++)
501     Spells[i].known = FALSE;
502 
503   Spells[S_MON_DET].powerdrain = 3;
504   Spells[S_MON_DET].id = S_MON_DET;
505 
506   Spells[S_OBJ_DET].powerdrain = 3;
507   Spells[S_OBJ_DET].id = S_OBJ_DET;
508 
509   Spells[S_IDENTIFY].powerdrain = 10;
510   Spells[S_IDENTIFY].id = S_IDENTIFY;
511 
512   Spells[S_FIREBOLT].powerdrain = 20;
513   Spells[S_FIREBOLT].id = S_FIREBOLT;
514 
515   Spells[S_SLEEP].powerdrain = 15;
516   Spells[S_SLEEP].id = S_SLEEP;
517 
518   Spells[S_LBALL].powerdrain = 25;
519   Spells[S_LBALL].id = S_LBALL;
520 
521   Spells[S_TELEPORT].powerdrain = 20;
522   Spells[S_TELEPORT].id = S_TELEPORT;
523 
524   Spells[S_DISRUPT].powerdrain = 30;
525   Spells[S_DISRUPT].id = S_DISRUPT;
526 
527   Spells[S_DISINTEGRATE].powerdrain = 40;
528   Spells[S_DISINTEGRATE].id = S_DISINTEGRATE;
529 
530   Spells[S_MISSILE].powerdrain = 10;
531   Spells[S_MISSILE].id = S_MISSILE;
532 
533   Spells[S_HEAL].powerdrain = 15;
534   Spells[S_HEAL].id = S_HEAL;
535 
536   Spells[S_DISPEL].powerdrain = 40;
537   Spells[S_DISPEL].id = S_DISPEL;
538 
539   Spells[S_BREATHE].powerdrain = 20;
540   Spells[S_BREATHE].id = S_BREATHE;
541 
542   Spells[S_INVISIBLE].powerdrain = 15;
543   Spells[S_INVISIBLE].id = S_INVISIBLE;
544 
545   Spells[S_WARP].powerdrain = 50;
546   Spells[S_WARP].id = S_WARP;
547 
548   Spells[S_ENCHANT].powerdrain = 30;
549   Spells[S_ENCHANT].id = S_ENCHANT;
550 
551   Spells[S_BLESS].powerdrain = 30;
552   Spells[S_BLESS].id = S_BLESS;
553 
554   Spells[S_RESTORE].powerdrain = 20;
555   Spells[S_RESTORE].id = S_RESTORE;
556 
557   Spells[S_CURE].powerdrain = 20;
558   Spells[S_CURE].id = S_CURE;
559 
560   Spells[S_TRUESIGHT].powerdrain = 20;
561   Spells[S_TRUESIGHT].id = S_TRUESIGHT;
562 
563   Spells[S_HELLFIRE].powerdrain = 90;
564   Spells[S_HELLFIRE].id = S_HELLFIRE;
565 
566   Spells[S_KNOWLEDGE].powerdrain = 10;
567   Spells[S_KNOWLEDGE].id = S_KNOWLEDGE;
568 
569   Spells[S_HERO].powerdrain = 20;
570   Spells[S_HERO].id = S_HERO;
571 
572   Spells[S_RETURN].powerdrain = 10;
573   Spells[S_RETURN].id = S_RETURN;
574 
575   Spells[S_DESECRATE].powerdrain = 50;
576   Spells[S_DESECRATE].id = S_DESECRATE;
577 
578   Spells[S_HASTE].powerdrain = 15;
579   Spells[S_HASTE].id = S_HASTE;
580 
581   Spells[S_SUMMON].powerdrain = 20;
582   Spells[S_SUMMON].id = S_SUMMON;
583 
584   Spells[S_SANCTUARY].powerdrain = 75;
585   Spells[S_SANCTUARY].id = S_SANCTUARY;
586 
587   Spells[S_ACCURACY].powerdrain = 20;
588   Spells[S_ACCURACY].id = S_ACCURACY;
589 
590   Spells[S_RITUAL].powerdrain = 50;
591   Spells[S_RITUAL].id = S_RITUAL;
592 
593   Spells[S_APPORT].powerdrain = 15;
594   Spells[S_APPORT].id = S_APPORT;
595 
596   Spells[S_SHADOWFORM].powerdrain = 50;
597   Spells[S_SHADOWFORM].id = S_SHADOWFORM;
598 
599   Spells[S_ALERT].powerdrain = 15;
600   Spells[S_ALERT].id = S_ALERT;
601 
602   Spells[S_REGENERATE].powerdrain = 20;
603   Spells[S_REGENERATE].id = S_REGENERATE;
604 
605   Spells[S_SANCTIFY].powerdrain = 75;
606   Spells[S_SANCTIFY].id = S_SANCTIFY;
607 
608   Spells[S_CLAIRVOYANCE].powerdrain = 10;
609   Spells[S_CLAIRVOYANCE].id = S_CLAIRVOYANCE;
610 
611   Spells[S_DRAIN].powerdrain = 40;
612   Spells[S_DRAIN].id = S_DRAIN;
613 
614   Spells[S_LEVITATE].powerdrain = 25;
615   Spells[S_LEVITATE].id = S_LEVITATE;
616 
617   Spells[S_POLYMORPH].powerdrain = 30;
618   Spells[S_POLYMORPH].id = S_POLYMORPH;
619 
620   Spells[S_FEAR].powerdrain = 10;
621   Spells[S_FEAR].id = S_FEAR;
622 
623   Spells[S_WISH].powerdrain = 100;
624   Spells[S_WISH].id = S_WISH;
625 
626 }
627 
628 
629 
630 
631 
632 
cast_spell(spell)633 void cast_spell(spell)
634 int spell;
635 {
636   switch(spell) {
637   case S_MON_DET:s_mondet();
638     break;
639   case S_OBJ_DET:s_objdet();
640     break;
641   case S_IDENTIFY:s_identify();
642     break;
643   case S_FIREBOLT:s_firebolt();
644     break;
645   case S_SLEEP:s_sleep();
646     break;
647   case S_LBALL:s_lball();
648     break;
649   case S_TELEPORT:s_teleport();
650     break;
651   case S_DISRUPT:s_disrupt();
652     break;
653   case S_DISINTEGRATE:s_disintegrate();
654     break;
655   case S_MISSILE:s_missile();
656     break;
657   case S_HEAL:s_heal();
658     break;
659   case S_DISPEL:s_dispel();
660     break;
661   case S_BREATHE:s_breathe();
662     break;
663   case S_INVISIBLE:s_invisible();
664     break;
665   case S_WARP:s_warp();
666     break;
667   case S_ENCHANT:s_enchant();
668     break;
669   case S_BLESS:s_bless();
670     break;
671   case S_RESTORE:s_restore();
672     break;
673   case S_CURE:s_cure();
674     break;
675   case S_TRUESIGHT:s_truesight();
676     break;
677   case S_HELLFIRE:s_hellfire();
678     break;
679   case S_KNOWLEDGE:s_knowledge();
680     break;
681   case S_HERO:s_hero();
682     break;
683   case S_RETURN:s_return();
684     break;
685   case S_DESECRATE:s_desecrate();
686     break;
687   case S_HASTE:s_haste();
688     break;
689   case S_SUMMON:s_summon();
690     break;
691   case S_SANCTUARY:s_sanctuary();
692     break;
693   case S_ACCURACY:s_accuracy();
694     break;
695   case S_RITUAL:s_ritual();
696     break;
697   case S_APPORT:s_apport();
698     break;
699   case S_SHADOWFORM:s_shadowform();
700     break;
701   case S_ALERT:s_alert();
702     break;
703   case S_REGENERATE:s_regenerate();
704     break;
705   case S_SANCTIFY:s_sanctify();
706     break;
707   case S_CLAIRVOYANCE:s_clairvoyance();
708     break;
709   case S_DRAIN:s_drain();
710     break;
711   case S_LEVITATE:s_levitate();
712     break;
713   case S_FEAR:s_fear();
714     break;
715   case S_POLYMORPH:s_polymorph();
716     break;
717   case S_WISH:s_wish();
718     break;
719   default: mprint("Your odd spell fizzles with a small 'sput'.");
720     break;
721   }
722 }
723 
724 
725 
726 static char *spell_names[] = {		/* alphabetical listing */
727 "accuracy", "alertness", "apportation", "ball lightning", "blessing",
728 "breathing", "clairvoyance", "curing", "desecration", "disintegrate",
729 "dispelling", "disrupt", "enchantment", "energy drain", "fear", "firebolt",
730 "haste", "healing", "hellfire", "heroism", "identification", "invisibility",
731 "levitate", "magic missile", "monster detection", "object detection",
732 "polymorph", "regeneration", "restoration", "return", "ritual magic",
733 "sanctification", "sanctuary", "self knowledge", "shadow form", "sleep",
734 "summoning", "teleport", "the warp", "true sight", "wishing" };
735 
736 static int spell_ids[] = {	/* in the same order as spell_names[] */
737 S_ACCURACY, S_ALERT, S_APPORT, S_LBALL, S_BLESS, S_BREATHE, S_CLAIRVOYANCE,
738 S_CURE, S_DESECRATE, S_DISINTEGRATE, S_DISPEL, S_DISRUPT, S_ENCHANT, S_DRAIN,
739 S_FEAR, S_FIREBOLT, S_HASTE, S_HEAL, S_HELLFIRE, S_HERO, S_IDENTIFY,
740 S_INVISIBLE, S_LEVITATE, S_MISSILE, S_MON_DET, S_OBJ_DET, S_POLYMORPH,
741 S_REGENERATE, S_RESTORE, S_RETURN, S_RITUAL, S_SANCTIFY, S_SANCTUARY,
742 S_KNOWLEDGE, S_SHADOWFORM, S_SLEEP, S_SUMMON, S_TELEPORT, S_WARP, S_TRUESIGHT,
743 S_WISH };
744 
showknownspells(first,last)745 void showknownspells(first, last)
746 int first, last;
747 {
748   int i,printed=FALSE;
749 
750   menuclear();
751   menuprint("\nPossible Spells:\n");
752   for (i = first; i <= last; i++)
753     if (Spells[spell_ids[i]].known) {
754       printed = TRUE;
755       menuprint(spell_names[i]);
756       menuprint(" (");
757       menunumprint(Spells[spell_ids[i]].powerdrain);
758       menuprint(" mana)");
759       menuprint("\n");
760     }
761   if (! printed)
762     menuprint("\nNo spells match that prefix!");
763   showmenu();
764 }
765 
spellparse()766 int spellparse()
767 {
768   int first, last, pos;
769   char byte, prefix[80];
770   int found = 0;
771   int f, l;
772 
773   first = 0;
774   while (first < NUMSPELLS && !Spells[spell_ids[first]].known)
775     first++;
776   if (first == NUMSPELLS) {
777     print1("You don't know any spells!");
778     return ABORT;
779   }
780   last = NUMSPELLS - 1;
781   pos = 0;
782   print2("");
783   do {
784     byte = mgetc();
785     if (byte == BACKSPACE || byte == DELETE) {
786       if (pos > 0) {
787         prefix[--pos] = '\0';
788 	byte = prefix[pos - 1];
789 	f = first;
790 	while (f >= 0 && !strncmp(prefix, spell_names[f], pos)) {
791 	  if (Spells[spell_ids[f]].known)
792 	    first = f;
793 	  f--;
794 	}
795 	l = last;
796 	while (l < NUMSPELLS && !strncmp(prefix, spell_names[l], pos)) {
797 	  if (Spells[spell_ids[l]].known)
798 	    last = l;
799 	  l++;
800 	}
801 	if (found)
802 	  found = 0;
803 	print2(prefix);
804       }
805       if (pos == 0) {
806 	first = 0;
807 	last = NUMSPELLS - 1;
808 	found = 0;
809 	print2("");
810       }
811     }
812     else if (byte == ESCAPE) {
813       xredraw();
814       return ABORT;
815     }
816     else if (byte == '?')
817       showknownspells(first, last);
818     else if (byte != '\n') {
819       if (byte >= 'A' && byte <= 'Z')
820 	byte += 'a' - 'A';
821       if (found)
822 	continue;
823       f = first;
824       l = last;
825       while (f < NUMSPELLS &&
826 	  (!Spells[spell_ids[f]].known ||
827 	  strlen(spell_names[f]) < pos || spell_names[f][pos] < byte))
828 	f++;
829       while (l >= 0 && (!Spells[spell_ids[l]].known ||
830 	  strlen(spell_names[l]) < pos || spell_names[l][pos] > byte))
831 	l--;
832       if (l < f)
833 	continue;
834       prefix[pos++] = byte;
835       prefix[pos] = '\0';
836       nprint2(prefix + pos - 1);
837       first = f;
838       last = l;
839       if (first == last && !found) {	/* unique name */
840 	found = 1;
841 	nprint2(spell_names[first] + pos);
842       }
843     }
844   } while (byte != '\n');
845   xredraw();
846   if (found)
847     return spell_ids[first];
848   else {
849     print3("That is an ambiguous abbreviation!");
850     return ABORT;
851   }
852 }
853