This isn't a complaint, request, or anything of that nature, I'm just curious. Is it something that's just been commonly accepted? Something that's limited somehow to only 10? Or....?
I think it's generally a user-interface thing. There isn't really a technical limit, but having unlimited savestates means you need some way of selecting a slot from an unlimited list of possibilities, and your keyboard only has around 100 keys.
Lua allows you to have thousands of savestates (for internal use only for the mostpart) and I hacked snes9x to have a slider control for my savestate select ("previous" and "next" selections with no limit in the forward direction) when playing exclusively on a joypad.
There's an easy way to make an infinite number of savestates available - type them.
Each savestate could have an associated screenshot depicting what the screen looked like at the time. (If it can't find the screenshot, because the savestate was made before that version for example, it shows nothing or loads it and creates the screenshot). When you hover over a savestate, it could show the screenshot. When you save a state, you could do it like /nameofstate, and when you load you could do it like \nameofstate, (obviously you'd want to use as small names as possible to be fast to type while meaningful to you) and as you type the names of states it could autocomplete to are shown as well as their associated screenshots. You could have memory watches saved and displayed when you hover over a savestate, as well (e.g. if you're comparing the x position and frame count of many different attempts, you'd like to save each one and hover over them all and see which one got further into the stage in the same amount of time!)
Is there a particular reason why no TASing emulator has implemented this yet? Wouldn't it be more user friendly than having to associate 10 numbers with what you're currently doing, and having to reuse them again and again and again for different mappings as you test different things? And if you go test something else at the same time you have to cram it into those 10 and so on... etc
I think this is what TheAngryPanda was hinting at.
I've always liked SNES9x's approach to savestates, at least when playing games. You get a 4x3 grid of screenshots, each corresponding to a savestate, and you can navigate the grid with your controller. I use a PS2 controller with save/load state bound to the Start and Select buttons, so I can easily interact with savestates without ever having to put down the controller to type something.
For TASing, odds are you won't be using a controller anyway, so typing is not as much of an issue. Having some streamlined method to support arbitrary, reasonably-labeled savestates makes sense. I'd suggest that when you hit the loadstate button, the emulator should bring up a list of all savestates you've made; you can start typing and it'd automatically winnow down the list based on what you've typed. Then you can tab-complete to finish the names. For example:
>>> [hit loadstate button]
boss1
boss2
cave
gamestart
level1
level2
stupidautoscroller
>>> b
boss1
boss2
>>> [tab]
>>> boss
boss1
boss2
>>> boss1
boss1
>>> [enter]
loaded state "boss1"
Pyrel - an open-source rewrite of the Angband roguelike game in Python.
Most rerecording emulators do have unlimited savestates (you can use "Save State As" command and then type the name in the Browse/Savefile dialog). But they usually have 10 auto-named slots, that's different thing. The particular number of slots is because there are 10 numeric keys on the keyboard (plus at least 10 functional keys), which conveniently allows to use any slot anytime (either switch to any slot directly (without cycling through), or actually save/load the state of this slot without tedious searching).
Have you tried TASing? There's no time for typing. You need to juggle savestates using mostly motor memory, or else you're gonna lose attention.
www.fceux.com/web/help/taseditor/index.html?TraditionalTASing.html#savestates
Memory watches are last week, it's better to draw Lua overlay on the actual screenshot. For this exact effect.
A certain emulator definitely has. Not exactly what you described, but I believe it's something which resembles your idea after it's been refined by 1.5 years of development and field testing.
The problem of scale is solved by only testing two (or 3-4 at most) strategies at a time (so their results can be saved in a limited number of slots) and culling early.
The fact is, human memory is even more limited, so there's no point in increasing the number of slots. Some TASers actually use only ~4 slots when working, and others use most of slots for navigation/rewinding (and only a couple of them for storing strategies).
Appreciate all the answers.
I kind of figured it was mostly due to the 10 numerical keys and whatnot. Makes the most sense.
I actually didn't know about the "Save State As" command, I'll have to play around with that.
Regarding the "only test 3-4 strategies" thing, for the game I'm working on (Secret of Evermore). The RNG is determined on a per frame AND player input basis, so there are tons of combinations to test repeatedly for the desirable outcome. This alone uses up around 3-4 states normally just due to various reasons that differ from manipulation to manipulation. That being said, I've minimized it down to 2-3 recently after just understanding how things work better regarding the player input aspect. So in any fight that requires me to attack a large amount of times while manipulating drops and maximizing damage output with favorable positioning tends to utilize around 5-6 states at any given time. Knowing that, I've began breaking each fight into something like this:
state 5 = start of area (clean slate basically)
state 6 = player input location (where the dog is at in my case as well as if he's sniffing)
state 7 = start of combat + initial manipulations (first point of backup for fight)
state 8 = secondary manipulations during previously manipulated events (boy starts attack, damage isn't calculated until X frames later, between start and X frames i can manipulate things)
state 9 = 2nd basic reference point for various things (common-use state)
state 0 = 1st basic reference point for various things (common-use state)
states 1-4 are various points throughout the game, 1 being the very beginning for reference against older versions of the TAS. 3 and 4 are occasionally used during heavily manipulated things that the above "setup" can't handle.
Is there a better/easier way to do this? I imagine the save state as feature could be used fairly well here?
edit: I would like to point out that I am in no way saying not having more states slows me down, I progress through these states rapidly and am very organized about it as well as efficient in practice. I'm simply trying to improve said efficiency. :)
Being new to all this sort of stuff, I actually don't know how to do either of those options. :(
That being said, it isn't as bad as it seems on paper really, there are direct paths to where you need to go and I don't stray from them (even for manipulations) unless it's 100% required. So far in my latest version of this particular TAS I've gotten every manipulation within 2 frames of ideal, the one exception was required for even better manipulations later on the same map to hit a certain frame which I knew the enemy would give me 10 damage on a particular position.
If you know anywhere I can read up and learn via tutorials or something the stuff you're referring to, I'd happily go check it out considering how useful I'm sure it is; lol. I'm pretty lacking in terms of the coding area though, so it would literally be a brand new thing to me, which is fine.
edit: Regarding Secret of Evermore, after the first Act (or 2nd boss in the TAS) you gain a 999 damage glitch which basically removes enemy issues. It's all about movement and enemy manipulations at that point, which I've already mostly (there's 7 maps I'm not "okay" with) figured out from actually routing the game for real-time any% and 100% runs. That being said, I'm still looking through the lua guidebook from the newbie corner forum someone Ans made as well as the site and various tutorials to try and learn it.
Just in case you've got me wrong, I wasn't saying that it's enough to only test a few strategies! I was talking about the number of strategies that are kept simultaneously.
Why would you want to keep savestates of a strategy that is considered obsolete? Just reuse all the slots that store the timeline of the old strategy when recording next strategy.
This indeed looks like a problem caused by working with huge segments. It's only natural to break such segments into smaller subsegments. As I see it, you've already divided it into 3 segments:
A) pre-combat player input (dog/etc), until the start of combat
B) initial manipulations - those frames from the start of combat to the start of attack
C) secondary manipulations - X frames from the start of attack to the point of calculating damage
So I imagine you're doing the following (if not, then I would like to listen for your version of the workflow):
1. Slot 6 stores the start of segment A. Record a first version of pre-combat input using slots 2,3,4 for undoing mistakes. Then, at the frame when the combat is going to start, save state to slot 7 - this slot will store the end frame of segment A.
2. Slot 7 stores the start of segment B. Record a first version of initial manipulations using slots 2,3,4 for undoing mistakes. Then save state 8 right after pressing the trigger button - slot 8 will store the end frame of segment B.
3. Slot 8 stores the start of segment C. Record a first version of secondary manipulations using slots 2,3,4 for undoing mistakes. Then save state 9 after X frames elapsed - slot 9 will store the end frame of segment C.
4. At this point you have recorded the first strategy completely. Save it to slot 0. Since the final frame of the big segment coincides with the final frame of segment C, slot 0 will contain the same state as slot 9 (at least for now).
5. Now try different strategies. Do not touch segments A and B! Only rerecord segment C for now. Slot 8 stores the start of segment C. Record a 2nd version of secondary manipulations using slots 2,3,4 for undoing mistakes. Then save state 9 after X frames elapsed. Compare the result (damage produced in slot 9) with the result of slot 0 and rewrite the slot 0 if the 2nd strategy for segment C is better. Then try 3rd strat, 4th, etc... until you start thinking that trying different initial manipulations would produce better ground for secondary manipulations.
6. Slot 7 stores the start of segment B. Record a 2nd version of initial manipulations using slots 2,3,4 for undoing mistakes. Then save state 8 right after pressing the trigger button - slot 8 will store the end frame of segment B. Oh, and there's no need to keep the old state of slot 8!
7. Repeat steps 3-5, trying different versions of secondary manipulations, now they will likely produce different results, thus some of them may produce higher damage - each time the result improves, resave it to slot 0.
8. Repeat steps 6-7, trying 3rd strat for segment B, 4th strat, etc... until you start thinking that trying different pre-combat input would produce better ground.
9. Slot 6 stores the start of segment A. Record a 2nd version of pre-combat input using slots 2,3,4 for undoing mistakes. Then, at the frame when the combat is going to start, save state to slot 7 - this slot will store the new end frame of segment A.
10. Repeat steps 8-9, trying different strategies for segment A, for every new strategy you have to try different strategies for segment B and then for segment C. Any time you finish the segment C, compare the result (damage produced) to the slot 0, and overwrite slot 0 in case of improvement.
This is the only way to ensure you've tested everything. And it's more efficient than trying to rerecord the whole big segment from scratch every time you feel like you need to change something in the beginning.
Now, all this sounds like an exhaustive search (brute-forcing), but since you're human, you'll naturally be using some amazing heuristics, so you'll successfully skip many strategies before testing/recording them to their end.
Also, you can stop the search anytime and just take whatever you have in slot 0 at this point. At least it will be the best strategy from all those you've tested.
Anyway, as I see, most newbies don't divide the big segment into smaller ones, they usually only test a few strategies in a chaotic manner and get satisfied with a lucky but imperfect result. This is a viable option too, especially when you're tired.
If actual botting of the RNG is not an option, I doubt there's any better way than described above.
Subsegments are the way to go - both when you want to test a thousand of approaches and when you want to just try a few.
RNGs aside, most games are simple enough that a few different strategies actually exhaust the range of possibilities.
No. "Save State As" only slows down the process of loading states. And you don't need too many slots, even when you're working with such huge segments as in your case. And I consider you case to be really difficult one.
What would help: a Piano Roll which allows you to enter new strategies and test much them faster than with traditional rerecording. This way you won't even need slots 2,3,4 for undoing mistakes, because there's Ctrl+Z, rewinding and other neat stuff.
edit: Forgot to say thanks for the response(s). :)
That is essentially how I do things... I think? haha. Here's my "thought flow" so to say when TAS'ing this game. I'll use the the 1st enemy damage > dead > talon drop > progress path as an example.
State 1 = start of map (I've changed to using this recently because as you mentioned, it would include all previous data as well that was deemed acceptable to me. This is my start point in case all hell breaks loose during manipulations or if I simply want to re-watch and analyze for a more optimal approach, although most of this has already been done in my route test tas.
State 2 = Actual manipulation start point, where it all begins
State 3 = for mistake corrections (as mentioned)
State 4 = for manipulation polishing leading into the next segment of manipulations. This is a reference point I can fall back to "re-roll" the RNG for the next segment of manipulations. It's rarely used outside of heavy manipulation scenarios such as lengthy boss fights and item drop situations, such as my example below.
States 5-6 are my #2 segment, mistake corrections/polishing
States 7-9 are my finalizing segment, there is an extra state here as a reference point for further into the map that I can use to re-roll the RNG again if needed and still obtain the same result as before. The state I generally use for this is 8, it gets overwritten when I progress through an entire "big" segment or progress to the next sub-segment of said big segment.
State 0 = common use for various things/backup use/etc... this is essentially my "free" state.
As for the example, this is what I did this morning re-do'ing my previously acceptable starting area:
State 1 = start of segment 1
State 2 = approaching enemy (begin segment 1A)
State 3 = movement/dog manipulation to get perfect enemy attack pattern
State 4 = reference point of State 3's result as well as polishing/testing up to that point. Technically start of segment 1B, 1C, etc... general reference point overall.
State 5 = Same as State 2, separate for now but becomes State 2 if enemy drop is manipulated correctly
State 6 = Same as State 4, but for this segment. Becomes State 2 if talons are dropped within reasonable frames (0-2 frames is my limit). End segment 1B.
States 7-9 = the rest of the sub segment. In this case, segment 1C.
The reason it's so obnoxious to deal with is the RNG in the game: here's an example...
Let's say you want to deal 12 damage and are 4 frames away, here's the options:
RRRR
RRR
RR
R
R RR
RR R
RRR
R R
R R
etc...
Things that affect the resulting damage:
-Directional input
-Non-Player controlled character location
-Non-Player controlled character "state" (sniffing, not sniffing, attacking, walking)
-Attacking
-Any combination of the above
-Previous segment inputs (usually include the above unless it's nothing but movement)
It's not incredibly awful because the damage ranges are quite comfortable for the places it matters the most such that there are really only 2 outcomes that are not favorable. The problem, as always, lies solely with obtaining the proper sequence of sub-segments/segments to obtain the most direct and non-deviating approach possible.
Luckily, I have a slight edge in that I've routed the game for real-time, been involved with multiple theory TAS related things, as well as made the route test TAS. This kind of forces the fact upon me that I know what the best outcome is, I know how to get it, I just need to do it without straying from the straight-line path through each area.
Regarding it being exhaustive, absolutely. Like you said though, I already know what does and doesn't work in terms of movement, which narrows my options down drastically.
All that nonsense aside, what exactly do you mean by a Piano Roll? Is it more or less just having a set of options/inputs and altering them until the output is acceptable? Like I said, still new at this so some stuff people say I'm not familiar with. I'll do a search once I'm done typing this though.
Will definitely check it out, thanks for the help.
Posts like this are why I appreciate posts like the one Ans made previously so much. Great example, thank you.
Hell, you have an entire keyboard to play with; there's no reason why you couldn't have a save slot for every single letter, capitalized letter, and symbol.
Pyrel - an open-source rewrite of the Angband roguelike game in Python.
It would be cool if there was an emu that automatically did a savestate for every frame. That way you can then create pseudo windback features. The only problem being that your savestate folder would run into many Gigabytes, possibly even Terabytes.
Joined: 4/17/2010
Posts: 11495
Location: Lake Chargoggagoggmanchauggagoggchaubunagungamaugg
Bizhawk also has it :P
Warning: When making decisions, I try to collect as much data as possible before actually deciding. I try to abstract away and see the principles behind real world events and people's opinions. I try to generalize them and turn into something clear and reusable. I hate depending on unpredictable and having to make lottery guesses. Any problem can be solved by systems thinking and acting.
Moderator, Senior Ambassador, Experienced player
(907)
Joined: 9/14/2008
Posts: 1014
When I set up the "virtualbox-rr" rerecording environment in Linux for the NetHack run, ais523 and I had a lot of discussions on how best to handle savestates. We eventually decided to implement unlimited savestates using a list structure with buttons to move forward or back in an ever-expanding list, a button to save a new state at the end of the list, and a button to set the current state as the one to load when the load state key was pressed. In other words, there are five buttons total, including load savestate from working slot, create new savestate, go to previous slot, go to next slot, set current slot as working slot. It can be a little challenging to figure out where you are in the list so we added a show list method and save screenshots of the savestates, sort of. You see, everything is text-based, so it's a bit.. er.. different.
Anyway, after using that method I don't like going back to only 10 slots. I always feel like I'm throwing away something I might need.
A.C.
******