*elseif needs *goto?


I’m testing out the *elseif command and received an error. I’m confused as to where the *goto command should be put since this will eventually show a blurb describing a character’s relationship with the MC - which changes as the amount increases or decreases.

Think Tin Star where you can toggle between seeing the stat bar or read a description.

Here’s the error message:

Here’s my test code:

*if (dship1 >= 25)
    This is the text a player would see if [b]$!{d1name}'s[/b] relationship is greater than or equal 25.
*elseif (dship1 > 25) and (dship1 < 50)
    Else if greater than 25 but less than 50.
*elseif (dship1 > 50) and (dship1 < 75)
    Else if greater than 50 but less than 75.
*elseif (dship1 > 75) and (dship1 < 90)
    Else if greater than 75 but less than 90.
*elseif (dship1 >= 90) and (dship1 <= 100)
    Else if greater than or equal to 90 but less than or equal to 100.

Thanks for your help!


Yes, *elseif needs a *goto on the line after the descriptive text. Also, the last *elseif there should be an *else if that is the last one.

You could also do this with a bunch of *if commands, by the way, in which case you would not need the *gotos.

By the way, note that your code won’t know what to do if dship1 is exactly 50 or exactly 75.


The template is basically



I think I might need to use the *if commands, except there’s one tiny problem. After plopping in the *goto and *label commands and then running a quick play test, ChoiceScript stops responding. :thinking:

If I used the *if commands, that would only allow that text beneath that particular *if to show up, correct?

One of the previous problems I was having was that I did use the *if commands, for instance *if (dship1 >= x), was that the text didn’t replace it with the new text whenever the next threshold was met. Instead, it’d just awkwardly stack on-top of one another.

So, this:

*if (dship1 >= 25)
Greater than or equal to 25.
*if (dship1 >= 50)
Greater than or equal to 50.
*if (dship1 >= 75)
Greater than or equal to 75.
*if (dship1 >= 90)
Greater than or equal to 90.

would end up looking like this:

Greater than or equal to 25. Greater than or equal to 50. Greater than or equal to 75. Greater than or equal to 90.


If you do your parameters cleverly enough, ensuring that more than one *if cannot trigger, then yes, only one will show up --but it’s easy to mess that up, and that’s why *elseif and *else is so useful.


CS froze on me when I tried to play test the code with all of the *elseif and *goto’s. If I include the <= and >= signals, will it prevent CS from freezing when I go to play test it?


Apparently *else if is not a valid command either:


There is only:


You cannot add new conditions to the *else in the same line, but you can in the line below.

   *if (whatever >= 1)

*if ((dship1 >= 25) and (dship1 <=49))
   Greater than or equal to 25.
*if ((dship1 >= 50) and (dship1 <=74))
   Greater than or equal to 50.
*if ((dship1 >= 75) and (dship1 <=89))
   Greater than or equal to 75.
*if (dship1 >= 90)
   Greater than or equal to 90.


*if ((dship1 >= 25) and (dship1 <=49))
   Greater than or equal to 25.
   *goto x
*elseif ((dship1 >= 50) and (dship1 <=74))
   Greater than or equal to 50.
   *goto x
*elseif ((dship1 >= 75) and (dship1 <=89))
   Greater than or equal to 75.
   *goto x
   Greater than or equal to 90.
   *goto x


I’m guessing you can’t add new conditions to the *elseif command on the same line, as well? That might explain why CS keeps freezing when I try to run a play test.

@MeltingPenguins - I’ll try that out too - once CS finally unfreezes itself - thank you!


I think usually freezing means it’s looping. at least it often means that iirc


Makes sense.

@MeltingPenguins - I plopped in your first block of code and it’s all good! Thank you! :smiley:


For the *if and *elseif you can add as many conditions as you like in the same line, just make sure your parenthesis are set correctly.

One thing on the second example from @MeltingPenguins posted above, the one using the *elseif and *else will work incorrectly if dship1 is lower than 25. The *else will run both if its higher than 90 and lower than 25. You might want to add another first condition to catch dship1 when it’s 0 to 24.

The first example will not have this issue since there is no *else to catch all negative conditions, but also nothing will appear on it when the relationship stat is from 0 to 24.

Addendum, if you want to disable the need of using *gotos for *elseifs and *elses, a possibility is to use implicit control flow.


Don’t listen to GS about implicit flow. It will only cause trouble down the line.

Also, GS, I assumed that the variable starts out at 25 and can’t be lowered.


Er, what problems does implicit flow cause? :sweat_smile: I always thought it was extremely useful for removing a lot of code clutter.


For testing maybe, but it can easily eat entire sections, aka skip them under circumstances. Trying to remember who it was who had it skip about half the game.


By itself, none; a problem is caused only if the coder is forgetful and/or disorganized.

Implicit control flow simply removes the needs for *goto after *elseif, *else and *choice. So besides not needing to use *gotos in *elseif and *else (as you’ve said, it’s good because it cuts down a lot of unecessary labels right under those *elseifs and *elses) it transforms the *choice into a *fake_choice.

As in, if it does not encounter a *goto it will simply continue down the file. So if the coder makes a mistake and forgets to put something there the code will continue down the file down and that’s it. Nothing else is changed, you can still use *gotos wherever you want, including on *choice.

The great gain of implicit control flow on is to cut down on *gotos and *labels after the *elseifs and *elses, especially if you use that a lot. It also avoids workarounds of very long sections of *if, *if, *if… etc instead of a more organized *if, *elseif, *elseif, *elseif…, *else section (as is more usual in programming).

These claims are blown out of proportion; this is not absolute. I don’t want to start bickering but it’s getting tiresome having to reply to another total misinterpretation of yours once again in the same week.

If one author made a mistake about having half their game skipped the mistake is on them, not implicit control flow. By usint this they had in mind that it would cause something to proceed down if a *goto was not included. The fact that the code did exactly what it was supposed to do was not an error; the mistake was the author forgetting to include something.

I provide this alternative (and will continue to do so) because it’s helpful and because it’s optional. If you don’t like it or are not capable of using it, don’t use it. Choice of Magics is a game produced and published using implicit control flow, if you don’t believe me, just go look at its code in its demo and you will see it there after all variables are created. Don’t claim your opinions that it’s only for testing or it shouldn’t be used as fact; it is in use by an official CoG product. If you want, go ahead and tell the author of Choice of Magics they made a mistake in using it.

Choice of Magics code snippet

For others reading this, instead of going by arguments such as “don’t listen to X, it’s bad” with poor reasoning behind it, read my explanations and link above to the official CoG staff announcement about it and make your minds whether it’s something YOU want to use it or not.

Besides, next week I’m gonna make a wiki page about implicit control flow and *gosub params because I think they are valuable tools for coders and authors. They’ve been announced a while ago and not well known; I want to correct that and make them known for others that are interested on their uses.


Just because it can work does not negate the bad effect it can have when it doesn’t.
And if half a game is skipped because of something that would have resulted in an error without ICF it is to blame on it.

Anyway, back to topic

EDIT: @GoldenSilver Can we agree on this:
ICF can be a good thing for testing, but one should make sure that the game would also go smoothly without it. Better safe than sorry.


I feel like implicit flow is more of an “Advanced Choicescript” option, like calling variables by reference. If you’ve worked with it for years, or you’re coming into Choicescript from a programming background, sure, knock yourself out; you’re experienced in all the strange and hard-to-debug ways code can go wrong. But you’re going to have to proactively, systematically guard against bugs, when you’re working in a paradigm where fallthrough out of every single control structure is possible.

Just take a look at Gold’s code; he uses *bug all over the place to catch unexpected game states, including dividing between blocks of code separated by *goto or *gosub statements, to prevent inadvertent fallthrough from one game state to something completely different. Sticking to the default setting, where every *if and *choice block must end in a terminating command, obviates nearly all of that risk.


Implicit_control_flow is the correct approach, period. Ask any real programmer, after they get over their shock at the alternative. No other language thinks goto to get out of if/else is a good idea. It’s nuts.

Gotos have the problem that they might go anywhere, making the flow nonobvious on inspection, so they’re frowned upon in other languages - there is always a better way to do whatever it is you’re trying to do. Putting them in every if/else is particularly bizarre as a language choice - better to have the default be to continue, and then if you see a goto, you know it must go somewhere weird. Trying to avoid gotos generally has been accepted wisdom since the 70’s, with Dijkstra’s essay “Goto Considered Harmful.”

The bug statements you see in Choice of Magics are way better than trying to catch the more subtle bugs that result from not seeing the control flow clearly. Incidentally, Choice of Robots also got rid of gotos in its dialect; I just didn’t try to merge my changes with the main branch for Choice of Robots. I don’t think I could have maintained my sanity on any of those games if I was interrupting myself every few seconds for another goto or label, and a proliferation of gotos would have increased bugs.

If you don’t have a very branchy game, it probably doesn’t matter what you do. But if you do, I think 9 out of 10 programmers would agree that goto to get out of if/else is nuts, although the tenth programmer is Dan.