Ejemplo n.º 1
0
    public static void GenerateWorld(bool teamplay, bool cluster_water, bool nat_starts, List <PlayerData> picks, NodeLayoutData layout)
    {
        m_nations       = picks;
        m_nat_starts    = nat_starts;
        m_teamplay      = teamplay;
        m_cluster_water = cluster_water;
        m_layout        = layout;

        generate_nodes();
        generate_connections();
        calculate_triangles();
        generate_caprings();
        generate_seas();
        generate_lakes();
        assign_water_terrain();

        var valid      = m_nodes.Where(x => !x.HasNation && !x.IsAssignedTerrain && !x.ProvinceData.IsWater).ToList();
        var valid_conn = m_connections.Where(x => !x.IsCap && !x.IsInsideCapRing && !x.IsTouchingSea).ToList();

        if (!m_nat_starts)
        {
            valid = m_nodes.Where(x => !x.ProvinceData.IsWater).ToList();
        }

        generate_swamps(valid);
        generate_misc(valid);
        generate_rivers(valid_conn);
        generate_cliffs(valid_conn);
        generate_roads(valid_conn);
        generate_farms(valid);
        generate_sized(valid);
        generate_thrones();
        cleanup_connections();
    }
Ejemplo n.º 2
0
    private void MoveCameraForGeneration(NodeLayoutData layout)
    {
        var main_cam = Camera.main;
        var p        = main_cam.transform.position;

        p.x = layout.X;
        p.y = layout.Y * 0.5f;
        main_cam.transform.position = p;
    }
Ejemplo n.º 3
0
    private static void create_team_nodes(NodeLayoutData nl, List <PlayerData> nats)
    {
        for (var x = 0; x < nl.X; x++) // create all nodes first
        {
            for (var y = 0; y < nl.Y; y++)
            {
                var node = new Node(x, y, new ProvinceData());

                if ((x == 0 && y == 0) || (x == nl.X - 1 && y == nl.Y - 1))
                {
                    node.SetWrapCorner(true);
                }

                m_nodes.Add(node);
            }
        }

        var spawns = new List <SpawnPoint>();

        spawns.AddRange(nl.Spawns.Where(x => x.SpawnType == SpawnType.PLAYER));
        spawns = spawns.OrderBy(x => x.Y).ThenBy(x => x.X).ToList();

        while (nats.Any())
        {
            var pd = nats[0];

            var all = new List <PlayerData>();
            all.AddRange(nats.Where(x => x.TeamNum == pd.TeamNum));

            nats.RemoveAll(x => x.TeamNum == pd.TeamNum);

            var anchor  = spawns[0];
            var ordered = spawns.OrderBy(x => x.DistanceTo(anchor)).ToList();

            var i = 0;

            foreach (var p in all)
            {
                var s = ordered[i];
                spawns.Remove(s);

                var n = m_nodes.FirstOrDefault(x => x.X == s.X && x.Y == s.Y);
                n.SetPlayerInfo(p, new ProvinceData(p.NationData.CapTerrain));
                n.SetAssignedTerrain(true);

                m_starts.Add(n);

                i++;
            }
        }
    }
Ejemplo n.º 4
0
    private IEnumerator do_generate(NodeLayoutData layout) // pipeline for initial generation of all nodes and stuff
    {
        foreach (var obj in HideableButtons)
        {
            obj.SetActive(false);
        }

        if (layout == null)
        {
            layout = m_layouts.Layouts.FirstOrDefault(x => x.NumPlayers == m_player_count);
        }

        m_season = Season.SUMMER;

        // create the conceptual nodes and connections first
        WorldGenerator.GenerateWorld(m_teamplay, m_cluster_water, NatStarts.isOn, m_nations, layout);
        var conns = WorldGenerator.GetConnections();
        var nodes = WorldGenerator.GetNodes();

        // generate the unity objects using the conceptual nodes
        var mgr = GetComponent <ElementManager>();

        // position and resize the cameras
        var campos = new Vector3(layout.X * 0.5f * mgr.X - mgr.X, layout.Y * 0.5f * mgr.Y - mgr.Y, -10);

        CaptureCamera.transform.position = campos;

        var ortho = (mgr.Y * layout.Y * 100) / 100f / 2f;

        CaptureCamera.orthographicSize = ortho;

        yield return(StartCoroutine(mgr.GenerateElements(nodes, conns, layout)));

        set_province_names(mgr.Provinces);

        ProvinceManager.s_province_manager.SetLayout(layout);
        ConnectionManager.s_connection_manager.SetLayout(layout);
        Camera.main.transform.position = campos + new Vector3(500f, 0f, 0f);

        foreach (var obj in HideableButtons)
        {
            obj.SetActive(true);
        }
    }
Ejemplo n.º 5
0
    public void CalcAdjacent(List <Connection> conns, NodeLayoutData nl)
    {
        if (Diagonal)
        {
            var diags = Node1.ConnectedNodes.Where(x => Node2.ConnectedNodes.Contains(x)).ToList();
            diags.Add(Node1);
            diags.Add(Node2);

            Adjacent = conns.Where(x => diags.Contains(x.Node1) && diags.Contains(x.Node2) && x != this).ToList();
        }
        else
        {
            var diags = Node1.ConnectedNodes.Where(x => Node2.ConnectedNodes.Contains(x)).ToList();
            diags.Add(Node1);
            diags.Add(Node2);

            Adjacent = conns.Where(x => diags.Contains(x.Node1) && diags.Contains(x.Node2) && x.Diagonal && x != this).ToList();
        }
    }
Ejemplo n.º 6
0
 public abstract void Regenerate(List <ProvinceMarker> provs, List <ConnectionMarker> conns, NodeLayoutData layout);
Ejemplo n.º 7
0
 public abstract IEnumerator Generate(List <ProvinceMarker> provs, List <ConnectionMarker> conns, NodeLayoutData layout);
Ejemplo n.º 8
0
    private static void create_basic_nodes(NodeLayoutData nl, List <PlayerData> nats, List <PlayerData> water)
    {
        for (var x = 0; x < nl.X; x++) // create all nodes first
        {
            for (var y = 0; y < nl.Y; y++)
            {
                var node = new Node(x, y, new ProvinceData());

                if ((x == 0 && y == 0) || (x == nl.X - 1 && y == nl.Y - 1))
                {
                    node.SetWrapCorner(true);
                }

                m_nodes.Add(node);

                if (nl.HasSpawn(x, y, SpawnType.PLAYER))
                {
                    node.ProvinceData.AddTerrainFlag(Terrain.START);
                    m_starts.Add(node);
                }
            }
        }

        if (m_cluster_water) // put water nations close together if the user has this option ticked
        {
            var starts = m_nodes.Where(x => x.ProvinceData.Terrain.IsFlagSet(Terrain.START)).ToList();

            var start = starts.GetRandom();
            var nodes = get_closest_nodes(start);

            foreach (var d in water)
            {
                var n = nodes[0];
                nodes.Remove(n);
                starts.Remove(n);

                n.SetPlayerInfo(d, new ProvinceData(d.NationData.CapTerrain));
                n.SetAssignedTerrain(true);
            }

            foreach (var d in nats)
            {
                var n = starts.GetRandom();
                starts.Remove(n);

                n.SetPlayerInfo(d, new ProvinceData(d.NationData.CapTerrain));
                n.SetAssignedTerrain(true);
            }
        }
        else
        {
            nats.AddRange(water);

            foreach (var n in m_nodes.Where(x => x.ProvinceData.Terrain.IsFlagSet(Terrain.START)))
            {
                var d = nats.GetRandom();
                nats.Remove(d);

                n.SetPlayerInfo(d, new ProvinceData(d.NationData.CapTerrain));
                n.SetAssignedTerrain(true);
            }
        }
    }
Ejemplo n.º 9
0
 public void SetLayout(NodeLayoutData layout)
 {
     m_layout = layout;
 }
Ejemplo n.º 10
0
    public static void GenerateText(string mapname, NodeLayoutData layout, ElementManager mgr, List <PlayerData> nations, Vector2 mins, Vector2 maxs, List <ProvinceMarker> provs, bool teamplay, int[] province_ids)
    {
        var data_folder = Application.dataPath;
        var folder      = data_folder + "/Export/";
        var path        = folder + mapname + ".map";

        if (!Directory.Exists(folder))
        {
            Directory.CreateDirectory(folder);
        }

        if (File.Exists(path))
        {
            File.Delete(path);
        }

        var x = Mathf.RoundToInt(layout.X * mgr.X * 100);
        var y = Mathf.RoundToInt(layout.Y * mgr.Y * 100);

        provs = provs.Where(p => !p.IsDummy).ToList();
        provs = provs.OrderBy(p => p.ProvinceNumber).ToList();

        using (var fs = File.Create(path))
        {
            var dom_col_r = (int)(GenerationManager.s_generation_manager.OverlayColor.r * 255f);
            var dom_col_g = (int)(GenerationManager.s_generation_manager.OverlayColor.g * 255f);
            var dom_col_b = (int)(GenerationManager.s_generation_manager.OverlayColor.b * 255f);
            var dom_col_a = (int)(GenerationManager.s_generation_manager.OverlayColor.a * 255f);

            var map_stats = string.Format("Player count: {0}, Throne count: {1}, Province count: {2}, Provinces per player: {3}",
                                          layout.NumPlayers,
                                          layout.NumThrones,
                                          layout.TotalProvinces,
                                          (float)(layout.TotalProvinces / layout.NumPlayers));

            write(fs, "-- Basic Map Information");
            write(fs, "#dom2title " + mapname);
            write(fs, "#imagefile " + mapname + ".tga");
            write(fs, "#winterimagefile " + mapname + "_winter.tga");
            write(fs, "#mapsize " + x + " " + y);
            write(fs, "#wraparound");
            write(fs, "#maptextcol 0.2 0.0 0.0 1.0");
            write(fs, $"#mapdomcol {dom_col_r} {dom_col_g} {dom_col_b} {dom_col_a}");
            write(fs, "#description \"[Generated by MapNuke]  " + map_stats + "\"");

            write(fs, "\n-- Province Custom Name Data");

            foreach (var m in provs)
            {
                if (m.Node.ProvinceData.CustomName != string.Empty)
                {
                    write(fs, "#landname " + m.ProvinceNumber + " \"" + m.Node.ProvinceData.CustomName + "\"");
                }
            }

            write(fs, "\n-- Player Start Location Data");

            foreach (var d in nations)
            {
                if (d.NationData.ID > -1)
                {
                    write(fs, "#allowedplayer " + d.NationData.ID);
                }
            }

            foreach (var m in provs)
            {
                if (m.Node.HasNation)
                {
                    if (m.Node.Nation.NationData.ID == -1)
                    {
                        if (teamplay)
                        {
                            write(fs, "#teamstart " + m.ProvinceNumber + " " + m.Node.Nation.TeamNum);
                        }
                        else
                        {
                            write(fs, "#start " + m.ProvinceNumber);
                        }
                    }
                    else
                    {
                        write(fs, "#specstart " + m.Node.Nation.NationData.ID + " " + m.ProvinceNumber);
                    }
                }
            }

            write(fs, "\n-- Province Terrain Data");

            foreach (var m in provs)
            {
                var terr = m.Node.ProvinceData.Terrain;

                if (GeneratorSettings.s_generator_settings.UseClassicMountains && !terr.IsFlagSet(Terrain.MOUNTAINS) && mountain_count(m) >= 1f)
                {
                    terr |= Terrain.MOUNTAINS;
                }

                if (m.Node.Connections.Any(c => c.ConnectionType == ConnectionType.RIVER || c.ConnectionType == ConnectionType.SHALLOWRIVER))
                {
                    terr |= Terrain.FRESHWATER;
                }

                if (m.Node.HasNation)
                {
                    terr |= Terrain.START;
                }

                write(fs, "#terrain " + m.ProvinceNumber + " " + (int)terr);
            }

            write(fs, "\n-- Province Neighbour Data");

            foreach (var m in provs)
            {
                foreach (var c in m.Node.Connections)
                {
                    write(fs, "#neighbour " + c.Node1.ID + " " + c.Node2.ID);

                    if (c.ConnectionType != ConnectionType.STANDARD && c.ConnectionType != ConnectionType.SHALLOWRIVER)
                    {
                        write(fs, "#neighbourspec " + c.Node1.ID + " " + c.Node2.ID + " " + (int)c.ConnectionType);
                    }
                }
            }

            write(fs, "\n-- Province Border Data");

            {
                var cur = 0;
                for (var cur_y = 0; cur_y < y; ++cur_y)
                {
                    var cur_id = 0;
                    var cur_px = 0;
                    var cur_x  = 0;
                    for (; cur_x < x; ++cur_x)
                    {
                        var nex_id = province_ids[cur];
                        if (nex_id != cur_id)
                        {
                            if (cur_id != 0)
                            {
                                write(fs, "#pb " + (cur_x - cur_px) + " " + cur_y + " " + cur_px + " " + cur_id);
                            }
                            cur_px = 0;
                        }
                        cur_id = nex_id;
                        cur_px++;
                        cur++;
                    }
                    if (cur_id != 0)
                    {
                        write(fs, "#pb " + (cur_x - cur_px) + " " + cur_y + " " + cur_px + " " + cur_id);
                    }
                }
            }

            fs.Close();
        }
    }
Ejemplo n.º 11
0
    public IEnumerator GenerateElements(List <ProvinceMarker> provs, List <ConnectionMarker> conns, NodeLayoutData layout, float x, float y)
    {
        setup_cam(x, y);

        return(m_art.Generate(provs, conns, layout));// todo: allow the user to pick which art style?
    }
Ejemplo n.º 12
0
 public void RegenerateElements(List <ProvinceMarker> provs, List <ConnectionMarker> conns, NodeLayoutData layout) // totally regen these provinces and their connections
 {
     m_art.Regenerate(provs, conns, layout);
 }
Ejemplo n.º 13
0
 public void RegenerateElements(List <ProvinceMarker> provs, List <ConnectionMarker> conns, NodeLayoutData layout)
 {
     Resources.UnloadUnusedAssets();
     StartCoroutine(perform_async(() => do_regen(provs, conns, layout)));
 }
Ejemplo n.º 14
0
 private void do_regen(List <ProvinceMarker> provs, List <ConnectionMarker> conns, NodeLayoutData layout)
 {
     ArtManager.s_art_manager.RegenerateElements(provs, conns, layout);
 }
Ejemplo n.º 15
0
    public override IEnumerator Generate(List <ProvinceMarker> provs, List <ConnectionMarker> conns, NodeLayoutData layout)
    {
        var result = new List <GameObject>();

        m_all_conns = conns;
        m_all_provs = provs;

        calc_triangles(conns);

        foreach (var cm in conns)
        {
            cm.CreatePolyBorder();
            cm.ClearWrapMeshes();
            cm.RecalculatePoly();
            if (Util.ShouldYield())
            {
                yield return(null);
            }
        }

        foreach (var pm in provs)
        {
            pm.UpdateLabel();
            pm.RecalculatePoly();
            pm.ConstructPoly();
            pm.ClearWrapMeshes();
            result.AddRange(pm.CreateWrapMeshes());
            if (Util.ShouldYield())
            {
                yield return(null);
            }
        }

        m_all_sprites = new List <SpriteMarker>();

        foreach (var cm in conns)
        {
            m_all_sprites.AddRange(cm.PlaceSprites());
            if (Util.ShouldYield())
            {
                yield return(null);
            }
        }

        foreach (var pm in provs)
        {
            foreach (var x in pm.CalculateSpritePoints())
            {
                yield return(x);
            }
            m_all_sprites.AddRange(pm.PlaceSprites());
            if (Util.ShouldYield())
            {
                yield return(null);
            }
        }

        foreach (var m in m_all_sprites)
        {
            result.Add(m.gameObject);
            if (Util.ShouldYield())
            {
                yield return(null);
            }
        }

        ElementManager.s_element_manager.AddGeneratedObjects(result);
        CaptureCam.s_capture_cam.Render();
    }
Ejemplo n.º 16
0
    public override void Regenerate(List <ProvinceMarker> provs, List <ConnectionMarker> conns, NodeLayoutData layout)
    {
        var result = new List <GameObject>();
        var linked = new List <ConnectionMarker>();

        foreach (var m in conns)
        {
            if (m.LinkedConnection != null)
            {
                linked.Add(m.LinkedConnection);
            }
        }

        conns.AddRange(linked);

        foreach (var m in m_all_conns)
        {
            m.ClearTriangles();
        }

        /*foreach (var pm in provs)
         * {
         *  pm.UpdateConnections();
         * }*/

        calc_triangles(m_all_conns);

        foreach (var cm in conns)
        {
            cm.CreatePolyBorder();
            cm.ClearWrapMeshes();
            cm.RecalculatePoly();
        }

        foreach (var pm in provs)
        {
            pm.UpdateLabel();
            pm.RecalculatePoly();
            pm.ConstructPoly();
            pm.ClearWrapMeshes();
            result.AddRange(pm.CreateWrapMeshes()); // also create connection wrap meshes
        }

        var bad = provs.Where(x => x.NeedsRegen).ToList();
        var add = new List <ProvinceMarker>();

        if (bad.Any())
        {
            Debug.LogError(bad.Count + " provinces have invalid PolyBorders. Regenerating additional provinces.");

            foreach (var b in bad)
            {
                foreach (var adj in b.ConnectedProvinces)
                {
                    if (provs.Contains(adj))
                    {
                        continue;
                    }

                    if (adj.IsDummy)
                    {
                        add.AddRange(adj.LinkedProvinces);

                        if (adj.LinkedProvinces[0].LinkedProvinces.Count > 1)
                        {
                            foreach (var link in adj.LinkedProvinces[0].LinkedProvinces) // 3 dummies
                            {
                                add.AddRange(adj.ConnectedProvinces);
                            }
                        }
                        else
                        {
                            add.AddRange(adj.LinkedProvinces[0].ConnectedProvinces);
                        }
                    }
                    else
                    {
                        add.Add(adj);

                        if (adj.LinkedProvinces != null && adj.LinkedProvinces.Any())
                        {
                            foreach (var link in adj.LinkedProvinces)
                            {
                                add.AddRange(link.ConnectedProvinces);
                            }
                        }
                    }

                    if (!add.Contains(adj))
                    {
                        add.Add(adj);
                    }
                }

                if (b.LinkedProvinces != null && b.LinkedProvinces.Any())
                {
                    foreach (var link in b.LinkedProvinces)
                    {
                        add.AddRange(link.ConnectedProvinces);
                    }
                }
            }

            foreach (var pm in add)
            {
                foreach (var m in pm.Connections)
                {
                    if (!conns.Contains(m) && ((provs.Contains(m.Prov1) || add.Contains(m.Prov1)) && (provs.Contains(m.Prov2) || add.Contains(m.Prov2))))
                    {
                        conns.Add(m);
                    }
                }
            }

            foreach (var cm in conns)
            {
                cm.CreatePolyBorder();
                cm.ClearWrapMeshes();
                cm.RecalculatePoly();
            }

            foreach (var pm in add)
            {
                pm.UpdateLabel();
                pm.RecalculatePoly();
                pm.ConstructPoly();
                pm.ClearWrapMeshes();
                result.AddRange(pm.CreateWrapMeshes()); // also create connection wrap meshes
            }

            foreach (var pm in provs)
            {
                pm.UpdateLabel();
                pm.RecalculatePoly();
                pm.ConstructPoly();
                pm.ClearWrapMeshes();
                result.AddRange(pm.CreateWrapMeshes()); // also create connection wrap meshes
            }
        }

        foreach (var cm in conns)
        {
            m_all_sprites.AddRange(cm.PlaceSprites());
        }

        foreach (var pm in provs)
        {
            foreach (var unused in pm.CalculateSpritePoints())
            {
            }
            m_all_sprites.AddRange(pm.PlaceSprites());
        }

        var all = new List <SpriteMarker>();

        foreach (var m in m_all_sprites)
        {
            if (m != null && m.gameObject != null)
            {
                all.Add(m);
                result.Add(m.gameObject);
            }
        }

        m_all_sprites = all;

        ElementManager.s_element_manager.AddGeneratedObjects(result);
        CaptureCam.s_capture_cam.Render();
    }
Ejemplo n.º 17
0
    public IEnumerator GenerateElements(List <Node> nodes, List <Connection> conns, NodeLayoutData layout)
    {
        if (m_generated != null)
        {
            foreach (var o in m_generated)
            {
                GameObject.Destroy(o);
            }

            m_generated = new List <GameObject>();
        }

        m_generated   = new List <GameObject>();
        m_provinces   = new List <ProvinceMarker>();
        m_connections = new List <ConnectionMarker>();

        var min       = Vector3.zero - new Vector3(X, Y);
        var max       = new Vector3(X * (layout.X - 1), Y * (layout.Y - 1));
        var min_top   = new Vector3(min.x, max.y);
        var max_bot   = new Vector3(max.x, min.y);
        var dist_up   = Vector3.Distance(min, min_top);
        var dist_horz = Vector3.Distance(min, max_bot);

        MapBorder.SetBorders(min, max);

        foreach (var n in nodes) // create basic provinces
        {
            var pos     = new Vector3(n.X * X, n.Y * Y, 0);
            var randpos = pos - new Vector3(m_edge_tolerance * X + (UnityEngine.Random.Range(0f, X - (m_edge_tolerance * 2 * X))), m_edge_tolerance * Y + (UnityEngine.Random.Range(0f, Y - (m_edge_tolerance * 2 * Y))));

            var marker_obj = GameObject.Instantiate(ProvinceMarker);
            marker_obj.transform.position = randpos;

            var province_marker = marker_obj.GetComponent <ProvinceMarker>();
            var widget_obj      = GameObject.Instantiate(ProvinceWidget);
            var widget          = widget_obj.GetComponent <ProvinceWidget>();

            widget.SetParent(province_marker);
            province_marker.SetWidget(widget);
            province_marker.UpdateArtStyle();
            province_marker.SetNode(n);

            m_provinces.Add(province_marker);
            m_generated.Add(marker_obj);
            m_generated.Add(widget_obj);

            if (Util.ShouldYield())
            {
                yield return(null);
            }
        }

        adjust_province_positions();

        foreach (var m in m_provinces)
        {
            m.OffsetWidget(); // properly position widget
            if (Util.ShouldYield())
            {
                yield return(null);
            }
        }

        var dummies = new List <ProvinceMarker>();

        foreach (var m in m_provinces) // create dummy provinces
        {
            if (m.Node.X == 0 && m.Node.Y == 0)
            {
                var pos_up    = new Vector3(m.transform.position.x, m.transform.position.y + dist_up);
                var pos_right = new Vector3(m.transform.position.x + dist_horz, m.transform.position.y);
                var pos_diag  = new Vector3(m.transform.position.x + dist_horz, m.transform.position.y + dist_up);

                var g1 = GameObject.Instantiate(ProvinceMarker);
                g1.transform.position = pos_up;

                var m1 = g1.GetComponent <ProvinceMarker>();
                m1.UpdateArtStyle();
                m1.AddLinkedProvince(m);
                m.AddLinkedProvince(m1);
                m1.SetDummy(true, m);

                var g2 = GameObject.Instantiate(ProvinceMarker);
                g2.transform.position = pos_right;

                var m2 = g2.GetComponent <ProvinceMarker>();
                m2.UpdateArtStyle();
                m2.AddLinkedProvince(m);
                m.AddLinkedProvince(m2);
                m2.SetDummy(true, m);

                var g3 = GameObject.Instantiate(ProvinceMarker);
                g3.transform.position = pos_diag;

                var m3 = g3.GetComponent <ProvinceMarker>();
                m3.UpdateArtStyle();
                m3.AddLinkedProvince(m);
                m.AddLinkedProvince(m3);
                m3.SetDummy(true, m);

                dummies.Add(m1);
                dummies.Add(m2);
                dummies.Add(m3);
                m_generated.Add(g1);
                m_generated.Add(g2);
                m_generated.Add(g3);
            }
            else if (m.Node.X == 0)
            {
                var pos_right = new Vector3(m.transform.position.x + dist_horz, m.transform.position.y);

                var g1 = GameObject.Instantiate(ProvinceMarker);
                g1.transform.position = pos_right;

                var m1 = g1.GetComponent <ProvinceMarker>();
                m1.UpdateArtStyle();
                m1.AddLinkedProvince(m);
                m.AddLinkedProvince(m1);
                m1.SetDummy(true, m);

                dummies.Add(m1);
                m_generated.Add(g1);
            }
            else if (m.Node.Y == 0)
            {
                var pos_up = new Vector3(m.transform.position.x, m.transform.position.y + dist_up);

                var g1 = GameObject.Instantiate(ProvinceMarker);
                g1.transform.position = pos_up;

                var m1 = g1.GetComponent <ProvinceMarker>();
                m1.UpdateArtStyle();
                m1.AddLinkedProvince(m);
                m.AddLinkedProvince(m1);
                m1.SetDummy(true, m);

                dummies.Add(m1);
                m_generated.Add(g1);
            }

            if (Util.ShouldYield())
            {
                yield return(null);
            }
        }

        m_provinces.AddRange(dummies);
        var real_province  = new Dictionary <Node, ProvinceMarker>();
        var dummy_province = new Dictionary <Node, List <ProvinceMarker> >();

        foreach (var pm in m_provinces)
        {
            if (!dummy_province.ContainsKey(pm.Node))
            {
                dummy_province[pm.Node] = new List <ProvinceMarker> {
                }
            }
            ;
            if (pm.IsDummy)
            {
                dummy_province[pm.Node].Add(pm);
            }
            else
            {
                real_province[pm.Node] = pm;
            }
        }

        foreach (var c in conns) // create connection markers
        {
            var prov1 = real_province[c.Node1];
            var prov2 = real_province[c.Node2];
            var pd1   = dummy_province[c.Node1];
            var pd2   = dummy_province[c.Node2];

            if (pd1.Any() || pd2.Any())     // edge case
            {
                if (pd1.Any() && pd2.Any()) // both have an edge clone
                {
                    if (pd1.Any(x => x.Node.X == 0 && x.Node.Y == 0))
                    {
                        pd1.Add(prov1);
                        pd1   = pd1.OrderBy(x => Vector3.Distance(x.transform.position, prov2.transform.position)).ToList();
                        prov1 = pd1[0];
                    }
                    else if (pd2.Any(x => x.Node.X == 0 && x.Node.Y == 0))
                    {
                        pd2.Add(prov2);
                        pd2   = pd2.OrderBy(x => Vector3.Distance(x.transform.position, prov1.transform.position)).ToList();
                        prov2 = pd2[0];
                    }
                    else if (pd1.Any(x => x.Node.X == layout.X - 1 || x.Node.Y == layout.Y - 1))
                    {
                        pd2.Add(prov2);
                        pd2   = pd2.OrderBy(x => Vector3.Distance(x.transform.position, prov1.transform.position)).ToList();
                        prov2 = pd2[0];
                    }
                    else if (pd2.Any(x => x.Node.X == layout.X - 1 || x.Node.Y == layout.Y - 1))
                    {
                        pd1.Add(prov1);
                        pd1   = pd1.OrderBy(x => Vector3.Distance(x.transform.position, prov2.transform.position)).ToList();
                        prov1 = pd1[0];
                    }
                }
                else if (pd1.Any())
                {
                    pd1.Add(prov1);
                    pd1   = pd1.OrderBy(x => Vector3.Distance(x.transform.position, prov2.transform.position)).ToList();
                    prov1 = pd1[0];
                }
                else
                {
                    pd2.Add(prov2);
                    pd2   = pd2.OrderBy(x => Vector3.Distance(x.transform.position, prov1.transform.position)).ToList();
                    prov2 = pd2[0];
                }

                var g  = GameObject.Instantiate(ConnectionMarker);
                var m  = g.GetComponent <ConnectionMarker>();
                var p1 = prov1.transform.position;
                var p2 = prov2.transform.position;

                prov1.AddConnection(m);
                prov2.AddConnection(m);

                var center = get_weighted_center(p1, p2, prov1.Node, prov2.Node);
                g.transform.position = center;

                var w = GameObject.Instantiate(ConnectionWidget);
                w.transform.position = center + new Vector3(500f, 0f, 0f);

                m.UpdateArtStyle();
                m.SetEdgeConnection(true);
                m.SetProvinces(prov1, prov2);
                m.SetEndPoints(p1, p2);

                var widget = w.GetComponent <ConnectionWidget>();
                widget.SetParent(m);
                m.SetWidget(widget);

                m.SetConnection(c);

                m_connections.Add(m);
                m_generated.Add(g);
                m_generated.Add(w);
            }
            else // base case
            {
                var g  = GameObject.Instantiate(ConnectionMarker);
                var m  = g.GetComponent <ConnectionMarker>();
                var p1 = prov1.transform.position;
                var p2 = prov2.transform.position;

                prov1.AddConnection(m);
                prov2.AddConnection(m);

                var center = get_weighted_center(p1, p2, prov1.Node, prov2.Node);
                g.transform.position = center;

                var w = GameObject.Instantiate(ConnectionWidget);
                w.transform.position = center + new Vector3(500f, 0f, 0f);

                m.SetProvinces(prov1, prov2);
                m.SetEndPoints(p1, p2);

                var widget = w.GetComponent <ConnectionWidget>();
                widget.SetParent(m);

                m.UpdateArtStyle();
                m.SetWidget(widget);
                m.SetConnection(c);

                m_connections.Add(m);
                m_generated.Add(g);
                m_generated.Add(w);
            }
            if (Util.ShouldYield())
            {
                yield return(null);
            }
        }

        number_provinces();

        yield return(StartCoroutine(ArtManager.s_art_manager.GenerateElements(m_provinces, m_connections, layout, layout.X * X, layout.Y * Y)));
    }