Home
Memoirs of a Gamer
Movies I watched
Guidebook
Code Projects
Links
Adventure games, like most games, are driven by information, sometimes straight forward like player sprite positions, sometimes something abstract like whether a door is locked or unlocked. Sometimes even more complicated! As such Gorgon has a few different means of storing that necessary information built into the scripting system. These break down into immediate values, variables, arrays, and strings.
We'll cover strings in a separate article as that can be a slightly complicated topic on it's own, so for right now we'll stick to immediates, variables, and arrays.
Immediates are numeric constants written directly in the code. Take for example the line
= sys.Score,10 |
The numeral value "10" is our immediate. Immediates don't change during the runtime and will always be the same value. We can also use Defines to substitute an immediate with something to describe it's relevance and meaning.
Establishing our Define
define ROOM_BOBS_BEDROOM 14 |
And then using our Define
loadroom ROOM_BOBS_BEDROOM |
In this example we've decided room014 is Bob's bedroom script. We can easily reference our Define multiple times throughout our script and the Scriptor compiler tool will make sure they always all receive the same value. This also means that if we decide we want Bob's bedroom to be room 22 say, all we have to do is change that initial define statement and all references will automatically get updated.
NOTE: Define statements MUST occur outside of events and before their defined term is used.
What about when we want the data to be dynamic, like player positions, player health, how many times you've annoyed Police Officer Conroy? This is what variables are for. The Gorgon Virtual Machine supports up to 256 16 bit integer variables. These exact number of variables utilized and stored in save files is tracked by the primary game script (GAME.CSN), but each script file must be made aware of variables at compile time.
NOTE: Internally variables are identified by their index into the virtual machine's variable table. This means that two scripts can technically use unique names for the same variable. This is not advised as it can lead to confusion.
To define a variable we simply use the var command with a unique name. Once the variable is defined we can reference it in instructions in any events following the var command. For example
var jims_location |
declares our variable, calling it "jims_location". During system initialization, Gorgon sets all values in the variable table to 0. This can also be triggered using the "clearvars" instruction. It's invokation takes no parameters.
clearvars |
But say we just want to assign a value to jims_location only, what's the syntax to give it a value? Just use an assignment instruction like so:
= jims_location,ROOM_BOBS_BEDROOM |
This will set our variable the value referenced by ROOM_BOBS_BEDROOM! Now only working with immediates can be a little limiting, but we can also use other variables. Let's assume we've already declared a variable called "nextroom". To assign that variables current value to "jims_location" is equally straight forward.
= jims_location,nextroom |
What if we want to progammtically get the value to assign? That's where parenthesis come into play. Parenthesis can be used to substitute a parameter with the result of another instruction.
= jims_location,(+ jims_location,1) |
Gorgon supports instructions for Addition(+), Subtraction(-), Multiplication(*), Division(/), and Modulus(%). If you are unfamiliar with any of those, they work thusly:
Name | Syntax | Definition |
Addition | + A,B | returns A + B |
Subtraction | - A,B | returns A - B |
Multiplication | * A,B | returns A * B |
Division | / A,B | returns the dividend from A divided by B |
Modulus | % A,B | returns the remainder from A divided by B |
It's hard to imagine a programming environment where bitwise operations aren't relevant. As such the operators look like this:
Name | Syntax | Definition |
Bitwise NOT | ! A | returns the bitwise inverse of A |
Bitwise AND | & A,B | returns A AND B |
Bitwise OR | | A,B | returns A OR B |
Bitwise XOR | ^ A,B | returns A XOR B |
Bitshift Left | << A,B | returns A shifted left B places |
Bitshift Right | >> A,B | returns A shifted right B places |
Of course, conditions will be need to be tested from time to time. Games need win conditions, sometimes lose conditions, and all maner of gating the behviour of activities on the board. In Gorgon those look like:
Name | Syntax | Definition |
Equals | == A,B | returns true if A and B are equal |
Less Than | < A,B | returns true if A is less than B |
Less Than or Equals | <= A,B | returns true if A is less than or equal to B |
Greater Than | > A,B | returns true if A is greater than B |
Greater Than or Equals | >= A,B | returns true if A is greater than or equal to B |
Not Equals | != A,B | returns true if A and B are not equal |
As all our values are internally tracked as 16 bit integers, you may be wondering what exactly is true? The answer is simple, true has no specific value defined, only what isn't false. What is false? Zero! So any positive or negative value is effectively true.
The Scriptor compiler tool does support the use of the keywords "true" and "false". These are replaced by integer immediates at compile time with true equaling 1 and false equaling 0.
Sometimes you'll need a series of pre-defined values that can be accessed based on some input. Now you might think "I can just test for specific input values with if blocks and assign the appropriate value!" And there will be cases where that's necessary. But if the value for each input is constant, then this might be an excellent time to use an array. Arrays are series of integer values stored in the script's data segment. They must be declared outside of any events and take the form of
data 10,11,5,4,3 |
In this example we've declared the sequence 10, 11, 5, 4, and 3. If we want to access these values we can use square brackets with a numeric value, like this
= jims_location=[1] |
This will set the variable "jims_location" to the value stored at index 1 in the data segment for this script. In the above case, that would be the value "11". But what if we wanted to use a calculated index? Well, simply replace the "1" above with a variable or other such value.
= jims_location=[var1] |
= johns_location=[(+ var2,3)] |
Remember that if you reference a value beyond the available data segment the Gorgon environment will just return the value 0 and carry on as if nothing went wrong. This means to maintain expected behavior you will have to test for limits in your script itself. That is unless you genuinely want to just have the returned value be 0 after some period.
If you need to access data from another script's data segment, you will have to call an event from the appropriate script as each script can only access it's own data segment.
Keeping track of variable names and Defines in a big project could create confusion. This is why the Scriptor compiler also supports including shared code files. The include command will look a little strange at first as it takes what should be a string but isn't actually a string for the filename.
include shared_names.gs |
Placing a line like this will parse the contents of "shared_name.gs" into the current script file. This can be handy for having a single file with all variable declarations and Defines. Like most non-instruction commands, this must be entered outside of an event. The most logical place for an include command is at the beginning of a script file.
The files included are treated as true script files, so anything that can be placed in a script file can be in the shared file, whether data declarations, events, or even data sets.