
All rights to the GRAAL system remains with Performance Software and is copyright (C) 1997/1998 Per Thulin.
Users of GRAAL may use the system freely to distribute their own graphic adventures, but are completely forbidden to use any of the supplied example material - puzzles, characters, animations, or scenes - in their own work. Quite simply, all material used in your own GRAAL adventures must be your own!
The shareware version of GRAAL is not crippled in any way, but it is not quite adapted for "professional" use, which is explained later in this manual.
See the file Registration.form for details on how to register.
The GRAAL Editor is coded in Blitz 2 Basic. You know it makes even more sense... ;)
graal.main
If you look at these files, and disregard the abundance of comment lines starting with /*, you will quickly realise how precious little GRAAL code is actually needed for the basics of an adventure. Also, remember that there is an editor included making your GRAAL-coding life a lot easier - you don't have to enter that many tricky parts manually, because the editor can help you.
The GRAAL documentation is divided into three main parts:
Furthermore, I have tried to print names of files and sections of scripts in a special font:
file.name
Of course, those of you who only have the ascii manual will not benefit from this. Register and order the manual! :)
...or maybe it has just begun. Because, although GRAAL is a powerful tool, designing a graphic adventure still needs an awful lot of hard work from your side - all GRAAL does is take most of the actual coding work out of the job and lets you get on with designing the story, logic, backgrounds, objects, animated characters and dialogue. Which, in itself, should keep you busy for quite a while.
GRAAL was mainly invented along with the 7-room demo of the first ever GRAAL adventure "Olaf Longhair, Part I", delaying the release of both, but ensuring that GRAAL really works on a full-scale and rather advanced graphic adventure. Although maybe not quite up to LucasArts standards, it proves that GRAAL can make at least a budget-level game any day! And since this manual was written parallel to the code that went into "Olaf" and GRAAL itself, you should find everything of importance right here.
You will not go far without a good paint program like Deluxe Paint, Brilliance or Personal Paint to create all backgrounds, objects and animations. An image processing program like Photopaint, Image FX or ADPro is a good complement.
To take some of the work out of the backdrop scene creation, why not use a
modelling and rendering package? (Believe it or not, there are some good ones that are freeware, even - POV-ray, for instance.)
A sound sampler and software could also come in handy, as could a scanner or digitizer. But hey, it's up to you. Or rather, your wallet.
Apart from the essential graal.guide reference file, the "Olaf "demo provided with the package provides you with well commented script files of all types, and a couple of GRAAL-driven "disk-mag demos" are available on aminet showing off techniques not used in "Olaf". (game/role/GraalHerald1.lha and game/role/GraalHerald2.lha).
Together, these information sources demonstrate most major GRAAL techniques. (Beware: READ THE COPYRIGHT NOTICE!)
The GRAAL code needed to make an adventure tick is contained in a number of script files. It is a compact language; if it wasn't for the heavy commenting, they would not take up too much space at all.
There are different types of script files, each controlling a different portion of the game. Their relationships form a tree-shaped structure, like this:
The numbers are only examples. There may be any number of section scripts beneath the main script, and any number of room scripts under each section script.
Although placed in the middle of the structure, the importance of section scripts vary greatly depending on the design of your adventure. In some cases, you may want to have only one section file, containing nothing at all! More about this further on.
In all the script files there are three basic kinds of lines:
/*which can be followed by any text, like in
/* This is a comment if ever I saw one!Use comments a lot, because the GRAAL syntax is not particularly reader-friendly, and what was clear in your mind when you typed it in may seem like pointless rubbish a couple of weeks later - if you don't have the comments there to remind you. First and foremost, ALWAYS document what your variables (called room and object flags - more about them later) contain and how they are supposed to be used!
Hint: The GRAAL_Editor uses the first line of each script file to explain its contents in file requesters, making it easier to find the file you want. Therefore, always make the first line of each script a comment, like this:
/* Short description of script contents
statement: parameter1;parameter2;...;parameterNIn many cases, the parameters contained in a statement line are conditions or commands, containing their own parameters. Example:
ACTION: 4;IFRF 2=0;SAY I Can't do that;EXITIn this example, ACTION: is a statement that comes into play when GRAAL is checking a command input by the player. More precisely, the ACTION: statement in this example will be used if a sentence using verb 4 (parameter 1) has been entered by the player. GRAAL will then execute the commands SAY and EXIT, but only if the condition IFRF 2=0 has been fulfilled first.
Note: There must be a space between the ":" and the parameters, but there must be no spaces around the semicolons separating the parameters! Also, there is no semi-colon after the last parameter in a line.
Each statement in a script file may be up to 255 characters long. The script files are case sensitive, so make sure all statement and command names are written in upper case.
Any line in the three types of script files mentioned above that does not conform to the rules will be spotted by GRAAL at run-time, normally causing the execution of the adventure to halt with an error message. Double-check everything, and use the GRAAL editor for help with the parameter syntax and syntax checking!
Good questions! The first, and in many ways the most important, is the main script. It is always called graal.main because that is what it must be called - if GRAAL doesn't find a graal.main script in the current directory, it will say so and terminate.
The main script sets up everything that is common to the entire adventure, such as:
Since GRAAL reserves memory for each possible room number from 1 and up to the highest room number used, it is a waste to have "gaps" in the room sequence. If you have deleted some rooms in the middle of the sequence, use the vacant numbers when you add new rooms, thus minimising the gaps in the numbering sequence.
The room scripts do much the same for each adventure location or "room" as the main script does for the adventure as a whole.
They contain, among other things, the following:
How you define sections is up to you, and you do not need to use the concept at all if it is irrelevant. (In that case, just use section 1 for all the rooms, and place no commands in the 1.section script - just a few comment lines describing what the blazes you are up to, with a couple of totally blank lines in between.)
The cut-scene scripts are a little special (but simpler) than the previous script files, and will be discussed later on.
(You should, of course, run the syntax checker in the GRAAL_Editor on all scripts first to get rid of all typing errors and other such mistakes. This takes far less time than re-running GRAAL_2!)
First, the GRAAL_2 program loads. Then, the GRAAL title screen is shown. The progress indicator (the horizontal bar) indicates that the contents of the main script are being loaded and processed. When the title screen disappears and the screen goes blank for a moment, the system is working on the first room and section scripts.
Most likely, you will get some error messages before everything starts running smoothly. A GRAAL "run-time error" message will appear in yellow text surrounded by a red border on screen, stating the type of error, which room was currently loaded, and which file was last accessed.
Note: The file referenced in the error message is not always the actual culprit! For example, if GRAAL has loaded a small cutscene script, executed it and run into a problem in the calling script later on, it is still the name of the completely innocent cutscene file that is shown. Take this information for what it is.
Some problems may be of a less severe nature. In those cases, GRAAL sometimes lets you decide whether to continue playing, or exit the program (in which case it tries to clean up the memory just as if you give the "Q"uit command when playing the game the normal way).
However, continuing after such a warning is seldom safe: The error almost certainly affects some aspect of the game. While things like flag value errors may often be corrected using the on-line monitor (see the appendices), other problems propagate and make GRAAL keel over shortly after the first, ignored error message.
Also note that in the error messages, the offensive statements and commands are sometimes printed in a slightly different way from how they appear in the script: This is because all RIMGn, SIMGn, ROBJn and SOBJn references, which are relative numbers, are translated directly upon loading to become absolute numbers. So if your N_xxxxIMGS: statement in the main script decide that room images start at image number 51, an erroneous statement containing RIMG4 would actually show the number as "54" in the error message. (Sorry 'bout that. Read on, and you will probably understand what the heck I am talking about later.)
There will most likely always be some errors that are not trapped properly, and the system may just "die on you". In those cases, try to determine how far the loading process has actually gone, and check the structure of YOUR scripts carefully against the Olaf demo and the order in which things appear there! Also, resetting your Amiga before trying again often helps. As always, there is a certain amount of memory thrashing going on if you make a lot of consecutive test runs.
For an overview of the basic features of the GRAAL_2 player interface, read the "Olaf.guide" that contains instructions for the demo adventure.
On the subject of loading saved games, note that saved game files can only be used with the same GRAAL driver and adventure version with which they were saved - each time you add or delete objects, rooms and other stuff in the adventure, the saved game file format changes, and renders old saved game files unusable. To make the task of testing a little easier, have a look at the macro feature (``Macros'' on page 70).
4 Starting on an Adventure
I won't bother you with a lot of talk about how you must plan the contents of your adventure, have a good storyline, so on and so forth. If you don't that's not my fault, is it? I simply assume you HAVE a story to tell, and that you are well aware of how graphic adventures of this kind works - if you don't, you'd better play some first. I will then show how you can do it all using GRAAL.

Here are some examples of statements that can be set almost immediately. Other ones will be dealt with once we start designing rooms, objects and characters for the adventure.
If you use the GRAAL Editor, you can read more about each statement if you place the cursor in the statement name somewhere and then press the [Help] key or click the <?> button.
NAME: "Olaf Longhair Goes East"The name of my adventure is "Olaf Longhair Goes East". (The quotes are not there because they enclose a string or anything - I actually want them displayed on screen when the name of the adventure is called up by pressing the [V] key during a game!)
VERSION: versionThe adventure version number. This is especially useful to guarantee that you don't try to load old saved game files when testing a newer version of the adventure.
Then follows a lot of statements dealing with the player interface layout, and numbers setting limits for how many images, objects, and other things GRAAL can handle in your adventure. Basically, the size of the comand area, the number of available commands, their positions and appearance, the layout of inventory lists, and dialogue alternative displays can all be adjusted to suit your needs. Read the comments in the graal.main script, that's the best way to learn about them. Many of these statements require graphic images to be specified and positioned - more about graphics follows below.
The statements
MSGFONT: xen;8each loads a font with a certain size and stores it in memory for later use in the game. (For more information on what font is used where, go to the on-line reference.)
COMFONT: garnet;9
TITLEFONT1: olaf;27
TITLEFONT2: times;14
To keep things easy to handle on the player side, we do NOT install these fonts in the normal Workbench FONTS: drawer, but keep them in a special FONTS drawer inside the drawer where all the other game files reside.
This means all fonts you wish to use in the game must be copied to this special "game fonts" drawer in your development directory. The only trouble is that GRAAL needs to have its fonts drawer "prepared" with the standard Amiga FIXFONTS command in order to be able to load the fonts.
What this means is that whenever you change the fonts in the drawer, you should run the standard Workbench "fixfonts" program, with the logical assign FONTS: pointing to the game fonts drawer. You do this in a CLI shell, and the commands used should look something like this ("DH1:" below is a hard disk drive, and "MYADVENTURE" is the path to your development drawer on that disk):
> assign FONTS: to DH1:MYADVENTURE/FONTSThe last command re-assigns FONTS: to the Workbench FONTS drawer.
> fixfonts
> assign FONTS: to SYS:FONTS
One of the things GRAAL makes so easy to manage is the point and click control of the main character - in this case, Olaf. GRAAL controls what animation sequence is the correct one to use in all standard situations, in which direction Olaf is heading, where in a room he can actually place his feet, and so on.
Wonderful as all this may be, it doesn't relieve you of the responsibility for the character design - in other words, before GRAAL can do all this wonderful stuff, you must design the main character and the animations used for his basic movements.
Basically, what we need now are some still images and animation cels showing Olaf in various standardised poses. For "Olaf", all these are placed in the IFF picture file Olaf_Original.iff, which you should take a look at now.

Also note that there are no separate images for the right and left profiles - to make life a little easier, and less memory consuming, the profile images will simply be flipped by GRAAL when a reversed view is required.
We will need more images of Olaf during the course of the game, but since they will only be used for special occasions, they are loaded into memory only when they are needed and erased afterwards. So Olaf_Original.iff contains all the "global" images of our main character and favourite hero.
A still is any image that is static.
An animation is any image that moves, and it does so by using a number of slightly different stills replacing each other, sometimes referred to as animation cels.
In GRAAL, all images used in the game - stills as well as animation cels - are stored in an image bank.
BOB is short for Blitter OBject. BOBs are well-known to Amos programmers. They are, basically, the way GRAAL manages the display of all graphic items on screen that aren't just backdrops: Objects, animated characters, texts, and so on. BOBs can be put into the display and deleted again without harming the backdrop picture. To achieve this, the system must keep track of all these graphic items by assigning each one used at any time with a BOB number.
Any BOB may use any image (or vice versa, depending on how you look at the world). For example, BOB number 44 may be used to display a flower, held in image bank position 56, in one scene. In another room or scene, the same BOB number 44 may be used to display a knife, which is image 78 in the bank. Confusing?
You usually specify BOB numbers in the statements that define image-related things, like OBJECT:, ANIM: and STATIC: stetement. There are also commands to handle BOBs that are not connected to any specific item: BOBON and BOBOFF.
Since re-cycling is the word of the day, there is no difference in the image types used for different purposes - all are stored in the image bank, and you may use the same image as an animation cel in one situation and as a still image in another.
The image bank, where we store all images, must be logically divided into three sections:
N_GLOBALIMGS: 90This means that right now, we believe we need 50 global images, 30 for use in sections, and 70 for use in rooms. If we change our minds later on, we can always change the numbers then.
N_SECTIONIMGS: 30
N_ROOMIMGS: 70
Let's define the main character's images. The statement
CLPART: Olaf_Original.iff
tells GRAAL that following statements will grab images from the picture file Olaf_Original.iff
IMGS: 10;11;1;1;31;47;32;0tells GRAAL to grab 10 images and store them in image slot 11 and upwards.
In the GRAAL editor, try this:
If you want to use multiple controllable characters, automatic character scaling, or make the single controlled character "clickable", you have to define a CHAR: statement for it.
In my demo adventure, I do use character scaling, so let's define Olaf with a CHAR: statement:
CHAR: 1;18;11;40;1;1;37;0;22;1.2;47;31
1;means Olaf is character number one. There must ALWAYS be a character number one if CHAR: statements are used at all!
18;means that Olaf is object 18. We'll come back to defining objects later - in this case, the object definition holds some important information about Olaf, like which animation channel he will be using.
We will not go into details about the other parameters here - read all about it in the on-line reference.
(In older versions of GRAAL, there was no CHAR: statement, or indeed a character object - instead, you had separate CHARACTER_WIDTH:, CHARACTER_HEIGHT: and similar statements to set the properties now dealt with in the CHAR: statement.)
Anyway, on with it. We need to define some graphics concering some standard movements and still images for our hero:
STILL_RIGHT: 14These statements tell which still images are to be shown when Olaf is facing in the respective direction, doing nothing.
STILL_LEFT: //14
STILL_BACK: 12
STILL_FRONT: 11
Wait a minute, what's that strange "//14" thing? Well, it's a convenient way of re-using graphics. Any image number prefixed with "//" will display the image flipped left/right, so you don't have to create graphics for both views. Neat, eh?
Anyway, on with it.
PAUSE_RIGHT: 13These images are used when Olaf pauses after having gone in a certain direction. If you wish, they may be set to exactly the same values as the STILL_... images. However, as you see, Olaf uses image 13, a slightly more relaxed, forward-facing and "ready-for-input" pose, for the right and left poses in these statements than in the STILL_... statements.
PAUSE_LEFT: //13
PAUSE_BACK: 12
PAUSE_FRONT: 11
You don't HAVE to make the left pose the flipped-over version of the right pose - if you want to draw different images for each direction, go right ahead. Also, if there is any risk of both views of the same image being shown on screen at the same time, they should be separate images! For more info, see ``Character and Graphics Design'' on page 53.
So far, all we have done is specify still images. Now we enter into the gruesome, yet strangely attractive world of animation:
WALK_RIGHT: A 0,(16,6)(15,6)(14,6)(17,6) ...
And yes, AMOS Pro users will immediately give a cry of joy: It's AMAL!
WALK_LEFT: A 0,(//16,6)(//15,6)(//14,6)(//17,6) ...
WALK_AWAY: A 0,(29,8)(30,8)(31,8)(30,8)
WALK_TOWARD: A 0,(26,8)(27,8)(28,8)(27,8)
It's quite wise to use 6 frames as the smallest time space for any image during background scrolling - 3 is possible and may work well if you have a limited number of BOBs in each scene in your adventure. However, if you paint on a large canvas so to speak, the system will have problems fitting all graphic updates into a 3 frame space and so the animation may become jerky. (6 isn't safe in all situations, but it usually works and is a good compromise.)
TALK_MAP: 11;A 0,(20,18)(11,12)(20,12)(11,6)(19,12)
Not only walking is animated and automated in GRAAL - talking is as well.HANDLE_MAP: 11;A 1,(11,12)(36,1);A 1,(11,12)(34,1);A 1,(11,12)...
Standard "manipulation" or handling of objects are specified in a similar manner - the animation to be used when a certain object is handled depends on a) the previous character image on screen and b) whether the object in question is placed high up, low down or in mid-air - an animation sequence for each possible position is supplied in the same statement, separated by semicolons.5 "A Room! A Room! A Kingdom for a Room!"
As you may gather from the heading of this chapter, we now quite badly need a room or other location to move about in - having our hero confined to a lot of abstract image and animation statements in the main script will not make anyone happy.UPDATE: 3;1
which sets the updating speed of the scene area. The higher the numbers, the slower the screen updating, and the more graphics GRAAL is capable to shift between updates. To keep animations etc. from becoming jerky, the numbers must be set high enough to cope with all graphics.SECTION: 1
statement, indicating that this room is part of section 1, as are all the rooms making up Constantinople in this game.BACKDROP: 1BG.IFF
takes care of that.START_POS: 1;13;20;115;L;1
statement. This not only indicates where Olaf starts, but whether the background screen starts scrolled to the far left, far right or the middle. (In this case, it's all the same, since the scene fits within the screen width.)FLOOR: 1;16;114;304;119;1-1/2-2/3-3/4-4
Each such statement defines a rectangular part of the picture where Olaf may place his feet. If there is more than one such rectangle, each is defined by a separate floor statement, and all floors must overlap with at least one other floor to enable Olaf to find his way from one floor to another. The last parameter, "1-1/2-2/3-3/4-4", describe how Olaf navigates between the four floors in this room. See the FLOOR: statement in the on-line reference for more information about this.EXIT: 1;7;66;12;112;10;113;Exit to\street
defines an exit from the bar. This creates a "clickable" rectangle on the screen with some additional parameters describing the properties of the exit. We will come back to the subject of switching rooms further on.CLPART: 1FG.IFF
is a statement telling GRAAL that we wish to grab some clipart from the 1FG.IFF file to use as images in this room. ROOMIMGS: ...
statements follow the syntax of the IMGS: statement we used in the main script. Every image grabbed with this statement should later be referred to by a "room image number", which is a number preceeded by RIMG. For example, RIMG3 means room image 3.6 The Object Matter
You could, theoretically, spring Olaf loose in the bar now, but there would be absolutely nothing to do - just an exit pointing to an undefined room, floors to move about on - and a barrel to hide behind! So far, there is not a single object to interact with!OBJECT: 16;piece of\paper;8;VIS;56;RIMG6;66;119;14;0;
In the GRAAL Editor, you get a better view of the parameters if you place the cursor on the word OBJECT: and then click <Edit Parameters> to load the object into the Edit Parameters window:
//14;with;PICK;0;8;47;LOW;WD;an;this;it

16;means this is global object number 16.
piece of\paper;
is the name of the object. The backslash is replaced by a line break when the name is shown in the scene area.
8;is the room where the object first appears.
VIS;means the object can be seen and handled. (NVIS means "invisible".)
56;is the BOB number that will be used when displaying the object.
RIMG6;is the image number which is used to display the object by default. This could also be an animation sequence using the same animation syntax as the TALK_MAP: etc. statements explained previously.
But wait a minute! We use an room image, obviously grabbed in the 8.room script, to display a global object, which is obviously not tied to that one room? Isn't this strange?
No, it actually makes sense. Room 8 is the only place where the piece of paper will actually be SHOWN in that shape - when it is used further on in the game, it will only be displayed using its inventory icon. So this is a safe use of room images!
66;119;is the x and y position where the image will be displayed (i relation to the room image's hotspot).
14;0;is the "character offset". When Olaf wants to handle the piece of paper, he will walk to a position 14 pixels to the right and 0 pixels above the object's hotspot.
Normally, we talk about the relative positions of the character's and object's hotspots here. (See ``All About 3D and Hotspots'' on page 57.) However, if you prefix the x value with a "W", for example W8;0; the x position refers to the edge of the character that is closest to the object instead. That technique allows for multiple characters of different widths more easily. However, if you only have one character, or all characters look more or less the same, don't bother.
//14;
is the still image used to display Olaf once he has walked up to the object. Since the object is to the left of him, he will face it using image //14. And specifying the correct still image for each object is vital: Should Olaf begin to handle the object after walking up to it, the HANDLE_MAP: sequence linked to image //14 will be used. Should he start to talk, the TALK_MAP: sequence linked to the image will be used. This is all done automatically, as long as you specify the HANDLE_MAP:s, TALK_MAP:s and still images used for object handling correctly!with;
is a preposition. If a preposition exists, it is assumed that this object can not be used on its own with the USE verb - it must be combined with something else, and so the sentence line will read USE PIECE OF PAPER WITH, and the system will wait for a second object to be clicked. If this parameter is left blank, the object will be used on its own.PICK;
indicates that the object can be picked up (the condition IFPICK returns TRUE). NPICK is used for the opposite.0;
If the object is animated using an animation command (instead of the single RIMG17 for this example), the animation channel must be specified here. The range of possible values is 2-16, and as with BOB numbers, the same number may not be used for two things simultaneously. The piece of paper is not animated, and therefore this parameter is 0.8;
This is the object's "quick command", that is, the command issued when the player points to the object and clicks the right mouse button. Verb 8 is LOOK AT.47;
This is the object icon used to show the object in the inventory: Global image 47.LOW;
This is an important one for all objects which can be picked or handled! It determines which of the "handle animations" Olaf will use. Since the piece of paper is on the floor, the LOW animation will be used. (Always place objects, or Olaf, using the character offset co-ordinates so that one of the three positions can be used in a natural way!)DW;
This is an "attribute string" which can be used to determine some general properties for the object. "D" stands for dead object, and "W" for "wood". (A rather pointless attribute in this case. Basically, it only tells us that it is softer than stone or steel!)a;this;it
Often, you refer to an object in sentences and messages. For example, if someone looks at an apple, just may wish the message "Just an apple" to appear.7 Section Objects and Images
There is a third class of objects involved in the bar scene: Those defined in the section script 1.section with the SECTIONOBJ: statements. These are objects that only exist the very first time a new section of the game is visited, and disappear again during the visit to the section. It is not a completely necessary feature, but in the demo some of the objects in Constantinople are of this kind - the magic flute, for example, which disappears into the pawn shop before you can leave town.8 Camera! Action! Lights!
8.1 ACTION: statements
All conditions and commands executed in response to the player's actions are placed in ACTION: statements (except for the ones executed during dialogues, but we'll leave them out of the discussion for the moment).ACTION: 2;IFOBJ SOBJ3;ADDRF 0,20,1
IFOBJ SOBJ3 tells us to perform the rest of the actions if we pointed to room object SOBJ3, and we did. What happens next? Well, 1 is added to the value of room flag 20 for room 0. More about flags later - suffice to say they are like variables in ordinary programming languages, and this particular flag is used to hold the player score in "Olaf". So you get one point for picking up the cup...ACTION: 2;IFOBJ ROBJ6;....
This is not a match, because the line is only relevant if we're trying to pick up ROBJ6. Going through the rest of the ACTION: 2;... lines in 1.room, we quickly discover that there are no more lines concering the mug there.ACTION: 2;IFCARR;SAY I Already have it!;EXIT
IFCARR says that if the object we refer to is already in the inventory, then let Olaf say "I already have it!". EXIT means no more tests on ACTION: statements will be done for our current input: The sentence line will be cleared and Olaf is ready to try something else.ACTION: 2;IFPICK;MOBJ;HANDLE;W 12;PICK;HANDLE -1;EXIT
Now behold the true power of the GRAAL. This is the stuff we have been tormenting ourselves for all along the tutorial up to this point!IFPICK;
If the object is "pickable"...MOBJ;
Olaf walks to the default offset position next to the object (as specified in the OBJECT: statement for the cup)...HANDLE;
Olaf stretches out a hand according to the HANDLE_MAP: animation...W 12;
and waits for about 1/4 of a second...PICK;
grabs the object (it disappears from the screen and enters the inventory list)...HANDLE -1;
lowers the hand again to the position it had before the HANDLE command...EXIT;
...and then we are done!ACTION: 2;IFTYPE -;SAY That was rather far-fetched, wasn't it?;EXIT
IFTYPE -;
This checks if the referred object was an abstract object, like the horizon in the Constantinople harbour. Since abstract objects can't very well be picked up under any circumstances, SAY That was rather far-fetched, wasn't it?;EXIT
makes Olaf "speak" this sentence using the talk-map corresponding to his current position on the screen.ACTION: 2;SAY I can't pick that up.;EXIT
gives a rather dull but to-the-point message to the player. Don't go erasing ACTION: statements in the supplied example main script altogether the first thing you do - a lot of these "safety net" actions should be in almost any game, although you should of course alter the wording and detailed behaviour to suit your own needs! Special ACTION: Statements
The verb numbers corresponding to normal player input goes from 1 and upwards. Instead of an ordinary verb number, the following can appear as the first parameter of an ACTION: statement:0
(zero) - the verb number used for "go to" (that is, clicking an exit. See ``Using Exits'' on page 36).
-1
Timer events. See ``Timer Events'' on page 62.
-2
Things to do after a LOAD or RESUME command. See ``The Load / Save Room.'' on page 63.
?
means any normal verb number from 1 and upwards will match this statement. For example, you may have a room where no ordinary actions should be possible. All player input (except exit movements) could then be trapped in the room script with a singleACTION: ?;EXIT
statement. Repeating Verbs and Conditions
If the first parameter in an ACTION: statement reads=
the verb number and initial conditions from the action statement immediately above, saving you some typing if several statements begin in the same way. ACTION: 1;IFOBJ 2;IFOBJ2 21;MOBJ 21;SAY Here you go!;...
The second line will actually be interpreted as
ACTION: =;RESP R,4,Thank you very much!;EXIT
ACTION: 1;IFOBJ2;IFOBJ2 21;RESP R,4,Thank you very much!;EXIT
If only some of the initial conditions should be repeated, but a blank space in between conditions. Here's the example once more, this time repeating only the first condition:ACTION: 1;IFOBJ 2; ;IFOBJ2 21;MOBJ 21;SAY Here you go!;...
Now the second line will actually read
ACTION: =;RESP R,4,Thank you very much!;EXIT
ACTION: 1;IFOBJ2;RESP R,4,Thank you very much!;EXIT
The method can also be used to repeat the initial part of DACT: and LACT: statements.9 Using Exits
Now that we are familiar with the general behaviour of ACTION: statements, it is time to explain how exits work.ACTION: 0;IFOBJ 1;MEXIT;CIMG 12;GOTO 2,1
0;
was the verb number indicating an "exit click".IFOBJ 1;
tests if it was exit number 1 that was clicked.MEXIT;
is a special command that can only be used in ACTION: 0;... statements. It makes the main character move to the exit point specified in the EXIT: statement (not to be confused with the EXIT *command*, which is something completely different).CIMG 12
Perhaps we wish the character to face the door before exiting.GOTO 2,1
is a command specifying which room and entrance to go to. Voilà!10 The DACT: Statements
In each room script, there must be at least one DACT: statement. The DACT: statements contain conditions and commands that are run through each time the room is entered. The flow of control is the same as for ACTION: statements: If a condition is not met, the rest of that DACT: statement is disregarded, and if an EXIT command is encountered, no more DACT: lines will be checked this time around.11 Flags and String Variables
In order to keep track of what is going on in your adventure, you need a way to store information about the player's actions. In GRAAL, there are two forms of variables that can be used to stora information: Flags and string variables.11.1 Flags
Flags can hold integer numbers. There are 20 flags for each room and 6 for each object. In reality, you can use any flag for any purpose you like, but naturally it is most logical to keep information regarding a certain room in that room's room flags, information about an object in its own object flags, and so on. Also, this is often most convenient - if you refer to the current room's or object's flags, you don't have to specify the room or object number in most flag-handling conditions and commands.11.2 String Variables
In addition to the flags, there are 12 "global" string variables that can hold text strings like the player name, or just snippets of text you have to repeat in several text-displaying commands. There are commands to set and test string variable contents, and there is also a PROMPT command that asks the player for input. The PROMPT command uses the dialogue area to display a prompt on the first line and a text cursor on the second line. The player then enters the text of his choice, and ends the input by pressing the Enter key. Simple as that.12 Displaying text
There are a number of commands that share the same routines when displaying text messages on the screen: SAY, THINK, RESP, TEXT, and the dialogue lines in the LINE: statements (see next chapter). Here's what you can do to spice up the messages to your player:12.1 Text styles
SAY, THINK, RESP, and LINE: all take care of displaying the sentences "spoken" by the characters in the game. You can set the general properties for how this text should look with the SPEECH_LAYOUT: statement in graal.main. You can choose between transparent, semi-transparent or solid background, square, rounded or cartoon-style speech bubbles, and so on.12.2 Variables and Other Special Strings
The value of any room flag, object flag or string variable can be shown in sentences. SAY I have #O#1#1# gold coins
may come out as "I have 23 gold coins".I can't see #W13#.
will display as "I can't see it".12.3 Audio Information
Starting with GRAAL 2.3, you have the option of making a GRAAL "talkie", that is, have spoken dialogue instead of just plain old text displays. The SPEECHMODE command decides whether GRAAL should use text, audio or both. (Switching this via a command means you can code set-up screens where the players can chosse which type of output they want.)SAY <sample/D/D/D>This is the text to be spoken.
For random alternatives, an audio info string must be related to each alternative for a complete sound track:SAY <cantdothat/D/D/D>I can't do that.|<impossible/D/D/D>That is
impossible!
If no audio information is available for a string, the text is always displayed in the normal way regardless of audio setting.13 Having a Chat

In the bar where the game starts, there is a bearded bartender who is very likely to become the first person Olaf speaks to. Let's look at how this is done.
Note: The examples in this chapter is for a "Text only" adventure, whereas the current Olaf demo also has some audio information appended to each sentence that the characters speak in room 1. See ``Audio Information'' on page 40.
First of all, any character involved in conversations must be defined as an object using an OBJECT: statement - it can be a global, section or room object. There is nothing special with the definition: Just make sure the object is visible and placed in the room where the dialogue takes place. Also, assign an animation channel to it.
DLG: 1;5;11;-20;A 0,(RIMG4,12)(RIMG6,24)...
1;
means this is dialogue speech definition number one. 5;
means that the appearance of the speaking partner is defined by global object 5 (the bartender).11;
is the colour used for the text displayed when the bartender speaks.20;
determines how far above the bartender's head the text is displayed.A 0,(RIMG4,12)(RIMG6,24)....
is the animation used when the bartender talks.ACTION: 5;IFOBJ 5;IFOF 1=0;MOBJ;SAY Hello;RESP R,1,Hello,yourself;
DSET 1,+3,+7,+9,+11,+12;EXIT
5;
the verb is TALK TO - we have a matchIFOBJ 5;
the object is the BEARDED MAN/BARTENDER - we still have a matchIFOF 1=0;
Hello, what's this? It's a test of an object flag, as mentioned in ``Flags and String Variables'' on page 38. By assigning values to flags and testing them, you can keep track of everything that has happened to an object - it's up to you to decide what to use the flags for. In this case, I have decided to use flag 1 for the bartender to see if this is the first time ever we talk to him. All flags are initially 0, so this test - IFOF 1=0 - is true in our case. Before the dialogue is ended, the flag values will be set to 1 to indicate that next time around, we should resume the conversation in a slightly different manner.
OK, on with it:
MOBJ;
We move up to the bartender just like we move up to any object before manipulating it.SAY Hello;
Say "Hello".RESP R,1,Hello, yourself.;
This is the bartender's response. "1" means GRAAL will look up the statement DSET 1,+3,+7,+9,+11,+12
This command engages us in dialogue number one and tells GRAAL to add the four dialogue alternatives 3, 7, 9, 11 and 12 to the list of possible lines for Olaf to speak. Since this is the first DSET command ever to be performed for dialogue one, they will be the ONLY four alternatives.EXIT
exits the parsing of the TALK TO command, and leaves us to get on with the dialogue - the player now has to select a dialogue line from the dialogue area which has replaced the normal control area.LINE: 1;3;What is this place?;Where did you say I was?;
1;3;
means this is line 3 of dialogue 1What is this place?;
This is the line appearing in the dialogue command area (where the player can choose a line to say) when the alternative is previously unused.Where did you say I was?;
is the version that will appear if the alternative is "re-used". If this second version is specified as a blank space only, the first version of the sentence will always be used.LINE: 1;7;Do you know anything about the ship in the harbour?; ;IFOF 2=1
First of all, notice there is no second version of this line. The question will always look the same, regardless of how many times Olaf puts it to the poor bartender.What is this place?
However, if he trundles off to the harbour to look at the ship, and only then returns to talk to the bartender, line 7
My head hurts.
Could you help me, please...
Do you know anything about the ship in the harbour?
is also available.My head hurts.
This means the number "11" is returned. GRAAL now starts to search for LACT: statements starting with 1;11; - there had better be one, or nothing will happen! Fortunately, there is:LACT: 1;11;RESP R,1,That's probably because...;DSET 1,N11
This is a typical example of a simple response to a dialogue line. The bartender speaks, and then another DSET command is given. Because we already are in dialogue mode, this command only "refreshes" the dialogue - that is, makes alterations to the current set of valid alternatives. In this case, the adjustment is to take away line 11 and tell GRAAL that it should never been shown again. That's what N11 means.What is this place?
The response to this one is a bit more substantial. The bartender makes a long response - so long, in fact, that is does not fit into one LACT: statement with ease. Instead, there are two statements, performed in sequence. When using this technique, remember NOT to put an EXIT or DSET command at the end of the first statement, because that would interrupt the process and prohibit the second statement from being executed!NAME bartender;
command, renaming object 5 "bartender" if it has not been done already.EDLG;EXIT
is performed, which switches the game back to normal input mode. As you se in the LACT statement, object flag 1 for the bartender is set to 1 with a SETOF (set object flag) command to indicate that if we TALK TO the bartender again, it is a resumed conversation - the initial "hellos" will be expressed a bit differently.14 Multiple Characters and Inventories
In the dialogues described in the previous chapter, the "speaking partners" were little more than ordinary objects, animated to make them look and act like human beings (or wizards, hobbits, monsters... take your pick). 14.1 Multiple Character Graphics
To make the multiple character feature feasible, each character uses the same animation patterns, sequences and default still images as the main (default) character. The only thing that differs between the characters are the image numbers being used.STILL_...
statements are defined only for the main character, exactly the same way as in single-character games. Also, the CIMG command expects you to specify an image number for the main character, and then automatically uses the corresponding image for the currently controlled character instead, and the same goes for the IFCIMG condition.
PAUSE_...
WALK_...
HANDLE_MAP: ...
TALK_MAP: ...
/* Clipart file containing all graphics for the main character
in graal.main should take care of that.
CLPART: main_character.iff
/* The IMGS: statements below grab 3*10=30 images
IMGS: 10;11;...
IMGS: 10;21;...
IMGS: 10;31;...
CLPART: second_character.iff
would place the graphics for the second character in slots 41 to 70.
IMGS: 10;41;...
IMGS: 10;51;...
IMGS: 10;61;...
14.2 Character Objects
Each controllable character must be a global object, although they may not be treated as such on screen - you can choose if the name should appear when you move the mouse pointer over the character in the scene area or not.
Now, we need to tell GRAAL that there are multiple controllable characters in the game, and define some more properties for them that cannot be deduced from their respective OBJECT: definitions. This is done with CHAR: statements:
CHAR: no;object;stimg;eimg;floor;colour;height;text_offset;width;speed;
im_height;im_width
nois the character number. The main (default) character is always number 1, and if CHAR: statements are used at all, there MUST be one for character number 1!
objectThis is the object number of the object defining the character, as discussed earlier.
startimage;endimageThese parameters define the first and last image number of the "image block" containing all default character graphics.
startfloorThis one may seem a little odd. Each character's starting position in the game is defined by the room and x/y parameters of the OBJECT: statement, but we also need to know what floor in the room contains that point, which is a piece of information not available in the OBJECT: statement.
colour;height;text_offset;width;speedWhen using a only one controllable character, all these things are set in separate statements.
im_height;im_widthThis is the height and width of the graphic images that make up the display of your character - refer to its IMGS: paremeters to get the values. (The height and width specified before is the approximate character height and width, but the character seldom takes upp all the space within the cut-out images!)
Examples:
CHAR: 1;1;11;40;2;11;40;10;20;1.2;47;31Character 1 is global object 1, occupies image slots 11-40, and starts out on floor 2 - the room and exact position are specified in the object definition.
Furthermore, it uses text colour 11, is about 40 pixels high, has an extra 10 pixels above its head to the place where related text is displayed, is 20 pixels wide, and walks at a speed of 1.2. (This is one of the very few floating point numbers used in GRAAL!) The images are 47 pixels high and 31 pixels wide
CHAR: 2;20;41;70;1;4;0;40;18;1.5;35;20Character 2 is global object 20, occupies image slots 41-70, and starts out on floor 1 - once again, the room and exact position are specified in the object definition.
It uses colour 4, its height is set to 0 which makes the mouse pointer point to its feet, the text is displayed 40 pixels higher up than that, it is 18 pixels wide and uses a walking speed of 1.5. The images are 35 pixels high and 20 wide.
Note that if your various controllable characters are of different heights, it is probably a very wise thing to set the height to 0 as in this example, otherwise offsets from objects and the mouse cursor will look very strange indeed.
Well, here it is. Switching between characters is r-e-a-l-l-y easy - in fact, I can't think of a single way to make it any easier. The command to use is simply
SWITCH character
INVENTORY 2,U;SWITCH 2would switch to inventory 2 (and update the command area to show the change), and then also immediately switch to character 2.
Note: The inventory switching is handled completely separately from the character switching, and there is no law that says character 1 must use inventory 1 and so forth. This is because you may want to switch inventory lists for other purposes than switching characters!
Another note: The default inventory is inventory 1. (There's a big shock for you... :)
To make an object start out in an inventory rather than in a room, you use a special form of room number in the OBJECT: statement room parameter. Simply type an "I" followed by the inventory number:
I2will place the object in inventory 2.
PICK, GET, and PUT commands always work with the currently selected inventory. To place things in another inventory than the currently selected, you must use the PUT command specifying the inventory in a similar way to the OBJECT: statement room number:
PUT 4,U,I2would move object 4 to inventory 2. The parameter "U" indicates that the move is made from the current inventory, since U means we wish to update the inventory display to show the change.
Technically, each inventory is a room number, calculated by
1000 - inventory number = inventory room
which means inventory 1 is actually room 999. This concept works as long as you don't have more than 995 rooms in your game, and I really don't think you do...
FOLLOW character,startx,starty,followx,followy
will cause the specified character to follow the one under player control around.
This continues until a SWITCH command switches the control to another character, or you give a FOLLOW OFF command.
The parameters following the character specification deals with where the following character will position itself in relation to the current character.
Generally speaking, it will strive to always stop "behind" the controlled character.
startx,startyAfter a FOLLOW command has been given, any GOTO command moving the controlled character to a new room will cause the following character to go there, too. startx specifies the number of pixels between the characters. It is the Left/Right/Middle parameter of the START_POS: statement that determines whether the following character will be to the left or the right of the controlled one. Thus, it should always be a positive number; GRAAL determines the actual sign. starty should normally be a small, negative number.
followx, followyThese number work about the same way as startx and starty, except they determine the offset between the characters after having walked around in a room. Both numbers should always be positive: GRAAL "knows" where to place the following character in most cases.
Note that when the controlled character goes next to a floor boundary, the following character probably ends up a few pixels off that floor, depending on your offset settings. There are two things to remember about this:
IFCHAR characteris TRUE if the current character under player control is the specified character.
IFHERE objectis TRUE if the specified object is in the room. Note that the parameter is the object number and not the character number - because this may also come in handy for other objects apart from characters.
This chapter deals with designing your main character and planning your graphics, something that must be done with some thought and consideration - although small adjustments are easy to make at any stage during the game development, things like the character size influence every other piece of graphics you create, so beware!
Naturally, how you want the backdrops to relate to the main character is also a factor - is he a small guy in a big, cruel world, or an ace detective always moving around in cramped Victorian tunnels and Baker Street studies?
Colours not used for portrayal of the main character, or frequently occurring objects, can change according to the current scene - the more colours you have left to play with, the more variation you can bring to the backdrops.
15.3 Pointer Shapes and Colours
The shape of the two mouse pointers used in GRAAL can be changed in graal.main by using the ARROW_CURSOR: and CROSSHAIR_CURSOR: statements.
0 Black (transparent. Do NOT use this for the black parts of the backdrop itself!)
1 White
2 Black (Use THIS for the black parts of the backdrop picture!)
17 Pointer colour 1
18 Pointer colour 2
19 Pointer colour 3
To get the animation smooth, it should be designed to work with frame updating taking place every 6th vertical blank. This may sound like nonsense to you, but what it means is that you can switch the animation cel every six 50ths of a second, which equals six frames displayed on a PAL TV system (or 60ths of a second on an NTSC system).
Actually, too many animation cels for a certain movement may not necessarily add that much to the game anyway. Olaf uses only 5 cels for a basic walking movement, each cel being shown for 6 50ths of a second.
So, now you should have you basic animations designed. Good. First, test them against some different backdrops that you think will be representative for the game in your excellent paint program.
Then, satisfied that your character basically looks OK, you should now design a "dummy room" in GRAAL, place some "dummy objects" in that room that will force your character to use all his newly learned physical skills. Then, give him a good work-out.
PTRN n
which tells GRAAL to go look for the animation code in a script called n.ptrn. Here is part of the pattern script for the captain's movements as described above:
/* The captain's standard movements for room 3The pattern contains three things:
/*
S:
A 15,(RIMG6,6)(RIMG5,6)(RIMG4,6)(RIMG7,6)(RIMG8,6)(RIMG7,6)...
M 20,0,70 M 20,10,150 M 98,-6,200
A 1,(RIMG4,100)
M 0,0,100
A 3,(RIMG9,72)(RIMG10,128)
M 6,0,1
M 0,0,499
A 1,(RIMG4,50)
M -6,0,1
M 0,0,49
A 15,(//RIMG6,6)(//RIMG5,6)(//RIMG4,6)(//RIMG7,6)(//RIMG8,6)...
...
A 1,(//RIMG4,500)
M 6,0,1
M 0,0,499
J S
The rest of the script is made up of "blocks" where we first specify an animation sequence, and how many times it should be repeated, and then one or more movement commands that decide how the object is to be moved during that animation.
In the M(ove) commands, the first number is the number of pixels to move left or right (negative numbers = left), the second is the number of pixels to move up or down (negative numbers = up), and the third is the number of frames the movement should take. Note that only the M(ove) commands control the timing of the program. If one or move M(ove) commands before the A(nimation) command has run out of frames to display, the program still moves on to the next A(nimation) command. This means that in most cases, the total number of frames that the A(nimation) command takes should match the number of frames the corresponding M(ove) command(s) will take.
This way, the entire animation will keep in sync.
To specify a "still image" in the middle of the pattern, do like this:
A 1,(RIMG4,100)Here, RIMG4 is shown for a hundred frames, and during that time, the M 0,0,100 command keeps it still, because it is told to move nowhere (0,0).
M 0,0,100
The rule is, if you run the risk of having the same image in both the original and the flipped version on screen at the same time, you have to make the flipped version into a proper image in the image bank, with its own image number.
This simple fact allows us to play with foreground and background objects. Anything placed towards the bottom of the screen will, generally speaking, be "in front". I'm talking about objects as well as STATIC: and ANIM: images now, mind you - everything drawn directly onto the background picture will naturally always be part of the background!
So, as a rule anything lower down goes "in front" of anything further up, but that's not necessarily the way we want people to perceive things - take the mug on top of the barrel in the bar in room 1, for instance. Looking only at the placement of the images of the mug and the barrel, the mug should logically be partly hidden by the barrel, because it is further up the picture. It's not. Instead, it looks like it is placed ON the barrel, which is what we want. Also, when Olaf walks behind the barrel, he must also walk behind the mug - if the mug is on the barrel but Olaf seems to be walking in front of the mug but behind the barrel, everything becomes hideously unrealistic.
The answer to this problem? It's simply a matter of setting each image's hotspot correctly. The hotspot is the point of each image that will actually be placed at the x and y coordinate specified when displaying the image.
Each image has its own hotspot, and it is normally set when the image is loaded with an ...IMGS: statement (the last parameter - look it up in the reference). The GRAAL default is to place the hotspot at the middle of the bottom edge of the image - you might say at the "foot" of the image. This is normally very appropriate, especially so for people and living objects. But you can place the hotspot anywhere you like - if you specify a value other than the default, the hotspot will be offset in the y direction that number of pixels from the top edge of the image. Both negative and positive values are allowed, and hotspots can be placed outside the actual width and height of the image.
Study the ROOMIMGS: statement for the mug image in room one, compare that to the mug's x and y position in the OBJECT: statement in graal.main, and you will see that the hotspot is placed well below the actual image, making it the "frontmost" object in the bar.
The hotspot of an image can also be altered using the HOTSP command - this is used in some cutscenes dealing with the ship in the harbour, to switch the depth-placing of the sail. This is because the captain first walks behind the sail, but when summoned ashore, he suddenly has to go in front of it! The solution? Just alter the sail's hotspot and re-display the image using new coordinates!
To begin with, the 3D scaling process relies on the information about graphics stored in the CHAR: statements in graal.main. So even if you only have one controllable character, you have to create a global object and a CHAR: statement for it, as discussed in ``Multiple Characters and Inventories'' on page 46.
After that, the process is a simple one: At the very start of a room script, put a
3D:
statement. (See the on-line reference for details).
Depending on the command used to start the cutscene, the command area either disappears completely, has a special "cut-scene icon" overlaying part of it, or remains totally unaffected (although still unusable until the cutscene has ended). You may use this to alter the degree of "movie-feel" the cutscene invokes. Cutscenes that are so short that the player hardly notices anything special happening control-wise should NOT mess with the display of the command area.
The immense usefulness of cutscenes may not be apparent at first, but you will soon find out that you use quite a lot of them - because in addition to being used for "movie scenes", they are also very handy whenever you have a sequence of GRAAL commands that you need to use in a lot of different places. In these cases, cutscenes can act the way procedures or subroutines do in ordinary programming languages. In those cases, you must make sure the entire cutscene is executed, and you probably don't want to show the cutscene indicator to the player. It's easy enough - just read on!
The logic of cutscenes ought to be a fairly simple subject, since there are no conditions allowed in them. In practice, two things require you to think very carefully about designing your cutscenes: The "skip" function (pressing the [Esc] key to jump past a cutscene) and nested cutscenes.
The FINAL section is ONLY used if the [Esc] key was pressed during execution of the main part. It must duplicate all statements necessary to set the scene exactly the same way it would have been set if the main part had been run through completely. Remember, you never know exactly where in the flow of the main part the player decides to press [Esc] to break out of the action!
"Why on earth would I want to do that?" you ask. Well, a good example is the harbour scene in room 3 of "Olaf". There are a number of occasions when Olaf needs to interact with the captain, calling him ashore time and time again. The captain's going ashore and aboard can not be handled as simple PTRN sequences, because he, the ship itself, and the sail need to be rearranged in various ways to make the captain go behind the sail, in front of the sail but behind the gangplank, etc.
Therefore, the captain going ashore is played using one cutscene, the going aboard in another (well, actually two, depending on whether his hat is secured with the rubber band or not). These cutscenes are then used from within, or in conjunction with, a number of others specifying what is going on when the captain comes ashore to talk to Olaf.
Let us call the first cutscene the "master scene" and those called from within that "sub-scenes". Now, what we have to watch out for is this:
If we press [Esc] at the very beginning of the master scene, or indeed anywhere before the last sub-scene, this means some of the sub-scenes will not come into play at all. However, the contents in each sub-scene may affect how the game should be set up at the end of the master scene.
To conclusion is that the FINAL section of the master scene also must include all statements that are present in the FINAL sections of the relevant sub-scenes. Let's look at Olaf and the captain again, when Olaf tries to use the dictionary on the captain and gets it all wrong. This is depicted in CUTSCENE 13 structured like this:
First, you use a DOAFTER command to set one of three "timer devices" to go off after a certain period of time (and this can also be a random amount).
Next, you specify a number of ACTION: -1;... statements, because each time a timer reaches zero, it goes through the list of ACTION: -1;... statements to see if it should do anything. (Each timer - there can be up to three running at the same time - uses its own "fake object number", so you can use IFOBJ conditions to see what statements belong to which timer if you have several running simultaneously.)
The timer will go on repeating itself, until you issue a CANCEL command for it. If you want the time between the timer events to change continuously, you should end each ACTION: -1,... command sequence with another DOAFTER for the same timer, specifying another random interval.
The timer device called "0" is a little special. It doesn't check the time elapsed since the DOAFTER command, but rather how long the player has been inactive. You can use this to trigger "stall anims" (like the one in "Simon the Sorcerer", where Simon puts on his headphones when nothing happens).
Normally, the cursor will flicker during execution of the ACTION: -1;... statements, because as always the player can't do anything while a command sequence is being executed. However, if the timer events are performed very quickly, you can use a TCURS ON command to stop the cursor from disappearing.
One of the uses for a timer is the concept of in-game date and time. GRAAL contains a number of commands and layout statements to set, advance, check, and automatically display the date and time, even on an analogue clock face with hands for the hours and minutes. (These things are displayed in special, reserved sections of the command area.)
There is more on each of these subjects in the command descriptions in the on-line reference.
The room is called by clicking verb 10, which is represented on screen by a diskette icon. Because the load/save room should be available everywhere, the code for jumping to it is in an
ACTION: 10;...statement in graal.main, containing the following:
Note 1: This means we now have ACTION: -2;... statements in graal.main that should always be executed after loading a game. So ACTION: -2;... statements in room and section scripts must never contain EXIT or GOTO commands, because this would prevent the statements in the main script from being executed!
Note 2: If you have designed your own save/load/quit functions, you could disable the ordinary short-cut keys for the standard requesters in the finished version of the game. You do this by putting a couple of DISABLE_... statements in the main script. Or, you could define your own save/load commands, pointing to your newly designed room, and map the standard short-cut keys (S/L/Q) to these commands. You do not necessarily have to put the "clickable areas" for these commands inside the command area visible to the player - if you put the areas off the screen with some coordinates like 500;500;501;501, you force the player to use the short-cut keys to access those commands.
Finally, remember that it is up to you to keep track of whether the command area is displayed or not every inch along the way - saving a game whilst the command area is not shown requires mechanisms to check out how it should be after each and every loading of a new game position.
The alley also demonstrates a typical use of the 3D scaling function - the way the 3D: statement is set up in 2.room, GRAAL uses 3 different image sizes to display Olaf, depending on how far into the alley he has gone.
First, the "foreign language" was "typed" in an ordinary picture (3FG.IFF) using DPAINT.
Then, the "words" were grabbed as room images using ROOMIMGS: statements.
Rajah's responses to Olaf dialogue lines are as follows:
This technique is useful in a lot of circumstances - many times, it relieves you of having to think up a lot of elaborate ideas for a room where you really don't want the player prowling around.
However, as soon as the seagull is scared off, Olaf is free to approach the pollard and pick up the feather. This is made possible by two FLOOR and one NFLOOR commands executed in the cutscene where the seagull takes off (4.scene).
Having chased the seagull away, one problem remains: The next time we re-enter the room, we want things to be the way they are now, and not according to how they are set up in the room script statements.
A room flag comes to the rescue here - it allows us to "remember" the seagull status between visits to the room.
Room flag 1 for the room (room 3) is used - as long as it is zero (the initial state), the seagull is on the pollard. As soon as the bird is scared off, we set the flag to 1 with a SETRF 1=1 command in the cutscene. This room flag is tested in a DACT: statement - if it is set to 1, the bird is moved to the roof of the shed, and the default floor definitions are changed exactly the same way as in cutscene 4.
Remember, as long as the LIGHTS ON command has not been used, the scene remains black and we can move anything we want around without the player being aware of what is done!
The movement of the llama and spit animations are synchronised - the llama being displayed on top of the spit. (Well, almost synchronised. If you leave the llama sequence on and walk away for a quarter of an hour, you will notice that things have become a little strange when you return. But who could keep away from the game that long, anyway? And if you don't like it, you can always make one big animation of the whole thing!)
Room 5 is an outline map of the East, showing the towns of Constantinople, Gurgan and Baghdad. The thing is, there is no Olaf, and nothing to do except watch a short cutscene and, when revisiting, point to one of the three towns. Also, this room does not use the command area at all - instead, the scene area itself takes up more space, and the command area is hidden.
Olaf was done away with by a simple CHAR OFF command in a DACT: statement - nothing strange about that (once you read the on-line reference). Remember that the main character will always be made visible when entering a new room, unless you put it away with CHAR OFF.
Because we don't need the command area for this room, each GOTO command leading into this room from other rooms is preceeded with a COMAREA OFF command. (See the load/save room above for more about hiding the command area.) In the room itself, a room flag for room 40 (the save/load room) is set to indicate the status of the command area (shown or hidden) - this flag is used in the save/load procedures, as described in ``The Load / Save Room.'' on page 63.
We need to make sure the command area is replaced when entering a new room. The only rooms Olaf can go to from room 5 is room 6 and room 7, so in each of these, a COMAREA ON command in the DACT: statements prior to LIGHTS ON restores the command area. (Keep the COMAREA ON commands close to LIGHTS ON to make sure the command area disappears/re-appears in sync with the scene area.)
19 The On-line Monitor
GRAAL's on-line monitor is a great help when things go wrong in your scripts. It allows you to examine flags and other information "on the fly", and also make temporary corrections. This helps to lower the number of times you have to restart GRAAL during the tests. (Naturally, the monitor cannot be called up from an encrypted game unless there is a DEBUG: statement in graal.main.)
These are the commands your are likely to use most:
Some rules:
Click once to activate. The trace console will open at the top of the scene area. Then click < Back to GRAAL> and provide GRAAL with some input.
As soon as GRAAL starts working on an input sentence, all conditions and commands about to be executed are shown in green in the trace console. For each command, you have to press a keyboard key to continue through the script. The full stop key is a good choice, because it also allows you to skip the pauses caused by commands like SAY and W(ait).
The text colour in the trace window changes from green to red while the command is being executed. An empty trace window means GRAAL is waiting for more player input.

To deactivate the trace mode, call up the monitor again and click < Trace > once more.
The trace mode can also be activated and deactivated from within scripts with the TRACE ON and TRACE OFF commands.
The primary use is for testing - being able to play the same sequence of events back over and over again, and having it done automatically, makes testing a whole lot easier. They are especially useful for running through parts of the game which are really "finished", but still need to be tested from time to time to check that no alterations you have made to other parts of the game affects them, or when changes to scripts means you cannot use old saved game files to put you in the desired part of the game.
The macro functions only work in development mode. In encrypted games, they are not available unless there is a DEBUG: statement in graal.main.
Tip: Before playing a macro, you may want to put the text display at maximum speed by pressing the [ I ] key a number of times first.
Changing the N_GLOBALIMGS:, N_SECTIONIMGS:, GLOBALOBJS: or SECTIONOBJS: statements offsets the image and object numbers, and previously recorded macros will stop working. That's a very good reason to set them reasonably high right from the beginning.
On line 2 (and nowhere else): The common part of the delivery diskette volume name, for example
MYADVENTURE_DISK
When GDC does its stuff later, the diskettes will be labelled
MYADVENTURE_DISK A MYADVENTURE_DISK Band so on.
Below line 3: The names of all the files, grouped according to delivery diskette. Each file name is on its own line, preceded by the diskette suffix and a space. For example:
A 1.roommeans the script file 1.room is delivered on MYADVENTURE_DISK A.
Remember: The files should be grouped according to volume, and the groups should be sorted alphabetically, starting with everything on diskette A.
You may have as many comment lines and empty lines in between the file entries as you like.
The following stuff should ALWAYS be on diskette A:
1) GRAAL_2 *
The main program. It does not have to be called GRAAL_2 - rename it to anything you want your adventure called.
2) FONTS *
A special entry which copies the entire fonts: drawer in your development directory.
3) graal.main
The graal.main script file
4) diskinfo.graal *
5) The picture files for the command and dialogue areas (if you don't specify DEFAULT, in which case the graphics included in the GRAAL_2 program itself are used).
6) The resource file for requesters (suffix .rsb). If you use the DEFAULT, no entry is needed - it's already in the GRAAL_2 program itself.
The asterisk (*) after some of the file names tells GPRO not to compress and encrypt these files (see below). Apart from the files above, always mark all user documentation and icon (.info) files with asterisks in the same manner!!
The GREP program starts by inspecting the main script, and from there it goes on to find all references to all files used by your adventure.(This, of course, requires that a proper START_ROOM: statement exists in graal.main, otherwise it will not find all the information.)
GREP creates a report over what files are used where, and also gives you helpful suggestions regarding the contents of your diskinfo.graal file and some of the statement settings in graal.main. This information is saved in a file called graal.report.
You can start GREP in two ways:
You should test the adventure thoroughly in the test directory, making sure everything is included, before making the delivery diskettes. (GDC is automatically copied from development to this test directory by gpro, because you need it there to make the diskettes.)
This program is only available to registered users (in other words, it needs the personal keyfile to work). Unregistered users are confined to copying the game files directly onto the delivery diskettes from the development directory using GDC, and then testing the diskettes.
GPRO now checks if there is a valid graal.key file in the directory. If not, it will say so, urge you to register GRAAL, and terminate.
The user interface is as follows:

< > No: Do a normal file copy.
Note that the selected file is renamed diskinfo.graal (the default name) in the destination directory, and therefore, diskinfo.graal is the name that should ALWAYS be used when referring to the diskinfo file IN the diskinfo file!
GPRO saves the names of the last diskinfo file and destination directory in a file, and so remembers the settings until the next time it is used.
The following files/diskinfo entries should NEVER be compressed during copying:
GRAAL_2 icon files documentation files graal.key diskinfo.graal
To make sure a file is never encrypted, just put a space and an asterisk after the file name in the diskinfo.graal file, for example:
A Disk.info *
Of course, you may want to compress GRAAL_2 to save disk space, but do so before the final copying process, and use a utility that creates a self-decompressing executable file (like PowerPacker or CrunchMania).
Note that encrypted games DO NOT require the keyfile to run, and the key file must never be distributed with your finished games. It's your private property!
The compression routine puts the emphasis on speed rather than efficiency. On average, 30%-40% less space is used by a compressed adventure.
The percentage gained varies greatly with the structure and complexity of the files. Some examples:
120K tracker module gained 42%
GRAAL games with compressed files require up to 200K or so extra RAM space to do their job. Running a reasonably large adventure thus takes a little more than 1,5MB...
On fast machines, I perceive a performance increase running compressed games, but perhaps that's only my imagination... It's not unreasonable, though, that the reduced disk access more than makes up for the unpacking time.
On slow machines, the unpacking time becomes more noticeable, and running a GRAAL game on an unexpanded 68000 machine with no memory cacheing can be a nuisance. To help out a little, consider NOT compressing and encrypting long sound samples, and perhaps you could leave the tracker modules alone, too. Because the tracker modules are probably the biggest files you have, this will also save some working space (perhaps a 100K or so).
However, GDC is not intended for making copies of the game. Just use GDC to make the "master diskettes", and then use some proper diskette copying software for the copies.
If you have run GPRO, the GDC program was copied to the test directory automatically, and you should run it from there.
If you don't have access to GPRO, you run GDC directly from the development directory.
GDC runs from CLI only. Open a shell, and switch to the appropriate directory. Then type RUN GDC. (Don't forget the "RUN" bit, or GDC may lock up during the copying process!)

The "gauges" or "meters" labelled A, B, and so on, are updated to show how much space is used on each disk. If you have specified too much for a certain volume in the diskinfo file, the top of that meter turns red to show that you must edit the diskinfo file and re-distribute the files to make it all fit. (We're talking standard DD diskettes here, of course.)
If you have left GDC running while editing the file, you could use the button to re-calculate the space requirements. On the other hand, it might be a good idea to exit the program, make sure you update the right file in the right place, and only then re-run GDC...
You don't need more than 18 diskettes, do you? Please! Tell me you don't!
NICE TIP: It's good practice to keep the diskinfo.graal file updated during development. Start GDC now and then to see if the distribution of files seem about right with respect to the space requirements... Also, use GREP to check that the diskinfo.graal information is correct.
At first, you may find the concept behind it all slightly confusing. While other "user-friendly" games development systems opt for point-and-click control of everything, storing the results away in cryptic databases, GRAAL is basically made up of ASCII scripts that can be created using any text editor. While this means more typing and requires a deeper understanding of what's going on, it also has some definite advantages. It means greater flexibility in your creations, a better overview, and a total freedom when it comes to documenting the scripts via comment lines. And the GRAAL editor steps in to bring you the best of the "point'n'click world", too. It makes the typing of the scripts a lot easier, and you will not want to be without it.
In short, the editor spares you from annoying things such as trying to remember what script does what, what the parameters of that "OBJECT:" statement mean, and what the coordinates of your last 6 FLOOR: and PATH: definitions actually looks like on screen. The end result is the same as you would get with any other editor, though - ASCII script files with lists of GRAAL statements and commands.
In addition, the GRAAL editor has the following advantages:
amigaguide.library v. 34 or later must be in your LIBS: drawer. (This can be found for free on Aminet.)
On AGA machines, the editor screen "clones" your Workbench setting by default. If you have a hi-res Workbench, it uses a hi-res screen; with a Productivity Workbench, it opens in Productivity mode... you get the picture. Just make sure that your Workbench is at least 640 pixels wide, and everything should operate smoothly. (The screen mode can be customised using the tooltypes in the GRAAL Editor icon - see the end of this chapter.)
On non-AGA machines, a normal hi-res, non-interlaced screen is always used.
Also note that the editor must be placed in your game development library on your hard disk for all file fetching routines to operate without problems. The GRAAL.guide file should also be placed in the same directory.
CPU NOCACHE NOBURST

If there is no main script, the editor asks if one should be created. If you answer "yes", a template for such a script will be created in the editing window (which makes up the main part of the editor display).
You can also use the "New" option in the "Project" menu to create a new script. The "New" option has six suboptions. The first one, "empty", just opens a new, empty editing window on top of the first one. The editor handles up to ten script windows simultaneously, and you can switch between them quite easily with the "Select Window" option in the "Edit" menu (or [Amiga>+[W>).
The suboption "graal.main" creates a main script template, as discussed above.
The last four suboptions, ".room", ".section", ".scene", and ".ptrn" creates a template for the specified script type. Before the template is shown, a requester pops up showing a recommended script number - this number is the first number not already occupied by any of the existing scripts. You can change it if you wish, but remember that it's a waste of space leaving unnecessary gaps in the number sequences.
The requester also has a gadget for a short script description - you should enter a meaningful description of the room, cutscene or whatever here. This comment is placed in the first (comment) line of the script, and you will see why it's so useful is a very short while... in the next section, as it were!
"Load general" brings up an ordinary file requester.
"Load graal.main file" loads the graal.main straight away - not much use asking for its name, because it's always the same.
"Load .room file" and so on brings up a list requester showing the numbers and descriptions (see above) of all existing scripts of the desired type, neatly sorted in ascending order.
Most of the time, you probably want to open a script in a new window, which is why you should use the "Load Another" option instead. It looks exactly like the "Load" options, but in this case, the suboptions have keyboard short-cuts ([amiga>+[3-8>). Learn to use them, as this is the quickest way to open scripts.
Note: scene scripts with a space in the name will not be properly treated by the loader. Simply put, do not use spaces in script names.
All this should make development a little less frustrating. However, GRAAL itself checks a lot of other stuff too, and will still throw runtime errors at you from time to time. Further improvements will probably appear over time.
Note: The syntax checker uses the script name suffix to determine what statements and commands are allowed - so it can only be used in scripts following the GRAAL naming conventions. And it does NOT work with pattern scripts.
Note that just like the syntax checker, the help function uses the script name suffix to determine what statements and commands are allowed - so it can only be used in scripts following the GRAAL naming conventions.
Just a few words about useful keyboard keys:
[shift]+[down arrow]
[shift]+[right arrow] Moves the cursor past the last character of
[shift]+[left arrow] Moves the cursor to the beginning of the line.
[control]+[right arrow] Moves to the next semi-colon of the line; that
[Esc] Closes the current window.
[enter] Exits a string gadget (for example, in the
Other available short-cut keys are all listed in the menus.
Use [amiga]+[w] to open a window containing a list of all currently open editing windows and their contents. In addition, all windows where unsaved changes exist are marked with an asterisk ( * ) before the window number.
Click on any name in the list, and that window will become active and placed on top of the other windows. You can also use the cursor keys and select a window with the [enter> key. In fact, the GRAAL text editing functions have been designed to make as little use of the mouse as possible - the keyboard is much faster once you get accustomed to using all short-cut keys.
If you need to view more than one script at the same time, just resize the editing windows and place them next to each other - nothing could be simpler. (Though I must confess I don't use this much myself - window switching is so much easier!)
The GREP program is described elsewhere in this manual.
This is how to do it:

UPPERCASE text entered by the cycle button should be kept as is. Occasionally, a text in lowercase may appear, which you should change to a proper value.
For example, if the text "obj" is shown as one of the cycle alternatives, this means you should replace "obj" with a proper object number.
If a statement or command contain parameters which can be edited in this way, one or more of the special editing buttons beneath the string gadgets will become available. They also have keyboard short-cuts in the form of keys [F1] to [F8].
Usually, the editor finds the relevant backdrop picture and room script to use automatically, but may occasionally ask you for a file name when it cannot decide which part of the adventure you are referring to.
Sometimes, the editor asks "Reload the object and image data?". If you haven't altered any images, or switched rooms or anything since the last time you used the graphical editing functions, you can answer "no", which speeds up the process.
If the backdrop picture is one of the rooms in your game, all previously defined objects placed in that room are also shown for reference. In many cases, floors and paths are also shown, with their respective numbers shown close to the center of the each floor and path. If the backdrop picture is wider than the screen, use the left and right cursor keys to scroll it.
Note: If objects overlap, the editor does not bother to sort them in the proper order.
The details of all the "graphical editing" operations are explained below, and there is also a brief help text on a screen directly below the picture you are about to edit. Once you are done, press "Enter" to save the changes, or "Esc" to cancel.
To re-size, click and drag the bottom left corner (the little square) of the rectangle. To move the rectangle, click and drag anywhere else on the screen.
If you use this option to edit the cut-out frames for images, you will get a number of rectangles on screen corresponding to the number of images to be cut out by the ...IMGS: statement. Use the leftmost rectangle to re-size: all duplicate frames will also be re-sized automatically. To alter the spacing between the frames, use the up and down cursor keys.

If the previous position and image used are known, the object or image will start out in its old position.
Click and hold the mouse button. Drag the mouse to move the image to the desired location and release. (If it's an object, a copy of the image will remain the object's previous position when you drag the image.)
To select another image, use the up and down cursor keys.
To flip the image left/right, press the "x" key.
Note: When you save the changes with the "Enter" key, the selected image will normally be placed in the "image" parameter. However, if the "image" parameter previously contained an animation sequence or a PTRN specification, it will NOT be affected. This is to prevent a lot of hard work being undone by an over-smart editor...

As from GRAAL 2.2, the Editor asks you if the character width should be taken into consideration. Answering "yes" means GRAAL will calculate the position of the edge of the character closest to the object, rather than the center of the image. This is only a concern if you have multiple characters with varying widths that can try to manipulate the object.
To add a new point, press the "arrow up" key. The new point will be inserted between the last and the second last point.
To delete a point, press the "arrow down" key. It is always the second last point that is deleted.

The "highlight ink" colour is only used in the sentence display area. It is the colour used when a completed sentence is highlighted during command execution.
Select the statement with [Enter], the <OK> button, or by clicking it a second time with the mouse. A new line containing the statement will be inserted at the cursor position, and the parameter editor window is opened automatically.
Similarly, positioning the cursor on a line that has a statement, but neither on the statement nor the existing command names, brings up a requester asking if you wish to insert a new condition or command. Be careful not to insert a new command in the middle of parameters belonging to another command...
Note: scene scripts can't contain statements. Therefore, it's always the condition/command list that appears when using the <Edit Parameters> function in an empty space.
SCREEN=WB|NTSC|PAL
(Note: The SCREEN tooltype only works with AGA machines.)
GRAAL=name Sets the name of the GRAAL driver program being started
IMAGEFILTER=filter
#?.iff|#?.pic|#?.i16|#?.i32|#?.i64
TRACKFILTER=filter
#?.trk|#?.track|#?.mod|#?.sng
SAMPLEFILTER=filter
#?.snd|#?.raw|#?.8svx
CHECKONSAVE=YES|NO
PAINTAPP=path:name [arguments]
a[3] Open new window & Load any file
a[S] Save
a[W] Select Window
a[K] Check Syntax
[Shift] + [Left Arrow] Start of line
[Help] Show Amigaguide help for current statement / command
[Esc] Close current window / requester
[F1] Run GRAAL from Editing Window
[F1]-[F8] Editing buttons in Parameter Editing Window
A: Use numbers below 60. Make sure a BOB number is never used for more than one thing at a time in the same room. Otherwise, no: No information is connected to or "belongs to" BOB numbers and their use, so there are no other fixed rules.
A: Same thing. Look up the reserved channel numbers in graal.guide, and make sure you never try to use the same channel for two things in the same room!
A: A room object can only exist in one room - therefore, it can never be picked up or added to the inventory. Nor can you use its object flags for very much, because they will be reset each time you exit the room.
ROBJ references should only exist in room scripts, never in .sect or graal.main!
A: A section object only exists within one section, and preferably disappears totally during the first visit to the section - otherwise, you must keep track of how the objects have been handled via room flags or such devices, if you happen to re-enter the section.
In other words, take particular care if your adventure is designed in such a way that you can go back to, for example, section 1 from section 2 - not only must you be sure that section 1 still looks okay with respect to section object use, but also, the section 2 section objects will suffer the same problems! Even if you haven't "solved" section 2 yet completely, going back to section 1 will end your first visit to section 2 and thus reset your section objects for section 2!!
SOBJ references should only be used in room and section scripts, not in the main script.
A: There are a couple of ways.
A) Try using PATH: statements.
These allow you to connect otherwise unconnected floors using "twisting" paths. Read more about the room PATH: statement in the on-line reference.
B) Use an un-named exit.
When you specify an EXIT: with no description, GRAAL shows no exit name in the scene area, nor does it put a "Go to ..." message in the sentence box when the exit is clicked. That way the un-named exit is just a "clickable area" in the scene area, and you can use ACTION: 0;... statements for it to do anything you like.
A: Yes, why not indeed? Just use EXIT: statements with no name/description to define the clickable areas needed on screen, and then ACTION: 0;... statements to handle the player input.
Or, define room objects that are actually buttons.
Or, use the multiple inventories and put your menu selecting in a special inventory, then access them with some special "select" command.
There's more than one way to fling an otter...
A: The neatest (and quickest) way is probably to put a "SCORE" button in the command area using the VERB_ZONE: and VERB_TEXT: statements in the main script. VERB_TEXT: allows you to define "direct verbs", that is, commands that do not wait for or use an object. If you define a verb "SCORE" and make that a direct verb, you can then use a TEXT command to display the score held in a flag (preferably a room flag for room 0 - as mentioned elsewhere, these make excellent "global flags").
Q: I don't quite understand the FLOOR: statements.
A: The best description is in graal.guide. Make sure you read ALL the information about FLOOR: and PATH: there - it's even got some diagrams! Then look at one of the rooms in the demo adventure to put theory to practice.
A: Check this:
A: Naughty you - you have probably used the undocumented MED-module feature of GRAAL! It can play MED modules (MMD0 and MMD1 formats), provided you have the file extension ".med" in the module name. However, this causes the above bug in the sample routines to appear - this is Amos's fault. I know there exists an Amos bugfix or work-around for this, but I DON'T HAVE IT. If anyone has seen it, mail it pronto, and the med support will be made official!
Q: The command area behaves strangely - it doesn't go away when I tell it to in CUTSCENE commands.
A: You have probably not put it back correctly in a previous cutscene. All sequences of events that start with either CUTSCENE ...,NF or CUTSCENE ...,F must end with an equivalent CUTSCENE ...,N or CUTSCENE ...,S. ALWAYS restore the command area before doing a DSET - it may seem the DSET restores it for you after the dialogue has ended, but not really 100%. This goes for the COMAREA command, too. COMAREA OFF is just another way of saying CUTSCENE "blank file",NF, and COMAREA ON is equivalent to CUTSCENE "blank file",N
Q: The song I'm playing with the TRACK command doesn't stop after playing through once, but starts over in a weird tempo.
A: Unfortunately, the tracker "stop song" command 0FFE stopped working with the tracker command set I started using in GRAAL 2.1. Fortunately, there is a way around this: At the very end of the song, put a blank block, and have that block repeat itself by putting a tracker "jump" command (0B..) in it.
Q: 1. A scaled character changes its size when it starts moving/stops moving.
A: You have been unlucky with the way the 3D scaling zones (in the room 3D: statement) coincide with the FLOOR: settings. There are a number of things you can try to make it all look nicer:
called from other cutscenes 62