private static bool ColumnScan(Cell root, ref List <Cell> cellGrouping, Direction startingDirection) { var currentDirection = startingDirection; var currentCell = root; var result = new List <Cell>(); //A circle has 4 steps of scanning for (int i = 0; i < 4; i++) { if (CellCollection.HasCellAt(currentCell.Step(currentDirection))) { var nextCell = CellCollection.cells[currentCell.Step(currentDirection)]; if (!nextCell.HasSameRoom(root)) { break; } currentDirection = currentDirection.Right(); result.Add(currentCell); currentCell = nextCell; } else { break; } } if (result.Count == 4) { cellGrouping = result; return(true); } return(false); }
public static Direction DirectionToNeighbor(this Cell cell, Cell targetCell) { foreach (var direction in Directionf.Directions()) { if (CellCollection.HasCellAt(cell.Step(direction)) && CellCollection.cells[cell.Step(direction)] == targetCell) { return(direction); } } return(Direction.Up); }
private static List <Cell> ProjectRoom_PartialBloom(Cell root, ref List <Cell> cellsLeftToClaim, int claimAmount, float claimChance) { var result = new List <Cell>() { root }; var claimedAmount = result.Count; var currentRoots = new List <Cell> { root }; while (claimedAmount < claimAmount) { var nextRoots = new List <Cell>(); foreach (var currentRoot in currentRoots.ToList()) { foreach (var direction in Directionf.Directions().Shuffle()) { var target = currentRoot.Step(direction); if (CellCollection.HasCellAt(target) && cellsLeftToClaim.Any(x => x.position == target)) { var chanceRoll = Random.Range(0.0f, 1.0f); if (chanceRoll <= claimChance) { nextRoots.Add(CellCollection.cells[target]); cellsLeftToClaim.Remove(CellCollection.cells[target]); claimedAmount++; result.Add(CellCollection.cells[target]); } else { claimedAmount--; } } } if (!nextRoots.Any()) //Ran out of cells to claim, just take what we got { return(result); } } currentRoots = nextRoots; } return(result); }
public static List <Cell> NeighborCellsInRegion(this Cell cell) { var result = new List <Cell>(); if (cell.regionId == "") { return(result); } foreach (var direction in Directionf.Directions()) { if (CellCollection.HasCellAt(cell.Step(direction)) && CellCollection.cells[cell.Step(direction)].regionId == cell.regionId) { result.Add(CellCollection.cells[cell.Step(direction)]); } } return(result); }
private static void Wall_ParseMain(Room room, ref Scaffold scaffold) { foreach (var cell in room.GetCells()) { foreach (var direction in Directionf.Directions()) { if (CellCollection.HasCellAt(cell.Step(direction))) { var neighbor = CellCollection.cells[cell.Step(direction)]; if (neighbor.roomId != cell.roomId) { RenderWallNode(cell, direction, ref scaffold); } } else { RenderWallNode(cell, direction, ref scaffold); } } } }
public static List <Cell> NeighborCellsOutOfRoom(this Cell cell, bool includeElevation = false) { var result = new List <Cell>(); foreach (var direction in Directionf.Directions()) { if (CellCollection.HasCellAt(cell.Step(direction)) && CellCollection.cells[cell.Step(direction)].roomId != cell.roomId) { if (!includeElevation && CellCollection.cells[cell.Step(direction)].type == CellType.Elevation) { continue; } else { result.Add(CellCollection.cells[cell.Step(direction)]); } } } return(result); }
public static List <Cell> Project(Cell root, ref List <Cell> cellsLeftToClaim, int claimAmount) { var result = new List <Cell>() { root }; var claimedAmount = result.Count; var currentRoots = new List <Cell> { root }; while (claimedAmount < claimAmount) { var nextRoots = new List <Cell>(); foreach (var currentRoot in currentRoots.ToList()) { foreach (var direction in Directionf.Directions().Shuffle()) { var target = currentRoot.Step(direction); if (CellCollection.HasCellAt(target) && cellsLeftToClaim.Any(x => x.position == target)) { nextRoots.Add(CellCollection.cells[target]); cellsLeftToClaim.Remove(CellCollection.cells[target]); claimedAmount++; result.Add(CellCollection.cells[target]); } } if (!nextRoots.Any()) //Ran out of cells to claim, just take what we got { return(result); } } currentRoots = nextRoots; } return(result); }
private static void Elevation_Parse(Room room, ref Scaffold scaffold) { foreach (var cell in room.GetCells().Where(x => x.type == CellType.Elevation)) { //Upper Scan if (CellCollection.HasCellAt(cell.Step(Direction.Up))) { var upper = CellCollection.cells[cell.Step(Direction.Up)]; if (!scaffold.elevation.Any(x => x.lower == cell)) { var node = new Node_Elevation(); node.lower = cell; node.upper = upper; node.position = upper.position; node.rootCells.Add(upper); node.rootCells.Add(cell); cell.elevationOverride_Lower = true; upper.elevationOverride_Upper = true; scaffold.elevation.Add(node); } } } }
public static void Proliferate(ref Region region) { var cellsWithOpenings = region.GetCells().Where(x => x.NeighborOpenings().Any() && x.type == CellType.Cell).ToList(); var cellsToAdd = new List <Cell>(); foreach (var cell in cellsWithOpenings) { //Recheck for openings var openings = cell.NeighborOpenings(); if (!openings.Any()) { continue; } foreach (var opening in openings) { var currentCell = cell; for (int i = 0; i < region.proliferationAmount; i++) { if (CellCollection.HasCellAt(currentCell.Step(opening))) { break; } else { var nextCell = new Cell(CellType.Cell, currentCell.Step(opening)); nextCell.parent = currentCell; nextCell.regionId = region.id; cellsToAdd.Add(nextCell); currentCell = cell; } } } } CellCollection.Add(cellsToAdd); }
public static List <Cell> NeighborCellsInRoom(this Cell cell, bool includeDiagonal = false) { var result = new List <Cell>(); foreach (var direction in Directionf.Directions()) { if (CellCollection.HasCellAt(cell.Step(direction)) && CellCollection.cells[cell.Step(direction)].roomId == cell.roomId) { result.Add(CellCollection.cells[cell.Step(direction)]); } if (includeDiagonal) { if (CellCollection.HasCellAt(cell.Step(direction).Step(direction.Right())) && CellCollection.cells[cell.Step(direction).Step(direction.Right())].roomId == cell.roomId) { result.Add(CellCollection.cells[cell.Step(direction).Step(direction.Right())]); } } } return(result); }
public static void Expand(ref Region region) { var cellsToAdd = new List <Cell>(); var cells = region.GetCells(); var sequenceLength = cells.Last().sequence; var sequenceMiddle = cells.Sum(s => s.sequence) / cells.Where(x => x.sequence > 0).Count(); var pathwayCells = cells.Where(x => x.type == CellType.Pathway).ToArray(); foreach (var pathwayCell in pathwayCells) //Ignore elevation cells, those cannot expand { cellsToAdd = new List <Cell>(); var expansionAmount = 0; foreach (var direction in Directionf.Directions()) { if (region.cellExpansionConstant) { expansionAmount = region.cellExpansionAmount; var currentCell = pathwayCell; for (int i = 0; i < expansionAmount; i++) { if (CellCollection.HasCellAt(currentCell.position.Step(direction))) { break; } else { var cell = new Cell(CellType.Cell, currentCell.position.Step(direction)); cell.parent = currentCell; cell.regionId = region.id; cellsToAdd.Add(cell); currentCell = cell; } } } else { if (pathwayCell.sequence <= sequenceMiddle) { expansionAmount = Mathf.FloorToInt( Mathf.Lerp(region.cellExpansionStart, region.cellExpansionMiddle, pathwayCell.sequence / (sequenceLength - sequenceMiddle))); } else { expansionAmount = Mathf.FloorToInt( Mathf.Lerp(region.cellExpansionMiddle, region.cellExpansionEnd, (pathwayCell.sequence - sequenceMiddle) / (sequenceLength - sequenceMiddle))); } var currentCell = pathwayCell; for (int i = 0; i < expansionAmount; i++) { if (CellCollection.HasCellAt(currentCell.position.Step(direction))) { break; } else { var cell = new Cell(CellType.Cell, currentCell.position.Step(direction)); cell.parent = currentCell; cell.regionId = region.id; cellsToAdd.Add(cell); currentCell = cell; } } } } try { CellCollection.Add(cellsToAdd); } catch (Exception e) { continue; } } }
public static bool BuildPath(ref Region region) { //Get direction of pathway var directions = FindDirectionVector(region.startPosition, region.endPosition); var xDistance = GetDistance(region.startPosition.x, region.endPosition.x, Cellf.CELL_STEP_OFFSET); var yDistance = GetDistance(region.startPosition.y, region.endPosition.y, Cellf.CELL_STEP_OFFSET / 2); var zDistance = GetDistance(region.startPosition.z, region.endPosition.z, Cellf.CELL_STEP_OFFSET); var retries = RETRIES; var success = false; while (retries > 0) { retries--; #region Reset Values var finishEndCellMetadata = false; var cellsToAdd = new List <Cell>(); var xTemp = xDistance; var yTemp = yDistance; var zTemp = zDistance; Cell currentCell = null; Cell lastCell = null; Cell secondLastCell = null; //Used to prevent the end of a path from being an elevation cell #endregion #region Init //Start cell if (CellCollection.HasCellAt(region.startPosition)) //If starting from an existing path { currentCell = CellCollection.cells[region.startPosition]; } else { var cell = new Cell(CellType.Pathway, region.startPosition); cell.sequence = sequence++; cell.regionId = region.id; cell.parent = currentCell; cellsToAdd.Add(cell); currentCell = cell; } //Force horizontal start if (xTemp > 0 || zTemp > 0) { var directionsToTry = new List <Direction>(); if (xTemp > 0) { directionsToTry.Add(directions.xDirection); } if (zTemp > 0) { directionsToTry.Add(directions.zDirection); } var directionToGo = directionsToTry[Random.Range(0, directionsToTry.Count)]; if (directionToGo == directions.xDirection) { xTemp--; } else { zTemp--; } if (CellCollection.HasCellAt(currentCell.Step(directionToGo))) { success = false; retries--; continue; } var cell = new Cell(CellType.Pathway, currentCell.Step(directionToGo)); cell.sequence = sequence++; cell.regionId = region.id; cell.parent = currentCell; currentCell.children.Add(cell); cellsToAdd.Add(cell); currentCell = cell; } //End cell if (CellCollection.HasCellAt(region.endPosition)) //If connecting to an existing path { lastCell = CellCollection.cells[region.endPosition]; } else { var cell = new Cell(CellType.Pathway, region.endPosition); //Sequence and parents will have to be added later finishEndCellMetadata = true; cell.regionId = region.id; cellsToAdd.Add(cell); lastCell = cell; } //Remove a temp increment for the end cell var directionsForEnd = new List <Direction>(); if (xTemp > 0) { directionsForEnd.Add(directions.xDirection); } if (zTemp > 0) { directionsForEnd.Add(directions.zDirection); } var directionToRemoveFrom = directionsForEnd[Random.Range(0, directionsForEnd.Count)]; if (directionToRemoveFrom == directions.xDirection) { xTemp--; } else { zTemp--; } //Force horizontal end if (xTemp > 0 || zTemp > 0) { var directionsToTry = new List <Direction>(); if (xTemp > 0) { directionsToTry.Add(directions.xDirection.Opposite()); } if (zTemp > 0) { directionsToTry.Add(directions.zDirection.Opposite()); } var directionToGo = directionsToTry[Random.Range(0, directionsToTry.Count)]; if (directionToGo == directions.xDirection.Opposite()) { xTemp--; } else { zTemp--; } if (CellCollection.HasCellAt(lastCell.Step(directionToGo))) { success = false; retries--; continue; } var cell = new Cell(CellType.Pathway, lastCell.Step(directionToGo)); //Sequence and parent will have to be added later cell.children.Add(lastCell); cell.regionId = region.id; cellsToAdd.Add(cell); lastCell.parent = cell; //End cell parent finalized secondLastCell = cell; //Save this for metadata finalization at the end } #endregion #region Generate bool elevationMode = false; while (xTemp + zTemp + yTemp > 0) { var directionsLeft = new List <Direction>(); //Force elevation to all generate at once, don't let it scatter because it is weird and non-sense if (elevationMode) { directionsLeft = GetDirectionsLeft(0, yTemp, 0, directions); if (!directionsLeft.Any()) { elevationMode = false; directionsLeft = GetDirectionsLeft(xTemp, yTemp, zTemp, directions); } } else { directionsLeft = GetDirectionsLeft(xTemp, yTemp, zTemp, directions); } var currentDirection = directionsLeft[Random.Range(0, directionsLeft.Count)]; if (currentDirection == Direction.Up || currentDirection == Direction.Down) { elevationMode = true; } var type = (currentDirection == Direction.Up || currentDirection == Direction.Down) ? CellType.Elevation : CellType.Pathway; if (type == CellType.Elevation) //Retroactivly change the previous generated cell to be an elevation cell as well { cellsToAdd.First(x => x == currentCell).type = type; } if (CellCollection.HasCellAt(currentCell.position.Step(currentDirection))) { success = false; retries--; continue; } var cell = new Cell(type, currentCell.position.Step(currentDirection)); cell.parent = currentCell; currentCell.children.Add(cell); cell.regionId = region.id; cell.sequence = sequence++; cellsToAdd.Add(cell); currentCell = cell; switch (currentDirection) { case Direction.North: case Direction.South: zTemp--; break; case Direction.East: case Direction.West: xTemp--; break; case Direction.Up: case Direction.Down: yTemp--; break; default: success = false; break; } if (xTemp + yTemp + zTemp == 0) { success = true; } } #endregion //The last cell generated in the above loop should be the one right before the forced horizontal cell, if that exists if (secondLastCell != null) { cellsToAdd.First(x => x == secondLastCell).sequence = sequence++; cellsToAdd.First(x => x == secondLastCell).parent = currentCell; currentCell.children.Add(secondLastCell); } cellsToAdd.First(x => x == lastCell).sequence = sequence++; if (success) { CellCollection.Add(cellsToAdd.OrderBy(o => o.sequence).ToList()); break; } } return(success); }
public bool RenderEntity(LevelRoom room, SuiteEntity entity) { if (renderContainer == null) { ResetRenderContainer(room); } var projectionScaffolds = new List <Scaffold_Node>(); var success = false; //Shortcut to prevent expensive calculations if something obvious can prevent more computation if (!ValidateRoom(room)) { return(false); } foreach (var cell in CellCollection.GetByRoom(room.roomId).ToList().Shuffle()) { foreach (var direction in Directionf.Directions()) { var projection = entity.BuildProjection(cell.position, direction); //Projection cannot clip room cell space if (projection.spaces.Any(x => !CellCollection.HasCellAt(x) || CellCollection.cells[x].roomId != room.roomId)) { continue; } //Projection cannot intersect existing projections if (nextContainerInstance.cellPositionsTaken.Any(a => projection.spaces.Contains(a))) { continue; } //Project cannot intersect with existing scaffold claims if (!VerifyProjectionScaffoldDoesntIntersect(projection, entity, room, cell.position, direction, out projectionScaffolds)) { continue; } //Projection cannot block navigation through room if (!VerifyProjectionDoesNotBlockRoomPathways(projection)) { continue; } //If we made it this far, this projection is valid, we will claim it ClaimProjection(projection, projectionScaffolds, cell, direction, entity); success = true; break; } if (success) { renderContainer = nextContainerInstance; renderContainer.claimedScaffolds.ForEach(x => Level.roomScaffolds[room.roomId].SetNodeClaimed(x.id)); RollbackRenderContainer(); break; //A claim was found } } return(success); }
//This projection type will attempt to claim the most successful projection that claims the most cells possible private static List <Cell> ProjectionAttempt(Cell root, ref List <Cell> cellsLeftToClaim, int claimAmount, float claimChance, Direction primaryDirection, Direction secondaryDirection) { bool terminate = false; #region Step 1 var result = new List <Cell>() { root }; var claimedAmount = result.Count; cellsLeftToClaim.Remove(root); if (claimedAmount >= claimAmount) { return(result); } #endregion #region Step 2 var steps = new List <Vector3>() { root.Step(primaryDirection), //2_1 root.Step(secondaryDirection) //2_2 }; foreach (var step in steps) { if (CellCollection.HasCellAt(step) && cellsLeftToClaim.Contains(CellCollection.cells[step])) { var cell = CellCollection.cells[step]; result.Add(cell); cellsLeftToClaim.Remove(cell); claimedAmount = result.Count; } else { terminate = true; } } if (terminate || result.Count >= claimAmount) { return(result); } #endregion #region Step 3 steps = new List <Vector3>() { root.Step(primaryDirection).Step(secondaryDirection), //3_1 root.Step(primaryDirection.Opposite()).Step(secondaryDirection), //3_2 root.Step(primaryDirection).Step(secondaryDirection.Opposite()), //3_3 }; foreach (var step in steps) { if (CellCollection.HasCellAt(step) && cellsLeftToClaim.Contains(CellCollection.cells[step])) { var cell = CellCollection.cells[step]; result.Add(cell); cellsLeftToClaim.Remove(cell); claimedAmount = result.Count; } else { terminate = true; } } if (terminate || result.Count >= claimAmount) { return(result); } #endregion #region Step 4 steps = new List <Vector3>() { root.Step(primaryDirection.Opposite()), //4_1 root.Step(secondaryDirection.Opposite()) //4_2 }; foreach (var step in steps) { if (CellCollection.HasCellAt(step) && cellsLeftToClaim.Contains(CellCollection.cells[step])) { var cell = CellCollection.cells[step]; result.Add(cell); cellsLeftToClaim.Remove(cell); claimedAmount = result.Count; } else { terminate = true; } } if (terminate || result.Count >= claimAmount) { return(result); } #endregion #region Step 5 steps = new List <Vector3>() { root.Step(primaryDirection.Opposite()).Step(secondaryDirection.Opposite())//5_1 }; foreach (var step in steps) { if (CellCollection.HasCellAt(step) && cellsLeftToClaim.Contains(CellCollection.cells[step])) { var cell = CellCollection.cells[step]; result.Add(cell); cellsLeftToClaim.Remove(cell); claimedAmount = result.Count; } else { terminate = true; } } if (terminate || result.Count >= claimAmount) { return(result); } #endregion #region Step 6 steps = new List <Vector3>() { root.Step(primaryDirection, 2), //6_1 root.Step(secondaryDirection, 2), //6_2 root.Step(primaryDirection, 2).Step(secondaryDirection), //6_3 root.Step(primaryDirection).Step(secondaryDirection, 2), //6_4 root.Step(primaryDirection.Opposite()).Step(secondaryDirection, 2), //6_5 root.Step(primaryDirection, 2).Step(secondaryDirection.Opposite()), //6_6 }; foreach (var step in steps) { if (CellCollection.HasCellAt(step) && cellsLeftToClaim.Contains(CellCollection.cells[step])) { var cell = CellCollection.cells[step]; result.Add(cell); cellsLeftToClaim.Remove(cell); claimedAmount = result.Count; } else { terminate = true; } } if (terminate || result.Count >= claimAmount) { return(result); } #endregion #region Step 7 steps = new List <Vector3>() { root.Step(primaryDirection, 2).Step(secondaryDirection, 2) //7_1 }; foreach (var step in steps) { if (CellCollection.HasCellAt(step) && cellsLeftToClaim.Contains(CellCollection.cells[step])) { var cell = CellCollection.cells[step]; result.Add(cell); cellsLeftToClaim.Remove(cell); claimedAmount = result.Count; } else { terminate = true; } } if (terminate || result.Count >= claimAmount) { return(result); } #endregion return(result); }