# I want to calculate a weighted average based on the choices the user takes in the game.

As the player moves through the game, I want the game to take a weighted number associated with each passage they click on and recalculate it. Below would be an example of the math used in JS.

``````function weightedAverage(v1, w1, v2, w2) {
if (w1 === 0) return v2;
if (w2 === 0) return v1;
return ((v1 * w1) + (v2 * w2)) / (w1 + w2);
}``````

The problem I forsee is that with this code example I would have to define each passage with variables v1, v2, v3, etc. which could get quite unwieldy if I have hundreds of passages.

Is there a simpler method that would update and recalculate every time the player clicked on a passage? Would I use temporary variables? An array?

Apologies in advance; I'm very new to coding and despite my best efforts I can't figure out where to start.

by (44.7k points)
edited by

I tried combining the above information with the information you posted in the /r/twinegames Reddit, and also this information on calculating a weighted center, and I think I figured out what you're trying to do.

First, you need to initialize your values in your "StoryInit" passage like this:

``````<<set \$xSums = 0>>
<<set \$xWeights = 0>>
<<set \$xMean = 0>>
<<set \$ySums = 0>>
<<set \$yWeights = 0>>
<<set \$yMean = 0>>``````

Next you'd need to add a passage, give it "widget" and "nobr" tags, and put something like this code in it:

``````<<widget "wlink">>
/* Usage format: <<wlink "Link text" "Passage name" X XWeight Y YWeight>> */
/* Example: <<wlink "Go south" "Round room" 4 10 -3 8>> */
<<set _passageName = \$args>>
<<set _xSums = \$xSums + (\$args * \$args)>>
<<set _xWeights = \$xWeights + \$args>>
<<set _xMean = _xSums / _xWeights>>
<<set _ySums = \$ySums + (\$args * \$args)>>
<<set _yWeights = \$yWeights + \$args>>
<<set _yMean = _ySums / _yWeights>>

<<if (_xMean < 0) || (_yMean < 0)>>
/* This is an example where if either X or Y will be less than zero */
/* if you click this link, then it takes you a different passage. */
<<set _passageName = "Maze exit">>
<</if>>

<<capture _xSums, _xWeights, _xMean, _ySums, _yWeights, _yMean>>
<<set \$xSums = _xSums>>
<<set \$xWeights = _xWeights>>
<<set \$xMean = _xMean>>
<<set \$ySums = _ySums>>
<<set \$yWeights = _yWeights>>
<<set \$yMean = _yMean>>
<</capture>>
<</widget>>``````

You'll need to modify that middle chunk of code to work the way you want, but this should make it so that any time you want to link to another passage, you would use the <<wlink>> widget to set the link text, passage name, X, X weight, Y, and Y weight which would be used to evaluate the new X and Y mean values and take you to a different passage, if needed, depending on their values.  See the SugarCube <<widget>> macro documentation for details on how widgets work.

If the values and weights for each passage you're going to will always be the same, regardless of where you came from, then you could create a setup object in the "StoryInit" passage which stores the values for each passage you'd go to like this:

``````<<set setup.passages = {}>> /* Initialize object */
<<set setup.passages["Round room"]   = {x:  4, xWeight: 10, y: -3, yWeight:  8}>>
<<set setup.passages["Machine room"] = {x:  7, xWeight:  5, y:  4, yWeight: 10}>>
etc...``````

And then you would modify the widget like this:

``````<<widget "wlink">>
/* Example: <<wlink "Go south" "Round room">> */
<<set _passageName = \$args>>
<<set _passage = setup.passages[_passageName]>>
<<set _xSums = \$xSums + (_passage.x * _passage.xWeight)>>
<<set _xWeights = \$xWeights + _passage.xWeight>>
<<set _xMean = _xSums / _xWeights>>
<<set _ySums = \$ySums + (_passage.y * _passage.yWeight)>>
<<set _yWeights = \$yWeights + _passage.yWeight>>
<<set _yMean = _ySums / _yWeights>>

<<if (_xMean < 0) || (_yMean < 0)>>
/* This is an example where if either X or Y will be less than zero */
/* if you click this link, then it takes you a different passage. */
<<set _passageName = "Maze exit">>
<</if>>

<<capture _xSums, _xWeights, _xMean, _ySums, _yWeights, _yMean>>
<<set \$xSums = _xSums>>
<<set \$xWeights = _xWeights>>
<<set \$xMean = _xMean>>
<<set \$ySums = _ySums>>
<<set \$yWeights = _yWeights>>
<<set \$yMean = _yMean>>