It's not only the flipper's altitude that matters but also its velocity.
Although it is possible to write a script that predicts all the math, I think it may be a bit too difficult for me.
We need the flipper's hitbox data. (Note that US version has less Z-Height on flipper, if that info helps finding the data...?)
With that said, I could do a simplified script but it may or may not work out.
I will keep trying.
My thought process so far:
(1) Move the ball 7F before it reaches inside the flipper's area of effect for the first time.
(2) Save state A.
(3) Try different inputs so the flipper collides with ball in different ways
(Previously I considered only the 10 possible flipper positionings (called "altitude" before)
but we should consider how the ball is hit, from positioning A in one frame to positioning B in the next frame - refered to as "velocity" above.)
After the tried input, brute force for as long as the ball is still inside the flipper.
(2^10 is only 1024 tries for 10 frames of trying pressing or not pressing the flipper, so this is ok.)
After the ball leaves the flipper's area of effect, check if we reached a new scenario (ball in different position, different speed, etc.) and if yes, save state B.
After the flipper last collides with the ball, there should be no more input.
(4) For each saved state B, let ball reach to 7F before any flipper and repeat from (1)
or if there is less than 7F before reaching the next flipper, rewind to state A in read-only and let it run to 7F before the next flipper from there,
repeat from (1) while replicating the input of the previous flipper.
---
After each frame, check winning conditions. Examples:
- Star key count increased
- Exit reached
After each frame, check losing conditions. Examples:
- Ball reached an undesired transition (i.e. wrong exit)
- Star count below a certain pre-set after certain frame count
- Door to the next room closed after certain frame count
- Fastest record time exceeded
- Ball is too far up in the room after a certain framecount - meant to reduce on unnecessary attempts where ball is not going to be near the exit
- Ball is too low in the room after a certain frame count - meant to reduce on unncessary attempts where ball is not going to be near the exit
- Enemy not hit after certain frame count
- Yellow Coins lower than certain pre-set after certain frame count
- Blue Coins lower than certain pre-set after certain frame count
- (...)
If winning condition is reached and it beats the previous fastest time, then save a state and update the fastest time variable (that is checked by "losing condition: fastest record time exceeded"). Then discard the current attempt.
If losing condition is reached, discard the current attempt.