Neale Pickett
·
2013-07-18
rwrite.c
1/*
2 * Read and execute the user commands
3 *
4 * @(#)rwrite.c 4.73 (Berkeley) 08/06/83
5 */
6
7#include <curses.h>
8#include <ctype.h>
9#include "netprot.h"
10
11/*
12 * command:
13 * Process the user commands
14 */
15void
16command(void)
17{
18 char ch;
19 int ntimes = 1; /* Number of player moves */
20 char *fp;
21 THING *mp;
22 static char countch, direction, newcount = FALSE;
23
24 if (on(Player, ISHASTE))
25 ntimes++;
26 /*
27 * Let the daemons start up
28 */
29 do_daemons(BEFORE);
30 do_fuses(BEFORE);
31 while (ntimes--)
32 {
33 Again = FALSE;
34 if (Has_hit)
35 {
36 endmsg();
37 Has_hit = FALSE;
38 }
39 /*
40 * these are illegal things for the player to be, so if any are
41 * set, someone's been poking in memeory
42 */
43 if (on(Player, ISSLOW|ISGREED|ISINVIS|ISREGEN|ISTARGET))
44 exit(1);
45
46 look(TRUE);
47 if (!Running)
48 Door_stop = FALSE;
49 status();
50 Lastscore = Purse;
51 move(Hero.y, Hero.x);
52 if (!((Running || Count) && Jump))
53 refresh(); /* Draw screen */
54 Take = 0;
55 After = TRUE;
56 /*
57 * Read command or continue run
58 */
59#ifdef MASTER
60 if (Wizard)
61 Noscore = TRUE;
62#endif
63 if (!No_command)
64 {
65 if (Running || To_death)
66 ch = Runch;
67 else if (Count)
68 ch = countch;
69 else
70 {
71 ch = readchar();
72 Move_on = FALSE;
73 if (Mpos != 0) /* Erase message if its there */
74 msg("");
75 }
76 }
77 else
78 ch = '.';
79 if (No_command)
80 {
81 if (--No_command == 0)
82 {
83 Player.t_flags |= ISRUN;
84 msg("you can move again");
85 }
86 }
87 else
88 {
89 /*
90 * check for prefixes
91 */
92 newcount = FALSE;
93 if (isdigit(ch))
94 {
95 Count = 0;
96 newcount = TRUE;
97 while (isdigit(ch))
98 {
99 Count = Count * 10 + (ch - '0');
100 ch = readchar();
101 }
102 countch = ch;
103 /*
104 * turn off Count for commands which don't make sense
105 * to repeat
106 */
107 switch (ch)
108 {
109 case CTRL('B'): case CTRL('H'): case CTRL('J'):
110 case CTRL('K'): case CTRL('L'): case CTRL('N'):
111 case CTRL('U'): case CTRL('Y'):
112 case '.': case 'a': case 'b': case 'h': case 'j':
113 case 'k': case 'l': case 'm': case 'n': case 'q':
114 case 'r': case 's': case 't': case 'u': case 'y':
115 case 'z': case 'B': case 'C': case 'H': case 'I':
116 case 'J': case 'K': case 'L': case 'N': case 'U':
117 case 'Y':
118#ifdef MASTER
119 case CTRL('D'): case CTRL('A'):
120#endif
121 break;
122 default:
123 Count = 0;
124 }
125 }
126 /*
127 * execute a command
128 */
129 if (Count && !Running)
130 Count--;
131 if (ch != 'a' && ch != ESCAPE && !(Running || Count || To_death))
132 {
133 L_last_comm = Last_comm;
134 L_last_dir = Last_dir;
135 L_last_pick = Last_pick;
136 Last_comm = ch;
137 Last_dir = '\0';
138 Last_pick = NULL;
139 }
140over:
141 switch (ch)
142 {
143 when ',': {
144 THING *obj = NULL;
145 int found = 0;
146 for (obj = Lvl_obj; obj != NULL; obj = next(obj))
147 {
148 if (obj->o_pos.y == Hero.y && obj->o_pos.x == Hero.x)
149 {
150 found=1;
151 break;
152 }
153 }
154
155 if (found) {
156 if (levit_check())
157 ;
158 else
159 pick_up(obj->o_type);
160 }
161 else {
162 if (!Terse)
163 addmsg("you are ");
164 msg("not standing on any object");
165 }
166 }
167 when 'h': do_move(0, -1);
168 when 'j': do_move(1, 0);
169 when 'k': do_move(-1, 0);
170 when 'l': do_move(0, 1);
171 when 'y': do_move(-1, -1);
172 when 'u': do_move(-1, 1);
173 when 'b': do_move(1, -1);
174 when 'n': do_move(1, 1);
175 when 'H': do_run('h');
176 when 'J': do_run('j');
177 when 'K': do_run('k');
178 when 'L': do_run('l');
179 when 'Y': do_run('y');
180 when 'U': do_run('u');
181 when 'B': do_run('b');
182 when 'N': do_run('n');
183 when CTRL('H'): case CTRL('J'): case CTRL('K'): case CTRL('L'):
184 case CTRL('Y'): case CTRL('U'): case CTRL('B'): case CTRL('N'):
185 {
186 if (!on(Player, ISBLIND))
187 {
188 Door_stop = TRUE;
189 Firstmove = TRUE;
190 }
191 if (Count && !newcount)
192 ch = direction;
193 else
194 {
195 ch += ('A' - CTRL('A'));
196 direction = ch;
197 }
198 goto over;
199 }
200 when 'F':
201 Kamikaze = TRUE;
202 /* FALLTHROUGH */
203 case 'f':
204 if (!get_dir())
205 {
206 After = FALSE;
207 break;
208 }
209 Delta.y += Hero.y;
210 Delta.x += Hero.x;
211 if (((mp = moat(Delta.y, Delta.x)) == NULL
212 || (!see_monst(mp)) && !on(Player, SEEMONST)))
213 {
214 if (!Terse)
215 addmsg("I see ");
216 msg("no monster there");
217 After = FALSE;
218 }
219 else if (diag_ok(&Hero, &Delta))
220 {
221 To_death = TRUE;
222 Max_hit = 0;
223 mp->t_flags |= ISTARGET;
224 Runch = ch = Dir_ch;
225 goto over;
226 }
227 when 't':
228 if (!get_dir())
229 After = FALSE;
230 else
231 missile(Delta.y, Delta.x);
232 when 'a':
233 if (Last_comm == '\0')
234 {
235 msg("you haven't typed a command yet");
236 After = FALSE;
237 }
238 else
239 {
240 ch = Last_comm;
241 Again = TRUE;
242 goto over;
243 }
244 when 'q': quaff();
245 when 'Q':
246 After = FALSE;
247 Q_comm = TRUE;
248 quit(0);
249 Q_comm = FALSE;
250 when 'i': After = FALSE; inventory(Pack, 0);
251 when 'I': After = FALSE; picky_inven();
252 when 'd': drop();
253 when 'r': read_scroll();
254 when 'e': eat();
255 when 'w': wield();
256 when 'W': wear();
257 when 'T': take_off();
258 when 'P': ring_on();
259 when 'R': ring_off();
260 when 'o': option(); After = FALSE;
261 when 'c': call(); After = FALSE;
262 when '>': After = FALSE; d_level();
263 when '<': After = FALSE; u_level();
264 when '?': After = FALSE; help();
265 when '/': After = FALSE; identify();
266 when 's': search();
267 when 'z':
268 if (get_dir())
269 do_zap();
270 else
271 After = FALSE;
272 when 'D': After = FALSE; discovered();
273 when CTRL('P'): After = FALSE; msg(Huh);
274 when CTRL('R'):
275 After = FALSE;
276 clearok(curscr,TRUE);
277 wrefresh(curscr);
278 when 'v':
279 After = FALSE;
280 msg("version %s. (mctesq was here)", Release);
281 when 'S':
282 After = FALSE;
283 save_game();
284 when '.': ; /* Rest command */
285 when ' ': After = FALSE; /* "Legal" illegal command */
286 when '^':
287 After = FALSE;
288 if (get_dir()) {
289 Delta.y += Hero.y;
290 Delta.x += Hero.x;
291 fp = &flat(Delta.y, Delta.x);
292 if (chat(Delta.y, Delta.x) != TRAP)
293 msg("no trap there");
294 else if (on(Player, ISHALU))
295 msg(Tr_name[rnd(NTRAPS)]);
296 else {
297 msg(Tr_name[*fp & F_TMASK]);
298 *fp |= F_SEEN;
299 }
300 }
301#ifdef MASTER
302 when '+':
303 After = FALSE;
304 if (Wizard)
305 {
306 Wizard = FALSE;
307 turn_see(TRUE);
308 msg("not wizard any more");
309 }
310 else
311 {
312/* if (Wizard = passwd()) */
313 if (Wizard = 1)
314 {
315 Noscore = TRUE;
316 turn_see(FALSE);
317 msg("you are suddenly as smart as Ken Arnold in dungeon #%d", Dnum);
318 }
319 else
320 msg("sorry");
321 }
322#endif
323 when ESCAPE: /* Escape */
324 Door_stop = FALSE;
325 Count = 0;
326 After = FALSE;
327 Again = FALSE;
328 when 'm':
329 Move_on = TRUE;
330 if (!get_dir())
331 After = FALSE;
332 else
333 {
334 ch = Dir_ch;
335 countch = Dir_ch;
336 goto over;
337 }
338 when ')': current(Cur_weapon, "wielding", NULL);
339 when ']': current(Cur_armor, "wearing", NULL);
340 when '=':
341 current(Cur_ring[LEFT], "wearing",
342 Terse ? "(L)" : "on left hand");
343 current(Cur_ring[RIGHT], "wearing",
344 Terse ? "(R)" : "on right hand");
345 when '@':
346 Stat_msg = TRUE;
347 status();
348 Stat_msg = FALSE;
349 After = FALSE;
350 otherwise:
351 After = FALSE;
352#ifdef MASTER
353 if (Wizard) switch (ch)
354 {
355 when '|': msg("@ %d,%d", Hero.y, Hero.x);
356 when 'C': create_obj();
357 when '$': msg("Inpack = %d", Inpack);
358 when CTRL('G'): inventory(Lvl_obj, 0);
359 when CTRL('W'): whatis(FALSE, 0);
360 when CTRL('D'): Level++; new_level();
361 when CTRL('A'): Level--; new_level();
362 when CTRL('F'): show_map();
363 when CTRL('T'): teleport();
364 when CTRL('E'): msg("food left: %d", Food_left);
365 when CTRL('C'): add_pass();
366 when CTRL('X'): turn_see(on(Player, SEEMONST));
367 when CTRL('~'):
368 {
369 THING *item;
370
371 if ((item = get_item("charge", STICK)) != NULL)
372 item->o_charges = 10000;
373 }
374 when CTRL('I'):
375 {
376 int i;
377 THING *obj;
378
379 for (i = 0; i < 9; i++)
380 raise_level();
381 /*
382 * Give him a sword (+1,+1)
383 */
384 obj = new_item();
385 init_weapon(obj, TWOSWORD);
386 obj->o_hplus = 1;
387 obj->o_dplus = 1;
388 add_pack(obj, TRUE);
389 Cur_weapon = obj;
390 /*
391 * And his suit of armor
392 */
393 obj = new_item();
394 obj->o_type = ARMOR;
395 obj->o_which = PLATE_MAIL;
396 obj->o_arm = -5;
397 obj->o_flags |= ISKNOW;
398 obj->o_count = 1;
399 obj->o_group = 0;
400 Cur_armor = obj;
401 add_pack(obj, TRUE);
402 }
403 when '*' :
404 pr_list();
405 otherwise:
406 illcom(ch);
407 }
408 else
409#endif
410 illcom(ch);
411 }
412 /*
413 * turn off flags if no longer needed
414 */
415 if (!Running)
416 Door_stop = FALSE;
417 }
418 /*
419 * If he ran into something to take, let him pick it up.
420 */
421 if (Take != 0)
422 pick_up(Take);
423 if (!Running)
424 Door_stop = FALSE;
425 if (!After)
426 ntimes++;
427 }
428 do_daemons(AFTER);
429 do_fuses(AFTER);
430 if (ISRING(LEFT, R_SEARCH))
431 search();
432 else if (ISRING(LEFT, R_TELEPORT) && rnd(50) == 0)
433 teleport();
434 if (ISRING(RIGHT, R_SEARCH))
435 search();
436 else if (ISRING(RIGHT, R_TELEPORT) && rnd(50) == 0)
437 teleport();
438}
439
440/*
441 * illcom:
442 * What to do with an illegal command
443 */
444void
445illcom(char ch)
446{
447 Save_msg = FALSE;
448 Count = 0;
449 msg("illegal command '%s'", unctrl(ch));
450 Save_msg = TRUE;
451}
452
453/*
454 * search:
455 * Player gropes about him to find hidden things.
456 */
457void
458search(void)
459{
460 int y, x;
461 char *fp;
462 int ey, ex;
463 int probinc;
464 bool found;
465
466 ey = Hero.y + 1;
467 ex = Hero.x + 1;
468 probinc = (on(Player, ISHALU) ? 3 : 0);
469 probinc += (on(Player, ISBLIND) ? 2 : 0);
470 found = FALSE;
471 for (y = Hero.y - 1; y <= ey; y++)
472 for (x = Hero.x - 1; x <= ex; x++)
473 {
474 if (y == Hero.y && x == Hero.x)
475 continue;
476 fp = &flat(y, x);
477 if (!(*fp & F_REAL))
478 switch (chat(y, x))
479 {
480 case '|':
481 case '-':
482 if (rnd(5 + probinc) != 0)
483 break;
484 chat(y, x) = DOOR;
485foundone:
486 found = TRUE;
487 *fp |= F_REAL;
488 Count = FALSE;
489 Running = FALSE;
490 break;
491 case FLOOR:
492 if (rnd(2 + probinc) != 0)
493 break;
494 chat(y, x) = TRAP;
495 if (!Terse)
496 addmsg("you found ");
497 if (on(Player, ISHALU))
498 msg(Tr_name[rnd(NTRAPS)]);
499 else {
500 msg(Tr_name[*fp & F_TMASK]);
501 *fp |= F_SEEN;
502 }
503 goto foundone;
504 break;
505 case ' ':
506 if (rnd(3 + probinc) != 0)
507 break;
508 chat(y, x) = PASSAGE;
509 goto foundone;
510 }
511 }
512 if (found)
513 look(FALSE);
514}
515
516/*
517 * help:
518 * Give single character help, or the whole mess if he wants it
519 */
520void
521help(void)
522{
523 struct h_list *strp;
524 char helpch;
525 unsigned int numprint, cnt;
526
527 msg("character you want help for (* for all): ");
528 helpch = readchar();
529 Mpos = 0;
530 /*
531 * If its not a *, print the right help string
532 * or an error if he typed a funny character.
533 */
534 if (helpch != '*')
535 {
536 move(0, 0);
537 for (strp = Helpstr; strp->h_desc != NULL; strp++)
538 if (strp->h_ch == helpch)
539 {
540 Lower_msg = TRUE;
541 msg("%s%s", unctrl(strp->h_ch), strp->h_desc);
542 Lower_msg = FALSE;
543 return;
544 }
545 msg("unknown character '%s'", unctrl(helpch));
546 return;
547 }
548 /*
549 * Here we print help for everything.
550 * Then wait before we return to command mode
551 */
552 numprint = 0;
553 for (strp = Helpstr; strp->h_desc != NULL; strp++)
554 if (strp->h_print)
555 numprint++;
556 if (numprint & 01) /* round odd numbers up */
557 numprint++;
558 numprint /= 2;
559 if (numprint > LINES - 1)
560 numprint = LINES - 1;
561
562 wclear(Hw);
563 cnt = 0;
564 for (strp = Helpstr; strp->h_desc != NULL; strp++)
565 if (strp->h_print)
566 {
567 wmove(Hw, cnt % numprint, cnt >= numprint ? COLS / 2 : 0);
568 if (strp->h_ch)
569 waddstr(Hw, unctrl(strp->h_ch));
570 waddstr(Hw, strp->h_desc);
571 if (++cnt >= numprint * 2)
572 break;
573 }
574 wmove(Hw, LINES - 1, 0);
575 waddstr(Hw, "--Press space to continue--");
576 wrefresh(Hw);
577 wait_for(' ');
578 clearok(stdscr, TRUE);
579/*
580 refresh();
581*/
582 msg("");
583 touchwin(stdscr);
584 wrefresh(stdscr);
585}
586
587/*
588 * identify:
589 * Tell the player what a certain thing is.
590 */
591void
592identify(void)
593{
594 int ch;
595 struct h_list *hp;
596 char *str;
597 static struct h_list ident_list[] = {
598 '|', "wall of a room", FALSE,
599 '-', "wall of a room", FALSE,
600 GOLD, "gold", FALSE,
601 STAIRS, "a staircase", FALSE,
602 DOOR, "door", FALSE,
603 FLOOR, "room floor", FALSE,
604 PLAYER, "you", FALSE,
605 PASSAGE, "passage", FALSE,
606 TRAP, "trap", FALSE,
607 POTION, "potion", FALSE,
608 SCROLL, "scroll", FALSE,
609 FOOD, "food", FALSE,
610 WEAPON, "weapon", FALSE,
611 ' ', "solid rock", FALSE,
612 ARMOR, "armor", FALSE,
613 AMULET, "the Amulet of Yendor", FALSE,
614 RING, "ring", FALSE,
615 STICK, "wand or staff", FALSE,
616 '\0'
617 };
618
619 msg("what do you want identified? ");
620 ch = readchar();
621 Mpos = 0;
622 if (ch == ESCAPE)
623 {
624 msg("");
625 return;
626 }
627 if (isupper(ch))
628 str = Monsters[ch-'A'].m_name;
629 else
630 {
631 str = "unknown character";
632 for (hp = ident_list; hp->h_ch != '\0'; hp++)
633 if (hp->h_ch == ch)
634 {
635 str = hp->h_desc;
636 break;
637 }
638 }
639 msg("'%s': %s", unctrl(ch), str);
640}
641
642/*
643 * d_level:
644 * He wants to go down a level
645 */
646void
647d_level(void)
648{
649 if (levit_check())
650 return;
651 if (chat(Hero.y, Hero.x) != STAIRS)
652 msg("I see no way down");
653 else
654 {
655 Level++;
656 Seenstairs = FALSE;
657 new_level();
658 }
659}
660
661/*
662 * u_level:
663 * He wants to go up a level
664 */
665void
666u_level(void)
667{
668 if (levit_check())
669 return;
670 if (chat(Hero.y, Hero.x) == STAIRS)
671 if (Amulet)
672 {
673 Level--;
674 if (Level == 0)
675 total_winner();
676 new_level();
677 msg("you feel a wrenching sensation in your gut");
678 }
679 else
680 msg("your way is magically blocked");
681 else
682 msg("I see no way up");
683}
684
685/*
686 * levit_check:
687 * Check to see if she's levitating, and if she is, print an
688 * appropriate message.
689 */
690bool
691levit_check(void)
692{
693 if (!on(Player, ISLEVIT))
694 return FALSE;
695 msg("You can't. You're floating off the ground!");
696 return TRUE;
697}
698
699/*
700 * call:
701 * Allow a user to call a potion, scroll, or ring something
702 */
703void
704call(void)
705{
706 THING *obj;
707 struct obj_info *op;
708 char **guess, *elsewise = NULL;
709 bool *know;
710
711 obj = get_item("call", CALLABLE);
712 /*
713 * Make certain that it is somethings that we want to wear
714 */
715 if (obj == NULL)
716 return;
717 switch (obj->o_type)
718 {
719 when RING:
720 op = &Ring_info[obj->o_which];
721 elsewise = R_stones[obj->o_which];
722 goto norm;
723 when POTION:
724 op = &Pot_info[obj->o_which];
725 elsewise = P_colors[obj->o_which];
726 goto norm;
727 when SCROLL:
728 op = &Scr_info[obj->o_which];
729 elsewise = S_names[obj->o_which];
730 goto norm;
731 when STICK:
732 op = &Ws_info[obj->o_which];
733 elsewise = Ws_made[obj->o_which];
734norm:
735 know = &op->oi_know;
736 guess = &op->oi_guess;
737 if (*guess != NULL)
738 elsewise = *guess;
739 when FOOD:
740 msg("you can't call that anything");
741 return;
742 otherwise:
743 guess = &obj->o_label;
744 know = NULL;
745 elsewise = obj->o_label;
746 }
747 if (know != NULL && *know)
748 {
749 msg("that has already been identified");
750 return;
751 }
752 if (elsewise != NULL && elsewise == op->oi_guess)
753 {
754 if (!Terse)
755 addmsg("Was ");
756 msg("called \"%s\"", elsewise);
757 }
758 if (Terse)
759 msg("call it: ");
760 else
761 msg("what do you want to call it? ");
762 if (elsewise == NULL)
763 strcpy(Prbuf, "");
764 else
765 strcpy(Prbuf, elsewise);
766 if (get_str(Prbuf, stdscr) == NORM)
767 {
768 if (*guess != NULL)
769 free(*guess);
770 *guess = malloc((unsigned int) strlen(Prbuf) + 1);
771 strcpy(*guess, Prbuf);
772 }
773}
774
775/*
776 * current:
777 * Print the current weapon/armor
778 */
779/* VARARGS2 */
780void
781current(THING *cur, char *how, char *where)
782{
783 After = FALSE;
784 if (cur != NULL)
785 {
786 if (!Terse)
787 addmsg("you are %s (", how);
788 Inv_describe = FALSE;
789 addmsg("%c) %s", cur->o_packch, inv_name(cur, TRUE));
790 Inv_describe = TRUE;
791 if (where)
792 addmsg(" %s", where);
793 endmsg();
794 }
795 else
796 {
797 if (!Terse)
798 addmsg("you are ");
799 addmsg("%s nothing", how);
800 if (where)
801 addmsg(" %s", where);
802 endmsg();
803 }
804}