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