I’m responsible for the annoying behavior with *else
. Here’s the background, which may or may not make sense if you don’t have a programming background.
ChoiceScript has a relatively unusual design goal: the goal is to support very large functions, hundreds or even thousands of lines long. In general-purpose programming languages (basically any programming language in ordinary use, like JavaScript, Python, C, etc.) having functions that are more than a few dozen lines long is a bad idea.
They’re a bad idea because they can often require jumping to another part of the code that you can’t even see on the screen. The standard example I use is:
*choice
#Be very naughty.
[…30 lines of code…]
Santa refuses to give you a present.
#Be mostly nice.
[…30 lines of code…]
Santa gives you a present reluctantly.
#Be as nice as can be.
[…30 lines of code…]
Santa gives you a present enthusiastically.
Inside the gift box is a video game!
The same principle applies to *if
/*else
chains.
*if naughty > 70
[...30 lines of code...]
Santa refuses to give you a present.
*elseif naughty > 50
[...30 lines of code...]
Santa gives you a present reluctantly.
*else
[...30 lines of code...]
Santa gives you a present enthusiastically.
Inside the gift box is a video game!
If the example is short enough, then it’s obvious that there’s a bug here: player gets a video game even if Santa refuses to provide one. But when the code gets long enough, when the “video game” line is more than a hundred lines away from the “Santa refuses” line, it’s very hard to find this bug just by reading the code.
In a regular programming language, you’d probably handle it like this:
*choice
#Be very naughty.
*gosub naughty
#Be mostly nice.
*gosub mostly_nice
#Be as nice as can be.
*gosub very_nice
Inside the gift box is a video game!
*label naughty
[…30 lines of code…]
Sanda refuses to give you a present.
*return
*label mostly_nice
[…30 lines of code…]
Santa gives you a present reluctantly.
*return
*label very_nice
[…30 lines of code…]
Santa gives you a present enthusiastically.
*return
But the goal of ChoiceScript was to allow you to have hundreds of lines of code right there on the spot, without using subroutines. So, how could we do it?
I decided to require a *goto
at the end of every indented block; before every *else
or *elseif
and before every #option
you’d have to *goto
(or *finish
or *ending
etc.)
*choice
#Be very naughty.
[…30 lines of code…]
Santa refuses to give you a present.
*goto present
#Be mostly nice.
[…30 lines of code…]
Santa gives you a present reluctantly.
*goto present
#Be as nice as can be.
[…30 lines of code…]
Santa gives you a present enthusiastically.
*label present
Inside the gift box is a video game!
That makes it obvious that the *goto present
line right next to the “Santa refuses” line is an error.
And so it is forbidden to “fall into” *else
or an #option
. (It’s OK to “fall out” of the last #option
or *else
because that’s guaranteed not to jump to a line of code you can’t see: you’ll just go to the next line.)
The primary drawback of this rule is that it’s outrageously annoying for short code. If you really do want a *choice
or *if
/*elseif
/*else
chain that’s under a dozen lines long, having to add those extra *goto
lines is a lot of extra typing.
@benhamill is also right that this means that *else
is kinda “fluffy.” In a language with *if
and *goto
, you never really need an *else
command at all; you can rewrite all of your *elseif
commands to be simple *if
statements. But I think you’ll find that the code is usually easier to read when you use *else
and *elseif
commands, even if it means that you have to add *goto
lines.
For the record, another approach I’ve considered is to explicitly forbid large jumps. So if you omit the *goto
you might get an error like this:
*line 34: Large jump error. After this line, we’d need to jump ahead 68 lines to line 102; that’s too big a jump to be safe. Add a goto statement so we know that’s what you meant to do.
(Perhaps the number would be configurable by the author; you could set it to 0 to get today’s annoying behavior, or turn off “large jump errors" completely.)
But I haven’t done that yet, partly because it would require work, but also because it would make ChoiceScript even weirder than it is today.