1 /* source/moria1.c: misc code, mainly handles player movement, inventory, etc
2
3 Copyright (c) 1989-94 James E. Wilson, Robert A. Koeneke
4
5 This software may be copied and distributed for educational, research, and
6 not for profit purposes provided that this copyright and statement are
7 included in all such copies. */
8
9 #ifdef __TURBOC__
10 #include <stdlib.h>
11 #endif
12
13 #include <stdio.h>
14 #include <ctype.h>
15
16 #include "config.h"
17 #include "constant.h"
18 #include "types.h"
19 #include "externs.h"
20
21 #ifdef USG
22 #ifndef ATARIST_MWC
23 #include <string.h>
24 #else
25 char *strcat();
26 int strlen();
27 #endif
28 #else
29 #include <strings.h>
30 #endif
31
32 #if defined(LINT_ARGS)
33 static void inven_screen(int);
34 static char map_roguedir(char);
35 static void sub1_move_light(int, int, int, int);
36 static void sub3_move_light(int, int, int, int);
37 #endif
38
39 #ifdef ATARIST_TC
40 /* Include this to get prototypes for standard library functions. */
41 #include <stdlib.h>
42 #endif
43
44 /* Changes speed of monsters relative to player -RAK- */
45 /* Note: When the player is sped up or slowed down, I simply */
46 /* change the speed of all the monsters. This greatly */
47 /* simplified the logic. */
change_speed(num)48 void change_speed(num)
49 register int num;
50 {
51 register int i;
52 #ifdef ATARIST_MWC
53 int32u holder;
54 #endif
55
56 py.flags.speed += num;
57 #ifdef ATARIST_MWC
58 py.flags.status |= (holder = PY_SPEED);
59 #else
60 py.flags.status |= PY_SPEED;
61 #endif
62 for (i = mfptr - 1; i >= MIN_MONIX; i--)
63 m_list[i].cspeed += num;
64 }
65
66
67 /* Player bonuses -RAK- */
68 /* When an item is worn or taken off, this re-adjusts the player */
69 /* bonuses. Factor=1 : wear; Factor=-1 : removed */
70 /* Only calculates properties with cumulative effect. Properties that
71 depend on everything being worn are recalculated by calc_bonuses() -CJS- */
py_bonuses(t_ptr,factor)72 void py_bonuses(t_ptr, factor)
73 register inven_type *t_ptr;
74 register int factor;
75 {
76 register int i, amount;
77 #ifdef ATARIST_MWC
78 int32u holder;
79 #endif
80
81 amount = t_ptr->p1 * factor;
82 if (t_ptr->flags & TR_STATS)
83 {
84 for(i = 0; i < 6; i++)
85 if ((1 << i) & t_ptr->flags)
86 bst_stat(i, amount);
87 }
88 if (TR_SEARCH & t_ptr->flags)
89 {
90 py.misc.srh += amount;
91 py.misc.fos -= amount;
92 }
93 if (TR_STEALTH & t_ptr->flags)
94 py.misc.stl += amount;
95 if (TR_SPEED & t_ptr->flags)
96 change_speed(-amount);
97 #ifdef ATARIST_MWC
98 if (((holder = TR_BLIND) & t_ptr->flags) && (factor > 0))
99 py.flags.blind += 1000;
100 if (((holder = TR_TIMID) & t_ptr->flags) && (factor > 0))
101 py.flags.afraid += 50;
102 if ((holder = TR_INFRA) & t_ptr->flags)
103 py.flags.see_infra += amount;
104 #else
105 if ((TR_BLIND & t_ptr->flags) && (factor > 0))
106 py.flags.blind += 1000;
107 if ((TR_TIMID & t_ptr->flags) && (factor > 0))
108 py.flags.afraid += 50;
109 if (TR_INFRA & t_ptr->flags)
110 py.flags.see_infra += amount;
111 #endif
112 }
113
114 /* Recalculate the effect of all the stuff we use. -CJS- */
calc_bonuses()115 void calc_bonuses()
116 {
117 register int32u item_flags;
118 #if defined(ATARIST_MWC)
119 int32u holder; /* to avoid a compiler bug */
120 #endif
121 int old_dis_ac;
122 register struct flags *p_ptr;
123 register struct misc *m_ptr;
124 register inven_type *i_ptr;
125 register int i;
126
127 p_ptr = &py.flags;
128 m_ptr = &py.misc;
129 if (p_ptr->slow_digest)
130 p_ptr->food_digested++;
131 if (p_ptr->regenerate)
132 p_ptr->food_digested -= 3;
133 p_ptr->see_inv = FALSE;
134 p_ptr->teleport = FALSE;
135 p_ptr->free_act = FALSE;
136 p_ptr->slow_digest = FALSE;
137 p_ptr->aggravate = FALSE;
138 p_ptr->sustain_str = FALSE;
139 p_ptr->sustain_int = FALSE;
140 p_ptr->sustain_wis = FALSE;
141 p_ptr->sustain_con = FALSE;
142 p_ptr->sustain_dex = FALSE;
143 p_ptr->sustain_chr = FALSE;
144 p_ptr->fire_resist = FALSE;
145 p_ptr->acid_resist = FALSE;
146 p_ptr->cold_resist = FALSE;
147 p_ptr->regenerate = FALSE;
148 p_ptr->lght_resist = FALSE;
149 p_ptr->ffall = FALSE;
150
151 old_dis_ac = m_ptr->dis_ac;
152 m_ptr->ptohit = tohit_adj(); /* Real To Hit */
153 m_ptr->ptodam = todam_adj(); /* Real To Dam */
154 m_ptr->ptoac = toac_adj(); /* Real To AC */
155 m_ptr->pac = 0; /* Real AC */
156 m_ptr->dis_th = m_ptr->ptohit; /* Display To Hit */
157 m_ptr->dis_td = m_ptr->ptodam; /* Display To Dam */
158 m_ptr->dis_ac = 0; /* Display AC */
159 m_ptr->dis_tac = m_ptr->ptoac; /* Display To AC */
160 for (i = INVEN_WIELD; i < INVEN_LIGHT; i++)
161 {
162 i_ptr = &inventory[i];
163 if (i_ptr->tval != TV_NOTHING)
164 {
165 m_ptr->ptohit += i_ptr->tohit;
166 if (i_ptr->tval != TV_BOW) /* Bows can't damage. -CJS- */
167 m_ptr->ptodam += i_ptr->todam;
168 m_ptr->ptoac += i_ptr->toac;
169 m_ptr->pac += i_ptr->ac;
170 if (known2_p(i_ptr))
171 {
172 m_ptr->dis_th += i_ptr->tohit;
173 if (i_ptr->tval != TV_BOW)
174 m_ptr->dis_td += i_ptr->todam; /* Bows can't damage. -CJS- */
175 m_ptr->dis_tac += i_ptr->toac;
176 m_ptr->dis_ac += i_ptr->ac;
177 }
178 else if (! (TR_CURSED & i_ptr->flags))
179 /* Base AC values should always be visible, as long as the item
180 is not cursed. */
181 m_ptr->dis_ac += i_ptr->ac;
182 }
183 }
184 m_ptr->dis_ac += m_ptr->dis_tac;
185
186 if (weapon_heavy)
187 m_ptr->dis_th += (py.stats.use_stat[A_STR] * 15 -
188 inventory[INVEN_WIELD].weight);
189
190 /* Add in temporary spell increases */
191 if (p_ptr->invuln > 0)
192 {
193 m_ptr->pac += 100;
194 m_ptr->dis_ac += 100;
195 }
196 if (p_ptr->blessed > 0)
197 {
198 m_ptr->pac += 2;
199 m_ptr->dis_ac += 2;
200 }
201 if (p_ptr->detect_inv > 0)
202 p_ptr->see_inv = TRUE;
203
204 /* can't print AC here because might be in a store */
205 if (old_dis_ac != m_ptr->dis_ac)
206 #ifdef ATARIST_MWC
207 p_ptr->status |= (holder = PY_ARMOR);
208 #else
209 p_ptr->status |= PY_ARMOR;
210 #endif
211
212 item_flags = 0;
213 i_ptr = &inventory[INVEN_WIELD];
214 for (i = INVEN_WIELD; i < INVEN_LIGHT; i++)
215 {
216 item_flags |= i_ptr->flags;
217 i_ptr++;
218 }
219 #if !defined(ATARIST_MWC)
220 if (TR_SLOW_DIGEST & item_flags)
221 p_ptr->slow_digest = TRUE;
222 if (TR_AGGRAVATE & item_flags)
223 p_ptr->aggravate = TRUE;
224 if (TR_TELEPORT & item_flags)
225 p_ptr->teleport = TRUE;
226 if (TR_REGEN & item_flags)
227 p_ptr->regenerate = TRUE;
228 if (TR_RES_FIRE & item_flags)
229 p_ptr->fire_resist = TRUE;
230 if (TR_RES_ACID & item_flags)
231 p_ptr->acid_resist = TRUE;
232 if (TR_RES_COLD & item_flags)
233 p_ptr->cold_resist = TRUE;
234 if (TR_FREE_ACT & item_flags)
235 p_ptr->free_act = TRUE;
236 if (TR_SEE_INVIS & item_flags)
237 p_ptr->see_inv = TRUE;
238 if (TR_RES_LIGHT & item_flags)
239 p_ptr->lght_resist = TRUE;
240 if (TR_FFALL & item_flags)
241 p_ptr->ffall = TRUE;
242 #else
243 /* this avoids a bug in the Mark Williams C compiler for the Atari ST */
244 holder = TR_SLOW_DIGEST;
245 if (holder & item_flags)
246 p_ptr->slow_digest = TRUE;
247 holder = TR_AGGRAVATE;
248 if (holder & item_flags)
249 p_ptr->aggravate = TRUE;
250 holder = TR_TELEPORT;
251 if (holder & item_flags)
252 p_ptr->teleport = TRUE;
253 holder = TR_REGEN;
254 if (holder & item_flags)
255 p_ptr->regenerate = TRUE;
256 holder = TR_RES_FIRE;
257 if (holder & item_flags)
258 p_ptr->fire_resist = TRUE;
259 holder = TR_RES_ACID;
260 if (holder & item_flags)
261 p_ptr->acid_resist = TRUE;
262 holder = TR_RES_COLD;
263 if (holder & item_flags)
264 p_ptr->cold_resist = TRUE;
265 holder = TR_FREE_ACT;
266 if (holder & item_flags)
267 p_ptr->free_act = TRUE;
268 holder = TR_SEE_INVIS;
269 if (holder & item_flags)
270 p_ptr->see_inv = TRUE;
271 holder = TR_RES_LIGHT;
272 if (holder & item_flags)
273 p_ptr->lght_resist = TRUE;
274 holder = TR_FFALL;
275 if (holder & item_flags)
276 p_ptr->ffall = TRUE;
277 #endif
278
279 i_ptr = &inventory[INVEN_WIELD];
280 for (i = INVEN_WIELD; i < INVEN_LIGHT; i++)
281 {
282 #ifdef ATARIST_MWC
283 if ((holder = TR_SUST_STAT) & i_ptr->flags)
284 #else
285 if (TR_SUST_STAT & i_ptr->flags)
286 #endif
287 switch(i_ptr->p1)
288 {
289 case 1: p_ptr->sustain_str = TRUE; break;
290 case 2: p_ptr->sustain_int = TRUE; break;
291 case 3: p_ptr->sustain_wis = TRUE; break;
292 case 4: p_ptr->sustain_con = TRUE; break;
293 case 5: p_ptr->sustain_dex = TRUE; break;
294 case 6: p_ptr->sustain_chr = TRUE; break;
295 default: break;
296 }
297 i_ptr++;
298 }
299
300 if (p_ptr->slow_digest)
301 p_ptr->food_digested--;
302 if (p_ptr->regenerate)
303 p_ptr->food_digested += 3;
304 }
305
306
307 /* Displays inventory items from r1 to r2 -RAK- */
308 /* Designed to keep the display as far to the right as possible. The -CJS-
309 parameter col gives a column at which to start, but if the display does
310 not fit, it may be moved left. The return value is the left edge used. */
311 /* If mask is non-zero, then only display those items which have a non-zero
312 entry in the mask array. */
show_inven(r1,r2,weight,col,mask)313 int show_inven(r1, r2, weight, col, mask)
314 register int r1, r2;
315 int weight, col;
316 char *mask;
317 {
318 register int i;
319 int total_weight, len, l, lim, current_line;
320 bigvtype tmp_val;
321 vtype out_val[23];
322
323 len = 79 - col;
324 if (weight)
325 lim = 68;
326 else
327 lim = 76;
328
329 for (i = r1; i <= r2; i++) /* Print the items */
330 {
331 if (mask == CNIL || mask[i])
332 {
333 objdes(tmp_val, &inventory[i], TRUE);
334 tmp_val[lim] = 0; /* Truncate if too long. */
335 (void) sprintf(out_val[i], " %c) %s", 'a'+i, tmp_val);
336 l = strlen(out_val[i]);
337 if (weight)
338 l += 9;
339 if (l > len)
340 len = l;
341 }
342 }
343
344 col = 79 - len;
345 if (col < 0)
346 col = 0;
347
348 current_line = 1;
349 for (i = r1; i <= r2; i++)
350 {
351 if (mask == CNIL || mask[i])
352 {
353 /* don't need first two spaces if in first column */
354 if (col == 0)
355 prt(&out_val[i][2], current_line, col);
356 else
357 prt(out_val[i], current_line, col);
358 if (weight)
359 {
360 total_weight = inventory[i].weight*inventory[i].number;
361 (void) sprintf (tmp_val, "%3d.%d lb",
362 (total_weight) / 10, (total_weight) % 10);
363 prt (tmp_val, current_line, 71);
364 }
365 current_line++;
366 }
367 }
368 return col;
369 }
370
371
372 /* Return a string describing how a given equipment item is carried. -CJS- */
describe_use(i)373 char *describe_use(i)
374 register int i;
375 {
376 register char *p;
377
378 switch(i)
379 {
380 case INVEN_WIELD:
381 p = "wielding"; break;
382 case INVEN_HEAD:
383 p = "wearing on your head"; break;
384 case INVEN_NECK:
385 p = "wearing around your neck"; break;
386 case INVEN_BODY:
387 p = "wearing on your body"; break;
388 case INVEN_ARM:
389 p = "wearing on your arm"; break;
390 case INVEN_HANDS:
391 p = "wearing on your hands"; break;
392 case INVEN_RIGHT:
393 p = "wearing on your right hand"; break;
394 case INVEN_LEFT:
395 p = "wearing on your left hand"; break;
396 case INVEN_FEET:
397 p = "wearing on your feet"; break;
398 case INVEN_OUTER:
399 p = "wearing about your body"; break;
400 case INVEN_LIGHT:
401 p = "using to light the way"; break;
402 case INVEN_AUX:
403 p = "holding ready by your side"; break;
404 default:
405 p = "carrying in your pack"; break;
406 }
407 return p;
408 }
409
410
411 /* Displays equipment items from r1 to end -RAK- */
412 /* Keep display as far right as possible. -CJS- */
show_equip(weight,col)413 int show_equip(weight, col)
414 int weight, col;
415 {
416 register int i, line;
417 int total_weight, l, len, lim;
418 register char *prt1;
419 bigvtype prt2;
420 vtype out_val[INVEN_ARRAY_SIZE-INVEN_WIELD];
421 register inven_type *i_ptr;
422
423 line = 0;
424 len = 79 - col;
425 if (weight)
426 lim = 52;
427 else
428 lim = 60;
429 for (i = INVEN_WIELD; i < INVEN_ARRAY_SIZE; i++) /* Range of equipment */
430 {
431 i_ptr = &inventory[i];
432 if (i_ptr->tval != TV_NOTHING)
433 {
434 switch(i) /* Get position */
435 {
436 case INVEN_WIELD:
437 if (py.stats.use_stat[A_STR]*15 < i_ptr->weight)
438 prt1 = "Just lifting";
439 else
440 prt1 = "Wielding";
441 break;
442 case INVEN_HEAD:
443 prt1 = "On head"; break;
444 case INVEN_NECK:
445 prt1 = "Around neck"; break;
446 case INVEN_BODY:
447 prt1 = "On body"; break;
448 case INVEN_ARM:
449 prt1 = "On arm"; break;
450 case INVEN_HANDS:
451 prt1 = "On hands"; break;
452 case INVEN_RIGHT:
453 prt1 = "On right hand"; break;
454 case INVEN_LEFT:
455 prt1 = "On left hand"; break;
456 case INVEN_FEET:
457 prt1 = "On feet"; break;
458 case INVEN_OUTER:
459 prt1 = "About body"; break;
460 case INVEN_LIGHT:
461 prt1 = "Light source"; break;
462 case INVEN_AUX:
463 prt1 = "Spare weapon"; break;
464 default:
465 prt1 = "Unknown value"; break;
466 }
467 objdes(prt2, &inventory[i], TRUE);
468 prt2[lim] = 0; /* Truncate if necessary */
469 (void) sprintf(out_val[line], " %c) %-14s: %s", line+'a',
470 prt1, prt2);
471 l = strlen(out_val[line]);
472 if (weight)
473 l += 9;
474 if (l > len)
475 len = l;
476 line++;
477 }
478 }
479 col = 79 - len;
480 if (col < 0)
481 col = 0;
482
483 line = 0;
484 for (i = INVEN_WIELD; i < INVEN_ARRAY_SIZE; i++) /* Range of equipment */
485 {
486 i_ptr = &inventory[i];
487 if (i_ptr->tval != TV_NOTHING)
488 {
489 /* don't need first two spaces when using whole screen */
490 if (col == 0)
491 prt(&out_val[line][2], line+1, col);
492 else
493 prt(out_val[line], line+1, col);
494 if (weight)
495 {
496 total_weight = i_ptr->weight*i_ptr->number;
497 (void) sprintf(prt2, "%3d.%d lb",
498 (total_weight) / 10, (total_weight) % 10);
499 prt(prt2, line+1, 71);
500 }
501 line++;
502 }
503 }
504 erase_line(line+1, col);
505 return col;
506 }
507
508 /* Remove item from equipment list -RAK- */
takeoff(item_val,posn)509 void takeoff(item_val, posn)
510 int item_val, posn;
511 {
512 register char *p;
513 bigvtype out_val, prt2;
514 register inven_type *t_ptr;
515 #ifdef ATARIST_MWC
516 int32u holder;
517 #endif
518
519 equip_ctr--;
520 t_ptr = &inventory[item_val];
521 inven_weight -= t_ptr->weight*t_ptr->number;
522 #ifdef ATARIST_MWC
523 py.flags.status |= (holder = PY_STR_WGT);
524 #else
525 py.flags.status |= PY_STR_WGT;
526 #endif
527
528 if (item_val == INVEN_WIELD || item_val == INVEN_AUX)
529 p = "Was wielding ";
530 else if (item_val == INVEN_LIGHT)
531 p = "Light source was ";
532 else
533 p = "Was wearing ";
534
535 objdes(prt2, t_ptr, TRUE);
536 if (posn >= 0)
537 (void) sprintf(out_val, "%s%s (%c)", p, prt2, 'a'+posn);
538 else
539 (void) sprintf(out_val, "%s%s", p, prt2);
540 msg_print(out_val);
541 if (item_val != INVEN_AUX) /* For secondary weapon */
542 py_bonuses(t_ptr, -1);
543 invcopy(t_ptr, OBJ_NOTHING);
544 }
545
546
547 /* Used to verify if this really is the item we wish to -CJS-
548 wear or read. */
verify(prompt,item)549 int verify(prompt, item)
550 char *prompt;
551 int item;
552 {
553 bigvtype out_str, object;
554
555 objdes(object, &inventory[item], TRUE);
556 object[strlen(object)-1] = '?'; /* change the period to a question mark */
557 (void) sprintf(out_str, "%s %s", prompt, object);
558 return get_check(out_str);
559 }
560
561
562 /* All inventory commands (wear, exchange, take off, drop, inventory and
563 equipment) are handled in an alternative command input mode, which accepts
564 any of the inventory commands.
565
566 It is intended that this function be called several times in succession,
567 as some commands take up a turn, and the rest of moria must proceed in the
568 interim. A global variable is provided, doing_inven, which is normally
569 zero; however if on return from inven_command it is expected that
570 inven_command should be called *again*, (being still in inventory command
571 input mode), then doing_inven is set to the inventory command character
572 which should be used in the next call to inven_command.
573
574 On return, the screen is restored, but not flushed. Provided no flush of
575 the screen takes place before the next call to inven_command, the inventory
576 command screen is silently redisplayed, and no actual output takes place at
577 all. If the screen is flushed before a subsequent call, then the player is
578 prompted to see if we should continue. This allows the player to see any
579 changes that take place on the screen during inventory command input.
580
581 The global variable, screen_change, is cleared by inven_command, and set
582 when the screen is flushed. This is the means by which inven_command tell
583 if the screen has been flushed.
584
585 The display of inventory items is kept to the right of the screen to
586 minimize the work done to restore the screen afterwards. -CJS-*/
587
588 /* Inventory command screen states. */
589 #define BLANK_SCR 0
590 #define EQUIP_SCR 1
591 #define INVEN_SCR 2
592 #define WEAR_SCR 3
593 #define HELP_SCR 4
594 #define WRONG_SCR 5
595
596 /* Keep track of the state of the inventory screen. */
597 static int scr_state, scr_left, scr_base;
598 static int wear_low, wear_high;
599
600 /* Draw the inventory screen. */
inven_screen(new_scr)601 static void inven_screen(new_scr)
602 int new_scr;
603 {
604 register int line;
605
606 if (new_scr != scr_state)
607 {
608 scr_state = new_scr;
609 switch(new_scr)
610 {
611 case BLANK_SCR:
612 line = 0;
613 break;
614 case HELP_SCR:
615 if (scr_left > 52)
616 scr_left = 52;
617 prt(" ESC: exit", 1, scr_left);
618 prt(" w : wear or wield object", 2, scr_left);
619 prt(" t : take off item", 3, scr_left);
620 prt(" d : drop object", 4, scr_left);
621 prt(" x : exchange weapons", 5, scr_left);
622 prt(" i : inventory of pack", 6, scr_left);
623 prt(" e : list used equipment", 7, scr_left);
624 line = 7;
625 break;
626 case INVEN_SCR:
627 scr_left = show_inven(0, inven_ctr - 1, show_weight_flag, scr_left,
628 CNIL);
629 line = inven_ctr;
630 break;
631 case WEAR_SCR:
632 scr_left = show_inven(wear_low, wear_high, show_weight_flag,
633 scr_left, CNIL);
634 line = wear_high - wear_low + 1;
635 break;
636 case EQUIP_SCR:
637 scr_left = show_equip(show_weight_flag, scr_left);
638 line = equip_ctr;
639 break;
640 }
641 if (line >= scr_base)
642 {
643 scr_base = line + 1;
644 erase_line(scr_base, scr_left);
645 }
646 else
647 {
648 while (++line <= scr_base)
649 erase_line(line, scr_left);
650 }
651 }
652 }
653
654 /* This does all the work. */
inven_command(command)655 void inven_command(command)
656 char command;
657 {
658 register int slot, item;
659 int tmp, tmp2, selecting, from, to;
660 char *prompt, *swap, *disp, *string;
661 char which, query;
662 bigvtype prt1, prt2;
663 register inven_type *i_ptr;
664 inven_type tmp_obj;
665 #ifdef ATARIST_MWC
666 int32u holder;
667 #endif
668
669 free_turn_flag = TRUE;
670 save_screen();
671 /* Take up where we left off after a previous inventory command. -CJS- */
672 if (doing_inven)
673 {
674 /* If the screen has been flushed, we need to redraw. If the command is
675 a simple ' ' to recover the screen, just quit. Otherwise, check and
676 see what the user wants. */
677 if (screen_change)
678 {
679 if (command == ' ' || !get_check("Continuing with inventory command?"))
680 {
681 doing_inven = FALSE;
682 return;
683 }
684 scr_left = 50;
685 scr_base = 0;
686 }
687 tmp = scr_state;
688 scr_state = WRONG_SCR;
689 inven_screen(tmp);
690 }
691 else
692 {
693 scr_left = 50;
694 scr_base = 0;
695 /* this forces exit of inven_command() if selecting is not set true */
696 scr_state = BLANK_SCR;
697 }
698 do
699 {
700 if (isupper((int)command))
701 command = tolower((int)command);
702
703 /* Simple command getting and screen selection. */
704 selecting = FALSE;
705 switch(command)
706 {
707 case 'i': /* Inventory */
708 if (inven_ctr == 0)
709 msg_print("You are not carrying anything.");
710 else
711 inven_screen(INVEN_SCR);
712 break;
713 case 'e': /* Equipment */
714 if (equip_ctr == 0)
715 msg_print("You are not using any equipment.");
716 else
717 inven_screen(EQUIP_SCR);
718 break;
719 case 't': /* Take off */
720 if (equip_ctr == 0)
721 msg_print("You are not using any equipment.");
722 /* don't print message restarting inven command after taking off
723 something, it is confusing */
724 else if (inven_ctr >= INVEN_WIELD && !doing_inven)
725 msg_print("You will have to drop something first.");
726 else
727 {
728 if (scr_state != BLANK_SCR)
729 inven_screen(EQUIP_SCR);
730 selecting = TRUE;
731 }
732 break;
733 case 'd': /* Drop */
734 if (inven_ctr == 0 && equip_ctr == 0)
735 msg_print("But you're not carrying anything.");
736 else if (cave[char_row][char_col].tptr != 0)
737 msg_print("There's no room to drop anything here.");
738 else
739 {
740 selecting = TRUE;
741 if ((scr_state == EQUIP_SCR && equip_ctr > 0) || inven_ctr == 0)
742 {
743 if (scr_state != BLANK_SCR)
744 inven_screen(EQUIP_SCR);
745 command = 'r'; /* Remove - or take off and drop. */
746 }
747 else if (scr_state != BLANK_SCR)
748 inven_screen(INVEN_SCR);
749 }
750 break;
751 case 'w': /* Wear/wield */
752 for (wear_low = 0;
753 wear_low < inven_ctr && inventory[wear_low].tval > TV_MAX_WEAR;
754 wear_low++)
755 ;
756 for(wear_high = wear_low;
757 wear_high < inven_ctr && inventory[wear_high].tval >=TV_MIN_WEAR;
758 wear_high++)
759 ;
760 wear_high--;
761 if (wear_low > wear_high)
762 msg_print("You have nothing to wear or wield.");
763 else
764 {
765 if (scr_state != BLANK_SCR && scr_state != INVEN_SCR)
766 inven_screen(WEAR_SCR);
767 selecting = TRUE;
768 }
769 break;
770 case 'x':
771 if (inventory[INVEN_WIELD].tval == TV_NOTHING &&
772 inventory[INVEN_AUX].tval == TV_NOTHING)
773 msg_print("But you are wielding no weapons.");
774 #ifdef ATARIST_MWC
775 else if ((holder = TR_CURSED) & inventory[INVEN_WIELD].flags)
776 #else
777 else if (TR_CURSED & inventory[INVEN_WIELD].flags)
778 #endif
779 {
780 objdes(prt1, &inventory[INVEN_WIELD], FALSE);
781 (void) sprintf(prt2,
782 "The %s you are wielding appears to be cursed.", prt1);
783 msg_print(prt2);
784 }
785 else
786 {
787 free_turn_flag = FALSE;
788 tmp_obj = inventory[INVEN_AUX];
789 inventory[INVEN_AUX] = inventory[INVEN_WIELD];
790 inventory[INVEN_WIELD] = tmp_obj;
791 if (scr_state == EQUIP_SCR)
792 scr_left = show_equip(show_weight_flag, scr_left);
793 py_bonuses(&inventory[INVEN_AUX], -1); /* Subtract bonuses */
794 py_bonuses(&inventory[INVEN_WIELD], 1); /* Add bonuses */
795 if (inventory[INVEN_WIELD].tval != TV_NOTHING)
796 {
797 (void) strcpy(prt1, "Primary weapon : ");
798 objdes(prt2, &inventory[INVEN_WIELD], TRUE);
799 msg_print(strcat(prt1, prt2));
800 }
801 else
802 msg_print("No primary weapon.");
803 /* this is a new weapon, so clear the heavy flag */
804 weapon_heavy = FALSE;
805 check_strength();
806 }
807 break;
808 case ' ': /* Dummy command to return again to main prompt. */
809 break;
810 case '?':
811 inven_screen(HELP_SCR);
812 break;
813 default:
814 /* Nonsense command */
815 bell();
816 break;
817 }
818
819 /* Clear the doing_inven flag here, instead of at beginning, so that
820 can use it to control when messages above appear. */
821 doing_inven = 0;
822
823 /* Keep looking for objects to drop/wear/take off/throw off */
824 which = 'z';
825 while (selecting && free_turn_flag)
826 {
827 swap = "";
828 if (command == 'w')
829 {
830 from = wear_low;
831 to = wear_high;
832 prompt = "Wear/Wield";
833 }
834 else
835 {
836 from = 0;
837 if (command == 'd')
838 {
839 to = inven_ctr - 1;
840 prompt = "Drop";
841 if (equip_ctr > 0)
842 swap = ", / for Equip";
843 }
844 else
845 {
846 to = equip_ctr - 1;
847 if (command == 't')
848 prompt = "Take off";
849 else /* command == 'r' */
850 {
851 prompt = "Throw off";
852 if (inven_ctr > 0)
853 swap = ", / for Inven";
854 }
855 }
856 }
857 if (from > to)
858 selecting = FALSE;
859 else
860 {
861 if (scr_state == BLANK_SCR)
862 disp = ", * to list";
863 else
864 disp = "";
865 (void) sprintf(prt1,
866 "(%c-%c%s%s%s, space to break, ESC to exit) %s which one?",
867 from+'a', to+'a', disp, swap,
868 ((command == 'w' || command == 'd') ? ", 0-9" : "")
869 , prompt);
870 /* Abort everything. */
871 if (!get_com(prt1, &which))
872 {
873 selecting = FALSE;
874 which = ESCAPE;
875 }
876 /* Draw the screen and maybe exit to main prompt. */
877 else if (which == ' ' || which == '*')
878 {
879 if (command == 't' || command == 'r')
880 inven_screen(EQUIP_SCR);
881 else if (command == 'w' && scr_state != INVEN_SCR)
882 inven_screen(WEAR_SCR);
883 else
884 inven_screen(INVEN_SCR);
885 if (which == ' ')
886 selecting = FALSE;
887 }
888 /* Swap screens (for drop) */
889 else if (which == '/' && swap[0])
890 {
891 if (command == 'd')
892 command = 'r';
893 else
894 command = 'd';
895 if (scr_state == EQUIP_SCR)
896 inven_screen(INVEN_SCR);
897 else if (scr_state == INVEN_SCR)
898 inven_screen(EQUIP_SCR);
899 }
900 else
901 {
902 if ((which >= '0') && (which <= '9')
903 && (command != 'r') && (command != 't'))
904 {
905 /* look for item whose inscription matches "which" */
906 register int m;
907 for (m = from;
908 m <= to && ((inventory[m].inscrip[0] != which)
909 || (inventory[m].inscrip[1] != '\0'));
910 m++);
911 if (m <= to)
912 item = m;
913 else
914 item = -1;
915 }
916 else if ((which >= 'A') && (which <= 'Z'))
917 item = which - 'A';
918 else
919 item = which - 'a';
920 if (item < from || item > to)
921 bell();
922 else /* Found an item! */
923 {
924 if (command == 'r' || command == 't')
925 {
926 /* Get its place in the equipment list. */
927 tmp = item;
928 item = 21;
929 do
930 {
931 item++;
932 if (inventory[item].tval != TV_NOTHING)
933 tmp--;
934 }
935 while (tmp >= 0);
936 if (isupper((int)which) && !verify(prompt, item))
937 item = -1;
938 #ifdef ATARIST_MWC
939 else if ((holder = TR_CURSED) & inventory[item].flags)
940 #else
941 else if (TR_CURSED & inventory[item].flags)
942 #endif
943 {
944 msg_print("Hmmm, it seems to be cursed.");
945 item = -1;
946 }
947 else if (command == 't' &&
948 !inven_check_num(&inventory[item]))
949 {
950 if (cave[char_row][char_col].tptr != 0)
951 {
952 msg_print("You can't carry it.");
953 item = -1;
954 }
955 else if (get_check("You can't carry it. Drop it?"))
956 command = 'r';
957 else
958 item = -1;
959 }
960 if (item >= 0)
961 {
962 if (command == 'r')
963 {
964 inven_drop(item, TRUE);
965 /* As a safety measure, set the player's
966 inven weight to 0,
967 when the last object is dropped*/
968 if (inven_ctr == 0 && equip_ctr == 0)
969 inven_weight = 0;
970 }
971 else
972 {
973 slot = inven_carry(&inventory[item]);
974 takeoff(item, slot);
975 }
976 check_strength();
977 free_turn_flag = FALSE;
978 if (command == 'r')
979 selecting = FALSE;
980 }
981 }
982 else if (command == 'w')
983 {
984 /* Wearing. Go to a bit of trouble over replacing
985 existing equipment. */
986 if (isupper((int)which) && !verify(prompt, item))
987 item = -1;
988 else switch(inventory[item].tval)
989 { /* Slot for equipment */
990 case TV_SLING_AMMO: case TV_BOLT: case TV_ARROW:
991 case TV_BOW: case TV_HAFTED: case TV_POLEARM:
992 case TV_SWORD: case TV_DIGGING: case TV_SPIKE:
993 slot = INVEN_WIELD; break;
994 case TV_LIGHT: slot = INVEN_LIGHT; break;
995 case TV_BOOTS: slot = INVEN_FEET; break;
996 case TV_GLOVES: slot = INVEN_HANDS; break;
997 case TV_CLOAK: slot = INVEN_OUTER; break;
998 case TV_HELM: slot = INVEN_HEAD; break;
999 case TV_SHIELD: slot = INVEN_ARM; break;
1000 case TV_HARD_ARMOR: case TV_SOFT_ARMOR:
1001 slot = INVEN_BODY; break;
1002 case TV_AMULET: slot = INVEN_NECK; break;
1003 case TV_RING:
1004 if (inventory[INVEN_RIGHT].tval == TV_NOTHING)
1005 slot = INVEN_RIGHT;
1006 else if (inventory[INVEN_LEFT].tval == TV_NOTHING)
1007 slot = INVEN_LEFT;
1008 else
1009 {
1010 slot = 0;
1011 /* Rings. Give choice over where they go. */
1012 do
1013 {
1014 if (!get_com(
1015 "Put ring on which hand (l/r/L/R)?", &query))
1016 {
1017 item = -1;
1018 slot = -1;
1019 }
1020 else if (query == 'l')
1021 slot = INVEN_LEFT;
1022 else if (query == 'r')
1023 slot = INVEN_RIGHT;
1024 else
1025 {
1026 if (query == 'L')
1027 slot = INVEN_LEFT;
1028 else if (query == 'R')
1029 slot = INVEN_RIGHT;
1030 else
1031 bell();
1032 if (slot && !verify("Replace", slot))
1033 slot = 0;
1034 }
1035 }
1036 while(slot == 0);
1037 }
1038 break;
1039 default:
1040 msg_print("IMPOSSIBLE: I don't see how you can use that.");
1041 item = -1;
1042 break;
1043 }
1044 if (item >= 0 && inventory[slot].tval != TV_NOTHING)
1045 {
1046 #ifdef ATARIST_MWC
1047 if ((holder = TR_CURSED) & inventory[slot].flags)
1048 #else
1049 if (TR_CURSED & inventory[slot].flags)
1050 #endif
1051 {
1052 objdes(prt1, &inventory[slot], FALSE);
1053 (void) sprintf(prt2, "The %s you are ", prt1);
1054 if (slot == INVEN_HEAD)
1055 (void) strcat(prt2, "wielding ");
1056 else
1057 (void) strcat(prt2, "wearing ");
1058 msg_print(strcat(prt2, "appears to be cursed."));
1059 item = -1;
1060 }
1061 else if (inventory[item].subval == ITEM_GROUP_MIN &&
1062 inventory[item].number > 1 &&
1063 !inven_check_num(&inventory[slot]))
1064 {
1065 /* this can happen if try to wield a torch,
1066 and have more than one in inventory */
1067 msg_print("You will have to drop something first.");
1068 item = -1;
1069 }
1070 }
1071 if (item >= 0)
1072 {
1073 /* OK. Wear it. */
1074 free_turn_flag = FALSE;
1075
1076 /* first remove new item from inventory */
1077 tmp_obj = inventory[item];
1078 i_ptr = &tmp_obj;
1079
1080 wear_high--;
1081 /* Fix for torches */
1082 if (i_ptr->number > 1
1083 && i_ptr->subval <= ITEM_SINGLE_STACK_MAX)
1084 {
1085 i_ptr->number = 1;
1086 wear_high++;
1087 }
1088 inven_weight += i_ptr->weight*i_ptr->number;
1089 inven_destroy(item); /* Subtracts weight */
1090
1091 /* second, add old item to inv and remove from
1092 equipment list, if necessary */
1093 i_ptr = &inventory[slot];
1094 if (i_ptr->tval != TV_NOTHING)
1095 {
1096 tmp2 = inven_ctr;
1097 tmp = inven_carry(i_ptr);
1098 /* if item removed did not stack
1099 with anything in inventory,
1100 then increment wear_high */
1101 if (inven_ctr != tmp2)
1102 wear_high++;
1103 takeoff(slot, tmp);
1104 }
1105
1106 /* third, wear new item */
1107 *i_ptr = tmp_obj;
1108 equip_ctr++;
1109 py_bonuses(i_ptr, 1);
1110 if (slot == INVEN_WIELD)
1111 string = "You are wielding";
1112 else if (slot == INVEN_LIGHT)
1113 string = "Your light source is";
1114 else
1115 string = "You are wearing";
1116 objdes(prt2, i_ptr, TRUE);
1117 /* Get the right equipment letter. */
1118 tmp = INVEN_WIELD;
1119 item = 0;
1120 while (tmp != slot)
1121 if (inventory[tmp++].tval != TV_NOTHING)
1122 item++;
1123
1124 (void) sprintf(prt1, "%s %s (%c)", string, prt2,
1125 'a'+item);
1126 msg_print(prt1);
1127 /* this is a new weapon, so clear heavy flag */
1128 if (slot == INVEN_WIELD)
1129 weapon_heavy = FALSE;
1130 check_strength();
1131 #ifdef ATARIST_MWC
1132 if (i_ptr->flags & (holder = TR_CURSED))
1133 #else
1134 if (i_ptr->flags & TR_CURSED)
1135 #endif
1136 {
1137 msg_print("Oops! It feels deathly cold!");
1138 add_inscribe(i_ptr, ID_DAMD);
1139 /* To force a cost of 0,
1140 even if unidentified. */
1141 i_ptr->cost = -1;
1142 }
1143 }
1144 }
1145 else /* command == 'd' */
1146 {
1147 if (inventory[item].number > 1)
1148 {
1149 objdes(prt1, &inventory[item], TRUE);
1150 prt1[strlen(prt1)-1] = '?';
1151 (void) sprintf(prt2, "Drop all %s [y/n]", prt1);
1152 prt1[strlen(prt1)-1] = '.';
1153 prt(prt2, 0, 0);
1154 query = inkey();
1155 if (query != 'y' && query != 'n')
1156 {
1157 if (query != ESCAPE)
1158 bell();
1159 erase_line(MSG_LINE, 0);
1160 item = -1;
1161 }
1162 }
1163 else if (isupper((int)which) && !verify(prompt, item))
1164 item = -1;
1165 else
1166 query = 'y';
1167 if (item >= 0)
1168 {
1169 free_turn_flag = FALSE; /* Player turn */
1170 inven_drop(item, query == 'y');
1171 check_strength();
1172 }
1173 selecting = FALSE;
1174 /* As a safety measure, set the player's inven weight
1175 to 0, when the last object is dropped. */
1176 if (inven_ctr == 0 && equip_ctr == 0)
1177 inven_weight = 0;
1178 }
1179 if (free_turn_flag == FALSE && scr_state == BLANK_SCR)
1180 selecting = FALSE;
1181 }
1182 }
1183 }
1184 }
1185 if (which == ESCAPE || scr_state == BLANK_SCR)
1186 command = ESCAPE;
1187 else if (!free_turn_flag)
1188 {
1189 /* Save state for recovery if they want to call us again next turn.*/
1190 if (selecting)
1191 doing_inven = command;
1192 else
1193 doing_inven = ' '; /* A dummy command to recover screen. */
1194 /* flush last message before clearing screen_change and exiting */
1195 msg_print(CNIL);
1196 screen_change = FALSE;/* This lets us know if the world changes */
1197 command = ESCAPE;
1198 }
1199 else
1200 {
1201 /* Put an appropriate header. */
1202 if (scr_state == INVEN_SCR)
1203 {
1204 if (! show_weight_flag || inven_ctr == 0)
1205 (void) sprintf(prt1,
1206 "You are carrying %d.%d pounds. In your pack there is %s",
1207 inven_weight / 10, inven_weight % 10,
1208 (inven_ctr == 0 ? "nothing." : "-"));
1209 else
1210 (void) sprintf (prt1,
1211 "You are carrying %d.%d pounds. Your capacity is %d.%d pounds. %s",
1212 inven_weight / 10, inven_weight % 10,
1213 weight_limit () / 10, weight_limit () % 10,
1214 "In your pack is -");
1215 prt(prt1, 0, 0);
1216 }
1217 else if (scr_state == WEAR_SCR)
1218 {
1219 if (wear_high < wear_low)
1220 prt("You have nothing you could wield.", 0, 0);
1221 else
1222 prt("You could wield -", 0, 0);
1223 }
1224 else if (scr_state == EQUIP_SCR)
1225 {
1226 if (equip_ctr == 0)
1227 prt("You are not using anything.", 0, 0);
1228 else
1229 prt("You are using -", 0, 0);
1230 }
1231 else
1232 prt("Allowed commands:", 0, 0);
1233 erase_line(scr_base, scr_left);
1234 put_buffer("e/i/t/w/x/d/?/ESC:", scr_base, 60);
1235 command = inkey();
1236 erase_line(scr_base, scr_left);
1237 }
1238 }
1239 while (command != ESCAPE);
1240 if (scr_state != BLANK_SCR)
1241 restore_screen();
1242 calc_bonuses();
1243 }
1244
1245
1246 /* Get the ID of an item and return the CTR value of it -RAK- */
get_item(com_val,pmt,i,j,mask,message)1247 int get_item(com_val, pmt, i, j, mask, message)
1248 int *com_val;
1249 char *pmt;
1250 int i, j;
1251 char *mask;
1252 char *message;
1253 {
1254 vtype out_val;
1255 char which;
1256 register int test_flag, item;
1257 int full, i_scr, redraw;
1258
1259 item = FALSE;
1260 redraw = FALSE;
1261 *com_val = 0;
1262 i_scr = 1;
1263 if (j > INVEN_WIELD)
1264 {
1265 full = TRUE;
1266 if (inven_ctr == 0)
1267 {
1268 i_scr = 0;
1269 j = equip_ctr - 1;
1270 }
1271 else
1272 j = inven_ctr - 1;
1273 }
1274 else
1275 full = FALSE;
1276
1277 if (inven_ctr > 0 || (full && equip_ctr > 0))
1278 {
1279 do
1280 {
1281 if (redraw)
1282 {
1283 if (i_scr > 0)
1284 (void) show_inven (i, j, FALSE, 80, mask);
1285 else
1286 (void) show_equip (FALSE, 80);
1287 }
1288 if (full)
1289 (void) sprintf(out_val,
1290 "(%s: %c-%c,%s%s / for %s, or ESC) %s",
1291 (i_scr > 0 ? "Inven" : "Equip"), i+'a', j+'a',
1292 (i_scr > 0 ? " 0-9," : ""),
1293 (redraw ? "" : " * to see,"),
1294 (i_scr > 0 ? "Equip" : "Inven"), pmt);
1295 else
1296 (void) sprintf(out_val,
1297 "(Items %c-%c,%s%s ESC to exit) %s",
1298 i+'a', j+'a',
1299 (i_scr > 0 ? " 0-9," : ""),
1300 (redraw ? "" : " * for inventory list,"), pmt);
1301 test_flag = FALSE;
1302 prt(out_val, 0, 0);
1303 do
1304 {
1305 which = inkey();
1306 switch(which)
1307 {
1308 case ESCAPE:
1309 test_flag = TRUE;
1310 free_turn_flag = TRUE;
1311 i_scr = -1;
1312 break;
1313 case '/':
1314 if (full)
1315 {
1316 if (i_scr > 0)
1317 {
1318 if (equip_ctr == 0)
1319 {
1320 prt("But you're not using anything -more-",0,0);
1321 (void) inkey();
1322 }
1323 else
1324 {
1325 i_scr = 0;
1326 test_flag = TRUE;
1327 if (redraw)
1328 {
1329 j = equip_ctr;
1330 while (j < inven_ctr)
1331 {
1332 j++;
1333 erase_line(j, 0);
1334 }
1335 }
1336 j = equip_ctr - 1;
1337 }
1338 prt(out_val, 0, 0);
1339 }
1340 else
1341 {
1342 if (inven_ctr == 0)
1343 {
1344 prt("But you're not carrying anything -more-",0,0);
1345 (void) inkey();
1346 }
1347 else
1348 {
1349 i_scr = 1;
1350 test_flag = TRUE;
1351 if (redraw)
1352 {
1353 j = inven_ctr;
1354 while (j < equip_ctr)
1355 {
1356 j++;
1357 erase_line (j, 0);
1358 }
1359 }
1360 j = inven_ctr - 1;
1361 }
1362 }
1363 }
1364 break;
1365 case '*':
1366 if (!redraw)
1367 {
1368 test_flag = TRUE;
1369 save_screen();
1370 redraw = TRUE;
1371 }
1372 break;
1373 default:
1374 if ((which >= '0') && (which <= '9') && (i_scr != 0))
1375 /* look for item whose inscription matches "which" */
1376 {
1377 register int m;
1378 for (m = i;
1379 (m < INVEN_WIELD)
1380 && ((inventory[m].inscrip[0] != which)
1381 || (inventory[m].inscrip[1] != '\0'));
1382 m++);
1383 if (m < INVEN_WIELD)
1384 *com_val = m;
1385 else
1386 *com_val = -1;
1387 }
1388 else if (isupper((int)which))
1389 *com_val = which - 'A';
1390 else
1391 *com_val = which - 'a';
1392 if ((*com_val >= i) && (*com_val <= j)
1393 && (mask == CNIL || mask[*com_val]))
1394 {
1395 if (i_scr == 0)
1396 {
1397 i = 21;
1398 j = *com_val;
1399 do
1400 {
1401 while (inventory[++i].tval == TV_NOTHING);
1402 j--;
1403 }
1404 while (j >= 0);
1405 *com_val = i;
1406 }
1407 if (isupper((int)which) && !verify("Try", *com_val))
1408 {
1409 test_flag = TRUE;
1410 free_turn_flag = TRUE;
1411 i_scr = -1;
1412 break;
1413 }
1414 test_flag = TRUE;
1415 item = TRUE;
1416 i_scr = -1;
1417 }
1418 else if (message)
1419 {
1420 msg_print (message);
1421 /* Set test_flag to force redraw of the question. */
1422 test_flag = TRUE;
1423 }
1424 else
1425 bell();
1426 break;
1427 }
1428 }
1429 while (!test_flag);
1430 }
1431 while (i_scr >= 0);
1432 if (redraw)
1433 restore_screen();
1434 erase_line(MSG_LINE, 0);
1435 }
1436 else
1437 prt("You are not carrying anything.", 0, 0);
1438 return(item);
1439 }
1440
1441 /* I may have written the town level code, but I'm not exactly */
1442 /* proud of it. Adding the stores required some real slucky */
1443 /* hooks which I have not had time to re-think. -RAK- */
1444
1445 /* Returns true if player has no light -RAK- */
no_light()1446 int no_light()
1447 {
1448 register cave_type *c_ptr;
1449
1450 c_ptr = &cave[char_row][char_col];
1451 if (!c_ptr->tl && !c_ptr->pl)
1452 return TRUE;
1453 return FALSE;
1454 }
1455
1456
1457 /* map rogue_like direction commands into numbers */
map_roguedir(comval)1458 static char map_roguedir(comval)
1459 register char comval;
1460 {
1461 switch(comval)
1462 {
1463 case 'h':
1464 comval = '4';
1465 break;
1466 case 'y':
1467 comval = '7';
1468 break;
1469 case 'k':
1470 comval = '8';
1471 break;
1472 case 'u':
1473 comval = '9';
1474 break;
1475 case 'l':
1476 comval = '6';
1477 break;
1478 case 'n':
1479 comval = '3';
1480 break;
1481 case 'j':
1482 comval = '2';
1483 break;
1484 case 'b':
1485 comval = '1';
1486 break;
1487 case '.':
1488 comval = '5';
1489 break;
1490 }
1491 return(comval);
1492 }
1493
1494
1495 /* Prompts for a direction -RAK- */
1496 /* Direction memory added, for repeated commands. -CJS */
get_dir(prompt,dir)1497 int get_dir(prompt, dir)
1498 char *prompt;
1499 int *dir;
1500 {
1501 char command;
1502 int save;
1503 static char prev_dir; /* Direction memory. -CJS- */
1504
1505 if (default_dir) /* used in counted commands. -CJS- */
1506 {
1507 *dir = prev_dir;
1508 return TRUE;
1509 }
1510 if (prompt == CNIL)
1511 prompt = "Which direction?";
1512 for (;;)
1513 {
1514 save = command_count; /* Don't end a counted command. -CJS- */
1515 #ifdef MAC
1516 if (!get_comdir(prompt, &command))
1517 #else
1518 if (!get_com(prompt, &command))
1519 #endif
1520 {
1521 free_turn_flag = TRUE;
1522 return FALSE;
1523 }
1524 command_count = save;
1525 if (rogue_like_commands)
1526 command = map_roguedir(command);
1527 if (command >= '1' && command <= '9' && command != '5')
1528 {
1529 prev_dir = command - '0';
1530 *dir = prev_dir;
1531 return TRUE;
1532 }
1533 bell();
1534 }
1535 }
1536
1537
1538
1539 /* Similar to get_dir, except that no memory exists, and it is -CJS-
1540 allowed to enter the null direction. */
get_alldir(prompt,dir)1541 int get_alldir(prompt, dir)
1542 char *prompt;
1543 int *dir;
1544 {
1545 char command;
1546
1547 for(;;)
1548 {
1549 #ifdef MAC
1550 if (!get_comdir(prompt, &command))
1551 #else
1552 if (!get_com(prompt, &command))
1553 #endif
1554 {
1555 free_turn_flag = TRUE;
1556 return FALSE;
1557 }
1558 if (rogue_like_commands)
1559 command = map_roguedir(command);
1560 if (command >= '1' && command <= '9')
1561 {
1562 *dir = command - '0';
1563 return TRUE;
1564 }
1565 bell();
1566 }
1567 }
1568
1569
1570 /* Moves creature record from one space to another -RAK- */
move_rec(y1,x1,y2,x2)1571 void move_rec(y1, x1, y2, x2)
1572 register int y1, x1, y2, x2;
1573 {
1574 int tmp;
1575
1576 /* this always works correctly, even if y1==y2 and x1==x2 */
1577 tmp = cave[y1][x1].cptr;
1578 cave[y1][x1].cptr = 0;
1579 cave[y2][x2].cptr = tmp;
1580 }
1581
1582
1583 /* Room is lit, make it appear -RAK- */
light_room(y,x)1584 void light_room(y, x)
1585 int y, x;
1586 {
1587 register int i, j, start_col, end_col;
1588 int tmp1, tmp2, start_row, end_row;
1589 register cave_type *c_ptr;
1590 int tval;
1591
1592 tmp1 = (SCREEN_HEIGHT/2);
1593 tmp2 = (SCREEN_WIDTH /2);
1594 start_row = (y/tmp1)*tmp1;
1595 start_col = (x/tmp2)*tmp2;
1596 end_row = start_row + tmp1 - 1;
1597 end_col = start_col + tmp2 - 1;
1598 for (i = start_row; i <= end_row; i++)
1599 for (j = start_col; j <= end_col; j++)
1600 {
1601 c_ptr = &cave[i][j];
1602 if (c_ptr->lr && ! c_ptr->pl)
1603 {
1604 c_ptr->pl = TRUE;
1605 if (c_ptr->fval == DARK_FLOOR)
1606 c_ptr->fval = LIGHT_FLOOR;
1607 if (! c_ptr->fm && c_ptr->tptr != 0)
1608 {
1609 tval = t_list[c_ptr->tptr].tval;
1610 if (tval >= TV_MIN_VISIBLE && tval <= TV_MAX_VISIBLE)
1611 c_ptr->fm = TRUE;
1612 }
1613 print(loc_symbol(i, j), i, j);
1614 }
1615 }
1616 }
1617
1618
1619 /* Lights up given location -RAK- */
lite_spot(y,x)1620 void lite_spot(y, x)
1621 register int y, x;
1622 {
1623 if (panel_contains(y, x))
1624 print(loc_symbol(y, x), y, x);
1625 }
1626
1627
1628 /* Normal movement */
1629 /* When FIND_FLAG, light only permanent features */
sub1_move_light(y1,x1,y2,x2)1630 static void sub1_move_light(y1, x1, y2, x2)
1631 register int x1, x2;
1632 int y1, y2;
1633 {
1634 register int i, j;
1635 register cave_type *c_ptr;
1636 int tval, top, left, bottom, right;
1637
1638 if (light_flag)
1639 {
1640 for (i = y1-1; i <= y1+1; i++) /* Turn off lamp light */
1641 for (j = x1-1; j <= x1+1; j++)
1642 cave[i][j].tl = FALSE;
1643 if (find_flag && !find_prself)
1644 light_flag = FALSE;
1645 }
1646 else if (!find_flag || find_prself)
1647 light_flag = TRUE;
1648
1649 for (i = y2-1; i <= y2+1; i++)
1650 for (j = x2-1; j <= x2+1; j++)
1651 {
1652 c_ptr = &cave[i][j];
1653 /* only light up if normal movement */
1654 if (light_flag)
1655 c_ptr->tl = TRUE;
1656 if (c_ptr->fval >= MIN_CAVE_WALL)
1657 c_ptr->pl = TRUE;
1658 else if (!c_ptr->fm && c_ptr->tptr != 0)
1659 {
1660 tval = t_list[c_ptr->tptr].tval;
1661 if ((tval >= TV_MIN_VISIBLE) && (tval <= TV_MAX_VISIBLE))
1662 c_ptr->fm = TRUE;
1663 }
1664 }
1665
1666 /* From uppermost to bottom most lines player was on. */
1667 if (y1 < y2)
1668 {
1669 top = y1 - 1;
1670 bottom = y2 + 1;
1671 }
1672 else
1673 {
1674 top = y2 - 1;
1675 bottom = y1 + 1;
1676 }
1677 if (x1 < x2)
1678 {
1679 left = x1 - 1;
1680 right = x2 + 1;
1681 }
1682 else
1683 {
1684 left = x2 - 1;
1685 right = x1 + 1;
1686 }
1687 for (i = top; i <= bottom; i++)
1688 for (j = left; j <= right; j++) /* Leftmost to rightmost do*/
1689 print(loc_symbol(i, j), i, j);
1690 }
1691
1692
1693 /* When blinded, move only the player symbol. */
1694 /* With no light, movement becomes involved. */
sub3_move_light(y1,x1,y2,x2)1695 static void sub3_move_light(y1, x1, y2, x2)
1696 register int y1, x1;
1697 int y2, x2;
1698 {
1699 register int i, j;
1700
1701 if (light_flag)
1702 {
1703 for (i = y1-1; i <= y1+1; i++)
1704 for (j = x1-1; j <= x1+1; j++)
1705 {
1706 cave[i][j].tl = FALSE;
1707 print(loc_symbol(i, j), i, j);
1708 }
1709 light_flag = FALSE;
1710 }
1711 else if (!find_flag || find_prself)
1712 print(loc_symbol(y1, x1), y1, x1);
1713
1714 if (!find_flag || find_prself)
1715 print('@', y2, x2);
1716 }
1717
1718
1719 /* Package for moving the character's light about the screen */
1720 /* Four cases : Normal, Finding, Blind, and Nolight -RAK- */
move_light(y1,x1,y2,x2)1721 void move_light(y1, x1, y2, x2)
1722 int y1, x1, y2, x2;
1723 {
1724 if (py.flags.blind > 0 || !player_light)
1725 sub3_move_light(y1, x1, y2, x2);
1726 else
1727 sub1_move_light(y1, x1, y2, x2);
1728 }
1729
1730
1731 /* Something happens to disturb the player. -CJS-
1732 The first arg indicates a major disturbance, which affects search.
1733 The second arg indicates a light change. */
disturb(s,l)1734 void disturb(s, l)
1735 int s, l;
1736 {
1737 command_count = 0;
1738 if (s && (py.flags.status & PY_SEARCH))
1739 search_off();
1740 if (py.flags.rest != 0)
1741 rest_off();
1742 if (l || find_flag)
1743 {
1744 find_flag = FALSE;
1745 check_view();
1746 }
1747 flush();
1748 }
1749
1750
1751 /* Search Mode enhancement -RAK- */
search_on()1752 void search_on()
1753 {
1754 change_speed(1);
1755 py.flags.status |= PY_SEARCH;
1756 prt_state();
1757 prt_speed();
1758 py.flags.food_digested++;
1759 }
1760
search_off()1761 void search_off()
1762 {
1763 #ifdef ATARIST_MWC
1764 int32u holder;
1765 #endif
1766
1767 check_view();
1768 change_speed(-1);
1769 #ifdef ATARIST_MWC
1770 py.flags.status &= ~(holder = PY_SEARCH);
1771 #else
1772 py.flags.status &= ~PY_SEARCH;
1773 #endif
1774 prt_state();
1775 prt_speed();
1776 py.flags.food_digested--;
1777 }
1778
1779
1780 /* Resting allows a player to safely restore his hp -RAK- */
rest()1781 void rest()
1782 {
1783 int rest_num;
1784 vtype rest_str;
1785
1786 if (command_count > 0)
1787 {
1788 rest_num = command_count;
1789 command_count = 0;
1790 }
1791 else
1792 {
1793 prt("Rest for how long? ", 0, 0);
1794 rest_num = 0;
1795 if (get_string(rest_str, 0, 19, 5))
1796 {
1797 if (rest_str[0] == '*')
1798 rest_num = -MAX_SHORT;
1799 else
1800 rest_num = atoi(rest_str);
1801 }
1802 }
1803 /* check for reasonable value, must be positive number in range of a
1804 short, or must be -MAX_SHORT */
1805 if ((rest_num == -MAX_SHORT)
1806 || (rest_num > 0) && (rest_num < MAX_SHORT))
1807 {
1808 if (py.flags.status & PY_SEARCH)
1809 search_off();
1810 py.flags.rest = rest_num;
1811 py.flags.status |= PY_REST;
1812 prt_state();
1813 py.flags.food_digested--;
1814 prt ("Press any key to stop resting...", 0, 0);
1815 put_qio();
1816 }
1817 else
1818 {
1819 if (rest_num != 0)
1820 msg_print ("Invalid rest count.");
1821 erase_line(MSG_LINE, 0);
1822 free_turn_flag = TRUE;
1823 }
1824 }
1825
rest_off()1826 void rest_off()
1827 {
1828 #ifdef ATARIST_MWC
1829 int32u holder;
1830 #endif
1831
1832 py.flags.rest = 0;
1833 #ifdef ATARIST_MWC
1834 py.flags.status &= ~(holder = PY_REST);
1835 #else
1836 py.flags.status &= ~PY_REST;
1837 #endif
1838 prt_state();
1839 msg_print(CNIL); /* flush last message, or delete "press any key" message */
1840 py.flags.food_digested++;
1841 }
1842
1843
1844 /* Attacker's level and plusses, defender's AC -RAK- */
test_hit(bth,level,pth,ac,attack_type)1845 int test_hit(bth, level, pth, ac, attack_type)
1846 int bth, level, pth, ac, attack_type;
1847 {
1848 register int i, die;
1849
1850 disturb (1, 0);
1851 i = bth + pth * BTH_PLUS_ADJ
1852 + (level * class_level_adj[py.misc.pclass][attack_type]);
1853 /* pth could be less than 0 if player wielding weapon too heavy for him */
1854 /* always miss 1 out of 20, always hit 1 out of 20 */
1855 die = randint (20);
1856 if ((die != 1) && ((die == 20)
1857 || ((i > 0) && (randint (i) > ac)))) /* normal hit */
1858 return TRUE;
1859 else
1860 return FALSE;
1861 }
1862
1863
1864 /* Decreases players hit points and sets death flag if necessary*/
1865 /* -RAK- */
take_hit(damage,hit_from)1866 void take_hit(damage, hit_from)
1867 int damage;
1868 char *hit_from;
1869 {
1870 if (py.flags.invuln > 0) damage = 0;
1871 py.misc.chp -= damage;
1872 if (py.misc.chp < 0)
1873 {
1874 if (!death)
1875 {
1876 death = TRUE;
1877 (void) strcpy(died_from, hit_from);
1878 total_winner = FALSE;
1879 }
1880 new_level_flag = TRUE;
1881 }
1882 else
1883 prt_chp();
1884 }
1885