Balloon Maker Tutorial

Ok, word of warning: this isn't going to be easy! You can't absorb this information passively like a TV program; instead you are going to have to learn a new way of thinking. You will come across a whole bunch of words you don't understand, some symbols you probably haven't seen before, and if you haven't done any programming before then you will definitely come across some things completely foreign to you (like strings, integers and floats).

My advice? DON'T PANIC!

If you are still reading this then I can confess that actually it is going to be easy, but you still need to put effort in. It won't happen on its own, and there is no known program that can turn your thoughts into reality at the press of a button. In this tutorial you'll be given a fully functioning piece of code, and we'll try and explain how (and why) it works. You don't have to remember every single command in the code, but as you look at more and more CAOS code you will find that certain commands are used all the time ... and others are very specific to a problem, and so not used by most agents.

You will need the following items to play along with this tutorial, if you haven't got them - go get them now!

Getting started
You should start a clean new world in Docking Station - call it whatever you like, this will be used for testing your agents.

It is always a good idea to create a new world when you are making agents. CAOS is powerful stuff, and it is possible to really mess up your world if things go disastrously wrong! If you don't mind the possibility of killing all your creatures, destroying various machines and knackering your carefully crafted world then ignore this top tip (but don't go crying to customer support).

So enough already - what are we doing exactly?
The subject of this tutorial will be a balloon making machine, which is a relatively simple agent that produces other agents. It is a good starting point because it covers various aspects of agent making - and it is easy to modify and make your own dispensers.

Open up the ZIP file and:

  1. Place the C16 file in your "Docking Station/Images" folder.
  2. Create a directory in your "Docking Station/Bootstrap" folder called "tutorial".
  3. Place the COS file in this "Docking Station/Bootstrap/tutorial" folder.

IMPORTANT! If you want to take a break from this tutorial and play DS properly you will need to remove your new bootstrap folder and the contents, if you don't you will find that you have some problems. Remember to put the folder back when you are ready to carry on with the tutorial.

Inject it for the first time ...
Ok, you've started up a new world and placed all the files in the right place. Now do this:

  1. In DS, press CTRL + Shift + C simultaneously. This opens up the CAOS Command Line (CCL) and allows you to enter CAOS straight into the engine.
  2. Type this into the CCL: ject "balloon_maker.cos" 7

Notice how the camera moves to somewhere completely out of the game world and a badly drawn object falls to the ground? Good. This is an early lesson in the best way to specify where you want something to inject to. Because we aren't injecting things using the normal agent injector (the page on the Comms Screen that lists all your expansion agents and allows you to inject/remove them), and because this is a game where the agent injector hasn't been used yet, we encounter an immediate problem. For now, don't worry about the why - we'll cover that later - for now do the following:

  1. If you closed your CCL open it up again (CTRL + SHIFT + C opens/closes the CCL)
  2. Type this: ject "balloon_maker.cos" 1
  3. Go to the Comms room (use the Favourite Place icon at the top to get back to the Norn area, and navigate as normal)
  4. Click the button to open the agent injector
  5. Inject any agent you like, although the autonamer is a good choice because it won't get in the way. Remember that to inject an agent you need to select the agent you want, and then click the green tick to inject it.
  6. Now type this into the CCL: ject "balloon_maker.cos" 7

This time you should see the same badly drawn agent appear near the agent injector - which is exactly what we want.

... and relax
Well, you've just used your first CAOS command - JECT. But what exactly did the bit in quotes do and what does the number at the end mean? This is where your motivation and brain come in! Open up your CAOS Language Guide (you can use any web browser) and find the JECT command. The entry for JECT tells you everything you need to know to start using it, but for a complete novice there is probably a lot still unanswered - like what do (command), (string) and (integer) mean - and what are Remove, Event and Install scripts?

The entries in the CAOS Language Guide show the syntax of the command - that is to say, how you construct the command. The syntax for JECT looks like this:

JECT (command) cos_file (string) flags (integer).

Which, in English, can be read like this "JECT is a command, which needs two pieces of information. The first piece of information needed is the name of a cos file - and this name must be given as a string. The second piece of information needed is a thing called 'flags' - which we know is an integer". If you look in the description for JECT it explains what 'flags' are possible.

String is a common term in programming and is the name of a data type. In DS we have 4 data types, illustrated below:

  1. String
    A string is a piece of text, characters, and is usually contained within double-quote marks. Examples of strings include; "this is a string", "hello", "mark", "eight".
  2. Integer
    An integer is a whole number. Examples of integers include; 5, 9, -12, 9872345.
  3. Float
    A float is a number specified with decimal places. Examples of floats include; 1.5, -25.75, 5.0, 99.99.
  4. Agent
    Agent is a special data type for DS, it is a pointer to an agent in the game. For now, don't worry about it beyond knowing that it exists as a data type

So, knowing what a string is you should understand better what you were doing when you typed ject "balloon_maker.cos" 7 into the CCL. It shouldn't surprise you to learn that "balloon_maker.cos" is a string, and is also the name of the file you placed into your Bootstrap/tutorial folder - what a coincidence. The value of 7 on the end is an integer and to understand what it signifies you need to look at the entry for JECT again. The CAOS Language Guide says that flags has the following meaning:

1 = Remove script
2 = Event scripts
4 = Install script

But what then does '7' signify? You will come across this kind of feature in many CAOS commands - to work out the value you have to break down the number (7) into the values allowed for this command. So, in this case, 7 is actually 1+2+4 ... i.e. every flag is set. This means that the JECT command with '7' at the end will inject remove script, the event scripts and the install script. For our COS file, this has the effect of removing all the balloons and all balloon makers - then injecting all the event scripts - and then injecting the installation script.

Remember earlier on, after we injected the agent for the first time, we used JECT again but with a value of '1'? It should be clear now that this forces the JECT command to only inject the Remove Script part. Similarly, if we used a value of '6' this would inject the Event and Install scripts (4+2=6) only. With our COS file this means we would not remove any existing balloons or balloon makers, but instead would just inject the events and create a new balloon maker.

So, the million dollar question, what are remove, event and install scripts? It is time to explain some of the basic features of a COS file!

The COS files provide a handy way to organise your CAOS code, and there are generally 3 sections to a COS file: the Install script, the Event scripts and the Remove script.

Out of these three parts, really only one of them is rigidly defined - and that is the event scripts. Event scripts always take the same form in CAOS (they start with SCRP [something] [something] [something] [something] and end with ENDM), whereas the Install and Remove scripts can be whatever you like ... they are just CAOS. For example, it is possible to make the remove script actually inject something if you wrote it that way, and vice versa with the install script! Also, each part is optional - it is possible to write a COS file that only has event scripts, for example. Don't worry if this doesn't make too much sense at the moment, just remember that there are usually these three parts to a COS file.

To put this into context, open up the 'balloon_maker.cos' file with Notepad and have a look at it. If you have the CAOS Tool (a tool by Creature Labs for working with COS files and CAOS) it will colour the commands, layout the text and generally make things easier to read. If you're using Notepad you will just see a lot of text, sorry. In a COS file, the asterisk () symbol marks a line as a comment. That is, everything on a line beginning with is not acted on by the game engine, which means you can write anything you like here - the usual reason for doing this is to explain what your code is trying to do. If you scroll down the COS file you will see the three sections marked with comments: install, event and remove scripts. The three parts are usually placed in this order too, with the install script at the top of the file, the remove script at the end of the file, and the events in the middle.

Time to investigate
Right, back to the task in hand! You should have a green box object in your Comms room, and it has two markings on it - one is a round balloon and the other is a cow balloon. If you move your hand over the buttons on the box you should see them change colour ... groovy. You can also pick up the box with the hand, but for now just leave it in the Comms room. Now press one of the buttons. You should see the button flash and a balloon will appear behind the box and start to float to the ceiling. If you press the other button a similar thing will happen, but importantly the type of balloon is different for each button. Note also that the balloons are a random colour each time. You can press the buttons a few times and you will soon have a lot of balloons stuck to the ceiling.

With time the balloons will start to descend from the ceiling; they won't stay there forever. Now let's investigate the balloons - you should be able to pick one up in the hand. Try throwing it around the room a bit and see how it acts. Pick up the box and throw that around - you should notice that the box 'feels' much heavier than the balloon ... it drops much quicker than the balloons. You can also click on a balloon to interact with it - clicking on a balloon makes it move slightly, but also there is a chance that you will pop the balloon and it will burst and fall to the floor (if it isn't there already).

Break it down
Looking at the COS file for this agent, it can be seen that there are the following sections to it:

It is easy to be overwhelmed when looking at a whole COS file, with lots of events. An easy way to get over this is to try to look at the events in isolation - remember that events always begin with SCRP [something] [something] [something] [something]. To be more precise, events always begin with SCRP [integer] [integer] [integer] [integer]. For more information on events, you can read the CDN article entitled: "Event information"

Bring it on
Things are going to get more in-depth now, hold on to something tight if you have a delicate constitution. Remember, all of the CAOS commands are 4 characters long (for example, NEW: or ATTR or ACCG or ANIM) and they are all listed in the CAOS Language Guide you created - you will need to refer to this document a lot as we go through the code.

Install Script
The very first part of the install script creates the balloon maker as a compound object. Later on when we look at how the balloons themselves are created we will see that they are an example of a simple object.

Simple and Compound objects are two of the main types of objects you can create in the game (the other types are skeletal creatures, and non-skeletal creatures - but we wont be dealing with them in this tutorial). One of the easiest ways to illustrate the difference between a simple and a compound object is to look at the sprite files. Open up the sprite file called 'ds portals.c16' - you will find this in your "Docking Station/Images" folder. This is the sprite file for the portable portals you can create in DS - notice that the images within the sprite file show the individual animation frames. The important thing to note is each image is complete, that is to say if you created something using frame 3 (for example) it would look like a portal - this is a simple object. Simple objects only have one part to them, and when you animate them the whole sprite changes. Now open up the image for the balloon maker (balloon_maker.c16) and look at those images. If this was a simple object we'd expect to see the same thing we see in the game - namely a green box with two buttons on it. Instead we see a plain green box, and then a couple of separate images for the buttons. With compound objects we can start off with a base part (the plain green box) and then add new parts to it - in our case we add two buttons, one uses the round balloon images and the other uses the cow balloon images. The reasons for this are to save on the number (and size) of images we need to animate a complex object. If you think about it, knowing what you know about how the balloon maker works, we'd need the following images if we were to make it as a simple object:

The advantage with compound objects is that you have more flexibility to create your objects and change them, and this is especially true if you want a variety of buttons on the object or it has a variety of complex animations. This balloon maker example is fairly trivial. The number of frames we'd need for a simple object version of this object isn't too many - all we have really saved by making it a compound object is the size of the image file. Now if you open up the sprite file called "comms.c16" you will see a big saving in terms of image size and number of animations. This file contains all the images for the Comms room screen ... which is made up of little parts. If this was created as a simple object we'd need many more frames of animation (one for every situation the screen can be in).

After having said all that, the major trick that compound objects have up their sleeves is the ability to attach special parts to them - such as buttons, text entry areas, text display areas, camera screens and even graphing gadgets. You'll meet your first parts any second now!

Ok, back to our code. The first line is NEW: COMP which is the command for creating a compound object. Look it up in the CAOS Language Guide to see what the integers and string following the command mean. You will find that these parameters define the classifier of the object, the sprite file to use, which images to use from this file, and finally its image plane - which is how far into the screen it appears. For this object we've said that it uses only one image contained in the file 'balloon_maker.c16' and that this image is at position 0 (the first image in the file). The first three of these parameters are collectively called the classifier and are a very special part of creating agents. Every single agent needs a classifer, and different agents need their own unique classifier. There is an article on the CDN that talks about CDN Classifiers in a bit more detail. The important bits to take away from this are:

For this tutorial, I have chosen a classifier reserved especially for this balloon maker (the balloons have their own classifer, also reserved). Notice that all balloons have the same classifier - this is because you want all balloons to act the same way. Each event script is linked to a particular classifer - you will notice that the first three integers of the SCRP command relate to the classifer of the agent they are for. The last part of the SCRP command is the event number, and these numbers are listed at the end of the CAOS Language Guide. When you come to create your own objects from scratch, you will need to get your own classifier. The CDN holds a classifier database that allows you to reserve a number for your use - you can access the historic database here. However, that's unlikely to benefit you, so instead see the newer database here or the massive spreadsheet here.

The next line in the balloon_maker.cos sets up the attributes of the object, again you should look at the CAOS Language Guide to see how we came up with the number 198 and what it actually means! There is an article on the CDN about attributes entitled "Attributes of agents". The things to remember about attributes are:

The next line defines the BHVR of the object, which dictates what actions a creature can take on the object. Next up, we have 3 commands (ELAS, AERO, ACCG) that help refine the physical properties of our object - these are only relevant because the object has physics and suffers collisions. Altering these values affects how quickly something falls to the floor (ACCG), how much of its velocity it loses because of 'air resistance' (AERO) and how much of its velocity it loses when it hits the floor (ELAS).

At this point you might want to make a few small changes to the properties of the object to get the hang of how they interact. Remember, if you want to remove all the balloon makers from the game you need to type ject "balloon_maker.cos" 1, and if you want to inject a new one you should type ject "balloon_maker.cos" 7.

Here are some things you can try:

Ok, we've nearly finished looking at the Install Script, just a few more lines to go! If you've altered the COS file make sure you put it back to how it was (ELAS 5, AERO 10, ACCG 10).

The next line in the install script is PAT: BUTT. This takes a large number of parameters so be careful when comparing it to the CAOS Language Guide entry. The first parameter is part_id, which we've given a value of '1'. Every part of a compound object needs a unique ID number. These don't have to be sequential (1, then 2, then 3 etc) but it makes sense to write them sequentially. So, part 0 is actually the base part we created with the NEW: COMP command and now we've made a part 1 too.

Carrying on reading the PAT: BUTT line we see a reference to the sprite file to use, which image in this file is to be considered the first image for this part and how many images (from 'first image') are to be considered to 'belong' to this part. For this button part we've said that it uses 2 images in the 'balloon_maker.c16' file but these two images start at image number 1 (rather than 0, which is the first image in the file). If you look in the sprite file with SpriteBuilder you will see that 2 images starting at 1 consists of two images of the round balloon ... a blue one and a red one.

Next in PAT: BUTT we have parameters called rel_x, rel_y and rel_plane. These values are used to position the part relative to the base part (part 0). These coordinates are measured from the top-left of the base part, so if we said that rel_x and rel_y were both 0 we would have created the button in the top corner of the balloon maker. As it is, we've specified rel_x as 0 and rel_y as 20, which means that this part is to be created 0 pixels across and 20 pixels down from the top-left corner of the balloon maker. You can play around with these two numbers if you like and see how it changes the position of the round balloon button. Don't make the values too large though or the button wont even be on the balloon maker any more! The dimensions of the balloon maker are 98 pixels across and 73 pixels in height

rel-plane is used to specify the relative plane of the part. In this case we've set it to 1, which means it exists one plane above whatever the plane of part 0 is. This means that the button will always be visible in front of the balloon maker (which is obviously pretty important!) rather than behind it.

The next parameter in PAT: BUTT is called anim_hover. This is used to specify the animation to play when the mouse hovers over the button. In this case we've specified the animation to be '1' ... which isn't animation at all! It is a static image, but that works just as well. We've said that when the hand hovers over the button it is to use pose 1. Now, remember that we said the balloon button had two images starting at 1? Well, saying to use pose 1 means 'use your pose 1' ... which isn't the same as image 1 in the sprite file. Pose 1 for the round balloon button is therefore image 2 in the sprite file. This can catch people out a lot of times, so pay attention when you are specifying how many images an object has and which images to use.

Next in PAT: BUTT we have message_id. The whole point of a button part (PAT: BUTT) is to trigger an event message when the button is pressed. This parameter is where we say which event to trigger. We've put a 0 in there which, if you check the CAOS Language Guide 'Message Numbers' section, you can see relates to an Activate 1 event. This means that pressing this button causes an Activate 1 event to be triggered on this agent.

Finally, the last part of this PAT: BUTT is called option. Don't worry about this at the moment (feel free to see what the CAOS guide says though!) - we've marked it as 0 (which means 'any part of the sprite image can be clicked on').

ANIM [0]
The next two lines of CAOS deal with giving the button a default animation state. If you look up the command ANIM in the CAOS Guide you will see that it is used to give a list of pose numbers to display. As it happens, with this code we are not animating but telling it to use a certain image frame (image 0). Before the ANIM though there is a command that says 'PART 1' - why? Well, because we've created a compound object the engine needs to be explicitly told which part we are referring to when we use a command like ANIM ... we might want to animate just one part of an object rather than the whole thing. This is why we specify PART 1 *before* the ANIM command. If we were giving this command to a simple object then there would be no need to specify which part, because simple objects only have one part.

And another part ...
After this animation code, there is our friend PAT: BUTT again ... this time creating a different button. If you look at the code you will see that it chooses different image numbers to display (checking with the sprite file shows this to be the blue and red cow buttons) but also it sends a different event when pressed (because message_id is different). The location to create the button is also different, which makes sense because otherwise it would be on top of the round balloon button! Immediately after the button creation there is animation code again ... notice that PART is used again to specify which part we are giving the animation code to.

This part of the code is what actually moves the object into the world. If you look up MVSF in the CAOS Guide you will see that it is specified like this:

MVSF (command) x (float) y (float)

Which means that it takes two float values (numbers with decimal points) - one for the X position in the world, and one for the Y position in the world. But if you look at the code itself we have written MVSF like this: mvsf game "CreatorX" game "CreatorY" ... which seems to be wrong. This is where the concept of variables comes in ... if you aren't familiar with programming you might not have come across them before. A variable is something that 'takes the place of' a value - but it does have to be the same type (string, float, agent etc). This means you can use variables in place of numbers, so long as the variable itself 'contains' a number. CAOS has a few types of variables that it uses, and you can define your own. For now, all you need to know is that there are two variables in the game used for positioning agents near the creator. One of them is called game "CreatorX" and the other is called game "CreatorY". Both of these variables are number types, so they can be used in place of numbers. Just to demonstrate that these are numbers you can type the following into the CCL (CAOS Command Line):
outv game "CreatorX"

NOTE: This is case sensitive, which means you must have a capital 'C' and a capital 'X'.

The CCL should return the value '6100' - which is the number value contained within this variable. You can do a similar thing for the other variable, and it should return a value of 9230. Using these values makes the code in our COS file actually read like:

mvsf 6100 9230

We will talk more about variables a bit later in this tutorial, as they are used a lot in most agents.

You may be wondering at this point though how you find out where the position (6100, 9230) actually IS in the game! We've provided a helpful tool in the game that tells you the locations ... you can press CTRL + SHIFT + X to add/remove it. When it is active you should see numbers next to your hand pointer - as you move they change. These numbers are giving you the coordinates for the tip of the finger.

This XY Location tool is actually written in CAOS too! CAOS is flexible enough to do lots of things, and you can make all sorts of things to help you play/develop with creatures when you are comfortable with it. If you are interested, the code for this is contained within the 'dev tool.cos' file in the bootstrap. You might want to get more familiar with CAOS before looking at it though.

And finally, the last part of the install script is CMRT 0 ... which simply makes the camera move to the current TARG object. In this case, TARG is the object we've just created (the balloon maker) - but in other scripts it might not be so obvious what TARG is. There is an article on the CDN that talks about what TARG is called "The TARG object".

That has now covered the whole of the install script. Is there anything unclear? Anything you're unsure of? Looking at the CAOS Guide might help you, or you can ask questions in the CDN newsgroup but please make sure you ask a question that isn't vague! Asking 'how do I make a new toy?' probably won't get many replies, but asking what ATTR actually does might. Now it is is time to move onto the event scripts, there are a few of these and they'll be covered in the order they appear in the COS file.

Balloon Maker - Activate 1 event

SCRP 2 23 999 1
This part of the code begins with scrp 2 23 999 1 which, if you've been paying attention, you'll know to mean marks this chunk of code (all the way down to the first ENDM) as being an event. Specifically the event belongs to objects with a classifier of family=2, genus=23 and species=999. Looking up at the install script you should see that the balloon maker was given this very classifier. The '1' on the end of the event script marks this as being an activate 1 script - look at the 'Script Numbers' section of the CAOS Guide to see a list of event numbers.

Remember when we created the button parts we said that the button triggers an event - and we gave a value of 0 to the message_id parameter and said that this caused an activate 1 event? Well, it pays to keep an eye on the 'Message Numbers' and 'Script Numbers' section of the CAOS Guide because for the low event numbers the message number and event numbers aren't always the same. There is no good reason for this apart from legacy from previous versions of Creatures - sorry. For later event numbers though you will find that the message number is the same as the event number, which is obviously much easier to remember and makes for less mistakes. You've been warned!

Next up in the event we have the LOCK command. To understand what this does it is important to know how events are processed - and how you can alter this behaviour. By default all scripts run 'real time' ... that is to say the engine works its way through the code in the event and may take a few seconds to get through it all. This means that everything else in the world is carrying on as normal, creatures may be moving around - insects buzzing about - you get the idea. The other thing with events is that, by default, they can be interruped before they have finished. An example would be if I pressed the button for the round balloon, and then pressed it again before it had finished making that first balloon. The button part will run the event from the beginning, even though it hadn't finished processing the first press. This isn't always a bad thing, sometimes it is nice to have things able to be interrupted. There are two ways you can alter this default behaviour of events - one of them is with the INST command (and its partner SLOW), and the other is with the LOCK command.

LOCK doesn't alter how fast the event gets processed - it may still take a few seconds (it all depends on how much code you have in your event!) - but it does alter it so that it can't be interrupted anymore. This means that if I press the round balloon button I won't be able to press it again until it has finished processing that event (actually, this isn't strictly true ... I can *press* the button, and the button will try to trigger the activate 1 event but it will fail and simply not do anything).

INST is a bit different. It too makes it so that an event can't be interrupted but it also does something more major - it causes the whole event to be processed in one tick (a tick is a unit of time in the game, you will come across this concept later). This means that the whole engine waits for this event to finish before doing anything else. Ordinarily this is ok as the engine can process events very fast and you won't notice any difference. INST is very important though in certain circumstances, especially if you have a long event code. For example, if you wanted to do something to a creature in your event code - but it died in between the event starting and finishing you would get an error if the event was running at default speed. When you make the event run in an INST, though, there is no chance of the world changing while you are busy running your event. There is a counter-command to INST called SLOW, which makes the event drop back to running 'real time' when you don't need to guarantee that kind of code safety.

SNDE "lemd"
This command plays a sound file - it takes the name of the sound file as a parameter, so here you see we are trying to play the sound effect called 'lemd.wav'. This file came with Docking Station so everyone should have it.

You've come across this command before, it simply means "any animation commands I use from now on I want to refer to part 1". In this case, part 1 of our current 'targ' object is the round balloon button.

ANIM [1 0 1 0]
You've also encountered this command before. It means "animate using the frames I have specified" - and because this is referring to part 1 it will be the round balloon button that animates with these frames. Frames 1 and 0 are the only frames we are going to animate it with, but it is important to remember again that these frames relate to the images you specified for the creation of this button - which may NOT be the same as the image numbers in the file. Confused? Have a look at the sprite file again and the PAT: BUTT code which we used to create the button. The two images (0 and 1) refered to in this animation refer to images 1 and 2 in the file.

This command makes the script wait until any animation has finished playing. This is useful to allow things to happen in relation to the animation. For example, if you made a coffee vendor you would only want a cup of coffee to be dispensed when the animation had reached a certain frame - you can use OVER to ensure this kind of effect. In our case we are waiting for the [1 0 1 0] animation to finish.

ANIM [0]
You should definitely know what this command does by now, but it may at first seem weird to specify that we now show frame 0 when the last ANIM command we used ended with 0! The reason for this is all to do with the fact we are wanted to use the anim_hover feature of button parts. The anim_hover feature uses the last used ANIM command as the default state to return to. What this means is that if we hadn't specified this ANIM 0 here, the next time the user moved the mouse over the button it would have flashed as normal (as specified in the anim_hover field when we created the button) - but once it had played that animation it would have returned to the ANIM [1 0 1 0] we wrote just a few lines ago. What we actually want it to return to after performing its anim_hover animation is just a plain button. If this isn't clear at the moment don't worry about it too much - you can play around (say, comment out this ANIM [0]) and so see for yourself how the object is affected.

MESG WRT+ OWNR 1000 0 0 0
The MESG commands (there are a few, have a look at the CAOS Guide) are a way of triggering an event in an agent. It is very similar to some of the functionality in the PAT: BUTT command. If you remember, when we created the button there was a field called message_id that triggers an specified event whenever the button is pressed. The MESG commands are similar in that they trigger another event to run, but they don't have to rely on the user pressing a button ... which means you can trigger an event whenever you like in code. The MESG WRT+ command is used to trigger an event and also to pass a parameter into the event (actually, this command passes two parameters but we are only using one of them to actually mean anything.) Passing a parameter means in the triggered event you can check to see what parameter was passed, and then alter the code based on that. For this particular line we are triggering event number 1000 (which is a custom event, we can make it do whatever we like) with the parameters having a value of 0. When we get to the description of event 1000 you can see what it is that we do with these parameters.

This command marks the end of an event script - all event scripts need to finish with ENDM.

So in summary, this activate 1 event locks itself (so it can't be interupted), plays a sound effect, animates the round balloon button and then triggers event number 1000 with a parameter of 0.

Balloon Maker - Activate 2 event
The majority of this event is the same as the activate 1 event, there are a few subtle differences - only the differences are explained here.

SCRP 2 23 999 2
Marks this event as belonging to the balloon maker, and shows it to be an activate 2 event.

This difference makes the animation commands work on PART 2 rather than the PART 1 we used in the activate 1 event. Part 2 of this object is the cow balloon button.

MESG WRT+ 1000 1 0 0
You'll notice that we are triggering exactly the same event (number 1000) as the event we triggered in the activate 1 event, but the difference is that this time we are passing a parameter of 1 (rather than 0). When we look at the 1000 event you will see how this affects what happens.

Balloon Maker - hit event
This event covers what happens if the balloon maker is 'hit'. Hit is an event that is usually only triggered by creatures ... and obviously relates to them 'hitting' the object! You can't generally make the hand perform a 'hit' action so care must be taken with events like these to make sure they actually work. Often you have to find an obedient creature to do your testing for you!

SCRP 2 23 999 3
Marks this as an event belonging to the balloon maker, specifically the hit event.

This marks the event to run 'in an instant'. This means nothing else in the world will run until this event has finished, and also means that it can not be interrupted.

SETV is a command for 'setting a variable' - specifically an integer variable. VELY is an integer variable that relates to the Y velocity of an object. Y veloity is the up/down velocity (as opposed to X velocity, which is the sideways velocity). A negative value of Y velocity makes the object move up ... a positive value makes it move down. Notice that the amount of velocity need to make an object leave the ground changes depending on how 'heavy' it is (as defined by ACCG).

SNDC "hit_"
This plays a sound file named 'hit_.wav', that comes with Docking Station.

Marks the end of this script.

Balloon Maker - event 1000
This is our first custom event. You will notice that the event number 1000 is not mentioned in the CAOS Language Guide ... this is because it isn't an event that the engine is aware of. It is customary to number all custom events from 1000 onwards (you can have up to 65,000 events!), as all of the in-built events are numbered below 1000.

SCRP 2 23 999 1000
Marks this event as belonging to the balloon maker, and numbers it as event 1000.

Makes the rest of the script run 'in an instant'.

DOIF _P1_ NE 0 AND _P1_ NE 1
Ok, this bit probably looks complicated! It is the first time we've come across a DOIF command, so have a look in the CAOS Guide for the syntax. 'NE' is the CAOS way of saying 'not equal' - although you can also use the more conventional math symbol (<>) for this if you like.

In this line _P1_ is the name given to the first parameter passed into this event. If you remember, in the activate 1 and activate 2 events we triggered this event with the MESG WRT+ command ... and passed in a first parameter value of either 0 or 1. Rewriting this DOIF line into something more readable would produce this: "DOIF (the first parameter is not 0) AND (the first parameter is not 1)". If this condition is true, then the code directly under the DOIF is executed. If the condition is false (that is to say, the first parameter is either 0 or 1) then the next bit of code that is executed is the code after the ENDI (short for 'end if'). DOIF always has to have an ENDI after it somewhere, if it doesn't you will get syntax errors.

You might now be wondering what the point of this line is - it is simply checking to see if the parameter has a value of 0 or 1. Lets look at the next line to see what happens if the condition is false.

This command simply stops the current event script from executing ... no more of the CAOS will be run until it is triggered again. Because this command is in the DOIF-ENDI segment, it means the event will only stop executing here if the value of _p1_ is not either 0 or 1. The reason for this is just to make sure Bad Things(tm) don't happen, because the rest of the event is relying on _p1_ being either 0 or 1! It is a good practice to get into; making sure that if something goes wrong, your code can still cope.

This is the command needed to close the DOIF clause. As mentioned earlier, if the DOIF condition is false then the code contained within the DOIF - ENDI loop is not executed.

DOIF _P1_ EQ 0
Another conditional check! This is easier, and only has one condition to check. It is checking whether _P1_ is equal (EQ) to 0.

It is the SETV command again, used for setting a variable to a numerical value. In this case we are setting a temporary variable to the value of 5.

We very briefly mentioned variables earlier in this example, but now is the time to learn more! As has been said, a variable can be thought of as a container of something ... they are used to 'hold' a value. There are two main kind of variables - temporary and persistant. Temporary variables only store their value for the duration of the script, and once the script has finished running they are all set back to being empty. A persistent variable though holds the information it has for the _whole lifetime of the agent_. Persistent variables are associated with an agent; that is to say an agent has a certain number of these persistant variables that you can use to store information. Temporary variables are sometimes called 'VA variables' because that is how they are written in CAOS, and they range from va00 to va99 (making one hundred temporary variables you can use in a script). Persistant variables are sometimes called 'OV variables', and there are also a hundred of these ... from ov00 to ov99. Don't worry about OV variables too much, we will talk some more about those later - but do worry about VA variables, because we are using those now!

ELIF _P1_ EQ 1
This is called 'else if' ... and is another (optional) part to a DOIF-ENDI clause. This part is saying 'else if (the first parameter) is equal to 1' ... and if that is true then the code underneath will be executed.

This is setting the temporary variable VA00 to a value of 7.

The closing of the conditional clause. Just to make sure that you understood the DOIF-ELIF-ENDI clause, here is the explanation of it in English!

If _p1_ is equal to 0 then set va00 to 5, else if _p1_ is equal to 1 then set va00 to 7 instead.

We are now setting a different temporary variable (va10), and we are setting it to POSL. POSL is the value of the left-position of the current agent ... which in this case is the balloon maker itself.

The concept of a 'current agent' object is fundamental to the way the CAOS Language works, you can read an CDN_article about this concept - called 'The TARG Object'.

This sets another variable, va11, to the top-position of the agent. We are going to use va10 and va11 (the left postion and the top position of the balloon maker) to position our newly made balloon.

The ADDV command is used for adding one numerical value to another. The RAND command is used for creating a random number - here we are wanting a number between 0 and 45. The whole of this line can then be read as 'add a random number between 0 and 45, to my variable va10'. The reason for doing this is that we want a bit of variation in where our balloon is created. We are going to use va10 as the left coordinate for placing the balloon, so by adding anywhere between 0 and 45 pixels to that location we get variation.

ADDV VA11 20
This is the ADDV command again, but this time we are adding 20 to our va11 variable. Remember that the coordinates in the world are measured from the top-left of the world. So, if we were to use va11 as our Y coordinate, adding 20 to it moves the position to below the top of the balloon maker ... not above it!

: SIMP 2 21 999 "balloon_maker" 2 va00 1999
Now this is where we can actually start to make the balloon! You've come across the NEW: command before, and this time we are just making a simple object rather than a compound object. You will notice that we have chosen a different classifier for the balloon ... the genus is 21 rather than 23, as this makes the object belong to the 'toy' group of objects.

Notice that we are specifying the balloons as having two images, but that the first image is va00. This is where the power of variables can be demonstrated! If you cast your mind back we set va00 earlier on in this script, and we set it to either 5 or 7 depending on what value of _p1_ was passed to this event. Cast your mind back even further still, and you will remember that the value of _p1_ depended on which button was pressed to make a balloon. Putting this all together, and having a look at image 5 and image 7 in the sprite file you should see that these numbers correspond to either a round ballon or a cow balloon. We could easily have made two events - one for making round balloons and one for making cow balloons - rather than doing this 'make a balloon based on a value' but it would obviously mean more code to write. In this case it is much easier to just write a general purpose 'make a balloon' routine and alter it dynamically.

So, we've just made the balloon itself - but it has no physical properties and hasn't actually been placed in the world yet. If you read the 'TARG Object' CDN_article you will realise that the TARG is now no longer referring to the balloon maker ... instead all CAOS commands now will operate on the newly created balloon instead.

ATTR 198
This gives the balloon suitable attributes.

This specifies what actions creatures can take on the balloon.

Here we specify the acceleration due to gravity of the balloon. Yes, we've made it negative! This means the balloon will actually float into the air rather than fall to the floor.

Specifies the bounciness of the balloon.

TICK 500
We briefly mentioned 'tick' before. Basically, the smallest unit of game time is a tick ... and there are roughly 20 ticks a second. The TICK command starts a timer in the agent that counts down from the number specified - in this case it counts down from 500. When the counter reaches 0 the agent will trigger its timer event. Timer events are very useful for controlling agents, because you can make them happen regularly and as often as you like. So, this line is setting the timer for the agent, and after roughly 25 seconds the timer event for the balloon will execute. We will have a look at the timer event for the balloon very soon, to see exactly what it is that the balloon will do.

SETV VA20 RAND 0 255
SETV VA21 RAND 0 255
SETV VA22 RAND 0 255
These three lines are giving each of the temporary variables (va20, va21 and va22) a random number between 0 and 255. We're going to use these random numbers in the next line to tint the balloon.

TINT VA20 VA21 VA22 128 128
And here we apply those random numbers! The tint command is used for colouring a sprite, if you look in the CAOS Language Guide you will see that the first 3 values it takes are for a red component, a green component and a blue component. These 3 components have a range of 0 to 255 ... hence the random number range we used previously. The last two elements of the tint command are slightly more complicated, but there is no need to explain those here ... just rest assured that values of 128 for them mean 'default'. If you look at the sprite file again for these balloon images you will notice that they are both plain grey. This is the best colour for tinting as it gives a neutral base to the colour. If we'd had colour in the images already then tinting them would have produced more unpredicatable results.

And here we finally position the balloon in the game world - with the values of va10 and va11 being used for the coordinates. Remember that we derived va10 and va11 from the current position of the balloon maker, which should mean our balloons appear in a sensible position relative to the balloon maker.

VELO RAND -2 2 0
The VELO command is a way of setting both the X and Y velocity in one go (previously in this example we used VELY to just give velocity in the Y direction - we could have used VELO then too, and given a value of '0' for the X component). Notice that we are using RAND again to give a random element to the X component. The result of this command is that the balloon will have an X velocity of between -2 and 2, and a Y velocity of 0.

The traditional end marker of a script.

Putting that all together we have now completed the balloon maker scripts! That last event (number 1000) is where most of the work takes place - it created a balloon (with the image of the balloon based on a parameter passed into the event). It then coloured the balloon and placed it into the world near the balloon maker, with a random amount of velocity.

Unfortunately, that is not the end of the COS file - because now we need to give the balloon itself some scripts, and dictate how it reacts in the world. Hold onto your hats ...

Balloon - Activate 1 event

SCRP 2 21 999 1
Marks the following code as being an event script for the balloon, specifically an activate 1 event.

Make the rest of the event run in an instant

STIM commands are a way of triggering a genetic effect in a creature, and are much better than directly altering chemicals yourself. There is a list of STIM numbers at the end of the CAOS Language Guide, and if you look for number 97 (the one used here) you will see that it corresponds to 'played with toy'. Basically what this does is trigger a response in the creature so that it knows it has played with a toy - and its genome will produce the suitable response to that to aid with learning. Genetic Stims are used extensively, and there are stims for things like 'I've eaten a seed' - or 'I've hit a bug' - and these provide a standard way to interface to the creature's brain and biochemistry.

FROM was talked about in the 'TARG Object' CDN_article linked to earlier. Putting it succinctly, the FROM object is a pointer to the object that caused this event to fire. As this is the activate 1 event for the balloon, the likely candidates for making the activate 1 script fire are either the hand or a creature. If a stim is fired on the hand it is just ignored, so we don't actually need to check what made this event fire!

VELO RAND -5 5 RAND -5 5
Give the balloon some velocity ... a bit of random in both X and Y directions!

These three lines are a conditional check. The condition that is being checked is whether a random number between 0 and 10 is 0. If this condition is true (that is, if the random number that is generated between 0 and 10 is 0) then we will perform the MESG WRIT command. The MESG WRIT command is very similar to the MESG WRT+ command used earlier ... but the major difference is that we can't pass parameters with this version. That isn't a problem though - you don't always need to pass a parameter. In this case, what we are doing is giving a small chance that when the balloon gets an activate 1 event it might trigger another event within it too ... the event number 1000.
Remember that it is traditional to number custom events from 1000 upwards, so this is a custom event for the balloon.

And that's the end of the activate 1 script.

Balloon Activate 2, Pickup and Hit
We're not going to bother going through the next three events line by line, because the Activate 2 and Pickup events are actually identical to the Activate 1 event ... and the Hit event is only slightly different. If you look at the Hit event you should see that the only differences are (a) a slightly more random velocity given to the balloon and (b) an increased chance of the 1000 event being triggered. What is this magical 1000 event we keep wanting to trigger in the balloons? It is an event that will make the balloon burst! From this logic you can see that there is a chance that the balloon bursts when it is played with (Activate 1, Activate 2 or Pickup) and a larger chance of it bursting when it is Hit.

Balloon - event 1000

SCRP 2 21 999 1000
Marks the event as belonging to the balloon, and the fact that it is the code for event number 1000

LOCK was discussed earlier, this prevents any other events from running until this script has finished. The reason for this is that we are going to be doing things to the balloon that will change it forever ... specifically destroy it ... and we don't want a Norn coming along and pushing the balloon and activating it while it is in the middle of being killed!

SNDC "pop1"
Play the sound file called 'pop1.wav'

Makes the balloon adopt its pose 1 image. Looking in the sprite file (and remembering that the balloon has two images starting at either 5 or 7) you will see that pose 1 is of a balloon exploded into pieces.

This alters the ACCG of the balloon, giving it a quite heavy value. This means the balloon will plummet to the ground if it isn't there already!

The WAIT command makes the script 'wait' for a certain amount of time before carrying on. The time we have specified is 5 ticks, which isn't very long at all ... but the delay is needed otherwise the next line will run too soon and we won't see the balloon change pose or fall to the floor.

The KILL command removes an object from the game, and because we have specified the object to be killed as TARG it means that it is the balloon that is removed. As the balloon is also the OWNR of the script (the script 'belongs' to the balloon) nothing beyond this line will be processed ... which doesn't make any difference to us because this is the last line in the script anyway.

The end of the script.

Balloon - timer event

SCRP 2 21 999 9
Marks this event as the timer event for the balloon

Make the rest of the script run in an instant

This is our old friend DOIF ... which you should know is a conditional check. The new thing though is that this is the first time we've encountered an OV variable. We talked about them before, and the important thing is that they are _associated with an individual agent_ ... rather than with the script itself. This means that the ov00 we are checking here is the ov00 of the particular balloon that is running the script. By default, all variables start at 0 ... so this code is simply checking if the variable is 0, and if it is then it is setting it to 1. The logic of why we are doing this should become clear as we look at the rest of the code.

Ok, a nice simple check ... is ov00 for this agent equal to 1?

Here we are setting a temporary variable to the value of the balloon's ACCG.

DOIF VA00 LT 0.5
ADDV VA00 0.2
Another DOIF check ... but this one is actually inside the DOIF OV00 EQ 1 check too! This is called 'nesting' and you can have as many DOIFs inside each other as you like so long as you remember to close them with the ENDI before you close the outer check. Here we are seeing if the value of va00 is less than 0.5 ... remember that we set va00 to ACCG just a moment ago (so we are really checking what value ACCG is for the agent). If this condition is true, and ACCG is less than 0.5 we then add 0.2 to va00 ... and then set ACCG to the value in va00. The net effect of this is to make the balloon 'heavier' with time ... unless it is above a certain weight already.

NEGV performs a mathematical negation on the value given to it. What this means is that if ov00 is 1, it will be turned into -1 ... and vice versa.

This 'else - endi' is the closure for the DOIF OV00 EQ 1 line above, and so if the DOIF check is false it will then execute the code after the ELSE ... in this case negate ov00.

You may be wondering what is the point of all this negation! It is being used in this case to slow down the effect of the balloons gaining weight ... every other execution of the timer script it will gain weight as opposed to doing it every execution. It sometimes helps to run through the code with a value for ov00 in mind, and work out how it changes with repeated executions.

This sets va01 to the value of 0. We do this because we will check in a little while if it is still 0 - if it has changed it is because some test we are about to perform worked. Using a variable in this way is often referred to as using a 'flag'. Pay attention and see what happens!

ENUM 2 21 999
Ok, if you have read the TARG Object article you will have at least seen mention of ENUM before. If not then read the CDN_article now!

If after reading it things are still unclear, the essence of ENUM is this:

The net result of all this is that this command is used to check up on a whole range of objects at once.

This command is checking whether the current TARG object (and remember we are inside the ENUM-NEXT structure here, so TARG will be one of the balloons in the world) is the same object as the OWNR of this script. What does that mean? Well, ENUM will pick up all objects that match the classifier ... even the one doing the check. This code simply means that we aren't interested in doing anything if the current ENUM'd TARG is the object doing the checking.

TOUC is used to see if one object is touching another ... if they are then TOUC returns a value of 1. The two objects we are checking is the current TARG and the OWNR. This is why we put the previous DOIF check, if TARG and OWNR were the same object we'd get weird results!

Here we are setting va01 to 1. We are doing this to 'flag' that this object doing the checking is actually touching another balloon. Because we are in the ENUM-NEXT structure, and this might not be the last balloon, it is possible that the code is then going to go and check on more balloons. In this case we aren't actually interested in how many balloons it is touching, or which balloons it is touching ... all we care about that there is at least one balloon touching the OWNR.

This closes the DOIF TOUC code.

This closes the DOIF TARG NE OWNR code.

And this closes the ENUM code.

VELO RAND -5 5 RAND -5 5
And finally, we now can check whether our 'flag' variable was set during that ENUM-NEXT structure. If it was set (is equal to 1) then we will give our OWNR balloon some random velocity. If not, we won't do anything.

The end of this script. The TICK command though, once it reaches 0 sets itself back to its initial value. This means that the balloons will keep on executing their timer script until they die. You can make an agent not run the timer script by specifying TICK 0.

Putting it all together, each balloon checks periodically (because of the timer) whether it is touching another balloon. If it is then it will move slightly. It also gains weight in the timer script, which has the effect of eventually making the balloon fall to the floor.

Removal Script
Finally, the last part of the COS file is the CAOS needed to remove all of the agents created in this COS file. This means it removes the balloons and the balloon maker.

This is needed to indentify that the rest of the COS file is now to be executed whenever you 'inject' the removal code.

ENUM 2 23 999
An enumeration loop again! This goes through all the balloon makers (because they have a classifier 2 23 999) and if any exist they will have KILL TARG run on them ... which removes them from the game.

ENUM 2 21 999
Essentially the same as above, except this time we are enumerating through the balloons themselves. Any that are found will be KILLed.

If you have worked through this in one go (and your brain is still functioning) then congratulations! There is a lot to take in here, but hopefully it has covered enough material for you to start making your own objects. Remember: The CAOS Language Guide is your friend, it contains the knowledge of the universe within it - refer to it often.

Now that you've got some basic knowledge it will be much easier to extend that. You can look through the 'bootstrap' folder in Docking Station and there you will find every COS file that makes the game work ... from user interface, to comms screen, to commedia - all are implemented in CAOS.

Downloads:   Tutorial Files