0 votes
by (8.7k points)

I'd like $npcDecision to be drawn randomly from a Set() called $npc.options.

How do I do that?  None of these guesses worked:

<<set $npcDecision to $npc.options.random()>>

<<set $npcDecision to Array.random($npc.options)>>

<<set $npcDeciion to Set.random($npc.options)>>

:-/   sorry for my ignorance.  I did try and find the answer online.

2 Answers

+1 vote
by (63.7k points)
selected by
 
Best answer

SugarCube doesn't currently extend Set the way it does Array—though I'll be rectifying that soon enough—so methods like .random() don't currently exist on instances of Set.

The easiest thing would be to simply convert the Set to an array wherever you need to use .random().  For example:

<<set $npcDecision to Array.from($npc.options).random()>>

 

For something a little more seamless you could add the following code to your Story JavaScript, which will add a .random() method to Set.

/*
	Randomly selects an element from the base Set and returns it.

	NOTE: SugarCube only.
*/
if (!Set.prototype.random) {
	Object.defineProperty(Set.prototype, 'random', {
		configurable : true,
		writable     : true,

		value() {
			if (this == null) {
				throw new TypeError('Set.prototype.random called on null or undefined');
			}

			return Array.from(this.values()).random();
		}
	});
}

 

+1 vote
by (149k points)
edited by

The Javascript Set object doesn't have a random() function, nor does the SugarCube 2.x story format add a random() function to the Set object like it does to the Array object.

You can use code like the following within your story's Story Javascript area to create your own custom random() function on the Javascript Set object.

/*
* Returns a random value from the related set.
*
* Does not modify the original collection.
*/
Object.defineProperty(Set.prototype, 'random', {
	configurable : true,
	writable     : true,

	value() {
		if (this == null) {
			throw new TypeError('Set.prototype.random called on null or undefined');
		}
		return Array.from(this.values()).random();
	}
});

note: you may want to get a more experienced Javascript programmer to look over the above in case it contains incompatibilities with older web-browsers.

The new custom random() function is uses as follows:

<<set $npc to {'options': new Set()}>>\
<<set $npc.options.add(1).add(3).add(5)>>\

options: <<= $npc.options>>

random: <<= $npc.options.random()>>

edit: altered <Set>.random() example based on TheMadExile suggestions.

by (63.7k points)

A few notes on your method.

  1. Your null check here is one of the few instances where you want to use the lazy equality operator, since that will also catch undefined.
  2. I'd suggest using <Set>.values() rather than <Set>.keys(), as the latter is an alias for the former—and makes more sense besides.
by (8.7k points)
Works perfectly, thank you, Greyelf.

EDIT: and thanks also, Exile!
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.
...