/* * Sphere Search is done iteratively in “Spheres” and is used to attempt to trace a path * from the beginning to the end of the game. The first sphere s is simply all locations which are * reachable from the beginning of the game. As it searches these locations, it adds key items * found to a temporary set; we do not want those items to affect reachability until the next sphere * iteration so we do not yet add them to I. After all reachable locations have been found, sphere s * is added to the list of spheres S, and all items in the temporary set are added to I. It then * iterates again with a new sphere s. */ public SphereSearchInfo SphereSearch(WorldGraph world) { SphereSearchInfo output = new SphereSearchInfo(); output.Spheres = new List <WorldGraph>(); List <Item> owneditems = new List <Item>(); //Initial sphere s0 includes items reachable from the start of the game WorldGraph s0 = GetReachableLocations(world, owneditems); owneditems = s0.CollectMajorItems(); //Collect all major items reachable from the start of the game output.Spheres.Add(s0); //Add initial sphere to sphere list //sx indicates every sphere after the first. Any major items found in s0 means sx should be bigger. WorldGraph sx = GetReachableLocations(world, owneditems); int temp = owneditems.Where(x => x.Importance >= 2).Count(); //Temp is the count of previously owned major items owneditems = sx.CollectAllItems(); //Used to find new count of major items //If counts are equal then no new major items found, stop searching while (owneditems.Where(x => x.Importance >= 2).Count() > temp) //If new count is not greater than old count, that means all currently reachable locations have been found { output.Spheres.Add(sx); //If new locations found, add to sphere list //Take the same steps taken before the loop: Get new reachable locations, collect new major items, and check to see if new count is larger than old count sx = GetReachableLocations(world, owneditems); temp = owneditems.Where(x => x.Importance >= 2).Count(); //Only want to consider count of major items owneditems = sx.CollectAllItems(); } //At this point, either a dead end has been found or all locations have been discovered //If the goal item is in the list of owned items, means the end has been found and thus the game is completable output.Completable = owneditems.Count(x => x.Name == world.GoalItemName) > 0; return(output); }
//Calculates the bias for a given permutation of items in the world graph public BiasOutput CalcDistributionBias(WorldGraph world) { //Get total counts for majors and items so a percent can be calculated int totalmajorcount = world.Items.Where(x => x.Importance >= 2).Count(); int totallocationcount = world.GetLocationCount(); //Find spheres in randomized world Search searcher = new Search(); List <WorldGraph> spheres = searcher.SphereSearch(world).Spheres; //Initialize variables to use in the loop double[] spherebias = new double[spheres.Count]; int rollingmajorcount = 0; int rollinglocationcount = 0; for (int i = 0; i < spheres.Count; i++) { WorldGraph sphere = spheres[i]; //Check the number of major items in the sphere, not counting those in previous spheres int majoritemcount = sphere.CollectMajorItems().Count - rollingmajorcount; rollingmajorcount += majoritemcount; //Check the number of locations in the sphere, not counting those in previous spheres int locationcount = sphere.GetLocationCount() - rollinglocationcount; rollinglocationcount += locationcount; //Find the percentage of major items and locations in this sphere double majorpercent = majoritemcount / (double)totalmajorcount; double locationpercent = locationcount / (double)totallocationcount; //Now find the difference between the two percentages double difference = majorpercent - locationpercent; spherebias[i] = difference; } //Now that we have a list of biases find the sum of their absolute values to determine absolute bias //Also use the positivity of bias before and after the median to determine bias direction double overallsum = 0; double beforesum = 0; //Sums bias before median so a bias direction can be computed double aftersum = 0; //Sums bias after median so a bias direction can be computed bool even = spherebias.Length % 2 == 0; //Want to check if even so can determine when after the median is int median = spherebias.Length / 2; //Use median to determine bias direction for (int i = 0; i < spherebias.Length; i++) { overallsum += Math.Abs(spherebias[i]); if (i < median) //Before median, add to that sum { beforesum += spherebias[i]; } else if ((i >= median && even) || (i > median && !even)) //After median, add to that sum. If it's even then >= makes sense so every index is checked, if odd then skip middle { aftersum = spherebias[i]; } } //Package output and return BiasOutput output = new BiasOutput(); output.biasvalue = overallsum / spherebias.Length; //Get average of absolute value to determine overall bias output.direction = beforesum < aftersum; //If bias is more positive before the median, the direction is toward the beginning, otherwise toward end return(output); }