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