Mercurial > hg > early-roguelike
comparison arogue7/command.c @ 125:adfa37e67084
Import Advanced Rogue 7.7 from the Roguelike Restoration Project (r1490)
author | John "Elwin" Edwards |
---|---|
date | Fri, 08 May 2015 15:24:40 -0400 |
parents | |
children | b786053d2f37 |
comparison
equal
deleted
inserted
replaced
124:d10fc4a065ac | 125:adfa37e67084 |
---|---|
1 /* | |
2 * command.c - Read and execute the user commands | |
3 * | |
4 * Advanced Rogue | |
5 * Copyright (C) 1984, 1985, 1986 Michael Morgan, Ken Dalka and AT&T | |
6 * All rights reserved. | |
7 * | |
8 * Based on "Rogue: Exploring the Dungeons of Doom" | |
9 * Copyright (C) 1980, 1981 Michael Toy, Ken Arnold and Glenn Wichman | |
10 * All rights reserved. | |
11 * | |
12 * See the file LICENSE.TXT for full copyright and licensing information. | |
13 */ | |
14 | |
15 /* | |
16 * Read and execute the user commands | |
17 * | |
18 */ | |
19 | |
20 #include "curses.h" | |
21 #include <ctype.h> | |
22 #include <signal.h> | |
23 #include "mach_dep.h" | |
24 #include "rogue.h" | |
25 #ifdef PC7300 | |
26 #include "sys/window.h" | |
27 extern struct uwdata wdata; | |
28 #endif | |
29 | |
30 /* | |
31 * command: | |
32 * Process the user commands | |
33 */ | |
34 | |
35 command() | |
36 { | |
37 unsigned char ch; | |
38 struct linked_list *item; | |
39 unsigned char countch, direction, newcount = FALSE; | |
40 int segment = 1; | |
41 int monst_limit, monst_current; | |
42 | |
43 monst_limit = monst_current = 1; | |
44 while (playing) { | |
45 /* | |
46 * Let the daemons start up, but only do them once a round | |
47 * (round = 10 segments). | |
48 */ | |
49 if (segment >= 10) { | |
50 do_daemons(BEFORE); | |
51 do_fuses(BEFORE); | |
52 } | |
53 | |
54 after = TRUE; | |
55 do { | |
56 /* One more tick of the clock. */ | |
57 if (segment >= 10 && after && (++turns % DAYLENGTH) == 0) { | |
58 daytime ^= TRUE; | |
59 if (levtype == OUTSIDE) { | |
60 if (daytime) msg("The sun rises above the horizon"); | |
61 else msg("The sun sinks below the horizon"); | |
62 } | |
63 light(&hero); | |
64 } | |
65 | |
66 /* | |
67 * Don't bother with these updates unless the player's going | |
68 * to do something. | |
69 */ | |
70 if (player.t_action == A_NIL && player.t_no_move <= 1) { | |
71 look(after, FALSE); | |
72 lastscore = purse; | |
73 wmove(cw, hero.y, hero.x); | |
74 if (!((running || count) && jump)) { | |
75 status(FALSE); | |
76 } | |
77 } | |
78 | |
79 /* Draw the screen */ | |
80 if (!((running || count) && jump)) { | |
81 wmove(cw, hero.y, hero.x); | |
82 draw(cw); | |
83 } | |
84 | |
85 after = TRUE; | |
86 | |
87 /* | |
88 * Read command or continue run | |
89 */ | |
90 if (--player.t_no_move <= 0) { | |
91 take = 0; /* Nothing here to start with */ | |
92 player.t_no_move = 0; /* Be sure we don't go too negative */ | |
93 if (!running) door_stop = FALSE; | |
94 | |
95 /* Was the player being held? */ | |
96 if (player.t_action == A_FREEZE) { | |
97 player.t_action = A_NIL; | |
98 msg("You can move again."); | |
99 } | |
100 | |
101 if (player.t_action != A_NIL) ch = (char) player.t_action; | |
102 else if (running) { | |
103 char scratch; | |
104 | |
105 /* If in a corridor or maze, if we are at a turn with | |
106 * only one way to go, turn that way. | |
107 */ | |
108 scratch = CCHAR( winat(hero.y, hero.x) ); | |
109 if ((scratch==PASSAGE||scratch==DOOR||levtype==MAZELEV) && | |
110 off(player, ISHUH) && | |
111 off(player, ISBLIND)) { | |
112 int y, x; | |
113 if (getdelta(runch, &y, &x) == TRUE) { | |
114 corr_move(y, x); | |
115 } | |
116 } | |
117 ch = runch; | |
118 } | |
119 else if (count) ch = countch; | |
120 else { | |
121 ch = readchar(); | |
122 if (mpos != 0 && !running) /* Erase message if its there */ | |
123 msg(""); | |
124 } | |
125 | |
126 /* | |
127 * check for prefixes | |
128 */ | |
129 if (isdigit(ch)) | |
130 { | |
131 count = 0; | |
132 newcount = TRUE; | |
133 while (isdigit(ch)) | |
134 { | |
135 count = count * 10 + (ch - '0'); | |
136 if (count > 255) | |
137 count = 255; | |
138 ch = readchar(); | |
139 } | |
140 countch = ch; | |
141 /* | |
142 * turn off count for commands which don't make sense | |
143 * to repeat | |
144 */ | |
145 switch (ch) { | |
146 case 'h': case 'j': case 'k': case 'l': | |
147 case 'y': case 'u': case 'b': case 'n': | |
148 case 'H': case 'J': case 'K': case 'L': | |
149 case 'Y': case 'U': case 'B': case 'N': | |
150 case C_SEARCH: case '.': | |
151 break; | |
152 default: | |
153 count = 0; | |
154 } | |
155 } | |
156 | |
157 /* Save current direction */ | |
158 if (!running) { /* If running, it is already saved */ | |
159 switch (ch) { | |
160 case 'h': case 'j': case 'k': case 'l': | |
161 case 'y': case 'u': case 'b': case 'n': | |
162 case 'H': case 'J': case 'K': case 'L': | |
163 case 'Y': case 'U': case 'B': case 'N': | |
164 runch = tolower(ch); | |
165 } | |
166 } | |
167 | |
168 /* Perform the action */ | |
169 switch (ch) { | |
170 case 'f': | |
171 if (!on(player, ISBLIND)) | |
172 { | |
173 door_stop = TRUE; | |
174 firstmove = TRUE; | |
175 } | |
176 if (count && !newcount) | |
177 ch = direction; | |
178 else | |
179 ch = readchar(); | |
180 switch (ch) | |
181 { | |
182 case 'h': case 'j': case 'k': case 'l': | |
183 case 'y': case 'u': case 'b': case 'n': | |
184 ch = toupper(ch); | |
185 } | |
186 direction = ch; | |
187 } | |
188 newcount = FALSE; | |
189 | |
190 /* | |
191 * execute a command | |
192 */ | |
193 if (count && !running) | |
194 count--; | |
195 switch (ch) { | |
196 case '!' : shell(); | |
197 when 'h' : do_move(0, -1); | |
198 when 'j' : do_move(1, 0); | |
199 when 'k' : do_move(-1, 0); | |
200 when 'l' : do_move(0, 1); | |
201 when 'y' : do_move(-1, -1); | |
202 when 'u' : do_move(-1, 1); | |
203 when 'b' : do_move(1, -1); | |
204 when 'n' : do_move(1, 1); | |
205 when 'H' : do_run('h'); | |
206 when 'J' : do_run('j'); | |
207 when 'K' : do_run('k'); | |
208 when 'L' : do_run('l'); | |
209 when 'Y' : do_run('y'); | |
210 when 'U' : do_run('u'); | |
211 when 'B' : do_run('b'); | |
212 when 'N' : do_run('n'); | |
213 when A_PICKUP: | |
214 player.t_action = A_NIL; | |
215 if (add_pack(NULL, FALSE, NULL)) { | |
216 char tch; | |
217 | |
218 tch = CCHAR( mvwinch(stdscr, hero.y, hero.x) ); | |
219 if (tch != FLOOR && tch != PASSAGE) { | |
220 player.t_action = A_PICKUP; /*get more */ | |
221 player.t_no_move += 2 * movement(&player); | |
222 } | |
223 } | |
224 when A_ATTACK: | |
225 /* Is our attackee still there? */ | |
226 if (isalpha(winat(player.t_newpos.y, | |
227 player.t_newpos.x))) { | |
228 /* Our friend is still here */ | |
229 player.t_action = A_NIL; | |
230 fight(&player.t_newpos, cur_weapon, FALSE); | |
231 } | |
232 else { /* Our monster has moved */ | |
233 player.t_action = A_NIL; | |
234 } | |
235 when A_THROW: | |
236 if (player.t_action == A_NIL) { | |
237 item = get_item(pack, "throw", ALL, FALSE, FALSE); | |
238 if (item != NULL && get_dir(&player.t_newpos)) { | |
239 player.t_action = A_THROW; | |
240 player.t_using = item; | |
241 player.t_no_move = 2 * movement(&player); | |
242 } | |
243 else | |
244 after = FALSE; | |
245 } | |
246 else { | |
247 missile(player.t_newpos.y, player.t_newpos.x, | |
248 player.t_using, &player); | |
249 player.t_action = A_NIL; | |
250 player.t_using = 0; | |
251 } | |
252 when 'Q' : after = FALSE; quit(0); | |
253 when 'i' : after = FALSE; inventory(pack, ALL); | |
254 when 'I' : after = FALSE; picky_inven(); | |
255 when C_DROP : player.t_action = C_DROP; drop(NULL); | |
256 when 'P' : | |
257 if (levtype != POSTLEV) { | |
258 /* We charge 2 movement units per item */ | |
259 player.t_no_move = | |
260 2 * grab(hero.y, hero.x) * movement(&player); | |
261 } | |
262 else { | |
263 /* Let's quote the wise guy a price */ | |
264 buy_it(); | |
265 after = FALSE; | |
266 } | |
267 when C_COUNT : count_gold(); | |
268 when C_QUAFF : quaff(-1, NULL, NULL, TRUE); | |
269 when C_READ : read_scroll(-1, NULL, TRUE); | |
270 when C_EAT : eat(); | |
271 when C_WIELD : wield(); | |
272 when C_WEAR : wear(); | |
273 when C_TAKEOFF : take_off(); | |
274 when 'o' : option(); | |
275 when CTRL('N') : nameit(); | |
276 when '=' : after = FALSE; display(); | |
277 when 'm' : nameitem(NULL, TRUE); | |
278 when '>' : after = FALSE; d_level(); | |
279 when '<' : after = FALSE; u_level(); | |
280 when '?' : after = FALSE; help(); | |
281 when '/' : after = FALSE; identify(NULL); | |
282 when C_USE : use_mm(-1); | |
283 when CTRL('T') : | |
284 if (player.t_action == A_NIL) { | |
285 if (get_dir(&player.t_newpos)) { | |
286 player.t_action = CTRL('T'); | |
287 player.t_no_move = 2 * movement(&player); | |
288 } | |
289 else | |
290 after = FALSE; | |
291 } | |
292 else { | |
293 steal(); | |
294 player.t_action = A_NIL; | |
295 } | |
296 when C_DIP : dip_it(); | |
297 when 'G' : | |
298 if (player.t_action == A_NIL) { | |
299 player.t_action = 'G'; | |
300 player.t_no_move = movement(&player); | |
301 } | |
302 else { | |
303 gsense(); | |
304 player.t_action = A_NIL; | |
305 } | |
306 when C_SETTRAP : set_trap(&player, hero.y, hero.x); | |
307 when C_SEARCH : | |
308 if (player.t_action == A_NIL) { | |
309 player.t_action = C_SEARCH; | |
310 player.t_no_move = 5 * movement(&player); | |
311 } | |
312 else { | |
313 search(FALSE, FALSE); | |
314 player.t_action = A_NIL; | |
315 } | |
316 when C_ZAP : if (!player_zap(NULL, FALSE)) | |
317 after=FALSE; | |
318 when C_PRAY : pray(); | |
319 when C_CHANT : chant(); | |
320 when C_CAST : cast(); | |
321 when 'a' : | |
322 if (player.t_action == A_NIL) { | |
323 if (get_dir(&player.t_newpos)) { | |
324 player.t_action = 'a'; | |
325 player.t_no_move = 2 * movement(&player); | |
326 } | |
327 else | |
328 after = FALSE; | |
329 } | |
330 else { | |
331 affect(); | |
332 player.t_action = A_NIL; | |
333 } | |
334 when 'v' : after = FALSE; | |
335 msg("Advanced Rogue Version %s.", | |
336 release); | |
337 when CTRL('L') : after = FALSE; clearok(curscr, TRUE); | |
338 touchwin(cw); /* MMMMMMMMMM */ | |
339 when CTRL('R') : after = FALSE; msg(huh); | |
340 when 'S' : | |
341 after = FALSE; | |
342 if (save_game()) | |
343 { | |
344 wclear(cw); | |
345 draw(cw); | |
346 endwin(); | |
347 #ifdef PC7300 | |
348 endhardwin(); | |
349 #endif | |
350 exit(0); | |
351 } | |
352 when '.' : | |
353 player.t_no_move = movement(&player); /* Rest */ | |
354 player.t_action = A_NIL; | |
355 when ' ' : after = FALSE; /* Do Nothing */ | |
356 #ifdef WIZARD | |
357 when CTRL('P') : | |
358 after = FALSE; | |
359 if (wizard) | |
360 { | |
361 wizard = FALSE; | |
362 trader = 0; | |
363 msg("Not wizard any more"); | |
364 } | |
365 else | |
366 { | |
367 if (waswizard || passwd()) | |
368 { | |
369 msg("Welcome, oh mighty wizard."); | |
370 wizard = waswizard = TRUE; | |
371 } | |
372 else | |
373 msg("Sorry"); | |
374 } | |
375 #endif | |
376 when ESCAPE : /* Escape */ | |
377 door_stop = FALSE; | |
378 count = 0; | |
379 after = FALSE; | |
380 when '#': | |
381 if (levtype == POSTLEV) /* buy something */ | |
382 buy_it(); | |
383 after = FALSE; | |
384 when '$': | |
385 if (levtype == POSTLEV) /* price something */ | |
386 price_it(); | |
387 after = FALSE; | |
388 when '%': | |
389 if (levtype == POSTLEV) /* sell something */ | |
390 sell_it(); | |
391 after = FALSE; | |
392 otherwise : | |
393 after = FALSE; | |
394 #ifdef WIZARD | |
395 if (wizard) switch (ch) | |
396 { | |
397 case 'M' : create_obj(TRUE, 0, 0); | |
398 when CTRL('W') : wanderer(); | |
399 when CTRL('I') : inventory(lvl_obj, ALL); | |
400 when CTRL('Z') : whatis(NULL); | |
401 when CTRL('D') : level++; new_level(NORMLEV); | |
402 when CTRL('F') : overlay(stdscr,cw); | |
403 when CTRL('X') : overlay(mw,cw); | |
404 when CTRL('J') : teleport(); | |
405 when CTRL('E') : msg("food left: %d\tfood level: %d", | |
406 food_left, foodlev); | |
407 when CTRL('A') : activity(); | |
408 when CTRL('C') : | |
409 { | |
410 int tlev; | |
411 prbuf[0] = 0; | |
412 msg("Which level? "); | |
413 if(get_str(prbuf,msgw) == NORM) { | |
414 tlev = atoi(prbuf); | |
415 if(tlev < 1) { | |
416 mpos = 0; | |
417 msg("Illegal level."); | |
418 } | |
419 else if (tlev > 199) { | |
420 levtype = MAZELEV; | |
421 level = tlev - 200 + 1; | |
422 } | |
423 else if (tlev > 99) { | |
424 levtype = POSTLEV; | |
425 level = tlev - 100 + 1; | |
426 } | |
427 else { | |
428 levtype = NORMLEV; | |
429 level = tlev; | |
430 } | |
431 new_level(levtype); | |
432 } | |
433 } | |
434 when CTRL('G') : | |
435 { | |
436 item=get_item(pack,"charge",STICK,FALSE,FALSE); | |
437 if (item != NULL) { | |
438 (OBJPTR(item))->o_charges=10000; | |
439 } | |
440 } | |
441 when CTRL('H') : | |
442 { | |
443 register int i; | |
444 register struct object *obj; | |
445 | |
446 for (i = 0; i < 9; i++) | |
447 raise_level(); | |
448 /* | |
449 * Give the rogue a sword | |
450 */ | |
451 if (cur_weapon==NULL || cur_weapon->o_type != | |
452 RELIC) { | |
453 item = spec_item(WEAPON, TWOSWORD, 5, 5); | |
454 add_pack(item, TRUE, NULL); | |
455 cur_weapon = OBJPTR(item); | |
456 (OBJPTR(item))->o_flags |= (ISKNOW|ISPROT); | |
457 } | |
458 /* | |
459 * And his suit of armor | |
460 */ | |
461 if (player.t_ctype != C_MONK) { | |
462 item = spec_item(ARMOR, PLATE_ARMOR, 10, 0); | |
463 obj = OBJPTR(item); | |
464 if (player.t_ctype == C_THIEF) | |
465 obj->o_which = STUDDED_LEATHER; | |
466 obj->o_flags |= (ISKNOW | ISPROT); | |
467 obj->o_weight = armors[PLATE_ARMOR].a_wght; | |
468 cur_armor = obj; | |
469 add_pack(item, TRUE, NULL); | |
470 } | |
471 purse += 20000; | |
472 } | |
473 otherwise : | |
474 msg("Illegal command '%s'.", unctrl(ch)); | |
475 count = 0; | |
476 } | |
477 else | |
478 #endif | |
479 { | |
480 msg("Illegal command '%s'.", unctrl(ch)); | |
481 count = 0; | |
482 after = FALSE; | |
483 } | |
484 } | |
485 | |
486 /* | |
487 * If he ran into something to take, let him pick it up. | |
488 * unless it's a trading post | |
489 */ | |
490 if (auto_pickup && take != 0 && levtype != POSTLEV) { | |
491 /* get ready to pick it up */ | |
492 player.t_action = A_PICKUP; | |
493 player.t_no_move += 2 * movement(&player); | |
494 } | |
495 } | |
496 | |
497 /* If he was fighting, let's stop (for now) */ | |
498 if (player.t_quiet < 0) player.t_quiet = 0; | |
499 | |
500 if (!running) | |
501 door_stop = FALSE; | |
502 | |
503 if (after && segment >= 10) { | |
504 /* | |
505 * Kick off the rest if the daemons and fuses | |
506 */ | |
507 | |
508 /* | |
509 * If player is infested, take off a hit point | |
510 */ | |
511 if (on(player, HASINFEST)) { | |
512 if ((pstats.s_hpt -= infest_dam) <= 0) death(D_INFESTATION); | |
513 } | |
514 | |
515 /* | |
516 * The eye of Vecna is a constant drain on the player | |
517 */ | |
518 if (cur_relic[EYE_VECNA]) { | |
519 if ((--pstats.s_hpt) <= 0) death(D_RELIC); | |
520 } | |
521 | |
522 /* | |
523 * if player has body rot then take off five hits | |
524 */ | |
525 if (on(player, DOROT)) { | |
526 if ((pstats.s_hpt -= 5) <= 0) death(D_ROT); | |
527 } | |
528 do_daemons(AFTER); | |
529 do_fuses(AFTER); | |
530 } | |
531 } while (after == FALSE); | |
532 | |
533 /* Make the monsters go */ | |
534 if (--monst_current <= 0) | |
535 monst_current = monst_limit = runners(monst_limit); | |
536 | |
537 #ifdef NEEDLOOK | |
538 /* Shall we take a look? */ | |
539 if (player.t_no_move <= 1 && | |
540 !((running || count) && jump)) | |
541 look(FALSE, FALSE); | |
542 #endif | |
543 | |
544 if (++segment > 10) segment = 1; | |
545 t_free_list(monst_dead); | |
546 } | |
547 } | |
548 | |
549 /* | |
550 * display | |
551 * tell the player what is at a certain coordinates assuming | |
552 * it can be seen. | |
553 */ | |
554 display() | |
555 { | |
556 coord c; | |
557 struct linked_list *item; | |
558 struct thing *tp; | |
559 int what; | |
560 | |
561 msg("What do you want to display (* for help)?"); | |
562 c = get_coordinates(); | |
563 mpos = 0; | |
564 if (!cansee(c.y, c.x)) { | |
565 msg("You can't see what is there."); | |
566 return; | |
567 } | |
568 what = mvwinch(cw, c.y, c.x); | |
569 if (isalpha(what)) { | |
570 item = find_mons(c.y, c.x); | |
571 tp = THINGPTR(item); | |
572 msg("%s", monster_name(tp)); | |
573 return; | |
574 } | |
575 if ((item = find_obj(c.y, c.x)) != NULL) { | |
576 msg("%s", inv_name(OBJPTR(item), FALSE)); | |
577 return; | |
578 } | |
579 identify(what); | |
580 } | |
581 | |
582 /* | |
583 * quit: | |
584 * Have player make certain, then exit. | |
585 */ | |
586 | |
587 void | |
588 quit(sig) | |
589 int sig; | |
590 { | |
591 /* | |
592 * Reset the signal in case we got here via an interrupt | |
593 */ | |
594 if (signal(SIGINT, quit) != quit) | |
595 mpos = 0; | |
596 msg("Really quit? <yes or no> "); | |
597 draw(cw); | |
598 prbuf[0] = '\0'; | |
599 if ((get_str(prbuf, msgw) == NORM) && strcmp(prbuf, "yes") == 0) { | |
600 clear(); | |
601 move(lines-1, 0); | |
602 draw(stdscr); | |
603 score(pstats.s_exp + (long) purse, CHICKEN, 0); | |
604 #ifdef PC7300 | |
605 endhardwin(); | |
606 #endif | |
607 exit(0); | |
608 } | |
609 else | |
610 { | |
611 signal(SIGINT, quit); | |
612 wmove(cw, 0, 0); | |
613 wclrtoeol(cw); | |
614 status(FALSE); | |
615 draw(cw); | |
616 mpos = 0; | |
617 count = 0; | |
618 running = FALSE; | |
619 } | |
620 } | |
621 | |
622 /* | |
623 * bugkill: | |
624 * killed by a program bug instead of voluntarily. | |
625 */ | |
626 | |
627 void | |
628 bugkill(sig) | |
629 int sig; | |
630 { | |
631 signal(sig, quit); /* If we get it again, give up */ | |
632 death(D_SIGNAL); /* Killed by a bug */ | |
633 } | |
634 | |
635 | |
636 /* | |
637 * search: | |
638 * Player gropes about him to find hidden things. | |
639 */ | |
640 | |
641 search(is_thief, door_chime) | |
642 register bool is_thief, door_chime; | |
643 { | |
644 register int x, y; | |
645 register char ch, /* The trap or door character */ | |
646 sch, /* Trap or door character (as seen on screen) */ | |
647 mch; /* Monster, if a monster is on the trap or door */ | |
648 register struct linked_list *item; | |
649 register struct thing *mp; /* Status on surrounding monster */ | |
650 | |
651 /* | |
652 * Look all around the hero, if there is something hidden there, | |
653 * give him a chance to find it. If its found, display it. | |
654 */ | |
655 if (on(player, ISBLIND)) | |
656 return; | |
657 for (x = hero.x - 1; x <= hero.x + 1; x++) | |
658 for (y = hero.y - 1; y <= hero.y + 1; y++) | |
659 { | |
660 if (y==hero.y && x==hero.x) | |
661 continue; | |
662 | |
663 /* Mch and ch will be the same unless there is a monster here */ | |
664 mch = CCHAR( winat(y, x) ); | |
665 ch = CCHAR( mvwinch(stdscr, y, x) ); | |
666 sch = CCHAR( mvwinch(cw, y, x) ); /* What's on the screen */ | |
667 | |
668 if (door_chime == FALSE && isatrap(ch)) { | |
669 register struct trap *tp; | |
670 | |
671 /* Is there a monster on the trap? */ | |
672 if (mch != ch && (item = find_mons(y, x)) != NULL) { | |
673 mp = THINGPTR(item); | |
674 if (sch == mch) sch = mp->t_oldch; | |
675 } | |
676 else mp = NULL; | |
677 | |
678 /* | |
679 * is this one found already? | |
680 */ | |
681 if (isatrap(sch)) | |
682 continue; /* give him chance for other traps */ | |
683 tp = trap_at(y, x); | |
684 /* | |
685 * if the thief set it then don't display it. | |
686 * if its not a thief he has 50/50 shot | |
687 */ | |
688 if((tp->tr_flags&ISTHIEFSET) || (!is_thief && rnd(100)>50)) | |
689 continue; /* give him chance for other traps */ | |
690 tp->tr_flags |= ISFOUND; | |
691 | |
692 /* Let's update the screen */ | |
693 if (mp != NULL && mvwinch(cw, y, x) == mch) | |
694 mp->t_oldch = ch; /* Will change when monst moves */ | |
695 else mvwaddch(cw, y, x, ch); | |
696 | |
697 count = 0; | |
698 running = FALSE; | |
699 | |
700 /* Stop what we were doing */ | |
701 player.t_no_move = movement(&player); | |
702 player.t_action = A_NIL; | |
703 player.t_using = NULL; | |
704 | |
705 if (fight_flush) md_flushinp(); | |
706 msg(tr_name(tp->tr_type)); | |
707 } | |
708 else if (ch == SECRETDOOR) { | |
709 if (door_chime == TRUE || (!is_thief && rnd(100) < 20)) { | |
710 struct room *rp; | |
711 coord cp; | |
712 | |
713 /* Is there a monster on the door? */ | |
714 if (mch != ch && (item = find_mons(y, x)) != NULL) { | |
715 mp = THINGPTR(item); | |
716 | |
717 /* Screen will change when monster moves */ | |
718 if (sch == mch) mp->t_oldch = ch; | |
719 } | |
720 mvaddch(y, x, DOOR); | |
721 count = 0; | |
722 /* | |
723 * if its the entrance to a treasure room, wake it up | |
724 */ | |
725 cp.y = y; | |
726 cp.x = x; | |
727 rp = roomin(&cp); | |
728 if (rp->r_flags & ISTREAS) | |
729 wake_room(rp); | |
730 | |
731 /* Make sure we don't shoot into the room */ | |
732 if (door_chime == FALSE) { | |
733 count = 0; | |
734 running = FALSE; | |
735 | |
736 /* Stop what we were doing */ | |
737 player.t_no_move = movement(&player); | |
738 player.t_action = A_NIL; | |
739 player.t_using = NULL; | |
740 } | |
741 } | |
742 } | |
743 } | |
744 } | |
745 | |
746 | |
747 /* | |
748 * help: | |
749 * Give single character help, or the whole mess if he wants it | |
750 */ | |
751 | |
752 help() | |
753 { | |
754 register struct h_list *strp = helpstr; | |
755 #ifdef WIZARD | |
756 struct h_list *wizp = wiz_help; | |
757 #endif | |
758 register char helpch; | |
759 register int cnt; | |
760 | |
761 msg("Character you want help for (* for all): "); | |
762 helpch = readchar(); | |
763 mpos = 0; | |
764 /* | |
765 * If its not a *, print the right help string | |
766 * or an error if he typed a funny character. | |
767 */ | |
768 if (helpch != '*') { | |
769 wmove(msgw, 0, 0); | |
770 while (strp->h_ch) { | |
771 if (strp->h_ch == helpch) { | |
772 msg("%s%s", unctrl(strp->h_ch), strp->h_desc); | |
773 return; | |
774 } | |
775 strp++; | |
776 } | |
777 #ifdef WIZARD | |
778 if (wizard) { | |
779 while (wizp->h_ch) { | |
780 if (wizp->h_ch == helpch) { | |
781 msg("%s%s", unctrl(wizp->h_ch), wizp->h_desc); | |
782 return; | |
783 } | |
784 wizp++; | |
785 } | |
786 } | |
787 #endif | |
788 | |
789 msg("Unknown character '%s'", unctrl(helpch)); | |
790 return; | |
791 } | |
792 /* | |
793 * Here we print help for everything. | |
794 * Then wait before we return to command mode | |
795 */ | |
796 wclear(hw); | |
797 cnt = 0; | |
798 while (strp->h_ch) { | |
799 mvwaddstr(hw, cnt % 23, cnt > 22 ? 40 : 0, unctrl(strp->h_ch)); | |
800 waddstr(hw, strp->h_desc); | |
801 strp++; | |
802 if (++cnt >= 46 && strp->h_ch) { | |
803 wmove(hw, lines-1, 0); | |
804 wprintw(hw, morestr); | |
805 draw(hw); | |
806 wait_for(' '); | |
807 wclear(hw); | |
808 cnt = 0; | |
809 } | |
810 } | |
811 #ifdef WIZARD | |
812 if (wizard) { | |
813 while (wizp->h_ch) { | |
814 mvwaddstr(hw, cnt % 23, cnt > 22 ? 40 : 0, unctrl(wizp->h_ch)); | |
815 waddstr(hw, wizp->h_desc); | |
816 wizp++; | |
817 if (++cnt >= 46 && wizp->h_ch) { | |
818 wmove(hw, lines-1, 0); | |
819 wprintw(hw, morestr); | |
820 draw(hw); | |
821 wait_for(' '); | |
822 wclear(hw); | |
823 cnt = 0; | |
824 } | |
825 } | |
826 } | |
827 #endif | |
828 wmove(hw, lines-1, 0); | |
829 wprintw(hw, spacemsg); | |
830 draw(hw); | |
831 wait_for(' '); | |
832 wclear(hw); | |
833 draw(hw); | |
834 wmove(cw, 0, 0); | |
835 wclrtoeol(cw); | |
836 status(FALSE); | |
837 touchwin(cw); | |
838 } | |
839 /* | |
840 * identify: | |
841 * Tell the player what a certain thing is. | |
842 */ | |
843 | |
844 identify(ch) | |
845 register char ch; | |
846 { | |
847 register char *str; | |
848 | |
849 if (ch == 0) { | |
850 msg("What do you want identified? "); | |
851 ch = readchar(); | |
852 mpos = 0; | |
853 if (ch == ESCAPE) | |
854 { | |
855 msg(""); | |
856 return; | |
857 } | |
858 } | |
859 if (isalpha(ch)) | |
860 str = monsters[id_monst(ch)].m_name; | |
861 else switch(ch) | |
862 { | |
863 case '|': | |
864 case '-': | |
865 str = (levtype == OUTSIDE) ? "boundary of sector" | |
866 : "wall of a room"; | |
867 when GOLD: str = "gold"; | |
868 when STAIRS : str = (levtype == OUTSIDE) ? "entrance to a dungeon" | |
869 : "passage leading down"; | |
870 when DOOR: str = "door"; | |
871 when FLOOR: str = (levtype == OUTSIDE) ? "meadow" : "room floor"; | |
872 when VPLAYER: str = "the hero of the game ---> you"; | |
873 when IPLAYER: str = "you (but invisible)"; | |
874 when PASSAGE: str = "passage"; | |
875 when POST: str = "trading post"; | |
876 when POOL: str = (levtype == OUTSIDE) ? "lake" | |
877 : "a shimmering pool"; | |
878 when TRAPDOOR: str = "trapdoor"; | |
879 when ARROWTRAP: str = "arrow trap"; | |
880 when SLEEPTRAP: str = "sleeping gas trap"; | |
881 when BEARTRAP: str = "bear trap"; | |
882 when TELTRAP: str = "teleport trap"; | |
883 when DARTTRAP: str = "dart trap"; | |
884 when MAZETRAP: str = "entrance to a maze"; | |
885 when FOREST: str = "forest"; | |
886 when POTION: str = "potion"; | |
887 when SCROLL: str = "scroll"; | |
888 when FOOD: str = "food"; | |
889 when WEAPON: str = "weapon"; | |
890 when ' ' : str = "solid rock"; | |
891 when ARMOR: str = "armor"; | |
892 when MM: str = "miscellaneous magic"; | |
893 when RING: str = "ring"; | |
894 when STICK: str = "wand or staff"; | |
895 when SECRETDOOR:str = "secret door"; | |
896 when RELIC: str = "artifact"; | |
897 otherwise: str = "unknown character"; | |
898 } | |
899 msg("'%s' : %s", unctrl(ch), str); | |
900 } | |
901 | |
902 /* | |
903 * d_level: | |
904 * He wants to go down a level | |
905 */ | |
906 | |
907 d_level() | |
908 { | |
909 bool no_phase=FALSE; | |
910 char position = CCHAR( winat(hero.y, hero.x) ); | |
911 | |
912 | |
913 /* If we are on a trading post, go to a trading post level. */ | |
914 if (position == POST) { | |
915 new_level(POSTLEV); | |
916 return; | |
917 } | |
918 | |
919 /* If we are at a top-level trading post, we probably can't go down */ | |
920 if (levtype == POSTLEV && level == 0 && position != STAIRS) { | |
921 msg("I see no way down."); | |
922 return; | |
923 } | |
924 | |
925 if (winat(hero.y, hero.x) != STAIRS) { | |
926 if (off(player, CANINWALL) || /* Must use stairs if can't phase */ | |
927 (levtype == OUTSIDE && rnd(100) < 90)) { | |
928 msg("I see no way down."); | |
929 return; | |
930 } | |
931 | |
932 /* Is there any dungeon left below? */ | |
933 if (level >= nfloors) { | |
934 msg("There is only solid rock below."); | |
935 return; | |
936 } | |
937 | |
938 extinguish(unphase); /* Using phase to go down gets rid of it */ | |
939 no_phase = TRUE; | |
940 } | |
941 | |
942 /* Is this the bottom? */ | |
943 if (level >= nfloors) { | |
944 msg("The stairway only goes up."); | |
945 return; | |
946 } | |
947 | |
948 level++; | |
949 new_level(NORMLEV); | |
950 if (no_phase) unphase(); | |
951 } | |
952 | |
953 /* | |
954 * u_level: | |
955 * He wants to go up a level | |
956 */ | |
957 | |
958 u_level() | |
959 { | |
960 bool no_phase = FALSE; | |
961 register struct linked_list *item; | |
962 struct thing *tp; | |
963 struct object *obj; | |
964 | |
965 if (winat(hero.y, hero.x) != STAIRS) { | |
966 if (off(player, CANINWALL)) { /* Must use stairs if can't phase */ | |
967 msg("I see no way up."); | |
968 return; | |
969 } | |
970 | |
971 extinguish(unphase); | |
972 no_phase = TRUE; | |
973 } | |
974 | |
975 if (level == 0) { | |
976 msg("The stairway only goes down."); | |
977 return; | |
978 } | |
979 | |
980 /* | |
981 * does he have the item he was quested to get? | |
982 */ | |
983 if (level == 1) { | |
984 for (item = pack; item != NULL; item = next(item)) { | |
985 obj = OBJPTR(item); | |
986 if (obj->o_type == RELIC && obj->o_which == quest_item) | |
987 total_winner(); | |
988 } | |
989 } | |
990 /* | |
991 * check to see if he trapped a UNIQUE, If he did then put it back | |
992 * in the monster table for next time | |
993 */ | |
994 for (item = tlist; item != NULL; item = next(item)) { | |
995 tp = THINGPTR(item); | |
996 if (on(*tp, ISUNIQUE)) | |
997 monsters[tp->t_index].m_normal = TRUE; | |
998 } | |
999 t_free_list(tlist); /* Monsters that fell below are long gone! */ | |
1000 | |
1001 if (levtype != POSTLEV) level--; | |
1002 if (level > 0) new_level(NORMLEV); | |
1003 else { | |
1004 level = -1; /* Indicate that we are new to the outside */ | |
1005 msg("You emerge into the %s", daytime ? "light" : "night"); | |
1006 new_level(OUTSIDE); /* Leaving the dungeon */ | |
1007 } | |
1008 | |
1009 if (no_phase) unphase(); | |
1010 } | |
1011 | |
1012 /* | |
1013 * Let him escape for a while | |
1014 */ | |
1015 | |
1016 shell() | |
1017 { | |
1018 register char *sh; | |
1019 | |
1020 /* | |
1021 * Set the terminal back to original mode | |
1022 */ | |
1023 sh = getenv("SHELL"); | |
1024 wclear(hw); | |
1025 wmove(hw, lines-1, 0); | |
1026 draw(hw); | |
1027 endwin(); | |
1028 in_shell = TRUE; | |
1029 fflush(stdout); | |
1030 /* | |
1031 * Fork and do a shell | |
1032 */ | |
1033 | |
1034 md_shellescape(); | |
1035 | |
1036 printf(retstr); | |
1037 noecho(); | |
1038 raw(); | |
1039 keypad(cw,1); | |
1040 keypad(msgw,1); | |
1041 in_shell = FALSE; | |
1042 wait_for('\n'); | |
1043 clearok(cw, TRUE); | |
1044 touchwin(cw); | |
1045 } | |
1046 | |
1047 /* | |
1048 * see what we want to name -- an item or a monster. | |
1049 */ | |
1050 nameit() | |
1051 { | |
1052 char answer; | |
1053 | |
1054 msg("Name monster or item (m or i)? "); | |
1055 answer = readchar(); | |
1056 mpos = 0; | |
1057 | |
1058 while (answer != 'm' && answer != 'i' && answer != ESCAPE) { | |
1059 mpos = 0; | |
1060 msg("Please specify m or i, for monster or item - "); | |
1061 answer = readchar(); | |
1062 } | |
1063 | |
1064 switch (answer) { | |
1065 case 'm': namemonst(); | |
1066 when 'i': nameitem(NULL, FALSE); | |
1067 } | |
1068 } | |
1069 | |
1070 /* | |
1071 * allow a user to call a potion, scroll, or ring something | |
1072 */ | |
1073 nameitem(item, mark) | |
1074 struct linked_list *item; | |
1075 bool mark; | |
1076 { | |
1077 register struct object *obj; | |
1078 register char **guess, *elsewise; | |
1079 register bool *know; | |
1080 | |
1081 if (item == NULL) { | |
1082 if (mark) item = get_item(pack, "mark", ALL, FALSE, FALSE); | |
1083 else item = get_item(pack, "name", CALLABLE, FALSE, FALSE); | |
1084 if (item == NULL) return; | |
1085 } | |
1086 /* | |
1087 * Make certain that it is somethings that we want to wear | |
1088 */ | |
1089 obj = OBJPTR(item); | |
1090 switch (obj->o_type) | |
1091 { | |
1092 case RING: | |
1093 guess = r_guess; | |
1094 know = r_know; | |
1095 elsewise = (r_guess[obj->o_which] != NULL ? | |
1096 r_guess[obj->o_which] : r_stones[obj->o_which]); | |
1097 when POTION: | |
1098 guess = p_guess; | |
1099 know = p_know; | |
1100 elsewise = (p_guess[obj->o_which] != NULL ? | |
1101 p_guess[obj->o_which] : p_colors[obj->o_which]); | |
1102 when SCROLL: | |
1103 guess = s_guess; | |
1104 know = s_know; | |
1105 elsewise = (s_guess[obj->o_which] != NULL ? | |
1106 s_guess[obj->o_which] : s_names[obj->o_which]); | |
1107 when STICK: | |
1108 guess = ws_guess; | |
1109 know = ws_know; | |
1110 elsewise = (ws_guess[obj->o_which] != NULL ? | |
1111 ws_guess[obj->o_which] : ws_made[obj->o_which]); | |
1112 when MM: | |
1113 guess = m_guess; | |
1114 know = m_know; | |
1115 elsewise = (m_guess[obj->o_which] != NULL ? | |
1116 m_guess[obj->o_which] : "nothing"); | |
1117 otherwise: | |
1118 if (!mark) { | |
1119 msg("You can't call that anything."); | |
1120 return; | |
1121 } | |
1122 else know = (bool *) 0; | |
1123 } | |
1124 if ((obj->o_flags & ISPOST) || (know && know[obj->o_which]) && !mark) { | |
1125 msg("That has already been identified."); | |
1126 return; | |
1127 } | |
1128 if (mark) { | |
1129 if (obj->o_mark[0]) { | |
1130 addmsg(terse ? "M" : "Was m"); | |
1131 msg("arked \"%s\"", obj->o_mark); | |
1132 } | |
1133 msg(terse ? "Mark it: " : "What do you want to mark it? "); | |
1134 prbuf[0] = '\0'; | |
1135 } | |
1136 else { | |
1137 if (elsewise) { | |
1138 addmsg(terse ? "N" : "Was n"); | |
1139 msg("amed \"%s\"", elsewise); | |
1140 strcpy(prbuf, elsewise); | |
1141 } | |
1142 else prbuf[0] = '\0'; | |
1143 msg(terse ? "Name it: " : "What do you want to name it? "); | |
1144 } | |
1145 if (get_str(prbuf, msgw) == NORM) { | |
1146 if (mark) { | |
1147 strncpy(obj->o_mark, prbuf, MARKLEN-1); | |
1148 obj->o_mark[MARKLEN-1] = '\0'; | |
1149 } | |
1150 else if (prbuf[0] != '\0') { | |
1151 if (guess[obj->o_which] != NULL) | |
1152 free(guess[obj->o_which]); | |
1153 guess[obj->o_which] = new((unsigned int) strlen(prbuf) + 1); | |
1154 strcpy(guess[obj->o_which], prbuf); | |
1155 } | |
1156 } | |
1157 } | |
1158 | |
1159 /* Name a monster */ | |
1160 | |
1161 namemonst() | |
1162 { | |
1163 register struct thing *tp; | |
1164 struct linked_list *item; | |
1165 coord c; | |
1166 | |
1167 /* Find the monster */ | |
1168 msg("Choose the monster (* for help)"); | |
1169 c = get_coordinates(); | |
1170 | |
1171 /* Make sure we can see it and that it is a monster. */ | |
1172 mpos = 0; | |
1173 if (!cansee(c.y, c.x)) { | |
1174 msg("You can't see what is there."); | |
1175 return; | |
1176 } | |
1177 | |
1178 if (isalpha(mvwinch(cw, c.y, c.x))) { | |
1179 item = find_mons(c.y, c.x); | |
1180 if (item != NULL) { | |
1181 tp = THINGPTR(item); | |
1182 if (tp->t_name == NULL) | |
1183 strcpy(prbuf, monsters[tp->t_index].m_name); | |
1184 else | |
1185 strcpy(prbuf, tp->t_name); | |
1186 | |
1187 addmsg(terse ? "N" : "Was n"); | |
1188 msg("amed \"%s\"", prbuf); | |
1189 msg(terse ? "Name it: " : "What do you want to name it? "); | |
1190 | |
1191 if (get_str(prbuf, msgw) == NORM) { | |
1192 if (prbuf[0] != '\0') { | |
1193 if (tp->t_name != NULL) | |
1194 free(tp->t_name); | |
1195 tp->t_name = new((unsigned int) strlen(prbuf) + 1); | |
1196 strcpy(tp->t_name, prbuf); | |
1197 } | |
1198 } | |
1199 return; | |
1200 } | |
1201 } | |
1202 | |
1203 msg("There is no monster there to name."); | |
1204 } | |
1205 | |
1206 count_gold() | |
1207 { | |
1208 if (player.t_action != C_COUNT) { | |
1209 msg("You take a break to count your money..."); | |
1210 player.t_using = NULL; | |
1211 player.t_action = C_COUNT; /* We are counting */ | |
1212 player.t_no_move = (purse/300 + 1) * movement(&player); | |
1213 return; | |
1214 } | |
1215 if (purse > 100) | |
1216 msg("You think you have about %d gold pieces.", purse); | |
1217 else | |
1218 msg("You have %d gold pieces.", purse); | |
1219 player.t_action = A_NIL; | |
1220 } |