Skip to content

Story generation #8

Description

@Kinrany

Hi! I'm trying to convert stories written in another tool into stories written in ink.

I wondered if I could use your crate. I assume it is not intended for this purpose, but I wonder how hard it would be to change that.


This is not exactly the feedback you asked for, but I have an idea of what the high-level API could look like and I thought you might want to hear it:

  1. Source code representation struct Source: represents an .ink text file. Implements From<&str> for parsing and Display for printing. Allows errors.
  2. High-level story representation struct Story: has all the content of the story, but without the details. Implements TryFrom<Source> and Into<Source>. Does not allow errors. Can be used to start playing a story.
  3. Runtime representation enum Playthrough { Text, Choice }: tracks the current state of the story being played. Stops at either a text line or a choice. Basically a state machine.

The implementation of the runtime representation is a lower level detail than the overview and less important. I'll just present the API that I think seems the most obvious (after thinking about it for like 20 minutes) for embedding the crate as a story engine in another program.

The most common flow would look like this:

// read the text
let source: Source = "hello world".into();
// compile the story
let story: Story = text.try_into()?;
// create an active instance of the story
let mut playthrough = story.start();

loop {
    match playthrough {
        Text { line, next } => {
            // show the paragraph and
            // proceed to the next step
            println!("{}", line);
            playthrough = next;   
        },
        Choice(choice) => {
            // show the options, let the reader choose one,
            // pass the chosen option to the state machine,
            // proceed to the step determined by the chosen option
            println!("{}", choice.options);
            playthrough = choice.choose(get_chosen_option());
        },
        End => {
            println!("FIN");
            break;
        }
    }
}

This would neatly split the implementation into three smaller reusable parts that would allow a range of different. It would allow using the crate for editing ink files and for publishing finished stories in various formats.

Any or all of this might be overengineering though 🙂

Metadata

Metadata

Assignees

No one assigned

    Labels

    enhancementNew feature or request

    Projects

    No projects

    Milestone

    No milestone

    Relationships

    None yet

    Development

    No branches or pull requests

    Issue actions