Ejemplo n.º 1
0
        public IEnumerable <MapSection> GetNeighbors(MapSection center)
        {
            HashSet <MapSection> retval;

            if (!NeighborsOfSection.TryGetValue(center, out retval))
            {
                retval = new HashSet <MapSection>();

                foreach (var neighboringCell in center.Cells.SelectMany(cell => Grid.GetNeighbors(cell)))
                {
                    var sectionOfNeighbor = GetSectionOfCell(neighboringCell);

                    if (sectionOfNeighbor != center)
                    {
                        retval.Add(sectionOfNeighbor);
                    }
                }

                NeighborsOfSection[center] = retval;
            }

            return(retval);
        }
        private bool TryExpandChunk(
            List <MapSection> chunk, HashSet <MapSection> unassignedSections,
            GridPartition partition, IMapTemplate mapTemplate,
            ExpansionWeightFunction weightFunction, bool mustBeContiguous
            )
        {
            expansionCandidates.Clear();

            foreach (MapSection section in chunk)
            {
                nearbySections.Clear();

                sectionsWithinDistance.Clear();

                if (mustBeContiguous)
                {
                    foreach (var adjacentSection in partition.GetNeighbors(section))
                    {
                        if (unassignedSections.Contains(adjacentSection))
                        {
                            nearbySections.Add(adjacentSection);
                        }
                    }
                }
                else
                {
                    foreach (IHexCell nearbyCell in Grid.GetCellsInRadius(section.CentroidCell, mapTemplate.HomelandExpansionMaxCentroidSeparation))
                    {
                        MapSection sectionOfCell = partition.GetSectionOfCell(nearbyCell);

                        if (unassignedSections.Contains(sectionOfCell))
                        {
                            sectionsWithinDistance.Add(sectionOfCell);
                        }
                    }

                    var sectionsSurroundedByUnassigned = sectionsWithinDistance.Where(
                        nearby => partition.GetNeighbors(nearby).Count(neighbor => !unassignedSections.Contains(neighbor)) <= 0
                        );

                    if (sectionsSurroundedByUnassigned.Any())
                    {
                        foreach (var surroundedSection in sectionsSurroundedByUnassigned)
                        {
                            nearbySections.Add(surroundedSection);
                        }
                    }
                    else
                    {
                        foreach (var sectionWithin in sectionsWithinDistance)
                        {
                            nearbySections.Add(sectionWithin);
                        }
                    }
                }

                foreach (var nearby in nearbySections)
                {
                    expansionCandidates.Add(nearby);
                }
            }

            if (expansionCandidates.Count > 0)
            {
                var newSection = MapSectionRandomSampler.SampleElementsFromSet(
                    expansionCandidates, 1, section => weightFunction(section, chunk)
                    ).FirstOrDefault();

                if (newSection != null)
                {
                    unassignedSections.Remove(newSection);
                    chunk.Add(newSection);
                    return(true);
                }
            }

            return(false);
        }
        //Creates something akin to a Voronoi diagram of the cells,
        //using a process similiar to Lloyd's algorithm to make the
        //shapes more regular
        public GridPartition GetPartitionOfGrid(IHexGrid grid, IMapTemplate template)
        {
            float xMin = 0f, zMin = 0f;
            float xMax = (grid.CellCountX + grid.CellCountZ * 0.5f - grid.CellCountZ / 2) * RenderConfig.InnerRadius * 2f;
            float zMax = grid.CellCountZ * RenderConfig.OuterRadius * 1.5f;

            var randomPoints = new List <Vector3>();

            var regionOfPoint = new Dictionary <Vector3, MapSection>();

            for (int i = 0; i < template.VoronoiPointCount; i++)
            {
                var randomPoint = new Vector3(
                    UnityEngine.Random.Range(xMin, xMax),
                    0f,
                    UnityEngine.Random.Range(zMin, zMax)
                    );

                regionOfPoint[randomPoint] = new MapSection(grid);

                randomPoints.Add(randomPoint);
            }

            int iterationsLeft = template.VoronoiPartitionIterations;

            while (iterationsLeft > 0)
            {
                foreach (var cell in grid.Cells)
                {
                    Vector3 nearestPoint    = Vector3.zero;
                    float   shorestDistance = float.MaxValue;

                    foreach (var voronoiPoint in regionOfPoint.Keys)
                    {
                        float distanceTo = Vector3.Distance(cell.GridRelativePosition, voronoiPoint);

                        if (distanceTo < shorestDistance)
                        {
                            nearestPoint    = voronoiPoint;
                            shorestDistance = distanceTo;
                        }
                    }

                    if (regionOfPoint.ContainsKey(nearestPoint))
                    {
                        regionOfPoint[nearestPoint].AddCell(cell);
                    }
                }

                if (--iterationsLeft > 0)
                {
                    randomPoints.Clear();

                    var newRegionOfPoints = new Dictionary <Vector3, MapSection>();
                    foreach (var region in regionOfPoint.Values)
                    {
                        if (region.Cells.Count > 0)
                        {
                            randomPoints.Add(region.Centroid);

                            newRegionOfPoints[region.Centroid] = new MapSection(grid);
                        }
                    }

                    regionOfPoint = newRegionOfPoints;
                }
            }

            return(new GridPartition(regionOfPoint.Values, grid));
        }