comparison urogue/move.c @ 256:c495a4f288c6

Import UltraRogue from the Roguelike Restoration Project (r1490)
author John "Elwin" Edwards
date Tue, 31 Jan 2017 19:56:04 -0500
parents
children e52a8a7ad4c5
comparison
equal deleted inserted replaced
253:d9badb9c0179 256:c495a4f288c6
1 /*
2 move.c - Hero movement commands
3
4 UltraRogue: The Ultimate Adventure in the Dungeons of Doom
5 Copyright (C) 1985, 1986, 1992, 1993, 1995 Herb Chong
6 All rights reserved.
7
8 Based on "Advanced Rogue"
9 Copyright (C) 1984, 1985 Michael Morgan, Ken Dalka
10 All rights reserved.
11
12 Based on "Rogue: Exploring the Dungeons of Doom"
13 Copyright (C) 1980, 1981 Michael Toy, Ken Arnold and Glenn Wichman
14 All rights reserved.
15
16 See the file LICENSE.TXT for full copyright and licensing information.
17 */
18
19 #include <stdlib.h>
20 #include <ctype.h>
21 #include "rogue.h"
22
23 /*
24 do_run()
25 Start the hero running
26 */
27
28 void
29 do_run(char ch)
30 {
31 running = TRUE;
32 after = FALSE;
33 runch = ch;
34
35 if (doorstop && !on(player, ISBLIND))
36 {
37 door_stop = TRUE;
38 firstmove = TRUE;
39 }
40 }
41
42 /*
43 step_ok()
44 returns true if it is ok for type to step on ch flgptr will be
45 NULL if we don't know what the monster is yet!
46 */
47
48 int
49 step_ok(int y, int x, int can_on_monst, struct thing *flgptr)
50 {
51 struct linked_list *item;
52 char ch;
53
54 /* What is here? Don't check monster window if MONSTOK is set */
55
56 if (can_on_monst == MONSTOK)
57 ch = CCHAR( mvinch(y, x) );
58 else
59 ch = winat(y, x);
60
61 switch (ch)
62 {
63 case ' ':
64 case '|':
65 case '-':
66 case SECRETDOOR:
67 if (flgptr && on(*flgptr, CANINWALL))
68 return(TRUE);
69
70 return(FALSE);
71
72 case SCROLL:
73 /*
74 * If it is a scroll, it might be a scare monster scroll so
75 * we need to look it up to see what type it is.
76 */
77
78 if (flgptr && flgptr->t_ctype == C_MONSTER)
79 {
80 item = find_obj(y, x);
81
82 if (item != NULL && (OBJPTR(item))->o_type == SCROLL
83 && (OBJPTR(item))->o_which == S_SCARE
84 && rnd(flgptr->t_stats.s_intel) < 12)
85 return(FALSE); /* All but smart ones are scared */
86 }
87 return(TRUE);
88
89 default:
90 return(!isalpha(ch));
91 }
92 }
93
94 /*
95 corr_move()
96 Check to see that a move is legal. If so, return correct
97 character. If not, if player came from a legal place, then try to turn
98 him.
99 */
100
101 void
102 corr_move(int dy, int dx)
103 {
104 char ch;
105 short legal = 0; /* Number of legal alternatives */
106 int y = 0, x = 0; /* Holds legal new position */
107 int *ny, *nx; /* Point to which direction to change */
108
109 /* New position */
110
111 player.t_nxtpos.y = hero.y + dy;
112 player.t_nxtpos.x = hero.x + dx;
113
114 /* A bad diagonal move is illegal */
115
116 if (!diag_ok(&hero, &player.t_nxtpos, &player))
117 return;
118
119 /* If it is a legal move, just return */
120
121 if (player.t_nxtpos.x >= 0 && player.t_nxtpos.x < COLS && player.t_nxtpos.y > 0 && player.t_nxtpos.y < LINES - 2)
122 {
123 ch = winat(player.t_nxtpos.y, player.t_nxtpos.x);
124
125 switch (ch)
126 {
127 case ' ':
128 case '|':
129 case '-':
130 break;
131 default:
132 return;
133 }
134 }
135
136 /* Check the legal alternatives */
137
138 if (dy == 0)
139 {
140 ny = &dy;
141 nx = &dx;
142 }
143 else
144 {
145 ny = &dx;
146 nx = &dy;
147 }
148
149 for (*nx = 0, *ny = -1; *ny < 2; *ny += 2)
150 {
151 /* New position */
152 player.t_nxtpos.y = hero.y + dy;
153 player.t_nxtpos.x = hero.x + dx;
154
155 if (player.t_nxtpos.x < 0 || player.t_nxtpos.x > COLS - 1 || player.t_nxtpos.y < 1 || player.t_nxtpos.y > LINES - 3)
156 continue;
157
158 ch = winat(player.t_nxtpos.y, player.t_nxtpos.x);
159
160 switch (ch)
161 {
162 case ' ':
163 case '|':
164 case '-':
165 break;
166 default:
167 legal++;
168 y = dy;
169 x = dx;
170 }
171 }
172
173 /* If we have 2 legal moves, make no change */
174
175 if (legal != 1)
176 return;
177
178 /* Make the change */
179
180 if (y == 0) /* Move horizontally */
181 {
182 if (x == 1)
183 runch = 'l';
184 else
185 runch = 'h';
186 }
187 else /* Move vertically */
188 {
189 if (y == 1)
190 runch = 'j';
191 else
192 runch = 'k';
193 }
194
195 return;
196 }
197
198
199 /*
200 do_move()
201 Check to see that a move is legal. If it is handle the
202 consequences (fighting, picking up, etc.)
203 */
204
205 void
206 do_move(int dy, int dx)
207 {
208 char ch;
209 coord old_hero;
210 char hch;
211
212 firstmove = FALSE;
213
214 if (player.t_no_move)
215 {
216 player.t_no_move--;
217 msg("You are still stuck in the bear trap.");
218 return;
219 }
220
221 /* Do a confused move (maybe) */
222
223 if ((rnd(100) < 80 && on(player, ISHUH)) ||
224 (is_wearing(R_DELUSION) && rnd(100) < 25) ||
225 on(player, STUMBLER) && rnd(40) == 0)
226 player.t_nxtpos = rndmove(&player);
227 else
228 {
229 player.t_nxtpos.y = hero.y + dy;
230 player.t_nxtpos.x = hero.x + dx;
231 }
232
233 /*
234 * Check if he tried to move off the screen or make an illegal
235 * diagonal move, and stop him if he did.
236 */
237
238 if (player.t_nxtpos.x < 0 || player.t_nxtpos.x > COLS - 1 || player.t_nxtpos.y < 1 || player.t_nxtpos.y >= LINES - 2
239 || !diag_ok(&hero, &player.t_nxtpos, &player))
240 {
241 after = fighting = running = FALSE;
242 return;
243 }
244
245 if (running && ce(hero, player.t_nxtpos))
246 after = running = FALSE;
247
248 ch = winat(player.t_nxtpos.y, player.t_nxtpos.x);
249
250 if (isalpha(ch))
251 debug("Moving onto monster %c",ch);
252
253 /* Take care of hero trying to move close to something frightening */
254
255 if (on(player, ISFLEE))
256 {
257 if (rnd(10) < 1)
258 {
259 turn_off(player, ISFLEE);
260 msg("You regain your composure.");
261 }
262 else if (DISTANCE(player.t_nxtpos, player.t_chasee->t_pos) <
263 DISTANCE(hero,player.t_chasee->t_pos))
264 return;
265 }
266
267 /* Take care of hero being held */
268
269 if (on(player, ISHELD) && !isalpha(ch))
270 {
271 if (rnd(pstats.s_str) > 14)
272 {
273 msg("You break free of the hold.");
274
275 if (--hold_count == 0)
276 turn_off(player, ISHELD);
277 }
278 else
279 {
280 msg("You are being held.");
281 return;
282 }
283 }
284
285 /* Might lose disguise */
286
287 if (on(player, ISDISGUISE) && rnd(11 * pstats.s_dext) == 0)
288 {
289 extinguish_fuse(FUSE_UNDISGUISE);
290 undisguise(NULL);
291 }
292
293 /* assume he's not in a wall */
294
295 if (!isalpha(ch))
296 turn_off(player, ISINWALL);
297
298 hch = CCHAR( mvinch(hero.y, hero.x) ); /* Where hero was */
299 old_hero = hero; /* Save hero's old position */
300
301 switch (ch)
302 {
303 case ' ':
304 case '|':
305 case '-':
306 case SECRETDOOR:
307 if (off(player, CANINWALL))
308 {
309 after = running = FALSE;
310 return;
311 }
312 else if (running)
313 {
314 after = running = FALSE;
315 return;
316 }
317 turn_on(player, ISINWALL);
318 break;
319
320 case TRAPDOOR:
321 case TELTRAP:
322 case BEARTRAP:
323 case SLEEPTRAP:
324 case ARROWTRAP:
325 case DARTTRAP:
326 case POOL:
327 case MAZETRAP:
328 case FIRETRAP:
329 case POISONTRAP:
330 case LAIR:
331 case RUSTTRAP:
332 ch = be_trapped(&player, player.t_nxtpos);
333
334 if (!is_wearing(R_LEVITATION) && off(player, CANFLY) &&
335 (old_hero.x != hero.x || old_hero.y != hero.y
336 || pool_teleport))
337 {
338 pool_teleport = FALSE;
339 return;
340 }
341
342 break;
343
344 case GOLD:
345 case POTION:
346 case SCROLL:
347 case FOOD:
348 case WEAPON:
349 case ARMOR:
350 case RING:
351 case ARTIFACT:
352 case STICK:
353 running = FALSE;
354 take = ch;
355 break;
356
357 default:
358 break;
359 }
360
361 if (ch == FIRETRAP)
362 light(&hero);
363
364 hero = player.t_nxtpos; /* Move the hero */
365
366 /* adjust lighting */
367
368 if (roomin(hero) == NULL && (hch == '-' || hch == '|' ||
369 hch == DOOR || hch == SECRETDOOR))
370 {
371 /* Leaving a room -- darken it */
372 struct room *rp = roomin(old_hero);
373 int is_lit = FALSE;
374
375 if (!(rp->r_flags & ISDARK))
376 is_lit = TRUE;
377
378 rp->r_flags |= ISDARK; /* Fake darkness */
379 light(&old_hero);
380
381 if (is_lit)
382 rp->r_flags &= ~ISDARK; /* Restore light state */
383 }
384 else if (ch == DOOR || ch == SECRETDOOR || ch == '|' || ch == '-')
385 {
386 /* Entering a room */
387 running = FALSE;
388 if (hch != '|' && hch != '-')
389 light(&hero); /* knows whether the hero can see things in */
390 }
391
392 /* handle other situations */
393
394 if (ch == STAIRS)
395 running = FALSE;
396 else if (ch == POST)
397 {
398 running = FALSE;
399 new_level(POSTLEV,0);
400 return;
401 }
402 else if (isalpha(ch))
403 {
404 struct linked_list *mp;
405 struct thing *tp;
406 char t;
407
408 running = FALSE;
409
410 mp = find_mons(hero.y, hero.x);
411
412 if (mp == NULL)
413 return;
414
415 tp = THINGPTR(mp);
416
417 if (good_monster(*tp)) /* Exchange places with your buddy */
418 {
419 mvwaddch(cw, old_hero.y, old_hero.x, ch);
420 mvwaddch(mw, old_hero.y, old_hero.x, ch);
421 mvwaddch(mw, hero.y, hero.x, ' ');
422 mvwaddch(cw, hero.y, hero.x, tp->t_oldch);
423
424 (*tp).t_pos.x = old_hero.x; /* Update monster position variables */
425 (*tp).t_pos.y = old_hero.y;
426 (*tp).t_oldpos.x = old_hero.x;
427 (*tp).t_oldpos.y = old_hero.y;
428
429 t = (*tp).t_oldch;
430 (*tp).t_oldch = player.t_oldch;
431 player.t_oldch = t;
432
433 turn_on(*tp, ISRUN);
434
435 mvwaddch(cw, hero.y, hero.x, PLAYER);
436
437 /* make sure that the room shows OK */
438
439 light(&hero);
440
441 wrefresh(cw);
442 return;
443 }
444 else
445 {
446 hero = old_hero; /* Restore hero -- we'll fight instead of move */
447
448 /* make sure that the room shows OK */
449 light(&hero);
450
451 fight(&player.t_nxtpos, cur_weapon, NOTHROWN);
452
453 return;
454 }
455 }
456 else
457 fighting = FALSE;
458
459 ch = winat(old_hero.y, old_hero.x);
460 mvwaddch(cw, old_hero.y, old_hero.x, ch);
461 mvwaddch(cw, hero.y, hero.x, PLAYER);
462 }
463
464 /*
465 light()
466 Called to illuminate a room. If it is dark, remove anything that might
467 move.
468 */
469
470 void
471 light(coord *cp)
472 {
473 struct room *rp;
474 int j, k, x, y;
475 char ch, rch;
476 struct linked_list *item;
477 int jlow, jhigh, klow, khigh; /* Boundaries of lit area */
478
479 if ((rp = roomin(*cp)) != NULL && !on(player, ISBLIND))
480 {
481
482 /* is he wearing ring of illumination and in same room? */
483
484 if ((is_wearing(R_LIGHT) || on(player, ISELECTRIC)) &&
485 cp == &hero)
486 rp->r_flags &= ~ISDARK;
487
488 /* If we are in a maze, don't look at the whole room (level) */
489
490 if (levtype == MAZELEV)
491 {
492 jlow = max(0, hero.y - 2 - rp->r_pos.y);
493 jhigh = min(rp->r_max.y, hero.y + 2 - rp->r_pos.y + 1);
494 klow = max(0, hero.x - 2 - rp->r_pos.x);
495 khigh = min(rp->r_max.x, hero.x + 2 - rp->r_pos.x + 1);
496 }
497 else
498 {
499 jlow = klow = 0;
500 jhigh = rp->r_max.y;
501 khigh = rp->r_max.x;
502 }
503
504 for (j = 0; j < rp->r_max.y; j++)
505 {
506 for (k = 0; k < rp->r_max.x; k++)
507 {
508 /* Is this in the given area -- needed for maze */
509
510 if ((j < jlow || j >= jhigh) && (k < klow || k >= khigh))
511 continue;
512
513 y = rp->r_pos.y + j;
514 x = rp->r_pos.x + k;
515
516 ch = show(y, x);
517 wmove(cw, y, x);
518
519 /* Figure out how to display a secret door */
520
521 if (ch == SECRETDOOR)
522 {
523 if (j == 0 || j == rp->r_max.y - 1)
524 ch = '-';
525 else
526 ch = '|';
527 }
528
529 /*
530 * For monsters, if they were previously not
531 * seen and now can be seen, or vice-versa,
532 * make sure that will happen.
533 */
534
535 if (isalpha(ch))
536 {
537 struct thing *tp;
538
539 item = wake_monster(y, x);
540
541 if (item == NULL)
542 continue;
543
544 tp = THINGPTR(item);
545
546 /* Previously not seen -- now can see it */
547
548 if (tp->t_oldch == ' ' && cansee(tp->t_pos.y, tp->t_pos.x))
549 tp->t_oldch = CCHAR( mvinch(y, x) );
550
551 /* Previously seen -- now can't see it */
552
553 else if (off(player, ISBLIND) && tp->t_oldch != ' ' &&
554 !cansee(tp->t_pos.y, tp->t_pos.x))
555 tp->t_oldch = ' ';
556 }
557
558 /*
559 * If the room is a dark room, we might want
560 * to remove monsters and the like from it
561 * (since they might move). A dark room or
562 * not in line-of-sight in a maze.
563 */
564
565 if (((rp->r_flags & ISDARK) &&
566 !(rp->r_flags & HASFIRE)) ||
567 (levtype == MAZELEV &&
568 !maze_view(y, x)))
569 {
570 rch = CCHAR( mvwinch(cw, y, x) );
571
572 switch (rch)
573 {
574 case DOOR:
575 case STAIRS:
576 case TRAPDOOR:
577 case TELTRAP:
578 case BEARTRAP:
579 case SLEEPTRAP:
580 case ARROWTRAP:
581 case DARTTRAP:
582 case POOL:
583 case MAZETRAP:
584 case FIRETRAP:
585 case POISONTRAP:
586 case LAIR:
587 case RUSTTRAP:
588 case POST:
589 case '|':
590 case '-':
591 case ' ':
592 ch = rch;
593 break;
594
595 case FLOOR:
596 ch = (on(player, ISBLIND) ? FLOOR : ' ');
597 break;
598 default:
599 ch = ' ';
600 break;
601 }
602 }
603 mvwaddch(cw, y, x, ch);
604 }
605 }
606 }
607 }
608
609 /*
610 blue_light()
611 magically light up a room (or level or make it dark)
612 */
613
614 int
615 blue_light(int flags)
616 {
617 struct room *rp;
618 int blessed = (flags & ISBLESSED);
619 int cursed = (flags & ISCURSED);
620 int ret_val = FALSE; /* Whether or not affect is known */
621
622 rp = roomin(hero); /* What room is hero in? */
623
624 /* Darken the room if the magic is cursed */
625
626 if (cursed)
627 {
628 if ((rp == NULL) || (rp->r_flags & ISDARK))
629 nothing_message(flags);
630 else
631 {
632 if (!(rp->r_flags & HASFIRE))
633 msg("The room suddenly goes dark.");
634 else
635 nothing_message(flags);
636
637 rp->r_flags |= ISDARK;
638 ret_val = TRUE;
639 }
640 }
641 else
642 {
643 ret_val = TRUE;
644
645 if (rp && (rp->r_flags & ISDARK) && !(rp->r_flags & HASFIRE))
646 {
647 msg("The room is lit by a %s blue light.",
648 blessed ? "bright" : "shimmering");
649 }
650 else if (winat(hero.y, hero.x) == PASSAGE)
651 msg("The corridor glows %sand then fades.", blessed ? "brightly " : "");
652 else
653 {
654 ret_val = FALSE;
655 nothing_message(flags);
656 }
657
658 if (blessed)
659 {
660 short i; /* Index through rooms */
661
662 for (i = 0; i < MAXROOMS; i++)
663 rooms[i].r_flags &= ~ISDARK;
664 }
665 else if (rp)
666 rp->r_flags &= ~ISDARK;
667 }
668
669 /* Light the room and put the player back up */
670
671 light(&hero);
672 mvwaddch(cw, hero.y, hero.x, PLAYER);
673
674 return (ret_val);
675 }
676
677 /*
678 show()
679 returns what a certain thing will display as to the un-initiated
680 */
681
682 char
683 show(int y, int x)
684 {
685 char ch = winat(y, x);
686 struct linked_list *it;
687 struct thing *tp;
688
689 if (isatrap(ch))
690 {
691 struct trap *trp = trap_at(y, x);
692 return (trp->tr_flags & ISFOUND) ? ch : trp->tr_show;
693 }
694 else if (isalpha(ch))
695 {
696 if ((it = find_mons(y, x)) == NULL)
697 {
698 debug("Can't find monster in move.");
699 return ' ';
700 }
701 tp = THINGPTR(it);
702
703 if (on(*tp, ISDISGUISE))
704 ch = tp->t_disguise; /* As a mimic */
705 else if (on(*tp, ISINVIS) || (on(*tp, ISSHADOW) &&
706 rnd(100) < 90) || on(*tp, CANSURPRISE))
707 {
708 if (off(player, CANSEE) || on(*tp, CANSURPRISE))
709 ch = CCHAR( mvwinch(stdscr, y, x) ); /* Invisible */
710 }
711 else if (on(*tp, CANINWALL))
712 {
713 char tch;
714
715 tch = CCHAR( mvwinch(stdscr, y, x) );
716
717 if (tch == WALL || tch == '-' || tch == '|')
718 ch = CCHAR( winch(stdscr) ); /* As Xorn */
719 }
720 }
721 return(ch);
722 }
723
724 /*
725 be_trapped()
726 The guy stepped on a trap.... Make him pay.
727 */
728
729 char
730 be_trapped(struct thing *th, coord tc)
731 {
732 struct trap *tp;
733 char ch, *mname = NULL;
734 int is_player = (th == &player), can_see = cansee(tc.y, tc.x);
735 struct linked_list *mitem = NULL;
736
737 tp = trap_at(tc.y, tc.x);
738 ch = tp->tr_type;
739
740 if (!is_player)
741 {
742 mitem = find_mons(th->t_pos.y, th->t_pos.x);
743 mname = monsters[th->t_index].m_name;
744
745 /* Flying monsters do not set off traps */
746
747 if (!mitem || (on(*th, CANFLY) &&
748 (ch == BEARTRAP || ch == MAZETRAP || ch == TRAPDOOR
749 || ch == ARROWTRAP || ch == DARTTRAP)))
750 {
751 debug("%s avoided trap.", mname);
752 return(ch);
753 }
754 }
755 else
756 {
757 short thief_bonus = -50;
758
759 count = running = FALSE;
760 mvwaddch(cw, tp->tr_pos.y, tp->tr_pos.x, tp->tr_type);
761
762 if (no_command)
763 return(ch);
764
765 if (player.t_ctype == C_THIEF || player.t_ctype == C_NINJA)
766 thief_bonus = 10;
767
768 if (((is_wearing(R_LEVITATION) || on(player, CANFLY)) &&
769 (ch != FIRETRAP ||
770 (ch == FIRETRAP && !(tp->tr_flags & ISFOUND))))
771 || (moving && (tp->tr_flags & ISFOUND) && rnd(100) <
772 thief_bonus + 2 * pstats.s_dext + 5 * pstats.s_lvl) &&
773 (ch == BEARTRAP || ch == MAZETRAP || ch == TRAPDOOR
774 || ch == ARROWTRAP || ch == DARTTRAP))
775 {
776 static char trname[1024];
777 msg(tr_name(ch,trname));
778 tp->tr_flags |= ISFOUND;
779 return(ch);
780 }
781
782 if (moving)
783 msg("Your attempt fails.");
784 }
785
786 tp->tr_flags |= ISFOUND;
787
788 switch(ch)
789 {
790 case TRAPDOOR:
791 if (is_player)
792 {
793 level++;
794 new_level(NORMLEV,0);
795 addmsg("You fell into a trap");
796
797 if (player.t_ctype != C_THIEF
798 && player.t_ctype != C_ASSASIN
799 && player.t_ctype != C_NINJA
800 && rnd(pstats.s_dext) < 4)
801 {
802 addmsg(" and were damaged by the fall");
803
804 if ((pstats.s_hpt -= roll(1, 6)) <= 0)
805 {
806 addmsg("! The fall killed you.");
807 endmsg();
808 death(D_FALL);
809
810 return(ch);
811 }
812 }
813
814 addmsg("!");
815 endmsg();
816
817 if (off(player, ISCLEAR) && rnd(4) < 3)
818 {
819 if (on(player, ISHUH))
820 lengthen_fuse(FUSE_UNCONFUSE, rnd(8) + HUHDURATION);
821 else
822 light_fuse(FUSE_UNCONFUSE,0,rnd(8)+HUHDURATION, AFTER);
823
824 turn_on(player, ISHUH);
825 }
826 else
827 msg("You feel dizzy for a moment, but it quickly passes.");
828 }
829 else
830 {
831 if (can_see)
832 msg("The %s fell into a trap!", mname);
833
834 if (on(*th, ISFAMILIAR))
835 turn_off(player, HASFAMILIAR);
836
837 killed(NULL,mitem,NOMESSAGE,NOPOINTS);
838 }
839 break;
840
841 case BEARTRAP:
842 if (is_stealth(th))
843 {
844 if (is_player)
845 msg("You pass a bear trap.");
846 else if (can_see)
847 msg("The %s passes a bear trap.", mname);
848 }
849 else
850 {
851 th->t_no_move += BEARTIME;
852
853 if (is_player)
854 msg("You are caught in a bear trap.");
855 else if (can_see)
856 msg("The %s is caught in a bear trap.", mname);
857 }
858 break;
859
860 case SLEEPTRAP:
861 if (is_player)
862 {
863 msg("A strange white mist envelops you.");
864
865 if (!is_wearing(R_ALERT))
866 {
867 if (!is_wearing(R_BREATHE) && off(player, HASOXYGEN))
868 {
869 msg("You fall asleep.");
870 no_command += SLEEPTIME;
871 }
872 }
873 }
874 else
875 {
876 if (can_see)
877 msg("A strange white mist envelops the %s.", mname);
878
879 if (on(*th, ISUNDEAD))
880 {
881 if (can_see)
882 msg("The mist doesn't seem to affect the %s.", mname);
883 }
884
885 if (on(*th, ISUNDEAD) || on(*th, HASOXYGEN))
886 {
887 if (can_see)
888 msg("The mist doesn't seem to affect the %s.", mname);
889 }
890 else
891 {
892 th->t_no_move += SLEEPTIME;
893 }
894 }
895 break;
896
897 case ARROWTRAP:
898 if (swing(th->t_ctype, th->t_stats.s_lvl - 1, th->t_stats.s_arm, 1))
899 {
900 if (is_player)
901 {
902 msg("Oh no! An arrow shot you.");
903
904 if ((pstats.s_hpt -= roll(1, 6)) <= 0)
905 {
906 msg("The arrow killed you.");
907 death(D_ARROW);
908 return(ch);
909 }
910 }
911 else
912 {
913 if (can_see)
914 msg("An arrow shot the %s.", mname);
915
916 if (on(*th, NOSHARP))
917 {
918 if (can_see)
919 msg("The arrow has no effect!");
920 }
921 else
922 {
923 if ((th->t_stats.s_hpt -= roll(1, 6)) <= 0)
924 {
925 if (can_see)
926 msg("The arrow killed the %s.", mname);
927
928 if (on(*th, ISFAMILIAR))
929 turn_off(player, HASFAMILIAR);
930
931 killed(NULL, mitem, NOMESSAGE, NOPOINTS);
932 }
933 }
934 }
935 }
936 else
937 {
938 struct linked_list *itm;
939 struct object *an_arrow;
940
941 if (is_player)
942 msg("An arrow shoots past you.");
943 else if (can_see)
944 msg("An arrow shoots by the %s.", mname);
945
946 itm = new_item(sizeof *an_arrow);
947 an_arrow = OBJPTR(itm);
948 an_arrow->o_type = WEAPON;
949 an_arrow->o_which = ARROW;
950 an_arrow->o_hplus = rnd(3) - 1;
951 an_arrow->o_dplus = rnd(3) - 1;
952 init_weapon(an_arrow, ARROW);
953 an_arrow->o_count = 1;
954 an_arrow->o_pos = tc;
955 an_arrow->o_mark[0] = '\0';
956 fall(&player, itm, FALSE, FALSE);
957 }
958 break;
959
960 case TELTRAP:
961 if (is_player)
962 {
963 teleport();
964
965 if (off(player, ISCLEAR))
966 {
967 msg("Wait, what's going on here. Huh? What? Who?");
968
969 if (on(player, ISHUH))
970 lengthen_fuse(FUSE_UNCONFUSE, rnd(8) + HUHDURATION);
971 else
972 light_fuse(FUSE_UNCONFUSE,0,rnd(8)+HUHDURATION, AFTER);
973
974 turn_on(player, ISHUH);
975 }
976 else
977 msg("You feel dizzy for a moment, but it quickly passes.");
978 }
979 else
980 {
981 int rm;
982
983 /* Erase the monster from the old position */
984
985 if (isalpha(mvwinch(cw, th->t_pos.y, th->t_pos.x)))
986 mvwaddch(cw, th->t_pos.y, th->t_pos.x, th->t_oldch);
987
988 mvwaddch(mw, th->t_pos.y, th->t_pos.x, ' ');
989
990 /* Get a new position */
991
992 do
993 {
994 rm = rnd_room();
995 rnd_pos(&rooms[rm], &th->t_pos);
996 }
997 while(winat(th->t_pos.y, th->t_pos.x) != FLOOR);
998
999 /* Put it there */
1000
1001 mvwaddch(mw, th->t_pos.y, th->t_pos.x, th->t_type);
1002 th->t_oldch = CCHAR( mvwinch(cw, th->t_pos.y, th->t_pos.x) );
1003
1004 if (can_see)
1005 msg("The %s seems to have disappeared!", mname);
1006 }
1007 break;
1008
1009 case DARTTRAP:
1010
1011 if (swing(th->t_ctype, th->t_stats.s_lvl + 1,th->t_stats.s_arm, 1))
1012 {
1013 if (is_player)
1014 {
1015 msg("A small dart just hit you in the shoulder.");
1016
1017 if ((pstats.s_hpt -= roll(1, 4)) <= 0)
1018 {
1019 msg("The dart killed you.");
1020 death(D_DART);
1021 return(ch);
1022 }
1023
1024 /* Now the poison */
1025
1026 if (player.t_ctype != C_PALADIN
1027 && !(player.t_ctype == C_NINJA &&
1028 pstats.s_lvl > 12) && !save(VS_POISON))
1029 {
1030
1031 /*
1032 * 75% chance it will do point
1033 * damage - else strength
1034 */
1035
1036 if (rnd(100) < 75)
1037 {
1038 pstats.s_hpt /= 2;
1039
1040 if (pstats.s_hpt == 0)
1041 {
1042 death(D_POISON);
1043 return(ch);
1044 }
1045 }
1046 else if (!is_wearing(R_SUSABILITY))
1047 chg_str(-1, FALSE, FALSE);
1048 }
1049 }
1050 else
1051 {
1052 int orig_hp = th->t_stats.s_hpt;
1053
1054 if (can_see)
1055 msg("A small dart just hit the %s.", mname);
1056
1057 /*
1058 * Poison has no effect on poisonous or
1059 * undead monsters
1060 */
1061
1062 if (off(*th, CANPOISON) &&
1063 off(*th, ISUNDEAD) &&
1064 !save_throw(VS_POISON, th))
1065 th->t_stats.s_hpt /= 2;
1066
1067 /* Now the dart damage */
1068
1069 if (off(*th, NOSHARP))
1070 th->t_stats.s_hpt -= roll(1, 4);
1071
1072 if (orig_hp == th->t_stats.s_hpt)
1073 if (can_see)
1074 msg("The dart has not effect!");
1075 else if (th->t_stats.s_hpt < 0)
1076 {
1077 if (can_see)
1078 msg("The dart killed the %s.", mname);
1079
1080 if (on(*th, ISFAMILIAR))
1081 turn_off(player, HASFAMILIAR);
1082
1083 killed(NULL, mitem, NOMESSAGE, NOPOINTS);
1084 }
1085 }
1086 }
1087 else
1088 {
1089 if (is_player)
1090 msg("A small dart whizzes by your ear and vanishes.");
1091 else if (can_see)
1092 msg("A small dart whizzes by the %s and vanishes.", mname);
1093 }
1094 break;
1095
1096 case POOL:
1097 {
1098 int i;
1099
1100 i = rnd(100);
1101
1102 if (is_player)
1103 {
1104 if (on(player, ISELECTRIC))
1105 {
1106 msg("Oh no!!! The water shorts you out");
1107 extinguish_fuse(FUSE_UNELECTRIFY);
1108 turn_off(player, ISELECTRIC);
1109
1110 if (!is_wearing(R_ELECTRESIST))
1111 {
1112 if ((pstats.s_hpt -= roll(1, 10)) <= 0)
1113 {
1114 addmsg("! The shock killed you.");
1115 endmsg();
1116 death(D_DROWN);
1117 return(ch);
1118 }
1119 }
1120 }
1121
1122 if ((tp->tr_flags & ISGONE))
1123 {
1124 if (i < 30)
1125 {
1126 teleport(); /* teleport away */
1127
1128 if (off(player, ISCLEAR))
1129 {
1130 if (on(player, ISHUH))
1131 lengthen_fuse(FUSE_UNCONFUSE,rnd(8)+HUHDURATION);
1132 else
1133 light_fuse(FUSE_UNCONFUSE,0,rnd(8)+HUHDURATION,AFTER);
1134 turn_on(player, ISHUH);
1135 }
1136 else
1137 msg("You feel dizzy for a moment, but it quickly passes.");
1138
1139 pool_teleport = TRUE;
1140 }
1141 else if ((i < 45) && level > 2)
1142 {
1143 level -= rnd(2) + 1;
1144 new_level(NORMLEV,0);
1145 pool_teleport = TRUE;
1146 msg("You here a faint groan from below.");
1147
1148 if (off(player, ISCLEAR))
1149 {
1150 if (on(player, ISHUH))
1151 lengthen_fuse(FUSE_UNCONFUSE,rnd(8)+HUHDURATION);
1152 else
1153 light_fuse(FUSE_UNCONFUSE, 0, rnd(8) + HUHDURATION, AFTER);
1154
1155 turn_on(player, ISHUH);
1156 }
1157 else
1158 msg("You feel dizzy for a moment, but it quickly passes.");
1159 }
1160 else if (i < 70)
1161 {
1162 level += rnd(4) + 1;
1163 new_level(NORMLEV,0);
1164 pool_teleport = TRUE;
1165 msg("You find yourself in strange surroundings.");
1166
1167 if (off(player, ISCLEAR))
1168 {
1169 if (on(player, ISHUH))
1170 lengthen_fuse(FUSE_UNCONFUSE, rnd(8) + HUHDURATION);
1171 else
1172 light_fuse(FUSE_UNCONFUSE, 0, rnd(8) + HUHDURATION, AFTER);
1173
1174 turn_on(player, ISHUH);
1175 }
1176 else
1177 msg("You feel dizzy for a moment, but it quickly passes.");
1178 }
1179 else if (i > 95)
1180 {
1181 if (is_wearing(R_BREATHE) || on(player, HASOXYGEN))
1182 msg("You splash in the pool unharmed.");
1183 else
1184 {
1185 msg("Oh no!!! You drown in the pool!!! --More--");
1186 wait_for(' ');
1187 death(D_DROWN);
1188 return(ch);
1189 }
1190 }
1191 }
1192 }
1193 else
1194 {
1195 if (can_see)
1196 msg("The %s fell into the pool!", mname);
1197
1198 if (i < 15)
1199 {
1200 if (off(*th, HASOXYGEN))
1201 {
1202 if (can_see)
1203 msg("The %s has drowned!", mname);
1204
1205 if (on(*th, ISFAMILIAR))
1206 turn_off(player, HASFAMILIAR);
1207
1208 killed(NULL, mitem, NOMESSAGE, NOPOINTS);
1209 }
1210 }
1211 }
1212 }
1213 break;
1214
1215 case MAZETRAP:
1216
1217 if (is_player)
1218 {
1219 level++;
1220 new_level(MAZELEV,0);
1221 addmsg("You are surrounded by twisty passages");
1222
1223 if (rnd(4) < 1)
1224 {
1225 addmsg(" and were damaged by the fall");
1226
1227 if ((pstats.s_hpt -= roll(1, 6)) <= 0)
1228 {
1229 addmsg("! The fall killed you.");
1230 endmsg();
1231 death(D_FALL);
1232 return(ch);
1233 }
1234 }
1235
1236 addmsg("!");
1237 endmsg();
1238
1239 if (off(player, ISCLEAR))
1240 {
1241 if (on(player, ISHUH))
1242 lengthen_fuse(FUSE_UNCONFUSE, rnd(8) + HUHDURATION);
1243 else
1244 {
1245 light_fuse(FUSE_UNCONFUSE, 0, rnd(8) + HUHDURATION, AFTER);
1246 turn_on(player, ISHUH);
1247 }
1248 }
1249 else
1250 msg("You feel dizzy for a moment, but it quickly passes.");
1251 }
1252 else
1253 {
1254 if (can_see)
1255 msg("The %s fell into a trap!", mname);
1256
1257 if (on(*th, ISFAMILIAR))
1258 turn_off(player, HASFAMILIAR);
1259
1260 killed(NULL, mitem, NOMESSAGE, NOPOINTS);
1261 }
1262 break;
1263
1264 case FIRETRAP:
1265 {
1266 struct room *rp = roomin(hero);
1267
1268 if (is_player)
1269 {
1270 if (is_wearing(R_FIRERESIST) || on(player, NOFIRE))
1271 msg("You pass through the flames unharmed.");
1272 else
1273 {
1274 addmsg("You are burned by the flames");
1275
1276 if ((pstats.s_hpt -= roll(pstats.s_lvl, 2)) <= 0)
1277 {
1278 addmsg("! The flames killed you.");
1279 endmsg();
1280 death(D_FIRE);
1281 return(ch);
1282 }
1283
1284 addmsg("!");
1285
1286 endmsg();
1287 }
1288 }
1289 else
1290 {
1291 if (on(*th, CANBBURN))
1292 {
1293 if (can_see)
1294 msg("The %s is burned to death by the flames.", mname);
1295
1296 killed(NULL, mitem, NOMESSAGE, NOPOINTS);
1297 }
1298 else if (on(*th, NOFIRE))
1299 {
1300 if (can_see)
1301 msg("The %s passes through the flames unharmed.", mname);
1302 }
1303 else
1304 {
1305 if (can_see)
1306 msg("The %s is burned by the flames.", mname);
1307
1308 if ((th->t_stats.s_hpt -= roll(th->t_stats.s_lvl, 3)) < 0)
1309 {
1310 if (can_see)
1311 msg("The %s is burned to death by the flames.", mname);
1312
1313 if (on(*th, ISFAMILIAR))
1314 turn_off(player, HASFAMILIAR);
1315
1316 killed(NULL, mitem, NOMESSAGE, NOPOINTS);
1317 }
1318 else if (th->t_stats.s_intel < rnd(20))
1319 {
1320 if (can_see)
1321 msg("The %s turns and runs away in fear.", mname);
1322
1323 turn_on(*th, ISFLEE);
1324 }
1325 }
1326 }
1327
1328 if (rp != NULL)
1329 {
1330 rp->r_flags &= ~ISDARK;
1331 light(&hero);
1332 }
1333 }
1334 break;
1335
1336 case POISONTRAP:
1337 if (is_player)
1338 {
1339 msg("You fall into a pool of poison.");
1340
1341 if (rnd(4) > 0)
1342 {
1343 msg("You swallow some of the liquid and feel very sick.");
1344 pstats.s_hpt -= pstats.s_hpt / 3;
1345
1346 if (player.t_ctype != C_PALADIN
1347 && !(player.t_ctype == C_NINJA &&
1348 pstats.s_lvl > 12)
1349 && !is_wearing(R_SUSABILITY))
1350 chg_str(-2, FALSE, FALSE);
1351 }
1352 else
1353 msg("The stuff tastes horrible.");
1354 }
1355 else
1356 {
1357 if (can_see)
1358 msg("The %s falls into the pool of poison.", mname);
1359
1360 if (rnd(4) > 0 && off(*th, ISUNDEAD))
1361 if (th->t_stats.s_hpt *= 2.0 / 3.0 < 0)
1362 {
1363 if (can_see)
1364 msg("The %s dies from the poison.", mname);
1365
1366 if (on(*th, ISFAMILIAR))
1367 turn_off(player, HASFAMILIAR);
1368
1369 killed(NULL, mitem, NOMESSAGE, NOPOINTS);
1370 }
1371 }
1372 break;
1373
1374 case LAIR:
1375 if (is_player)
1376 {
1377 msg("You found a monster lair!");
1378 mpos = 0;
1379 new_level(THRONE,0);
1380 }
1381 else
1382 {
1383 if (can_see)
1384 msg("The %s fell into a trap!", mname);
1385
1386 if (on(*th, ISFAMILIAR))
1387 turn_off(player, HASFAMILIAR);
1388
1389 killed(NULL, mitem, NOMESSAGE, NOPOINTS);
1390 }
1391 break;
1392
1393 case RUSTTRAP:
1394 if (is_player)
1395 {
1396 msg("You are splashed by water.");
1397
1398 if (cur_armor != NULL &&
1399 cur_armor->o_which != SOFT_LEATHER &&
1400 cur_armor->o_which != HEAVY_LEATHER &&
1401 cur_armor->o_which != CUIRBOLILLI &&
1402 cur_armor->o_which != PADDED_ARMOR &&
1403 cur_armor->o_which != CRYSTAL_ARMOR &&
1404 cur_armor->o_which != MITHRIL &&
1405 !(cur_armor->o_flags & ISPROT) &&
1406 cur_armor->o_ac < pstats.s_arm + 1)
1407 {
1408 msg("Your armor weakens!");
1409 cur_armor->o_ac++;
1410 }
1411 else if (cur_armor != NULL && (cur_armor->o_flags & ISPROT))
1412 msg("The rust vanishes instantly!");
1413 }
1414 else
1415 {
1416 if (can_see)
1417 msg("The %s is splashed by water.", mname);
1418 }
1419 }
1420
1421 return(ch);
1422 }
1423
1424 /*
1425 dip_it()
1426 Dip an object into a magic pool
1427 */
1428
1429 void
1430 dip_it(void)
1431 {
1432 struct linked_list *what;
1433 struct object *ob;
1434 struct trap *tp;
1435 int wh, i;
1436
1437 tp = trap_at(hero.y, hero.x);
1438
1439 if (tp == NULL || !(tp->tr_type == POOL || tp->tr_type == POISONTRAP))
1440 {
1441 msg("I see no pools here.");
1442 return;
1443 }
1444
1445 if (tp->tr_flags & ISGONE)
1446 {
1447 msg("This %s appears to have been used once already.",
1448 (tp->tr_type == POOL ? "shimmering pool" : "poison pool"));
1449 return;
1450 }
1451
1452 if ((what = get_item("dip", 0)) == NULL)
1453 {
1454 msg("");
1455 after = FALSE;
1456 return;
1457 }
1458
1459 ob = OBJPTR(what);
1460 mpos = 0;
1461
1462 if (ob == cur_armor)
1463 {
1464 msg("You have to take off your armor before you can dip it.");
1465 return;
1466 }
1467 else if (ob == cur_ring[LEFT_1] || ob == cur_ring[LEFT_2] ||
1468 ob == cur_ring[LEFT_3] || ob == cur_ring[LEFT_4] ||
1469 ob == cur_ring[RIGHT_1] || ob == cur_ring[RIGHT_2] ||
1470 ob == cur_ring[RIGHT_3] || ob == cur_ring[RIGHT_4])
1471 {
1472 msg("You have to take that ring off before you can dip it.");
1473 return;
1474 }
1475
1476 tp->tr_flags |= ISGONE;
1477
1478 if (ob != NULL && tp->tr_type == POOL)
1479 {
1480 wh = ob->o_which;
1481 ob->o_flags |= ISKNOW;
1482 i = rnd(100);
1483
1484 switch (ob->o_type)
1485 {
1486 case WEAPON:
1487 if (i < 50)
1488 {
1489 if (!(ob->o_flags & ISCURSED))
1490 {
1491 ob->o_hplus += 1;
1492 ob->o_dplus += 1;
1493 }
1494 else
1495 {
1496 ob->o_hplus = rnd(2);
1497 ob->o_dplus = rnd(2);
1498 }
1499
1500 ob->o_flags &= ~ISCURSED;
1501 msg("The %s glows blue for a moment.", weaps[wh].w_name);
1502 }
1503 else if (i < 70) /* curse weapon here */
1504 {
1505 if (!(ob->o_flags & ISCURSED))
1506 {
1507 ob->o_hplus = -(rnd(2) + 1);
1508 ob->o_dplus = -(rnd(2) + 1);
1509 }
1510 else /* if already cursed */
1511 {
1512 ob->o_hplus--;
1513 ob->o_dplus--;
1514 }
1515
1516 ob->o_flags |= ISCURSED;
1517 msg("The %s glows red for a moment.", weaps[wh].w_name);
1518 }
1519 else
1520 msg("Nothing seems to happen.");
1521 break;
1522
1523 case ARMOR:
1524
1525 if (i < 50) /* enchant armor */
1526 {
1527 if (!(ob->o_flags & ISCURSED))
1528 ob->o_ac -= rnd(2) + 1;
1529 else
1530 ob->o_ac = -rnd(3) + armors[wh].a_class;
1531
1532 ob->o_flags &= ~ISCURSED;
1533 msg("The %s glows blue for a moment.", armors[wh].a_name);
1534 }
1535 else if (i < 75) /* curse armor */
1536 {
1537 if (!(ob->o_flags & ISCURSED))
1538 ob->o_ac = rnd(3) + armors[wh].a_class;
1539 else
1540 ob->o_ac += rnd(2) + 1;
1541
1542 ob->o_flags |= ISCURSED;
1543 msg("The %s glows red for a moment.", armors[wh].a_name);
1544 }
1545 else
1546 msg("Nothing seems to happen");
1547 break;
1548
1549 case STICK:
1550 {
1551 int j;
1552
1553 j = rnd(8) + 1;
1554
1555 if (i < 50) /* add charges */
1556 {
1557 ob->o_charges += j;
1558 know_items[TYP_STICK][wh] = TRUE;
1559
1560 if (ob->o_flags & ISCURSED)
1561 ob->o_flags &= ~ISCURSED;
1562
1563 msg("The %s %s glows blue for a moment.",
1564 ws_made[wh], ws_type[wh]);
1565 }
1566 else if (i < 65) /* remove charges */
1567 {
1568 if ((ob->o_charges -= i) < 0)
1569 ob->o_charges = 0;
1570
1571 know_items[TYP_STICK][wh] = TRUE;
1572
1573 if (ob->o_flags & ISBLESSED)
1574 ob->o_flags &= ~ISBLESSED;
1575 else
1576 ob->o_flags |= ISCURSED;
1577
1578 msg("The %s %s glows red for a moment.",
1579 ws_made[wh], ws_type[wh]);
1580 }
1581 else
1582 msg("Nothing seems to happen.");
1583 }
1584 break;
1585
1586 case SCROLL:
1587
1588 know_items[TYP_SCROLL][wh] = TRUE;
1589 msg("The '%s' scroll unfurls.", s_names[wh]);
1590 break;
1591
1592 case POTION:
1593
1594 know_items[TYP_POTION][wh] = TRUE;
1595 msg("The %s potion bubbles for a moment.", p_colors[wh]);
1596 break;
1597
1598 case RING:
1599 if (i < 50) /* enchant ring */
1600 {
1601 if (!(ob->o_flags & ISCURSED))
1602 ob->o_ac += rnd(2) + 1;
1603 else
1604 ob->o_ac = rnd(2) + 1;
1605
1606 ob->o_flags &= ~ISCURSED;
1607 }
1608 else if (i < 80) /* curse ring */
1609 {
1610 if (!(ob->o_flags & ISCURSED))
1611 ob->o_ac = -(rnd(2) + 1);
1612 else
1613 ob->o_ac -= (rnd(2) + 1);
1614
1615 ob->o_flags |= ISCURSED;
1616 }
1617
1618 know_items[TYP_RING][wh] = TRUE;
1619 msg("The %s ring vibrates for a moment.", r_stones[wh]);
1620 break;
1621
1622 default:
1623 msg("The pool bubbles for a moment.");
1624 }
1625 }
1626 else if (ob != NULL && tp->tr_type == POISONTRAP)
1627 {
1628 if ((player.t_ctype == C_PALADIN) ||
1629 (player.t_ctype == C_CLERIC && rnd(2)))
1630 {
1631 msg("Trying to use poison is evil.");
1632 luck += 2;
1633 }
1634
1635 if (ob->o_type != WEAPON || rnd(10) > 0)
1636 msg("Nothing seems to happen.");
1637 else
1638 {
1639 msg("Your %s is covered with a black sticky liquid.",
1640 weaps[ob->o_which].w_name);
1641 ob->o_flags |= ISPOISON;
1642 }
1643 }
1644 else
1645 msg("Nothing seems to happen.");
1646 }
1647
1648 /*
1649 trap_at()
1650 find the trap at (y,x) on screen.
1651 */
1652
1653 struct trap *
1654 trap_at(int y, int x)
1655 {
1656 struct trap *tp, *ep;
1657
1658 ep = &traps[ntraps];
1659
1660 for (tp = traps; tp < ep; tp++)
1661 if (tp->tr_pos.y == y && tp->tr_pos.x == x)
1662 break;
1663
1664 if (tp == ep)
1665 {
1666 debug((sprintf(prbuf, "Trap at %d,%d not in array", y, x), prbuf));
1667 tp = NULL;
1668 }
1669
1670 return(tp);
1671 }
1672
1673 /*
1674 set_trap()
1675 set a trap at (y, x) on screen.
1676 */
1677
1678 void
1679 set_trap(struct thing *tp, int y, int x)
1680 {
1681 int is_player = (tp == &player);
1682 int selection = rnd(7) + 1;
1683 char ch = 0, och;
1684 int thief_bonus = 0;
1685
1686 switch(och = CCHAR( mvinch(y, x) ))
1687 {
1688 case WALL:
1689 case FLOOR:
1690 case PASSAGE:
1691 break;
1692 default:
1693 msg("The trap failed!");
1694 return;
1695 }
1696
1697 if (is_player && (player.t_ctype == C_THIEF ||
1698 player.t_ctype == C_NINJA))
1699 thief_bonus = 10;
1700
1701 if (ntraps >= 2 * MAXTRAPS || ++trap_tries >= MAXTRPTRY ||
1702 rnd(60) >= (tp->t_stats.s_dext + tp->t_stats.s_lvl / 2 +
1703 thief_bonus))
1704 {
1705 if (is_player)
1706 msg("The trap failed!");
1707
1708 return;
1709 }
1710
1711 /* Set up for redraw */
1712
1713 clearok(cw, TRUE);
1714 touchwin(cw);
1715
1716 if (is_player)
1717 {
1718 add_line("[1] Trap Door");
1719 add_line("[2] Bear Trap");
1720 add_line("[3] Sleep Trap");
1721 add_line("[4] Arrow Trap");
1722 add_line("[5] Teleport Trap");
1723 add_line("[6] Dart Trap");
1724 add_line("[7] Fire Trap");
1725 end_line();
1726 msg("Which trap? ");
1727
1728 selection = (short) ((readchar() & 0177) - '0');
1729
1730 while (selection < 1 || selection > 7)
1731 {
1732 if (selection == (short) ESCAPE - (short) '0')
1733 {
1734 after = FALSE;
1735 return;
1736 }
1737
1738 msg("");
1739 msg("Please enter a selection between 1 and 7: ");
1740 selection = (short) ((readchar() & 0177) - '0');
1741 }
1742 }
1743
1744 switch (selection)
1745 {
1746 case 1: ch = TRAPDOOR; break;
1747 case 2: ch = BEARTRAP; break;
1748 case 3: ch = SLEEPTRAP;break;
1749 case 4: ch = ARROWTRAP;break;
1750 case 5: ch = TELTRAP; break;
1751 case 6: ch = DARTTRAP; break;
1752 case 7: ch = FIRETRAP; break;
1753 }
1754
1755 mvaddch(y, x, ch);
1756
1757 traps[ntraps].tr_type = ch;
1758 traps[ntraps].tr_flags = ISTHIEFSET;
1759 traps[ntraps].tr_show = och;
1760 traps[ntraps].tr_pos.y = y;
1761 traps[ntraps++].tr_pos.x = x;
1762 }
1763
1764
1765 /*
1766 rndmove()
1767 move in a random direction if the monster/person is confused
1768 */
1769
1770 coord
1771 rndmove(struct thing *who)
1772 {
1773 int x, y;
1774 int ex, ey, nopen = 0;
1775 coord ret; /* what we will be returning */
1776 coord dest;
1777
1778 ret = who->t_pos;
1779
1780 /*
1781 * Now go through the spaces surrounding the player and set that
1782 * place in the array to true if the space can be moved into
1783 */
1784
1785 ey = ret.y + 1;
1786 ex = ret.x + 1;
1787
1788 for (y = who->t_pos.y - 1; y <= ey; y++)
1789 if (y > 0 && y < LINES - 2)
1790 for (x = who->t_pos.x - 1; x <= ex; x++)
1791 {
1792 if (x < 0 || x >= COLS)
1793 continue;
1794
1795 if (step_ok(y, x, NOMONST, who))
1796 {
1797 dest.y = y;
1798 dest.x = x;
1799
1800 if (!diag_ok(&who->t_pos, &dest, who))
1801 continue;
1802
1803 if (rnd(++nopen) == 0)
1804 ret = dest;
1805 }
1806 }
1807
1808 return(ret);
1809 }
1810
1811 /*
1812 isatrap()
1813 Returns TRUE if this character is some kind of trap
1814 */
1815
1816 int
1817 isatrap(int ch)
1818 {
1819 switch(ch)
1820 {
1821 case DARTTRAP:
1822 case TELTRAP:
1823 case TRAPDOOR:
1824 case ARROWTRAP:
1825 case SLEEPTRAP:
1826 case POOL:
1827 case MAZETRAP:
1828 case FIRETRAP:
1829 case POISONTRAP:
1830 case LAIR:
1831 case RUSTTRAP:
1832 case BEARTRAP:
1833 return (TRUE);
1834 default:
1835 return (FALSE);
1836 }
1837 }