Moving an object from one array to another using a for loop

Twine Version: newest

Hello! So I’m having an issue with an inventory system I’ve been implementing from scratch. I’ve hit a snag where I’m using a widget to create a button for each item on the floor in a room, with the idea being you click the button and it adds that item to the inventory array. However, it seems to only add an “undefined” to the end. At first I wondered if I needed a capture macro but either I was using it wrong or that wasn’t the case because it didn’t solve the issue.

below is my widget

<<widget pickup>>
<<for _b to 0; _b < _floor.length; _b++>>
	<<button "pickup _floor[_b].name">>
    	<<run $inventory.push(_floor[_b])>>
        <<redo>>
    <</button>>
<</for>>
<</widget>>

And here is the room containing the item

You are on the northern end of main street.

There are a number of shops here.

There is a small <<link "Diner" diner>><</link>>. It doesn't look too busy.

You can go to the <<link "southern main street" mainstreet2>><<AdvanceTime>><</link>>
<<nobr>>
<<if $ID1 == 0>>
<<set _floor = [{ ID:4, type:"weapon", name:"Katana", plural:"Katanas", description:"Steel folded one million times", damage:4, accuracy:2,value:2000,quantity:1}]>>
<<set $ID1 = 1>>
<<pickup>>
<</if>><</nobr>>

You do need to use <<capture>>. This worked for me:

<<widget pickup>>
    <<for _b to 0; _b < _floor.length; _b++>>
        <<capture _b>>
            <<button "pickup _floor[_b].name">>
                <<run $inventory.push(_floor[_b])>>
                <<redo>>
            <</button>>
        <</capture>>
    <</for>>
<</widget>>

svlin has explained how to resolve your issue using the <<capture>> macro, the following tries to explain why the error occurs in the first place.

The <<run>> macro in that <<button>> macro’s body…

<<run $inventory.push(_floor[_b])>>

…doesn’t get processed until the generated button is selected.

So the value of the _b temporary variable isn’t determined until that point in time, and by then that variable’s value will likely be either:

  • the value it had at the end of the <<for>> loop iteration. eg. _floor.length
  • undefined, if that variable has gone out of scope.

And if the _b variable’s value is equal to _floor.length then the _floor[_b] array element reference will fail, because JavaScript uses an offset (zero-based) array index system, so there is never an array element that has an index equal to the array’s length.
eg. this _floor[_floor.length] will always product an error in JavaScript.

1 Like

Thank you guys! I figured I might need to use Capture, but when I tried it I put it in the button and I guess that messed it up. Works perfectly now.