Rogue 3.6 reconstruction from http://rogue.rogueforge.net/rogue36/.
[rogue-pphs.git] / command.c
1 /*
2 * Read and execute the user commands
3 *
4 * @(#)command.c 3.45 (Berkeley) 6/15/81
5 *
6 * Rogue: Exploring the Dungeons of Doom
7 * Copyright (C) 1980, 1981 Michael Toy, Ken Arnold and Glenn Wichman
8 * All rights reserved.
9 *
10 * See the file LICENSE.TXT for full copyright and licensing information.
11 */
12
13 #include "curses.h"
14 #include <stdlib.h>
15 #include <ctype.h>
16 #include <signal.h>
17 #include <string.h>
18 #include "rogue.h"
19
20 /*
21 * command:
22 * Process the user commands
23 */
24
25 command()
26 {
27 register char ch;
28 register int ntimes = 1; /* Number of player moves */
29 static char countch, direction, newcount = FALSE;
30
31
32 if (on(player, ISHASTE)) ntimes++;
33 /*
34 * Let the daemons start up
35 */
36 do_daemons(BEFORE);
37 do_fuses(BEFORE);
38 while (ntimes--)
39 {
40 look(TRUE);
41 if (!running)
42 door_stop = FALSE;
43 status();
44 lastscore = purse;
45 wmove(cw, hero.y, hero.x);
46 if (!((running || count) && jump))
47 draw(cw); /* Draw screen */
48 take = 0;
49 after = TRUE;
50 /*
51 * Read command or continue run
52 */
53 if (wizard)
54 waswizard = TRUE;
55 if (!no_command)
56 {
57 if (running) ch = runch;
58 else if (count) ch = countch;
59 else
60 {
61 ch = readchar(cw);
62 if (mpos != 0 && !running) /* Erase message if its there */
63 msg("");
64 }
65 }
66 else ch = ' ';
67 if (no_command)
68 {
69 if (--no_command == 0)
70 msg("You can move again.");
71 }
72 else
73 {
74 /*
75 * check for prefixes
76 */
77 if (isdigit(ch))
78 {
79 count = 0;
80 newcount = TRUE;
81 while (isdigit(ch))
82 {
83 count = count * 10 + (ch - '0');
84 ch = readchar(cw);
85 }
86 countch = ch;
87 /*
88 * turn off count for commands which don't make sense
89 * to repeat
90 */
91 switch (ch) {
92 case 'h': case 'j': case 'k': case 'l':
93 case 'y': case 'u': case 'b': case 'n':
94 case 'H': case 'J': case 'K': case 'L':
95 case 'Y': case 'U': case 'B': case 'N':
96 case 'q': case 'r': case 's': case 'f':
97 case 't': case 'C': case 'I': case ' ':
98 case 'z': case 'p':
99 break;
100 default:
101 count = 0;
102 }
103 }
104 switch (ch)
105 {
106 case 'f':
107 if (!on(player, ISBLIND))
108 {
109 door_stop = TRUE;
110 firstmove = TRUE;
111 }
112 if (count && !newcount)
113 ch = direction;
114 else
115 ch = readchar(cw);
116 switch (ch)
117 {
118 case 'h': case 'j': case 'k': case 'l':
119 case 'y': case 'u': case 'b': case 'n':
120 ch = toupper(ch);
121 }
122 direction = ch;
123 }
124 newcount = FALSE;
125 /*
126 * execute a command
127 */
128 if (count && !running)
129 count--;
130 switch (ch)
131 {
132 case '!' : shell();
133 when 'h' : do_move(0, -1);
134 when 'j' : do_move(1, 0);
135 when 'k' : do_move(-1, 0);
136 when 'l' : do_move(0, 1);
137 when 'y' : do_move(-1, -1);
138 when 'u' : do_move(-1, 1);
139 when 'b' : do_move(1, -1);
140 when 'n' : do_move(1, 1);
141 when 'H' : do_run('h');
142 when 'J' : do_run('j');
143 when 'K' : do_run('k');
144 when 'L' : do_run('l');
145 when 'Y' : do_run('y');
146 when 'U' : do_run('u');
147 when 'B' : do_run('b');
148 when 'N' : do_run('n');
149 when 't':
150 if (!get_dir())
151 after = FALSE;
152 else
153 missile(delta.y, delta.x);
154 when 'Q' : after = FALSE; quit(0);
155 when 'i' : after = FALSE; inventory(pack, 0);
156 when 'I' : after = FALSE; picky_inven();
157 when 'd' : drop();
158 when 'q' : quaff();
159 when 'r' : read_scroll();
160 when 'e' : eat();
161 when 'w' : wield();
162 when 'W' : wear();
163 when 'T' : take_off();
164 when 'P' : ring_on();
165 when 'R' : ring_off();
166 when 'o' : option();
167 when 'c' : call();
168 when '>' : after = FALSE; d_level();
169 when '<' : after = FALSE; u_level();
170 when '?' : after = FALSE; help();
171 when '/' : after = FALSE; identify();
172 when 's' : search();
173 when 'z' : do_zap(FALSE);
174 when 'p':
175 if (get_dir())
176 do_zap(TRUE);
177 else
178 after = FALSE;
179 when 'v' : msg("Rogue version %s. (mctesq was here)", release);
180 when CTRL('L') : after = FALSE; clearok(curscr,TRUE);draw(curscr);
181 when CTRL('R') : after = FALSE; msg(huh);
182 when 'S' :
183 after = FALSE;
184 if (save_game())
185 {
186 wmove(cw, LINES-1, 0);
187 wclrtoeol(cw);
188 draw(cw);
189 endwin();
190 exit(0);
191 }
192 when ' ' : ; /* Rest command */
193 when CTRL('P') :
194 after = FALSE;
195 if (wizard)
196 {
197 wizard = FALSE;
198 msg("Not wizard any more");
199 }
200 else
201 {
202 if (wizard = passwd())
203 {
204 msg("You are suddenly as smart as Ken Arnold in dungeon #%d", dnum);
205 wizard = TRUE;
206 waswizard = TRUE;
207 }
208 else
209 msg("Sorry");
210 }
211 when ESCAPE : /* Escape */
212 door_stop = FALSE;
213 count = 0;
214 after = FALSE;
215 otherwise :
216 after = FALSE;
217 if (wizard) switch (ch)
218 {
219 case '@' : msg("@ %d,%d", hero.y, hero.x);
220 when 'C' : create_obj();
221 when CTRL('I') : inventory(lvl_obj, 0);
222 when CTRL('W') : whatis();
223 when CTRL('D') : level++; new_level();
224 when CTRL('U') : level--; new_level();
225 when CTRL('F') : show_win(stdscr, "--More (level map)--");
226 when CTRL('X') : show_win(mw, "--More (monsters)--");
227 when CTRL('T') : teleport();
228 when CTRL('E') : msg("food left: %d", food_left);
229 when CTRL('A') : msg("%d things in your pack", inpack);
230 when CTRL('C') : add_pass();
231 when CTRL('N') :
232 {
233 register struct linked_list *item;
234
235 if ((item = get_item("charge", STICK)) != NULL)
236 ((struct object *) ldata(item))->o_charges = 10000;
237 }
238 when CTRL('H') :
239 {
240 register int i;
241 register struct linked_list *item;
242 register struct object *obj;
243
244 for (i = 0; i < 9; i++)
245 raise_level();
246 /*
247 * Give the rogue a sword (+1,+1)
248 */
249 item = new_item(sizeof *obj);
250 obj = (struct object *) ldata(item);
251 obj->o_type = WEAPON;
252 obj->o_which = TWOSWORD;
253 init_weapon(obj, SWORD);
254 obj->o_hplus = 1;
255 obj->o_dplus = 1;
256 add_pack(item, TRUE);
257 cur_weapon = obj;
258 /*
259 * And his suit of armor
260 */
261 item = new_item(sizeof *obj);
262 obj = (struct object *) ldata(item);
263 obj->o_type = ARMOR;
264 obj->o_which = PLATE_MAIL;
265 obj->o_ac = -5;
266 obj->o_flags |= ISKNOW;
267 cur_armor = obj;
268 add_pack(item, TRUE);
269 }
270 otherwise :
271 msg("Illegal command '%s'.", unctrl(ch));
272 count = 0;
273 }
274 else
275 {
276 msg("Illegal command '%s'.", unctrl(ch));
277 count = 0;
278 }
279 }
280 /*
281 * turn off flags if no longer needed
282 */
283 if (!running)
284 door_stop = FALSE;
285 }
286 /*
287 * If he ran into something to take, let him pick it up.
288 */
289 if (take != 0)
290 pick_up(take);
291 if (!running)
292 door_stop = FALSE;
293 }
294 /*
295 * Kick off the rest if the daemons and fuses
296 */
297 if (after)
298 {
299 look(FALSE);
300 do_daemons(AFTER);
301 do_fuses(AFTER);
302 if (ISRING(LEFT, R_SEARCH))
303 search();
304 else if (ISRING(LEFT, R_TELEPORT) && rnd(100) < 2)
305 teleport();
306 if (ISRING(RIGHT, R_SEARCH))
307 search();
308 else if (ISRING(RIGHT, R_TELEPORT) && rnd(100) < 2)
309 teleport();
310 }
311 }
312
313 /*
314 * quit:
315 * Have player make certain, then exit.
316 */
317
318 void
319 quit(int p)
320 {
321 /*
322 * Reset the signal in case we got here via an interrupt
323 */
324 if (signal(SIGINT, quit) != &quit)
325 mpos = 0;
326 msg("Really quit?");
327 draw(cw);
328 if (readchar(cw) == 'y')
329 {
330 clear();
331 move(LINES-1, 0);
332 draw(stdscr);
333 endwin();
334 score(purse, 1, 0);
335 exit(0);
336 }
337 else
338 {
339 signal(SIGINT, quit);
340 wmove(cw, 0, 0);
341 wclrtoeol(cw);
342 status();
343 draw(cw);
344 mpos = 0;
345 count = 0;
346 }
347 }
348
349 /*
350 * search:
351 * Player gropes about him to find hidden things.
352 */
353
354 search()
355 {
356 register int x, y;
357 register char ch;
358
359 /*
360 * Look all around the hero, if there is something hidden there,
361 * give him a chance to find it. If its found, display it.
362 */
363 if (on(player, ISBLIND))
364 return;
365 for (x = hero.x - 1; x <= hero.x + 1; x++)
366 for (y = hero.y - 1; y <= hero.y + 1; y++)
367 {
368 ch = winat(y, x);
369 switch (ch)
370 {
371 case SECRETDOOR:
372 if (rnd(100) < 20) {
373 mvaddch(y, x, DOOR);
374 count = 0;
375 }
376 break;
377 case TRAP:
378 {
379 register struct trap *tp;
380
381 if (mvwinch(cw, y, x) == TRAP)
382 break;
383 if (rnd(100) > 50)
384 break;
385 tp = trap_at(y, x);
386 tp->tr_flags |= ISFOUND;
387 mvwaddch(cw, y, x, TRAP);
388 count = 0;
389 running = FALSE;
390 msg(tr_name(tp->tr_type));
391 }
392 }
393 }
394 }
395
396 /*
397 * help:
398 * Give single character help, or the whole mess if he wants it
399 */
400
401 help()
402 {
403 register struct h_list *strp = helpstr;
404 register char helpch;
405 register int cnt;
406
407 msg("Character you want help for (* for all): ");
408 helpch = readchar(cw);
409 mpos = 0;
410 /*
411 * If its not a *, print the right help string
412 * or an error if he typed a funny character.
413 */
414 if (helpch != '*')
415 {
416 wmove(cw, 0, 0);
417 while (strp->h_ch)
418 {
419 if (strp->h_ch == helpch)
420 {
421 msg("%s%s", unctrl(strp->h_ch), strp->h_desc);
422 break;
423 }
424 strp++;
425 }
426 if (strp->h_ch != helpch)
427 msg("Unknown character '%s'", unctrl(helpch));
428 return;
429 }
430 /*
431 * Here we print help for everything.
432 * Then wait before we return to command mode
433 */
434 wclear(hw);
435 cnt = 0;
436 while (strp->h_ch)
437 {
438 mvwaddstr(hw, cnt % 23, cnt > 22 ? 40 : 0, unctrl(strp->h_ch));
439 waddstr(hw, strp->h_desc);
440 cnt++;
441 strp++;
442 }
443 wmove(hw, LINES-1, 0);
444 wprintw(hw, "--Press space to continue--");
445 draw(hw);
446 wait_for(hw,' ');
447 wclear(hw);
448 draw(hw);
449 wmove(cw, 0, 0);
450 wclrtoeol(cw);
451 status();
452 touchwin(cw);
453 }
454
455 /*
456 * identify:
457 * Tell the player what a certain thing is.
458 */
459
460 identify()
461 {
462 register char ch, *str;
463
464 msg("What do you want identified? ");
465 ch = readchar(cw);
466 mpos = 0;
467 if (ch == ESCAPE)
468 {
469 msg("");
470 return;
471 }
472 if (isalpha(ch) && isupper(ch))
473 str = monsters[ch-'A'].m_name;
474 else switch(ch)
475 {
476 case '|':
477 case '-':
478 str = "wall of a room";
479 when GOLD: str = "gold";
480 when STAIRS : str = "passage leading down";
481 when DOOR: str = "door";
482 when FLOOR: str = "room floor";
483 when PLAYER: str = "you";
484 when PASSAGE: str = "passage";
485 when TRAP: str = "trap";
486 when POTION: str = "potion";
487 when SCROLL: str = "scroll";
488 when FOOD: str = "food";
489 when WEAPON: str = "weapon";
490 when ' ' : str = "solid rock";
491 when ARMOR: str = "armor";
492 when AMULET: str = "The Amulet of Yendor";
493 when RING: str = "ring";
494 when STICK: str = "wand or staff";
495 otherwise: str = "unknown character";
496 }
497 msg("'%s' : %s", unctrl(ch), str);
498 }
499
500 /*
501 * d_level:
502 * He wants to go down a level
503 */
504
505 d_level()
506 {
507 if (winat(hero.y, hero.x) != STAIRS)
508 msg("I see no way down.");
509 else
510 {
511 level++;
512 new_level();
513 }
514 }
515
516 /*
517 * u_level:
518 * He wants to go up a level
519 */
520
521 u_level()
522 {
523 if (winat(hero.y, hero.x) == STAIRS)
524 {
525 if (amulet)
526 {
527 level--;
528 if (level == 0)
529 total_winner();
530 new_level();
531 msg("You feel a wrenching sensation in your gut.");
532 return;
533 }
534 }
535 msg("I see no way up.");
536 }
537
538 /*
539 * Let him escape for a while
540 */
541
542 shell()
543 {
544 /*
545 * Set the terminal back to original mode
546 */
547 wclear(hw);
548 wmove(hw, LINES-1, 0);
549 draw(hw);
550 endwin();
551 in_shell = TRUE;
552 fflush(stdout);
553
554 md_shellescape();
555
556 printf("\n[Press return to continue]");
557 fflush(stdout);
558 noecho();
559 crmode();
560 in_shell = FALSE;
561 wait_for(cw,'\n');
562 clearok(cw, TRUE);
563 touchwin(cw);
564 draw(cw);
565 }
566
567 /*
568 * allow a user to call a potion, scroll, or ring something
569 */
570 call()
571 {
572 register struct object *obj;
573 register struct linked_list *item;
574 register char **guess, *elsewise;
575 register bool *know;
576
577 item = get_item("call", CALLABLE);
578 /*
579 * Make certain that it is somethings that we want to wear
580 */
581 if (item == NULL)
582 return;
583 obj = (struct object *) ldata(item);
584 switch (obj->o_type)
585 {
586 case RING:
587 guess = r_guess;
588 know = r_know;
589 elsewise = (r_guess[obj->o_which] != NULL ?
590 r_guess[obj->o_which] : r_stones[obj->o_which]);
591 when POTION:
592 guess = p_guess;
593 know = p_know;
594 elsewise = (p_guess[obj->o_which] != NULL ?
595 p_guess[obj->o_which] : p_colors[obj->o_which]);
596 when SCROLL:
597 guess = s_guess;
598 know = s_know;
599 elsewise = (s_guess[obj->o_which] != NULL ?
600 s_guess[obj->o_which] : s_names[obj->o_which]);
601 when STICK:
602 guess = ws_guess;
603 know = ws_know;
604 elsewise = (ws_guess[obj->o_which] != NULL ?
605 ws_guess[obj->o_which] : ws_made[obj->o_which]);
606 otherwise:
607 msg("You can't call that anything");
608 return;
609 }
610 if (know[obj->o_which])
611 {
612 msg("That has already been identified");
613 return;
614 }
615 if (terse)
616 addmsg("C");
617 else
618 addmsg("Was c");
619 msg("alled \"%s\"", elsewise);
620 if (terse)
621 msg("Call it: ");
622 else
623 msg("What do you want to call it? ");
624 strcpy(prbuf, elsewise);
625 if (get_str(prbuf, cw) == NORM)
626 {
627 if (guess[obj->o_which] != NULL)
628 free(guess[obj->o_which]);
629 guess[obj->o_which] = malloc((unsigned int) strlen(prbuf) + 1);
630 if (guess[obj->o_which] != NULL)
631 strcpy(guess[obj->o_which], prbuf);
632 }
633 }