Пример #1
0
    public FilledRegion Apply(FillData data)
    {
        List <Region> spawnAreas = new List <Region>();

        //Get data.
        Generation.BeingFilled = data.BeingFilled;
        int numb   = Generation.NumbPlateaus;
        int width  = Generation.PlateauWidth;
        int space  = Generation.SpaceBetweenPlateaus;
        int border = Generation.Border;

        //Plateau location data.
        int height = (int)Math.Round((PlateauRelativeHeight * data.BeingFilled.Height), 0);

        if (height >= data.BeingFilled.Height)
        {
            height = data.BeingFilled.Height - 1;
        }
        int top = data.BeingFilled.Bottom - height;

        //Add the plateaus.
        Region r;

        for (int i = 0; i < numb; ++i)
        {
            r = new Region(data.BeingFilled.Left + border + (i * (space + width)), top, width - 1, data.BeingFilled.Bottom - top);
            data.FillRegion(true, r);
            spawnAreas.Add(new Region(new Location(r.Left, data.BeingFilled.Top),
                                      r.TopRight.Above));
        }

        //Make room for any holes that the plateaus covered.
        foreach (Location l in data.HolesAlongPerimeter())
        {
            //The hole is covered if it is just under the region and the space right above it is covered.
            if (data.BeingFilled.Touches(l.Above, true, true, false) &&
                data.GetMapAt(l.Above))
            {
                //Make a litle tunnel under the plateau.
                int[]  plateauSides = PlateauSides(l.X, numb, width, space, border, data.BeingFilled.Left, data.BeingFilled.Right);
                Region cleared      = new Region(plateauSides[0], data.BeingFilled.Bottom, width - 1, 0);
                data.FillRegion(false, cleared);
            }
        }

        return(new SteppedHallwayRegion(data.BeingFilled, spawnAreas));
    }
Пример #2
0
    public FilledRegion Apply(FillData data)
    {
        bool horizontal = data.BeingFilled.Width > data.BeingFilled.Height;
        bool vertical   = data.BeingFilled.Height > data.BeingFilled.Width;

        //Put a thin line through the middle.
        if (horizontal)
        {
            data.FillRegion(true, new Region(data.BeingFilled.Left + 1, data.BeingFilled.CenterY, data.BeingFilled.Width - 2, 0, true));
        }
        else if (vertical)
        {
            data.FillRegion(true, new Region(data.BeingFilled.CenterX, data.BeingFilled.Top + 1, 0, data.BeingFilled.Height - 2, true));
        }

        return(new LineRegion(data.BeingFilled));
    }
    public FilledRegion Apply(FillData data)
    {
        //Fill the square.
        data.FillRegion(true, new Region(data.BeingFilled.TopLeft.Right.Below, data.BeingFilled.BottomRight.Left.Above));

        //Create the lines.
        Region horz  = new Region(data.BeingFilled.LeftMid.Right, data.BeingFilled.Center.Left);
        Region horz2 = new Region(data.BeingFilled.Center.Right, data.BeingFilled.RightMid.Left);
        Region vert  = new Region(data.BeingFilled.TopMid.Below, data.BeingFilled.Center.Above);
        Region vert2 = new Region(data.BeingFilled.Center.Below, data.BeingFilled.BottomMid.Above);

        data.FillRegion(false, horz);
        data.FillRegion(false, horz2);
        data.FillRegion(false, vert);
        data.FillRegion(false, vert2);

        Region center = new Region(data.BeingFilled.Center, data.BeingFilled.Center);

        data.Holes.Add(center.Center);
        data.FillRegion(false, center);

        return(new CarvedPlusRegion(data.BeingFilled));
    }
Пример #4
0
    public void IterateFillPattern()
    {
        //Already done?
        if (iterateFillPatternsRegionCount >= Regions.Count)
        {
            return;
        }

        //Run an iteration.

        FilledRegion temp;
        Region       r = Regions[iterateFillPatternsRegionCount];

        iterateFillPatternsRegionCount++;

        //Pick a random applicable pattern (assuming one exists) and apply it.
        FillPattern p = Settings.MostSuitable(r);

        if (p != null)
        {
            //Clear the space, and apply the pattern.
            FillData.BeingFilled = r;
            FillData.FillRegion(false, r);
            temp = p.Apply(FillData);

            //If the filled region is blank, replace it with a BlankRegion.
            bool blank = true;
            for (int i = temp.Covering.Left; i <= temp.Covering.Right; ++i)
            {
                for (int j = temp.Covering.Top; j <= temp.Covering.Bottom; ++j)
                {
                    if (FillData.GetMapAt(new Location(i, j)))
                    {
                        blank = false;
                        break;
                    }
                }
                if (!blank)
                {
                    break;
                }
            }
            if (blank)
            {
                temp = new BlankRegion(temp.Covering);
            }

            //Now add it.
            FilledRegions.Add(temp);
            Region r2;

            //Make sure the spawn points are all valid.
            foreach (Spawns s in FilledRegions[FilledRegions.Count - 1].PotentialSpawns.Keys)
            {
                for (int i = 0; i < FilledRegions[FilledRegions.Count - 1].PotentialSpawns[s].Count; ++i)
                {
                    r2 = FilledRegions[FilledRegions.Count - 1].PotentialSpawns[s][i];

                    if (r2.Width < 0 || r2.Height < 0)
                    {
                        FilledRegions[FilledRegions.Count - 1].PotentialSpawns[s].RemoveAt(i--);
                    }
                }
            }
        }
        //If no regions fit, add a "NoRegion".
        else
        {
            FilledRegions.Add(new NoRegion(r));
        }
    }
    public FilledRegion Apply(FillData data)
    {
        //The spawning areas.
        List <Region> spawningAreas = new List <Region>();

        //Get/set some data.
        Region area = data.BeingFilled;

        PlateauGeneration.BeingFilled = data.BeingFilled;
        //If the corridor is going to be vertical, flip the width and height.
        if (area.Height > area.Width)
        {
            PlateauGeneration.BeingFilled = new Region(area.Y, area.X, area.Height, area.Width);
        }

        int numb        = PlateauGeneration.NumbPlateaus;
        int plateauSize = PlateauGeneration.PlateauWidth;

        int space  = PlateauGeneration.SpaceBetweenPlateaus;
        int border = PlateauGeneration.Border;

        //Plateau size data.
        //"maxSize" is the largest allowable hurdle height.
        int maxSize = PlateauGeneration.BeingFilled.Height - 1;

        if (area.Height > area.Width)
        {
            //Vertical.

            //Add the plateaus.
            int hurdleWidth, plateauExtent;
            for (int i = 0; i < numb; ++i)
            {
                //Get a width within the given random variation.
                hurdleWidth = (int)Math.Round((area.Width + 1) * (HurdleAverageSpaceScale + ((2 * HurdleHeightVariance * (float)GeneratorSettings.R.NextDouble()) - HurdleHeightVariance)), 0);
                //Keep it constrained.
                if (hurdleWidth > maxSize)
                {
                    hurdleWidth = maxSize;
                }
                if (hurdleWidth < 1)
                {
                    hurdleWidth = 1;
                }

                //Get the width of the plateau given the size of a hurdle.
                plateauExtent  = area.Width + 1 - hurdleWidth;
                plateauExtent /= 2;

                //Fill in the plateaus.
                data.FillRegion(true, new Region(area.Left, area.Top + border + (i * (space + plateauSize)), plateauExtent - 1, plateauSize - 1));
                if ((2 * plateauExtent) + hurdleWidth >= area.Width + 1)
                {
                    data.FillRegion(true, new Region(area.Right - plateauExtent + 1, area.Top + border + (i * (space + plateauSize)), plateauExtent - 1, plateauSize - 1));
                }
                else
                {
                    data.FillRegion(true, new Region(area.Right - plateauExtent, area.Top + border + (i * (space + plateauSize)), plateauExtent, plateauSize - 1));
                }
            }

            //Make room for any holes that the plateaus covered.
            foreach (Location l in data.HolesAlongPerimeter())
            {
                //The hole is covered if it is just left/right of the region and the space just right/left of it (respectively) is filled.
                if ((area.Touches(l.Left, true, true, false) && data.GetMapAt(l.Left)) ||
                    (area.Touches(l.Right, true, true, false) && data.GetMapAt(l.Right)))
                {
                    //Make a little tunnel under the plateau.
                    int[]  plateauSides = SteppedHallwayPattern.PlateauSides(l.Y, numb, plateauSize, space, border, area.Top, area.Bottom);
                    Region cleared;
                    if (l.X - 1 == area.Right)
                    {
                        cleared = new Region(data.BeingFilled.Right, plateauSides[0], 0, plateauSize - 1);
                    }
                    else
                    {
                        cleared = new Region(data.BeingFilled.Left, plateauSides[0], 0, plateauSize - 1);
                    }
                    data.FillRegion(false, cleared);
                }
            }
        }
        else
        {
            //Horizontal.

            //Add the plateaus.
            int hurdleHeight, plateauHeight;
            for (int i = 0; i < numb; ++i)
            {
                //Get a height within the given random variation.
                hurdleHeight = (int)Math.Round((area.Height + 1) * (HurdleAverageSpaceScale + ((2 * HurdleHeightVariance * (float)GeneratorSettings.R.NextDouble()) - HurdleHeightVariance)), 0);
                //Keep it constrained.
                if (hurdleHeight > maxSize)
                {
                    hurdleHeight = maxSize;
                }
                if (hurdleHeight < 1)
                {
                    hurdleHeight = 1;
                }

                //Get the height of the plateau given the size of a hurdle.
                plateauHeight  = area.Height + 1 - hurdleHeight;
                plateauHeight /= 2;

                //Fill in the plateaus.
                data.FillRegion(true, new Region(area.Left + border + (i * (space + plateauSize)), area.Top, plateauSize - 1, plateauHeight - 1));
                if ((2 * plateauHeight) + hurdleHeight >= area.Height + 1)
                {
                    data.FillRegion(true, new Region(area.Left + border + (i * (space + plateauSize)), area.Bottom - plateauHeight + 1, plateauSize - 1, plateauHeight - 1));
                    spawningAreas.Add(new Region(area.Left + border + (i * (space + plateauSize)), area.Top + plateauHeight, plateauSize - 1, data.BeingFilled.Height - plateauHeight - plateauHeight - 2));
                }
                else
                {
                    data.FillRegion(true, new Region(area.Left + border + (i * (space + plateauSize)), area.Bottom - plateauHeight, plateauSize - 1, plateauHeight));
                    spawningAreas.Add(new Region(area.Left + border + (i * (space + plateauSize)), area.Top + plateauHeight, plateauSize - 1, data.BeingFilled.Height - plateauHeight - plateauHeight - 1));
                }
            }
        }


        //Make room for any holes that the plateaus covered.
        foreach (Location l in data.HolesAlongPerimeter())
        {
            //Horizontal.
            if (area.Height < area.Width)
            {
                //The hole is covered if it is just below/above the region and the space above/below it (respectively) is filled.
                if ((area.Touches(l.Above, true, true, false) && data.GetMapAt(l.Above)) ||
                    (area.Touches(l.Below, true, true, false) && data.GetMapAt(l.Below)))
                {
                    //Make a little tunnel under the plateau.
                    int[] plateauSides = SteppedHallwayPattern.PlateauSides(l.X, numb, plateauSize, space, border, area.Left, area.Right);

                    Region cleared;
                    if (l.Y - 1 == area.Bottom)
                    {
                        cleared = new Region(plateauSides[0], data.BeingFilled.Bottom, plateauSize - 1, 0);
                    }
                    else
                    {
                        cleared = new Region(plateauSides[0], data.BeingFilled.Top, plateauSize - 1, 0);
                    }

                    data.FillRegion(false, cleared);
                }
            }

            //Vertical.
            else if ((area.Touches(l.Left, true, true, false) && data.GetMapAt(l.Left)) ||
                     (area.Touches(l.Right, true, true, false) && data.GetMapAt(l.Right)))
            {
                //Make a little tunnel under the plateau.
                int[] plateauSides = SteppedHallwayPattern.PlateauSides(l.Y, numb, plateauSize, space, border, area.Top, area.Bottom);

                Region cleared;
                if (l.X - 1 == area.Right)
                {
                    cleared = new Region(data.BeingFilled.Right, plateauSides[0], 0, plateauSize - 1);
                }
                else
                {
                    cleared = new Region(data.BeingFilled.Left, plateauSides[0], 0, plateauSize - 1);
                }

                data.FillRegion(false, cleared);
            }
        }

        //Return the new regions.
        return(new ThickHurdleRegion(data.BeingFilled, spawningAreas));
    }
Пример #6
0
    private void FillTunnels()
    {
        //Go through all nodes and make tunnels,
        //  with special edge tunnels around the perimeter (if the level wraps around).
        Location lastNodePos = (Settings.TunnelLength + MaxRoomSize) * (Settings.NumberOfNodes - new Location(1, 1));
        Location topLeft, nextTopLeft;
        Region   beingCleared;

        foreach (PositionalNode n in NodeStates.Keys)//Graph.AllNodes(new PositionalNode(new float[2] { 1.0f, 1.0f }, 0)))
        {
            //Fill in the tunnel to the right and down from this cell.

            //Down.
            if (n.Coordinate[1] < lastNodePos.Y)
            {
                topLeft = new Location(VerticalTunnelX((int)n.Coordinate[0]), NodeAreas[n].Bottom);
                if (NodeStates[n] == NodeState.Room)
                {
                    topLeft = topLeft.Below;
                }
                nextTopLeft = NodeAreas[new PositionalNode(new float[2] {
                    n.Coordinate[0], n.Coordinate[1] + MaxRoomSize.Y + Settings.TunnelLength.Y
                }, 0)].TopLeft;

                beingCleared = new Region(topLeft, new Location(topLeft.X + Settings.TunnelThickness.Y - 1, nextTopLeft.Y - 1));
                FillData.FillRegion(false, beingCleared);
                Regions.Add(beingCleared);

                for (int x = beingCleared.Left; x <= beingCleared.Right; ++x)
                {
                    Holes.Add(new Location(x, beingCleared.Top));
                    Holes.Add(new Location(x, beingCleared.Bottom));
                }
            }
            //Right.
            if (n.Coordinate[0] < lastNodePos.X)
            {
                topLeft     = new Location(NodeAreas[n].Right, HorizontalTunnelY((int)n.Coordinate[1])).Right;
                nextTopLeft = NodeAreas[new PositionalNode(new float[2] {
                    n.Coordinate[0] + MaxRoomSize.X + Settings.TunnelLength.X, n.Coordinate[1]
                }, 0)].TopLeft;

                beingCleared = new Region(topLeft, new Location(nextTopLeft.X - 1, topLeft.Y + Settings.TunnelThickness.X - 1));
                FillData.FillRegion(false, beingCleared);
                Regions.Add(beingCleared);

                for (int y = beingCleared.Top; y <= beingCleared.Bottom; ++y)
                {
                    Holes.Add(new Location(beingCleared.Left, y));
                    Holes.Add(new Location(beingCleared.Right, y));
                }
            }

            //Border cases.

            //Left border.
            if (Settings.WrapAroundX && n.Coordinate[0] == 1.0f)
            {
                topLeft     = new Location(0, HorizontalTunnelY((int)n.Coordinate[1]));
                nextTopLeft = NodeAreas[n].TopLeft.Left;

                beingCleared = new Region(topLeft, new Location(nextTopLeft.X, topLeft.Y + Settings.TunnelThickness.X - 1));
                FillData.FillRegion(false, beingCleared);
                Regions.Add(beingCleared);

                for (int y = beingCleared.Top; y <= beingCleared.Bottom; ++y)
                {
                    Holes.Add(new Location(beingCleared.Right, y));
                }
            }
            //Top border.
            if (Settings.WrapAroundY && n.Coordinate[1] == 1.0f)
            {
                topLeft     = new Location(VerticalTunnelX((int)n.Coordinate[0]), 0);
                nextTopLeft = NodeAreas[n].TopLeft.Above;

                beingCleared = new Region(topLeft, new Location(topLeft.X + Settings.TunnelThickness.Y - 1, nextTopLeft.Y));
                FillData.FillRegion(false, beingCleared);
                Regions.Add(beingCleared);

                for (int x = beingCleared.Left; x <= beingCleared.Right; ++x)
                {
                    Holes.Add(new Location(x, beingCleared.Bottom));
                }
            }
            //Right border.
            if (Settings.WrapAroundX && n.Coordinate[0] == lastNodePos.X + 1)
            {
                topLeft = new Location(NodeAreas[n].Right, HorizontalTunnelY((int)n.Coordinate[1])).Right;

                beingCleared = new Region(topLeft, new Location(Map.GetLength(0) - 1, topLeft.Y + Settings.TunnelThickness.X - 1));
                FillData.FillRegion(false, beingCleared);
                Regions.Add(beingCleared);

                for (int y = beingCleared.Top; y <= beingCleared.Bottom; ++y)
                {
                    Holes.Add(new Location(beingCleared.Left, y));
                }
            }
            //Bottom border.
            if (Settings.WrapAroundY && n.Coordinate[1] == lastNodePos.Y + 1)
            {
                topLeft = new Location(VerticalTunnelX((int)n.Coordinate[0]), NodeAreas[n].Bottom).Below;

                beingCleared = new Region(topLeft, new Location(topLeft.X + Settings.TunnelThickness.Y - 1, Map.GetLength(1) - 1));
                FillData.FillRegion(false, beingCleared);
                Regions.Add(beingCleared);

                for (int x = beingCleared.Left; x <= beingCleared.Right; ++x)
                {
                    Holes.Add(new Location(x, beingCleared.Top));
                }
            }
        }
    }
Пример #7
0
    public void IterateBase()
    {
        if (DoneBaseGen)
        {
            return;
        }

        count += 1;

        PositionalNode current = baseGenIterateCounter.Current;

        //Make either a room or a tunnel junction at the given spot.
        if (GeneratorSettings.R.NextDouble() < Settings.PercentRooms)
        {
            //Room.

            Location size = new Location(Settings.RoomDimensions.X + (int)Settings.RoomXVariance.Random(),
                                         Settings.RoomDimensions.Y + (int)Settings.RoomYVariance.Random());
            size = new Location(System.Math.Max(size.X, Settings.TunnelThickness.X),
                                System.Math.Max(size.Y, Settings.TunnelThickness.Y));
            Region room = new Region((int)current.Coordinate[0],
                                     (int)current.Coordinate[1],
                                     size.X - 1, size.Y - 1);
            if (!room.SubRegionOf(new Region(0, 0, Map.GetLength(0), Map.GetLength(1))))
            {
                DoneBaseGen = !baseGenIterateCounter.MoveNext();
                NodeStates.Remove(current);
                return;
            }

            //Move the room to the center.
            Location offset = new Location((int)Math.Round((MaxRoomSize.X - room.Width - 1) / 2.0f, 0), (int)Math.Round((MaxRoomSize.Y - room.Height - 1) / 2.0f, 0));
            room = new Region(room.TopLeft + offset, room.BottomRight + offset);

            //Clear the room area.
            Regions.Add(room);
            FillData.FillRegion(false, room);
            //Add the room data.
            NodeStates[current] = NodeState.Room;
            NodeAreas.Add(current, room);
        }
        else
        {
            //Tunnel junction.

            Location size  = MaxRoomSize;
            Region   space = new Region((int)current.Coordinate[0],
                                        (int)current.Coordinate[1],
                                        size.X - 1, size.Y - 1);

            space = new Region(space.Left + Settings.JunctionOffset.X,
                               space.Top + Settings.JunctionOffset.Y,
                               Settings.TunnelThickness.Y - 1,
                               Settings.TunnelThickness.X - 1);
            if (!space.SubRegionOf(new Region(0, 0, Map.GetLength(0), Map.GetLength(1))))
            {
                DoneBaseGen = !baseGenIterateCounter.MoveNext();
                NodeStates.Remove(current);
                return;
            }

            Regions.Add(space);
            FillData.FillRegion(false, space);

            //Add the room data.
            NodeStates[current] = NodeState.TunnelJunction;
            NodeAreas.Add(current, space);
        }

        //Prepare for the next iteration.
        DoneBaseGen = !baseGenIterateCounter.MoveNext();
    }
Пример #8
0
    public FilledRegion Apply(FillData data)
    {
        //Start on either the relative top or bottom of the corridor.
        bool top = MathF.R.NextDouble() > 0.5;

        //Set up the plateau properties.
        bool horizontal = data.BeingFilled.Width > data.BeingFilled.Height;

        if (horizontal)
        {
            Generation.BeingFilled = data.BeingFilled;
        }
        else
        {
            Generation.BeingFilled = new Region(data.BeingFilled.Y,
                                                data.BeingFilled.X,
                                                data.BeingFilled.Height,
                                                data.BeingFilled.Width);
        }

        int spaceBetween = Generation.SpaceBetweenPlateaus;
        int border       = Generation.Border;
        int plateauWidth = Generation.PlateauWidth;
        int numbPlateaus = Generation.NumbPlateaus;

        //Fill the area. Also keep track of the free space above/below plateaus.
        List <Region> freeAreas = new List <Region>();

        for (int i = 0; i < numbPlateaus; ++i)
        {
            if (top)
            {
                if (horizontal)
                {
                    data.FillRegion(true, new Region(data.BeingFilled.Left + border + (i * (spaceBetween + plateauWidth)),
                                                     data.BeingFilled.Top,
                                                     plateauWidth - 1,
                                                     data.BeingFilled.Height - 1));
                    freeAreas.Add(new Region(data.BeingFilled.Left + border + (i * (spaceBetween + plateauWidth)),
                                             data.BeingFilled.Bottom,
                                             plateauWidth - 1, 0));
                }
                else
                {
                    data.FillRegion(true, new Region(data.BeingFilled.Left,
                                                     data.BeingFilled.Top + border + (i * (spaceBetween + plateauWidth)),
                                                     data.BeingFilled.Width - 1,
                                                     plateauWidth - 1));
                    freeAreas.Add(new Region(data.BeingFilled.Left + 1,
                                             data.BeingFilled.Top + border + (i * (spaceBetween + plateauWidth)) - 1,
                                             data.BeingFilled.Width - 2, 0));
                }
            }
            else
            {
                if (horizontal)
                {
                    data.FillRegion(true, new Region(data.BeingFilled.Left + border + (i * (spaceBetween + plateauWidth)),
                                                     data.BeingFilled.Top + 1,
                                                     plateauWidth - 1,
                                                     data.BeingFilled.Height - 1));
                    freeAreas.Add(new Region(data.BeingFilled.Left + border + (i * (spaceBetween + plateauWidth)),
                                             data.BeingFilled.Top,
                                             plateauWidth - 1, 0));
                }
                else
                {
                    data.FillRegion(true, new Region(data.BeingFilled.Left + 1,
                                                     data.BeingFilled.Top + border + (i * (spaceBetween + plateauWidth)),
                                                     data.BeingFilled.Width - 1,
                                                     plateauWidth - 1));
                    freeAreas.Add(new Region(data.BeingFilled.Left + 1,
                                             data.BeingFilled.Top + border + (i * (spaceBetween + plateauWidth)) - 1,
                                             data.BeingFilled.Width - 2, 0));
                }
            }

            top = !top;
        }

        Region area = data.BeingFilled;

        //Make room for any holes that the plateaus covered.
        //TODO: Instead of clearing out the bottom, just clear that column of plateau. Possibly also do this for other plateau patterns?
        foreach (Location l in data.HolesAlongPerimeter())
        {
            //Horizontal.
            if (area.Height < area.Width)
            {
                //The hole is covered if it is just below/above the region and the space above/below it (respectively) is filled.
                if ((area.Touches(l.Above, true, true, false) && data.GetMapAt(l.Above)) ||
                    (area.Touches(l.Below, true, true, false) && data.GetMapAt(l.Below)))
                {
                    //Make a little tunnel under the plateau.
                    int[] plateauSides = SteppedHallwayPattern.PlateauSides(l.X, numbPlateaus, plateauWidth, spaceBetween, border, area.Left, area.Right);

                    Region cleared;
                    if (l.Y - 1 == area.Bottom)
                    {
                        cleared = new Region(plateauSides[0], data.BeingFilled.Bottom, plateauWidth - 1, 0);
                    }
                    else
                    {
                        cleared = new Region(plateauSides[0], data.BeingFilled.Top, plateauWidth - 1, 0);
                    }

                    data.FillRegion(false, cleared);
                }
            }

            //Vertical
            else if ((area.Touches(l.Left, true, true, false) && data.GetMapAt(l.Left)) ||
                     (area.Touches(l.Right, true, true, false) && data.GetMapAt(l.Right)))
            {
                //Make a little tunnel under the plateau.
                int[] plateauSides = SteppedHallwayPattern.PlateauSides(l.Y, numbPlateaus, plateauWidth, spaceBetween, border, area.Top, area.Bottom);

                Region cleared;
                if (l.X - 1 == area.Right)
                {
                    cleared = new Region(data.BeingFilled.Right, plateauSides[0], 0, plateauWidth - 1);
                }
                else
                {
                    cleared = new Region(data.BeingFilled.Left, plateauSides[0], 0, plateauWidth - 1);
                }

                data.FillRegion(false, cleared);
            }
        }

        if (horizontal)
        {
            return(new ZipperRegion(data.BeingFilled, freeAreas));
        }
        else
        {
            return(new ZipperRegion(data.BeingFilled, new List <Region>()));
        }
    }
Пример #9
0
    public FilledRegion Apply(FillData data)
    {
        Region clearArea = new Region(data.BeingFilled.Center.Left.Above, data.BeingFilled.Center.Right.Below);

        //Fill the inner ring.
        //Move from each corner of the X to the center.
        Location counter;
        Location center = data.BeingFilled.Center;
        bool     moveHorizontally;
        bool     horizontalBias = data.BeingFilled.Width > data.BeingFilled.Height;

        //Fill in the center.
        data.FillRegion(true, new Region(clearArea.TopLeft.Above.Left, clearArea.BottomRight.Below.Right));
        for (int i = 0; i < 4; ++i)
        {
            //Get the point to start from.
            switch (i)
            {
            case 0:
                counter = data.BeingFilled.TopLeft.Right.Below;
                data.SetMapAt(counter, false);
                break;

            case 1:
                counter = data.BeingFilled.TopRight.Left.Below;
                data.SetMapAt(counter, false);
                break;

            case 2:
                counter = data.BeingFilled.BottomLeft.Right.Above;
                data.SetMapAt(counter, false);
                break;

            case 3:
                counter = data.BeingFilled.BottomRight.Left.Above;
                data.SetMapAt(counter, false);
                break;

            default: throw new InvalidOperationException();
            }

            //Clear a path to the center.
            while (!clearArea.Touches(counter, true, true, true))
            {
                //Get which direction to move in.
                float relativeDistX = Math.Abs(counter.X - center.X) / (float)data.BeingFilled.Width;
                float relativeDistY = Math.Abs(counter.Y - center.Y) / (float)data.BeingFilled.Height;
                if (relativeDistX > relativeDistY)
                {
                    moveHorizontally = true;
                }
                else if (relativeDistX < relativeDistY)
                {
                    moveHorizontally = false;
                }
                else
                {
                    moveHorizontally = horizontalBias;
                }

                //Move that direction, add the region, and fill part of the X after moving.
                if (moveHorizontally)
                {
                    int amount = Math.Sign(center.X - counter.X);

                    counter.X += amount;
                    data.SetMapAt(counter, false);

                    data.SetMapAt(new Location(counter.X + amount, counter.Y), true);
                    if (counter.Y > 1 && counter.Y < data.BeingFilled.Bottom - 1)
                    {
                        data.SetMapAt(new Location(counter.X, counter.Y + Math.Sign(counter.Y - center.Y)), true);
                    }
                }
                else
                {
                    int amount = Math.Sign(center.Y - counter.Y);

                    counter.Y += amount;
                    data.SetMapAt(counter, false);

                    data.SetMapAt(new Location(counter.X, counter.Y + amount), true);
                    if (counter.X > 1 && counter.X < data.BeingFilled.Right - 1)
                    {
                        data.SetMapAt(new Location(counter.X + Math.Sign(counter.X - center.X), counter.Y), true);
                    }
                }
            }

            //Keep the center clear.
            data.FillRegion(false, clearArea);
        }

        //Just to be safe, clear the perimeter at the end.
        data.FillPerimeter(false, data.BeingFilled);

        return(new XRegion(data.BeingFilled, data.Map));
    }