Advertisement
spacechase0

SDV location distance

Nov 19th, 2017
210
0
Never
Not a member of Pastebin yet? Sign Up, it unlocks many cool features!
C# 6.46 KB | None | 0 0
  1.     // Algorithm for calculating "distance"
  2.     public static class DistanceCalculator
  3.     {
  4.         // We remember the calculations for all static maps, since they *shouldnt* change during gameplay
  5.         private static Dictionary<string, double> _Cache = new Dictionary<string, double>();
  6.         // The extra "distance" added for every floor down into the skull cave (Always 121 or more floors)
  7.         private const double SkullDepthPenalty = 0.2;
  8.         // The extra "distance" added for every floor down into mines (Never more then 120 floors)
  9.         private const double MineDepthPenalty = 0.1;
  10.         // The extra "distance" added for every warp that has to be used
  11.         private const double DistancePenalty = 1;
  12.         // The name of the "leyline" map property to pay attention to
  13.         private const string LeylineProperty = "AlchemyLeyline";
  14.  
  15.  
  16.         private class Entry
  17.         {
  18.             public GameLocation loc;
  19.             public double dist;
  20.  
  21.             public Entry(GameLocation loc, double dist)
  22.             {
  23.                 this.loc = loc;
  24.                 this.dist = dist;
  25.             }
  26.         }
  27.  
  28.         public static void Explore()
  29.         {
  30.             _Cache.Clear();
  31.             foreach ( var loc in Game1.locations )
  32.             {
  33.                 if (loc.map.Properties.ContainsKey(LeylineProperty))
  34.                     ExploreFrom(loc);
  35.             }
  36.         }
  37.         private static void ExploreFrom( GameLocation start )
  38.         {
  39.             Dictionary<string, double> did = new Dictionary<string, double>();
  40.             Queue<Entry> q = new Queue<Entry>();
  41.             q.Enqueue(new Entry(start, start.map.Properties[LeylineProperty]));
  42.             did.Add(start.name, start.map.Properties[LeylineProperty]);
  43.             while ( q.Count > 0 )
  44.             {
  45.                 var entry = q.Dequeue();
  46.                 foreach ( var warp in entry.loc.warps )
  47.                 {
  48.                     if ( !did.ContainsKey( warp.TargetName ) || entry.dist + DistancePenalty < did[ warp.TargetName ] )
  49.                     {
  50.                         did[warp.TargetName] = entry.dist + DistancePenalty;
  51.                         q.Enqueue(new Entry(Game1.getLocationFromName(warp.TargetName), entry.dist + DistancePenalty));
  52.                     }
  53.                 }
  54.                 for (int x = 0; x < entry.loc.map.Layers[0].LayerSize.Width; x++)
  55.                 {
  56.                     for (int y = 0; y < entry.loc.map.Layers[0].LayerSize.Height; y++)
  57.                     {
  58.                         string prop = entry.loc.doesTileHaveProperty(x, y, "Action", "Buildings");
  59.                         if (prop == null)
  60.                             continue;
  61.                         switch (prop)
  62.                         {
  63.                             case "WarpCommunityCenter":
  64.                             case "WarpGreenhouse":
  65.                                 string targetName = prop.Substring(4);
  66.                                 if (!did.ContainsKey(targetName) || did[targetName] < entry.dist + DistancePenalty)
  67.                                 {
  68.                                     did[targetName] = entry.dist + DistancePenalty;
  69.                                     q.Enqueue(new Entry(Game1.getLocationFromName(targetName), entry.dist + DistancePenalty));
  70.                                 }
  71.                                 break;
  72.                             case "EnterSewer":
  73.                                 targetName = "Sewer";
  74.                                 if (!did.ContainsKey(targetName) || did[targetName] < entry.dist + DistancePenalty)
  75.                                 {
  76.                                     did[targetName] = entry.dist + DistancePenalty;
  77.                                     q.Enqueue(new Entry(Game1.getLocationFromName(targetName), entry.dist + DistancePenalty));
  78.                                 }
  79.                                 break;
  80.                             case "WizardHatch":
  81.                                 targetName = "WizardHouseBasement";
  82.                                 if (!did.ContainsKey(targetName) || did[targetName] < entry.dist + DistancePenalty)
  83.                                 {
  84.                                     did[targetName] = entry.dist + DistancePenalty;
  85.                                     q.Enqueue(new Entry(Game1.getLocationFromName(targetName), entry.dist + DistancePenalty));
  86.                                 }
  87.                                 break;
  88.                             default:
  89.                                 var props = prop.Split(' ');
  90.                                 if ((props[0].Equals("Warp") || props[0].Equals("LockedDoorWarp") || props[0].Equals("WarpMensLocker") || props[0].Equals("WarpWomensLocker")) && Game1.getLocationFromName(props[3]) != null)
  91.                                 {
  92.                                     Log.trace(prop);
  93.                                     if (!did.ContainsKey(props[3]) || entry.dist + DistancePenalty < did[props[3]])
  94.                                     {
  95.                                         did[props[3]] = entry.dist + DistancePenalty;
  96.                                         q.Enqueue(new Entry(Game1.getLocationFromName(props[3]), entry.dist + DistancePenalty));
  97.                                     }
  98.                                 }
  99.                                 break;
  100.                         }
  101.                     }
  102.                 }
  103.             }
  104.  
  105.             foreach ( var entry in did )
  106.             {
  107.                 if (!_Cache.ContainsKey(entry.Key) || _Cache[entry.Key] > entry.Value)
  108.                     _Cache[entry.Key] = entry.Value;
  109.             }
  110.         }
  111.  
  112.         public static double GetPathDistance( GameLocation loc )
  113.         {
  114.             if (_Cache.Count == 0)
  115.                 Explore();
  116.  
  117.             /*
  118.             Log.trace(_Cache.Count + " " + Game1.locations.Count);
  119.             foreach ( var val in _Cache )
  120.             {
  121.                 Log.trace(val.Key + " = " + val.Value);
  122.             }*/
  123.  
  124.             var dist = double.MaxValue;
  125.             if (_Cache.ContainsKey(loc.name))
  126.                 dist = _Cache[loc.name];
  127.            
  128.             if ( loc is StardewValley.Locations.MineShaft shaft )
  129.             {
  130.                 if (shaft.mineLevel > 120) // SkullCave
  131.                     dist += shaft.mineLevel * SkullDepthPenalty;
  132.                 else // Mines
  133.                     dist += shaft.mineLevel * MineDepthPenalty;
  134.             }
  135.  
  136.             return dist;
  137.         }
  138.     }
Advertisement
Add Comment
Please, Sign In to add comment
Advertisement