1 2
6 7 8
Taechuk
He/Him
Player (62)
Joined: 12/4/2017
Posts: 66
Link to video Fluctuant Travelor 54.20 714 rerecords
Post subject: Initial research
Editor, Experienced player (854)
Joined: 5/2/2015
Posts: 696
Location: France
Link to video Movie file 1-02 -1f vs human WR 1772 rerecords For frame comparaisons, use adress 0x021FBA20 (2 byte). Speed (4 byte) is available at 0x20DDBAC and 0x20DDBF4, both adresses being the same. Divide it by 65536 to get the displayed speed. (For example, a speed value of 3478176 is equal to 3478176 / 65536 = 53 speed.) Note that speed is 1 frame behind the actual speed counter, located at 0x021FBA24 (2 byte). Other main relevant adresses like x, y, and z speed as well as position are dynamically allocated and change each level. Both position and speed are floating point; you can get these in RAM watch by setting the data type of these adresses to Fixed Point 20.12. You need to divide speed values by 10^3 to get equal magnitude for both position and speed; for some reason, speed values are 10^3 bigger than position ones when set to floating point. To get the norm of the speed vector, use √(vx²+vy²+vz²) with vx, vy and vz as the values of each speed adress for X, Y and Z. I haven't figured out yet what the relation between these values and the speed value itself is. I was thinking it corresponded to the above formula, but that's apparently not it. Either it's a mistake in my reasoning, or the speed value uses a different way to calculate speed. To see what I mean in more detail: use this RAM watch along with the movie file above, and play until 1-02, then play with the adresses. Because most of the adresses are dynamically allocated, these will only work on 1-02 and I don't have any pointers yet. I'm making a script to display all this info in a TAS-friendly way. Onto the level. Most of it is just movement optimisation. There are three things I'd like to explain in detail: - Initial boosting. As already known, boosting is done by holding up-right then up-left, or up-left then up-right. The reason it works is because air acceleration is faster when holding diagonally. When doing any movement input, it both moves the level and the ball. So, even when the ape is in the air, doing different input will change its direction, even though the ape is not touching with the level in any way. What is the optimal boost? First of all, boosting right then left is always faster on all my tests (most likely due to floating point imprecision, but don't quote me on this). Second, changing direction, here meaning going from up right to up left, kills speed. So, the longer up right is held before switching direction, the more speed the ape gets. Of course, holding up right has the downside of also rotating the ape's angle. So, if you hold up right for more frames, you get more speed, but at the cost of a "worse", meaning oriented more to the right, angle. This is detrimental if you want to go forward. Bottom line, you always need to boost right then left, but the number of frames to boost right depends. - Collision. It seems (speculation for now) that there are only a few types of collision. In this level, I avoid all "large" collisions which make the ape make a loud soud and instead go for "medium" one which make Aiai make a less loud sound, when forced to collide with the track. At a high speed, you are supposed to always get these large collisions, yet I manage to get medium ones on the three turns (how exactly this happens is unknown for now.) If you wish to see an example of medium vs large, change the input in this level starting at 56:00, when the ape is about to collide with the turn. If we hold up right for even a tiny bit longer, then we get a large collision which knocks the ape back further than a medium one. (Only netting medium collisions can get this 52:81 time.) - Optimal movement. When having to turn, hold up left or up right. When in the air, up. When on the ground and having to go straight, hold up (127, 0 stylus coordinates). Every single area of the touchpad is a valid input, leading to 256*193 = 49408 valid different inputs per frame, and each of them give the ape a different speed. In situations where I have to optimise a turn, I have 256 inputs to test for the turning frame. An example of this: say we have to switch from holding up right to up left to make a turn. If we hold up-right then up left on frame 2, we hit a wall. If we hold up-right until frame 2 then up left on frame 3, we make the turn without hitting the wall. So we are forced to hold up right on frame 1, but maybe holding up right (the extreme input) in frame 2 will overshoot the wall a bit. Instead, start doing inputs that get closer and closer to up left on frame 2. If we hit the wall, the next input goes a little farther up right; if we don't, a little farther up left. Bisecting inputs like this, we eventually find the optimal input for the turn. (This is why you see inputs that are not up left or up right in this movie.) This is a lot of text, so please do ask if clarification is needed.
Taechuk
He/Him
Player (62)
Joined: 12/4/2017
Posts: 66
I hate this game sometimes.
Taechuk
He/Him
Player (62)
Joined: 12/4/2017
Posts: 66
Link to video That was annoying to get. Spiral Staircase 57.76 817 rerecords Here's the clip :
Taechuk
He/Him
Player (62)
Joined: 12/4/2017
Posts: 66
Link to video Mini Bump 58.38 128 rerecords
Taechuk
He/Him
Player (62)
Joined: 12/4/2017
Posts: 66
Link to video Double Scepter 55.05 621 rerecords
Taechuk
He/Him
Player (62)
Joined: 12/4/2017
Posts: 66
Link to video Pincer 57.33 434 rerecords IDK if I'm working too fast, but at least I manage to improve on the WRs. One thing is sure : I'm definitely trying a lot harder than on my first attempt.
Taechuk
He/Him
Player (62)
Joined: 12/4/2017
Posts: 66
Link to video Starfish 57.08 OK I don't know how that could have possibly worked out... 655 rerecords Here's the clip frame by frame, just to show how unexpected that clip is :
Taechuk
He/Him
Player (62)
Joined: 12/4/2017
Posts: 66
Link to video Deviant Drop 57.00 1022 rerecords
Taechuk
He/Him
Player (62)
Joined: 12/4/2017
Posts: 66
Link to video Backslide 54.58 651 rerecords Went a bit out of order because I wanted to redo this level. Tried to get off the starting platform sooner while still having enough speed to reach the top. Ended up saving a bunch of frames.
Taechuk
He/Him
Player (62)
Joined: 12/4/2017
Posts: 66
Link to video Backslide 54.60 654 rerecords That ending sucked. Let me take off that frame.
Taechuk
He/Him
Player (62)
Joined: 12/4/2017
Posts: 66
Link to video Receding Curves 56.50 976 rerecords Couldn't find a way to save a frame. Might come back on that one.
Taechuk
He/Him
Player (62)
Joined: 12/4/2017
Posts: 66
Link to video Displacement 54.86 580 rerecords
Taechuk
He/Him
Player (62)
Joined: 12/4/2017
Posts: 66
Link to video Labyrinthine 57.43 528 rerecords
Editor, Experienced player (854)
Joined: 5/2/2015
Posts: 696
Location: France
(If you are wondering how to hide the top bar like I did here, Tools > View Layer > uncheck Main OBJ) This took a bit of time to do due to some DeSmuME quirks, but here is an initial lua script for this game, which should be pretty easy to understand if you look at the script: http://tasvideos.org/userfiles/info/49023977547981422 I included the adresses for X, Y, Z position and speed, as well as a time counter; the number in square brackets being the number of frames before the next second. It will work on every level.
Taechuk
He/Him
Player (62)
Joined: 12/4/2017
Posts: 66
I've been trying to tie 3-1 Racket's WR and I'm just unable to reach it. I keep getting 55.93. I'm currently at 2251 rerecords and I just don't get how Silverboxer got his 55.95. If you want to try with what I've got yet, here's the file : http://tasvideos.org/userfiles/info/49076423055371651
Taechuk
He/Him
Player (62)
Joined: 12/4/2017
Posts: 66
Link to video Basin 58.45 680 rerecords (I had .45 after like 60 rerecords, but I could find a way to get better)
Editor, Experienced player (854)
Joined: 5/2/2015
Posts: 696
Location: France
Taechuk wrote:
If you want to try with what I've got yet, here's the file : http://tasvideos.org/userfiles/info/49076423055371651
Sure! Here's a movie that beats WR by a frame: http://tasvideos.org/userfiles/info/49089997547856064 Link to video 5265 rerecords Here's a slightly updated lua script (I will probably set up a repo for it because this is not the best source control): http://tasvideos.org/userfiles/info/49090278993160476 It now shows position in white, position derivatives in green (how much the position changed last frame) as well as the game's X, Y and Z speed values in teal. The last value is the total speed. There are a few observations I've made that seem to confirm my initial hypotheses, so I'll write them down here. As expected, TASing this game is not trivial and there are a lot of hidden delicaties. Before that, I'll talk about optimisation boundaries. This is something that emerges naturally when TASing pretty much anything, and applies to any game. What I mean by boundaries is "what goal you want to optimise". If we're TASing a simple platformer, then our optimisation boundary is go right as fast as possible. So, if we TAS two different "routes", end both at the same frame (ideally a well defined end point), and see that on one of these routes our character is farther right in the first route, then we can say that the first route is unequivocally faster. Rarely are things this simple in any game, though. I call these boundaries because they mark easy to divide sections of a TAS. In this game our principal boundary is to get to the goal as fast as possible. This boundary is position gated; this means that if we're even 0.01 X units off the goal, then we lost a frame, so we need to agressively optimise for position. To accomplish this we want as much speed as possible, because if we gain more speed we travel faster and thus get closer to the goal. We also want this speed to be aimed towards the goal. In cases going directly to the goal isn't possible, or there is another route that would let us gain more speed and thus reach the goal faster, then we take a detour. The biggest way to gain speed in this game is to get in the air, so we will seek detours that let us gain as much air time as we can. Let's take a more concrete example. In this level, we start in an elevated position. There is a slope we can get air time off, compared to if we went straight to the goal. This slope gives us enough speed that reaching the goal is faster with it. There is also a corner we can get air speed out of at the end that we'ill be using. So, here are our boundaries: - Fall off the starting platform as fast as possible. - Hit the ramp and get a bunch of air time. This is more important; we will neglect the first boundary if it means we can hit the ramp with a better angle and get more speed out of it, even if we fall off slower. - Go straight to the corner. - Get a bunch of air time out of the corner and go straight to the goal. We can't judge accurately how important each of these are compared to another; should we spend some extra frames on the starting platform to get more speed off the ramp? Only testing tells us this. Once these boundaries are acknowledged, then we find the best input (and this creates a lot of other things we must optimise as well in order to fulfill these boundaries). - Optimal movement. Here's a slight correction regarding my earlier post. While in the air, diagonal input is optimal (up-left or up right); while on the ground, up input (127, 0) is optimal. - Boosting. At the start of the level, the ape falls from the sky and bounces twice. This is free air time, so we can use it by going diagonally. Swapping input instantly (going from up-right to up-left input) wastes some speed, but it's needed because we would not get a good angle otherwhise, so the later we do it, the more speed we get out of the boost. Boosting right then left is always faster, but by a minuscule amount, so always boost right then left in symetrical levels. - 2-frame gap. This is a really wierd thing that I don't fully understand yet. In certain situations, such as when taking a sharp turn or just before doing a collision, there are two frames where altering the input only alters two of the speed values and not three. In these situations, the optimal input becomes much different. You can see an example in this run at emulator frame 1150 to 1152 (where I hold up-right to abuse this).
Taechuk
He/Him
Player (62)
Joined: 12/4/2017
Posts: 66
Just went and searched for the banana counter address. Found a few addresses that looks for bananas. 021FBF48 is the banana counter for lives (resets at 0 once it reaches 10 and adds a life). If we set it higher than 10, it will go down by 10 every frame and add a life until it's not over 10. 021FBF70 is the post world 11 counter for unlocking world 12. We can set it to 2006 to instantly unlock world 12. It cannot go up until we beat world 11, but we can change it's value anytime. It will only unlock world 12 if you have beaten world 10. Not a major thing, just felt like searching for them. Another address I found is 021FBF34, this one is for lives. It can actually go over 99, but it will only show the 2 last digits. Practice mode sets this coutner at 99, but it only does so when we enter the level the first time. It doesn't decrease in practice mode. Also, you can have it overflow at 255.
Taechuk
He/Him
Player (62)
Joined: 12/4/2017
Posts: 66
12-10 Palpitation 53.73 351 rerecords Shoutouts to SilverBawxer for showing this clip, I tried to reproduce it and... there you go. Got insanely lucky on that one. Not really sure if it's possible to get it a cycle earlier, otherwise there is not much improvement here. Edit : AAAAAAH Why do I improve by a frame right after I upload something.... Link to video 53.75 353 rerecords
Taechuk
He/Him
Player (62)
Joined: 12/4/2017
Posts: 66
Link to video 5-6 Conveyor 55.68 509 rerecords That's probably the 2nd biggest difference from WR to TAS, beating the current WR by 13.78 or 827 frames, 1st being Road to Nowhere with 14.75/885 frames, which I honestly want to give a try
Editor, Experienced player (854)
Joined: 5/2/2015
Posts: 696
Location: France
Well, suddently a lot of people got interested in TASing for this game. Silverbawxer did the below: Link to video Here's a few more observations based on my speed script. - Every frame that the ape spends in the air, he will gain a specific amount of negative Y speed due to "gravity". There is no reasonable cap to this speed, like for X and Z speed (except the cap of a 32-bit integer). I'll call this gravity: a gravity of 10 means that the ape gets negative 10 Y speed each frame. Speed values here are the teal values on my script. At base value (without any input) it is 10 gravity, meaning the ape gains 10 negative Y speed each frame, or gets substracted 10 y speed from his Y value each frame to word it differently. What's interesting is that doing inputs actually changes this gravity. In particular, exact center input will still apply -10 gravity, but the farther you get from the center, the lower gravity gets! By deduction we know how boosting works now: * When falling into a level, we bounce due to being dropped from an elevated position. This puts us in the air. * We accelerate faster in the air than on the ground. Accelerating faster gives us more speed. * We deduce that the longer we stay in the air, the more speed we get. Put in another way, we want to stay in the air for as much frames as we possibly can; worded differently, we want to get as much air time as possible, while still going in the right direction (it is no use for speed it doens't direct us towards our goals). * We can influence gravity and make it lower. * Lesser gravity means the ape's Y speed is reduced less each frame. * If the ape's Y speed is reduced less each frame, then we stay in the air longer, because the effect of gravity isn't as important. We now know that we can get more air time than usual. But remember our goals; we want the most speed. * Gravity is the smallest in inputs that are the furtherest away from the center of the touchpad: these are up-left, up-right, down-left and down-right. * Reducing gravity makes our bounce take more time, thus we gain more air time, thus we gain more speed. We now know that the objectively best inputs for speed, and speed alone, are up-left, up-right, down-left and down-right when boosting. But we want to be going in the right direction. Indeed, if we get most speed by going up-right solely while boosting, then the ape ends up being angled further away from where we want to go.. in most cases. This is where it starts becoming situational. But, given that we drop and that the target is in a straight line in front of where the ape is facing: * Going up-right and up-left gives us the most speed but skews our angle. This means it gives us more overall speed, but less effective speed towards the direction we actually want to. * We have a way to redirect speed, which is called turning. By holding up-left or up-right, the ape turns to the left or to the right. How to resolve this situation? It seems in this case, that holding up-right to get air time gives less effective speed even though it gets more speed. We need a way to redirect speed, which also does not compromise on getting gravity as low as possible. The answer is to apply this by first going up-left, then, while the ape is still in the air, turn to up-right. So we both keep the benefits of changing gravity AND get to change the ape's angle at the same time! Perfect. And this is how boosting works. So, this movement which looked really unintuitive at first glance: going up right then up left or vice versa, is very logical when you look at it. The question that should follow is when do we swap back to the opposite direction? It depends. And this is a direct tradeoff: the more we wait before doing the swap, the more speed we get, but at the cost of a worse angle. This should be rigorously kept in mind when optimising initial boosting. The last thing is that changing direction slows up down in the air. I have an idea of why this happens but I can't advance anything for now. We can do exactly one direction swap during a boost and still get the maximal air time, any more and you lose 1 or more frames of air time (very very bad.) - In the same line of thought, what happens if the situation is reversed? What if we want to fall as fast as possible? Then the answer is simple, make gravity max by inputting dead center. Of course, if you have to move then this becomes suboptimal, but in cases where it's almost or just a straight fall using this is crucial. Note that doing no input and doing center input have the same effect, it sets gravity to 10. However, switching from input to no input takes time and wastes speed, while switching from input to center input does not waste speed because the change is instant. I haven't figured out why this happens either. - Probably, some other SMB1/2 TAS tricks work like air boosting, need to be looked at in detail.
Player (149)
Joined: 4/18/2015
Posts: 17
Link to video 6-9 Free Ride 52.75 740 rerecords
Taechuk
He/Him
Player (62)
Joined: 12/4/2017
Posts: 66
Link to video Road to Nowhere 50.31 3539 rerecords Featuring a really weird bounce, this beats xy2_'s tas by a frame. More improvements are probably possible if we manage to get a better bounce. This was the only way I could make it work.
Post subject: Progress update
Editor, Experienced player (854)
Joined: 5/2/2015
Posts: 696
Location: France
It has been a good three months since this project was started, with three TASers on it, although we have been mostly working in secret since we started. Currently, about 80% of the game is TASed - 83 out of 108 (bonus levels nonwithstanding). We track all known records (be they human or tool-assisted) and have as such beaten them on these 83 individual levels.
1 2
6 7 8