/// <summary> /// Find all nodes that are the end of a siding (so where main path and siding path come together again) /// </summary> private void FindSidingEnds() { Dictionary <int, AIPathNode> lastUse = new Dictionary <int, AIPathNode>(); for (AIPathNode node1 = FirstNode; node1 != null; node1 = node1.NextMainNode) { if (node1.JunctionIndex >= 0) { lastUse[node1.JunctionIndex] = node1; } AIPathNode node2 = node1.NextSidingNode; while (node2 != null && node2.NextSidingNode != null) { if (node2.JunctionIndex >= 0) { lastUse[node2.JunctionIndex] = node2; } node2 = node2.NextSidingNode; } if (node2 != null) { node2.Type = AIPathNodeType.SidingEnd; } } //foreach (KeyValuePair<int, AIPathNode> kvp in lastUse) // kvp.Value.IsLastSwitchUse = true; }
public static void WriteNode(BinaryWriter outf, AIPathNode node) { if (node == null) { outf.Write((int)-1); } else { outf.Write(node.Index); } }
/// <summary> /// Returns the index of the vector node connection this path node to the (given) nextNode. /// </summary> public int FindTVNIndex(AIPathNode nextNode, TrackDatabaseFile TDB, TrackSectionsFile tsectiondat) { int junctionIndexThis = JunctionIndex; int junctionIndexNext = nextNode.JunctionIndex; // if this is no junction, try to find the TVN index if (junctionIndexThis < 0) { try { return(findTrackNodeIndex(TDB, tsectiondat, this)); } catch { junctionIndexThis = FindJunctionOrEndIndex(this.Location, TDB.TrackDB, false); } } // this is a junction; if the next node is no junction, try that one. if (junctionIndexNext < 0) { try { return(findTrackNodeIndex(TDB, tsectiondat, nextNode)); } catch { junctionIndexNext = FindJunctionOrEndIndex(nextNode.Location, TDB.TrackDB, false); } } //both this node and the next node are junctions: find the vector node connecting them. for (int i = 0; i < TDB.TrackDB.TrackNodes.Count(); i++) { TrackNode tn = TDB.TrackDB.TrackNodes[i]; if (tn == null || tn.TrVectorNode == null) { continue; } if (tn.TrPins[0].Link == junctionIndexThis && tn.TrPins[1].Link == junctionIndexNext) { return(i); } if (tn.TrPins[1].Link == junctionIndexThis && tn.TrPins[0].Link == junctionIndexNext) { return(i); } } return(-1); }
/// <summary> /// Constructor from other AIPathNode /// </summary> /// <param name="otherNode"></param> public AIPathNode(AIPathNode otherNode) { ID = otherNode.ID; Index = otherNode.Index; Type = otherNode.Type; WaitTimeS = otherNode.WaitTimeS; WaitUntil = otherNode.WaitUntil; NCars = otherNode.NCars; NextMainNode = null; // set after completion of copying to get correct reference NextSidingNode = null; // set after completion of copying to get correct reference NextMainTVNIndex = otherNode.NextMainTVNIndex; NextSidingTVNIndex = otherNode.NextSidingTVNIndex; Location = otherNode.Location; JunctionIndex = otherNode.JunctionIndex; IsFacingPoint = otherNode.IsFacingPoint; IsVisited = otherNode.IsVisited; }
// restore game state public AIPath(TrackDatabaseFile TDB, TrackSectionsFile tsectiondat, BinaryReader inf) { pathName = inf.ReadString(); TrackDB = TDB.TrackDB; TSectionDat = tsectiondat; int n = inf.ReadInt32(); for (int i = 0; i < n; i++) { Nodes.Add(new AIPathNode(inf)); } for (int i = 0; i < n; i++) { Nodes[i].NextMainNode = ReadNode(inf); Nodes[i].NextSidingNode = ReadNode(inf); } FirstNode = Nodes[0]; //LastVisitedNode = ReadNode(inf); }
/// <summary> /// constructor out of other path /// </summary> /// <param name="otherPath"></param> public AIPath(AIPath otherPath) { TrackDB = otherPath.TrackDB;; TSectionDat = otherPath.TSectionDat; FirstNode = new AIPathNode(otherPath.FirstNode); foreach (AIPathNode otherNode in otherPath.Nodes) { Nodes.Add(new AIPathNode(otherNode)); } // set correct node references for (int iNode = 0; iNode <= otherPath.Nodes.Count - 1; iNode++) { AIPathNode otherNode = otherPath.Nodes[iNode]; if (otherNode.NextMainNode != null) { Nodes[iNode].NextMainNode = Nodes[otherNode.NextMainNode.Index]; } if (otherNode.NextSidingNode != null) { Nodes[iNode].NextSidingNode = Nodes[otherNode.NextSidingNode.Index]; } } if (otherPath.FirstNode.NextMainNode != null) { FirstNode.NextMainNode = Nodes[otherPath.FirstNode.NextMainNode.Index]; } if (otherPath.FirstNode.NextSidingNode != null) { FirstNode.NextSidingNode = Nodes[otherPath.FirstNode.NextSidingNode.Index]; } pathName = otherPath.pathName; }
/// <summary> /// Try to find the tracknode corresponding to the given node's location. /// This will raise an exception if it cannot be found /// </summary> /// <param name="TDB"></param> /// <param name="tsectiondat"></param> /// <param name="node"></param> /// <returns>The track node index that has been found (or an exception)</returns> private static int findTrackNodeIndex(TrackDatabaseFile TDB, TrackSectionsFile tsectiondat, AIPathNode node) { Traveller traveller = new Traveller(tsectiondat, TDB.TrackDB.TrackNodes, node.Location); return(traveller.TrackNodeIndex); }
public string pathName; //name of the path to be able to print it. /// <summary> /// Creates an AIPath from PAT file information. /// First creates all the nodes and then links them together into a main list /// with optional parallel siding list. /// </summary> public AIPath(TrackDatabaseFile TDB, TrackSectionsFile tsectiondat, string filePath, bool isTimetableMode) { PathFile patFile = new PathFile(filePath); pathName = patFile.Name; TrackDB = TDB.TrackDB; TSectionDat = tsectiondat; bool fatalerror = false; if (patFile.PathNodes.Count <= 0) { fatalerror = true; Nodes = null; return; } foreach (PathNode tpn in patFile.PathNodes) { Nodes.Add(new AIPathNode(tpn, patFile.DataPoints[(int)tpn.PathDataPoint], TrackDB, isTimetableMode)); } FirstNode = Nodes[0]; //LastVisitedNode = FirstNode; // Connect the various nodes to each other for (int i = 0; i < Nodes.Count; i++) { AIPathNode node = Nodes[i]; node.Index = i; PathNode tpn = patFile.PathNodes[i]; // find TVNindex to next main node. if (tpn.HasNextMainNode) { node.NextMainNode = Nodes[(int)tpn.NextMainNode]; node.NextMainTVNIndex = node.FindTVNIndex(node.NextMainNode, TDB, tsectiondat, i == 0 ? -1 : Nodes[i - 1].NextMainTVNIndex); if (node.JunctionIndex >= 0) { node.IsFacingPoint = TestFacingPoint(node.JunctionIndex, node.NextMainTVNIndex); } if (node.NextMainTVNIndex < 0) { node.NextMainNode = null; Trace.TraceWarning("Cannot find main track for node {1} in path {0}", filePath, i); fatalerror = true; } } // find TVNindex to next siding node if (tpn.HasNextSidingNode) { node.NextSidingNode = Nodes[(int)tpn.NextSidingNode]; node.NextSidingTVNIndex = node.FindTVNIndex(node.NextSidingNode, TDB, tsectiondat, i == 0 ? -1 : Nodes[i - 1].NextMainTVNIndex); if (node.JunctionIndex >= 0) { node.IsFacingPoint = TestFacingPoint(node.JunctionIndex, node.NextSidingTVNIndex); } if (node.NextSidingTVNIndex < 0) { node.NextSidingNode = null; Trace.TraceWarning("Cannot find siding track for node {1} in path {0}", filePath, i); fatalerror = true; } } if (node.NextMainNode != null && node.NextSidingNode != null) { node.Type = AIPathNodeType.SidingStart; } } FindSidingEnds(); if (fatalerror) { Nodes = null; // invalid path - do not return any nodes } }
/// <summary> /// Returns the index of the vector node connection this path node to the (given) nextNode. /// </summary> public int FindTVNIndex(AIPathNode nextNode, TrackDatabaseFile TDB, TrackSectionsFile tsectiondat, int previousNextMainTVNIndex) { int junctionIndexThis = JunctionIndex; int junctionIndexNext = nextNode.JunctionIndex; // if this is no junction, try to find the TVN index if (junctionIndexThis < 0) { try { return(findTrackNodeIndex(TDB, tsectiondat, this)); } catch { junctionIndexThis = FindJunctionOrEndIndex(this.Location, TDB.TrackDB, false); } } // this is a junction; if the next node is no junction, try that one. if (junctionIndexNext < 0) { try { return(findTrackNodeIndex(TDB, tsectiondat, nextNode)); } catch { junctionIndexNext = FindJunctionOrEndIndex(nextNode.Location, TDB.TrackDB, false); } } //both this node and the next node are junctions: find the vector node connecting them. var iCand = -1; for (int i = 0; i < TDB.TrackDB.TrackNodes.Count(); i++) { if (!(TDB.TrackDB.TrackNodes[i] is TrackVectorNode tn)) { continue; } if (tn.TrackPins[0].Link == junctionIndexThis && tn.TrackPins[1].Link == junctionIndexNext) { iCand = i; if (i != previousNextMainTVNIndex) { break; } Trace.TraceInformation("Managing rocket loop at trackNode {0}", iCand); } else if (tn.TrackPins[1].Link == junctionIndexThis && tn.TrackPins[0].Link == junctionIndexNext) { iCand = i; if (i != previousNextMainTVNIndex) { break; } Trace.TraceInformation("Managing rocket loop at trackNode {0}", iCand); } } return(iCand); }