1 /* omega copyright (C) by Laurence Raphael Brothers, 1987,1988,1989 */
2 /* aux2.c */
3 /* some functions called by ocom.c, also see aux1.c and aux3.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 aux3.c are not huge */
7 
8 #include "glob.h"
9 
10 /* Player stats like str, agi, etc give modifications to various abilities
11    chances to do things, etc. Positive is good, negative bad. */
statmod(stat)12 int statmod(stat)
13 int stat;
14 {
15   return((stat-10)/2);
16 }
17 
18 
19 /* effects of hitting */
p_hit(m,dmg,dtype)20 void p_hit (m,dmg,dtype)
21 struct monster *m;
22 int dmg;
23 int dtype;
24 {
25   int dmult;
26 
27   /* chance for critical hit..., 3/10 */
28   switch (random_range(10)) {
29     case 0:
30     if (random_range(100) < Player.level) {
31       strcpy(Str3,"You annihilate ");
32       dmult = 1000;
33     }
34     else {
35       strcpy(Str3,"You blast ");
36       dmult=5;
37     }
38     break;
39     case 1:
40     case 2:
41     strcpy(Str3,"You smash ");
42     dmult=2; break;
43 
44     default:
45     dmult=1;
46     if (random_range(10)) strcpy(Str3,"You hit ");
47     else switch(random_range(4)) {
48     case 0: strcpy(Str3,"You damage "); break;
49     case 1: strcpy(Str3,"You inflict bodily harm on "); break;
50     case 2: strcpy(Str3,"You injure "); break;
51     case 3: strcpy(Str3,"You molest "); break;
52     }
53     break;
54   }
55   if (Lunarity == 1) dmult = dmult * 2;
56   else if (Lunarity == -1) dmult = dmult / 2;
57   if (m->uniqueness == COMMON) strcat(Str3,"the ");
58   strcat(Str3,m->monstring);
59   strcat(Str3,". ");
60   if (Verbosity != TERSE) mprint(Str3);
61   else mprint("You hit it.");
62   m_damage(m,dmult * random_range(dmg),dtype);
63   if ((Verbosity != TERSE) && (random_range(10)==3) && (m->hp > 0))
64     mprint("It laughs at the injury and fights on!");
65 }
66 
67 /* and effects of missing */
player_miss(m,dtype)68 void player_miss(m,dtype)
69 struct monster *m;
70 int dtype;
71 {
72   if (random_range(30)==1) /* fumble 1 in 30 */
73     p_fumble(dtype);
74   else {
75     if (Verbosity != TERSE) {
76       if (random_range(10))
77 	strcpy(Str3,"You miss ");
78       else switch(random_range(4)) {
79       case 0: strcpy(Str3,"You flail lamely at "); break;
80       case 1: strcpy(Str3,"You only amuse "); break;
81       case 2: strcpy(Str3,"You fail to even come close to "); break;
82       case 3: strcpy(Str3,"You totally avoid contact with "); break;
83       }
84       if (m->uniqueness == COMMON) strcat(Str3,"the ");
85       strcat(Str3,m->monstring);
86       strcat(Str3,". ");
87       mprint(Str3);
88     }
89     else mprint("You missed it.");
90   }
91 }
92 
93 /* oh nooooo, a fumble.... */
p_fumble(dtype)94 void p_fumble(dtype)
95 int dtype;
96 {
97   mprint("Ooops! You fumbled....");
98   switch(random_range(10)) {
99     case 0:
100     case 1:
101     case 2:
102     case 3:
103     case 4:
104     case 5: drop_weapon(); break;
105     case 6:
106     case 7:
107     case 8: break_weapon(); break;
108     case 9: mprint("Oh No! You hit yourself!");
109 	    p_damage(Player.dmg,dtype,"stupidity");
110 	    break;
111   }
112 }
113 
114 /* try to drop a weapon (from fumbling) */
drop_weapon()115 void drop_weapon()
116 {
117   if (Player.possessions[O_WEAPON_HAND] != NULL) {
118     strcpy(Str1,"You dropped your ");
119     strcat(Str1,Player.possessions[O_WEAPON_HAND]->objstr);
120     mprint(Str1);
121     morewait();
122     p_drop_at(Player.x,Player.y,1,Player.possessions[O_WEAPON_HAND]);
123     conform_lost_objects(1,Player.possessions[O_WEAPON_HAND]);
124   }
125   else mprint("You feel fortunate.");
126 }
127 
128 
129 /* try to break a weapon (from fumbling) */
break_weapon()130 void break_weapon()
131 {
132   if (Player.possessions[O_WEAPON_HAND] != NULL) {
133     strcpy(Str1,"Your ");
134     strcat(Str1,itemid(Player.possessions[O_WEAPON_HAND]));
135     strcat(Str1," vibrates in your hand....");
136     mprint(Str1);
137     (void) damage_item(Player.possessions[O_WEAPON_HAND]);
138     morewait();
139   }
140 }
141 
142 
143 /* hooray */
p_win()144 void p_win()
145 {
146   morewait();
147   clearmsg();
148   print1("You won!");
149   morewait();
150   display_win();
151   endgraf();
152   exit(0);
153 }
154 
155 
156 /* handle a h,j,k,l, etc., to change x and y by dx and dy */
157 /* for targeting in dungeon */
movecursor(x,y,dx,dy)158 void movecursor(x,y,dx,dy)
159 int *x,*y;
160 int dx,dy;
161 {
162   if (inbounds(*x+dx,*y+dy)) {
163     *x += dx;
164     *y += dy;
165     screencheck(*y);
166   }
167   omshowcursor(*x,*y);
168 }
169 
170 
171 /* is Player immune to damage type dtype */
p_immune(dtype)172 int p_immune(dtype)
173 int dtype;
174 {
175   return(Player.immunity[dtype]>0);
176 }
177 
178 
179 
180 
181 
182 
183 /* deal with each possible stati -- values are per move */
184 /* this function is executed every move */
185 /* A value over 1000 indicates a permanent effect */
minute_status_check()186 void minute_status_check()
187 {
188   int i;
189 
190   if (Player.status[HASTED]>0) {
191     if (Player.status[HASTED] < 1000) {
192       Player.status[HASTED]--;
193       if (Player.status[HASTED]==0) {
194 	mprint("The world speeds up.");
195 	calc_melee();
196       }
197     }
198   }
199 
200 
201   if (Player.status[POISONED]>0) {
202     Player.status[POISONED]--;
203     p_damage(3,POISON,"poison");
204     if (Player.status[POISONED] == 0) {
205       showflags();
206       mprint("You feel better now.");
207     }
208   }
209 
210 
211   if (Player.immunity[UNSTOPPABLE]>0) {
212     for(i=0;i<NUMIMMUNITIES;i++)
213     Player.immunity[i]--;
214     if (Player.immunity[UNSTOPPABLE]==1)
215       mprint("You feel vincible again.");
216   }
217 
218 
219   if (Player.status[IMMOBILE]>0) {
220     Player.status[IMMOBILE]--;
221     if (Player.status[IMMOBILE] == 0)
222       mprint("You can move again.");
223   }
224 
225 
226   if (Player.status[SLEPT]>0) {
227     Player.status[SLEPT]--;
228     if (Player.status[SLEPT] == 0) {
229       mprint("You woke up.");
230     }
231   }
232 
233   if (Player.status[REGENERATING]>0) {
234     if ((Player.hp < Player.maxhp) && (Player.mana > 0)){
235       Player.hp++;
236       Player.mana--;
237       dataprint();
238     }
239     if (Player.status[REGENERATING] < 1000) {
240       Player.status[REGENERATING]--;
241       if (Player.status[REGENERATING] == 0) {
242 	mprint("You feel less homeostatic.");
243       }
244     }
245   }
246 
247   if (Player.status[SLOWED]>0) {
248     if (Player.status[SLOWED] < 1000) {
249       Player.status[SLOWED]--;
250       if (Player.status[SLOWED] == 0) {
251 	mprint("You feel quicker now.");
252 	calc_melee();
253       }
254     }
255   }
256 
257   if (Player.status[RETURNING]>0) {
258     Player.status[RETURNING]--;
259     if (Player.status[RETURNING] == 10)
260       mprint("Your return spell slowly hums towards activation...");
261     else if (Player.status[RETURNING] == 8)
262       mprint("There is an electric tension in the air!");
263     else if (Player.status[RETURNING] == 5)
264       mprint("A vortex of mana begins to form around you!");
265     else if (Player.status[RETURNING] == 1)
266       mprint("Your surroundings start to warp and fade!");
267     if (Player.status[RETURNING] == 0)
268       level_return();
269   }
270 
271   if (Player.status[AFRAID]>0) {
272     if (Player.status[AFRAID] < 1000) {
273       Player.status[AFRAID]--;
274       if (Player.status[AFRAID] == 0) {
275 	mprint("You feel bolder now.");
276       }
277     }
278   }
279 
280 }
281 
282 
283 
284 /* effect of gamma ray radiation... */
moon_check()285 void moon_check()
286 {
287   /* 24 day lunar cycle */
288   Phase = (Phase+1)%24;
289   phaseprint();
290   Lunarity = 0;
291   if (((Player.patron == DRUID) && ((Phase/2 == 3) || (Phase/2 == 9))) ||
292       ((Player.alignment > 10) && (Phase/2 == 6)) ||
293       ((Player.alignment < -10) && (Phase/2 == 0))) {
294     mprint("As the moon rises you feel unusually vital!");
295     Lunarity = 1;
296   }
297   else
298   if (((Player.patron == DRUID) && ((Phase/2 == 0) || (Phase/2 == 6))) ||
299       ((Player.alignment > 10) && (Phase/2 == 0)) ||
300       ((Player.alignment < -10) && (Phase/2 == 6))) {
301     mprint("The rise of the moon tokens a strange enervation!");
302     Lunarity = -1;
303   }
304 
305 }
306 
307 
308 
309 /* check 1/hour for torch to burn out if used */
torch_check()310 void torch_check()
311 {
312   int i;
313   for(i=O_READY_HAND;i<=O_WEAPON_HAND;i++) {
314     if (Player.possessions[i]!=NULL)
315       if ((Player.possessions[i]->id == THINGID+8) && /*torch */
316 	  (Player.possessions[i]->aux > 0)) {
317 	Player.possessions[i]->aux--;
318 	if (Player.possessions[i]->aux==0) {
319 	  mprint("Your torch goes out!!!");
320 	  conform_unused_object(Player.possessions[i]);
321 	  if (Player.possessions[i]->number > 1) {
322 	    Player.possessions[i]->number--;
323 	    Player.possessions[i]->aux = 6;
324 	  }
325 	  else {
326 	    Player.possessions[i]->usef = I_NO_OP;
327 	    Player.possessions[i]->cursestr =
328 	      Player.possessions[i]->truename =
329 		Player.possessions[i]->objstr = "burnt-out torch";
330 	  }
331 	}
332       }
333   }
334 }
335 
336 
337 
338 /* values are in multiples of ten minutes */
339 /* values over 1000 indicate a permanent effect */
tenminute_status_check()340 void tenminute_status_check()
341 {
342   if ((Player.status[SHADOWFORM]>0) && (Player.status[SHADOWFORM]<1000)) {
343     Player.status[SHADOWFORM]--;
344     if (Player.status[SHADOWFORM] == 0) {
345       Player.immunity[NORMAL_DAMAGE]--;
346       Player.immunity[ACID]--;
347       Player.immunity[THEFT]--;
348       Player.immunity[INFECTION]--;
349       mprint("You feel less shadowy now.");
350     }
351   }
352 
353   if ((Player.status[ILLUMINATION]>0) && (Player.status[ILLUMINATION]<1000)) {
354     Player.status[ILLUMINATION]--;
355     if (Player.status[ILLUMINATION] == 0) {
356       mprint("Your light goes out!");
357     }
358   }
359 
360 
361   if ((Player.status[VULNERABLE]>0) && (Player.status[VULNERABLE]<1000)){
362     Player.status[VULNERABLE]--;
363     if (Player.status[VULNERABLE] == 0)
364       mprint("You feel less endangered.");
365   }
366 
367 
368   if ((Player.status[DEFLECTION]>0) && (Player.status[DEFLECTION]<1000)){
369     Player.status[DEFLECTION]--;
370     if (Player.status[DEFLECTION] == 0)
371       mprint("You feel less well defended.");
372   }
373 
374   if ((Player.status[ACCURATE]>0) && (Player.status[ACCURACY]<1000)){
375     Player.status[ACCURATE]--;
376     if (Player.status[ACCURATE] == 0) {
377       calc_melee();
378       mprint("The bulls' eyes go away.");
379     }
380   }
381   if ((Player.status[HERO]>0) && (Player.status[HERO]<1000)){
382     Player.status[HERO]--;
383     if (Player.status[HERO] == 0) {
384       calc_melee();
385       mprint("You feel less than super.");
386     }
387   }
388 
389   if ((Player.status[LEVITATING]>0) && (Player.status[LEVITATING]<1000)){
390     Player.status[LEVITATING]--;
391     if (Player.status[LEVITATING] == 0)
392       mprint("You're no longer walking on air.");
393   }
394 
395   if (Player.status[DISEASED]>0) {
396     Player.status[DISEASED]--;
397     if (Player.status[DISEASED] == 0) {
398       showflags();
399       mprint("You feel better now.");
400     }
401   }
402 
403 
404   if ((Player.status[INVISIBLE] > 0) && (Player.status[INVISIBLE]<1000)){
405     Player.status[INVISIBLE]--;
406     if (Player.status[INVISIBLE] == 0)
407       mprint("You feel more opaque now.");
408   }
409 
410   if ((Player.status[BLINDED]>0) && (Player.status[BLINDED]<1000)) {
411     Player.status[BLINDED]--;
412     if (Player.status[BLINDED] == 0)
413       mprint("You can see again.");
414   }
415 
416   if ((Player.status[TRUESIGHT]>0) && (Player.status[TRUESIGHT]<1000)) {
417     Player.status[TRUESIGHT]--;
418     if (Player.status[TRUESIGHT] == 0)
419       mprint("You feel less keen now.");
420   }
421 
422   if ((Player.status[BERSERK]>0) && (Player.status[BERSERK]<1000)) {
423     Player.status[BERSERK]--;
424     if (Player.status[BERSERK] == 0)
425       mprint("You stop foaming at the mouth.");
426   }
427 
428   if ((Player.status[ALERT]>0) && (Player.status[ALERT] < 1000)) {
429     Player.status[ALERT]--;
430     if (Player.status[ALERT] == 0)
431       mprint("You feel less alert now.");
432   }
433 
434   if ((Player.status[BREATHING]>0) && (Player.status[BREATHING] < 1000)) {
435     Player.status[BREATHING]--;
436     if (Player.status[BREATHING] == 0)
437       mprint("You feel somewhat congested.");
438   }
439 
440   if ((Player.status[DISPLACED]>0) && (Player.status[DISPLACED] < 1000)) {
441     Player.status[DISPLACED]--;
442     if (Player.status[DISPLACED]==0)
443       mprint("You feel a sense of position.");
444   }
445   timeprint();
446   dataprint();
447 }
448 
449 
450 
451 /* Increase in level at appropriate experience gain */
gain_level()452 void gain_level()
453 {
454   int gained=FALSE;
455   int hp_gain; /* FIXED! 12/30/98 */
456 
457   if (gamestatusp(SUPPRESS_PRINTING))
458     return;
459   while (expval(Player.level+1) <= Player.xp) {
460     if (!gained)
461       morewait();
462     gained = TRUE;
463     Player.level++;
464     print1("You have attained a new experience level!");
465     print2("You are now ");
466     nprint2(getarticle(levelname(Player.level)));
467     nprint2(levelname(Player.level));
468     hp_gain = random_range(Player.con)+1; /* start fix 12/30/98 */
469     if (Player.hp < Player.maxhp )
470       Player.hp += hp_gain*Player.hp/Player.maxhp;
471     else if (Player.hp < Player.maxhp + hp_gain)
472       Player.hp = Player.maxhp + hp_gain;
473     /* else leave current hp alone */
474     Player.maxhp += hp_gain;
475     Player.maxmana = calcmana();
476     /* If the character was given a bonus, let him keep it.  Otherwise
477      * recharge him. */
478     Player.mana = max(Player.mana, Player.maxmana); /* end fix 12/30/98 */
479     morewait();
480   }
481   if (gained) clearmsg();
482   calc_melee();
483 }
484 
485 /* experience requirements */
expval(plevel)486 long expval(plevel)
487 int plevel;
488 {
489   switch(plevel) {
490     case 0:return(0L);
491     case 1:return(20L);
492     case 2:return(50L);
493     case 3:return(200L);
494     case 4:return(500L);
495     case 5:return(1000L);
496     case 6:return(2000L);
497     case 7:return(3000L);
498     case 8:return(5000L);
499     case 9:return(7000L);
500     case 10:return(10000L);
501     default:return((plevel-9) * 10000L);
502   }
503 }
504 
505 /* If an item is unidentified, it isn't worth much to those who would buy it */
item_value(item)506 long item_value(item)
507 pob item;
508 {
509   if (item->known == 0) {
510     if (item->objchar == THING) return(1);
511     else return(true_item_value(item) / 10);
512   }
513   else if (item->known == 1) {
514     if (item->objchar == THING) return(item->basevalue);
515     else return(item->basevalue / 2);
516   }
517   else return(true_item_value(item));
518 }
519 
520 
521 /* figures value based on item base-value, charge, plus, and blessing */
true_item_value(item)522 long true_item_value(item)
523 pob item;
524 {
525  long value = item->basevalue;
526 
527   if (item->objchar == THING) return(item->basevalue);
528   else {
529     if (item->objchar == STICK) value += value*item->charge/20;
530     if (item->plus > -1) value += value*item->plus/4;
531     else value /= -item->plus;
532     if (item->blessing > 0) value *= 2;
533     return((long) value);
534   }
535 }
536 
537 /* kill off player if he isn't got the "breathing" status */
p_drown()538 void p_drown()
539 {
540   int attempts = 3, i;
541 
542   if (Player.status[BREATHING] > 0)
543     mprint("Your breathing is unaffected!");
544   else while (Player.possessions[O_ARMOR] ||
545       Player.itemweight > ((int) (Player.maxweight / 2))) {
546     menuclear();
547     switch (attempts--) {
548       case 3: print3("You try to hold your breath..."); break;
549       case 2: print3("You try to hold your breath... You choke..."); break;
550       case 1: print3("You try to hold your breath... You choke... Your lungs fill..."); break;
551       case 0: p_death("drowning");
552     }
553     morewait();
554     menuprint("a: Drop an item.\n");
555     menuprint("b: Bash an item.\n");
556     menuprint("c: Drop your whole pack.\n");
557     showmenu();
558     switch(menugetc()) {
559       case 'a':
560 	drop();
561 	if (Level->site[Player.x][Player.y].p_locf == L_WATER && Level->site[Player.x][Player.y].things)
562 	{
563 	    mprint("It sinks without a trace.");
564 	    free_objlist(Level->site[Player.x][Player.y].things);
565 	    Level->site[Player.x][Player.y].things = NULL;
566 	}
567 	break;
568       case 'b':
569 	bash_item();
570 	break;
571       case 'c':
572 	setgamestatus(SUPPRESS_PRINTING);
573 	for(i=0;i<MAXPACK;i++) {
574 	  if (Player.pack[i] != NULL)
575 	    if (Level->site[Player.x][Player.y].p_locf != L_WATER)
576 	      p_drop_at(Player.x,Player.y,Player.pack[i]->number,Player.pack[i]);
577 	    free((char *) Player.pack[i]);
578 	  Player.pack[i] = NULL;
579 	}
580 	if (Level->site[Player.x][Player.y].p_locf == L_WATER)
581 	  mprint("It sinks without a trace.");
582 	Player.packptr = 0;
583 	resetgamestatus(SUPPRESS_PRINTING);
584 	calc_melee();
585 	break;
586     }
587   }
588   show_screen();
589   return;
590 }
591 
592 
593 /* the effect of some weapon on monster m, with dmgmod a bonus to damage */
weapon_use(dmgmod,weapon,m)594 void weapon_use(dmgmod,weapon,m)
595 int dmgmod;
596 pob weapon;
597 struct monster *m;
598 {
599   int aux = (weapon==NULL ? -2 : weapon->aux); /* bare hands */
600   switch(aux) {
601     case -2: weapon_bare_hands(dmgmod,m); break;
602     default:
603     case I_NO_OP: weapon_normal_hit(dmgmod,weapon,m); break;
604     case I_ACIDWHIP: weapon_acidwhip(dmgmod,weapon,m); break;
605     case I_TANGLE: weapon_tangle(dmgmod,weapon,m); break;
606     case I_ARROW: weapon_arrow(dmgmod,weapon,m); break;
607     case I_BOLT: weapon_bolt(dmgmod,weapon,m); break;
608     case I_DEMONBLADE: weapon_demonblade(dmgmod,weapon,m); break;
609     case I_LIGHTSABRE: weapon_lightsabre(dmgmod,weapon,m); break;
610     case I_MACE_DISRUPT: weapon_mace_disrupt(dmgmod,weapon,m); break;
611     case I_VORPAL: weapon_vorpal(dmgmod,weapon,m); break;
612     case I_DESECRATE: weapon_desecrate(dmgmod,weapon,m); break;
613     case I_FIRESTAR: weapon_firestar(dmgmod,weapon,m); break;
614     case I_DEFEND: weapon_defend(dmgmod,weapon,m); break;
615     case I_VICTRIX: weapon_victrix(dmgmod,weapon,m); break;
616     case I_SCYTHE: weapon_scythe(dmgmod,weapon,m); break;
617   }
618 }
619 
620 
621 /* for printing actions in printactions above */
actionlocstr(dir)622 char *actionlocstr(dir)
623 char dir;
624 {
625   switch(dir) {
626   case 'L': strcpy(Str3,"low."); break;
627   case 'C': strcpy(Str3,"center."); break;
628   case 'H': strcpy(Str3,"high."); break;
629   default: strcpy(Str3,"wildly."); break;
630   }
631   return(Str3);
632 }
633 
634 
635 /* execute player combat actions versus monster m */
tacplayer(m)636 void tacplayer(m)
637 struct monster *m;
638 {
639   int i=0;
640 
641   while (i < strlen(Player.meleestr)) {
642     if (m->hp > 0) {
643       switch(Player.meleestr[i]) {
644       case 't': case 'T':
645 	if (Player.possessions[O_WEAPON_HAND] == NULL)
646 	  strcpy(Str1,"You punch ");
647 	else strcpy(Str1,"You thrust ");
648 	strcat(Str1,actionlocstr(Player.meleestr[i+1]));
649 	if (Verbosity == VERBOSE) mprint(Str1);
650 	if (player_hit(2*statmod(Player.dex),Player.meleestr[i+1],m))
651 	  weapon_use(0,Player.possessions[O_WEAPON_HAND],m);
652 	else player_miss(m,NORMAL_DAMAGE);
653 	break;
654       case 'c': case 'C':
655 	if (Player.possessions[O_WEAPON_HAND] == NULL)
656 	  strcpy(Str1,"You punch ");
657 	else if (Player.possessions[O_WEAPON_HAND]->type == CUTTING)
658 	  strcpy(Str1,"You cut ");
659 	else if (Player.possessions[O_WEAPON_HAND]->type == STRIKING)
660 	  strcpy(Str1,"You strike ");
661 	else strcpy(Str1,"You attack ");
662 	strcat(Str1,actionlocstr(Player.meleestr[i+1]));
663 	if (Verbosity == VERBOSE) mprint(Str1);
664 	if (player_hit(0,Player.meleestr[i+1],m))
665 	  weapon_use(2*statmod(Player.str),
666 		     Player.possessions[O_WEAPON_HAND],
667 		     m);
668 	else player_miss(m,NORMAL_DAMAGE);
669 	break;
670       case 'l': case 'L':
671 	strcpy(Str1,"You lunge ");
672 	strcat(Str1,actionlocstr(Player.meleestr[i+1]));
673 	if (Verbosity == VERBOSE) mprint(Str1);
674 	if (player_hit(Player.level+Player.dex,Player.meleestr[i+1],m))
675 	  weapon_use(Player.level,Player.possessions[O_WEAPON_HAND],m);
676 	else player_miss(m,NORMAL_DAMAGE);
677 	break;
678       }
679     }
680     i+=2;
681   }
682 }
683 
684 
685 
686 
687 /* checks to see if player hits with hitmod vs. monster m at location hitloc */
player_hit(hitmod,hitloc,m)688 int player_hit(hitmod,hitloc,m)
689 int hitmod;
690 char hitloc;
691 struct monster *m;
692 {
693   int i=0,blocks=FALSE,goodblocks=0,hit;
694   if (m->hp < 1) {
695     mprint("Unfortunately, your opponent is already dead!");
696     return(FALSE);
697   }
698   else {
699     if (hitloc == 'X') hitloc = random_loc();
700 
701     transcribe_monster_actions(m);
702 
703     while (i<strlen(m->meleestr)) {
704       if ((m->meleestr[i] == 'B') || (m->meleestr[i] == 'R')) {
705 	blocks = TRUE;
706 	if (hitloc == m->meleestr[i+1])
707 	  goodblocks++;
708       }
709       i+=2;
710     }
711 
712     if (! blocks) goodblocks = -1;
713     hit = hitp(Player.hit+hitmod,m->ac+goodblocks*10);
714     if ((! hit) && (goodblocks > 0)) {
715       if (m->uniqueness == COMMON) {
716 	strcpy(Str1,"The ");
717 	strcat(Str1,m->monstring);
718       }
719       else strcpy(Str1,m->monstring);
720       strcat(Str1," blocks it!");
721       if (Verbosity == VERBOSE) mprint(Str1);
722     }
723     return(hit);
724   }
725 }
726 
727 
728 
729 
730 
731 
732 
733 /* This function is used to undo all items temporarily, should
734 always be used in pairs with on being TRUE and FALSE, and may cause
735 anomalous stats and item-usage if used indiscriminately */
736 
toggle_item_use(on)737 void toggle_item_use(on)
738 int on;
739 {
740   static int used[MAXITEMS];
741   int i;
742   setgamestatus(SUPPRESS_PRINTING);
743   if (on)
744     for(i=0;i<MAXITEMS;i++) {
745       used[i] = FALSE;
746       if (Player.possessions[i] != NULL) {
747 	if ((used[i] = Player.possessions[i]->used) == TRUE) {
748 	  Player.possessions[i]->used = FALSE;
749 	  item_use(Player.possessions[i]);
750 	}
751       }
752     }
753   else {
754     for(i=1;i<MAXITEMS;i++)
755       if (used[i]) {
756 	Player.possessions[i]->used = TRUE;
757 	item_use(Player.possessions[i]);
758       }
759     calc_melee();
760     showflags();
761     dataprint();
762     timeprint();
763   }
764   resetgamestatus(SUPPRESS_PRINTING);
765 }
766 
767 
enter_site(site)768 void enter_site(site)
769 Symbol site;
770 {
771   switch(site) {
772   case CITY: change_environment(E_CITY); break;
773   case VILLAGE: change_environment(E_VILLAGE); break;
774   case CAVES: change_environment(E_CAVES); break;
775   case CASTLE: change_environment(E_CASTLE); break;
776   case VOLCANO: change_environment(E_VOLCANO); break;
777   case TEMPLE: change_environment(E_TEMPLE); break;
778   case DRAGONLAIR: change_environment(E_DLAIR); break;
779   case STARPEAK: change_environment(E_STARPEAK); break;
780   case MAGIC_ISLE: change_environment(E_MAGIC_ISLE); break;
781   default:print3("There's nothing to enter here!"); break;
782   }
783 }
784 
785 
786 
787 /* Switches context dungeon/countryside/city, etc */
change_environment(new_environment)788 void change_environment(new_environment)
789 char new_environment;
790 {
791   int i,emerging = FALSE;
792 
793   Player.sx = -1; Player.sy = -1; /* reset sanctuary if there was one */
794   resetgamestatus(LOST);	/* in case the player gets lost _on_ a site */
795 
796   resetgamestatus(FAST_MOVE);
797 
798   Last_Environment = Current_Environment;
799   if (Last_Environment == E_COUNTRYSIDE) {
800     LastCountryLocX = Player.x;
801     LastCountryLocY = Player.y;
802   }
803   if (((Last_Environment == E_CITY) ||
804        (Last_Environment == E_VILLAGE)) &&
805       ((new_environment == E_MANSION) ||
806        (new_environment == E_HOUSE) ||
807        (new_environment == E_HOVEL) ||
808        (new_environment == E_SEWERS) ||
809        (new_environment == E_ARENA))) {
810     LastTownLocX = Player.x;
811     LastTownLocY = Player.y;
812   }
813   else if (((Last_Environment == E_MANSION) ||
814 	    (Last_Environment == E_HOUSE) ||
815 	    (Last_Environment == E_HOVEL) ||
816 	    (Last_Environment == E_SEWERS) ||
817 	    (Last_Environment == E_ARENA)) &&
818 	   ((new_environment == E_CITY) ||
819 	    (new_environment == E_VILLAGE))) {
820     Player.x = LastTownLocX;
821     Player.y = LastTownLocY;
822     emerging = TRUE;
823   }
824 
825   Current_Environment = new_environment;
826   switch(new_environment) {
827   case E_ARENA:
828     LENGTH = 16;
829     WIDTH = 64;
830     Player.x = 5;
831     Player.y = 7;
832     setgamestatus(ARENA_MODE);
833     load_arena();
834     ScreenOffset = 0;
835     show_screen();
836     break;
837   case E_ABYSS:
838     LENGTH = 16;
839     WIDTH = 64;
840     Player.x = 32;
841     Player.y = 15;
842     load_abyss();
843     abyss_file();
844     lose_all_items();
845     ScreenOffset = 0;
846     show_screen();
847     break;
848   case E_CIRCLE:
849     LENGTH = 16;
850     WIDTH = 64;
851     Player.x = 32;
852     Player.y = 14;
853     load_circle(TRUE);
854     if (Objects[ARTIFACTID+21].uniqueness == UNIQUE_TAKEN) {
855       print1("A bemused voice says:");
856       print2("'Why are you here? You already have the Star Gem!'");
857       morewait();
858     }
859     else if (Player.rank[CIRCLE] > 0) {
860       print1("You hear the voice of the Prime Sorceror:");
861       print2("'Congratulations on your attainment of the Circle's Demesne.'");
862       morewait();
863       print1("For the honor of the Circle, you may take the Star Gem");
864       print2("and destroy it on the acme of Star Peak.");
865       morewait();
866       print1("Beware the foul LawBringer who resides there...");
867       print2("By the way, some of the members of the Circle seem to");
868       morewait();
869       print1("have become a bit jealous of your success --");
870       print2("I'd watch out for them too if I were you.");
871       morewait();
872     }
873     else if (Player.alignment > 0) {
874       print1("A mysterious ghostly image materializes in front of you.");
875       print2("It speaks: 'Greetings, fellow abider in Law. I am called");
876       morewait();
877       print1("The LawBringer. If you wish to advance our cause, obtain");
878       print2("the mystic Star Gem and return it to me on Star Peak.");
879       morewait();
880       print1("Beware the power of the evil Circle of Sorcerors and the");
881       print2("forces of Chaos which guard the gem.'");
882       morewait();
883       print1("The strange form fades slowly.");
884       morewait();
885     }
886     ScreenOffset = 0;
887     show_screen();
888     break;
889   case E_COURT:
890     WIDTH = 64;
891     LENGTH = 24;
892     Player.x = 32;
893     Player.y = 2;
894     LastCountryLocX = 6;
895     LastCountryLocY = 1;
896     load_court(TRUE);
897     ScreenOffset = 0;
898     show_screen();
899     break;
900   case E_MANSION:
901     WIDTH = 64;
902     LENGTH = 16;
903     load_house(E_MANSION, TRUE);
904     Player.y = 8;
905     Player.x = 2;
906     ScreenOffset = 0;
907     show_screen();
908     break;
909   case E_HOUSE:
910     WIDTH = 64;
911     LENGTH = 16;
912     load_house(E_HOUSE, TRUE);
913     Player.y = 13;
914     Player.x = 2;
915     ScreenOffset = 0;
916     show_screen();
917     break;
918   case E_HOVEL:
919     WIDTH = 64;
920     LENGTH = 16;
921     load_house(E_HOVEL, TRUE);
922     Player.y = 9;
923     Player.x = 2;
924     ScreenOffset = 0;
925     show_screen();
926     break;
927   case E_DLAIR:
928     WIDTH = 64;
929     LENGTH = 16;
930     Player.y = 9;
931     Player.x = 2;
932     load_dlair(gamestatusp(KILLED_DRAGONLORD), TRUE);
933     ScreenOffset = 0;
934     show_screen();
935     break;
936   case E_STARPEAK:
937     WIDTH = 64;
938     LENGTH = 16;
939     Player.y = 9;
940     Player.x = 2;
941     load_speak(gamestatusp(KILLED_LAWBRINGER), TRUE);
942     ScreenOffset = 0;
943     show_screen();
944     break;
945   case E_MAGIC_ISLE:
946     WIDTH = 64;
947     LENGTH = 16;
948     Player.y = 14;
949     Player.x = 62;
950     load_misle(gamestatusp(KILLED_EATER), TRUE);
951     ScreenOffset = 0;
952     show_screen();
953     break;
954   case E_TEMPLE:
955     WIDTH = 64;
956     LENGTH = 16;
957     load_temple(Country[Player.x][Player.y].aux, TRUE);
958     Player.y = 15;
959     Player.x = 32;
960     ScreenOffset = 0;
961     show_screen();
962     break;
963   case E_CITY:
964     WIDTH = 64;
965     LENGTH = 64;
966     if (emerging) {
967       print1("You emerge onto the street.");
968       emerging = FALSE;
969     }
970     else {
971       print1("You pass through the massive gates of Rampart, the city.");
972       Player.x = 62;
973       Player.y = 21;
974     }
975     if (City == NULL) load_city(TRUE);
976 #ifdef SAVE_LEVELS
977     else
978     	msdos_changelevel(Level,new_environment,0);
979 #endif
980     Level = City;
981     ScreenOffset = Player.y - (ScreenLength/2);
982     show_screen();
983     break;
984   case E_VILLAGE:
985     WIDTH = 64;
986     LENGTH = 16;
987     if (!emerging) {
988       /* different villages per different locations */
989       switch(Country[Player.x][Player.y].aux) {
990       case 1:
991 	Player.x = 0;
992 	Player.y = 6;
993 	Villagenum = 1;
994 	break;
995       default:
996 	print3("Very strange, a nonexistent village.");
997       case 2:
998 	Player.x = 39;
999 	Player.y = 15;
1000 	Villagenum = 2;
1001 	break;
1002       case 3:
1003 	Player.x = 63;
1004 	Player.y = 8;
1005 	Villagenum = 3;
1006 	break;
1007       case 4:
1008 	Player.x = 32;
1009 	Player.y = 15;
1010 	Villagenum = 4;
1011 	break;
1012       case 5:
1013 	Player.x = 2;
1014 	Player.y = 8;
1015 	Villagenum = 5;
1016 	break;
1017       case 6:
1018 	Player.x = 2;
1019 	Player.y = 2;
1020 	Villagenum = 6;
1021 	break;
1022       }
1023     }
1024     if ((! emerging) || (TempLevel == NULL)) load_village(Villagenum, TRUE);
1025     else if (TempLevel->environment != E_VILLAGE) load_village(Villagenum, TRUE);
1026 #ifndef SAVE_LEVELS
1027     else Level = TempLevel;
1028 #else
1029     else {
1030       msdos_changelevel(Level,new_environment,0);
1031       Level = TempLevel;
1032       }
1033 #endif
1034     if (emerging) {
1035       print1("You emerge onto the street.");
1036       emerging = FALSE;
1037     }
1038     else
1039       print1("You enter a small rural village.");
1040     ScreenOffset = 0;
1041     show_screen();
1042     break;
1043   case E_CAVES:
1044     WIDTH = 64;
1045     LENGTH = 64;
1046     print1("You enter a dark cleft in a hillside;");
1047     print2("You note signs of recent passage in the dirt nearby.");
1048     if (gamestatusp(MOUNTED)) {
1049       morewait();
1050       print1("Seeing as you might not be coming back, you feel compelled");
1051       print2("to let your horse go, rather than keep him hobbled outside.");
1052       resetgamestatus(MOUNTED);
1053       calc_melee();
1054     }
1055     MaxDungeonLevels = CAVELEVELS;
1056     if (Current_Dungeon != E_CAVES) {
1057 #ifdef SAVE_LEVELS
1058     msdos_changelevel(Level,0,-1);
1059 #endif
1060       free_dungeon();
1061       Dungeon = NULL;
1062       Level = NULL;
1063       Current_Dungeon = E_CAVES;
1064     }
1065     change_level(0,1,FALSE);
1066     break;
1067   case E_VOLCANO:
1068     WIDTH = 64;
1069     LENGTH = 64;
1070     print1("You pass down through the glowing crater.");
1071     if (gamestatusp(MOUNTED)) {
1072       morewait();
1073       print1("Seeing as you might not be coming back, you feel compelled");
1074       print2("to let your horse go, rather than keep him hobbled outside.");
1075       resetgamestatus(MOUNTED);
1076       calc_melee();
1077     }
1078     MaxDungeonLevels = VOLCANOLEVELS;
1079     if (Current_Dungeon != E_VOLCANO) {
1080 #ifdef SAVE_LEVELS
1081     msdos_changelevel(Level,0,-1);
1082 #endif
1083       free_dungeon();
1084       Dungeon = NULL;
1085       Level = NULL;
1086       Current_Dungeon = E_VOLCANO;
1087     }
1088     change_level(0,1,FALSE);
1089     break;
1090   case E_ASTRAL:
1091     WIDTH = 64;
1092     LENGTH = 64;
1093     print1("You are in a weird flickery maze.");
1094     if (gamestatusp(MOUNTED)) {
1095       print2("Your horse doesn't seem to have made it....");
1096       resetgamestatus(MOUNTED);
1097       calc_melee();
1098     }
1099     MaxDungeonLevels = ASTRALLEVELS;
1100     if (Current_Dungeon != E_ASTRAL) {
1101 #ifdef SAVE_LEVELS
1102     msdos_changelevel(Level,0,-1);
1103 #endif
1104       free_dungeon();
1105       Dungeon = NULL;
1106       Level = NULL;
1107       Current_Dungeon = E_ASTRAL;
1108     }
1109     change_level(0,1,FALSE);
1110     break;
1111   case E_CASTLE:
1112     WIDTH = 64;
1113     LENGTH = 64;
1114     print1("You cross the drawbridge. Strange forms move beneath the water.");
1115     if (gamestatusp(MOUNTED)) {
1116       morewait();
1117       print1("Seeing as you might not be coming back, you feel compelled");
1118       print2("to let your horse go, rather than keep him hobbled outside.");
1119       resetgamestatus(MOUNTED);
1120     }
1121     MaxDungeonLevels = CASTLELEVELS;
1122     if (Current_Dungeon != E_CASTLE) {
1123 #ifdef SAVE_LEVELS
1124     msdos_changelevel(Level,0,-1);
1125 #endif
1126       free_dungeon();
1127       Dungeon = NULL;
1128       Level = NULL;
1129       Current_Dungeon = E_CASTLE;
1130     }
1131     change_level(0,1,FALSE);
1132     break;
1133   case E_SEWERS:
1134     WIDTH = 64;
1135     LENGTH = 64;
1136     print1("You pry open a manhole and descend into the sewers below.");
1137     if (gamestatusp(MOUNTED)) {
1138       print2("You horse waits patiently outside the sewer entrance....");
1139       dismount_steed();
1140     }
1141     MaxDungeonLevels = SEWERLEVELS;
1142     if (Current_Dungeon != E_SEWERS) {
1143 #ifdef SAVE_LEVELS
1144     msdos_changelevel(Level,0,-1);
1145 #endif
1146       free_dungeon();
1147       Dungeon = NULL;
1148       Level = NULL;
1149       Current_Dungeon = E_SEWERS;
1150     }
1151     change_level(0,1,FALSE);
1152     break;
1153   case E_COUNTRYSIDE:
1154     WIDTH = 64;
1155     LENGTH = 64;
1156     print1("You return to the fresh air of the open countryside.");
1157     if (Last_Environment == E_CITY) {
1158       Player.x = 27;
1159       Player.y = 19;
1160     }
1161     else {
1162       Player.x = LastCountryLocX;
1163       Player.y = LastCountryLocY;
1164     }
1165     for(i=0;i<9;i++)
1166       c_set(Player.x+Dirs[0][i], Player.y+Dirs[1][i], SEEN);
1167     ScreenOffset = Player.y - (ScreenLength/2);
1168     show_screen();
1169     break;
1170   case E_TACTICAL_MAP:
1171     WIDTH = 64;
1172     LENGTH = 16;
1173     print1("You are now on the tactical screen; exit off any side to leave");
1174     make_country_screen(Country[Player.x][Player.y].current_terrain_type);
1175     make_country_monsters(Country[Player.x][Player.y].current_terrain_type);
1176     Player.x = WIDTH/2;
1177     Player.y = LENGTH/2;
1178     while (Level->site[Player.x][Player.y].locchar == WATER) {
1179       if (Player.y < LENGTH/2 + 5)
1180 	Player.y++;
1181       else if (Player.x > WIDTH/2 - 10) {
1182 	Player.x--;
1183 	Player.y = LENGTH/2 - 5;
1184       }
1185       else {
1186 	Level->site[Player.x][Player.y].locchar =
1187 	  Level->site[Player.x][Player.y].showchar = FLOOR;
1188 	Level->site[Player.x][Player.y].p_locf = L_NO_OP;
1189       }
1190     }
1191     ScreenOffset = 0;
1192     show_screen();
1193     break;
1194   case E_NEVER_NEVER_LAND: default:
1195     print1("There must be some mistake. You don't look like Peter Pan.");
1196     print2("(But here you are in Never-Never Land)");
1197     ScreenOffset = Player.y - (ScreenLength/2);
1198     show_screen();
1199     break;
1200   }
1201   setlastxy(Player.x, Player.y);
1202   if (Current_Environment != E_COUNTRYSIDE)
1203     showroom(Level->site[Player.x][Player.y].roomnumber);
1204   else
1205     terrain_check(FALSE);
1206 }
1207 
1208 
1209 
1210