protected List <Bounding> SingleFind() { List <Value2D <T> > list = new List <Value2D <T> >(); DrawAction <T> action; if (_tester.StrokeAction != null) { action = _tester.StrokeAction.IfThen(Draw.AddTo(list)); } else if (_tester.UnitAction != null) { action = _tester.UnitAction.IfThen(Draw.AddTo(list)); } else { return(new List <Bounding>(0)); } _arr.DrawRect(_scope, action); List <Bounding> ret = new List <Bounding>(); foreach (var v in list) { ret.Add(new Bounding(v.x, v.x, v.y, v.y)); } return(ret); }
public override HashSet <IAffectable> GetTargets(SpellCastInfo castInfo) { Container2D <GridSpace> level = BigBoss.Levels.Level.Array; var targetSpaces = new HashSet <GridSpace>(); foreach (GridSpace point in castInfo.TargetSpaces) { level.DrawCircle(point.X, point.Y, Radius, Draw.AddTo(targetSpaces)); } castInfo.TargetSpaces = targetSpaces.ToArray(); return(base.GetTargets(castInfo)); }
protected void ConstructBFS(LayoutObject obj, out Queue <Value2D <GenSpace> > queue, out Container2D <bool> visited) { visited = new MultiMap <bool>(); queue = new Queue <Value2D <GenSpace> >(); obj.GetConnectedGrid().DrawPerimeter(Draw.Not(Draw.IsType <GenSpace>(GridType.NULL)), new StrokedAction <GenSpace>() { UnitAction = Draw.SetTo <GenSpace, bool>(visited, true), StrokeAction = Draw.AddTo(queue).And(Draw.SetTo <GenSpace, bool>(visited, true)) }, false); }
protected override bool ModifyInternal(RoomSpec spec) { int secretRoomSize = 2; #region DEBUG if (BigBoss.Debug.logging(Logs.LevelGen)) { BigBoss.Debug.printHeader(Logs.LevelGen, "Hidden Room Mod"); spec.Grids.ToLog(Logs.LevelGen, "Final Room After placing doors"); } #endregion RandomPicker <GenSpace> picker; spec.Grids.DrawPotentialExternalDoors(Draw.PickRandom(out picker)); Value2D <GenSpace> doorSpace; if (!picker.Pick(spec.Random, out doorSpace)) { return(false); } var floors = new List <Value2D <GenSpace> >(); spec.Grids.DrawRect( (doorSpace.x - secretRoomSize), (doorSpace.x + secretRoomSize), (doorSpace.y - secretRoomSize), (doorSpace.y + secretRoomSize), new StrokedAction <GenSpace>() { UnitAction = Draw.IsTypeThen(GridType.NULL, Draw.SetTo(GridType.Floor, spec.Theme).And(Draw.AddTo(floors))), StrokeAction = Draw.IsType <GenSpace>(GridType.NULL).IfThen(Draw.SetTo(GridType.Wall, spec.Theme)) }); bool chest = spec.Random.Percent(.75d); if (chest) { List <Value2D <GenSpace> > chestOptions = new List <Value2D <GenSpace> >(); spec.Grids.DrawPoints(floors.Cast <Point>(), Draw.Not(Draw.HasAround(false, Draw.IsType <GenSpace>(GridType.Door))) .IfThen(Draw.AddTo(chestOptions))); spec.Grids.SetTo(chestOptions.Random(spec.Random), GridType.Chest, spec.Theme); } else { spec.Grids.SetTo(floors.Random(spec.Random), GridType.SmallLoot, spec.Theme); } spec.Grids.SetTo(doorSpace, GridType.Door, spec.Theme); #region DEBUG if (BigBoss.Debug.logging(Logs.LevelGen)) { spec.Grids.ToLog(Logs.LevelGen, "Final Room After placing doors"); BigBoss.Debug.printFooter(Logs.LevelGen, "Hidden Room Mod"); } #endregion return(true); }
public override bool Modify(SpawnSpec spec) { MultiMap <GridSpace> spawnable = new MultiMap <GridSpace>(); spec.Room.DrawAll(Draw.If <GridSpace>((g) => g.Spawnable).IfThen(Draw.AddTo(spawnable))); Value2D <GridSpace> space; if (!spawnable.GetRandom(spec.Random, out space)) { return(false); } BigBoss.DungeonMaster.SpawnNPC(space.val, space.val.Theme.Keywords); return(true); }
protected void PlaceDoors() { #region DEBUG if (BigBoss.Debug.logging(Logs.LevelGen)) { BigBoss.Debug.printHeader(Logs.LevelGen, "Place Doors"); } #endregion foreach (LayoutObject room in Objects) { #region DEBUG if (BigBoss.Debug.logging(Logs.LevelGen)) { BigBoss.Debug.printHeader(Logs.LevelGen, "Place Doors on " + room); } #endregion var potentialDoors = new MultiMap <GenSpace>(); room.Grids.DrawPotentialExternalDoors(Draw.AddTo <GenSpace>(potentialDoors)); int numDoors = Rand.Next(doorsMin, doorsMax); #region DEBUG if (BigBoss.Debug.logging(Logs.LevelGen)) { potentialDoors.ToLog(Logs.LevelGen, "Potential Doors"); BigBoss.Debug.w(Logs.LevelGen, "Number of doors to generate: " + numDoors); } #endregion foreach (Value2D <GenSpace> doorSpace in potentialDoors.GetRandom(Rand, numDoors, minDoorSpacing)) { room.Grids.SetTo(doorSpace, GridType.Door, Theme); } #region DEBUG if (BigBoss.Debug.logging(Logs.LevelGen)) { room.ToLog(Logs.LevelGen, "Room After placing doors"); BigBoss.Debug.printFooter(Logs.LevelGen, "Place Doors on " + room); } #endregion } #region DEBUG if (BigBoss.Debug.logging(Logs.LevelGen)) { BigBoss.Debug.printFooter(Logs.LevelGen, "Place Doors"); } #endregion }
protected override bool ModifyInternal(RoomSpec spec) { int size = spec.Random.Next(3, 5); BigBoss.Debug.w(Logs.LevelGen, "Size: " + size); // Add an extra 2 for stroke width for analysis size += 2; List <Bounding> locations = spec.Grids.FindRectangles(size, size, false, new StrokedAction <GenSpace>() { UnitAction = Draw.Or(Draw.IsType <GenSpace>(GridType.Floor), Draw.IsType <GenSpace>(GridType.Wall)).And(Draw.Empty()), StrokeAction = Draw.Walkable() }, spec.Grids.Bounding); if (locations.Count == 0) { return(false); } #region Debug if (BigBoss.Debug.logging(Logs.LevelGen) && BigBoss.Debug.Flag(DebugManager.DebugFlag.FineSteps)) { BigBoss.Debug.w(Logs.LevelGen, locations.Count + " Options: "); var save = new MultiMap <GenSpace>(); var copy = new Array2D <GenSpace>(spec.Grids); foreach (Bounding r in locations) { save.Clear(); copy.DrawRect(r.XMin + 1, r.XMax - 1, r.YMin + 1, r.YMax - 1, Draw.AddTo(save).And(Draw.SetTo(GridType.Path_Vert, spec.Theme))); copy.ToLog(Logs.LevelGen); copy.PutAll(save); } } #endregion Bounding l = locations.Random(spec.Random); // Draw inner square without stroke (stroke was just used to analyze surroundings) spec.Grids.DrawRect(l.XMin + 1, l.XMax - 1, l.YMin + 1, l.YMax - 1, Draw.SetTo(GridType.Wall, spec.Theme)); return(true); }
protected override bool ModifyInternal(RoomSpec spec) { #region Debug if (BigBoss.Debug.logging(Logs.LevelGen)) { BigBoss.Debug.printHeader(Logs.LevelGen, "Splitter Mod"); } #endregion Bounding bounds = spec.Grids.Bounding; List <int> options = new List <int>(); bool horizontal = spec.Random.NextBool(); int from = bounds.GetMin(horizontal); int to = bounds.GetMax(horizontal); int fromAlt = bounds.GetMin(!horizontal); int toAlt = bounds.GetMax(!horizontal); // Iterate and find all viable options for (int i = fromAlt; i <= toAlt; i++) { Counter floorCount; Counter side1; Counter side2; if (spec.Grids.DrawLine(from, to, i, horizontal, // If no doors around Draw.Not(Draw.Around(false, Draw.IsType <GenSpace>(GridType.Door))) // Not blocking walking .And(Draw.Not(Draw.Blocking <GenSpace>(Draw.Walkable()))) // Count floors on line as well as sides .And(Draw.IsType <GenSpace>(GridType.Floor).IfThen(Draw.Count <GenSpace>(out floorCount))) .And(Draw.Loc(horizontal ? GridLocation.TOP : GridLocation.LEFT, Draw.IsTypeThen(GridType.Floor, Draw.Count <GenSpace>(out side1)))) .And(Draw.Loc(horizontal ? GridLocation.BOTTOM : GridLocation.RIGHT, Draw.IsTypeThen(GridType.Floor, Draw.Count <GenSpace>(out side2))))) // Has a floor in each && floorCount > 0 && side1 > 0 && side2 > 0 ) { options.Add(i); } } if (options.Count == 0) { return(false); } #region Debug if (BigBoss.Debug.logging(Logs.LevelGen) && BigBoss.Debug.Flag(DebugManager.DebugFlag.FineSteps)) { foreach (int i in options) { Container2D <GenSpace> copy = new Array2D <GenSpace>(spec.Grids); copy.DrawLine(from, to, i, horizontal, Draw.IsType <GenSpace>(GridType.NULL).IfNotThen(Draw.SetTo(GridType.INTERNAL_RESERVED_BLOCKED, spec.Theme))); copy.ToLog(Logs.LevelGen); } } #endregion // Draw selected splitter int picked = options.Random(spec.Random); List <Point> walls = new List <Point>(); spec.Grids.DrawLine(from, to, picked, horizontal, Draw.Not(Draw.IsType <GenSpace>(GridType.NULL)).IfThen(Draw.SetTo(GridType.Wall, spec.Theme).And(Draw.AddTo <GenSpace>(walls)))); #region Debug if (BigBoss.Debug.logging(Logs.LevelGen)) { BigBoss.Debug.w(Logs.LevelGen, "Picked splitter:"); spec.Grids.ToLog(Logs.LevelGen); } #endregion spec.Grids.PlaceSomeDoors(walls, spec.Theme, spec.Random, 5); #region DEBUG if (BigBoss.Debug.logging(Logs.LevelGen)) { BigBoss.Debug.printFooter(Logs.LevelGen, "Splitter Mod"); } #endregion return(true); }
public static List <Value2D <GenSpace> > PlaceSomeDoors(this Container2D <GenSpace> arr, IEnumerable <Point> points, Theme theme, System.Random rand, int desiredWallToDoorRatio = -1, Point shift = null) { if (desiredWallToDoorRatio < 0) { desiredWallToDoorRatio = LevelGenerator.desiredWallToDoorRatio; } var acceptablePoints = new MultiMap <GenSpace>(); Counter numPoints = new Counter(); DrawAction <GenSpace> call = Draw.Count <GenSpace>(numPoints).And(Draw.CanDrawDoor().IfThen(Draw.AddTo(acceptablePoints))); if (shift != null) { call = call.Shift <GenSpace>(shift.x, shift.y); } arr.DrawPoints(points, call); if (DoorRatioPicker == null) { DoorRatioPicker = new ProbabilityList <int>(); DoorRatioPicker.Add(-2, .25); DoorRatioPicker.Add(-1, .5); DoorRatioPicker.Add(0, 1); DoorRatioPicker.Add(1, .5); DoorRatioPicker.Add(2, .25); } int numDoors = numPoints / desiredWallToDoorRatio; numDoors += DoorRatioPicker.Get(rand); if (numDoors <= 0) { numDoors = 1; } List <Value2D <GenSpace> > pickedPts = acceptablePoints.GetRandom(rand, numDoors, 1); foreach (Point picked in pickedPts) { arr.SetTo(picked, GridType.Door, theme); } return(pickedPts); }
protected void ConfirmConnection() { #region DEBUG if (BigBoss.Debug.logging(Logs.LevelGen)) { BigBoss.Debug.printHeader(Logs.LevelGen, "Confirm Connections"); } #endregion DrawAction <GenSpace> passTest = Draw.ContainedIn <GenSpace>(Path.PathTypes).Or(Draw.CanDrawDoor()); var layoutCopy = Container.GetGrid().Array; List <LayoutObject> rooms = new List <LayoutObject>(Layout.Rooms.Cast <LayoutObject>()); var runningConnected = Container2D <GenSpace> .CreateArrayFromBounds(layoutCopy); // Create initial queue and visited var startingRoom = rooms.Take(); startingRoom.GetConnectedGrid().DrawAll(Draw.AddTo(runningConnected)); Container2D <bool> visited; Queue <Value2D <GenSpace> > queue; ConstructBFS(startingRoom, out queue, out visited); visited = visited.Array; LayoutObject fail; while (!startingRoom.ConnectedTo(rooms, out fail)) { // Find start points #region DEBUG if (BigBoss.Debug.logging(Logs.LevelGen)) { runningConnected.ToLog(Logs.LevelGen, "Source Setup"); fail.ToLog(Logs.LevelGen, "Failed to connect to this"); } #endregion Value2D <GenSpace> startPoint; Value2D <GenSpace> endPoint; LayoutObject hit; if (!FindNextPathPoints(layoutCopy, runningConnected, out hit, passTest, queue, visited, out startPoint, out endPoint)) { throw new ArgumentException("Cannot find path to fail room"); } // Connect #region DEBUG if (BigBoss.Debug.logging(Logs.LevelGen)) { layoutCopy.SetTo(startPoint, GridType.INTERNAL_RESERVED_CUR, Theme); layoutCopy.ToLog(Logs.LevelGen, "Largest after putting blocked"); BigBoss.Debug.w(Logs.LevelGen, "Start Point:" + startPoint); } #endregion var hitConnected = hit.GetConnectedGrid(); var stack = layoutCopy.DrawJumpTowardsSearch( startPoint.x, startPoint.y, 3, 5, Draw.IsType <GenSpace>(GridType.NULL).And(Draw.Inside <GenSpace>(layoutCopy.Bounding.Expand(5))), passTest.And(Draw.ContainedIn(hitConnected)), Rand, endPoint, true); var path = new Path(stack); if (path.Valid) { #region DEBUG if (BigBoss.Debug.logging(Logs.LevelGen)) { path.Bake(null).ToLog(Logs.LevelGen, "Connecting Path"); } #endregion path.Simplify(); Point first = path.FirstEnd; Point second = path.SecondEnd; LayoutObject leaf1, leaf2; LayoutObject pathObj = path.Bake(Theme); Container.ConnectTo(first, pathObj, first, out leaf1, out pathObj); Container.ConnectTo(second, pathObj, second, out leaf2, out pathObj); if (leaf1[first].Type == GridType.Wall) { leaf1.SetTo(first, GridType.Door, Theme); } if (leaf2[second].Type == GridType.Wall) { leaf2.SetTo(second, GridType.Door, Theme); } foreach (var v in pathObj) { layoutCopy[v] = v.val; runningConnected.Put(v); if (!visited[v]) { queue.Enqueue(v); } visited[v] = true; } foreach (var p in path) { layoutCopy.DrawAround(p.x, p.y, false, Draw.IsType <GenSpace>(GridType.NULL).IfThen(Draw.SetTo(pathObj, GridType.Floor, Theme).And(Draw.SetTo(GridType.Floor, Theme)))); layoutCopy.DrawCorners(p.x, p.y, new DrawAction <GenSpace>((arr, x, y) => { if (!arr.IsType(x, y, GridType.NULL)) { return(false); } return(arr.Cornered(x, y, Draw.IsType <GenSpace>(GridType.Floor))); }).IfThen(Draw.SetTo(pathObj, GridType.Floor, Theme))); } Container.Objects.Add(pathObj); hitConnected.DrawAll(Draw.AddTo(runningConnected)); #region DEBUG if (BigBoss.Debug.logging(Logs.LevelGen)) { Container.ToLog(Logs.LevelGen, "Final Connection"); } #endregion } else { throw new ArgumentException("Cannot create path to hit room"); } } #region DEBUG if (BigBoss.Debug.logging(Logs.LevelGen)) { BigBoss.Debug.printFooter(Logs.LevelGen, "Confirm Connections"); } #endregion }
protected void ClusterAround(LayoutObjectContainer cluster, LayoutObject obj) { #region Debug if (BigBoss.Debug.logging(Logs.LevelGen)) { BigBoss.Debug.printHeader("Cluster Around"); } #endregion obj.ShiftOutside(cluster, new Point(1, 0), null, false, false); obj.Shift(-1, 0); // Shift to overlapping slightly MultiMap <bool> visited = new MultiMap <bool>(); visited[0, 0] = true; ProbabilityList <ClusterInfo> shiftOptions = new ProbabilityList <ClusterInfo>(); Queue <Point> shiftQueue = new Queue <Point>(); shiftQueue.Enqueue(new Point()); Container2D <GenSpace> clusterGrid = cluster.GetGrid(); Container2D <GenSpace> objGrid = obj.GetGrid(); #region Debug if (BigBoss.Debug.logging(Logs.LevelGen)) { var tmp = new MultiMap <GenSpace>(); tmp.PutAll(obj.GetGrid()); tmp.PutAll(cluster.GetGrid()); tmp.ToLog(Logs.LevelGen, "Starting placement"); } #endregion while (shiftQueue.Count > 0) { Point curShift = shiftQueue.Dequeue(); #region Debug if (BigBoss.Debug.Flag(DebugManager.DebugFlag.FineSteps) && BigBoss.Debug.logging(Logs.LevelGen)) { var tmpMap = new MultiMap <GenSpace>(); tmpMap.PutAll(clusterGrid); tmpMap.PutAll(objGrid, curShift); tmpMap.ToLog(Logs.LevelGen, "Analyzing at shift " + curShift); } #endregion // Test if pass List <Point> intersectPoints = new List <Point>(); if (objGrid.DrawAll((arr, x, y) => { if (GridTypeEnum.EdgeType(arr[x, y].GetGridType())) { GridType clusterType = clusterGrid[x + curShift.x, y + curShift.y].GetGridType(); if (clusterType == GridType.NULL) { return(true); } intersectPoints.Add(new Point(x, y)); return(GridTypeEnum.EdgeType(clusterType)); } else { return(!clusterGrid.Contains(x + curShift.x, y + curShift.y)); } }) && intersectPoints.Count > 0) { // Passed test // queue surrounding points visited.DrawAround(curShift.x, curShift.y, true, Draw.Not(Draw.EqualTo(true)).IfThen(Draw.AddTo <bool>(shiftQueue).And(Draw.SetTo(true)))); #region Debug if (BigBoss.Debug.Flag(DebugManager.DebugFlag.FineSteps) && BigBoss.Debug.logging(Logs.LevelGen)) { BigBoss.Debug.w(Logs.LevelGen, "passed with " + intersectPoints.Count); } #endregion shiftOptions.Add(new ClusterInfo() { Shift = curShift, Intersects = intersectPoints }, Math.Pow(intersectPoints.Count, 3)); } } #region Debug if (BigBoss.Debug.logging(Logs.LevelGen)) { shiftOptions.ToLog(Logs.LevelGen, "Shift options"); } #endregion List <Point> clusterDoorOptions = new List <Point>(); ClusterInfo info; var placed = new List <Value2D <GenSpace> >(0); while (shiftOptions.Take(Rand, out info)) { clusterGrid.DrawPoints(info.Intersects, Draw.CanDrawDoor().IfThen(Draw.AddTo <GenSpace>(clusterDoorOptions)).Shift(info.Shift)); #region Debug if (BigBoss.Debug.logging(Logs.LevelGen)) { BigBoss.Debug.w(Logs.LevelGen, "selected " + info.Shift); var tmpMap = new MultiMap <GenSpace>(); clusterGrid.DrawAll(Draw.CopyTo(tmpMap)); objGrid.DrawAll(Draw.CopyTo(tmpMap, info.Shift)); tmpMap.DrawPoints(info.Intersects, Draw.SetTo(GridType.INTERNAL_RESERVED_CUR, Theme).Shift(info.Shift)); tmpMap.ToLog(Logs.LevelGen, "Intersect Points"); tmpMap = new MultiMap <GenSpace>(); clusterGrid.DrawAll(Draw.CopyTo(tmpMap)); objGrid.DrawAll(Draw.CopyTo(tmpMap, info.Shift)); tmpMap.DrawPoints(clusterDoorOptions, Draw.SetTo(GridType.Door, Theme)); tmpMap.ToLog(Logs.LevelGen, "Cluster door options"); } #endregion if (clusterDoorOptions.Count > 0) { // Cluster side has door options obj.Shift(info.Shift.x, info.Shift.y); placed = obj.PlaceSomeDoors(clusterDoorOptions, Theme, Rand); if (placed.Count != 0) { // Placed a door foreach (Point p in placed) { LayoutObject clusterObj; cluster.GetObjAt(p, out clusterObj); obj.Connect(clusterObj); } break; } else { #region Debug if (BigBoss.Debug.logging(Logs.LevelGen)) { BigBoss.Debug.w(Logs.LevelGen, "selected point failed to match " + info.Shift + ". Backing up"); } #endregion obj.Shift(-info.Shift.x, -info.Shift.y); } } } if (placed.Count == 0) { throw new ArgumentException("Could not cluster rooms"); } #region Debug if (BigBoss.Debug.logging(Logs.LevelGen)) { var tmpMap = new MultiMap <GenSpace>(); tmpMap.PutAll(clusterGrid); tmpMap.PutAll(obj.GetGrid()); tmpMap.ToLog(Logs.LevelGen, "Final setup " + info.Shift); BigBoss.Debug.printFooter("Cluster Around"); } #endregion }