Skip to content
New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

Add timings to strats (e.g. for escape timings) #1462

Open
blkerby opened this issue Apr 12, 2024 · 4 comments
Open

Add timings to strats (e.g. for escape timings) #1462

blkerby opened this issue Apr 12, 2024 · 4 comments

Comments

@blkerby
Copy link
Contributor

blkerby commented Apr 12, 2024

Currently, escape timings in Map Rando are defined in a JSON file that mostly just gives one timing for each pair of doors in every room: https://github.com/blkerby/MapRandomizer/blob/main/rust/data/escape_timings.json. Recently there has been interest in supporting more refined escape timings, ones that don't assume all movement items are collected, and possibly taking into account cross-room strats (e.g. to shinespark through Croc Speedway in reverse). This is a much bigger undertaking than what we've done so far with escape timings, and I think it would make sense to be part of the sm-json-data. If this is done, a main benefit would be that in Desolate seeds it would no longer be needed for all movement items to be given for the escape, and escapes could require doing trickier strats. It would also allow us to support more options for "Escape start" seeds, where you would get only a subset of the items and again might have to do trickier strats.

Kyle and I were discussing a couple possible strategies:

  1. Include timing data on strats in sm-json-data; e.g. this could be a new strat property frames. Ideally every strat could have a timing, but incomplete coverage can also work; strats that don't have a timing just wouldn't be logically usable in the escape.
  2. Create a new project/repository specifically for escape timings. It would probably follow a similar structure to sm-json-data and share the same schemas, tech, and helper definitions but could have its own room data.

If possible, the first option seems most appealing, since having timing data on strats could have many applications, making it nice if it could stay integrated with the rest of the data. Examples of other things that could be done with it include finding optimized routes through a seed (minimizing total time) and supporting randomizer options that modify which rooms are heated.

There are a number of challenges:

  • In many non-heated rooms, junctions are currently defined in the way that doesn't make sense for measuring timings. For example, in Business Center the main junction has a large area covering most of the room, so there's no reasonable way to define timings for strats that move to or from that junction. I think that for timings, we would often need new strats that go directly from door to door, bypassing the junction. In some cases defining new junctions could be helpful; similar to what we're already doing in heated rooms, junctions would basically need to be defined as specific points in the room rather than large areas. The new strats that bypass the junctions (or use new ones) could clutter up the data, which was part of the motivation for considering using a separate project. On the other hand, we already have lots of strats that will seem like clutter to many players (e.g. G-mode strats, grapple teleports, runways, Crystal Flash refills, etc.); we could just add an attribute to mark strats that are only useful for "speed" purposes, i.e. where the timing matters, so then these strats could be filtered out if people aren't interested in them.
  • During the escape, enemies might be cleared, and this can make some strats not work. Most of it could probably be handled by the randomizer disabling "canUseEnemies" tech during the escape if enemies are cleared, though we need to go through and make sure that requirement is included everywhere that it is needed (e.g. it's currently missing in farm strats). There are some cases where the enemies being gone makes things significantly easier, e.g. in Wasteland or Three Musketeers; these could probably be handled by treating an obstacle as automatically cleared if it has "obstacleType": "enemies".
  • Depending on randomizer modifications, Hyper Beam can be used to open gates and destroy certain kinds of blocks. We would need to add strats for this, probably using a new logical requirement that could look something like {"hyperBeamShot": "PowerBombBlock"}, to support different possible behavior as far as which kinds of blocks can be destroyed.
  • Many strats use "or"s to define multiple alternatives of how to do something, and these alternatives could take different amounts of time. If a frames timing is a strat-level property, it would have to be based on the worst case among all the alternatives, which isn't ideal if the timings are substantially different. A couple ways that this could be avoided: 1) introducing frames logical requirement (either instead of or in addition to the strat property) similar to heatFrames, lavaFrames, etc., 2) splitting apart the strats into simpler strats to avoid the need for "or". Overall, I tend to favor splitting apart strats because this can also help improve the clarity of strat names & notes. A frames logical requirement would make me a bit nervous because it could easily be forgotten in some places, which would result in unsound logic. On the other hand, there are some strats which contain many "or"s (G-mode strats being a common example), where it could be difficult to split apart without getting an exponential blow-up in the amount of strats. Adding new junction nodes could be a solution in some of those cases. In other cases we could probably tolerate just having a single worst-case timing or no timing at all. G-mode strats may be less important for escape timings anyway, since they require enemies to set up and tend to be time consuming.

The way I'm envisioning this, adding timings to strats would be a long-term project that could happen in phases, starting with the lowest difficulty strats and moving up from there. If we can cover the "Basic" strats (plus Hyper Beam gate shots and maybe a few other little things), that's already enough for it to be usable in randomizers; I think we would launch it in Map Rando at that point. Adding higher difficulty strats just allows for tighter escape timings, smaller sets of placed items, and spicier tricks potentially required in the escape.

@kjbranch
Copy link
Contributor

In the short term, strats would only be useful for the escape, so some simplifications can happen to reduce the scale of the project:

  • Hyper beam can probably always be assumed in the escape, so that can simplify:
    • Any strats that need specific beam types (for enemy kill speed or for Wave or Plasma properties)
    • Hyper Beam can't freeze enemies, so none of those would need to be timed.
  • Rooms with a single door can probably be ignored. Runway timings should be able to be implicitly determined, so only useful non-adjacent runways would need to be modeled.

Maybe someday this could be thorough enough to change which rooms are heated. Even if the only strats that had Frames were those in Hard or below, that could still change the game significantly and is something that has been requested from many players.

@osse101
Copy link
Contributor

osse101 commented Apr 13, 2024

  • Including execution times on each strat would be cool since that let's us use those values instead of heatFrames, so it'd be more possible to make rooms heated.
  • Putting accurate frame counts on strats has been one of the harder things to do and maintain, and the standard for how crisp the expected execution should be has changed over time.
  • Many variables are going to affect execution time. Each Or branch, enemyKill, or previousNode. Everything relating to momentum.
  • Basic itself has some fuzzy rules on how you are able to move, particularly when doing platforming.
  • Strats are setup for minimal equipment, but having extra items may mean you move faster or slower through the strat. And turning off speed or hijump for every room may not be possible.
  • There needs to be an Enemies and No Enemies version. I think having enemies is closer to what vanilla does.
  • Hyper breaking various block types is a Map Rando feature. Varia turning blocks into an easier to break form could be seen as a similar feature. But there would still need to be a solution to no ammo, random room escapes in sm-json-data
  • Putting a timer on relatively difficult strats would make them even harder to do right away. But that's a randomizer problem.

I'd like frame counts on strats but I don't want them to be inaccurate, incomplete, inconsistent, or outdated. Unless inaccurate is what we want since its more manageable to model.
Strat frame counts would slow down adding new strats too much -> placeholder unassigned value
Strat branches -> Frame count of best case and add additionalExecutionFrames requirement. Probably no better than purely doing executionFrames.

I'd be more interested in separately doing door to door room timings with different loadouts. But I think that is the only difference. Strat times would ensure better coverage while being useful for other purposes.

Timing data is sm data so I think it has a place here.

@blkerby
Copy link
Contributor Author

blkerby commented Apr 13, 2024

Yeah, thinking about this more and talking it over with Kyle, it does seem like we would need a frames logical requirement for this, in order to have enough flexibility to include it in or branches, and in that case there's probably no reason to also have a strat property for it. executionFrames is another option for what it could be named; the advantage of frames is just being shorter to type and read, since it is going to be so commonly used.

Another thing (suggestion from Kyle) is that heatFrames can implicitly include frames as well, so there wouldn't be a need to double them up in all the heated rooms. heatFrames is unique in that each strat will be either entirely heated or entirely unheated, so the existing heatFrames (where specified) should always align with the total frames. This is not the case with lavaFrames, acidFrames, etc., where in many cases only part of the time of the strat will be spent taking that damage; so frames would not be implicitly included in those. We will have to be careful with strats that require heatProof (possibly just in an or branch), since those will either need frames to be explicitly added or to be treated as "never".

For doing door-to-door timings with different loadouts, there are some cases where I imagine this could blow up to some extent. I'm thinking of Mt. Everest for example. There are so many ways of moving through the room, and it's not just determined by item loadout: tech and entrance conditions also play a role. It seems like there's some trade-off between doing door-to-door timings vs. using the junctions. Door-to-door timings are easier to measure in the Practice Hack, but it would be a lot of new strats with a lot of duplication and overlap with the existing strats, which could be messy. In this case I think there could be more of a benefit to using the junctions and adding timing data to (a subset of) the existing strats, though we would want to redefine the junctions slightly to become points in the room rather than areas.

I'm hoping that it won't be necessary to create separate "Enemies" vs. "No enemies" versions of strats in very many cases. I think in most cases the strats can just be written under the assumption that the enemies are there; and if it depends on the enemies being there, then it should have a canUseEnemies requirement. In rare cases we may want a way to add alternative strats that assume the enemy isn't there; we could introduce a new logical requirement for that. In most cases though it seems like there's not a lot of difference between having Hyper Beam to clear out enemies vs. the enemies not being there. I have wondered if we might want to have a version of canUseEnemies that specifies the enemy name, since for platform-like enemies such as Kamers and Trippers there could be room for different behaviors as far as whether they get cleared during the escape or not. Granted, the timing data could eventually be used for purposes other than escape, so we'll want to be careful to avoid hidden assumptions about having Hyper Beam for instance, but for prioritizing how to populate the timing data it makes sense to start with stuff that's relevant to the escape.

@blkerby
Copy link
Contributor Author

blkerby commented Apr 13, 2024

For difficult strats, it's a good point that their effective difficulty can be changed by having a timer put on them. We could account for this on the randomizer side, e.g. maybe by applying a larger escape multiplier to high-difficulty strats. We might even consider entirely excluding strats with very high difficulty (e.g. Extreme or Insane); even if those strats had timing data I'm not sure if we would want the randomizer to require them during the escape.

Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment
Projects
None yet
Development

No branches or pull requests

3 participants