1 /* source/misc1.c: misc utility and initialization code, magic objects code
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 #include "config.h"
10 #include "constant.h"
11 #include "types.h"
12 #include "externs.h"
13 
14 #ifdef __TURBOC__
15 #include	<stdlib.h>
16 #endif
17 
18 #ifdef Pyramid
19 #include <sys/time.h>
20 #else
21 #include <time.h>
22 #endif
23 #if !defined(GEMDOS) && !defined(MAC) && !defined(AMIGA)
24 #ifndef VMS
25 #include <sys/types.h>
26 #else
27 #include <types.h>
28 #endif
29 #endif
30 
31 #if !defined(ATARIST_MWC) && !defined(MAC) && !defined(VMS) && !defined(AMIGA) && !defined(__FreeBSD__)
32 long time();
33 #endif
34 struct tm *localtime();
35 
36 #if defined(LINT_ARGS)
37 static void compact_objects(void);
38 #endif
39 
40 
41 /* gets a new random seed for the random number generator */
init_seeds(seed)42 void init_seeds(seed)
43 int32u seed;
44 {
45   register int32u clock_var;
46 
47   if (seed == 0)
48 #if defined(MAC) || defined(__FreeBSD__)
49     clock_var = time((time_t *)0);
50 #else
51     clock_var = time((long *)0);
52 #endif
53   else
54     clock_var = seed;
55   randes_seed = (int32) clock_var;
56 
57   clock_var += 8762;
58   town_seed = (int32) clock_var;
59 
60   clock_var += 113452L;
61   set_rnd_seed(clock_var);
62   /* make it a little more random */
63   for (clock_var = randint(100); clock_var != 0; clock_var--)
64     (void) rnd();
65 }
66 
67 /* holds the previous rnd state */
68 static int32u old_seed;
69 
70 /* change to different random number generator state */
set_seed(seed)71 void set_seed(seed)
72 int32u seed;
73 {
74   old_seed = get_rnd_seed ();
75 
76   /* want reproducible state here */
77   set_rnd_seed (seed);
78 }
79 
80 
81 /* restore the normal random generator state */
reset_seed()82 void reset_seed()
83 {
84   set_rnd_seed (old_seed);
85 }
86 
87 
88 /* Check the day-time strings to see if open		-RAK-	*/
check_time()89 int check_time()
90 {
91 #ifdef MORIA_HOU
92 #if defined(MAC) || defined(__FreeBSD__)
93   time_t clock_var;
94 #else
95   long clock_var;
96 #endif
97   register struct tm *tp;
98 
99 #if defined(MAC) || defined(__FreeBSD__)
100   clock_var = time((time_t *)0);
101 #else
102   clock_var = time((long *)0);
103 #endif
104   tp = localtime(&clock_var);
105   if (days[tp->tm_wday][tp->tm_hour+4] == 'X')
106     return TRUE;
107   else
108     return FALSE;
109 #else
110   return TRUE;
111 #endif
112 }
113 
114 
115 /* Generates a random integer x where 1<=X<=MAXVAL	-RAK-	*/
randint(maxval)116 int randint(maxval)
117 int maxval;
118 {
119   register long randval;
120 
121   randval = rnd ();
122   return ((int)(randval % maxval) + 1);
123 }
124 
125 /* Generates a random integer number of NORMAL distribution -RAK-*/
randnor(mean,stand)126 int randnor(mean, stand)
127 int mean, stand;
128 {
129   register int tmp, offset, low, iindex, high;
130 
131 #if 0
132   /* alternate randnor code, slower but much smaller since no table */
133   /* 2 per 1,000,000 will be > 4*SD, max is 5*SD */
134   tmp = damroll(8, 99);	 /* mean 400, SD 81 */
135   tmp = (tmp - 400) * stand / 81;
136   return tmp + mean;
137 #endif
138 
139   tmp = randint(MAX_SHORT);
140 
141   /* off scale, assign random value between 4 and 5 times SD */
142   if (tmp == MAX_SHORT)
143     {
144       offset = 4 * stand + randint(stand);
145 
146       /* one half are negative */
147       if (randint(2) == 1)
148 	offset = -offset;
149 
150       return mean + offset;
151     }
152 
153   /* binary search normal normal_table to get index that matches tmp */
154   /* this takes up to 8 iterations */
155   low = 0;
156   iindex = NORMAL_TABLE_SIZE >> 1;
157   high = NORMAL_TABLE_SIZE;
158   while (TRUE)
159     {
160       if ((normal_table[iindex] == tmp) || (high == (low+1)))
161 	break;
162       if (normal_table[iindex] > tmp)
163 	{
164 	  high = iindex;
165 	  iindex = low + ((iindex - low) >> 1);
166 	}
167       else
168 	{
169 	  low = iindex;
170 	  iindex = iindex + ((high - iindex) >> 1);
171 	}
172     }
173 
174   /* might end up one below target, check that here */
175   if (normal_table[iindex] < tmp)
176     iindex = iindex + 1;
177 
178   /* normal_table is based on SD of 64, so adjust the index value here,
179      round the half way case up */
180   offset = ((stand * iindex) + (NORMAL_TABLE_SD >> 1)) / NORMAL_TABLE_SD;
181 
182   /* one half should be negative */
183   if (randint(2) == 1)
184     offset = -offset;
185 
186   return mean + offset;
187 }
188 
189 
190 /* Returns position of first set bit			-RAK-	*/
191 /*     and clears that bit */
bit_pos(test)192 int bit_pos(test)
193 int32u *test;
194 {
195   register int i;
196   register int32u mask = 0x1;
197 
198   for (i = 0; i < sizeof(*test)*8; i++) {
199     if (*test & mask) {
200       *test &= ~mask;
201       return(i);
202     }
203     mask <<= 1;
204   }
205 
206   /* no one bits found */
207   return(-1);
208 }
209 
210 /* Checks a co-ordinate for in bounds status		-RAK-	*/
in_bounds(y,x)211 int in_bounds(y, x)
212 int y, x;
213 {
214   if ((y > 0) && (y < cur_height-1) && (x > 0) && (x < cur_width-1))
215     return(TRUE);
216   else
217     return(FALSE);
218 }
219 
220 
221 /* Calculates current boundaries				-RAK-	*/
panel_bounds()222 void panel_bounds()
223 {
224   panel_row_min = panel_row*(SCREEN_HEIGHT/2);
225   panel_row_max = panel_row_min + SCREEN_HEIGHT - 1;
226   panel_row_prt = panel_row_min - 1;
227   panel_col_min = panel_col*(SCREEN_WIDTH/2);
228   panel_col_max = panel_col_min + SCREEN_WIDTH - 1;
229   panel_col_prt = panel_col_min - 13;
230 }
231 
232 
233 /* Given an row (y) and col (x), this routine detects  -RAK-	*/
234 /* when a move off the screen has occurred and figures new borders.
235    Force forcses the panel bounds to be recalculated, useful for 'W'here. */
get_panel(y,x,force)236 int get_panel(y, x, force)
237 int y, x, force;
238 {
239   register int prow, pcol;
240   register int panel;
241 
242   prow = panel_row;
243   pcol = panel_col;
244   if (force || (y < panel_row_min + 2) || (y > panel_row_max - 2))
245     {
246       prow = ((y - SCREEN_HEIGHT/4)/(SCREEN_HEIGHT/2));
247       if (prow > max_panel_rows)
248 	prow = max_panel_rows;
249       else if (prow < 0)
250 	prow = 0;
251     }
252   if (force || (x < panel_col_min + 3) || (x > panel_col_max - 3))
253     {
254       pcol = ((x - SCREEN_WIDTH/4)/(SCREEN_WIDTH/2));
255       if (pcol > max_panel_cols)
256 	pcol = max_panel_cols;
257       else if (pcol < 0)
258 	pcol = 0;
259     }
260   if ((prow != panel_row) || (pcol != panel_col))
261     {
262       panel_row = prow;
263       panel_col = pcol;
264       panel_bounds();
265       panel = TRUE;
266       /* stop movement if any */
267       if (find_bound)
268 	end_find();
269     }
270   else
271     panel = FALSE;
272   return(panel);
273 }
274 
275 
276 /* Tests a given point to see if it is within the screen -RAK-	*/
277 /* boundaries.							  */
panel_contains(y,x)278 int panel_contains(y, x)
279 register int y, x;
280 {
281   if ((y >= panel_row_min) && (y <= panel_row_max) &&
282       (x >= panel_col_min) && (x <= panel_col_max))
283     return (TRUE);
284   else
285     return (FALSE);
286 }
287 
288 
289 /* Distance between two points				-RAK-	*/
distance(y1,x1,y2,x2)290 int distance(y1, x1, y2, x2)
291 int y1, x1, y2, x2;
292 {
293   register int dy, dx;
294 
295   dy = y1 - y2;
296   if (dy < 0)
297     dy = -dy;
298   dx = x1 - x2;
299   if (dx < 0)
300     dx = -dx;
301 
302   return ((((dy + dx) << 1) - (dy > dx ? dx : dy)) >> 1);
303 }
304 
305 /* Checks points north, south, east, and west for a wall -RAK-	*/
306 /* note that y,x is always in_bounds(), i.e. 0 < y < cur_height-1, and
307    0 < x < cur_width-1	*/
next_to_walls(y,x)308 int next_to_walls(y, x)
309 register int y, x;
310 {
311   register int i;
312   register cave_type *c_ptr;
313 
314   i = 0;
315   c_ptr = &cave[y-1][x];
316   if (c_ptr->fval >= MIN_CAVE_WALL)
317     i++;
318   c_ptr = &cave[y+1][x];
319   if (c_ptr->fval >= MIN_CAVE_WALL)
320     i++;
321   c_ptr = &cave[y][x-1];
322   if (c_ptr->fval >= MIN_CAVE_WALL)
323     i++;
324   c_ptr = &cave[y][x+1];
325   if (c_ptr->fval >= MIN_CAVE_WALL)
326     i++;
327 
328   return(i);
329 }
330 
331 
332 /* Checks all adjacent spots for corridors		-RAK-	*/
333 /* note that y, x is always in_bounds(), hence no need to check that
334    j, k are in_bounds(), even if they are 0 or cur_x-1 is still works */
next_to_corr(y,x)335 int next_to_corr(y, x)
336 register int y, x;
337 {
338   register int k, j, i;
339   register cave_type *c_ptr;
340 
341   i = 0;
342   for (j = y - 1; j <= (y + 1); j++)
343     for (k = x - 1; k <= (x + 1); k++)
344       {
345 	c_ptr = &cave[j][k];
346 	/* should fail if there is already a door present */
347 	if (c_ptr->fval == CORR_FLOOR
348 	    && (c_ptr->tptr == 0 || t_list[c_ptr->tptr].tval < TV_MIN_DOORS))
349 	  i++;
350       }
351   return(i);
352 }
353 
354 
355 /* generates damage for 2d6 style dice rolls */
damroll(num,sides)356 int damroll(num, sides)
357 int num, sides;
358 {
359   register int i, sum = 0;
360 
361   for (i = 0; i < num; i++)
362     sum += randint(sides);
363   return(sum);
364 }
365 
pdamroll(array)366 int pdamroll(array)
367 int8u *array;
368 {
369   return damroll((int)array[0], (int)array[1]);
370 }
371 
372 
373 /* A simple, fast, integer-based line-of-sight algorithm.  By Joseph Hall,
374    4116 Brewster Drive, Raleigh NC 27606.  Email to jnh@ecemwl.ncsu.edu.
375 
376    Returns TRUE if a line of sight can be traced from x0, y0 to x1, y1.
377 
378    The LOS begins at the center of the tile [x0, y0] and ends at
379    the center of the tile [x1, y1].  If los() is to return TRUE, all of
380    the tiles this line passes through must be transparent, WITH THE
381    EXCEPTIONS of the starting and ending tiles.
382 
383    We don't consider the line to be "passing through" a tile if
384    it only passes across one corner of that tile. */
385 
386 /* Because this function uses (short) ints for all calculations, overflow
387    may occur if deltaX and deltaY exceed 90. */
388 
los(fromY,fromX,toY,toX)389 int los(fromY, fromX, toY, toX)
390 int fromY, fromX, toY, toX;
391 {
392   register int tmp, deltaX, deltaY;
393 
394   deltaX = toX - fromX;
395   deltaY = toY - fromY;
396 
397   /* Adjacent? */
398   if ((deltaX < 2) && (deltaX > -2) && (deltaY < 2) && (deltaY > -2))
399     return TRUE;
400 
401   /* Handle the cases where deltaX or deltaY == 0. */
402   if (deltaX == 0)
403     {
404       register int p_y;	/* y position -- loop variable	*/
405 
406       if (deltaY < 0)
407 	{
408 	  tmp = fromY;
409 	  fromY = toY;
410 	  toY = tmp;
411 	}
412       for (p_y = fromY + 1; p_y < toY; p_y++)
413 	if (cave[p_y][fromX].fval >= MIN_CLOSED_SPACE)
414 	  return FALSE;
415       return TRUE;
416     }
417   else if (deltaY == 0)
418     {
419       register int px;	/* x position -- loop variable	*/
420 
421       if (deltaX < 0)
422 	{
423 	  tmp = fromX;
424 	  fromX = toX;
425 	  toX = tmp;
426 	}
427       for (px = fromX + 1; px < toX; px++)
428 	if (cave[fromY][px].fval >= MIN_CLOSED_SPACE)
429 	  return FALSE;
430       return TRUE;
431     }
432 
433   /* Now, we've eliminated all the degenerate cases.
434      In the computations below, dy (or dx) and m are multiplied by a
435      scale factor, scale = abs(deltaX * deltaY * 2), so that we can use
436      integer arithmetic. */
437 
438   {
439     register int px,	/* x position				*/
440      p_y,		/* y position				*/
441      scale2;		/* above scale factor / 2		*/
442     int scale,		/* above scale factor			*/
443      xSign,		/* sign of deltaX			*/
444      ySign,		/* sign of deltaY			*/
445      m;			/* slope or 1/slope of LOS		*/
446 
447     scale2 = abs(deltaX * deltaY);
448     scale = scale2 << 1;
449     xSign = (deltaX < 0) ? -1 : 1;
450     ySign = (deltaY < 0) ? -1 : 1;
451 
452     /* Travel from one end of the line to the other, oriented along
453        the longer axis. */
454 
455     if (abs(deltaX) >= abs(deltaY))
456       {
457 	register int dy;		/* "fractional" y position	*/
458 	/* We start at the border between the first and second tiles,
459 	   where the y offset = .5 * slope.  Remember the scale
460 	   factor.  We have:
461 
462 	   m = deltaY / deltaX * 2 * (deltaY * deltaX)
463 	     = 2 * deltaY * deltaY. */
464 
465 	dy = deltaY * deltaY;
466 	m = dy << 1;
467 	px = fromX + xSign;
468 
469 	/* Consider the special case where slope == 1. */
470 	if (dy == scale2)
471 	  {
472 	    p_y = fromY + ySign;
473 	    dy -= scale;
474 	  }
475 	else
476 	  p_y = fromY;
477 
478 	while (toX - px)
479 	  {
480 	    if (cave[p_y][px].fval >= MIN_CLOSED_SPACE)
481 	      return FALSE;
482 
483 	    dy += m;
484 	    if (dy < scale2)
485 	      px += xSign;
486 	    else if (dy > scale2)
487 	      {
488 		p_y += ySign;
489 		if (cave[p_y][px].fval >= MIN_CLOSED_SPACE)
490 		  return FALSE;
491 		px += xSign;
492 		dy -= scale;
493 	      }
494 	    else
495 	      {
496 		/* This is the case, dy == scale2, where the LOS
497 		   exactly meets the corner of a tile. */
498 		px += xSign;
499 		p_y += ySign;
500 		dy -= scale;
501 	      }
502 	  }
503 	return TRUE;
504       }
505     else
506       {
507 	register int dx;		/* "fractional" x position	*/
508 	dx = deltaX * deltaX;
509 	m = dx << 1;
510 
511 	p_y = fromY + ySign;
512 	if (dx == scale2)
513 	  {
514 	    px = fromX + xSign;
515 	    dx -= scale;
516 	  }
517 	else
518 	  px = fromX;
519 
520 	while (toY - p_y)
521 	  {
522 	    if (cave[p_y][px].fval >= MIN_CLOSED_SPACE)
523 	      return FALSE;
524 	    dx += m;
525 	    if (dx < scale2)
526 	      p_y += ySign;
527 	    else if (dx > scale2)
528 	      {
529 		px += xSign;
530 		if (cave[p_y][px].fval >= MIN_CLOSED_SPACE)
531 		  return FALSE;
532 		p_y += ySign;
533 		dx -= scale;
534 	      }
535 	    else
536 	      {
537 		px += xSign;
538 		p_y += ySign;
539 		dx -= scale;
540 	      }
541 	  }
542 	return TRUE;
543       }
544   }
545 }
546 
547 
548 /* Returns symbol for given row, column			-RAK-	*/
loc_symbol(y,x)549 unsigned char loc_symbol(y, x)
550 int y, x;
551 {
552   register cave_type *cave_ptr;
553   register struct flags *f_ptr;
554 
555   cave_ptr = &cave[y][x];
556   f_ptr = &py.flags;
557 
558   if ((cave_ptr->cptr == 1) && (!find_flag || find_prself))
559     return '@';
560   else if (f_ptr->status & PY_BLIND)
561     return ' ';
562   else if ((f_ptr->image > 0) && (randint (12) == 1))
563     return randint (95) + 31;
564   else if ((cave_ptr->cptr > 1) && (m_list[cave_ptr->cptr].ml))
565     return c_list[m_list[cave_ptr->cptr].mptr].cchar;
566   else if (!cave_ptr->pl && !cave_ptr->tl && !cave_ptr->fm)
567     return ' ';
568   else if ((cave_ptr->tptr != 0)
569 	   && (t_list[cave_ptr->tptr].tval != TV_INVIS_TRAP))
570     return t_list[cave_ptr->tptr].tchar;
571   else if (cave_ptr->fval <= MAX_CAVE_FLOOR)
572     {
573 #ifdef MSDOS
574       return floorsym;
575 #else
576       return '.';
577 #endif
578     }
579   else if (cave_ptr->fval == GRANITE_WALL || cave_ptr->fval == BOUNDARY_WALL
580 	   || highlight_seams == FALSE)
581     {
582 #ifdef MSDOS
583       return wallsym;
584 #else
585 #ifndef ATARI_ST
586       return '#';
587 #else
588       return (unsigned char)240;
589 #endif
590 #endif
591     }
592   else	/* Originally set highlight bit, but that is not portable, now use
593 	   the percent sign instead. */
594     {
595       return '%';
596     }
597 }
598 
599 
600 /* Tests a spot for light or field mark status		-RAK-	*/
test_light(y,x)601 int test_light(y, x)
602 int y, x;
603 {
604   register cave_type *cave_ptr;
605 
606   cave_ptr = &cave[y][x];
607   if (cave_ptr->pl || cave_ptr->tl || cave_ptr->fm)
608     return(TRUE);
609   else
610     return(FALSE);
611 }
612 
613 
614 /* Prints the map of the dungeon			-RAK-	*/
prt_map()615 void prt_map()
616 {
617   register int i, j, k;
618   register unsigned char tmp_char;
619 
620   k = 0;
621   for (i = panel_row_min; i <= panel_row_max; i++)  /* Top to bottom */
622     {
623       k++;
624       erase_line (k, 13);
625       for (j = panel_col_min; j <= panel_col_max; j++)	/* Left to right */
626 	{
627 	  tmp_char = loc_symbol(i, j);
628 	  if (tmp_char != ' ')
629 	    print(tmp_char, i, j);
630 	}
631     }
632 }
633 
634 
635 /* Compact monsters					-RAK-	*/
636 /* Return TRUE if any monsters were deleted, FALSE if could not delete any
637    monsters.  */
compact_monsters()638 int compact_monsters()
639 {
640   register int i;
641   int cur_dis, delete_any;
642   register monster_type *mon_ptr;
643 #ifdef ATARIST_MWC
644   int32 holder;
645 #endif
646 
647   msg_print("Compacting monsters...");
648 
649   cur_dis = 66;
650   delete_any = FALSE;
651   do
652     {
653       for (i = mfptr - 1; i >= MIN_MONIX; i--)
654 	{
655 	  mon_ptr = &m_list[i];
656 	  if ((cur_dis < mon_ptr->cdis) && (randint(3) == 1))
657 	    {
658 	      /* Never compact away the Balrog!! */
659 #ifdef ATARIST_MWC
660 	      if (c_list[mon_ptr->mptr].cmove & (holder = CM_WIN))
661 #else
662 	      if (c_list[mon_ptr->mptr].cmove & CM_WIN)
663 #endif
664 		/* Do nothing */
665 		;
666 	      /* in case this is called from within creatures(), this is a
667 		 horrible hack, the m_list/creatures() code needs to be
668 		 rewritten */
669 	      else if (hack_monptr < i)
670 		{
671 		  delete_monster(i);
672 		  delete_any = TRUE;
673 		}
674 	      else
675 		/* fix1_delete_monster() does not decrement mfptr, so
676 		   don't set delete_any if this was called */
677 		fix1_delete_monster(i);
678 	    }
679 	}
680       if (!delete_any)
681 	{
682 	  cur_dis -= 6;
683 	  /* Can't delete any monsters, return failure.  */
684 	  if (cur_dis < 0)
685 	    return FALSE;
686 	}
687     }
688   while (!delete_any);
689   return TRUE;
690 }
691 
692 
693 /* Add to the players food time				-RAK-	*/
add_food(num)694 void add_food(num)
695 int num;
696 {
697   register struct flags *p_ptr;
698   register int extra, penalty;
699 
700   p_ptr = &py.flags;
701   if (p_ptr->food < 0)	p_ptr->food = 0;
702   p_ptr->food += num;
703   if (p_ptr->food > PLAYER_FOOD_MAX)
704     {
705       msg_print("You are bloated from overeating.");
706 
707       /* Calculate how much of num is responsible for the bloating.
708 	 Give the player food credit for 1/50, and slow him for that many
709 	 turns also.  */
710       extra = p_ptr->food - PLAYER_FOOD_MAX;
711       if (extra > num)
712 	extra = num;
713       penalty = extra / 50;
714 
715       p_ptr->slow += penalty;
716       if (extra == num)
717 	p_ptr->food = p_ptr->food - num + penalty;
718       else
719 	p_ptr->food = PLAYER_FOOD_MAX + penalty;
720     }
721   else if (p_ptr->food > PLAYER_FOOD_FULL)
722     msg_print("You are full.");
723 }
724 
725 
726 /* Returns a pointer to next free space			-RAK-	*/
727 /* Returns -1 if could not allocate a monster.  */
popm()728 int popm()
729 {
730   if (mfptr == MAX_MALLOC)
731     {
732       if (! compact_monsters())
733 	return -1;
734     }
735   return (mfptr++);
736 }
737 
738 
739 /* Gives Max hit points					-RAK-	*/
max_hp(array)740 int max_hp(array)
741 int8u *array;
742 {
743   return(array[0] * array[1]);
744 }
745 
746 
747 /* Places a monster at given location			-RAK-	*/
place_monster(y,x,z,slp)748 int place_monster(y, x, z, slp)
749 register int y, x, z;
750 int slp;
751 {
752   register int cur_pos;
753   register monster_type *mon_ptr;
754 
755   cur_pos = popm();
756   if (cur_pos == -1)
757     return FALSE;
758   mon_ptr = &m_list[cur_pos];
759   mon_ptr->fy = y;
760   mon_ptr->fx = x;
761   mon_ptr->mptr = z;
762   if (c_list[z].cdefense & CD_MAX_HP)
763     mon_ptr->hp = max_hp(c_list[z].hd);
764   else
765     mon_ptr->hp = pdamroll(c_list[z].hd);
766   /* the c_list speed value is 10 greater, so that it can be a int8u */
767   mon_ptr->cspeed = c_list[z].speed - 10 + py.flags.speed;
768   mon_ptr->stunned = 0;
769   mon_ptr->cdis = distance(char_row, char_col,y,x);
770   mon_ptr->ml = FALSE;
771   cave[y][x].cptr = cur_pos;
772   if (slp)
773     {
774       if (c_list[z].sleep == 0)
775 	mon_ptr->csleep = 0;
776       else
777 	mon_ptr->csleep = (c_list[z].sleep * 2) +
778 	  randint((int)c_list[z].sleep*10);
779     }
780   else
781     mon_ptr->csleep = 0;
782   return TRUE;
783 }
784 
785 
786 /* Places a monster at given location			-RAK-	*/
place_win_monster()787 void place_win_monster()
788 {
789   register int y, x, cur_pos;
790   register monster_type *mon_ptr;
791 
792   if (!total_winner)
793     {
794       cur_pos = popm();
795       /* Check for case where could not allocate space for the win monster,
796 	 this should never happen.  */
797       if (cur_pos == -1)
798 	abort();
799       mon_ptr = &m_list[cur_pos];
800       do
801 	{
802 	  y = randint(cur_height-2);
803 	  x = randint(cur_width-2);
804 	}
805       while ((cave[y][x].fval >= MIN_CLOSED_SPACE) || (cave[y][x].cptr != 0)
806 	     || (cave[y][x].tptr != 0) ||
807 	      (distance(y,x,char_row, char_col) <= MAX_SIGHT));
808       mon_ptr->fy = y;
809       mon_ptr->fx = x;
810       mon_ptr->mptr = randint(WIN_MON_TOT) - 1 + m_level[MAX_MONS_LEVEL];
811       if (c_list[mon_ptr->mptr].cdefense & CD_MAX_HP)
812 	mon_ptr->hp = max_hp(c_list[mon_ptr->mptr].hd);
813       else
814 	mon_ptr->hp = pdamroll(c_list[mon_ptr->mptr].hd);
815       /* the c_list speed value is 10 greater, so that it can be a int8u */
816       mon_ptr->cspeed = c_list[mon_ptr->mptr].speed - 10 + py.flags.speed;
817       mon_ptr->stunned = 0;
818       mon_ptr->cdis = distance(char_row, char_col,y,x);
819       cave[y][x].cptr = cur_pos;
820       mon_ptr->csleep = 0;
821     }
822 }
823 
824 
825 /* Return a monster suitable to be placed at a given level.  This makes
826    high level monsters (up to the given level) slightly more common than
827    low level monsters at any given level.   -CJS- */
get_mons_num(level)828 int get_mons_num (level)
829 int level;
830 {
831   register int i, j, num;
832 
833   if (level == 0)
834     i = randint (m_level[0]) - 1;
835   else
836     {
837       if (level > MAX_MONS_LEVEL)
838 	level = MAX_MONS_LEVEL;
839       if (randint (MON_NASTY) == 1)
840 	{
841 	  i = randnor (0, 4);
842 	  level = level + abs(i) + 1;
843 	  if (level > MAX_MONS_LEVEL)
844 	    level = MAX_MONS_LEVEL;
845 	}
846       else
847 	{
848 	  /* This code has been added to make it slightly more likely to
849 	     get the higher level monsters. Originally a uniform
850 	     distribution over all monsters of level less than or equal to the
851 	     dungeon level. This distribution makes a level n monster occur
852 	     approx 2/n% of the time on level n, and 1/n*n% are 1st level. */
853 
854 	  num = m_level[level] - m_level[0];
855 	  i = randint (num) - 1;
856 	  j = randint (num) - 1;
857 	  if (j > i)
858 	    i = j;
859 	  level = c_list[i + m_level[0]].level;
860 	}
861       i = randint(m_level[level]-m_level[level-1]) - 1 + m_level[level-1];
862     }
863   return i;
864 }
865 
866 
867 /* Allocates a random monster				-RAK-	*/
alloc_monster(num,dis,slp)868 void alloc_monster(num, dis, slp)
869 int num, dis;
870 int slp;
871 {
872   register int y, x, i;
873   int l;
874 
875   for (i = 0; i < num; i++)
876     {
877       do
878 	{
879 	  y = randint(cur_height-2);
880 	  x = randint(cur_width-2);
881 	}
882       while (cave[y][x].fval >= MIN_CLOSED_SPACE || (cave[y][x].cptr != 0) ||
883 	     (distance(y, x, char_row, char_col) <= dis));
884 
885       l = get_mons_num (dun_level);
886       /* Dragons are always created sleeping here, so as to give the player a
887 	 sporting chance.  */
888       if (c_list[l].cchar == 'd' || c_list[l].cchar == 'D')
889 	slp = TRUE;
890       /* Place_monster() should always return TRUE here.  It does not
891 	 matter if it fails though.  */
892       (void) place_monster(y, x, l, slp);
893     }
894 }
895 
896 
897 /* Places creature adjacent to given location		-RAK-	*/
summon_monster(y,x,slp)898 int summon_monster(y, x, slp)
899 int *y, *x;
900 int slp;
901 {
902   register int i, j, k;
903   int l, summon;
904   register cave_type *cave_ptr;
905 
906   i = 0;
907   summon = FALSE;
908   l = get_mons_num (dun_level + MON_SUMMON_ADJ);
909   do
910     {
911       j = *y - 2 + randint(3);
912       k = *x - 2 + randint(3);
913       if (in_bounds(j, k))
914 	{
915 	  cave_ptr = &cave[j][k];
916 	  if (cave_ptr->fval <= MAX_OPEN_SPACE && (cave_ptr->cptr == 0))
917 	    {
918 	      /* Place_monster() should always return TRUE here.  */
919 	      if (!place_monster(j, k, l, slp))
920 		return FALSE;
921 	      summon = TRUE;
922 	      i = 9;
923 	      *y = j;
924 	      *x = k;
925 	    }
926 	}
927       i++;
928     }
929   while (i <= 9);
930   return(summon);
931 }
932 
933 
934 /* Places undead adjacent to given location		-RAK-	*/
summon_undead(y,x)935 int summon_undead(y, x)
936 int *y, *x;
937 {
938   register int i, j, k;
939   int l, m, ctr, summon;
940   register cave_type *cave_ptr;
941 
942   i = 0;
943   summon = FALSE;
944   l = m_level[MAX_MONS_LEVEL];
945   do
946     {
947       m = randint(l) - 1;
948       ctr = 0;
949       do
950 	{
951 	  if (c_list[m].cdefense & CD_UNDEAD)
952 	    {
953 	      ctr = 20;
954 	      l	 = 0;
955 	    }
956 	  else
957 	    {
958 	      m++;
959 	      if (m > l)
960 		ctr = 20;
961 	      else
962 		ctr++;
963 	    }
964 	}
965       while (ctr <= 19);
966     }
967   while(l != 0);
968   do
969     {
970       j = *y - 2 + randint(3);
971       k = *x - 2 + randint(3);
972       if (in_bounds(j, k))
973 	{
974 	  cave_ptr = &cave[j][k];
975 	  if (cave_ptr->fval <= MAX_OPEN_SPACE && (cave_ptr->cptr == 0))
976 	    {
977 	      /* Place_monster() should always return TRUE here.  */
978 	      if (! place_monster(j, k, m, FALSE))
979 		return FALSE;
980 	      summon = TRUE;
981 	      i = 9;
982 	      *y = j;
983 	      *x = k;
984 	    }
985 	}
986       i++;
987     }
988   while(i <= 9);
989   return(summon);
990 }
991 
992 
993 /* If too many objects on floor level, delete some of them-RAK-	*/
compact_objects()994 static void compact_objects()
995 {
996   register int i, j;
997   int ctr, cur_dis, chance;
998   register cave_type *cave_ptr;
999 
1000   msg_print("Compacting objects...");
1001 
1002   ctr = 0;
1003   cur_dis = 66;
1004   do
1005     {
1006       for (i = 0; i < cur_height; i++)
1007 	for (j = 0; j < cur_width; j++)
1008 	  {
1009 	    cave_ptr = &cave[i][j];
1010 	    if ((cave_ptr->tptr != 0)
1011 		&& (distance(i, j, char_row, char_col) > cur_dis))
1012 	      {
1013 		switch(t_list[cave_ptr->tptr].tval)
1014 		  {
1015 		  case TV_VIS_TRAP:
1016 		    chance = 15;
1017 		    break;
1018 		  case TV_INVIS_TRAP:
1019 		  case TV_RUBBLE:
1020 		  case TV_OPEN_DOOR: case TV_CLOSED_DOOR:
1021 		    chance = 5;
1022 		    break;
1023 		  case TV_UP_STAIR: case TV_DOWN_STAIR:
1024 		  case TV_STORE_DOOR:
1025 		    /* stairs, don't delete them */
1026 		    /* shop doors, don't delete them */
1027 		    chance = 0;
1028 		    break;
1029 		  case TV_SECRET_DOOR: /* secret doors */
1030 		    chance = 3;
1031 		    break;
1032 		  default:
1033 		    chance = 10;
1034 		  }
1035 		if (randint (100) <= chance)
1036 		  {
1037 		    (void) delete_object(i, j);
1038 		    ctr++;
1039 		  }
1040 	      }
1041 	  }
1042       if (ctr == 0)  cur_dis -= 6;
1043     }
1044   while (ctr <= 0);
1045   if (cur_dis < 66)  prt_map();
1046 }
1047 
1048 /* Gives pointer to next free space			-RAK-	*/
popt()1049 int popt()
1050 {
1051   if (tcptr == MAX_TALLOC)
1052     compact_objects();
1053   return (tcptr++);
1054 }
1055 
1056 
1057 /* Pushs a record back onto free space list		-RAK-	*/
1058 /* Delete_object() should always be called instead, unless the object in
1059    question is not in the dungeon, e.g. in store1.c and files.c */
pusht(x)1060 void pusht(x)
1061 register int8u x;
1062 {
1063   register int i, j;
1064 
1065   if (x != tcptr - 1)
1066     {
1067       t_list[x] = t_list[tcptr - 1];
1068 
1069       /* must change the tptr in the cave of the object just moved */
1070       for (i = 0; i < cur_height; i++)
1071 	for (j = 0; j < cur_width; j++)
1072 	  if (cave[i][j].tptr == tcptr - 1)
1073 	    cave[i][j].tptr = x;
1074     }
1075   tcptr--;
1076   invcopy(&t_list[tcptr], OBJ_NOTHING);
1077 }
1078 
1079 
1080 /* Boolean : is object enchanted	  -RAK- */
magik(chance)1081 int magik(chance)
1082 int chance;
1083 {
1084   if (randint(100) <= chance)
1085     return(TRUE);
1086   else
1087     return(FALSE);
1088 }
1089 
1090 
1091 /* Enchant a bonus based on degree desired -RAK- */
m_bonus(base,max_std,level)1092 int m_bonus(base, max_std, level)
1093 int base, max_std, level;
1094 {
1095   register int x, stand_dev, tmp;
1096 
1097   stand_dev = (OBJ_STD_ADJ * level / 100) + OBJ_STD_MIN;
1098   /* Check for level > max_std since that may have generated an overflow.  */
1099   if (stand_dev > max_std || level > max_std)
1100     stand_dev = max_std;
1101   /* abs may be a macro, don't call it with randnor as a parameter */
1102   tmp = randnor(0, stand_dev);
1103   x = (abs(tmp) / 10) + base;
1104   if (x < base)
1105     return(base);
1106   else
1107     return(x);
1108 }
1109