/**
 * Clear the dungeon, ready for generation to begin.
 */
static void cave_clear(struct chunk *c, struct player *p)
{
	int x, y;

	/* Clear the monsters */
	wipe_mon_list(c, p);

	/* Deal with artifacts */
	for (y = 0; y < c->height; y++) {
		for (x = 0; x < c->width; x++) {
			struct object *obj = square_object(c, y, x);
			while (obj) {
				if (obj->artifact) {
					if (!OPT(birth_no_preserve) && !object_was_sensed(obj))
						obj->artifact->created = FALSE;
					else
						history_lose_artifact(obj->artifact);
				}
				obj = obj->next;
			}
		}
	}
	/* Free the chunk */
	cave_free(c);
}
Exemple #2
0
/**
 * Free player struct
 */
static void cleanup_player(void) {
	int i;

	/* Free the things that are always initialised */
	mem_free(player->obj_k);
	mem_free(player->timed);
	mem_free(player->upkeep->quiver);
	mem_free(player->upkeep->inven);
	mem_free(player->upkeep);
	player->upkeep = NULL;

	/* Free the things that are only there if there is a loaded player -
	 * checking if there are quests will suffice */
	if (player->quests) {
		player_quests_free(player);
		player_spells_free(player);
		object_pile_free(player->gear);
		object_pile_free(player->gear_k);
		for (i = 0; i < player->body.count; i++)
			string_free(player->body.slots[i].name);
		mem_free(player->body.slots);
		string_free(player->body.name);
		mem_free(player->history);
	}
	if (player->cave) {
		cave_free(player->cave);
		player->cave = NULL;
	}

	/* Free the basic player struct */
	mem_free(player);
	player = NULL;
}
Exemple #3
0
/**
 * Generate a random level.
 *
 * Confusingly, this function also generate the town level (level 0).
 * \param c is the level we're going to end up with, in practice the global cave
 * \param p is the current player struct, in practice the global player
 */
void cave_generate(struct chunk **c, struct player *p) {
	const char *error = "no generation";
	int y, x, tries = 0;
	struct chunk *chunk;

	assert(c);

	/* Generate */
	for (tries = 0; tries < 100 && error; tries++) {
		struct dun_data dun_body;

		error = NULL;

		/* Mark the dungeon as being unready (to avoid artifact loss, etc) */
		character_dungeon = FALSE;

		/* Allocate global data (will be freed when we leave the loop) */
		dun = &dun_body;
		dun->cent = mem_zalloc(z_info->level_room_max * sizeof(struct loc));
		dun->door = mem_zalloc(z_info->level_door_max * sizeof(struct loc));
		dun->wall = mem_zalloc(z_info->wall_pierce_max * sizeof(struct loc));
		dun->tunn = mem_zalloc(z_info->tunn_grid_max * sizeof(struct loc));

		/* Choose a profile and build the level */
		dun->profile = choose_profile(p->depth);
		chunk = dun->profile->builder(p);
		if (!chunk) {
			error = "Failed to find builder";
			mem_free(dun->cent);
			mem_free(dun->door);
			mem_free(dun->wall);
			mem_free(dun->tunn);
			continue;
		}

		/* Ensure quest monsters */
		if (is_quest(chunk->depth)) {
			int i;
			for (i = 1; i < z_info->r_max; i++) {
				monster_race *r_ptr = &r_info[i];
				int y, x;
				
				/* The monster must be an unseen quest monster of this depth. */
				if (r_ptr->cur_num > 0) continue;
				if (!rf_has(r_ptr->flags, RF_QUESTOR)) continue;
				if (r_ptr->level != chunk->depth) continue;
	
				/* Pick a location and place the monster */
				find_empty(chunk, &y, &x);
				place_new_monster(chunk, y, x, r_ptr, TRUE, TRUE, ORIGIN_DROP);
			}
		}

		/* Clear generation flags. */
		for (y = 0; y < chunk->height; y++) {
			for (x = 0; x < chunk->width; x++) {
				sqinfo_off(chunk->squares[y][x].info, SQUARE_WALL_INNER);
				sqinfo_off(chunk->squares[y][x].info, SQUARE_WALL_OUTER);
				sqinfo_off(chunk->squares[y][x].info, SQUARE_WALL_SOLID);
				sqinfo_off(chunk->squares[y][x].info, SQUARE_MON_RESTRICT);
			}
		}

		/* Regenerate levels that overflow their maxima */
		if (cave_monster_max(chunk) >= z_info->level_monster_max)
			error = "too many monsters";

		if (error) ROOM_LOG("Generation restarted: %s.", error);

		mem_free(dun->cent);
		mem_free(dun->door);
		mem_free(dun->wall);
		mem_free(dun->tunn);
	}

	if (error) quit_fmt("cave_generate() failed 100 times!");

	/* Free the old cave, use the new one */
	if (*c)
		cave_free(*c);
	*c = chunk;

	/* Place dungeon squares to trigger feeling (not in town) */
	if (player->depth)
		place_feeling(*c);

	/* Save the town */
	else if (!chunk_find_name("Town")) {
		struct chunk *town = chunk_write(0, 0, z_info->town_hgt,
										 z_info->town_wid, FALSE, FALSE, FALSE);
		town->name = string_make("Town");
		chunk_list_add(town);
	}

	(*c)->feeling = calc_obj_feeling(*c) + calc_mon_feeling(*c);

	/* Validate the dungeon (we could use more checks here) */
	chunk_validate_objects(*c);

	/* The dungeon is ready */
	character_dungeon = TRUE;

	/* Free old and allocate new known level */
	if (cave_k)
		cave_free(cave_k);
	cave_k = cave_new(cave->height, cave->width);
	if (!cave->depth)
		cave_known();

	(*c)->created_at = turn;
}