Howdy, Stranger!

It looks like you're new here. If you want to get involved, click one of these buttons!

Using variables and function return values as the index of an array.

I just started using Twine a few days ago, but have apparently stumbled upon some unanswered weirdness (as far as I can see). So I've been trying a few things and I've noticed it's seems unnecessarily difficult to use a variable as the index in an array.

I'm using Twine 2.0's Sugarcube (the standalone program), for reference.


First the normal "variable as array index" setup::
	<<set $holder = 0>>
	<<set $Weekdays =["Aday", "Baday", "Seeday"]>>
        $Weekdays[$holder]

This prints (as expected):
Aday


Then the "variable as array index in nested arrays" setup:
	<<set $holder = 0>>
        <<set $StatsA =[]>>
	<<set $PCArrayA =["PC", "Archer", "bow and arrow", "leather", "7", "royalblue"]>>
        <<set $Stats[0] = $PCArrayA>>
        $StatsA[$holder][0]
        $StatsA[0][$holder]
(I know the 7 ends up as a string and this may not be the most efficient way of holding such information but play along.)

This prints:
$StatsA[$holder][0]
PC

Alright, for some reason the first index of a pseudo multidimensional array can't take a variable, for whatever reason. So the first question: Is there a way to force Twine to accept $holder as a variable instead of (I guess) part of just as some weird text with brackets? I tried quotes but that doesn't help (and doesn't seem like it should anyway, because then the index is literally $holder instead of the number in $holder).


Secondly, I figured I'd also ask if it's possible to make classes? Or if I need to learn more Javascript and/or Twine+Javascript interaction to do something like the code below. I'd appreciate some links on how to actually make and use these if they exist.

(syntax is basically made up, since I couldn't find anything about this searching for classes, functions or methods in twine that were coder/author-defined):
<<set $time={
	year: 0,
        month: 0,
        day: 0,
	weekday() {return this.day % 3} 
>>
<<set $time.day += 1>>
<<set $Weekdays =["Aday", "Baday", "Seeday"]>> 
Today is $Weekdays[$time.weekday()]


To essentially return:
Today is Baday.


Thanks for any help after slogging through that wall of text.

Comments

  • Assuming that you've actually installed and are using SugarCube 2—rather than SugarCube 1, which is what Twine 2 currently comes with.

    I just started using Twine a few days ago, but have apparently stumbled upon some unanswered weirdness (as far as I can see). […]

    Alright, for some reason the first index of a pseudo multidimensional array can't take a variable, for whatever reason. So the first question: Is there a way to force Twine to accept $holder as a variable instead of (I guess) part of just as some weird text with brackets? I tried quotes but that doesn't help (and doesn't seem like it should anyway, because then the index is literally $holder instead of the number in $holder).
    Reading the documentation is usually helpful in situations like this. The naked variable markup is intended to easily allow the printing of variables—e.g. $foo. Once you start engaging in compound expressions, method calls, and the like, the markup calls it quits. As noted in its documentation, in such cases you must use the one of the print macros: <<print>>, <<=>>, <<->>.

    For example:
    <<=$StatsA[$holder][0]>>
    <<=$StatsA[0][$holder]>>
    

    Secondly, I figured I'd also ask if it's possible to make classes? Or if I need to learn more Javascript and/or Twine+Javascript interaction to do something like the code below. I'd appreciate some links on how to actually make and use these if they exist.
    Yes, you may create and use JavaScript classes, if that's what you actually mean—though, that comes with a huge caveat. And yes, you should learn more about JavaScript, if you plan on heading in that direction—you might want to start with something like MDN's JavaScript Guide.

    Note that your example—which contains a error—is not a true JavaScript class (either notation), but rather a generic object with an attached method. It's an example of JavaScript's underlying prototypal OOP model. A class—which is to say an object template which uses one of the two classical model syntaxes supported by JavaScript—will have a constructor.

    And now the caveat. You may use generic objects, and some other JavaScript natives, without issue as the system knows how to restore them from serialization—e.g. saves and session serializations. Custom classes, on the other hand, cannot be restored by the system from serialization without support from the class itself—meaning that the class must include some code to help the system properly restore it. I'm not going into detail here, as this is the deepest end of the pool and it's not clear that you actually need/want classes anyway—generic objects suit most.
  • Then the "variable as array index in nested arrays" setup:
    	<<set $holder = 0>>
            <<set $StatsA =[]>>
    	<<set $PCArrayA =["PC", "Archer", "bow and arrow", "leather", "7", "royalblue"]>>
            <<set $Stats[0] = $PCArrayA>>
            $StatsA[$holder][0]
            $StatsA[0][$holder]
    
    You define an array variable named $StatsA but you try to assign your $PCArrayA array to the first element of an undefined variable named $Stats.

    Alright, for some reason the first index of a pseudo multidimensional array can't take a variable....
    You can use a variable based index, you just cant do it with naked variables. Try using a <<print>> macro:
    <<print $StatsA[$holder][0]>>
    

    Secondly, I figured I'd also ask if it's possible to make classes? Or if I need to learn more Javascript....
    You need to learn Javascript, in particular Objects.

    note: the following example is not meant to be an indication of best practice, it is just to demonstrate that it is possible to do what you asked.
    <<set $time = {
    	year: 0,
    	month: 0,
    	day: 0,
    	weekday: function() {
    		return this.day % 3;
    	}
    }>>
    <<set $time.day += 1>>
    <<set $Weekdays = ["Aday", "Baday", "Seeday"]>>
    Today is <<print $Weekdays[$time.weekday()]>>
    
  • edited September 2016
    Assuming that you've actually installed and are using SugarCube 2—rather than SugarCube 1, which is what Twine 2 currently comes with.


    […]
    Alright, for some reason the first index of a pseudo multidimensional array can't take a variable, for whatever reason. So the first question: Is there a way to force Twine to accept $holder as a variable instead of (I guess) part of just as some weird text with brackets? I tried quotes but that doesn't help (and doesn't seem like it should anyway, because then the index is literally $holder instead of the number in $holder).

    Reading the documentation is usually helpful in situations like this. The naked variable markup is intended to easily allow the printing of variables—e.g. $foo. Once you start engaging in compound expressions, method calls, and the like, the markup calls it quits. As noted in its documentation, in such cases you must use the one of the print macros: <<print>>, <<=>>, <<->>.

    For example:
    <<=$StatsA[$holder][0]>>
    <<=$StatsA[0][$holder]>>
    

    Secondly, I figured I'd also ask if it's possible to make classes? Or if I need to learn more Javascript and/or Twine+Javascript interaction to do something like the code below. I'd appreciate some links on how to actually make and use these if they exist.
    Yes, you may create and use JavaScript classes, if that's what you actually mean—though, that comes with a huge caveat. And yes, you should learn more about JavaScript, if you plan on heading in that direction—you might want to start with something like MDN's JavaScript Guide.
    I had actually just been using Sugar Cube 1, but that's updated now. Thanks for the heads-up (and the useful link the the Javascript knowledge base (and the additional heads-up about how Javascript may weirdly affect stuff Twine can't work with out of the box).

    I think you're right, it seems I was looking to use just the underlying OOP abilities without an actual class.

    greyelf wrote: »
    Then the "variable as array index in nested arrays" setup:
    	<<set $holder = 0>>
            <<set $StatsA =[]>>
    	<<set $PCArrayA =["PC", "Archer", "bow and arrow", "leather", "7", "royalblue"]>>
            <<set $Stats[0] = $PCArrayA>>
            $StatsA[$holder][0]
            $StatsA[0][$holder]
    
    You define an array variable named $StatsA but you try to assign your $PCArrayA array to the first element of an undefined variable named $Stats.

    I will blame posting this at 3 am, but I did have it right in the code (apparently did not copy over the most-recently edited version, but I will try to take that as a lesson in meticulously checking my variable names.

    greyelf wrote: »
    Secondly, I figured I'd also ask if it's possible to make classes? Or if I need to learn more Javascript....
    You need to learn Javascript, in particular Objects.

    note: the following example is not meant to be an indication of best practice, it is just to demonstrate that it is possible to do what you asked.
    <<set $time = {
    	year: 0,
    	month: 0,
    	day: 0,
    	weekday: function() {
    		return this.day % 3;
    	}
    }>>
    <<set $time.day += 1>>
    <<set $Weekdays = ["Aday", "Baday", "Seeday"]>>
    Today is <<print $Weekdays[$time.weekday()]>>
    

    This is also very helpful to see an actual functional version of the code. I'm wondering what sort of better/best practices you mean (maybe comments indicating use? Or should I be using a bunch of robust get/set statements?)



    You seemed to have a lot of the same information as TheMadExile, but I wanted to say I still found it very useful to have 2 versions saying similar stuff. I also appreciate the speedy responses. Despite my requests for more information, I think you have both solved my issues with the <<print>> solution and Javascript object info.
Sign In or Register to comment.