/// <summary> /// Returns a list of wall edges with definite 4-directional normals /// </summary> /// <param name="rect"></param> /// <param name="checkBlock">Determines if this is ground that can be burrowed into.</param> /// <param name="checkGround">Determines if this is ground that can reach a wall.</param> /// <returns></returns> public static List <LocRay4> DetectWalls(Rect rect, Grid.LocTest checkBlock, Grid.LocTest checkGround) { if (checkBlock == null) { throw new ArgumentNullException(nameof(checkBlock)); } List <LocRay4> walls = new List <LocRay4>(); for (int xx = rect.X; xx < rect.Width; xx++) { for (int yy = rect.Y; yy < rect.Height; yy++) { Loc testLoc = new Loc(xx, yy); if (checkBlock(testLoc)) { LocRay4 ray = GetWallDir(testLoc, checkBlock, checkGround); if (ray.Dir != Dir4.None) { walls.Add(ray); } } } } return(walls); }
public static void UnsafeAddHall(LocRay4 locRay, GridPlan floorPlan, IPermissiveRoomGen hallGen, ComponentCollection components) { floorPlan.SetHall(locRay, hallGen, components.Clone()); GenContextDebug.DebugProgress("Hall"); if (floorPlan.GetRoomPlan(locRay.Loc) == null || floorPlan.GetRoomPlan(locRay.Traverse(1)) == null) { floorPlan.Clear(); throw new InvalidOperationException("Can't create a hall without rooms to connect!"); } }
/// <summary> /// Sets the RoomGen found in the specified hall. /// </summary> /// <param name="locRay">The location of the room + the direction of the connecting hall relative to the room.</param> /// <param name="hallGen"></param> /// <param name="components">components to include in the hall</param> public void SetHall(LocRay4 locRay, IPermissiveRoomGen hallGen, ComponentCollection components) { if (locRay.Dir == Dir4.None) { throw new ArgumentException("Invalid direction."); } else if (!locRay.Dir.Validate()) { throw new ArgumentOutOfRangeException("Invalid enum value."); } GridHallPlan plan = null; if (hallGen != null) { plan = new GridHallPlan((IPermissiveRoomGen)hallGen.Copy(), components); } switch (locRay.Dir) { case Dir4.Down: if (locRay.Loc.Y < this.GridHeight - 1) { this.VHalls[locRay.Loc.X][locRay.Loc.Y].SetHall(plan); } break; case Dir4.Left: if (locRay.Loc.X > 0) { this.HHalls[locRay.Loc.X - 1][locRay.Loc.Y].SetHall(plan); } break; case Dir4.Up: if (locRay.Loc.Y > 0) { this.VHalls[locRay.Loc.X][locRay.Loc.Y - 1].SetHall(plan); } break; case Dir4.Right: if (locRay.Loc.X < this.GridWidth - 1) { this.HHalls[locRay.Loc.X][locRay.Loc.Y].SetHall(plan); } break; case Dir4.None: throw new ArgumentException($"No hall for dir {nameof(Dir4.None)}"); default: throw new ArgumentOutOfRangeException(nameof(locRay.Dir), "Invalid enum value."); } }
public int GetRoomNum(LocRay4 locRay) { GridHallPlan hall = this.GetHall(locRay); if (hall != null) { Loc moveLoc = locRay.Traverse(1); return(this.Rooms[moveLoc.X][moveLoc.Y]); } return(-1); }
public virtual LocRay4 ChooseRoomExpansion(IRandom rand, GridPlan floorPlan, bool branch) { List <LocRay4> availableRays = GetPossibleExpansions(floorPlan, branch); if (availableRays.Count == 0) { return(new LocRay4(Dir4.None)); } LocRay4 chosenRay = availableRays[rand.Next(availableRays.Count)]; return(chosenRay); }
public static void SafeAddHall(LocRay4 locRay, GridPlan floorPlan, IPermissiveRoomGen hallGen, IRoomGen roomGen, bool preferHall = false) { floorPlan.SetHall(locRay, hallGen); if (floorPlan.GetRoomPlan(locRay.Loc) == null) { floorPlan.AddRoom(locRay.Loc, roomGen, false, preferHall); } Loc dest = locRay.Traverse(1); if (floorPlan.GetRoomPlan(dest) == null) { floorPlan.AddRoom(dest, roomGen, false, preferHall); } }
protected bool ExpandPath(IRandom rand, GridPlan floorPlan, bool branch) { LocRay4 chosenRay = this.ChooseRoomExpansion(rand, floorPlan, branch); if (chosenRay.Dir == Dir4.None) { return(false); } floorPlan.SetHall(chosenRay, this.GenericHalls.Pick(rand)); floorPlan.AddRoom(chosenRay.Traverse(1), this.GenericRooms.Pick(rand)); GenContextDebug.DebugProgress(branch ? "Branched Path" : "Extended Path"); return(true); }
/// <summary> /// Returns a list of wall edges with definite 4-directional normals, connected to a start position /// </summary> /// <param name="start"></param> /// <param name="rect"></param> /// <param name="checkBlock">Determines if this is ground that can be burrowed into.</param> /// <param name="checkGround">Determines if this is ground that can reach a wall.</param> /// <returns></returns> public static List <LocRay4> DetectWalls(Loc start, Rect rect, Grid.LocTest checkBlock, Grid.LocTest checkGround) { if (checkBlock == null) { throw new ArgumentNullException(nameof(checkBlock)); } if (checkGround == null) { throw new ArgumentNullException(nameof(checkGround)); } bool[][] checkGrid = new bool[rect.Width][]; bool[][] fillGrid = new bool[rect.Width][]; for (int xx = 0; xx < rect.Width; xx++) { checkGrid[xx] = new bool[rect.Height]; fillGrid[xx] = new bool[rect.Height]; } List <LocRay4> walls = new List <LocRay4>(); // scan and find solely-facing walls // cache already-checked walls since flood fill occasionally checks twice Grid.FloodFill( rect, (Loc testLoc) => { if (fillGrid[testLoc.X][testLoc.Y]) { return(true); } if (!checkGrid[testLoc.X][testLoc.Y] && checkBlock(testLoc)) { LocRay4 ray = GetWallDir(testLoc, checkBlock, checkGround); if (ray.Dir != Dir4.None) { walls.Add(ray); } } checkGrid[testLoc.X][testLoc.Y] = true; return(!checkGround(testLoc)); }, (Loc testLoc) => true, (Loc fillLoc) => fillGrid[fillLoc.X][fillLoc.Y] = true, start); return(walls); }
public static void SafeAddHall(LocRay4 locRay, GridPlan floorPlan, IPermissiveRoomGen hallGen, IRoomGen roomGen, ComponentCollection roomComponents, ComponentCollection hallComponents, bool preferHall = false) { floorPlan.SetHall(locRay, hallGen, hallComponents.Clone()); ComponentCollection collection = preferHall ? hallComponents : roomComponents; if (floorPlan.GetRoomPlan(locRay.Loc) == null) { floorPlan.AddRoom(locRay.Loc, roomGen, collection.Clone(), preferHall); } Loc dest = locRay.Traverse(1); if (floorPlan.GetRoomPlan(dest) == null) { floorPlan.AddRoom(dest, roomGen, collection.Clone(), preferHall); } }
/// <summary> /// Returns the RoomGen found in the specified hall. /// </summary> /// <param name="locRay">The location of the room + the direction of the connecting hall relative to the room.</param> /// <returns></returns> public GridHallPlan GetHall(LocRay4 locRay) { switch (locRay.Dir) { case Dir4.Down: if (locRay.Loc.Y < this.GridHeight - 1) { return(this.VHalls[locRay.Loc.X][locRay.Loc.Y].MainHall); } break; case Dir4.Left: if (locRay.Loc.X > 0) { return(this.HHalls[locRay.Loc.X - 1][locRay.Loc.Y].MainHall); } break; case Dir4.Up: if (locRay.Loc.Y > 0) { return(this.VHalls[locRay.Loc.X][locRay.Loc.Y - 1].MainHall); } break; case Dir4.Right: if (locRay.Loc.X < this.GridWidth - 1) { return(this.HHalls[locRay.Loc.X][locRay.Loc.Y].MainHall); } break; case Dir4.None: break; default: throw new ArgumentOutOfRangeException(nameof(locRay.Dir), "Invalid enum value."); } return(null); }
public override void ApplyToPath(IRandom rand, GridPlan floorPlan) { List <LocRay4> endBranches = new List <LocRay4>(); for (int ii = 0; ii < floorPlan.RoomCount; ii++) { GridRoomPlan roomPlan = floorPlan.GetRoomPlan(ii); if (!BaseRoomFilter.PassesAllFilters(roomPlan, this.Filters)) { continue; } if (roomPlan.Bounds.Size == new Loc(1)) { List <int> adjacents = floorPlan.GetAdjacentRooms(ii); if (adjacents.Count == 1) { endBranches.Add(new LocRay4(roomPlan.Bounds.Start)); } } } List <List <LocRay4> > candBranchPoints = new List <List <LocRay4> >(); for (int nn = 0; nn < endBranches.Count; nn++) { LocRay4 chosenBranch = endBranches[nn]; while (chosenBranch.Loc != new Loc(-1)) { List <LocRay4> connectors = new List <LocRay4>(); List <LocRay4> candBonds = new List <LocRay4>(); foreach (Dir4 dir in DirExt.VALID_DIR4) { if (dir != chosenBranch.Dir) { if (floorPlan.GetHall(new LocRay4(chosenBranch.Loc, dir)) != null) { connectors.Add(new LocRay4(chosenBranch.Loc, dir)); } else { Loc loc = chosenBranch.Loc + dir.GetLoc(); if (Collision.InBounds(floorPlan.GridWidth, floorPlan.GridHeight, loc) && floorPlan.GetRoomIndex(loc) > -1) { candBonds.Add(new LocRay4(chosenBranch.Loc, dir)); } } } } if (connectors.Count == 1) { if (candBonds.Count > 0) { candBranchPoints.Add(candBonds); chosenBranch = new LocRay4(new Loc(-1)); } else { chosenBranch = new LocRay4(connectors[0].Traverse(1), connectors[0].Dir.Reverse()); } } else { chosenBranch = new LocRay4(new Loc(-1)); } } } // compute a goal amount of terminals to connect // this computation ignores the fact that some terminals may be impossible var randBin = new RandBinomial(candBranchPoints.Count, this.ConnectPercent); int connectionsLeft = randBin.Pick(rand); while (candBranchPoints.Count > 0 && connectionsLeft > 0) { // choose random point to connect int randIndex = rand.Next(candBranchPoints.Count); List <LocRay4> candBonds = candBranchPoints[randIndex]; LocRay4 chosenDir = candBonds[rand.Next(candBonds.Count)]; // connect floorPlan.SetHall(chosenDir, this.GenericHalls.Pick(rand), this.HallComponents); candBranchPoints.RemoveAt(randIndex); GenContextDebug.DebugProgress("Connected Branch"); connectionsLeft--; // check to see if connection destination was also a candidate, // counting this as a double if so for (int ii = candBranchPoints.Count - 1; ii >= 0; ii--) { if (candBranchPoints[ii][0].Loc == chosenDir.Traverse(1)) { candBranchPoints.RemoveAt(ii); connectionsLeft--; } } } }