Mars Lander - Puzzle discussion

It means that, at least for the first turns, most of your offspring will not land and maybe not even crash. Why so few genes ? Would you lose too much time if you add 40 or 60 genes ?

I understand why you were surprised by my evaluation function that only “roughly” looks at the distance to the landing site.

I start with 120 genes, one for each turn, but when I mutate the chromosome, I only mutate le genes used before crashing/landing, so the number of genes is not that important, as long as there is enough to “crash/land”.

With my 700ish mutations, I’m not that far.

I’m trying to work on “Coders Strike back”, but I’ll get back to Mars Lander and I’ll try some of your ideas.

Thanks for your help.

For me, I don’t mind if the offspring can’t find a landing solution in the time he has. As long as the fitness function is getting him closer to the end and he has plenty of fuel and a good safety margin when he can finally see it, I don’t worry about calculating the whole thing on turn 1. Lots of other philosophies are out there. Good luck with it, and let us know what your final solution is.

Just an observation, a single-member GA using only mutation is closer to a Monte Carlo than a GA.

I’ve tried both single member and population, and it’s roughly the same. I think I’ll try other problems for a while and I’ll get back to it with a fresh mind.

Thanks for your answers, it really helped me.

I don’t understand why this won’t work for the level 1:

import sys
import math

surface_n = int(input()) # the number of points used to draw the surface of Mars.
for i in range(surface_n):
# land_x: X coordinate of a surface point. (0 to 6999)
# land_y: Y coordinate of a surface point. By linking all the points together in a sequential fashion, you form the surface of Mars.
land_x, land_y = [int(j) for j in input().split()]

game loop

while True:
# h_speed: the horizontal speed (in m/s), can be negative.
# v_speed: the vertical speed (in m/s), can be negative.
# fuel: the quantity of remaining fuel in liters.
# rotate: the rotation angle in degrees (-90 to 90).
# power: the thrust power (0 to 4).
x, y, h_speed, v_speed, fuel, rotate, power = [int(i) for i in input().split()]

# Write an action using print
# To debug: print("Debug messages...", file=sys.stderr)

if v_speed < -40:
print(“0 4”)
else:
print(“0 0”)

# 2 integers: rotate power. rotate is the desired rotation angle (should be 0 for level 1), power is the desired thrust power (0 to 4).

I have the error “Timeout: your program did not provide an input in due time. Mars Lander self-destroyed!”

I don’t know what language that is, but you probably need to flush the output stream. In some languages it’s enough to include a linebreak. As in print("0 4\n") and print("0 0\n").

Not an expert in that language, but you might check whether print() includes a line break. Lots of languages include print() and printLine().

Python needs indentations (either spaces or tabs, but be consistent and don’t mix them).
print() adds a newline by default, so that’s not the problem here.

the problem might be in the condition, because anything shows up according to the error message.
I need help to find the issue, because i have some trouble seeing where it comes from atm

your code is working with indents added (not passing the tests but no timeout):

import sys
import math

surface_n = int(input()) # the number of points used to draw the surface of Mars.
for i in range(surface_n):
# land_x: X coordinate of a surface point. (0 to 6999)
# land_y: Y coordinate of a surface point. By linking all the points together in a sequential fashion, you form the surface of Mars.
    land_x, land_y = [int(j) for j in input().split()]

# game loop
while True:
# h_speed: the horizontal speed (in m/s), can be negative.
# v_speed: the vertical speed (in m/s), can be negative.
# fuel: the quantity of remaining fuel in liters.
# rotate: the rotation angle in degrees (-90 to 90).
# power: the thrust power (0 to 4).
    x, y, h_speed, v_speed, fuel, rotate, power = [int(i) for i in input().split()]

# Write an action using print
# To debug: print("Debug messages...", file=sys.stderr)
    if v_speed < -40:
        print("0 4")
    else:
        print("0 0")
1 Like

Thank you haha i’m so dumb i didn’t see that

Tried to maximise the program with the equation of movement and with a Sampler and could not optimize over -8m/s at the landing.

I’m working on the Mars Lander - Episode 2. I’m trying to figure out a way to detect if I’m over the landing zone. I could theoretically obtain a VSpeed of 0 m/s and have a non-zero horizontal speed which would allow me to fly across the mars surface. The problem is the Y value is not the distance of the space ship above the mars surface it is just a Y coordinate. Therefore, how can I detect when I’m over the landing zone without being able to detect changes in landscape?

You have your position [x y] and the surface as line segments with [x1 y1] [x2 y2] for every segment. You can find the segment below yourself with that information. The landing platform is one of those segments. And if you have that and take the intersection between two particular lines you can get your height above the surface.

I am trying to solve this puzzle using a genetic algorithm. Since I need to determine how well some set of instructions does, I am trying to reverse engineer the game engine such that I can accurately simulate the outcome of those instructions. My current understanding is as follows, I put strange/annoying behavior in italics and questions in bold, please correct me if I’m wrong:

The position and velocity are stored as floating point numbers. (float or double?)
At the beginning of each turn, the angle and the power are instantly updated to be as close as possible to the output of your program. If you are out of fuel, the power wil be set to zero. The power stays the same during the entire turn, even if the lander runs out of fuel during that turn. (Either lazy programming, or to make the problem slightly easier.)

Then the new position and velocity are calculated with the exact mathematical formulas:
x[t+1] = x[t] + v[t] + a[t]/2
v[t+1] = v[t] + a[t]
where a[t] is the acceleration at turn t based on the angle, power and gravity and x[t] and v[t] are the position and velocity at the beginning of turn t respectively.

Finally, there is a collision check:

  • if you collide with non flat ground, you crash
    for the following two checks, the speed you would have had at the end of the turn if there was no collision is used, rounded to the nearest integer rather than the unrounded speed at the time of the collision (Either lazy programming, or to make the problem slightly easier.)
  • if you collide with the landing site, and your speed or angle is too high, you crash
  • if you collide with the landing site and your speed and angle are both safe, you land
  • if there is no collision, the new position, velocity, angle, power and fuel are given to your program as input. However, the position and velocity are first rounded to the nearest integer. (Ridiculous. Why would you do that?)

Each turn, I simulate the trajectory myself using the assumptions above (I use doubles). My rounded simulated values always correspond to the integer input every turn, which suggests that those assumptions are correct, and my simulation accurately implements them.

I now need to figure out how the collision check is done. It is possible to derive an exact formula for that, and I expected the game engine to do that as well, since it also uses exact formulas to calculate the next position and velocity. However, I made a disturbing (to my inner mathematician) discovery:
In Mars Lander 1, keeping the angle at zero, I got to a simulated y-value of around 99.8. Since the landing site is at y = 100, I expected to have landed, but the simulation went on for another turn.
It appears that the position is rounded, before the collision check is done. This means that the game engine does not use the exact trajectory to detect a collision. So my question is: how exactly does the game engine detect collisions? The only way I can think of, consistent with this, is as follows:
The trajectory used for the collision detection is a straight line between the rounded previous position, and the rounded current position. Is this correct? If so, why is this bad approximation being used? Has anyone had any issues with inaccurate collision detection?

2 Likes

I think you figured out correctly all tricks of the game engine, including the famous horrible “we give you integers in input, but we’ll keep working on doubles on our side”. Just ignore those inputs and rely instead on the doubles you had computed.
Not an easy task overall indeed, and not a very fund one either.

The way I check for collisions is the one you describe : look for any intersection between the segment formed by your old position to new position, and any of the surface segments.
If there is at least one such intersection, then you either crashed or landed, depending on the other variables.

Note that “reverse engineering” of the game engine is not needed anymore for official contests, since they always provide the referee since beginning of the year.
However, there was no “physical / collision” game since they do that, so we never had insights on their physical engine.

Episode 2 is an impossible task. The time given to land is ridiculously small, very bad puzzle. I rate 0/5.:rage:

Can anyone give me a link to a tutorial for the math I would need to solve this? I just have no idea where to start.

1 Like

There is a second part to that, the correct angle is 21.9°, not 22°. The difference seems small, but because of the initial engine power and this rounding, you cannot maintain your altitude at this degree.
Unless you use 21°for horizontal movement :slight_smile:

Episode 2 is a very difficult one…

Detect landing zone => OK
Create a simulator to see what will happen for getting good rotate and power values => OK
Using the simulator at each turn => response time too high :frowning:
Arrrrggggg !!!

It will be nice to let some initialisation time available before the while loop.