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