private RCT2TrackData GenerateWoodenRollerCoasterTrack() { RCT2TrackData trackData = new RCT2TrackData(); trackData.TrackData = new List <RCT2TrackPiece>(); Random random = new Random(); //Begin Station trackData.TrackData.Add(new RideData.RCT2TrackPiece() { TrackElement = RideData.RCT2TrackElements.RCT2TrackElement.BeginStation, Qualifier = new RideData.RCT2Qualifier() { IsChainLift = false, TrackColourSchemeNumber = 0, TrackRotation = RideData.RCT2Qualifier.RCT2QualifierRotation.Zero, AtTerminalStation = false, StationNumber = 0 } }); //End Station trackData.TrackData.Add(new RideData.RCT2TrackPiece() { TrackElement = RideData.RCT2TrackElements.RCT2TrackElement.EndStation, Qualifier = new RideData.RCT2Qualifier() { IsChainLift = false, TrackColourSchemeNumber = 0, TrackRotation = RideData.RCT2Qualifier.RCT2QualifierRotation.Zero, AtTerminalStation = false, StationNumber = 0 } }); //TODO: Marking valid track pieces as invalid // The prior connection check is failing for (int i = 2; i < length; i++) { List <RCT2TrackElements.RCT2TrackElement> candidates = RCT2TrackElements.FindValidSuccessors(whitelistedTracks, trackData.TrackData[i - 1].TrackElement); bool reselect = false; do { //If we have no candidates left if (candidates.Count <= 0) { return(null); //if (steppedBack) //{ // return null; //} //if (i < 3) //{ // throw new Exception("ERROR: Unable to create Coaster - Index stepped back too far"); //} ////Console.WriteLine("ERROR: No Valid Track Pieces Found, Stepping back and starting again"); //trackData.TrackData.Remove(trackData.TrackData.Last()); //i -= 2; //steppedBack = true; //TODO - Make this a better solution, right now it's a hack to make it work //break; } //Select our successor and remove it from the potential pool RCT2TrackElements.RCT2TrackElement successor = candidates[random.Next(candidates.Count)]; candidates.Remove(successor); RCT2TrackElementProperty property = RCT2TrackElements.TrackElementPropertyMap[successor]; //Console.WriteLine($"\tAttempting Track Piece {successor.ToString()}"); RCT2Qualifier qualifier; //Create our qualifier bit if (property.Displacement.Y > 0) { //TODO: Check if it should be a chain // Perform a lookup to see if previous track was chain lift // Or if our current velocity would be negative/0 // If not possible, do a lookup to see if previous X tracks contained a decline, if not we need one bool chainLift = trackData.TrackData[i - 1].Qualifier.IsChainLift; //If our current velocity would be negative or zero, we need a chain lift qualifier = new RCT2Qualifier() { IsChainLift = true, TrackColourSchemeNumber = 0, TrackRotation = RideData.RCT2Qualifier.RCT2QualifierRotation.Zero, AtTerminalStation = false, StationNumber = 0 }; } else { qualifier = new RCT2Qualifier() { IsChainLift = false, TrackColourSchemeNumber = 0, TrackRotation = RideData.RCT2Qualifier.RCT2QualifierRotation.Zero, AtTerminalStation = false, StationNumber = 0 }; } //Add to track trackData.TrackData.Add(new RCT2TrackPiece() { TrackElement = successor, Qualifier = qualifier }); //If it's invalid RCT2TrackData.InvalidityCode invalidityCode = trackData.CheckValidity(); if (invalidityCode != RCT2TrackData.InvalidityCode.Valid) { //Remove it and try again reselect = true; trackData.TrackData.Remove(trackData.TrackData.Last()); //Console.WriteLine($"\tInvalid Selection, Code: {invalidityCode.ToString()}"); } else { reselect = false; } } while (reselect); //Console.WriteLine($"{trackData.TrackData.Last().TrackElement.ToString()} Selected!"); } //for (int i = 0; i < trackData.TrackData.Count(); i++) //{ // Console.WriteLine("\t" + trackData.TrackData[i].TrackElement.ToString()); //} return(trackData); }
private List <RCT2RideData> Crossover(RCT2RideData parent1, RCT2RideData parent2) { List <RCT2RideData> children = new List <RCT2RideData>(); int crossoverPoint = length; int redoCount = 0; bool redo = false; RCT2TrackData.InvalidityCode parent1Invalidity = parent1.TrackData.CheckValidity(); RCT2TrackData.InvalidityCode parent2Invalidity = parent2.TrackData.CheckValidity(); //Create crossover point if (random.NextDouble() <= crossoverRate) { crossoverPoint = random.Next(length); } do { if (redoCount >= crossoverAttempts) { crossoverPoint = length; } //Add first halves to each child RCT2TrackData child1Track = new RCT2TrackData(); RCT2TrackData child2Track = new RCT2TrackData(); for (int i = 0; i < crossoverPoint; i++) { child1Track.TrackData.Add(parent1.TrackData.TrackData[i]); child2Track.TrackData.Add(parent2.TrackData.TrackData[i]); } //Add second halves to each child for (int i = crossoverPoint; i < parent2.TrackData.TrackData.Count(); i++) { child1Track.TrackData.Add(parent2.TrackData.TrackData[i]); } for (int i = crossoverPoint; i < parent1.TrackData.TrackData.Count(); i++) { child2Track.TrackData.Add(parent1.TrackData.TrackData[i]); } RCT2RideData child1 = new RCT2RideData(parent1); RCT2RideData child2 = new RCT2RideData(parent2); child1.TrackData = child1Track; child2.TrackData = child2Track; //If the created children are invalid, keep trying //Wont cause an infinite loop as we will eventually crossover at point 0 //Which acts as if we never crossed over at all RCT2TrackData.InvalidityCode child1Invalidity = child1.TrackData.CheckValidity(); RCT2TrackData.InvalidityCode child2Invalidity = child2.TrackData.CheckValidity(); if (child1Invalidity != RCT2TrackData.InvalidityCode.Valid || child2Invalidity != RCT2TrackData.InvalidityCode.Valid) { redo = true; redoCount++; crossoverPoint = random.Next(length); } else { redo = false; children.Add(child1); children.Add(child2); if (crossoverPoint != length) { successfulCrossovers++; } } } while (redo); return(children); }