Real Time Conversation

Hey everyone,

I’m fairly new here to Inform 7. What I’m trying to do is create a sort of real time conversation system that gives the user a certain amount of time to answer a dialogue option. If they do not choose within a certain timeframe, the default option will be selected.

I’ve been trying to use a combination of Sarah’s real time extension, and Mark’s simple chat, but with little to no success so far.

Any suggestions?

Thanks,

HighZ

I can’t really give any answer, other than suggesting that it might help if you were a bit more specific about what you’ve tried and how it failed.

Also note that, while an interesting idea, there’s a real risk that this might turn out to be really annoying to play. There’s a reason why even most real-time action games pause the time whenever dialogue happens.

Telltale games new work. i.e. Walking Dead or Wolf Among Us use this type of mechanic as a central gameplay idea. By forcing the user to make a decision in an amount of time that is similar to real life it provides a lot more immersion into the game.

I don’t really know what I’m doing for the most part.

I’m stuck here. I’m not sure how to automatically trigger silence to be chosen when the timer hits 0

Include Simple Chat by Mark Tilford.
Include Glulx Entry Points by Emily Short.
Include Basic Real Time by Sarah Morayati.

This is the fake action rule:
the action fires in four turns from now.

Talking to is an action applying to one visible thing.

Understand “talk to [someone]” as talking to.
Report talking to: say “You have nothing to say.”.

Lobby is a room. Lisa is a woman in Lobby

when play begins:
forbid exiting on zero;

Initial Lisa, Remember, Forgot, Silence, Goodbye are chat nodes.

Instead of talking to Lisa: run a conversation from Initial Lisa.

Report giving text for Initial Lisa:
instead say “A woman looks up as you approach her. Do you remember who I am?”.

Carry out finding responses to Initial Lisa: link to Remember; link to Forgot; link to Silence; start timer for 5 seconds;

Report giving link to Remember:
say “Yeah, I remember you.” instead;
Report giving text for Remember:
say “I thought so” instead;
Carry out finding responses to Remember: link to Goodbye.

Report giving link to Forgot:
say “No, but you seem familiar” instead;
Report giving text for Forgot:
say “How could you forget”;
Carry out finding responses to Forgot: link to Goodbye

Report giving link to Silence:
say “…” instead;
say “Haha, you’re speechless.”;
Carry out finding responses to Silence: link to Goodbye

Report giving link to Goodbye:
instead say “I have to go”.
Report giving text for Goodbye:
instead say “'No matter, I’ll see you soon”.

Debatable.

Of course in some situations it works better than others. I’m just talking from my experience. But I’m not trying to argue the effectiveness of the mechanic.

And then there’s the obvious problem of informing the user how much time they have left to make a decision, but I really just want to get something basic down first.

I think it works in Walking Dead and other games like Mass Effect because essentially the player is pointing a joystick in the direction of four options onscreen (which are a summary of how to respond, not the actual line of dialogue) and pressing a button. If the player has to type a response, or read through a list of responses and pick a number, it might not work as well.

I tried an experiment with a CYOA that had real time stuff happening, and my testers got REALLY mad when they didn’t have time to take in everything on the screen and felt they were being rushed. Timing things works well for graphic games where one can respond instinctively. In a text game, the player is reading and comprehending with a different kind of brain function, so I think anything that serves to prod the player to “hey! read this faster!” needs to be done really effectively to work in a game.

Even Versu, which has NPCs who can actively bring up conversation on their own is turn-based and always gives the player the option to jump in or forfeit saying something. You have to make sure you’re almost never letting it happen that the player knows what they want to do but are prevented from doing so by the interface - which will have the opposite effect of destroying immersion, especially if what they can’t do is something that would happen easily and naturally in real life.

This is working in part, but there is a run-time error when it tries to reference the table that never got chosen if the user waits in silence.

Any ideas?

Spoiler for length

[spoiler]Include Simple Chat by Mark Tilford.
Include Glulx Entry Points by Emily Short.

when play begins:
forbid exiting on zero;

Talking to is an action applying to one visible thing.

Understand “talk to [someone]” as talking to.
Report talking to: say “You have nothing to say.”.

Lobby is a room. Lisa is a woman in Lobby.

Instead of talking to Lisa: run a conversation from Initial Lisa.

Initial Lisa, Remember, Forgot, Silence, Default, Goodbye are chat nodes.

Report giving text for Initial Lisa:
instead say “A woman looks up as you approach her. [line break] Do you remember me? [line break]”;
Carry out finding responses to Initial Lisa: link to Remember; link to Forgot; link to Silence;
start a 2000 millisecond timer;

Report giving link to Remember:
say “Yeah I remember you” instead.
Report giving text for Remember:
say "Lisa: I thought so [line break] " instead;
Carry out finding responses to Remember: link to Goodbye;
stop the timer;

Report giving link to Forgot:
say “No, but you seem familiar” instead.
Report giving text for Forgot:
say "Lisa: How could you not remember me?[line break] " instead;
Carry out finding responses to Forgot: link to Goodbye;
stop the timer;

Report giving link to Silence:
say “…” instead;
Report giving text for Silence:
say "Lisa: Haha, you’re speechless.[line break] " instead;
Carry out finding responses to Silence: link to Goodbye;
stop the timer;

A glulx timed activity rule:
run a conversation from Silence;
stop the timer;
re-request line event in main window;

Report giving link to Goodbye: instead say “I have to go”.
Report giving text for Goodbye:
instead say “Lisa: No matter, I’ll see you soon”;

To re-request line event in main window:
(- glk_request_line_event(gg_mainwin, buffer + WORDSIZE, INPUT_BUFFER_LEN - WORDSIZE, buffer–>0); -)

To cancel line input in the/-- main-window:
(- glk_cancel_line_event(gg_mainwin, gg_event); buffer–>0 = gg_event–>2; -)

To start a/-- (T - a number) millisecond/ms timer:
(- if (glk_gestalt(gestalt_Timer, 0)) glk_request_timer_events({T}); -)

To stop the/-- timer:
(- if (glk_gestalt(gestalt_Timer, 0)) glk_request_timer_events(0); -)[/spoiler]

Looks close; just a few things to tweak. First off, running a conversation from the Glulx timed activity rule will lead to trouble, because the original conversation is still waiting for its reply even while the new conversation (starting from Silence) charges forward. This is where your table errors come from. So instead, we want a way for the timer event to act as a response to Lisa:

The row number for silence is a number that varies. To decide what number is the chosen row number: (- ct_1 -). A Glulx timed activity rule: stop the timer; choose the row with a result of silence in the Table of Current Choices; now the row number for silence is the chosen row number; now the Glulx replacement command is "[the row number for silence]".
Working from the bottom up, the Glulx replacement command'' is provided by Glulx Entry Points for just these situations—those where we want a non-line-input event to act as a command—so we set that variable to select Silence. We have to find the option number for Silence by looking at one of Simple Chat's tables, but because in Inform the chosen row depends on which phrase is running, we can't just write "[the chosen row number]"; it won't be the same inside Inform's text-to-indexed-text conversion routine. Therefore, we stash the number in the variablethe row number for silence’’ on the line above. Getting at the row number is also a tricky point, because it’s hidden down in I6. The phrase about ct_1 takes care of that.

Even then, this code won’t work because version 9 of Glulx Entry Points doesn’t honor the Glulx replacement command from timed activity rules (version 10 may, but I don’t have my copy handy to check). So we also have to patch the extension with I6:

[code]Section - HandleGlkEvent routine with support for timer input (in place of Section - HandleGlkEvent routine in Glulx Entry Points by Emily Short)

Include (-
[ HandleGlkEvent event context abortres newcmd cmdlen;
context = 0; ! suppress ignored warning
switch (event–>0) {
evtype_Redraw:
if (FollowRulebook((+glulx redrawing rules+)) && RulebookSucceeded()) { rtrue; }
evtype_Arrange:
if (FollowRulebook((+glulx arranging rules+)) && RulebookSucceeded()) { rtrue; }
evtype_Timer:
FollowRulebook((+glulx timed activity rules+));
if ( FollowRulebook((+command-counting rules +)) && RulebookSucceeded()) {
FollowRulebook((+input-cancelling rules+));
FollowRulebook((+command-showing rules+));
if (FollowRulebook((+command-pasting rules+))) { return 2; }
}
evtype_SoundNotify:
if (FollowRulebook((+glulx sound notification rules+)) && RulebookSucceeded()) { rtrue; }
evtype_Hyperlink:
FollowRulebook((+glulx hyperlink rules+));
if ( FollowRulebook((+command-counting rules +)) && RulebookSucceeded()) {
FollowRulebook((+input-cancelling rules+));
FollowRulebook((+command-showing rules+));
if (FollowRulebook((+command-pasting rules+))) { return 2; }
}
evtype_CharInput:
if (FollowRulebook((+glulx character input rules+)) && RulebookSucceeded()) { rtrue; }
evtype_LineInput:
if (FollowRulebook((+glulx line input rules+)) && RulebookSucceeded()) { return 2; }
evtype_MouseInput:
FollowRulebook((+glulx mouse input rules+));
if ( FollowRulebook((+command-counting rules +)) && RulebookSucceeded()) {
FollowRulebook((+input-cancelling rules+));
FollowRulebook((+command-showing rules+));
if ( FollowRulebook((+command-pasting rules+)) ) { return 2; }
}
}
];
-) before “Glulx.i6t”.[/code]
So, drop the first code block in in place of your timed activity rule and add the second block, and your conversation should work.

Incidentally, for future posts, you can use code tags to preserve formatting, and it may also be useful to know that opinions here seem to favor not spoilering code blocks even when they are huge.

Thanks so much man!

That worked great!