inkle / ink

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

Condition count / number of conditions at runtime #866

Open wilg opened 9 months ago

wilg commented 9 months ago

This is kind of a strange one! I'm trying to implement an Ink-powered variant of the Valve/Naughty Dog dialogue database system.

https://www.gdcvault.com/play/1020386/A-Context-Aware-Character-Dialog https://www.gdcvault.com/play/1015528/AI-driven-Dynamic-Dialog-through

The way I have it right now, when the player is in "free roam", the ink script generates lots of choices for what might happen, with various conditions. My custom logic then picks from the list of choices that are available.

= Interactions
* { near(Apple) } [Ambient: ambient_apple]
    Apple: Didn't I tell you to go get your Personality Program? #v:654
    Apple: You're no son of mine. #v:655
* { near(Apple) } [Ambient: ambient_apple_2]
    Apple: Please get going. You're making me crazy. #v:656
    Apple: You don't want to see me when I'm crazy. #v:657
    Z: I'm sorry, father. #v:658
* { near(Gathy) } [Ambient: gathy_1]
    Gathy: I'm Gathy Journelle, and I'm here to report the news. #v:659
    Z: Hello, Gathy. #v:660
    Gathy: Hello, robot. #v:661
+ (test_thing) { near(Apple) && test_thing < 7 } [Ambient: test]
    { once:
    - Apple: You're a very boring robot. #v:662
    - Apple: I'm not sure why I even bothered to build you. #v:663
    - Apple: I guess I was just lonely. #v:664
    - Apple: I'm still lonely. #v:665
    - Apple: I'm lonely and I'm bored. #v:666
    - Apple: My life is a sad joke. #v:667
    - Apple: A commentary on the futility of existence. #v:668
    }

- -> Free_Roam

I believe something similar (or the same?) was done in Inkle's Heaven's Vault.

A clever element of how both Naughty Dog and Valve handle selecting between multiple lines that are available is that they choose the most specific line, defined as the line with most conditions. Otherwise, they pick randomly. (On top of this there are priority systems, but this simple heuristic apparently works quite well in practice without having to fuss with manual priorities.)

The idea is that a line like "comment about out of ammo" would have less specific conditions than "comment about out of ammo when there are enemies alive and we are an the lava level" and therefore the latter is generally the best choice.

I think it should be possible to dig this out of the parser and put the count on the Line object so my custom code can use it to select the best line.

I'd love to know:

Thanks!