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