Beispiel #1
0
/**
 * Perform the basic "tunnel" command
 *
 * Assumes that no monster is blocking the destination.
 * Uses twall() (above) to do all "terrain feature changing".
 * Returns true if repeated commands may continue.
 */
static bool do_cmd_tunnel_aux(int y, int x)
{
	bool more = false;
	int digging_chances[DIGGING_MAX];
	bool okay = false;
	bool gold = square_hasgoldvein(cave, y, x);
	bool rubble = square_isrubble(cave, y, x);

	/* Verify legality */
	if (!do_cmd_tunnel_test(y, x)) return (false);

	calc_digging_chances(&player->state, digging_chances);

	/* Do we succeed? */
	okay = (digging_chances[square_digging(cave, y, x) - 1] > randint0(1600));

	/* Success */
	if (okay && twall(y, x)) {
		/* Rubble is a special case - could be handled more generally NRM */
		if (rubble) {
			/* Message */
			msg("You have removed the rubble.");

			/* Place an object (except in town) */
			if ((randint0(100) < 10) && player->depth) {
				/* Create a simple object */
				place_object(cave, y, x, player->depth, false, false,
							 ORIGIN_RUBBLE, 0);

				/* Observe the new object */
				if (!ignore_item_ok(square_object(cave, y, x)) &&
					square_isseen(cave, y, x))
					msg("You have found something!");
			} 
		} else if (gold) {
			/* Found treasure */
			place_gold(cave, y, x, player->depth, ORIGIN_FLOOR);
			msg("You have found something!");
		} else {
			msg("You have finished the tunnel.");
		}
	} else {
		/* Failure, continue digging */
		if (rubble)
			msg("You dig in the rubble.");
		else
			msg("You tunnel into the %s.",
				square_apparent_name(cave, player, y, x));
		more = true;
		if (square_issecretdoor(cave, y, x))
			/* Occasional Search XXX XXX */
			if (randint0(100) < 25) search(false);
	}

	/* Result */
	return (more);
}
/**
 * Examine a grid, return a keypress.
 *
 * The "mode" argument contains the "TARGET_LOOK" bit flag, which
 * indicates that the "space" key should scan through the contents
 * of the grid, instead of simply returning immediately.  This lets
 * the "look" command get complete information, without making the
 * "target" command annoying.
 *
 * The "info" argument contains the "commands" which should be shown
 * inside the "[xxx]" text.  This string must never be empty, or grids
 * containing monsters will be displayed with an extra comma.
 *
 * Note that if a monster is in the grid, we update both the monster
 * recall info and the health bar info to track that monster.
 *
 * This function correctly handles multiple objects per grid, and objects
 * and terrain features in the same grid, though the latter never happens.
 *
 * This function must handle blindness/hallucination.
 */
static ui_event target_set_interactive_aux(int y, int x, int mode)
{
	struct object *obj = NULL;

	const char *s1, *s2, *s3;

	bool boring;

	int floor_max = z_info->floor_size;
	struct object **floor_list = mem_zalloc(floor_max * sizeof(*floor_list));
	int floor_num;

	ui_event press;

	char out_val[TARGET_OUT_VAL_SIZE];

	char coords[20];

	const char *name;

	/* Describe the square location */
	coords_desc(coords, sizeof(coords), y, x);

	/* Repeat forever */
	while (1) {
		/* Paranoia */
		press.type = EVT_KBRD;
		press.key.code = ' ';
		press.key.mods = 0;

		/* Assume boring */
		boring = TRUE;

		/* Default */
		s1 = "You see ";
		s2 = "";
		s3 = "";


		/* The player */
		if (cave->squares[y][x].mon < 0) {
			/* Description */
			s1 = "You are ";

			/* Preposition */
			s2 = "on ";
		}

		/* Hallucination messes things up */
		if (player->timed[TMD_IMAGE]) {
			const char *name = "something strange";

			/* Display a message */
			if (player->wizard)
				strnfmt(out_val, sizeof(out_val),
						"%s%s%s%s, %s (%d:%d, cost=%d, when=%d).", s1, s2, s3,
						name, coords, y, x, (int)cave->squares[y][x].cost,
						(int)cave->squares[y][x].when);
			else
				strnfmt(out_val, sizeof(out_val), "%s%s%s%s, %s.",
						s1, s2, s3, name, coords);

			prt(out_val, 0, 0);
			move_cursor_relative(y, x);

			press.key = inkey();

			/* Stop on everything but "return" */
			if (press.key.code == KC_ENTER)
				continue;

			mem_free(floor_list);
			return press;
		}

		/* Actual monsters */
		if (cave->squares[y][x].mon > 0) {
			monster_type *m_ptr = square_monster(cave, y, x);
			const monster_lore *l_ptr = get_lore(m_ptr->race);

			/* Visible */
			if (mflag_has(m_ptr->mflag, MFLAG_VISIBLE) &&
				!mflag_has(m_ptr->mflag, MFLAG_UNAWARE)) {
				bool recall = FALSE;

				char m_name[80];

				/* Not boring */
				boring = FALSE;

				/* Get the monster name ("a kobold") */
				monster_desc(m_name, sizeof(m_name), m_ptr, MDESC_IND_VIS);

				/* Hack -- track this monster race */
				monster_race_track(player->upkeep, m_ptr->race);

				/* Hack -- health bar for this monster */
				health_track(player->upkeep, m_ptr);

				/* Hack -- handle stuff */
				handle_stuff(player);

				/* Interact */
				while (1) {
					/* Recall or target */
					if (recall) {
						lore_show_interactive(m_ptr->race, l_ptr);
						press = inkey_m();
					} else {
						char buf[80];

						/* Describe the monster */
						look_mon_desc(buf, sizeof(buf),
									  cave->squares[y][x].mon);

						/* Describe, and prompt for recall */
						if (player->wizard) {
							strnfmt(out_val, sizeof(out_val),
									"%s%s%s%s (%s), %s (%d:%d, cost=%d, when=%d).",
									s1, s2, s3, m_name, buf, coords, y, x,
									(int)cave->squares[y][x].cost,
									(int)cave->squares[y][x].when);
						} else {
							strnfmt(out_val, sizeof(out_val),
									"%s%s%s%s (%s), %s.",
									s1, s2, s3, m_name, buf, coords);
						}

						prt(out_val, 0, 0);

						/* Place cursor */
						move_cursor_relative(y, x);

						/* Command */
						press = inkey_m();
					}

					/* Normal commands */
					if ((press.type == EVT_MOUSE) && (press.mouse.button == 1)
						&& (KEY_GRID_X(press) == x) && (KEY_GRID_Y(press) == y))
						recall = !recall;
					else
					if ((press.type == EVT_KBRD) && (press.key.code == 'r'))
						recall = !recall;
					else
						break;
				}

				if (press.type == EVT_MOUSE) {
					/* Stop on right click */
					if (press.mouse.button == 2)
						break;

					/* Sometimes stop at "space" key */
					if (press.mouse.button && !(mode & (TARGET_LOOK))) break;
				} else {
					/* Stop on everything but "return"/"space" */
					if (press.key.code != KC_ENTER && press.key.code != ' ')
						break;

					/* Sometimes stop at "space" key */
					if ((press.key.code == ' ') && !(mode & (TARGET_LOOK)))
						break;
				}

				/* Take account of gender */
				if (rf_has(m_ptr->race->flags, RF_FEMALE)) s1 = "She is ";
				else if (rf_has(m_ptr->race->flags, RF_MALE)) s1 = "He is ";
				else s1 = "It is ";

				/* Use a verb */
				s2 = "carrying ";

				/* Scan all objects being carried */
				for (obj = m_ptr->held_obj; obj; obj = obj->next) {
					char o_name[80];

					/* Obtain an object description */
					object_desc(o_name, sizeof(o_name), obj,
								ODESC_PREFIX | ODESC_FULL);

					/* Describe the object */
					if (player->wizard) {
						strnfmt(out_val, sizeof(out_val),
								"%s%s%s%s, %s (%d:%d, cost=%d, when=%d).",
								s1, s2, s3, o_name, coords, y, x,
								(int)cave->squares[y][x].cost,
								(int)cave->squares[y][x].when);
					}

					prt(out_val, 0, 0);
					move_cursor_relative(y, x);
					press = inkey_m();

					if (press.type == EVT_MOUSE) {
						/* Stop on right click */
						if (press.mouse.button == 2)
							break;

						/* Sometimes stop at "space" key */
						if (press.mouse.button && !(mode & (TARGET_LOOK)))
							break;
					} else {
						/* Stop on everything but "return"/"space" */
						if ((press.key.code != KC_ENTER) &&
							(press.key.code != ' '))
							break;

						/* Sometimes stop at "space" key */
						if ((press.key.code == ' ') && !(mode & (TARGET_LOOK)))
							break;
					}

					/* Change the intro */
					s2 = "also carrying ";
				}

				/* Double break */
				if (obj) break;

				/* Use a preposition */
				s2 = "on ";
			}
		}

		/* A trap */
		if (square_isvisibletrap(cave, y, x)) {
			struct trap *trap = cave->squares[y][x].trap;

			/* Not boring */
			boring = FALSE;

			/* Interact */
			while (1) {
				/* Change the intro */
				if (cave->squares[y][x].mon < 0) {
					s1 = "You are ";
					s2 = "on ";
				} else {
					s1 = "You see ";
					s2 = "";
				}

				/* Pick proper indefinite article */
				s3 = (is_a_vowel(trap->kind->desc[0])) ? "an " : "a ";

				/* Describe, and prompt for recall */
				if (player->wizard) {
					strnfmt(out_val, sizeof(out_val),
							"%s%s%s%s, %s (%d:%d, cost=%d, when=%d).", s1, s2,
							s3, trap->kind->name, coords, y, x,
							(int)cave->squares[y][x].cost,
							(int)cave->squares[y][x].when);
				} else {
					strnfmt(out_val, sizeof(out_val), "%s%s%s%s, %s.", 
							s1, s2, s3, trap->kind->desc, coords);
				}

				prt(out_val, 0, 0);

				/* Place cursor */
				move_cursor_relative(y, x);

				/* Command */
				press = inkey_m();
		
				/* Stop on everything but "return"/"space" */
				if ((press.key.code != KC_ENTER) && (press.key.code != ' '))
					break;
		
				/* Sometimes stop at "space" key */
				if ((press.key.code == ' ') && !(mode & (TARGET_LOOK)))
					break;
			}
		}
	
		/* Double break */
		if (square_isvisibletrap(cave, y, x))
			break;
	
		/* Assume not floored */
		floor_num = scan_floor(floor_list, floor_max, y, x, 0x0A, NULL);

		/* Scan all marked objects in the grid */
		if ((floor_num > 0) &&
		    (!(player->timed[TMD_BLIND]) ||
			 (y == player->py && x == player->px))) {
			/* Not boring */
			boring = FALSE;

			track_object(player->upkeep, floor_list[0]);
			handle_stuff(player);

			/* If there is more than one item... */
			if (floor_num > 1)
				while (1) {
					/* Describe the pile */
					if (player->wizard) {
						strnfmt(out_val, sizeof(out_val),
								"%s%s%sa pile of %d objects, %s (%d:%d, cost=%d, when=%d).",
								s1, s2, s3, floor_num, coords, y, x,
								(int)cave->squares[y][x].cost,
								(int)cave->squares[y][x].when);
					} else {
						strnfmt(out_val, sizeof(out_val),
								"%s%s%sa pile of %d objects, %s.",
								s1, s2, s3, floor_num, coords);
					}

					prt(out_val, 0, 0);
					move_cursor_relative(y, x);
					press = inkey_m();

					/* Display objects */
					if (((press.type == EVT_MOUSE) && (press.mouse.button == 1)
						 && (KEY_GRID_X(press) == x) && 
						 (KEY_GRID_Y(press) == y)) ||
						((press.type == EVT_KBRD) && (press.key.code == 'r'))) {
						int rdone = 0;
						int pos;
						while (!rdone) {
							/* Save screen */
							screen_save();

							/* Display */
							show_floor(floor_list, floor_num,
									   (OLIST_WEIGHT | OLIST_GOLD), NULL);

							/* Describe the pile */
							prt(out_val, 0, 0);
							press = inkey_m();

							/* Load screen */
							screen_load();

							if (press.type == EVT_MOUSE) {
								pos = press.mouse.y-1;
							} else {
								pos = press.key.code - 'a';
							}
							if (0 <= pos && pos < floor_num) {
								track_object(player->upkeep, floor_list[pos]);
								handle_stuff(player);
								continue;
							}
							rdone = 1;
						}

						/* Now that the user's done with the display loop,
						 * let's do the outer loop over again */
						continue;
					}

					/* Done */
					break;
				}
			/* Only one object to display */
			else {
				/* Get the single object in the list */
				struct object *obj = floor_list[0];

				/* Allow user to recall an object */
				press = target_recall_loop_object(obj, y, x, out_val, s1, s2,
												  s3, coords);

				/* Stop on everything but "return"/"space" */
				if ((press.key.code != KC_ENTER) && (press.key.code != ' '))
					break;

				/* Sometimes stop at "space" key */
				if ((press.key.code == ' ') && !(mode & (TARGET_LOOK))) break;

				/* Plurals */
				s1 = VERB_AGREEMENT(obj->number, "It is ", "They are ");

				/* Preposition */
				s2 = "on ";
			}

		}

		/* Double break */
		if (obj) break;

		name = square_apparent_name(cave, player, y, x);

		/* Terrain feature if needed */
		if (boring || square_isinteresting(cave, y, x)) {
			/* Hack -- handle unknown grids */

			/* Pick a prefix */
			if (*s2 && square_isdoor(cave, y, x)) s2 = "in ";

			/* Pick proper indefinite article */
			s3 = (is_a_vowel(name[0])) ? "an " : "a ";

			/* Hack -- special introduction for store doors */
			if (square_isshop(cave, y, x))
				s3 = "the entrance to the ";

			/* Display a message */
			if (player->wizard) {
				strnfmt(out_val, sizeof(out_val),
						"%s%s%s%s, %s (%d:%d, cost=%d, when=%d).", s1, s2, s3,
						name, coords, y, x, (int)cave->squares[y][x].cost,
						(int)cave->squares[y][x].when);
			} else {
				strnfmt(out_val, sizeof(out_val),
						"%s%s%s%s, %s.", s1, s2, s3, name, coords);
			}

			prt(out_val, 0, 0);
			move_cursor_relative(y, x);
			press = inkey_m();

			if (press.type == EVT_MOUSE) {
				/* Stop on right click */
				if (press.mouse.button == 2)
					break;
			} else {
				/* Stop on everything but "return"/"space" */
				if ((press.key.code != KC_ENTER) && (press.key.code != ' '))
					break;
			}
		}

		/* Stop on everything but "return" */
		if (press.type == EVT_MOUSE) {
				/* Stop on right click */
				if (press.mouse.button != 2)
					break;
		} else {
    			if (press.key.code != KC_ENTER) break;
		}
	}

	mem_free(floor_list);

	/* Keep going */
	return (press);
}