I’m familiar with modular programming, but it doesn’t really apply here in quite the way you’re thinking (or at least, it would be bad design to try to apply it the way you’re apparently describing here due to how Twine works).
The JavaScript section and StoryInit passage should be used to initialize any code or variables which are used throughout the game, especially variables whose contents will never change. Otherwise, all other variables should be created (<<set>>
) or destroyed (<<unset>>
) on an as-needed basis, and temporary variables (the ones that start with an underscore) should be used whenever possible.
Whether your story is internally broken up into several parts or not doesn’t change that.
The reason why is that, every story variable which you add will get copied into every step of the game’s history, up until the point where the variable is destroyed. Keeping too many variables and/or not getting rid of variables you no longer need will bloat up the game’s history. And the larger the data in your game’s history is, the slower your game will get during saves, loads, and passage transitions. Thus it’s best to minimize the use and size of story variables however possible.
If one “chapter” (or whatever you want to define a module as) starts needing some variables, just define them as needed. There’s no need for a special “initialization section” for each chapter. You can initialize them right in the passage where you first need them.
If you want to make sure that you don’t overwrite a variable which was already initialized, then you can do something like this:
<<if ndef $someVar>>
<<set $someVar = "initial value">>
<</if>>
That would initialize the variable only if it was currently undefined.
If a chapter could have several “entry points”, then it would be best to make a widget which initializes the chapter’s variables using that technique, and then call that widget at the start of each “entry point” passage in that chapter.
Basically, if you have any variables which are used throughout the game, then those variables aren’t actually “modular” and you should initialize them in the JavaScript section and/or the StoryInit passage. On the other hand, any other story variables, such as ones which are only used once you enter a particular chapter of the game, should simply be initialized when first used and then disposed of when no longer useful.
There is no need or point to having a special “initialization section” for each chapter, and having them will likely make your game run more slowly. If you simply prefer having such sections, just initialize the relevant story variables in the first passage of each chapter, however you will likely be unnecessarily bloating up the game history by doing so.
And, since it’s relevant here, I should mention that you can use the Config.history.maxStates setting to control how many moments in the game history that your game will keep track of. If you expect to use a large number of variables and/or the variables contain lots of strings, then you might want to reduce that setting from the default value of 100
moments of game history, to something more like 10
or 20
. That will also help prevent slowdown in your game.
Another trick to shrink the history is, instead of storing data which will never change in story variables, store that data on the SugarCube setup object, which is not saved into the game’s history. For example, in your JavaScript section, you might have:
setup.day = ["Sunday", "Monday", "Tuesday", "Wednesday", "Thursday", "Friday", "Saturday"];
and then in any of your passages you could do:
Day $dayNum (<<= setup.day[$dayNum % 7]>>)
(<<=>>
is an alias of the <<print>>
macro)
Then, if $dayNum was set to 12
, that code would display:
Day 12 (Friday)
Since the days of the week won’t change, it’s fine to not store that variable in the game’s history, and thus by using the setup object in this way, it means that you’re storing a smaller amount of data in the game’s history than if you’d used a story variable to store that.
Anyways, hopefully you understand my confusion/concern now, and what I was trying to explain makes sense to you.