示例#1
0
文件: mon-make.c 项目: seebs/angband
/** 
 * Helper function to place monsters that appear as friends or escorts
 */
 bool place_friends(struct cave *c, int y, int x, monster_race *race, 
		monster_race *friends_race, int total, bool sleep, byte origin)
 {
	int level_difference, extra_chance, nx, ny;
	bool is_unique, success = TRUE;
	
	/* Find the difference between current dungeon depth and monster level */
	level_difference = p_ptr->depth - friends_race->level + 5;
	
	/* Handle unique monsters */
	is_unique = rf_has(friends_race->flags, RF_UNIQUE);
	
	/* Make sure the unique hasn't been killed already */
	if (is_unique){
		total = friends_race->cur_num < friends_race->max_num ? 1 : 0;
	}
	
	/* More than 4 levels OoD, no groups allowed */
	if (level_difference <= 0 && !is_unique){
		return FALSE;
	}
	
	/* Reduce group size within 5 levels of natural depth*/
	if (level_difference < 10 && !is_unique){
		extra_chance = (total * level_difference) % 10;
		total = total * level_difference / 10;
		
		/* Instead of flooring the group value, we use the decimal place
		   as a chance of an extra monster */
		if (randint0(10) > extra_chance){
			total += 1;
		}
	}
	
	/* No monsters in this group */
	if (total <= 0){
		return FALSE;
	}
	
	/* Handle friends same as original monster */
	if (race->ridx == friends_race->ridx){
		place_new_monster_group(c, y, x, race, sleep, total, origin);
	}
	
	/* Find a nearby place to put the other groups */
	for (int j = 0; j < 50; j++){
		scatter(&ny, &nx, y, x, GROUP_DISTANCE, FALSE);
		if (cave_isopen(cave, ny, nx)) break;
	}
		
	/* Place the monsters */
	success = place_new_monster_one(ny, nx, friends_race, sleep, origin);
	if (total > 1){
		success = place_new_monster_group(c, ny, nx, friends_race, sleep, total, origin);
	}
	
	return success;
	
}
示例#2
0
/**
 * Attempts to place a monster of the given race at the given location.
 *
 * Note that certain monsters are placed with a large group of
 * identical or similar monsters. However, if `group_okay` is false,
 * then such monsters are placed by themselves.
 *
 * If `sleep` is true, the monster is placed with its default sleep value,
 * which is given in monster.txt.
 *
 * `origin` is the item origin to use for any monster drops (e.g. ORIGIN_DROP,
 * ORIGIN_DROP_PIT, etc.) 
 *
 * Note the "bizarre" use of non-recursion to prevent annoying output
 * when running a code profiler.
 *
 * Note the use of the "monster allocation table" to restrict
 * the "get_mon_num()" function to "legal" escort types.
 */
bool place_new_monster(struct cave *c, int y, int x, int r_idx, bool sleep,
	bool group_okay, byte origin)
{
	int i;

	monster_race *r_ptr;

	assert(c);
	
	assert(r_idx > 0);
	r_ptr = &r_info[r_idx];
	
	/* Place one monster, or fail */
	if (!place_new_monster_one(y, x, r_ptr, sleep, origin)) return (FALSE);

	/* We're done unless the group flag is set */
	if (!group_okay) return (TRUE);

	/* Friends for certain monsters */
	if (rf_has(r_ptr->flags, RF_FRIEND)) {
		int total = group_size_2(r_ptr);
		(void)place_new_monster_group(c, y, x, r_ptr, sleep, total, origin);
	}

	/* Friends for certain monsters */
	if (rf_has(r_ptr->flags, RF_FRIENDS)) {
		int total = group_size_1(r_ptr);
		(void)place_new_monster_group(c, y, x, r_ptr, sleep, total, origin);
	}

	/* Escorts for certain monsters */
	if (rf_has(r_ptr->flags, RF_ESCORT)) {
		/* Try to place several "escorts" */
		for (i = 0; i < 50; i++) {
			int nx, ny, z, d = 3;
			monster_race *z_ptr;

			/* Pick a location */
			scatter(&ny, &nx, y, x, d, 0);

			/* Require empty grids */
			if (!cave_empty_bold(ny, nx)) continue;

			/* Set the escort index */
			place_monster_idx = r_idx;

			/* Set the escort hook */
			get_mon_num_hook = place_monster_okay;

			/* Prepare allocation table */
			get_mon_num_prep();

			/* Pick a random race */
			z = get_mon_num(r_ptr->level);

			/* Remove restriction */
			get_mon_num_hook = NULL;

			/* Prepare allocation table */
			get_mon_num_prep();

			/* Handle failure */
			if (!z) break;

			/* Place a single escort */
			z_ptr = &r_info[z];
			(void)place_new_monster_one(ny, nx, z_ptr, sleep, origin);

			/* Place a "group" of escorts if needed */
			if (rf_has(z_ptr->flags, RF_FRIEND)) {
				int total = group_size_2(z_ptr);
				(void)place_new_monster_group(c, ny, nx, z_ptr, sleep, total, origin);
			}
			
			if (rf_has(z_ptr->flags, RF_FRIENDS) || rf_has(r_ptr->flags, RF_ESCORTS)) {
				int total = group_size_1(z_ptr);
				(void)place_new_monster_group(c, ny, nx, z_ptr, sleep, total, origin);
			}
		}
	}

	/* Success */
	return (TRUE);
}