Problems with setting variable by _args[1]

Twine Version: 2.8.1 Story Format: Sugarcube 2.36.1

Hello! I have a passage with a test, but cannot count points $mcPts for correct (true) answers.

<<switch $tempCounter>>
<<case 0>>
Какие магические существа живут на севере?
<<cycle "$mcTest.north">>
	<<option "речные змеи" false>>
	<<option "морозные волки" true>>
	<<option "спектральные шакалы" false>>
<</cycle>>
<<case 1>>
Какие магические существа живут на западе?
<<cycle "$mcTest.west">>
	<<option "корр-муры" true>>
	<<option "огнеолени" false>>
    <<option "пангунгу" false>>
<</cycle>>
<<case 2>>
Какие магические существа живут на востоке?
<<cycle "$mcTest.east">>
	<<option "антары"  false>>
	<<option "спектральные шакалы"  false>>
    <<option "пангунгу" true>>
<</cycle>>
<<case 3>>
Какие магические существа живут на юге?
<<cycle "$mcTest.south">>
	<<option "вирмы" true>>
    <<option "морозные волки"  false>>
    <<option "корр-муры" false>>
<</cycle>>
<</switch>><br>

<<if $tempCounter<4>>
<<link "Следующий вопрос" `passage()`>><<set $tempCounter+=1>><</link>>
<<else>><<linkreplace "Следующий вопрос" t8n>>Последний вопрос.<</linkreplace>><</if>>
<br>

/*gives $mcPts=0, seems _args[1] does not pass value to $mcPts*/
<<countPtsObj $mcTest $mcPts>>
number of correct answers: $mcPts<br>

/*alternative widget works and gives $mGrades["creat"]=4 if all keys of $mcTest are true
<<countPtsObj $mcTest $mGrades>>
<<print "Grades="+$mGrades["creat"]>><br>
*/

In StoryInit I have:

<<set $mcPts=0>>
<<set $mcTest={north: false, west: false, east: false, south: false}>>
<<set $tempCounter=0>>
<<set $mGrades={creat: 0, elem: 0}>>

In widgets:

/*takes variable as _args[1]*/
<<widget "countPtsObj">>
<<if _args>>
<<capture _args, _i>>
	<<set _args[1]=0>>
	<<if Object.keys(_args[0]).length isnot 0>>
        <<for _i range Object.keys(_args[0])>>
   		<<if _args[0][_i]===true>><<set _args[1]+=1>><</if>>
        <<print "args0 "+"_i ="+_args[0][_i]+", ">><<print "args1="+_args[1]>>
        <</for>>
         <</if>>
    <<print _args[1]>>
<</capture>>   
<</if>>
<</widget>>

/*alternative widget, for object as _args[1]*/
<<widget "countPtsObj">>
    <<capture _args>>
    		<<set _args[1][Object.keys(_args[1])[0]]=0>>
            <<for _key range Object.keys(_args[0])>>
            <<if _args[0][_key]===true>>
            	<<set _args[1][Object.keys(_args[1])[0]]+=1>>
                <<print "right ">>
            <<else>><<print "wrong ">>
            <</if>>
            <<print "args0 "+_key+"="+_args[0][_key]+", ">>
            <</for>>
        <<print Object.keys(_args[1])>>
    <</capture>>
<</widget>>

The alternative widget with _args[1] works. I probably missed some logic about _args or made a mistake.
Thanks in advance.

First. You don’t have to capture _args, it’s already effectively captured for the widget.

Second. Your problem is twofold:

  1. You’re passing in the value of $mcPts rather than the variable itself. You can fix this by quoting the variable when you pass it to the widget—e.g., "$mcPts".
  2. Since you’ll have the variable name, from step 1, rather than its value, you must use the State.getVar() method and State.setVar() method to access it.

For example, your initial setting of the variable:

<<set _args[1] = 0>>

Would become:

<<run State.setVar(_args[1], 0)>>

And your incrementing of its value:

<<set _args[1] += 1>>

Would become:

<<run State.setVar(_args[1], State.getVar(_args[1]) + 1)>>
2 Likes

Thanks a lot for the answer! It works!
But I might go with the object version)
So, the problem seems that Sugarcube code is based on JS, and JS function (widget) acts on objects by reference, while on usual variables function acts by value?
“Any changes made to the object will be visible to you after the function is done executing.” (javascript pass object as reference)