Conversations: choice language syntax vs parser language syntax

Continuing the discussion from Iron ChIF: Season One Episode 2 (Audience Commentary):

Hybrid Choices and Dialog’s choice mode work just fine from the player’s perspective. They’re no less expressive than Ink, and can do everything Ink or ChoiceScript can do.

The problem is the boilerplate you need for every. single. choice. Compare this bit of Ink code:

- I looked at Monsieur Fogg
*	... and I could contain myself no longer.
	'What is the purpose of our journey, Monsieur?'
	'A wager,' he replied.
	* * 	'A wager!'[] I returned.
			He nodded.
			* * * 	'But surely that is foolishness!'
			* * *  'A most serious matter then!'
			- - - 	He nodded again.
			* * *	'But can we win?'
					'That is what we will endeavour to find out,' he answered.
			* * *	'A modest wager, I trust?'
					'Twenty thousand pounds,' he replied, quite flatly.
			* * * 	I asked nothing further of him then[.], and after a final, polite cough, he offered nothing more to me. <>
	* * 	'Ah[.'],' I replied, uncertain what I thought.
	- - 	After that, <>
*	... but I said nothing[] and <>
- we passed the day in silence.
- -> END

(From the documentation)

This is what Ink calls a “weave”. A line starting with one or more *s is a choice, and a line starting with one or more -s is a “gather point”. Ink takes all the choices at the same level (same number of symbols), up until the next gather point at the same level, and presents them as a menu.

When the player picks a choice, all the code inside that choice is run…which can include more choices and gather points, one level deeper. So if you play this example, you get two choices, because there are two one-star lines before the one-dash gather:

I looked at Monsieur Fogg

1: ... and I could contain myself no longer.
2: ... but I said nothing

And if you pick the first one, you get two options, because there are two two-star lines before the two-dash gather:

> 1
... and I could contain myself no longer.
'What is the purpose of our journey, Monsieur?'
'A wager,' he replied.

1: 'A wager!'
2: 'Ah.'

And the first one leads to two more options, because there are two three-star lines before the three-dash gather:

> 1
'A wager!' I returned.
He nodded.

1: 'But surely that is foolishness!'
2: 'A most serious matter then!'

No matter which you pick, flow resumes at that three-dash gather, and presents three more options (the next three three-star lines):

> 2
'A most serious matter then!'
He nodded again.

1: 'But can we win?'
2: 'A modest wager, I trust?'
3: I asked nothing further of him then.

And finally it flows back to the two-dash gather, then the one-dash gather, and the example is over.

> 2
'A modest wager, I trust?'
'Twenty thousand pounds,' he replied, quite flatly.
After that, we passed the day in silence.

This example doesn’t do anything except printing text. But these choices could also set variables, or do math, or redirect to another passage entirely (the syntax is -> somewhere_else), and so on.

I absolutely love this syntax. It’s fantastic for writing a conversation. (ChoiceScript has something similar, though I find Ink’s more readable.) But now imagine the several lines of boilerplate needed for each and every one of these choices in Inform or Dialog!

That’s why I’m considering a transpiler that turns an Ink weave into a chunk of Dialog code, so you can write your conversation in the simple, fluid syntax, then embed it in a Dialog game. But right now, including a short choice-based segment in a parser game tends to require a lot of very clunky boilerplate code, because the syntax of parser languages isn’t designed to make it easy to write choices.

5 Likes

I’m not going to translate that whole thing into Dialog by hand, but here’s a segment from the Dialog manual for comparison:

(intro)		(activate node #start)

#start
(disp *)	You extend your wings. A warm, buzzy feeling spreads through your body
		as you leave the hive.
(* offers #rosebush)
(* offers #poppies)

#rosebush
(initial label *)	Follow a scent of roses.
(label *)		Return to the rosebush.
(disp *)		You hover for a while near the pink rosebush.
(* offers #poppies)

#poppies
(initial label *)	Follow a scent of poppies.
(label *)		Return to the patch of poppies.
(disp *)		You circle a fragrant patch of poppies.
(* offers #rosebush)

#rosebush-collect
(#rosebush offers *)
(sticky *)
(label *)		Collect nectar from the rosebush.
(disp *)		Yum! Rose nectar!
(* flows to #collect-done)

#poppies-collect
(#poppies offers *)
(sticky *)
(label *)		Collect nectar from the poppies.
(disp *)		Yum! Poppy nectar!
(* flows to #collect-done)

#collect-done
(* offers #rosebush/#poppies/#land)

#land
(label *)	Return back home.
(disp *)	After an impeccable landing, you find yourself back at the hive.
		(game over { A day well spent! })

This is expressing basically the same thing—a directed graph where nodes connect to each other via choices—but every choice requires up to six lines of code to define.

3 Likes

What I would say about Hybrid Choices is that it can feel heavy if it’s used for dialog alone. It does that well, but it’s built for more than that. Rather, it’s a Very Inform System with objects, relations, and rulebooks.

Each node (“page”) requires a minimum of four lines, I think.

I’d say the hardest part is organization, especially if you starting throwing custom rules into the mix. Unlike the Ink example, there’s no visible hierarchy. You can use a relations debug command to see how every page connects, and that’s something, but it still may be hard to visualize a complex exchange.

princesspalantirs is a page. it is for princesstalk. it is a dead-end.
cdesc is "About the spheres[if princesspalantirs is previously displayed] (read)".
"'They belong wherever the PROTAGONIST finds them, just like everything else in this place. Steve and I[em]she pats the dragon's flank[em]don't explore much, since he's too big to fit through most passageways.'".

a page-toggle for princesspalantirs:
	now the dragon is proper-named;
	now the printed name of the dragon is "Steve";

It’s the right choice for me, but it isn’t lightweight.

2 Likes

If you are thinking of writing an Ink->Dialog tool, you might consider writing it as a diagram converter instead? An idea to consider.

One thing is, conversations always work a bit different when inside a parser game.

Out of curiosity, I had a go at this concept, and here is what i got after a swift hack…

Here’s my diagram for Fogg:

So the only conversation is the one here, but in general you’ll have more and it’s always possible that some of these will happen at different points in the parser flow. So you have to be a bit more modular.

You can play it and see.

Play it

Some differences are;

  • Repeating your choice back to the game after you’ve selected it feels a bit wrong for parser.

  • There’s a bit of dialogue intro in the Ink version. “I looked at Monsieur Fogg”. Is that every time you engage in conversation? Or will there be random variations or just this once?

  • You might want to add background questions into your dialogue. These can happen interspersed with situational dialogue. I added some fake ones :slight_smile:

An idea anyway.

Inform is supposed to have a choice mode with a totally different syntax, especially designed for dialogues.

It says it’s implemented already, so one should be able to play with it by compiling Inform themself. I personnaly haven’t tried.

While it does seem cool, I’m kind of wary of having yet another syntax in Inform. Dialog’s choice mode is a lot of boilerplate, but I find it actually really readible for something that simply uses regular Dialog concepts!

1 Like

I’ve thought about making a more markdown-like/Ink-like DSL that can be transpiled to Dialog for a nicer writing experience, maybe with some automagic guessing of grammar properties (plural * etc.) and synonyms. But I keep not getting around to it, because it turns out that I’m not actually that keen on writing parser games.

I also once got a decent chunk of the way through making a “write parser games in Ink” framework, before eventually coming to my senses.

2 Likes

One frustration baezil and I have had with Hybrid Choices is not being able to make choices available or not based on properties or scenes; those are variables that exist in the game, but are off-limits for use in Hybrid Choices (as far as we can tell—I’d love to hear we’re wrong!). Aside from the general clunkiness, this is the major area of improvement I’d like to see.

2 Likes

That seems like it should be possible (and it definitely is in Dialog), but I don’t know enough about Hybrid Choices to say. Hopefully someone else can chime in!

You can! You need a choice-switch for [page] rule.

a choice-switch for requesttalk:
	if the sailor holds the jar, rule fails;
	otherwise:
		rule succeeds;

In this case, page requesttalk appears (rule succeeds) when the jar is not held by the sailor.

You can also make page-toggle rules that fire when a page is displayed.

3 Likes

Oh awesome, that’s exciting! Thanks!

2 Likes

I don’t know how I forgot/missed this. My misery is boundless and my shame unending.

2 Likes