Ejemplo n.º 1
0
        public void ShouldParseTheParameterToCorrectTypeEvenIfInputIsNotOfSameType()
        {
            GeneratorParameterCollection coll = new GeneratorParameterCollection();
            var gp1 = new GeneratorParameter("Date", DateTime.Now.ToString(), GeneratorParameterParser.DateTimeParser);
            var gp2 = new GeneratorParameter("Decimal", 1000, GeneratorParameterParser.DecimalParser);

            coll.Add(gp1);
            coll.Add(gp2);

            Decimal  dec  = coll.GetValueOf <Decimal>("Decimal");
            DateTime date = coll.GetValueOf <DateTime>("Date");
        }
Ejemplo n.º 2
0
        public void ShouldNotChangeValueWhenTryingToSetValueOfWrongDataType()
        {
            DateTime           d = DateTime.Now;
            GeneratorParameter p = new GeneratorParameter("date", d, dateTimeParser);

            Assert.That(d, Is.EqualTo(p.Value));

            // Try to Set value to wrong datatype
            p.Value = 10;

            Assert.That(d, Is.EqualTo(p.Value));
        }
Ejemplo n.º 3
0
        public void ShouldGetParameterFromCollection()
        {
            GeneratorParameterCollection coll = new GeneratorParameterCollection();
            var gp1 = new GeneratorParameter("Date", DateTime.Now, GeneratorParameterParser.DateTimeParser);
            var gp2 = new GeneratorParameter("Decimal", new Decimal(10), GeneratorParameterParser.DecimalParser);

            coll.Add(gp1);
            coll.Add(gp2);

            Decimal got = coll.GetValueOf <Decimal>("Decimal");

            DateTime got2 = coll.GetValueOf <DateTime>("Date");
        }
Ejemplo n.º 4
0
        public void ShouldBeEqualIfSameName()
        {
            GeneratorParameter withOtherValue           = new GeneratorParameter("peter", 10, GeneratorParameterParser.IntegerParser);
            GeneratorParameter withOtherName            = new GeneratorParameter("Generator", 1, GeneratorParameterParser.IntegerParser);
            GeneratorParameter withOtherParser          = new GeneratorParameter("peter", 1, GeneratorParameterParser.DecimalParser);
            GeneratorParameter withAllPropertiesChanged = new GeneratorParameter("generator", "streng", GeneratorParameterParser.StringParser);

            Assert.That(p1, Is.Not.EqualTo(nullGenParam));

            Assert.That(p1, Is.EqualTo(withOtherValue));
            Assert.That(p1, Is.Not.EqualTo(withOtherName));
            Assert.That(p1, Is.EqualTo(withOtherParser));
            Assert.That(p1, Is.Not.EqualTo(withAllPropertiesChanged));
        }
        public override void Initialize()
        {
            Debug.WriteLine("Init");

            XmlDocument tilesetXml = new XmlDocument();

            tilesetXml.Load("Content/tilesDef.xml");
            tileset = new Tileset(tilesetXml.SelectSingleNode("tiles"), Content);

            Sprite bikeNorth = new Sprite(Content.Load <Texture2D>("tiles"), new Rectangle(64, 384, 64, 48));
            Sprite bikeWest  = new Sprite(Content.Load <Texture2D>("tiles"), new Rectangle(0, 384, 64, 48));
            Sprite bikeEast  = new Sprite(Content.Load <Texture2D>("tiles"), new Rectangle(128, 384, 64, 48));
            Sprite bikeSouth = new Sprite(Content.Load <Texture2D>("tiles"), new Rectangle(128 + 64, 384, 64, 48));

            bikeSprites = new Sprite[] { bikeNorth, bikeEast, bikeSouth, bikeWest };

            var mapParameter = new GeneratorParameter()
            {
                size                 = new Point(128, 128),
                baseHeight           = 1,
                minHeight            = 8,
                maxHeight            = 16,
                waterMinDiff         = 4,
                forestSize           = 0.3f,
                resourceSize         = 0.5f,
                citiesNumber         = 0.4f,
                citySize             = 7.5f,
                citySizeRandomOffset = 2.5f,
                hasCities            = true,
                hasWater             = true,
                hasCityConnections   = true,
                hasRivers            = false,
                tileset              = tileset,
                randomSeed           = 869719833//615228352//1571703035 //123456789 //189370585 //1621216522 //123456789 //1571703035
            };

            map = new Map(mapParameter, camera, Content, GraphicsDevice, Config.Resolution);

            renderer = new IsoRenderer(map, tileset, Content.Load <SpriteFont>("Fonts/Xolonium_18"));

            simulator = new Simulator(0, map, CreateAgent, RemoveAgentFromScene);

            CreateUI();

            CameraInput.Initialize();
        }
Ejemplo n.º 6
0
        public override void Initialize()
        {
            XmlDocument tilesetXml = new XmlDocument();

            tilesetXml.Load("Content/tilesDef.xml");
            tileset = new Tileset(tilesetXml.SelectSingleNode("tiles"), Content);

            mapParameter = new GeneratorParameter()
            {
                size                 = new Point(128, 128),
                baseHeight           = 1,
                minHeight            = 8,
                maxHeight            = 16,
                waterMinDiff         = 4,
                forestSize           = 0.3f,
                resourceSize         = 0.5f,
                citiesNumber         = 0.4f,
                citySize             = 7.5f,
                citySizeRandomOffset = 2.5f,
                hasCities            = true,
                hasWater             = true,
                hasCityConnections   = true,
                hasRivers            = false,
                tileset              = tileset,
                randomSeed           = 869719833//615228352//1571703035 //123456789 //189370585 //1621216522 //123456789 //1571703035
            };

            cities = new List <City>(64);
            map    = new Map(mapParameter, camera, Content, GraphicsDevice, Config.Resolution);

            foreach (World.Generation.Room r in map.cityRooms)
            {
                cities.Add(new City(map.tiles, r));
            }

            renderer = new IsoRenderer(map, tileset, cityFont);

            CreateUI();

            SetCameraBounds();
            CameraInput.Initialize();
        }
Ejemplo n.º 7
0
        public void ShouldGetExceptionWhenTryingToGetWrongDataTypeFromParameterCollection()
        {
            GeneratorParameterCollection coll = new GeneratorParameterCollection();
            var gp1 = new GeneratorParameter("Date", DateTime.Now, GeneratorParameterParser.DateTimeParser);
            var gp2 = new GeneratorParameter("Decimal", "peter", GeneratorParameterParser.StringParser);

            coll.Add(gp1);
            coll.Add(gp2);

            bool gotException = false;

            try
            {
                Decimal got = coll.GetValueOf <Decimal>("Decimal");
            }
            catch (Exception)
            {
                gotException = true;
            }
            Assert.That(gotException, Is.True);
        }
Ejemplo n.º 8
0
        public void Apply(GeneratorParameter param, Tile[,] tiles)
        {
            if (param.citiesNumber == 0f)
            {
                return;
            }

            this.param = param;
            this.tiles = tiles;

            int numCities          = GetNumberOfCities(); //TODO: Propably adjust non placeable.
            int notPlaceableCities = 0;
            List <CityPlacementInfo> cityPlacementInfo = GetCityPlacementInfo(numCities, ref notPlaceableCities);

            foreach (CityPlacementInfo info in cityPlacementInfo)
            {
                Room room = GrowCity(info);
                if (room != null && room.Tiles.Count > 5)
                {
                    cities.Add(room);
                }
            }

            MergeOverlapingCities();

            int totalSize = 0;

            foreach (Room r in cities)
            {
                totalSize += r.Tiles.Count;
            }
            float avgSize = (float)totalSize / cities.Count;

            foreach (Room cityRoom in cities)
            {
                MakeCityDistricts(cityRoom, avgSize);
            }

            Debug.WriteLine($"Number of cities: {numCities}. Not placeable were: {notPlaceableCities}. Avg. city size: {avgSize}");
        }
        private void SmoothHeight(GeneratorParameter param, Tile[,] tiles)
        {
            for (int x = 0; x < param.size.X; x++)
            {
                for (int y = 0; y < param.size.Y; y++)
                {
                    int h = tiles[x, y].GetMaxHeight();
                    int smallerNeighbours = 0;
                    int biggerNeighbours  = 0;

                    foreach (Point p in IterateNeighboursEightDir(x, y))
                    {
                        int nh = tiles[p.X, p.Y].GetMaxHeight();
                        if (nh < h)
                        {
                            smallerNeighbours++;
                        }
                        else if (nh > h)
                        {
                            biggerNeighbours++;
                        }
                    }

                    if (smallerNeighbours > 5)
                    {
                        h -= 1;
                        tiles[x, y].height = new int[] { h, h, h, h };
                    }
                    else if (biggerNeighbours > 5)
                    {
                        h += 1;
                        tiles[x, y].height = new int[] { h, h, h, h };
                    }
                }
            }
        }
Ejemplo n.º 10
0
    void OnGUI()
    {
        //Still developing the mouseover interface for ERAs, I believe this is necessary to force an update when the mouse position changes.
        if (!wantsMouseMove)
        {
            wantsMouseMove = true;
        }

        if (eranalyser == null)
        {
            eranalyser = new ERAnalyser();
        }

        //This probably needs to be called on wake
        SetupStyles();

        GUILayout.Space(15);

        /*
         *  HEADER SECTION
         *
         *  This includes the 'Click here to load a new generator!' and 'Load metrics!' section with Monobehaviour selector.
         *  In future this area may include the tabbing environment for switching between user modes.
         */
        GUILayout.BeginHorizontal();

        GUILayout.BeginVertical();
        GUILayout.BeginHorizontal(GUILayout.Width(300));
        GUILayout.FlexibleSpace();
        GUILayout.Label("Metrics:", rightAlignText, GUILayout.Width(75));
        analyser = (MonoBehaviour)EditorGUILayout.ObjectField("", analyser, typeof(MonoBehaviour), true);
        GUILayout.FlexibleSpace();
        GUILayout.EndHorizontal();

        GUILayout.BeginHorizontal(GUILayout.Width(300));
        GUILayout.FlexibleSpace();
        DrawOnGUISprite(scientistSprite);
        if (analyser == null)
        {
            GUILayout.Label("Please select a MonoBehaviour with metrics to load");
        }
        else if (GUILayout.Button("Load Metrics", buttonStyle, GUILayout.Width(150)))
        {
            SetupMetrics(analyser);
        }
        DrawOnGUISprite(scientistSprite);
        GUILayout.FlexibleSpace();
        GUILayout.EndHorizontal();
        GUILayout.EndVertical();

        GUILayout.BeginVertical();
        GUILayout.BeginHorizontal();
        GUILayout.FlexibleSpace();
        GUILayout.Label("Generator:", rightAlignText, GUILayout.Width(75));
        generator = (MonoBehaviour)EditorGUILayout.ObjectField("", generator, typeof(MonoBehaviour), true, GUILayout.Width(300));
        GUILayout.FlexibleSpace();
        GUILayout.EndHorizontal();

        GUILayout.BeginHorizontal();
        GUILayout.FlexibleSpace();
        DrawOnGUISprite(botSprite);

        if (generator == null)
        {
            GUILayout.Label("Please select a generator to instrument.");
        }
        else
        {
            if (GUILayout.Button("Setup Generator", buttonStyle, GUILayout.Width(150)))
            {
                SetupGenerator();
            }
        }
        DrawOnGUISprite(botSprite);
        GUILayout.FlexibleSpace();
        GUILayout.EndHorizontal();
        GUILayout.EndVertical();

        GUILayout.BeginHorizontal(GUILayout.Width(300));
        GUILayout.FlexibleSpace();
        GUILayout.EndHorizontal();

        GUILayout.EndHorizontal();

        GUILayout.Space(10);

        /*
         *  MAIN EDITOR SPACE
         *
         *  Currently this area is split into three regions: the left-hand bar contains metrics and auto-tuning,
         *  the central pane contains the main visual content (either the generator output or the ERA analysis),
         *  and the right-hand bar contains discovered parameters + settings menu, and the ERA interface.
         */

        GUILayout.BeginHorizontal();

        GUILayout.BeginVertical(GUILayout.Width(10));
        GUILayout.Space(10);
        GUILayout.EndVertical();

        /*
         *  METRICS
         *
         *  For each discovered metric, display its current value here and its name. This is updated whenever a new
         *  piece of content is generated.
         */
        GUILayout.BeginVertical(GUILayout.Width(300));

        GUILayout.BeginVertical();
        GUILayout.Label("Metrics", centerAlignText);
        GUILayout.Box("", GUILayout.ExpandWidth(true), GUILayout.Height(1));
        GUILayout.Space(20);

        if (metricList != null)
        {
            for (int i = 0; i < metricList.Count; i++)
            {
                GeneratorMetric m = metricList[i];

                GUILayout.BeginHorizontal();
                GUILayout.Label(m.name, leftAlignText);
                GUILayout.FlexibleSpace();
                if (Double.IsNaN(m.currentValue))
                {
                    m.currentValue = 0;
                }
                GUILayout.Label(Math.Round((Decimal)(float)m.currentValue, 3, MidpointRounding.AwayFromZero) + "", rightAlignText);
                GUILayout.EndHorizontal();
                GUILayout.Space(10);
            }
        }
        GUILayout.EndVertical();

        GUILayout.FlexibleSpace();

        /*
         *  AUTO-TUNING
         *
         *  Auto-tuning allows Danesh to automatically discover parameter configuraitons to achieve a certain average metric value.
         *  The user can select which parameters to change by checking boxes, and then check metrics to target and input values for them.
         */

        GUILayout.BeginVertical();
        GUILayout.Label("Auto-Tuning", centerAlignText);
        GUILayout.Box("", GUILayout.ExpandWidth(true), GUILayout.Height(1));
        GUILayout.Space(20);

        GUILayout.Label("Targeted Parameters", centerAlignSubtext);
        GUILayout.BeginHorizontal();
        GUILayout.FlexibleSpace();
        GUILayout.Box("", GUILayout.Width(125), GUILayout.Height(1));
        GUILayout.FlexibleSpace();
        GUILayout.EndHorizontal();

        GUILayout.Space(10);

        if (parameterList != null)
        {
            for (int i = 0; i < parameterList.Count; i++)
            {
                GeneratorParameter p = parameterList[i];
                if (p.locked)
                {
                    continue;
                }

                GUILayout.BeginHorizontal();

                p.activated = GUILayout.Toggle(p.activated, "", GUILayout.Width(20));
                GUILayout.Space(10);
                if (p.activated)
                {
                    GUILayout.Label(p.name, leftAlignText, GUILayout.Width(200));
                }
                else
                {
                    GUILayout.Label(p.name, leftAlignTextGhost, GUILayout.Width(200));
                }
                GUILayout.FlexibleSpace();

                GUILayout.EndHorizontal();
                GUILayout.Space(5);
            }
        }

        GUILayout.Space(20);

        GUILayout.Label("Targeted Metrics", centerAlignSubtext);
        GUILayout.BeginHorizontal();
        GUILayout.FlexibleSpace();
        GUILayout.Box("", GUILayout.Width(125), GUILayout.Height(1));
        GUILayout.FlexibleSpace();
        GUILayout.EndHorizontal();

        GUILayout.Space(10);

        if (metricList != null && metricTargets != null && metricInputs != null)
        {
            for (int i = 0; i < metricList.Count; i++)
            {
                GeneratorMetric m = metricList[i];

                GUILayout.BeginHorizontal();
                m.targeted = GUILayout.Toggle(m.targeted, "", GUILayout.Width(20));
                GUILayout.Space(10);
                if (m.targeted)
                {
                    GUILayout.Label(m.name, leftAlignText);
                }
                else
                {
                    GUILayout.Label(m.name, leftAlignTextGhost);
                }
                GUILayout.EndHorizontal();
                GUILayout.BeginHorizontal();
                if (m.targeted)
                {
                    GUILayout.Label("Target Value:", rightAlignText);
                }
                else
                {
                    GUILayout.Label("Target Value:", rightAlignTextGhost);
                }
                GUILayout.Space(10);

                if (metricInputs != null)
                {
                    metricInputs[i] = GUILayout.TextField(metricInputs[i], 25, GUILayout.Width(50));
                }

                float res = 0f;
                if (float.TryParse(metricInputs[i], out res))
                {
                    metricTargets[i] = res;
                }
                GUILayout.EndHorizontal();
                GUILayout.Space(10);
            }
        }

        GUILayout.Space(20);

        GUILayout.BeginHorizontal();
        GUILayout.FlexibleSpace();
        if (GUILayout.Button("Start Auto-Tuning", buttonStyle, GUILayout.Width(150)))
        {
            DaneshAutoTuner at = new DaneshAutoTuner();
            //Construct the list of parameters
            List <GeneratorParameter> tuningParams = new List <GeneratorParameter>();
            foreach (GeneratorParameter p in parameterList)
            {
                if (p.activated)
                {
                    tuningParams.Add(p);
                }
            }
            List <GeneratorMetric> tuningMetrics = new List <GeneratorMetric>();
            List <float>           tuningTargets = new List <float>();
            for (int i = 0; i < metricList.Count; i++)
            {
                GeneratorMetric m = metricList[i];
                if (m.targeted)
                {
                    tuningTargets.Add(metricTargets[i]);
                    tuningMetrics.Add(m);
                }
            }

            at.Tune(this, tuningParams, tuningMetrics, tuningTargets);
        }
        if (!showATTooltip && GUILayout.Button("?", GUILayout.Width(25)))
        {
            showATTooltip = true;
        }
        GUILayout.FlexibleSpace();
        GUILayout.EndHorizontal();

        if (showATTooltip)
        {
            GUILayout.Space(10);
            GUILayout.BeginVertical();
            GUILayout.Label("Tick the parameters you want to modify, and set the metric values you would like the generated content to have. When you click Auto-Tune, Danesh will try to find parameter values that make the generator produce content close to the target metrics.", tooltipStyle, GUILayout.Width(300));

            GUILayout.Space(10);
            GUILayout.BeginHorizontal();
            GUILayout.FlexibleSpace();
            if (GUILayout.Button("Close", GUILayout.Width(100)))
            {
                showATTooltip = false;
            }
            GUILayout.FlexibleSpace();
            GUILayout.EndHorizontal();
            GUILayout.EndVertical();
            GUILayout.Space(10);
        }
        else
        {
            GUILayout.Space(20);
        }

        GUILayout.EndVertical();

        GUILayout.EndVertical();

        /*
         *  MAIN PANE
         *
         *  We display a lot of information here. At the moment, what we show is based on the MainTab enum value. I'm going to change the way this is rendered eventually
         *  and break some of it out into other files or parts of this file. I get the feeling that Unity UIs are supposed to be a bit clunky but they shouldn't be this
         *  cluttered, I don't think.
         */

        GUILayout.BeginVertical();

        //Display the output of the generator, using the textureToBeDisplayed variable.
        if (MainTab == Tabs.OUTPUT)
        {
            GUILayout.Label("Generator Output", centerAlignText);
            GUILayout.Box("", GUILayout.ExpandWidth(true), GUILayout.Height(1));
            GUILayout.Space(20);

            GUILayout.BeginHorizontal();
            GUILayout.FlexibleSpace();
            if (hasDisplay)
            {
                GUILayout.Label(textureToBeDisplayed);
            }
            else if (noGeneratorFound)
            {
                GUILayout.Label("Danesh couldn't find a generation method. Did you use the [MapGenerator] attribute?", errorTextStyle);
            }
            GUILayout.FlexibleSpace();
            GUILayout.EndHorizontal();

            GUILayout.BeginHorizontal();
            GUILayout.FlexibleSpace();
            if (generator != null && !noGeneratorFound && GUILayout.Button("Generate Content", buttonStyle, GUILayout.Width(150)))
            {
                GenerateMap();
            }
            GUILayout.FlexibleSpace();
            GUILayout.EndHorizontal();
        }
        //Display the output of the ERA/RERA here, with selectors to change the axes.
        //TODO: Draw axes on/near the image to show the metric values for X/Y
        else if (MainTab == Tabs.ERA)
        {
            GUILayout.Label("Expressive Range Histogram", centerAlignText);
            GUILayout.Box("", GUILayout.ExpandWidth(true), GUILayout.Height(1));
            GUILayout.Space(20);

            GUILayout.BeginHorizontal();
            GUILayout.FlexibleSpace();
            if (hasDisplay)
            {
                GUILayout.Label(textureToBeDisplayed);
                if (Event.current.type == EventType.Repaint)
                {
                    eraRect = GUILayoutUtility.GetLastRect();
                }
            }
            GUILayout.FlexibleSpace();
            GUILayout.EndHorizontal();

            GUILayout.Space(30);

            GUILayout.BeginHorizontal();
            GUILayout.FlexibleSpace();
            GUILayout.Label("Metric 1 (X-Axis):");
            int prior_x = x_axis_era;
            x_axis_era = EditorGUILayout.Popup(x_axis_era, axis_options);
            GUILayout.FlexibleSpace();
            GUILayout.EndHorizontal();

            GUILayout.BeginHorizontal();
            GUILayout.FlexibleSpace();
            GUILayout.Label("Metric 2 (Y-Axis):");
            int prior_y = y_axis_era;
            y_axis_era = EditorGUILayout.Popup(y_axis_era, axis_options);
            GUILayout.FlexibleSpace();
            GUILayout.EndHorizontal();

            GUILayout.Space(30);

            GUILayout.BeginHorizontal();
            GUILayout.FlexibleSpace();
            if (GUILayout.Button("Back To Generator", buttonStyle))
            {
                SwitchToOutputMode();
                GenerateMap();
            }
            GUILayout.FlexibleSpace();
            GUILayout.EndHorizontal();

            if (prior_x != x_axis_era || prior_y != y_axis_era)
            {
                //Change
                DisplayTexture(eranalyser.GenerateGraphForAxes(x_axis_era, y_axis_era));
            }
        }

        GUILayout.EndVertical();

        /*
         *  RIGHT COLUMN
         *
         *  Parameters and the ERA/RERA setup interface.
         */

        GUILayout.BeginVertical(GUILayout.Width(300));
        GUILayout.Label("Generator Parameters", centerAlignText);
        GUILayout.Box("", GUILayout.ExpandWidth(true), GUILayout.Height(1));
        GUILayout.Space(20);

        /*
         *  PARAMETERS
         *
         *  Parameters are displayed with a slider that lets you change their value. The textbox shows their current value
         *  but it's slightly misleading because it can't be edited at the moment. I might change that but there's feedback
         *  issues in updating all the UI stuff at once. It's a nice feature but not a priority.
         *
         *  If the Parameter is 'locked' this means it was discovered by Danesh but does not have all the information it needs
         *  yet. It prompts the user to add in information (min/max values) and then lock or discard the parameter.
         */

        if (parameterList != null)
        {
            for (int i = 0; i < parameterList.Count; i++)
            {
                GeneratorParameter p = parameterList[i];

                GUILayout.BeginHorizontal();

                if (!p.locked)
                {
                    GUILayout.Label(p.name, rightAlignText);
                }
                else if (p.locked)
                {
                    GUILayout.Label("New Parameter: " + p.name, leftAlignText);
                }

                GUILayout.EndHorizontal();

                GUILayout.BeginHorizontal();
                if (!p.locked)
                {
                    if (p.type == "float")
                    {
                        object newVal = (object)GUILayout.HorizontalSlider((float)p.currentValue, (float)p.minValue, (float)p.maxValue);
                        if (newVal != p.currentValue)
                        {
                            //Change in the generator
                            p.field.SetValue(generator, newVal);
                        }
                        p.currentValue = newVal;
                        GUILayout.TextField(Math.Round((Decimal)(float)p.currentValue, 3, MidpointRounding.AwayFromZero) + "", 20, GUILayout.Width(50));
                    }
                    if (p.type == "int")
                    {
                        object newVal = (object)(int)GUILayout.HorizontalSlider(Convert.ToInt32(p.currentValue), Convert.ToInt32(p.minValue), Convert.ToInt32(p.maxValue));
                        if (newVal != p.currentValue)
                        {
                            //Change in the generator
                            p.field.SetValue(generator, newVal);
                        }
                        p.currentValue = newVal;
                        GUILayout.TextField(Convert.ToInt32(p.currentValue) + "", 20, GUILayout.Width(50));
                    }
                    if (p.type == "bool")
                    {
                        GUILayout.FlexibleSpace();
                        bool cval = (bool)p.currentValue;
                        cval = (bool)GUILayout.Toggle(cval, "", GUILayout.Width(20));
                        p.field.SetValue(generator, (object)cval);
                        p.currentValue = (object)cval;
                    }
                }
                else
                {
                    if (p.type == "float")
                    {
                        GUILayout.Label("Min: ", rightAlignText);
                        string mnv = GUILayout.TextField((Decimal)(float)(p.minValue) + "", 20, GUILayout.Width(40));
                        GUILayout.Label("Max: ", rightAlignText);
                        string mxv = GUILayout.TextField((Decimal)(float)(p.maxValue) + "", 20, GUILayout.Width(40));
                        if (GUILayout.Button("\u2713", buttonStyle, GUILayout.Width(30)))
                        {
                            p.ParseSetMinValue(mnv);
                            p.ParseSetMaxValue(mxv);
                            p.locked = false;
                        }
                        if (GUILayout.Button("\u00D7", buttonStyle, GUILayout.Width(30)))
                        {
                            parameterList.RemoveAt(i);
                        }
                        GUILayout.TextField(Math.Round((Decimal)(float)p.currentValue, 3, MidpointRounding.AwayFromZero) + "", 20, GUILayout.Width(50));
                    }
                    if (p.type == "int")
                    {
                        GUILayout.Label("Min: ", rightAlignText);
                        string mnv = GUILayout.TextField(Convert.ToInt32(p.minValue) + "", 20, GUILayout.Width(40));
                        p.ParseSetMinValue(mnv);
                        GUILayout.Label("Max: ", rightAlignText);
                        string mxv = GUILayout.TextField(Convert.ToInt32(p.maxValue) + "", 20, GUILayout.Width(40));
                        p.ParseSetMaxValue(mxv);
                        if (GUILayout.Button("\u2713", buttonStyle, GUILayout.Width(30)))
                        {
                            p.ParseSetMinValue(mnv);
                            p.ParseSetMaxValue(mxv);
                            p.locked = false;
                        }
                        if (GUILayout.Button("\u00D7", buttonStyle, GUILayout.Width(30)))
                        {
                            parameterList.RemoveAt(i);
                        }
                        GUILayout.TextField(Convert.ToInt32(p.currentValue) + "", 20, GUILayout.Width(50));
                    }
                    if (p.type == "bool")
                    {
                        bool cval = (bool)p.currentValue;
                        GUILayout.FlexibleSpace();

                        p.currentValue = (bool)GUILayout.Toggle(cval, "", GUILayout.Width(20));

                        if (GUILayout.Button("\u2713", buttonStyle, GUILayout.Width(30)))
                        {
                            p.locked = false;
                        }
                        if (GUILayout.Button("\u00D7", buttonStyle, GUILayout.Width(30)))
                        {
                            parameterList.RemoveAt(i);
                        }
                    }
                }
                //p.currentValue = (object) GUILayout.HorizontalSlider((bool) p.currentValue, 0.0F, 10.0F);
                // GUILayout.TextField(Math.Round((Decimal)(float)p.currentValue, 3, MidpointRounding.AwayFromZero)+"", 20, GUILayout.Width(50));
                GUILayout.EndHorizontal();
                GUILayout.Space(15);
            }
        }

        GUILayout.Space(10);
        GUILayout.BeginHorizontal();
        GUILayout.FlexibleSpace();
        if (parameterList != null && metricList != null && GUILayout.Button("Search For Parameters", buttonStyle, GUILayout.Width(200)))
        {
            ParameterFinder           pf = new ParameterFinder();
            List <GeneratorParameter> ps = pf.FindParameters(this, generator);
            foreach (GeneratorParameter p in ps)
            {
                parameterList.Add(p);
            }
        }
        if (!showParamSearchTooltip && GUILayout.Button("!", GUILayout.Width(25)))
        {
            showParamSearchTooltip = true;
        }
        GUILayout.FlexibleSpace();
        GUILayout.EndHorizontal();

        if (showParamSearchTooltip)
        {
            GUILayout.BeginVertical();
            GUILayout.Label("Warning: This is an experimental feature and can change the internal workings of your generator. Back up before using this!", warningTTStyle, GUILayout.Width(300));

            GUILayout.BeginHorizontal();
            GUILayout.FlexibleSpace();
            if (GUILayout.Button("Close", GUILayout.Width(100)))
            {
                showParamSearchTooltip = false;
            }
            GUILayout.FlexibleSpace();
            GUILayout.EndHorizontal();
            GUILayout.EndVertical();
        }

        /*
         *  RESET/SAVE/LOAD
         *
         *  Avoiding side effects in the generator is a really important objective for Danesh. We can't avoid all side effects without
         *  knowing what the generator code does, of course, but we do our best. One piece of functionality is the reset button which restores
         *  parameter values to what they were on load. It does not undo other unseen changes.
         *
         *  Saving and loading serialises to text files. This is basic and there are no safety catches, meaning it's possible to load a config
         *  for a different generator. We can secure this later by connecting the monobehaviour id to it or something.
         */

        GUILayout.Space(10);
        GUILayout.BeginHorizontal();
        GUILayout.FlexibleSpace();
        if (parameterList != null && !reallyReset && GUILayout.Button("Reset Generator", buttonStyle, GUILayout.Width(150)))
        {
            reallyReset = true;
        }
        else if (reallyReset)
        {
            GUILayout.Label("Really Reset?");
            GUILayout.FlexibleSpace();
            GUILayout.EndHorizontal();
            GUILayout.BeginHorizontal();
            GUILayout.FlexibleSpace();
            if (GUILayout.Button("Yes", buttonStyle, GUILayout.Width(50)))
            {
                foreach (GeneratorParameter p in parameterList)
                {
                    p.field.SetValue(generator, p.originalValue);
                    p.currentValue = p.originalValue;
                }
                reallyReset = false;
            }
            GUILayout.FlexibleSpace();
            if (GUILayout.Button("No", buttonStyle, GUILayout.Width(50)))
            {
                reallyReset = false;
            }
        }
        GUILayout.FlexibleSpace();
        GUILayout.EndHorizontal();

        GUILayout.Space(10);
        GUILayout.BeginHorizontal();
        GUILayout.FlexibleSpace();
        if (parameterList != null && !beginSave && GUILayout.Button("Save Configuration", buttonStyle, GUILayout.Width(150)))
        {
            beginSave = true;
            beginLoad = false;
            saveName  = GetRandomConfigName();
        }
        else if (beginSave)
        {
            GUILayout.Label("Config. Name:");
            saveName = GUILayout.TextField(saveName, 20, GUILayout.Width(200));
            GUILayout.FlexibleSpace();
            GUILayout.EndHorizontal();
            GUILayout.BeginHorizontal();
            GUILayout.FlexibleSpace();
            if (GUILayout.Button("Save", buttonStyle, GUILayout.Width(100)))
            {
                //Save the configuration
                if (File.Exists(saveName + ".param"))
                {
                    Debug.Log("File '" + saveName + "'' already exists.");
                    return;
                }
                var sr = File.CreateText(saveName + ".param");
                foreach (GeneratorParameter p in parameterList)
                {
                    sr.WriteLine(p.field.Name + ":" + p.type + ":" + p.currentValue);
                }
                sr.Close();

                beginSave = false;
            }
            GUILayout.FlexibleSpace();
            if (GUILayout.Button("Cancel", buttonStyle, GUILayout.Width(100)))
            {
                beginSave = false;
            }
        }
        GUILayout.FlexibleSpace();
        GUILayout.EndHorizontal();

        GUILayout.Space(10);
        GUILayout.BeginHorizontal();
        GUILayout.FlexibleSpace();
        if (parameterList != null && !beginLoad && GUILayout.Button("Load Configuration", buttonStyle, GUILayout.Width(150)))
        {
            beginSave         = false;
            beginLoad         = true;
            possibleLoadFiles = new List <string>();

            DirectoryInfo root  = new DirectoryInfo(".");
            FileInfo[]    infos = root.GetFiles();
            // Debug.Log(infos.Length+" files found");
            foreach (FileInfo f in infos)
            {
                // Debug.Log(f.Name);
                if (f.Name.EndsWith(".param"))
                {
                    possibleLoadFiles.Add(f.Name);
                }
            }

            selectedFile = 0;
        }
        else if (beginLoad)
        {
            if (possibleLoadFiles.Count == 0)
            {
                GUILayout.Label("Found no files to load!");
                if (GUILayout.Button("Cancel", buttonStyle, GUILayout.Width(100)))
                {
                    beginLoad = false;
                }
            }
            else
            {
                GUILayout.BeginVertical();
                GUILayout.Label("Select a file", centerAlignSubtext);
                selectedFile = EditorGUILayout.Popup("", selectedFile, possibleLoadFiles.ToArray(), GUILayout.Width(250));
                GUILayout.EndVertical();

                GUILayout.FlexibleSpace();
                GUILayout.EndHorizontal();
                GUILayout.Space(10);
                GUILayout.BeginHorizontal();
                GUILayout.FlexibleSpace();
                if (GUILayout.Button("Load", buttonStyle, GUILayout.Width(100)))
                {
                    //Load the configuration
                    string       line;
                    StreamReader theReader = new StreamReader(possibleLoadFiles[selectedFile]);
                    using (theReader){
                        do
                        {
                            line = theReader.ReadLine();
                            if (line != null)
                            {
                                //Parse the line
                                string[] parts = line.Split(':');
                                foreach (GeneratorParameter p in parameterList)
                                {
                                    if (p.field.Name == parts[0])
                                    {
                                        p.ParseAndSetValue(parts[2]);
                                    }
                                }
                            }
                        }while (line != null);
                    }
                    theReader.Close();

                    beginLoad = false;
                }
                GUILayout.FlexibleSpace();
                if (GUILayout.Button("Cancel", buttonStyle, GUILayout.Width(100)))
                {
                    beginLoad = false;
                }
            }
        }
        GUILayout.FlexibleSpace();
        GUILayout.EndHorizontal();

        GUILayout.FlexibleSpace();

        /*
         *  EXPRESSIVE RANGE
         *
         *  See the details on danesh.procjam.com for more information about what expressive range analysis consists of.
         *  This runs the RERA and ERA functions and updates the main context pane with the histogram results when done.
         */
        GUILayout.BeginVertical();
        GUILayout.Label("Expressive Range", centerAlignText);
        GUILayout.Box("", GUILayout.ExpandWidth(true), GUILayout.Height(1));
        GUILayout.Space(20);

        GUILayout.Space(20);

        numberOfERARuns = EditorGUILayout.IntField("Sample Size (ERA):", numberOfERARuns);

        GUILayout.BeginHorizontal();
        GUILayout.FlexibleSpace();
        if (GUILayout.Button("Perform ER Analysis", buttonStyle, GUILayout.Width(150)))
        {
            eranalyser.StartERA(this, numberOfERARuns);
            Texture2D tex = eranalyser.GenerateGraphForAxes(x_axis_era, y_axis_era);
            DisplayTexture(tex);
            SwitchToERAMode();
        }
        if (!showERATooltip && GUILayout.Button("?", GUILayout.Width(25)))
        {
            showERATooltip = true;
        }
        GUILayout.FlexibleSpace();
        GUILayout.EndHorizontal();

        if (showERATooltip)
        {
            GUILayout.BeginVertical();
            GUILayout.Label("An ER Analysis lets you analyse the kind of content the generator is currently making. Danesh uses the generator to make " + numberOfERARuns + " pieces of content (set by 'Sample Size', above) and then plots the metric scores of each piece of content on a histogram.", tooltipStyle, GUILayout.Width(300));

            GUILayout.BeginHorizontal();
            GUILayout.FlexibleSpace();
            if (GUILayout.Button("Close", GUILayout.Width(100)))
            {
                showERATooltip = false;
            }
            GUILayout.FlexibleSpace();
            GUILayout.EndHorizontal();
            GUILayout.EndVertical();
        }
        GUILayout.Space(20);

        numberOfRERARuns = EditorGUILayout.IntField("Sample Size (RERA):", numberOfRERARuns);

        GUILayout.BeginHorizontal();
        GUILayout.FlexibleSpace();
        if (GUILayout.Button("Random ER Analysis", buttonStyle, GUILayout.Width(150)))
        {
            eranalyser.StartRERA(this, numberOfRERARuns);
            DisplayTexture(eranalyser.GenerateGraphForAxes(x_axis_era, y_axis_era));
            SwitchToERAMode();
        }
        if (!showRERATooltip && GUILayout.Button("?", GUILayout.Width(25)))
        {
            showRERATooltip = true;
        }
        GUILayout.FlexibleSpace();
        GUILayout.EndHorizontal();

        if (showRERATooltip)
        {
            GUILayout.BeginVertical();
            GUILayout.Label("A Random ER Analysis is a special kind of ERA that lets you see what your generator can do with different parameters. It randomises the parameters of the generator each time it generates a piece of content, creating a histogram of all the different kinds of output possible.", tooltipStyle, GUILayout.Width(300));

            GUILayout.BeginHorizontal();
            GUILayout.FlexibleSpace();
            if (GUILayout.Button("Close", GUILayout.Width(100)))
            {
                showERATooltip = false;
            }
            GUILayout.FlexibleSpace();
            GUILayout.EndHorizontal();
            GUILayout.EndVertical();
        }

        GUILayout.Space(20);
        GUILayout.EndVertical();

        GUILayout.EndVertical();

        GUILayout.BeginVertical(GUILayout.Width(10));
        GUILayout.Space(10);
        GUILayout.EndVertical();

        GUILayout.EndHorizontal();

        /*
         *  This is the current code that detects mouse movement and position over the ERA and paints in a data point if it exists.
         *  It needs rewriting, badly.
         */

        if (MainTab == Tabs.ERA && Event.current.type == EventType.MouseMove)
        {
            float tex_mx = Event.current.mousePosition.x - eraRect.x;
            float tex_my = Event.current.mousePosition.y - eraRect.y + 5;

            /*
             *  Hi, welcome to Open Source With Mike Cook, today I'll be revealing my secrets to writing the worst code in human history
             */

            int x = (int)(100 * (tex_mx / eraRect.width));
            if (x < 0)
            {
                x = 0;
            }
            if (x > 99)
            {
                x = 99;
            }
            int y = 100 - (int)(100 * (tex_my / eraRect.height));
            if (y < 0)
            {
                y = 0;
            }
            if (y > 99)
            {
                y = 99;
            }

            Debug.Log("Cursor at " + tex_mx + ", " + tex_my + ". Within " + eraRect.width + ", " + eraRect.height + ". " + (tex_mx > 0 && tex_my > 0 && tex_mx < eraRect.width && tex_my < eraRect.height));

            if (tex_mx > 0 && tex_my > 0 && tex_mx < eraRect.width && tex_my < eraRect.height)
            {
                Debug.Log("Cursor at " + tex_mx + ", " + tex_my + ". Within " + eraRect.width + ", " + eraRect.height + ". " + (tex_mx > 0 && tex_my > 0 && tex_mx < eraRect.width && tex_my < eraRect.height));

                // int x = 100*(int)(tex_mx/eraRect.width);
                // int y = 100*(int)(tex_my/eraRect.height);

                Debug.Log("Looking for metrics " + x + ", " + y);
                Debug.Log(" - " + (eranalyser.eraSamples[x_axis_era][y_axis_era][x, y] != null));
                Debug.Log(" - " + (eranalyser.eraSamples[x_axis_era][y_axis_era][y, x] != null));

                //If the cursor target is null, be generous and find an adjacent one, because it's really hard to find the exact spot right now
                if (eranalyser.eraSamples[x_axis_era][y_axis_era][x, y] != null)
                {
                    for (int i = -1; i < 2; i++)
                    {
                        for (int j = -1; j < 2; j++)
                        {
                            if ((i != 0 || j != 0) && x + i >= 0 && x + i < 100 && y + j >= 0 && y + j < 100 && eranalyser.eraSamples[x_axis_era][y_axis_era][x + i, y + j] != null)
                            {
                                x = x + i;
                                y = y + j;
                                break;
                            }
                        }
                    }
                }

                if (eranalyser.eraSamples[x_axis_era][y_axis_era][x, y] != null && (x != last_era_x || y != last_era_y))
                {
                    Debug.Log("Generating a new preview window");
                    last_era_preview = VisualiseContent(eranalyser.eraSamples[x_axis_era][y_axis_era][x, y]);
                    TextureScale.Point(last_era_preview, 100, 100);
                    last_era_preview.Apply();
                    last_era_x = x;
                    last_era_y = y;
                    Repaint();
                }
                if (eranalyser.eraSamples[x_axis_era][y_axis_era][x, y] == null && (x != last_era_x || y != last_era_y))
                {
                    last_era_preview = null;
                    last_era_x       = 0;
                    last_era_y       = 0;
                    // GUI.DrawTexture(new Rect(tex_mx, tex_my, 100, 100), last_era_preview);
                }
                else
                {
                    // last_era_preview = null;
                }
            }
            else
            {
                //Outside of the ERA, nullify
                last_era_preview = null;
                last_era_x       = 0;
                last_era_y       = 0;
            }
        }
        else if (MainTab == Tabs.ERA && Event.current.type == EventType.Repaint)
        {
            if (last_era_preview != null)
            {
                GUI.DrawTexture(new Rect(Event.current.mousePosition.x, Event.current.mousePosition.y, 100, 100), last_era_preview);
                // GUILayout.Label(last_era_preview);
            }
        }
    }
Ejemplo n.º 11
0
    List <List <float> > SampleExpressiveRangeRandomly(int totalAttempts, Danesh gen)
    {
        float progressBar = 0f;

        EditorUtility.DisplayProgressBar("Computing Randomised Expressive Range Histogram", "Working...", progressBar);
        List <List <float> > res = new List <List <float> >();

        List <GeneratorMetric> metrics = danesh.GetMetricsForActiveGenerator();

        /*
         *  Current:
         *  eraSample[metric1][metric2] = object[,] of samples representing the histogram
         *  Lot of data duplication here, not the most efficient way to do it
         */
        eraSamples = new List <List <GeneratorSample[, ]> >();

        for (int i = 0; i < metrics.Count; i++)
        {
            List <GeneratorSample[, ]> secondmetric = new List <GeneratorSample[, ]>();
            for (int j = 0; j < metrics.Count; j++)
            {
                GeneratorSample[,] sampleH = new GeneratorSample[100, 100];
                secondmetric.Add(sampleH);
            }
            eraSamples.Add(secondmetric);
        }

        List <GeneratorParameter> genParams = gen.GetParametersForActiveGenerator();

        for (int att = 0; att < totalAttempts; att++)
        {
            //Hold this so we can find this version later
            object[] ps = new object[genParams.Count];
            //Randomly parameterise the generator
            for (int i = 0; i < genParams.Count; i++)
            {
                GeneratorParameter p = genParams[i];
                p.RandomiseValue();
                ps[i] = p.GetValue();
            }

            object map = danesh.GenerateContent();

            List <float> nums = new List <float>();
            for (int i = 0; i < metrics.Count; i++)
            {
                float score = (float)danesh.GetMetric(i, new object[] { map });
                nums.Add(score);
            }

            //Update the samples list
            for (int i = 0; i < nums.Count; i++)
            {
                int index1 = (int)Mathf.Floor(nums[i] * 100f);
                if (index1 < 0)
                {
                    index1 = 0;
                }
                if (index1 > 99)
                {
                    index1 = 99;
                }
                for (int j = 0; j < nums.Count; j++)
                {
                    int index2 = (int)Mathf.Floor(nums[j] * 100f);
                    if (index2 < 0)
                    {
                        index2 = 0;
                    }
                    if (index2 > 99)
                    {
                        index2 = 99;
                    }
                    eraSamples[i][j][index1, index2] = new GeneratorSample(map, ps);
                }
            }

            res.Add(nums);
            EditorUtility.DisplayProgressBar("Computing Randomised Expressive Range Histogram", "Evaluating random expressive range... " + (100 * (float)att / (float)totalAttempts).ToString("F0") + " percent complete", (float)att / (float)totalAttempts);
        }
        EditorUtility.ClearProgressBar();
        return(res);
    }
        public void Apply(GeneratorParameter param, Tile[,] tiles)
        {
            if (!param.hasCityConnections)
            {
                return;
            }

            List <(Room, Room)> toConnect = GetRoomsToConnect();

            foreach ((Room r, Room r2) in toConnect)
            {
                Debug.Assert(r != r2);
                if (r == null || r.Tiles.Count < 5)
                {
                    continue;
                }

                Point start = r.MiddlePoint;

                //get a road tile near the middle point, if it is not a road
                if (tiles[start.X, start.Y].type != TileType.Road)
                {
                    for (int x = start.X - 2; x <= start.X + 2; x++)
                    {
                        for (int y = start.Y - 2; y <= start.Y + 2; y++)
                        {
                            if (GeneratorHelper.IsInRange(x, y) && tiles[x, y].type == TileType.Road)
                            {
                                start = new Point(x, y);
                                break;
                            }
                        }
                        if (tiles[start.X, start.Y].type == TileType.Road)
                        {
                            break;
                        }
                    }
                }

                Debug.Assert(tiles[start.X, start.Y].type == TileType.Road);

                if (r2 != null && r2.Tiles.Count > 5)
                {
                    Point target     = r2.MiddlePoint;
                    float targetDist = float.MaxValue;
                    foreach (Point p in r2.Tiles)
                    {
                        if (tiles[p.X, p.Y].type == TileType.Road && tiles[p.X, p.Y].AllHeightsAreSame())
                        {
                            float dist = (start - p).ToVector2().LengthSquared();
                            if (dist < targetDist)
                            {
                                target     = p;
                                targetDist = dist;
                            }
                        }
                    }
                    Debug.Assert(tiles[target.X, target.Y].type == TileType.Road);

                    Func <Tile, bool>  IsWalkable = (t) => t.IsRoadPlaceable();
                    Func <Tile, float> Cost       = (t) =>
                    {
                        if (t.type == TileType.Road)
                        {
                            return(1f);
                        }
                        else if (t.type == TileType.Water)
                        {
                            return(7f);
                        }
                        else if (t.type == TileType.Forest)
                        {
                            return(3f);
                        }
                        else if (t.type == TileType.House)
                        {
                            return(20f);
                        }
                        else
                        {
                            return(3f);
                        }
                    };

                    List <Point> path = GeneratorHelper.AStar(tiles, start, target, IsWalkable, Cost, GeneratorHelper.IterateNeighboursFourDirRoads);

                    if (path != null && !(path.Count == 1 && path[0] == new Point(-1, -1)))
                    {
                        for (int k = 0; k < path.Count; k++)
                        {
                            Point p = path[k];

                            if (tiles[p.X, p.Y].type == TileType.Water || tiles[p.X, p.Y].type == TileType.Bridge)
                            {
                                tiles[p.X, p.Y].type = TileType.Bridge;
                            }
                            else
                            {
                                tiles[p.X, p.Y].type = TileType.Road;
                            }
                        }
                    }
                    else
                    {
                        Debug.WriteLine("Target not reached");
                    }
                }
            }
        }
Ejemplo n.º 13
0
        private void CreateCitiesCellularAutomata(GeneratorParameter param, Tile[,] tiles)
        {
            var            rooms    = GeneratorHelper.GetCellularAutomataAsRooms(6, 53, true);
            HashSet <Room> toRemove = new HashSet <Room>();
            int            count    = 7;

            foreach (Room room in rooms)
            {
                int size = room.Tiles.Count;
                if (size < 15)
                {
                    toRemove.Add(room);
                    continue;
                }

                int modX = 3;
                int modY = 3;
                if (random.NextDouble() < 0.5)
                {
                    modX = random.Next(3, 6);
                }
                else
                {
                    modY = random.Next(3, 6);
                }

                cities.Add(room);
                count += 7;

                double levelThree = GetPercentageOfCitizenLevel(DistrictType.Business);
                double levelOne   = GetPercentageOfCitizenLevel(DistrictType.Suburb);

                foreach (Point p in room.Tiles)
                {
                    Tile t = tiles[p.X, p.Y];

                    double       prob = random.NextDouble();
                    DistrictType lvl  = DistrictType.None;
                    if (prob <= levelOne)
                    {
                        lvl = DistrictType.Suburb;
                    }
                    else if (prob <= levelOne + levelThree)
                    {
                        lvl = DistrictType.Business;
                    }
                    else
                    {
                        lvl = DistrictType.City;
                    }

                    if (t.type == TileType.Nothing && t.AllHeightsAreSame())
                    {
                        if ((p.X % modX) == 0 || (p.Y % modY) == 0)
                        {
                            t.type = TileType.Road;
                        }
                        else
                        {
                            t.SetCitizenLevel(lvl);
                            t.type       = TileType.House;
                            t.onTopIndex = param.tileset.GetRandomHouseIndex(t.citizenLevel);
                        }
                    }
                }
                room.Tiles.RemoveWhere((p) => tiles[p.X, p.Y].type == TileType.Water || tiles[p.X, p.Y].type == TileType.Forest);

                if (room.Tiles.Count < 15)
                {
                    toRemove.Add(room);
                    continue;
                }
            }

            cities.RemoveAll((r) => toRemove.Contains(r));
        }
Ejemplo n.º 14
0
 public void Apply(GeneratorParameter param, Tile[,] tiles)
 {
     CreateCitiesCellularAutomata(param, tiles);
     ConnectRoadArtifacts(param, tiles);
     ConnectRoadArtifacts(param, tiles);
 }
Ejemplo n.º 15
0
        private void ConnectRoadArtifacts(GeneratorParameter param, Tile[,] tiles)
        {
            for (int x = 0; x < param.size.X; x++)
            {
                for (int y = 0; y < param.size.Y; y++)
                {
                    Tile t = tiles[x, y];

                    if (t.type != TileType.Nothing || !t.IsRoadPlaceable())
                    {
                        continue;
                    }

                    int  roadNeighbours = 0;
                    bool wasLastRoad    = IsInRange(x - 1, y) && tiles[x - 1, y].type == TileType.Road;
                    bool loops          = false;

                    if (IsInRange(x, y - 1) && tiles[x, y - 1].type == TileType.Road)
                    {
                        roadNeighbours++;
                        if (wasLastRoad && IsInRange(x - 1, y - 1) && tiles[x - 1, y - 1].type == TileType.Road)
                        {
                            loops = true;
                        }
                        wasLastRoad = true;
                    }
                    else
                    {
                        wasLastRoad = false;
                    }

                    if (IsInRange(x + 1, y) && tiles[x + 1, y].type == TileType.Road)
                    {
                        roadNeighbours++;
                        if (wasLastRoad && IsInRange(x + 1, y - 1) && tiles[x + 1, y - 1].type == TileType.Road)
                        {
                            loops = true;
                        }
                        wasLastRoad = true;
                    }
                    else
                    {
                        wasLastRoad = false;
                    }

                    if (IsInRange(x, y + 1) && tiles[x, y + 1].type == TileType.Road)
                    {
                        roadNeighbours++;
                        if (wasLastRoad && IsInRange(x + 1, y + 1) && tiles[x + 1, y + 1].type == TileType.Road)
                        {
                            loops = true;
                        }
                        wasLastRoad = true;
                    }
                    else
                    {
                        wasLastRoad = false;
                    }

                    if (IsInRange(x - 1, y) && tiles[x - 1, y].type == TileType.Road)
                    {
                        roadNeighbours++;
                        if (wasLastRoad && IsInRange(x - 1, y + 1) && tiles[x - 1, y + 1].type == TileType.Road)
                        {
                            loops = true;
                        }
                        wasLastRoad = true;
                    }
                    else
                    {
                        wasLastRoad = false;
                    }


                    if (roadNeighbours > 1 && !loops)
                    {
                        t.type       = TileType.Road;
                        t.onTopIndex = 0;
                        //t.color = Color.Aquamarine;
                    }
                }
            }
        }
        /// <summary>
        /// Auto tiling the onTopIndex for the road tiles. Based on the four directional neighbour tiles calculate the roadDir index.
        /// </summary>
        private void CalculateCorrectRoadTile(GeneratorParameter param, Tile[,] tiles)
        {
            bool IsRoadOrBridge(int x, int y)
            {
                return(tiles[x, y].type == TileType.Road || tiles[x, y].type == TileType.Bridge);
            }

            //classic auto tile by giving the directional neighbour roads power of two values, result is a road dir index between 0 and 15.
            for (int x = 0; x < param.size.X; x++)
            {
                for (int y = 0; y < param.size.Y; y++)
                {
                    Tile t = tiles[x, y];

                    if (t.type != TileType.Bridge && t.type != TileType.Road)
                    {
                        continue;
                    }

                    int roadDir = 0;

                    if (IsInRange(x - 1, y) && IsRoadOrBridge(x - 1, y))
                    {
                        roadDir += 8;
                    }

                    if (IsInRange(x + 1, y) && IsRoadOrBridge(x + 1, y))
                    {
                        roadDir += 2;
                    }

                    if (IsInRange(x, y - 1) && IsRoadOrBridge(x, y - 1))
                    {
                        roadDir += 1;
                    }

                    if (IsInRange(x, y + 1) && IsRoadOrBridge(x, y + 1))
                    {
                        roadDir += 4;
                    }

                    int slope = t.GetSlopeIndex();
                    if (slope != 0)
                    {
                        if (!(slope == 6 && roadDir == 10 ||
                              slope == 12 && roadDir == 5 ||
                              slope == 9 && roadDir == 10 ||
                              slope == 3 && roadDir == 5))
                        {
                            //on these slopes roads can not be placed. And it should not happen in the first place.
                            t.type = TileType.Nothing;
                            continue;
                        }
                    }
                    t.onTopIndex = roadDir;
                }
            }

            //Special case: check if a curve tile could be a diagonal tile.
            for (int x = 0; x < param.size.X; x++)
            {
                for (int y = 0; y < param.size.Y; y++)
                {
                    if (tiles[x, y].type != TileType.Road)
                    {
                        continue;
                    }

                    int roadDir = tiles[x, y].onTopIndex;

                    if (roadDir == 9 || roadDir == 6 || roadDir == 3 || roadDir == 12)
                    {
                        int expectedConnectionRoadDir1 = connectedTo[roadDir];
                        int expectedConnectionRoadDir2 = changeTo[expectedConnectionRoadDir1];
                        int count = 0;
                        foreach (Point p in GeneratorHelper.IterateNeighboursFourDir(x, y))
                        {
                            if (tiles[p.X, p.Y].type == TileType.Road &&
                                (tiles[p.X, p.Y].onTopIndex == expectedConnectionRoadDir1 ||
                                 tiles[p.X, p.Y].onTopIndex == expectedConnectionRoadDir2))
                            {
                                count += 1;
                            }
                        }
                        //if one or two tiles with expected road dir, change the road.
                        if (count == 1 || count == 2)
                        {
                            tiles[x, y].onTopIndex = changeTo[roadDir];
                        }
                    }
                }
            }
        }
        public void Apply(GeneratorParameter param, Tile[,] tiles)
        {
            CalculateCorrectRoadTile(param, tiles);

            SetRoomsToTile(tiles);
        }
Ejemplo n.º 18
0
    public List <GeneratorParameter> FindParameters(DaneshWindow d, MonoBehaviour b)
    {
        // Debug.Log("Searching for parameters... "+d.metricList.Count+" metrics found.");
        List <GeneratorParameter> res = new List <GeneratorParameter>();

        //Collect a control sample set
        List <float>   metricAverages = new List <float>();
        List <float[]> stdev_samples  = new List <float[]>();
        List <float>   stdev          = new List <float>();

        for (int i = 0; i < d.metricList.Count; i++)
        {
            metricAverages.Add(0);
            stdev_samples.Add(new float[numSamples]);
        }

        for (int s = 0; s < numSamples; s++)
        {
            object output = d.GenerateContent();
            for (int i = 0; i < d.metricList.Count; i++)
            {
                GeneratorMetric m  = d.metricList[i];
                float           sc = (float)m.method.Invoke(null, new object[] { output });
                metricAverages[i]  += sc;
                stdev_samples[i][s] = sc;
            }
        }

        //Calculate averages and standard deviation
        for (int i = 0; i < d.metricList.Count; i++)
        {
            metricAverages[i] = metricAverages[i] / numSamples;
            // Debug.Log("Average for metric "+i+": "+metricAverages[i]);
            float sqdif = 0;
            foreach (float s in stdev_samples[i])
            {
                sqdif += Mathf.Pow(s - metricAverages[i], 2f);
            }
            sqdif = sqdif / numSamples;
            stdev.Add(Mathf.Sqrt(sqdif));
            // Debug.Log("Standard deviation for metric "+i+": "+stdev[i]);
        }

        foreach (FieldInfo field in d.generator.GetType().GetFields())
        {
            bool useParam = true;
            foreach (Attribute _attr in field.GetCustomAttributes(false))
            {
                if (_attr is TunableAttribute)
                {
                    //We already know this parameter is good so don't worry.
                    useParam = false;
                }
            }
            if (!useParam)
            {
                continue;
            }

            //Remember the original value
            object original_value = field.GetValue(b);
            //Change the value to something
            List <object> sampleValues = GetSampleValues(field, b);
            // Debug.Log(sampleValues.Count+" sample values found");
            //For each sample value, change the field to that value, run samples, get average
            foreach (object o in sampleValues)
            {
                field.SetValue(b, o);

                List <float> sampleData = new List <float>();
                for (int i = 0; i < d.metricList.Count; i++)
                {
                    sampleData.Add(0);
                }
                bool sampleFailed = false;
                for (int _ = 0; _ < numSamples; _++)
                {
                    try{
                        object output = d.GenerateContent();
                        for (int i = 0; i < d.metricList.Count; i++)
                        {
                            GeneratorMetric m = d.metricList[i];
                            sampleData[i] += (float)m.method.Invoke(null, new object[] { output });
                        }
                    }
                    catch (Exception e) {
                        //This failed, check the next value
                        sampleFailed = true;
                        break;
                    }
                }
                if (sampleFailed)
                {
                    continue;
                }
                //Did this change any of the metrics more than one standard deviation from the original sampling?
                bool nextParam = false;
                for (int i = 0; i < d.metricList.Count; i++)
                {
                    sampleData[i] = sampleData[i] / numSamples;
                    if (Mathf.Abs(sampleData[i] - metricAverages[i]) > stdev[i])
                    {
                        Debug.Log("Parameter " + field.Name + " may have an impact on metrics");
                        nextParam = true;
                        GeneratorParameter p = new GeneratorParameter(field.Name, original_value, original_value, original_value, field, b);
                        p.locked = true;
                        res.Add(p);
                        break;
                    }
                }
                if (nextParam)
                {
                    field.SetValue(b, original_value);
                    break;
                }
            }

            field.SetValue(b, original_value);
        }

        return(res);
    }
        private void CreateSlopes(GeneratorParameter param, Tile[,] tiles)
        {
            bool AllHeightsHigher(int[] heights, int than)
            {
                for (int i = 0; i < heights.Length; i++)
                {
                    if (heights[i] <= than)
                    {
                        return(false);
                    }
                }
                return(true);
            }

            bool HasSlopeUp(SlopeIndex slope, int x, int y)
            {
                int h = tiles[x, y].GetMaxHeight();

                switch (slope)
                {
                case SlopeIndex.North:
                    if (IsInRange(x, y - 1))
                    {
                        int height = tiles[x, y - 1].GetMaxHeight();

                        return((height == h + 1 || height == h + 2) && AllHeightsHigher(tiles[x, y - 1].height, h));
                    }
                    else
                    {
                        return(false);
                    }

                case SlopeIndex.East:
                    if (IsInRange(x + 1, y))
                    {
                        int height = tiles[x + 1, y].GetMaxHeight();
                        return((height == h + 1 || height == h + 2) && AllHeightsHigher(tiles[x + 1, y].height, h));
                    }
                    else
                    {
                        return(false);
                    }

                case SlopeIndex.South:
                    if (IsInRange(x, y + 1))
                    {
                        int height = tiles[x, y + 1].GetMaxHeight();
                        return((height == h + 1 || height == h + 2) && AllHeightsHigher(tiles[x, y + 1].height, h));
                    }
                    else
                    {
                        return(false);
                    }

                case SlopeIndex.West:
                    if (IsInRange(x - 1, y))
                    {
                        int height = tiles[x - 1, y].GetMaxHeight();
                        return((height == h + 1 || height == h + 2) && AllHeightsHigher(tiles[x - 1, y].height, h));
                    }
                    else
                    {
                        return(false);
                    }
                }

                return(false);
            }

            // check for 3 higher neighbours -> make it higher
            for (int x = 0; x < param.size.X; x++)
            {
                for (int y = 0; y < param.size.Y; y++)
                {
                    int h = tiles[x, y].GetMaxHeight();
                    if (!tiles[x, y].AllHeightsAreSame())
                    {
                        continue;
                    }

                    int higher = 0;
                    foreach (Point p in IterateNeighboursEightDir(x, y))
                    {
                        if (p.X == x || p.Y == y)
                        {
                            if (tiles[p.X, p.Y].GetMaxHeight() > h)
                            {
                                higher++;
                            }
                        }
                    }

                    if (higher >= 3)
                    {
                        for (int i = 0; i < tiles[x, y].height.Length; i++)
                        {
                            tiles[x, y].height[i] += 1;
                        }
                    }
                }
            }


            //check for 3 corner slops
            for (int x = 0; x < param.size.X; x++)
            {
                for (int y = 0; y < param.size.Y; y++)
                {
                    /*if(tiles[x, y].type == TileType.Water)
                     * {
                     *  tiles[x, y].height = new int[] { 5, 5, 5, 5 };
                     * }*/

                    if (!tiles[x, y].AllHeightsAreSame())
                    {
                        continue;
                    }

                    int directions = 0;

                    if (HasSlopeUp(SlopeIndex.North, x, y))
                    {
                        directions += (int)SlopeIndex.North;
                    }

                    if (HasSlopeUp(SlopeIndex.East, x, y))
                    {
                        directions += (int)SlopeIndex.East;
                    }

                    if (HasSlopeUp(SlopeIndex.South, x, y))
                    {
                        directions += (int)SlopeIndex.South;
                    }

                    if (HasSlopeUp(SlopeIndex.West, x, y))
                    {
                        directions += (int)SlopeIndex.West;
                    }


                    if (directions > 0)
                    {
                        if (directions == 3 || directions == 6 || directions == 12 || directions == 9)
                        {
                            int oldH = tiles[x, y].height[0];
                            for (int i = 0; i < 4; i++)
                            {
                                tiles[x, y].height[i] += 1;
                            }

                            if (directions == 3)
                            {
                                tiles[x, y].height[3]--;
                            }

                            if (directions == 6)
                            {
                                tiles[x, y].height[0]--;
                            }

                            if (directions == 12)
                            {
                                tiles[x, y].height[1]--;
                            }

                            if (directions == 9)
                            {
                                tiles[x, y].height[2]--;
                            }
                        }
                    }
                }
            }


            //check for ramp slopes
            for (int x = 0; x < param.size.X; x++)
            {
                for (int y = 0; y < param.size.Y; y++)
                {
                    if (!tiles[x, y].AllHeightsAreSame() || tiles[x, y].type == TileType.Water)
                    {
                        continue;
                    }

                    int directions = 0;


                    if (HasSlopeUp(SlopeIndex.North, x, y))
                    {
                        directions += (int)SlopeIndex.North;
                    }
                    else if (HasSlopeUp(SlopeIndex.East, x, y))
                    {
                        directions += (int)SlopeIndex.East;
                    }
                    else if (HasSlopeUp(SlopeIndex.South, x, y))
                    {
                        directions += (int)SlopeIndex.South;
                    }
                    else if (HasSlopeUp(SlopeIndex.West, x, y))
                    {
                        directions += (int)SlopeIndex.West;
                    }

                    if (directions > 0)
                    {
                        int oldH = tiles[x, y].height[0];
                        for (int i = 0; i < 4; i++)
                        {
                            tiles[x, y].height[i] -= 1;
                        }



                        if ((directions & 1) == 0)  //north
                        {
                            tiles[x, y].height[2] += 1;
                            tiles[x, y].height[3] += 1;
                        }

                        if ((directions & 2) == 0)
                        {
                            tiles[x, y].height[0] += 1;
                            tiles[x, y].height[3] += 1;
                        }

                        if ((directions & 4) == 0)
                        {
                            tiles[x, y].height[1] += 1;
                            tiles[x, y].height[0] += 1;
                        }

                        if ((directions & 8) == 0)
                        {
                            tiles[x, y].height[2] += 1;
                            tiles[x, y].height[1] += 1;
                        }
                    }
                }
            }


            // check for one-corner slops
            for (int x = 0; x < param.size.X; x++)
            {
                for (int y = 0; y < param.size.Y; y++)
                {
                    int h = tiles[x, y].GetMaxHeight();
                    if (!tiles[x, y].AllHeightsAreSame() || tiles[x, y].type == TileType.Water)
                    {
                        continue;
                    }

                    //tiles[x, y].color = Color.Red;

                    if (IsInRange(x - 1, y - 1))
                    {
                        int height = tiles[x - 1, y - 1].GetMaxHeight();
                        if (AllHeightsHigher(tiles[x - 1, y - 1].height, h) && (height == h + 1 || height == h + 2))
                        {
                            tiles[x, y].height[0] += 1;
                            continue;
                        }
                    }


                    if (IsInRange(x - 1, y + 1))
                    {
                        int height = tiles[x - 1, y + 1].GetMaxHeight();
                        if (AllHeightsHigher(tiles[x - 1, y + 1].height, h) && (height == h + 1 || height == h + 2))
                        {
                            tiles[x, y].height[3] += 1;
                            continue;
                        }
                    }

                    if (IsInRange(x + 1, y + 1))
                    {
                        int height = tiles[x + 1, y + 1].GetMaxHeight();
                        if (AllHeightsHigher(tiles[x + 1, y + 1].height, h) && (height == h + 1 || height == h + 2))
                        {
                            tiles[x, y].height[2] += 1;
                            continue;
                        }
                    }

                    if (IsInRange(x + 1, y - 1))
                    {
                        int height = tiles[x + 1, y - 1].GetMaxHeight();
                        if (AllHeightsHigher(tiles[x + 1, y - 1].height, h) && (height == h + 1 || height == h + 2))
                        {
                            tiles[x, y].height[1] += 1;
                            continue;
                        }
                    }
                }
            }
        }