-+-+-+-+-+-+-+-+ START OF PART 29 -+-+-+-+-+-+-+-+ X may occur if deltaX and deltaY exceed 90. */ X Xint los(fromY, fromX, toY, toX) Xint fromY, fromX, toY, toX; X`7B X register int tmp, deltaX, deltaY; X X deltaX = toX - fromX; X deltaY = toY - fromY; X X /* Adjacent? */ X if ((deltaX < 2) && (deltaX > -2) && (deltaY < 2) && (deltaY > -2)) X return TRUE; X X /* Handle the cases where deltaX or deltaY == 0. */ X if (deltaX == 0) X `7B X register int p_y;`09/* y position -- loop variable`09*/ X X if (deltaY < 0) X`09`7B X`09 tmp = fromY; X`09 fromY = toY; X`09 toY = tmp; X`09`7D X for (p_y = fromY + 1; p_y < toY; p_y++) X`09if (cave`5Bp_y`5D`5BfromX`5D.fval >= MIN_CLOSED_SPACE) X`09 return FALSE; X return TRUE; X `7D X else if (deltaY == 0) X `7B X register int px;`09/* x position -- loop variable`09*/ X X if (deltaX < 0) X`09`7B X`09 tmp = fromX; X`09 fromX = toX; X`09 toX = tmp; X`09`7D X for (px = fromX + 1; px < toX; px++) X`09if (cave`5BfromY`5D`5Bpx`5D.fval >= MIN_CLOSED_SPACE) X`09 return FALSE; X return TRUE; X `7D X X /* Now, we've eliminated all the degenerate cases. X In the computations below, dy (or dx) and m are multiplied by a X scale factor, scale = abs(deltaX * deltaY * 2), so that we can use X integer arithmetic. */ X X `7B X register int px,`09/* x position`09`09`09`09*/ X p_y,`09`09/* y position`09`09`09`09*/ X scale2;`09`09/* above scale factor / 2`09`09*/ X int scale,`09`09/* above scale factor`09`09`09*/ X xSign,`09`09/* sign of deltaX`09`09`09*/ X ySign,`09`09/* sign of deltaY`09`09`09*/ X m;`09`09`09/* slope or 1/slope of LOS`09`09*/ X X scale2 = abs(deltaX * deltaY); X scale = scale2 << 1; X xSign = (deltaX < 0) ? -1 : 1; X ySign = (deltaY < 0) ? -1 : 1; X X /* Travel from one end of the line to the other, oriented along X the longer axis. */ X X if (abs(deltaX) >= abs(deltaY)) X `7B X`09register int dy;`09`09/* "fractional" y position`09*/ X`09/* We start at the border between the first and second tiles, X`09 where the y offset = .5 * slope. Remember the scale X`09 factor. We have: X X`09 m = deltaY / deltaX * 2 * (deltaY * deltaX) X`09 = 2 * deltaY * deltaY. */ X X`09dy = deltaY * deltaY; X`09m = dy << 1; X`09px = fromX + xSign; X X`09/* Consider the special case where slope == 1. */ X`09if (dy == scale2) X`09 `7B X`09 p_y = fromY + ySign; X`09 dy -= scale; X`09 `7D X`09else X`09 p_y = fromY; X X`09while (toX - px) X`09 `7B X`09 if (cave`5Bp_y`5D`5Bpx`5D.fval >= MIN_CLOSED_SPACE) X`09 return FALSE; X X`09 dy += m; X`09 if (dy < scale2) X`09 px += xSign; X`09 else if (dy > scale2) X`09 `7B X`09`09p_y += ySign; X`09`09if (cave`5Bp_y`5D`5Bpx`5D.fval >= MIN_CLOSED_SPACE) X`09`09 return FALSE; X`09`09px += xSign; X`09`09dy -= scale; X`09 `7D X`09 else X`09 `7B X`09`09/* This is the case, dy == scale2, where the LOS X`09`09 exactly meets the corner of a tile. */ X`09`09px += xSign; X`09`09p_y += ySign; X`09`09dy -= scale; X`09 `7D X`09 `7D X`09return TRUE; X `7D X else X `7B X`09register int dx;`09`09/* "fractional" x position`09*/ X`09dx = deltaX * deltaX; X`09m = dx << 1; X X`09p_y = fromY + ySign; X`09if (dx == scale2) X`09 `7B X`09 px = fromX + xSign; X`09 dx -= scale; X`09 `7D X`09else X`09 px = fromX; X X`09while (toY - p_y) X`09 `7B X`09 if (cave`5Bp_y`5D`5Bpx`5D.fval >= MIN_CLOSED_SPACE) X`09 return FALSE; X`09 dx += m; X`09 if (dx < scale2) X`09 p_y += ySign; X`09 else if (dx > scale2) X`09 `7B X`09`09px += xSign; X`09`09if (cave`5Bp_y`5D`5Bpx`5D.fval >= MIN_CLOSED_SPACE) X`09`09 return FALSE; X`09`09p_y += ySign; X`09`09dx -= scale; X`09 `7D X`09 else X`09 `7B X`09`09px += xSign; X`09`09p_y += ySign; X`09`09dx -= scale; X`09 `7D X`09 `7D X`09return TRUE; X `7D X `7D X`7D X X X/* Returns symbol for given row, column`09`09`09-RAK-`09*/ Xunsigned char loc_symbol(y, x) Xint y, x; X`7B X register cave_type *cave_ptr; X register struct flags *f_ptr; X X cave_ptr = &cave`5By`5D`5Bx`5D; X f_ptr = &py.flags; X X if ((cave_ptr->cptr == 1) && (!find_flag `7C`7C find_prself)) X return '@'; X else if (f_ptr->status & PY_BLIND) X return ' '; X else if ((f_ptr->image > 0) && (randint (12) == 1)) X return randint (95) + 31; X else if ((cave_ptr->cptr > 1) && (m_list`5Bcave_ptr->cptr`5D.ml)) X return c_list`5Bm_list`5Bcave_ptr->cptr`5D.mptr`5D.cchar; X else if (!cave_ptr->pl && !cave_ptr->tl && !cave_ptr->fm) X return ' '; X else if ((cave_ptr->tptr != 0) X`09 && (t_list`5Bcave_ptr->tptr`5D.tval != TV_INVIS_TRAP)) X return t_list`5Bcave_ptr->tptr`5D.tchar; X else if (cave_ptr->fval <= MAX_CAVE_FLOOR) X `7B X#ifdef MSDOS X return floorsym; X#else X return '.'; X#endif X `7D X else if (cave_ptr->fval == GRANITE_WALL `7C`7C cave_ptr->fval == BOUNDARY_ VWALL X`09 `7C`7C highlight_seams == FALSE) X `7B X#ifdef MSDOS X return wallsym; X#else X#ifndef ATARI_ST X return '#'; X#else X return (unsigned char)240; X#endif X#endif X `7D X else`09/* Originally set highlight bit, but that is not portable, now use X`09 the percent sign instead. */ X `7B X return '%'; X `7D X`7D X X X/* Tests a spot for light or field mark status`09`09-RAK-`09*/ Xint test_light(y, x) Xint y, x; X`7B X register cave_type *cave_ptr; X X cave_ptr = &cave`5By`5D`5Bx`5D; X if (cave_ptr->pl `7C`7C cave_ptr->tl `7C`7C cave_ptr->fm) X return(TRUE); X else X return(FALSE); X`7D X X X/* Prints the map of the dungeon`09`09`09-RAK-`09*/ Xvoid prt_map() X`7B X register int i, j, k; X register unsigned char tmp_char; X X k = 0; X for (i = panel_row_min; i <= panel_row_max; i++) /* Top to bottom */ X `7B X k++; X erase_line (k, 13); X for (j = panel_col_min; j <= panel_col_max; j++)`09/* Left to right */ X`09`7B X`09 tmp_char = loc_symbol(i, j); X`09 if (tmp_char != ' ') X`09 print(tmp_char, i, j); X`09`7D X `7D X`7D X X X/* Compact monsters`09`09`09`09`09-RAK-`09*/ X/* Return TRUE if any monsters were deleted, FALSE if could not delete any X monsters. */ Xint compact_monsters() X`7B X register int i; X int cur_dis, delete_any; X register monster_type *mon_ptr; X#ifdef ATARIST_MWC X int32 holder; X#endif X X msg_print("Compacting monsters..."); X X cur_dis = 66; X delete_any = FALSE; X do X `7B X for (i = mfptr - 1; i >= MIN_MONIX; i--) X`09`7B X`09 mon_ptr = &m_list`5Bi`5D; X`09 if ((cur_dis < mon_ptr->cdis) && (randint(3) == 1)) X`09 `7B X`09 /* Never compact away the Balrog!! */ X#ifdef ATARIST_MWC X`09 if (c_list`5Bmon_ptr->mptr`5D.cmove & (holder = CM_WIN)) X#else X`09 if (c_list`5Bmon_ptr->mptr`5D.cmove & CM_WIN) X#endif X`09`09/* Do nothing */ X`09`09; X`09 /* in case this is called from within creatures(), this is a X`09`09 horrible hack, the m_list/creatures() code needs to be X`09`09 rewritten */ X`09 else if (hack_monptr < i) X`09`09`7B X`09`09 delete_monster(i); X`09`09 delete_any = TRUE; X`09`09`7D X`09 else X`09`09/* fix1_delete_monster() does not decrement mfptr, so X`09`09 don't set delete_any if this was called */ X`09`09fix1_delete_monster(i); X`09 `7D X`09`7D X if (!delete_any) X`09`7B X`09 cur_dis -= 6; X`09 /* Can't delete any monsters, return failure. */ X`09 if (cur_dis < 0) X`09 return FALSE; X`09`7D X `7D X while (!delete_any); X return TRUE; X`7D X X X/* Add to the players food time`09`09`09`09-RAK-`09*/ Xvoid add_food(num) Xint num; X`7B X register struct flags *p_ptr; X register int extra, penalty; X X p_ptr = &py.flags; X if (p_ptr->food < 0)`09p_ptr->food = 0; X p_ptr->food += num; X if (p_ptr->food > PLAYER_FOOD_MAX) X `7B X msg_print("You are bloated from overeating."); X X /* Calculate how much of num is responsible for the bloating. X`09 Give the player food credit for 1/50, and slow him for that many X`09 turns also. */ X extra = p_ptr->food - PLAYER_FOOD_MAX; X if (extra > num) X`09extra = num; X penalty = extra / 50; X X p_ptr->slow += penalty; X if (extra == num) X`09p_ptr->food = p_ptr->food - num + penalty; X else X`09p_ptr->food = PLAYER_FOOD_MAX + penalty; X `7D X else if (p_ptr->food > PLAYER_FOOD_FULL) X msg_print("You are full."); X`7D X X X/* Returns a pointer to next free space`09`09`09-RAK-`09*/ X/* Returns -1 if could not allocate a monster. */ Xint popm() X`7B X if (mfptr == MAX_MALLOC) X `7B X if (! compact_monsters()) X`09return -1; X `7D X return (mfptr++); X`7D X X X/* Gives Max hit points`09`09`09`09`09-RAK-`09*/ Xint max_hp(array) Xint8u *array; X`7B X return(array`5B0`5D * array`5B1`5D); X`7D X X X/* Places a monster at given location`09`09`09-RAK-`09*/ Xint place_monster(y, x, z, slp) Xregister int y, x, z; Xint slp; X`7B X register int cur_pos; X register monster_type *mon_ptr; X X cur_pos = popm(); X if (cur_pos == -1) X return FALSE; X mon_ptr = &m_list`5Bcur_pos`5D; X mon_ptr->fy = y; X mon_ptr->fx = x; X mon_ptr->mptr = z; X if (c_list`5Bz`5D.cdefense & CD_MAX_HP) X mon_ptr->hp = max_hp(c_list`5Bz`5D.hd); X else X mon_ptr->hp = pdamroll(c_list`5Bz`5D.hd); X /* the c_list speed value is 10 greater, so that it can be a int8u */ X mon_ptr->cspeed = c_list`5Bz`5D.speed - 10 + py.flags.speed; X mon_ptr->stunned = 0; X mon_ptr->cdis = distance(char_row, char_col,y,x); X mon_ptr->ml = FALSE; X cave`5By`5D`5Bx`5D.cptr = cur_pos; X if (slp) X `7B X if (c_list`5Bz`5D.sleep == 0) X`09mon_ptr->csleep = 0; X else X`09mon_ptr->csleep = (c_list`5Bz`5D.sleep * 2) + X`09 randint((int)c_list`5Bz`5D.sleep*10); X `7D X else X mon_ptr->csleep = 0; X return TRUE; X`7D X X X/* Places a monster at given location`09`09`09-RAK-`09*/ Xvoid place_win_monster() X`7B X register int y, x, cur_pos; X register monster_type *mon_ptr; X X if (!total_winner) X `7B X cur_pos = popm(); X /* Check for case where could not allocate space for the win monster, X`09 this should never happen. */ X if (cur_pos == -1) X`09abort(); X mon_ptr = &m_list`5Bcur_pos`5D; X do X`09`7B X`09 y = randint(cur_height-2); X`09 x = randint(cur_width-2); X`09`7D X while ((cave`5By`5D`5Bx`5D.fval >= MIN_CLOSED_SPACE) `7C`7C (cave`5By` V5D`5Bx`5D.cptr != 0) X`09 `7C`7C (cave`5By`5D`5Bx`5D.tptr != 0) `7C`7C X`09 (distance(y,x,char_row, char_col) <= MAX_SIGHT)); X mon_ptr->fy = y; X mon_ptr->fx = x; X mon_ptr->mptr = randint(WIN_MON_TOT) - 1 + m_level`5BMAX_MONS_LEVEL`5D V; X if (c_list`5Bmon_ptr->mptr`5D.cdefense & CD_MAX_HP) X`09mon_ptr->hp = max_hp(c_list`5Bmon_ptr->mptr`5D.hd); X else X`09mon_ptr->hp = pdamroll(c_list`5Bmon_ptr->mptr`5D.hd); X /* the c_list speed value is 10 greater, so that it can be a int8u */ X mon_ptr->cspeed = c_list`5Bmon_ptr->mptr`5D.speed - 10 + py.flags.spee Vd; X mon_ptr->stunned = 0; X mon_ptr->cdis = distance(char_row, char_col,y,x); X cave`5By`5D`5Bx`5D.cptr = cur_pos; X mon_ptr->csleep = 0; X `7D X`7D X X X/* Return a monster suitable to be placed at a given level. This makes X high level monsters (up to the given level) slightly more common than X low level monsters at any given level. -CJS- */ Xint get_mons_num (level) Xint level; X`7B X register int i, j, num; X X if (level == 0) X i = randint (m_level`5B0`5D) - 1; X else X `7B X if (level > MAX_MONS_LEVEL) X`09level = MAX_MONS_LEVEL; X if (randint (MON_NASTY) == 1) X`09`7B X`09 i = randnor (0, 4); X`09 level = level + abs(i) + 1; X`09 if (level > MAX_MONS_LEVEL) X`09 level = MAX_MONS_LEVEL; X`09`7D X else X`09`7B X`09 /* This code has been added to make it slightly more likely to X`09 get the higher level monsters. Originally a uniform X`09 distribution over all monsters of level less than or equal to the X`09 dungeon level. This distribution makes a level n monster occur X`09 approx 2/n% of the time on level n, and 1/n*n% are 1st level. */ X X`09 num = m_level`5Blevel`5D - m_level`5B0`5D; X`09 i = randint (num) - 1; X`09 j = randint (num) - 1; X`09 if (j > i) X`09 i = j; X`09 level = c_list`5Bi + m_level`5B0`5D`5D.level; X`09`7D X i = randint(m_level`5Blevel`5D-m_level`5Blevel-1`5D) - 1 + m_level`5Bl Vevel-1`5D; X `7D X return i; X`7D X X X/* Allocates a random monster`09`09`09`09-RAK-`09*/ Xvoid alloc_monster(num, dis, slp) Xint num, dis; Xint slp; X`7B X register int y, x, i; X int l; X X for (i = 0; i < num; i++) X `7B X do X`09`7B X`09 y = randint(cur_height-2); X`09 x = randint(cur_width-2); X`09`7D X while (cave`5By`5D`5Bx`5D.fval >= MIN_CLOSED_SPACE `7C`7C (cave`5By`5D V`5Bx`5D.cptr != 0) `7C`7C X`09 (distance(y, x, char_row, char_col) <= dis)); X X l = get_mons_num (dun_level); X /* Dragons are always created sleeping here, so as to give the player V a X`09 sporting chance. */ X if (c_list`5Bl`5D.cchar == 'd' `7C`7C c_list`5Bl`5D.cchar == 'D') X`09slp = TRUE; X /* Place_monster() should always return TRUE here. It does not X`09 matter if it fails though. */ X (void) place_monster(y, x, l, slp); X `7D X`7D X X X/* Places creature adjacent to given location`09`09-RAK-`09*/ Xint summon_monster(y, x, slp) Xint *y, *x; Xint slp; X`7B X register int i, j, k; X int l, summon; X register cave_type *cave_ptr; X X i = 0; X summon = FALSE; X l = get_mons_num (dun_level + MON_SUMMON_ADJ); X do X `7B X j = *y - 2 + randint(3); X k = *x - 2 + randint(3); X if (in_bounds(j, k)) X`09`7B X`09 cave_ptr = &cave`5Bj`5D`5Bk`5D; X`09 if (cave_ptr->fval <= MAX_OPEN_SPACE && (cave_ptr->cptr == 0)) X`09 `7B X`09 /* Place_monster() should always return TRUE here. */ X`09 if (!place_monster(j, k, l, slp)) X`09`09return FALSE; X`09 summon = TRUE; X`09 i = 9; X`09 *y = j; X`09 *x = k; X`09 `7D X`09`7D X i++; X `7D X while (i <= 9); +-+-+-+-+-+-+-+- END OF PART 29 +-+-+-+-+-+-+-+-