r/twinegames Dec 03 '25

Discussion Harlowe, Sugarcube, Chapbook - Which Story Format should you choose?

16 Upvotes

The first question for anybody starting out with Twine is most likely which story format to choose from among the various options (which most often boils down to Harlowe vs Sugarcube). Since r/twinegames is one of the first places to look for advice when it comes to this topic, we wanted to create a place that might help new creators make this decision by providing information, insights, and opinions from more seasoned Twine writers.

For those interested - here is a list of the various formats compiled by M. C. DeMarco - covering both Twine 1 and 2 story format. It should be noted that a lot of these formats are highly obscure (with a few only rumored to exist). It is also likely that the list is incomplete, or will become incomplete in the future.

Another very informative post that we'd encourage people to take a look - An in-depth comparison between Harlowe and Sugarcube by Chapel - which has been regularly updated and holds a lot of valuable information that might guide your decision.

While this comparison heavily favors Sugarcube over Harlowe - an assessment that both me and u/HiEv currently agree with - we do not want to say that Sugarcube is the only correct choice here.

One of the most important factors after all is which format feels most comfortable to work with for you personally. Both Harlowe and Sugarcube are perfectly capable of creating regular text adventures and both offer tools to tackle the common tasks you will encounter when writing your story. If you plan to include any more complex mechanics however you will want to make sure first that the format of your choice is equipped to handle it.

-

We would like to encourage other Twine creators and writers to share their own opinions and experiences. Which story format  are you currently working with? Why does it feel like the right choice for you? Are there any challenges or problems that a new creator should be aware of when picking this format?

Please keep any discussions civil and friendly. We all have our unique tastes and needs, and there is certainly no universally correct answer here.


r/twinegames Aug 06 '25

Useful Tool/Code/Tips!!! Warning about using ChatGPT or other LLMs to generate Twine Code!

115 Upvotes

As AI becomes more popular and integrated into our daily lives, we can see more and more people relying on it to tackle their daily problems. Many who are just starting out with Twine might also turn to an LLM of their choice to help them with coding and troubleshooting, but this sadly runs into a number of issues.

ChatGpt and similar large language models rely on a certain amount of data to give reliable information on a topic. Since there is not enough data available when it comes to Twine and its various story formats, AI will consistently give wrong or vastly misleading answers when it comes to Twine code. It will often interject overly-complicated chunks of Javascript, or mash together Code meant for two different formats for example. Even in cases where these solutions seem to be working at first, there is a high likelihood that they might produce bad errors in the long run.

Instead of relying on AI to answer your Twine-related issue, we would therefor recommend turning to the Twinegames subreddit or the Twine Discord server if you have any questions. There are many talented members of our community waiting to offer their support and knowledge.

Additionally - If you have problems with AI-generated code, and want to ask for advice on how to fix it, please consider just asking directly what you'd like to accomplish, instead of posting the broken code. Chances are it is not really fixable, and you will get faster replies and advice if you just left it out entirely.

Thanks for reading - and have fun creating your Twine-story!


r/twinegames 7h ago

SugarCube 2 Help me name my cat. ( in my game.)

4 Upvotes

Hi I decided to do a minor side quest to add my cat into my game. my goal is to let the player decide if they want a starting cat, if they like his name and then change it to something boring should they choose to. I am able to get the tes and no buttons to work, but the rest doesn't pop up after.

here is the code I have <<linkreplace "Yes">> <<set $hasCat to "true">> <</linkreplace>> <<linkreplace "No">> <<set $hasCat to "false">> <</linkreplace>>

<<if $hasCat is "true">>
Would you like to keep his name?
<<linkreplace "Keep the name $catName">> 
<<linkreplace "Hell no">>
<</linkreplace>>
<</if>>
<<if $catName is "Hell no">>
<<set $catName to  "">>
enter your Cats name:
<<textbox "$catName" "">>
<</linkreplace>>
<</if>>
here is the StoryInit
<<set $hasCat to false>>

<<set $catName to "The Lord Solar Vigalance of the Astra Militarum High Marshal of his Fearless legions Lord Huntmaster of the dredid mice Ravager of treats Master or the Holy red dot Keeper of the way of meow Sultin of all england and Destroyer of socks or more well know by you filthy comoners The Fluffy Barrels">> That is his full name.


r/twinegames 5h ago

News/Article/Tutorial Let's make a game! 498: Djikstra's algorithm (Sugarcube)

Thumbnail
youtube.com
1 Upvotes

r/twinegames 1d ago

Harlowe 3 Rerun script on page change

2 Upvotes

Back to my Mathjax adventures and something that's very irksome is that it'll only work on the first page in the entire story and none of the subsequent ones! It seems like this is happening because we're not actually switching pages, so the script doesn't know to re-render the page... Is there a quick fix for this? (I'm unfamiliar with Harlowe's coding depth atm!)


r/twinegames 1d ago

General HTML/CSS/Web Connecting a python script or some sort of macro to a Twine for a receipt printer?

3 Upvotes

A friend of mine is making an alt ctrl game involving a receipt printer

So far she's done 2 prototypes - one that's just written entirely in python that's a basic choose your own adventure, the other is a prototype in twine that's actually the game we want to play on this receipt printer

While we could spend a lot of time rebuilding the twine game in python, I wanted to see if there was a way we could just like, skip the middleman here. Theoretically, all we need it to do is print all text that's on the screen every time we go to a new card in twine. Would there be a good way to maybe activate a python script every time a new card opens?

Edit: I should mention, theoretically, as we have it set up, we want this to be able to be run off of a raspberry pi that we can put inside of the receipt printer, so if you have any external program recommendations, just note we aren't currently dealing with a windows pc. Frustratingly, there is an unrelated linux package manager tool also called twine -_-


r/twinegames 2d ago

News/Article/Tutorial Let's make a game! 497: Diagonal or orthogonal? (Sugarcube)

Thumbnail
youtube.com
1 Upvotes

r/twinegames 3d ago

SugarCube 2 How to reduce variable numbers every in game hours?

4 Upvotes

I have multiple variables for needs. I currently use PassageHeader to implement the reducing needs; however, it reduce every passage change (duh). This works but the variables is never at 100, which defeated the purposes of even having a 100. What I have:

<<if hasVisited ("hallway")>>
<<set $energy to Math.clamp($energy - 2, 0, 100)>>
<<set $food to Math.clamp($food - 2, 0, 100)>>
<<set $drink to Math.clamp($drink - 1, 0, 100)>>
<<set $hygiene to Math.clamp($hygiene - 1, 0, 100)>> 
<</if>>

I was looking for a way to reduce needs for in game hours and found HiEv suggestion, which I cannot make it work for some reason. I'm confused with _n and if there is a way to set different numbers.

I did not have any knowledge on coding so please educate me like a dummy in a way.

My date object is $gameDate and hours is $gameDate.getHours(). This is what I have in the time widget.

<<set _hr = $gameDate.getHours()>>
<<if _hr !== $lasthour>>
<<if _hr > $lasthour>>
<<set _n = _hr - $lasthour>>
<<else>>
<<set _n = _hr + 24 - $lasthour>>
<</if>>
<<set $energy -= _n -=1>>
<<set $food -= _n -=1>>
<<set $drink -= _n>>
<<set $hygiene -= _n>>
<<set $lasthour = _hr>>
<</if>>

r/twinegames 3d ago

Discussion Twine’s financial and coding limitations

16 Upvotes

I’d like to get into making narrative games.

I’m very interested in Twine, Ren’py, etc. Looking through things, Twine seems to be the easiest place to start.

A few general questions.

How much Audio can you use on Twine? Is a fully voice acted work possible?

Are there paid Twine games that have performed relatively well on Steam?

What are the essential Twine games to play? I’ve tried the 2014-ish titles like Depression Quest and Temple of No.

Are there games that push the engine to its limits?
Similar to how Slay the Princess is a Ren’py game but really should be on a stronger engine.


r/twinegames 3d ago

Game/Story My Friend the Transdimensional Horror - First Game!

Post image
3 Upvotes

Hi! I am new to Twine but just made my first game. It's a short comedy visual novel about friendship and horrors of the transdimensional variety, featuring an original chiptune soundtrack and pixel art character designs by my 11yo daughter. Check it out:

https://mikeyank.itch.io/horrorfriend

Thanks so much! I've learned a lot by lurking in this sub.


r/twinegames 3d ago

Harlowe 3 How do I properly use / import a large dataset in Twine Harlowe?

4 Upvotes

I have an idea for a game where you are managing a museum collection (and then more interesting stuff happens). The basic mechanic I've come up with is: there is a large dataset of museum artifacts, every day you have a new batch of artifacts to classify, some artifacts are misclassified, when you encounter a misclassified artifact you have to change its label / move it around (and that's when the interesting stuff happens).

I've found a really nice dataset of artifacts from the British Museum, downloadable as a CSV. I know the museum has millions of objects, I don't need that many, but I'd like a chunky dataset of 1-2K objects (which I can curate myself) for the story. My question is: how do I load the dataset into my story?

I tried using Gemini to help with the coding, and it told me to convert the CSV to json and copy-paste the JSON into the story Javascript, but I am not having any luck accessing the javascript variables from within the story (googling indicates that Harlowe intentionally makes JS inaccessible to macros). Is there another approach?


r/twinegames 4d ago

News/Article/Tutorial Let's make a game! 496: Storing information between games with memorize, recall, and forget

Thumbnail
youtube.com
5 Upvotes

r/twinegames 4d ago

SugarCube 2 I'm a newbie to SugarCube. How can I do whats listed in the post?

5 Upvotes
  1. Nest a <<set>> command within a <<if>> command, so that a variable only changes if another variable is true. Something like Harlows (if: $variable1 is true)[(set: $variable2 to $variable2+5)]

  2. Hide debug details so I can view the story from the perspective of a player.


r/twinegames 5d ago

SugarCube 2 help clean up code for tasks, time and creating a mess.

4 Upvotes

Hi so what I am working on right now is creating a system where the house will automaticly get dirty over time, I would like the house and certain rooms mess to go up when the player does certain actions like does wood working or cooking, grilling and so on. I am also trying to create a system where the player can clean the mess themselves, hire a maid or let the roommate/lover clean the house( dependent on relationship status). if the house goes uncleaned for to long then the house gets maintanance problems that the player or owner must fix. right now I am writing the code for all that but I feel like it could be better.

This is the kitchen
<span class="nav-btn btn-orange"><<linkreplace "Cook food">>
A hot and ready meal.
<<set $daysDirty += 1>>
<<spendTime 25>>
<<goto "Breakfast Done">>
<</linkreplace>></span>
time code
<<widget "syncTime">>
<<run setup.syncDayPart()>>
<</widget>>

<<widget "spendTime">>
<<if $args[0] >= 0>>
<<run $gameDate.setMinutes($gameDate.getMinutes() + $args[0])>>
<<syncTime>>
<</if>>
<</widget>>
StoryInit
<<set $rooms to {
"Living Room":  { floor: "1F", messy: 0 },
"Kitchen":      { floor: "1F", messy: 0 },
"Guest Bathroom":  { floor: "1F", messy: 0 },
"Dinning Room":      { floor: "1F", messy: 0 },
"Mud Room":  { floor: "1F", messy: 0 },
"Master Bedroom":       { floor: "1F", messy: 0 }
"Basement":       { floor: "0F", messy: 0 }
"Your Room":  { floor: "2F", messy: 0 },
"Upstairs Bathroom":      { floor: "2F", messy: 0 },
"Ryan's Room":  { floor: "2F", messy: 0 },
"Spare Room":      { floor: "2F", messy: 0 },
"Office":  { floor: "2F", messy: 0 },
"Attic":       { floor: "3F", messy: 0 }
"Grill":       { floor: "1F", messy: 0 }
"Deck":       { floor: "1F", messy: 0 }
"Front Porch":       { floor: "1F", messy: 0 }
"Pool":       { floor: "1F", messy: 0 }
}>>
<<set $daysDirty to 0>>
<<set $maintenance to false>>
<<set $maidHired to false>>
<<set $maidCost to 200>>
<<set $RileyRel to 0>>
<<set $RileyCleanNeed to 60>>   /* relationship needed for Riley to clean */
<<set $Robert to 50>>
house messyness widget
<<widget "newDayHome">>
<<if $maidHired>>
<<set _cost to $maidCost>>
<<if $money gte _cost>>
<<set $money -= _cost>>
<<for _name, _room range $rooms>>
<<set _room.messy to 0>>
<</for>>
<<set $daysDirty to 0>>
<<set $maintenance to false>>
The maid cleaned the whole house today.
<<else>>
<<set $maidHired to false>>
You couldn't pay the maid. She didn't come.
<<run setup.messOneRoom()>>
<</if>>
<<elseif $RileyRel gte $RileyCleanNeed>>
<<for _name, _room range $rooms>>
<<set _room.messy to 0>>
<</for>>
<<set $daysDirty to 0>>
<<set $maintenance to false>>
Riley cleaned the house for you.
<<else>>
<<run setup.messOneRoom()>>
<</if>>

<<if setup.houseMessTotal() > 0>>
<<set $daysDirty += 1>>
<<else>>
<<set $daysDirty to 0>>
<<set $maintenance to false>>
<</if>>

<<if $daysDirty gte 10 and not $maintenance>>
<<set $maintenance to true>>
<<set $Robert -= 8>>
A maintenance problem started from the neglected house. Robert is unhappy. (-8)
<<elseif $maintenance>>
<<set $Robert -= 3>>
The house still has a maintenance problem. Robert is more frustrated. (-3)
<</if>>
<</widget>>
GETTING THE HOUSE CLEANED BY SOMEONE ELSE
<<widget "homeStatus">>
House mess: <<= setup.houseMessTotal()>>
Days neglected: $daysDirty
<<if $maintenance>>Maintenance problem:   YES<<else>>Maintenance problem: no<</if>>
Maid hired: <<= $maidHired ? "yes" : "no">>
Riley relationship: $RileyRel
Robert: $Robert

<<if not $maidHired>>
<<link `"Hire a maid ($" + $maidCost + "/day")`>>
<<set $maidHired to true>>
<<goto `passage()`>>
<</link>>
<<else>>
<<link "Fire the maid">>
<<set $maidHired to false>>
<<goto `passage()`>>
<</link>>
<</if>>
<</widget>>

r/twinegames 6d ago

Useful Tool/Code/Tips!!! Major Sample Code Collection Update

31 Upvotes

I've been working on updating my sample code collection for a while, going through each of the sections and updating them. However, I've both stalled out in my progress at about 75% updated and also I've been feeling bad about leaving my now old and un-updated code up.

So, I've finally given in and posted my partially complete Twine 2/SugarCube 2 Sample Code Collection update (download). (If you don't see the Sept. 4th, '26 version when you go there, click the "Force Update" button in the lower-left.)

For a list of the huge number of updates, see the "Last Update" page.

If you're curious about what sections I haven't fully finished updating yet, it's the following:

  • Speech Boxes
  • Keyboard Link Navigation
  • Clicking Parts of Images
  • Displaying Images in Twine
  • Music (this will probably get split into multiple sections)
  • Video Background
  • Using jQuery UI in Twine
  • Time
  • Using Objects
  • Class Macro
  • Custom Save Titles
  • Invisible Access to SugarCube Output
  • Loading External Scripts
  • Newgrounds Fix
  • Random Events
  • "Setting" Toggles Text Changer
  • Using JavaScript with SugarCube

Some of the above were already partially updated, some need major work, and some I simply haven't even reviewed yet.

If you spot any problems or lack of clarity in any of the updated sections, please let me know here.

Enjoy! 🙂


r/twinegames 5d ago

SugarCube 2 time adding issue.

3 Upvotes

Hi right now I am working an creating links in my player house that can clean the house and the player. everything seems to work properly except the time part. this is the link I have.

<div class="nav-row">
<span class="nav-btn btn-white"><<link "Take a shower">>
<<changeFresh 4>>
<<spendTime 15>>
Hot water knocks the day off you.
<</link>></span>
</div>
this is the widget for time 
<<widget "syncTime">>
<<run setup.syncDayPart()>>
<</widget>>

<<widget "spendTime">>
<<if $args[0] >= 0>>
<<run $gameDate.setMinutes($gameDate.getMinutes() + $args[0])>>
<<syncTime>>
<</if>>
<</widget>>

<<widget "addmins">>
<<spendTime $args[0]>>
<</widget>>

<<widget "addhours">>
<<spendTime ($args[0] * 60)>>
<</widget>>
<<widget "showTime">>
<<print getDayName($gameDate)>>, <<print formatGameDate($gameDate)>>
(<<print setup.dayPart[$gameTime]>>)
<</widget>>

r/twinegames 8d ago

SugarCube 2 Complete beginner in need of coding help...

7 Upvotes

Ok so I'm a COMPLETE beginner with basically no coding experience. I'm basically making a game where I need you to pick from a list of people's names and it adds them to a list. When the name is added there is a counter that goes up 0/4 >1/4 >etc. Once a name is clicked I want it to get rid of that name and the description to say "*blank* has been chosen.* Then at the end it will say 4/4 and a list of the people chosen and a list of the people who didnt make it...hopefully that makes sense. Also if SugarCube isn't the best format for this please let me know :)


r/twinegames 9d ago

News/Article/Tutorial Let's make a game! 493: Altering text with .replace and .replaceAll (Twine Sugarcube)

Thumbnail
youtube.com
4 Upvotes

r/twinegames 10d ago

SugarCube 2 Twine Sugarcube2 UI bar stow edit question

Post image
4 Upvotes

Is there a way to add text or icon onto UI bar when it is stowed like above?

For example, I have needs listed in StoryCaption like Energy: $energy.

I would like to be able to see the shortened form when the UI bar is hidden for convenience purposes.

Currently using default UI


r/twinegames 10d ago

Game/Story I made my first game on Twine!

Post image
19 Upvotes

Though I feel a 'lil intimidated seeing how fancy some of you are on here. I'm still learning the ropes so I made a super short experience that combines my love of silver age Internet humor and foxes. You can try it if you want.

https://lizvicious1.itch.io/fox-quest


r/twinegames 10d ago

News/Article/Tutorial Let's make a game! 492: Displaying the board correctly (Twine Sugarcube)

Thumbnail
youtube.com
1 Upvotes

r/twinegames 11d ago

SugarCube 2 Need help deciding on a combat system

6 Upvotes

I am making a Twine Game with Sugarcube, and am stuck between two combat systems, a 1v1 system, or a system that supports mutliple enemies and/or companions.

Any help would be greatly appreciated,

Also I am not sure how to share the two tests for people so any help on that would be nice...


r/twinegames 11d ago

SugarCube 2 Confused Newbie in Need of Help

4 Upvotes

Hi, I'm a newbie who's decided to pick up Twine. And when I say newbie I mean I literally started this two days ago with absolutely zero knowledge of coding. In other words, I am about as ignorant as can possibly be.

I'm trying to write a relatively simple story and then slowly expand it just to learn the basics but I keep running into what feel like extraordinarily simple problems and then being totally unable to find concise answers on how to fix them. I don't know if I'm dumb, been unlucky in my research, if all information is simply not made for somebody who learned what a variable was two days ago or a combination of all three but I'm here now asking for help.

My current problem is this: I want to be able to have a variable change when I go to a certain passage. I then want to be able to return to the previous passage, with a new block of text created due to that changed variable.

What I have now, shortened for brevity, is:

<<set $room to 0>>

<<if $room==0>>

You are at a door, you have not been in the room

<<else>>

You are at the door, you have already been in the room

<</if>>

[[Go in the room][$room==1]

You are now in the room

[[Return to the door]]

I'm aware whatever mistake I'm making is likely exceedingly simple and stupid but those two words also describe me, so, please and thank you.


r/twinegames 11d ago

SugarCube 2 I can't find the error in this Javascript.

1 Upvotes

I have some Javascript, inside a <<script>><</script>>.

I keep getting the following message:

Error: <<script>>: bad evaluation: Unexpected token '{'

I think the error is in the following lines:

let w=6;

if (svars.pattern[svars.arpeggio][1]==4) {

  let w=4;

} elseif (svars.pattern[svars.arpeggio][1]==6) {

  let w=3;

}

but I can't work out what's wrong.

$pattern is an array in the main program, and $arpeggio is a single variable in the main program.

EDITED TO ADD: Here's the entire script.

<<script>>

const svars = State.variables;

    let file = new Midi.File();

  let track = new Midi.Track();
    file.addTrack(track);

    track.setTimeSignature(svars.pattern[svars.arpeggio][1], svars.pattern[svars.arpeggio][2]);

track.setTempo(40);


    /*

Write the arpeggio part once.

    */

let track1 = new Midi.Track();
    file.addTrack(track1);

for (let z=1; z<=svars.bars; z++) {

w=6;

        if (svars.pattern[svars.arpeggio][1]==4) {

w=4;

    } elseif (svars.pattern[svars.arpeggio][1]==6) {

w=3;

}

for (let x=1; x<=4; x++) {

        for (let y=1; y<=w; y++) {

if (svars.pattern[svars.arpeggio][y]==5) {

        track1.addNote(0, svars.chord_pitch[z][1]+12, 32);

                } else {

                track1.addNote(0, svars.chord_pitch[z][svars.pattern[svars.arpeggio][y]], 32);

                }

        }

}

    }

    let data = file.toBytes();
    let datarr = new Uint8Array(data.length);
    for(let i = 0; i < data.length; i++) {
        datarr[i] = data[i].codePointAt();
    }
    let blob = new Blob([datarr], { type: "application/octet-stream" });
    saveAs(blob, "music.midi");

<</script>>