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