Best practice -- *choice vs *fake_choice

I’m working on my first full-length project and I’ve found that I’m using *fake_choice a lot more than *choice, mostly to set variables and obtain user input in cases where I want to bring up the same line after each choice and continue the story in a similar way. Being forced to use a *goto or *finish/*ending in the choices seems too restrictive in a lot of cases. The wiki urges being judicious with *fake_choice (which I understand, choices should feel meaningful) but I just wanted to make sure I wasn’t violating some unwritten-but-important rule by using a split of less *choice and more *fake_choice.

Thanks!

2 Likes

I think the addition of implicit control flow actually removes the need to use a *goto or *finish, which might help you if you’re using *fake_choice just to get around that limitation. Additionally, I think there are limitations in nesting *fake_choices that aren’t present when you use *choice, so that’s also something to consider.

5 Likes

If a choice still leads to the same place I use *fake_choice especially as a lot of the choices like that still offer different text but at the same time they still end up in the same place.

Picking up a weapon off a table no matter which one you pick you still will leave the room so a choice like that a fake_choice would work fine there.

2 Likes

ICF can cause all sorts of other troubles, though. It can’t tell the difference between an intentionally missing *goto and a missed one. And that stuff can be bloody hard to find.

3 Likes

I think in the end it’s completely up to you and how you work best. There are no (unwritten) rules or etiquettes on how to distrebute commands as long as the result makes sense and is what you want to archive.
I have seen people use *choice for everything and I have seen people almost exclusively using *fake_choice. Both extremes ended up with amazing wips/games, so it really doesn’t matter too much imo
Both commands have their advantages and disadvantages, so see what works best for you and happy coding! :grin:
(I personally use *fake_choice more too, unless there are consequences that wouldn’t lead back to the ‘common path’ after a long time, so I might be a tad biased :wink: )

2 Likes

The term “fake” choice irritates me to no end :angry: precisely because the user IS making a choice, and those choices can be extremely meaningful to the narrative. But since it’s a command baked into CS, there’s no way to rename it… GRR

As for how often you use “fake” choice versus “real” choice, that is completely up to you. The player/user can’t see the difference - all they care about is how fun your story is!

2 Likes

Code-wise, if I understand your flow, there’s no difference between *choice or the other one. As EC mentioned, the new modifier *create implicit_control_flow true eliminates the need of any *gos at the end of a *choice block, practically turning *choice to no different than *fake_choice. The only edge-case exception you might want to be aware of is the use of conditional checks inside a choice body as there’re several known quirks on 'em.

*choice
   *if A
      #Option A
         text
   *if (B) # Option B
      text
1 Like

I used to use a lot of *fake_choices until I learned about implicit control flow. Since I have some programming background I don’t find it difficult at all—that’s basically how 99% of programming languages work anyway.

If a choice leads to a different piece of text than I include the *goto command right away, or at least a TODO tag so I remember to go back.


Yeah, I’m also picky like that, but what’s done is done. I think *flavour_choice would be a better name.

Here @jasonstevanhill makes a distinction between Fake Choice and Flavour Choice.
But honestly, it sounds like word juggling to me. :grimacing:

A Fake Choice is one that has no mechanical effect upon the game. (…), a well-done Fake Choice establishes character but does so in the mind of the reader, not in the internal logic of the game.

(…)

A Flavor Choice has no effect on Primary or Secondary Variables—on “winning” or “losing” the game—but instead customizes the narrative to the reader’s desires. Classic examples of this are choices like “what’s your name?” “what’s your gender?” or “what’s your sexual orientation?”

Taxonomy notwithstanding, both are produced by using the *fake_choice command.

However, I do agree that’s a poor choice (get it? choice? :wink:) of nomenclature, since I’m guessing most of *fake_choices are in fact Flavour Choices.

2 Likes

Both can be. But if I’ve understood rightly, the original intent of *fake_choice was to only be for the first kind. Flavor choices still require setting variables, and the original CoGs used *choice for that.

But the desire to skip *gotos all the time led to an ever-broadening use of *fake_choice, until it became a total misnomer. Any writer who uses it for Flavor Choices has no reason not to use it to set primary or secondary variables as well.

5 Likes

I was just quoting the article, where Jason states both are produced using *fake_choice.

A Fake Choice and a *fake_choice aren’t necessarily the same thing, though they can be.

(…)

A variant on the Fake Choice is the Flavor Choice .

I don’t know anything about the original intent or whatnot.


But you’re right in saying they can be. You could make fake and flavour choices with the *choice command as well. The only difference is that (without implicit control flow turned on) you’d have to add a *goto at the end of every *choice body, even if all options lead to the following block of text.

My take on it is that *fake_choice was labelled so because of two things:

1 - Apparently before you couldn’t use any command inside *fake_choices (I’m unsure if it was actually this way at any point) so for this reason they were always “fake” because they didn’t do anything.

2 - It was assumed that previously the actual “difference” or “branching” was only possible if a *goto was used since only by going to another place of the code would the user experience any sort of changes in their gameplay. It didn’t take into consideration that these *fake_choices could set stats, have other choices inside them, gosubs, or even that some *fake_choice options could have *gotos while others didn’t. Use of these could provide “difference” or “branching” in other ways so they are still choices at the end of the day.

Another difference I remember is that there seems to be an issue if you nest *fake_choices inside another, while such a problem does not happen while using *choice, so that makes *choice more viable and consistent imo. If ICF is being used, then I’d say always use *choice and forget about *fake_choice.

I don’t even mind the *goto requirement at the end much, what really angers me is the need for *gotos at *elses. I studied some languages and frameworks and work with some daily but ChoiceScript is the only one that has this requirement or that uses *gotos at all, leading to an immense redundancy of unnecessary *labels and *gotos.

2 Likes

Amen to that. It took me a long time to figure out that *else at the bottom of a stack needed a *goto. Logically, it shouldn’t, but that’s how CS rolls… :roll_of_toilet_paper:

2 Likes

I mean, in the hands of someone who knows what they’re doing, I am fine with implicit control flow. I train my authors to use *fake_choice primarily, and to do as much clever nesting as they can for story branches rather than having a bunch of labels for routing. I consider *fake_choice best practice for more or less uncomplex narratives, and strongly prefer to see *fake_choice and *gosub wielded well for code efficiencies.

7 Likes

If you notice, there’s no *choice anywhere in that article. The “Establishing Choice” example also uses *fake_choice, and after that Jason stops typing in any commands at all.

It’s a good example of how the ChoiceScript command *fake_choice, whiich was originally the way to represent Fake Choices that set no variables, has turned into the default command for just about any kind of choice because of its greater convenience.

I’ve been waiting for years for Dan to deprecate *fake_choice because it’s become inaccurate and thus confusing. For a coding language whose main goal is helping non-programmers use it effectively (which is if I’ve understood rightly the reason for the abundance of *gotos) the non-fakeness of fake_choice seems like something worth changing…

Why not change *choice to do what *fake_choice does now, rather than train authors to use *fake_choice as much as possible?

4 Likes

If I’d take a shot at guessing, it’s because CS is promoted as “writer first, coder later.” *choice*goto and *fake_choice is much more human readable than *choice without *goto but *set implicit_control_flow true.

It’d be janky to teach newcomers of CS “Welcome! You can use *choice, but put this *goto, but you can not putting it by using ICF instead.”

1 Like

I think the current solution is enough. Newcomers can use *choice with *gotos and *labels. And as people get more comfortable they can switch to implicit control flow. Like bicycle training wheels.

That being said, I do understand the concern with non-coders, but I think it’s not really necessary. Anyone who has ever learned Python or Java or JavaScript or PHP or Kotlin or what-have-you had to get used to implicit control flow. Programmers are not a different species, they are not super genius people—at least not solely for the fact of learning a programming language—, and all of them had to get used to implicit control flow.

Although, it does lower the risk of errors for beginners, making sure every choice is explicitly redirected. So… :man_shrugging:

I’m not a fan, but I get why it’s there, and I’m grateful there’s an option for implicit control.

3 Likes

I tend to use fake_choice most of the time, but use choice for places where the narrative truly branches as a reminder for myself.

4 Likes

I disagree with this; if one can understand what *fake_choice does (code continuing down) then they can understand implicit_control_flow. It’s the same thing, there’s nothing “advanced” about it.

When I learned programming it was always like that; this wasn’t even an issue at all since there are a lot more other complex things in programming than “code continuing down”.

4 Likes

I know. It’s very easy to understand it even if you only ever scraped the surface of programming. However, many others are simply go “What? Coding? I’m out.” I’ve seen numbers of it happening in this forum.

*fake_choice might be an old thing, and *setref is also a proof that CS is unafraid of evolving. However, this one is a pretty finicky case where even Dan isn’t unsure if ICF is bug free and whether to have it on by default on that cost.


So, yeah. Maybe the wiki needs some massive revamps? :grimacing:

It was always optional to use; if the fact that they were there might scare newcomers then one might as well remove *gosubs, *params and arrays.