Mercurial > hg > early-roguelike
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 } |