Mercurial > hg > early-roguelike
comparison rogue4/command.c @ 12:9535a08ddc39
Import Rogue 5.2 from the Roguelike Restoration Project (r1490)
author | edwarj4 |
---|---|
date | Sat, 24 Oct 2009 16:52:52 +0000 |
parents | |
children | 4967c46f1320 |
comparison
equal
deleted
inserted
replaced
11:949d558c2162 | 12:9535a08ddc39 |
---|---|
1 /* | |
2 * Read and execute the user commands | |
3 * | |
4 * @(#)command.c 4.31 (Berkeley) 4/6/82 | |
5 * | |
6 * Rogue: Exploring the Dungeons of Doom | |
7 * Copyright (C) 1980, 1981, 1982 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 <curses.h> | |
15 #include <ctype.h> | |
16 #include <stdlib.h> | |
17 #include <string.h> | |
18 #include "rogue.h" | |
19 | |
20 char countch, direction, newcount = FALSE; | |
21 | |
22 /* | |
23 * command: | |
24 * Process the user commands | |
25 */ | |
26 command() | |
27 { | |
28 register char ch; | |
29 register int ntimes = 1; /* Number of player moves */ | |
30 char *unctrol(); | |
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 /* | |
42 * these are illegal things for the player to be, so if any are | |
43 * set, someone's been poking in memeory | |
44 */ | |
45 if (on(player, ISSLOW|ISCANC|ISGREED|ISINVIS|ISMEAN|ISREGEN)) | |
46 auto_save(-1); | |
47 | |
48 look(TRUE); | |
49 if (!running) | |
50 door_stop = FALSE; | |
51 status(); | |
52 lastscore = purse; | |
53 move(hero.y, hero.x); | |
54 if (!((running || count) && jump)) | |
55 refresh(); /* Draw screen */ | |
56 take = 0; | |
57 after = TRUE; | |
58 /* | |
59 * Read command or continue run | |
60 */ | |
61 #ifdef WIZARD | |
62 if (wizard) | |
63 noscore = TRUE; | |
64 #endif | |
65 if (!no_command) | |
66 { | |
67 if (running) ch = runch; | |
68 else if (count) ch = countch; | |
69 else | |
70 { | |
71 ch = readchar(); | |
72 if (mpos != 0 && !running) /* Erase message if its there */ | |
73 msg(""); | |
74 } | |
75 } | |
76 else | |
77 ch = '.'; | |
78 if (no_command) | |
79 { | |
80 if (--no_command == 0) | |
81 { | |
82 player.t_flags |= ISRUN; | |
83 msg("you can move again"); | |
84 } | |
85 } | |
86 else | |
87 { | |
88 /* | |
89 * check for prefixes | |
90 */ | |
91 if (isdigit(ch)) | |
92 { | |
93 count = 0; | |
94 newcount = TRUE; | |
95 while (isdigit(ch)) | |
96 { | |
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': | |
113 #ifdef WIZARD | |
114 case CTRL('D'): case CTRL('U'): | |
115 #endif | |
116 break; | |
117 default: | |
118 count = 0; | |
119 } | |
120 } | |
121 switch (ch) | |
122 { | |
123 case 'f': | |
124 if (!on(player, ISBLIND)) | |
125 { | |
126 door_stop = TRUE; | |
127 firstmove = TRUE; | |
128 } | |
129 if (count && !newcount) | |
130 ch = direction; | |
131 else | |
132 ch = readchar(); | |
133 switch (ch) | |
134 { | |
135 case 'h': case 'j': case 'k': case 'l': | |
136 case 'y': case 'u': case 'b': case 'n': | |
137 ch = toupper(ch); | |
138 } | |
139 direction = ch; | |
140 } | |
141 newcount = FALSE; | |
142 /* | |
143 * execute a command | |
144 */ | |
145 if (count && !running) | |
146 count--; | |
147 switch (ch) | |
148 { | |
149 case '!' : shell(); | |
150 when 'h' : do_move(0, -1); | |
151 when 'j' : do_move(1, 0); | |
152 when 'k' : do_move(-1, 0); | |
153 when 'l' : do_move(0, 1); | |
154 when 'y' : do_move(-1, -1); | |
155 when 'u' : do_move(-1, 1); | |
156 when 'b' : do_move(1, -1); | |
157 when 'n' : do_move(1, 1); | |
158 when 'H' : do_run('h'); | |
159 when 'J' : do_run('j'); | |
160 when 'K' : do_run('k'); | |
161 when 'L' : do_run('l'); | |
162 when 'Y' : do_run('y'); | |
163 when 'U' : do_run('u'); | |
164 when 'B' : do_run('b'); | |
165 when 'N' : do_run('n'); | |
166 when 't': | |
167 if (!get_dir()) | |
168 after = FALSE; | |
169 else | |
170 missile(delta.y, delta.x); | |
171 when 'Q' : after = FALSE; quit(-1); | |
172 when 'i' : after = FALSE; inventory(pack, 0); | |
173 when 'I' : after = FALSE; picky_inven(); | |
174 when 'd' : drop(); | |
175 when 'q' : quaff(); | |
176 when 'r' : read_scroll(); | |
177 when 'e' : eat(); | |
178 when 'w' : wield(); | |
179 when 'W' : wear(); | |
180 when 'T' : take_off(); | |
181 when 'P' : ring_on(); | |
182 when 'R' : ring_off(); | |
183 when 'o' : option(); after = FALSE; | |
184 when 'c' : call(); after = FALSE; | |
185 when '>' : after = FALSE; d_level(); | |
186 when '<' : after = FALSE; u_level(); | |
187 when '?' : after = FALSE; help(); | |
188 when '/' : after = FALSE; identify(); | |
189 when 's' : search(); | |
190 when 'z': | |
191 if (get_dir()) | |
192 do_zap(); | |
193 else | |
194 after = FALSE; | |
195 when 'D': after = FALSE; discovered(); | |
196 when CTRL('R') : after = FALSE; msg(huh); | |
197 when CTRL('L') : | |
198 after = FALSE; | |
199 clearok(curscr,TRUE); | |
200 wrefresh(curscr); | |
201 when 'v' : | |
202 after = FALSE; | |
203 msg("rogue version %s. (mctesq was here)", release); | |
204 when 'S' : | |
205 after = FALSE; | |
206 if (save_game()) | |
207 { | |
208 move(LINES-1, 0); | |
209 clrtoeol(); | |
210 refresh(); | |
211 endwin(); | |
212 exit(0); | |
213 } | |
214 when '.' : ; /* Rest command */ | |
215 when ' ' : after = FALSE; /* "Legal" illegal command */ | |
216 when '^' : | |
217 after = FALSE; | |
218 if (get_dir()) { | |
219 delta.y += hero.y; | |
220 delta.x += hero.x; | |
221 if (chat(delta.y, delta.x) != TRAP) | |
222 msg("no trap there"); | |
223 else | |
224 msg(tr_name(flat(delta.y, delta.x) & F_TMASK)); | |
225 } | |
226 #ifdef WIZARD | |
227 when CTRL('P') : | |
228 after = FALSE; | |
229 if (wizard) | |
230 { | |
231 wizard = FALSE; | |
232 turn_see(TRUE); | |
233 msg("not wizard any more"); | |
234 } | |
235 else | |
236 { | |
237 if (wizard = passwd()) | |
238 { | |
239 noscore = TRUE; | |
240 turn_see(FALSE); | |
241 msg("you are suddenly as smart as Ken Arnold in dungeon #%d", dnum); | |
242 } | |
243 else | |
244 msg("sorry"); | |
245 } | |
246 #endif | |
247 when ESCAPE : /* Escape */ | |
248 door_stop = FALSE; | |
249 count = 0; | |
250 after = FALSE; | |
251 otherwise : | |
252 after = FALSE; | |
253 #ifdef WIZARD | |
254 if (wizard) switch (ch) | |
255 { | |
256 case '@' : msg("@ %d,%d", hero.y, hero.x); | |
257 when 'C' : create_obj(); | |
258 when CTRL('I') : inventory(lvl_obj, 0); | |
259 when CTRL('W') : whatis(FALSE); | |
260 when CTRL('D') : level++; new_level(); | |
261 when CTRL('U') : if (level > 1) level--; new_level(); | |
262 when CTRL('F') : show_map(); | |
263 when CTRL('T') : teleport(); | |
264 when CTRL('E') : msg("food left: %d", food_left); | |
265 when CTRL('A') : msg("%d things in your pack", inpack); | |
266 when CTRL('K') : add_pass(); | |
267 when CTRL('X') : turn_see(on(player, SEEMONST)); | |
268 when CTRL('N') : | |
269 { | |
270 register THING *item; | |
271 | |
272 if ((item = get_item("charge", STICK)) != NULL) | |
273 item->o_charges = 10000; | |
274 } | |
275 when CTRL('H') : | |
276 { | |
277 register int i; | |
278 register THING *obj; | |
279 | |
280 for (i = 0; i < 9; i++) | |
281 raise_level(); | |
282 /* | |
283 * Give the rogue a sword (+1,+1) | |
284 */ | |
285 obj = new_item(); | |
286 obj->o_type = WEAPON; | |
287 obj->o_which = TWOSWORD; | |
288 init_weapon(obj, SWORD); | |
289 obj->o_hplus = 1; | |
290 obj->o_dplus = 1; | |
291 obj->o_count = 1; | |
292 obj->o_group = 0; | |
293 add_pack(obj, TRUE); | |
294 cur_weapon = obj; | |
295 /* | |
296 * And his suit of armor | |
297 */ | |
298 obj = new_item(); | |
299 obj->o_type = ARMOR; | |
300 obj->o_which = PLATE_MAIL; | |
301 obj->o_ac = -5; | |
302 obj->o_flags |= ISKNOW; | |
303 obj->o_count = 1; | |
304 obj->o_group = 0; | |
305 cur_armor = obj; | |
306 add_pack(obj, TRUE); | |
307 } | |
308 otherwise : | |
309 illcom(ch); | |
310 } | |
311 else | |
312 #endif | |
313 illcom(ch); | |
314 } | |
315 /* | |
316 * turn off flags if no longer needed | |
317 */ | |
318 if (!running) | |
319 door_stop = FALSE; | |
320 } | |
321 /* | |
322 * If he ran into something to take, let him pick it up. | |
323 */ | |
324 if (take != 0) | |
325 pick_up(take); | |
326 if (!running) | |
327 door_stop = FALSE; | |
328 if (!after) | |
329 ntimes++; | |
330 } | |
331 do_daemons(AFTER); | |
332 do_fuses(AFTER); | |
333 if (ISRING(LEFT, R_SEARCH)) | |
334 search(); | |
335 else if (ISRING(LEFT, R_TELEPORT) && rnd(50) == 0) | |
336 teleport(); | |
337 if (ISRING(RIGHT, R_SEARCH)) | |
338 search(); | |
339 else if (ISRING(RIGHT, R_TELEPORT) && rnd(50) == 0) | |
340 teleport(); | |
341 } | |
342 | |
343 /* | |
344 * illcom: | |
345 * What to do with an illegal command | |
346 */ | |
347 illcom(ch) | |
348 char ch; | |
349 { | |
350 save_msg = FALSE; | |
351 count = 0; | |
352 msg("illegal command '%s'", unctrol(ch)); | |
353 save_msg = TRUE; | |
354 } | |
355 | |
356 /* | |
357 * search: | |
358 * Player gropes about him to find hidden things. | |
359 */ | |
360 search() | |
361 { | |
362 register int y, x; | |
363 register char *fp; | |
364 register int ey, ex; | |
365 | |
366 if (on(player, ISBLIND)) | |
367 return; | |
368 ey = hero.y + 1; | |
369 ex = hero.x + 1; | |
370 for (y = hero.y - 1; y <= ey; y++) | |
371 for (x = hero.x - 1; x <= ex; x++) | |
372 { | |
373 if (y == hero.y && x == hero.x) | |
374 continue; | |
375 fp = &flat(y, x); | |
376 if (!(*fp & F_REAL)) | |
377 switch (chat(y, x)) | |
378 { | |
379 case '|': | |
380 case '-': | |
381 if (rnd(5) != 0) | |
382 break; | |
383 chat(y, x) = DOOR; | |
384 *fp |= F_REAL; | |
385 count = running = FALSE; | |
386 break; | |
387 case FLOOR: | |
388 if (rnd(2) != 0) | |
389 break; | |
390 chat(y, x) = TRAP; | |
391 *fp |= F_REAL; | |
392 count = running = FALSE; | |
393 msg("%s%s", terse ? "" : "you found ", tr_name(*fp & F_TMASK)); | |
394 break; | |
395 } | |
396 } | |
397 } | |
398 | |
399 /* | |
400 * help: | |
401 * Give single character help, or the whole mess if he wants it | |
402 */ | |
403 help() | |
404 { | |
405 register const struct h_list *strp = helpstr; | |
406 register char helpch; | |
407 register int cnt; | |
408 | |
409 msg("character you want help for (* for all): "); | |
410 helpch = readchar(); | |
411 mpos = 0; | |
412 /* | |
413 * If its not a *, print the right help string | |
414 * or an error if he typed a funny character. | |
415 */ | |
416 if (helpch != '*') | |
417 { | |
418 move(0, 0); | |
419 while (strp->h_ch) | |
420 { | |
421 if (strp->h_ch == helpch) | |
422 { | |
423 msg("%s%s", unctrol(strp->h_ch), strp->h_desc); | |
424 break; | |
425 } | |
426 strp++; | |
427 } | |
428 if (strp->h_ch != helpch) | |
429 msg("unknown character '%s'", unctrol(helpch)); | |
430 return; | |
431 } | |
432 /* | |
433 * Here we print help for everything. | |
434 * Then wait before we return to command mode | |
435 */ | |
436 wclear(hw); | |
437 cnt = 0; | |
438 while (strp->h_ch) | |
439 { | |
440 mvwaddstr(hw, cnt % 23, cnt > 22 ? 40 : 0, unctrol(strp->h_ch)); | |
441 waddstr(hw, strp->h_desc); | |
442 cnt++; | |
443 strp++; | |
444 } | |
445 wmove(hw, LINES-1, 0); | |
446 wprintw(hw, "--Press space to continue--"); | |
447 wrefresh(hw); | |
448 w_wait_for(hw,' '); | |
449 wmove(stdscr, 0, 0); | |
450 wclrtoeol(stdscr); | |
451 touchwin(stdscr); | |
452 clearok(stdscr, TRUE); | |
453 refresh(); | |
454 } | |
455 | |
456 /* | |
457 * identify: | |
458 * Tell the player what a certain thing is. | |
459 */ | |
460 identify() | |
461 { | |
462 register char ch; | |
463 register const char *str; | |
464 | |
465 msg("what do you want identified? "); | |
466 ch = readchar(); | |
467 mpos = 0; | |
468 if (ch == ESCAPE) | |
469 { | |
470 msg(""); | |
471 return; | |
472 } | |
473 if (isupper(ch)) | |
474 str = monsters[ch-'A'].m_name; | |
475 else switch (ch) | |
476 { | |
477 case '|': | |
478 case '-': | |
479 str = "wall of a room"; | |
480 when GOLD: str = "gold"; | |
481 when STAIRS : str = "a staircase"; | |
482 when DOOR: str = "door"; | |
483 when FLOOR: str = "room floor"; | |
484 when PLAYER: str = "you"; | |
485 when PASSAGE: str = "passage"; | |
486 when TRAP: str = "trap"; | |
487 when POTION: str = "potion"; | |
488 when SCROLL: str = "scroll"; | |
489 when FOOD: str = "food"; | |
490 when WEAPON: str = "weapon"; | |
491 when ' ' : str = "solid rock"; | |
492 when ARMOR: str = "armor"; | |
493 when AMULET: str = "the Amulet of Yendor"; | |
494 when RING: str = "ring"; | |
495 when STICK: str = "wand or staff"; | |
496 otherwise: str = "unknown character"; | |
497 } | |
498 msg("'%s': %s", unctrol(ch), str); | |
499 } | |
500 | |
501 /* | |
502 * d_level: | |
503 * He wants to go down a level | |
504 */ | |
505 d_level() | |
506 { | |
507 if (chat(hero.y, hero.x) != STAIRS) | |
508 msg("I see no way down"); | |
509 else | |
510 { | |
511 level++; | |
512 new_level(); | |
513 } | |
514 } | |
515 | |
516 /* | |
517 * u_level: | |
518 * He wants to go up a level | |
519 */ | |
520 u_level() | |
521 { | |
522 if (chat(hero.y, hero.x) == STAIRS) | |
523 if (amulet) | |
524 { | |
525 level--; | |
526 if (level == 0) | |
527 total_winner(); | |
528 new_level(); | |
529 msg("you feel a wrenching sensation in your gut"); | |
530 } | |
531 else | |
532 msg("your way is magically blocked"); | |
533 else | |
534 msg("I see no way up"); | |
535 } | |
536 | |
537 /* | |
538 * call: | |
539 * Allow a user to call a potion, scroll, or ring something | |
540 */ | |
541 call() | |
542 { | |
543 register THING *obj; | |
544 register char **guess; | |
545 const char *elsewise; | |
546 register bool *know; | |
547 | |
548 obj = get_item("call", CALLABLE); | |
549 /* | |
550 * Make certain that it is somethings that we want to wear | |
551 */ | |
552 if (obj == NULL) | |
553 return; | |
554 switch (obj->o_type) | |
555 { | |
556 case RING: | |
557 guess = r_guess; | |
558 know = r_know; | |
559 elsewise = (r_guess[obj->o_which] != NULL ? | |
560 r_guess[obj->o_which] : r_stones[obj->o_which]); | |
561 when POTION: | |
562 guess = p_guess; | |
563 know = p_know; | |
564 elsewise = (p_guess[obj->o_which] != NULL ? | |
565 p_guess[obj->o_which] : p_colors[obj->o_which]); | |
566 when SCROLL: | |
567 guess = s_guess; | |
568 know = s_know; | |
569 elsewise = (s_guess[obj->o_which] != NULL ? | |
570 s_guess[obj->o_which] : s_names[obj->o_which]); | |
571 when STICK: | |
572 guess = ws_guess; | |
573 know = ws_know; | |
574 elsewise = (ws_guess[obj->o_which] != NULL ? | |
575 ws_guess[obj->o_which] : ws_made[obj->o_which]); | |
576 otherwise: | |
577 msg("you can't call that anything"); | |
578 return; | |
579 } | |
580 if (know[obj->o_which]) | |
581 { | |
582 msg("that has already been identified"); | |
583 return; | |
584 } | |
585 if (!terse) | |
586 addmsg("Was "); | |
587 msg("called \"%s\"", elsewise); | |
588 if (terse) | |
589 msg("call it: "); | |
590 else | |
591 msg("what do you want to call it? "); | |
592 if (guess[obj->o_which] != NULL) | |
593 free(guess[obj->o_which]); | |
594 strcpy(prbuf, elsewise); | |
595 if (get_str(prbuf, stdscr) == NORM) | |
596 { | |
597 guess[obj->o_which] = malloc((unsigned int) strlen(prbuf) + 1); | |
598 strcpy(guess[obj->o_which], prbuf); | |
599 } | |
600 } |