public void Apply(int rotationChange, int powerChange, MarsLanderEnvironment environment) { if (Status != LanderStatus.Flying) return; if (Situation.Fuel < Situation.Power + powerChange) powerChange = 0; if (Situation.Fuel < Situation.Power) powerChange = -1; Situation.Power += LimitPower(powerChange); Situation.Rotation += LimitRotation(rotationChange); Situation.Fuel -= Situation.Power; Situation.HorizontalSpeed += Trigonometry.GetHorizontalSpeedFraction(Situation.Rotation, ZeroDegreesDirection.Top) * Situation.Power; if (Situation.HorizontalSpeed > MarsLanderRules.MaxHorizontalSpeed) Situation.HorizontalSpeed = MarsLanderRules.MaxHorizontalSpeed; if (Situation.HorizontalSpeed < MarsLanderRules.MinHorizontalSpeed) Situation.HorizontalSpeed = MarsLanderRules.MinHorizontalSpeed; Situation.VerticalSpeed += Trigonometry.GetVerticalSpeedFraction(Situation.Rotation, ZeroDegreesDirection.Top) * Situation.Power - MarsLanderRules.Gravity; if (Situation.VerticalSpeed > MarsLanderRules.MaxVerticalSpeed) Situation.VerticalSpeed = MarsLanderRules.MaxVerticalSpeed; if (Situation.VerticalSpeed < MarsLanderRules.MinVerticalSpeed) Situation.VerticalSpeed = MarsLanderRules.MinVerticalSpeed; Situation.X += Situation.HorizontalSpeed; Situation.Y += Situation.VerticalSpeed; RoundValues(); Situations.Add(Situation.Clone()); Actions.Add($"{rotationChange} {powerChange}"); SetStatus(environment); }
public bool WillHitLandingZone(MarsLanderEnvironment environment, int withinTheseTurns = 5) { var puppet = Clone(); var landingZone = environment.GetLandingZone(); var turns = 0; while (puppet.Status == LanderStatus.Flying && turns < withinTheseTurns) { puppet.Apply(0, 0, environment); turns += 1; } if (puppet.Status == LanderStatus.Flying) return false; return puppet.Situation.X >= landingZone.LeftX && puppet.Situation.X < landingZone.RightX; }
private List <Generation> GetBestLanding(LandRequest landRequest) { var environment = new MarsLanderEnvironment(landRequest.Map.SurfaceZones.ToList()); var lander = new Lander { Situation = new Situation { Fuel = landRequest.Map.InitialFuel, Power = landRequest.Map.InitialPower, Rotation = landRequest.Map.InitialRotation, X = landRequest.Map.InitialX, Y = landRequest.Map.InitialY, HorizontalSpeed = landRequest.Map.InitialHorizontalSpeed, VerticalSpeed = landRequest.Map.InitialVerticalSpeed } }; var evolution = new MarsLanderEvolution(environment, landRequest.AiWeight); if (landRequest.Parameters.Actions != null) { evolution.MaxActions = landRequest.Parameters.Actions <= 0 ? null : landRequest.Parameters.Actions; } var sw = Stopwatch.StartNew(); evolution.Run(landRequest.Parameters.Generations, landRequest.Parameters.Population, lander); sw.Stop(); var highestScore = evolution.Generations .SelectMany(generation => generation.Actors) .Select(actor => actor.Score) .OrderBy(score => score) .First(); _logger.LogInformation("{elapsed}", sw.Elapsed); _logger.LogInformation("Highest Score: {@score}", highestScore); return(evolution.Generations); }
private GenerationActor ScoreActor(MarsLanderActor actor, MarsLanderEnvironment environment) { if (actor.Lander.Status == LanderStatus.Landed) { return new GenerationActor { Lander = actor.Lander.Clone(), Score = 0 } } ; var distanceFromFlatSurface = environment.GetDistanceFromFlatSurface(actor.Lander); var horizontalDistance = distanceFromFlatSurface.HorizontalDistance; var verticalDistance = distanceFromFlatSurface.VerticalDistance; var horizontalSpeed = actor.Lander.Situation.HorizontalSpeed; var verticalSpeed = actor.Lander.Situation.VerticalSpeed; var rotation = actor.Lander.Situation.Rotation; var fuel = actor.Lander.Situation.Fuel; var originalSituation = actor.Original.Situation; if (horizontalDistance > 0 && horizontalSpeed < 0 || horizontalDistance < 0 && horizontalSpeed > 0) { // Discourage going into the wrong direction. BUT don't include things like overshooting the landing zone, // as it went the correct direction initially. var landingZone = environment.GetLandingZone(); if (actor.Lander.Situation.X < originalSituation.X && landingZone.LeftX > originalSituation.X || actor.Lander.Situation.X > originalSituation.X && landingZone.RightX < originalSituation.X) { // We landed further away from the landing zone than when we started. return(new GenerationActor { Lander = actor.Lander.Clone(), Score = 100_000_000 });
public MarsLanderEvolution(MarsLanderEnvironment environment, AiWeight aiWeight) { _environment = environment; _aiWeight = aiWeight; }
public MarsLanderActor(Lander lander, MarsLanderEnvironment environment) { Original = lander.Clone(); Lander = lander.Clone(); _environment = environment; }
public void Apply(string action, MarsLanderEnvironment environment) { var actionArray = action.Split(" "); Apply(int.Parse(actionArray[0]), int.Parse(actionArray[1]), environment); }