(removed)

This is all great. can’t wait to see how it evolves.

BTW nice taste in visual novels.

1 Like

Thanks!

And yes, Higurashi is awesome. :smiley: I’ve been going through it lately. I’m currently on volume 4. I’ve been watching each arc of the anime to compare it after finishing a volume too. Hehe. I’m a dork.

After this, I’ll probably do the same with Umineko.

1 Like

Those two are my all time favorite visual novels. Especially Umineko, That is a masterpiece.

1 Like

I got bored and made another demo.

This time I took my 15 year old text adventure engine and made it work using sadako script. The engine is almost entirely in JS, but it takes the definitions of the objects from sadako script. Because of that, you can have use all of the normal sadako script stuff, including jumps and returns, all the fancy links and dialog windows, etc. However, due to the hacky nature of splicing the two together, choices aren’t working in this demo. Sorry about that.

The demo is here:
http://tayruh.thanatos.feralhosting.com/text_adventure/

You can see the sadako script here:
http://tayruh.thanatos.feralhosting.com/text_adventure/textadv.sko

As far as the usability of the engine, it’s not that bad. I actually got quite a lot of functionality to work way back then.

1 Like

I just released a new version of Sadako, version 0.12.0. There are quite a few significant additions.

I have all of the changes and some code examples on the release page, but the big ones are:

  • I have now added for and while loops to sadako script.
  • You now have the ability to select a portion of a choice’s display text as being the link instead of all if it being a link.
  • I completely reworked the text replacement for $: and _: embedded variables ($. and _. and other variable embedding remains the same as they were).

The last one means something like this is totally valid script:

[:&
	$.locations = {
		"w_world": { name: "Westworld" }
	};
	$.player_location = "w_world";
:]

Welcome to $:locations[$.player_location].name.toUpperCase()! I hope you enjoy your stay!

// outputs:
Welcome to WESTWORLD! I hope you enjoy your stay!

You can find the current release here: https://github.com/Tayruh/sadako/releases/tag/0.12.0

2 Likes

I managed to put together a VS Code language extension for Sadako.

It was a learning experience. I’m going to be dreaming of regular expressions tonight. :sweat_smile:

Here’s a snazzy screenshot of it in action:

But anyway, you can find it here on the repository: https://github.com/Tayruh/sadako/raw/master/vs-code/releases

To install, just click these items in order (exensions tab -> three dot menu -> install from vsix):

Visual Studio Code uses TextMate standards in JSON format which you can find here in the repository. (There’s also a .yaml file in there because I wrote it in YAML and then transpiled it to JSON because it made my eyes bleed less). A lot of other editors (like Atom, Sublime Text, TextMate (obviously)) also use the TextMate format, so porting to another editor should be fairly easy. If anyone wants to port it, feel free to do so.

4 Likes

Minor release today. I only added one new feature, but it’s a really useful one.

You see, for those unaware, the way that Sadako works is that it goes through the script until it sees a choice. It then collects the choices until it sees a line that is not a choice (whether it be a condition block, or a depth token, or whatever). The script then stops processing and waits for the user to click a link.

The downside of doing it this way is that once you have already started a list of choices, it’s impossible to include choices from other places in the script using jump or include tokens, because in order to use those tokens, you would have to use a depth token first (to separate it from the choice story block), which would halt the script and wait for input.

In other words, this is broken:

Example.
+ Choice 1
- >> choices
<< END

= choices
+ Choice 2

// outputs:
Example.
<Choice 1>

As you can see, the script ends before the jump to choices because a - depth token halts the script after a list of choices. It was intentionally designed this way, but it comes with that unfortunate side effect of being unable to include choices from elsewhere.

I have now added a + >>= choice include token. Basically it’s just a + static choice (at the correct depth level) followed by the typical >>= include token. What makes this special is that it can be used during the listing of choices and (unlike a normal >>= include token) will not only include a story block but will also include its choices.

Therefore, this works now:

Example.
+ Choice 1
+ >>= choices
+ Choice 5
- << END

= choices
+ Choice 2
+ >>= more_choices
- << END

= more_choices
+ Choice 3
+ Choice 4
- << END

// outputs:
Example.
<Choice 1>
<Choice 2>
<Choice 3>
<Choice 4>
<Choice 5>

Anyway… that’s about it. A small change with large effect.

You can find the new release here: https://github.com/Tayruh/sadako/releases/tag/0.12.2

3 Likes

Since I haven’t received any feedback on my engine thus far, I’m curious if anyone has spent any time messing with it and what their thoughts are. Is there anything you’d like to see added or would like to see changed? I’m all ears.

I’m also sorry that I haven’t released a full game using the engine yet. To be honest, I’m not very good at creative writing. I have to be in the right head space for it. I’ve always been better about writing an engine than producing content with it.

Trying out your engine has been on my to-do list for awhile now, I just haven’t had time lately for creative projects. I’ve used GUI editors before like Adrift (mostly tinkering) but know enough programming to understand the advantages of writing directly in script code. One aspect I really like looking at your engine is how flexible it is. When it comes to storytelling in digital media being able to do pure text to mixed media projects all with one engine is really appealing to me. The fact that it uses web technology like html and javascript is another factor I like.

1 Like

Thanks. :slight_smile: Making it flexible was one of my primary goals from the beginning.

One of the things I disliked about Twine and other hypertext engines was how tied into a specific HTML framework each one is (with the exception of the Snowman story format, maybe). You can customize using CSS and such, but it’s generally pretty difficult to make it your own and do something really crazy with it. This is one thing that I think Ink got right, even though its HTML version was more of an afterthought.

1 Like

The engine looks cool and will check it out when i have some free time. Might i recommend making an IFComp game to promote it? I think Dialog did it and now a lot of people are checking it out!

2 Likes

I’ve been wanting to make a game and enter it on a competition for that reason, but I’m currently out of ideas on what to make. :sweat_smile: I’ve been brainstorming but no luck so far.

Writing isn’t one of my strong suits. Other than that Monster demo game, I haven’t actually written anything since highschool, so it doesn’t come easy to me. But I agree that would probably be the best form of promotion.

1 Like

What about writing a beginning for Introcomp that shows off what Sadako can do? The focus of Introcomp is feedback and getting to trial-run an idea.

2 Likes

Hmmm. I wasn’t aware of that competition. That sounds pretty perfect, to be honest. I’ll see if I can figure something out to submit.

2 Likes

One thing that usually helps me in brainstorming is think about all the games/stories/concepts/troupes that i like and combining them.

If writing is not your strongest suit, you might like to find some collaborators? i think there’s a category here about seeking collaborators.

Wow this is really cool and a lot of work!

Can I ask about the structure you’ve decided on here? I was just looking at the initial demo.sko

I checked the reference here

sometimes you have characters at the top level and sometimes objects… or maybe it’s just that a ‘page’ could be named different types of things?

## inventory

## living_room ~:room
	(:title "Living Room":) 

## erin
	>> living_room.erin_watching

	- >> remote :: *.waiting_for_remote.isActive

The thing I liked most about Twine was the simple visual editor. It seemed really hard to actually extract the generated data from that though…

Some of that [:& _.test = "first":] syntax! I can imagine writing that VSCode plugin drove you crazy on regexes.

Is there a text parser here or is all user input event/button driven?
I like the RiveScript subset of regex for easy authoring and captures, I find that’s a very simple language and built a few things with it. It’s very easy for non-techies to pick up and write simple stuff with, although gets ugly as soon as you do have conditionals and other logic.

Great work! Looks like you’re having a productive Covid :smiley:

1 Like

Thanks! :blush:

It’s all event driven with clicks. However, if you check out the visual novel demo and the text adventure demo (this post), you can see that it’s really configurable.

Basically when you click a link it either calls sadako.doChoice() or sadako.doLink(). All you have to do is fire those calls from inside a parser command and it should work, which is how the text adventure demo functions. I tried to make it so that all of the HTML related stuff can be completely removed if needed and it’ll function as pure JS.

Well, I guess I should start by clarifying something, just in case you misunderstood: Sadako is a hypertext engine, which means it’s shares a lot more in common with Twine and Ink than a parser engine. You can fake an object based game with your text (which is what I do in my demos), but there’s no actual object interaction.

That being said, the script is set up like a combination of Twine and Ink. It goes:

## page_name ~:page_tag
	Some text.
	+ Choice 1 text.
		Result of choice 1.
	+ Choice 2 text.
		Result of choice 2.
		++ Choice following choice 2 result.
			Results of that choice.
	- The script will resume here after both choice 1 and choice 2 blocks.
	>> label  //jump to a label
	The script resumes here after the jump.
	Clicking [:new_page @: here:] will jump to a new page.
	<< END  //the script halts here to wait for input

	= label
	This will be displayed after the script jumps to this label.
	<<  //return to where we were

## new_page
	This is a new page.

The important takeaway from this script is that Sadako doesn’t care about indentation with spaces and tabs (I only use them for clarity). Instead, it uses token counts to track the depth of a block of code. This concept is borrowed from Ink.

In the example both choice 1 and choice 2 will be displayed initially because they both only have one + choice token. The choice inside choice 2 will display after you select it because clicking a choice increases the depth by one, so now ++ is valid. The use of one - depth token resets the depth back to one, which makes the script leave the block. Choices always look for the next non-choice token once their block ends, which is why choice 1 jumps to - after its block ends.

I don’t know if that’s a good example for you or not. Hopefully it wasn’t too confusing. It’s only a small portion of what the engine can do, but those are the most common things.

FWIW, with the exception of a few things like ~ if and << END, I designed the engine to only use characters instead of reserved words for its functionality. It might be a bit confusing on first viewing, but the end result is cleaner looking script where function calls don’t blend in with the room descriptions and make everything look like a garbled mess. IMO, anyway.

thanks for the reply!

I meant in terms of the top-level ## items in that example demo script.
Which I think are called “pages” right?

I’m confused because some pages are named after people erin and others inventory or remote. Perhaps those are just like names for “scenes” in a movie, maybe “talk to Erin”
Is that just a visual separator or is there any functional importance to it?
Since you have labels also which are used for jumping around, I think.

	>> label  //jump to a label
	The script resumes here after the jump.
	Clicking [:new_page @: here:] will jump to a new page.
	<< END  //the script halts here to wait for input

	= label

A benefit is you could use a markdown renderer and provide a visual outline to authors, as it’s an H2 symbol.

It reminds me a bit of RASA’s NLU story format, which is a kind of weird markdown hybrid. This is really just a format for training texts for an NLU (natural language understanding) engine, so more like a parser in IF parlance.

So that would mean that ++ is two steps indented?
image

It seems like a neat hack to make parsing easier, but from a UX - it also means people have to be very specific in their use of token counts, whereas the indent does NOT actually matter. I’m not sure that is intuitive…? But it’s good for copy and paste, sharing stories, unlike python’s whitespace rules…

maybe if you were flat formatting…

+ topic
++ subtopic
+++ subsub

then token count matches the indents…

I do really like the “outliner” format for story authoring though, how you can nest blocks, and then continue or fall “up” the conversation tree when a topic is exhausted. I believe Minsky wrote about that topic in Society of Mind but I can’t find the reference now.

The very first version of the pullstring IDE had a nice “outliner” style where all the indentation was managed for you, but “significant”.

Personally I’m trying to go far with a structured YAML format, so I don’t have to write my own parser for authored scripts.
But that approach does make it a little obtuse to author logic like conditionals. I’ve considered things like the mongoDB query syntax, where it’s purely expressed as data eg:

var query2 = {
  $and:[
    {userName: "bob"},  
    {animal: {$in: ['beefalo', 'deerclops'] } }
  ]}

really ugly as JSON or YAML but the benefit is you can provide a visual editor as the syntax is very defined. And the parser is also available.

anyway back to work

It’s probably easiest to think of pages as separate files that you can include in one script file for convenience. I could have dumped all of the Erin related stuff into the Living Room page since she’s listed right there in the description, but it would have been really messy. Making the script jump to a new page is completely transparent to the player and makes for cleaner code.

Another reason is that labels are associated with pages. When you click on the choice ±± {talked} [Back] in the erin page, it increments erin.talked by 1. That way you can check whether you’ve talked to her already or not. It’s cleaner than living_room.erin_talked or something similar.

As for the remote, I separated that one off because I use it as an inventory item. It’s probably more complex than is necessary for a simple demo with only one item, but the game.js file has a function that links the description and usage of an inventory item to a page with the same name. So that’s the reason for that.

As for the depth token concept, initially I was trying to emulate Ink a bit. That’s how they do it also. But then I wondered the same thing as you, which is whether the potential errors were worth the clarity.

My thought process was this: There are only three ways to do multi level blocks, AFAIK. You can do open/close tags, indentation, or token counts. I was going for as little unnecessary typing as possible, so I ruled out tags. Indentation and token counts have the same potential errors, except indentation demands exactly the right indentation and the errors are not as obvious (4 spaces do not equal 1 tab, but they usually look the same). While tokens require you to use the correct amount, you can see them, so the errors don’t happen as much as you may think. I also have a few compile-time error catches in there that alert you if you accidentally go from a depth of 1 to a depth of 3.