/* * Copyright (C) 2002-2007 The Warp Rogue Team * Part of the Warp Rogue Project * * This software is free software; you can redistribute it and/or modify * it under the terms of the GNU General Public License. * This software is distributed in the hope that it will be useful, * but WITHOUT ANY WARRANTY. * * See the license.txt file for more details. */ /* * Module Name: WorldGeneration * Description: - */ /* * Area Generator 'dungeon' */ #define Uses_Area #define Uses_Sector #define Uses_Object #define Uses_Terrain #define Uses_ProgramManager #define Uses_LoadSave #define Uses_Util #define Uses_Random #include "mheader.h" #include "cellpnt.h" #include "generate.h" #define MIN_POOLS 2 #define MAX_POOLS 6 #define MIN_POOL_EXTENSION 0 #define MAX_POOL_EXTENSION 5 #define DUNGEON_Y_MIN 1 #define DUNGEON_X_MIN 8 #define DUNGEON_Y_MAX 61 #define DUNGEON_X_MAX 118 #define DUNGEON_GATE_HEIGHT 5 #define DUNGEON_GATE_SIDE_EX 2 /* * dungeon generator configuration type */ typedef struct { char wall[OBJECT_NAME_SIZE]; char floor[TERRAIN_NAME_SIZE]; char way_up[OBJECT_NAME_SIZE]; char way_down[OBJECT_NAME_SIZE]; char obstacle[OBJECT_NAME_SIZE]; char obstacle2[OBJECT_NAME_SIZE]; char pool[TERRAIN_NAME_SIZE]; WORLD_COORD gate_level; char env_terrain[TERRAIN_NAME_SIZE]; char env_object[OBJECT_NAME_SIZE]; } DUNGEON_CONFIG; static void dungeon_generate_sector(const AREA_POINT *, CPN_TILE ); static void dungeon_build_gate(void); static void add_pools(void); static void add_pool(void); /* * dungeon generator configuartion */ static DUNGEON_CONFIG DungeonConfig; /* * dungeon generator configuration template (default values) */ static const DUNGEON_CONFIG DungeonConfigTemplate = { /* WALL */ "", /* FLOOR */ "", /* WAY_UP */ "", /* WAY_DOWN */ "", /* OBSTACLE */ "", /* OBSTACLE2 */ "", /* POOL */ "", /* GATE_LEVEL */ WORLD_COORD_NIL, /* ENV_TERRAIN */ "", /* EVN_OBJECT */ "" }; /* * the area section occupied by the dungeon */ static const AREA_SECTION DungeonArea = { DUNGEON_Y_MIN, DUNGEON_Y_MAX, DUNGEON_X_MIN, DUNGEON_X_MAX }; /* * generates a dungeon level */ void dungeon_generate(void) { AREA *area; CPN_DUNGEON *dungeon_map; AREA_COORD y, x; area = active_area(); dungeon_map = cpn_build_dungeon(5, 5, NULL); if (dungeon_map == NULL) { die(cpn_get_error()); } for (y = 0; y < dungeon_map->height; y++) { for (x = 0; x < dungeon_map->width; x++) { AREA_POINT p; p.y = y + DUNGEON_Y_MIN; p.x = x + DUNGEON_X_MIN; dungeon_generate_sector(&p, dungeon_map->map[y][x]); } } cpn_free_dungeon(dungeon_map); if (area->location.z == DungeonConfig.gate_level) { dungeon_build_gate(); } add_environment(DungeonConfig.env_terrain, DungeonConfig.env_object ); add_connections(&DungeonArea, DungeonConfig.way_up, DungeonConfig.way_down ); if (!is_empty_string(DungeonConfig.pool)) add_pools(); } /* * resets the dungeon generator */ void dungeon_reset(void) { DungeonConfig = DungeonConfigTemplate; } /* * sets the wall object */ void dungeon_set_wall(const char *object) { strcpy(DungeonConfig.wall, object); } /* * sets the floor terrain */ void dungeon_set_floor(const char *terrain) { strcpy(DungeonConfig.floor, terrain); } /* * sets the connection objects */ void dungeon_set_connections(const char *way_up, const char *way_down) { strcpy(DungeonConfig.way_up, way_up); strcpy(DungeonConfig.way_down, way_down); } /* * sets the obstacle objects */ void dungeon_set_obstacles(const char *obstacle, const char *obstacle2) { strcpy(DungeonConfig.obstacle, obstacle); strcpy(DungeonConfig.obstacle2, obstacle2); } /* * sets the pool terrain */ void dungeon_set_pools(const char *terrain) { strcpy(DungeonConfig.pool, terrain); } /* * sets the gate level */ void dungeon_set_gate_level(WORLD_COORD level) { DungeonConfig.gate_level = level; } /* * sets the environment */ void dungeon_set_environment(const char *terrain, const char *object) { strcpy(DungeonConfig.env_terrain, terrain); if (object != NULL) { strcpy(DungeonConfig.env_object, object); } } /* * generates a hive city sector */ static void dungeon_generate_sector(const AREA_POINT *p, CPN_TILE dungeon_tile ) { TERRAIN *terrain; OBJECT *object = NULL; terrain = terrain_create(DungeonConfig.floor); place_terrain(terrain, p); if (dungeon_tile == CPN_FLOOR) return; if (dungeon_tile == CPN_WALL) { object = object_create(DungeonConfig.wall); } else if (dungeon_tile == CPN_DESTRUCTABLE_OBSTACLE) { object = object_create(DungeonConfig.obstacle); } else if (dungeon_tile == CPN_DESTRUCTABLE_OBSTACLE_2) { object = object_create(DungeonConfig.obstacle2); } else { die("*** CORE ERROR *** dungeon conversion failed"); } if (object != NULL) { place_object(object, p); } } /* * adds pools */ static void add_pools(void) { int i; for (i = random_int(MIN_POOLS, MAX_POOLS); i > 0; --i) { add_pool(); } } /* * adds a pool */ static void add_pool(void) { TERRAIN *terrain; AREA_POINT pool_centre; DIRECTION direction[MAX_REAL_DIRECTIONS]; int i, j; if (sector_random(&pool_centre, SC_FREE) == NULL) { return; } terrain_destroy(terrain_at(&pool_centre)); sector_at(&pool_centre)->terrain = NULL; terrain = terrain_create(DungeonConfig.pool); place_terrain(terrain, &pool_centre); randomised_directions(direction); for (i = random_int(MIN_POOL_EXTENSION, MAX_POOL_EXTENSION), j = 0; i > 0; --i, ++j) { AREA_POINT pool_extension; pool_extension = pool_centre; move_area_point(&pool_extension, direction[j]); if (out_of_area_bounds(&pool_extension)) { continue; } if (sector_is_class(&pool_extension, SC_FREE)) { terrain_destroy(terrain_at(&pool_extension)); sector_at(&pool_extension)->terrain = NULL; terrain = terrain_create(DungeonConfig.pool); place_terrain(terrain, &pool_extension); } } } /* * builds the dungeon gate */ static void dungeon_build_gate(void) { AREA_POINT c; c.y = DungeonArea.bottom; c.x = DungeonArea.left + ((DungeonArea.right - DUNGEON_X_MIN) / 2); build_gate(&c, DUNGEON_GATE_HEIGHT, DUNGEON_GATE_SIDE_EX); }