Dialogue¶
Many narrative games involve dialogue in which characters talk with one another. Dialogue provides a convenient way of structuring back-and-forth talk in which the player’s choice of response leads to the interlocutor saying something else. Back and forth until the end of the conversation.
Dialogue relies on a data structure of lists and dicts recording what gets said, possible responses, and what happens when each response is given. That data structure looks like this:
{
"START": {
"content": [
"Hello",
"Have we met?"
],
"options": {
"You don't remember?": "FRIENDS",
"I think not": "STRANGERS"
}
},
"FRIENDS": {
"content": [
"Oh, of course.",
"I didn't recognize you with that wig."
],
"options": {
"Do you like it? It's new.": "WIG",
"I doubt that.": "ANGRY",
}
},
...
}
Writing dialogue this way can get tedious. Instead, you can write dialogue in a simplified dialect of the
Ink language and use Dialogue.from_ink(). Here is the Ink code for the Grandma’s Soup example game.
It should be pretty self-explanatory:
=== START ===
Oh hello there, my dear. It's so nice to see you. I knew you were coming today
so I decided to make your favorite soup.
Before I can make it though, I need to forage some vegetables from the island.
My legs are not as strong as they used to be. Do you think you could help me?
+ Of course, grandma! -> HELP
+ Meh, I was gonna play fortnite -> BADBOY
=== HELP ===
Oh you are such a dear.
+ What do you need? -> VEGGIES
=== BADBOY ===
You are a very bad boy.
+ Sorry, I'll help. -> VEGGIES
=== VEGGIES ===
I just need a few things. I need carrots and potatoes and
tomatos.
Oh, and can't forget a mushroom!
+ OK -> END
=== CARROTS ===
Oh, these are lovely carrots. But I still need more vegetables.
+ OK -> END
=== TOMATOS ===
Oh, these are such ripe tomatos. But I still need more vegetables.
+ OK -> END
=== POTATOES ===
Oh, these are very spuddy potatoes. But I still need more vegetables.
+ OK -> END
=== MUSHROOM ===
Oh, what a beautiful mushroom. It reminds me of my girlhood. But I still need
more vegetables.
+ OK -> END
=== SOUP ===
Ah, now we have everything we need for some delicious soup! why don't you go
explore the island and I'll call you when it is ready?
+ OK -> END
-
class
quest.dialogue.Dialogue(knots)[source]¶ Models a dialogue interaction as a graph of knots. Each knot has a list of content and then a list of choices leading to further knots (or ending the dialogue). where each choice links to another talk turn or ends the dialogue. A Dialogue instance has a “result” property which the game can use to determine what happened.
-
classmethod
from_ink(ink_path)[source]¶ Reads talk turns from a YAML file and uses them to initialize a new Dialogue. Note that this is a @classmethod, which means it should be used by the Dialogue class, not an instance of Dialgoue. For example:
>>> dialogue = Dialogue.from_ink("examples/dialogue_sample.ink")
- Parameters
ink_path – A string with the ink filename containing talk turns. talk turns. For an example of the expected format, see quest/examples/dialogue_sample.ink.
- Returns
A newly-created Dialogue instance.
-
run(start_at='START')[source]¶ Starts (or re-starts) a run of the dialogue by setting the current knot to start_at and running to True.
- Parameters
start_at – (default “START”) Name of knot to start at.
-
choose(choice)[source]¶ Chooses an option and moves to another knot. If that knot is “END”, ends the current dialogue run.
- Parameters
choice (int) – The index of the choice to follow.
-
replace_vars(contents)[source]¶ Returns the content items of a knot or option content list with the ink variables replaced with variables from the game’s dialogue_vars dictionary.
- Parameters
content (str) – the ink content
dialogue_vars (dict) – the variables from the game associated with their value
-
classmethod
-
class
quest.dialogue.DialogueRunner[source]¶ Runs a Dialgoue from the command line. This is useful for testing out dialogue. If you have a file called “conversation.ink”, here’s an example of how to run it:
>>> dialogue = Dialogue.from_ink("conversation.ink") >>> runner = DialogueRunner() >>> runner.run(dialogue)