Home Sweet Albia
Creatures 1 | Creatures 3 & Docking Station | Miscellaneous
Favorites | Agents | Tools | Guides
Agenteering | Linux Install

A Guide to Agenteering

(14 Feb 2024)

A guide to making agents for Creatures 3 and Docking Station using Theist.

I've archived the original 2006 Mac-centric version of the guide here in case you're feeling extra nostalgic.

Table of Contents

  1. Prepare Yourself

    1. Get the Tools
    2. Reserve Classifiers
  2. Agent-Making Time

    1. Create a Sprite File
    2. Create a Catalogue File
    3. Create a Script File
    4. Add Dependencies
    5. Add a DS Tag
    6. Add a C3 Tag
    7. Save the Agent
    8. Try It Out
    9. Updating Files
    10. Advanced Testing
  3. Look Smart with Sprites

    1. Come Up with a Concept
    2. Do Some Drawing (or Modeling or Photography)
    3. Tweak the Images
  4. Stick to the Script

    1. Order From CAOS
    2. Create a New Object
    3. Activation Script
    4. Pick-Up Script
    5. Drop Script
    6. Timer Script
    7. Blowing Bubbles
    8. Bubble Scripts
    9. Remove Script
  5. Moving On

    1. Make a README File
    2. Zip It Up
    3. Share It Far and Wide
    4. Learn More
    5. Many Thanks

Prepare Yourself

Get the Tools

References to bookmark:

Reserve Classifiers

Every type of object in the game is identified by a unique classification number. If your agent uses a number already being used by another agent in somebody's world, it'll cause some weird things to happen.

To avoid conflicts, it’s best practice to reserve some scripts for your agents at the Creatures Caves website. (Note: You’ll need to make an account to reserve script numbers. For the best security, remember to use a unique password and change it regularly.)


Agent-Making Time

We're going to use Theist and Spritist to put together our sample agent, the Bubble Blower. We'll get more into the details of how to draw sprites and write scripts later on, but for now we'll use some pre-made files to walk through the overall process of making an agent and getting it into the game.

Create a Sprite File

Creatures 3 and Docking Station use a sprite file format called C16, which stores multiple image frames in a single file. We can use Spritist to create a C16 sprite from a series of PNG files - in particular, these sample images for our bubble blower. Go ahead and download and unzip them, then load up Spritist.

Click the "New" button to create a new sprite.

Click the "Insert Image" button and select the PNG files one at a time - or just drag all the PNGs into Spritist to add them all at once.

There we go! We can see all the frames for our sprite. Note: Since everything in the game refers to images by frame index number, make sure the order of frames matches the screenshot here - if not, drag them into the right order.

Click the "Save" button and save your sprite as "bubble_blower.c16".

Create a Catalogue File

A catalogue file contains the help text that comes up when a player right-clicks on an agent with the "?" turned on. It's just a text file with the file extension set to ".catalogue" and a pretty simple format for each entry:

TAG "Agent Help [classifier]"
"[agent name]"
"[agent description]"

So in our case we have both the bubble wand and the bubbles themselves. We can put them in the same file like this:

TAG "Agent Help 2 21 999"
"Bubble Blower Wand"
"A wand to blow bubbles for your creatures."

TAG "Agent Help 2 21 1000"
"Bubble"
"A wandering bubble. So delicate!"

You can copy and paste that into your favorite text editor (even just notepad.exe) and save it as "bubble_blower.catalogue", or just download the pre-made catalogue file and unzip it.

Create a Script File

Next up, we create our script file. What script file? Why, this script file! That’s right, I’ve already written a bubble blower script to get us started. More on scripting lies ahead.

Add Dependencies

Open up Theist and we're ready to start creating our agent file. Notice that the window is divided up into two columns: tags on the left, and dependencies on teh right. We'll get to tags in a moment, but for now let's focus on dependencies.

Dependencies are the files that get bundled up in our agent file. When we inject an agent into our game, these files get added to the appropriate folders in the install directory. Essentially an agent file is like a ZIP file specifically for Creatures 3/Docking Station.

We'll start by adding the three files we just created - bubble_blower.c16, bubble_blower.catalogue, and bubble_blower.cos. Either click the "Add Dependency to Agent" button add them one at a time, or drag the files into Theist to add them all at once.

And there we go, all our files are added as dependencies, and will get packaged into the agent file so our agent can use them in the game.

Add a DS Tag

A single agent file can actually hold multiple agents. Each one is defined by a tag. In fact, since C3 and DS are technically separate games that can be played independently, each game will need its own tag if we want our agent to show up in both injectors. We can add the first one by clicking the "Add Tag to Agent" button.

Theist will ask what kind of tag we want to create, and we'll choose "Add Agent Tag." (We can see there are also egg tags and garden box tags, but for now we’re going to stick to agents.)

Now we can see all our agent tag properties! It's defaulted to making a DS tag first, which is fine. We'll make the C3 tag by duplicating this one after we fill out all the fields so we don't have to do it all twice.

Our dependencies are all de-selected by default for new tags. We want our DS tag to include all three of them, though, so we should check them all.

Let's give our DS tag a name with the Agent Tag Name field. This is how it will show up in the injector.

Since we already added a sprite file, we can set our injector image to use it by choosing it from Animation File dropdown.

We can use an Animation String to show an animated preview in the injector, but for now let's keep it simple by just showing the first frame of the sprite. (If we wanted to use a different frame for the injector, we'd want to change the Sprite First Image number as well as the Animation String.)

Let's write a description for the injector. (You can add translations for other languages that the game supports using the + button.) For now we'll skip the Web Label and Web URL, but if you have a website, you can fill in those fields if you like.

The remove script is what gets called when a player clicks on the "⊘" button on the injector. Since our script file already includes a remove script (rscr), we can click the "Generate Remove Script" button to get Theist to extract it for us.

Add a C3 Tag

Creating the C3 tag is as easy as clicking the "duplicate tag" button for our DS tag.

It copied over all our info!

Let's give it a more appropriate name...

... and set the Game Support selection to Creatures 3. The C3 injector shows much less info than the DS injector, so there are fewer fields to fill out. (On the other hand we can set the Bioenergy value, but since the bubbles blower isn't organic material, we can probably leave it at 0.)

Save the Agent

Traditionally, saving everything into an agent file is called "compiling." But in Theist we just need to click the "Save" button and choose a location to save the agent file to. That's it! All the dependency files and tag info will be saved inside, ready to be injected into the game or opened by Theist at a later date if you need to change anything.

Try It Out

Now let’s try it out in the game. Copy your agent file to the Docking Station/My Agents folder, wherever you’ve installed your copy of the game. When you start the game, you should be able to find the Bubble Blower in the Docking Station comms room. Press the green check button, and et voila, your bubble blower should magically appear!

For Creatures 3, the steps are the same, except you copy your agent file to Creatures 3/My Agents instead. Now it will show up in the Creatures 3 injector in the ship’s engineering bay even in undocked worlds.

Updating Files

An agent file is kind of like a zip file - it compresses all the files an agent needs into a single file. When you first inject an agent, the game extracts all the files and puts them in the right folders. Except for scripts, which get put into the world itself. From then on, the agent file itself is just used to show the agent in the injector. That means that if you change the sprites, sounds, or catalogues for your agent after you’ve injected it into any world, you have to find and delete the old versions so the game can replace them with your new versions - or replace them manually if you prefer.

Note that if you want to see the new version of your agent show up in the Docking Station injector - even you just changed the name, description, or injector preview - you need to do the following dance:

  1. Delete the original agent file from Docking Station/My Agents.
  2. In the Comms room, switch views from the injector to something else and back again. The agent will be removed from the list, forcing the game to re-scan the file when you add it again.
  3. Add the new agent file to Docking Station/My Agents.
  4. Switch views in the Comms room again. Your agent will be back in the list, and this time it will be the updated version.

Advanced Testing

It can be annoying to have to re-compile and re-inject your agent every time you update the script, especially in the early stages when you might need to make lots of small changes. There’s a trick you can do to get your script in the game faster: put your ".cos" file directly in the game’s bootstrap folder and inject it manually.

Move your script file to Docking Station/Bootstrap/010 Docking Station (or any folder in Bootstrap, you can even make a new one for testing purposes). In the game, you can open the CAOS command line with CTRL+SHIFT+S and type

ject "bubble_blower.cos" 7

(or whatever your script file is named). This will run the remove script and re-inject the agent - assuming you’ve injected it before, or at least copied the sprites and sound files manually into their proper game folders. You can then edit the script from there, and keep ‘jecting it all you want.

Just remember to move your script file back into your project folder when you’re done, otherwise it won’t get included in your compiled agent.

Also note that all scripts in the Bootstrap folder will be injected into any new worlds you create, so make sure you delete your test script from the Bootstrap folder when you’re done and avoid making new worlds while you’re in the middle of testing.


Look Smart with Sprites

Come Up with a Concept

Every agent starts as an idea. It helps to sketch pictures of what you want your agent to look like, and think about how your agent will behave. If you outline the poses and animations your agent will use, you won't have to spend as much time drawing sprites you won't need. You can also start a folder dedicated to all the files for your agent, just to keep things nice and organized.

Do Some Drawing (or Modeling or Photography)

The official Creatures 3 and Docking Station sprites use 3D models that have been exported as 2D sprites, sometimes with additional polish added on top of that. You don’t have to start with a 3D model if you don’t want to, though. You can edit a photo of an object, scan a hand-made drawing or painting, or draw your agent digitally.

Tips:

Tweak the Images

The important thing is that you end up with one PNG file per frame, with a transparent background. Most graphics editors will let you export your work as PNG files, so that shouldn’t be a problem. The Creatures games actually have their own image formats (S16 and C16), but Theist will take care of the conversion for you.

Tips:


Stick to the Script

Order From CAOS

When we put together the Bubble Blower, we used a pre-made script. Go ahead and open it up in a text or code editor: you’ll see it’s just a lot of comments (the lines that start with asterisks) and short, mysterious commands (the lines that start with four-letter words followed by numbers).

The mystery commands are the actual code that makes the agent function. The comments are just for us. The Creatures game engine uses its own scripting language called CAOS, for Creatures Agent Object Script. It’s simple and efficient for the game, but not very readable for humans, so it’s best to have a copy of the CAOS Docs on hand to look up what the (many, many) commands do.

Let’s walk through the Bubble Blower script line by line so you understand all the parts well enough to mess around with it or make something from scratch.

Create a New Object

The first command in most scripts is inst, which tells the game to do everything that follows in one game tick - practically instantly. That way nothing else can interrupt it while it’s creating the object and setting all its properties.

* everything that follows happens in one tick (instantly)
				inst

Next, we’ll create the actual object. It doesn’t have any moving parts or anything, so we’ll use new: simp to create a simple object. Unlike inst, new: simp has a number of arguments that follow - numbers and strings (bits of text enclosed in quotes) that specify details about the command.

* create new object
new: simp 2 21 999 "bubble_blower" 5 0 4000

The first three numbers, 2 21 999, represent the unique classifier for our object. The first number, 2, is the family. In this case it’s an object that lives in the world. The second number, 21, is the genus, which is basically what word a norn would use for it. In this case, it’s a toy. Finally the third number, 999, is the species. This is unique to the bubble blower wand. There could be a different object in 2 11 999, but if anything else uses 2 21 999, the game will think they both share the same properties and scripts. That’s why it’s a good idea to reserve classifiers for the stuff you make. Don’t worry though - there are plenty to go around! We won’t run out anytime soon.

The next argument is a string, "bubble_blower". This is the name of the sprite file this object will use. The 5 means it’ll use 5 frames, and the 0 is the base, meaning frame 0 is the first of those five frames (the rest counting up from there, so 1, 2, 3, and 4).

The last argument, 4000, is the plane the object sits on. The higher the number, the closer to the front of the screen it is. It’ll appear in front of any object with a lower plane. This is just a good number for toys, since it’s kind of in the middle: in front of the norns and most plants and environmental objects.

ATTR and BHVR

Agents have two properties that determine what the Hand/the world can do with it, and what creatures can do with it: ATTR and BHVR.

* set attributes: can be carried by agents (+1),
* hand can pick it up (+2) and activate it (+4),
* and affected by collisions (+64) and physics (+128)
attr 199

* set behaviors: creatures can active 1 (push) it (+1),
* and pick it up (+32)
bhvr 33

The value of these properties is determined by adding together a bunch of numbers representing individual things that can affect the agent. It’s not worth memorizing this system, just use an ATTR + BHVR calculator.

For the bubble blower wand, we’re going to use some pretty common values for basic toys.

Physics Properties

The Creatures engine has a 2D physics system, so we need to set a bunch of properties on our agent so it behaves the way we want when it’s dropped or thrown.

* set gravity
accg 3

* set permeability
* (what kinds of surfaces it will fall through)
perm 60

* set elasticity
* (how much it bounces)
elas 0

* set friction
* (how much it slides on the ground, eg. when dropped on slope)
fric 100

* set aerodynamics
* (how quickly it slows when going through air, eg. when thrown)
aero 2

There’s also the puhl command for setting the x/y offset on the sprite to a more reasonable place for the hand to pick it up from. This puts the opening of the wand above the hand, so it looks more like how it would be used in real-life.

* set the offset for where the hands picks it up
* (-1 = set for all sprites)
puhl -1 20 55

Injection Boilerplate

To make the agent appear in the right spot from both the C3 and DS injectors - and not error out if you only have C3 installed - there’s some standard code that we can use.

* boilerplate for placing agent after being injected
* from either C3 or DS

doif game "CreatorX" ne 0 and game "CreatorY" ne 0
    mvsf game "CreatorX" game "CreatorY"
else
    mvsf 5440 3580
    velo rand 30 40 -5
endi

doif room targ eq grap 5440 3580
    mvsf 5440 3580
    velo rand 30 40 -5
endi

That’s it for getting the agent into the world. Next up, we’re going to add some scripts to get it to do stuff when the Hand or a creature interacts with it.

Activation Script

When the Hand or a creature pushes an agent, its Activate 1 script is called. Scripts start with the command scrp, followed by the agent’s classifier, followed by the script number - in this case, 1. The end of the script is marked by endm.

* activate 1 script
scrp 2 21 999 1
    ...
endm

So what do we put inside? Well, we definitely want creatures to know they’ve played with a toy so they get those happy chemicals released.

* reward creature for playing with a toy
stim writ from 97 1

We also want to animate the bubble blower wand by telling it to move through a series of sprite frames - it stands upright and then shows the bubble inside getting larger and larger, before returning to the original bubble-less frame. The bubble is now free to be its own separate agent - but first we need to tell the script to wait for the animation to finish with the over command.

* animate wand
anim [1 2 2 3 3 4 4 1]

* wait for animation to stop
over

Now that the bubble is fully grown, it’s time to create a new agent for the bubble. Since there are several ways to create bubbles with the wand - another is to hold it and wave it around to auto-generate bubbles on a timer - I’ve put the code for this in a custom script. User-defined scripts like this are safest to start at script number 1000, well away from any system-defined scripts (like this very Activate 1 script). We’ll get to the definition of that later - for now we just want to call it.

* call create-bubble script
call 1000 0 0

With the bubble on its way, the wand can collapse to the ground again by changing its frame with pose. We’ll just wait a few ticks first so it feels more natural.

* wait 5 ticks
wait 5

* change sprite
pose 0

That’s it! Not the simplest script, but with a more basic toy you can always get away with just writing a stim and running an animation.

Pick-Up Script

When the bubble blower is picked up by Hand or creature, script number 4 is called. We want to change the frame to the upright wand, and start blowing those bubbles. In the timer script we’ll start making bubbles automatically, so here we just need to set the rate at which the timer script is called with tick.

* pick-up script
scrp 2 21 999 4

    * change sprite
    pose 1

    * start timer at a rate of every 5 ticks
    tick 5

endm

Drop Script

The opposite of the pick-up script, the drop script - number 5 - needs to stop the timer and change the frame so the wand lies on the ground again. (Once again we’re using wait to make the frame-change feel more natural.)

* drop script
scrp 2 21 999 5

    * stop timer
    tick 0

    * wait 5 ticks
    wait 5

    * change sprite
    pose 0

endm

Timer Script

The bubble blower is going to blow bubbles continuously while it’s being held. That’s why we set the timer rate with tick 5 in the pick-up script, and stopped the timer with tick 0 in the drop script. That way the timer script - script number 9 - is called every five ticks while the Hand or a creature is holding the wand.

The code is going to look similar to the activate script. The wand will animate blowing a bubble, and when that animation is over, a new bubble will be created by calling our custom script.

* timer script
scrp 2 21 999 9

    * animate wand
    anim [2 3 4 1]

    * wait for animation to stop
    over

    * call create-bubble script
    call 1000 0 0

endm

Blowing Bubbles

Now for the big one: our custom script for creating bubbles, script number 1000. This is going to look similar to how we created the bubble blower wand, starting with an inst to make sure the rest of the script can’t get interrupted halfway through.

* custom create-bubble script
scrp 2 21 999 1000

    * everything that follows in this script
    * happens in one tick (instantly)
    inst

Before we can create the bubble itself, we have to store the wand’s current position so the bubble can show up in the right spot. The reason we have to do this ahead of time is because once the bubble is created with the new: command, all further commands in the script target the new agent.

We can store the wand’s positions in some local script variables, va01 and va02, so we can use them later. Script variables are attached to the script, not the object, so they don’t care about the target object. They do disappear once the script ends, though. (If you do want to store variable data in the object instead, you can use ov01 - ov99. Just be aware that each agent has its own set of object variables, so if you switch targets, you’re going to be accessing a different set of object variables.) The command setv takes a variable and then a value to store in it, in this case the positional data from posx and posy.

* set variables 1 and 2 to the wand's x and y positions
setv va01 posx
setv va02 posy

That’s the center of the sprite, though, and won’t place the bubble at the opening of the wand. We have to do some math. CAOS provides addv and subv to add and subtract from the value stored in a variable.

* subtract some values from variables 1 and 2
* so bubble will appear in the right place
subv va01 7
subv va02 13

Ok, now it’s time for new: simp. We need a different classifier from the wand, so we’ll use 2 21 1000. And since bubbles only need one sprite frame - the sixth frame in the sprite file - and we want to put the bubbles a little in front of the wand, the full line looks like this:

* create bubble (this changes target
* of commands to the newly-created bubble)
new: simp 2 21 1000 "bubble_blower" 1 5 4100

Next up is our regular bunch of attributes, behaviors, and physics properties, albeit with some slightly different values from the wand since bubbles are practically weightless and are meant to just float around:

* set attributes: hand can pick it up (+2) and activate it (+4),
* and affected by collisions (+64)
attr 70

* set behaviors: creatures can active 1 (push) it (+1),
* and pick it up (+32)
bhvr 33

* set physics properties
accg .1
perm 60
elas 0
fric 50
aero 0

Remember those local script variables holding onto the x and y positions for the new bubble? Now it’s time to use them. The move-safely command, mvsf (this makes sure it won’t end up stuck in a wall by accident), conveniently takes an x and a y argument. So we can plug in the values stored in va01 and va02 to move the bubble to the right spot.

* move to the x, y coordinates stored in variables 1 and 2
mvsf va01 va02

Once the bubble is positioned let’s give it a little push in a random direction by using the velo command to set the x and y parts of its velocity. The rand command lets us use a random number between -1 and 1 for each part.

* set a random initial velocity
velo rand -1 1 rand -1 1

To add some continuous movement - and an eventual pop - we’ll use a timer script for the bubble and set the rate to something random.

* start timer
tick rand 10 20

When we’re done with the bubble, we can target the original owner of this script again - the wand - with targ ownr. This may not be strictly necessary at the end of a script, but I included it here in case you want to mess around with the script and add additional wand-targeted code after the bubble is created and sent on its way.

* return target of commands from bubble
* back to wand (the owner of this script)
targ ownr

And that’s it for the last of the bubble blower wand scripts. On to the scripts for the bubble itself!

endm

Bubble Scripts

You now know everything you need to understand most of the bubble scripts.

* activate 1 script
scrp 2 21 1000 1
    * call pop-bubble script
    call 1000 0 0
endm

* pick-up script
scrp 2 21 1000 4
    * stop timer
    tick 0
endm

* drop script
scrp 2 21 1000 5
    * start timer at a rate of every 10-20 ticks
    tick rand 10 20
endm

In the timer script, we introduce a bit of flow control, some branching code. Doif will only run the commands under it if some condition is met, in this case when a random number between 0 and 9 is equal to 0 - in other words, a 1 in 10 chance. Anything under else will run if that initial condition is not true, so the other 9 in 10 chances. Finally it’s wrapped up with endi - any code after that runs normally.

* timer script
scrp 2 21 1000 9
    * 1 in 10 chance for bubble to pop
    doif rand 0 9 eq 0
        * call pop-bubble script
        call 1000 0 0
    else
        * if bubble doesn't pop,
        * change velocity in random direction
        velo rand -1 1 rand -1 1
        * reset timer at a new rate of every 10-20 ticks
        tick rand 10 20
    endi
endm

When the bubble pops, we play a sound effect with sndc and then destroy the bubble - the current target object - with kill targ.

* custom pop-bubble script
scrp 2 21 1000 1000
    * play popping sound effect
    sndc "pop_"

    * wait 5 ticks (for sound to finish playing)
    wait 5

    * delete bubble
    kill targ
endm

Remove Script

The last step is to create a remove script to fully delete the agents and their scripts from the world when the player presses the remove button on the injector.*

The remove script starts simply enough:

rscr

To remove all the wands and bubbles, we use the command enum to look at all the agents with a particular classifier, one at a time, like it’s going through a checklist. The current item in the list is the target of the following commands, which means we can remove the agent with kill targ. Then next picks the next agent in the list, until there aren’t any more agents with the specified classifier.

* remove wand
enum 2 21 999
    kill targ
next

* remove bubbles
enum 2 21 1000
    kill targ
next

That takes care of the agents themselves. We also want to remove the scripts we created for them, which we can do with scrx (basically the inverse of scrp).

* remove wand scripts
scrx 2 21 999 1
scrx 2 21 999 4
scrx 2 21 999 5
scrx 2 21 999 9
scrx 2 21 999 1000

* remove bubble scripts
scrx 2 21 1000 1
scrx 2 21 1000 4
scrx 2 21 1000 5
scrx 2 21 1000 9
scrx 2 21 1000 1000

Removing scripts is especially important to do while developing agents to avoid unexpected behaviors. Once you create a script, it sticks around in your world’s scriptorium and continues to affect any agents with its classifier until you overwrite or remove it. For example, if you want to let bubble timer keep running even while the bubble is being held, you don’t need the pick-up or drop scripts anymore - but you would need to run scrx on those scripts to stop them from affecting your bubbles. In the final version of your cos file you shouldn’t remove scripts you aren’t also defining, you just need to keep this in mind while you’re still messing around. You can also run scrx from the CAOS command line.

* Traditionally the remove script here in the script file only gets called when using the ject command from the CAOS command line. You’d need to separately define the one used by the in-game injector in the PRAY source file, which usually just meant copying it from the script file and pasting it into the PRAY file (and removing all line breaks). Theist makes it easy to just write it once by setting the Remove Script property to Auto. It will scan the first script file for the remove script, and do the copy-paste-line-break-removal dance for you.


Moving On

It’s time to strike off on your own agenteering adventures!

Make a README File

When you share your agent, you probably want to let people know what they’re getting into. It’s best practice to include a text file, readme.txt, with the following info:

Zip It Up

With your agent file (or files) and readme.txt, zip them up so you can distribute them together.

Share It Far and Wide

There are three main places you can share your work:

Learn More

Many Thanks

Original 2006 guide: Thanks to Moe, Spook, RProgrammer, and Malkin

Updated 2023 guide: Thanks to Amaikokonut for some awesome CAOS tools, 20kdc for help with Theist, and EemFoo for support and encouragement!