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