Howdy, Stranger!

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

[Sugarcube 2]Evaluating variables within link titles?

Hey, so I'm curious if there's an easy way to force-evaluate a variable when it's like:
[[Buy $weapon.id|Buy]]

To make this work, I had to resort to this:
<a data-passage="Buy">Buy $next_weapon.id</a>

Which works fine. But is less succinct than some kind of shortcut to force-evaluate things. Anything like this available?

Comments

  • Both of the following work:
    [["Buy " + $weapon.id|Buy]]
    
    <<print "[[Buy " + $weapon.id + "|Buy]]">>
    
  • Oh right! Thanks, I didn't think to try that. Handy for the future.
  • edited October 2015
    Hey, somewhat related to this, I have another question.

    Let's say...
    <<set $weapon to {id: "dagger"}>>
    <<set $weaponIDs to {dagger: "hello!"}>>
    
    $weaponIDs[$weapon.id]
    

    This usually only gives me [object][dagger] instead of Hello!, no matter what kind of configuration I give it. I've tried $weaponIDs[$weapon["id"]], $weaponIDs["" + $weapon.id], and if I just try $weaponIDs["dagger"] it works.

    The problem I have is...
    $weapon.id /*works, prints "dagger" */
    
    $weaponIDs["dagger"] /* works, prints "Hello!" */
    
    $weaponIDs[$weapon.id] /* doesn't work, prints [object][dagger] */
    

    So... is there are secret here? Because I can do it in javascript easy. I just tested it quickly by:
    <<set $temp to 0>>
    <<script>>
    State.variables.temp = State.variables.weaponIDs[State.variables.weapon.id];
    <</script>>
    $temp
    

    And that puts "Hello!" in $temp, so it works.

    So... is there a way to get this to work, outside of wrapping it in javascript? I can do that if I need to, but I'm wondering if there might be a cute work around I can use for this?
  • Actually, I thought of another way to do this...
    <<set $temp2 to $weapon.id>>
    $weaponIDs[$temp2]
    

    And this works too. So, is this roundabout way what we currently need to do?
  • edited October 2015
    I'd like to also point out that while...
    <<if $coins gt $weapons[$weapon.next].cost>>\
    	<<set	$weapon to $weapons[$weapon.next],
    			$coins to ($coins - $weapon.cost)
    	>>\
    <</if>>
    

    Doesn't evaluate $weapons[$weapon.next].cost or $weapons[$weapon.next] when for instance <<print>>ed, it does do the calculations correctly. So, it might just be an issue of representation and not actual usability. But, having said that, it would be great if things like strings could be printed out as well.

    Oh, and while I'm here,
    <<if $weapon.next neq 0>>\
    	<<set $temp to $weapon.next>>
    	[["buy " + $weapons[$weapon.next].name|buy]] ($weapons[$temp].cost coins, does $weapons[$temp].damage damage)
    <</if>>\
    

    Wherever there's a $temp, $weapon.next failed to work. So, it actually worked that first time, but failed in the subsequent ones.
  • The current naked $variable formatter is not meant to print constructs of arbitrary complexity. It's a shortcut for printing $variables. If you need to print expressions, or even just arbitrarily nested objects, you have to use one of the <<print>> macro variants (i.e. <<=>>, <<->>, and <<print>>).

    IOW, you'll need to use one of the following:
    <<print $weaponIDs[$weapon.id]>>
    
    <<= $weaponIDs[$weapon.id]>>
    

    tryguy wrote: »
    I'd like to also point out that while...
    <<if $coins gt $weapons[$weapon.next].cost>>\
    	<<set	$weapon to $weapons[$weapon.next],
    			$coins to ($coins - $weapon.cost)
    	>>\
    <</if>>
    

    Doesn't evaluate $weapons[$weapon.next].cost or $weapons[$weapon.next] when for instance <<print>>ed, it does do the calculations correctly. So, it might just be an issue of representation and not actual usability. But, having said that, it would be great if things like strings could be printed out as well.

    Oh, and while I'm here,
    <<if $weapon.next neq 0>>\
    	<<set $temp to $weapon.next>>
    	[["buy " + $weapons[$weapon.next].name|buy]] ($weapons[$temp].cost coins, does $weapons[$temp].damage damage)
    <</if>>\
    

    Wherever there's a $temp, $weapon.next failed to work. So, it actually worked that first time, but failed in the subsequent ones.
    I have no idea what you're trying to say, or think you're trying to say, here. Try again?

    Also, what are $weapons and $weapon.next supposed to be? I'm assuming that $weapons is either an object or array, and $weapon.next is an index/key, but having the specifics is kind of important.
  • Fair enough. I like that there's <<= to handle expressions.

    And it works very well, but I encountered this situation again:
    /*So, we have declarations*/
    <<set
    	$maxHP to 10,
    	$hp to $maxHP,
    	$days to 0,
    	$coins to 10,
    	$weapons to {
    		bigSword : {
    			id		: "bigSword",
    			name	: "big sword",
    			cost		: 50,
    			damage	: 5,
    			next		: 0
    		},
    		smallSword : {
    			id		: "smallSword",
    			name	: "small sword",
    			cost		: 30,
    			damage	: 3,
    			next		: "bigSword"
    		},
    		dagger : {
    			id		: "dagger",
    			name	: "dagger",
    			cost		: 10,
    			damage	: 1,
    			next		: "smallSword"
    		}
    	},
    	$weapon to $weapons.dagger
    >>\
    
    /*And then code to use them*/
    
    Your current weapon is a $weapon.name, which does $weapon.damage damage.
    <<if $weapon.next neq 0>>\
    /*testing*/
    	<<set $temp to $weapon.next>>\
    	[["buy " + $weapons[$weapon.next].name|buy]]
    	[["buy " + $weapons[$temp].name|buy]]
    	[["buy " + $weapons.$temp.name|buy]]
    	[["buy " + <<= $weapons[$weapon.next].name>>|buy]]
    	[["buy " + <<= $weapons[$temp].name>>|buy]]
    	[["buy " + <<= $weapons.$temp.name>>|buy]]
    	[["buy " + <<print $weapons[$weapon.next].name>>|buy]]
    	[["buy " + <<print $weapons[$temp].name>>|buy]]
    	[["buy " + <<print $weapons.$temp.name>>|buy]]
    	<a data-passage="buy">buy <<= $weapons[$weapon.next].name>></a>
    /*testing*/
    	(<<= $weapons[$weapon.next].cost>> coins, does <<= $weapons[$weapon.next].damage>> damage)
    <</if>>\
    

    So, the issue I was having before was one of display. But that was solved with the <<= macro. I'll be using that from now on, now that I know about it.

    But with this passage (which relates to the original question), I have inconsistent results, as seen with the pic.

    So, using the raw variable works in this situation, regardless of complexity. But the other <<= and <<print macros don't. But it does work if I use the <a data-passage= convention.

    Generally though, I like the <<= macro. So thanks for the help. I think I overlooked it because of the minimal docs on it. But, now I know, it's cool.
  • The <<print>> macro variants are used to insert content into the current page, you are incorrectly trying to use them to evaluate an expression like $weapons[$weapon.next].name so that you can append the result to the "Buy " string.
  • I see. So, do you know of a sugarcube 2 macro to purely evaluate an expression?

    Often times I do want to print directly to the page. Other times I just want to evaluate the expression so I can use it. So... what's the solution here?
  • Well, OK. So, is it just simply better to use intermediary variables like so:
    	<<set $temp2 to $weapons[$weapon.next].name>>
    	[["buy " + $temp2|buy]]
    

    This is essentially evaluating the "complex" structure and storing the simple string in $temp2.

    Then we use the simple variable to play with string concatenation. So, is this the best way to go about things?
  • The first two markup links of your example code both contain an example of how to evaluate an expression:
    "buy " + $weapons[$weapon.next].name
    "buy " + $weapons[$temp].name
    
    ... they are both adding the contents of an instance variable on an array element to the "Buy " string.
  • tryguy wrote: »
    This is essentially evaluating the "complex" structure and storing the simple string in $temp2.

    Then we use the simple variable to play with string concatenation. So, is this the best way to go about things?
    The main issue you seem to be having is the level of complexity of the things you are tying to evaluate:
    eg. $weapons[$weapon.next].name

    The above requires a number of steps to determine a result:
    note: the following is only an approximation of what is happening!

    a. Transpose all $variables with their real variable references:
    State.variables.weapons[State.variables.weapon.next].name
    
    b. Determine the value of State.variables.weapon.next
    State.variables.weapons["smallSword"].name
    
    c. Determine the value of the "smallSword" array element's name variable:
    "small sword"
    
  • That's fair enough.

    I've decided to go with:
    [["buy " + $weapons[$weapon.next].name|buy]] (<<=$weapons[$weapon.next].cost>> coins, does <<=$weapons[$weapon.next].damage>> damage)
    

    And I'll try to use raw variables when I can, but as a final resort, I'm glad I can fall back on something like this:
    <<set $temp to $weapons[$weapon.next].name>>
    [["buy " + $temp|buy]]
    

    It seems to be failsafe. The trick is knowing when this might be needed without extensively testing these things. Anyway, I'm moving on from this.
  • Let me touch on some specific items.

    [["buy " + $weapons.$temp.name|buy]]
    
    That fails because you're trying to use a variable with the dot notation, which you cannot do. Dot notation is only available when you're using the actual property name and the property name is a valid identifier, all other property access (incl. using a variable) must use the square bracket notation.

    [["buy " + <<= …>>|buy]]
    
    [["buy " + <<print …>>|buy]]
    
    Those both failed because you're trying to use markup (macros in this case) within the wiki link markup, which you cannot do. The wiki link markup only accepts either plain text or TwineScript expressions.
  • Also, the whole next property thing is a really awkward way of iterating over the members of your inventory, not to mention requiring more effort on your part (since you have to manually set the value of each next property). You'd probably be much better served by simply iterating over the key/value pairs of the $weapons object.
  • Also, the whole next property thing is a really awkward way of iterating over the members of your inventory, not to mention requiring more effort on your part (since you have to manually set the value of each next property). You'd probably be much better served by simply iterating over the key/value pairs of the $weapons object.

    Yeah, fair enough. I had it that way because I was following the tutorial game. I think the idea was to be able to eventually store attributes of items so you could present different combinations, dependent on what the requirement was.

    So, not just a mechanism to iterate through. They way they originally had it was very much a linked list, but they mentioned being able to store just strings instead, and I did that.

    But, I think the endgame of it was to enable different aspects of the items to be pulled when the user wanted to see different things.

    I haven't progressed much beyond where she left it. But I like the idea of combinations, so I might see now to go about this. Not just for a combat game. But for other aspects, items meeting needs. Some items meeting them more easily than others, etc. It's interesting.
  • edited November 2015
    tryguy wrote: »
    So, not just a mechanism to iterate through. They way they originally had it was very much a linked list, but they mentioned being able to store just strings instead, and I did that.
    There's still just one bit of conditioning and code duplication that we have yet to get rid of: figuring out the right "upgrade" to show to a player based on their current weapon.
    She explained what the next attribute was for, it was used to determine which of the possible weapons types was the logical upgrade of the player's current weapon. Her version of the shop would only sell you the next weapon upgrade, you could not purchase any other weapon.
  • She talked about having another table to look the upgrade up on. The idea was that there may not be a one-to-one link, but a range of matches. Not only for a linear upgrade, but on a whole host of qualities.

    But, go ahead and just use simple stuff if you want. In the meantime, I'll be looking at how to do these combination things she talked about.
  • tryguy wrote: »
    She talked about having another table to look the upgrade up on. The idea was that there may not be a one-to-one link, but a range of matches. Not only for a linear upgrade, but on a whole host of qualities.
    Yes she did, but she also implied that it would need to be based on something other that the weapon's next property, which would make the next property redundant/deprecated.

    The solution is fairly straight forward, create a second datamap using the weapon ids as the keys and an array of possible upgrade weapon id's as the values.
    Something like the following, which has not been tested:
    (set: $upgrades  to (datamap:
    	"dagger", (array: "small sword", "bigger sword", "biggest sword"),
    	"small sword", (array: "bigger sword", "biggest sword"),
    	"bigger sword", (array: "biggest sword")
    ))
    
  • Combinations.

    A weapon might have different qualities. The big sword might have bigger impact, but slower to swing. The biggest might only be accessible if you meet the strength requirement for it.

    But beyond that. If it's a social game, then other attributes may be in play. Items that you buy to enhance your glamour factor. Items that attach some special credence.

    Those are the kinds of combinations she was inherently talking about. Not just for her tutorial game, but for things to explore. I probably won't talk anymore about this until I have some kind of system that plays with this. But, currently I'm working on other things. I will come back to combinations though, since it seems fun.
  • The $upgrades variable in my example could be dynamically populated based on whatever criteria (combination of attributes) you want to use and as many times as you need to, the point is that once that structure has been populated it is fairly easy to use to both search and display its content.

    I look forward to seeing the system you end up designing and implementing. :)
Sign In or Register to comment.