comparison srogue/command.c @ 36:2128c7dc8a40

Import Super-Rogue 9.0 from the Roguelike Restoration Project (r1490)
author elwin
date Thu, 25 Nov 2010 12:21:41 +0000
parents
children 5ea4a4d8f961
comparison
equal deleted inserted replaced
35:05018c63a721 36:2128c7dc8a40
1 /*
2 * Read and execute the user commands
3 *
4 * @(#)command.c 9.0 (rdk) 7/17/84
5 *
6 * Super-Rogue
7 * Copyright (C) 1984 Robert D. Kindelberger
8 * All rights reserved.
9 *
10 * Based on "Rogue: Exploring the Dungeons of Doom"
11 * Copyright (C) 1980, 1981 Michael Toy, Ken Arnold and Glenn Wichman
12 * All rights reserved.
13 *
14 * See the file LICENSE.TXT for full copyright and licensing information.
15 */
16
17 #include <ctype.h>
18 #include <signal.h>
19 #include <limits.h>
20 #include "rogue.h"
21 #include "rogue.ext"
22 #ifdef __DJGPP__
23 #include <process.h>
24 #endif
25
26 /*
27 * command:
28 * Process the user commands
29 */
30 command()
31 {
32 reg char ch;
33 reg int ntimes = 1; /* Number of player moves */
34 static char countch, direction, newcount = FALSE;
35
36 if (pl_on(ISHASTE))
37 ntimes++;
38 /*
39 * Let the daemons start up
40 */
41 while (ntimes-- > 0) {
42 do_daemons(BEFORE);
43 look(TRUE);
44 if (!running)
45 door_stop = FALSE;
46 lastscore = purse;
47 wmove(cw, hero.y, hero.x);
48 if (!(running || count))
49 draw(cw); /* Draw screen */
50 take = 0;
51 after = TRUE;
52 /*
53 * Read command or continue run
54 */
55 if (wizard)
56 waswizard = TRUE;
57 if (player.t_nocmd <= 0) {
58 player.t_nocmd = 0;
59 if (running)
60 ch = runch;
61 else if (count)
62 ch = countch;
63 else {
64 ch = readchar();
65 if (mpos != 0 && !running) /* Erase message if its there */
66 msg("");
67 }
68 }
69 else
70 ch = '.';
71 if (player.t_nocmd > 0) {
72 if (--player.t_nocmd <= 0)
73 msg("You can move again.");
74 }
75 else {
76 /*
77 * check for prefixes
78 */
79 if (isdigit(ch)) {
80 count = 0;
81 newcount = TRUE;
82 while (isdigit(ch)) {
83 count = count * 10 + (ch - '0');
84 ch = readchar();
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 case 'f':
106 case 'g':
107 if (pl_off(ISBLIND)) {
108 door_stop = TRUE;
109 firstmove = TRUE;
110 }
111 if (count && !newcount)
112 ch = direction;
113 else
114 ch = readchar();
115 switch (ch) {
116 case 'h': case 'j': case 'k': case 'l':
117 case 'y': case 'u': case 'b': case 'n':
118 ch = toupper(ch);
119 }
120 direction = ch;
121 }
122 newcount = FALSE;
123 /*
124 * execute a command
125 */
126 if (count && !running)
127 count--;
128 switch (ch) {
129 case '!' : shell(); after = FALSE;
130 when 'h' : do_move(0, -1);
131 when 'j' : do_move(1, 0);
132 when 'k' : do_move(-1, 0);
133 when 'l' : do_move(0, 1);
134 when 'y' : do_move(-1, -1);
135 when 'u' : do_move(-1, 1);
136 when 'b' : do_move(1, -1);
137 when 'n' : do_move(1, 1);
138 when 'H' : do_run('h');
139 when 'J' : do_run('j');
140 when 'K' : do_run('k');
141 when 'L' : do_run('l');
142 when 'Y' : do_run('y');
143 when 'U' : do_run('u');
144 when 'B' : do_run('b');
145 when 'N' : do_run('n');
146 when 't':
147 if (!get_dir())
148 after = FALSE;
149 else
150 missile(delta.y, delta.x);
151 when 'Q' : after = FALSE; quit(-1);
152 when 'i' : after = FALSE; inventory(pack, 0);
153 when 'I' : after = FALSE; picky_inven();
154 when 'd' : drop(NULL);
155 when 'q' : quaff();
156 when 'r' : read_scroll();
157 when 'e' : eat();
158 when 'w' : wield();
159 when 'W' : wear();
160 when 'T' : take_off();
161 when 'P' : ring_on();
162 when 'R' : ring_off();
163 when 'O' : option();
164 when 'c' : call();
165 when '>' : after = FALSE; d_level();
166 when '<' : after = FALSE; u_level();
167 when '?' : after = FALSE; help();
168 when '/' : after = FALSE; identify(0);
169 when 's' : search();
170 when 'z' : do_zap(FALSE);
171 when 'p':
172 if (get_dir())
173 do_zap(TRUE);
174 else
175 after = FALSE;
176 when 'v': msg("Super Rogue version %s.",release);
177 when 'D': dip_it();
178 when CTRL('L') : after = FALSE; restscr(cw);
179 when CTRL('R') : after = FALSE; msg(huh);
180 when 'a': after = FALSE; dispmax();
181 when '@' : if (author())
182 msg("Hero @ %d,%d : Stairs @ %d,%d",hero.y,hero.x,stairs.y,stairs.x);
183 when 'S' :
184 after = FALSE;
185 if (save_game()) {
186 wclear(cw);
187 draw(cw);
188 endwin();
189 byebye(0);
190 }
191 when '.' : ; /* Rest command */
192 when ' ' : after = FALSE; /* do nothing */
193 when '=' :
194 if (author()) {
195 activity();
196 after = FALSE;
197 }
198 when CTRL('P') :
199 after = FALSE;
200 if (wizard) {
201 wizard = FALSE;
202 msg("Not wizard any more");
203 }
204 else {
205 wizard = passwd();
206 if (wizard) {
207 msg("Welcome back, Bob!!!!!");
208 waswizard = TRUE;
209 }
210 else
211 msg("Sorry");
212 }
213 when ESCAPE : /* Escape */
214 door_stop = FALSE;
215 count = 0;
216 after = FALSE;
217 when '#':
218 if (levtype == POSTLEV) /* buy something */
219 buy_it();
220 after = FALSE;
221 when '$':
222 if (levtype == POSTLEV) /* price something */
223 price_it();
224 after = FALSE;
225 when '%':
226 if (levtype == POSTLEV) /* sell something */
227 sell_it();
228 after = FALSE;
229 otherwise :
230 after = FALSE;
231 if (wizard) switch (ch) {
232 case CTRL('A') : ;
233 when 'C' : create_obj(FALSE);
234 when CTRL('I') : inventory(lvl_obj, 1);
235 when CTRL('W') : whatis(NULL);
236 when CTRL('D') : level++; new_level(NORMLEV);
237 when CTRL('U') : if (level > 1) level--; new_level(NORMLEV);
238 when CTRL('F') : displevl();
239 when CTRL('X') : dispmons();
240 when CTRL('T') : teleport(rndspot,&player);
241 when CTRL('E') : msg("food left: %d", food_left);
242 when CTRL('O') : add_pass();
243 when 'M' : {
244 int tlev, whichlev;
245 prbuf[0] = '\0';
246 msg("Which level? ");
247 if (get_str(prbuf,cw) == NORM) {
248 whichlev = NORMLEV;
249 tlev = atoi(prbuf);
250 if (tlev < 1)
251 level = 1;
252 if (tlev >= 200) {
253 tlev -= 199;
254 whichlev = MAZELEV;
255 }
256 else if (tlev >= 100) {
257 tlev -= 99;
258 whichlev = POSTLEV;
259 }
260 level = tlev;
261 new_level(whichlev);
262 }
263 }
264 when CTRL('N') : {
265 struct linked_list *item;
266
267 item = get_item("charge", STICK);
268 if (item != NULL) {
269 (OBJPTR(item))->o_charges = 10000;
270 msg("");
271 }
272 }
273 when CTRL('H') : {
274 int i;
275 struct linked_list *item;
276 struct object *obj;
277
278 him->s_exp = e_levels[him->s_lvl + 7] + 1;
279 check_level();
280 /*
281 * Give the rogue a very good sword
282 */
283 item = new_thing(FALSE, WEAPON, TWOSWORD);
284 obj = OBJPTR(item);
285 obj->o_hplus = 3;
286 obj->o_dplus = 3;
287 obj->o_flags = ISKNOW;
288 i = add_pack(item, TRUE);
289 if (i)
290 cur_weapon = obj;
291 else
292 discard(item);
293 /*
294 * And his suit of armor
295 */
296 item = new_thing(FALSE, ARMOR, PLATEARMOR);
297 obj = OBJPTR(item);
298 obj->o_ac = -8;
299 obj->o_flags = ISKNOW;
300 i = add_pack(item, TRUE);
301 if (i)
302 cur_armor = obj;
303 else
304 discard(item);
305 nochange = FALSE;
306 }
307 otherwise:
308 msg(illegal, unctrl(ch));
309 count = 0;
310 }
311 else {
312 msg(illegal, unctrl(ch));
313 count = 0;
314 }
315 }
316 /*
317 * turn off flags if no longer needed
318 */
319 if (!running)
320 door_stop = FALSE;
321 }
322 /*
323 * If he ran into something to take, let the
324 * hero pick it up if not in a trading post.
325 */
326 if (take != 0 && levtype != POSTLEV)
327 pick_up(take);
328 if (!running)
329 door_stop = FALSE;
330 }
331 /*
332 * Kick off the rest if the daemons and fuses
333 */
334 if (after) {
335 int j;
336
337 look(FALSE);
338 do_daemons(AFTER);
339 do_fuses();
340 if (pl_on(ISSLOW))
341 waste_time();
342 for (j = LEFT; j <= RIGHT; j++) {
343 if (cur_ring[j] != NULL) {
344 if (cur_ring[j]->o_which == R_SEARCH)
345 search();
346 else if (cur_ring[j]->o_which == R_TELEPORT)
347 if (rnd(100) < 5)
348 teleport(rndspot, &player);
349 }
350 }
351 }
352 }
353
354
355 /*
356 * quit:
357 * Have player make certain, then exit.
358 */
359 void
360 quit(int a)
361 {
362 reg char ch, good;
363 /*
364 * Reset the signal in case we got here via an interrupt
365 */
366 if (signal(SIGINT, quit) != quit)
367 mpos = 0;
368 msg("Really quit? [y/n/s]");
369 /* ch = tolower(readchar());*/
370 ch = readchar();
371 if (ch == 'y') {
372 clear();
373 move(LINES-1, 0);
374 refresh();
375 score(purse, CHICKEN, 0);
376 byebye(0);
377 }
378 else if (ch == 's') {
379 good = save_game();
380 if (good) {
381 wclear(cw);
382 draw(cw);
383 endwin();
384 byebye(0);
385 }
386 }
387 else {
388 signal(SIGINT, quit);
389 wmove(cw, 0, 0);
390 wclrtoeol(cw);
391 draw(cw);
392 mpos = 0;
393 count = 0;
394 nochange = FALSE;
395 }
396 }
397
398 /*
399 * search:
400 * Player gropes about him to find hidden things.
401 */
402
403 search()
404 {
405 reg int x, y;
406 reg char ch;
407
408 /*
409 * Look all around the hero, if there is something hidden there,
410 * give him a chance to find it. If its found, display it.
411 */
412 if (pl_on(ISBLIND))
413 return;
414 for (x = hero.x - 1; x <= hero.x + 1; x++) {
415 for (y = hero.y - 1; y <= hero.y + 1; y++) {
416 ch = winat(y, x);
417 if (isatrap(ch)) { /* see if its a trap */
418 reg struct trap *tp;
419
420 if ((tp = trap_at(y, x)) == NULL)
421 break;
422 if (tp->tr_flags & ISFOUND)
423 break; /* no message if its seen */
424 if (mvwinch(cw, y, x) == ch)
425 break;
426 if (rnd(100) > (him->s_lvl * 9 + herowis() * 5))
427 break;
428 tp->tr_flags |= ISFOUND;
429 mvwaddch(cw, y, x, tp->tr_type);
430 count = 0;
431 running = FALSE;
432 msg(tr_name(tp->tr_type));
433 }
434 else if(ch == SECRETDOOR) {
435 if (rnd(100) < (him->s_lvl * 4 + herowis() * 5)) {
436 mvaddch(y, x, DOOR);
437 count = 0;
438 }
439 }
440 }
441 }
442 }
443
444 /*
445 * help:
446 * Give single character help, or the whole mess if he wants it
447 */
448 help()
449 {
450 extern struct h_list helpstr[];
451 reg struct h_list *strp;
452 reg char helpch;
453 reg int cnt;
454
455 strp = &helpstr[0];
456 msg("Character you want help for (* for all): ");
457 helpch = readchar();
458 mpos = 0;
459 /*
460 * If its not a *, print the right help string
461 * or an error if he typed a funny character.
462 */
463 if (helpch != '*') {
464 wmove(cw, 0, 0);
465 while (strp->h_ch) {
466 if (strp->h_ch == helpch) {
467 msg("%s%s", unctrl(strp->h_ch), strp->h_desc);
468 break;
469 }
470 strp++;
471 }
472 if (strp->h_ch != helpch)
473 msg("Unknown character '%s'", unctrl(helpch));
474 return;
475 }
476 /*
477 * Here we print help for everything.
478 * Then wait before we return to command mode
479 */
480 wclear(hw);
481 cnt = 0;
482 while (strp->h_ch) {
483 mvwaddstr(hw, cnt % 23, cnt > 22 ? 40 : 0, unctrl(strp->h_ch));
484 waddstr(hw, strp->h_desc);
485 cnt++;
486 strp++;
487 }
488 wmove(hw, LINES-1, 0);
489 wprintw(hw,spacemsg);
490 draw(hw);
491 wait_for(hw,' ');
492 wclear(hw);
493 draw(hw);
494 wmove(cw, 0, 0);
495 wclrtoeol(cw);
496 touchwin(cw);
497 nochange = FALSE;
498 }
499
500
501 /*
502 * identify:
503 * Tell the player what a certain thing is.
504 */
505 char *
506 identify(what)
507 int what;
508 {
509 reg char ch, *str;
510
511 if (what == 0) {
512 msg("What do you want identified? ");
513 ch = readchar();
514 mpos = 0;
515 if (ch == ESCAPE) {
516 msg("");
517 return NULL;
518 }
519 }
520 else
521 ch = what;
522 if (isalpha(ch))
523 str = monsters[midx(ch)].m_name;
524 else {
525 switch(ch) {
526 case '|':
527 case '-': str = "the wall of a room";
528 when GOLD: str = "gold";
529 when STAIRS: str = "passage leading up/down";
530 when DOOR: str = "door";
531 when FLOOR: str = "room floor";
532 when PLAYER: str = "you";
533 when PASSAGE: str = "passage";
534 when POST: str = "trading post";
535 when MAZETRAP: str = "maze trap";
536 when TRAPDOOR: str = "trapdoor";
537 when ARROWTRAP: str = "arrow trap";
538 when SLEEPTRAP: str = "sleeping gas trap";
539 when BEARTRAP: str = "bear trap";
540 when TELTRAP: str = "teleport trap";
541 when DARTTRAP: str = "dart trap";
542 when POOL: str = "magic pool";
543 when POTION: str = "potion";
544 when SCROLL: str = "scroll";
545 when FOOD: str = "food";
546 when WEAPON: str = "weapon";
547 when ' ' : str = "solid rock";
548 when ARMOR: str = "armor";
549 when AMULET: str = "The Amulet of Yendor";
550 when RING: str = "ring";
551 when STICK: str = "wand or staff";
552 otherwise:
553 if (what == 0)
554 str = "unknown character";
555 else
556 str = "a magical ghost";
557 }
558 }
559 if (what == 0)
560 msg("'%s' : %s", unctrl(ch), str);
561 return str;
562 }
563
564 /*
565 * d_level:
566 * He wants to go down a level
567 */
568 d_level()
569 {
570 if (winat(hero.y, hero.x) != STAIRS)
571 msg("I see no way down.");
572 else {
573 if (pl_on(ISHELD)) {
574 msg("You are being held.");
575 return;
576 }
577 level++;
578 new_level(NORMLEV);
579 }
580 }
581
582 /*
583 * u_level:
584 * He wants to go up a level
585 */
586 u_level()
587 {
588 if (winat(hero.y, hero.x) == STAIRS) {
589 if (pl_on(ISHELD)) {
590 msg("You are being held.");
591 return;
592 }
593 else { /* player not held here */
594 if (amulet) {
595 level--;
596 if (level == 0)
597 total_winner();
598 new_level(NORMLEV);
599 msg("You feel a wrenching sensation in your gut.");
600 return;
601 }
602 }
603 }
604 msg("I see no way up.");
605 }
606
607
608 /*
609 * Let him escape for a while
610 */
611 shell()
612 {
613 reg int pid;
614 reg char *sh;
615 int ret_status;
616
617 /*
618 * Set the terminal back to original mode
619 */
620 sh = getenv("SHELL");
621 wclear(hw);
622 wmove(hw, LINES-1, 0);
623 draw(hw);
624 endwin();
625 in_shell = TRUE;
626 fflush(stdout);
627 /*
628 * Fork and do a shell
629 */
630 #ifndef __DJGPP__
631 while((pid = fork()) < 0)
632 sleep(1);
633 if (pid == 0) {
634 setuid(playuid); /* Set back to original user */
635 setgid(playgid);
636 execl(sh == NULL ? "/bin/sh" : sh, "shell", "-i", 0);
637 perror("No shelly");
638 byebye(-1);
639 }
640 else {
641 signal(SIGINT, SIG_IGN);
642 signal(SIGQUIT, SIG_IGN);
643 while (wait(&ret_status) != pid)
644 continue;
645 signal(SIGINT, quit);
646 signal(SIGQUIT, endit);
647
648 #else
649 {
650 char shell[PATH_MAX];
651
652 if (sh && *sh)
653 strncpy(shell,sh,PATH_MAX);
654 else
655 sprintf(shell, "%s\\bin\\sh.exe", getenv("DJDIR"));
656
657 if (spawnl(P_WAIT,shell, "shell", "-i", 0) == -1)
658 msg("No shelly: %s", shell);
659
660 #endif
661 printf("\n%s", retstr);
662 fflush(stdout);
663 noecho();
664 crmode();
665 in_shell = FALSE;
666 wait_for(cw, '\n');
667 restscr(cw);
668 }
669 }
670
671
672 /*
673 * call:
674 * Allow a user to call a potion, scroll, or ring something
675 */
676 call()
677 {
678 reg struct object *obj;
679 reg struct linked_list *item;
680 reg char **guess, *elsewise;
681 int wh;
682
683 if ((item = get_item("call", 0)) == NULL)
684 return;
685 obj = OBJPTR(item);
686 wh = obj->o_which;
687 switch (obj->o_type) {
688 case RING:
689 guess = r_guess;
690 elsewise = (r_guess[wh] != NULL ? r_guess[wh] : r_stones[wh]);
691 when POTION:
692 guess = p_guess;
693 elsewise = (p_guess[wh] != NULL ? p_guess[wh] : p_colors[wh]);
694 when SCROLL:
695 guess = s_guess;
696 elsewise = (s_guess[wh] != NULL ? s_guess[wh] : s_names[wh]);
697 when STICK:
698 guess = ws_guess;
699 elsewise =(ws_guess[wh] != NULL ?
700 ws_guess[wh] : ws_stuff[wh].ws_made);
701 otherwise:
702 msg("You can't call %ss anything",obj->o_typname);
703 return;
704 }
705 msg("Was called \"%s\"", elsewise);
706 msg(callit);
707 if (guess[wh] != NULL)
708 free(guess[wh]);
709 strcpy(prbuf, elsewise);
710 if (get_str(prbuf, cw) == NORM) {
711 guess[wh] = new(strlen(prbuf) + 1);
712 strcpy(guess[wh], prbuf);
713 }
714 }