Skip to content

[Titanic] Inquiry: Speedrun Tool, complex situations, and approach for new commands #255

Description

@mischlern

I'm thinking through some odd situations that could be encountered in a run that might be hard to determine with the current speedrun tool.


Gorse-Joneses in M1

If the player intends to skip the Rubaiyat in Mission 1, they must speak with the Gorse-Joneses and set joneshint to 1 in order to access Burns for the photos. They appear in the Grand Staircase (A-D) whenever the player map jumps there or uses the elevator (lift).

I'd want to try something like this using modern techniques (psudeo-code):

while( "joneshint" != "1") {        // loop multiple commands until we meet this condition
  mapJump(gstair2, deck: a)
  if (talking) {
    say([101])
  }
}

Or, something like this for a linear script:

...
10: door()
11: mapJump(gstair2, deck: a)
12: say([101], skip = true)         // 'skip' meaning some way to try say() and ignore if not in conversation
13: goToIf(11, joneshint != 1)      // "go to line 11 if we don't have the hint yet"
14: up()
...

I see combo() and hammer() for clicks, but no obvious way to do a multi-command conditional loop like this.


Phases during M4 Sinking

The phases during M4 are determined by a mix of real time (+1 sec/sec), player movement (varied), and conversations (+2 min/talk). As such, there may be times where the sheet will be interrupted mid command by an unexpected movie. This may be easily accounted for if runs are very precise and deterministic– sink1.mov always plays after this move, so add an ESC and continue`. However, we have the potential here for small variations (browser lag, different times to settle) and large variations (like tie in blackjack for second hand, lose blackjack and reload).

I'd imagine wanting something like JQuery triggers: "I'm expecting this to occur, and whenever it does, do this." In psudeo-code:

watchFor(movie, `sink1.mov`, skipMovie(until: awaiting))
watchFor(movie, `sink2.mov`, skipMovie(until: awaiting))
watchFor(movie, `sink3.mov`, skipMovie(until: awaiting))

I have no clue how this could be done in linear script, other than adding esc() commands to the end of any movement or conversation.


Blackjack, to win

Repeating the game until we win is, I believe, the same issue as the Gorse-Joneses: the need for loops and conditionals. In this case save() at the start, play a game, and if the conditions aren't what we want, load() and repeat the loop until we get our condition.

What I want to focus on here is how might we get a script to play Blackjack efficiently to win as often (quickly) as possible, assuming we can't do something like deterministic RNG manipulation, and assuming we don't flat out cheat and read variables like cardstring or dealerdowncard.

How might we define a set of conditional rules and actions in a sequence like this (psudeo-code)?

if playertotal <= 11, then hit and start list again;
else if score >= 18, then stay;
else if score - 10 < "dealerupcard", then hit and start list again;
else stay;

Likewise, how can the script read something like dealerupcard when it doesn't exist (at least in the details log)? If it doesn't exist, the only way to determine it would be to "subtract" dealerdowncard from dealertotal, involving parsing to get the down card value and creating our own variables to store the down card value and the up card value after the subtraction.

With linear code, the most consistent approach to win (assuming loops and simple conditionals are available) is to always Stay, read the ownership of the Rubaiyat or the Boat Pass after the game concludes, and reload if not the state we want. (Losing the Rubaiyat would be hammer() Hit until we don't own it, with a conditional check to load() if we win by Blackjack.)


What is the intent/direction of this tool?

As seen in my examples above, I'm not sure what to suggest to best address these situations.

I can see two general approaches (ends of a spectrum):

  • Non-linear: More like modern coding languages, with definable variables/functions, loop blocks, complex conditionals, etc.
  • Linear: Like tool assisted speedruns on deterministic consoles and emulators where runners must write linear sets of instructions per frame. In this case, the engine helps manage the variance in timing like a human can (e.g. watch for a condition like a screen loading or an item owned, then continue), but otherwise executes a series of player inputs.

The current scripting feels more linear, with a few examples of non-linear added in like hammer() or x(until: y). What is the goal for the speedrun tool commands? To stay more linear (like TAS) or open up more complex logic given we have full engine access?


Bonus: Accessing playe-hidden information

What about using data not available to the player? There's an opportunity to limit the tool (as best as possible) to what a human can know or determine. Looking at blackjack as a prime example, one could argue that a script should be able to read the player's cards and playertotal, but never playerdowncard and dealertotal.

That said, that might be more a question that something like a speedrun category definition can answer. Users could use this tool to do anything with any variable, but runs for specific purpose must avoid certain variables.

Activity

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

Metadata

Metadata

Assignees

No one assigned

    Labels

    enhancementNew feature or requestspeedruntitanicTitanic: Adventure Out of Time (taoot/)

    Projects

    No projects

      Milestone

      No milestone

      Relationships

      None yet

      Development

      No branches or pull requests

      Issue actions