Question about card game mechanic

Using Sugarcube 2.21.0

I’m a Javascript neophyte working on a game mechanic where the player has a hand of cards (currently an array of objects). When faced with certain ‘challenge’ passages, their hand is displayed and they can select a card to deal with the challenge. Right now I’m trying to generate buttons based on their $hand that will pass a card object to a new object, $activeCard, that will display text describing the action they wish to take. A link at the bottom of the passage will take the player to a results passage that will remove the card from their hand and then evaluate $activeCard to see if the action succeeded or not.

Currently, I can’t pass the $hand object to the $activeCard object. I’m trying to do the Stupid Print Trick:

There is a heavy door in front of you.

<<nobr>><<for _i=0; _i< $hand.length; _i++>>
<<='<<button "' + '$hand[_i].name' + '">><<set ' + '$activeCard' + ' = ' + '$hand[_i]' + '>><<script>>state.display(state.active.title, null, "back")<</script>><</button>>'>>
<</for>><</nobr>>

<<switch $activeCard.suit>>
<<"cups">>You try to sweettalk the door, but it ignores your pleas.
<<"swords">>You attempt to pick the lock on the door...
<<"wands">>You smash the door open!
<<"coins">>You study the door for weaknesses...
<<default>>
<</switch>>

[[Do it|DoorResult]]

When I force the ‘$hand[_i]’ variable to 0,1,or 2, it works, but I can’t seem to dynamically generate the different variables. The current error is “bad evaluation: Cannot read property ‘suit’ of undefined”

  1. How can I dynamically generate the buttons so that correspond to cards in hand
  2. Is there a better way to denote the card they want to play without passing it to $activeCard? My ultimate goal would be to create a challenge widget or some function that could accept arguments and clean up the individual code passages.

Thanks for any help!!

The problem is that the value of _i has changed at the point the user has clicked the button. Normally, to prevent that, you need to use the <<capture>> macro to “capture” the value of _i at the time the code is generated.

However, since you’re using the “stupid print trick”, you can just take the variables out of quotes, so that it prints the correct value. This means that your code that generates the buttons should look like this:

<<nobr>><<for _i=0; _i< $hand.length; _i++>>
	<<= '<<button "' + $hand[_i].name + '" `passage()`>><<set $activeCard = ' + $hand[_i] + '>><</button>>'>>
<</for>><</nobr>>

The state.display() method and state.active.title property are depreciated SugarCube v1 code. SugarCube v2 uses State (with a capital “S”), and has better ways of doing those kinds of things.

In this case, we’re now using the passage() function to get the name of the current passage (instead of using State.active.title) and passing that as the second parameter of the <<button>> macro, so that clicking that button takes you to that passage. The passage() function is inside “backquotes” (the accent mark found on the tilde “~” key), so that its value of that function is passed to the <<button>> macro as the passage name (see “Passing an expression as an argument” for details).

Also, you had a bunch of unnecessary bits of code where you were generating the string to print (e.g. doing '$activeCard' + ' = ' is the same as doing '$activeCard = '), so I simplified that as well.

Hope that helps! :slight_smile:

Thanks for the help! I’m still getting the hang of printing, so that makes sense that I’m overdoing it.

Regarding the for loop, I’m still running into some issues. The buttons render, but clicking one:

  1. produces a new error: “Error: <>: bad evaluation: Unexpected identifier.”
  2. “deactivates” the button, removing all css and making it unclickabout. Removing passage() doesn’t deactivate the button so I assume something about refreshing the passage is creating an issue.

Working backwards, I’m think I’m trying create a For loop that generates:

<<button $hand[0].name `passage()`>><<set $activeCard = $hand[0]>><</button>>
<<button $hand[1].name `passage()`>><<set $activeCard = $hand[1]>><</button>>
<<button $hand[2].name `passage()`>><<set $activeCard = $hand[2]>><</button>>

but could work for any number of cards in hand. Something about the variable capture is still eluding me.

Like I mentioned before, since you were using the so-called “stupid print trick”, you didn’t need to use the <<capture>> macro. However, if you did want to do that then the code would look more like this:

<<nobr>><<for _i=0; _i< $hand.length; _i++>>
	<<capture _i>>
		<<button $hand[_i].name `passage()`>><<set $activeCard = $hand[_i]>><</button>>
	<</capture>>
<</for>><</nobr>>

Try that and see if that works better for you.

P.S. If you want to display anything inside a <<...>> in this forum, you’ll need to select that text and click the “Preformatted text” button (the </> button) so it will show what’s inside. If you look at your “item 1” in your previous post, you can see that it shows “Error: <>: bad evaluation”, due to the forum software removing the contents of the macro.

The Capture macro totally solves it! Though I still feel like I’m missing something by not understanding the print version, capture seems like maybe a cleaner solution overall.

Thanks so much for your help and for the note about the forum text formatting!