1 /* omega copyright (C) by Laurence Raphael Brothers, 1987,1988,1989 */
2 /* effect3.c */
3 
4 #include "glob.h"
5 
6 /* if know id, then summon that monster; else (if < 0) get one. */
summon(blessing,id)7 void summon(blessing,id)
8 int blessing,id;
9 {
10   int i,looking=TRUE,x,y;
11   pml tml;
12 
13   if (id < 0) {
14     if (blessing > 0) {
15       id = monsterlist();
16       xredraw();
17     }
18     /* for (id ==0) case, see below -- get a "fair" monster */
19     else if (blessing < 0) id = random_range(NUMMONSTERS);
20   }
21   for(i=0;((i<8) && looking);i++) {
22     x = Player.x+Dirs[0][i];
23     y = Player.y+Dirs[1][i];
24     looking = ((! inbounds(x,y)) ||
25 	       (Level->site[x][y].locchar != FLOOR) ||
26 	       (Level->site[x][y].creature != NULL));
27   }
28 
29   if (! looking) {
30     if ((blessing == 0) && (id < 0))
31       Level->site[x][y].creature = m_create(x,y,WANDERING,difficulty());
32     else Level->site[x][y].creature = make_creature(id);
33     Level->site[x][y].creature->x = x;
34     Level->site[x][y].creature->y = y;
35     tml = ((pml) checkmalloc(sizeof(mltype)));
36     tml->m = Level->site[x][y].creature;
37     if (blessing > 0)
38       m_status_reset(tml->m,HOSTILE);
39     else if (blessing < 0)
40       m_status_set(tml->m,HOSTILE);
41     tml->next = Level->mlist;
42     Level->mlist = tml;
43   }
44 }
45 
46 
47 
itemlist(itemindex,num)48 int itemlist(itemindex,num)
49 int itemindex,num;
50 {
51   int i,itemno;
52 
53   print2("Show ID list? ");
54   if (ynq2() == 'y') {
55     menuclear();
56     for(i=0;i<num;i++) {
57       menunumprint(i+1);
58       menuprint(":");
59       menuprint(Objects[i+itemindex].truename);
60       menuprint("\n");
61     }
62     showmenu();
63   }
64   mprint("Item ID? ");
65   itemno = (int) parsenum()-1;
66   if ((itemno >= num)||(itemno<0)) itemno = ABORT;
67   return(itemno);
68 }
69 
monsterlist()70 int monsterlist()
71 {
72   int i,itemno;
73   print2("Show ID list? ");
74   if (ynq2() == 'y')
75     do {
76       clearmsg();
77       print1("Summon monster: ");
78       menuclear();
79       for(i=0;i<NUMMONSTERS;i++) {
80 	menunumprint(i+1);
81 	menuprint(":");
82 	menuprint(Monsters[i].monstring);
83 	menuprint("\n");
84       }
85       showmenu();
86       itemno = (int) parsenum()-1;
87       if ((itemno < 0) || (itemno > NUMMONSTERS-1)) {
88 	print3("How about trying a real monster?");
89 	morewait();
90       }
91     } while ((itemno < 0) || (itemno > NUMMONSTERS-1));
92   else
93     do {
94       print1("Summon monster: ");
95       itemno = (int) parsenum()-1;
96     } while ((itemno < 0) || (itemno > NUMMONSTERS-1));
97   return(itemno);
98 }
99 
100 
101 
102 /* uncurse all items, cure diseases, and neutralize poison */
cleanse(blessing)103 void cleanse(blessing)
104 int blessing;
105 {
106   int i;
107 
108   if (blessing > -1) {
109     if (blessing > 0)
110       for(i=0;i<MAXITEMS;i++)
111 	if (Player.possessions[i] != NULL) {
112 	  if ((Player.possessions[i]->used) &&
113 	      (Player.possessions[i]->blessing < 0)) {
114 	    Player.possessions[i]->used = FALSE;
115 	    item_use(Player.possessions[i]);
116 	    Player.possessions[i]->blessing = 0;
117 	    Player.possessions[i]->used = TRUE;
118 	    item_use(Player.possessions[i]);
119 	  }
120 	}
121 
122     if (Player.status[POISONED] > 0) {
123       Player.status[POISONED] = 0;
124     }
125     if (Player.status[DISEASED] > 0) {
126       Player.status[DISEASED] = 0;
127     }
128     showflags();
129     mprint("You feel radiant!");
130   }
131   else {
132     Player.status[POISONED] += 10;
133     Player.status[DISEASED] += 10;
134     mprint("You feel besmirched!");
135     showflags();
136   }
137 }
138 
annihilate(blessing)139 void annihilate(blessing)
140 int blessing;
141 {
142   pml ml;
143   int i;
144 
145   if (blessing == 0) {
146     mprint("Lightning strikes flash all around you!!!");
147     for(i=0;i<9;i++)
148       if (Level->site[Player.x+Dirs[0][i]][Player.y+Dirs[1][i]].creature !=
149 	  NULL)
150 	m_death(Level->site[Player.x+Dirs[0][i]][Player.y+Dirs[1][i]].creature);
151   }
152   if (blessing > 0) {
153     if (Current_Environment == E_COUNTRYSIDE) {
154 	clearmsg();
155 	print1("Bolts of lightning flash down for as far as you can see!!!");
156 	morewait();
157 	print1("There is a rain of small birds and insects from the sky, and you");
158 	print2("notice that you can't hear any animal noises around here any more...");
159 	Player.alignment -= 3;
160     }
161     else {
162       mprint("Thousands of bolts of lightning flash throughout the level!!!");
163       for(ml=Level->mlist;ml!=NULL;ml=ml->next)
164 	if (ml->m != NULL && ml->m->hp > 0)
165 	  m_death(ml->m);
166     }
167   }
168   else {
169     mprint("You are hit by a bolt of mystic lightning!");
170     p_death("self-annihilation");
171   }
172 }
173 
174 
175 
176 
sleep_monster(blessing)177 void sleep_monster(blessing)
178 int blessing;
179 {
180   pml ml;
181   int x=Player.x,y=Player.y;
182   struct monster *target;
183 
184   if (blessing == 0) setspot(&x,&y);
185 
186   if (blessing < 0)
187     sleep_player(abs(blessing)+2);
188   else if (blessing > 0) {
189     mprint("A silence pervades the area.");
190     for (ml=Level->mlist;ml!=NULL;ml=ml->next) {
191       m_status_reset(ml->m,AWAKE);
192       ml->m->wakeup = 0;
193     }
194   }
195   else {
196     target = Level->site[x][y].creature;
197     if (target != NULL) {
198       if (target->uniqueness == COMMON) {
199 	strcpy(Str1,"The ");
200 	strcat(Str1,target->monstring);
201       }
202       else strcpy(Str1,target->monstring);
203       if (! m_immunityp(target,SLEEP)) {
204 	strcat(Str1," seems to have fallen asleep.");
205 	m_status_reset(target,AWAKE);
206 	target->wakeup = 0;
207       }
208       else strcat(Str1," is bright eyed, and bushy tailed!");
209       mprint(Str1);
210     }
211     else mprint("Nothing to sleep there!");
212   }
213 }
214 
sleep_player(amount)215 void sleep_player(amount)
216 int amount;
217 {
218   if (Player.status[SLEPT] == 0) { /* prevent player from sleeping forever */
219     mprint("You feel sleepy...");
220     if (! p_immune(SLEEP)) {
221       Player.status[SLEPT] += random_range(amount*2)+2;
222     }
223     else mprint("but you shrug off the momentary lassitude.");
224   }
225 }
226 
227 
hide(x,y)228 void hide(x,y)
229 int x,y;
230 {
231   if (inbounds(x,y)) {
232     lset(x,y,SECRET);
233     lset(x, y, CHANGED);
234     putspot(x, y, WALL);
235     mprint("You feel sneaky.");
236   }
237 }
238 
clairvoyance(vision)239 void clairvoyance(vision)
240 int vision;
241 {
242   int i,j;
243   int x = Player.x, y = Player.y;
244   mprint("Clairvoyance... ");
245   setspot(&x,&y);
246   for(i=x-vision;i<x+vision+1;i++)
247     for(j=y-vision;j<y+vision+1;j++) {
248       if (inbounds(i,j)) {
249 	Level->site[i][j].showchar = SPACE;
250 	lreset(i,j,SECRET);
251 	lset(i, j, CHANGED);
252 	dodrawspot(i,j);
253       }
254     }
255   levelrefresh();
256 }
257 
aggravate()258 void aggravate()
259 {
260   pml tm;
261 
262   for (tm=Level->mlist;tm!=NULL;tm=tm->next){
263     m_status_set(tm->m,AWAKE);
264     m_status_set(tm->m,HOSTILE);
265   }
266 }
267 
268 
269 
270 
learnspell(blessing)271 void learnspell(blessing)
272 int blessing;
273 {
274   int i,spell,done=FALSE;
275   if (blessing < 0) {
276     for(i=NUMSPELLS;((i>-1) && (! done));i--)
277       if (Spells[i].known) {
278 	done = TRUE;
279 	Objects[SCROLLID+1].known = TRUE;
280 	mprint("You feel forgetful.");
281 	Spells[i].known = FALSE;
282       }
283     if (i == ABORT)
284       mprint("You feel fortunate.");
285   }
286   else {
287     Objects[SCROLLID+1].known = TRUE;
288     spell = random_range(NUMSPELLS);
289     print1("Spell Research");
290     if ((random_range(4*Spells[spell].powerdrain)+
291 	 Spells[spell].powerdrain) <
292 	(4*Player.iq+8*Player.level)) {
293       nprint1(" -- Research successful: ");
294       nprint1(spellid(spell));
295       if (Spells[spell].known) {
296 	print2("...is now easier to cast.");
297 	Spells[spell].powerdrain = ((int) ((Spells[spell].powerdrain+1)/2));
298       }
299       else {
300 	print2("...is added to your repertoire");
301 	Spells[spell].known = TRUE;
302 	gain_experience(Spells[spell].powerdrain*10);
303       }
304     }
305     else nprint1(" -- Research unsuccessful.");
306   }
307 }
308 
309 
amnesia()310 void amnesia()
311 {
312   int i,j;
313   for (j=0;j<LENGTH;j++)
314     for (i=0;i<WIDTH;i++)
315       lreset(i,j,SEEN);
316 
317   erase_level();
318   drawvision(Player.x,Player.y);
319 }
320 
321 
322 /*affects player only */
level_drain(levels,source)323 void level_drain(levels,source)
324 int levels;
325 char *source;
326 {
327   int decrement = ((int) (Player.maxhp / (Player.level+1)));
328 
329   Player.level -= levels;
330 
331   Player.maxhp -= (levels * decrement);
332   Player.hp -= (levels * decrement);
333 
334   if ((Player.hp < 1) || (Player.level < 0))
335     p_death(source);
336 }
337 
338 
339 
340 
disrupt(x,y,amount)341 void disrupt(x,y,amount)
342 int x,y,amount;
343 {
344   struct monster *target;
345 
346   if ((x ==Player.x) && (y==Player.y)) {
347     mprint("You feel disrupted!");
348     p_damage(amount,NORMAL_DAMAGE,"magical disruption");
349   }
350   else {
351     target = Level->site[x][y].creature;
352     if (target != NULL) {
353       if (target->uniqueness == COMMON) {
354 	strcpy(Str1,"The ");
355 	strcat(Str1,target->monstring);
356       }
357       else strcpy(Str1,target->monstring);
358       if (! m_immunityp(target,NORMAL_DAMAGE)) {
359 	strcat(Str1," was blasted!");
360 	mprint(Str1);
361 	m_damage(target,amount,NORMAL_DAMAGE);
362 	target->wakeup = 0;
363       }
364       else {
365 	strcat(Str1," does not seem affected.");
366 	mprint(Str1);
367       }
368     }
369   }
370 }
371 
372 
373 
374 
disintegrate(x,y)375 void disintegrate(x,y)
376 int x,y;
377 {
378   struct monster *target;
379   if (! inbounds(x,y)) mprint("You feel a sense of wastage.");
380   else if ((x==Player.x)&&(y==Player.y)) {
381     if (Player.possessions[O_CLOAK] != NULL) {
382       mprint("Your cloak disintegrates!");
383       dispose_lost_objects(1,Player.possessions[O_CLOAK]);
384     }
385     else if (Player.possessions[O_ARMOR] != NULL) {
386       mprint("Your armor disintegrates!");
387       dispose_lost_objects(1,Player.possessions[O_ARMOR]);
388     }
389     else {
390       mprint("Uh, oh....");
391       mprint("Zzzap! You've been disintegrated!");
392       p_damage(250,UNSTOPPABLE,"disintegration");
393     }
394   }
395   else {
396     if (!view_los_p(Player.x, Player.y, x, y))
397       setgamestatus(SUPPRESS_PRINTING);
398     if ((target = Level->site[x][y].creature) != NULL) {
399       if (target->uniqueness == COMMON) {
400 	strcpy(Str1,"The ");
401 	strcat(Str1,target->monstring);
402       }
403       else strcpy(Str1,target->monstring);
404       strcat(Str1," disintegrates!");
405       mprint(Str1);
406       m_damage(target,100,UNSTOPPABLE);
407       if (target->hp > 0) mprint("It was partially protected by its armor.");
408     }
409     else if (Level->site[x][y].locchar == ALTAR) {
410       mprint("Zzzzap! the altar seems unaffected...");
411       mprint("But an angry deity retaliates....");
412       disintegrate(Player.x,Player.y);
413     }
414     else if (Level->site[x][y].p_locf == L_TRAP_PIT) {
415       if (Current_Environment == Current_Dungeon) {
416 	mprint("A hole is blasted in the base of the pit!");
417 	Level->site[x][y].locchar = TRAP;
418 	Level->site[x][y].p_locf = L_TRAP_DOOR;
419 	Level->site[x][y].aux = S_DISINTEGRATE;
420 	lset(x, y, CHANGED);
421       }
422       else mprint("The hole just gets deeper....");
423     }
424     else if (Level->site[x][y].locchar == FLOOR) {
425       mprint("You zap a hole in the floor!");
426       Level->site[x][y].locchar = TRAP;
427       Level->site[x][y].p_locf = L_TRAP_PIT;
428       lset(x, y, CHANGED);
429     }
430     else if ((Level->site[x][y].locchar == WALL) ||
431 	     (Level->site[x][y].locchar == OPEN_DOOR) ||
432 	     (Level->site[x][y].locchar == CLOSED_DOOR) ||
433 	     (Level->site[x][y].locchar == PORTCULLIS) ||
434 	     (Level->site[x][y].locchar == STATUE)) {
435       mprint("The site is reduced to rubble!");
436       if (Level->site[x][y].locchar == WALL)
437 	tunnelcheck();
438       Level->site[x][y].p_locf = L_RUBBLE;
439       Level->site[x][y].locchar = RUBBLE;
440       lreset(x,y,SECRET);
441       lset(x, y, CHANGED);
442     }
443     else if ((Level->site[x][y].locchar == RUBBLE) ||
444 	     (Level->site[x][y].locchar == TRAP)) {
445       mprint("The site is blasted clear!");
446       Level->site[x][y].p_locf = L_NO_OP;
447       Level->site[x][y].locchar = FLOOR;
448       lreset(x,y,SECRET);
449       lset(x, y, CHANGED);
450     }
451     else if (Level->site[x][y].locchar == HEDGE) {
452       if (Level->site[x][y].p_locf == L_TRIFID) {
453 	mprint("The trifid screams as it disintgrates!");
454 	gain_experience(50);
455 	Level->site[x][y].p_locf = L_NO_OP;
456 	Level->site[x][y].locchar = FLOOR;
457 	lreset(x,y,SECRET);
458 	lset(x, y, CHANGED);
459       }
460       else {
461 	mprint("The hedge is blasted away!");
462 	Level->site[x][y].p_locf = L_NO_OP;
463 	Level->site[x][y].locchar = FLOOR;
464 	lreset(x,y,SECRET);
465 	lset(x, y, CHANGED);
466       }
467     }
468     else mprint("The blast has no effect.");
469     if (!view_los_p(Player.x, Player.y, x, y))
470       resetgamestatus(SUPPRESS_PRINTING);
471     else
472       plotspot(x, y, TRUE);
473   }
474 }
475 
acid_cloud()476 void acid_cloud()
477 {
478   mprint("You are caught in an acid cloud!  ");
479   if (Player.possessions[O_CLOAK] != NULL) {
480     (void) damage_item(Player.possessions[O_CLOAK]);
481     mprint("You are burned by acid.");
482     p_damage(3,ACID,"an acid cloud");
483   }
484   else if (Player.possessions[O_ARMOR] != NULL) {
485     mprint("You are burned by acid.");
486     p_damage(3,ACID,"an acid cloud");
487     (void) damage_item(Player.possessions[O_ARMOR]);
488   }
489   else if (p_immune(ACID))
490   {
491     mprint("You resist the effects!");
492     return;
493   }
494   else {
495     mprint("The acid eats away at your bare skin!");
496     p_damage(25,ACID,"an acid cloud");
497   }
498 }
499 
500 
501 
502 /* teleport player */
p_teleport(type)503 void p_teleport(type)
504 int type;
505 {
506   int x=Player.x,y=Player.y;
507   drawspot(x,y);
508   if (type < 0) {
509     x = random_range(WIDTH);
510     y = random_range(LENGTH);
511     if ((Level->site[x][y].locchar != FLOOR) &&
512 	(Level->site[x][y].locchar != OPEN_DOOR)) {
513       mprint("You teleported into a solid object....");
514       mprint("You are dead!");
515       p_death("teleportation into a solid object");
516     }
517     else {
518       Player.x = x;
519       Player.y = y;
520     }
521   }
522   else if (type == 0)
523     findspace(&(Player.x),&(Player.y),-1);
524   else {
525     setspot(&Player.x,&Player.y);
526     if ((Level->site[Player.x][Player.y].locchar != FLOOR) ||
527 	(Level->site[Player.x][Player.y].creature != NULL)) {
528       mprint("You feel deflected.");
529       p_teleport(0);
530     }
531   }
532   screencheck(Player.y);
533   roomcheck();
534 }
535 
536 
p_poison(toxicity)537 void p_poison(toxicity)
538 int toxicity;
539 {
540   mprint("You feel sick.");
541   if (! p_immune(POISON))
542     Player.status[POISONED]+=toxicity;
543   else mprint("The sickness fades!");
544   showflags();
545 }
546 
apport(blessing)547 void apport(blessing)
548 int blessing;
549 {
550   int i,index,x=Player.x,y=Player.y;
551   if (blessing > -1) {
552     mprint("Apport from:");
553     setspot(&x,&y);
554     if (Level->site[x][y].things != NULL) {
555       pickup_at(x,y);
556       plotspot(x, y, TRUE);
557     }
558     else mprint("There's nothing there to apport!");
559   }
560   else {
561     mprint("You have a sense of loss.");
562     for(i=0;i<abs(blessing);i++) {
563       index = random_item();
564       if (index != ABORT) {
565 	drop_at(x,y,Player.possessions[index]);
566 	dispose_lost_objects(Player.possessions[index]->number,
567 	  Player.possessions[index]);
568       }
569     }
570   }
571 }
572 
573 
strategic_teleport(blessing)574 void strategic_teleport(blessing)
575 int blessing;
576 {
577   int new_env;
578 
579   /* WDT HACK: Game balance issue: the star gem is supposed to be the only
580    * way out of the astral plane (including the Circle of Sorcerors).  However,
581    * Hy Magic offers the Location wish, and some artifacts grant this
582    * as well.  Seems to me that Hy Magic ought to allow it, and nothing
583    * else (aside from the Star Gem, of course). */
584   if ((Current_Environment == E_CIRCLE || Current_Environment == E_ASTRAL) &&
585       !gamestatusp(CHEATED))
586   {
587     mprint("Some property of this eerie place interferes with the magic!\n");
588     return;
589   }
590   mprint("Magic portals open up all around you!");
591   if (blessing < 0) {
592     morewait();
593     mprint("You are dragged into one!");
594     change_environment(E_COUNTRYSIDE);
595     do {
596       Player.x = random_range(WIDTH);
597       Player.y = random_range(LENGTH);
598     } while(Country[Player.x][Player.y].base_terrain_type == CHAOS_SEA);
599   }
600   else {
601     mprint("Below each portal is a caption. Enter which one:");
602     menuclear();
603     menuprint("a: Rampart\n");
604     menuprint("b: Village of Star View\n");
605     menuprint("c: Village of Woodmere\n");
606     menuprint("d: Village of Stormwatch\n");
607     menuprint("e: Village of Thaumaris\n");
608     menuprint("f: Village of Skorch\n");
609     menuprint("g: Village of Whorfen\n");
610     menuprint("h: Temple of the Noose\n");
611     menuprint("i: The Parthenon\n");
612     menuprint("j: Temple of the Black Hand\n");
613     menuprint("k: Temple of the Hidden Moon\n");
614     menuprint("l: WoodHenge\n");
615     menuprint("m: Temple of Destiny\n");
616     menuprint("n: HellWell Volcano\n");
617     if (gamestatusp(CHEATED))
618       menuprint("z: Anywhere\n");
619     menuprint("ANYTHING ELSE: Avoid entering a portal.");
620     showmenu();
621     switch((char) mcigetc()) {
622     case 'a':
623       change_environment(E_COUNTRYSIDE);
624       Player.x = 27;
625       Player.y = 19;
626       break;
627     case 'b':
628       change_environment(E_COUNTRYSIDE);
629       Player.x = 56;
630       Player.y = 5;
631       break;
632     case 'c':
633       change_environment(E_COUNTRYSIDE);
634       Player.x = 35;
635       Player.y = 11;
636       break;
637     case 'd':
638       change_environment(E_COUNTRYSIDE);
639       Player.x = 10;
640       Player.y = 40;
641       break;
642     case 'e':
643       change_environment(E_COUNTRYSIDE);
644       Player.x = 7;
645       Player.y = 6;
646       break;
647     case 'f':
648       change_environment(E_COUNTRYSIDE);
649       Player.x = 41;
650       Player.y = 43;
651       break;
652     case 'g':
653       change_environment(E_COUNTRYSIDE);
654       Player.x = 20;
655       Player.y = 41;
656       break;
657     case 'h':
658       change_environment(E_COUNTRYSIDE);
659       Player.x = 22;
660       Player.y = 30;
661       break;
662     case 'i':
663       change_environment(E_COUNTRYSIDE);
664       Player.x = 51;
665       Player.y = 11;
666       break;
667     case 'j':
668       change_environment(E_COUNTRYSIDE);
669       Player.x = 45;
670       Player.y = 45;
671       break;
672     case 'k':
673       change_environment(E_COUNTRYSIDE);
674       Player.x = 19;
675       Player.y = 46;
676       break;
677     case 'l':
678       change_environment(E_COUNTRYSIDE);
679       Player.x = 32;
680       Player.y = 5;
681       break;
682     case 'm':
683       change_environment(E_COUNTRYSIDE);
684       Player.x = 49;
685       Player.y = 59;
686       break;
687     case 'n':
688       change_environment(E_COUNTRYSIDE);
689       Player.x = 30;
690       Player.y = 58;
691       break;
692     default:
693       if (gamestatusp(CHEATED)) {
694 	mprint("Enter environment number: ");
695 	new_env = (int) parsenum();
696 	change_environment(new_env);
697       }
698     }
699     xredraw();
700     if (gamestatusp(LOST)) {
701       print1("You know where you are now.");
702       resetgamestatus(LOST);
703       Precipitation = 0;
704     }
705   }
706   setlastxy(Player.x, Player.y);
707   screencheck(Player.y);
708   drawvision(Player.x,Player.y);
709   if (Current_Environment == E_COUNTRYSIDE)
710     terrain_check(FALSE);
711 }
712 
713 
714 
hero(blessing)715 void hero(blessing)
716 int blessing;
717 {
718   if (blessing > -1) {
719       mprint("You feel super!");
720       Player.status[HERO] += random_range(5)+1+blessing;
721       calc_melee();
722     }
723   else {
724     Player.status[HERO]=0;
725     calc_melee();
726     mprint("You feel cowardly.");
727     level_drain(abs(blessing),"a potion of cowardice");
728   }
729 }
730 
731 
levitate(blessing)732 void levitate(blessing)
733 int blessing;
734 {
735   if (blessing > -1) {
736     if (gamestatusp(MOUNTED))
737       mprint("You have a strange feeling of lightness in your saddle.");
738     else {
739       mprint("You start to float a few inches above the floor.");
740       mprint("You discover you can easily control your altitude...");
741       mprint("(Note use of '@' command may be useful while levitating)");
742       Player.status[LEVITATING] += random_range(5)+1+blessing;
743     }
744   }
745   else mprint("Nothing much happens.");
746 }
747 
748 
749 /* has effect of switching between 1st level and deepest level attained */
level_return()750 void level_return()
751 {
752   if (Current_Environment == Current_Dungeon) {
753     mprint("The vortex of mana carries you off!");
754     if (Level->depth > 1)
755       change_level(Level->depth,1,FALSE);
756     else change_level(Level->depth,deepest[Current_Environment],FALSE);
757   }
758   else if (Current_Environment == E_COUNTRYSIDE) {
759     mprint("A mysterious force wafts you back home!");
760     Player.x = 27;
761     Player.y = 19;
762     screencheck(Player.y);
763     drawvision(Player.x,Player.y);
764     locprint("Back Outside Rampart.");
765   }
766   else mprint("A feeble vortex of magic swirls by and has no further effect.");
767 }
768 
769 
cure(blessing)770 void cure(blessing)
771 int blessing;
772 {
773   int happened = FALSE;
774   if (blessing > -1) {
775     if (Player.status[DISEASED]) {
776       Player.status[DISEASED]=0;
777       mprint("You feel hygienic!");
778       happened = TRUE;
779     }
780     if (Player.status[POISONED]) {
781       Player.status[POISONED] -= 5+blessing*10;
782       if (Player.status[POISONED] > 0)
783 	mprint("The effect of the poison has been reduced.");
784       else {
785 	Player.status[POISONED] = 0;
786 	mprint("The poison has been purged from your system.");
787       }
788       happened = TRUE;
789     }
790     if (Player.status[BLINDED]) {
791       Player.status[BLINDED]=0;
792       happened = TRUE;
793       mprint("Cobwebs clear from before your eyes.");
794     }
795     if (! happened) mprint("Nothing much happens.");
796   }
797   else disease(12);
798   showflags();
799 }
800 
disease(amount)801 void disease(amount)
802 int amount;
803 {
804   mprint("You feel ill.");
805   if (! Player.immunity[INFECTION]) {
806     mprint("You begin to shiver with ague.");
807     Player.status[DISEASED]+=random_range(amount*2)+1;
808   }
809   else mprint("The illness fades.");
810 }
811 
truesight(blessing)812 void truesight(blessing)
813 int blessing;
814 {
815   if (blessing > -1) {
816     Player.status[TRUESIGHT]+=random_range(10)+1;
817     mprint("You feel sharp.");
818   }
819   else {
820     Player.status[BLINDED]+=random_range(10)+1;
821     mprint("You've been blinded!");
822   }
823 }
824 
825 
826 
dispel(blessing)827 void dispel(blessing)
828 int blessing;
829 {
830   int i,x=Player.x,y=Player.y;
831   pob o;
832     if (blessing > -1) {
833       setspot(&x,&y);
834       if ((x==Player.x)&&(y==Player.y)) {
835         for(i=0;i<MAXITEMS;i++) {
836 	o = Player.possessions[i];
837 	if (o != NULL)
838 	  if ((o->used) && (o->blessing < 0)) {
839 	    if (blessing+1 + o->blessing >=0) {
840 	      o->used = FALSE;
841 	      setgamestatus(SUPPRESS_PRINTING);
842 	      item_use(o);
843 	      resetgamestatus(SUPPRESS_PRINTING);
844   	      mprint("You hear a sighing sound from");
845 	      mprint(itemid(o));
846 	      o->blessing = 0;
847 	      o->used = TRUE;
848 	      setgamestatus(SUPPRESS_PRINTING);
849 	      item_use(o);
850 	      resetgamestatus(SUPPRESS_PRINTING);
851   	    }
852   	    else {
853   	      mprint("You hear dark laughter from");
854 	      mprint(itemid(o));
855 	    }
856 	  }
857       }
858     }
859     else if (Level->site[x][y].creature != NULL) {
860       if (Level->site[x][y].creature->level < blessing * 3) {
861 	Level->site[x][y].creature->specialf = M_NO_OP;
862 	if (Level->site[x][y].creature->meleef != M_NO_OP)
863 	  Level->site[x][y].creature->meleef = M_MELEE_NORMAL;
864 	Level->site[x][y].creature->strikef = M_NO_OP;
865 	Level->site[x][y].creature->immunity=0;
866 	m_status_reset(Level->site[x][y].creature,M_INVISIBLE);
867 	m_status_reset(Level->site[x][y].creature,INTANGIBLE);
868       }
869       else mprint("The monster ignores the effect!");
870     }
871     else if ((Level->site[x][y].p_locf == L_TRAP_FIRE) ||
872 	     (Level->site[x][y].p_locf == L_STATUE_WAKE) ||
873 	     (Level->site[x][y].p_locf == L_TRAP_TELEPORT) ||
874 	     (Level->site[x][y].p_locf == L_TRAP_DISINTEGRATE)) {
875       Level->site[x][y].p_locf = L_NO_OP;
876       if (Level->site[x][y].locchar == TRAP)
877 	Level->site[x][y].locchar = FLOOR;
878       lset(x, y, CHANGED);
879     }
880     else if (Level->site[x][y].p_locf == L_MAGIC_POOL)
881       Level->site[x][y].p_locf = L_WATER;
882     else mprint("Nothing much seems to happen.");
883   }
884   else {
885     mprint("A smell of ozone and positive ions fills the air..");
886     if (Player.status[ACCURACY] && (Player.status[ACCURACY] < 1000))
887       Player.status[ACCURACY]=1;
888     if (Player.status[DISPLACED]&&(Player.status[DISPLACED] < 1000))
889 	Player.status[DISPLACED]=1;
890     if (Player.status[HASTED]&&(Player.status[HASTED] < 1000))
891       Player.status[HASTED]=1;
892     if (Player.status[BREATHING]&&(Player.status[BREATHING] < 1000))
893       Player.status[BREATHING]=1;
894     if (Player.status[INVISIBLE]&&(Player.status[INVISIBLE] < 1000))
895 	Player.status[INVISIBLE]=1;
896     if (Player.status[REGENERATING]&&(Player.status[REGENERATING] < 1000))
897       Player.status[REGENERATING]=1;
898     if (Player.status[ALERT]&&(Player.status[ALERT] < 1000))
899 	Player.status[ALERT]=1;
900     if (Player.status[HERO]&&(Player.status[HERO] < 1000))
901 	Player.status[HERO]=1;
902     if (Player.status[LEVITATING]&&(Player.status[LEVITATING] < 1000))
903 	Player.status[LEVITATING]=1;
904     if (Player.status[ACCURATE]&&(Player.status[ACCURATE] < 1000))
905 	Player.status[ACCURATE]=1;
906     if (Player.status[TRUESIGHT]&&(Player.status[TRUESIGHT] < 1000))
907 	Player.status[TRUESIGHT]=1;
908     tenminute_status_check();
909   }
910 }
911 
912 
polymorph(blessing)913 void polymorph(blessing)
914 int blessing;
915 {
916   int x=Player.x,y=Player.y,newmonster;
917   struct monster *m;
918   setspot(&x,&y);
919   clearmsg();
920   if ((x==Player.x)&&(y==Player.y)) {
921     /* WDT HACK: shouldn't this use one of the 'getarticle' functions
922      * to prevent things like "a elder grue" (should be "an elder grue")?
923      */
924     mprint("You enjoy your new life as a");
925     mprint(Monsters[random_range(NUMMONSTERS)].monstring);
926     mprint("But your game is over....");
927     p_death("polymorphing oneself");
928   }
929   else if ((m=Level->site[x][y].creature) == NULL)
930     mprint("Nothing happens.");
931   else {
932     if (m_immunityp(m,OTHER_MAGIC) || (m->level > random_range(12))) {
933       strcpy(Str1,"The ");
934       strcat(Str1,m->monstring);
935       strcat(Str1," resists the change!");
936       m_status_set(m,HOSTILE);
937     }
938     else {
939       if (blessing < 0) {
940 	do newmonster = random_range(NUMMONSTERS);
941 	while ((newmonster == NPC) ||
942 	       (newmonster == MAST_THIEF) ||
943 	       (Monsters[newmonster].level <= m->level) ||
944 	       (Monsters[newmonster].uniqueness != COMMON));
945       }
946       else {
947 	do newmonster = random_range(NUMMONSTERS);
948 	while ((newmonster == NPC) ||
949 	       (newmonster == MAST_THIEF) ||
950 	       (Monsters[newmonster].uniqueness != COMMON));
951       }
952       /* WDT HACK: most of this could (and should) be implemented by
953        * the following line: "*m = Monsters[newmonster];".  The exception,
954        * of course, are the parts where the new monster inherits the old
955        * one's abilities.  This would be better because it would be robust
956        * even in the face of additions to the monster structure. */
957       m->id = Monsters[newmonster].id;
958       m->hp = max(m->hp,Monsters[newmonster].id);
959       m->speed = Monsters[newmonster].speed;
960       m->hit = Monsters[newmonster].hit;
961       m->ac = Monsters[newmonster].ac;
962       m->dmg = Monsters[newmonster].dmg;
963       m->sense = Monsters[newmonster].sense;
964       m->wakeup = Monsters[newmonster].wakeup;
965       m->level = max(m->level,Monsters[newmonster].level);
966       m->status = Monsters[newmonster].status;
967       m->immunity = (m->immunity | Monsters[newmonster].immunity);
968       m->xpv = max(m->xpv,Monsters[newmonster].wakeup);
969       m->transformid = Monsters[newmonster].transformid;
970       m->corpsevalue = Monsters[newmonster].corpsevalue;
971       m->corpseweight = Monsters[newmonster].corpseweight;
972       m->monchar = Monsters[newmonster].monchar;
973       m->meleestr = Monsters[newmonster].meleestr;
974       m->monstring = Monsters[newmonster].monstring;
975       m->corpsestr = Monsters[newmonster].corpsestr;
976       m->talkf = Monsters[newmonster].talkf;
977       m->movef = Monsters[newmonster].movef;
978       m->meleef = Monsters[newmonster].meleef;
979       m->strikef = Monsters[newmonster].strikef;
980       m->specialf = Monsters[newmonster].specialf;
981       m_status_set(m,HOSTILE);
982     }
983   }
984 }
985 
986 
987 
988 
hellfire(x,y,blessing)989 void hellfire(x,y,blessing)
990 int x,y,blessing;
991 {
992   struct monster *m;
993   if ((x==Player.x)&&(y==Player.y)) {
994     mprint("You have been completely annihilated. Congratulations.");
995     p_death("hellfire");
996   }
997   else if ((m=Level->site[x][y].creature) == NULL) {
998     mprint("The gods are angry over your waste of power...");
999     level_drain(5,"indiscriminate use of hellfire");
1000   }
1001   else {
1002     mprint("The monster writhes in the flames...");
1003     if (blessing < 0) {
1004       mprint("...and appears stronger.");
1005       morewait();
1006       mprint("Much stronger.");
1007       m->hp += 1000;
1008       m->hit +=20;
1009       m->dmg += 100;
1010       m_status_set(m,HOSTILE);
1011     }
1012     else {
1013       if (m->uniqueness == COMMON) {
1014 	mprint("and is utterly annihilated. Only a greasy spot remains...");
1015 	m->corpsestr = "a greasy spot";
1016 	m->id = 0;
1017 	free_objlist(m->possessions);
1018 	m->possessions = NULL;
1019       }
1020       else
1021 	mprint("and dies, cursing your name and the uncaring gods....");
1022       m_death(m);
1023     }
1024   }
1025 }
1026 
1027 
drain(blessing)1028 void drain(blessing)
1029 int blessing;
1030 {
1031   int x=Player.x,y=Player.y;
1032   struct monster *m;
1033   setspot(&x,&y);
1034   mprint("You begin to drain energy...");
1035   if ((x==Player.x)&&(y==Player.y)) {
1036     mprint("You drain your own energy....");
1037     mprint("Uh, oh, positive feedback....");
1038     level_drain(Player.level,"self-vampirism");
1039   }
1040   else if ((m=Level->site[x][y].creature) != NULL) {
1041     if ((blessing > -1) && (! m_immunityp(m,NEGENERGY))) {
1042       mprint("The monster seems weaker...");
1043       m_damage(m,m->level*m->level,NEGENERGY);
1044       m->hit = max(m->hit - m->level, 1);
1045       m->dmg = max(m->dmg - m->level*m->level, 1);
1046       m->ac = max(m->ac - m->level, 1);
1047       m->level = max(1,m->level-1);
1048       mprint("You feel stronger...");
1049       gain_experience(m->level*5);
1050       Player.hp+=(m->level*m->level / 2);
1051     }
1052     else {
1053       mprint("The effect reverses itself!");
1054       mprint("The monster seems stronger...");
1055       m->hp+=Player.level*Player.level;
1056       m->hit += Player.level;
1057       m->dmg += Player.level*Player.level;
1058       m->ac += Player.level;
1059       m->level++;
1060       mprint("You feel weaker...");
1061       Player.mana = min(0,Player.level*Player.level);
1062       level_drain(m->level,"negative energy conflict");
1063     }
1064   }
1065   else if (blessing < 0) {
1066     mprint("You seem to lose energy, instead of gaining it!");
1067     level_drain(3,"reversed energy drain");
1068   }
1069   else if (Level->site[x][y].locchar == ALTAR) {
1070     mprint("The altar collapses in on itself....");
1071     Level->site[x][y].locchar = ABYSS;
1072     Level->site[x][y].p_locf = L_ABYSS;
1073     lset(x, y, CHANGED);
1074     if (! Player.patron) {
1075       mprint("You drain some theurgic energy from the altar....");
1076       gain_experience(40);
1077       Player.hp += 20;
1078       Player.pow+=2;
1079     }
1080     if (Level->site[x][y].aux == Player.patron) {
1081       mprint("Your deity is enraged.");
1082       mprint("You are struck by godsfire.");
1083       p_damage(Player.hp-1,UNSTOPPABLE,"godsfire");
1084       mprint("You feel atheistic.");
1085       Player.patron = -1;
1086       Player.rank[PRIESTHOOD] = 0;
1087     }
1088     else {
1089       mprint("You feel the wrath of a god....");
1090       p_damage(random_range(Player.level*10),UNSTOPPABLE,"divine wrath");
1091       if (Player.patron != 0) {
1092 	mprint("Your deity doesn't seem to mind your action, though.");
1093 	gain_experience(100);
1094       }
1095     }
1096   }
1097   else {
1098     mprint("You drain some energy from the ambient megaflow.");
1099     Player.hp++;
1100   }
1101 }
1102 
sanctuary()1103 void sanctuary()
1104 {
1105   if (Level->environment == E_TEMPLE)
1106     mprint("Odd, the spell has no effect. I wonder why.");
1107   else {
1108     mprint("You're standing on sacred ground!");
1109     Player.sx = Player.x;
1110     Player.sy = Player.y;
1111   }
1112 }
1113 
shadowform()1114 void shadowform()
1115 {
1116   /* WDT HACK: this fix might work, but it seems like the immunity
1117    * will be FAR too short.  It's obviously better than the old
1118    * situation, though... */
1119   if (!Player.status[SHADOWFORM]) {
1120     mprint("You feel like a shadow.");
1121     Player.immunity[NORMAL_DAMAGE]++;
1122     Player.immunity[ACID]++;
1123     Player.immunity[THEFT]++;
1124     Player.immunity[INFECTION]++;
1125     Player.status[SHADOWFORM]+=Player.level;
1126   }
1127   else {
1128     mprint("You feel even more shadowy.");
1129     Player.status[SHADOWFORM]+=Player.level;
1130   }
1131 }
1132 
illuminate(blessing)1133 void illuminate(blessing)
1134 int blessing;
1135 {
1136   int r=Level->site[Player.x][Player.y].roomnumber;
1137   if (blessing > -1) {
1138     if (r > ROOMBASE) {
1139       if (loc_statusp(Player.x,Player.y,LIT))
1140 	mprint("A glow surrounds you.");
1141       else {
1142 	mprint("The room lights up!");
1143 	Player.status[ILLUMINATION]+=blessing+3;
1144 	spreadroomlight(Player.x,
1145 			Player.y,
1146 			Level->site[Player.x][Player.y].roomnumber);
1147       }
1148     }
1149     else mprint("You see a faint glimmer of light which quickly fades.");
1150   }
1151   else {
1152     if (r > ROOMBASE) {
1153       if (! loc_statusp(Player.x,Player.y,LIT))
1154 	mprint("Nothing much happens.");
1155       else {
1156 	mprint("The room darkens!");
1157 	spreadroomdark(Player.x,
1158 		       Player.y,
1159 		       Level->site[Player.x][Player.y].roomnumber);
1160       }
1161     }
1162     else mprint("The gloom thickens for a moment.");
1163   }
1164 }
1165 
1166 
drain_life(amount)1167 void drain_life(amount)
1168 int amount;
1169 {
1170   amount = abs(amount);
1171   mprint("You feel cold!");
1172   if (p_immune(NEGENERGY))
1173     mprint("... but the feeling quickly fades.");
1174   else {
1175     if (random_range(2)) {
1176       mprint("The coldness spreads throughout your body...");
1177       Player.str-=amount;
1178       Player.con-=amount;
1179       if ((Player.str < 3) || (Player.con < 3)) {
1180 	mprint("You suffer a fatal heart attack!!!");
1181 	Player.hp = 0;
1182 	strcpy(Str2,"a coronary");
1183 	p_death(Str2);
1184       }
1185     }
1186     else {
1187       mprint("The coldness saps your very soul...");
1188       strcpy(Str2,"soul destruction");
1189       level_drain(amount,Str2);
1190     }
1191   }
1192 }
1193 
1194 
inflict_fear(x,y)1195 void inflict_fear(x,y)
1196 int x,y;
1197 {
1198   struct monster *m;
1199   if ((Player.x == x) && (Player.y == y)) {
1200     mprint("You shudder with otherworldly dread.");
1201     if (Player.immunity[FEAR] > 0)
1202       mprint("You brace up and face your fear like a hero!");
1203     else {
1204       mprint("You panic!");
1205       Player.status[AFRAID]+=10;
1206     }
1207   }
1208   else if ((m = Level->site[x][y].creature) != NULL) {
1209     if (m->uniqueness == COMMON) {
1210       strcpy(Str2,"The ");
1211       strcat(Str2,m->monstring);
1212     }
1213     else strcpy(Str2,m->monstring);
1214     m->speed = max(2,m->speed-1);
1215     if (m_immunityp(m,FEAR))
1216       strcat(Str2,"seems enraged!");
1217     else {
1218       strcat(Str2,"is terrorized!");
1219       m_dropstuff(m);
1220       if (m_statusp(m,MOBILE))
1221 	m->movef = M_MOVE_SCAREDY;
1222     }
1223   }
1224   else mprint("A thrill of fear tickles your spine ... and passes.");
1225 }
1226 
1227 
1228 
1229 
1230 /*Turns on deflection status for the player */
deflection(blessing)1231 void deflection(blessing)
1232 int blessing;
1233 {
1234   if (blessing > -1) {
1235       mprint("You feel buffered.");
1236       Player.status[DEFLECTION] = blessing + random_range(6);
1237     }
1238   else {
1239     mprint("You feel vulnerable");
1240     Player.status[VULNERABLE] += random_range(6) - blessing;
1241   }
1242 }
1243