comparison urogue/command.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 911f0aa6e758
comparison
equal deleted inserted replaced
253:d9badb9c0179 256:c495a4f288c6
1 /*
2 command.c - Read and execute the user 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 <string.h>
20 #include <stdlib.h>
21 #include <ctype.h>
22 #include "rogue.h"
23
24 /*
25 command()
26 Process the user commands
27 */
28
29 void
30 command(void)
31 {
32 static char repcommand; /* Command to repeat if we are repeating */
33 static int fight_to_death; /* Flags if we are fighting to death */
34 static coord dir; /* Last direction specified */
35
36 object *obj;
37 char ch;
38 int ntimes = 1; /* Number of player moves */
39 coord nullcoord;
40
41 nullcoord.x = nullcoord.y = 0;
42
43 if (on(player, CANFLY) && rnd(2))
44 ntimes++;
45
46 if (on(player, ISHASTE))
47 ntimes++;
48
49 if (fighting && att_bonus())
50 ntimes *= 2;
51
52 if (on(player, ISSLOW))
53 {
54 if (player.t_turn != TRUE)
55 ntimes--;
56
57 player.t_turn ^= TRUE;
58 }
59
60 if (ntimes == 0)
61 return;
62
63 while (ntimes--)
64 {
65 moving = FALSE;
66
67 /* If player is infested, take off a hit point */
68
69 if (on(player, HASINFEST) && !is_wearing(R_HEALTH))
70 {
71 if ((pstats.s_hpt -= infest_dam) <= 0)
72 {
73 death(D_INFESTATION);
74 return;
75 }
76 }
77
78 look(after);
79
80 if (!running)
81 door_stop = FALSE;
82
83 status(FALSE);
84 wmove(cw, hero.y, hero.x);
85
86 if (!((running || count) && jump))
87 wrefresh(cw); /* Draw screen */
88
89 take = 0;
90 after = TRUE;
91
92 /*
93 * Read command or continue run
94 */
95
96 if (!no_command)
97 {
98 if (fighting)
99 {
100 ch = (fight_to_death) ? 'F' : 'f';
101 }
102 else if (running)
103 {
104 /*
105 * If in a corridor, if we are at a turn with
106 * only one way to go, turn that way.
107 */
108
109 if ((winat(hero.y, hero.x) == PASSAGE) && off(player, ISHUH) &&
110 (off(player, ISBLIND)))
111 switch (runch)
112 {
113 case 'h': corr_move(0, -1); break;
114 case 'j': corr_move(1, 0); break;
115 case 'k': corr_move(-1, 0); break;
116 case 'l': corr_move(0, 1); break;
117 }
118
119 ch = runch;
120 }
121 else if (count)
122 ch = repcommand;
123 else
124 {
125 ch = readchar();
126
127 if (mpos != 0 && !running)
128 msg(""); /* Erase message if its there */
129 }
130 }
131 else
132 {
133 ch = '.';
134 fighting = moving = FALSE;
135 }
136
137 if (no_command)
138 {
139 if (--no_command == 0)
140 msg("You can move again.");
141 }
142 else
143 {
144
145 /*
146 * check for prefixes
147 */
148
149 if (isdigit(ch))
150 {
151 count = 0;
152 while (isdigit(ch))
153 {
154 count = count * 10 + (ch - '0');
155 ch = readcharw(cw);
156 }
157 repcommand = ch;
158
159 /*
160 * Preserve count for commands which can be
161 * repeated.
162 */
163
164 switch(ch)
165 {
166 case 'h':
167 case 'j':
168 case 'k':
169 case 'l':
170 case 'y':
171 case 'u':
172 case 'b':
173 case 'n':
174 case 'H':
175 case 'J':
176 case 'K':
177 case 'L':
178 case 'Y':
179 case 'U':
180 case 'B':
181 case 'N':
182 case 'q':
183 case 'r':
184 case 's':
185 case 'm':
186 case 't':
187 case 'C':
188 case 'I':
189 case '.':
190 case 'z':
191 case 'p':
192 break;
193 default:
194 count = 0;
195 }
196 }
197
198 /* Save current direction */
199
200 if (!running) /* If running, it is already saved */
201 switch (ch)
202 {
203 case 'h':
204 case 'j':
205 case 'k':
206 case 'l':
207 case 'y':
208 case 'u':
209 case 'b':
210 case 'n':
211 runch = ch;
212 break;
213 case 'H':
214 case 'J':
215 case 'K':
216 case 'L':
217 case 'Y':
218 case 'U':
219 case 'B':
220 case 'N':
221 runch = (char) tolower(ch);
222 break;
223 }
224
225 /*
226 * execute a command
227 */
228
229 if (count && !running)
230 count--;
231
232 switch(ch)
233 {
234 /*
235 * Movement and combat commands
236 */
237
238 case 'h': do_move(0,-1); break;
239 case 'j': do_move(1, 0); break;
240 case 'k': do_move(-1, 0); break;
241 case 'l': do_move(0, 1); break;
242 case 'y': do_move(-1, -1); break;
243 case 'u': do_move(-1, 1); break;
244 case 'b': do_move(1, -1); break;
245 case 'n': do_move(1, 1); break;
246 case 'H': do_run('h'); break;
247 case 'J': do_run('j'); break;
248 case 'K': do_run('k'); break;
249 case 'L': do_run('l'); break;
250 case 'Y': do_run('y'); break;
251 case 'U': do_run('u'); break;
252 case 'B': do_run('b'); break;
253 case 'N': do_run('n'); break;
254 case 'm':
255 moving = TRUE;
256 if (!get_dir())
257 {
258 after = FALSE;
259 break;
260 }
261 do_move(delta.y, delta.x);
262 break;
263 case 'F':
264 case 'f':
265 fight_to_death = (ch == 'F');
266 if (!fighting)
267 {
268 if (get_dir())
269 {
270 dir = delta;
271 beast = NULL;
272 }
273 else
274 {
275 after = FALSE;
276 break;
277 }
278 }
279 do_fight(dir, (ch == 'F') ? TRUE : FALSE);
280 break;
281 case 't':
282 if (get_dir())
283 missile(delta.y, delta.x, get_item("throw", 0),
284 &player);
285 else
286 after = FALSE;
287
288 /*
289 * Informational commands - Do not do
290 * after daemons
291 */
292 break;
293
294 case 0x7f: /* sometime generated by */
295 /* suspend/foreground */
296 case ESCAPE:
297 case ' ':
298 after = FALSE; /* do nothing */
299 break;
300 case 'Q':
301 after = FALSE;
302 quit();
303 break;
304 case 'i':
305 after = FALSE;
306 inventory(pack, '*');
307 break;
308 case 'I':
309 after = FALSE;
310 inventory(pack, 0);
311 break;
312 case '~':
313 after = FALSE;
314 next_exp_level(MESSAGE);
315 break;
316 case '>':
317 after = FALSE;
318 d_level();
319 break;
320 case '<':
321 after = FALSE;
322 u_level();
323 break;
324 case '?':
325 after = FALSE;
326 help();
327 break;
328 case '/':
329 after = FALSE;
330 identify();
331 break;
332 case 'v':
333 after = FALSE;
334 msg("UltraRogue Version %s.", release);
335 break;
336 case 'o':
337 after = FALSE;
338 option();
339 strcpy(fd_data[1].mi_name, fruit);
340 break;
341 case 12: /* ctrl-l */
342 case 18: /* ctrl-r */
343 after = FALSE;
344 clearok(cw, TRUE);
345 wrefresh(cw);
346 break;
347 case 16: /* ctrl-p */
348 {
349 int decrement = FALSE;
350 after = FALSE;
351
352 if (mpos == 0)
353 decrement = TRUE;
354
355 msg_index = (msg_index + 9) % 10;
356 msg(msgbuf[msg_index]);
357 if (decrement)
358 msg_index = (msg_index + 9) % 10;
359 }
360 break;
361
362 case 'S':
363 after = FALSE;
364 if (save_game())
365 {
366 wclear(cw);
367 wrefresh(cw);
368 endwin();
369 exit(0);
370 }
371 break;
372
373 /*
374 * Other misc commands
375 */
376
377 case '.': break; /* rest */
378 case ',': add_pack(NULL, NOMESSAGE); break;
379 case 'q': quaff(&player, -1, ISNORMAL); break;
380 case 'r': read_scroll(&player, -1, ISNORMAL); break;
381 case 'd': drop(NULL); break;
382 case '^': set_trap(&player, hero.y, hero.x); break;
383 case 'c': incant(&player, nullcoord); break;
384 case 'D': dip_it(); break;
385 case 'e': eat(); break;
386 case '=': listen(); break;
387 case 'A': apply(); break;
388 case 'w': wield(); break;
389 case 'W': wear(); break;
390 case 'T': take_off(); break;
391 case 'P': ring_on(); break;
392 case 'R': ring_off(); break;
393 case 'p': prayer(); break;
394 case 'C': call(FALSE); break;
395 case 'M': call(TRUE); break;
396 case 's': search(FALSE); break;
397
398 /*
399 * Directional commands - get_dir sets delta
400 */
401 case 20: /* ctrl-t */
402 if (get_dir())
403 steal();
404 else
405 after = FALSE;
406 break;
407
408 case 'z':
409 if (get_dir())
410 do_zap(&player, -1, ISNORMAL);
411 else
412 after = FALSE;
413 break;
414
415 case 'a':
416 if (get_dir())
417 affect();
418 else
419 after = FALSE;
420 touchwin(cw);
421 break;
422
423 /*
424 * wizard commands
425 */
426
427 case 0x17: /* ctrl-w */
428 after = FALSE;
429
430 if (!wizard)
431 {
432 if (!canwizard)
433 {
434 msg("Illegal command '^W'.");
435 break;
436 }
437
438 if (passwd())
439 {
440 msg("Welcome, oh mighty wizard.");
441 wizard = waswizard = TRUE;
442 }
443 else
444 {
445 msg("Incorrect password.");
446 break;
447 }
448 }
449
450 msg("Wizard command: ");
451 mpos = 0;
452 ch = readchar();
453
454 switch (ch)
455 {
456 case 'v':
457 wiz_verbose = !wiz_verbose;
458 break;
459
460 case 'e':
461 wizard = FALSE;
462 msg("Not wizard any more.");
463 break;
464
465 case 's': activity(); break;
466 case 't': teleport(); break;
467 case 'm': overlay(mw, cw); break;
468 case 'f': overlay(stdscr, cw); break;
469 case 'i': inventory(lvl_obj, 0); break;
470 case 'c': buy_it('\0', ISNORMAL); break;
471 case 'I': whatis(NULL); break;
472 case 'F':
473 msg("food left: %d\tfood level: %d",
474 food_left,foodlev);
475 break;
476 case 'M':
477 creat_mons(&player, get_monster_number("create"),
478 MESSAGE);
479 break;
480
481 case 'r':
482 msg("rnd(4)%d, rnd(40)%d, rnd(100)%d",
483 rnd(4), rnd(40), rnd(100));
484 break;
485
486 case 'C':
487 obj = get_object(pack, "charge", STICK, NULL);
488
489 if (obj != NULL)
490 obj->o_charges = 10000;
491
492 break;
493
494 case 'w':
495 obj = get_object(pack, "price", 0, NULL);
496
497 if (obj != NULL)
498 msg("Worth %d.", get_worth(obj));
499
500 break;
501
502 case 'g':
503 {
504 int tlev;
505
506 prbuf[0] = '\0';
507 msg("Which level? ");
508
509 if (get_string(prbuf, cw) == NORM)
510 {
511 msg("");
512
513 if ((tlev = atoi(prbuf)) < 1)
514 msg("Illegal level.");
515 else if (tlev > 3000)
516 {
517 levtype = THRONE;
518 level = tlev - 3000;
519 }
520 else if (tlev > 2000)
521 {
522 levtype = MAZELEV;
523 level = tlev - 2000;
524 }
525 else if (tlev > 1000)
526 {
527 levtype = POSTLEV;
528 level = tlev - 1000;
529 }
530 else
531 {
532 levtype = NORMLEV;
533 level = tlev;
534 }
535
536 new_level(levtype,0);
537 }
538 }
539 break;
540
541 case 'o': make_omnipotent(); break;
542
543 case ESCAPE: /* Escape */
544 door_stop = FALSE;
545
546 count = 0;
547 after = FALSE;
548 break;
549
550 default:
551 msg("Illegal wizard command '%s', %d.",
552 unctrl(ch), ch);
553 count = 0;
554 break;
555
556 }
557
558 break;
559
560 default:
561 msg("Illegal command '%s', %d.",
562 unctrl(ch), ch);
563 count = 0;
564 after = FALSE;
565 break;
566 }
567
568 /*
569 * turn off flags if no longer needed
570 */
571 if (!running)
572 door_stop = FALSE;
573 }
574
575 /*
576 * If he ran into something to take, let him pick it up.
577 */
578 if (take != 0)
579 if (!moving)
580 pick_up(take);
581 else
582 show_floor();
583 if (!running)
584 door_stop = FALSE;
585 } /* end while */
586 }
587
588
589 void
590 do_after_effects(void)
591 {
592 int i;
593
594 /* Kick off the rest of the daemons and fuses */
595
596 look(FALSE);
597 do_daemons(AFTER);
598 do_fuses(AFTER);
599
600 /* Special abilities */
601
602 if ((player.t_ctype == C_THIEF || player.t_ctype == C_ASSASIN ||
603 player.t_ctype == C_NINJA || player.t_ctype == C_RANGER) &&
604 (rnd(100) < (2 * pstats.s_dext + 5 * pstats.s_lvl)))
605 search(TRUE);
606
607 for (i = 0; i < ring_value(R_SEARCH); i++)
608 search(FALSE);
609
610 if (is_wearing(R_TELEPORT) && rnd(50) < 2)
611 {
612 teleport();
613
614 if (off(player, ISCLEAR))
615 {
616 if (on(player, ISHUH))
617 lengthen_fuse(FUSE_UNCONFUSE, rnd(8) + HUHDURATION);
618 else
619 light_fuse(FUSE_UNCONFUSE, 0, rnd(8) + HUHDURATION, AFTER);
620
621 turn_on(player, ISHUH);
622 }
623 else
624 msg("You feel dizzy for a moment, but it quickly passes.");
625 }
626
627 /* accidents and general clumsiness */
628
629 if (fighting && rnd(50) == 0)
630 {
631 msg("You become tired of this nonsense.");
632 fighting = after = FALSE;
633 }
634
635 if (on(player, ISELECTRIC))
636 electrificate();
637
638 if (!fighting && (no_command == 0) && cur_weapon != NULL
639 && rnd(on(player, STUMBLER) ? 399 : 9999) == 0
640 && rnd(pstats.s_dext) <
641 2 - hitweight() + (on(player, STUMBLER) ? 4 : 0))
642 {
643 msg("You trip and stumble over your weapon.");
644 running = after = FALSE;
645
646 if (rnd(8) == 0 && (pstats.s_hpt -= roll(1, 10)) <= 0)
647 {
648 msg("You break your neck and die.");
649 death(D_FALL);
650 return;
651 }
652 else if (cur_weapon->o_flags & ISPOISON && rnd(4) == 0)
653 {
654 msg("You are cut by your %s!",
655 inv_name(cur_weapon, LOWERCASE));
656
657 if (player.t_ctype != C_PALADIN
658 && !(player.t_ctype == C_NINJA &&
659 pstats.s_lvl > 12)
660 && !save(VS_POISON))
661 {
662 if (pstats.s_hpt == 1)
663 {
664 msg("You die from the poison in the cut.");
665 death(D_POISON);
666 return;
667 }
668 else
669 {
670 msg("You feel very sick now.");
671 pstats.s_hpt /= 2;
672 chg_str(-2, FALSE, FALSE);
673 }
674 }
675 }
676 }
677
678 /* Time to enforce weapon and armor restrictions */
679 if (rnd(9999) == 0)
680 if (((cur_weapon == NULL) ||
681 (wield_ok(&player, cur_weapon, NOMESSAGE)))
682 && ((cur_armor == NULL) ||
683 (wear_ok(&player, cur_armor, NOMESSAGE))))
684 {
685 switch (player.t_ctype)
686 {
687 case C_CLERIC:
688 case C_DRUID:
689 case C_RANGER:
690 case C_PALADIN:
691 if (rnd(luck) != 0)
692 /* You better have done
693 * little wrong */
694 goto bad_cleric;
695
696 msg("You are enraptured by the renewed "
697 "power of your god.");
698 break;
699
700 case C_MAGICIAN:
701 case C_ILLUSION:
702 msg("You become in tune with the universe.");
703 break;
704
705 case C_THIEF:
706 case C_NINJA:
707 case C_ASSASIN:
708 msg("You become supernaly sensitive to your "
709 "surroundings.");
710 break;
711
712 case C_FIGHTER:
713 msg("You catch your second wind.");
714 break;
715
716 default:
717 msg("What a strange type you are!");
718 break;
719 }
720 pstats.s_hpt = max_stats.s_hpt += rnd(pstats.s_lvl) + 1;
721 pstats.s_power = max_stats.s_power += rnd(pstats.s_lvl) + 1;
722 }
723 else
724 { /* he blew it - make him pay */
725
726 int death_cause = 0;
727
728 switch (player.t_ctype)
729 {
730 case C_CLERIC:
731 case C_DRUID:
732 case C_RANGER:
733 case C_PALADIN:
734 bad_cleric:
735 msg("Your god scourges you for your misdeeds.");
736 death_cause = D_GODWRATH;
737 break;
738
739 case C_MAGICIAN:
740 case C_ILLUSION:
741 msg("You short out your manna on the unfamiliar %s.",
742 (cur_armor != NULL ? "armor" : "weapon"));
743
744 death_cause = D_SPELLFUMBLE;
745 break;
746
747 case C_THIEF:
748 case C_NINJA:
749 case C_ASSASIN:
750 msg("You trip and fall because of the unfamiliar %s.",
751 (cur_armor != NULL ? "armor" : "weapon"));
752 death_cause = D_CLUMSY;
753 break;
754
755 case C_FIGHTER:
756 debug("Fighter getting raw deal?");
757 break;
758
759 default:
760 msg("What a strange type you are!");
761 break;
762 }
763
764 aggravate();
765 pstats.s_power /= 2;
766 pstats.s_hpt /= 2;
767 player.t_no_move++;
768
769 if ((pstats.s_hpt -= rnd(pstats.s_lvl)) <= 0)
770 {
771 death(death_cause);
772 }
773 }
774
775 if (rnd(500000) == 0)
776 {
777 new_level(THRONE,0);
778 fighting = running = after = FALSE;
779 command();
780 }
781 }
782
783 void
784 make_omnipotent(void)
785 {
786 int i;
787 struct linked_list *item;
788 struct object *obj;
789
790 for (i = 0; i < 20; i++)
791 raise_level();
792
793 max_stats.s_hpt += 1000;
794 max_stats.s_power += 1000;
795 pstats.s_hpt = max_stats.s_hpt;
796 pstats.s_power = max_stats.s_power;
797 max_stats.s_str = pstats.s_str = 25;
798 max_stats.s_intel = pstats.s_intel = 25;
799 max_stats.s_wisdom = pstats.s_wisdom = 25;
800 max_stats.s_dext = pstats.s_dext = 25;
801 max_stats.s_const = pstats.s_const = 25;
802
803 if (cur_weapon == NULL || cur_weapon->o_which != CLAYMORE)
804 {
805 item = spec_item(WEAPON, CLAYMORE, 10, 10);
806 cur_weapon = OBJPTR(item);
807 cur_weapon->o_flags |= ISKNOW;
808 add_pack(item, NOMESSAGE);
809 }
810
811 /* and a kill-o-zap stick */
812
813 item = spec_item(STICK, WS_DISINTEGRATE, 10000, 0);
814 obj = OBJPTR(item);
815 obj->o_flags |= ISKNOW;
816 know_items[TYP_STICK][WS_DISINTEGRATE] = TRUE;
817
818 if (guess_items[TYP_STICK][WS_DISINTEGRATE])
819 {
820 ur_free(guess_items[TYP_STICK][WS_DISINTEGRATE]);
821 guess_items[TYP_STICK][WS_DISINTEGRATE] = NULL;
822 }
823
824 add_pack(item, NOMESSAGE);
825
826 /* and his suit of armor */
827
828 if (cur_armor == NULL ||
829 !(cur_armor->o_which == CRYSTAL_ARMOR ||
830 cur_armor->o_which == MITHRIL))
831 {
832 item = spec_item(ARMOR, CRYSTAL_ARMOR, 15, 0);
833 obj = OBJPTR(item);
834 obj->o_flags |= ISKNOW;
835 obj->o_weight =
836 (int) (armors[CRYSTAL_ARMOR].a_wght * 0.2);
837 cur_armor = obj;
838 add_pack(item, NOMESSAGE);
839 }
840
841 /* and some rings (have to put them on, for now) */
842
843
844 if (!is_wearing(R_SEARCH))
845 {
846 item = spec_item(RING, R_SEARCH, 0, 0);
847 obj = OBJPTR(item);
848 obj->o_flags |= ISKNOW;
849 know_items[TYP_RING][R_SEARCH] = TRUE;
850
851 if (guess_items[TYP_RING][R_SEARCH])
852 {
853 ur_free(guess_items[TYP_RING][R_SEARCH]);
854 guess_items[TYP_RING][R_SEARCH] = NULL;
855 }
856
857 add_pack(item, NOMESSAGE);
858 }
859
860 if (!is_wearing(R_PIETY))
861 {
862 item = spec_item(RING, R_PIETY, 0, 0);
863 obj = OBJPTR(item);
864 obj->o_flags |= ISKNOW;
865 know_items[TYP_RING][R_PIETY] = TRUE;
866
867 if (guess_items[TYP_RING][R_PIETY])
868 {
869 ur_free(guess_items[TYP_RING][R_PIETY]);
870 guess_items[TYP_RING][R_PIETY] = NULL;
871 }
872
873 add_pack(item, NOMESSAGE);
874 }
875
876 item = spec_item(SCROLL, S_ELECTRIFY, 0, 0);
877 obj = OBJPTR(item);
878 obj->o_flags |= ISKNOW;
879 know_items[TYP_SCROLL][S_ELECTRIFY] = TRUE;
880
881 if (guess_items[TYP_SCROLL][S_ELECTRIFY])
882 {
883 ur_free(guess_items[TYP_SCROLL][S_ELECTRIFY]);
884 guess_items[TYP_SCROLL][S_ELECTRIFY] = NULL;
885 }
886
887 add_pack(item, NOMESSAGE);
888
889 /* Spiff him up a bit */
890 quaff(&player, P_SHERO, ISBLESSED);
891 quaff(&player, P_CLEAR, ISBLESSED);
892 quaff(&player, P_FIRERESIST, ISBLESSED);
893 quaff(&player, P_TRUESEE, ISBLESSED);
894 quaff(&player, P_PHASE, ISBLESSED);
895 purse += 50000L;
896 updpack();
897 }
898
899
900 /*
901 quit()
902 Have player make certain, then exit.
903 */
904
905 void
906 quit_handler(int sig)
907 {
908 if (signal(SIGINT, quit_handler) != quit_handler)
909 mpos = 0;
910
911 sig = 0;
912
913 quit();
914 }
915
916 void
917 quit(void)
918 {
919 msg("Really quit?");
920
921 wrefresh(cw);
922
923 if (readchar() == 'y')
924 {
925 clear();
926 wclear(cw);
927 wrefresh(cw);
928 move(LINES - 1, 0);
929 wrefresh(stdscr);
930 score(pstats.s_exp, pstats.s_lvl, CHICKEN, 0);
931 byebye();
932 }
933 else
934 {
935 signal(SIGINT, quit_handler);
936 wmove(cw, 0, 0);
937 wclrtoeol(cw);
938 status(FALSE);
939 wrefresh(cw);
940 mpos = 0;
941 count = 0;
942 fighting = running = 0;
943 }
944 }
945
946 /*
947 search()
948 Player gropes about him to find hidden things.
949 */
950
951 void
952 search(int is_thief)
953 {
954 int x, y;
955 char ch;
956
957 /*
958 * Look all around the hero, if there is something hidden there, give
959 * him a chance to find it. If its found, display it.
960 */
961
962 if (on(player, ISBLIND))
963 return;
964
965 for (x = hero.x - 1; x <= hero.x + 1; x++)
966 for (y = hero.y - 1; y <= hero.y + 1; y++)
967 {
968 ch = winat(y, x);
969
970 if (isatrap(ch))
971 {
972 static char trname[1024]; /* temp scratch space */
973 struct trap *tp;
974 struct room *rp;
975
976 if (isatrap( mvwinch(cw, y, x)))
977 continue;
978
979 tp = trap_at(y, x);
980
981 if ((tp->tr_flags & ISTHIEFSET) ||
982 (rnd(100) > 50 && !is_thief))
983 break;
984
985 rp = roomin(hero);
986
987 if (tp->tr_type == FIRETRAP && rp != NULL)
988 {
989 rp->r_flags &= ~ISDARK;
990 light(&hero);
991 }
992
993 tp->tr_flags |= ISFOUND;
994 mvwaddch(cw, y, x, ch);
995 count = 0;
996 running = FALSE;
997 msg(tr_name(tp->tr_type,trname));
998 }
999 else if (ch == SECRETDOOR)
1000 {
1001 if (rnd(100) < 20 && !is_thief)
1002 {
1003 mvaddch(y, x, DOOR);
1004 count = 0;
1005 }
1006 }
1007 }
1008 }
1009
1010 /*
1011 help()
1012 Give single character help, or the whole mess if he wants it
1013 */
1014
1015 void
1016 help(void)
1017 {
1018 const struct h_list *strp = helpstr;
1019 char helpch;
1020 int cnt;
1021
1022 msg("Character you want help for (* for all): ");
1023 helpch = readchar();
1024 mpos = 0;
1025
1026 /*
1027 * If its not a *, print the right help string or an error if he
1028 * typed a funny character.
1029 */
1030
1031 if (helpch != '*')
1032 {
1033 wmove(cw, 0, 0);
1034
1035 while (strp->h_ch)
1036 {
1037 if (strp->h_desc == 0)
1038 if (!wizard)
1039 break;
1040 else
1041 {
1042 strp++;
1043 continue;
1044 }
1045
1046 if (strp->h_ch == helpch)
1047 {
1048 msg("%s%s", unctrl(strp->h_ch), strp->h_desc);
1049 break;
1050 }
1051 strp++;
1052 }
1053
1054 if (strp->h_ch != helpch)
1055 msg("Unknown character '%s'.", unctrl(helpch));
1056
1057 return;
1058 }
1059
1060 /*
1061 * Here we print help for everything. Then wait before we return to
1062 * command mode
1063 */
1064
1065 wclear(hw);
1066 cnt = 0;
1067
1068 while (strp->h_ch)
1069 {
1070 if (strp->h_desc == 0)
1071 if (!wizard)
1072 break;
1073 else
1074 {
1075 strp++;
1076 continue;
1077 }
1078
1079 mvwaddstr(hw, cnt % 23, cnt > 22 ? 40 : 0, unctrl(strp->h_ch));
1080 waddstr(hw, strp->h_desc);
1081 strp++;
1082
1083 if (++cnt >= 46 && strp->h_ch && (strp->h_desc != NULL || wizard))
1084 {
1085 wmove(hw, LINES - 1, 0);
1086 wprintw(hw, (char *) morestr);
1087 wrefresh(hw);
1088 wait_for(' ');
1089 wclear(hw);
1090 cnt = 0;
1091 }
1092 }
1093
1094 wmove(hw, LINES - 1, 0);
1095 wprintw(hw, (char *) morestr);
1096 wrefresh(hw);
1097 wait_for(' ');
1098 wclear(hw);
1099 wrefresh(hw);
1100
1101 wmove(cw, 0, 0);
1102 wclrtoeol(cw);
1103 status(FALSE);
1104 touchwin(cw);
1105
1106 return;
1107 }
1108
1109 /*
1110 identify()
1111 Tell the player what a certain thing is.
1112 */
1113
1114 void
1115 identify(void)
1116 {
1117 int ch;
1118 char *str;
1119
1120 msg("What do you want identified? ");
1121 mpos = 0;
1122
1123 if ((ch = readchar()) == ESCAPE)
1124 {
1125 msg("");
1126 return;
1127 }
1128
1129 if (isalpha(ch))
1130 {
1131 id_monst(ch);
1132 return;
1133 }
1134
1135 switch (ch)
1136 {
1137 case '|':
1138 case '-': str = "wall of a room"; break;
1139 case GOLD: str = "gold"; break;
1140 case STAIRS: str = "passage leading down"; break;
1141 case DOOR: str = "door"; break;
1142 case FLOOR: str = "room floor"; break;
1143 case VPLAYER: str = "The hero of the game ---> you"; break;
1144 case IPLAYER: str = "you (but invisible)"; break;
1145 case PASSAGE: str = "passage"; break;
1146 case POST: str = "trading post"; break;
1147 case POOL: str = "a shimmering pool"; break;
1148 case TRAPDOOR: str = "trapdoor"; break;
1149 case ARROWTRAP: str = "arrow trap"; break;
1150 case SLEEPTRAP: str = "sleeping gas trap"; break;
1151 case BEARTRAP: str = "bear trap"; break;
1152 case TELTRAP: str = "teleport trap"; break;
1153 case DARTTRAP: str = "dart trap"; break;
1154 case MAZETRAP: str = "entrance to a maze"; break;
1155 case FIRETRAP: str = "fire trap"; break;
1156 case POISONTRAP: str = "poison pool trap"; break;
1157 case LAIR: str = "monster lair entrance"; break;
1158 case RUSTTRAP: str = "rust trap"; break;
1159 case POTION: str = "potion"; break;
1160 case SCROLL: str = "scroll"; break;
1161 case FOOD: str = "food"; break;
1162 case WEAPON: str = "weapon"; break;
1163 case ' ': str = "solid rock"; break;
1164 case ARMOR: str = "armor"; break;
1165 case ARTIFACT: str = "an artifact from bygone ages"; break;
1166 case RING: str = "ring"; break;
1167 case STICK: str = "wand or staff"; break;
1168 default: str = "unknown character"; break;
1169 }
1170 msg("'%s'; %s", unctrl(ch), str);
1171 }
1172
1173 /*
1174 d_level()
1175 He wants to go down a level
1176 */
1177
1178 void
1179 d_level(void)
1180 {
1181 int no_phase = FALSE;
1182
1183 if (mvinch(hero.y, hero.x) != STAIRS)
1184 {
1185 if (off(player, CANINWALL)) /* Must use stairs if can't phase */
1186 {
1187 msg("I see no way down.");
1188 return;
1189 }
1190
1191 extinguish_fuse(FUSE_UNPHASE);/*Using phase to go down gets rid of it*/
1192 no_phase = TRUE;
1193 }
1194
1195 if (is_wearing(R_LEVITATION) || on(player, CANFLY))
1196 {
1197 msg("You can't! You're floating in the air.");
1198 return;
1199 }
1200
1201 if (rnd(pstats.s_dext) < 3 * (2 - hitweight() +
1202 (on(player, STUMBLER) ? 4 : 0)))
1203 {
1204 msg("You trip and fall down the stairs.");
1205
1206 if ((pstats.s_hpt -= roll(1, 10)) <= 0)
1207 {
1208 msg("You break your neck and die.");
1209 death(D_FALL);
1210 return;
1211 }
1212 }
1213
1214 level++;
1215 new_level(NORMLEV,0);
1216
1217 if (no_phase)
1218 unphase(NULL);
1219
1220 return;
1221 }
1222
1223 /*
1224 u_level()
1225 He wants to go up a level
1226 */
1227
1228 void
1229 u_level(void)
1230 {
1231 char ch = 0;
1232
1233 if (has_artifact && ((ch = CCHAR(mvinch(hero.y, hero.x))) == STAIRS ||
1234 (on(player, CANINWALL)
1235 && (is_wearing(R_LEVITATION) || on(player, CANFLY)))))
1236 {
1237 if (--level == 0)
1238 total_winner();
1239 else if (rnd(wizard ? 3 : 15) == 0)
1240 new_level(THRONE,0);
1241 else
1242 {
1243 new_level(NORMLEV,0);
1244 msg("You feel a wrenching sensation in your gut.");
1245 }
1246
1247 if (on(player, CANINWALL) && ch != STAIRS)
1248 {
1249 extinguish_fuse(FUSE_UNPHASE);
1250 unphase(NULL);
1251 }
1252
1253 return;
1254 }
1255 else if (ch != STAIRS &&
1256 !(on(player, CANINWALL) && (is_wearing(R_LEVITATION)
1257 || on(player, CANFLY))))
1258 msg("I see no way up.");
1259 else
1260 msg("Your way is magically blocked.");
1261
1262 return;
1263 }
1264
1265 /*
1266 call()
1267 allow a user to call a potion, scroll, or ring something
1268 */
1269
1270 void
1271 call(int mark)
1272 {
1273 struct object *obj;
1274 char *elsewise;
1275 int item_type = numthings;
1276 char **item_color = NULL;
1277
1278 if (mark)
1279 obj = get_object(pack, "mark", 0, bff_markable);
1280 else
1281 obj = get_object(pack, "call", 0, bff_callable);
1282
1283 if (obj == NULL)
1284 return;
1285
1286 switch (obj->o_type)
1287 {
1288 case RING:
1289 item_type = TYP_RING;
1290 item_color = r_stones;
1291 break;
1292 case POTION:
1293 item_type = TYP_POTION;
1294 item_color = p_colors;
1295 break;
1296 case SCROLL:
1297 item_type = TYP_SCROLL;
1298 item_color = s_names;
1299 break;
1300 case STICK:
1301 item_type = TYP_STICK;
1302 item_color = ws_made;
1303 default:
1304 if (!mark)
1305 {
1306 msg("You can't call that anything.");
1307 return;
1308 }
1309 break;
1310 }
1311
1312 elsewise = (guess_items[item_type][obj->o_which] != NULL ?
1313 guess_items[item_type][obj->o_which] : item_color[obj->o_which]);
1314
1315 if (know_items[item_type][obj->o_which] && !mark)
1316 {
1317 msg("That has already been identified.");
1318 return;
1319 }
1320
1321 if (mark)
1322 {
1323 if (obj->o_mark[0])
1324 msg("Was marked \"%s\".", obj->o_mark);
1325
1326 msg("What do you want to mark it? ");
1327 prbuf[0] = '\0';
1328 }
1329 else
1330 {
1331 msg("Was called \"%s\".", elsewise);
1332 msg("What do you want to call it? ");
1333
1334 if (guess_items[item_type][obj->o_which] != NULL)
1335 ur_free(guess_items[item_type][obj->o_which]);
1336
1337 strcpy(prbuf, elsewise);
1338 }
1339
1340 if (get_string(prbuf, cw) == NORM)
1341 {
1342 if (mark)
1343 {
1344 strncpy(obj->o_mark, prbuf, MARKLEN - 1);
1345 obj->o_mark[MARKLEN - 1] = '\0';
1346 }
1347 else
1348 {
1349 guess_items[item_type][obj->o_which] = new_alloc(strlen(prbuf) + 1);
1350 strcpy(guess_items[item_type][obj->o_which], prbuf);
1351 }
1352 }
1353
1354 return;
1355 }
1356
1357 /*
1358 att_bonus()
1359 bonus attacks for certain player classes
1360 */
1361
1362 int
1363 att_bonus(void)
1364 {
1365 int bonus = FALSE;
1366
1367 if ((player.t_ctype == C_FIGHTER || player.t_ctype == C_PALADIN)
1368 && (pstats.s_lvl > 12 ||
1369 (pstats.s_lvl > 6 && pstats.s_lvl < 13 && rnd(2))))
1370 bonus = TRUE;
1371
1372 else if ((player.t_ctype == C_RANGER)
1373 && (pstats.s_lvl > 14 ||
1374 (pstats.s_lvl > 7 && pstats.s_lvl < 15 && rnd(2))))
1375 bonus = TRUE;
1376
1377 else if ((player.t_ctype == C_NINJA)
1378 && (pstats.s_lvl > 8 ||
1379 (pstats.s_lvl > 4 && pstats.s_lvl < 9 && rnd(2))))
1380 bonus = TRUE;
1381
1382 return(bonus);
1383 }