CubeScript Tutorial: Part 1 — An Introduction

This is the first installment of a multi-part series I’m doing on CubeScript. As the title suggests, I’m starting with a relatively abstract introduction.

What is CubeScript?

CubeScript is the console language of Cube-based games; it is used to write scripts that can be executed in-game. Scripts written in CubeScript can be anywhere from a single line to hundreds of lines in length (I’ve never seen thousands, but I guess that’s theoretically possible too :P).

While CubeScript shares many features with conventional programming languages, it has significant differences too. For example, one central focus of CubeScript is easy GUI design, a topic that will likely be covered in a later post.

Basics

A CubeScript script is basically just a series of syntactically valid statements. A statement will generally be either the invocation of a command or an assignment to a variable. For example, if you’ve ever executed the following in the console:

fov 90

then you’ve used CubeScript; that’s a simple command. Command invocations follow a format wherein the command name is followed by the space-separated arguments to the command. fov, for example, takes just one argument. A command like bind, on the other hand, takes two: the key to bind, and the action to perform whenever that key is pushed.

Assignments are fairly straightforward too, especially if you’re familiar with conventional programming languages, as the format is largely the same. For example, if we want to store the value 42 in a variable x, we would simply do:

x = 42

In the old days of CubeScript, assignment itself was actually done via the command alias! There is little reason to use alias over = now, but it’s good to know in case you see it used in older scripts.

I should also mention that CubeScript scripts are typically placed in either autoexec.cfg (in your Sauerbraten folder) or in their own cfg file alongside autoexec.cfg, whereupon they can be executed with the command exec file.cfg from autoexec.cfg. For larger scripts spanning multiple files, it is also possible to package the files in their own folder and use something like exec folder/file.cfg.

Finally, CubeScript also supports comments, with a syntax similar to that of C/C++/Java:

// this is a comment

Note that /* */-comments are not supported.

Operators

Now that we’ve covered what a CubeScript script actually is, we can go on to talk about more complicated things you can do in one. The first thing to go over is operators such as +, -, *, / etc. Now, it is important to note here that CubeScript uses polish/prefix notation, like Lisp, if you’re familiar with that family of languages. Therefore, something like 2 + 3 would, in CubeScript, be expressed as (+ 2 3). (This is basically a result of the fact that operators such as + are just commands themselves, so they follow the same syntax as commands, but you probably don’t need to worry too much about that.) So, returning to our x variable, let’s say we want to assign to x the sum of 2 and 3, we’d simply do this:

x = (+ 2 3)

If you want to represent a more complicated expression like (2 + 3) * 4, you have to do some nesting of the parenthesis:

x = (* (+ 2 3) 4)

The inner (+ 2 3) is evaluated first, and its result is then multiplied by 4.

Polish notation might take some getting used to at first, but once you get the hang of it, it’s really quite easy.

Next, we have to be able to access the values we’ve assigned to variables. This is done simply by prefixing the variable name with a $. For example:

x = (+ 2 3)
echo $x

would echo “5”. Of course, values of variables can be used in expressions being assigned to said variables. For instance, to increment x by one:

x = (+ $x 1)

A more exhaustive list of operators can be found in the official documentation here, but they all work in essentially the same way.

Basic Control Flow

As with most other languages, CubeScript supports some basic control flow constructs such as if-else statements and loops.

In CubeScript, if-else statement follow this syntax:

if <condition> [ <if body> ] [ <else body> ]

For instance:

if (= $x 42) [
    echo "x is 42!"
] [
    echo "x is not 42!"
]

The snippet above will echo “x is 42!” if x is indeed 42, and will echo “x is not 42!” otherwise. Note that the else-portion is optional: if <condition> [ <if body> ] is valid by itself:

if (= $x 42) [
    echo "x is 42!"
]

Let’s move on to loops. The two most basic types of loops in CubeScript are associated with the commands while and loop. while should seem familiar if you’ve programmed in any conventional language before. It has a syntax of

while [ <condition> ] [ <body> ]

and will repeatedly execute <body> so long as <condition> is “true” (i.e. not zero). I’ll reuse the example used in the official docs for while, because I think it’s a pretty good one:

 i = 0
 while [ (< $i 10) ] [ echo $i; i = (+ $i 1) ]
  • First, i = 0 simply assigns the variable i to zero, as we know.
  • The condition (< $i 10) returns 1 (“true”) if the value in i is less than 10, and returns 0 (“false”) otherwise.
  • The loop body does two things (the two statements composing the body are separated by a semicolon):
    • echo $i just echoes the value of i.
    • i = (+ $i 1) increments the value of i (just like the example with x above).

So, in plain English, we can translate this snippet as “set i to 0; while i is less than 10, echo i and increment it”. It shouldn’t be too hard to see now that all we will be doing here is echoing the integers from 0 up to 9.

The next kind of loop is, well, loop, and it has this syntax: loop <var> <N> [ <body> ]. In this case, var is the name of some variable, and N is a non-negative integer. loop will set var to 0, then execute body N times, and each time it will increment var (meaning var will take on the values from 0 to N-1). Again I’ll use the example from the docs:

loop i 10 [ echo $i ]

This actually does the same thing as the while snippet above: it just echoes the integers from 0 to 9 inclusive.

There are a few other loop constructs for looping over lists and strings. I’ll cover these in a future post.

Conclusion

This has been a very brief and, in many ways, high-level introduction to the wonderful world of CubeScript. I’ll apologize in advance to those of you who were already familiar with all this, but for those who were not, I hope you got something out of this overview, and that you’re now better prepared to delve into more complex topics in future posts.

In the near future, I’m planning to go over functions (i.e. the inner workings of [ ] blocks), strings, lists, and GUI design. Let me know if I left anything out, and thanks for reading!

10 thoughts to “CubeScript Tutorial: Part 1 — An Introduction”

    1. Boom, u comment is at least as useful as the main post, ty.
      P.S. Main post is very good 2 – ty 2 professor Chaos ;D.

  1. Very nice tutorial, although I think it should be rather in the “tips and tricks” section, so it won’t disappear soon enough (and keep this post an announcement).

  2. Thank you. It is well understood, now I have many more things clear, I think I have difficulties because only know in detail the “pseudocode”

    You can give one or two more examples of “loop”

    echo = “print” (only do that?)

    1. Example of another loop: countto9 = [loop i 10 [sleep (* @i 100) [echo @i]]]

      “You can give one or two more examples of “loop”” – I’m not sure if this was a ‘Can you give’ question, or a ‘You can add to tutorial’ comment. But, there’s another loop example anyways.

      (raffael: fixed)

      1. -missed a bracket at the end of the loop. There should be 3, not 2.

        An edit comment button would be nice. (or is there one and I’m just too blind to see it?)

  3. Thanks a lot for this!!!
    I hope so much that this engine will get more used, because it is so brilliantly fast!
    Tutorials like this help a lot to attract modders and alike.

Leave a Reply

Your email address will not be published. Required fields are marked *