Howdy, Stranger!

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

Help with arrays in sugarcube 2

Hello

I'm sorry if this is a very noobish question, but i'm having a hard time understand arrays in general, so here goes.

I'm trying to make a "trait" system, with different ranks, so say your character has 3 levels of a given trait, namely "Strength", which goes like this "nStr, Str1, Str2, Str3", where nStr represents not having the trait at all.

How could i include something like this in an array, so i can merely print all of your characters traits in one go, like a list? example: $traitlist

If we say that there also exist a leveled traits for Dexterity and Intelligence, then a printed example would look something like this:

Traits = $traitlist ==> Traits = Str2, Dex1, Int3

and in case you had nStr (which is not having the trait at all, then it would look like this:

Traits = $traitlist ==> Traits = Dex1, Int3

It would also be fine if there was an way to make an array where you could just throw in objects and take them out. I am not too keen on widgets, and i would very much appreciate it if it was kept simple.

Thank you very much.

ps

I read the Sugarcube document, but couldn't find anything helping with something like this.

Comments

  • edited June 2017
    Remove an element from an array:
    // Given: $fruits = [ "Apples", "Oranges", "Plums", "Oranges" ]
    $fruits.delete("Oranges")          → $fruits [ "Apples", "Plums" ]; Returns [ "Oranges", "Oranges" ]
    $fruits.delete("Apples", "Plums")  → $fruits [ "Oranges", "Oranges" ]; Returns [ "Apples", "Plums" ]
    

    Add an element to an array:
    // Given $sports = ["soccer", "baseball"]
    $sports.push("football", "swimming")          → $sports ["soccer", "baseball", "football", "swimming"]
    


    What you probably should be using is a datamap:
    <<set $character to {
    "str": 3,
    "dex": 2,
    "int": 4
    }>>
    
    Strength: $character.str
    Dexterity: $character.dex
    Intelligence: $character.int
    

    If you want to just have it all regulated with a single array, it would have to look something like:
    <<set $traits to [["Strength", 0], ["Dexterity", 2], ["Intelligence", 4]]>>
    

    $traits now gives you: Strength, 0, Dexterity, 2, Intelligence, 4

    You'd have to use a <<for>> macro to accomplish what you want to do:
    <<nobr>>
    <<for _i to 0; _i lt $traits.length; _i ++>>
    	<<if $traits[_i][1] > 0>>
    		<<print $traits[_i][0]>>: <<print $traits[_i][1]>>
    		<br>
    	<</if>>
    <</for>>
    <</nobr>>
    

    That seems a bit overcomplicted to me though.
  • A datamap sounds interesting, not at home right now so i can't test it out myself, but i guess i would go about it like this then for increasing a level (taking your example into my example):

    <<set $character.str += 1>>

    and i guess simply printing out all numbers would be $character

    Do you think i could do this with strings as well?

    like

    <<set $character to {
    "str": Strong,
    "dex": Dextrous,
    "int": Intelligent
    }>>

    and if i wanted to change the str string i would just <<set $character.str == "Very Strong">>

    Thank you a ton! :)
  • edited June 2017
    I'm afraid printing the entire datamap isn't possible in sugarcube at the moment (or maybe somebody will correct me on this). You can do something like that in Harlowe from what I know, but in Sugarcube you'd have have to either make a widget or manually reference everything you want to print.
    I'd still use datamaps, just because it will make it a lot more easier to reference your characters traits in your text if you have track the stats of more than one character and it will make it a lot easier to work with loops, <<for>> macros and widgets once you get accustomed to using them.

    Luckily using widgets is a lot easier than you might think. You just create a passage for your widgets, give it the tag "widget" and then you all you'd have to say would be something like:
    <<widget status>>
    Strength: $character.str
    Dexterity: $character.dex
    Intelligence: $character.int
    <</widget>>
    

    Basically the text you want printed, whenever the status is shown. Now, whenever you type <<status>>, Twine will print out all stats as set up within the widget, like for example:
    Strength: Weak
    Dexterity: Dextrous
    Intelligence: Clever
    



    I have been using numbers in my earlier example, since that will make it a lot easier if you want to implement the stats into something like a combat system, e.g.
    <<set $goblin.hp -= $character.str>>
    

    If you have different uses for your stats, you can go with strings instead of numbers, but you'll have to use quotation marks:
    <<set $character to {
    "str": "Strong",
    "dex": "Dextrous",
    "int": "Intelligent"
    }>>
    
    <<set $character.str = "Very Strong">>
    
    You are <font style="text-transform: lowercase;">$character.str, $character.dex and $character.int</font>.
    
  • edited June 2017
    Just to add my two cents, you can have both numbers and arrays for the status descriptions, which is probably how I'd do it:
    <<set $character to {
        str : 2,
        dex : 3,
        int : 0
    }>>
    
    <<set $status to {
        str : ['weak', 'strong', 'very strong', 'herculean'],
        dex : ['clumsy', 'quick', 'graceful', 'preternatural'],
        int : ['dumb', 'witty', 'brilliant', 'genius']
    }>>
    
    Status:
    |Strength: |$character.str |(<<print $status.str[$character.str]>>)|
    |Dexterity: |$character.dex |(<<print $status.dex[$character.dex]>>)|
    |Intelligence: |$character.int |(<<print $status.int[$character.int]>>)|
    

    Each number will point to an index in the array, starting at 0, so the two systems should match up very nicely.

    For printing everything, you can use a second array containing the keys to create a <<for>> loop:
    <<set $allStats to ['str', 'dex', 'int']>>
    <<for _i to 0; _i < $allStats.length; _i++>>
        <<set _current to $allStats[_i]>>
    |<<print _current.toUpperFirst()>>: |<<print $character[_current]>> | (<<print $status[_current][$character[_current]].toLowerCase()>>)|
    <</for>>
    
  • edited June 2017
    Chapel wrote: »
    Just to add my two cents, you can have both numbers and arrays for the status descriptions, which is probably how I'd do it:
    <<set $character to {
        str : 2,
        dex : 3,
        int : 0
    }>>
    
    <<set $status to {
        str : ['weak', 'strong', 'very strong', 'herculean'],
        dex : ['clumsy', 'quick', 'graceful', 'preternatural'],
        int : ['dumb', 'witty', 'brilliant', 'genius']
    }>>
    
    Status:
    |Strength: |$character.str |(<<print $status.str[$character.str]>>)|
    |Dexterity: |$character.dex |(<<print $status.dex[$character.dex]>>)|
    |Intelligence: |$character.int |(<<print $status.int[$character.int]>>)|
    

    Each number will point to an index in the array, starting at 0, so the two systems should match up very nicely.

    That's a good idea, but if we want to do this, we should probably use something like this:
    Status:
    |Strength: |$character.str |(<<print $status.str[$character.str.clamp(0, 3)]>>)|
    |Dexterity: |$character.dex |(<<print $status.dex[$character.dex.clamp(0,3)]>>)|
    |Intelligence: |$character.int |(<<print $status.int[$character.int.clamp(0, 3)]>>)|
    

    We use the <Number>.clamp(min , max) method to make sure that the numbers that represent our stats will stay within the bounds of the corresponding array.
  • Sylen wrote: »
    and if i wanted to change the str string i would just <<set $character.str == "Very Strong">>

    No. '==' is a comparison operator. The assignment operator is '=', or 'to'.

  • idling wrote: »
    What you probably should be using is a datamap:
    <<set $character to {
    "str": 3,
    "dex": 2,
    "int": 4
    }>>
    
    Strength: $character.str
    Dexterity: $character.dex
    Intelligence: $character.int
    
    Just to be clear. That is a generic object, not a JavaScript Map object (a.k.a. datamap)—which is guaranteed to exist by SugarCube v2, but not v1, and, yes, SugarCube v2 can print a Map, though the formatting probably won't be to anyone's liking.

    idling wrote: »
    Chapel wrote: »
    Just to add my two cents, you can have both numbers and arrays for the status descriptions, which is probably how I'd do it: […]
    That's a good idea, but if we want to do this, we should probably use something like this: […]

    We use the <Number>.clamp(min , max) method to make sure that the numbers that represent our stats will stay within the bounds of the corresponding array.
    I'd think that it would make more sense to use <Number>.clamp() during assignments, so you never have to worry about your values being out of range in the first place.
  • I'd think that it would make more sense to use <Number>.clamp() during assignments, so you never have to worry about your values being out of range in the first place.

    Depends on what game mechanics we're aiming for - Whether we want the character traits to be able to go beyond the boundaries by some means or to be always within the strict limits.
Sign In or Register to comment.