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