Annotation of early-roguelike/urogue/command.c, Revision 1.1.1.1
1.1 rubenllo 1: /*
2: command.c - Read and execute the user commands
3:
4: UltraRogue: The Ultimate Adventure in the Dungeons of Doom
5: Copyright (C) 1985, 1986, 1992, 1993, 1995 Herb Chong
6: All rights reserved.
7:
8: Based on "Advanced Rogue"
9: Copyright (C) 1984, 1985 Michael Morgan, Ken Dalka
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 <string.h>
20: #include <stdlib.h>
21: #include <ctype.h>
22: #include "rogue.h"
23:
24: /*
25: command()
26: Process the user commands
27: */
28:
29: void
30: command(void)
31: {
32: static char repcommand; /* Command to repeat if we are repeating */
33: static int fight_to_death; /* Flags if we are fighting to death */
34: static coord dir; /* Last direction specified */
35:
36: object *obj;
37: char ch;
38: int ntimes = 1; /* Number of player moves */
39: coord nullcoord;
40:
41: nullcoord.x = nullcoord.y = 0;
42:
43: if (on(player, CANFLY) && rnd(2))
44: ntimes++;
45:
46: if (on(player, ISHASTE))
47: ntimes++;
48:
49: if (fighting && att_bonus())
50: ntimes *= 2;
51:
52: if (on(player, ISSLOW))
53: {
54: if (player.t_turn != TRUE)
55: ntimes--;
56:
57: player.t_turn ^= TRUE;
58: }
59:
60: if (ntimes == 0)
61: return;
62:
63: while (ntimes--)
64: {
65: moving = FALSE;
66:
67: /* If player is infested, take off a hit point */
68:
69: if (on(player, HASINFEST) && !is_wearing(R_HEALTH))
70: {
71: if ((pstats.s_hpt -= infest_dam) <= 0)
72: {
73: death(D_INFESTATION);
74: return;
75: }
76: }
77:
78: look(after);
79:
80: if (!running)
81: door_stop = FALSE;
82:
83: status(FALSE);
84: wmove(cw, hero.y, hero.x);
85:
86: if (!((running || count) && jump))
87: wrefresh(cw); /* Draw screen */
88:
89: take = 0;
90: after = TRUE;
91:
92: /*
93: * Read command or continue run
94: */
95:
96: if (!no_command)
97: {
98: if (fighting)
99: {
100: ch = (fight_to_death) ? 'F' : 'f';
101: }
102: else if (running)
103: {
104: /*
105: * If in a corridor, if we are at a turn with
106: * only one way to go, turn that way.
107: */
108:
109: if ((winat(hero.y, hero.x) == PASSAGE) && off(player, ISHUH) &&
110: (off(player, ISBLIND)))
111: switch (runch)
112: {
113: case 'h': corr_move(0, -1); break;
114: case 'j': corr_move(1, 0); break;
115: case 'k': corr_move(-1, 0); break;
116: case 'l': corr_move(0, 1); break;
117: }
118:
119: ch = runch;
120: }
121: else if (count)
122: ch = repcommand;
123: else
124: {
125: ch = readchar();
126:
127: if (mpos != 0 && !running)
128: msg(""); /* Erase message if its there */
129: }
130: }
131: else
132: {
133: ch = '.';
134: fighting = moving = FALSE;
135: }
136:
137: if (no_command)
138: {
139: if (--no_command == 0)
140: msg("You can move again.");
141: }
142: else
143: {
144:
145: /*
146: * check for prefixes
147: */
148:
149: if (isdigit(ch))
150: {
151: count = 0;
152: while (isdigit(ch))
153: {
154: count = count * 10 + (ch - '0');
155: ch = readcharw(cw);
156: }
157: repcommand = ch;
158:
159: /*
160: * Preserve count for commands which can be
161: * repeated.
162: */
163:
164: switch(ch)
165: {
166: case 'h':
167: case 'j':
168: case 'k':
169: case 'l':
170: case 'y':
171: case 'u':
172: case 'b':
173: case 'n':
174: case 'H':
175: case 'J':
176: case 'K':
177: case 'L':
178: case 'Y':
179: case 'U':
180: case 'B':
181: case 'N':
182: case 'q':
183: case 'r':
184: case 's':
185: case 'm':
186: case 't':
187: case 'C':
188: case 'I':
189: case '.':
190: case 'z':
191: case 'p':
192: break;
193: default:
194: count = 0;
195: }
196: }
197:
198: /* Save current direction */
199:
200: if (!running) /* If running, it is already saved */
201: switch (ch)
202: {
203: case 'h':
204: case 'j':
205: case 'k':
206: case 'l':
207: case 'y':
208: case 'u':
209: case 'b':
210: case 'n':
211: runch = ch;
212: break;
213: case 'H':
214: case 'J':
215: case 'K':
216: case 'L':
217: case 'Y':
218: case 'U':
219: case 'B':
220: case 'N':
221: runch = (char) tolower(ch);
222: break;
223: }
224:
225: /*
226: * execute a command
227: */
228:
229: if (count && !running)
230: count--;
231:
232: switch(ch)
233: {
234: /*
235: * Movement and combat commands
236: */
237:
238: case 'h': do_move(0,-1); break;
239: case 'j': do_move(1, 0); break;
240: case 'k': do_move(-1, 0); break;
241: case 'l': do_move(0, 1); break;
242: case 'y': do_move(-1, -1); break;
243: case 'u': do_move(-1, 1); break;
244: case 'b': do_move(1, -1); break;
245: case 'n': do_move(1, 1); break;
246: case 'H': do_run('h'); break;
247: case 'J': do_run('j'); break;
248: case 'K': do_run('k'); break;
249: case 'L': do_run('l'); break;
250: case 'Y': do_run('y'); break;
251: case 'U': do_run('u'); break;
252: case 'B': do_run('b'); break;
253: case 'N': do_run('n'); break;
254: case 'm':
255: moving = TRUE;
256: if (!get_dir())
257: {
258: after = FALSE;
259: break;
260: }
261: do_move(delta.y, delta.x);
262: break;
263: case 'F':
264: case 'f':
265: fight_to_death = (ch == 'F');
266: if (!fighting)
267: {
268: if (get_dir())
269: {
270: dir = delta;
271: beast = NULL;
272: }
273: else
274: {
275: after = FALSE;
276: break;
277: }
278: }
279: do_fight(dir, (ch == 'F') ? TRUE : FALSE);
280: break;
281: case 't':
282: if (get_dir())
283: missile(delta.y, delta.x, get_item("throw", 0),
284: &player);
285: else
286: after = FALSE;
287:
288: /*
289: * Informational commands - Do not do
290: * after daemons
291: */
292: break;
293:
294: case 0x7f: /* sometime generated by */
295: /* suspend/foreground */
296: case ESCAPE:
297: case ' ':
298: after = FALSE; /* do nothing */
299: break;
300: case 'Q':
301: after = FALSE;
302: quit();
303: break;
304: case 'i':
305: after = FALSE;
306: inventory(pack, '*');
307: break;
308: case 'I':
309: after = FALSE;
310: inventory(pack, 0);
311: break;
312: case '~':
313: after = FALSE;
314: next_exp_level(MESSAGE);
315: break;
316: case '>':
317: after = FALSE;
318: d_level();
319: break;
320: case '<':
321: after = FALSE;
322: u_level();
323: break;
324: case '?':
325: after = FALSE;
326: help();
327: break;
328: case '/':
329: after = FALSE;
330: identify();
331: break;
332: case 'v':
333: after = FALSE;
334: msg("UltraRogue Version %s.", release);
335: break;
336: case 'o':
337: after = FALSE;
338: option();
339: strcpy(fd_data[1].mi_name, fruit);
340: break;
341: case 12: /* ctrl-l */
342: case 18: /* ctrl-r */
343: after = FALSE;
344: clearok(cw, TRUE);
345: wrefresh(cw);
346: break;
347: case 16: /* ctrl-p */
348: {
349: int decrement = FALSE;
350: after = FALSE;
351:
352: if (mpos == 0)
353: decrement = TRUE;
354:
355: msg_index = (msg_index + 9) % 10;
356: msg(msgbuf[msg_index]);
357: if (decrement)
358: msg_index = (msg_index + 9) % 10;
359: }
360: break;
361:
362: case 'S':
363: after = FALSE;
364: if (save_game())
365: {
366: wclear(cw);
367: wrefresh(cw);
368: endwin();
369: printf("\n");
370: exit(0);
371: }
372: break;
373:
374: /*
375: * Other misc commands
376: */
377:
378: case '.': break; /* rest */
379: case ',': add_pack(NULL, NOMESSAGE); break;
380: case 'q': quaff(&player, -1, ISNORMAL); break;
381: case 'r': read_scroll(&player, -1, ISNORMAL); break;
382: case 'd': drop(NULL); break;
383: case '^': set_trap(&player, hero.y, hero.x); break;
384: case 'c': incant(&player, nullcoord); break;
385: case 'D': dip_it(); break;
386: case 'e': eat(); break;
387: case '=': listen(); break;
388: case 'A': apply(); break;
389: case 'w': wield(); break;
390: case 'W': wear(); break;
391: case 'T': take_off(); break;
392: case 'P': ring_on(); break;
393: case 'R': ring_off(); break;
394: case 'p': prayer(); break;
395: case 'C': call(FALSE); break;
396: case 'M': call(TRUE); break;
397: case 's': search(FALSE); break;
398:
399: /*
400: * Directional commands - get_dir sets delta
401: */
402: case 20: /* ctrl-t */
403: if (get_dir())
404: steal();
405: else
406: after = FALSE;
407: break;
408:
409: case 'z':
410: if (get_dir())
411: do_zap(&player, -1, ISNORMAL);
412: else
413: after = FALSE;
414: break;
415:
416: case 'a':
417: if (get_dir())
418: affect();
419: else
420: after = FALSE;
421: touchwin(cw);
422: break;
423:
424: /*
425: * wizard commands
426: */
427:
428: #ifdef WIZARD
429: case 0x17: /* ctrl-w */
430: after = FALSE;
431:
432: if (!wizard)
433: {
434: if (!canwizard)
435: {
436: msg("Illegal command '^W'.");
437: break;
438: }
439:
440: if (passwd())
441: {
442: msg("Welcome, oh mighty wizard.");
443: wizard = waswizard = TRUE;
444: }
445: else
446: {
447: msg("Incorrect password.");
448: break;
449: }
450: }
451:
452: msg("Wizard command: ");
453: mpos = 0;
454: ch = readchar();
455:
456: switch (ch)
457: {
458: case 'v':
459: wiz_verbose = !wiz_verbose;
460: break;
461:
462: case 'e':
463: wizard = FALSE;
464: msg("Not wizard any more.");
465: break;
466:
467: case 's': activity(); break;
468: case 't': teleport(); break;
469: case 'm': overlay(mw, cw); break;
470: case 'f': overlay(stdscr, cw); break;
471: case 'i': inventory(lvl_obj, 0); break;
472: case 'c': buy_it('\0', ISNORMAL); break;
473: case 'I': whatis(NULL); break;
474: case 'F':
475: msg("food left: %d\tfood level: %d",
476: food_left,foodlev);
477: break;
478: case 'M':
479: creat_mons(&player, get_monster_number("create"),
480: MESSAGE);
481: break;
482:
483: case 'r':
484: msg("rnd(4)%d, rnd(40)%d, rnd(100)%d",
485: rnd(4), rnd(40), rnd(100));
486: break;
487:
488: case 'C':
489: obj = get_object(pack, "charge", STICK, NULL);
490:
491: if (obj != NULL)
492: obj->o_charges = 10000;
493:
494: break;
495:
496: case 'w':
497: obj = get_object(pack, "price", 0, NULL);
498:
499: if (obj != NULL)
500: msg("Worth %d.", get_worth(obj));
501:
502: break;
503:
504: case 'g':
505: {
506: int tlev;
507:
508: prbuf[0] = '\0';
509: msg("Which level? ");
510:
511: if (get_string(prbuf, cw) == NORM)
512: {
513: msg("");
514:
515: if ((tlev = atoi(prbuf)) < 1)
516: msg("Illegal level.");
517: else if (tlev > 3000)
518: {
519: levtype = THRONE;
520: level = tlev - 3000;
521: }
522: else if (tlev > 2000)
523: {
524: levtype = MAZELEV;
525: level = tlev - 2000;
526: }
527: else if (tlev > 1000)
528: {
529: levtype = POSTLEV;
530: level = tlev - 1000;
531: }
532: else
533: {
534: levtype = NORMLEV;
535: level = tlev;
536: }
537:
538: new_level(levtype,0);
539: }
540: }
541: break;
542:
543: case 'o': make_omnipotent(); break;
544:
545: case ESCAPE: /* Escape */
546: door_stop = FALSE;
547:
548: count = 0;
549: after = FALSE;
550: break;
551:
552: default:
553: msg("Illegal wizard command '%s', %d.",
554: unctrl(ch), ch);
555: count = 0;
556: break;
557:
558: }
559:
560: break;
561: #endif
562:
563: default:
564: msg("Illegal command '%s', %d.",
565: unctrl(ch), ch);
566: count = 0;
567: after = FALSE;
568: break;
569: }
570:
571: /*
572: * turn off flags if no longer needed
573: */
574: if (!running)
575: door_stop = FALSE;
576: }
577:
578: /*
579: * If he ran into something to take, let him pick it up.
580: */
581: if (take != 0)
582: if (!moving)
583: pick_up(take);
584: else
585: show_floor();
586: if (!running)
587: door_stop = FALSE;
588: } /* end while */
589: }
590:
591:
592: void
593: do_after_effects(void)
594: {
595: int i;
596:
597: /* Kick off the rest of the daemons and fuses */
598:
599: look(FALSE);
600: do_daemons(AFTER);
601: do_fuses(AFTER);
602:
603: /* Special abilities */
604:
605: if ((player.t_ctype == C_THIEF || player.t_ctype == C_ASSASIN ||
606: player.t_ctype == C_NINJA || player.t_ctype == C_RANGER) &&
607: (rnd(100) < (2 * pstats.s_dext + 5 * pstats.s_lvl)))
608: search(TRUE);
609:
610: for (i = 0; i < ring_value(R_SEARCH); i++)
611: search(FALSE);
612:
613: if (is_wearing(R_TELEPORT) && rnd(50) < 2)
614: {
615: teleport();
616:
617: if (off(player, ISCLEAR))
618: {
619: if (on(player, ISHUH))
620: lengthen_fuse(FUSE_UNCONFUSE, rnd(8) + HUHDURATION);
621: else
622: light_fuse(FUSE_UNCONFUSE, 0, rnd(8) + HUHDURATION, AFTER);
623:
624: turn_on(player, ISHUH);
625: }
626: else
627: msg("You feel dizzy for a moment, but it quickly passes.");
628: }
629:
630: /* accidents and general clumsiness */
631:
632: if (fighting && rnd(50) == 0)
633: {
634: msg("You become tired of this nonsense.");
635: fighting = after = FALSE;
636: }
637:
638: if (on(player, ISELECTRIC))
639: electrificate();
640:
641: if (!fighting && (no_command == 0) && cur_weapon != NULL
642: && rnd(on(player, STUMBLER) ? 399 : 9999) == 0
643: && rnd(pstats.s_dext) <
644: 2 - hitweight() + (on(player, STUMBLER) ? 4 : 0))
645: {
646: msg("You trip and stumble over your weapon.");
647: running = after = FALSE;
648:
649: if (rnd(8) == 0 && (pstats.s_hpt -= roll(1, 10)) <= 0)
650: {
651: msg("You break your neck and die.");
652: death(D_FALL);
653: return;
654: }
655: else if (cur_weapon->o_flags & ISPOISON && rnd(4) == 0)
656: {
657: msg("You are cut by your %s!",
658: inv_name(cur_weapon, LOWERCASE));
659:
660: if (player.t_ctype != C_PALADIN
661: && !(player.t_ctype == C_NINJA &&
662: pstats.s_lvl > 12)
663: && !save(VS_POISON))
664: {
665: if (pstats.s_hpt == 1)
666: {
667: msg("You die from the poison in the cut.");
668: death(D_POISON);
669: return;
670: }
671: else
672: {
673: msg("You feel very sick now.");
674: pstats.s_hpt /= 2;
675: chg_str(-2, FALSE, FALSE);
676: }
677: }
678: }
679: }
680:
681: /* Time to enforce weapon and armor restrictions */
682: if (rnd(9999) == 0)
683: if (((cur_weapon == NULL) ||
684: (wield_ok(&player, cur_weapon, NOMESSAGE)))
685: && ((cur_armor == NULL) ||
686: (wear_ok(&player, cur_armor, NOMESSAGE))))
687: {
688: switch (player.t_ctype)
689: {
690: case C_CLERIC:
691: case C_DRUID:
692: case C_RANGER:
693: case C_PALADIN:
694: if (rnd(luck) != 0)
695: /* You better have done
696: * little wrong */
697: goto bad_cleric;
698:
699: msg("You are enraptured by the renewed "
700: "power of your god.");
701: break;
702:
703: case C_MAGICIAN:
704: case C_ILLUSION:
705: msg("You become in tune with the universe.");
706: break;
707:
708: case C_THIEF:
709: case C_NINJA:
710: case C_ASSASIN:
711: msg("You become supernaly sensitive to your "
712: "surroundings.");
713: break;
714:
715: case C_FIGHTER:
716: msg("You catch your second wind.");
717: break;
718:
719: default:
720: msg("What a strange type you are!");
721: break;
722: }
723: pstats.s_hpt = max_stats.s_hpt += rnd(pstats.s_lvl) + 1;
724: pstats.s_power = max_stats.s_power += rnd(pstats.s_lvl) + 1;
725: }
726: else
727: { /* he blew it - make him pay */
728:
729: int death_cause = 0;
730:
731: switch (player.t_ctype)
732: {
733: case C_CLERIC:
734: case C_DRUID:
735: case C_RANGER:
736: case C_PALADIN:
737: bad_cleric:
738: msg("Your god scourges you for your misdeeds.");
739: death_cause = D_GODWRATH;
740: break;
741:
742: case C_MAGICIAN:
743: case C_ILLUSION:
744: msg("You short out your manna on the unfamiliar %s.",
745: (cur_armor != NULL ? "armor" : "weapon"));
746:
747: death_cause = D_SPELLFUMBLE;
748: break;
749:
750: case C_THIEF:
751: case C_NINJA:
752: case C_ASSASIN:
753: msg("You trip and fall because of the unfamiliar %s.",
754: (cur_armor != NULL ? "armor" : "weapon"));
755: death_cause = D_CLUMSY;
756: break;
757:
758: case C_FIGHTER:
759: debug("Fighter getting raw deal?");
760: break;
761:
762: default:
763: msg("What a strange type you are!");
764: break;
765: }
766:
767: aggravate();
768: pstats.s_power /= 2;
769: pstats.s_hpt /= 2;
770: player.t_no_move++;
771:
772: if ((pstats.s_hpt -= rnd(pstats.s_lvl)) <= 0)
773: {
774: death(death_cause);
775: }
776: }
777:
778: if (rnd(500000) == 0)
779: {
780: new_level(THRONE,0);
781: fighting = running = after = FALSE;
782: command();
783: }
784: }
785:
786: void
787: make_omnipotent(void)
788: {
789: int i;
790: struct linked_list *item;
791: struct object *obj;
792:
793: for (i = 0; i < 20; i++)
794: raise_level();
795:
796: max_stats.s_hpt += 1000;
797: max_stats.s_power += 1000;
798: pstats.s_hpt = max_stats.s_hpt;
799: pstats.s_power = max_stats.s_power;
800: max_stats.s_str = pstats.s_str = 25;
801: max_stats.s_intel = pstats.s_intel = 25;
802: max_stats.s_wisdom = pstats.s_wisdom = 25;
803: max_stats.s_dext = pstats.s_dext = 25;
804: max_stats.s_const = pstats.s_const = 25;
805:
806: if (cur_weapon == NULL || cur_weapon->o_which != CLAYMORE)
807: {
808: item = spec_item(WEAPON, CLAYMORE, 10, 10);
809: cur_weapon = OBJPTR(item);
810: cur_weapon->o_flags |= ISKNOW;
811: add_pack(item, NOMESSAGE);
812: }
813:
814: /* and a kill-o-zap stick */
815:
816: item = spec_item(STICK, WS_DISINTEGRATE, 10000, 0);
817: obj = OBJPTR(item);
818: obj->o_flags |= ISKNOW;
819: know_items[TYP_STICK][WS_DISINTEGRATE] = TRUE;
820:
821: if (guess_items[TYP_STICK][WS_DISINTEGRATE])
822: {
823: ur_free(guess_items[TYP_STICK][WS_DISINTEGRATE]);
824: guess_items[TYP_STICK][WS_DISINTEGRATE] = NULL;
825: }
826:
827: add_pack(item, NOMESSAGE);
828:
829: /* and his suit of armor */
830:
831: if (cur_armor == NULL ||
832: !(cur_armor->o_which == CRYSTAL_ARMOR ||
833: cur_armor->o_which == MITHRIL))
834: {
835: item = spec_item(ARMOR, CRYSTAL_ARMOR, 15, 0);
836: obj = OBJPTR(item);
837: obj->o_flags |= ISKNOW;
838: obj->o_weight =
839: (int) (armors[CRYSTAL_ARMOR].a_wght * 0.2);
840: cur_armor = obj;
841: add_pack(item, NOMESSAGE);
842: }
843:
844: /* and some rings (have to put them on, for now) */
845:
846:
847: if (!is_wearing(R_SEARCH))
848: {
849: item = spec_item(RING, R_SEARCH, 0, 0);
850: obj = OBJPTR(item);
851: obj->o_flags |= ISKNOW;
852: know_items[TYP_RING][R_SEARCH] = TRUE;
853:
854: if (guess_items[TYP_RING][R_SEARCH])
855: {
856: ur_free(guess_items[TYP_RING][R_SEARCH]);
857: guess_items[TYP_RING][R_SEARCH] = NULL;
858: }
859:
860: add_pack(item, NOMESSAGE);
861: }
862:
863: if (!is_wearing(R_PIETY))
864: {
865: item = spec_item(RING, R_PIETY, 0, 0);
866: obj = OBJPTR(item);
867: obj->o_flags |= ISKNOW;
868: know_items[TYP_RING][R_PIETY] = TRUE;
869:
870: if (guess_items[TYP_RING][R_PIETY])
871: {
872: ur_free(guess_items[TYP_RING][R_PIETY]);
873: guess_items[TYP_RING][R_PIETY] = NULL;
874: }
875:
876: add_pack(item, NOMESSAGE);
877: }
878:
879: item = spec_item(SCROLL, S_ELECTRIFY, 0, 0);
880: obj = OBJPTR(item);
881: obj->o_flags |= ISKNOW;
882: know_items[TYP_SCROLL][S_ELECTRIFY] = TRUE;
883:
884: if (guess_items[TYP_SCROLL][S_ELECTRIFY])
885: {
886: ur_free(guess_items[TYP_SCROLL][S_ELECTRIFY]);
887: guess_items[TYP_SCROLL][S_ELECTRIFY] = NULL;
888: }
889:
890: add_pack(item, NOMESSAGE);
891:
892: /* Spiff him up a bit */
893: quaff(&player, P_SHERO, ISBLESSED);
894: quaff(&player, P_CLEAR, ISBLESSED);
895: quaff(&player, P_FIRERESIST, ISBLESSED);
896: quaff(&player, P_TRUESEE, ISBLESSED);
897: quaff(&player, P_PHASE, ISBLESSED);
898: purse += 50000L;
899: updpack();
900: }
901:
902:
903: /*
904: quit()
905: Have player make certain, then exit.
906: */
907:
908: void
909: quit_handler(int sig)
910: {
911: if (signal(SIGINT, quit_handler) != quit_handler)
912: mpos = 0;
913:
914: sig = 0;
915:
916: quit();
917: }
918:
919: void
920: quit(void)
921: {
922: msg("Really quit?");
923:
924: wrefresh(cw);
925:
926: if (readchar() == 'y')
927: {
928: clear();
929: wclear(cw);
930: wrefresh(cw);
931: move(LINES - 1, 0);
932: wrefresh(stdscr);
933: score(pstats.s_exp, pstats.s_lvl, CHICKEN, 0);
934: byebye();
935: }
936: else
937: {
938: signal(SIGINT, quit_handler);
939: wmove(cw, 0, 0);
940: wclrtoeol(cw);
941: status(FALSE);
942: wrefresh(cw);
943: mpos = 0;
944: count = 0;
945: fighting = running = 0;
946: }
947: }
948:
949: /*
950: search()
951: Player gropes about him to find hidden things.
952: */
953:
954: void
955: search(int is_thief)
956: {
957: int x, y;
958: char ch;
959:
960: /*
961: * Look all around the hero, if there is something hidden there, give
962: * him a chance to find it. If its found, display it.
963: */
964:
965: if (on(player, ISBLIND))
966: return;
967:
968: for (x = hero.x - 1; x <= hero.x + 1; x++)
969: for (y = hero.y - 1; y <= hero.y + 1; y++)
970: {
971: ch = winat(y, x);
972:
973: if (isatrap(ch))
974: {
975: static char trname[1024]; /* temp scratch space */
976: struct trap *tp;
977: struct room *rp;
978:
979: if (isatrap( mvwinch(cw, y, x)))
980: continue;
981:
982: tp = trap_at(y, x);
983:
984: if ((tp->tr_flags & ISTHIEFSET) ||
985: (rnd(100) > 50 && !is_thief))
986: break;
987:
988: rp = roomin(hero);
989:
990: if (tp->tr_type == FIRETRAP && rp != NULL)
991: {
992: rp->r_flags &= ~ISDARK;
993: light(&hero);
994: }
995:
996: tp->tr_flags |= ISFOUND;
997: mvwaddch(cw, y, x, ch);
998: count = 0;
999: running = FALSE;
1000: msg(tr_name(tp->tr_type,trname));
1001: }
1002: else if (ch == SECRETDOOR)
1003: {
1004: if (rnd(100) < 20 && !is_thief)
1005: {
1006: mvaddch(y, x, DOOR);
1007: count = 0;
1008: }
1009: }
1010: }
1011: }
1012:
1013: /*
1014: help()
1015: Give single character help, or the whole mess if he wants it
1016: */
1017:
1018: void
1019: help(void)
1020: {
1021: const struct h_list *strp = helpstr;
1022: char helpch;
1023: int cnt;
1024:
1025: msg("Character you want help for (* for all): ");
1026: helpch = readchar();
1027: mpos = 0;
1028:
1029: /*
1030: * If its not a *, print the right help string or an error if he
1031: * typed a funny character.
1032: */
1033:
1034: if (helpch != '*')
1035: {
1036: wmove(cw, 0, 0);
1037:
1038: while (strp->h_ch)
1039: {
1040: if (strp->h_desc == 0)
1041: if (!wizard)
1042: break;
1043: else
1044: {
1045: strp++;
1046: continue;
1047: }
1048:
1049: if (strp->h_ch == helpch)
1050: {
1051: msg("%s%s", unctrl(strp->h_ch), strp->h_desc);
1052: break;
1053: }
1054: strp++;
1055: }
1056:
1057: if (strp->h_ch != helpch)
1058: msg("Unknown character '%s'.", unctrl(helpch));
1059:
1060: return;
1061: }
1062:
1063: /*
1064: * Here we print help for everything. Then wait before we return to
1065: * command mode
1066: */
1067:
1068: wclear(hw);
1069: cnt = 0;
1070:
1071: while (strp->h_ch)
1072: {
1073: if (strp->h_desc == 0)
1074: if (!wizard)
1075: break;
1076: else
1077: {
1078: strp++;
1079: continue;
1080: }
1081:
1082: mvwaddstr(hw, cnt % 23, cnt > 22 ? 40 : 0, unctrl(strp->h_ch));
1083: waddstr(hw, strp->h_desc);
1084: strp++;
1085:
1086: if (++cnt >= 46 && strp->h_ch && (strp->h_desc != NULL || wizard))
1087: {
1088: wmove(hw, LINES - 1, 0);
1089: wprintw(hw, (char *) morestr);
1090: wrefresh(hw);
1091: wait_for(' ');
1092: wclear(hw);
1093: cnt = 0;
1094: }
1095: }
1096:
1097: wmove(hw, LINES - 1, 0);
1098: wprintw(hw, (char *) morestr);
1099: wrefresh(hw);
1100: wait_for(' ');
1101: wclear(hw);
1102: wrefresh(hw);
1103:
1104: wmove(cw, 0, 0);
1105: wclrtoeol(cw);
1106: status(FALSE);
1107: touchwin(cw);
1108:
1109: return;
1110: }
1111:
1112: /*
1113: identify()
1114: Tell the player what a certain thing is.
1115: */
1116:
1117: void
1118: identify(void)
1119: {
1120: int ch;
1121: char *str;
1122:
1123: msg("What do you want identified? ");
1124: mpos = 0;
1125:
1126: if ((ch = readchar()) == ESCAPE)
1127: {
1128: msg("");
1129: return;
1130: }
1131:
1132: if (isalpha(ch))
1133: {
1134: id_monst(ch);
1135: return;
1136: }
1137:
1138: switch (ch)
1139: {
1140: case '|':
1141: case '-': str = "wall of a room"; break;
1142: case GOLD: str = "gold"; break;
1143: case STAIRS: str = "passage leading down"; break;
1144: case DOOR: str = "door"; break;
1145: case FLOOR: str = "room floor"; break;
1146: case VPLAYER: str = "The hero of the game ---> you"; break;
1147: case IPLAYER: str = "you (but invisible)"; break;
1148: case PASSAGE: str = "passage"; break;
1149: case POST: str = "trading post"; break;
1150: case POOL: str = "a shimmering pool"; break;
1151: case TRAPDOOR: str = "trapdoor"; break;
1152: case ARROWTRAP: str = "arrow trap"; break;
1153: case SLEEPTRAP: str = "sleeping gas trap"; break;
1154: case BEARTRAP: str = "bear trap"; break;
1155: case TELTRAP: str = "teleport trap"; break;
1156: case DARTTRAP: str = "dart trap"; break;
1157: case MAZETRAP: str = "entrance to a maze"; break;
1158: case FIRETRAP: str = "fire trap"; break;
1159: case POISONTRAP: str = "poison pool trap"; break;
1160: case LAIR: str = "monster lair entrance"; break;
1161: case RUSTTRAP: str = "rust trap"; break;
1162: case POTION: str = "potion"; break;
1163: case SCROLL: str = "scroll"; break;
1164: case FOOD: str = "food"; break;
1165: case WEAPON: str = "weapon"; break;
1166: case ' ': str = "solid rock"; break;
1167: case ARMOR: str = "armor"; break;
1168: case ARTIFACT: str = "an artifact from bygone ages"; break;
1169: case RING: str = "ring"; break;
1170: case STICK: str = "wand or staff"; break;
1171: default: str = "unknown character"; break;
1172: }
1173: msg("'%s'; %s", unctrl(ch), str);
1174: }
1175:
1176: /*
1177: d_level()
1178: He wants to go down a level
1179: */
1180:
1181: void
1182: d_level(void)
1183: {
1184: int no_phase = FALSE;
1185:
1186: if (mvinch(hero.y, hero.x) != STAIRS)
1187: {
1188: if (off(player, CANINWALL)) /* Must use stairs if can't phase */
1189: {
1190: msg("I see no way down.");
1191: return;
1192: }
1193:
1194: extinguish_fuse(FUSE_UNPHASE);/*Using phase to go down gets rid of it*/
1195: no_phase = TRUE;
1196: }
1197:
1198: if (is_wearing(R_LEVITATION) || on(player, CANFLY))
1199: {
1200: msg("You can't! You're floating in the air.");
1201: return;
1202: }
1203:
1204: if (rnd(pstats.s_dext) < 3 * (2 - hitweight() +
1205: (on(player, STUMBLER) ? 4 : 0)))
1206: {
1207: msg("You trip and fall down the stairs.");
1208:
1209: if ((pstats.s_hpt -= roll(1, 10)) <= 0)
1210: {
1211: msg("You break your neck and die.");
1212: death(D_FALL);
1213: return;
1214: }
1215: }
1216:
1217: level++;
1218: new_level(NORMLEV,0);
1219:
1220: if (no_phase)
1221: unphase(NULL);
1222:
1223: return;
1224: }
1225:
1226: /*
1227: u_level()
1228: He wants to go up a level
1229: */
1230:
1231: void
1232: u_level(void)
1233: {
1234: char ch = 0;
1235:
1236: if (has_artifact && ((ch = CCHAR(mvinch(hero.y, hero.x))) == STAIRS ||
1237: (on(player, CANINWALL)
1238: && (is_wearing(R_LEVITATION) || on(player, CANFLY)))))
1239: {
1240: if (--level == 0)
1241: total_winner();
1242: else if (rnd(wizard ? 3 : 15) == 0)
1243: new_level(THRONE,0);
1244: else
1245: {
1246: new_level(NORMLEV,0);
1247: msg("You feel a wrenching sensation in your gut.");
1248: }
1249:
1250: if (on(player, CANINWALL) && ch != STAIRS)
1251: {
1252: extinguish_fuse(FUSE_UNPHASE);
1253: unphase(NULL);
1254: }
1255:
1256: return;
1257: }
1258: else if (ch != STAIRS &&
1259: !(on(player, CANINWALL) && (is_wearing(R_LEVITATION)
1260: || on(player, CANFLY))))
1261: msg("I see no way up.");
1262: else
1263: msg("Your way is magically blocked.");
1264:
1265: return;
1266: }
1267:
1268: /*
1269: call()
1270: allow a user to call a potion, scroll, or ring something
1271: */
1272:
1273: void
1274: call(int mark)
1275: {
1276: struct object *obj;
1277: char *elsewise;
1278: int item_type = numthings;
1279: char **item_color = NULL;
1280:
1281: if (mark)
1282: obj = get_object(pack, "mark", 0, bff_markable);
1283: else
1284: obj = get_object(pack, "call", 0, bff_callable);
1285:
1286: if (obj == NULL)
1287: return;
1288:
1289: switch (obj->o_type)
1290: {
1291: case RING:
1292: item_type = TYP_RING;
1293: item_color = r_stones;
1294: break;
1295: case POTION:
1296: item_type = TYP_POTION;
1297: item_color = p_colors;
1298: break;
1299: case SCROLL:
1300: item_type = TYP_SCROLL;
1301: item_color = s_names;
1302: break;
1303: case STICK:
1304: item_type = TYP_STICK;
1305: item_color = ws_made;
1306: break;
1307: default:
1308: if (!mark)
1309: {
1310: msg("You can't call that anything.");
1311: return;
1312: }
1313: break;
1314: }
1315:
1316: if (!mark && know_items[item_type][obj->o_which])
1317: {
1318: msg("That has already been identified.");
1319: return;
1320: }
1321:
1322: if (mark)
1323: {
1324: if (obj->o_mark[0])
1325: msg("Was marked \"%s\".", obj->o_mark);
1326:
1327: msg("What do you want to mark it? ");
1328: prbuf[0] = '\0';
1329: }
1330: else
1331: {
1332: elsewise = (guess_items[item_type][obj->o_which] != NULL ?
1333: guess_items[item_type][obj->o_which] : item_color[obj->o_which]);
1334:
1335: msg("Was called \"%s\".", elsewise);
1336: msg("What do you want to call it? ");
1337:
1338: if (guess_items[item_type][obj->o_which] != NULL)
1339: ur_free(guess_items[item_type][obj->o_which]);
1340:
1341: strcpy(prbuf, elsewise);
1342: }
1343:
1344: if (get_string(prbuf, cw) == NORM)
1345: {
1346: if (mark)
1347: {
1348: strncpy(obj->o_mark, prbuf, MARKLEN - 1);
1349: obj->o_mark[MARKLEN - 1] = '\0';
1350: }
1351: else
1352: {
1353: guess_items[item_type][obj->o_which] = new_alloc(strlen(prbuf) + 1);
1354: strcpy(guess_items[item_type][obj->o_which], prbuf);
1355: }
1356: }
1357:
1358: return;
1359: }
1360:
1361: /*
1362: att_bonus()
1363: bonus attacks for certain player classes
1364: */
1365:
1366: int
1367: att_bonus(void)
1368: {
1369: int bonus = FALSE;
1370:
1371: if ((player.t_ctype == C_FIGHTER || player.t_ctype == C_PALADIN)
1372: && (pstats.s_lvl > 12 ||
1373: (pstats.s_lvl > 6 && pstats.s_lvl < 13 && rnd(2))))
1374: bonus = TRUE;
1375:
1376: else if ((player.t_ctype == C_RANGER)
1377: && (pstats.s_lvl > 14 ||
1378: (pstats.s_lvl > 7 && pstats.s_lvl < 15 && rnd(2))))
1379: bonus = TRUE;
1380:
1381: else if ((player.t_ctype == C_NINJA)
1382: && (pstats.s_lvl > 8 ||
1383: (pstats.s_lvl > 4 && pstats.s_lvl < 9 && rnd(2))))
1384: bonus = TRUE;
1385:
1386: return(bonus);
1387: }
CVSweb