public static PathDataLog LoadFromFile(string filename) { var pathData = new PathDataLog(); try { Scribe.InitLoading(filename); ScribeMetaHeaderUtility.LoadGameDataHeader(ScribeMetaHeaderUtility.ScribeHeaderMode.Map, false); Scribe.EnterNode("PathData"); pathData.ExposeData(); Scribe.ExitNode(); } catch (Exception e) { Log.Error("Exception while loading: " + e); } finally { // done loading Scribe.FinalizeLoading(); Scribe.mode = LoadSaveMode.Inactive; } return(pathData); }
public static void SaveFromPathCall(Map map, IntVec3 startVec, LocalTargetInfo dest, TraverseParms traverseParms, PathEndMode peMode) { CellRect destinationRect; if (dest.HasThing && peMode != PathEndMode.OnCell) { destinationRect = dest.Thing.OccupiedRect(); } else { destinationRect = CellRect.SingleCell(dest.Cell); } var dumper = new PathDataLog { mapSize = map.Size, start = startVec, dest = destinationRect, peMode = peMode, tpMode = traverseParms.mode, tpMaxDanger = traverseParms.maxDanger, tpCanBash = traverseParms.canBash, tpMoveCardinal = traverseParms.pawn?.TicksPerMoveCardinal ?? -1, tpMoveDiagonal = traverseParms.pawn?.TicksPerMoveDiagonal ?? -1, pathGrid = map.pathGrid.pathGrid, fakeEdificeGrid = new ByteGrid(map), avoidGrid = traverseParms.pawn?.GetAvoidGrid(), allowedArea = traverseParms.pawn?.playerSettings?.AreaRestrictionInPawnCurrentMap }; foreach (var cell in map.AllCells) { var rb = cell.GetRegionBarrier(map); int value = Edifice_None; if (rb != null) { var door = rb as Building_Door; if (door != null) { switch (traverseParms.mode) { case TraverseMode.ByPawn: if (!traverseParms.canBash && door.IsForbiddenToPass(traverseParms.pawn)) { value = Edifice_NonTraversableDoor; } else if (!door.FreePassage) { value = door.PawnCanOpen(traverseParms.pawn) ? door.TicksToOpenNow : Edifice_NonTraversableDoor; } else { value = 0; } break; case TraverseMode.NoPassClosedDoors: value = !door.FreePassage ? Edifice_NonTraversableDoor : 0; break; } } else if ((rb as Building)?.PathFindCostFor(traverseParms.pawn) > 0) { value = Edifice_KnownArmedTrap; } else { value = Edifice_Impassible; } } dumper.fakeEdificeGrid[cell] = (byte)value; } var savePath = Path.Combine(GenFilePaths.DevOutputFolderPath, $"{traverseParms.pawn} - {Find.TickManager.TicksAbs}"); if (File.Exists(savePath + ".xml")) { savePath = savePath + " "; int saveNum = 1; while (File.Exists(savePath + saveNum + ".xml")) { saveNum++; } savePath = savePath + saveNum; } try { SaveGame(savePath); try { Scribe.InitWriting(savePath + ".xml", "PathDataLog"); } catch (Exception ex) { GenUI.ErrorDialog("Stuff went wrong " + ex); throw; } ScribeMetaHeaderUtility.WriteMetaHeader(); Scribe_Deep.LookDeep(ref dumper, "PathData"); } catch (Exception ex2) { Log.Error("Exception while saving: " + ex2); } finally { Scribe.FinalizeWriting(); } }
//Wrapper function to run extra testing/logging code. public PawnPath FindPath(IntVec3 start, LocalTargetInfo dest, TraverseParms traverseParms, PathEndMode peMode = PathEndMode.OnCell) { #if DEBUG if (traverseParms.pawn != null) { Log.Message($"Pathfinding times for pawn {traverseParms.pawn}, mode: {traverseParms.mode}\n Move speed: {traverseParms.pawn.TicksPerMoveCardinal}, {traverseParms.pawn.TicksPerMoveDiagonal}"); } disableDebugFlash = true; //disable debug flash during timing tests var sw = new Stopwatch(); PawnPath temp = null; var vanillaCost = float.MaxValue - 1000; diagonalPerceivedCostWeight = 1.0f; sw.Start(); temp = FindPathInner(start, dest, traverseParms, peMode, HeuristicMode.Vanilla); sw.Stop(); Log.Message("~~ Vanilla ~~ " + sw.ElapsedTicks + " ticks, " + debug_openCellsPopped + " open cells popped, " + temp.TotalCost + " path cost!"); vanillaCost = temp.TotalCost; temp.Dispose(); //sw.Reset(); //sw.Start(); //temp = FindPathInner(start, dest, traverseParms, peMode, HeuristicMode.AdmissableOctile); //sw.Stop(); //Log.Message("~~ Admissable Octile ~~ " + sw.ElapsedTicks + " ticks, " + debug_openCellsPopped + " open cells popped, " + temp.TotalCost + " path cost!"); //var optimal = temp.TotalCost; //temp.Dispose(); try { diagonalPerceivedCostWeight = diagonalCostWeightSetting; sw.Reset(); sw.Start(); temp = FindPathInner(start, dest, traverseParms, peMode, HeuristicMode.Better); sw.Stop(); Log.Message("~~ Better ~~ " + sw.ElapsedTicks + " ticks, " + debug_openCellsPopped + " open cells popped, " + temp.TotalCost + " path cost! (" /*+ sw.ElapsedMilliseconds*/ + "ms)"); } catch { if (Current.ProgramState == ProgramState.Playing) { PathDataLog.SaveFromPathCall(this.map, start, dest, traverseParms, peMode); } } //var sb = new StringBuilder(); //foreach (var pathmax in new [] {false, true}) //{ // pathmaxEnabled = pathmax; // foreach (var weight in new[] {false, true}) // { // weightEnabled = weight; // sw.Reset(); // sw.Start(); // temp = FindPathInner(start, dest, traverseParms, peMode); // sw.Stop(); // sb.AppendLine($"pathmax: {pathmax}, weight: {weight}, pops: {debug_openCellsPopped}, pathcost: {temp.TotalCost}, elapsed: {sw.ElapsedTicks}"); // temp.Dispose(); // } //} //Log.Message(sb.ToString()); //Log.Message("\t Distance Map Pops: " + RegionLinkDijkstra.nodes_popped); //Log.Message("\t Total open cells added: " + debug_totalOpenListCount); //Log.Message("\t Closed cells reopened: " + closedCellsReopened); //Log.Message($"\t Total Heuristic Estimate {debug_totalHeuristicCostEstimate}, off by {((temp.TotalCost / debug_totalHeuristicCostEstimate) - 1.0f).ToStringPercent()}"); temp?.Dispose(); disableDebugFlash = false; #endif #if PFPROFILE if (!hasRunOnce) { disableDebugFlash = true; var jitRun = FindPathInner(start, dest, traverseParms, peMode, HeuristicMode.Better); jitRun.Dispose(); hasRunOnce = true; disableDebugFlash = false; } sws.Clear(); #endif var result = FindPathInner(start, dest, traverseParms, peMode, HeuristicMode.Better); #if PFPROFILE var profsb = new StringBuilder(); foreach (var pfsw in sws) { profsb.AppendLine("SW " + pfsw.Key + ": " + pfsw.Value.ElapsedTicks.ToString("##,#") + " ticks."); } Log.Message(profsb.ToString()); #endif #if DEBUG if (Current.ProgramState == ProgramState.Playing) { if (debug_openCellsPopped > 2500 || (vanillaCost + 100) < result.TotalCost || result == PawnPath.NotFound) { PathDataLog.SaveFromPathCall(this.map, start, dest, traverseParms, peMode); } } #endif return(result); }