예제 #1
0
        private GenChunkAddedStatus GenAddChunk(Random rand, Stack <GenEndPoint> endPoints, List <GenEndPoint> looseEnds, List <GenChunkRect> rects, ChunkTemplate[] templates, ref int area, int maxDepth = 0, bool first = false)
        {
            ChunkTemplate template;

            Chunk newChunk;
            List <GenEndPoint> endsToAdd;

            if (first)
            {
                template = templates[rand.Next(templates.Length)];
                newChunk = new Chunk(0, 0, template, this);
                Chunks.Add(newChunk);
                endsToAdd = new List <GenEndPoint>();
                for (int i = 0; i < 4; ++i)
                {
                    foreach (ChunkConnector connector in template.GetConnectors((ConnectorFace)i))
                    {
                        endsToAdd.Add(new GenEndPoint(newChunk, connector, 0));
                    }
                }

                while (endsToAdd.Count > 0)
                {
                    int index = rand.Next(endsToAdd.Count);
                    endPoints.Push(endsToAdd[index]);
                    endsToAdd.RemoveAt(index);
                }

                rects.Add(new GenChunkRect(newChunk));
                area += newChunk.Area;

                return(GenChunkAddedStatus.Added);
            }

            List <ChunkTemplate> validTemplates = new List <ChunkTemplate>();

            GenEndPoint endPoint = endPoints.Pop();

            ConnectorFace oppositeFace = (ConnectorFace)(((int)endPoint.Face + 2) % 4);

            foreach (ChunkTemplate temp in templates)
            {
                if (temp.GetConnectors(oppositeFace, endPoint.Size, endPoint.Skin).Length != 0)
                {
                    validTemplates.Add(temp);
                }
            }

            if (validTemplates.Count == 0)
            {
                endPoints.Push(endPoint);
                return(GenChunkAddedStatus.ImpossibleToAdd);
            }

            template = validTemplates[rand.Next(validTemplates.Count)];

            ChunkConnector[] cons = template.GetConnectors(oppositeFace, endPoint.Size, endPoint.Skin);

            if (cons.Length == 0)
            {
                endPoints.Push(endPoint);
                return(GenChunkAddedStatus.NotAdded);
            }

            ChunkConnector con = cons[rand.Next(cons.Length)];

            int x = endPoint.X - con.X;
            int y = endPoint.Y - con.Y;

            switch (endPoint.Face)
            {
            case ConnectorFace.Left:
                --x; break;

            case ConnectorFace.Top:
                --y; break;

            case ConnectorFace.Right:
                ++x; break;

            case ConnectorFace.Bottom:
                ++y; break;
            }

            GenChunkRect newRect = new GenChunkRect(x, y, template);

            foreach (GenChunkRect rect in rects)
            {
                if (rect.Intersects(newRect))
                {
                    endPoints.Push(endPoint);
                    return(GenChunkAddedStatus.NotAdded);
                }
            }

            newChunk = new Chunk(x, y, template, this);
            Chunks.Add(newChunk);
            endsToAdd = new List <GenEndPoint>();
            for (int i = 0; i < 4; ++i)
            {
                foreach (ChunkConnector connector in template.GetConnectors((ConnectorFace)i))
                {
                    if (connector.X != con.X || connector.Y != con.Y)
                    {
                        GenEndPoint end = new GenEndPoint(newChunk, connector, endPoint.Depth + 1);
                        if (maxDepth != 0 && endPoint.Depth >= maxDepth)
                        {
                            looseEnds.Add(end);
                        }
                        else
                        {
                            endsToAdd.Add(end);
                        }
                    }
                }
            }

            while (endsToAdd.Count > 0)
            {
                int index = rand.Next(endsToAdd.Count);
                endPoints.Push(endsToAdd[index]);
                endsToAdd.RemoveAt(index);
            }

            rects.Add(newRect);
            area += newChunk.Area;

            return(GenChunkAddedStatus.Added);
        }
예제 #2
0
        public void Generate(uint seed = 0)
        {
            Random rand = seed == 0 ? new Random() : new Random((int)seed);

            int area     = 0;
            int areaGoal = rand.Next(DungeonClass.AreaMin, DungeonClass.AreaMax);
            int maxDepth = (int)Math.Pow(areaGoal, 1 / 3) + 16;

            ChunkTemplate[]     templates = DungeonClass.ChunkTemplates;
            Stack <GenEndPoint> endPoints = new Stack <GenEndPoint>();
            List <GenEndPoint>  looseEnds = new List <GenEndPoint>();
            List <GenChunkRect> rects     = new List <GenChunkRect>();

            GenAddChunk(rand, endPoints, looseEnds, rects, templates, ref area, 0, true);

            int tries = 0;

            while (endPoints.Count > 0)
            {
                if (tries < 64 && area < areaGoal)
                {
                    switch (GenAddChunk(rand, endPoints, looseEnds, rects, templates, ref area, maxDepth))
                    {
                    case GenChunkAddedStatus.Added:
                        tries = 0; break;

                    case GenChunkAddedStatus.NotAdded:
                        ++tries; break;

                    case GenChunkAddedStatus.ImpossibleToAdd:
                        tries = 64; break;
                    }
                }
                else
                {
                    looseEnds.Add(endPoints.Pop());
                    tries = 0;
                }
            }

            for (int i = looseEnds.Count - 1; i >= 0; --i)
            {
                GenEndPoint end        = looseEnds[i];
                bool        horizontal = end.Face == ConnectorFace.Left || end.Face == ConnectorFace.Right;

                bool matchFound = false;

                for (int j = i - 1; j >= 0; --j)
                {
                    GenEndPoint match = looseEnds[j];

                    if (end.Size == match.Size && end.Skin == match.Skin &&
                        ((int)match.Face ^ (int)end.Face) == 0x2 &&
                        ((horizontal && end.Y == match.Y && (end.X + 1 == match.X || end.X == match.X + 1)) ||
                         (!horizontal && end.X == match.X && (end.Y + 1 == match.Y || end.Y == match.Y + 1))))
                    {
                        looseEnds.RemoveAt(i--);
                        looseEnds.RemoveAt(j);

                        matchFound = true;
                        break;
                    }
                }

                if (!matchFound)
                {
                    for (int j = 0; j < end.Size; ++j)
                    {
                        end.Chunk.GetTile(
                            end.X + (!horizontal ? j : 0),
                            end.Y + (horizontal ? j : 0)).IsWall = true;
                    }
                }
            }

            PostWorldInitialize();

            myHasGenerated = true;
        }