Choicescript - a programmers rant

Hello everyone,

As of last few weeks I have been fiddling around with the choicescript. As a programmer by trade, I have tried to get a bit more bang out of its possibilities and there are two things that I am currently sorely missing:
First:
Is there anything similar to *getref var1 var2?
By that I mean inverse operation to the *setref - it is definitely nice to be able to store things into variable by their name but it would be a bit more convenient to be able to retrieve their value afterwards without doing some nasty things.
(well, truth to be told, complete solution would include allowing dynamic allocation of permanent variables, that would be super-awesome, but that would be a wee bit more complicated I guess)

Second: is there any way to parse strings? That would be really useful to use as a storage(for example inventory) not to mention that it could save some space. (Yes, It is possible to create something like an inventory even without parsing string or dynamic variables, no it is not comfortable.)
I am aware that it is a topic most of the users wont find important, so take this mostly as a curious question. (My solution at the moment seems to be working, as far as my testing went, but it is uuuugly. Not to mention the size of variable declaration file. Tends to grow.)

There are few minor things still:
What is a reasonable size of the CS game alltogether? I am experimenting with some code generation(mostly automatic variable declaration) and the files tend to get a bit bloated(well, not that it is necessary, but it is convenient)

Is it possible to get Hosted Game, that features direct use of javascript(via *script)? I have read that there is no support CS-vise, and I am ok with that. Only considering the eventual deploy.(not that it would happen anytime soon, but better ask now, then halfway through the story)

Regards,
Sima Tian

P.S.: My salutations to the CS authors. To me it seems like quite a nice way to enable people work with something reasonably easy to work with but yet allowing some interesting possibilities.
P.P.S.: something that could be quite easy to implement and would make life of everyone slightly more comfortable would be having *multicreate var1,var2,var3,var4
It would

  1. save space in the startup file(the *create being unnecessary overhead)
  2. be much more pleasant to write without having the files overly bloated. (ugh, the custom save system declarations are a killer)
    P.P.P.S.: what about having default variable value? Something like ā€œnullā€/0/space I keep forgetting to initialize and most of the time the initial value is just zero.
5 Likes
  1. If you mean showing the variable, itā€™s simply ${var1} etc
  2. I think you can do that with sub routines (if I understood you correctly)
  3. the minimum, iirc is 60k words total (with code) the maxā€¦ depends on you
1 Like

I kind of struggled with parsing substrings too, but you can call individual letters using their index.

I.e.
foo#x where x is the index of the letter.

To get an entire substring, you can mimic a while loop using labels and *goto

I.e.
*label hello
*set z +1
*if foo#z = ā€œ.ā€
*goto bye
*set substring substring&foo#z
*goto hello

Its ugly, clunky and not good with the automated test though.

4 Likes

Ahh, the part with recalling individual letters sounds awesome. I will be able to do rest. (It wasnt mentioned in the tutorial, was it? If yes, then I missed it :slight_smile: )

2 Likes

Thank you for the response, but unfortunately it seems I was not clear enough in the questions:

  1. no, I meant loading the variable somewhere where it can do me some good. E.G. into subroutine to act as a memory cell. As a side note: would ${var1} work when the ā€œvar1ā€ is a string stored in a variable? That is what I mean by getRef
  2. the missing part was the indexing of characters by their index - as nauhziy pointed out.
  3. I meant the maximum of actual size, sorry for not being clear enough, my bad. I use a wee bit of code generation and when I tried working with a reasonably sized aray of 10K variables, the loading got a tad slow.
    (no need to panicā€¦yet, MVAHAHAHA. No, really, just trying things out.)
2 Likes
  1. Yes it works for strings, int and float. Never rly tried it for anything else

  2. How did you create the array?

*create myref "myvar"
*create myvar 4

${{myref}}

My advice: Donā€™t fall into the trap that many programmers do: you hack CS so much you realise you may as well just have wrote your own engine in a proper scripting/programming language. You must have picked it up for a reason, right? Part of the fun is its simplicity. Yes, there are things it lacks (*create_array please!), but Iā€™d advise against bullying it into parsing 10kā€™s worth of variables. Thatā€™s slow enough in single-threaded JS.

5 Likes

Well, I wrote a bit of C# code that generates:

*create v1
*create v2
...
*create vWhateverSizeNeeded

And then one scene to access the variables:
*label load
*set variableAccess1 ("v"&argument1)
*gosub_scene variableLoad
*set returnValue1 variableReturn1

*comment set variable with ID==argument1 to argument2
*label save
*temp test ("v"&argument1)
*setref test argument2
*return

But since I had no *getRef the loading of the variables has second part in scene called variableLoad. This one is bloated and ugly:
*gotoref variableAccess1
*label v0
*set variableReturn1 v0
*return
*label v1
*set variableReturn1 v1
*return
*label v2
*set variableReturn1 v2
*return
*label v3
*set variableReturn1 v3
*return
*label v4

This basically enables me to anytime save variable with:
*set argument1 variableIndex (e.g. 123)
*set argument2 IntendedValue
*gosub_scene variableAccess save

and later load it with
*set argument1 variableIndex (e.g. 123)
*gosub_scene variableAccess load

It is not nice, especially considering the in-game save system I have that basically means creating all the variables X times where the X is number of intended save slots. I will have to either decrease the number of variables(1K is kinda ok, 10K was slow) or decrease number of save slots.
The thing is, with less than cca 1K variables it is a bit hard to write something more complex. Was thinking of having parts of the game generated after start to make things a wee bit more replayableā€¦

There are few things I will experiment a bit more before trying to include/share them, but so far these seem to be working reasonably well. (foooor example saving some space by bit-packing booleans to ints? or something along these lines, as the size might be an issue for me.)
The annoying part would be writing the MALLOC on top of the array, as I need to save space. :expressionless: Donā€™t want to do that if I can prevent it.

As a side note, is there a string size limit?
And you mentioned floats? the tutorial claimed only int, string and bool as far as I recall? Not that I need it at the moment, but, but, but float?

At the moment I am mostly fiddling around with concepts + writing bits and pieces of the story.

Ad CJW:
You are completely right. The thing is simple: it is for some reason more liberating to try and hack something that exists - the constraints are forcing me to thing. To bend thigs. To reassemble. To work around.
I tried working in something more free more than once. I usually fail on too much freedom. Here I can write while thinking: wouldnā€™t it be great to bend the things to be able to generate custom-made maze for each user? Would it be interesting for them? How bit can the maze be to not be daunting?
Not: How the hell should I begin. There are too many options. Help.
as for the ${{myref}} I am bloody idiot: some time ago I have started looking through the wiki instead of tutorials(easier to find regular stuff) And I recall seeing this in the oficial guide. Drat.

UPDATE: it works for displaying, but while trying to
*set variable ${{myref}}
it throws an error invalid expression, could not extract another token :frowning:
And Thanks

2 Likes

I know exactly what you mean, but believe me (and I speak only from experience), you will get to a point where it becomes impractical. By all means mod, and hackā€¦ But limit your scope. Pre-generating variables with another language script isnā€™t a bad idea for example, nor is extending the CS language. Iā€™d avoid *script though (again, speaking from experience). Just modify the CS source if youā€™re going to go that far. *script gets messy fast.

Youā€™re thinking far, far too low level here. There is no use or need for mallocs or bit packing in CS. What memory are you running out of? RAM? That seems unlikely on modern machines with a text based game.

No problem!

Use *set {myref}, the $ is used like a ā€œprintā€ operator. Think of {} like ā€˜valueOfā€™.

2 Likes

*script would be last resort. True, in that case it would be easier to write the game completely in JS. And you are right about one of the reasons of choosing CS: Not much thinking coding wise, when not trying to bypass something.
Can focus on the story.
Most of the time.
When not *line_breaking.
For some reason I have the feeling that half of my story is *line_break or *page_break.

No, not running out of the ram I guess. Just that the overall loading time slowed down when the file size went to few dozen megabytes. Well, that was to be expected I am afraid. Made me thinking about ways to keep things nice and dandy while having my array.

Thanks again, finally it works. Now I can dump the ugly variableLoad file. And maybe even the load variable subroutine? Hell yea.
And shoot me again.
Why is there even the *setref command in the tutorial? It took me a while to wrap my head around it(its a bit counter-intuitive Im afraid.) while the {} is much much nicer.
*set {ref} value
works better, possibly saving me some headache.
Well, glad that I asked.

1 Like

Just wait till you try to make an *if with more than 2 varā€¦

1 Like

You mean the brackets?
*if (((var1=var2) or (var1=var3)) and someOtherVar)
Or is there something that I have missed?
The daunting task that I had not the courage to try are the nested choices. And I hope that I will not need it anytime soon.

2 Likes

I think that way it wont workā€¦

1 Like

Always think of them in pairs, once I started doing that, *if variations worked just fine as long as the brackets are correct

2 Likes

Yep, the check is always a pair of twos.

And to be honest, nested choice is actually a really simple thing. Much easier thanā€¦ well, the other points you have mentioned thus far :stuck_out_tongue:

1 Like

What is the difference between:

*goto {var}

And

*gotoref var

?

I tried and both did the same thing and worked for what i wanted.

1 Like

oddā€¦ i thought *goto would only work for labels OĆ³

1 Like

I donā€™t remember thereā€™s any command named *gotoref :thinking:

There is *setref, but thatā€™s obsolete.

1 Like

Both are deprecated in favour of the curly brace syntax.

2 Likes

I peeked in here hoping to maybe get a better grasp on coding for choice script and this is is like reading Greekā€¦

1 Like