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