1 /* omega copyright (C) by Laurence Raphael Brothers, 1987,1988,1989 */
2 /* aux1.c */
3 /* auxiliary functions for those in com.c, also see aux2.c and aux3.c */
4
5 #include "glob.h"
6
7
8
9 /* check to see if too much tunneling has been done in this level */
tunnelcheck()10 void tunnelcheck()
11 {
12 if ((Level->depth == 0 && Current_Environment != E_DLAIR) ||
13 Current_Environment == E_ASTRAL)
14 return;
15 Level->tunnelled++;
16 if ((Level->tunnelled) > LENGTH/4)
17 mprint("Dust and stone fragments fall on you from overhead.");
18 if ((Level->tunnelled) > LENGTH/2)
19 mprint("You hear groaning and creaking noises.");
20 if ((Level->tunnelled) > 3*LENGTH/4)
21 mprint("The floor trembles and you hear a loud grinding screech.");
22 if ((Level->tunnelled) > LENGTH) {
23 mprint("With a scream of tortured stone, the entire dungeon caves in!!!");
24 gain_experience(5000);
25 if (Player.status[SHADOWFORM]) {
26 change_environment(E_COUNTRYSIDE);
27 switch (Country[Player.x][Player.y].base_terrain_type)
28 {
29 case CASTLE:
30 case STARPEAK:
31 case CAVES:
32 case VOLCANO:
33 Country[Player.x][Player.y].current_terrain_type = MOUNTAINS;
34 break;
35 case DRAGONLAIR:
36 Country[Player.x][Player.y].current_terrain_type = DESERT;
37 break;
38 case MAGIC_ISLE:
39 Country[Player.x][Player.y].current_terrain_type = CHAOS_SEA;
40 break;
41 }
42 Country[Player.x][Player.y].base_terrain_type =
43 Country[Player.x][Player.y].current_terrain_type;
44 c_set(Player.x, Player.y, CHANGED);
45 print1("In your shadowy state, you float back up to the surface.");
46 return;
47 }
48 mprint("You are flattened into an unpleasant jellylike substance.");
49 p_death("dungeon cave-in");
50 }
51 }
52
53 /* displays a room's name */
showroom(i)54 void showroom(i)
55 int i;
56 {
57 strcpy(Str1,"");
58 strcpy(Str2,"");
59 switch(Current_Environment) {
60 case E_MANSION:
61 strcpy(Str2,"A luxurious mansion: ");
62 break;
63 case E_HOUSE:
64 strcpy(Str2,"A house: ");
65 break;
66 case E_HOVEL:
67 strcpy(Str2,"A hovel: ");
68 break;
69 case E_CITY:
70 strcpy(Str2,"The City of Rampart");
71 break;
72 case E_VILLAGE:
73 switch(Villagenum) {
74 case 1: strcpy(Str2,"The Village of Star View"); break;
75 case 2: strcpy(Str2,"The Village of Woodmere"); break;
76 case 3: strcpy(Str2,"The Village of Stormwatch"); break;
77 case 4: strcpy(Str2,"The Village of Thaumaris"); break;
78 case 5: strcpy(Str2,"The Village of Skorch"); break;
79 case 6: strcpy(Str2,"The Village of Whorfen"); break;
80 }
81 break;
82 case E_CAVES:
83 strcpy(Str2,"The Goblin Caves: ");
84 break;
85 case E_CASTLE:
86 strcpy(Str2,"The Archmage's Castle: ");
87 break;
88 case E_ASTRAL:
89 strcpy(Str2,"The Astral Plane: ");
90 break;
91 case E_VOLCANO:
92 strcpy(Str2,"The Volcano: ");
93 break;
94 case E_SEWERS:
95 strcpy(Str2,"The Sewers: ");
96 break;
97 case E_TACTICAL_MAP:
98 strcpy(Str2,"The Tactical Map ");
99 break;
100 default:
101 strcpy(Str2,"");
102 break;
103 }
104 if (Current_Environment == Current_Dungeon) {
105 strcpy(Str1,"Level ");
106 if (Level->depth < 10) {
107 Str1[6] = Level->depth + '0';
108 Str1[7] = 0;
109 }
110 else {
111 Str1[6] = (Level->depth / 10) + '0';
112 Str1[7] = (Level->depth % 10) + '0';
113 Str1[8] = 0;
114 }
115 strcat(Str1," (");
116 strcat(Str1,roomname(i));
117 strcat(Str1,")");
118 }
119 else if (strlen(Str2) == 0 || Current_Environment == E_MANSION ||
120 Current_Environment == E_HOUSE || Current_Environment == E_HOVEL)
121 strcpy(Str1,roomname(i));
122 strcat(Str2,Str1);
123 locprint(Str2);
124 }
125
126
player_on_sanctuary()127 int player_on_sanctuary()
128 {
129 if ((Player.x==Player.sx) &&
130 (Player.y==Player.sy))
131 return(TRUE);
132 else {
133 if (Player.patron) {
134 if ((Level->site[Player.x][Player.y].locchar == ALTAR) &&
135 (Level->site[Player.x][Player.y].aux == Player.patron))
136 return(TRUE);
137 else return(FALSE);
138 }
139 else return(FALSE);
140 }
141 }
142
143
144 /* check a move attempt, maybe attack something, return TRUE if ok to move. */
145 /* x y is the proposed place to move to */
p_moveable(x,y)146 int p_moveable(x,y)
147 int x,y;
148 {
149 setgamestatus(SKIP_MONSTERS);
150 if (! inbounds(x,y)) return (FALSE);
151 else if (Player.status[SHADOWFORM]) {
152 switch(Level->site[x][y].p_locf) {
153 case L_CHAOS: case L_ABYSS: case L_VOID:
154 return confirmation();
155 default:
156 resetgamestatus(SKIP_MONSTERS);
157 return(TRUE);
158 }
159 }
160 else if (loc_statusp(x,y,SECRET)) {
161 if (!gamestatusp(FAST_MOVE)) print3("Ouch!");
162 return(FALSE);
163 }
164 else if (Level->site[x][y].creature != NULL) {
165 if (! gamestatusp(FAST_MOVE)) {
166 fight_monster(Level->site[x][y].creature);
167 resetgamestatus(SKIP_MONSTERS);
168 return(FALSE);
169 }
170 else return(FALSE);
171 }
172 else if ((Level->site[x][y].locchar == WALL) ||
173 (Level->site[x][y].locchar == STATUE) ||
174 (Level->site[x][y].locchar == PORTCULLIS) ||
175 (Level->site[x][y].locchar == CLOSED_DOOR) ||
176 (gamestatusp(FAST_MOVE) &&
177 ((Level->site[x][y].locchar == HEDGE) ||
178 (Level->site[x][y].locchar == LAVA) ||
179 (Level->site[x][y].locchar == ABYSS) ||
180 (Level->site[x][y].locchar == VOID_CHAR) ||
181 (Level->site[x][y].locchar == FIRE) ||
182 (Level->site[x][y].locchar == WHIRLWIND) ||
183 (Level->site[x][y].locchar == WATER) ||
184 (Level->site[x][y].locchar == LIFT) ||
185 (Level->site[x][y].locchar == TRAP)))) {
186 if (! gamestatusp(FAST_MOVE)) print3("Ouch!");
187 return(FALSE);
188 }
189 else if (optionp(CONFIRM)) {
190 if ((Level->site[x][y].locchar == HEDGE) ||
191 (Level->site[x][y].locchar == LAVA) ||
192 (Level->site[x][y].locchar == FIRE) ||
193 (Level->site[x][y].locchar == WHIRLWIND) ||
194 (Level->site[x][y].locchar == ABYSS) ||
195 (Level->site[x][y].locchar == VOID_CHAR) ||
196 (Level->site[x][y].locchar == WATER) ||
197 (Level->site[x][y].locchar == RUBBLE) ||
198 (Level->site[x][y].locchar == LIFT) ||
199 (Level->site[x][y].locchar == TRAP)) {
200 /* horses WILL go into water... */
201 if (gamestatusp(MOUNTED)) {
202 if (Level->site[x][y].locchar != WATER ||
203 Level->site[x][y].p_locf != L_WATER) {
204 print1("You can't convince your steed to continue.");
205 setgamestatus(SKIP_MONSTERS);
206 return(FALSE);
207 }
208 else return(TRUE);
209 }
210 else if (confirmation()) resetgamestatus(SKIP_MONSTERS);
211 else setgamestatus(SKIP_MONSTERS);
212 return(!gamestatusp(SKIP_MONSTERS));
213 }
214 else {
215 resetgamestatus(SKIP_MONSTERS);
216 return(TRUE);
217 }
218 }
219 else {
220 resetgamestatus(SKIP_MONSTERS);
221 return(TRUE);
222 }
223 }
224
225
226
227 /* check a move attempt in the countryside */
p_country_moveable(x,y)228 int p_country_moveable(x,y)
229 int x,y;
230 {
231 if (! inbounds(x,y)) return (FALSE);
232 else if (optionp(CONFIRM)) {
233 if ((Country[x][y].current_terrain_type == CHAOS_SEA) ||
234 (Country[x][y].current_terrain_type == MOUNTAINS))
235 return(confirmation());
236 else return(TRUE);
237 }
238 else return(TRUE);
239 }
240
241
242
243
244
245 /* search once particular spot */
searchat(x,y)246 void searchat(x,y)
247 int x,y;
248 {
249 int i;
250 if (inbounds(x,y) && (random_range(3) || Player.status[ALERT])) {
251 if (loc_statusp(x,y,SECRET)) {
252 lreset(x,y,SECRET);
253 lset(x, y, CHANGED);
254 if ((Level->site[x][y].locchar==OPEN_DOOR) ||
255 (Level->site[x][y].locchar==CLOSED_DOOR)) {
256 mprint("You find a secret door!");
257 for(i=0;i<=8;i++) { /* FIXED! 12/25/98 */
258 lset(x+Dirs[0][i],y+Dirs[1][i],STOPS);
259 lset(x+Dirs[0][i], y+Dirs[1][i], CHANGED);
260 }
261 }
262 else mprint("You find a secret passage!");
263 drawvision(Player.x,Player.y);
264 }
265 if ((Level->site[x][y].p_locf >= TRAP_BASE) &&
266 (Level->site[x][y].locchar != TRAP) &&
267 (Level->site[x][y].p_locf <= TRAP_BASE+NUMTRAPS)) {
268 Level->site[x][y].locchar = TRAP;
269 lset(x, y, CHANGED);
270 mprint("You find a trap!");
271 drawvision(Player.x,Player.y);
272 resetgamestatus(FAST_MOVE);
273 }
274 }
275 }
276
277
278
279 /* This is to be called whenever anything might change player performance in
280 melee, such as changing weapon, statistics, etc. */
calc_melee()281 void calc_melee()
282 {
283 calc_weight();
284
285 Player.maxweight = (Player.str * Player.agi * 10);
286 Player.absorption = Player.status[PROTECTION];
287 Player.defense = 2 * statmod(Player.agi)+(Player.level/2);
288 Player.hit = Player.level + statmod(Player.dex)+1;
289 Player.dmg = statmod(Player.str)+3;
290 Player.speed = 5 - min(4,(statmod(Player.agi)/2));
291 if (Player.status[HASTED] > 0) Player.speed = Player.speed / 2;
292 if (Player.status[SLOWED] > 0) Player.speed = Player.speed * 2;
293 if (Player.itemweight > 0)
294 switch(Player.maxweight / Player.itemweight) {
295 case 0: Player.speed+=6; break;
296 case 1: Player.speed+=3; break;
297 case 2: Player.speed+=2; break;
298 case 3: Player.speed+=1; break;
299 }
300
301 if (Player.status[ACCURATE]) Player.hit+=20;
302 if (Player.status[HERO]) Player.hit+=Player.dex;
303 if (Player.status[HERO]) Player.dmg+=Player.str;
304 if (Player.status[HERO]) Player.defense+=Player.agi;
305 if (Player.status[HERO]) Player.speed=Player.speed / 2;
306
307 Player.speed = max(1,min(25,Player.speed));
308
309 if (gamestatusp(MOUNTED)) {
310 Player.speed = 3;
311 Player.hit += 10;
312 Player.dmg += 10;
313 }
314
315 /* weapon */
316 /* have to check for used since it could be a 2h weapon just carried
317 in one hand */
318 if (Player.possessions[O_WEAPON_HAND] != NULL)
319 if (Player.possessions[O_WEAPON_HAND]->used &&
320 ((Player.possessions[O_WEAPON_HAND]->objchar==WEAPON)||
321 (Player.possessions[O_WEAPON_HAND]->objchar==MISSILEWEAPON))) {
322 Player.hit +=
323 Player.possessions[O_WEAPON_HAND]->hit +
324 Player.possessions[O_WEAPON_HAND]->plus;
325 Player.dmg +=
326 Player.possessions[O_WEAPON_HAND]->dmg +
327 Player.possessions[O_WEAPON_HAND]->plus;
328 }
329
330 /* shield or defensive weapon */
331 if (Player.possessions[O_SHIELD] != NULL) {
332 Player.defense +=
333 Player.possessions[O_SHIELD]->aux +
334 Player.possessions[O_SHIELD]->plus;
335 }
336
337 /* armor */
338 if (Player.possessions[O_ARMOR] != NULL) {
339 Player.absorption += Player.possessions[O_ARMOR]->dmg;
340 Player.defense +=
341 Player.possessions[O_ARMOR]->plus -
342 Player.possessions[O_ARMOR]->aux;
343 }
344
345 if (strlen(Player.meleestr) > 2*maneuvers())
346 default_maneuvers();
347 comwinprint();
348 showflags();
349 dataprint();
350 }
351
352
353 /* player attacks monster m */
fight_monster(m)354 void fight_monster(m)
355 struct monster *m;
356 {
357 int hitmod = 0;
358 int reallyfight = TRUE;
359
360 if (Player.status[AFRAID]) {
361 print3("You are much too afraid to fight!");
362 reallyfight = FALSE;
363 }
364 else if (player_on_sanctuary()) {
365 print3("You restrain yourself from desecrating this holy place.");
366 reallyfight = FALSE;
367 }
368 else if (Player.status[SHADOWFORM]) {
369 print3("Your attack has no effect in your shadowy state.");
370 reallyfight = FALSE;
371 }
372 else if ((Player.status[BERSERK]<1) && (! m_statusp(m,HOSTILE))) {
373 if (optionp(BELLICOSE)) reallyfight = TRUE;
374 else reallyfight = confirmation();
375 }
376 else reallyfight = TRUE;
377
378 if (reallyfight) {
379
380 if (Lunarity == 1) hitmod += Player.level;
381 else if (Lunarity == -1) hitmod -= (Player.level / 2);
382
383 if (! m->attacked) Player.alignment -= 2; /* chaotic action */
384 m_status_set(m,AWAKE);
385 m_status_set(m,HOSTILE);
386 m->attacked = TRUE;
387 Player.hit += hitmod;
388 tacplayer(m);
389 Player.hit -= hitmod;
390 }
391 }
392
393
394
395
396 /* Attempt to break an object o */
damage_item(o)397 int damage_item(o)
398 pob o;
399 {
400 int i;
401 /* special case -- break star gem */
402 if (o->id == ARTIFACTID+21) {
403 print1("The Star Gem shatters into a million glistening shards....");
404 if (Current_Environment == E_STARPEAK) {
405 if (! gamestatusp(KILLED_LAWBRINGER))
406 print2("You hear an agonizing scream of anguish and despair.");
407 morewait();
408 print1("A raging torrent of energy escapes in an explosion of magic!");
409 print2("The energy flows to the apex of Star Peak where there is");
410 morewait();
411 clearmsg();
412 print1("an enormous explosion!");
413 morewait();
414 annihilate(1);
415 print3("You seem to gain strength in the chaotic glare of magic!");
416 Player.str = max(Player.str, Player.maxstr + 5); /* FIXED! 12/25/98 */
417 Player.pow = max(Player.pow, Player.maxpow + 5); /* ditto */
418 Player.alignment -= 200;
419 dispose_lost_objects(1,o);
420 }
421 else {
422 morewait();
423 print1("The shards coalesce back together again, and vanish");
424 print2("with a muted giggle.");
425 dispose_lost_objects(1,o);
426 Objects[o->id].uniqueness = UNIQUE_UNMADE; /* FIXED! 12/30/98 */
427 /* WDT HACK: the above is correct only if UNIQUE_UNMADE means that
428 * the artifact hasn't been generated yet. (Clearly, Omega is a
429 * little buggy in that regard with respect to artifacts in general
430 * -- it's almost trivial to force two identical artefacts to be
431 * generated right now.) */
432 }
433 return 1;
434 }
435 else {
436 if (o->fragility < random_range(30)) {
437 if (o->objchar == STICK) {
438 strcpy(Str1,"Your ");
439 strcat(Str1,(o->blessing >= 0 ? o->truename : o->cursestr));
440 strcat(Str1," explodes!");
441 print1(Str1);
442 morewait();
443 if (o->charge < 1)
444 nprint1(" Fzzz... Out of Power... Oh well...");
445 else {
446 nprint1(" Ka-Blamm!!!");
447 /* general case. Some sticks will eventually do special things */
448 morewait();
449 manastorm(Player.x, Player.y, o->charge*o->level*10);
450 dispose_lost_objects(1,o);
451 }
452 return 1;
453 }
454 else if ((o->blessing > 0) && (o->level > random_range(10))) {
455 strcpy(Str1,"Your ");
456 strcat(Str1,itemid(o));
457 strcat(Str1," glows strongly.");
458 print1(Str1);
459 return 0;
460 }
461 else if ((o->blessing < -1) && (o->level > random_range(10))) {
462 strcpy(Str1,"You hear an evil giggle from your ");
463 strcat(Str1,itemid(o));
464 print1(Str1);
465 return 0;
466 }
467 else if (o->plus > 0) {
468 strcpy(Str1,"Your ");
469 strcat(Str1,itemid(o));
470 strcat(Str1," glows and then fades.");
471 print1(Str1);
472 o->plus--;
473 return 0;
474 }
475 else {
476 if (o->blessing > 0) print1("You hear a faint despairing cry!");
477 else if (o->blessing < 0) print1("You hear an agonized scream!");
478 strcpy(Str1,"Your ");
479 strcat(Str1,itemid(o));
480 strcat(Str1," shatters in a thousand lost fragments!");
481 print2(Str1);
482 morewait();
483 dispose_lost_objects(1,o);
484 return 1;
485 }
486 }
487 return 0;
488 }
489 }
490
491
492
493
494
495
496
497 /* do dmg points of damage of type dtype, from source fromstring */
p_damage(dmg,dtype,fromstring)498 void p_damage(dmg,dtype,fromstring)
499 int dmg,dtype;
500 char *fromstring;
501 {
502 if (! p_immune(dtype)) {
503 if (gamestatusp(FAST_MOVE)) {
504 drawvision(Player.x,Player.y);
505 resetgamestatus(FAST_MOVE);
506 }
507 if (dtype == NORMAL_DAMAGE) Player.hp -= max(1,(dmg-Player.absorption));
508 else Player.hp -= dmg;
509 if (Player.hp < 1) p_death(fromstring);
510 }
511 else mprint("You resist the effects!");
512 dataprint();
513 }
514
515 /* game over, you lose! */
p_death(fromstring)516 void p_death(fromstring)
517 char *fromstring;
518 {
519 Player.hp = -1;
520 print3("You died!");
521 morewait();
522 display_death(fromstring);
523 #ifdef SAVE_LEVELS
524 kill_all_levels();
525 #endif
526 endgraf();
527 exit(0);
528 }
529
530
531 /* move the cursor around, like for firing a wand, sets x and y to target */
setspot(x,y)532 void setspot(x,y)
533 int *x,*y;
534 {
535 char c = ' ';
536 mprint("Targeting.... ? for help");
537 omshowcursor(*x,*y);
538 while ((c != '.') && (c != ESCAPE)) {
539 c = lgetc();
540 switch(c) {
541 case 'h':case '4': movecursor(x,y,-1,0); break;
542 case 'j':case '2': movecursor(x,y,0,1); break;
543 case 'k':case '8': movecursor(x,y,0,-1); break;
544 case 'l':case '6': movecursor(x,y,1,0); break;
545 case 'b':case '1': movecursor(x,y,-1,1); break;
546 case 'n':case '3': movecursor(x,y,1,1); break;
547 case 'y':case '7': movecursor(x,y,-1,-1); break;
548 case 'u':case '9': movecursor(x,y,1,-1); break;
549 case '?':
550 clearmsg();
551 mprint("Use vi keys or numeric keypad to move cursor to target.");
552 mprint("Hit the '.' key when done, or ESCAPE to abort.");
553 break;
554 }
555 }
556 if (c==ESCAPE) *x = *y= ABORT;
557 screencheck(Player.y);
558 }
559
560
561 /* get a direction: return index into Dirs array corresponding to direction */
getdir()562 int getdir()
563 {
564 while (1) {
565 mprint("Select direction [hjklyubn, ESCAPE to quit]: ");
566 switch (mgetc()) {
567 case '4':
568 case 'h':
569 case 'H': return(5);
570 case '2':
571 case 'j':
572 case 'J': return(6);
573 case '8':
574 case 'k':
575 case 'K': return(7);
576 case '6':
577 case 'l':
578 case 'L': return(4);
579 case '7':
580 case 'y':
581 case 'Y': return(3);
582 case '9':
583 case 'u':
584 case 'U': return(1);
585 case '1':
586 case 'b':
587 case 'B': return(2);
588 case '3':
589 case 'n':
590 case 'N': return(0);
591 case ESCAPE: return(ABORT);
592 default: print3("That's not a direction! ");
593 }
594 }
595 }
596
597
598
599 /* functions describes monster m's state for examine function */
mstatus_string(m)600 char *mstatus_string(m)
601 struct monster *m;
602 {
603 if (m_statusp(m, M_INVISIBLE) && !Player.status[TRUESIGHT])
604 strcpy(Str2, "Some invisible creature");
605 else if (m->uniqueness == COMMON) {
606 if (m->hp < Monsters[m->id].hp / 3)
607 strcpy(Str2,"a grievously injured ");
608 else if (m->hp < Monsters[m->id].hp / 2)
609 strcpy(Str2,"a severely injured ");
610 else if (m->hp < Monsters[m->id].hp)
611 strcpy(Str2,"an injured ");
612 else strcpy(Str2,getarticle(m->monstring));
613 if (m->level > Monsters[m->id].level) {
614 strcat(Str2," (level ");
615 strcat(Str2,wordnum(m->level+1-Monsters[m->id].level));
616 strcat(Str2,") ");
617 }
618 strcat(Str2,m->monstring);
619 }
620 else {
621 strcpy(Str2,m->monstring);
622 if (m->hp < Monsters[m->id].hp / 3)
623 strcat(Str2," who is grievously injured ");
624 else if (m->hp < Monsters[m->id].hp / 2)
625 strcat(Str2," who is severely injured ");
626 else if (m->hp < Monsters[m->id].hp)
627 strcat(Str2," who is injured ");
628 }
629 return(Str2);
630 }
631
632
633
634
635 /* for the examine function */
describe_player()636 void describe_player()
637 {
638 if (Player.hp < (Player.maxhp /5))
639 print1("A grievously injured ");
640 else if (Player.hp < (Player.maxhp /2))
641 print1("A seriously wounded ");
642 else if (Player.hp < Player.maxhp)
643 print1("A somewhat bruised ");
644 else print1("A fit ");
645
646 if (Player.status[SHADOWFORM])
647 nprint1("shadow");
648 else
649 nprint1(levelname(Player.level));
650 nprint1(" named ");
651 nprint1(Player.name);
652 if (gamestatusp(MOUNTED))
653 nprint1(" (riding a horse.)");
654 }
655
656
657 /* access to player experience... */
658 /* share out experience among guild memberships */
gain_experience(amount)659 void gain_experience(amount)
660 int amount;
661 {
662 int i,count=0,share;
663 Player.xp += (long) amount;
664 gain_level(); /* actually, check to see if should gain level */
665 for(i=0;i<NUMRANKS;i++)
666 if (Player.guildxp[i] > 0) count++;
667 share = amount/(max(count,1));
668 for(i=0;i<NUMRANKS;i++)
669 if (Player.guildxp[i] > 0) Player.guildxp[i]+=share;
670 }
671
672 /* try to hit a monster in an adjacent space. If there are none
673 return FALSE. Note if you're berserk you get to attack ALL
674 adjacent monsters! */
goberserk()675 int goberserk()
676 {
677 int wentberserk=FALSE,i;
678 char meleestr[80];
679 strcpy(meleestr,Player.meleestr);
680 strcpy(Player.meleestr,"lLlClH");
681 for(i=0;i<8;i++)
682 if (Level->site[Player.x+Dirs[0][i]][Player.y+Dirs[1][i]].creature
683 != NULL) {
684 wentberserk=TRUE;
685 fight_monster(Level->site[Player.x+Dirs[0][i]][Player.y+Dirs[1][i]].creature);
686 morewait();
687 }
688 strcpy(Player.meleestr,meleestr);
689 return(wentberserk);
690 }
691
692 /* identifies a trap for examine() by its aux value */
trapid(trapno)693 char *trapid(trapno)
694 int trapno;
695 {
696 switch (trapno) {
697 case L_TRAP_SIREN:return("A siren trap");
698 case L_TRAP_DART:return("A dart trap");
699 case L_TRAP_PIT:return("A pit");
700 case L_TRAP_SNARE:return("A snare");
701 case L_TRAP_BLADE:return("A blade trap");
702 case L_TRAP_FIRE:return("A fire trap");
703 case L_TRAP_TELEPORT:return("A teleport trap");
704 case L_TRAP_DISINTEGRATE:return("A disintegration trap");
705 case L_TRAP_DOOR:return("A trap door");
706 case L_TRAP_MANADRAIN:return("A manadrain trap");
707 case L_TRAP_ACID:return("An acid shower trap");
708 case L_TRAP_SLEEP_GAS:return("A sleep gas trap");
709 case L_TRAP_ABYSS:return("A concealed entrance to the abyss");
710 default: return("A completely inoperative trap.");
711 }
712 }
713
714
715 /* checks current food status of player, every hour, and when food is eaten */
foodcheck()716 void foodcheck()
717 {
718 if (Player.food > 48) {
719 print3("You vomit up your huge meal.");
720 Player.food = 12;
721 }
722 else if (Player.food == 30)
723 print3("Time for a smackerel of something.");
724 else if (Player.food == 20)
725 print3("You feel hungry.");
726 else if (Player.food == 12)
727 print3("You are ravenously hungry.");
728 else if (Player.food == 3) {
729 print3("You feel weak.");
730 if (gamestatusp(FAST_MOVE)) {
731 drawvision(Player.x,Player.y);
732 resetgamestatus(FAST_MOVE);
733 }
734 }
735 else if (Player.food < 0) {
736 if (gamestatusp(FAST_MOVE)) {
737 drawvision(Player.x,Player.y);
738 resetgamestatus(FAST_MOVE);
739 }
740 print3("You're starving!");
741 p_damage(-5*Player.food,UNSTOPPABLE,"starvation");
742 }
743 showflags();
744 }
745
746
747
748
749 /* see whether room should be illuminated */
roomcheck()750 void roomcheck()
751 {
752 static int oldroomno = -1;
753 #ifdef MSDOS_SUPPORTED_ANTIQUE
754 static int oldlevel = -1;
755 #else
756 static plv oldlevel = NULL;
757 #endif
758 int roomno = Level->site[Player.x][Player.y].roomnumber;
759
760 if ((roomno == RS_CAVERN) ||
761 (roomno == RS_SEWER_DUCT) ||
762 (roomno == RS_KITCHEN) ||
763 (roomno == RS_BATHROOM) ||
764 (roomno == RS_BEDROOM) ||
765 (roomno == RS_DININGROOM) ||
766 (roomno == RS_CLOSET) ||
767 (roomno > ROOMBASE))
768 if ((! loc_statusp(Player.x,Player.y,LIT)) &&
769 (! Player.status[BLINDED]) &&
770 (Player.status[ILLUMINATION] || (difficulty() < 6))) {
771 showroom(Level->site[Player.x][Player.y].roomnumber);
772 spreadroomlight(Player.x,Player.y,roomno);
773 levelrefresh();
774 }
775 if ((oldroomno != roomno) ||
776 #ifdef MSDOS_SUPPORTED_ANTIQUE
777 (oldlevel != Level->depth)) {
778 #else
779 (oldlevel != Level)) {
780 #endif
781 showroom(roomno);
782 oldroomno = roomno;
783 #ifdef MSDOS_SUPPORTED_ANTIQUE
784 oldlevel = Level->depth;
785 #else
786 oldlevel = Level;
787 #endif
788 }
789 }
790
791
792
793
794
795 /* ask for mercy */
796 void surrender(m)
797 struct monster *m;
798 {
799 int i;
800 long bestitem,bestvalue;
801
802 switch(random_range(4)) {
803 case 0: print1("You grovel at the monster's feet..."); break;
804 case 1: print1("You cry 'uncle'!"); break;
805 case 2: print1("You beg for mercy."); break;
806 case 3: print1("You yield to the monster."); break;
807 }
808 if (m->id == GUARD) {
809 if (m_statusp(m,HOSTILE))
810 monster_talk(m);
811 else {
812 print2("The guard (bored): Have you broken a law? [yn] ");
813 if (ynq2() == 'y') {
814 print2("The guard grabs you, and drags you to court.");
815 morewait();
816 send_to_jail();
817 }
818 else print2("Then don't bother me. Scat!");
819 }
820 }
821 else if ((m->talkf==M_NO_OP) ||
822 (m->talkf==M_TALK_STUPID))
823 print3("Your plea is ignored.");
824 else {
825 morewait();
826 print1("Your surrender is accepted.");
827 if (Player.cash > 0) nprint1(" All your gold is taken....");
828 Player.cash = 0;
829 bestvalue = 0;
830 bestitem = ABORT;
831 for (i=1;i<MAXITEMS;i++)
832 if (Player.possessions[i] != NULL)
833 if (bestvalue < true_item_value(Player.possessions[i])) {
834 bestitem = i;
835 bestvalue = true_item_value(Player.possessions[i]);
836 }
837 if (bestitem != ABORT) {
838 print2("You also give away your best item... ");
839 nprint2(itemid(Player.possessions[bestitem]));
840 nprint2(".");
841 morewait();
842 givemonster(m,Player.possessions[bestitem]);
843 morewait(); /* msgs come from givemonster */
844 conform_unused_object(Player.possessions[bestitem]);
845 Player.possessions[bestitem] = NULL;
846 }
847 print2("You feel less experienced... ");
848 Player.xp = max(0,Player.xp - m->xpv);
849 nprint2("The monster seems more experienced!");
850 m->level = (min(10,m->level+1));
851 m->hp += m->level*20;
852 m->hit += m->level;
853 m->dmg += m->level;
854 m->ac += m->level;
855 m->xpv += m->level*10;
856 morewait();
857 clearmsg();
858 if ((m->talkf == M_TALK_EVIL) && random_range(10)) {
859 print1("It continues to attack you, laughing evilly!");
860 m_status_set(m,HOSTILE);
861 m_status_reset(m,GREEDY);
862 }
863 else if (m->id == HORNET || m->id == GUARD)
864 print1("It continues to attack you. ");
865 else {
866 print1("The monster leaves, chuckling to itself....");
867 m_teleport(m);
868 }
869 }
870 dataprint();
871 }
872
873
874 /* threaten a monster */
875 void threaten(m)
876 struct monster *m;
877 {
878 char response;
879 switch(random_range(4)) {
880 case 0:mprint("You demand that your opponent surrender!"); break;
881 case 1:mprint("You threaten to do bodily harm to it."); break;
882 case 2:mprint("You attempt to bluster it into submission."); break;
883 case 3:mprint("You try to cow it with your awesome presence."); break;
884 }
885 morewait(); /* FIXED! 12/25/98 */
886 if (! m_statusp(m,HOSTILE)) {
887 print3("You only annoy it with your futile demand.");
888 m_status_set(m,HOSTILE);
889 }
890 else if (((m->level*2 > Player.level) && (m->hp > Player.dmg)) ||
891 (m->uniqueness != COMMON))
892 print1("It sneers contemptuously at you.");
893 else if ((m->talkf != M_TALK_GREEDY) &&
894 (m->talkf != M_TALK_HUNGRY) &&
895 (m->talkf != M_TALK_EVIL) &&
896 (m->talkf != M_TALK_MAN) &&
897 (m->talkf != M_TALK_BEG) &&
898 (m->talkf != M_TALK_THIEF) &&
899 (m->talkf != M_TALK_MERCHANT) &&
900 (m->talkf != M_TALK_IM))
901 print1("Your demand is ignored");
902 else {
903 print1("It yields to your mercy.");
904 Player.alignment+=3;
905 print2("Kill it, rob it, or free it? [krf] ");
906 do response = (char) mcigetc();
907 while ((response != 'k')&&(response != 'r')&&(response !='f'));
908 if (response == 'k') {
909 m_death(m);
910 print2("You treacherous rogue!");
911 Player.alignment -= 13;
912 }
913 else if (response == 'r') {
914 Player.alignment-=2;
915 print2("It drops its treasure and flees.");
916 m_dropstuff(m);
917 m->hp = -1;
918 Level->site[m->x][m->y].creature = NULL;
919 putspot(m->x,m->y,getspot(m->x,m->y,FALSE));
920 }
921 else {
922 Player.alignment+=2;
923 print2("'If you love something set it free ... '");
924 if (random_range(100)==13) {
925 morewait();
926 print2("'...If it doesn't come back, hunt it down and kill it.'");
927 }
928 print3("It departs with a renewed sense of its own mortality.");
929 m->hp = -1;
930 Level->site[m->x][m->y].creature = NULL;
931 putspot(m->x,m->y,getspot(m->x,m->y,FALSE));
932 }
933 }
934 }
935
936 /* name of the player's experience level */
937 char *levelname(level)
938 int level;
939 {
940 switch(level) {
941 case 0:strcpy(Str3,"neophyte");break;
942 case 1:strcpy(Str3,"beginner");break;
943 case 2:strcpy(Str3,"tourist");break;
944 case 3:strcpy(Str3,"traveller");break;
945 case 4:strcpy(Str3,"wayfarer");break;
946 case 5:strcpy(Str3,"peregrinator");break;
947 case 6:strcpy(Str3,"wanderer");break;
948 case 7:strcpy(Str3,"hunter");break;
949 case 8:strcpy(Str3,"scout");break;
950 case 9:strcpy(Str3,"trailblazer");break;
951 case 10:strcpy(Str3,"discoverer");break;
952 case 11:strcpy(Str3,"explorer");break;
953 case 12:strcpy(Str3,"senior explorer");break;
954 case 13:strcpy(Str3,"ranger");break;
955 case 14:strcpy(Str3,"ranger captain");break;
956 case 15:strcpy(Str3,"ranger knight");break;
957 case 16:strcpy(Str3,"adventurer");break;
958 case 17:strcpy(Str3,"experienced adventurer");break;
959 case 18:strcpy(Str3,"skilled adventurer");break;
960 case 19:strcpy(Str3,"master adventurer");break;
961 case 20:strcpy(Str3,"hero");break;
962 case 21:strcpy(Str3,"superhero");break;
963 case 22:strcpy(Str3,"demigod");break;
964 default:
965 if (level < 100) {
966 strcpy(Str3,"Order ");
967 Str3[6] = ((level/10)-2) + '0';
968 Str3[7] = 0;
969 strcat(Str3," Master of Omega");
970 }
971 else strcpy(Str3,"Ultimate Master of Omega");
972 break;
973 }
974 return(Str3);
975 }
976