How to create a chatbot style story in Twine

Hello Im new to twine.
Im creating a story (non-linear) that simulates a chatbot
In twine you will be taken to another passage when you click the link
Im trying to preserve the previous passage that goes up the page once a new passe is displayed (Link selected).
Not sure where to look at to achieve this.
Hope someone can help.
Thank you in advance.

Hi Andlen!

I’m not sure what kind of effect you’re trying for. Could you post an example of what you’d like the output to look like?

There are lots of different ways to write chatbots. How best to do it depends on a lot of things, primarily what exactly you need it to be able to do in your game.

If you’re interested, I outlined one method in this r/twinegames thread: “Making a default “I don’t understand” response to the player’s typing”

Also, I showed how you could add a textbox for entering text to the bottom of the screen in this post: “How to make a textbox fill the width of the screen?”

Hope that helps! :slight_smile:

I don’t see anywhere you’ve clarified which story format you’re using, but if I interpretted your question right and you’re using SugarCube, you can do something like this:

First of all, you’ll want a variable - an Array - to store the titles of the passages the player has already had displayed to them. That way, everything they’ve already seen will apear when they load a saved game or refresh the page in the browser.

Create a passage with the name StoryInit and make sure spelling and capitalization is exact. In this passage, along with anything else you want to set up the first time a user starts a brand new game, create an array something like this:

<<set $Visited = []>>

Then, to achieve the effect you want for story progression, you’ll probably want to use a “Master” passage which the user will remain on throughout the game and use the <<include PassageName>> macro to display the other passages:

The main passage would look something like this:

<div id="progression">
	<p>Are you ready for a grand adventure?</p>
	<div id="choices">
		<<link "Varily!">>
			<<run $Visited.push("Begin the Adventure")>>
			<<remove "#choices">>
			<<append "#progression">>
				<<include "Begin the Adventure">>
			<</append>>
		<</link>>
		<<link "Nope. Too scared.">>
			<<run $Visited.push("Encourage to Begin")>>
			<<remove "#choices">>
			<<append "#progression">>
				<<include "Encourage to Begin">>
			<</append>>
		<</link>>
	</div>
	
	<<for _i, _passage range $Visited>>
		<<include _passage>>
		<<if _i < $Visited.length - 1>>
			<<script>>
				setTimeout(function () {
					$("#choices").remove();
				}, 15);
			<</script>>
		<</if>>
	<</for>>
</div>

Passage titled: Begin the Adventure

<p> Splendid! You bravely step forth onto the forest path, ready to do the things that need doing by an adventurer what can do it.
</p>
<p> Soon, you come to a fork in the path. One appears to be a deliberate trail, while the other looks more like a game trail. Which do you choose?
</p>
<div id="choices">
	<<link "The man-made trail">>
		<<run $Visited.push("Along the Main Trail")>>
		<<remove "#choices">>
		<<append "#progression">>
			<<include "Along the Main Trail">>
		<</append>>
	<</link>>
	<<link "The game trail">>
		<<run $Visited.push("Along the Game Trail")>>
		<<remove "#choices">>
		<<append "#progression">>
			<<include "Along the Game Trail">>
		<</append>>
	<</link>>
</div>

Explanation:
So, in the starting passage, we have a region with the ID “progression”. This will contain the passages the player visits. In this, we have the very first text the player will see in the game, along with the first “choices” region in which we have <<link>> macros. Each of these links will add its assigned passage title to the $Visited array, remove its “choices” container so that the links within disappear, and add (append) its assigned passage to the story “progression”. This will be the functionality of all links that you want to use to navigate the story.

Next, we have a <<for>> loop. At the very beginning of the story, this won’t run at all because the $Visited array is empty. However, if the player has made progress and is loading their game or refreshes their browser, it will start looping through each passage title in order, displaying its contents in the “progression” div just like clicking a link would. Then, it checks if it is at the end of the array (the most recent passage). If it isn’t, it waits a brief time to ensure the included passage has actually had time to be displayed before removing that passages “choices”, as one has already been picked. If it is at the most recent passage, this won’t happen and the “choices” will be displayed for the user to pick from.

NOTE: I used the JavaScript setTimeout() method instead of SugarCube’s <<timed>> macro because the least amount of time you can set for the <<timed>> macro is 40 milliseconds. This isn’t much on its own, but the time it takes for the full story to be displayed will increase much more quickly than if the delay is smaller. Keep in mind that will still take a while for a long story to display using this method I’m showing you now.

Now, as you can see, the passages themselves also have a “choices” div which will appear when it is included, and which is removed when one of the links is clicked or if it is being displayed in the initial <<for>> loop and isn’t the most recent passage.

Keep in mind that there are other ways to do this, but as you are new to Twine, this might be the easiest way to get started with it and see how these features work. You could reduce the display delay by simply storing the entire story in an array, but this will make your save files huge eventually and that can get dangerous.

I hope this helps. If you’re actually using Harlow or another format, I can’t really help you there as I’m not familiar with Harlow’s script, but perhaps the concept I’ve shown you can be translated.

2 Likes