예제 #1
0
        private int SortByDistance(TerritoryPoint x, TerritoryPoint y)
        {
            float dist  = x.Distance;
            float dist2 = y.Distance;

            if (dist < dist2)
            {
                return(-1);
            }
            if (dist > dist2)
            {
                return(1);
            }

            return(0);
        }
예제 #2
0
        private void AddPointToRegion(TerritoryPoint newPoint)
        {
            int xx = newPoint.Position.X / RegionGridSize;
            int yy = newPoint.Position.Y / RegionGridSize;
            List <TerritoryPoint> list = null;

            if (!Regions.ContainsKey(new Point(xx, yy)))
            {
                list = new List <TerritoryPoint>();
                Regions[new Point(xx, yy)] = list;
            }
            else
            {
                list = Regions[new Point(xx, yy)];
            }


            list.Add(newPoint);
        }
예제 #3
0
        private void CreateProvinces(int numProvinces, Color testColor, List <Point> pts, int w, int h, LockBitmap provinces, bool bSea)
        {
            Regions.Clear();
            int numPoints = numProvinces * 50;

            if (bSea)
            {
                numPoints = numProvinces * 50;
            }

            #region GenerateRandomPoints

            var             points  = new List <TerritoryPoint>();
            var             usePts  = new HashSet <Point>(pts);
            List <Vector2f> vpoints = new List <Vector2f>();
            HashSet <Point> done    = new HashSet <Point>();
            // int numSeaPoints = numPoints / 140;
            int numSeaPoints = numPoints / 340;
            for (int n = 0; n < numPoints; n++)
            {
                Point newPoint  = Point.Empty;
                bool  duplicate = true;



                {
                    int nn = Rand.Next(pts.Count);
                    newPoint = pts[nn];

                    //   pts.RemoveAt(nn);

                    /*
                     *                  foreach (TerritoryPoint p in points)
                     *                      if (p.Position.X == newPoint.Position.X && p.Position.Y == newPoint.Position.Y)
                     *                      {
                     *                          duplicate = true;
                     *                          break;
                     *                      }*/
                }


                {
                    vpoints.Add(new Vector2f(newPoint.X, newPoint.Y));
                }
            }
            points.Clear();
            int vorStrength = 0;
            if (pts.Count > 150)
            {
                vorStrength += 2;
            }
            Voronoi v      = new Voronoi(vpoints, new Rectf(0, 0, w, h), 0);
            var     coords = v.SiteCoords();
            coords = coords.Where(c => usePts.Contains(new Point((int)c.x, (int)c.y))).ToList();
            for (int n = 0; n < coords.Count; n++)
            {
                TerritoryPoint newPoint  = null;
                bool           duplicate = true;

                newPoint = new TerritoryPoint((int)coords[n].x, (int)coords[n].y);

                if (newPoint != null)
                {
                    points.Add(newPoint);
                }
            }

            #endregion

            if (points.Count == 0)
            {
                points.Add(new TerritoryPoint()
                {
                    Position = usePts.OrderBy(o => Rand.Next(1000000)).First()
                });
            }

            #region GenerateTerritories

            var colours    = new List <Color>();
            var origPoints = new List <TerritoryPoint>(points);
            for (int n = 0; n < numProvinces; n++)
            {
                TerritoryPoint initialPoint = null;
                int            i            = 0;//rand.Next(points.Count());
                while (initialPoint == null)
                {
                    i            = Rand.Next(origPoints.Count());
                    initialPoint = origPoints[i];
                    if (initialPoint.Owner != -1)
                    {
                        initialPoint = null;
                    }
                    else
                    {
                        i = points.IndexOf(initialPoint);
                    }
                }
                bool requireSea = false;
                if (initialPoint.Sea)
                {
                    requireSea = true;
                }
                foreach (TerritoryPoint p in points)
                {
                    int dx = p.Position.X - initialPoint.Position.X;
                    int dy = p.Position.Y - initialPoint.Position.Y;
                    p.Distance = (float)Math.Sqrt(dx * dx + dy * dy);
                }

                points.Sort(SortByDistance);

                int c = 0;

                for (c = 0; c < Math.Min(maxPointsPerTerritory, points.Count); c++)
                {
                    if (points[c].Owner != -1)
                    {
                        break;
                    }
                }

                int owner = n + totalGeneratedProvinces;
                while ((colorMap[owner + 1].G == 0 && colorMap[owner + 1].B == 0) || colorMap[owner + 1] == Color.FromArgb(255, 69, 91, 186) || colorMap[owner + 1] == Color.FromArgb(255, 130, 158, 75) || colorProvinceMap.ContainsKey(colorMap[owner + 1]))
                {
                    owner = n + (++totalGeneratedProvinces);
                }


                // if (c >= minPointsPerTerritory)// || i >= seaStart)
                {
                    for (int c2 = 0; c2 < c; c2++)
                    {
                        if (points[c2].Owner == -1)
                        {
                            points[c2].Owner = owner;
                            origPoints.Remove(points[c2]);
                            AddPointToRegion(points[c2]);
                        }
                    }
                }

                totalGeneratedProvinces++;
            }

            #endregion

            #region GenerateBitmap
            foreach (var point in usePts)
            {
                int x = point.X;
                int y = point.Y;

                float          minDist = 1000000000;
                TerritoryPoint closest = null;

                List <TerritoryPoint> list = new List <TerritoryPoint>();

                bool found = false;

                int range = 1;
                while (!found)
                {
                    for (int xx = -range; xx <= range; xx++)
                    {
                        for (int yy = -range; yy <= range; yy++)
                        {
                            int gx = x / RegionGridSize;
                            int gy = y / RegionGridSize;

                            int tx = xx + gx;
                            int ty = yy + gy;

                            if (Regions.ContainsKey(new Point(tx, ty)))
                            {
                                var l = Regions[new Point(tx, ty)];

                                list.AddRange(l.Where(p => p.Owner != -1));
                            }
                        }
                    }

                    if (list.Count > 1)
                    {
                        break;
                    }

                    range++;
                }


                foreach (TerritoryPoint p in list)
                {
                    int dx = p.Position.X - x;
                    int dy = p.Position.Y - y;
                    p.Distance = (float)Math.Sqrt(dx * dx + dy * dy);

                    if (p.Owner != -1 && p.Distance < minDist)
                    {
                        closest = p;
                        minDist = p.Distance;
                    }
                }

                if (closest.Owner != -1)
                {
                    var col = colorMap[closest.Owner + 1];
                    if (!colorProvinceMap.ContainsKey(col))
                    {
                        var p = new Province();
                        p.Color = col;
                        p.isSea = bSea;
                        colorProvinceMap[col] = p;
                        this.provinces.Add(p);
                    }
                    colorProvinceMap[col].points.Add(new Point(x, y));
                    provinces.SetPixel(x, y, col);
                }
            }

            if (!bSea)
            {
                List <Point> choices = new List <Point>();
                var          pt      = usePts.OrderBy(o => Rand.Next(10000000));
                for (int nn = 0; nn < 2; nn++)
                {
                    foreach (var point in pt)
                    {
                        int x = point.X;
                        int y = point.Y;

                        Color use = provinces.GetPixel(x, y);
                        choices.Clear();
                        for (int xx = -1; xx <= 1; xx++)
                        {
                            for (int yy = -1; yy <= 1; yy++)
                            {
                                if (xx == 0 && yy == 0)
                                {
                                    continue;
                                }

                                Color test = provinces.GetPixel(x + xx, y + yy);
                                var   p    = new Point(x + xx, y + yy);
                                if (test != use)
                                {
                                    if (usePts.Contains(p))
                                    {
                                        choices.Add(p);
                                    }
                                }
                            }
                        }

                        if (choices.Count == 1)
                        {
                            Point p = choices[Rand.Next(choices.Count)];
                            colorProvinceMap[provinces.GetPixel(p.X, p.Y)].points.Remove(p);
                            provinces.SetPixel(p.X, p.Y, use);
                            colorProvinceMap[use].points.Add(p);
                        }
                    }
                }

                List <Color> choicesc = new List <Color>();
                foreach (var point in pt)
                {
                    int x = point.X;
                    int y = point.Y;

                    Color use = provinces.GetPixel(x, y);
                    choicesc.Clear();
                    for (int xx = -1; xx <= 1; xx++)
                    {
                        for (int yy = -1; yy <= 1; yy++)
                        {
                            if (xx == 0 && yy == 0)
                            {
                                continue;
                            }

                            Color test = provinces.GetPixel(x + xx, y + yy);
                            var   p    = new Point(x + xx, y + yy);
                            if (test != use)
                            {
                                if (usePts.Contains(p))
                                {
                                    choicesc.Add(test);
                                }
                            }
                        }
                    }

                    if (choices.Count >= 7)
                    {
                        Color p = choicesc[Rand.Next(choicesc.Count)];
                        colorProvinceMap[provinces.GetPixel(x, y)].points.Remove(new Point(x, y));
                        provinces.SetPixel(x, y, p);
                        colorProvinceMap[p].points.Add(new Point(x, y));
                    }
                }
            }

            #endregion
        }
예제 #4
0
        public void Generate(int numTerritories = 1500)
        {
            this.numTerritories = numTerritories;
            numPoints           = numTerritories * 50;

            #region GenerateRandomPoints
            this.generatedMap.TerrainMap.LockBits();
            ProvinceMap.LockBits();
            points = new List <TerritoryPoint>();

            int             tot     = (int)(((Width / RegionGridSize) * 0.4190996) * ((Height / RegionGridSize) * 0.4190996));
            List <Vector2f> vpoints = new List <Vector2f>();
            HashSet <Point> done    = new HashSet <Point>();
            // int numSeaPoints = numPoints / 140;
            int numSeaPoints = numPoints / 340;
            int seaStart     = numPoints - numSeaPoints;
            for (int n = 0; n < numPoints - numSeaPoints; n++)
            {
                TerritoryPoint newPoint  = null;
                bool           duplicate = true;


                while (duplicate)
                {
                    duplicate = false;

                    do
                    {
                        newPoint = new TerritoryPoint(Rand.Next(Width), Rand.Next(Height));
                    } while (done.Contains(newPoint.Position));


                    if (generatedMap.TerrainMap.GetPixel(newPoint.Position.X, newPoint.Position.Y) ==
                        Color.FromArgb(255, 69, 91, 186))
                    {
                        duplicate = true;
                        continue;
                    }

                    done.Add(newPoint.Position);

                    /*
                     *                  foreach (TerritoryPoint p in points)
                     *                      if (p.Position.X == newPoint.Position.X && p.Position.Y == newPoint.Position.Y)
                     *                      {
                     *                          duplicate = true;
                     *                          break;
                     *                      }*/
                }

                if (newPoint != null)
                {
                    vpoints.Add(new Vector2f(newPoint.Position.X, newPoint.Position.Y));
                    points.Add(newPoint);
                }
            }
            points.Clear();
            Voronoi v      = new Voronoi(vpoints, new Rectf(0, 0, Width, Height), 32);
            var     coords = v.SiteCoords();
            coords = coords.Where(c => generatedMap.TerrainMap.GetPixel((int)c.x, (int)c.y) != Color.FromArgb(255, 69, 91, 186)).ToList();
            for (int n = 0; n < coords.Count; n++)
            {
                TerritoryPoint newPoint  = null;
                bool           duplicate = true;

                newPoint = new TerritoryPoint((int)coords[n].x, (int)coords[n].y);

                if (newPoint != null)
                {
                    points.Add(newPoint);

                    int xx = newPoint.Position.X / RegionGridSize;
                    int yy = newPoint.Position.Y / RegionGridSize;
                    List <TerritoryPoint> list = null;
                    if (!Regions.ContainsKey(new Point(xx, yy)))
                    {
                        list = new List <TerritoryPoint>();
                        Regions[new Point(xx, yy)] = list;
                    }
                    else
                    {
                        list = Regions[new Point(xx, yy)];
                    }

                    newPoint.Sea = false;

                    list.Add(newPoint);
                }
            }

            #endregion


            #region GenerateTerritories
            List <TerritoryPoint> assigned   = new List <TerritoryPoint>();
            List <TerritoryPoint> unassigned = new List <TerritoryPoint>();

            colours = new List <Color>();
            var origPoints = new List <TerritoryPoint>(points);
            for (int n = 0; n < numTerritories; n++)
            {
                TerritoryPoint initialPoint = null;
                int            i            = 0;//rand.Next(points.Count());
                while (initialPoint == null)
                {
                    i            = Rand.Next(origPoints.Count());
                    initialPoint = origPoints[i];
                    if (initialPoint.Owner != -1)
                    {
                        initialPoint = null;
                    }
                    else
                    {
                        i = points.IndexOf(initialPoint);
                    }
                }
                bool requireSea = false;
                if (initialPoint.Sea)
                {
                    requireSea = true;
                }
                foreach (TerritoryPoint p in points)
                {
                    int dx = p.Position.X - initialPoint.Position.X;
                    int dy = p.Position.Y - initialPoint.Position.Y;
                    p.Distance = (float)Math.Sqrt(dx * dx + dy * dy);
                }

                points.Sort(SortByDistance);

                int c = 0;
                if (i >= seaStart)
                {
                    c = 1;
                }
                else
                {
                    for (c = 0; c < maxPointsPerTerritory; c++)
                    {
                        if (points[c].Owner != -1)
                        {
                            break;
                        }
                    }
                }

                if (c >= minPointsPerTerritory || i >= seaStart)
                {
                    for (int c2 = 0; c2 < c; c2++)
                    {
                        if (points[c2].Owner == -1)
                        {
                            points[c2].Owner = n;
                            origPoints.Remove(points[c2]);
                        }
                    }
                }
                else
                {
                    n--;
                }
            }

            #endregion

            #region GenerateBitmap
            int[]   provinceSize  = new int[numTerritories + 100];
            Color[] provinceColor = new Color[numTerritories + 100];
            for (int y = 0; y < Height; y++)
            {
                for (int x = 0; x < Width; x++)
                {
                    float          minDist = 1000000000;
                    TerritoryPoint closest = null;

                    if (generatedMap.TerrainMap.GetPixel(x, y) ==
                        Color.FromArgb(255, 69, 91, 186))
                    {
                        ProvinceMap.SetPixel(x, y, Color.White);

                        continue;
                    }
                    List <TerritoryPoint> list = new List <TerritoryPoint>();

                    bool found = false;

                    int range = 1;
                    while (!found)
                    {
                        for (int xx = -range; xx <= range; xx++)
                        {
                            for (int yy = -range; yy <= range; yy++)
                            {
                                int gx = x / RegionGridSize;
                                int gy = y / RegionGridSize;

                                int tx = xx + gx;
                                int ty = yy + gy;

                                if (Regions.ContainsKey(new Point(tx, ty)))
                                {
                                    var l = Regions[new Point(tx, ty)];

                                    list.AddRange(l.Where(p => p.Owner != -1));
                                }
                            }
                        }

                        if (list.Count > 1)
                        {
                            break;
                        }

                        range++;
                    }


                    foreach (TerritoryPoint p in list)
                    {
                        int dx = p.Position.X - x;
                        int dy = p.Position.Y - y;
                        p.Distance = (float)Math.Sqrt(dx * dx + dy * dy);

                        if (p.Owner != -1 && p.Distance < minDist)
                        {
                            closest = p;
                            minDist = p.Distance;
                        }
                    }

                    if (closest.Owner != -1)
                    {
                        provinceSize[closest.Owner]++;

                        var col = colorMap[closest.Owner + 1];
                        ProvinceMap.SetPixel(x, y, col);
                    }
                }
            }
            ProvinceMap.UnlockBits();

            ProvinceMap.Save24(Globals.MapOutputTotalDir + "map\\provincestest.bmp");
            #endregion
        }