Ejemplo n.º 1
0
/**
 * Return how many cardinal directions around (x, y) contain walls.
 * \param c current chunk
 * \param y
 * \param x co-ordinates
 * \return the number of walls 
 */
static int next_to_walls(struct chunk *c, int y, int x)
{
    int k = 0;
    assert(square_in_bounds(c, y, x));

    if (square_iswall(c, y + 1, x)) k++;
    if (square_iswall(c, y - 1, x)) k++;
    if (square_iswall(c, y, x + 1)) k++;
    if (square_iswall(c, y, x - 1)) k++;

    return k;
}
Ejemplo n.º 2
0
/**
 * Place hidden squares that will be used to generate feeling
 * \param c is the cave struct the feeling squares are being placed in
 */
static void place_feeling(struct chunk *c)
{
	int y,x,i,j;
	int tries = 500;
	
	for (i = 0; i < z_info->feeling_total; i++) {
		for (j = 0; j < tries; j++) {
			/* Pick a random dungeon coordinate */
			y = randint0(c->height);
			x = randint0(c->width);

			/* Check to see if it is not a wall */
			if (square_iswall(c, y, x))
				continue;

			/* Check to see if it is already marked */
			if (square_isfeel(c, y, x))
				continue;

			/* Set the cave square appropriately */
			sqinfo_on(c->squares[y][x].info, SQUARE_FEEL);
			
			break;
		}
	}

	/* Reset number of feeling squares */
	c->feeling_squares = 0;
}
Ejemplo n.º 3
0
/**
 * Creates magical stairs after finishing a quest monster.
 */
static void build_quest_stairs(int y, int x)
{
	int ny, nx;

	/* Stagger around */
	while (!square_changeable(cave, y, x) && !square_iswall(cave, y, x) &&
		   !square_isdoor(cave, y, x)) {
		/* Pick a location */
		scatter(cave, &ny, &nx, y, x, 1, FALSE);

		/* Stagger */
		y = ny; x = nx;
	}

	/* Push any objects */
	push_object(y, x);

	/* Explain the staircase */
	msg("A magical staircase appears...");

	/* Create stairs down */
	square_set_feat(cave, y, x, FEAT_MORE);

	/* Update the visuals */
	player->upkeep->update |= (PU_UPDATE_VIEW | PU_MONSTERS);

	/* Fully update the flow */
	player->upkeep->update |= (PU_FORGET_FLOW | PU_UPDATE_FLOW);
}
Ejemplo n.º 4
0
/**
 * Work out if a monster can move through the grid, if necessary bashing 
 * down doors in the way.
 *
 * Returns true if the monster is able to move through the grid.
 */
static bool process_monster_can_move(struct chunk *c, struct monster *mon,
		const char *m_name, int nx, int ny, bool *did_something)
{
	struct monster_lore *lore = get_lore(mon->race);

	/* Only fiery creatures can handle lava */
	if (square_isfiery(c, ny, nx) && !rf_has(mon->race->flags, RF_IM_FIRE))
		return false;

	/* Floor is open? */
	if (square_ispassable(c, ny, nx))
		return true;

	/* Permanent wall in the way */
	if (square_iswall(c, ny, nx) && square_isperm(c, ny, nx))
		return false;

	/* Normal wall, door, or secret door in the way */

	/* There's some kind of feature in the way, so learn about
	 * kill-wall and pass-wall now */
	if (mflag_has(mon->mflag, MFLAG_VISIBLE)) {
		rf_on(lore->flags, RF_PASS_WALL);
		rf_on(lore->flags, RF_KILL_WALL);
	}

	/* Monster may be able to deal with walls and doors */
	if (rf_has(mon->race->flags, RF_PASS_WALL)) {
		return true;
	} else if (rf_has(mon->race->flags, RF_KILL_WALL)) {
		/* Remove the wall */
		square_destroy_wall(c, ny, nx);

		/* Note changes to viewable region */
		if (square_isview(c, ny, nx))
			player->upkeep->update |= (PU_UPDATE_VIEW | PU_MONSTERS);

		/* Fully update the flow since terrain changed */
		player->upkeep->update |= (PU_FORGET_FLOW | PU_UPDATE_FLOW);

		return true;
	} else if (square_iscloseddoor(c, ny, nx) ||
			   square_issecretdoor(c, ny, nx)) {
		bool may_bash = rf_has(mon->race->flags, RF_BASH_DOOR) && one_in_(2);

		/* Take a turn */
		*did_something = true;

		/* Learn about door abilities */
		if (mflag_has(mon->mflag, MFLAG_VISIBLE)) {
			rf_on(lore->flags, RF_OPEN_DOOR);
			rf_on(lore->flags, RF_BASH_DOOR);
		}

		/* Creature can open or bash doors */
		if (!rf_has(mon->race->flags, RF_OPEN_DOOR) &&
			!rf_has(mon->race->flags, RF_BASH_DOOR))
			return false;

		/* Stuck door -- try to unlock it */
		if (square_islockeddoor(c, ny, nx)) {
			int k = square_door_power(c, ny, nx);

			if (randint0(mon->hp / 10) > k) {
				if (may_bash)
					msg("%s slams against the door.", m_name);
				else
					msg("%s fiddles with the lock.", m_name);

				/* Reduce the power of the door by one */
				square_set_door_lock(c, ny, nx, k - 1);
			}
		} else {
			/* Handle viewable doors */
			if (square_isview(c, ny, nx))
				player->upkeep->update |= (PU_UPDATE_VIEW | PU_MONSTERS);

			/* Closed or secret door -- open or bash if allowed */
			if (may_bash) {
				square_smash_door(c, ny, nx);

				msg("You hear a door burst open!");
				disturb(player, 0);

				/* Fall into doorway */
				return true;
			} else if (rf_has(mon->race->flags, RF_OPEN_DOOR)) {
				square_open_door(c, ny, nx);
			}
		}
	}

	return false;
}
Ejemplo n.º 5
0
/**
 * Gather whether the dungeon has disconnects in it and whether the player
 * is disconnected from the stairs
 */
void disconnect_stats(void)
{
	int i, y, x;

	int **cave_dist;

	bool has_dsc, has_dsc_from_stairs;

	static int temp;
	static char tmp_val[100];
	static char prompt[50];

	long dsc_area = 0, dsc_from_stairs = 0;

	/* This is the prompt for no. of tries */
	strnfmt(prompt, sizeof(prompt), "Num of simulations: ");

	/* This is the default value (50) */
	strnfmt(tmp_val, sizeof(tmp_val), "%d", tries);

	/* Ask for the input */
	if (!get_string(prompt,tmp_val,7)) return;

	/* Get the new value */
	temp = atoi(tmp_val);

	/* Try at least once */
	if (temp < 1)
		temp = 1;

	/* Save */
	tries = temp;

	for (i = 1; i <= tries; i++) {
		/* Assume no disconnected areas */
		has_dsc = FALSE;

		/* Assume you can't get to stairs */
		has_dsc_from_stairs = TRUE;

		/* Make a new cave */
		cave_generate(&cave, player);

		/* Allocate the distance array */
		cave_dist = mem_zalloc(cave->height * sizeof(int*));
		for (y = 0; y < cave->height; y++)
			cave_dist[y] = mem_zalloc(cave->width * sizeof(int));

		/* Set all cave spots to inaccessible */
		for (y = 0; y < cave->height; y++)
			for (x = 1; x < cave->width; x++)
				cave_dist[y][x] = -1;

		/* Fill the distance array with the correct distances */
		calc_cave_distances(cave_dist);

		/* Cycle through the dungeon */
		for (y = 1; y < cave->height - 1; y++) {
			for (x = 1; x < cave->width - 1; x++) {

				/* Don't care about walls */
				if (square_iswall(cave, y, x)) continue;

				/* Can we get there? */
				if (cave_dist[y][x] >= 0) {

					/* Is it a  down stairs? */
					if (square_isdownstairs(cave, y, x)) {

						has_dsc_from_stairs = FALSE;

						/* debug
						msg("dist to stairs: %d",cave_dist[y][x]); */
					}
					continue;
				}

				/* Ignore vaults as they are often disconnected */
				if (square_isvault(cave, y, x)) continue;

				/* We have a disconnected area */
				has_dsc = TRUE;
			}
		}

		if (has_dsc_from_stairs) dsc_from_stairs++;

		if (has_dsc) dsc_area++;

		msg("Iteration: %d",i); 

		/* Free arrays */
		for (y = 0; x < cave->height; x++)
			mem_free(cave_dist[y]);
		mem_free(cave_dist);
	}

	msg("Total levels with disconnected areas: %ld",dsc_area);
	msg("Total levels isolated from stairs: %ld",dsc_from_stairs);

	/* Redraw the level */
	do_cmd_redraw();
}
Ejemplo n.º 6
0
void calc_cave_distances(int **cave_dist)
{
	int dist, i;
	int oy, ox, ty, tx, d;

	/* Squares with distance from player of n - 1 */
	int d_x_old[DIST_MAX];
	int d_y_old[DIST_MAX];
	int d_old_max;

	/* Squares with distance from player of n */
	int d_x_new[DIST_MAX];
	int d_y_new[DIST_MAX];
	int d_new_max;

	/* Get player location */
	oy = d_y_old[0] = player->py;
	ox = d_x_old[0] = player->px;
	d_old_max = 1;

	/* Distance from player starts at 0 */
	dist = 0;

	/* Assign the distance value to the first square (player) */
	cave_dist[oy][ox] = dist;

	do {
		d_new_max = 0;
		dist++;

		/* Loop over all visited squares of the previous iteration */
		for (i = 0; i < d_old_max; i++){

			/* Get the square we want to look at */
			oy = d_y_old[i];
			ox = d_x_old[i];

			/* debug
			msg("x: %d y: %d dist: %d %d ",ox,oy,dist-1,i); */

			/* Get all adjacent squares */
			for (d = 0; d < 8; d++) {
				/* Adjacent square location */
				ty = oy + ddy_ddd[d];
				tx = ox + ddx_ddd[d];

				if (!(square_in_bounds_fully(cave, ty, tx))) continue;

				/* Have we been here before? */
				if (cave_dist[ty][tx] >= 0) continue;

				/* Is it a wall? */
				if (square_iswall(cave, ty, tx)) continue;

				/* Add the new location */
				d_y_new[d_new_max] = ty;
				d_x_new[d_new_max] = tx;

				/* Assign the distance to that spot */
				cave_dist[ty][tx] = dist;

				d_new_max++;

				/* debug
				msg("x: %d y: %d dist: %d ",tx,ty,dist); */
			}
		}

		/* Copy the new distance list to the old one */
		for (i = 0; i < d_new_max; i++) {
			d_y_old[i] = d_y_new[i];
			d_x_old[i] = d_x_new[i];
		}
		d_old_max = d_new_max;

	} while ((d_old_max > 0) || dist == DIST_MAX);
}
Ejemplo n.º 7
0
/**
 * Work out if a monster can move through the grid, if necessary bashing 
 * down doors in the way.
 *
 * Returns TRUE if the monster is able to move through the grid.
 */
static bool process_monster_can_move(struct chunk *c, struct monster *m_ptr,
		const char *m_name, int nx, int ny, bool *did_something)
{
	monster_lore *l_ptr = get_lore(m_ptr->race);

	/* Floor is open? */
	if (square_ispassable(c, ny, nx))
		return TRUE;

	/* Permanent wall in the way */
	if (square_iswall(c, ny, nx) && square_isperm(c, ny, nx))
		return FALSE;

	/* Normal wall, door, or secret door in the way */

	/* There's some kind of feature in the way, so learn about
	 * kill-wall and pass-wall now */
	if (mflag_has(m_ptr->mflag, MFLAG_VISIBLE)) {
		rf_on(l_ptr->flags, RF_PASS_WALL);
		rf_on(l_ptr->flags, RF_KILL_WALL);
	}

	/* Monster moves through walls (and doors) */
	if (rf_has(m_ptr->race->flags, RF_PASS_WALL)) 
		return TRUE;

	/* Monster destroys walls (and doors) */
	else if (rf_has(m_ptr->race->flags, RF_KILL_WALL)) {
		/* Forget the wall */
		sqinfo_off(c->squares[ny][nx].info, SQUARE_MARK);

		/* Notice */
		square_destroy_wall(c, ny, nx);

		/* Note changes to viewable region */
		if (player_has_los_bold(ny, nx))
			player->upkeep->update |= PU_UPDATE_VIEW;

		/* Update the flow, since walls affect flow */
		player->upkeep->update |= PU_UPDATE_FLOW;

		return TRUE;
	}

	/* Handle doors and secret doors */
	else if (square_iscloseddoor(c, ny, nx) || square_issecretdoor(c, ny, nx)) {
		bool may_bash = rf_has(m_ptr->race->flags, RF_BASH_DOOR) && one_in_(2);

		/* Take a turn */
		*did_something = TRUE;

		/* Learn about door abilities */
		if (mflag_has(m_ptr->mflag, MFLAG_VISIBLE)) {
			rf_on(l_ptr->flags, RF_OPEN_DOOR);
			rf_on(l_ptr->flags, RF_BASH_DOOR);
		}

		/* Creature can open or bash doors */
		if (!rf_has(m_ptr->race->flags, RF_OPEN_DOOR) && !rf_has(m_ptr->race->flags, RF_BASH_DOOR))
			return FALSE;

		/* Stuck door -- try to unlock it */
		if (square_islockeddoor(c, ny, nx)) {
			int k = square_door_power(c, ny, nx);

			if (randint0(m_ptr->hp / 10) > k) {
				if (may_bash)
					msg("%s slams against the door.", m_name);
				else
					msg("%s fiddles with the lock.", m_name);

				/* Reduce the power of the door by one */
				square_set_door_lock(c, ny, nx, k - 1);
			}
		} else {
			/* Handle viewable doors */
			if (player_has_los_bold(ny, nx))
				player->upkeep->update |= PU_UPDATE_VIEW;

			/* Closed or secret door -- open or bash if allowed */
			if (may_bash) {
				square_smash_door(c, ny, nx);

				msg("You hear a door burst open!");
				disturb(player, 0);

				/* Fall into doorway */
				return TRUE;
			} else if (rf_has(m_ptr->race->flags, RF_OPEN_DOOR)) {
				square_open_door(c, ny, nx);
			}
		}
	}

	return FALSE;
}
Ejemplo n.º 8
0
/* Destroy walls (and doors) */
static void project_feature_handler_KILL_WALL(project_feature_handler_context_t *context)
{
	const int x = context->x;
	const int y = context->y;

	/* Non-walls (etc) */
	if (square_ispassable(cave, y, x)) return;

	/* Permanent walls */
	if (square_isperm(cave, y, x)) return;

	/* Different treatment for different walls */
	if (square_iswall(cave, y, x) && !square_hasgoldvein(cave, y, x)) {
		/* Message */
		if (square_isseen(cave, y, x)) {
			msg("The wall turns into mud!");
			context->obvious = true;

			/* Forget the wall */
			square_forget(cave, y, x);
		}

		/* Destroy the wall */
		square_destroy_wall(cave, y, x);
	} else if (square_iswall(cave, y, x) && square_hasgoldvein(cave, y, x)) {
		/* Message */
		if (square_isseen(cave, y, x)) {
			msg("The vein turns into mud!");
			msg("You have found something!");
			context->obvious = true;

			/* Forget the wall */
			square_forget(cave, y, x);
		}

		/* Destroy the wall */
		square_destroy_wall(cave, y, x);

		/* Place some gold */
		place_gold(cave, y, x, player->depth, ORIGIN_FLOOR);
	} else if (square_ismagma(cave, y, x) || square_isquartz(cave, y, x)) {
		/* Message */
		if (square_isseen(cave, y, x)) {
			msg("The vein turns into mud!");
			context->obvious = true;

			/* Forget the wall */
			square_forget(cave, y, x);
		}

		/* Destroy the wall */
		square_destroy_wall(cave, y, x);
	} else if (square_isrubble(cave, y, x)) {
		/* Message */
		if (square_isseen(cave, y, x)) {
			msg("The rubble turns into mud!");
			context->obvious = true;

			/* Forget the wall */
			square_forget(cave, y, x);
		}

		/* Destroy the rubble */
		square_destroy_rubble(cave, y, x);

		/* Hack -- place an object */
		if (randint0(100) < 10){
			if (square_isseen(cave, y, x)) {
				msg("There was something buried in the rubble!");
				context->obvious = true;
			}
			place_object(cave, y, x, player->depth, false, false,
						 ORIGIN_RUBBLE, 0);
		}
	} else if (square_isdoor(cave, y, x)) {
		/* Hack -- special message */
		if (square_isseen(cave, y, x)) {
			msg("The door turns into mud!");
			context->obvious = true;

			/* Forget the wall */
			square_forget(cave, y, x);
		}

		/* Destroy the feature */
		square_destroy_door(cave, y, x);
	}

	/* Update the visuals */
	player->upkeep->update |= (PU_UPDATE_VIEW | PU_MONSTERS);

	/* Fully update the flow */
	player->upkeep->update |= (PU_FORGET_FLOW | PU_UPDATE_FLOW);
}
Ejemplo n.º 9
0
/**
 * Work out if a monster can move through the grid, if necessary bashing 
 * down doors in the way.
 *
 * Returns true if the monster is able to move through the grid.
 */
static bool monster_turn_can_move(struct chunk *c, struct monster *mon,
		const char *m_name, int nx, int ny, bool *did_something)
{
	struct monster_lore *lore = get_lore(mon->race);

	/* Dangerous terrain in the way */
	if (monster_hates_grid(c, mon, ny, nx)) {
		return false;
	}

	/* Floor is open? */
	if (square_ispassable(c, ny, nx)) {
		return true;
	}

	/* Permanent wall in the way */
	if (square_iswall(c, ny, nx) && square_isperm(c, ny, nx)) {
		return false;
	}

	/* Normal wall, door, or secret door in the way */

	/* There's some kind of feature in the way, so learn about
	 * kill-wall and pass-wall now */
	if (monster_is_visible(mon)) {
		rf_on(lore->flags, RF_PASS_WALL);
		rf_on(lore->flags, RF_KILL_WALL);
	}

	/* Monster may be able to deal with walls and doors */
	if (rf_has(mon->race->flags, RF_PASS_WALL)) {
		return true;
	} else if (rf_has(mon->race->flags, RF_KILL_WALL)) {
		/* Remove the wall */
		square_destroy_wall(c, ny, nx);

		/* Note changes to viewable region */
		if (square_isview(c, ny, nx))
			player->upkeep->update |= (PU_UPDATE_VIEW | PU_MONSTERS);

		return true;
	} else if (square_iscloseddoor(c, ny, nx) ||
			   square_issecretdoor(c, ny, nx)) {
		bool can_open = rf_has(mon->race->flags, RF_OPEN_DOOR);
		bool can_bash = rf_has(mon->race->flags, RF_BASH_DOOR);
		bool will_bash = false;

		/* Take a turn */
		*did_something = true;

		/* Learn about door abilities */
		if (monster_is_visible(mon)) {
			rf_on(lore->flags, RF_OPEN_DOOR);
			rf_on(lore->flags, RF_BASH_DOOR);
		}

		/* If creature can open or bash doors, make a choice */
		if (can_open) {
			/* Sometimes bash anyway (impatient) */
			if (can_bash) {
				will_bash = one_in_(2) ? true : false;
			}
		} else if (can_bash) {
			/* Only choice */
			will_bash = true;
		} else {
			/* Door is an insurmountable obstacle */
			return false;
		}

		/* Now outcome depends on type of door */
		if (square_islockeddoor(c, ny, nx)) {
			/* Locked door -- test monster strength against door strength */
			int k = square_door_power(c, ny, nx);
			if (randint0(mon->hp / 10) > k) {
				if (will_bash) {
					msg("%s slams against the door.", m_name);
				} else {
					msg("%s fiddles with the lock.", m_name);
				}

				/* Reduce the power of the door by one */
				square_set_door_lock(c, ny, nx, k - 1);
			}
		} else {
			/* Closed or secret door -- always open or bash */
			if (square_isview(c, ny, nx))
				player->upkeep->update |= (PU_UPDATE_VIEW | PU_MONSTERS);

			if (will_bash) {
				square_smash_door(c, ny, nx);

				msg("You hear a door burst open!");
				disturb(player, 0);

				/* Fall into doorway */
				return true;
			} else {
				square_open_door(c, ny, nx);
			}
		}
	}

	return false;
}