-+-+-+-+-+-+-+-+ START OF PART 49 -+-+-+-+-+-+-+-+ X`09 if (!known2_p(i_ptr)) X`09`09`7B X`09`09 msg_print("I don't see a trap."); X`09`09 free_turn_flag = TRUE; X`09`09`7D X`09 else if (CH_TRAPPED & i_ptr->flags) X`09`09`7B X`09`09 if ((tot - level) > randint(100)) X`09`09 `7B X`09`09 i_ptr->flags &= `7ECH_TRAPPED; X`09`09 if (CH_LOCKED & i_ptr->flags) X`09`09`09i_ptr->name2 = SN_LOCKED; X`09`09 else X`09`09`09i_ptr->name2 = SN_DISARMED; X`09`09 msg_print("You have disarmed the chest."); X`09`09 known2(i_ptr); X`09`09 py.misc.exp += level; X`09`09 prt_experience(); X`09`09 `7D X`09`09 else if ((tot > 5) && (randint(tot) > 5)) X`09`09 count_msg_print("You failed to disarm the chest."); X`09`09 else X`09`09 `7B X`09`09 msg_print("You set a trap off!"); X`09`09 known2(i_ptr); X`09`09 chest_trap(y, x); X`09`09 `7D X`09`09`7D X`09 else X`09`09`7B X`09`09 msg_print("The chest was not trapped."); X`09`09 free_turn_flag = TRUE; X`09`09`7D X`09 `7D X`09 else X`09 no_disarm = TRUE; X`09`7D X else X`09no_disarm = TRUE; X X if (no_disarm) X`09`7B X`09 msg_print("I do not see anything to disarm there."); X`09 free_turn_flag = TRUE; X`09`7D X `7D X`7D X X X/* An enhanced look, with peripheral vision. Looking all 8`09-CJS- X directions will see everything which ought to be visible. Can X specify direction 5, which looks in all directions. X X For the purpose of hindering vision, each place is regarded as X a diamond just touching its four immediate neighbours. A X diamond is opaque if it is a wall, or shut door, or something X like that. A place is visible if any part of its diamond is X visible: i.e. there is a line from the view point to part of X the diamond which does not pass through any opaque diamonds. X X Consider the following situation: X X @....`09`09`09 X`09X X`09X X X .##..`09`09`09 / \ / \ / \ / \ / \ X .....`09`09`09 X @ X . X . X 1 X . X X`09`09`09`09 \ / \ / \ / \ / \ / X`09`09`09`09 X`09X X`09X X X`09 Expanded view, with`09 / \ / \ / \ / \ / \ X`09 diamonds inscribed`09 X . X # X # X 2 X . X X`09 about each point,`09 \ / \ / \ / \ / \ / X`09 and some locations`09 X`09X X`09X X X`09 numbered.`09`09 / \ / \ / \ / \ / \ X`09`09`09`09 X . X . X . X 3 X 4 X X`09`09`09`09 \ / \ / \ / \ / \ / X`09`09`09`09 X`09X X`09X X X`09- Location 1 is fully visible. X`09- Location 2 is visible, even though partially obscured. X`09- Location 3 is invisible, but if either # were X`09 transparent, it would be visible. X`09- Location 4 is completely obscured by a single #. X X The function which does the work is look_ray. It sets up its X own co-ordinate frame (global variables map back to the X dungeon frame) and looks for everything between two angles X specified from a central line. It is recursive, and each call X looks at stuff visible along a line parallel to the center X line, and a set distance away from it. A diagonal look uses X more extreme peripheral vision from the closest horizontal and X vertical directions; horizontal or vertical looks take a call X for each side of the central line. */ X X/* Globally accessed variables: gl_nseen counts the number of places where X something is seen. gl_rock indicates a look for rock or objects. X X The others map co-ords in the ray frame to dungeon co-ords. X X dungeon y = char_row`09 + gl_fyx * (ray x) + gl_fyy * (ray y) X dungeon x = char_col`09 + gl_fxx * (ray x) + gl_fxy * (ray y) */ Xstatic int gl_fxx, gl_fxy, gl_fyx, gl_fyy; Xstatic int gl_nseen, gl_noquery; Xstatic int gl_rock; X/* Intended to be indexed by dir/2, since is only relevant to horizontal or X vertical directions. */ Xstatic int set_fxy`5B`5D = `7B 0, 1,`09 0, 0, -1 `7D; Xstatic int set_fxx`5B`5D = `7B 0, 0, -1, 1,`09 0 `7D; Xstatic int set_fyy`5B`5D = `7B 0, 0,`09 1, -1,`09 0 `7D; Xstatic int set_fyx`5B`5D = `7B 0, 1,`09 0, 0, -1 `7D; X/* Map diagonal-dir/2 to a normal-dir/2. */ Xstatic int map_diag1`5B`5D = `7B 1, 3, 0, 2, 4 `7D; Xstatic int map_diag2`5B`5D = `7B 2, 1, 0, 4, 3 `7D; X X#define GRADF`0910000`09/* Any sufficiently big number will do */ X X/* Look at what we can see. This is a free move. X X Prompts for a direction, and then looks at every object in X turn within a cone of vision in that direction. For each X object, the cursor is moved over the object, a description is X given, and we wait for the user to type something. Typing X ESCAPE will abort the entire look. X X Looks first at real objects and monsters, and looks at rock X types only after all other things have been seen. Only looks at rock X types if the highlight_seams option is set. */ X Xvoid look() X`7B X register int i, abort; X int dir, dummy; X X if (py.flags.blind > 0) X msg_print("You can't see a damn thing!"); X else if (py.flags.image > 0) X msg_print("You can't believe what you are seeing! It's like a dream!"); X else if (get_alldir("Look which direction?", &dir)) X `7B X abort = FALSE; X gl_nseen = 0; X gl_rock = 0; X gl_noquery = FALSE;`09/* Have to set this up for the look_see */ X if (look_see(0, 0, &dummy)) X`09abort = TRUE; X else X`09`7B X`09 do X`09 `7B X`09 abort = FALSE; X`09 if (dir == 5) X`09`09`7B X`09`09 for (i = 1; i <= 4; i++) X`09`09 `7B X`09`09 gl_fxx = set_fxx`5Bi`5D; gl_fyx = set_fyx`5Bi`5D; X`09`09 gl_fxy = set_fxy`5Bi`5D; gl_fyy = set_fyy`5Bi`5D; X`09`09 if (look_ray(0, 2*GRADF-1, 1)) X`09`09`09`7B X`09`09`09 abort = TRUE; X`09`09`09 break; X`09`09`09`7D X`09`09 gl_fxy = -gl_fxy; X`09`09 gl_fyy = -gl_fyy; X`09`09 if (look_ray(0, 2*GRADF, 2)) X`09`09`09`7B X`09`09`09 abort = TRUE; X`09`09`09 break; X`09`09`09`7D X`09`09 `7D X`09`09`7D X`09 else if ((dir & 1) == 0)`09/* Straight directions */ X`09`09`7B X`09`09 i = dir >> 1; X`09`09 gl_fxx = set_fxx`5Bi`5D; gl_fyx = set_fyx`5Bi`5D; X`09`09 gl_fxy = set_fxy`5Bi`5D; gl_fyy = set_fyy`5Bi`5D; X`09`09 if (look_ray(0, GRADF, 1)) X`09`09 abort = TRUE; X`09`09 else X`09`09 `7B X`09`09 gl_fxy = -gl_fxy; X`09`09 gl_fyy = -gl_fyy; X`09`09 abort = look_ray(0, GRADF, 2); X`09`09 `7D X`09`09`7D X`09 else X`09`09`7B X`09`09 i = map_diag1`5Bdir >> 1`5D; X`09`09 gl_fxx = set_fxx`5Bi`5D; gl_fyx = set_fyx`5Bi`5D; X`09`09 gl_fxy = -set_fxy`5Bi`5D; gl_fyy = -set_fyy`5Bi`5D; X`09`09 if (look_ray(1, 2*GRADF, GRADF)) X`09`09 abort = TRUE; X`09`09 else X`09`09 `7B X`09`09 i = map_diag2`5Bdir >> 1`5D; X`09`09 gl_fxx = set_fxx`5Bi`5D; gl_fyx = set_fyx`5Bi`5D; X`09`09 gl_fxy = set_fxy`5Bi`5D; gl_fyy = set_fyy`5Bi`5D; X`09`09 abort = look_ray(1, 2*GRADF-1, GRADF); X`09`09 `7D X`09`09`7D X`09 `7D X`09 while (abort == FALSE && highlight_seams && (++gl_rock < 2)); X`09 if (abort) X`09 msg_print("--Aborting look--"); X`09 else X`09 `7B X`09 if (gl_nseen) X`09`09`7B X`09`09 if (dir == 5) X`09`09 msg_print("That's all you see."); X`09`09 else X`09`09 msg_print("That's all you see in that direction."); X`09`09`7D X`09 else if (dir == 5) X`09`09msg_print("You see nothing of interest."); X`09 else X`09`09msg_print("You see nothing of interest in that direction."); X`09 `7D X`09`7D X `7D X`7D X X/* Look at everything within a cone of vision between two ray X lines emanating from the player, and y or more places away X from the direct line of view. This is recursive. X X Rays are specified by gradients, y over x, multiplied by X 2*GRADF. This is ONLY called with gradients between 2*GRADF X (45 degrees) and 1 (almost horizontal). X X (y axis)/ angle from X `5E`09 /`09 ___ angle to X `7C`09 /`09 ___ X ...`7C../.....___.................... parameter y (look at things in the X `7C / ___`09`09`09 cone, and on or above this line) X `7C/ ___ X @--------------------> direction in which you are looking. (x axis) X `7C X `7C */ Xstatic int look_ray(y, from, to) Xint y, from, to; X`7B X register int max_x, x; X int transparent; X X /* from is the larger angle of the ray, since we scan towards the X center line. If from is smaller, then the ray does not exist. */ X if (from <= to `7C`7C y > MAX_SIGHT) X return FALSE; X /* Find first visible location along this line. Minimum x such X that (2x-1)/x < from/GRADF <=> x > GRADF(2x-1)/from. This may X be called with y=0 whence x will be set to 0. Thus we need a X special fix. */ X x = (int)((long)GRADF * (2 * y - 1) / from + 1); X if (x <= 0) X x = 1; X X /* Find last visible location along this line. X Maximum x such that (2x+1)/x > to/GRADF <=> x < GRADF(2x+1)/to */ X max_x = (int)(((long)GRADF * (2 * y + 1) - 1) / to); X if (max_x > MAX_SIGHT) X max_x = MAX_SIGHT; X if (max_x < x) X return FALSE; X X /* gl_noquery is a HACK to prevent doubling up on direct lines of X sight. If 'to' is`09greater than 1, we do not really look at X stuff along the direct line of sight, but we do have to see X what is opaque for the purposes of obscuring other objects. */ X if (y == 0 && to > 1 `7C`7C y == x && from < GRADF*2) X gl_noquery = TRUE; X else X gl_noquery = FALSE; X if (look_see(x, y, &transparent)) X return TRUE; X if (y == x) X gl_noquery = FALSE; X if (transparent) X goto init_transparent; X X for (;;) X `7B X /* Look down the window we've found. */ X if (look_ray(y+1, from, (int)((2 * y + 1) * (long)GRADF / x))) X`09return TRUE; X /* Find the start of next window. */ X do X`09`7B X`09 if (x == max_x) X`09 return FALSE; X`09 /* See if this seals off the scan. (If y is zero, then it will.) */ X`09 from = (int)((2 * y - 1) * (long)GRADF / x); X`09 if (from <= to) X`09 return FALSE; X`09 x++; X`09 if (look_see(x, y, &transparent)) X`09 return TRUE; X`09`7D X while(!transparent); X init_transparent: X /* Find the end of this window of visibility. */ X do X`09`7B X`09 if (x == max_x) X`09 /* The window is trimmed by an earlier limit. */ X`09 return look_ray(y+1, from, to); X`09 x++; X`09 if (look_see(x, y, &transparent)) X`09 return TRUE; X`09`7D X while(transparent); X `7D X`7D X Xstatic int look_see(x, y, transparent) Xregister int x, y; Xint *transparent; X`7B X char *dstring, *string, query; X register cave_type *c_ptr; X register int j; X bigvtype out_val, tmp_str; X X if (x < 0 `7C`7C y < 0 `7C`7C y > x) X `7B X (void) sprintf(tmp_str, "Illegal call to look_see(%d, %d)", x, y); X msg_print(tmp_str); X `7D X if (x == 0 && y == 0) X dstring = "You are on"; X else X dstring = "You see"; X j = char_col + gl_fxx * x + gl_fxy * y; X y = char_row + gl_fyx * x + gl_fyy * y; X x = j; X if (!panel_contains(y, x)) X `7B X *transparent = FALSE; X return FALSE; X `7D X c_ptr = &cave`5By`5D`5Bx`5D; X *transparent = c_ptr->fval <= MAX_OPEN_SPACE; X if (gl_noquery) X return FALSE; /* Don't look at a direct line of sight. A hack. */ X out_val`5B0`5D = 0; X if (gl_rock == 0 && c_ptr->cptr > 1 && m_list`5Bc_ptr->cptr`5D.ml) X `7B X j = m_list`5Bc_ptr->cptr`5D.mptr; X (void) sprintf(out_val, "%s %s %s. `5B(r)ecall`5D", X`09`09 dstring, X`09`09 is_a_vowel( c_list`5Bj`5D.name`5B0`5D ) ? "an" : "a", X`09`09 c_list`5Bj`5D.name); X dstring = "It is on"; X prt(out_val, 0, 0); X move_cursor_relative(y, x); X query = inkey(); X if (query == 'r' `7C`7C query == 'R') X`09`7B X`09 save_screen(); X`09 query = roff_recall(j); X`09 restore_screen(); X`09`7D X `7D X if (c_ptr->tl `7C`7C c_ptr->pl `7C`7C c_ptr->fm) X `7B X if (c_ptr->tptr != 0) X`09`7B X`09 if (t_list`5Bc_ptr->tptr`5D.tval == TV_SECRET_DOOR) X`09 goto granite; X`09 if (gl_rock ==0 && t_list`5Bc_ptr->tptr`5D.tval != TV_INVIS_TRAP) X`09 `7B X`09 objdes(tmp_str, &t_list`5Bc_ptr->tptr`5D, TRUE); X`09 (void) sprintf(out_val, "%s %s ---pause---", dstring, tmp_str); X`09 dstring = "It is in"; X`09 prt(out_val, 0, 0); X`09 move_cursor_relative(y, x); X`09 query = inkey(); X`09 `7D X`09`7D X if ((gl_rock `7C`7C out_val`5B0`5D) && c_ptr->fval >= MIN_CLOSED_SPACE V) X`09`7B X`09 switch(c_ptr->fval) X`09 `7B X`09 case BOUNDARY_WALL: X`09 case GRANITE_WALL: X`09 granite: X`09 /* Granite is only interesting if it contains something. */ X`09 if(out_val`5B0`5D) X`09`09string = "a granite wall"; X`09 else X`09`09string = CNIL;`09/* In case we jump here */ X`09 break; X`09 case MAGMA_WALL: string = "some dark rock"; X`09 break; X`09 case QUARTZ_WALL: string = "a quartz vein"; X`09 break; X`09 default: string = CNIL; X`09 break; X`09 `7D X`09 if (string) X`09 `7B X`09 (void) sprintf(out_val, "%s %s ---pause---", dstring, string); X`09 prt(out_val, 0, 0); X`09 move_cursor_relative(y, x); X`09 query = inkey(); X`09 `7D X`09`7D X `7D X if (out_val`5B0`5D) X `7B X gl_nseen++; X if (query == ESCAPE) X`09return TRUE; X `7D X X return FALSE; X`7D X X Xstatic void inven_throw(item_val, t_ptr) Xint item_val; Xinven_type *t_ptr; X`7B X register inven_type *i_ptr; X#ifdef ATARIST_MWC X int32u holder; X#endif X X i_ptr = &inventory`5Bitem_val`5D; X *t_ptr = *i_ptr; X if (i_ptr->number > 1) X `7B X t_ptr->number = 1; X i_ptr->number--; X inven_weight -= i_ptr->weight; X#ifdef ATARIST_MWC X py.flags.status `7C= (holder = PY_STR_WGT); X#else X py.flags.status `7C= PY_STR_WGT; X#endif X `7D X else X inven_destroy(item_val); X`7D X X X/* Obtain the hit and damage bonuses and the maximum distance for a X thrown missile. */ Xstatic void facts(i_ptr, tbth, tpth, tdam, tdis) Xregister inven_type *i_ptr; Xint *tbth, *tpth, *tdam, *tdis; X`7B X register int tmp_weight; X X if (i_ptr->weight < 1) X tmp_weight = 1; X else X tmp_weight = i_ptr->weight; X X /* Throwing objects`09`09`09*/ X *tdam = pdamroll(i_ptr->damage) + i_ptr->todam; X *tbth = py.misc.bthb * 75 / 100; X *tpth = py.misc.ptohit + i_ptr->tohit; X +-+-+-+-+-+-+-+- END OF PART 49 +-+-+-+-+-+-+-+-