bool createFeature(int x, int y, Direction dir) { static const int roomChance = 50; // corridorChance = 100 - roomChance int dx = 0; int dy = 0; if (dir == North) dy = 1; else if (dir == South) dy = -1; else if (dir == West) dx = 1; else if (dir == East) dx = -1; if (getTile(x + dx, y + dy) != Floor && getTile(x + dx, y + dy) != Corridor) return false; if (randomInt(100) < roomChance) { if (makeRoom(x, y, dir)) { setTile(x, y, ClosedDoor); return true; } } else { if (makeCorridor(x, y, dir)) { if (getTile(x + dx, y + dy) == Floor) setTile(x, y, ClosedDoor); else // don't place a door between corridors setTile(x, y, Corridor); return true; } } return false; }
void DungeonGen::makeDungeon(v3s16 start_padding) { v3s16 areasize = vmanip->m_area.getExtent(); v3s16 roomsize; v3s16 roomplace; /* Find place for first room */ bool fits = false; for (u32 i = 0; i < 100; i++) { bool is_large_room = ((random.next() & 3) == 1); roomsize = is_large_room ? v3s16(random.range(8, 16),random.range(8, 16),random.range(8, 16)) : v3s16(random.range(4, 8),random.range(4, 6),random.range(4, 8)); // start_padding is used to disallow starting the generation of // a dungeon in a neighboring generation chunk roomplace = vmanip->m_area.MinEdge + start_padding + v3s16( random.range(0,areasize.X-roomsize.X-1-start_padding.X), random.range(0,areasize.Y-roomsize.Y-1-start_padding.Y), random.range(0,areasize.Z-roomsize.Z-1-start_padding.Z)); /* Check that we're not putting the room to an unknown place, otherwise it might end up floating in the air */ fits = true; for (s16 z = 1; z < roomsize.Z - 1; z++) for (s16 y = 1; y < roomsize.Y - 1; y++) for (s16 x = 1; x < roomsize.X - 1; x++) { v3s16 p = roomplace + v3s16(x, y, z); u32 vi = vmanip->m_area.index(p); if (vmanip->m_flags[vi] & VMANIP_FLAG_DUNGEON_INSIDE) { fits = false; break; } if (vmanip->m_data[vi].getContent() == CONTENT_IGNORE) { fits = false; break; } } if (fits) break; } // No place found if (fits == false) return; /* Stores the center position of the last room made, so that a new corridor can be started from the last room instead of the new room, if chosen so. */ v3s16 last_room_center = roomplace + v3s16(roomsize.X / 2, 1, roomsize.Z / 2); u32 room_count = random.range(2, 16); for (u32 i = 0; i < room_count; i++) { // Make a room to the determined place makeRoom(roomsize, roomplace); v3s16 room_center = roomplace + v3s16(roomsize.X / 2, 1, roomsize.Z / 2); // Place torch at room center (for testing) //vmanip->m_data[vmanip->m_area.index(room_center)] = MapNode(cid_torch); // Quit if last room if (i == room_count - 1) break; // Determine walker start position bool start_in_last_room = (random.range(0, 2) != 0); v3s16 walker_start_place; if(start_in_last_room) { walker_start_place = last_room_center; } else { walker_start_place = room_center; // Store center of current room as the last one last_room_center = room_center; } // Create walker and find a place for a door v3s16 doorplace; v3s16 doordir; m_pos = walker_start_place; bool r = findPlaceForDoor(doorplace, doordir); if (r == false) return; if (random.range(0,1) == 0) // Make the door makeDoor(doorplace, doordir); else // Don't actually make a door doorplace -= doordir; // Make a random corridor starting from the door v3s16 corridor_end; v3s16 corridor_end_dir; makeCorridor(doorplace, doordir, corridor_end, corridor_end_dir); // Find a place for a random sized room roomsize = v3s16(random.range(4,8),random.range(4,6),random.range(4,8)); m_pos = corridor_end; m_dir = corridor_end_dir; r = findPlaceForRoomDoor(roomsize, doorplace, doordir, roomplace); if (r == false) return; if (random.range(0,1) == 0) // Make the door makeDoor(doorplace, doordir); else // Don't actually make a door roomplace -= doordir; } }
void DungeonGen::makeDungeon(v3s16 start_padding) { v3s16 areasize = vm->m_area.getExtent(); v3s16 roomsize; v3s16 roomplace; float far_multi = farscale(5, vm->m_area.MinEdge.X, vm->m_area.MinEdge.Y, vm->m_area.MinEdge.Z); /* Find place for first room */ bool fits = false; for (u32 i = 0; i < 100 && !fits; i++) { bool is_large_room = ((random.next() & 3) == 1); if (is_large_room) { roomsize.Z = random.range(8, 16 * far_multi); roomsize.Y = random.range(8, 16 * far_multi); roomsize.X = random.range(8, 16 * far_multi); } else { roomsize.Z = random.range(4, 8 * far_multi); roomsize.Y = random.range(4, 6 * far_multi); roomsize.X = random.range(4, 8 * far_multi); } roomsize += dp.roomsize; // start_padding is used to disallow starting the generation of // a dungeon in a neighboring generation chunk roomplace = vm->m_area.MinEdge + start_padding; roomplace.Z += random.range(0, areasize.Z - roomsize.Z - start_padding.Z); roomplace.Y += random.range(0, areasize.Y - roomsize.Y - start_padding.Y); roomplace.X += random.range(0, areasize.X - roomsize.X - start_padding.X); /* Check that we're not putting the room to an unknown place, otherwise it might end up floating in the air */ fits = true; for (s16 z = 0; z < roomsize.Z; z++) for (s16 y = 0; y < roomsize.Y; y++) for (s16 x = 0; x < roomsize.X; x++) { v3s16 p = roomplace + v3s16(x, y, z); u32 vi = vm->m_area.index(p); if ((vm->m_flags[vi] & VMANIP_FLAG_DUNGEON_UNTOUCHABLE) || vm->m_data[vi].getContent() == CONTENT_IGNORE) { fits = false; break; } } } // No place found if (fits == false) return; /* Stores the center position of the last room made, so that a new corridor can be started from the last room instead of the new room, if chosen so. */ v3s16 last_room_center = roomplace + v3s16(roomsize.X / 2, 1, roomsize.Z / 2); u32 room_count = random.range(dp.rooms_min, random.range(dp.rooms_max, dp.rooms_max * far_multi)); for (u32 i = 0; i < room_count; i++) { // Make a room to the determined place makeRoom(roomsize, roomplace); v3s16 room_center = roomplace + v3s16(roomsize.X / 2, 1, roomsize.Z / 2); if (gennotify) gennotify->addEvent(dp.notifytype, room_center); #ifdef DGEN_USE_TORCHES // Place torch at room center (for testing) vm->m_data[vm->m_area.index(room_center)] = MapNode(c_torch); #endif // Quit if last room if (i == room_count - 1) break; // Determine walker start position bool start_in_last_room = (random.range(0, 2) != 0); v3s16 walker_start_place; if (start_in_last_room) { walker_start_place = last_room_center; } else { walker_start_place = room_center; // Store center of current room as the last one last_room_center = room_center; } // Create walker and find a place for a door v3s16 doorplace; v3s16 doordir; m_pos = walker_start_place; if (!findPlaceForDoor(doorplace, doordir)) return; if (random.range(0, 1) == 0) // Make the door makeDoor(doorplace, doordir); else // Don't actually make a door doorplace -= doordir; // Make a random corridor starting from the door v3s16 corridor_end; v3s16 corridor_end_dir; makeCorridor(doorplace, doordir, corridor_end, corridor_end_dir); // Find a place for a random sized room roomsize.Z = random.range(4, 8 * far_multi); roomsize.Y = random.range(4, 6 * far_multi); roomsize.X = random.range(4, 8 * far_multi); roomsize += dp.roomsize; m_pos = corridor_end; m_dir = corridor_end_dir; if (!findPlaceForRoomDoor(roomsize, doorplace, doordir, roomplace)) return; if (random.range(0, 1) == 0) // Make the door makeDoor(doorplace, doordir); else // Don't actually make a door roomplace -= doordir; } }