+1 vote
by (220 points)

I am using Twine 1.4.2 and Sugarcube.

I am trying to code a "grocery shopping" sort of sequence where you go to the store and select items for purchase. I want the player to be able to do two things:

  1. Click on items to add them to their cart
  2. Check their cart and see what items they have selected
The only way I know how to do this is to assign a variable for each item, check if the variable item is in the cart, and then display text accordingly. But this method seems troublesome when there are 100+ items to choose from (and therefore 100+ variables just for this sequence).
<<click "Buy milk">><<set $milk = "yes">><<script>>state.display(state.active.title, null, "back")<</script>>
<</click>>
<<click "Buy cheese">><<set $cheese = "yes">><<script>>state.display(state.active.title, null, "back")<</script>>
<</click>>

[[Check cart]]

And in the "Check cart" passage:

<<if $milk is "yes">>Milk
<<endif>><<if $cheese is "yes">>Cheese
<<endif>>

Is there a more efficient way to do this? I was thinking about if it's possible to just have a single variable (say, $cart) and add identities to it (milk, cheese) as the player clicks on items. Then, the "Check cart" passage would simply display all of the identities of $cart. Is this possible?

1 Answer

+2 votes
by (159k points)
selected by
 
Best answer

You can use an Array to store both the shop catalogue as well as which items have been selected by the Reader.

1. Use code like the following in your shop to display a selection of items.

<<set $catalogue to ["milk", "cheese", "bread"]>>\
<<set $cart to []>>\
\
Your cart: @@#cart;<<display "Show Cart">>@@

<<for _i to 0; _i lt $catalogue.length; _i++>>\
	<<capture _i>>\
		<<link `"buy " + $catalogue[_i]`>>\
			<<if not $cart.includes($catalogue[_i])>>\
				<<set $cart.push($catalogue[_i])>>\
				<<replace "#cart">><<display "Show Cart">><</replace>>
			<</if>>\
		<</link>>
    <</capture>>\
<</for>>\

... the above uses a <<for>> macro to loop the items in the catalogue. it uses the <<capture>> macro to allow access to the _i variable within the <<link>> macro's body at time of selection. It uses Custom Style Markup to define a HTML <span> element with an ID of cart in which we display the contents of the Show Cart passage, and it uses a <<replace>> macro within the links body to refresh the contents of the cart area. The above also uses the <Array>.includes() function to determine if a particular item is already within the cart.

2. The Show Cart passage:

<<for _i to 0; _i lt $cart.length; _i++>>\
<<if _i > 0>><<print ", ">><</if>>\
<<print $cart[_i]>>\
<</for>>\

.. the above loops the current content of the cart variable and displays each item contained within it.

by (220 points)
Thank you! This works well. One question though, if I may: with this code, how would I check whether or not the player left the store with a specific item? Let's say the story changes depending on whether or not the player purchased the milk, and I can't figure out a way to check whether that's true without implementing some variables.
by (159k points)

The $cart Array variable contains the items they left the shop with, simple use the  <Array>.includes() function to determine is said item is within the array.

by (220 points)
Thanks again! :D
...