pjohansson / inkling

Limited Rust implementation of the Ink markup/scripting language for game narratives
Other
42 stars 7 forks source link

RFC: What to return from `Story::resume` #2

Open pjohansson opened 4 years ago

pjohansson commented 4 years ago

Currently, Story::resume returns a Prompt which is an enum with two values: Done, to signify that the story reached an end, or Choice, to indicate that a branching point has been reached. The resume method follows the story until either one has been reached. The pro's of this is 1) it allows for the game loop to simply be while let Prompt::Choice(choice) = story.resume(...) { /* handle choices */ }, and 2) it parses the complete flow until an action has to be taken. The con is, that it may skip through a whole bunch of stitches and knots which do not contain a branching choice. The user might want to take action during a knot change.

Thus, I believe it would be preferable to change how Story::resume works. Instead of breaking only at branching points or the end, to additionally return once the story moves to a new knot or stitch, since these may mark changes in e.g. tone and graphics (through the use of tags, or whatnot). This would leave it for the user to then decide whether this means anything, or if the story should move on to the next knot or branching choice.

There are, however, two ways to go about adding this additional return on the move to a new stitch or knot:

1) Expand the Prompt enum to:

enum Prompt {
    Done,
    Choice(..),
    MoveTo(..),
}

(possibly renaming the enum in the process). This is straightforward with its intent, and the user can match on the content to figure out what to do. However, it disallows the simple while let Prompt::.. = story.resume(..) loop that is also very clear about its intent and is the simplest way to implement the main loop through the dialogue.

2) Expand the Prompt enum to (in pseudo code):

enum Prompt {
    Done,
    Action(enum Action {
        Choice(..),
        MoveTo(..),
    }),
}

That is, to introduce another enum (tentatively called Action) which contains the information about how to proceed with the story. This is slightly more complicated, but still allows for a simple while let Prompt::Action(..) = story.resume(..) loop. The user would just have to match on this to proceed.

I personally am leaning towards option 2), because I greatly favor the simple while let match which is a wonderful feature of Rust. But FWIW, if anyone else has experience with using these patterns in practice and prefers otherwise, I would be happy to know of it.

knownasilya commented 3 years ago

Option 2 👍