0 votes
asked by (530 points)

Hi everyone,

Let's say I have the following code:

<<set $Sara to {Strength: 10, Intelligence: 15, Agility: 10}>>
<<set $Rob to {Strength: 15, Intelligence: 10, Agility: 10}>>
<<set $Dennis to {Strength: 15, Intelligence: 5, Agility: 15}>>
<<set $party_members to {$Sara, $Rob, $Dennis}>>

How do I return the object from the $party_members array with the highest .Strength property?  And like in my example above, both $Rob and $Dennis have an identical .Strength property.  Is it possible to randomly return one of them if the desired property value is tied in first place?

Thanks.

3 Answers

+1 vote
answered by (32.2k points)
selected by
 
Best answer

As your code is above, $party_members isn't right.  For an array you should use [].  The {} is for objects.  That line should be:

<<set $party_members to [$Sara, $Rob, $Dennis]>>

Once you fix that, the code should be something like this:

<<if $party_members.length > 0>>
	<<set _HiBags = [ 0 ]>>
	<<set _HiVal = $party_members[0].Strength>>
	<<if $party_members.length > 1>>
		<<for _i = 1; i < $party_members.length; _i++>>
			<<set _Value = $party_members[i].Strength>>
			<<if _Value > _HiVal>>
				<<set _HiVal = _Value>>
				<<set _HiBags = [ _i ]>>
			<<elseif _Value === _HiVal>>
				<<set _HiBags.push( _i )>>
			<</if>>
		<</for>>
	<</if>>
	<<set _member_index = _HiBags[ random(_HiBags.length - 1) ]>>
<</if>>

After that you can use "$party_members[_member_index]" to get the result.

Basically, that creates an array of entries that are tied with the highest value seen so far, resetting the array whenever it finds a new highest value. At the end you just randomly pick one from that array of the items with the highest values.

(NOTE: I modified the above from some JavaScript I have that does the same thing, so there might be bugs, but it should be close.)

commented by (8.5k points)

Or a bit shorter:

<<set _HiVal = $party.map(o => o.Strength).reduce((a, b) => Math.max(a, b))>>
<<set _member = $party.filter(o => o.Strength === _HiVal).random()>>

And if you want the property to be an argument itself (in _property):

<<set _HiVal = $party.map(o => o[_property]).reduce((a, b) => Math.max(a, b))>>
<<set _member = $party.filter(o => o[_property] === _HiVal).random()>>

 

commented by (32.2k points)

Neat trick, Akjosch.  Thanks. smiley

0 votes
answered by (60k points)

Math.max() returns the highest value in a list of numbers.  To get that to work with an array, you can use the spread operator (...).

<<set $array to [0, 10, 15, 4, -6, 8]>>
<<set $highest to Math.max(...$array)>>

$highest /% should be 15 %/

The spread operator doesn't work in Internet Explorer.  If you want to do it without using the spread operator, you can use one of these instead:

https://developer.mozilla.org/en-US/docs/Web/JavaScript/Reference/Global_Objects/Math/max#Getting_the_maximum_element_of_an_array

 

commented by (32.2k points)
That won't work because $party_members is an array of objects, not an array of numbers.
0 votes
answered by (23.6k points)

I think the answer given here may contain what you are looking for.

Welcome to Twine Q&A, where you can ask questions and receive answers from other members of the community.

You can also find hints and information on Twine on the official wiki and the old forums archive.

See a spam question? Flag it instead of downvoting. A question flagged enough times will automatically be hidden while moderators review it.
...