Skip to content

Containers

In this documentation, we consider a container to be any generic class that has the primary purpose of storing more than one value.

array

This container stores a resizable list of elements that must all be the same type. In this documentation, "T" refers to the dynamic type that a given array was instanciated with.

  1. T[]();
  2. array<T>();
  3. array<T>(uint count);
  4. array<T>({item1, item2, item3})

Arguments (3):

Arguments (4):

Remarks:

Items in an array are accessed using what's known as the indexing operator, that is, arrayname[index] where index is an integer specifying what item you wish to access within the array. The biggest thing to keep in mind is that unlike many functions in NVGT which will silently return a negative value or some other error form upon failure, arrays will actually throw exceptions if you try accessing data outside the array's bounds. Unless you handle such an exception with a try/catch block, this results in an unhandled exception dialog appearing where the user can choose to copy the call stack before the program exits. The easiest way to avoid this is by combining your array accesses with healthy usage of the array.length() method to make sure that you don't access out-of-bounds data in the first place.

Data in arrays is accessed using 0-based indexing. This means that if 5 items are in an array, you access the first item with array[0] and the last with array[4]. If you are a new programmer this might take you a second to get used to, but within no time your brain will be calculating this difference for you almost automatically as you write your code, it becomes second nature and is how arrays are accessed in probably 90+% of well known programming languages. Just remember to use array[array.size() -1] to access the last item in the array, not array[array.length()] which would cause an index out of bounds exception.

There is a possible confusion regarding syntax ambiguity when declaring arrays which should be cleared up. What is the difference between array<string> items and string[] items and when should either one be used?

At it's lowest level, an array is a template class, meaning it's a class that can accept a dynamic type (array<T>). This concept also exists with the grid, async, and other classes in NVGT.

However, Angelscript provides a convenience feature called the default array type. This allows us to choose just one template class out of all the template classes in the entire engine, and to make that 1 class much easier to declare than all the others using the bracket syntax (T[]), and this array class happens to be our chozen default array type in NVGT.

Therefor, in reality array<T> and T[] do the exact same thing, it's just that the first one is the semantically correct method of declaring a templated class while the latter is a highly useful Angelscript shortcut. So now when you're looking at someone's code and you see a weird instance of array<T>, you can rest easy knowing that you didn't misunderstand the code and no you don't need to go learning some other crazy array type, that code author just opted to avoid using the Angelscript default array type shortcut for one reason or another.

Methods

empty

Determine whether or not the array is empty.

  1. bool array::empty();

  2. bool array::is_empty();

Returns:

bool: true if the array is empty, false if not.

Remarks:

This method is functionally equivalent to array.length() == 0.

Example:
void main() {
	string[] items;
	bool insert = random_bool();
	if (insert)
		items.insert_last(1);
	alert("The array is", items.empty() ? "empty" : "not empty");
}

erase

Remove an item from the array at a particular index.

void array::erase(uint index);

Arguments:
Remarks:

Passing an index that is less than 0 or greater or equal to the array's absolute length will result in an index out of bounds exception being thrown.

Example:
void main() {
	string[] items = {"this", "is", "a", "test"};
	alert("The list currently contains", join(items, ", "));
	items.erase(random(0, 2));
	alert("The list currently contains", join(items, ", "));
}

insert_at

Inserts an element into an array at a given position, moving other items aside to make room if necessary.

void array::insert_at(uint index, const T&in value);

Arguments:
Remarks:

This method adds an element to the given position of an array. If you pass index 0, the item will be inserted at the beginning of the aray, and if you pass the array's absolute length, the item will be inserted at the end. Any values less than 0 or greater than the array's absolute length will result in an index out of bounds exception being thrown.

Example:
void main() {
	string[] names = {"HTML", "CSS"};
	names.insert_at(0,"Java Script");
	names.insert_at(2, "php");
	alert("Languages", join(names, ", "));
}

insert_last

Appends an element to an array.

  1. void array::insert_last(const T&in);

  2. void array::push_back(const T&in);

Arguments
Remarks

This method adds an element to the end of an array.

Example:
void main() {
	string[] names = {"HTML", "CSS"};
	names.insert_last("Java Script");
	alert("Languages", join(names, ", "));
}

length

Returns the number of items in the array.

  1. uint array::length();

  2. uint array::size();

Returns:

uint: the number of items in the array.

Remarks:

This method returns the absolute number of elements in the array, that is, without taking 0-based indexing into account. For example an array containing {1, 2, 3} will have a length of 3, but you must access the last element with the index 2 and the first element with index 0, rather than using 3 for the last item and 1 for the first.

Example:
void main() {
	int[] items;
	for (uint i = 0; i < random(1, 10); i++)
		items.insert_last(i);
	alert("The array contains", items.length() + " " + (items.length() == 1 ? "item" : "items"));
}

remove_at

Removes an element of an array by a given position.

void array::remove_at(uint index);

Arguments:
Remarks:

Please note that the position value is 0 base, and failure to define correct index will cause NVGT to throw "index out of bounds" exception.

Example:
void main() {
	string[] names = {"HTML", "CSS"};
	names.remove_at(0);
	alert("Languages", join(names, ", "));
}

remove_last

Removes the last item from the array.

  1. void array::remove_last();
  2. void array::pop_back();
Remarks:

Calling this method on an empty array will throw an index out of bounds exception.

remove_range

Removes a group of items from an array, starting at a given position and removing the specified number of items after it.

void array::remove_range(uint start, uint count);

Arguments:
Example:
void main() {
	string[] items = {"there", "are", "a", "few", "items", "that","will", "disappear"};
	alert("The array currently is", join(items, ", "));
	items.remove_range(1, 3);
	alert("The array is now", join(items, ", "));
}

reserve

allocates the memory needed to hold the given number of items, but doesn't initialize them.

void array::reserve(uint length);

Arguments:
Remarks:

This method is provided because in computing, memory allocation is expensive. If you want to add 5000 elements to an array and you call array.insert_last() 5000 times without calling this reserve() method, you will also perform nearly 5000 memory allocations, and each one of those is a lot of work for the OS. Instead, you can call this function once with a value of 5000, which will perform only one expensive memory allocation, and now at least for the first 5000 calls to insert_last(), the array will not need to repetitively allocate tiny chunks of memory over and over again to add your intended elements. The importance of this cannot be stressed enough for large arrays, using the reserve() method particularly for bulk array inserts can literally speed your code up by hundreds of times in the area of array management.

resize

Resizes the array to the specified size, and initializes all resulting new elements to their default values.

void array::resize(uint length);

Arguments:
Remarks:

If the new size is smaller than the existing number of elements, items will be removed from the bottom or the end of the aray until the array has exactly the number of items specified in the argument to this method.

reverse

Reverses the array, so the last item becomes the first and vice versa.

void array::reverse();

Remarks:

This method reverses the array in place rather than creating a new array and returning it.

Example:
void main() {
	string[] items = {"This", "is", "a", "test"};
	alert("The array is currently", join(items, ", "));
	items.reverse();
	alert("The reversed array is", join(items, ", "));
}

dictionary

This container stores multiple pieces of data of almost any type, which are stored and referenced by unique keys which are just arbitrary strings.

  1. dictionary();
  2. dictionary(\{\{"key1", value1}, {"key2", value2\}\});

Arguments (2):

Remarks:

The idea behind a dictionary, or hash map / hash table as they are otherwise called, is that one can store some data referenced by a certain ID or key, before later retrieving that data very quickly given that same key used to store it.

Though explaining the details and guts of how hash maps work internally is beyond the scope of this documentation, here is an overly in depth wikipedia article that is sure to teach you more than you ever wished to know about this data structure. Honestly unless you wish to write your own dictionary implementation yourself in a low level language and/or are specifically worried about the efficiency of storing vast amounts of similar data which could stress the algorithm, it's enough to know that the dictionary internally turns your string keys into integer hashes, which are a lot faster for the computer to compare than the characters in the key strings themselves. Combine this with clever use of small lists or buckets determined by even more clever use of bitwise operations and other factors, and what you're left with is a structure that can store thousands of keys while still being able to look up a value given a key so quickly it's like magic, at least compared to the least efficient alternative which is looping through your thousands of data points and individually comparing them in order to find just one value you wish to look up.

NVGT's dictionaries are unordered, meaning that the get_keys() method will likely not return a list of keys in the order that you added them. In cases where this is very important to you, you can create a string array along side your dictionary and manually store key names yourself and then loop through that array instead of the output of get_keys() when you want to enumerate a dictionary in an ordered fassion. Note, of course, that this makes the entire system less efficient as now deleting or updating a key in the dictionary requires you to loop through your string array and find the key that needs deleting or updating, and dictionaries exist exactly to avoid such an expensive loop, though the same efficiency is preserved when simply looking up a key in the dictionary without writing to it, which can be enough in many cases. While in most cases it's best to write code that does not rely on the ordering of items in a dictionary, this at least provides an option to choose between ordering and better efficiency, should you really need such a thing.

Look at the individual documented methods of this class for examples of it's usage.

Methods

delete

This method deletes the given key from the dictionary.

bool dictionary::delete(const string &in key);

Arguments:
Returns:

bool: true if the key was successfully deleted, false otherwise.

Example:
void main() {
	dictionary data;
	data.set("nvgt", "An audiogame engine using AngelScript");
	alert("Information", data.delete("nvgt")); //true
	alert("Information", data.delete("nvgt")); //false because the key is already deleted, another word, it does not exist.
}

delete_all

This method deletes all keys from the dictionary.

bool dictionary::delete_all();

exists

Returns whether a given key exists in the dictionary.

bool dictionary::exists(const string &in key);

Arguments:
Returns:

bool: true if the key exists, false otherwise.

Example:
void main() {
	dictionary data;
	data.set("nvgt", "An audiogame engine using AngelScript");
	alert("Information", data.exists("nvgt")); //true
	alert("Information", data.exists("gameengine")); //false
}

get

Gets the data from a given key.

bool dictionary::get(const string &in key, ?&out value);

Arguments:
Returns:

bool: true if the dictionary retrieves the value of the key, false otherwise.

Remarks:

Please note that the value parameter should be a variable to receive the value. This means that dictionary will write to the variable, not read from.

Example:
void main() {
	dictionary data;
	data.set("nvgt", "An audiogame engine using AngelScript");
	string result;
	if (!data.get("nvgt", result))
		alert("Error", "Failed to retrieve the value of the key");
	else
		alert("Result is", result);
}

get_keys

Returns a string array containing the key names in the dictionary.

string[]@ dictionary::get_keys();

Returns:

string[]@: the list of keys in the dictionary on success, 0 otherwise.

Example:
void main() {
	dictionary data;
	data.set("nvgt", "An audiogame engine using AngelScript");
	string[]@ keys = data.get_keys();
	alert("Keys", join(keys, ", "));
}

get_size

Returns the size of the dictionary.

uint dictionary::get_size();

Returns:

uint: the size of the dictionary, another word, the total keys on success, 0 otherwise.

Example:
void main() {
	dictionary data;
	data.set("nvgt", "An audiogame engine using AngelScript");
	alert("Dictionary size is", data.get_size());
}

is_empty

Returns whether the dictionary is empty.

bool dictionary::is_empty();

Returns:

bool: true if the dictionary is empty, false otherwise.

Example:
void main() {
	dictionary data;
	data.set("nvgt", "An audiogame engine using AngelScript");
	alert("Information", data.is_empty()); //false
	data.delete_all();
	alert("Information", data.is_empty()); //true
}

set

Sets the data into a given key.

void dictionary::set(const string &in key, const ?&in value);

Arguments:
Remarks:

If the key already exists in the dictionary, its value will be overwritten.

grid

This type is essentially just a more convenient 2d array. One place it's super useful is when representing a game board.

  1. grid();

  2. grid(uint width, uint height);

  3. grid({repeat {repeat_same T\}\});

Arguments (2):

Remarks:

One of the things that makes this class especially convenient is its opIndex overload. It's possible to index into a grid like:

my_grid[1, 2];

to access the value at (1, 2) on your grid.

Example:

void main() {
	grid<bool> game_board(10, 10); // a 10x10 grid of booleans.
	game_board[4, 4] = true; // set the center of the board to true.
	alert("The center of the board is", game_board[4, 4]);
}

Methods

height

Returns the current height of the grid.

uint grid::height();

Returns:

uint: the height of the grid.

Example:
void main() {
	grid<int> g(random(1, 10), random(1, 10));
	alert("Grid height is", g.height());
}

resize

Resize a grid to the given width and height.

void grid::resize(uint width, uint height);

Arguments:
Example:
void main() {
	grid<int> g(5, 5);
	alert("Original width and height", g.width() + ", " + g.height());
	g.resize(random(1, 100), random(1, 100));
	alert("New width and height", g.width() + ", " + g.height());
}

width

Returns the current width of the grid.

uint grid::width();

Returns:

uint: the width of the grid.

Example:
void main() {
	grid<int> g(random(1, 10), random(1, 10));
	alert("Grid width is", g.width());
}

Operators

opIndex

Get or set the value of a grid cell given an x and a y.

T& grid::opIndex(uint row, uint column);

Arguments:
Returns:

T&: a reference to the value at the given position. It is of whatever type your grid holds.

Remarks:

This function can throw index out of bounds errors, exactly like arrays can, so be careful.

Example:
void main() {
	grid<int> the_grid;
	the_grid.resize(5, 5);
	for (uint i = 0; i < 5; i++) {
		for (uint j = 0; j < 5; j++) {
			the_grid[i, j] = random(1, 100);
		}
	}
	alert("Info", "The center is " + the_grid[2, 2]);
}