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