-
Notifications
You must be signed in to change notification settings - Fork 3
Arrays
This article assumes a basic understanding of how arrays are implemented and used in ChoiceScript (wiki).
When creating and using variables with cslib, a number of additional conventions must be followed and understood. These might seem like a bit of a bother at first, but we can assure you, they will make your life (and your game development) much easier in the long run.
Whilst ChoiceScript supports both local (created by *temp) and global (created by *create) arrays, cslib unfortunately (due to its reliance on *gosub_scene), only supports global arrays. Local variables do not exist outside of the exact instance of the scene in which they were created, and as ChoiceScript doesn't have a concept of 'scoping', there is no (vanilla) way to refer to these local values from outside that same instance of the scene.
On a related note, as ChoiceScript's parameter passing (wiki) is pass-by-value, this means that any cslib routine that expects an array as an argument, is actually expecting an array "reference". This simply means that you need to pass the name of the array as a string, as opposed to trying to pass one (or all) of the array variables themselves.
Note the quotes around the "my_arr" in the example below:
*gosub_scene cslib_array pop "my_arr"
*comment this refers to the variables named: 'my_arr_n' where 'n' is a numerical index
You can read more about references on the wiki page.
Any cslib function that accepts an array may assume (by convention) that the array has both a _count and a _max attribute associated with it (if it doesn't, things will probably go BOOM 💥).
What do we mean by attribute? The ChoiceScript array syntax supports string references (${stats["strength"]}), as well as numerical indexes (${characters[2]}) (so they're more like objects or dictionaries, really -- if you're familiar with other programming languages). So an attribute (within this documentation) refers to an array variable that is suffixed by a string-like name (as opposed to a number). I.e. If we have a variable called stats_strength, then "strength" is an attribute of the array 'stats'.
cslib expects every array it touches to have two attributes: "max" and "count". These are usually styled as the '_max' and '_count' values in our documentation and code comments, in order to help distinguish them from the actual words 'max' and 'count'. We will continue to refer them as such from here.
The _max attribute is pretty straight forward: it denotes the number of array variables you have in your game. This is something most people would have to do in vanilla ChoiceScript anyway (as there's no length function for arrays), though they may not have called it _max.
This value is a CONSTANT and should never be changed (by the user or cslib).
It's purpose is to quite simply stop cslib going off the end of your array and referring to array variables that don't exist.
The _count attribute tells cslib how many of those array variables contains useful data. Because you can't dynamically "grow" arrays in ChoiceScript, it is common practice to create an array that is larger than what you initially need, so you can artificially grow its size overtime. But why can't we use _max for this? Because if you overwrote _max, then you would no longer have a reference to reset it with. We could ask/expect CS users to store (and restore) this value themselves, but having a clear convention allows cslib to help diagnose any mistakes.
cslib is permitted to modify _count up to _max, or down to 0, and will do so as necessary. Users of cslib shouldn't need to modify _count directly, but will likely want to reference it (along with _max). For the brave (or foolish?!), modifying _count can allow you to 'trick' cslib into thinking an array is shorter than it currently is, which may have its uses, just don't forget to set it back.
Value Pop
*create my_arr_max 3
*create my_arr_count 3
*create my_arr_1 "Hello"
*create my_arr_2 "World"
*create my_arr_3 "!"
*comment remove the last value from the array
*gosub_scene cslib_array pop "my_arr"
*if my_arr_count < 3
cslib modified _count for us!
*else
*bug Well it should have done!
Value Push
*create my_arr_max 3
*create my_arr_count 2
*create my_arr_1 "Hello"
*create my_arr_2 "World"
*create my_arr_3 "!"
*comment check we have space left in the array before pushing
*if (my_arr_count < my_arr_max)
*gosub_scene cslib_array push "my_arr" "?"
*else
*goto not_enough_space
*if my_arr_count = 3
cslib modified _count for us!
*else
*bug Well it should have done!
Note that in the above example, _count was purposefully set as 2, i.e. it's ignoring the value of my_arr_3 and considers it to be available. When push is called, the routine will replace "!" for "?" and increase the _count from 2 to 3.
If we had left _count at 3, then cslib would have thrown a 'my_arr is already at max length' style error.