/// <summary> /// Writes all reachable modules and their (randomized) edges to the console for debugging purposes. /// </summary> public void WriteReachableToConsole() { foreach (var vertex in Reachable.Where(kvp => kvp.Value == true)) { if (!Modules.Any(v => v.WarpCode == vertex.Key)) { continue; } var module = Modules.Find(v => v.WarpCode == vertex.Key); StringBuilder sb = new StringBuilder(); sb.Append($"{module.WarpCode}"); if (module.Tags.Count > 0) { sb.Append($" [{module.Tags.Aggregate((i, j) => $"{i},{j}")}]"); } if (!string.IsNullOrWhiteSpace(module.LockedTag)) { sb.Append($" -[{module.LockedTag}]-"); } if (module.Unlock.Count > 0) { sb.Append($" =[{module.Unlock.Aggregate((i, j) => $"{i},{j}")}]="); } sb.AppendLine(); foreach (var edge in module.LeadsTo) { sb.Append($"-> {edge.WarpCode} ({RandomLookup[edge.WarpCode]})"); if (edge.Tags.Count > 0) { sb.Append($" [{edge.Tags.Aggregate((i, j) => $"{i},{j}")}]"); } if (edge.UnlockSets.Count > 0) { sb.Append(" =["); foreach (var set in edge.UnlockSets) { sb.Append($"{set.Aggregate((i, j) => $"{i},{j}")};"); } sb.Append("]="); } sb.AppendLine(); } Console.Write(sb.ToString()); } }
bool CheckMovementInitialization() { if (Selected && // we're selected Player.SelectedNode != null && // player has clicked on a map node (Player.SelectedNode.OccupiedBy == null || Player.SelectedNode.OccupiedBy.GetComponent <Hero>() == null) && // the map node is not occupied by an allied unit Reachable != null && Reachable.Contains(Player.SelectedNode)) // destination tile is reachable { // action upon completion Path.PathAction action; if (Player.SelectedNode.OccupiedBy == null) { action = Path.PathAction.Move; } else if (Player.SelectedNode.OccupiedBy.GetComponent <Monster>() != null) { action = Path.PathAction.Attack; } else { action = Path.PathAction.Use; } // if we're attacking, check whether we still can if (action == Path.PathAction.Attack) { if (AlreadyAttacked) { return(false); } AlreadyAttacked = true; } // forbid user interaction while moving Player.InvalidateSelection(); Player.Mode = Player.PlayerMode.Waiting; Player.InvalidateHighlight(Reachable); // initilize movement AStarPathFinder pf = new AStarPathFinder(action); Path = pf.Find(Tile, Player.SelectedNode); Tile.OccupiedBy = null; Tile = null; return(true); } return(false); }
/// <summary> /// Begin the reachability search. /// </summary> public void CheckReachability() { System.Diagnostics.Stopwatch sw = new System.Diagnostics.Stopwatch(); sw.Start(); // Reset objects needed for reachability testing. Reachable = Modules.ToDictionary(m => m.WarpCode, b => false); OnceQueue.Clear(); // Check reachability again to find unlocked edges. CheckReachabilityDFS(Reachable); // Continue to check to find newly unlocked edges, until none are unlocked. do { ReachableUpdated = false; var touched = Reachable.ToDictionary(kvp => kvp.Key, kvp => false); CheckReachabilityDFS(touched); } while (ReachableUpdated); Console.WriteLine($" > Time used to create digraph and check reachability...{sw.Elapsed}"); }
/// <summary> /// Default ctor /// </summary> public AttributeClassBuilder(Reachable.ReachableContext context, AssemblyCompiler compiler, TypeDefinition typeDef) : base(context, compiler, typeDef) { }
/// <summary> /// Default ctor /// </summary> public EnumInfoClassBuilder(Reachable.ReachableContext context, AssemblyCompiler compiler, TypeDefinition typeDef, EnumClassBuilder enumClassBuilder) : base(context, compiler, typeDef) { this.enumClassBuilder = enumClassBuilder; }
/// <summary> /// Default ctor /// </summary> public NullableEnumBaseClassBuilder(Reachable.ReachableContext context, AssemblyCompiler compiler, TypeDefinition typeDef) : base(context, compiler, typeDef) { }
public static void UpdateReachableAsync(int sleepTime = 30) { try { Thread.Sleep(sleepTime); // wait to let values update if (Updating) { return; } Updating = true; var argsList = RustLogic ? new List <string> { "reach-check", // TODO maybe we won't pass these explicitly? since it's samefolder shit "--areas", $"\"{Randomizer.BasePath}areas.wotw\"", "--locations", $"\"{Randomizer.BasePath}loc_data.csv\"", "--uber-states", $"\"{Randomizer.BasePath}state_data.csv\"", } : new List <string> { "-jar", $"\"{Randomizer.BasePath}SeedGen.jar\" ", "ReachCheck" }; argsList.AddRange(new List <string> { $"\"{SeedController.SeedFile}\"", $"{InterOp.get_max_health()}", $"{Convert.ToInt32(10*InterOp.get_max_energy())}", $"{UberGet.value(6, 0).Int}", $"{InterOp.get_ore()}", $"{InterOp.get_experience()}", }); if (RustLogic) { argsList.AddRange(TrackedConds.Where(c => c.Met()).Select(t => $"u:{t.Id.GroupID},{t.Id.ID}")); } argsList.AddRange(SaveController.SkillsFound.Select((AbilityType at) => $"s:{(int)at}")); argsList.AddRange(Teleporter.TeleporterStates.Keys.Where(t => new Teleporter(t).Has()).Select(t => $"t:{(int)t}")); if (new QuestEvent(QuestEventType.Water).Has()) { argsList.Add("w:0"); } argsList.AddRange(TrackedShards.Where(sh => new Shard(sh).Has()).Select(t => $"sh:{(int)t}")); var proc = new System.Diagnostics.Process(); proc.StartInfo.FileName = RustLogic ? @"seedgen.exe" : @"java.exe"; proc.StartInfo.Arguments = String.Join(" ", argsList); proc.StartInfo.CreateNoWindow = true; proc.StartInfo.UseShellExecute = false; proc.StartInfo.RedirectStandardOutput = true; proc.StartInfo.RedirectStandardError = true; proc.StartInfo.WorkingDirectory = Randomizer.BasePath; proc.Start(); if (!proc.WaitForExit(10000)) { Randomizer.Warn("MapController.waitForProc", "timed out waiting for reach check", false); } Reachable.Clear(); var rawOutput = proc.StandardOutput.ReadToEnd(); if (rawOutput.Trim() != "") { foreach (var rawCond in rawOutput.Split(',')) { try { var frags = rawCond.Split('|'); var cond = new UberStateCondition(int.Parse(frags[0]), frags[1]); if (cond.Loc().Type == LocType.Shop) { if (cond.Met() || hintTypes.Contains(cond.Pickup().Type)) { continue; // bought it or it's a hint. Either way it's known to be non progression, so it does not show on the map } if (ShopSlot.Twillen.Any(e => e.State.Equals(cond.Id))) { Reachable.Add(new UberStateCondition(2, "20000")); } else if (ShopSlot.Opher.Any(e => e.State.Equals(cond.Id))) { Reachable.Add(new UberStateCondition(1, "20000")); } else if (ShopSlot.LupoStore.Any(e => e.State.Equals(cond.Id))) { Reachable.Add(new UberStateCondition(48248, "20000")); } } Reachable.Add(cond); } catch (Exception e) { Randomizer.Error($"GetReachableAsync (post-return) while parsing |{rawCond}|", e); } } } /* * if(Randomizer.Dev) * Randomizer.Log($"Reach check:\nseed_gen_cli.exe {String.Join(" ", argsList)}\n gave output: \n{rawOutput}\n stderr was {proc.StandardError.ReadToEnd()}\nReachable after: {String.Join(" ", Reachable.Select(r => r.ToString()))}", false); */ InterOp.refresh_inlogic_filter(); } catch (Exception e) { Randomizer.Error("GetReachableAsync", e); } Updating = false; }
public static bool FilterIconShow(int groupId, int id, int value) => Reachable.Contains(new UberStateCondition(groupId, id, value));
/// <summary> /// If the edge contains the Locked tag it should be skipped unless an enabled fix or glitch is also tagged or /// if all of the edge's unlocks are reachable. /// </summary> /// <param name="edge">Edge to check.</param> /// <returns>True if the edge can be skipped.</returns> private bool IsLockedEdge(ModuleEdge edge) { bool isLocked = false; if (edge.IsLocked) { // Check to see if we can bypass this lock with an allowed glitch or enabled fix. if ((AllowGlitchClip && edge.IsClip) || (AllowGlitchDlz && edge.IsDlz) || (AllowGlitchFlu && edge.IsFlu) || // How to handle FluReq? One FLU still requires Carth... (AllowGlitchGpw && edge.IsGpw) || (EnabledFixBox && edge.IsFixBox) || (EnabledFixElev && edge.IsFixElev) || (EnabledFixMap && edge.IsFixMap) || (EnabledFixSpice && edge.IsFixSpice) || (EnabledUnlockDanRuins && edge.IsUnlockDanRuins) || (EnabledUnlockManSub && edge.IsUnlockManSub) || (EnabledUnlockStaBastila && edge.IsUnlockStaBastila) || (EnabledUnlockUnkSummit && edge.IsUnlockUnkSummit)) { isLocked = false; } else { // Check to see if the edge can be unlocked by any of the possible sets. var unlocked = true; foreach (var set in edge.UnlockSets) { // Reset assumption to true, as we're just looking for one false in each set. unlocked = true; // ALL vertices within a set need to be reachable. foreach (var target in set) { // If the tag is not in Reachable, then it's a one that we haven't seen and the edge is still locked. if (!Reachable.ContainsKey(target)) { Reachable.Add(target, false); unlocked = false; break; } // If not Reachable, then the edge is still locked. if (!Reachable[target]) { unlocked = false; break; } } // If a reachable set has been found, break out of the loop. if (unlocked) { break; } } // Set return value. isLocked = !unlocked; } } else { // Edge isn't locked. isLocked = false; } return(isLocked); }
/// <summary> /// Recursive method to perform Depth-First Search reachability checking. /// </summary> /// <param name="touched">Dictionary indicating if each module has been checked during this cycle.</param> /// <param name="v">The current module to check.</param> private void DepthFirstSearch(Dictionary <string, bool> touched, ModuleVertex v) { // This module has been reached, so assume reachable. touched[v.WarpCode] = true; if (touched[v.WarpCode] != Reachable[v.WarpCode]) { ReachableUpdated = true; Reachable[v.WarpCode] = true; } // Any tags associated with this vertex are also reachable. foreach (var t in v.Tags) { if (!Reachable.ContainsKey(t)) { Reachable.Add(t, true); } else { Reachable[t] = true; } } // Check to see if the locked tag is reachable too. if (!string.IsNullOrWhiteSpace(v.LockedTag)) { var isUnlocked = true; // If ALL tags are reachable, this tag is also reachable. foreach (var ul in v.Unlock) { if (Reachable.ContainsKey(ul) && Reachable[ul]) { isUnlocked = true; } else { isUnlocked = false; break; } } if (!Reachable.ContainsKey(v.LockedTag)) { Reachable.Add(v.LockedTag, isUnlocked); } else { Reachable[v.LockedTag] = isUnlocked; } } // Check each edge that hasn't been reached already. foreach (var edge in v.LeadsTo) { // If this is a once edge, determine how to handle it. if (IsOnceEdge(edge)) { // Ignore once edges if setting is enabled. if (!IgnoreOnceEdges) { // If allowed, enqueue the once edge for checking at the end of this cycle. if (!Reachable[RandomLookup[edge.WarpCode]] && !OnceQueue.Contains(edge)) { OnceQueue.Enqueue(edge); ReachableUpdated = true; } } continue; } // If this is a locked edge, determine if it is still locked. if (EnforceEdgeTagLocked && IsLockedEdge(edge)) { continue; } if (!touched[RandomLookup[edge.WarpCode]]) { DepthFirstSearch(touched, Modules.Find(m => m.WarpCode == RandomLookup[edge.WarpCode])); } } }
/// <summary> /// Default ctor /// </summary> public AndroidAppApplicationDerivedBuilder(Reachable.ReachableContext context, AssemblyCompiler compiler, TypeDefinition typeDef) : base(context, compiler, typeDef) { if (IsDot42InternalApplication()) Dot42InternalApplicationBuilder = this; }
/// <summary> /// Default ctor /// </summary> public NullableMarkerClassBuilder(Reachable.ReachableContext context, AssemblyCompiler compiler, TypeDefinition typeDef, ClassBuilder underlyingBuilder) : base(context, compiler, typeDef) { _underlyingBuilder = underlyingBuilder; }
public static void UpdateReachableAsync(int sleepTime = 30) { try { Thread.Sleep(sleepTime); // wait to let values update if (Updating) { return; } Updating = true; var argsList = new List <string> { "-jar", $"{Randomizer.BasePath}SeedGen.jar ", "ReachCheck", $"\"{SeedController.SeedFile}\"", $"{InterOp.get_max_health()}", $"{Convert.ToInt32(10*InterOp.get_max_energy())}", $"{UberGet.value(6, 0).Int}", $"{InterOp.get_ore()}", $"{InterOp.get_experience()}", }; // ^ this should probably be an array at this point... // TODO: send which key doors are already open argsList.AddRange(SaveController.SkillsFound.Select((AbilityType at) => $"s:{(int)at}")); argsList.AddRange(Teleporter.TeleporterStates.Keys.Where(t => new Teleporter(t).Has()).Select(t => $"t:{(int)t}")); if (new QuestEvent(QuestEventType.Water).Has()) { argsList.Add("w:0"); } var proc = new System.Diagnostics.Process(); proc.StartInfo.FileName = @"java.exe"; proc.StartInfo.Arguments = String.Join(" ", argsList); proc.StartInfo.CreateNoWindow = true; proc.StartInfo.UseShellExecute = false; proc.StartInfo.RedirectStandardOutput = true; proc.StartInfo.WorkingDirectory = Randomizer.BasePath; proc.Start(); if (!proc.WaitForExit(7500)) { Randomizer.Warn("MapController.waitForProc", "timed out waiting for reach check", false); } Reachable.Clear(); var rawOutput = proc.StandardOutput.ReadToEnd(); if (rawOutput.Trim() != "") { foreach (var rawCond in rawOutput.Split(',')) { try { var frags = rawCond.Split('|'); var cond = new UberStateCondition(int.Parse(frags[0]), frags[1]); Reachable.Add(cond); } catch (Exception e) { Randomizer.Error($"GetReachableAsync (post-return) while parsing |{rawCond}|", e); } } } // else // Randomizer.Log($"got output |{rawOutput}| from cmd. args: \"{String.Join(" ", argsList)}\" stderr was {proc.StandardError.ReadToEnd()}", false); InterOp.refresh_inlogic_filter(); } catch (Exception e) { Randomizer.Error("GetReachableAsync", e); } Updating = false; }