Important ChoiceScript Commands and Techniques

A guide of important techniques in the ChoiceScript programming language. Please post on the ChoiceScript forum if you have questions about this document.

Don’t Start Here!

Be sure to read our basic ChoiceScript Introduction page before reading these techniques.

Other Important Commands

  • *title: This command sets the title of the game. It must be used at the top of startup.txt, along with *create and *scene_list.

      *title Choice of the Dragon

    The Google Play Store for Android puts a limit of 30 characters on game titles. ChoiceScript will allow a title of any length, but if you’re planning to publish your game with us, you’ll need to come up with a name for your game that’s 30 characters or less, including spaces.

  • *author: This command sets the author “by line” of the game. It must be used at the top of startup.txt, along with *create, *title, and *scene_list.

      *author Dan Fabulich and Adam Strong-Morse
  • *temp: This command is very much like *create but it creates a temporary variable that only exists in the current file. Unlike *create, you can use *temp anywhere, and you’re not required to specify a starting value for a *temp variable.

      *temp conversation
      *set conversation "a little less"
      *temp action "a little more"
  • *comment: This command does nothing; any text you put after *comment will be ignored. It’s helpful to put remarks in the text that only the author should read.

      *comment TODO We should make this scene more interesting!
  • *page_break: Put in a “Next” button with no radio buttons. The game will continue on the subsequent page.

      You turn the corner slowly.  Blood rushes through your ears.  As you open the door...
      *page_break
      ... the masked murderer attacks!
  • *input_text: Provides a text box for the user to specify the value of a variable, e.g. the user’s name.
      Please enter your name.
      *input_text name
     
      Your name is ${name}, is that right?

    ChoiceScript won’t allow the player to leave the input blank. If you want to allow that, you can use:

      *input_text name allow_blank
  • *fake_choice: This convenience command behaves exactly like *choice, but no commands are allowed in the body of the choice; thus no *goto/*finish is required.

      What color do you prefer?
     
      *fake_choice
        #Red
          Red is the color of roses.
        #Blue
          Blue is the color of the sea.
        #Green
          Green is the color of spring.
     
      What an excellent choice!  And what flavor of ice cream would you like?
     
      *fake_choice
        #Vanilla
        #Chocolate
        #Strawberry
     
      Mmm, delicious!
      *finish

Percentile Stats and Fairmath

Stats that display on the stat screen usually range from 0 to 100. It can be difficult to guarantee that the player can never accidentally gains more than 100 points of leadership. To help with this, we’ve provided special commands that will keep stats in between 0 and 100.

*set leadership %+20
*set strength %-10

The “%+” and “%-” operators are called the “fairmath” operators. The idea is that as your leadership score gets higher, it becomes harder to increase, and easier to decrease. According to fairmath:

  • Fair Addition: (x %+ y) = (x + (100-x)*(y/100))
    • Large scores are hard to increase: (90 %+ 20) = (90 + 2) = 92
    • Small scores are easy to increase: (10 %+ 20) = (10 + 18) = 28
  • Fair Subtraction: (x %- y) = (x - x*(y/100))
    • Large scores are easy to decrease: (90 %- 20) = (90 - 18) = 72
    • Small scores are hard to decrease: (10 %- 20) = (10 - 2) = 8
  • 50 is equally easy to increase or decrease.
    • (50 %+ 20) = (50 + 10) = 60
    • (50 %- 20) = (50 - 10) = 40

We recommend that you always/only use Fairmath to update percentages. If you’re having trouble deciding how many points to allocate using Fairmath, here are some guidelines:

  • On average, Fairmath has half the effect of simple addition. So, for example, %+ 20 usually only gives the player about 10 more points.
  • If you want to give a small bump, make it %+10. If you want a large boost, make it %+40.
  • A player with a skill of 50% has average ability.
  • A skill of 60% is good; 70% is excellent.
  • 80% skill is almost impossible.

Types of *if Statements

You can do a lot more with *if statements than leadership > 15. Here’s a few tricks:

  • Equality and Inequality
    • Equal to: leadership = 40 (Is leadership equal to forty?)
    • Not equal to: leadership != 40 (Is leadership different from forty?)
    • Greater than: leadership >40 (Is leadership greater than forty?)
    • Less than: leadership <40 (Is leadership less than forty?)
    • Greater than OR equal to: leadership >=50 (Is leadership greater than or equal to fifty?)
    • Less than OR equal to: leadership <=40 (Is leadership less than or equal to forty?)
  • And/or/not (with mandatory parentheses)
    • And: (leadership > 30) and (strength > 40)
    • Or: (leadership > 60) or (strength > 70)
    • Not: not(strength > 70)
    • Complex parentheses: ((leadership > 60) and (agility > 20)) or (strength > 80)
  • Comparing text:
    • lover_name = "Jamie"
    • "2" = 2 (this is true!)
  • Setting variables to true or false:
    • *set finished false
    • *set correct guess = "blue"

Multireplace with @{}

Multireplace is a little bit like ${} replacement, but you give it a variable and a list of options. The variable must be either a number or true/false (true=1, false=2). @{} will insert the option corresponding to the number.

There @{count is one thing|are two things|are three things} here.
You are on the @{is_evil Dark|Light} Side of the Force.
Behold the dragon@{plural s|}!
Behold the dragon@{(dragons > 1) s|}!
Behold the dragon@{(dragons = 1) |s}!

The first word should be a variable name, followed by a space, and then a number of options separated by vertical pipes |. Empty options are allowed. You can also use more complex expressions by wrapping them in parentheses.

Note that the first option is numbered #1. If you want the first option to be zero, add 1 to the variable in parentheses, like this:

There @{(count+1) are no things|is one thing|are two things} here.

You can nest ${} replacements in @{} but you can’t nest @{} inside another @{}.

Conditional Options

Sometimes we want to show players that a choice is not available to them. We can do that like this:

  How will you handle this?
  *choice
    #Try to talk them out of it.
      They cannot be dissuaded.
      *finish
    #Force them to relent.
      They back down, for now.
      *finish
    *selectable_if (president) #Abuse my presidential powers to silence them
      This works; you will never hear from them again.
      *finish

If you aren’t president, you’ll see the option to abuse presidential power, but it will appear in grey; it won’t highlight if you click on it. This gives players a hint that if they play the game again, they might be able to choose that option, by making different choices earlier on.

If we want to hide the option altogether, we can use *if instead of *selectable_if, like this:

  How will you handle this?
  *choice
    #Try to talk them out of it.
      They cannot be dissuaded.
      *finish
    #Force them to relent.
      They back down, for now.
      *finish
    *if (president) #Abuse my presidential powers to silence them
      This works; you will never hear from them again.
      *finish

In this example, if you aren’t president, you won’t even see an option to abuse presidential power.

Sometimes we just want to revent certain options from being reused. We can do that with the *hide_reuse and *disable_reuse modifiers, like this:

  *label start
  *choice
    *hide_reuse #One.
      The loneliest number that you'll ever do.
      *goto start
    *disable_reuse #Two.
      Two can be as bad as one.
      *goto start
    #I can't decide!
      Well, think it over.
      *goto start
    #Done.
      OK!
      *finish

If the player selects #One, the option will be hidden; if the player selects #Two, the option will be unselectable (greyed out).

Automated Tests

Multiple-choice games written in ChoiceScript can be very hard to test, because each *choice point can create new variations of the game that need testing. When testing by hand, it can be hard to be certain whether some path of choices can cause the game to crash, or whether some important part of the story can’t be reached at all.

To help with this, we’ve developed two tools that can make debugging ChoiceScript games considerably easier.

  • Randomtest: The Randomtest tool automatically plays your game over and over, making random decisions for every choice, and generates a “hit count” report, which tells you how many times each line of code was used in random play.
  • Quicktest: Instead of running the code at random, Quicktest attempts to test every #option in every *choice, and both sides of every *if statement. In order to do this quickly, Quicktest “cheats” by skipping lines that it has already tested.

More information is available in our automated testing guide.

Next: Advanced Tricks

Questions?

Please post on the ChoiceScript forum if you have questions about this document.