示例#1
0
/**
 * Place 'num' sleeping monsters near (x, y).
 * \param c the current chunk
 * \param y1 co-ordinates to place the monsters near
 * \param x1 co-ordinates to place the monsters near
 * \param depth generation depth
 * \param num number of monsters to place
 */
void vault_monsters(struct chunk *c, int y1, int x1, int depth, int num)
{
    int k, i, y, x;

	/* If the starting location is illegal, don't even start */
	if (!square_in_bounds(c, y1, x1)) return;

    /* Try to summon "num" monsters "near" the given location */
    for (k = 0; k < num; k++) {
		/* Try nine locations */
		for (i = 0; i < 9; i++) {
			int d = 1;

			/* Pick a nearby location */
			scatter(c, &y, &x, y1, x1, d, true);

			/* Require "empty" floor grids */
			if (!square_isempty(c, y, x)) continue;

			/* Place the monster (allow groups) */
			pick_and_place_monster(c, y, x, depth, true, true,
								   ORIGIN_DROP_SPECIAL);

			break;
		}
    }
}
示例#2
0
/**
 * Place monsters, up to the number asked for, in a rectangle centered on 
 * y0, x0.  Accept values for monster depth, symbol, and maximum vertical 
 * and horizontal displacement.  Call monster restriction functions if 
 * needed.
 * \param c the current chunk being generated
 * \param type the type of monster (see comments to mon_restrict())
 * \param depth selection depth
 * \param num the number of monsters to try and place - inexact due to groups
 * \param y0
 * \param x0 the centre of the rectangle for monster placement
 * \param dy
 * \param dx the dimensions of the rectangle
 * \param origin the origin for monster drops
 *
 * Return prematurely if the code starts looping too much (this may happen 
 * if y0 or x0 are out of bounds, or the area is already occupied).
 */
void spread_monsters(struct chunk *c, const char *type, int depth, int num, 
					 int y0, int x0, int dy, int dx, byte origin)
{
    int i, j;			/* Limits on loops */
    int count;
    int y = y0, x = x0;
    int start_mon_num = c->mon_max;

    /* Restrict monsters.  Allow uniques. Leave area empty if none found. */
    if (!mon_restrict(type, depth, true))
		return;

    /* Build the monster probability table. */
    if (!get_mon_num(depth))
		return;


    /* Try to summon monsters within our rectangle of effect. */
    for (count = 0, i = 0; ((count < num) && (i < 50)); i++) {
		/* Get a location */
		if ((dy == 0) && (dx == 0)) {
			y = y0;
			x = x0;
			if (!square_in_bounds(c, y, x))
				return;
		} else {
			for (j = 0; j < 10; j++) {
				y = rand_spread(y0, dy);
				x = rand_spread(x0, dx);
				if (!square_in_bounds(c, y, x)) {
					if (j < 9)
						continue;
					else
						return;
				}
				break;
			}
		}

		/* Require "empty" floor grids */
		if (!square_isempty(c, y, x)) continue;

		/* Place the monster (sleeping, allow groups) */
		pick_and_place_monster(c, y, x, depth, true, true, origin);

		/* Rein in monster groups and escorts a little. */
		if (c->mon_max - start_mon_num > num * 2)
			break;

		/* Count the monster(s), reset the loop count */
		count++;
		i = 0;
    }

    /* Remove monster restrictions. */
    (void) mon_restrict(NULL, depth, true);
}
示例#3
0
文件: gen-monster.c 项目: lhz/angband
/**
 * To avoid rebuilding the monster list too often (which can quickly 
 * get expensive), we handle monsters of a specified race separately.
 *
 * \param c the current chunk being generated
 * \param racial_symbol the allowable monster_base symbols
 * \param vault_type the type of vault, which affects monster selection depth
 * \param data the vault text description, which contains the racial symbol
 * \param y1 the limits of the vault
 * \param y2 the limits of the vault
 * \param x1 the limits of the vault
 * \param x2 the limits of the vault
 */
void get_vault_monsters(struct chunk *c, char racial_symbol[], char *vault_type,
						const char *data, int y1, int y2, int x1, int x2)
{
    int i, y, x, depth;
    const char *t;

    for (i = 0; racial_symbol[i] != '\0'; i++) {
		/* Require correct race, allow uniques. */
		allow_unique = true;
		my_strcpy(base_d_char, format("%c", racial_symbol[i]),
				  sizeof(base_d_char));

		/* Determine level of monster */
		if (strstr(vault_type, "Lesser vault"))
			depth = player->depth + 2;
		else if (strstr(vault_type, "Medium vault"))
			depth = player->depth + 4;
		else if (strstr(vault_type, "Greater vault"))
			depth = player->depth + 6;
		else
			depth = player->depth;

		/* Prepare allocation table */
		get_mon_num_prep(mon_select);

		/* Build the monster probability table. */
		if (!get_mon_num(depth))
			continue;


		/* Place the monsters */
		for (t = data, y = y1; y <= y2; y++) {
			for (x = x1; x <= x2; x++, t++) {
				if (*t == racial_symbol[i]) {
					/* Place a monster */
					pick_and_place_monster(c, y, x, depth, false,
										   false, ORIGIN_DROP_SPECIAL);
				}
			}
		}
    }

    /* Clear any current monster restrictions. */
	get_mon_num_prep(NULL);
}
示例#4
0
/**
 * Picks a monster race, makes a new monster of that race, then attempts to 
 * place it in the dungeon at least `dis` away from the player. The monster 
 * race chosen will be appropriate for dungeon level equal to `depth`.
 *
 * If `sleep` is true, the monster is placed with its default sleep value,
 * which is given in monster.txt.
 *
 * Returns true if we successfully place a monster.
 */
bool pick_and_place_distant_monster(struct chunk *c, struct loc loc, int dis,
		bool sleep, int depth)
{
	int py = loc.y;
	int px = loc.x;

	int y = 0, x = 0;
	int	attempts_left = 10000;

	assert(c);

	/* Find a legal, distant, unoccupied, space */
	while (--attempts_left) {
		/* Pick a location */
		y = randint0(c->height);
		x = randint0(c->width);

		/* Require "naked" floor grid */
		if (!square_isempty(c, y, x)) continue;

		/* Do not put random monsters in marked rooms. */
		if ((!character_dungeon) && square_ismon_restrict(c, y, x))
			continue;

		/* Accept far away grids */
		if (distance(y, x, py, px) > dis) break;
	}

	if (!attempts_left) {
		if (OPT(cheat_xtra) || OPT(cheat_hear))
			msg("Warning! Could not allocate a new monster.");

		return false;
	}

	/* Attempt to place the monster, allow groups */
	if (pick_and_place_monster(c, y, x, depth, sleep, true, ORIGIN_DROP))
		return (true);

	/* Nope */
	return (false);
}
示例#5
0
文件: mon-make.c 项目: seebs/angband
/**
 * Picks a monster race, makes a new monster of that race, then attempts to 
 * place it in the dungeon at least `dis` away from the player. The monster 
 * race chosen will be appropriate for dungeon level equal to `depth`.
 *
 * If `sleep` is true, the monster is placed with its default sleep value,
 * which is given in monster.txt.
 *
 * Returns TRUE if we successfully place a monster.
 */
bool pick_and_place_distant_monster(struct cave *c, struct loc loc, int dis,
		bool sleep, int depth)
{
	int py = loc.y;
	int px = loc.x;

	int y = 0, x = 0;
	int	attempts_left = 10000;

	assert(c);

	/* Find a legal, distant, unoccupied, space */
	while (--attempts_left) {
		/* Pick a location */
		y = randint0(c->height);
		x = randint0(c->width);

		/* Require "naked" floor grid */
		if (!cave_isempty(c, y, x)) continue;

		/* Accept far away grids */
		if (distance(y, x, py, px) > dis) break;
	}

	if (!attempts_left) {
		if (OPT(cheat_xtra) || OPT(cheat_hear))
			msg("Warning! Could not allocate a new monster.");

		return FALSE;
	}

	/* Attempt to place the monster, allow groups */
	if (pick_and_place_monster(c, y, x, depth, sleep, TRUE, ORIGIN_DROP))
		return (TRUE);

	/* Nope */
	return (FALSE);
}
示例#6
0
文件: gen-monster.c 项目: lhz/angband
/**
 * Funtion for placing appropriate monsters in a room of chambers
 *
 * \param c the current chunk being generated
 * \param y1 the limits of the vault
 * \param x1 the limits of the vault
 * \param y2 the limits of the vault
 * \param x2 the limits of the vault
 * \param name the name of the monster type for use in mon_select()
 * \param area the total room area, used for scaling monster quantity
 */
void get_chamber_monsters(struct chunk *c, int y1, int x1, int y2, int x2, 
						  char *name, int area)
{
	int i, y, x;
	s16b monsters_left, depth;
	bool random = one_in_(20);

	/* Get a legal depth. */
	depth = c->depth + randint0(11) - 5;

	/* Choose a pit profile, using that depth. */
	if (!random)
		set_pit_type(depth, 0);

	/* Allow (slightly) tougher monsters. */
	depth = c->depth + (c->depth < 60 ? c->depth / 12 : 5);

	/* Set monster generation restrictions. Occasionally random. */
	if (random) {
		if (!mon_restrict("random", depth, true))
			return;
		my_strcpy(name, "random", sizeof(name));
	} else {
		if (!mon_restrict(dun->pit_type->name, depth, true))
			return;
		my_strcpy(name, dun->pit_type->name, sizeof(name));
	}

	/* Build the monster probability table. */
	if (!get_mon_num(depth)) {
		(void) mon_restrict(NULL, depth, false);
		name = NULL;
		return;
	}

	/* No normal monsters. */
	generate_mark(c, y1, x1, y2, x2, SQUARE_MON_RESTRICT);

	/* Allow about a monster every 20-30 grids. */
	monsters_left = area / (30 - c->depth / 10);

	/* Place the monsters. */
	for (i = 0; i < 300; i++) {
		/* Check for early completion. */
		if (!monsters_left)
			break;

		/* Pick a random in-room square. */
		y = y1 + randint0(1 + ABS(y2 - y1));
		x = x1 + randint0(1 + ABS(x2 - x1));

		/* Require a passable square with no monster in it already. */
		if (!square_isempty(c, y, x))
			continue;

		/* Place a single monster.  Sleeping 2/3rds of the time. */
		pick_and_place_monster(c, y, x, c->depth, (randint0(3) != 0), false,
											 ORIGIN_DROP_SPECIAL);

		/* One less monster to place. */
		monsters_left--;
	}

	/* Remove our restrictions. */
	(void) mon_restrict(NULL, depth, false);
}