-+-+-+-+-+-+-+-+ START OF PART 44 -+-+-+-+-+-+-+-+ X print(loc_symbol(y, x), y, x); X`7D X X X/* Normal movement`09`09`09`09`09*/ X/* When FIND_FLAG, light only permanent features`09*/ Xstatic void sub1_move_light(y1, x1, y2, x2) Xregister int x1, x2; Xint y1, y2; X`7B X register int i, j; X register cave_type *c_ptr; X int tval, top, left, bottom, right; X X if (light_flag) X `7B X for (i = y1-1; i <= y1+1; i++)`09 /* Turn off lamp light`09*/ X`09for (j = x1-1; j <= x1+1; j++) X`09 cave`5Bi`5D`5Bj`5D.tl = FALSE; X if (find_flag && !find_prself) X`09light_flag = FALSE; X `7D X else if (!find_flag `7C`7C find_prself) X light_flag = TRUE; X X for (i = y2-1; i <= y2+1; i++) X for (j = x2-1; j <= x2+1; j++) X `7B X`09c_ptr = &cave`5Bi`5D`5Bj`5D; X`09/* only light up if normal movement */ X`09if (light_flag) X`09 c_ptr->tl = TRUE; X`09if (c_ptr->fval >= MIN_CAVE_WALL) X`09 c_ptr->pl = TRUE; X`09else if (!c_ptr->fm && c_ptr->tptr != 0) X`09 `7B X`09 tval = t_list`5Bc_ptr->tptr`5D.tval; X`09 if ((tval >= TV_MIN_VISIBLE) && (tval <= TV_MAX_VISIBLE)) X`09 c_ptr->fm = TRUE; X`09 `7D X `7D X X /* From uppermost to bottom most lines player was on.`09 */ X if (y1 < y2) X `7B X top = y1 - 1; X bottom = y2 + 1; X `7D X else X `7B X top = y2 - 1; X bottom = y1 + 1; X `7D X if (x1 < x2) X `7B X left = x1 - 1; X right = x2 + 1; X `7D X else X `7B X left = x2 - 1; X right = x1 + 1; X `7D X for (i = top; i <= bottom; i++) X for (j = left; j <= right; j++) /* Leftmost to rightmost do*/ X print(loc_symbol(i, j), i, j); X`7D X X X/* When blinded, move only the player symbol.`09`09*/ X/* With no light, movement becomes involved.`09`09*/ Xstatic void sub3_move_light(y1, x1, y2, x2) Xregister int y1, x1; Xint y2, x2; X`7B X register int i, j; X X if (light_flag) X `7B X for (i = y1-1; i <= y1+1; i++) X`09for (j = x1-1; j <= x1+1; j++) X`09 `7B X`09 cave`5Bi`5D`5Bj`5D.tl = FALSE; X`09 print(loc_symbol(i, j), i, j); X`09 `7D X light_flag = FALSE; X `7D X else if (!find_flag `7C`7C find_prself) X print(loc_symbol(y1, x1), y1, x1); X X if (!find_flag `7C`7C find_prself) X print('@', y2, x2); X`7D X X X/* Package for moving the character's light about the screen`09 */ X/* Four cases : Normal, Finding, Blind, and Nolight`09 -RAK-`09 */ Xvoid move_light(y1, x1, y2, x2) Xint y1, x1, y2, x2; X`7B X if (py.flags.blind > 0 `7C`7C !player_light) X sub3_move_light(y1, x1, y2, x2); X else X sub1_move_light(y1, x1, y2, x2); X`7D X X X/* Something happens to disturb the player.`09`09-CJS- X The first arg indicates a major disturbance, which affects search. X The second arg indicates a light change. */ Xvoid disturb(s, l) Xint s, l; X`7B X command_count = 0; X if (s && (py.flags.status & PY_SEARCH)) X search_off(); X if (py.flags.rest != 0) X rest_off(); X if (l `7C`7C find_flag) X `7B X find_flag = FALSE; X check_view(); X `7D X flush(); X`7D X X X/* Search Mode enhancement`09`09`09`09-RAK-`09*/ Xvoid search_on() X`7B X change_speed(1); X py.flags.status `7C= PY_SEARCH; X prt_state(); X prt_speed(); X py.flags.food_digested++; X`7D X Xvoid search_off() X`7B X#ifdef ATARIST_MWC X int32u holder; X#endif X X check_view(); X change_speed(-1); X#ifdef ATARIST_MWC X py.flags.status &= `7E(holder = PY_SEARCH); X#else X py.flags.status &= `7EPY_SEARCH; X#endif X prt_state(); X prt_speed(); X py.flags.food_digested--; X`7D X X X/* Resting allows a player to safely restore his hp`09-RAK-`09*/ Xvoid rest() X`7B X int rest_num; X vtype rest_str; X X if (command_count > 0) X `7B X rest_num = command_count; X command_count = 0; X `7D X else X `7B X prt("Rest for how long? ", 0, 0); X rest_num = 0; X if (get_string(rest_str, 0, 19, 5)) X`09`7B X`09 if (rest_str`5B0`5D == '*') X`09 rest_num = -MAX_SHORT; X`09 else X`09 rest_num = atoi(rest_str); X`09`7D X `7D X /* check for reasonable value, must be positive number in range of a X short, or must be -MAX_SHORT */ X if ((rest_num == -MAX_SHORT) X `7C`7C (rest_num > 0) && (rest_num < MAX_SHORT)) X `7B X if (py.flags.status & PY_SEARCH) X`09search_off(); X py.flags.rest = rest_num; X py.flags.status `7C= PY_REST; X prt_state(); X py.flags.food_digested--; X prt ("Press any key to stop resting...", 0, 0); X put_qio(); X `7D X else X `7B X if (rest_num != 0) X`09msg_print ("Invalid rest count."); X erase_line(MSG_LINE, 0); X free_turn_flag = TRUE; X `7D X`7D X Xvoid rest_off() X`7B X#ifdef ATARIST_MWC X int32u holder; X#endif X X py.flags.rest = 0; X#ifdef ATARIST_MWC X py.flags.status &= `7E(holder = PY_REST); X#else X py.flags.status &= `7EPY_REST; X#endif X prt_state(); X msg_print(CNIL); /* flush last message, or delete "press any key" message V */ X py.flags.food_digested++; X`7D X X X/* Attacker's level and plusses, defender's AC`09`09-RAK-`09*/ Xint test_hit(bth, level, pth, ac, attack_type) Xint bth, level, pth, ac, attack_type; X`7B X register int i, die; X X disturb (1, 0); X i = bth + pth * BTH_PLUS_ADJ X + (level * class_level_adj`5Bpy.misc.pclass`5D`5Battack_type`5D); X /* pth could be less than 0 if player wielding weapon too heavy for him */ X /* always miss 1 out of 20, always hit 1 out of 20 */ X die = randint (20); X if ((die != 1) && ((die == 20) X`09`09 `7C`7C ((i > 0) && (randint (i) > ac)))) /* normal hit */ X return TRUE; X else X return FALSE; X`7D X X X/* Decreases players hit points and sets death flag if necessary*/ X/*`09`09`09`09`09`09`09 -RAK-`09 */ Xvoid take_hit(damage, hit_from) Xint damage; Xchar *hit_from; X`7B X if (py.flags.invuln > 0) damage = 0; X py.misc.chp -= damage; X if (py.misc.chp < 0) X `7B X if (!death) X`09`7B X`09 death = TRUE; X`09 (void) strcpy(died_from, hit_from); X`09 total_winner = FALSE; X`09`7D X new_level_flag = TRUE; X `7D X else X prt_chp(); X`7D $ CALL UNPACK MORIA1.C;1 1448022143 $ create 'f' X/* source/moria2.c: misc code, mainly handles player movement, inventory, et Vc X X Copyright (c) 1989-92 James E. Wilson, Robert A. Koeneke X X This software may be copied and distributed for educational, research, an Vd X not for profit purposes provided that this copyright and statement are X included in all such copies. */ X X#include X X#include "config.h" X#include "constant.h" X#include "types.h" X#include "externs.h" X X#if defined(LINT_ARGS) Xstatic int see_wall(int, int, int); Xstatic int see_nothing(int, int, int); X#else Xstatic int see_wall(); X#endif X X X/* Change a trap from invisible to visible`09`09-RAK-`09*/ X/* Note: Secret doors are handled here`09`09`09`09 */ Xvoid change_trap(y, x) Xregister int y, x; X`7B X register cave_type *c_ptr; X register inven_type *t_ptr; X X c_ptr = &cave`5By`5D`5Bx`5D; X t_ptr = &t_list`5Bc_ptr->tptr`5D; X if (t_ptr->tval == TV_INVIS_TRAP) X `7B X t_ptr->tval = TV_VIS_TRAP; X lite_spot(y, x); X `7D X else if (t_ptr->tval == TV_SECRET_DOOR) X `7B X /* change secret door to closed door */ X t_ptr->index = OBJ_CLOSED_DOOR; X t_ptr->tval = object_list`5BOBJ_CLOSED_DOOR`5D.tval; X t_ptr->tchar = object_list`5BOBJ_CLOSED_DOOR`5D.tchar; X lite_spot(y, x); X `7D X`7D X X X/* Searches for hidden things.`09`09`09-RAK-`09*/ Xvoid search(y, x, chance) Xint y, x, chance; X`7B X register int i, j; X register cave_type *c_ptr; X register inven_type *t_ptr; X register struct flags *p_ptr; X bigvtype tmp_str, tmp_str2; X X p_ptr = &py.flags; X if (p_ptr->confused > 0) X chance = chance / 10; X if ((p_ptr->blind > 0) `7C`7C no_light()) X chance = chance / 10; X if (p_ptr->image > 0) X chance = chance / 10; X for (i = (y - 1); i <= (y + 1); i++) X for (j = (x - 1); j <= (x + 1); j++) X if (randint(100) < chance)`09/* always in_bounds here */ X`09`7B X`09 c_ptr = &cave`5Bi`5D`5Bj`5D; X`09 /* Search for hidden objects`09`09 */ X`09 if (c_ptr->tptr != 0) X`09 `7B X`09 t_ptr = &t_list`5Bc_ptr->tptr`5D; X`09 /* Trap on floor?`09`09 */ X`09 if (t_ptr->tval == TV_INVIS_TRAP) X`09`09`7B X`09`09 objdes(tmp_str2, t_ptr, TRUE); X`09`09 (void) sprintf(tmp_str,"You have found %s",tmp_str2); X`09`09 msg_print(tmp_str); X`09`09 change_trap(i, j); X`09`09 end_find(); X`09`09`7D X`09 /* Secret door?`09`09 */ X`09 else if (t_ptr->tval == TV_SECRET_DOOR) X`09`09`7B X`09`09 msg_print("You have found a secret door."); X`09`09 change_trap(i, j); X`09`09 end_find(); X`09`09`7D X`09 /* Chest is trapped?`09 */ X`09 else if (t_ptr->tval == TV_CHEST) X`09`09`7B X`09`09 /* mask out the treasure bits */ X`09`09 if ((t_ptr->flags & CH_TRAPPED) > 1) X`09`09 if (!known2_p(t_ptr)) X`09`09 `7B X`09`09`09known2(t_ptr); X`09`09`09msg_print("You have discovered a trap on the chest!"); X`09`09 `7D X`09`09 else X`09`09 msg_print("The chest is trapped!"); X`09`09`7D X`09 `7D X`09`7D X`7D X X X/* The running algorithm:`09`09`09-CJS- X X Overview: You keep moving until something interesting happens. X If you are in an enclosed space, you follow corners. This is X the usual corridor scheme. If you are in an open space, you go X straight, but stop before entering enclosed space. This is X analogous to reaching doorways. If you have enclosed space on X one side only (that is, running along side a wall) stop if X your wall opens out, or your open space closes in. Either case X corresponds to a doorway. X X What happens depends on what you can really SEE. (i.e. if you X have no light, then running along a dark corridor is JUST like X running in a dark room.) The algorithm works equally well in X corridors, rooms, mine tailings, earthquake rubble, etc, etc. X X These conditions are kept in static memory: X`09find_openarea`09 You are in the open on at least one X`09`09`09 side. X`09find_breakleft`09 You have a wall on the left, and will X`09`09`09 stop if it opens X`09find_breakright`09 You have a wall on the right, and will X`09`09`09 stop if it opens X X To initialize these conditions is the task of find_init. If X moving from the square marked @ to the square marked . (in the X two diagrams below), then two adjacent sqares on the left and X the right (L and R) are considered. If either one is seen to X be closed, then that side is considered to be closed. If both X sides are closed, then it is an enclosed (corridor) run. X X`09 LL`09`09L X`09@.`09 L.R X`09 RR`09 @R X X Looking at more than just the immediate squares is X significant. Consider the following case. A run along the X corridor will stop just before entering the center point, X because a choice is clearly established. Running in any of X three available directions will be defined as a corridor run. X Note that a minor hack is inserted to make the angled corridor X entry (with one side blocked near and the other side blocked X further away from the runner) work correctly. The runner moves X diagonally, but then saves the previous direction as being X straight into the gap. Otherwise, the tail end of the other X entry would be perceived as an alternative on the next move. X X`09 #.# X`09 ##.## X`09 .@... X`09 ##.## X`09 #.# X X Likewise, a run along a wall, and then into a doorway (two X runs) will work correctly. A single run rightwards from @ will X stop at 1. Another run right and down will enter the corridor X and make the corner, stopping at the 2. X X`09#@`09 1 X`09########### ###### X`092`09 # X`09############# X`09# X X After any move, the function area_affect is called to X determine the new surroundings, and the direction of X subsequent moves. It takes a location (at which the runner has X just arrived) and the previous direction (from which the X runner is considered to have come). Moving one square in some X direction places you adjacent to three or five new squares X (for straight and diagonal moves) to which you were not X previously adjacent. X X ...!`09 ...`09 EG Moving from 1 to 2. X .12!`09 .1.!`09`09 . means previously adjacent X ...!`09 ..2!`09`09 ! means newly adjacent X`09`09 !!! X X You STOP if you can't even make the move in the chosen X direction. You STOP if any of the new squares are interesting X in any way: usually containing monsters or treasure. You STOP X if any of the newly adjacent squares seem to be open, and you X are also looking for a break on that side. (i.e. find_openarea X AND find_break) You STOP if any of the newly adjacent squares X do NOT seem to be open and you are in an open area, and that X side was previously entirely open. X X Corners: If you are not in the open (i.e. you are in a X corridor) and there is only one way to go in the new squares, X then turn in that direction. If there are more than two new X ways to go, STOP. If there are two ways to go, and those ways X are separated by a square which does not seem to be open, then X STOP. X X Otherwise, we have a potential corner. There are two new open X squares, which are also adjacent. One of the new squares is X diagonally located, the other is straight on (as in the X diagram). We consider two more squares further out (marked X below as ?). X`09 .X X`09 @.? X`09 #? X If they are both seen to be closed, then it is seen that no X benefit is gained from moving straight. It is a known corner. X To cut the corner, go diagonally, otherwise go straight, but X pretend you stepped diagonally into that next location for a X full view next time. Conversely, if one of the ? squares is X not seen to be closed, then there is a potential choice. We check X to see whether it is a potential corner or an intersection/room entrance. X If the square two spaces straight ahead, and the space marked with 'X' X are both blank, then it is a potential corner and enter if find_examine X is set, otherwise must stop because it is not a corner. */ X +-+-+-+-+-+-+-+- END OF PART 44 +-+-+-+-+-+-+-+-