Contents
1. Introduction
2. Basic Concepts
3. Comments
4. Statements
5. Expressions
6. Data Types, Variables and Constants
7. Assignments
8. Functions
9. Classes, Templates and Instances
10. Control Statements
11. Dynamic Variables
12. Significant Differences to C++
13. Loops
1. Introduction
The scripting language designed by us is called DAEDALUS in this document. As a rule the actual game program, which interprets the script code, is called "C++"-Code.
This chapter describes the scripting language DAEDALUS. While designing we got our inspiration from the programming language "C" above all, the scripting language "Quake-C" and partly Pascal. But DAEDALUS differs from them at some parts.
Intended use of DAEDALUS
- Dialogs / Informations
- NPC - AI
- Tasks
- Text Pool
- NPCs (Prototypes and Instances)
- Items (Prototypes and Instances)
- Implementation of Concept Rules
- "Event Programs" (realization of complex quests)
- Declaration of Sound Resources
- Declaration of Graphic Resources (incl. Ani informations)
2. Basic Concepts
There are 5 kinds of so-called tokens: identifiers, keywords, literals, operators and other separators. A script is assembled by those tokens. White-spaces, newline characters, comments etc. are ignored. There is no restriction for the length of identifiers.
Identifiers are names for variables, constants, instances, prototypes, classes and functions. An identifier is a sequence of letters and numerals. The first character must be a letter. After it letters, numerals 0 to 9 as well as the underline character (_) is allowed.
The keywords are:
- class
- const
- else
- float
- func
- if
- instance
- int
- other
- prototype
- return
- self
- string
- this
- var
- void
- while
Literals and strings ("Hello") and constant values (453). Operators will be described in a later chapter.
In this reference I describe the scripting language technically based on the book "Die C++ Programmiersprache" by Bjarne Stroustrup. Syntactical identifiers are written in italic letters.
The scripting language is not case-sensitive (differently from C).
But we recommend to use following conventions for naming the identifiers: (e.g. "dng" is the short identification for the module "dungeon.D")
- function: Dng_MoveLift();
- variable: dng_buttonsPressed;
- constant: DNG_NUM_TRIES;
3. Comments
The character sequence /* starts a comment that is ended bei the character sequence */. The character sequence // starts a comment that ends with the end of the line. Inside a comment the character sequences // and /*, as well as */ after a line comment, are of no consequence and are treated like other characters.
The concept for the comments was adopted from C++.
4. Statements
Statements are declarations, commands, or a block of statements:
statement
assignment
- if-statement
- return-statement
statement-block
Examples:
statement: door_open();
statement-list: door_open(); opened = TRUE;
statement-block: { door_open(); opened = TRUE; }
5. Expressions
Operators
An operator "calculates" from one or two values the resulting value. A relational and equality operator as well as a logical operator returns the integer value 1 if the expression is true, otherwise 0. Bitwise operators manipulate variables at a bit level.
The precedence (order of evaluation) is adopted from C++.
operator:
- calc-op
- cmp-op
- bool-op
- bit-op
a) Operators
calc-op:
- + Addition
- - Subtraction
- * Multiplication
- / Division
- % Remainder Operator (Modulo)
c) Relational Operators
cmp-op:
- < less than
- <= less than or equal
- > greater than
- >= greater than or equal
- == equal to
- != not equal to
d) Logical Operators
bool-op:
- ! logical NOT (negation)
- && logical AND
- || logical OR
e) Bitwise Operators
bit-op:
- & bitwise AND
- | bitwise OR
f) Signs
vorzeichen:
Expression
Expressions are build with the operators defined above as in C. Below just examples for expressions are demonstrated.
expression:
- literal
- calc-expressoin
- cmp-expression
- bool-expression
- bit-expression
a) Expression
expression:
- -x1 + x2
- x1 * (x2 + x3)
- (x2 % 2) * x3
b) Compares
cmp- expression:
c) Boolean Expressions
bool- expression:
A numeric value is true if it is not equal to zero.
d) Bitwise Manipulations
bit- expression:
6. Data Types, Variables and Constants
There are two kinds of types: basic types and classes.
It is not possible to define additional types, as usual in C/C++. Classes have a direct equivalent in the C-Code engine. Variables of a class are the so-called instances.
Basic Types
Corresponding to the types in C/C++
Furthermore it is possible to create int- and string-arrays:
- VAR INT attribute[MAX_ATTRIBUTES];
- VAR STRING names[MAX_NAMES];
You can create
unidimensional arrays only. The individual elements of the arrays are addressed like in C++, but it's only possible to use
constants for the index.
The fisrt element starts with the index zero.
C++ and DAEDALUS
Functions, variables and constants that need access in both C++-Code and DAEDALUS are declared in DAEDALUS at minimum. For that the keyword
extern is used. Variables and constants are defined in addition, i.e. values are assigned to them.
Variables and Constants
A declaration of a varibale must begin with the keyword var. This is valid for every single declaration, not just for one block as with PASCAL. Lists of variables are possible (similar to C).
vardecl:
- var type identifier [,identifier]opt [...]opt;
Examples:
correct:
- var int wert1, wert2, wert3;
- var string frage, antwort;
- var int wert;
wrong:
A declaration of a constant must begin with the keyword const.
constsdef:
- const type identifier = expression;
Example:
const type identifier[x] = { expression, expression, expression };
Storage Classes: global, local
There exist two different storage classes for varibles and constants:
- A variable or constant that is declared outside of any block has a global lifetime: after its declaration it is valid in the entire remaining script part.
- A variable or constant that is declared inside of a block is local regarding the outermost block.
Examples:
var int count;
func void Test()
{ var int x; var int y; }
The variable count is accessable global in the script. The variables x and y have, smilar to C/C++, the same local lifetime: the function Test().
7. Assignments
assignment:
- identifier = expression; // simple assignment
Examples:
- var int x1;
- x1 = 40;
- x1 = x1 / 2;
- x1 = x1* 3;
8. Functions
Definition
Definitions of functions are beginning with the keyword func.
func-def:
- func type identifier ( vardecl1opt , ... , vardecl8opt ) statement-block
Example:
func int UsingSchild(var int x1, var string s1)
{
[...]
};
Parameters
The size of the parameter list is unlimited, but it should be as small as possible to save memory.
Parameters are passed call-by-value, i.e. they don't return a value. Arrays are not allowed as parameters.
Function Calls
Function are called similar to C++. That means with its identifier and the mandatory parentheses.
9. Classes, Templates and Instances
Classes
The declarations of classes are describing exactly the data structure of the engine. So they are not extensible within the script but linked directly to the engine.
classdecl:
- class classname (base-classname)opt declaration-block
Example:
class Creature (Vob)
{
// attributes
var string name;
var int hitpoints;
var int hp_max;
// actions
var funcref birth;
var funcref death;
};
The attributes are pre-defined with default values:
- Variables of type int are set to the value 0
- Strings to the empty string ""
- Pointers refer to NULL.
Prototyps
With the keyword
prototype it is possible to create so-called prototypes, which have different default values:
prototype-def:
- prototype class-identifier identifier statement-block
A prototype can be regarded as a derived class at which ONLY the default values are changed. Or as a instance of the class to provide a basis (template) for further instances. The definition of the default values is done in the statement-block.
There is no separation of the class declaration (class), which reflects the exact structure of the engine-internal class, and the class definition (prototype).
Instances
Instances of classes or prototypes are describing the concrete representations of them. The instance of the class Material is a definite material with all its attributes.
instance-def:
- instance class-identifier identifier statement-block
- instance instance-identifier prototype-identifier statement-block
The statement-block of a instance definition serves for a definition of the variables that are member of to the class. The undefined attributes retain their default values. But all further statements are allowed to the extent to which they may be reasonable.
Short (fictitious) example for item/shield/wooden shield
class Item(Vob)
{
// attributes
var int damage;
var int attack;
var string description;
// actions
var funcref use;
};
prototype ShieldProtoType (Item)
{
damage = 0;
attack = 0;
descriptions = "";
// actions
use = UsingSchild();
};
instance WoodenShield1 (ShieldProtoType)
{
// attributes
description = "A quite pitiful wooden shield";
};
10. Control Statements
Conditional Branch: if-then-else
The if-statement was adopted from C++. Just the limited possibilities need to be observed. Furthermore a statement-block is always essential.
if-statement:
- if ( expression ) statement-block
- if ( expression ) statement-block else statement-block
wrong: if (x<4) SoundPlay(ID_sound_roar);
correct: if (x<4) { SoundPlay(ID_sound_roar); };
Return to Calling Function: return
For functions which return a value the return statement is used similar to C++:
return-statement:
11. Dynamic Variables
Some variables are dynamically set at the function call and then, e.g. in a dialog, refer to the instance of the NPC (self) and its conversational partner (other). Further on there exist build-in functions, which provide access to other VOBs.
To support this concept some global variables are declared and set dynamically at runtime of the game so that they may be used in functions. Currently this are following variables:
VAR C_NPC self;
VAR C_NPC other;
VAR C_NPC victim;
VAR C_NPC hero;
VAR C_NPC item;
12. Significant Differences to C++
Herein just a few pitfalls arising from differences to C++ are demonstrated in short. Where C++ allows single statements DAEDALUS requires a statement block. This applies to the if-statement.
Example:
if (x<4) { SoundPlay(); };
---
13. Loops
There are no loop constructs in Daedalus, but its possible create an iteration using a recursion.
FOR-Loop
Example:
var int Zaehler;
func void TestFunc()
{
// ... any code
// call of the loop
Zaehler = 0;
ForLoop();
// ... any code
};
func void ForLoop()
{
// ... code of the loop
// increase by 1
Zaehler = Zaehler + 1;
// loop iterates from 0 to 19
if (Zaehler >= 20)
{
ForLoop();
};
};
WHILE-Loop
Example:
func void TestFunc2()
{
// ... any code
// call of the loop
WhileLoop();
// ... any code
};
func void WhileLoop()
{
// check, if while condition still true
if (...)
{
// ... any code
// once again
WhileLoop();
};
};
Translated to English from a German text based on the G1MDK documentation (Copyright ©
[Piranha Bytes])
IN NO EVENT SHALL PIRANHA BYTES BE LIABLE FOR ANY FAULT IN THE TRANSLATION OF THIS DOCUMENT INCLUDING, BUT NOT LIMITED TO, ACCURACY AND COMPLETENESS.