creatures caves welcome, guest
downloads   gallery   dev   community   creatchi   forum   mycaves
hack shack | script reservations | dev resources | dev forum


Timer Scripts With Pushes  on 5/26/2013

     What are some tips and tricks you can use to make a plant or critter timer script (growing/fruiting plant, mobile critter) that also allows the item to be interacted with (pushed, pulled, hit, eaten), and easily 'resume its place' in the timer script?
- Malkin

Dear Malkin,
     If you followed the same learning curve I did, your first introduction to timer scripts might have been the Basic Plant Script on the Creatures Wiki. A lot of my early agents started out with timer scripts like that: just a line of subroutines, or even just the code itself laid out sequentially. This is fine at first, because this system works great for things that aren't interactive, like plants.

A timer script runs automatically every few ticks (depending on what you set the agent's TICK to). It will automatically be interrupted if another script is called (eg. if a Creature activates its Push Script), and when the timer script next runs, it starts over from the beginning. This means that if you have a plant with a timer script like the one in the tutorial above, it's going to want to restart the whole Grow -> Live -> Seed -> Die sequence every time it gets interrupted. This can cause errors in a lot of ways... say, if the plant tries to "grow" when it's already an adult, it may try to grab an out-of-range sprite.

One easy way to prevent a timer script from being interrupted is to LOCK the agent at the beginning of the script, and UNLOCK it at the end. Then if a Creature or another agent tries to interact with it, it just says "sorry, no can do!" and goes on with its timer. The downside is that the more often the timer script is running, and the longer it takes to run, the less often the agent is open for interactions. And if the whole script runs in one iteration of the timer script, as with the Basic Plant, the agent will essentially be locked for its entire existence (which is why I don't write timer scripts that way anymore). Since Norns don't understand the concept of an agent being "locked", this is a major downside.

The most surefire way to keep track of where an agent "left off" is to use OVxx variables to keep track of what it was doing last. If you're dealing with something like a plant growing or wilting, you can simply check the agent's pose, eg. "doif pose lt (whatever the final pose is)". Of course, this pose will probably change if you end up adding sprites later. And if you ever want to re-use the same code for another agent, that agent might have a different number of sprites. So it's easier to set an OVxx variable with that number when you first create the agent, and then have the agent check "doif pose lt OVxx".

Variables are even more useful if you're dealing with something that doesn't always follow a set pattern of behavior, such as a critter. A critter might wander randomly, interact with Creatures, look for food, play with nearby toys, or any number of other behaviors, often depending on less predictable factors like whether it's hungry or what's going on in its environment.

To do this, you first set a permanent (OVxx) variable as soon as the critter "decides" to do something--eg. as soon as it realizes it's hungry and starts looking for food--and reset that variable to "empty" as soon as the critter is finished doing that thing. Then, at the beginning of the timer script, you check that variable. If the variable is set to a certain action, you go straight to that subroutine. If it isn't set, you let the critter go through the normal process of what it wants to do next.

Using variables this way for critters can be overdone, though. Say, if I have a critter that gets interrupted by a Creature when it's in the process of looking for a mate. Being played with so much leaves it starving, but it ignores the food near it because its last action wasn't "find food". But because it's now starving, it dies before it can reproduce. You may end up seeing some strange behavior if you don't have a set "hierarchy" to prioritize your critter's actions.

If you use reference variables, it's also important to re-check them at the beginning of the timer script to make sure they're still "valid". For instance, let's say that I have a critter that seeks out and eats leaves, as described in the Hungry Critter Tutorial.

In the tutorial, the Hungry Critter only uses a temporary variable to reference the leaves it finds, which means that it "forgets" what it was looking for if the timer script is interrupted. If I want to use an OVxx variable so it can pick up the hunt where it left off, I need to remember that the leaf might not exist anymore by the time the critter gets around to looking again; it might have rotted, been eaten, autokilled, or simply moved. Yes, moved: I've had situations where a Creature carried a food item into another metaroom, and the critter that wanted to eat it spent the rest of its life trying to "follow" that food item! A lot of things can happen while your critter is distracted. [ntongue]
- Ghosthande

hack shack
script reservations
dev resources
active projects
dev forum
log in
lost pw
0 online
creatures caves is your #1 resource for the creatures artificial life game series: creatures, creatures 2, creatures 3, docking station, and the upcoming creatures family.

contact    help    privacy policy    terms & conditions    rules    donate    wiki