예제 #1
0
        public static SimpleGameMap GenerateMirroredMap(EMapSize size, int numTeams = -1)
        {
            var rnd   = StrategyGame.Random;
            var iSize = (int)size;

            // Lock Large/Small maps to 2/4 teams for less variation
            if (size == EMapSize.Small)
            {
                numTeams = 2;
            }
            if (size == EMapSize.Large)
            {
                numTeams = 4;
            }
            if (numTeams == -1 && size == EMapSize.Normal)
            {
                numTeams = rnd.Next(1, 3) * 2;
            }

            var map = new SimpleGameMap($"{size} Random{numTeams}");

            // 0:hor/1:vert/2:hor&vert
            var mirrorType      = numTeams == 2 ? rnd.Next(3) : 2;
            var mirrorIncrement = mirrorType == 2 ? 4 : 2;

            // Determine num sectors based on size & num teams
            // small: (min = num teams*2, max = num teams*4)
            // normal: (min = num teams*3, max = num teams*5)
            // large: (min = num teams*4, max = num teams*6)
            var minNumSectors = numTeams * (iSize + 2);
            var maxNumSectors = numTeams * (iSize + 4);

            var xDim         = 7;
            var yDim         = 7;
            var nextSectorId = 0;

            // Add sectors in all positions
            for (var x = 0; x < xDim; x++)
            {
                for (var y = 0; y < yDim; y++)
                {
                    var s = new SimpleMapSector(nextSectorId++, new Point(x, y));
                    map.Sectors.Add(s);
                }
            }

            var maxChances = map.Sectors.Count * 3;
            var l          = 0;
            // Loop with a decreasing chance to remove sectors (mirrored)
            var removeChance = 0.97;

            while ((l++ < maxChances || map.Sectors.Count - mirrorIncrement > maxNumSectors) && map.Sectors.Count - mirrorIncrement > minNumSectors)
            {
                var s = StrategyGame.RandomItem(map.Sectors);
                if (rnd.NextDouble() < removeChance)
                {
                    removeChance -= 0.03;
                    map.Sectors.Remove(s);

                    // Horiz mirrored or both
                    if (mirrorType == 0 || mirrorType == 2)
                    {
                        var mX = MirrorDimension(xDim, s.MapPosition.X);
                        var mY = s.MapPosition.Y;

                        var s2 = map.Sectors.FirstOrDefault(_ => _.MapPosition.X == mX && _.MapPosition.Y == mY);
                        if (s2 != null)
                        {
                            map.Sectors.Remove(s2);
                        }
                    }

                    // Vert mirrored or both
                    if (mirrorType == 1 || mirrorType == 2)
                    {
                        var mX = s.MapPosition.X;
                        var mY = MirrorDimension(yDim, s.MapPosition.Y);

                        var s2 = map.Sectors.FirstOrDefault(_ => _.MapPosition.X == mX && _.MapPosition.Y == mY);
                        if (s2 != null)
                        {
                            map.Sectors.Remove(s2);
                        }
                    }

                    // Mirrored for both dimensions
                    if (mirrorType == 2)
                    {
                        var mX = MirrorDimension(xDim, s.MapPosition.X);
                        var mY = MirrorDimension(yDim, s.MapPosition.Y);

                        var s2 = map.Sectors.FirstOrDefault(_ => _.MapPosition.X == mX && _.MapPosition.Y == mY);
                        if (s2 != null)
                        {
                            map.Sectors.Remove(s2);
                        }
                    }
                }
            }

            // Fix SectorIDs after removing, they actually need to be indexes...
            l = 0;
            foreach (var s in map.Sectors)
            {
                s.Id = l++;
            }

            // Triangulate, loop with a small chance to remove an edges if that sector has > 2 connections
            var vertices = new List <Vertex <SimpleMapSector> >();

            foreach (var s in map.Sectors)
            {
                var p = s.MapPosition;
                vertices.Add(new Vertex <SimpleMapSector>(new Vector2(p.X, p.Y), s));
            }

            var delaunay = Delaunay2D <SimpleMapSector> .Triangulate(vertices);

            var mapEdges = new List <Edge <SimpleMapSector> >();

            foreach (var edge in delaunay.Edges)
            {
                if (!map.WormholeExists(edge.U.Item.Id, edge.V.Item.Id))
                {
                    map.WormholeIds.Add(new WormholeId(edge.U.Item.Id, edge.V.Item.Id));
                }
            }

            // Find Starting Positions (mirrored)
            var teamsAdded = 0;

            {
                var startPosMinX = 0;
                var startPosMinY = 0;

                var startPosMaxX = mirrorType == 1 ? xDim : xDim / 2 - 1;
                var startPosMaxY = mirrorType == 0 ? yDim : yDim / 2 - 1;

                var startSectors = map.Sectors
                                   .Where(_ => _.MapPosition.X >= startPosMinX && _.MapPosition.X <= startPosMaxX &&
                                          _.MapPosition.Y >= startPosMinY && _.MapPosition.Y <= startPosMaxY)
                                   .ToList();
                var s = StrategyGame.RandomItem(startSectors);

                // Safety check
                if (s == null)
                {
                    return(GenerateMirroredMap(size));
                }

                s.StartingSectorTeam = ++teamsAdded;

                // Mirrored for both dimensions
                if (mirrorType == 2)
                {
                    var mX = MirrorDimension(xDim, s.MapPosition.X);
                    var mY = MirrorDimension(yDim, s.MapPosition.Y);

                    var s2 = map.Sectors.FirstOrDefault(_ => _.MapPosition.X == mX && _.MapPosition.Y == mY);
                    if (s2 != null)
                    {
                        s2.StartingSectorTeam = ++teamsAdded;
                    }
                }

                // Horiz mirrored or both
                if (mirrorType == 0 || (mirrorType == 2 && numTeams > 2))
                {
                    var mX = MirrorDimension(xDim, s.MapPosition.X);
                    var mY = s.MapPosition.Y;

                    var s2 = map.Sectors.FirstOrDefault(_ => _.MapPosition.X == mX && _.MapPosition.Y == mY);
                    if (s2 != null)
                    {
                        s2.StartingSectorTeam = ++teamsAdded;
                    }
                }

                // Vert mirrored or both
                if (mirrorType == 1 || (mirrorType == 2 && numTeams > 2))
                {
                    var mX = s.MapPosition.X;
                    var mY = MirrorDimension(yDim, s.MapPosition.Y);

                    var s2 = map.Sectors.FirstOrDefault(_ => _.MapPosition.X == mX && _.MapPosition.Y == mY);
                    if (s2 != null)
                    {
                        s2.StartingSectorTeam = ++teamsAdded;
                    }
                }
            }

            // Final Checks
            if (teamsAdded < numTeams || !map.IsValid())
            {
                return(GenerateMirroredMap(size));
            }

            return(map);
        }
예제 #2
0
        public static SimpleGameMap GenerateSimpleMap(EMapSize size)
        {
            var rnd          = StrategyGame.Random;
            var map          = new SimpleGameMap($"{size} Random");
            var mirror       = (EMirrorType)rnd.Next(2);
            var maxX         = (mirror == EMirrorType.Horizontal ? MaxWidth / 2 : MaxWidth);
            var maxY         = (mirror == EMirrorType.Vertical ? MaxHeight / 2 : MaxHeight);
            var nextSectorId = 0;
            var numSectors   = 2 + (int)size;

            var s1 = new SimpleMapSector(nextSectorId++, new Point(rnd.Next(maxX), rnd.Next(maxY)));

            s1.StartingSectorTeam = 1;
            map.Sectors.Add(s1);

            var s2 = new SimpleMapSector(nextSectorId++, MirrorPoint(s1.MapPosition, mirror));

            s2.StartingSectorTeam = 2;
            map.Sectors.Add(s2);

            for (var i = 0; i < numSectors; i++)
            {
                var             attemptCount = 0;
                bool            pathClear;
                Point           p;
                SimpleMapSector linkedSector;
                var             checkSectors = Utils.Shuffle(map.Sectors, rnd);
                do
                {
                    p            = new Point(rnd.Next(maxX), rnd.Next(maxY));
                    pathClear    = false;
                    linkedSector = null;
                    attemptCount++;

                    var existingSector = map.Sectors.FirstOrDefault(_ => _.MapPosition == p);
                    if (existingSector != null)
                    {
                        continue;
                    }

                    // Checking if there is a clear path from this point to any other random sector, to add a wormhole
                    foreach (var s in checkSectors)
                    {
                        if (s.MapPosition == p)
                        {
                            continue;
                        }

                        pathClear = IsPathClear(map, p, s.MapPosition, 2f);
                        if (pathClear)
                        {
                            linkedSector = s;
                            break;
                        }
                    }
                } while (!pathClear && attemptCount < 40);

                if (pathClear)
                {
                    var newS = new SimpleMapSector(nextSectorId++, p);
                    map.Sectors.Add(newS);

                    if (!map.WormholeExists(newS.Id, linkedSector.Id))
                    {
                        map.WormholeIds.Add(new WormholeId(newS.Id, linkedSector.Id));
                    }

                    var newS2 = new SimpleMapSector(nextSectorId++, MirrorPoint(newS.MapPosition, mirror));
                    map.Sectors.Add(newS2);

                    // Add wormhole from the mirrored sector to equivilant
                    var m2            = MirrorPoint(linkedSector.MapPosition, mirror);
                    var linkedSector2 = map.Sectors.FirstOrDefault(_ => _.MapPosition == m2);
                    if (linkedSector2 != null)
                    {
                        if (!map.WormholeExists(newS2.Id, linkedSector2.Id))
                        {
                            map.WormholeIds.Add(new WormholeId(newS2.Id, linkedSector2.Id));
                        }
                    }
                }
            }

            var c = 0;

            foreach (var a in map.Sectors)
            {
                var rndSectors = Utils.Shuffle(map.Sectors, rnd);
                foreach (var b in rndSectors)
                {
                    if (a.StartingSectorTeam != 0 && b.StartingSectorTeam != 0)
                    {
                        continue;
                    }
                    if (map.WormholeExists(a.Id, b.Id))
                    {
                        continue;
                    }

                    if (c < 2 && IsPathClear(map, a.MapPosition, b.MapPosition, 2f))
                    {
                        map.WormholeIds.Add(new WormholeId(a.Id, b.Id));

                        // mirror wormhole!
                        var ma = MirrorPoint(a.MapPosition, mirror);
                        var mb = MirrorPoint(b.MapPosition, mirror);
                        var sa = map.Sectors.FirstOrDefault(_ => _.MapPosition == ma);
                        var sb = map.Sectors.FirstOrDefault(_ => _.MapPosition == mb);

                        if (sa != null && sb != null && !map.WormholeExists(sa.Id, sb.Id))
                        {
                            map.WormholeIds.Add(new WormholeId(sa.Id, sb.Id));
                        }
                        c++;
                        break;
                    }
                }
            }

            if (!map.IsValid())
            {
                return(GenerateSimpleMap(size));
            }

            return(map);
        }