0 votes
by (550 points)

I want to write a game in which, at every turn, random passages are chosen from a pool of available passages. So there are two steps: first I filter the complete passage list to get the pool of passages that are adequate to the current situation; second, I pick a random passage from that pool.

The problem is in the first step.

I have done tests with the underscorejs function _.where and it does what I want.

<% s.passages = [

{name:"I drink", subject:"food"},

{name:"I sleep", subject:"rest"} ];

s.select = _.where( s.passages, {subject:"food"};

%>

This code would correctly pick the first element in the array and store it in s.select. So far so good.

Now my question: how should I change the _.where function to pick an element like this?

{name:"I drink", subject:["food","rest"]},

Instead of having a single subject, the value for that key is an array. So the condition is not subject equals "food", but subject contains "food". How can I write that condition inside _.where?

Thanks!

1 Answer

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

Based on the underscorejs's where documentation you don't, as it seems to be designed to filter a single set to property values for exact value matches and not a range of possible matches.

Based on what I read you could either:

1. Build a list of matches by calling the where function multiple times, once for each possible combination of property values you want, and then combining the results from each call together to form the final result. The following is a prototype of one possibles way to do this, you may want to get the advice of a more experienced Javascript programmer.

<%
s.passages = [
	{name: "I drink", subject: "food"},
	{name: "I sleep", subject: "rest"},
	{name: "I sleep", subject: "other value"}
];

s.select = ["food", "rest"]
	.map(function(value) {
		return _.where(s.passages, {subject: value});
	})
	.reduce(function(a, b) {
		return a.concat(b);
	}, []);
%>

select: (look in Developer Console for output)
<% s.select.forEach(function(el) {console.log(`select: ${el.name}`);}); %>

 2. Use the underscorejs filter function combined with a more complex custom function handler to conditionally test for the the set of property values you want. Due to lack of time I will leave that up to you (or someone else) to work out.

by (68.6k points)

2. Use the underscorejs filter function combined with a more complex custom function handler to conditionally test for the the set of property values you want. Due to lack of time I will leave that up to you (or someone else) to work out.

The following should work:

s.select = _.filter(s.passages, function(o) {
	return _.isArray(o.subject)
		? _.contains(o.subject, "food")
		: o.subject === "food";
});

 

by (550 points)
Thanks so much greyelf and TheMadExile! Your advice is always great. I've been able to implement cascading filters for arrays and multiple conditions, as I needed.

I'd like to credit you in the final game (due for Ectocomp later this month). How would you like me to do that (names, websites, etc.)?
by (159k points)

I'd like to credit you in the final game ... How would you like me to do that?

If this extra question was aimed at me then I missed seeing it in October, and it is probably to late now but to answer your question.

My greyelf persona doesn't have a deep web presents (no blog, no web-site, no social media) but if you want to honour me with a credit then either: simply use the greyelf username; or if you prefer something more real then contact me on gmail.
(guessing that persona's email address should be easy. *smile*)

...