Skip to content

Commit

Permalink
Merge branch 'main' of https://github.com/samtupy/nvgt
Browse files Browse the repository at this point in the history
  • Loading branch information
RoryMichie committed May 24, 2024
2 parents 40c7fd9 + 889175b commit 301e16e
Show file tree
Hide file tree
Showing 21 changed files with 261 additions and 3 deletions.
2 changes: 1 addition & 1 deletion doc/docgen.py
Original file line number Diff line number Diff line change
Expand Up @@ -154,7 +154,7 @@ def process_topic(tree, path, indent):
data = open(path, "r", encoding = "UTF8").read()
markdown = "\n"
if path.endswith(".nvgt"): markdown += parse_nvgt_markdown(tree, path, data)
else: markdown += data.replace("\t", "") # Todo: This won't work if a .md file contains a code fragment, get rid of markdown indents more dynamically.
else: markdown += data
# Print the html which will be used for the .chm file.
chm = make_chm_filename(path)
if chm:
Expand Down
2 changes: 1 addition & 1 deletion doc/src/advanced/plugin creation.md
Original file line number Diff line number Diff line change
Expand Up @@ -41,7 +41,7 @@ plugin_main(nvgt_plugin_shared* shared) {
```

### picking it apart
We shall forgo any specific comments or teaching about the c++ language itself here, but instead will focus on the plugin aspect itself.
We shall forgo any general comments or teaching about the c++ language itself here, but instead will just focus on the bits of code that specifically involve the plugin interface.

The first thing that you probably noticed was this include directive which includes "../../src/nvgt_plugin.h". Why there? While this will be described later, the gist is that NVGT's build setup already has some infrastructure set up to build plugins. NVGT's github repository has a plugin folder, and in there are folders for each plugin. This example is using such a structure. We will talk more in detail about this later, but for now it is enough to know that nvgt_plugin.h does not include anything else in nvgt's source tree, and can be safely copy pasted where ever you feel is best for your particular project (though we do recommend building plugins with NVGT's workspace).

Expand Down
2 changes: 2 additions & 0 deletions doc/src/references/builtin/!datatypes/!datatypes.md
Original file line number Diff line number Diff line change
@@ -1,2 +1,4 @@
# Datatypes
In this documentation, we consider a datatype to be any class or primative that typically stores one value. While such a datatype could contain a pointer/handle to a more complex type that may store many values (in which case the handle itself is the single value the datetype contains), the types documented here do not directly contain more than one piece of data be that a string of text, a dynamically typed handle or just a simple number.

Beware that a few of these datatypes may get quite advanced, and you are not expected to understand what all of them do (particularly the dynamically typed ones) during the course of normal game development. Instead, we recommend learning about basic datatypes here, and then coming back and looking at any that seemed confusing at first glance when you are trying to solve a particular problem usually relating to a variable you have that needs to be able to store more than one kind of value.
36 changes: 36 additions & 0 deletions doc/src/references/builtin/!datatypes/any/!any.nvgt
Original file line number Diff line number Diff line change
@@ -0,0 +1,36 @@
/**
A class that can hold one object of any type, most similar to a dictionary in terms of usage but with only one value and thus no keys.
1. any();
2. any(?&in value);
## Arguments (2):
* ?&in value: The default value stored in this object.
## Remarks:
Though NVGT uses Angelscript which is a statically typed scripting language, there are sometimes ocasions when one may not know the type of value that could be stored in a variable, or may want to create a function that can accept an argument of any type. While this isn't the only way to do so, the any object provides a safe way to acomplish this task, possibly the safest / least restrictive of all available such options. There should be no type that this object can't store.
The biggest downside to this class is simply that storing and retrieving values from it is just as bulky as the usual way of doing so from dictionary objects. That is, when retrieving a value one must first create a variable then call the any::retrieve() method passing a reference to that variable.
something to note is that the constructor of this class is not marked explicit, meaning that if you create a function that takes an any object as it's argument, the user would then be able to directly pass any type to that argument of your function without any extra work.
Again just like with dictionaries, there is no way to determine the type of a stored value. Instead if one wants to print the value contained within one of these variables, they must carefully attempt the retrieval with different types until it succeeds where the value can then be printed.
*/

// Example:
// Lets create a version of the join function that accepts an array of any objects and supports numbers, strings, and vectors.
string anyjoin(any@[]@ args, const string&in delimiter) {
if (@args == null) return ""; // Nobody should ever be passing the null keyword to this function, but if they do this line prevents an exception.
string[] args_as_strings;
for (uint i = 0; i < args.length() && args[i] != null; i++) {
// We must attempt retrieving each type we wish to support.
int64 arg_int;
double arg_double;
string arg_string;
vector arg_vector;
if (args[i].retrieve(arg_string)) args_as_strings.insert_last(arg_string);
else if (args[i].retrieve(arg_vector)) args_as_strings.insert_last("(%0, %1, %2)".format(arg_vector.x, arg_vector.y, arg_vector.z));
else if (args[i].retrieve(arg_double)) args_as_strings.insert_last(arg_double);
else if (args[i].retrieve(arg_int)) args_as_strings.insert_last(arg_int);
else args_as_strings.insert_last("<unknown type>");
}
return join(args_as_strings, delimiter);
}
void main() {
string result = anyjoin({"the player has", 5, "lives, has", 32.97, "percent health, and is at", vector(10, 15, 0)}, " ");
alert("example", result);
}
13 changes: 13 additions & 0 deletions doc/src/references/builtin/!datatypes/any/methods/retrieve.md
Original file line number Diff line number Diff line change
@@ -0,0 +1,13 @@
# retrieve
Fetch the value from an any object and store it in a variable.

`bool retrieve(?&out result);`

## Arguments:
* ?&out result: A variable that the value should be copied into.

## Returns:
bool: true if successful, false if the variable supplied is of the wrong type.

## Example:
See the main any chapter where this function is used several times.
18 changes: 18 additions & 0 deletions doc/src/references/builtin/!datatypes/any/methods/store.nvgt
Original file line number Diff line number Diff line change
@@ -0,0 +1,18 @@
/**
Store a new value in an any object, replacing an existing one.
void store(?&in value);
## Arguments:
* ?&in value: The value that should be stored (can be any type).
*/

// Example:
void main() {
int number;
string text;
any example;
example.store("hello");
example.retrieve(text); // Check the return value of the retrieve function for success if you are not certain of what type is stored.
example.store(42); // The previous text value has now been deleted.
example.retrieve(number);
alert(text, number);
}
36 changes: 36 additions & 0 deletions doc/src/references/builtin/!datatypes/ref/!ref.nvgt
Original file line number Diff line number Diff line change
@@ -0,0 +1,36 @@
/**
A class that can hold an extra reference to a handle of any type.
1. ref();
2. ref(const ?&in handle);
## Arguments (2):
* const ?&in handle: The handle that this ref object should store at construction.
## Remarks:
In Angelscript, a handle is the simplest method of pointing multiple variables at a single object, or passing an object to a function without copying it in memory. If you know any c++, it is sort of like a c++ shared pointer. You can only create a handle to a complex object, and a few built-in NVGT objects do not support them such as the random number generators because they are registered as value types. Describing handles much further is beyond the scope of this reference chapter, but you can [learn more about handles from the Angelscript documentation](https://www.angelcode.com/angelscript/sdk/docs/manual/doc_script_handle.html) including why a few complex objects in NVGT don't support them.
Usually handles must be typed to the object they are pointing at, for example I could create a variable called `dictionary@ d;~ to create an empty handle to a dictionary object.
The type restriction on handles is almost always perfectly ok, however in a few super rare cases it can become bothersome or could make a coding task more tedious. The ref object is a workaround for that. Where ever typed handles can be used to point to an object, a ref object could point to it as well.
Unlike normal typed handles, one must cast a ref object back to the type it is storing in order to actually call methods or access properties of the stored type.
The = (assignment) operator is supported which causes the ref object to point to the value supplied, and the == (equality) operator is supported to compare whether a ref object and either another ref object or typed handle are pointing to the same actual object.
*/

// Example:
// Lets create a function that can set the volume of either a mixer or a sound object.
void set_volume(ref@ obj, int volume) {
mixer@ m = cast<mixer@>(obj);
if (@m != null) {
m.set_volume(volume);
return;
}
sound@ s = cast<sound@>(obj);
if (@s != null) s.set_volume(volume);
}
void main() {
sound my_sound;
my_sound.load("c:\\windows\\media\\ding.wav");
mixer mix;
my_sound.set_mixer(mix);
set_volume(mix, -5);
alert("mixer volume", mix.volume);
set_volume(my_sound, -10);
alert("sound volume", my_sound.volume);
my_sound.close();
}
Original file line number Diff line number Diff line change
Expand Up @@ -2,7 +2,7 @@
This enum holds various constants that can be passed to the regular expression classes in order to change their behavior.

## Notes:
portions of this file were Copied from POCO header files.
Portions of this regexp_options documentation were Copied from POCO header files.
* Options marked [ctor] can be passed to the constructor of regexp objects.
* Options marked [match] can be passed to match, extract, split and subst.
* Options marked [subst] can be passed to subst.
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -6,6 +6,9 @@
* string delimiter: the delimiter used to seperate each element in the array (can be empty).
## Returns:
string: the given array as a string.
## Remarks:
If an empty array is passed, a blank string is returned.
The delimiter is not appended to the end of the last item in the returned string. For example if an array contains [1, 2, 3] and you join it with a delimiter of . (period), the result would be "1.2.3" without an extra delimiter appended.
*/

// Example:
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -6,6 +6,8 @@
* bool include_and = true: whether or not to include the word "and" in the output.
## Returns:
string: the specified number, converted to a readable string.
## Remarks:
At this time, this function only produces English results.
*/

// Example:
Expand Down
Original file line number Diff line number Diff line change
@@ -0,0 +1,14 @@
# random_interface
Defines the class structure that is available in NVGT's object based pseudorandom number generators. A class specifically called random_interface does not exist in the engine, but instead this reference describes methods available in multiple classes that do exist (see remarks).
1. random_interface();
2. random_interface(uint seed);
## Arguments (2):
* uint seed: The number used as the seed/starting point for the RNG, passing the same seed will yield the same sequence of random numbers.
# # Remarks:
NVGT contains several different pseudorandom number generators which can all be instanciated as many times as the programmer needs.

These generators all share pretty much exactly the same methods by signature and are interacted with in the same way, and so it will be documented only once here. Small topics explaining the differences for each actual generator are documented below this interface.

These classes all wrap a public domain single header library called [rnd.h](https://github.com/mattiasgustavsson/libs/blob/main/rnd.h) by mattiasgustavsson on Github. The explinations for each generator as well as the following more general expination about all of them were copied verbatim from the comments in that header, as they are able to describe the generators best and already contain links to more details.

The library includes four different generators: PCG, WELL, GameRand and XorShift. They all have different characteristics, and you might want to use them for different things. GameRand is very fast, but does not give a great distribution or period length. XorShift is the only one returning a 64-bit value. WELL is an improvement of the often used Mersenne Twister, and has quite a large internal state. PCG is small, fast and has a small state. If you don't have any specific reason, you may default to using PCG.
Original file line number Diff line number Diff line change
@@ -0,0 +1,12 @@
/**
Return the next random number from the generator.
uint next();
## Returns:
uint or uint64 depending on generator: The next random number (can be any supported by the integer type used).
*/

// Example:
void main() {
random_pcg r;
alert("info", r.next());
}
Original file line number Diff line number Diff line change
@@ -0,0 +1,12 @@
/**
Return the next random floatingpoint number from the generator.
float nextf();
## Returns:
float: The next random float (between 0.0 and 1.0).
*/

// Example:
void main() {
random_gamerand r;
alert("info", r.nextf());
}
Original file line number Diff line number Diff line change
@@ -0,0 +1,17 @@
/**
Return the next random number from the generator with in a minimum and maximum range.
int range(int min, int max);
## Arguments:
* int min: The minimum number that could be generated (inclusive).
* int max: The maximum number that could be generated (inclusive).
## Returns:
int: A random number within the given range.
## Remarks:
This function always works using 32 bit integers regardless of the generator used.
*/

// Example:
void main() {
random_xorshift r;
alert("info", r.range(1, 10));
}
Original file line number Diff line number Diff line change
@@ -0,0 +1,23 @@
/**
Seed the random number generator with a new startingpoint value.
void seed(uint new_seed = random_seed());
arguments:
* uint new_seed = random_seed(): The seed to use (may be uint64 depending on generator, if so will default to random_seed64).
## Remarks:
All pseudorandom number generators typically need to start from one tiny bit of real-world randomness or obscure value to properly get going.
By default, nvgt's random number generators are seeded by reading 4 random bytes from the operating system using it's provided API to do so. If you call this seed() function with no arguments, the rng will be re-seeded with a new random seed.
However, particularly when dealing with game recordings or online play, it can be useful to take control of the random number generator and cause it to replay values. This can be done by setting the seed of an RNG to a predetermined and reused value. This is because the rng is guaranteed to return the same set of numbers for a given seed, as the seed serves as the starting point for the RNG.
A common method for example may be to fetch the value of the ticks() or random_seed() function yourself, store the result in a variable, and use that variable to seed an rng. If you want someone else on the network to generate the same numbers for your online game, you need only to transmit that same stored ticks() or random_seed() value over the wire and have the receiver also seed the rng to that value. Now both clients are using the same seed, and from that point they will generate random numbers that are the same, so long as of course one end of the party doesn't somehow jump the gun and generate a random number that the other end does not, as now the clients would be out of sync. This is exactly why these random_xxx classes were provided, because it may be needed to generate different random numbers on each client while insuring that some special numbers (such as enemy spawns) always remain the same. Just create multiple random_xxx instances and share the seed with one while doing whatever you want with the other.
*/

// Example:
void main() {
uint seed = random_seed();
random_well r(seed);
int num = r.range(1, 100);
alert("example", "the number is " + num);
r.seed(seed); // Restore our original seed from before generating the number.
alert("The new number will still be " + num, r.range(1, 100));
r.seed(); // internally choose a random seed.
alert("unknown number", r.range(1, 100));
}
Original file line number Diff line number Diff line change
@@ -0,0 +1,13 @@
# random_gamerand
GameRand

Based on the random number generator by Ian C. Bullard:

http://www.redditmirror.cc/cache/websites/mjolnirstudios.com_7yjlc/mjolnirstudios.com/IanBullard/files/79ffbca75a75720f066d491e9ea935a0-10.html

GameRand is a random number generator based off an "Image of the Day" posted by Stephan Schaem. More information here:

http://www.flipcode.com/archives/07-15-2002.shtml


Look at nvgt's random_interface documentation above to learn how to use this class.
Original file line number Diff line number Diff line change
@@ -0,0 +1,10 @@
# random_pcg
PCG - Permuted Congruential Generator

PCG is a family of simple fast space-efficient statistically good algorithms for random number generation. Unlike many general-purpose RNGs, they are also hard to predict.

More information can be found here:

http://www.pcg-random.org/

Look at nvgt's random_interface documentation above to learn how to use this class.
Original file line number Diff line number Diff line change
@@ -0,0 +1,15 @@
# random_well
WELL - Well Equidistributed Long-period Linear

Random number generation, using the WELL algorithm by F. Panneton, P. L'Ecuyer and M. Matsumoto.

More information in the original paper:

http://www.iro.umontreal.ca/~panneton/WELLRNG.html

This code is originally based on WELL512 C/C++ code written by Chris Lomont (published in Game Programming Gems 7) and placed in the public domain.

http://lomont.org/Math/Papers/2008/Lomont_PRNG_2008.pdf


Look at nvgt's random_interface documentation above to learn how to use this class.
Original file line number Diff line number Diff line change
@@ -0,0 +1,11 @@
# random_xorshift
XorShift

A random number generator of the type LFSR (linear feedback shift registers). This specific implementation uses the XorShift+ variation, and returns 64-bit random numbers.

More information can be found here:

https://en.wikipedia.org/wiki/Xorshift


Look at nvgt's random_interface documentation above to learn how to use this class.
Original file line number Diff line number Diff line change
Expand Up @@ -7,6 +7,7 @@
## Returns:
string: a random ascii character in the given range.
## Remarks:
If you pass a string with more than one byte in it to either of the arguments in this function, only the first byte is used.
Note that this function uses a pseudorandom number generator. To lern more, click [here](https://en.wikipedia.org/wiki/Pseudorandom_number_generator).
*/

Expand Down
Original file line number Diff line number Diff line change
@@ -0,0 +1,20 @@
/**
Returns 4 or 8 random bytes from the operating system usually used for seeding random number generators.
1. uint random_seed();
2. uint64 random_seed64();
## Returns (1):
uint: A 4 byte random number.
## Returns (2):
uint64: An 8 byte random number.
## Remarks:
A more detailed description on seeding random number generators is in the documentation for the random_interface::seed function.
To retrieve the random bytes in the first place, this function uses cryptographic APIs on windows and /dev/urandom on unix.
*/

// Example:
void main() {
uint seed = random_seed();
alert("32 bit seed", seed);
uint64 seed64 = random_seed64();
alert("64 bit seed", seed64);
}

0 comments on commit 301e16e

Please sign in to comment.