Documentation | GOTHIC |
The Script language "DAEDALUS" | |
Author: Ulf Wohlers | Version: July 12th 2001 |
DAEDALUS was designed by:
Content:
|
1. IntroductionThe script language designed by us will be referred to as DAEDALUS in the following text. The game programme as such, that interprets the script code, will be regularly referred to as "C++"-Code. This chapter describes the script language DAEDALUS. During the design we were primarily inspired by the programming language "C", the script language "QuakeC" and to some extent Pascal. But DAEDALUS deviates from these in a few areas. Application of DAEDALUS
2. Syntax DescriptionThere are five kinds of so called tokens: identifier, keywords, literals, operators and other separators. A script is composed of these tokens. Spaces, line breaks, commentaries etc. are ignored. The length of identifiers is non-restricted. Identifier are names for variables, constants, instances, prototypes, classes and functions. An identifier is a sequence of letters and ciphers. The first sign must be a letter. Thereafter are allowed: letters, ciphers 0 to 9 and underscores. Keywords are: class const else float func if instance int other prototype return self string this var void while Literals are strings ("Hello") and constant values (453). Operators will be introduced further below. In this reference I describe the script language formally in dependence on the book "The C++ Programming Language" by Bjarne Stroustrup. Syntactical identifiers will be represented in italics. The script language is not case-sensitive (different than in C). But we recommend the following conventions for the naming of identifiers: ("dng" be the acronym for a module "dungeon.D")
3. CommentariesThe string /* begins a comment, which is closed by the string */. The string // begins a comment, which goes until the end of the line. Tthe strings // and /* within a comment as well as */ after a line comment have no further meaning and are handled like other signs. The commentary concept was adopted from C++. 4. StatementsStatements are declarations, commands or as well a statement block: statement vardecl constdecl assignment if-statement return-statement statement-block Example: statement: door_open(); statement-list: door_open(); opened = TRUE; statement-block: { door_open(); opened = TRUE; } 5. ExpressionsOperatorsAn operator "calculates" the resulting value from one or two values. A relational operator as well as a boolean operator delivers the integer value 1, if the expression is true, otherwise 0. Bit-Operators manipulate variables on bit level. The operator precedence was adopted from C++. operator: calc-op cmp-op bool-op bit-op a) Operators calc-op: + Addition - Subtraction * Multiplication / Division % Euclidean division (Modulo) c) Relational Operators cmp-op: < smaller than <= smaller or equal to > greater than >= greater or equal to == Equality != Inequality d) Boolean Operators bool-op: ! not && and || or e) Bitwise Operators bit-op: & and | or f) Signs sign: + positive - negative ExpressionsExpressions are formed by the operators presented above, as is common in C. Here just some examples of expressions are shown. 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: x1 < x2 x1 == x2 c) Boolean Expressions bool- expression: x1 && x2 x1 || x2 (x 6. Types, Variables and ConstantsTwo kinds of types exist: elementary types and classes. Additional types can not be defined, as is common in C/C++. Classes have a direct correspondent in the C-Code of the engine. Variables of a class are the so called instances. Elementary Typesfloat int string Correspond to the types in C/C++ Additionally, int- and string-arrays can be formed: VAR INT attribute[MAX_ATTRIBUTES]; VAR STRING names[MAX_NAMES]; Only one-dimensional arrays can be created. The single elements of the fields (arrays) are addressed as usual in C++, but for this only constants can be used as index: attribute[1] = 0; The first element begins with the index zero. C++ and DAEDALUSFunctions, variables and constants, which have to be accessed both in the C++-Code as well as in DAEDALUS, are declared at least in DAEDALUS. This is served by the keyword external. Variables and constants are also additionally defined, that means values are assigned to them. Variables and ConstantsA variable declaration must be initiated by the keyword var. This applies to every single declaration, not, like in PASCAL, for a whole block. But lists of variables are possible (as in C): vardecl: var type identifier [,identifier]opt [...]opt; Example: correct: var int value1, value2, value3; var string question, answer; var int value; wrong: int value; A constant definition must be initiated by the keyword const: constsdef: const type identifier = expression; Example: const type identifier[x] = { expression, expression, expression }; Framework: global, localThere exist two different frameworks for variables and constants:
Examples: var int count; func void test() { var int x; var int y; } The variable count is available globally in the script. The variables x and y - as in C/C++ - have the same local framework: the function test(). 7. Assignmentsassignment: identifier = expression; // simple assignment Example: var int x1; x1 = 40; x1 = x1 / 2; x1 = x1* 3; 8. FunctionsDefinitionFunction definitions are initiated by the keyword func. func-def: func type identifier ( vardecl1opt , ... , vardecl8opt ) statement-block Example: func int UsingShield(var int x1, var string s1) { [...] }; Parameter transferThe length of the parameter list is unlimited, but should be kept as short as possible for memory capacity reasons. Parameters are transfered call-by-value, that said, they don't return a value. Arrays are not allowed as parameter transfers. Function CallsFunctions are called as usual in C++. Also with their identifier as well as a mandatory parameter bracket. 9. Classes, Design Patterns and InstancesClassesThe Class declarations describe exactly the data structure of the engine. That means, they are not arbitrarily extendable in the script, but they are directly linked with 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 receive default values:
PrototypesWith the keyword prototype it is possible to create so-called prototypes, which have different default values: prototype-def: prototype class-identifier identifier statement-block One can see a prototype as a "derived" class, in which ONLY the default values were changed. Or as an instance of the class, that only serves as a pattern for additional instances. The definition of the default values happens in the statement-block. There is a separation between class declarations, which mirror the exact structure of the engine-internal class, and the class definition (prototype). InstancesInstances of classes or prototypes act as their concrete representations. The instance of a class material is a specific material with all its characteristics. instance-def: instance class-identifier identifier statement-block instance instance-identifier prototype-identifier statement-block The statement-block of an instance definition serves the definition of the variables, which belong to a class. Non defined attributes or actions keep their default value. But all additional assignments are allowed, insofar they make sense in any way. Small (fictitous) example for Item/Shield/WoodShield 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 WoodShield1 (ShieldProtoType) { // attributes description = "A quite miserable wooden shield"; }; 10. Control flowsBranching: if-then-elseThe if-statement was adopted from C++. Only the limited possibilities of expressions have to be respected. Other than that, a statement-block is always expected. 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); }; Function value return: returnIn functions, which return a value, a return assignment is used like in C++: return-statement: return ( expression ); 11. Dynamic VariablesSome variables are set dynamically with a function call and then they refer to, e.g. in a dialogue on the instance of the NPC (self) and his dialogue partner (other). Furthermore there will be Build-In-Functions, that allow an access to other VOBs. To support this concept several global variables are declared and dynamically set in the course of the game, such that these functions can be requested. The variables, at the moment, are the following: VAR C_NPC self; VAR C_NPC other; VAR C_NPC victim; VAR C_NPC hero; VAR C_NPC item; 12. Important Differences to C++Here just some pitfalls should be shown in short which result from the differences to C++. Where C++ also allows for single assignments, in DAEDALUS there must be an assignment block. This affects if-statements. Example: if (x<4) { SoundPlay(); }; |