1 /* omega copyright (C) by Laurence Raphael Brothers, 1987,1988,1989 */
2 /* aux3.c */
3 /* some functions called by com.c, also see aux1.c, aux2.c */
4 /* This is a real grab bag file. It contains functions used by
5    aux1.c and omega.c, as well as elsewhere. It is mainly here so aux1.c
6    and aux2.c are not huge */
7 
8 #include "glob.h"
9 
10 /* check every ten minutes */
tenminute_check()11 void tenminute_check()
12 {
13   if (Time % 60 == 0) hourly_check();
14   else {
15     if (Current_Environment == Current_Dungeon)  wandercheck();
16     minute_status_check();
17     tenminute_status_check();
18     if ((Player.status[DISEASED] < 1) && (Player.hp < Player.maxhp))
19       Player.hp = min(Player.maxhp,Player.hp+Player.level+1);
20     if (Current_Environment != E_COUNTRYSIDE && Current_Environment != E_ABYSS)
21       indoors_random_event();
22   }
23 }
24 
25 
26 
27 /* hourly check is same as ten_minutely check except food is also
28    checked, and since time moves in hours out of doors, also
29    outdoors_random_event is possible */
30 
hourly_check()31 void hourly_check()
32 {
33   Player.food--;
34   foodcheck();
35   if (hour()==0) { /* midnight, a new day */
36     moon_check();
37     Date++;
38   }
39   torch_check();
40   if (Current_Environment == Current_Dungeon)  wandercheck();
41   minute_status_check();
42   tenminute_status_check();
43   if ((Player.status[DISEASED] == 0) && (Player.hp < Player.maxhp))
44     Player.hp = min(Player.maxhp,Player.hp+Player.level+1);
45   if (Current_Environment != E_COUNTRYSIDE && Current_Environment != E_ABYSS)
46     indoors_random_event();
47 }
48 
49 
50 
51 
indoors_random_event()52 void indoors_random_event()
53 {
54   pml ml;
55   pol ol;
56   switch(random_range(1000)) {
57     case 0:
58       print3("You feel an unexplainable elation.");
59       morewait();
60       break;
61     case 1:
62       print3("You hear a distant rumbling.");
63       morewait();
64       break;
65     case 2:
66       print3("You realize your fly is open.");
67       morewait();
68       break;
69     case 3:
70       print3("You have a sudden craving for a pecan twirl.");
71       morewait();
72       break;
73     case 4:
74       print3("A mysterious healing flux settles over the level.");
75       morewait();
76       for (ml=Level->mlist;ml!=NULL;ml=ml->next)
77 	if (ml->m->hp > 0) ml->m->hp = Monsters[ml->m->id].hp;
78       Player.hp = max(Player.hp,Player.maxhp);
79       break;
80     case 5:
81       print3("You discover an itch just where you can't scratch it.");
82       morewait();
83       break;
84     case 6:
85       print3("A cosmic ray strikes!");
86       p_damage(10,UNSTOPPABLE,"a cosmic ray");
87       morewait();
88       break;
89     case 7:
90       print3("You catch your second wind....");
91       Player.maxhp++;
92       Player.hp = max(Player.hp, Player.maxhp);
93       Player.mana = max(Player.mana, calcmana());
94       morewait();
95       break;
96     case 8:
97       print3("You find some spare change in a hidden pocket.");
98       morewait();
99       Player.cash += Player.level*Player.level+1;
100       break;
101     case 9:
102       print3("You feel strangely lucky.");
103       morewait();
104       break;
105     case 10:
106       print3("You trip over something hidden in a shadow...");
107       morewait();
108       ol = ((pol) checkmalloc(sizeof(oltype)));
109       ol->thing = create_object(difficulty()); /* FIXED!  12/30/98 */
110       assert(ol->thing); /* WDT I want to make sure... */
111       ol->next = Level->site[Player.x][Player.y].things;
112       Level->site[Player.x][Player.y].things = ol;
113       pickup();
114       break;
115     case 11:
116       print3("A mysterious voice echoes all around you....");
117       morewait();
118       hint();
119       morewait();
120       break;
121     case 12:
122       if (Balance > 0) {
123 	print3("You get word of the failure of your bank!");
124 	Balance = 0;
125       }
126       else print3("You feel lucky.");
127       break;
128     case 13:
129       if (Balance > 0) {
130 	print3("You get word of a bank error in your favor!");
131 	Balance += 5000;
132       }
133       else print3("You feel unlucky.");
134       break;
135     }
136   dataprint();
137   showflags();
138 }
139 
140 
141 
outdoors_random_event()142 void outdoors_random_event()
143 {
144   int num,i,j;
145   pob ob;
146 
147   switch(random_range(300)) {
148   case 0:
149     switch(Country[Player.x][Player.y].current_terrain_type) {
150     case TUNDRA:
151       mprint("It begins to snow. Heavily.");
152       break;
153     case DESERT:
154       mprint("A sandstorm swirls around you.");
155       break;
156     default:
157       if ((Date > 75) && (Date < 330))
158 	mprint("You are drenched by a sudden downpour!");
159       else mprint("It begins to snow. Heavily.");
160     }
161     morewait();
162     mprint("Due to the inclement weather conditions, you have become lost.");
163     morewait();
164     Precipitation+=random_range(12)+1;
165     setgamestatus(LOST);
166     break;
167   case 1:
168     mprint("You enter a field of brightly colored flowers...");
169     mprint("Wow, man! These are some pretty poppies...");
170     morewait();
171     mprint("poppies...");
172     morewait();
173     mprint("poppies...");
174     morewait();
175     print3("You become somewhat disoriented...");
176     setgamestatus(LOST);
177     break;
178   case 2:
179     mprint("You discover a sprig of athelas growing lonely in the wild.");
180     morewait();
181     mprint("Using your herbalist lore you cook a cake of lembas....");
182     morewait();
183     ob = ((pob) checkmalloc(sizeof(objtype)));
184     *ob = Objects[FOODID+1];
185     gain_item(ob);
186     break;
187   case 3:
188     if (Precipitation > 0) {
189       mprint("You are struck by a bolt of lightning!");
190       p_damage(random_range(25),ELECTRICITY,"a lightning strike");
191       morewait();
192     }
193     else mprint("You feel static cling");
194     break;
195   case 4:
196     mprint("You find a fast-food establishment.");
197     morewait();
198     l_commandant();
199     break;
200   case 5:
201     mprint("A weird howling tornado hits from out of the West!");
202     morewait();
203     mprint("You've been caught in a chaos storm!");
204     morewait();
205     num = random_range(300);
206     if (num <10) {
207       mprint("Your cell-structure was disrupted!");
208       p_damage(random_range(100),UNSTOPPABLE,"a chaos storm");
209       morewait();
210     }
211     else if (num < 20) {
212       mprint("The chaos storm warps your frame!");
213       morewait();
214       mprint("Your statistical entropy has been maximized.");
215       morewait();
216       mprint("You feel average...");
217       morewait();
218       toggle_item_use(TRUE); /* FIXED! 12/30/98 */
219       Player.str = Player.maxstr = Player.con = Player.maxcon =
220 	Player.dex = Player.maxdex = Player.agi = Player.maxagi =
221 	  Player.iq = Player.maxiq = Player.pow = Player.maxpow =
222 	    ((Player.maxstr+Player.maxcon+Player.maxdex+Player.maxagi+
223 	      Player.maxiq+Player.maxpow+12)/6);
224       toggle_item_use(FALSE); /* FIXED! 12/30/98 */
225     }
226     else if (num < 30) {
227       mprint("Your entire body glows with an eerie flickering light.");
228       morewait();
229       toggle_item_use(TRUE); /* FIXED! 12/30/98 */
230       for(i=1;i<MAXITEMS;i++)
231 	if (Player.possessions[i] != NULL) {
232 	  Player.possessions[i]->plus++;
233 	  if (Player.possessions[i]->objchar == STICK)
234 	    Player.possessions[i]->charge+=10;
235 	  Player.possessions[i]->blessing+=10;
236 	}
237       toggle_item_use(FALSE); /* FIXED! 12/30/98 */
238       cleanse(1);
239       mprint("You feel filled with energy!");
240       morewait();
241       Player.maxpow += 5;
242       Player.pow += 5;
243       Player.mana = Player.maxmana = calcmana() * 5;
244       mprint("You also feel weaker. Paradoxical, no?");
245       morewait();
246       Player.con -= 5;
247       Player.maxcon -= 5;
248       if (Player.con < 3)
249 	p_death("congestive heart failure");
250     }
251     else if (num < 40) {
252       mprint("Your entire body glows black.");
253       morewait();
254       dispel(-1);
255       dispel(-1);
256       Player.pow-=10;
257       Player.mana=0;
258     }
259     else if (num < 60) {
260       mprint("The storm deposits you in a strange place....");
261       morewait();
262       Player.x = random_range(WIDTH);
263       Player.y = random_range(LENGTH);
264       screencheck(Player.y);
265     }
266     else if (num < 70) {
267       mprint("A tendril of the storm condenses and falls into your hands.");
268       morewait();
269       ob = ((pob) checkmalloc(sizeof(objtype)));
270       make_artifact(ob,-1);
271       gain_item(ob);
272     }
273     else if (num < 80) {
274       if (gamestatusp(MOUNTED)) {
275 	mprint("Your horse screams as he is transformed into an");
276 	morewait();
277 	mprint("imaginary unseen dead tortoise.");
278 	morewait();
279 	mprint("You are now on foot.");
280 	morewait();
281 	resetgamestatus(MOUNTED);
282       }
283       else {
284 	mprint("You notice you are riding a horse. Odd. Very odd....");
285 	morewait();
286 	mprint("Now that's a horse of a different color!");
287 	morewait();
288 	setgamestatus(MOUNTED);
289       }
290     }
291     else if (num < 90) {
292       mprint("You feel imbued with godlike power....");
293       morewait();
294       wish(1);
295     }
296     else if (num < 100) {
297       mprint("The chaos storm has wiped your memory!");
298       morewait();
299       mprint("You feel extraordinarily naive....");
300       morewait();
301       mprint("You can't remember a thing! Not even your name.");
302       morewait();
303       Player.xp = 0;
304       Player.level = 0;
305       for (i=0;i<NUMRANKS;i++) Player.rank[i] = 0;
306       for (i=0;i<NUMSPELLS;i++) Spells[i].known = FALSE;
307       rename_player();
308     }
309     else {
310       mprint("You survive the chaos storm relatively unscathed.");
311       morewait();
312       mprint("It was a learning experience.");
313       morewait();
314       gain_experience(1000);
315     }
316     break;
317   case 6: case 7: case 8: case 9: case 10:
318     mprint("An encounter!");
319     morewait();
320     change_environment(E_TACTICAL_MAP);
321     break;
322   case 11:
323     mprint("You find a Traveller's Aid station with maps of the local area.");
324     morewait();
325     if (gamestatusp(LOST)) {
326       resetgamestatus(LOST);
327       mprint("You know where you are now.");
328     }
329     for(i=Player.x-5;i<Player.x+6;i++)
330       for(j=Player.y-5;j<Player.y+6;j++)
331 	if (inbounds(i,j)) {
332 	  c_set(i, j, SEEN);
333 	  if (Country[i][j].current_terrain_type !=
334 	    Country[i][j].base_terrain_type) {
335 	    c_set(i, j, CHANGED);
336 	    Country[i][j].current_terrain_type =
337 	      Country[i][j].base_terrain_type;
338 	  }
339 	}
340     show_screen();
341     break;
342   case 12:
343     if (! gamestatusp(MOUNTED)) {
344       mprint("You develop blisters....");
345       p_damage(1,UNSTOPPABLE,"blisters");
346     }
347     break;
348   case 13:
349     mprint("You discover an itch just where you can't scratch it.");
350     break;
351   case 14:
352     mprint("A cosmic ray strikes!");
353     morewait();
354     p_damage(10,UNSTOPPABLE,"a cosmic ray");
355     break;
356   case 15:
357     mprint("You feel strangely lucky.");
358     break;
359   case 16:
360     mprint("The west wind carries with it a weird echoing voice....");
361     morewait();
362     hint();
363     morewait();
364     break;
365   }
366   dataprint();
367   showflags();
368 }
369 
370 
getlocation()371 char getlocation()
372 {
373   char c = '\0';
374 
375   menuprint(" (enter location [HCL]) ");
376   showmenu();
377   while (c == '\0')
378     switch (c = ((char) mcigetc())) {
379       case 'h':menuprint(" High."); break;
380       case 'c':menuprint(" Center."); break;
381       case 'l':menuprint(" Low."); break;
382       default: c = '\0'; break;
383     }
384   showmenu();
385   return (c - 'a' + 'A');
386 }
387 
388 
389 
390 
391 
392 
393 /* chance for player to resist magic somehow */
394 /* hostile_magic ranges in power from 0 (weak) to 10 (strong) */
magic_resist(hostile_magic)395 int magic_resist(hostile_magic)
396 int hostile_magic;
397 {
398   if ((Player.rank[COLLEGE]+Player.rank[CIRCLE] > 0) &&
399       (Player.level/2 + random_range(20) >
400        hostile_magic + random_range(20))) {
401     if (Player.mana > hostile_magic * hostile_magic) {
402       mprint("Thinking fast, you defend youself with a counterspell!");
403       Player.mana -= hostile_magic * hostile_magic;
404       dataprint();
405       return(TRUE);
406     }
407   }
408   if (Player.level/4 + Player.status[PROTECTION] + random_range(20) >
409       hostile_magic + random_range(30)) {
410     mprint("You resist the spell!");
411     return(TRUE);
412   }
413   else return(FALSE);
414 }
415 
416 
terrain_check(takestime)417 void terrain_check(takestime)
418 int takestime;
419 {
420   int faster = 0;
421 
422   if (Player.patron == DRUID) {
423     faster = 1;
424     switch(random_range(32)) {
425       case 0:print2("Along the many paths of nature..."); break;
426       case 1:print2("You move swiftly through the wilderness."); break;
427     }
428   }
429   else if (gamestatusp(MOUNTED)) {
430     faster = 1;
431     switch(random_range(32)) {
432       case 0:
433       case 1:print2("Clippity Clop.");break;
434       case 2:print2("....my spurs go jingle jangle jingle....");break;
435       case 3:print2("....as I go riding merrily along....");break;
436     }
437   }
438   else if (Player.possessions[O_BOOTS] &&
439       Player.possessions[O_BOOTS]->usef == I_BOOTS_7LEAGUE) {
440     takestime = 0;
441     switch(random_range(32)) {
442       case 0:print2("Boingg!"); break;
443       case 1:print2("Whooosh!"); break;
444       case 2:print2("Over hill, over dale...."); break;
445       case 3:print2("...able to leap over 7 leagues in a single bound....");
446 	break;
447     }
448   }
449   else if (Player.status[SHADOWFORM]) {
450     faster = 1;
451     switch(random_range(32)) {
452       case 0:print2("As swift as a shadow."); break;
453       case 1:print2("\"I walk through the trees...\""); break;
454     }
455   }
456   else switch(random_range(32)) {
457     case 0:print2("Trudge. Trudge."); break;
458     case 1:print2("The road goes ever onward...."); break;
459   }
460   switch(Country[Player.x][Player.y].current_terrain_type) {
461   case RIVER:
462     if ((Player.y < 6) && (Player.x > 20)) locprint("Star Lake.");
463     else if (Player.y < 41) {
464       if (Player.x < 10) locprint("Aerie River.");
465       else locprint("The Great Flood.");
466     }
467     else if (Player.x < 42) locprint("The Swamp Runs.");
468     else locprint("River Greenshriek.");
469     if (takestime) {
470       Time += 60;
471       hourly_check();
472       Time += 60;
473       hourly_check();
474       Time += 60;
475       hourly_check();
476     }
477     break;
478   case ROAD:
479     locprint("A well-maintained road.");
480     if (takestime) {
481       Time += 60;
482       hourly_check();
483     }
484     break;
485   case PLAINS:
486     locprint("A rippling sea of grass.");
487     if (takestime) {
488       Time += 60;
489       hourly_check();
490       if (! faster) {
491 	Time += 60;
492 	hourly_check();
493       }
494     }
495     break;
496   case TUNDRA:
497     locprint("The Great Northern Wastes.");
498     if (takestime) {
499       Time += 60;
500       hourly_check();
501       if (! faster) {
502 	Time += 60;
503 	hourly_check();
504       }
505     }
506     break;
507   case FOREST:
508     if (Player.y < 10) locprint("The Deepwood.");
509     else if (Player.y < 18) locprint("The Forest of Erelon.");
510     else if (Player.y < 46) locprint("The Great Forest.");
511     if (takestime) {
512       Time += 60;
513       hourly_check();
514       if (Player.rank[PRIESTHOOD] == 0 || Player.patron != DRUID) {
515 	Time += 60;
516 	hourly_check();
517 	if (! faster) {
518 	  Time += 60;
519 	  hourly_check();
520 	}
521       }
522     }
523     break;
524   case JUNGLE:
525     locprint("Greenshriek Jungle.");
526     if (takestime) {
527       Time += 60;
528       hourly_check();
529       Time += 60;
530       hourly_check();
531       if (! faster) {
532 	Time += 60;
533 	hourly_check();
534 	Time += 60;
535 	hourly_check();
536       }
537     }
538     break;
539   case DESERT:
540     locprint("The Waste of Time.");
541     if (takestime) {
542       Time += 60;
543       hourly_check();
544       Time += 60;
545       hourly_check();
546       if (! faster) {
547 	Time += 60;
548 	hourly_check();
549 	Time += 60;
550 	hourly_check();
551       }
552     }
553     break;
554   case MOUNTAINS:
555     if ((Player.y < 9) && (Player.x < 12))
556       locprint("The Magic Mountains");
557     else if ((Player.y < 9) && (Player.y > 2) && (Player.x < 40))
558       locprint("The Peaks of the Fist.");
559     else if (Player.x < 52)
560       locprint("The Rift Mountains.");
561     else locprint("Borderland Mountains.");
562     if (takestime) {
563       Time += 60;
564       hourly_check();
565       Time += 60;
566       hourly_check();
567       Time += 60;
568       hourly_check();
569       Time += 60;
570       hourly_check();
571       Time += 60;
572       hourly_check();
573       if (! faster) {
574 	Time += 60;
575 	hourly_check();
576 	Time += 60;
577 	hourly_check();
578 	Time += 60;
579 	hourly_check();
580       }
581     }
582     break;
583   case PASS:
584     locprint("A hidden pass.");
585     if (takestime) {
586       Time += 60;
587       hourly_check();
588     }
589     break;
590   case CHAOS_SEA:
591     locprint("The Sea of Chaos.");
592     if (takestime) {
593       Time += 60;
594       hourly_check();
595     }
596     mprint("You have entered the sea of chaos...");
597     morewait();
598     l_chaos();
599     break;
600   case SWAMP:
601     locprint("The Loathly Swamp.");
602     if (takestime) {
603       Time += 60;
604       hourly_check();
605       Time += 60;
606       hourly_check();
607       Time += 60;
608       hourly_check();
609       Time += 60;
610       hourly_check();
611       Time += 60;
612       hourly_check();
613       Time += 60;
614       hourly_check();
615       if (! faster) {
616 	Time += 60;
617 	hourly_check();
618 	Time += 60;
619 	hourly_check();
620       }
621     }
622     break;
623   case CITY:
624     if (gamestatusp(LOST)) {
625       resetgamestatus(LOST);
626       mprint("Well, I guess you know where you are now....");
627     }
628     locprint("Outside Rampart, the city.");
629     break;
630   case VILLAGE:
631     if (gamestatusp(LOST)) {
632       resetgamestatus(LOST);
633       mprint("The village guards let you know where you are....");
634     }
635     locprint("Outside a small village.");
636     break;
637   case CAVES:
638     locprint("A deserted hillside.");
639     if (takestime) {
640       Time += 60;
641       hourly_check();
642     }
643     mprint("You notice a concealed entrance into the hill.");
644     break;
645   case CASTLE:
646     locprint("Near a fortified castle.");
647     if (takestime) {
648       Time += 60;
649       hourly_check();
650     }
651     mprint("The castle is hewn from solid granite. The drawbridge is down.");
652     break;
653   case TEMPLE:
654     switch(Country[Player.x][Player.y].aux) {
655     case ODIN: locprint("A rough-hewn granite temple."); break;
656     case SET: locprint("A black pyramidal temple made of sandstone."); break;
657     case ATHENA: locprint("A classical marble-columned temple."); break;
658     case HECATE: locprint("A temple of ebony adorned with ivory."); break;
659     case DRUID: locprint("A temple formed of living trees."); break;
660     case DESTINY: locprint("A temple of some mysterious blue crystal."); break;
661     }
662     if (takestime) {
663       Time += 60;
664       hourly_check();
665     }
666     mprint("You notice an entrance conveniently at hand.");
667     break;
668   case MAGIC_ISLE:
669     locprint("A strange island in the midst of the Sea of Chaos.");
670     if (takestime) {
671       Time += 60;
672       hourly_check();
673     }
674     mprint("There is a narrow causeway to the island from here.");
675     break;
676   case STARPEAK:
677     locprint("Star Peak.");
678     if (takestime) {
679       Time += 60;
680       hourly_check();
681     }
682     mprint("The top of the mountain seems to glow with a allochroous aura.");
683     break;
684   case DRAGONLAIR:
685     locprint("A rocky chasm.");
686     if (takestime) {
687       Time += 60;
688       hourly_check();
689     }
690     mprint("You are at a cave entrance from which you see the glint of gold.");
691     break;
692   case VOLCANO:
693     locprint("HellWell Volcano.");
694     if (takestime) {
695       Time += 60;
696       hourly_check();
697     }
698     mprint("A shimmer of heat lightning plays about the crater rim.");
699     break;
700   default:
701     locprint("I haven't any idea where you are!!!");
702     break;
703    }
704   outdoors_random_event();
705 }
706 
707 
708 
countrysearch()709 void countrysearch()
710 {
711   int x,y;
712   Time+=60;
713   hourly_check();
714   for (x=Player.x-1;x<Player.x+2;x++)
715     for (y=Player.y-1;y<Player.y+2;y++)
716       if (inbounds(x,y)) {
717 	if (Country[x][y].current_terrain_type !=
718 	    Country[x][y].base_terrain_type) {
719 	  clearmsg();
720 	  mprint("Your search was fruitful!");
721 	  Country[x][y].current_terrain_type=Country[x][y].base_terrain_type;
722 	  c_set(x, y, CHANGED);
723 	  mprint("You discovered:");
724 	  mprint(countryid(Country[x][y].base_terrain_type));
725 	}
726       }
727 }
728 
countryid(terrain)729 char *countryid(terrain)
730 Symbol terrain;
731 {
732   switch(terrain&0xff) {
733   case MOUNTAINS&0xff:
734     strcpy(Str1,"Almost impassable mountains");
735     break;
736   case PLAINS&0xff:
737     strcpy(Str1,"Seemingly endless plains");
738     break;
739   case TUNDRA&0xff:
740     strcpy(Str1,"A frosty stretch of tundra");
741     break;
742   case ROAD&0xff:
743     strcpy(Str1,"A paved highway");
744     break;
745   case PASS&0xff:
746     strcpy(Str1,"A secret mountain pass");
747     break;
748   case RIVER&0xff:
749     strcpy(Str1,"A rolling river");
750     break;
751   case CITY&0xff:
752     strcpy(Str1,"The city of Rampart");
753     break;
754   case VILLAGE&0xff:
755     strcpy(Str1,"A rural village");
756     break;
757   case FOREST&0xff:
758     strcpy(Str1,"A verdant forest");
759     break;
760   case JUNGLE&0xff:
761     strcpy(Str1,"A densely overgrown jungle");
762     break;
763   case SWAMP&0xff:
764     strcpy(Str1,"A swampy fen");
765     break;
766   case VOLCANO&0xff:
767     strcpy(Str1,"A huge active volcano");
768     break;
769   case CASTLE&0xff:
770     strcpy(Str1,"An imposing castle");
771     break;
772   case STARPEAK&0xff:
773     strcpy(Str1,"A mysterious mountain.");
774     break;
775   case DRAGONLAIR&0xff:
776     strcpy(Str1,"A cavern filled with treasure.");
777     break;
778   case MAGIC_ISLE&0xff:
779     strcpy(Str1,"An island emanating magic.");
780     break;
781   case CAVES&0xff:
782     strcpy(Str1,"A hidden cave entrance");
783     break;
784   case TEMPLE&0xff:
785     strcpy(Str1,"A neoclassical temple");
786     break;
787   case DESERT&0xff:
788     strcpy(Str1,"A sere desert");
789     break;
790   case CHAOS_SEA&0xff:
791     strcpy(Str1,"The Sea of Chaos");
792     break;
793   default:
794     strcpy(Str1,"I have no idea.");
795     break;
796   }
797   return(Str1);
798 }
799 
800 static char *sitenames[] = {	/* alphabetical listing */
801 "alchemist", "arena", "armorer", "bank", "brothel", "casino", "castle",
802 "city gates", "collegium magii", "condo", "department of public works",
803 "diner", "explorers' club", "fast food", "gymnasium", "healer", "hospice",
804 "les crapuleux", "library", "mercenary guild", "oracle", "order of paladins",
805 "pawn shop", "sorcerors' guild ", "tavern", "temple", "thieves' guild" };
806 
807 static int sitenums[] = {	/* the order matches sitenames[] */
808  L_ALCHEMIST, L_ARENA, L_ARMORER, L_BANK, L_BROTHEL, L_CASINO, L_CASTLE,
809  L_COUNTRYSIDE, L_COLLEGE, L_CONDO, L_DPW, L_DINER, L_CLUB, L_COMMANDANT,
810  L_GYM, L_HEALER, L_CHARITY, L_CRAP, L_LIBRARY, L_MERC_GUILD, L_ORACLE,
811  L_ORDER, L_PAWN_SHOP, L_SORCERORS, L_TAVERN, L_TEMPLE, L_THIEVES_GUILD };
812 
showknownsites(first,last)813 void showknownsites(first, last)
814 int first, last;
815 {
816   int i,printed=FALSE;
817 
818   menuclear();
819   menuprint("\nPossible Sites:\n");
820   for (i = first; i <= last; i++)
821     if (CitySiteList[sitenums[i] - CITYSITEBASE][0]) {
822       printed = TRUE;
823       menuprint(sitenames[i]);
824       menuprint("\n");
825     }
826   if (! printed)
827     menuprint("\nNo known sites match that prefix!");
828   showmenu();
829 }
830 
parsecitysite()831 int parsecitysite()
832 {
833   int first, last, pos;
834   char byte, prefix[80];
835   int found = 0;
836   int f, l;
837 
838   first = 0;
839   last = NUMCITYSITES - 1;
840   pos = 0;
841   print2("");
842   do {
843     byte = mgetc();
844     if (byte == BACKSPACE || byte == DELETE) {
845       if (pos > 0) {
846         prefix[--pos] = '\0';
847 	byte = prefix[pos - 1];
848 	f = first;
849 	while (f >= 0 && !strncmp(prefix, sitenames[f], pos)) {
850 	  if (CitySiteList[sitenums[f] - CITYSITEBASE][0])
851 	    first = f;
852 	  f--;
853 	}
854 	l = last;
855 	while (l < NUMCITYSITES && !strncmp(prefix, sitenames[l], pos)) {
856 	  if (CitySiteList[sitenums[l] - CITYSITEBASE][0])
857 	    last = l;
858 	  l++;
859 	}
860 	if (found)
861 	  found = 0;
862 	print2(prefix);
863       }
864       if (pos == 0) {
865 	first = 0;
866 	last = NUMCITYSITES - 1;
867 	found = 0;
868 	print2("");
869       }
870     }
871     else if (byte == ESCAPE) {
872       xredraw();
873       return ABORT;
874     }
875     else if (byte == '?')
876       showknownsites(first, last);
877     else if (byte != '\n') {
878       if (byte >= 'A' && byte <= 'Z')
879 	byte += 'a' - 'A';
880       if (found)
881 	continue;
882       f = first;
883       l = last;
884       while (f < NUMCITYSITES &&
885 	  (!CitySiteList[sitenums[f] - CITYSITEBASE][0] ||
886 	  strlen(sitenames[f]) < pos || sitenames[f][pos] < byte))
887 	f++;
888       while (l >= 0 && (!CitySiteList[sitenums[l] - CITYSITEBASE][0] ||
889 	  strlen(sitenames[l]) < pos || sitenames[l][pos] > byte))
890 	l--;
891       if (l < f)
892 	continue;
893       prefix[pos++] = byte;
894       prefix[pos] = '\0';
895       nprint2(prefix + pos - 1);
896       first = f;
897       last = l;
898       if (first == last && !found) {	/* unique name */
899 	found = 1;
900 	nprint2(sitenames[first] + pos);
901       }
902     }
903   } while (byte != '\n');
904   xredraw();
905   if (found)
906     return sitenums[first] - CITYSITEBASE;
907   else {
908     print3("That is an ambiguous abbreviation!");
909     return ABORT;
910   }
911 }
912 
913 
914 /* are there hostile monsters within 2 moves? */
hostilemonstersnear()915 int hostilemonstersnear()
916 {
917   int i,j,hostile = FALSE;
918 
919   for (i=Player.x-2;((i<Player.x+3)&&(! hostile));i++)
920     for (j=Player.y-2;((j<Player.y+3)&&(! hostile));j++)
921       if (inbounds(i,j))
922 	if (Level->site[i][j].creature != NULL)
923 	  hostile = m_statusp(Level->site[i][j].creature,HOSTILE);
924 
925   return(hostile);
926 }
927 
928 /* random effects from some of stones in villages */
929 /* if alignment of stone is alignment of player, gets done sooner */
stonecheck(alignment)930 int stonecheck(alignment)
931 int alignment;
932 {
933   int *stone,match=FALSE,cycle=FALSE,i;
934 
935   if (alignment == 1) {
936     stone = &Lawstone;
937     match = Player.alignment > 0;
938   }
939   else if (alignment == -1) {
940     stone = &Chaostone;
941     match = Player.alignment < 0;
942   }
943   else {
944     stone = &Mindstone;
945     match = FALSE;
946   }
947   *stone += random_range(4) + (match ? random_range(4) : 0);
948   switch((*stone)++) {
949   case 0:case 2:case 4:case 6:case 8:case 10:case 12:case 14:case 16:case 18:
950   case 20:case 22:case 24:case 26:case 28:case 30:case 32:case 34:case 36:
951   case 38:case 40: print1("The stone glows grey.");
952     print2("Not much seems to happen this time.");
953     (*stone)--;
954     break;
955   case 1: print1("The stone glows black");
956     print2("A burden has been removed from your shoulders.....");
957     print3("Your pack has disintegrated!");
958     for(i=0;i<MAXPACK;i++)
959       if (Player.pack[i] != NULL) {
960 	free((char *) Player.pack[i]);
961 	Player.pack[i] = NULL;
962       }
963     Player.packptr = 0;
964     break;
965   case 3: print1("The stone glows microwave");
966     print2("A vortex of antimana spins about you!");
967     morewait();
968     dispel(-1);
969     break;
970   case 5: print1("The stone glows infrared");
971     print2("A portal opens nearby and an obviously confused monster appears!");
972     summon(-1,-1);
973     morewait();
974     break;
975   case 7: print1("The stone glows brick red");
976     print2("A gold piece falls from the heavens into your money pouch!");
977     Player.cash++;
978     break;
979   case 9: print1("The stone glows cherry red");
980     print2("A flush of warmth spreads through your body.");
981     augment(1);
982     break;
983   case 11: print1("The stone glows orange");
984     print2("A flux of energy blasts you!");
985     manastorm(Player.x,Player.y,random_range(Player.maxhp)+1);
986     break;
987   case 13: print1("The stone glows lemon yellow");
988     print2("You're surrounded by enemies! You begin to foam at the mouth.");
989     Player.status[BERSERK] += 10;
990     break;
991   case 15: print1("The stone glows yellow");
992     print2("Oh no! The DREADED AQUAE MORTIS!");
993     morewait();
994     print2("No, wait, it's just your imagination.");
995     break;
996   case 17: print1("The stone glows chartreuse");
997     print2("Your joints stiffen up.");
998     Player.agi -= 3;
999     break;
1000   case 19: print1("The stone glows green");
1001     print2("You come down with an acute case of Advanced Leprosy.");
1002     Player.status[DISEASED] = 1100;
1003     Player.hp = 1;
1004     Player.dex -= 5;
1005     break;
1006   case 21: print1("The stone glows forest green");
1007     print2("You feel wonderful!");
1008     Player.status[HERO]+=10;
1009     break;
1010   case 23: print1("The stone glows cyan");
1011     print2("You feel a strange twisting sensation....");
1012     morewait();
1013     strategic_teleport(-1);
1014     break;
1015   case 25: print1("The stone glows blue");
1016     morewait();
1017     print1("You feel a tingle of an unearthly intuition:");
1018     morewait();
1019     hint();
1020     break;
1021   case 27: print1("The stone glows navy blue");
1022     print2("A sudden shock of knowledge overcomes you.");
1023     morewait();
1024     clearmsg();
1025     identify(1);
1026     knowledge(1);
1027     break;
1028   case 29: print1("The stone glows blue-violet");
1029     print2("You feel forgetful.");
1030     for(i=0;i<NUMSPELLS;i++)
1031       if (Spells[i].known) {
1032 	Spells[i].known = FALSE;
1033 	break;
1034       }
1035     break;
1036   case 31: print1("The stone glows violet");
1037     morewait();
1038     acquire(0);
1039     break;
1040   case 33: print1("The stone glows deep purple");
1041     print2("You vanish.");
1042     Player.status[INVISIBLE]+=10;
1043     break;
1044   case 35: print1("The stone glows ultraviolet");
1045     print2("All your hair rises up on end.... A bolt of lightning hits you!");
1046     p_damage(random_range(Player.maxhp),ELECTRICITY,"mystic lightning");
1047     break;
1048   case 37: print1("The stone glows roentgen");
1049     print2("You feel more experienced.");
1050     gain_experience((Player.level+1)*250);
1051     break;
1052   case 39: print1("The stone glows gamma");
1053     print2("Your left hand shines silvery, and your right emits a golden aura.");
1054     morewait();
1055     enchant(1);
1056     bless(1);
1057     print3("Your hands stop glowing.");
1058     break;
1059   case 41:case 42:case 43:case 44:case 45:case 46:case 47:case 48:case 49:
1060     print1("The stone glows cosmic!");
1061     print2("The stone's energy field quiets for a moment...");
1062     *stone = 50;
1063     cycle = TRUE;
1064     break;
1065   default: print1("The stone glows polka-dot (?!?!?!?)");
1066     print2("You feel a strange twisting sensation....");
1067     morewait();
1068     *stone = 0;
1069     strategic_teleport(-1);
1070     break;
1071   }
1072   calc_melee();
1073   return(cycle);
1074 }
1075 
alert_guards()1076 void alert_guards()
1077 {
1078   int foundguard=FALSE;
1079   pml ml;
1080   int suppress = 0;
1081   for(ml=Level->mlist;ml!=NULL;ml=ml->next)
1082     if (((ml->m->id == GUARD) ||
1083 	 ((ml->m->id == HISCORE_NPC) && (ml->m->aux2 == 15))) && /*justiciar*/
1084 	(ml->m->hp > 0)) {
1085       foundguard=TRUE;
1086       m_status_set(ml->m,AWAKE);
1087       m_status_set(ml->m,HOSTILE);
1088     }
1089   if (foundguard) {
1090     mprint("You hear a whistle and the sound of running feet!");
1091     if (Current_Environment == E_CITY)
1092       Level->site[40][60].p_locf = L_NO_OP; /* pacify_guards restores this */
1093   }
1094   if ((! foundguard) && (Current_Environment == E_CITY) &&
1095       !gamestatusp(DESTROYED_ORDER)) {
1096     suppress = gamestatusp(SUPPRESS_PRINTING);
1097     resetgamestatus(SUPPRESS_PRINTING);
1098     print2("The last member of the Order of Paladins dies....");
1099     morewait();
1100     gain_experience(1000);
1101     Player.alignment -= 250;
1102     if (! gamestatusp(KILLED_LAWBRINGER)) {
1103       print1("A chime sounds from far away.... The sound grows stronger....");
1104       print2("Suddenly the great shadowy form of the LawBringer appears over");
1105       print3("the city. He points his finger at you....");
1106       morewait();
1107       print1("\"Cursed art thou, minion of chaos! May thy strength fail thee");
1108       print2("in thy hour of need!\" You feel an unearthly shiver as the");
1109       print3("LawBringer waves his palm across the city skies....");
1110       morewait();
1111       Player.str /= 2;
1112       dataprint();
1113       print1("You hear a bell tolling, and eerie moans all around you....");
1114       print2("Suddenly, the image of the LawBringer is gone.");
1115       print3("You hear a guardsman's whistle in the distance!");
1116       morewait();
1117       resurrect_guards();
1118     }
1119     else {
1120       print1("The Order's magical defenses have dropped, and the");
1121       print2("Legions of Chaos strike....");
1122       morewait();
1123       print1("The city shakes! An earthquake has struck!");
1124       print2("Cracks open in the street, and a chasm engulfs the Order HQ!");
1125       print3("Flames lick across the sky and you hear wild laughter....");
1126       morewait();
1127       gain_experience(5000);
1128       destroy_order();
1129     }
1130   }
1131   if (suppress)
1132     resetgamestatus(SUPPRESS_PRINTING);
1133 }
1134 
1135 
1136 /* can only occur when player is in city, so OK to use Level */
destroy_order()1137 void destroy_order()
1138 {
1139   int i,j;
1140   setgamestatus(DESTROYED_ORDER);
1141   if (Level != City) print1("Zounds! A Serious Mistake!");
1142   else
1143     for(i=35;i<46;i++)
1144       for(j=60;j<63;j++) {
1145 	if (i == 40 && (j == 60 || j == 61)) {
1146 	  lreset(i,j,SECRET);
1147 	  Level->site[i][j].locchar = FLOOR;
1148 	  Level->site[i][j].p_locf = L_NO_OP;
1149 	  lset(i, j, CHANGED);
1150 	}
1151 	else {
1152 	  Level->site[i][j].locchar = RUBBLE;
1153 	  Level->site[i][j].p_locf = L_RUBBLE;
1154 	  lset(i, j, CHANGED);
1155 	}
1156 	if (Level->site[i][j].creature != NULL) {
1157 	  Level->site[i][j].creature->hp = -1;
1158 	  Level->site[i][j].creature = NULL;
1159 	}
1160 	make_site_monster(i,j,GHOST);
1161 	Level->site[i][j].creature->monstring = "ghost of a Paladin";
1162 	m_status_set(Level->site[i][j].creature,HOSTILE);
1163       }
1164 }
1165 
1166 
1167 
maneuvers()1168 int maneuvers()
1169 {
1170   int m;
1171 
1172   m = 2 + Player.level/7;
1173   if (Player.rank[ARENA]) m++;
1174   if (Player.status[HASTED])
1175     m *= 2;
1176   if (Player.status[SLOWED])
1177     m /= 2;
1178   m = min(8,max(1,m));
1179 
1180   return(m);
1181 }
1182 
1183 /* for when haste runs out, etc. */
default_maneuvers()1184 void default_maneuvers()
1185 {
1186   int i;
1187   morewait();
1188   clearmsg();
1189   print1("Warning, resetting your combat options to the default.");
1190   print2("Use the 'F' command to select which options you prefer.");
1191   morewait();
1192   for(i=0;i<maneuvers();i+=2) {
1193     Player.meleestr[i*2]='A';
1194     Player.meleestr[(i*2)+1]='C';
1195     Player.meleestr[(i+1)*2]='B';
1196     Player.meleestr[((i+1)*2)+1]='C';
1197   }
1198   Player.meleestr[maneuvers()*2]=0;
1199 }
1200