This document contains a brief introduction into the scripting language as implemented so far. See PCC2 Quick Documentation for documentation about PCC2 as a whole.
Like PCC 1.x, PCC2 now contains a script interpreter. The script interpreter understands a simple programming language remotely based upon newer BASIC dialects, and extended to be useful in a VGAP context.
The scripting language is intended to be mostly identical to the PCC 1.x language. However, the underlying implementation is completely different (and, as I hope, more logical and consistent).
As of beta 8, PCC2 is able to evaluate expressions. You can therefore use the search function, the console ("calculator"), and unit labels. Execution of commands and scripts (canned command sequences) is scheduled for beta 9. Auto tasks are scheduled for beta 10.
! | This document is still incomplete.
In particular, it is missing the description of object properties.
You can refer to the PCC 1.x scripting manual for those.
However, please be aware that it is not yet 100% implemented yet.
Use the console to try out expressions if in doubt. Remarks about future features of PCC2 have been formatted in this style. |
Names identify things. Many programming languages therefore call them identifiers. A name can contain letters, digits, and the special characters "." (dot), "$" (dollar), and "_" (underscore); it may not start with a digit or dot, and may not end with a dot, though. PCC2 predefines many names you can use in various ways. Those are called properties (properties of objects, such as the name of a ship) and functions. Future versions of PCC2 will also allow you to define your own names, variables and subroutines.
The meaning of a name depends on the current context. For example, the word Mission can stand for the mission of a ship or for the mission of a starbase, which are governed by completely different rules. However, names have been chosen in such a way that similar things are represented by similar names. For example, you can use Name="Ares" to search for ships and planets having that name, and Owner$=7 searches for everything owned by player 7.
The current context is determined by the place you're invoking a script from. For example, a planet label expression is always evaluated in the context of the planet.
Contexts stack. You can temporarily open another context. For example, using the Find function to find a ship, as in Find(Ship, Name="Ares", Id), will evaluate the test and return expressions (second and third parameter) in ship context. However, names not found in that context will be looked up in the previous contexts.
There are important exceptions to these rules. For example, in Sin(30), Sin always means the sine function, no matter what context is active. Those exceptions are:
Property names follow some simple guidelines that aim to help you memorize properties.
The shortest name always gives a nice human-readable summary of an item. For example, Mission yields a ship's mission in text form ("Tow a ship"). By adding more words, you can ask for details. For example, Mission.Tow yields the "Tow" parameter of the mission. Alternatively, adding a dollar sign gives the internal representation. For example, Mission$ yields the mission number (7).
For programming, writing search queries, etc., you will probably use the "$" forms most often. For formatting text, you will most likely use the short standard form.
All names, values and expressions have a type. The type defines what you can do with the thing. PCC2 internally tracks these types. If you use a value in a way its type does not allow, PCC2 will show you an appropriate error message. The following types exist:
A very special value is Empty. This value is used for unknown values. For example, when you don't own a ship, it will yield Empty for its Cargo.N (fuel amount). As a general rule, an operation will yield Empty if one of their operands are Empty, but exceptions exist. In a boolean context, Empty counts as False.
Expressions compute values. They do so by combining elementary values (literals, properties, variables) using operators and functions. The following sections describe expressions in an informal style. For people who prefer it, there's a formal grammar at the end.
Decimal numbers can be used to specify integers or real numbers. The "." is used as the decimal point. A number is integer if it fits into a 32-bit integer number, otherwise it's treated as real.
Strings can be specified in two ways:
Special values are Pi (=3.14159265..., circumference/diameter ratio of a circle), True and False.
Most operations return Empty when one of their arguments is Empty. Operations taking more than one argument usually evaluate them all, even if the result would be known after evaluating only some. Exceptions are explicitly specified.
String operations are case-insensitive by default. That is, "A" compare equal to "a". To get case-sensitive operations, use the StrCase() function.
Some operations taking numerical operands only work with integers. When doing arithmetic, PCC2 keeps track of which values are integers and which are fractions. Arithmetic operators and "+", "-", "*" yield integers when their operands are integers, others like "/" may generate fractions even when used on integers.
The following table shows all operators supported by PCC2. Operators have a certain precedence or binding strength, which determines which parts of the expression belong to that operator. For example, in 2 + 3 * 4, the precedence of * is higher than the precedence of +, so the multiplication is performed first. The addition then adds 2 and the result of 3 * 4. The table shows operators in increasing order of precedence, i.e. later operators are evaluated before those shown first.
a; b | Sequence: evaluate a, discard its result, then evaluate b. |
a := b | Assignment: evaluate b, and assign it to a. Returns b. |
a Or b | Logical Or: return True if either operand is True. If the result is known after evaluating a, does not evaluate b (short-circuit evaluation). |
a Xor b | Logical Exclusive-Or: return True if one operand is True and one is False. If the result is known after evaluating a, does not evaluate b (short-circuit evaluation). |
a And b | Logical And: return False if either operand is False. If the result is known after evaluating a, does not evaluate b (short-circuit evaluation). |
Not a | Logical Not: return True if, False if operand is True. |
a = b | Comparison: return True if a is identical to b. |
a <> b | Comparison: return True if a is different from b. |
a < b | Comparison: return True if a is less than b. |
a > b | Comparison: return True if a is greater than b. |
a <= b | Comparison: return True if a less or equal to b. |
a >= b | Comparison: return True if a is greater or equal to b. |
a # b | Concatenation: convert a and b to strings and concatenate them. |
a & b | Concatenation: convert a and b to strings and concatenate them. If either is Empty but the other is not, treat the Empty one as empty string. |
a + b | Addition: add a and b, which may be numbers or strings. |
a - b | Subtraction: subtract b from a, which must both be numbers. |
a * b | Multiplication: multiply a and b, which must both be numbers. |
a / | Division: divide a by b, which must both be numbers. |
a \ b | Integer division: divide a by b, which must both be integers, and discard the remainder. |
a Mod b | Integer remainder: divide a by b and return the remainder. Both operands must be integers. |
-a | Negation: change sign of a, which must be a number. |
+a | Unary plus: do not change sign of a, which must be a number. Exists for symmetry with "-". |
a ^ b | Power: compute a-to-the-bth. Both operands must be numbers. |
Elementary functions are recognized whenever their name is followed by a parenthesized expression list. Elementary functions thus bypass normal name-lookup.
Most functions are regular, that is, they evaluate all their arguments, and yield Empty if an argument is Empty. Functions that do not follow these rules are marked as irregular.
Most functions expect their parameters of a particular type. In the descriptions, this is denoted by ":type" behind their name: Int=integer, Num=any numerical value, Str=string.
Those items are found by regular name lookup. If you define a local variable named identical to one of these (this is not possible in beta 7, but will be possible in later versions), using that name will find the local variable.
All items that are documented as func(...).prop are actually arrays that can also be used with the Find function, as Find(func, ...).
sequence: assignment sequence ";" assignment assignment: or-expr assignment ":=" or-expr or-expr: and-expr or-expr "Or" and-expr or-expr "Xor" and-expr and-expr: not-expr and-expr "And" not-expr not-expr: comparison "Not" not-expr comparison: concat-expr comparison "=" concat-expr comparison "<" concat-expr comparison ">" concat-expr comparison "<=" concat-expr comparison ">=" concat-expr comparison "<>" concat-expr concat-expr: add-expr concat-expr "#" add-expr concat-expr "&" add-expr add-expr: mult-expr add-expr "+" mult-expr add-expr "-" mult-expr mult-expr: neg-expr mult-expr "*" neg-expr mult-expr "/" neg-expr mult-expr "\" neg-expr mult-expr "Mod" neg-expr neg-expr: pow-expr "-" neg-expr "+" neg-expr pow-expr: primary-expr primary-expr "^" neg-expr primary-expr: "(" sequence ")" string-literal integer-literal float-literal "True" "False" "Pi" identifier invocation* invocation: "(" arguments ")" "." identifier arguments: nothing sequence ("," sequence)* identifier: sequence of letters, "$", "_", digits, ".", not starting with a digit or period not ending with a period string-literal: "'" (any character except for "'")* "'" """ (any character except for """ and "\", or "\" followed by any character) """ integer-literal, float-literal: digit digit* digit digit* "." digit* "." digit digit* A value is an integer if it has no decimal point and fits into 32-bit range. Otherwise, it's float.