Mercurial > hg > early-roguelike
comparison urogue/command.c @ 256:c495a4f288c6
Import UltraRogue from the Roguelike Restoration Project (r1490)
author | John "Elwin" Edwards |
---|---|
date | Tue, 31 Jan 2017 19:56:04 -0500 |
parents | |
children | 911f0aa6e758 |
comparison
equal
deleted
inserted
replaced
253:d9badb9c0179 | 256:c495a4f288c6 |
---|---|
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 exit(0); | |
370 } | |
371 break; | |
372 | |
373 /* | |
374 * Other misc commands | |
375 */ | |
376 | |
377 case '.': break; /* rest */ | |
378 case ',': add_pack(NULL, NOMESSAGE); break; | |
379 case 'q': quaff(&player, -1, ISNORMAL); break; | |
380 case 'r': read_scroll(&player, -1, ISNORMAL); break; | |
381 case 'd': drop(NULL); break; | |
382 case '^': set_trap(&player, hero.y, hero.x); break; | |
383 case 'c': incant(&player, nullcoord); break; | |
384 case 'D': dip_it(); break; | |
385 case 'e': eat(); break; | |
386 case '=': listen(); break; | |
387 case 'A': apply(); break; | |
388 case 'w': wield(); break; | |
389 case 'W': wear(); break; | |
390 case 'T': take_off(); break; | |
391 case 'P': ring_on(); break; | |
392 case 'R': ring_off(); break; | |
393 case 'p': prayer(); break; | |
394 case 'C': call(FALSE); break; | |
395 case 'M': call(TRUE); break; | |
396 case 's': search(FALSE); break; | |
397 | |
398 /* | |
399 * Directional commands - get_dir sets delta | |
400 */ | |
401 case 20: /* ctrl-t */ | |
402 if (get_dir()) | |
403 steal(); | |
404 else | |
405 after = FALSE; | |
406 break; | |
407 | |
408 case 'z': | |
409 if (get_dir()) | |
410 do_zap(&player, -1, ISNORMAL); | |
411 else | |
412 after = FALSE; | |
413 break; | |
414 | |
415 case 'a': | |
416 if (get_dir()) | |
417 affect(); | |
418 else | |
419 after = FALSE; | |
420 touchwin(cw); | |
421 break; | |
422 | |
423 /* | |
424 * wizard commands | |
425 */ | |
426 | |
427 case 0x17: /* ctrl-w */ | |
428 after = FALSE; | |
429 | |
430 if (!wizard) | |
431 { | |
432 if (!canwizard) | |
433 { | |
434 msg("Illegal command '^W'."); | |
435 break; | |
436 } | |
437 | |
438 if (passwd()) | |
439 { | |
440 msg("Welcome, oh mighty wizard."); | |
441 wizard = waswizard = TRUE; | |
442 } | |
443 else | |
444 { | |
445 msg("Incorrect password."); | |
446 break; | |
447 } | |
448 } | |
449 | |
450 msg("Wizard command: "); | |
451 mpos = 0; | |
452 ch = readchar(); | |
453 | |
454 switch (ch) | |
455 { | |
456 case 'v': | |
457 wiz_verbose = !wiz_verbose; | |
458 break; | |
459 | |
460 case 'e': | |
461 wizard = FALSE; | |
462 msg("Not wizard any more."); | |
463 break; | |
464 | |
465 case 's': activity(); break; | |
466 case 't': teleport(); break; | |
467 case 'm': overlay(mw, cw); break; | |
468 case 'f': overlay(stdscr, cw); break; | |
469 case 'i': inventory(lvl_obj, 0); break; | |
470 case 'c': buy_it('\0', ISNORMAL); break; | |
471 case 'I': whatis(NULL); break; | |
472 case 'F': | |
473 msg("food left: %d\tfood level: %d", | |
474 food_left,foodlev); | |
475 break; | |
476 case 'M': | |
477 creat_mons(&player, get_monster_number("create"), | |
478 MESSAGE); | |
479 break; | |
480 | |
481 case 'r': | |
482 msg("rnd(4)%d, rnd(40)%d, rnd(100)%d", | |
483 rnd(4), rnd(40), rnd(100)); | |
484 break; | |
485 | |
486 case 'C': | |
487 obj = get_object(pack, "charge", STICK, NULL); | |
488 | |
489 if (obj != NULL) | |
490 obj->o_charges = 10000; | |
491 | |
492 break; | |
493 | |
494 case 'w': | |
495 obj = get_object(pack, "price", 0, NULL); | |
496 | |
497 if (obj != NULL) | |
498 msg("Worth %d.", get_worth(obj)); | |
499 | |
500 break; | |
501 | |
502 case 'g': | |
503 { | |
504 int tlev; | |
505 | |
506 prbuf[0] = '\0'; | |
507 msg("Which level? "); | |
508 | |
509 if (get_string(prbuf, cw) == NORM) | |
510 { | |
511 msg(""); | |
512 | |
513 if ((tlev = atoi(prbuf)) < 1) | |
514 msg("Illegal level."); | |
515 else if (tlev > 3000) | |
516 { | |
517 levtype = THRONE; | |
518 level = tlev - 3000; | |
519 } | |
520 else if (tlev > 2000) | |
521 { | |
522 levtype = MAZELEV; | |
523 level = tlev - 2000; | |
524 } | |
525 else if (tlev > 1000) | |
526 { | |
527 levtype = POSTLEV; | |
528 level = tlev - 1000; | |
529 } | |
530 else | |
531 { | |
532 levtype = NORMLEV; | |
533 level = tlev; | |
534 } | |
535 | |
536 new_level(levtype,0); | |
537 } | |
538 } | |
539 break; | |
540 | |
541 case 'o': make_omnipotent(); break; | |
542 | |
543 case ESCAPE: /* Escape */ | |
544 door_stop = FALSE; | |
545 | |
546 count = 0; | |
547 after = FALSE; | |
548 break; | |
549 | |
550 default: | |
551 msg("Illegal wizard command '%s', %d.", | |
552 unctrl(ch), ch); | |
553 count = 0; | |
554 break; | |
555 | |
556 } | |
557 | |
558 break; | |
559 | |
560 default: | |
561 msg("Illegal command '%s', %d.", | |
562 unctrl(ch), ch); | |
563 count = 0; | |
564 after = FALSE; | |
565 break; | |
566 } | |
567 | |
568 /* | |
569 * turn off flags if no longer needed | |
570 */ | |
571 if (!running) | |
572 door_stop = FALSE; | |
573 } | |
574 | |
575 /* | |
576 * If he ran into something to take, let him pick it up. | |
577 */ | |
578 if (take != 0) | |
579 if (!moving) | |
580 pick_up(take); | |
581 else | |
582 show_floor(); | |
583 if (!running) | |
584 door_stop = FALSE; | |
585 } /* end while */ | |
586 } | |
587 | |
588 | |
589 void | |
590 do_after_effects(void) | |
591 { | |
592 int i; | |
593 | |
594 /* Kick off the rest of the daemons and fuses */ | |
595 | |
596 look(FALSE); | |
597 do_daemons(AFTER); | |
598 do_fuses(AFTER); | |
599 | |
600 /* Special abilities */ | |
601 | |
602 if ((player.t_ctype == C_THIEF || player.t_ctype == C_ASSASIN || | |
603 player.t_ctype == C_NINJA || player.t_ctype == C_RANGER) && | |
604 (rnd(100) < (2 * pstats.s_dext + 5 * pstats.s_lvl))) | |
605 search(TRUE); | |
606 | |
607 for (i = 0; i < ring_value(R_SEARCH); i++) | |
608 search(FALSE); | |
609 | |
610 if (is_wearing(R_TELEPORT) && rnd(50) < 2) | |
611 { | |
612 teleport(); | |
613 | |
614 if (off(player, ISCLEAR)) | |
615 { | |
616 if (on(player, ISHUH)) | |
617 lengthen_fuse(FUSE_UNCONFUSE, rnd(8) + HUHDURATION); | |
618 else | |
619 light_fuse(FUSE_UNCONFUSE, 0, rnd(8) + HUHDURATION, AFTER); | |
620 | |
621 turn_on(player, ISHUH); | |
622 } | |
623 else | |
624 msg("You feel dizzy for a moment, but it quickly passes."); | |
625 } | |
626 | |
627 /* accidents and general clumsiness */ | |
628 | |
629 if (fighting && rnd(50) == 0) | |
630 { | |
631 msg("You become tired of this nonsense."); | |
632 fighting = after = FALSE; | |
633 } | |
634 | |
635 if (on(player, ISELECTRIC)) | |
636 electrificate(); | |
637 | |
638 if (!fighting && (no_command == 0) && cur_weapon != NULL | |
639 && rnd(on(player, STUMBLER) ? 399 : 9999) == 0 | |
640 && rnd(pstats.s_dext) < | |
641 2 - hitweight() + (on(player, STUMBLER) ? 4 : 0)) | |
642 { | |
643 msg("You trip and stumble over your weapon."); | |
644 running = after = FALSE; | |
645 | |
646 if (rnd(8) == 0 && (pstats.s_hpt -= roll(1, 10)) <= 0) | |
647 { | |
648 msg("You break your neck and die."); | |
649 death(D_FALL); | |
650 return; | |
651 } | |
652 else if (cur_weapon->o_flags & ISPOISON && rnd(4) == 0) | |
653 { | |
654 msg("You are cut by your %s!", | |
655 inv_name(cur_weapon, LOWERCASE)); | |
656 | |
657 if (player.t_ctype != C_PALADIN | |
658 && !(player.t_ctype == C_NINJA && | |
659 pstats.s_lvl > 12) | |
660 && !save(VS_POISON)) | |
661 { | |
662 if (pstats.s_hpt == 1) | |
663 { | |
664 msg("You die from the poison in the cut."); | |
665 death(D_POISON); | |
666 return; | |
667 } | |
668 else | |
669 { | |
670 msg("You feel very sick now."); | |
671 pstats.s_hpt /= 2; | |
672 chg_str(-2, FALSE, FALSE); | |
673 } | |
674 } | |
675 } | |
676 } | |
677 | |
678 /* Time to enforce weapon and armor restrictions */ | |
679 if (rnd(9999) == 0) | |
680 if (((cur_weapon == NULL) || | |
681 (wield_ok(&player, cur_weapon, NOMESSAGE))) | |
682 && ((cur_armor == NULL) || | |
683 (wear_ok(&player, cur_armor, NOMESSAGE)))) | |
684 { | |
685 switch (player.t_ctype) | |
686 { | |
687 case C_CLERIC: | |
688 case C_DRUID: | |
689 case C_RANGER: | |
690 case C_PALADIN: | |
691 if (rnd(luck) != 0) | |
692 /* You better have done | |
693 * little wrong */ | |
694 goto bad_cleric; | |
695 | |
696 msg("You are enraptured by the renewed " | |
697 "power of your god."); | |
698 break; | |
699 | |
700 case C_MAGICIAN: | |
701 case C_ILLUSION: | |
702 msg("You become in tune with the universe."); | |
703 break; | |
704 | |
705 case C_THIEF: | |
706 case C_NINJA: | |
707 case C_ASSASIN: | |
708 msg("You become supernaly sensitive to your " | |
709 "surroundings."); | |
710 break; | |
711 | |
712 case C_FIGHTER: | |
713 msg("You catch your second wind."); | |
714 break; | |
715 | |
716 default: | |
717 msg("What a strange type you are!"); | |
718 break; | |
719 } | |
720 pstats.s_hpt = max_stats.s_hpt += rnd(pstats.s_lvl) + 1; | |
721 pstats.s_power = max_stats.s_power += rnd(pstats.s_lvl) + 1; | |
722 } | |
723 else | |
724 { /* he blew it - make him pay */ | |
725 | |
726 int death_cause = 0; | |
727 | |
728 switch (player.t_ctype) | |
729 { | |
730 case C_CLERIC: | |
731 case C_DRUID: | |
732 case C_RANGER: | |
733 case C_PALADIN: | |
734 bad_cleric: | |
735 msg("Your god scourges you for your misdeeds."); | |
736 death_cause = D_GODWRATH; | |
737 break; | |
738 | |
739 case C_MAGICIAN: | |
740 case C_ILLUSION: | |
741 msg("You short out your manna on the unfamiliar %s.", | |
742 (cur_armor != NULL ? "armor" : "weapon")); | |
743 | |
744 death_cause = D_SPELLFUMBLE; | |
745 break; | |
746 | |
747 case C_THIEF: | |
748 case C_NINJA: | |
749 case C_ASSASIN: | |
750 msg("You trip and fall because of the unfamiliar %s.", | |
751 (cur_armor != NULL ? "armor" : "weapon")); | |
752 death_cause = D_CLUMSY; | |
753 break; | |
754 | |
755 case C_FIGHTER: | |
756 debug("Fighter getting raw deal?"); | |
757 break; | |
758 | |
759 default: | |
760 msg("What a strange type you are!"); | |
761 break; | |
762 } | |
763 | |
764 aggravate(); | |
765 pstats.s_power /= 2; | |
766 pstats.s_hpt /= 2; | |
767 player.t_no_move++; | |
768 | |
769 if ((pstats.s_hpt -= rnd(pstats.s_lvl)) <= 0) | |
770 { | |
771 death(death_cause); | |
772 } | |
773 } | |
774 | |
775 if (rnd(500000) == 0) | |
776 { | |
777 new_level(THRONE,0); | |
778 fighting = running = after = FALSE; | |
779 command(); | |
780 } | |
781 } | |
782 | |
783 void | |
784 make_omnipotent(void) | |
785 { | |
786 int i; | |
787 struct linked_list *item; | |
788 struct object *obj; | |
789 | |
790 for (i = 0; i < 20; i++) | |
791 raise_level(); | |
792 | |
793 max_stats.s_hpt += 1000; | |
794 max_stats.s_power += 1000; | |
795 pstats.s_hpt = max_stats.s_hpt; | |
796 pstats.s_power = max_stats.s_power; | |
797 max_stats.s_str = pstats.s_str = 25; | |
798 max_stats.s_intel = pstats.s_intel = 25; | |
799 max_stats.s_wisdom = pstats.s_wisdom = 25; | |
800 max_stats.s_dext = pstats.s_dext = 25; | |
801 max_stats.s_const = pstats.s_const = 25; | |
802 | |
803 if (cur_weapon == NULL || cur_weapon->o_which != CLAYMORE) | |
804 { | |
805 item = spec_item(WEAPON, CLAYMORE, 10, 10); | |
806 cur_weapon = OBJPTR(item); | |
807 cur_weapon->o_flags |= ISKNOW; | |
808 add_pack(item, NOMESSAGE); | |
809 } | |
810 | |
811 /* and a kill-o-zap stick */ | |
812 | |
813 item = spec_item(STICK, WS_DISINTEGRATE, 10000, 0); | |
814 obj = OBJPTR(item); | |
815 obj->o_flags |= ISKNOW; | |
816 know_items[TYP_STICK][WS_DISINTEGRATE] = TRUE; | |
817 | |
818 if (guess_items[TYP_STICK][WS_DISINTEGRATE]) | |
819 { | |
820 ur_free(guess_items[TYP_STICK][WS_DISINTEGRATE]); | |
821 guess_items[TYP_STICK][WS_DISINTEGRATE] = NULL; | |
822 } | |
823 | |
824 add_pack(item, NOMESSAGE); | |
825 | |
826 /* and his suit of armor */ | |
827 | |
828 if (cur_armor == NULL || | |
829 !(cur_armor->o_which == CRYSTAL_ARMOR || | |
830 cur_armor->o_which == MITHRIL)) | |
831 { | |
832 item = spec_item(ARMOR, CRYSTAL_ARMOR, 15, 0); | |
833 obj = OBJPTR(item); | |
834 obj->o_flags |= ISKNOW; | |
835 obj->o_weight = | |
836 (int) (armors[CRYSTAL_ARMOR].a_wght * 0.2); | |
837 cur_armor = obj; | |
838 add_pack(item, NOMESSAGE); | |
839 } | |
840 | |
841 /* and some rings (have to put them on, for now) */ | |
842 | |
843 | |
844 if (!is_wearing(R_SEARCH)) | |
845 { | |
846 item = spec_item(RING, R_SEARCH, 0, 0); | |
847 obj = OBJPTR(item); | |
848 obj->o_flags |= ISKNOW; | |
849 know_items[TYP_RING][R_SEARCH] = TRUE; | |
850 | |
851 if (guess_items[TYP_RING][R_SEARCH]) | |
852 { | |
853 ur_free(guess_items[TYP_RING][R_SEARCH]); | |
854 guess_items[TYP_RING][R_SEARCH] = NULL; | |
855 } | |
856 | |
857 add_pack(item, NOMESSAGE); | |
858 } | |
859 | |
860 if (!is_wearing(R_PIETY)) | |
861 { | |
862 item = spec_item(RING, R_PIETY, 0, 0); | |
863 obj = OBJPTR(item); | |
864 obj->o_flags |= ISKNOW; | |
865 know_items[TYP_RING][R_PIETY] = TRUE; | |
866 | |
867 if (guess_items[TYP_RING][R_PIETY]) | |
868 { | |
869 ur_free(guess_items[TYP_RING][R_PIETY]); | |
870 guess_items[TYP_RING][R_PIETY] = NULL; | |
871 } | |
872 | |
873 add_pack(item, NOMESSAGE); | |
874 } | |
875 | |
876 item = spec_item(SCROLL, S_ELECTRIFY, 0, 0); | |
877 obj = OBJPTR(item); | |
878 obj->o_flags |= ISKNOW; | |
879 know_items[TYP_SCROLL][S_ELECTRIFY] = TRUE; | |
880 | |
881 if (guess_items[TYP_SCROLL][S_ELECTRIFY]) | |
882 { | |
883 ur_free(guess_items[TYP_SCROLL][S_ELECTRIFY]); | |
884 guess_items[TYP_SCROLL][S_ELECTRIFY] = NULL; | |
885 } | |
886 | |
887 add_pack(item, NOMESSAGE); | |
888 | |
889 /* Spiff him up a bit */ | |
890 quaff(&player, P_SHERO, ISBLESSED); | |
891 quaff(&player, P_CLEAR, ISBLESSED); | |
892 quaff(&player, P_FIRERESIST, ISBLESSED); | |
893 quaff(&player, P_TRUESEE, ISBLESSED); | |
894 quaff(&player, P_PHASE, ISBLESSED); | |
895 purse += 50000L; | |
896 updpack(); | |
897 } | |
898 | |
899 | |
900 /* | |
901 quit() | |
902 Have player make certain, then exit. | |
903 */ | |
904 | |
905 void | |
906 quit_handler(int sig) | |
907 { | |
908 if (signal(SIGINT, quit_handler) != quit_handler) | |
909 mpos = 0; | |
910 | |
911 sig = 0; | |
912 | |
913 quit(); | |
914 } | |
915 | |
916 void | |
917 quit(void) | |
918 { | |
919 msg("Really quit?"); | |
920 | |
921 wrefresh(cw); | |
922 | |
923 if (readchar() == 'y') | |
924 { | |
925 clear(); | |
926 wclear(cw); | |
927 wrefresh(cw); | |
928 move(LINES - 1, 0); | |
929 wrefresh(stdscr); | |
930 score(pstats.s_exp, pstats.s_lvl, CHICKEN, 0); | |
931 byebye(); | |
932 } | |
933 else | |
934 { | |
935 signal(SIGINT, quit_handler); | |
936 wmove(cw, 0, 0); | |
937 wclrtoeol(cw); | |
938 status(FALSE); | |
939 wrefresh(cw); | |
940 mpos = 0; | |
941 count = 0; | |
942 fighting = running = 0; | |
943 } | |
944 } | |
945 | |
946 /* | |
947 search() | |
948 Player gropes about him to find hidden things. | |
949 */ | |
950 | |
951 void | |
952 search(int is_thief) | |
953 { | |
954 int x, y; | |
955 char ch; | |
956 | |
957 /* | |
958 * Look all around the hero, if there is something hidden there, give | |
959 * him a chance to find it. If its found, display it. | |
960 */ | |
961 | |
962 if (on(player, ISBLIND)) | |
963 return; | |
964 | |
965 for (x = hero.x - 1; x <= hero.x + 1; x++) | |
966 for (y = hero.y - 1; y <= hero.y + 1; y++) | |
967 { | |
968 ch = winat(y, x); | |
969 | |
970 if (isatrap(ch)) | |
971 { | |
972 static char trname[1024]; /* temp scratch space */ | |
973 struct trap *tp; | |
974 struct room *rp; | |
975 | |
976 if (isatrap( mvwinch(cw, y, x))) | |
977 continue; | |
978 | |
979 tp = trap_at(y, x); | |
980 | |
981 if ((tp->tr_flags & ISTHIEFSET) || | |
982 (rnd(100) > 50 && !is_thief)) | |
983 break; | |
984 | |
985 rp = roomin(hero); | |
986 | |
987 if (tp->tr_type == FIRETRAP && rp != NULL) | |
988 { | |
989 rp->r_flags &= ~ISDARK; | |
990 light(&hero); | |
991 } | |
992 | |
993 tp->tr_flags |= ISFOUND; | |
994 mvwaddch(cw, y, x, ch); | |
995 count = 0; | |
996 running = FALSE; | |
997 msg(tr_name(tp->tr_type,trname)); | |
998 } | |
999 else if (ch == SECRETDOOR) | |
1000 { | |
1001 if (rnd(100) < 20 && !is_thief) | |
1002 { | |
1003 mvaddch(y, x, DOOR); | |
1004 count = 0; | |
1005 } | |
1006 } | |
1007 } | |
1008 } | |
1009 | |
1010 /* | |
1011 help() | |
1012 Give single character help, or the whole mess if he wants it | |
1013 */ | |
1014 | |
1015 void | |
1016 help(void) | |
1017 { | |
1018 const struct h_list *strp = helpstr; | |
1019 char helpch; | |
1020 int cnt; | |
1021 | |
1022 msg("Character you want help for (* for all): "); | |
1023 helpch = readchar(); | |
1024 mpos = 0; | |
1025 | |
1026 /* | |
1027 * If its not a *, print the right help string or an error if he | |
1028 * typed a funny character. | |
1029 */ | |
1030 | |
1031 if (helpch != '*') | |
1032 { | |
1033 wmove(cw, 0, 0); | |
1034 | |
1035 while (strp->h_ch) | |
1036 { | |
1037 if (strp->h_desc == 0) | |
1038 if (!wizard) | |
1039 break; | |
1040 else | |
1041 { | |
1042 strp++; | |
1043 continue; | |
1044 } | |
1045 | |
1046 if (strp->h_ch == helpch) | |
1047 { | |
1048 msg("%s%s", unctrl(strp->h_ch), strp->h_desc); | |
1049 break; | |
1050 } | |
1051 strp++; | |
1052 } | |
1053 | |
1054 if (strp->h_ch != helpch) | |
1055 msg("Unknown character '%s'.", unctrl(helpch)); | |
1056 | |
1057 return; | |
1058 } | |
1059 | |
1060 /* | |
1061 * Here we print help for everything. Then wait before we return to | |
1062 * command mode | |
1063 */ | |
1064 | |
1065 wclear(hw); | |
1066 cnt = 0; | |
1067 | |
1068 while (strp->h_ch) | |
1069 { | |
1070 if (strp->h_desc == 0) | |
1071 if (!wizard) | |
1072 break; | |
1073 else | |
1074 { | |
1075 strp++; | |
1076 continue; | |
1077 } | |
1078 | |
1079 mvwaddstr(hw, cnt % 23, cnt > 22 ? 40 : 0, unctrl(strp->h_ch)); | |
1080 waddstr(hw, strp->h_desc); | |
1081 strp++; | |
1082 | |
1083 if (++cnt >= 46 && strp->h_ch && (strp->h_desc != NULL || wizard)) | |
1084 { | |
1085 wmove(hw, LINES - 1, 0); | |
1086 wprintw(hw, (char *) morestr); | |
1087 wrefresh(hw); | |
1088 wait_for(' '); | |
1089 wclear(hw); | |
1090 cnt = 0; | |
1091 } | |
1092 } | |
1093 | |
1094 wmove(hw, LINES - 1, 0); | |
1095 wprintw(hw, (char *) morestr); | |
1096 wrefresh(hw); | |
1097 wait_for(' '); | |
1098 wclear(hw); | |
1099 wrefresh(hw); | |
1100 | |
1101 wmove(cw, 0, 0); | |
1102 wclrtoeol(cw); | |
1103 status(FALSE); | |
1104 touchwin(cw); | |
1105 | |
1106 return; | |
1107 } | |
1108 | |
1109 /* | |
1110 identify() | |
1111 Tell the player what a certain thing is. | |
1112 */ | |
1113 | |
1114 void | |
1115 identify(void) | |
1116 { | |
1117 int ch; | |
1118 char *str; | |
1119 | |
1120 msg("What do you want identified? "); | |
1121 mpos = 0; | |
1122 | |
1123 if ((ch = readchar()) == ESCAPE) | |
1124 { | |
1125 msg(""); | |
1126 return; | |
1127 } | |
1128 | |
1129 if (isalpha(ch)) | |
1130 { | |
1131 id_monst(ch); | |
1132 return; | |
1133 } | |
1134 | |
1135 switch (ch) | |
1136 { | |
1137 case '|': | |
1138 case '-': str = "wall of a room"; break; | |
1139 case GOLD: str = "gold"; break; | |
1140 case STAIRS: str = "passage leading down"; break; | |
1141 case DOOR: str = "door"; break; | |
1142 case FLOOR: str = "room floor"; break; | |
1143 case VPLAYER: str = "The hero of the game ---> you"; break; | |
1144 case IPLAYER: str = "you (but invisible)"; break; | |
1145 case PASSAGE: str = "passage"; break; | |
1146 case POST: str = "trading post"; break; | |
1147 case POOL: str = "a shimmering pool"; break; | |
1148 case TRAPDOOR: str = "trapdoor"; break; | |
1149 case ARROWTRAP: str = "arrow trap"; break; | |
1150 case SLEEPTRAP: str = "sleeping gas trap"; break; | |
1151 case BEARTRAP: str = "bear trap"; break; | |
1152 case TELTRAP: str = "teleport trap"; break; | |
1153 case DARTTRAP: str = "dart trap"; break; | |
1154 case MAZETRAP: str = "entrance to a maze"; break; | |
1155 case FIRETRAP: str = "fire trap"; break; | |
1156 case POISONTRAP: str = "poison pool trap"; break; | |
1157 case LAIR: str = "monster lair entrance"; break; | |
1158 case RUSTTRAP: str = "rust trap"; break; | |
1159 case POTION: str = "potion"; break; | |
1160 case SCROLL: str = "scroll"; break; | |
1161 case FOOD: str = "food"; break; | |
1162 case WEAPON: str = "weapon"; break; | |
1163 case ' ': str = "solid rock"; break; | |
1164 case ARMOR: str = "armor"; break; | |
1165 case ARTIFACT: str = "an artifact from bygone ages"; break; | |
1166 case RING: str = "ring"; break; | |
1167 case STICK: str = "wand or staff"; break; | |
1168 default: str = "unknown character"; break; | |
1169 } | |
1170 msg("'%s'; %s", unctrl(ch), str); | |
1171 } | |
1172 | |
1173 /* | |
1174 d_level() | |
1175 He wants to go down a level | |
1176 */ | |
1177 | |
1178 void | |
1179 d_level(void) | |
1180 { | |
1181 int no_phase = FALSE; | |
1182 | |
1183 if (mvinch(hero.y, hero.x) != STAIRS) | |
1184 { | |
1185 if (off(player, CANINWALL)) /* Must use stairs if can't phase */ | |
1186 { | |
1187 msg("I see no way down."); | |
1188 return; | |
1189 } | |
1190 | |
1191 extinguish_fuse(FUSE_UNPHASE);/*Using phase to go down gets rid of it*/ | |
1192 no_phase = TRUE; | |
1193 } | |
1194 | |
1195 if (is_wearing(R_LEVITATION) || on(player, CANFLY)) | |
1196 { | |
1197 msg("You can't! You're floating in the air."); | |
1198 return; | |
1199 } | |
1200 | |
1201 if (rnd(pstats.s_dext) < 3 * (2 - hitweight() + | |
1202 (on(player, STUMBLER) ? 4 : 0))) | |
1203 { | |
1204 msg("You trip and fall down the stairs."); | |
1205 | |
1206 if ((pstats.s_hpt -= roll(1, 10)) <= 0) | |
1207 { | |
1208 msg("You break your neck and die."); | |
1209 death(D_FALL); | |
1210 return; | |
1211 } | |
1212 } | |
1213 | |
1214 level++; | |
1215 new_level(NORMLEV,0); | |
1216 | |
1217 if (no_phase) | |
1218 unphase(NULL); | |
1219 | |
1220 return; | |
1221 } | |
1222 | |
1223 /* | |
1224 u_level() | |
1225 He wants to go up a level | |
1226 */ | |
1227 | |
1228 void | |
1229 u_level(void) | |
1230 { | |
1231 char ch = 0; | |
1232 | |
1233 if (has_artifact && ((ch = CCHAR(mvinch(hero.y, hero.x))) == STAIRS || | |
1234 (on(player, CANINWALL) | |
1235 && (is_wearing(R_LEVITATION) || on(player, CANFLY))))) | |
1236 { | |
1237 if (--level == 0) | |
1238 total_winner(); | |
1239 else if (rnd(wizard ? 3 : 15) == 0) | |
1240 new_level(THRONE,0); | |
1241 else | |
1242 { | |
1243 new_level(NORMLEV,0); | |
1244 msg("You feel a wrenching sensation in your gut."); | |
1245 } | |
1246 | |
1247 if (on(player, CANINWALL) && ch != STAIRS) | |
1248 { | |
1249 extinguish_fuse(FUSE_UNPHASE); | |
1250 unphase(NULL); | |
1251 } | |
1252 | |
1253 return; | |
1254 } | |
1255 else if (ch != STAIRS && | |
1256 !(on(player, CANINWALL) && (is_wearing(R_LEVITATION) | |
1257 || on(player, CANFLY)))) | |
1258 msg("I see no way up."); | |
1259 else | |
1260 msg("Your way is magically blocked."); | |
1261 | |
1262 return; | |
1263 } | |
1264 | |
1265 /* | |
1266 call() | |
1267 allow a user to call a potion, scroll, or ring something | |
1268 */ | |
1269 | |
1270 void | |
1271 call(int mark) | |
1272 { | |
1273 struct object *obj; | |
1274 char *elsewise; | |
1275 int item_type = numthings; | |
1276 char **item_color = NULL; | |
1277 | |
1278 if (mark) | |
1279 obj = get_object(pack, "mark", 0, bff_markable); | |
1280 else | |
1281 obj = get_object(pack, "call", 0, bff_callable); | |
1282 | |
1283 if (obj == NULL) | |
1284 return; | |
1285 | |
1286 switch (obj->o_type) | |
1287 { | |
1288 case RING: | |
1289 item_type = TYP_RING; | |
1290 item_color = r_stones; | |
1291 break; | |
1292 case POTION: | |
1293 item_type = TYP_POTION; | |
1294 item_color = p_colors; | |
1295 break; | |
1296 case SCROLL: | |
1297 item_type = TYP_SCROLL; | |
1298 item_color = s_names; | |
1299 break; | |
1300 case STICK: | |
1301 item_type = TYP_STICK; | |
1302 item_color = ws_made; | |
1303 default: | |
1304 if (!mark) | |
1305 { | |
1306 msg("You can't call that anything."); | |
1307 return; | |
1308 } | |
1309 break; | |
1310 } | |
1311 | |
1312 elsewise = (guess_items[item_type][obj->o_which] != NULL ? | |
1313 guess_items[item_type][obj->o_which] : item_color[obj->o_which]); | |
1314 | |
1315 if (know_items[item_type][obj->o_which] && !mark) | |
1316 { | |
1317 msg("That has already been identified."); | |
1318 return; | |
1319 } | |
1320 | |
1321 if (mark) | |
1322 { | |
1323 if (obj->o_mark[0]) | |
1324 msg("Was marked \"%s\".", obj->o_mark); | |
1325 | |
1326 msg("What do you want to mark it? "); | |
1327 prbuf[0] = '\0'; | |
1328 } | |
1329 else | |
1330 { | |
1331 msg("Was called \"%s\".", elsewise); | |
1332 msg("What do you want to call it? "); | |
1333 | |
1334 if (guess_items[item_type][obj->o_which] != NULL) | |
1335 ur_free(guess_items[item_type][obj->o_which]); | |
1336 | |
1337 strcpy(prbuf, elsewise); | |
1338 } | |
1339 | |
1340 if (get_string(prbuf, cw) == NORM) | |
1341 { | |
1342 if (mark) | |
1343 { | |
1344 strncpy(obj->o_mark, prbuf, MARKLEN - 1); | |
1345 obj->o_mark[MARKLEN - 1] = '\0'; | |
1346 } | |
1347 else | |
1348 { | |
1349 guess_items[item_type][obj->o_which] = new_alloc(strlen(prbuf) + 1); | |
1350 strcpy(guess_items[item_type][obj->o_which], prbuf); | |
1351 } | |
1352 } | |
1353 | |
1354 return; | |
1355 } | |
1356 | |
1357 /* | |
1358 att_bonus() | |
1359 bonus attacks for certain player classes | |
1360 */ | |
1361 | |
1362 int | |
1363 att_bonus(void) | |
1364 { | |
1365 int bonus = FALSE; | |
1366 | |
1367 if ((player.t_ctype == C_FIGHTER || player.t_ctype == C_PALADIN) | |
1368 && (pstats.s_lvl > 12 || | |
1369 (pstats.s_lvl > 6 && pstats.s_lvl < 13 && rnd(2)))) | |
1370 bonus = TRUE; | |
1371 | |
1372 else if ((player.t_ctype == C_RANGER) | |
1373 && (pstats.s_lvl > 14 || | |
1374 (pstats.s_lvl > 7 && pstats.s_lvl < 15 && rnd(2)))) | |
1375 bonus = TRUE; | |
1376 | |
1377 else if ((player.t_ctype == C_NINJA) | |
1378 && (pstats.s_lvl > 8 || | |
1379 (pstats.s_lvl > 4 && pstats.s_lvl < 9 && rnd(2)))) | |
1380 bonus = TRUE; | |
1381 | |
1382 return(bonus); | |
1383 } |