A modest proposal for the ChoiceScript language

My true concern is just the documentation, really. I suppose adding more optional features is fine, but it’d feel like a waste if everyone who uses CS doesn’t know (or even heard) about these features (how did I learn about [n/]?). I know @RETowers is working on an official(?) one, but I have no news whether we have the updated documentation or not, yet.

1 Like

IMO, this conversation would benefit from more clearly listing out the bugs that we’d want to eliminate, and then considering in more detail what it would be like to fix them.

Here are bugs that came up in the context of this thread:

  1. Accidentally forgetting to use FairMath. Using *set strength +20 or *set strength 20 instead of *set strength %+ 20 is easy to do and hard to notice.

    Today, this would only cause a QT/RT failure if this bug increases strength above 100; even then, it won’t tell you about the problem right away. The failure will only come up when you use FairMath on strength in the future, when it turns out that strength is greater than 100. Worst of all, it won’t tell you where strength increased over 100; it will just tell you that it happened at some point previously.

    Ideally, QT would fail on *set strength +20 because QT would know that strength is supposed to be a FairMath variable.

  2. Setting variables to invalid values. If you have a gender variable that you want to be "female", "male", or "nonbinary", it’s easy to accidentally write *set gender "femlae".

    QT/RT don’t really help with this much. RT can somewhat help you catch this if you review the RT output carefully and notice that *if gender = "female" never happens in tens of thousands of runs, but it’s always tricky to figure out why something didn’t happen.

    A good practice for this is not to use text for variables that should have a restricted range, but to use numbers instead, and to define some variables matching those numbers, like this:

    *create female 1
    *create male 2
    *create nonbinary 3
    *set gender female

    That way, if you accidentally write *set gender nonbnary, QT will instantly catch the problem. (It’s also more convenient to use numeric variables in multireplace.)

    But even if you intend to use numbers for gender, it would be easy to accidentally use *set gender "male", which has all of the same bugs, but no typos. It doesn’t even look like a bug when you read it out of context; you have to remember that it’s supposed to be *set gender male instead.

  3. Invalid values in *if statements. This is the other side of the coin of the previous point. *if gender = "femlae" is a bug that QT won’t catch; RT will only indicate it by pointing out unreachable lines. It’s even harder to notice when you write *if gender = "nonbinary" when you’re supposed to use a number *if gender = nonbinary.

I think these bugs absolutely can/do happen quite a bit, and that existing tools don’t help much in preventing them.

All of these problems are tricky for QT to catch because QT doesn’t know enough about what variables are allowed to do. How is QT supposed to know that *set gold +20 is allowed, but *set strength +20 is not? How would the author tell QT what the rules are?

Are these bugs serious enough that authors should jump through some hoops to prevent them? How, exactly, would we want to prevent them, if at all?


There’s at least one more bug I noted above:

  1. Accidentally transposing two variables in a *set statement. Take your numeric fake-enum approach. If at one point deep in your code you accidentally write *set male bob_sex instead of the converse, QT and RT will see no problem. Only when you notice some of your pronouns start going wrong, inconsistently and maybe only after a certain part of the story—or, worse, only in some playthroughs, but not in others—while playtesting will you have any idea that there’s a problem, and then you have no pointer from QT showing where to start finding the bug.

I’m not entirely sure about this. Some authors intentionally use normal math on fairmath stats; @Cataphrak for example uses + and - on fairmath stats early on in Sabres, then switches over to purely %+ and %- in a later chapter once the modifiers have piled up to the point they might approach the 0 or 100 bounds.

But maybe that should be discouraged?


This might cause me some problems, as @Chris_Conley’s mentioned. I tend to use “normal” math on certain “fairmath” variables when the situation calls for it (like in character generation), and I’d prefer not to be hit with a QT fail each time it happens.

Maybe some kind of alert instead?


So, of the four bugs listed there, which of them causes y’all the most trouble?

Other typo-related bugs I can think of:

  1. Forgetting a $ or { in ${}, e.g. Hello {name}
  2. Forgetting a * before commands, e.g. set gender female instead of *set gender female
  3. Capitalization mismatches, e.g. *set gender "Female" *if gender = "female"
  4. Messing up [b] or [i], e.g. This is supposed to be [b]bold/b]

I may be misreading #1 but if I create a variable and set it to true if I don’t alter the stat with the *set command wouldn’t it be constant? Likewise even if it only set once at the start of a game the value would still be constant.

I’m not a big coder so I may have just misread it.

1 Like

I screw up with all of the above, although CSIDE helps catch 5 and 6 as you type because of the color coding it uses.


I’m with Eric… Though the aftermath problems (where variable goes above 100 or below 0 and you can then not do aftermath) are the ones that drive me crazy…

Stricter type safety would actually interfere with the way I code my game. I have functions that rely on being able to parse strings into numbers implicitly, so that I can decrement numeric values within subroutines.

Here’s a much in demand feature for ChoiceScript language that I would appreciate being introduced first: The ability to delete saved game files. I have too many saved game files stinking up certain series.

1 Like

A ‘proper’ constant is immutable once declared. The idea is that it’s then impossible to mix up constants and variables because the compiler would flag an attempt to change the value of a constant as an error. Some languages have them, some don’t. It’s a useful way to cut down on certain hard to find errors but not an absolute necessity.

While CS seems limited in some respects, it’s really quite flexible in the way you can so easily just mix numerics and strings. I, too, tend to create stings of numeric values to cut down on the need for so many variables. Whether that’s a good idea or not, I have no idea. It’s just the way I like to do things…


What values are you storing in these string variables? Or could you post one of those subroutines? That sounds interesting.

1 Like

Relationship values. I have scenes that can take place with one of two NPCs, and in order to dock rel values, I need to pass negative value integers as strings and let JS do the parsing for me.

1 Like

Hmm… I feel like that can be done with standard ChoiceScript.

I do that sometimes too, and I just pass a value by reference:

*create bob_like 50
*create bob_trust 50
*create bob_them "him"
*create bob_they "he"
*create sam_like 50
*create sam_trust 50
*create sam_them "her"
*create sam_they "she"
*label Choose_Conversant

Who do you take with you?
		*gosub Conversation "bob"
		*gosub Conversation "sam"


*label Conversation

*params friend

$!{Friend} is happy to join you. "Thanks for the invite," ${friend&"_they"} says with a smile.

*set {friend&"_like"} %+ 10



Or am I misunderstanding what you need to do?

You’re misunderstanding what I said to begin with. I don’t think I gave the impression that I was asking for new features. I have my solution. My code works fine as it is.

I am currently working on a programming degree, and I can say that sometimes I find myself wishing CS could have the option to be closer to regular coding languages. However, I 9/10 choose to do it the CS way and be exceptionally lazy. I agree that 5 and 6 are easy enough to catch, and on a personal level, I test my code every time I write a few choices, so I’ve never really had problem that couldn’t be easily solved by either asking or testing out a fix.

I would enjoy constants though, ( even though the technically are already constants?) since, I myself use a WHOLE shit ton of variables, remembering them and typing every one out correctly all the time is a pain in my ass. As for Fairmath and Enums I’m not very familiar with it , nor have I learned about them officially. While I might be using it in practice, while doing my variable maths, I was unaware up until now.


Sure, and I was asking in order to understand your method, to make sure that any proposed changes would not break it.

1 Like