Arrays (ZScript)

From ZCWiki
Jump to: navigation, search

An array is a group of values of the same data type, such as a group of ten integers. The whole array has a single name, and the individual values in the array (called elements) are accessed by using an integer index. Arrays are useful because they allow you to store several items of related information in a convenient fashion, and it is relatively easy to step through all the elements in an array.

Syntax

Like other variables, arrays must be declared before they can be used. Declare an array as follows:

data-type name[max-elements];

data-type is one of the following types:

  • int - an integer.
  • float - a floating point number (a number with a decimal point).
  • bool - a boolean value which is either true or false.
  • npc - a pointer (a kind of reference) to a Non-playing Character (such as an enemy) on the screen.
  • ffc - a pointer to a freeform combo on the screen.
  • item - a pointer to an item on the screen.
  • lweapon - a pointer to an lweapon on the screen.
-->This compiles, but needs verification.
  • eweapon - a pointer to an eweapon on the screen.
-->This compiles, but needs verification.
  • itemdata - a pointer to an itemdata structure.
-->This compiles, but needs verification, and would most likely have limited, to no usefulness.

You can define the name to be any useful name, as long as it does not contain any illegal characters (spaces, characters used as operators, etc.). Underscores are legal characters.

max-elements is an integer specifying the maximum number of indices (elements) the array can hold. You may declare an array with a non-specific size, by manually setting each desired index (see below).

Declaration, Index Sizes

If you specify an index size, note that it must be a whole number, not a constant, or a calculation:

const int ARR_SIZE = 105; 
int myArray[ARR_SIZE];
// //You CANNOT do this. This syntax is not supported by ZScript. 
int myArray[100+5];
// //You CANNOT do this. This syntax is not supported by ZScript. 
int myArray[105];
// //This syntax IS CORRECT. 


The following example declares a 5-element array of integers named "myArray".

int myArray[5];

Declaration, Initialisation

Arrays declared, but not initialised will set each index position (i.e. element) at a value of '0' for numeric arrays, or false for Boolean arrays. The value stored in an uninitialised float index, is 0.0000.

You may opt to initialise arrays when you declare them, either fully, or in part. The format to initialise indices is as follows:

int myArray[5]={10,3,16,9,104};
float myArray[5]={10.6030,3.0000,16.0091,19.0000,104.0005};

Each index position is noted within curly braces, following an equals operator, separated by commas. Note that you do not use a trailing comma, after the last initialised index value.

Boolean arrays may be initialised with false/true values as follows:

bool myArray[5]={false,true,true,false,true};

If you initialise fewer indices than you declare, any uninitialised indices will contain either zero, or false data.

Example:

int myArray[10]={10,3,16,9,104};
// //Indices 5, through 0, will each have a value of zero 

If you are unsure what index size you will require, but you have enough information to populate a group of array indices, you may declare an array of a non-specific size, by leaving the space within the square braces empty. (Do not type a space, in-between the square braces.) An example of this, is as follows:

int myArray[]={10,3,16,9,104,201,90};
// //The array has seven initialised indices, and will be given a size of 7 during compilation.

You may read the size of any array in ZScript using the function SizeOfArray(). This will return an array size for an array without a declared size, that has initialised indices, equal to the total number of initialised indices; or will return the declared size of an array with a specific index size. SizeOfArray() does not return the size of Boolean arrays, and for this reason, it is advised to use int, or float arrays, and Automatic Typecasting to use these types, in place of Boolean declarations.

Index Numbering

Array index numbering begins at 0, and continues to (max-elements - 1 ). Thus, if you declare:

int myArray[512];

The first index of that array is myArray[0], and the last, is myArray[511].


Usage

You refer to the indices (i.e. elements) in an array by specifying the index of the element you wish to access. The index is enclosed in square braces. Note that the index starts at 0. In other words, the index of the 1st element in the array is 0, while the index of the last element in the array is 1 less than the array's size. For example, for an array "myArray" that holds 5 elements, the last element is myArray[4]. See the examples.

Take caution when using arrays of type npc, ffc, and item, as you'll need to do some extra initialization and checking. For instance, if you declare an array of type ffc, you still need to use the Screen->LoadFFC() method to point your array elements to the FFCs on the screen. Additionally, you may get unexpected results if you have an array of npcs, but the number of NPCs on the screen changes while your script is running (resulting in a reference to a non-existent NPC).

-->We need examples of using arrays with complex datatypes, for each datatype.

Examples

The following example declares a 5-element array of integers, and then sets each element to a value that is twice that element's index.

ffc script ArrayTest{
  void run(){
    int myArray[5];
    int index; 

    // Initialize all the elements
    // in the array.
    for(index=0; index<5; index++){
      myArray[index] = index * 2;
    }

    // Write the array values to
    // the logfile.
    for(index=0; index<5; index++){
      Trace(index);
      Trace(myArray[index]);
    }

  }
}

Strings, String Arrays

Arrays are also used to store Strings, whereby a string contains a number of indices equal to the number of characters in the string, plus one (for NULL). Strings are declared as int datatypes. Other value types (e.g. float may compile, but serve no useful purpose, as the value in each index will always be an integer.

The format for strings, differs slightly to other arrays, if declaring one with ASCII characters. In place of curly braces, text strings are placed between t a paid of double-quote marks, as follows:

int myArray[]="This is an ASCII string";

This will automatically be converted into an array, with each individual character converted into its ASCII value, occupying one index position of that array. For this reason, it is important to remember that a string always ends with an identifying NULL character (ASCII: 0) to denote string termination. it is possible to store multiple strings in one, larger array, and to manipulate them with the functions provided by String.zh.

Comprehending Char to Int

Each index in a string, contains a numeric value equivalent of one ASCII_Map, such as in the following example:

int string[]="Is a string.";
// //In this case, we do not declare a field value, and the size of the 
// //string itself sets this, when initialised. 

This is the same as:

int string[13]="Is a string.";
// //This sets an implicit index size, equal to the number of chars, plus null.


int string[255]="Is a string.";
// //The same as above, except that we now have 255 indices, so we may replace 
// //the data in this string, with a longer string. 
// //This renders down to each of the following, respectively:
int string[]={73,115,32,97,32,115,116,114,105,110,103,46,0};
int string[13]={73,115,32,97,32,115,116,114,105,110,103,46,0};
int string[255]={73,115,32,97,32,115,116,114,105,110,103,46,0}; //The remaining fields will all be '0'.


Making a Buffer[]

Often, you will find it useful to have a buffer, to which you can copy string datum, modify it, and transfer it elsewhere; or copy it back, after modification. To do this, declare a string with an implicit size, and the string contents as: " " .

Example:

int string[20]=" ";
// //Creates a buffer, with a size of '20'. Note that you may use 19 chars in it, as the last index must be NULL 


Allocation

An array remains in use, and available, as long as the script that allocated it, or the scope at which it was originally declared, is in use. Thus, the pointer to a local array is valid, and available to any other script, ignoring some aspects of scope, until the script that created it exits.

An array is freed when the scope in which it was declared is exited or when the script that declared it stops running. Only leaving the scope or quitting the script, will remove its pointer. There's nothing like malloc or free, available in ZScript.

Quirks of Scope

If you reference an array using a local function, by allowing the pointer of the array as an argument in that function, you can ignore one of the prime rules of scope. Likewise, if you know the exact pointer of your array, you can ignore all scope when returning values (e.g. SizeOfArray() ).

int MyArray[10];
 
item script rubbish{ 
	void run(){
		int x = 1;
		active.rubbish(x); //This will work, only if we know the pointer ID ahead of time.
                                   //That will almost never be the case. 
	}
}

global script active{
	void run(){
		int MyArray[20]; //Make an array.
		while ( true ) {
			rubbish(MyArray); //We pass the pointer of MyArray to the function.
			Waitframe();
		}
	}
	void rubbish(int MyArray){ //This accepts an integer as an input.    
		Trace(SizeOfArray(MyArray)); //This can trace the array, because we passed its pointer
                                             // to the arg int  MyArray.
		MyArray[1] = 100; //We can set this, because we passed the pointer.
	}
}


global script active{
	void run(){
		int MyArray[20]; //Make an array.
		while ( true ) {
			rubbish(MyArray); //We pass the pointer of MyArray to the function.
			Waitframe();
		}
	}
	void rubbish(int foo){ //Change the input name.
		Trace(SizeOfArray(foo)); //This can trace the array, because we passed the 
                                         //pointer of MyArray[20]  declared in
					 //the script, to an input with the label of foo. 
		foo[1] = 100; //We can set this, because we passed the pointer to 
                             //foo, and it will set MyArray[0] above to '100'.
 	}
}

In this example, MyArray[10] will be ignored, and MyArray[20] will be used. Priority appears to be given to arrays local to a script, that is also local to a function of a script.

--> All of this seems to be one vast bug, but people utilise it, 
    so fixing it would invalidate a good number of enemy scripts.