private int CalculateFitness(RCT2RideData candidate) { int fitness = 0; //Get Displacement to End & Max Y Displacement Vector3 prevWorldPos = new Vector3(0.0f, 0.0f, 0.0f); int worldDirectionChange = 0; double maxVarianceFromStart = 0; int maxYVariance = 0; for (int i = 0; i < candidate.TrackData.TrackData.Count; i++) { RCT2TrackElements.RCT2TrackElement currentElement = candidate.TrackData.TrackData[i].TrackElement; RCT2TrackElementProperty property = RCT2TrackElements.TrackElementPropertyMap[currentElement]; Vector3 worldDisplacement = candidate.TrackData.LocalDisplacementToWorld(property.Displacement, worldDirectionChange); //Update World Position Changes prevWorldPos += worldDisplacement; if (prevWorldPos.Y >= maxYVariance) { maxYVariance = (int)prevWorldPos.Y; } if (prevWorldPos.Length() >= maxVarianceFromStart) { maxVarianceFromStart = prevWorldPos.Length(); } //Update World Direction Changes worldDirectionChange = candidate.TrackData.UpdateRotation(worldDirectionChange, property.DirectionChange); } maxYVariance -= (int)prevWorldPos.Y; maxVarianceFromStart -= prevWorldPos.Length(); Vector3 displacementToEnd = new Vector3(0, 0, 0); displacementToEnd.X = Math.Abs(prevWorldPos.X); displacementToEnd.Y = Math.Abs(prevWorldPos.Y); displacementToEnd.Z = Math.Abs(prevWorldPos.Z); //Console.WriteLine(maxYDisplacement); double displacementToEndLength = displacementToEnd.Length(); fitness = (int)(((candidate.ExcitementTimesTen / (1 + candidate.NauseaTimesTen)) + /*maxVarianceFromStart*/ +maxYVariance) * 1000); return(fitness); }
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 RCT2RideData Mutation(RCT2RideData candidate) { //Console.WriteLine("------------"); //foreach (var track in candidate.TrackData.TrackData) //{ // Console.WriteLine(track.TrackElement.ToString()); //} bool hasExtraPiece = false; for (int i = 2; i < candidate.TrackData.TrackData.Count(); i++) { if (random.NextDouble() <= mutationRate) { //Get possible candidates RCT2RideData candidateCopy = new RCT2RideData(candidate); List <RCT2TrackElements.RCT2TrackElement> candidateReplacements = RCT2TrackElements.FindValidSuccessors(whitelistedTracks, candidate.TrackData.TrackData[i - 1].TrackElement); bool redo = false; do { //If we're out of possible replacements if (candidateReplacements.Count <= 0) { //Console.WriteLine("/////////////"); //foreach (var track in candidate.TrackData.TrackData) //{ // Console.WriteLine(track.TrackElement.ToString()); //} return(candidate); } //Construct our random element RCT2TrackPiece randomElement = new RCT2TrackPiece(); randomElement.TrackElement = candidateReplacements[random.Next(candidateReplacements.Count)]; candidateReplacements.Remove(randomElement.TrackElement); RCT2TrackElementProperty property = RCT2TrackElements.TrackElementPropertyMap[randomElement.TrackElement]; if (property.InputTrackDegree == RCT2TrackElementProperty.RCT2TrackDegree.Up25 || property.InputTrackDegree == RCT2TrackElementProperty.RCT2TrackDegree.Up60 || property.InputTrackDegree == RCT2TrackElementProperty.RCT2TrackDegree.Up90) { randomElement.Qualifier = new RCT2Qualifier() { IsChainLift = true, TrackColourSchemeNumber = 0, TrackRotation = RideData.RCT2Qualifier.RCT2QualifierRotation.Zero, AtTerminalStation = false, StationNumber = 0 }; } else { randomElement.Qualifier = new RCT2Qualifier() { IsChainLift = false, TrackColourSchemeNumber = 0, TrackRotation = RideData.RCT2Qualifier.RCT2QualifierRotation.Zero, AtTerminalStation = false, StationNumber = 0 }; } //Replace the existing element at that location with this if (hasExtraPiece) { candidateCopy.TrackData.TrackData.RemoveAt(i + 1); hasExtraPiece = false; } candidateCopy.TrackData.TrackData.RemoveAt(i); if (randomElement.TrackElement == RCT2TrackElements.RCT2TrackElement.FlatToIncline25 || randomElement.TrackElement == RCT2TrackElements.RCT2TrackElement.Incline25) { candidateCopy.TrackData.TrackData.Insert(i, randomElement); RCT2TrackPiece bridgeElement = new RCT2TrackPiece(); bridgeElement.TrackElement = RCT2TrackElements.RCT2TrackElement.Incline25ToFlat; bridgeElement.Qualifier = new RCT2Qualifier() { IsChainLift = true, TrackColourSchemeNumber = 0, TrackRotation = RideData.RCT2Qualifier.RCT2QualifierRotation.Zero, AtTerminalStation = false, StationNumber = 0 }; candidateCopy.TrackData.TrackData.Insert(i + 1, bridgeElement); //Console.WriteLine($"\tAttempted to Mutate into {randomElement.TrackElement.ToString()}"); hasExtraPiece = true; } else if (randomElement.TrackElement == RCT2TrackElements.RCT2TrackElement.FlatToDecline25 || randomElement.TrackElement == RCT2TrackElements.RCT2TrackElement.Decline25) { candidateCopy.TrackData.TrackData.Insert(i, randomElement); RCT2TrackPiece bridgeElement = new RCT2TrackPiece(); bridgeElement.TrackElement = RCT2TrackElements.RCT2TrackElement.Decline25ToFlat; bridgeElement.Qualifier = new RCT2Qualifier() { IsChainLift = false, TrackColourSchemeNumber = 0, TrackRotation = RideData.RCT2Qualifier.RCT2QualifierRotation.Zero, AtTerminalStation = false, StationNumber = 0 }; candidateCopy.TrackData.TrackData.Insert(i + 1, bridgeElement); //Console.WriteLine($"\tAttempted to Mutate into {randomElement.TrackElement.ToString()}"); hasExtraPiece = true; } else { candidateCopy.TrackData.TrackData.Insert(i, randomElement); } //If it makes the track invalid, try again if (candidateCopy.TrackData.CheckValidity() != RCT2TrackData.InvalidityCode.Valid) { redo = true; } else { redo = false; successfulMutations++; hasExtraPiece = false; } } while (redo); } } return(candidate); }