-
Notifications
You must be signed in to change notification settings - Fork 10
Declarations
World and global variables can be declared inside a script, a function, or any other block statement.
void add_kill() {
global int 1:kills;
++kills;
}
--
length()
returns the dimension length of the array.
int a[ 10 ];
int b[ 20 ][ 30 ];
script 1 open {
Print( d: a.length() ); // Output: 10
Print( d: b.length() ); // Output: 20
Print( d: b[ 0 ].length() ); // Output: 30
}
--
You can specify the size of a dimension of world and global arrays. World and global arrays can be multidimensional.
script 1 open {
global int 1:array[ 10 ];
global int 2:multi_array[ 10 ][ 20 ];
array[ 0 ] = 123;
multi_array[ 0 ][ 1 ] = 321;
}
--
When declaring an array, the length of a dimension can be omitted. The dimension length will be the number of values in the brace initializer. So if an array is initialized with 5 values, the length of the dimension is 5.
// Same as: str names[ 5 ];
str names[] = {
"Positron",
"Hypnotoad",
"AC3",
"Frank",
""
};
The dimension length can also be omitted for multi-dimensional arrays. The brace initializer with the most values determines the length of the dimension.
// Same as: int numbers[ 3 ][ 4 ];
int numbers[][] = {
{ 1, 2, 3 },
{ 4, 5, 6, 7 },
{ 8, 9 }
};
script "test" open {
Print( d: numbers.length() ); // Output: 3
Print( d: numbers[ 0 ].length() ); // Output: 4
}
--
An array can be initialized with a string. Each character of the string, including the NUL character, initializes an element of the array. If the dimension length is omitted, the dimension length will be the length of the string, plus 1 for the NUL character. The array must be one-dimensional and have either int
or raw
element type.
int letters[] = "abc";
script 1 open {
Print( d: letters.length() ); // Output: 4 (Includes NUL character)
Print( c: letters[ 0 ] ); // Output: a
Print( c: letters[ 1 ] ); // Output: b
Print( c: letters[ 2 ] ); // Output: c
}
--
An object outside of a script (or function) can be used before it is declared; the location of the object within the source file doesn't matter. In this example, a variable, a constant, and a function are used before they appear:
script 1 open {
v = c;
f(); // Output: 123
}
int v = 0;
enum c = 123;
void f() { Print( i: v ); }
An enum
is used to create a group of constants.
enum {
CONSTANT_A, // 0
CONSTANT_B, // 1
CONSTANT_C // 2
};
The first constant has a value of 0, the next constant has a value of 1, and so on. The value increases by 1.
enum {
CONSTANT_A, // 0
CONSTANT_B = 10, // 10
CONSTANT_C // 11
};
The value of a constant can be changed. The next value will increase starting from the new value.
enum CONSTANT_LONESOME = 123;
A single constant can also be created. This is similar to using #define
.
The last constant can have a comma after it. This is a convenience feature.
enum {
CONSTANT_A,
CONSTANT_B,
CONSTANT_C, // Comma here is allowed.
};
An enum
can appear in a script. The constants are only visible inside the script. An enum
can also appear in a function, and in other block statements.
script 1 open {
enum { CONSTANT_A, CONSTANT_B, CONSTANT_C };
enum CONSTANT_LONESOME = 123;
// Constants can be used here...
}
// ...but not here.
A structure is a group of data. It has a name and a list of members. The members are the actual data. In code, the struct
keyword is used to represent a structure:
struct boss {
int id;
str name;
};
Here, the structure is named boss
. It contains two members: an integer named id
and a string named name
.
--
A structure is used as a variable type. When a variable of a structure type is created, the variable will contain every member of the structure. If multiple variables of the same structure type are created, each variable will have its own copy of the members.
struct boss big_boss;
In the example above, we create a variable named big_boss
. The type of this variable is struct boss
, the structure we made earlier. When specifying the type, notice we use the struct
keyword plus the name of the structure we want to use.
--
The dot operator is used to access a member. A member can be modified like any other variable.
struct boss big_boss;
script 1 open {
// Modify members:
big_boss.id = 123;
big_boss.name = "Really Mean Boss";
// View members:
Print( s: "Boss ID is ", i: big_boss.id ); // Output: Boss ID is 123
Print( s: "Boss name is ", s: big_boss.name ); // Output: Boss name is Really Mean Boss
}
In the example above, we use the dot operator to access the id
member and change its value to 123. We do the same for the name
member, changing its value to "Really Mean Boss"
. We then print the values of the members, using the dot operator to access each member.
--
To initialize a variable of a structure type, the brace initializer is used. The first value in the initializer will be the starting value of the first member, the second value will be the starting value of the second member, and so on.
struct boss big_boss = { 123, "Really Mean Boss" };
script 1 open {
// View members:
Print( s: "Boss ID is ", i: big_boss.id ); // Output: Boss ID is 123
Print( s: "Boss name is ", s: big_boss.name ); // Output: Boss name is Really Mean Boss
}
The example above and the example in the previous section are similar. The difference is how the members get their values. In the example above, we assign the values of the members when we create the variable. In the example in the previous section, we first create the variable, and later assign the values.
--
A member can be an array or a structure, or both.
struct boss_list {
struct boss bosses[ 10 ];
int count;
};
// `list` initialized with a single boss.
struct boss_list list = {
{ { 123, "Really Mean Boss" } },
1
};
script 1 open {
// Add second boss:
list.bosses[ 1 ].id = 321;
list.bosses[ 1 ].name = "Spooky Boss";
++list.count;
}
In the example above, we create a structure named boss_list
. This structure has a member named bosses
that is an array, and this array can hold 10 boss
elements. The next member is an integer member named count
, the number of bosses.
We create a variable named list
using this new structure. The outermost braces initialize the list
variable. Th middle braces initialize the bosses
member, an array. The innermost braces initialize the first element of the array, a boss
structure.
Note: This section needs redoing.
In bcc, names of objects follow scoping rules.
A scope is a set of names, each name referring to some object—a variable say. The same name can be used to refer to some other object—such as a constant—as long as it's not in the same scope. Anywhere in your code, some scope is active. When you create a variable, say, the name of the variable is placed in the active scope.
A scope is commonly created by a code block, the statement delimited by braces ({}). At the start of a code block, a new scope is created. This new scope is now the active scope. The previous scope is still there, but is now the parent of the new scope. At the end of the code block, the active scope is destroyed, and the parent scope becomes the active scope again.
When using a name, the compiler will first search the active scope. If the name is not found, the parent scope is then searched. This continues until the top scope is reached. (The top scope is the first scope made and the last scope searched. It is the scope containing objects like scripts and functions.) Through this process, the first instance of the name found is the instance that will be used to retrieve an object.
#include "zcommon.acs"// In scope #0 (top scope) int a = 0;
script 1 open { // In scope #1 Print( i: a ); int a = 1; { // In scope #2 int a = 2; Print( i: a ); } Print( i: a ); }
0 2 1