inkle / ink

inkle's open source scripting language for writing interactive narrative.
http://www.inklestudios.com/ink
MIT License
4.11k stars 492 forks source link

Feature: Structured JSON-like data #179

Open joethephish opened 8 years ago

joethephish commented 8 years ago

This is a very distant future feature, perhaps for ink v3, which is likely to be years rather than months away!

Add the ability to put more complex data structures within ink by including nestable arrays and dictionaries, and standard dot syntax to reference them.

Would be good if the syntax was a superset of JSON, so it's possible to copy/paste data easily from other sources. YAML itself isn't quite right and would have collisions with ink syntax, but something along those lines would be good.

Note that adding something like this is a bit of a can of worms, since we may need a full set of standard library functions for manipulating the data structures (adding/removing elements, finding the index of elements, etc). It would create a whole new set of expectations that ink should be usable as a general purpose programming language.

jkant commented 8 years ago

I have a (somewhat convoluted and hacky) workaround to this issue that others may find useful. I am creating a list of characters, with various attributes (first name, last name, gender, etc.) as ScriptableObjects in a Unity project. Then I use an editor script to take the characters in my project folder, and write them out to an autogenerated ".ink" file in such a way that other ink files can access them.

This is the basic way that file is structured:

var _DetailCharID = -1
var _DetailCharFirstName = ""
var _DetailCharLastName = ""
var _DetailCharGender = -1

const CLINTON_ID = 0
const TRUMP_ID = 1

== function get_character_details(charID)
{
   - charID == CLINTON_ID:
      ~ _DetailCharFirstName = "Hillary"
      ~ _DetailCharLastName = "Clinton"
      ~ _DetailCharGender = GENDER_FEMALE
   - charID == TRUMP_ID:
      ~ _DetailCharFirstName = "Donald"
      ~ _DetailCharLastName = "Trump"
      ~ _DetailCharGender = GENDER_MALE
}

== function get_firstname(charID)
~ get_character_details(charID)
~ return _DetailCharFirstName

== function get_lastname(charID)
~ get_character_details(charID)
~ return _DetailCharLastName

== function get_gender(charID)
~ get_character_details(charID)
~ return _DetailCharacterGender

The limitation with this approach is that my code for writing the autogenerated file is a bit special-casey at the moment, although I think it could be made more generic with some more Reflection. Also, it relies on using Unity or some other external program.

The nice thing though is that it lets you have data structures in your game without making major changes to the Ink runtime.

But anyway, if there is interest in this approach then I can work on making my code more generic and then share it here.

ladyisidore commented 8 years ago

@jkant I'd love to see your method for doing this! It looks like it'd be very useful to me and solve a couple of problems I'm having.

joethephish commented 8 years ago

One possible technique that I was thinking of: You could define two external functions:

EXTERNAL get(strPropertyName)
EXTERNAL set(strPropertyName, value)

Then on the C# game side, have some data structure that it accesses using the strPropertyName. For example, if it was JSON-like, you could use dot-separated paths - e.g. world.cairo.population.

jkant commented 8 years ago

@joethephish great idea! Maybe I can combine my existing system (for those wanting to work with "only" ink files) with yours, so that both methods would work on the same set of data! I will get started on that...

jkant commented 5 years ago

Reviving this old thread to say that I've finally released my "Ink Objects" system that started with my experiment above. Hopefully the Ink community finds it useful! Get it here: http://jsk.itch.io/ink-objects. Hopefully it is still of use to you @isakgrozny

agathazeren commented 5 years ago

A probably less can of worms-y way to do it would be to allow references to stitches in passed in diverts (and representing properties as stitches) or allowing the storage of diverts that take parameters (and representing properties as parameters).