private bool TryCombiningRooms(RoomComposite composite, RCObj RCOrig, RCObj RCNew, int[] indsOrig) { foreach (int indA in indsOrig) { Direction dirA = RCOrig.connections[indA].side; Direction dirN = (Direction)(((int)dirA + 2) % 4); int[] indsN = RCNew.GetRandomConnections(dirN); foreach (int indN in indsN) { if (indA == -1 || indN == -1) // should be unneccesary { continue; } bool didAdd = composite.Add(RCOrig, indA, RCNew, indN); if (didAdd) { return(true); } } } return(false); }
private bool CanAddRoom(RCObj rco) { int width = rco.roomData.width; int height = rco.roomData.height; for (int r = 0; r < height; r++) { for (int c = 0; c < width; c += 7) // check every 7 columns maybe itll be faster { if (grid[MID + basePos.x + rco.pos.x + c, MID + basePos.y + rco.pos.y + r]) { return(false); } } } for (int r = 0; r < height; r++) // this might be wrong { if (grid[MID + basePos.x + rco.pos.x + width - 1, MID + basePos.y + rco.pos.y + r]) { return(false); } } return(true); }
public List <Vector3Int> path = new List <Vector3Int>(); // exclusive public HallwayObj(RCObj RCA, RCObj RCB, RCConnection conA, RCConnection conB, bool isStraight) { roomA = RCA; roomB = RCB; connectionA = conA; connectionB = conB; isPathStraight = isStraight; }
public int[] GetFurthestConnection(RCObj other, int n) { List <System.Tuple <int, int> > distIndexList = new List <System.Tuple <int, int> >(); for (int i = 0; i < connections.Count; i++) { if (!connections[i].isAvailable) { continue; } int maxManhattan = 0; int furthestInd = -1; for (int j = 0; j < other.connections.Count; j++) { if (!other.connections[j].isAvailable) { continue; } Vector3Int d = (pos + connections[i].pos) - (other.pos + other.connections[j].pos); int manhattan = Mathf.Abs(d.x) + Mathf.Abs(d.y); if (manhattan > maxManhattan) { maxManhattan = manhattan; furthestInd = i; } } distIndexList.Add(new System.Tuple <int, int>(maxManhattan, furthestInd)); } distIndexList.Sort(); if (Constants.doRandom && distIndexList.Count > 1 && distIndexList[0].Item2 == distIndexList[1].Item2 && Random.Range(0, 2) == 1) { System.Tuple <int, int> temp = distIndexList[0]; distIndexList[0] = distIndexList[1]; distIndexList[1] = temp; } distIndexList.Reverse(); int[] sortedIndexes = new int[n]; int count = 0; while (count < distIndexList.Count && count < n) { sortedIndexes[count] = distIndexList[count].Item2; count++; } while (count < n) { sortedIndexes[count] = -1; count++; } return(sortedIndexes); }
// assumes origRoom is already in rooms public bool Add(RCObj origRoom, int origConnectionIndex, RCObj newRoom, int newConnectionIndex) { if (!rooms.Contains(origRoom) || !origRoom.connections[origConnectionIndex].isAvailable || !newRoom.connections[newConnectionIndex].isAvailable) { Debug.LogWarning("Something went wrong when adding a room to composite!"); } Direction dirOut = origRoom.connections[origConnectionIndex].side; Vector3Int nearestPos = origRoom.pos + origRoom.connections[origConnectionIndex].pos - newRoom.connections[newConnectionIndex].pos + MIN_HALLWAY * DirectionUtil.Convert(dirOut); HallwayObj hallway = new HallwayObj(origRoom, newRoom, origRoom.connections[origConnectionIndex], newRoom.connections[newConnectionIndex], true); for (int i = 0; i < MAX_HALLWAY; i++) { if (Constants.doRandom) { if (Random.Range(0, 1f) < 0.3f) { continue; } } newRoom.pos = nearestPos + (i * DirectionUtil.Convert(dirOut)); if (CanAddRoom(newRoom)) { if (TryGenerateSimpleHallway(hallway)) { hallway.roomA.connectedObjects.Add(hallway.roomB); hallway.roomB.connectedObjects.Add(hallway.roomA); rooms.Add(newRoom); origRoom.connections[origConnectionIndex].isAvailable = false; newRoom.connections[newConnectionIndex].isAvailable = false; AddRoomToGrid(newRoom); AddHalwayToGrid(hallway); UpdateDoorAvailability(); return(true); } } } return(false); }
private void AddRoomToGrid(RCObj rco) { int width = rco.roomData.width; int height = rco.roomData.height; char[] roomChar = rco.roomData.roomString.ToCharArray(); for (int r = 0; r < height; r++) { for (int c = 0; c < width; c++) { char t = roomChar[r * (width + 1) + c]; if (t == RoomData.WALLCHAR || t == RoomData.FLOORCHAR) { // does this mirror rooms? grid[MID + basePos.x + rco.pos.x + c, MID + basePos.y + rco.pos.y + (height - r - 1)] = true; } } } }
public bool TryGenerateComplexHallway(RCObj RCA, RCObj RCB) { int[] lastRoomInds = RCB.GetClosestConnections(RCA, 2); int[] firstRoomInds = RCA.GetClosestConnections(RCB, 2); if (lastRoomInds[0] == -1 || firstRoomInds[0] == -1) // no available connections, restart composite { return(false); } for (int lastInd = 0; lastInd < 2; lastInd++) { if (lastRoomInds[lastInd] == -1) { continue; } for (int firstInd = 0; firstInd < 2; firstInd++) { if (firstRoomInds[firstInd] == -1) { continue; } HallwayObj complexHallway = new HallwayObj(RCA, RCB, RCA.connections[firstRoomInds[firstInd]], RCB.connections[lastRoomInds[lastInd]], false); if (TryGenerateComplexHallwayHelper(complexHallway)) { AddHalwayToGrid(complexHallway); complexHallway.connectionA.isAvailable = false; complexHallway.connectionB.isAvailable = false; UpdateDoorAvailability(); RCA.connectedObjects.Add(RCB); RCB.connectedObjects.Add(RCA); return(true); } } } return(false); }
private bool AddNode(FlowNode node, RCObj rco) { addedNodes[node] = rco; remainingNodes.Remove(node); foreach (FlowNode adj in node.neighbors) { if (addedNodes.ContainsKey(adj)) { if (!rco.connectedObjects.Contains(addedNodes[adj])) { bool didGen = dungeonComposite.TryGenerateComplexHallway(rco, addedNodes[adj]); if (!didGen) { return(false); } } } } return(true); }
private bool AddRoomRandom(RoomComposite composite, RCObj RCOrig, FlowNode nodeNew) { RoomData roomNew; RCObj RCNew; // try adding first 2 rooms together for (int i = 0; i < MAX_TRIES; i++) { roomNew = GetRoom(nodeNew); RCNew = new RCObj(roomNew); bool didAdd = TryCombiningRooms(composite, RCOrig, RCNew, RCOrig.GetAvailableConnections()); if (didAdd) { if (!AddNode(nodeNew, RCNew)) { return(false); // couldn't generate complex hallway } return(true); } } return(false); }
private bool TryGenerating(List <List <FlowNode> > cycles) { addedCycles = new List <List <FlowNode> >(); addedNodes = new Dictionary <FlowNode, RCObj>(); remainingNodes = new List <FlowNode>(); foreach (FlowNode node in currentFlow.verticies) { remainingNodes.Add(node.Copy()); } dungeonComposite = null; bool didGen = true; if (cycles.Count > 0) { // TODO: progress cycle a random amount if (Constants.doRandom) { int n = Random.Range(0, cycles.Count); for (int i = 0; i < n; i++) { cycles[0].Add(cycles[0][0]); } cycles[0].RemoveRange(0, n); } FlowNode nodeInit = cycles[0][0]; RoomData roomInit = GetRoom(nodeInit); RCObj RCInit = new RCObj(roomInit); dungeonComposite = new RoomComposite(RCInit); AddNode(nodeInit, RCInit); dungeonComposite = AddCycleToComposite(dungeonComposite, RCInit, cycles[0]); if (dungeonComposite == null) { return(false); } addedCycles.Add(cycles[0]); didGen = CheckOverlappingCycles(cycles); if (!didGen) { return(false); } } else { FlowNode maxNode = remainingNodes[0]; foreach (FlowNode node in remainingNodes) { if (node.neighbors.Count > maxNode.neighbors.Count) { maxNode = node; } } RoomData roomInit = GetRoom(maxNode); RCObj RCInit = new RCObj(roomInit); dungeonComposite = new RoomComposite(RCInit); didGen = AddNode(maxNode, RCInit); if (!didGen) { return(false); } } //Debug.Log(remainingNodes.Count + " remaining!"); int limitCount = 0; while (remainingNodes.Count > 0 && limitCount < 1000000) { limitCount++; List <FlowNode> frontierNodes = new List <FlowNode>(); foreach (FlowNode node in addedNodes.Keys) { foreach (FlowNode adj in node.neighbors) { if (remainingNodes.Contains(adj)) { frontierNodes.Add(adj); } } } FlowNode maxNode = remainingNodes[0]; foreach (FlowNode node in frontierNodes) { if (node.neighbors.Count > maxNode.neighbors.Count) { maxNode = node; } } FlowNode origNode = null; foreach (FlowNode node in addedNodes.Keys) { if (node.neighbors.Contains(maxNode)) { origNode = node; } } didGen = AddRoomRandom(dungeonComposite, addedNodes[origNode], maxNode); if (!didGen) { return(false); } if (addedCycles.Count < cycles.Count) { didGen = CheckOverlappingCycles(cycles); if (!didGen) { return(false); } } } if (dungeonComposite == null || limitCount > 1000000) { return(false); } return(true); }
private RoomComposite AddCycleToComposite(RoomComposite composite, RCObj RCA, List <FlowNode> cycle) { FlowNode nodeN = cycle[1]; RoomData roomN = null; RCObj RCN = null; bool didAdd = false; if (!addedNodes.ContainsKey(cycle[1])) { // try adding first 2 rooms together for (int i = 0; i < MAX_TRIES; i++) { roomN = GetRoom(nodeN); RCN = new RCObj(roomN); didAdd = TryCombiningRooms(composite, RCA, RCN, RCA.GetAvailableConnections()); if (didAdd) { if (!AddNode(nodeN, RCN)) { return(null); // couldn't generate complex hallway } break; } } // failed to place first two rooms if (!didAdd) { return(null); } } else { RCN = addedNodes[nodeN]; } // place rest of rooms for (int n = 2; n < cycle.Count; n++) { didAdd = false; FlowNode nodeM = cycle[n]; if (!addedNodes.ContainsKey(nodeM)) { int[] indsN; // get furthest dir if (n < (cycle.Count + 1) / 2) { indsN = RCN.GetFurthestConnection(RCA, 3); } else // get closest dir { indsN = RCN.GetClosestConnections(RCA, 3); } if (indsN[0] == -1) { continue; } for (int i = 0; i < MAX_TRIES; i++) { RoomData roomM = GetRoom(nodeM); RCObj RCM = new RCObj(roomM); didAdd = TryCombiningRooms(composite, RCN, RCM, indsN); if (didAdd) { if (!AddNode(nodeM, RCM)) { return(null); // couldn't generate complex hallway } RCN = RCM; break; } } if (!didAdd) { return(null); // restart composite } } else { // already added RCN = addedNodes[nodeM]; } } //if (!composite.TryGenerateComplexHallway(RCN, RCA)) // return null; // couldnt do the last hallway :( // succeeded //Debug.Log("Rooms added successfully!"); return(composite); }
private bool[,] grid = new bool[MAX_SIZE, MAX_SIZE]; // [x, y] = true if wall public RoomComposite(RCObj rco) { rooms.Add(rco); AddRoomToGrid(rco); }