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