Pulling other values from datamaps in Sugarcube?

Twine Version: 2.6.0
Story Format: Sugarcube 2.36.1

Hey - hoping someone can help me with something I’m having trouble getting my head around. This is my first time working with datamaps and I may be missing something extremely obvious! The code below isn’t for a specific project, I’m just modelling examples to try and understand how it all works, so very open to suggestions for changes.

I’m setting up the datamap as follows in StoryInit:

<<set $NPCs to {
	"NPC1":
	{
        name: "",
		description: "",
        location: "",
	},
	"NPC2":
	{
        name: "",
		description: "",
        location: "",
	},
	"NPC3":
	{
        name: "",
		description: "",
        location: "",
	}
  }>>

I’m then using a widget to allocate random values to name/description/location. So far so good - this all seems to be working fine.

Where I’m getting stuck is trying to figure out how to pull out an entry from the datamap based on a specific value. For example, one of the possible values for “location” is “beach”. How could I identify all the entries in the datamap that have “beach” as a location? And then how could I, for example, print the names of everyone who lives at the beach?

I’ve been Googling this and testing different stuff for hours with no luck whatsoever, so any help would be appreciated. An explanation in simple terms doubly so - I’m not a programmer at all and struggle to grasp this stuff sometimes!

Thanks in advance and sorry if this is a stupid question!

Ah, yeah, datamaps don’t help a lot with that: they’re not indexed on their content like a database might be. So you’d have to loop over the NPCs and choose the ones you want.

If you’re going to want to access things this way, you might be better off putting the NPCs in an array of datamaps (intead of a datamap of datamaps) so you can use Array.filter to grab the ones you want. There’s not much difference between $NPCs.NPC1 (or $NPCs["NPC1"]) and $NPCs[0].

The way you have it now… you could find the ones you want with SugarCube’s <<for>> loop:

<<set _beachbums to {}>>
<<for _id, _npc range $NPCs>>
    <<run _beachbums[_id] = _npc>>  /* put them in a collection for later use */
    _npc.name: _npc.description  /* or just do something with them immediately */
<</for>>

If $NPCs was an array… well, then you need some JavaScript. Hmm. Well, OK. Personally I like the Javascript arrow functions, but see what you think:

<<set _tourists to $NPCs.filter(npc => npc.location is "beach")>>

/* print them all with their descriptions */
<<for _i,_npc range _tourists>>_npc.name: _npc.description<</for>>

/* grab a random one: */
<<set _tourist to $NPCs.pluck()>>
_tourist.name: _tourist.description
1 Like

Ahh Josh, my hero!

I tooled around with making $NPCs an array a bit earlier but I didn’t know about Array.filter so didn’t get very far - this makes way more sense.

I think I understand this, will test it out properly after work and make sure. Thanks so much!

1 Like