Esempio n. 1
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);
}
Esempio n. 2
0
/**
 * 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);
}
Esempio n. 3
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.
 *
 * 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).
 */
extern void spread_monsters(char symbol, int depth, int num, int y0, int x0,
			    int dy, int dx)
{
    int i, j;			/* Limits on loops */
    int count;
    int y = y0, x = x0;
    int start_mon_num = m_max;
    bool dummy;

    /* Restrict monsters.  Allow uniques. */
    (void) mon_restrict(symbol, (byte) depth, &dummy, TRUE);

    /* Set generation level */
    monster_level = depth;

    /* 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 (!in_bounds(y, x))
		return;
	} else {
	    for (j = 0; j < 10; j++) {
		y = rand_spread(y0, dy);
		x = rand_spread(x0, dx);
		if (!in_bounds(y, x)) {
		    if (j < 9)
			continue;
		    else
			return;
		}
		break;
	    }
	}

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

	/* Place the monster (sleeping, allow groups, quickly) */
	(void) place_monster(y, x, TRUE, TRUE, TRUE);

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

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

    /* Remove monster restrictions. */
    (void) mon_restrict('\0', (byte) depth, &dummy, TRUE);

    /* Reset monster generation level. */
    monster_level = p_ptr->danger;
}
Esempio n. 4
0
extern void get_chamber_monsters(int y1, int x1, int y2, int x2)
{
    bool dummy;
    int i, y, x;
    s16b monsters_left, depth;
    char symbol;

    /* Description of monsters in room */
    char *name;

    /* Get a legal depth. */
    depth = p_ptr->danger + randint0(11) - 5;
    if (depth > 60)
	depth = 60;
    if (depth < 5)
	depth = 5;

    /* Choose a monster type, using that depth. */
    symbol = mon_symbol_at_depth[depth / 5 - 1][randint0(13)];

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

    /* Set monster generation restrictions.  Describe the monsters. */
    name = mon_restrict(symbol, (byte) depth, &dummy, TRUE);

    /* A default description probably means trouble, so stop. */
    if (streq(name, "misc") || !name[0])
	return;

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

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


    /* Usually, we want 35 monsters. */
    monsters_left = 35;

    /* Fewer monsters near the surface. */
    if (p_ptr->danger < 45)
	monsters_left = 5 + 2 * p_ptr->danger / 3;

    /* More monsters of kinds that tend to be weak. */
    if (strstr("abciBCFKRS", d_char_req))
	monsters_left += 15;

    /* 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 floor square with no monster in it already. */
	if (!cave_naked_bold(y, x))
	    continue;

	/* Place a single monster.  Sleeping 2/3rds of the time. */
	place_monster_aux(y, x, get_mon_num_quick(depth), (randint0(3) != 0),
			  FALSE);

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

    /* Remove our restrictions. */
    (void) mon_restrict('\0', (byte) depth, &dummy, FALSE);

    /* Describe */
    if (OPT(cheat_room)) {
	/* Room type */
	msg("Room of chambers (%s)", name);
    }
}
Esempio n. 5
0
/**
 * Town logic flow for generation of new town
 *
 * We start with a fully wiped cave of normal floors.
 *
 * Note that town_gen_hack() plays games with the R.N.G.
 *
 * This function does NOT do anything about the owners of the stores,
 * nor the contents thereof.  It only handles the physical layout.
 *
 * We place the player on the stairs at the same time we make them.
 *
 * Hack -- since the player always leaves the dungeon by the stairs,
 * he is always placed on the stairs, even if he left the dungeon via
 * word of recall or teleport level.
 */
static void town_gen(void)
{
	int i, y, x;

	int residents;
	int stage = p_ptr->stage;

	int qy = 0;
	int qx = 0;
	int width = DUNGEON_WID / 3;

	bool dummy;

	/* Hack - smaller for minor towns */
	if ((stage < KHAZAD_DUM_TOWN) && !MAP(DUNGEON)	&& !MAP(FANILLA))
		width /= 2;

	/* Day time */
	if (is_daylight) {
		/* Number of residents */
		residents = MIN_M_ALLOC_TD;
	}

	/* Night time or cave */
	else {
		/* Number of residents */
		residents = MIN_M_ALLOC_TN;
	}

	/* Start with solid walls */
	for (y = 0; y < DUNGEON_HGT; y++) {
		for (x = 0; x < DUNGEON_WID; x++) {
			/* Create "solid" perma-wall */
			cave_set_feat(y, x, FEAT_PERM_SOLID);
		}
	}

	/* Boundary walls (see town_illuminate() */
	for (x = qx; x < qx + width; x++) {
		cave_set_feat(qy, x, FEAT_PERM_INNER);
		cave_set_feat(qy + (DUNGEON_HGT / 3) - 1, x, FEAT_PERM_INNER);
	}

	/* Boundary walls (see town_illuminate() */
	for (y = qy; y < qy + (DUNGEON_HGT / 3); y++) {
		cave_set_feat(y, qx, FEAT_PERM_INNER);
		cave_set_feat(y, qx + width - 1, FEAT_PERM_INNER);
	}

	/* Then place some floors */
	for (y = qy + 1; y < qy + (DUNGEON_HGT / 3) - 1; y++) {
		for (x = qx + 1; x < qx + width - 1; x++) {
			/* Create empty floor */
			cave_set_feat(y, x, FEAT_FLOOR);
		}
	}

	/* Build stuff */
	town_gen_hack();

	/* Remove restrictions */
	(void) mon_restrict('\0', 0, &dummy, FALSE);

	/* Make some residents */
	for (i = 0; i < residents; i++) {
		/* Make a resident */
		(void) alloc_monster(3, TRUE, FALSE);
	}
}