In the latest version of ChoiceScript, new features are available for programmers. They’re documented in the Advanced ChoiceScript section of the documentation, which means that you probably don’t need to use them. (I like to discourage people from getting too fancy in ChoiceScript games, because adding complexity rarely adds to the fun of the game.)
Curly braces now replace *setref and *gotoref. For years, you’ve been able to use curly braces {} around variable names to return values by reference, like this:
*create honesty 30
*set virtue "honesty"
*set score {virtue}
Your ${virtue} score is now ${score}.
But the curly braces would only work on the right-hand side of the *set statement. Now you can use it on the left-hand side of *set, eliminating the need for a separate *setref command.
*set {virtue} %+ 20
Similarly, you can use it in a *goto statement, eliminating the need for *gotoref.
*create superpower "invisibility"
Your super power is:
*goto {superpower}
flight!
*finish
*label invisibility
invisibility.
*setref and *gotoref still work, but they’re now deprecated. We recommend using curly braces instead.
Curly braces now work in more commands. The new curly syntax now works in a bunch of commands, including *rand, *input_text, and *input_number, but most importantly, it works in *goto_scene, and *gosub_scene.
EDIT: Beware that Quicktest effectively skips *goto_scene and *gosub_scene lines that use {} or []. (Randomtest works fine.) If you have a file with a section that can only be reached using a curly referenced *goto_scene command, consider adding a section like this somewhere in your game, enumerating the possible destinations.
Quicktest will “run” those lines to verify that the chap1, chap2, and chap3 labels exist in the checkpoint scene, and verify that those labels will be actually covered by Quicktest.
${} now accepts arbitrary expressions. Previously, you could only use a simple variable name, like ${foo}, but now you can put any valid ChoiceScript expression in there, like ${gold+10} or even use curly braces for indirect references. ${{best_stat}}
Experimental support for arrays. I don’t want anybody to rely on this syntax yet, because I may need to change it yet, but I would like feedback on it. (In other words, talk to us before submitting a HG or CoG game that uses arrays.)
Arrays work by putting square brackets [] after the name of a variable, like this: foo[1]. It’s effectively the same thing as {"foo_"&1}. But you can put anything in the brackets, including variables, like this: strength[current_opponent].
Arrays work anywhere curly braces work:
*create current_opponent 1
*create strength_1 50
*create damage_1 20
You did ${damage[current_opponent]} points of damage.
*set strength[current_opponent] -damage[current_opponent]
*goto dialog[current_opponent]
*gosub_scene dialog[current_opponent] took_damage
I fully expect that there are bugs in the new code, so be sure to let me know of what you find.
Wait, these aren’t the kind of arrays I’m used to. So, I’m not explicitly *creating an array, I’m *creating variables that can be referred to in an array-like fashion? Strength_1 is element 1 of array ‘strength’?
*create strength_1 5
*create strength_2 10
{strength[1]} prints 5 and {strength[2]} prints 10, ${strength[3]} gives a ‘variable does not exist’ error. Is this correct?
To be clear, you can use the new curly stuff right away. We’ll use arrays ourselves in at least one project. If it works great and nobody had any significant objections, we’ll make arrays official.
By which I mean to say NOM NOM NOM NOM NOM NOM NOM NOM NOM.
Question, if I may, but what exactly does doing this:
*create current_opponent 1
*create strength_1 50
*create damage_1 20
You did ${damage[current_opponent]} points of damage.
Do? Does it tag opponent 1 with the damage? Or does it create an arithmetical equation subtracting “1” from whatever damage you inflicted?
So, if I’m understanding correctly, the [current_opponent] added to the end of a variable (since current opponent was created with a value of 1) it would reference all stats of current opponent (or at least all stats with _1). And it would no longer do so were current opponent set to 2 in this example?
Those are policy decisions, not technical issues. Obviously *script and CSS mods work today. But running arbitrary *script on choiceofgames.com is a security risk, so it’s very unlikely that we’ll ever allow that in games we host.
As for CSS mods, I guess we could? But that gets back to the question of what our games should look like. If we do a fancy UI redesign, would we stick with whatever custom CSS you provide? Or would we blow it away and replace it with our stuff?
Regarding the use of *script on the official COG site: Wouldn’t running the games on its own “dummy” site, on their own shared hosting plan and then adding it to the COG site in an iframe solve that issue?
That’s what sites do that want to host untrusted content, but for CoG games, we do trust/evaluate the content, and we’d like our main choiceofgames.com domain to receive full credit in Google for the game.
I see, makes sense, since it adds more pages, thereby authority and keyword density, not to mention you have the social buttons in the game there for social media backlinks… smart. Actually, if I may ask one last question, how would *script compromise security if its in it’s own folder? If I remember right *script simply calls a function into being from the index file right? So how would it do that? Via someone tampering with the code in a browsers’ dev console? Or would it reveal game file paths?
It’s a XSS attack. Basically, *script can do anything at all to the page, including sending your authentication cookies to a third party, prompting the user to enter their credit card information, tricking users into giving away passwords, etc.
The most severe XSS attacks involve disclosure of the user’s session cookie, allowing an attacker to hijack the user’s session and take over the account. Other damaging attacks include the disclosure of end user files, installation of Trojan horse programs, redirect the user to some other page or site, or modify presentation of content.
So, it would be an attack from the inside of the program itself much like adware on a computer? Couldn’t you (theoretically without thinking about work time it would take) check and fleece stuff like that from COG’s end?
I can’t write code that looks for “evil” *script. I can manually review *script commands, but that’s painful and time consuming. I guess I could whitelist some known-good *script, but normally I do that by adding features to ChoiceScript, converting *script to non-*script code.
I just finished reading this post, so I haven’t had the time to test any of the new features, but as a programmer, I am really excited for these. I’m planning on starting a new project soon, so I’ll likely dive into these and if I run into any issues/suggestions, I’ll forward them here!
Using curly braces has worked well but seems to be picked up as an error in the current Quicktest. If I run my game, curly braces work, but Quicktest gives this error:
QUICKTEST FAILED
ERROR: couldn’t open web/mygame/scenes/{hold_scene}.txt