Esempio n. 1
0
        //Experiment space
        static void Main(string[] args)
        {
            Fill       filler   = new Fill();
            Search     searcher = new Search();
            Statistics stats    = new Statistics();

            ////Uncomment to test different complexity measures and generate many worlds with different parameters.
            //double[] testaverages = new double[5];
            //for (int regioncount = 10; regioncount <= 50; regioncount += 5)
            //{
            //    for (int itemcount = 5; itemcount <= Math.Min(regioncount, 30); itemcount += 5)
            //    {
            //        List<TestComplexityOutput> complexity = AverageComplexity(regioncount, itemcount);
            //        Console.WriteLine("Regions: " + regioncount + ", Items: " + itemcount);
            //        Console.WriteLine("Sum: " + complexity.Average(x => x.sum));
            //        Console.WriteLine("Avg: " + complexity.Average(x => x.average));
            //        Console.WriteLine("Max: " + complexity.Average(x => x.max));
            //        Console.WriteLine("SOS: " + complexity.Average(x => x.sumofsquares));
            //        Console.WriteLine("Avg50: " + complexity.Average(x => x.top50));
            //        Console.WriteLine("Avg75: " + complexity.Average(x => x.top75));
            //        Console.Write(Environment.NewLine);
            //    }
            //}

            //Loop through each algorithm set to be used and each world in the list, performing specified algorithm on specified world and recording information about the result.
            string[] algos = { "Random", "Forward", "Assumed" };
            foreach (string worldname in testworlds)
            {
                DateTime   expstart = DateTime.Now;
                string     jsontext = File.ReadAllText("../../../WorldGraphs/" + worldname + ".json");
                WorldGraph world    = JsonConvert.DeserializeObject <WorldGraph>(jsontext);
                //Loop to perform fill algorithms
                for (int i = 0; i < 3; i++) //0 = Random, 1 = Forward, 2 = Assumed
                {
                    if (dotests[i])
                    {
                        int savecounter = 0;
                        int countofexp  = db.Results.Count(x => x.Algorithm == algos[i] && x.World == worldname);
                        while (countofexp < trials) //Go until there are trial number of records in db
                        {
                            InterestingnessOutput intstat = new InterestingnessOutput();
                            double difference             = -1;
                            while (true)                                    //If something goes wrong in playthrough search, may need to retry
                            {
                                WorldGraph  input           = world.Copy(); //Copy so that world is not passed by reference and overwritten
                                List <Item> majoritempool   = input.Items.Where(x => x.Importance == 2).ToList();
                                List <Item> minoritempool   = input.Items.Where(x => x.Importance < 2).ToList();
                                WorldGraph  randomizedgraph = new WorldGraph();
                                DateTime    start           = DateTime.Now; //Start timing right before algorithm
                                //Decide which algo to use based on i
                                switch (i)
                                {
                                case 0:
                                    randomizedgraph = filler.RandomFill(input, majoritempool);
                                    break;

                                case 1:
                                    randomizedgraph = filler.ForwardFill(input, majoritempool);
                                    break;

                                case 2:
                                    randomizedgraph = filler.AssumedFill(input, majoritempool);
                                    break;
                                }
                                randomizedgraph = filler.RandomFill(randomizedgraph, minoritempool); //Use random for minor items always since they don't matter
                                //Calculate metrics
                                DateTime end = DateTime.Now;
                                difference = (end - start).TotalMilliseconds;
                                try
                                {
                                    intstat = stats.CalcDistributionInterestingness(randomizedgraph);
                                    break; //Was successful, continue
                                }
                                catch { } //Something went wrong, retry fill from scratch
                                ////Uncomment to print the spheres of the result.
                                //SphereSearchInfo output = searcher.SphereSearch(randomizedgraph);
                                //Print_Spheres(output);
                            }
                            //Store result in database
                            Result result = new Result();
                            result.Algorithm       = algos[i];
                            result.World           = worldname;
                            result.Completable     = intstat.completable;
                            result.ExecutionTime   = difference;
                            result.Bias            = intstat.bias.biasvalue;
                            result.BiasDirection   = intstat.bias.direction;
                            result.Interestingness = intstat.interestingness;
                            result.Fun             = intstat.fun;
                            result.Challenge       = intstat.challenge;
                            result.Satisfyingness  = intstat.satisfyingness;
                            result.Boredom         = intstat.boredom;
                            db.Entry(result).State = EntityState.Added;
                            savecounter++;
                            if (savecounter >= 1000) //Save every 1000 results processed
                            {
                                db.SaveChanges();
                                savecounter = 0;
                            }
                            countofexp++;
                        }
                        db.SaveChanges(); //Save changes when combo of algo and world is done
                    }
                }
                DateTime expend        = DateTime.Now;
                double   expdifference = (expend - expstart).TotalMinutes;
                Console.WriteLine("Time to perform " + trials + " iterations for world " + worldname + ": " + expdifference + " minutes"); //Print how long this world took to do
            }
            Console.ReadLine();
        }
Esempio n. 2
0
        /*
         * Score info about human-like playthrough
         * Several considerations:
         * 1. Number of locations collected for each region traversed
         * 2. Number of regions traversed between finding major or helpful items
         * 3. Number of regions traversed between finding major items
         */
        public InterestingnessOutput ScorePlaythrough(WorldGraph world, PlaythroughInfo input, BiasOutput biasinfo)
        {
            //First, calculate fun metric, which desires a consistently high rate of checking item locations
            Queue <int>   RollingAvg = new Queue <int>();
            List <double> avgs       = new List <double>();
            List <bool>   highavg    = new List <bool>();

            foreach (int num in input.LocationsPerTraversal)
            {
                if (RollingAvg.Count == 5) //Rolling average of last 5 values
                {
                    RollingAvg.Dequeue();
                }
                RollingAvg.Enqueue(num);
                double avg = RollingAvg.Average();
                highavg.Add(avg >= 1); //If average is above 1, considered high enough to be fun, so add true to list, else add false
                avgs.Add(avg);
            }
            double fun = (double)highavg.Count(x => x) / highavg.Count(); //Our "Fun" score is the percentage of high values in the list
            //Next calculate challenge metric, which desires rate at which items are found to be within some optimal range so that it is not too often or too rare
            double LocationToItemRatio = (double)world.GetLocationCount() / world.Items.Where(x => x.Importance == 2).Count();
            int    low  = (int)Math.Floor(LocationToItemRatio * .5);
            int    high = (int)Math.Ceiling(LocationToItemRatio * 1.5);

            RollingAvg = new Queue <int>();
            avgs       = new List <double>();
            List <bool> avginrange = new List <bool>();

            foreach (int num in input.BetweenMajorList)
            {
                if (RollingAvg.Count == 3) //Tighter rolling average of last 3 values
                {
                    RollingAvg.Dequeue();
                }
                RollingAvg.Enqueue(num);
                double avg = RollingAvg.Average();
                avginrange.Add(low <= avg && avg <= high); //If value is within range rather than too high or too low, add true to list to indicate it is within a good range
                avgs.Add(avg);
            }
            double challenge = (double)avginrange.Count(x => x) / avginrange.Count(); //Our "Challenge" score is the percentage of values in the list within desirable range
            //Next calculate satisfyingness metric based on how many locations are unlocked when an item is found
            double      LocationToItemRatioWithoutInitial = (double)(world.GetLocationCount() - input.InitialReachableCount) / world.Items.Where(x => x.Importance == 2).Count();
            int         satthreshold = (int)Math.Floor(LocationToItemRatioWithoutInitial); //Set threshold as number of not-immediately-accessible locations divided by number of major items
            List <bool> SatisfyingReachesThreshold = new List <bool>();

            foreach (int num in input.LocationsUnlockedPerMajorFound)
            {
                SatisfyingReachesThreshold.Add(num >= satthreshold);
            }
            double satisfyingness = (double)SatisfyingReachesThreshold.Count(x => x) / SatisfyingReachesThreshold.Count(); //Our "Satisfyingness" score is the percentage of values above the desired threshold
            //Finally calculate boredom by observing regions which were visited more often than is expected
            //First get a count of how many times each region was visited
            List <int> visitcounts = new List <int>();

            foreach (Region r in world.Regions)
            {
                visitcounts.Add(input.Traversed.Count(x => x.Name == r.Name));
            }
            //Calculate threshold with max number of times region should be visited being the number of traversals divided by number of regions
            double      TraversedToRegionRatio = (double)input.Traversed.Count() / world.Regions.Count();
            int         borethreshold          = (int)Math.Ceiling(TraversedToRegionRatio);
            List <bool> VisitsAboveThreshold   = new List <bool>();

            foreach (int num in visitcounts)
            {
                VisitsAboveThreshold.Add(num > borethreshold);                                          //Again as before, add list of bool when value is above threshold
            }
            double boredom = (double)VisitsAboveThreshold.Count(x => x) / VisitsAboveThreshold.Count(); //Our "Boredom" score is the percentage of values above the desired threshold
            //Add calculated stats to output. If a result is NaN (possible when not completable) save as -1
            InterestingnessOutput output = new InterestingnessOutput();

            output.bias           = biasinfo;
            output.fun            = double.IsNaN(fun) ? -1 : fun;
            output.challenge      = double.IsNaN(challenge) ? -1 : challenge;
            output.satisfyingness = double.IsNaN(satisfyingness) ? -1 : satisfyingness;
            output.boredom        = double.IsNaN(boredom) ? -1 : boredom;
            //Use stats to calculate final interestingness score
            //Each score is a double in the range [0, 1]
            //Multiply each score (or its 1 - score if low score is desirable) by its percentage share of the total
            double biasscore      = (1 - output.bias.biasvalue) * .2;
            double funscore       = output.fun * .2;
            double challengescore = output.challenge * .2;
            double satscore       = output.satisfyingness * .2;
            double borescore      = (1 - output.boredom) * .2;
            double intscore       = biasscore + funscore + challengescore + satscore + borescore;

            //If any components are NaN, consider interestingness as NaN as well
            if (double.IsNaN(fun) || double.IsNaN(challenge) || double.IsNaN(satisfyingness) || double.IsNaN(boredom))
            {
                output.interestingness = -1;
            }
            else
            {
                output.interestingness = intscore;
            }
            output.completable = input.Completable;
            return(output);
        }
Esempio n. 3
0
        //Experiment space
        static void Main(string[] args)
        {
            Fill       filler   = new Fill();
            Search     searcher = new Search();
            Statistics stats    = new Statistics();

            //string testjsontext = File.ReadAllText("../../../WorldGraphs/World3.json");
            //WorldGraph testworld = JsonConvert.DeserializeObject<WorldGraph>(testjsontext);

            //double[] testaverages = new double[5];
            //for (int regioncount = 10; regioncount <= 50; regioncount += 5)
            //{
            //    for (int itemcount = 5; itemcount <= Math.Min(regioncount, 30); itemcount += 5)
            //    {
            //        List<TestComplexityOutput> complexity = AverageComplexity(regioncount, itemcount);
            //        Console.WriteLine("Regions: " + regioncount + ", Items: " + itemcount);
            //        Console.WriteLine("Sum: " + complexity.Average(x => x.sum));
            //        Console.WriteLine("Avg: " + complexity.Average(x => x.average));
            //        Console.WriteLine("Max: " + complexity.Average(x => x.max));
            //        Console.WriteLine("SOS: " + complexity.Average(x => x.sumofsquares));
            //        Console.WriteLine("Avg50: " + complexity.Average(x => x.top50));
            //        Console.WriteLine("Avg75: " + complexity.Average(x => x.top75));
            //        Console.Write(Environment.NewLine);
            //    }
            //}

            //string generatedjson = GenerateWorld(50, 30);

            //string jsontest = File.ReadAllText("../../../WorldGraphs/World5.json");
            //WorldGraph testworld = JsonConvert.DeserializeObject<WorldGraph>(jsontest);
            //int testlocationcount = testworld.GetLocationCount();

            //Search testsearcher = new Search();
            //testsearcher.PathsToRegion(world, world.Regions.First(x => x.Name == "Waterfall"));

            //Parser testparse = new Parser();
            //string result = testparse.Simplify("(Sword and Bow and Bow) or Has(Key,2)"); //Should be simplified to something like (Sword and Bow) or Has(Key,2)
            //string result2 = testparse.Simplify("Sword or Sword and Bow"); //Should be simplified to Sword
            ////majoritempool.RemoveAt(8);
            ////majoritempool.RemoveAt(0);
            //bool result = testparse.RequirementsMet("(Sword and Bow) or Has(Key,2)", majoritempool);

            //string testjsontext = File.ReadAllText("../../../WorldGraphs/TestWorldOriginal.json");
            //WorldGraph testworld = JsonConvert.DeserializeObject<WorldGraph>(testjsontext);
            //SphereSearchInfo testoutput = searcher.SphereSearch(testworld);
            //Print_Spheres(testoutput);

            string[] algos = { "Random", "Forward", "Assumed" };
            foreach (string worldname in testworlds)
            {
                DateTime   expstart = DateTime.Now;
                string     jsontext = File.ReadAllText("../../../WorldGraphs/" + worldname + ".json");
                WorldGraph world    = JsonConvert.DeserializeObject <WorldGraph>(jsontext);
                int        l        = world.GetLocationCount();
                //Loop to perform fill
                for (int i = 0; i < 3; i++) //0 = Random, 1 = Forward, 2 = assumed
                {
                    if (dotests[i])
                    {
                        //List<InterestingnessOutput> intstats = new List<InterestingnessOutput>();
                        //double totaltime = 0;
                        int savecounter = 0;
                        int countofexp  = db.Results.Count(x => x.Algorithm == algos[i] && x.World == worldname);
                        //int countofexp = 0;
                        while (countofexp < trials) //Go until there are trial number of records in db
                        {
                            InterestingnessOutput intstat = new InterestingnessOutput();
                            double difference             = -1;
                            while (true)                                    //If something goes wrong in playthrough search, may need to retry
                            {
                                WorldGraph  input           = world.Copy(); //Copy so that world is not passed by reference and overwritten
                                List <Item> majoritempool   = input.Items.Where(x => x.Importance == 2).ToList();
                                List <Item> minoritempool   = input.Items.Where(x => x.Importance < 2).ToList();
                                WorldGraph  randomizedgraph = new WorldGraph();
                                DateTime    start           = DateTime.Now; //Start timing right before algorithm
                                //Decide which algo to use based on i
                                switch (i)
                                {
                                case 0:
                                    randomizedgraph = filler.RandomFill(input, majoritempool);
                                    break;

                                case 1:
                                    randomizedgraph = filler.ForwardFill(input, majoritempool);
                                    break;

                                case 2:
                                    randomizedgraph = filler.AssumedFill(input, majoritempool);
                                    break;
                                }
                                randomizedgraph = filler.RandomFill(randomizedgraph, minoritempool); //Use random for minor items always since they don't matter
                                //Calculate metrics
                                DateTime end = DateTime.Now;
                                difference = (end - start).TotalMilliseconds;
                                //totaltime += difference;
                                //string randomizedjson = JsonConvert.SerializeObject(randomizedgraph);
                                //SphereSearchInfo output = searcher.SphereSearch(randomizedgraph);
                                //Print_Spheres(output);
                                try
                                {
                                    intstat = stats.CalcDistributionInterestingness(randomizedgraph);
                                    break; //Was successful, continue
                                }
                                catch { } //Something went wrong, retry fill from scratch
                            }
                            //intstats.Add(intstat);
                            //Store result in database
                            Result result = new Result();
                            result.Algorithm       = algos[i];
                            result.World           = worldname;
                            result.Completable     = intstat.completable;
                            result.ExecutionTime   = difference;
                            result.Bias            = intstat.bias.biasvalue;
                            result.BiasDirection   = intstat.bias.direction;
                            result.Interestingness = intstat.interestingness;
                            result.Fun             = intstat.fun;
                            result.Challenge       = intstat.challenge;
                            result.Satisfyingness  = intstat.satisfyingness;
                            result.Boredom         = intstat.boredom;
                            db.Entry(result).State = EntityState.Added;
                            savecounter++;
                            if (savecounter >= 1000) //Save every 1000 results processed
                            {
                                db.SaveChanges();
                                savecounter = 0;
                            }
                            countofexp++;
                        }
                        //double avgint = intstats.Where(x => x.completable).Average(x => x.interestingness);
                        //Console.WriteLine("Average interestingness for " + algos[i] + " Fill in world " + worldname + ": " + avgint);
                        //double avgbias = intstats.Where(x => x.completable).Average(x => x.bias.biasvalue);
                        //Console.WriteLine("Average bias for " + algos[i] + " Fill in world " + worldname + ": " + avgbias);
                        //double avgfun = intstats.Where(x => x.completable).Average(x => x.fun);
                        //Console.WriteLine("Average fun for " + algos[i] + " Fill in world " + worldname + ": " + avgfun);
                        //double avgchal = intstats.Where(x => x.completable).Average(x => x.challenge);
                        //Console.WriteLine("Average challenge for " + algos[i] + " Fill in world " + worldname + ": " + avgchal);
                        //double avgsat = intstats.Where(x => x.completable).Average(x => x.satisfyingness);
                        //Console.WriteLine("Average satisfyingness for " + algos[i] + " Fill in world " + worldname + ": " + avgsat);
                        //double avgbore = intstats.Where(x => x.completable).Average(x => x.boredom);
                        //Console.WriteLine("Average boredom for " + algos[i] + " Fill in world " + worldname + ": " + avgbore);
                        //double avgtime = totaltime / trials;
                        //Console.WriteLine("Average time to generate for " + algos[i] + " Fill in world " + worldname + ": " + avgtime + "ms");

                        db.SaveChanges(); //Save changes when combo of algo and world is done
                    }
                    //Console.Write(Environment.NewLine);
                }
                //Console.Write(Environment.NewLine);
                //Console.Write(Environment.NewLine);
                DateTime expend        = DateTime.Now;
                double   expdifference = (expend - expstart).TotalMinutes;
                Console.WriteLine("Time to perform " + trials + " iterations for world " + worldname + ": " + expdifference + " minutes");
            }
            Console.ReadLine();
        }