creatures caves welcome, guest
downloads   gallery   dev   community   creatchi   forum   mycaves
ccsf | links | advice | chat | polls | resources | post

Making a Smart Vendor   Development   Malkin | 11/11/2013  log in to like post  2

updated4/28/2022
A variation on the CDN "Making a Vendor for C3" tutorial with extra features - being a smart vendor and vending food on a timed basis.

This is a variation on the Creatures Development Network "Making a Vendor for C3" Tutorial, incorporating some extra features, like a hit and timer script for the vendor. Note that this does not cover the creation of the sprite file or the PRAY file, which are both essential to making sure your agent works properly.

Part of developing an agent is working out its 'story' - how it will behave in your world under a variety of circumstances. When you make an agent, you do not travel with it into other people's worlds, telling it every step of the way what to do, it has to have its own instructions. Writing down exactly what you want it to do is a good first step.

The story:
We want to make a vendor using the 'fishbowl' sprite that injects in the C3 corridor (or the bottom of the DS meso) that can be pushed and pulled by creatures to make food, that can be hit so that grendels can relieve their angst, and the vendor will occasionally vend on a timed basis, so that creatures can get some food and hopefully notice the vendor so that they can get more food.

The story of the vendor's food is that it uses the cheese sprite from the infinite cheese machine, it appears from the vendor when it's pushed, or pulled, or on a timed basis, it makes a noise when dropped and it stimulates a creature when it's eaten and then vanishes.

Potential problems to solve are:

We don't want piles of food, so we're going to make sure that if there's a lot of our food nearby, the vendor won't make more food. (This is often called being a 'smart vendor'.)

For learning's sake, we're going to make sure that the vendor and the food stimulate the creatures properly.

For good practice, we should make sure that any stray food items will eventually vanish - but not before they can be eaten!

We need to make sure that we're using the right images in our sprite file, otherwise the agent will appear wrongly in-game and may produce errors when we try to change its pose.

This story is missing a few of the finer details, but we need to tell the agent everything it needs to work on its own.

Make the vendor

When making a new item, you need to do it in one tick, (INSTantaneously) so that all of its attributes get installed properly.
inst

Create new simple object with the classifier 2 23 10, using the sprite 'fishbowl'. Use 2 pictures from inside the 'fishbowl' sprite, and use those 2 pictures starting at position 0 in the file. If you take a look with Sprite Builder or Monk, you'll notice that pictures in the sprite file are counted starting with 0.
new: simp 2 23 10 "fishbowl" 2 0 5000

Give it attributes that allow it to be picked up and activated by the hand. Responds to gravity and boundaries.
attr 199

Lets creatures push, pull and hit the vendor.
bhvr 11

A permeability that will allow it to sit on wooden platforms (rather than fall through them)
perm 60

Will not bounce.
elas 0

Will not slide around, at all.
fric 100

It's moderately heavy.
accg 3

Use doif to test if you can move into the preferred location. (The corridor area of the ship).
doif tmvt 5000 3400 = 1

If the move works, use mvto to inject yourself to the preferred location.
mvto 5000 3400

If the move doesn't work
else

Use mvsf to inject yourself to that location. While mvto gives pixel-perfect locations, if they're invalid, it can cause errors with the object. Mvsf gives a valid location near the coordinates specified.
mvsf 5000 3400

If mvsf doesn't work (e.g. because you're injecting this in DS standalone)
else

Use mvsf to inject this to a random location in the bottom of the DS meso.
mvsf rand 748 1550 9547

End the move-testing doif
endi

Set the timer running. This command tells the timer how often to fire – at the moment it's set for 3600 ticks, which means the vendor will try to vend a new item spontaneously every 3 minutes. It's easy to set up a spreadsheet in Excel or similar products to help you calculate ticks. The rule of thumb is that there are 20 ticks per second. As there are 180 seconds in 3 minutes, I've multiplied 20 by 180 to give me this number.
tick 3600

Move the camera to look at the object – this is just a cute feature, but can be useful for the player because we've done the 'C3, then DS' install.
cmrt 0



Now that we've put it in the world, we're going to tell it what to do when it's pushed.

Vendor Push
scrp 2 23 10 1

Firstly, for learning's sake, we're going to stimulate the creature that activated the vendor. Putting it as the very first thing ensures that it always stimulates the creatures, no matter if the vendor vends or not. Consistency is important for learning, so we always want them to get a feeling from pushing vendors.
stim writ from 90 1

And now we're going to lock the script so that the rest of it doesn't get disturbed.
lock

Only vend if there aren't already many nearby. Set a field of view of 300 pixels. The larger your range, the further away your vendor can search for vended items. Experiment with this number to find a happy medium.
rnge 300

Make a temporary variable, va66, equal to 0.
setv va66 0

See how many agents with the classifier 2 11 1000 are in that 300 pixel range.
esee 2 11 1000

Add 1 to our temporary variable for as many food items are in that range.
addv va66 1

Move on to the next part. Like every doif has an endi, every esee has a next to close.
next

ESEE leaves the target at the last ‘seen’ agent (the last food item that we count), so we need to manually change the target back to the vendor by adding in TARG OWNR. If we didn’t, when the food decayed, the vendor wouldn’t vend!
targ ownr

Now that we have this temporary variable, we can check it, and if there are four or fewer food items nearby, then that's a small enough number to make some more food. Again, experiment with this number – it's all about finding a happy medium.
doif va66 le 4

Make the bowl animate
anim [0 1 0 1 0 1 0 1 0 1 0]

Get the coordinates for the bowl – set a temporary variable (va00) as the leftmost part of the vendor. Once you've got that temporary variable, add 30 to it to bring the location closer to the middle. This is our X-location.
setv va00 posl
addv va00 30

Get the coordinates for the bowl – set a temporary variable (va01) as the topmost part of the vendor. Once you've got that temporary variable, add 10 to it to bring the location slightly down from the top. This is our Y-location. Moe explains this really well in his Beginner's Tutorial Part 3.
setv va01 post
addv va01 10

Now that we've set our location for the item to spawn from, we can produce the item! As we're going to be re-using this code in a few places, it has to be the same every time. Like making the vendor, we have to tell the game that this agent has to be made instantaneously:
inst

Food attributes:
new: simp 2 11 1000 "infinite_cheese_machine" 2 44 4900
attr 195
bhvr 48
elas 30
fric 50
accg 3

A similar test move and mvsf failsafe, this time using the temporary variables we set just earlier as our X and Y locations.
doif tmvt va00 va01 = 1
mvto va00 va01
else
mvsf va00 va01
endi

Give it some velocity!
velo rand -10 10 rand -15 -20

Give it a tick. This starts the timer script for the food. As we're going to use the timer script to destroy the food, we will give it a longish timer. The relationship between the tick of the food and the tick of the vendor will determine whether your vendor tends to have a surplus of food at its base, or whether its automatically created food items are few and far between. I'm giving it a random tick between 5 and 10 minutes long. Hopefully that will be long enough to let creatures find it. Again, this is a matter of experimentation. Because this tick is longer than the vendor's timer (3 minutes), the vendor will usually have a small pile of food at its base.
tick rand 6000 12000

Make it smell like food. This will let creatures navigate to your foodstuff even when they are far away.
emit 8 0.35

Now that we've finished making the food, we need to go back to the start of our code and end the population count doif.
endi

Now we need to formally end the push script.
endm


Vendor Pull
We want the pull script to work in the same way as the push script, so all we need to change is the part at the beginning when it wants to know what script it is – push scripts are scrp 1, pull scripts are scrp 2.
scrp 2 23 10 2

Firstly, for learning's sake, we're going to stimulate the creature that activated the vendor. Putting it as the very first thing ensures that it always stimulates the creatures, no matter if the vendor vends or not. Consistency is important for learning, so we always want them to get a feeling from pushing vendors.
stim writ from 90 1

And now we're going to lock the script so that the rest of it doesn't get disturbed.
lock

Only vend if there aren't already many nearby. Set a field of view of 300 pixels. The larger your range, the further away your vendor can search for vended items. Experiment with this number to find a happy medium.
rnge 300

Make a temporary variable, va66, equal to 0.
setv va66 0

See how many agents with the classifier 2 11 1000 are in that 300 pixel range.
esee 2 11 1000

Add 1 to our temporary variable for as many food items are in that range.
addv va66 1

Move on to the next part. Like every doif has an endi, every esee has a next to close.
next

Manually change the target back to the vendor.
targ ownr

Now that we have this temporary variable, we can check it, and if there are four or fewer food items nearby, then that's a small enough number to make some more food. Again, experiment with this number – it's all about finding a happy medium.
doif va66 le 4

Make the bowl animate
anim [0 1 0 1 0 1 0 1 0 1 0]

Get the coordinates for the bowl – set a temporary variable (va00) as the leftmost part of the vendor. Once you've got that temporary variable, add 30 to it to bring the location closer to the middle. This is our X-location.
setv va00 posl
addv va00 30

Get the coordinates for the bowl – set a temporary variable (va01) as the topmost part of the vendor. Once you've got that temporary variable, add 10 to it to bring the location slightly down from the top. This is our Y-location. Moe explains this really well in his Beginner's Tutorial Part 3.
setv va01 post
addv va01 10

Now that we've set our location for the item to spawn from, we can produce the item! As we're going to be re-using this code in a few places, it has to be the same every time. Like making the vendor, we have to tell the game that this agent has to be made instantaneously:
inst

Food attributes:
new: simp 2 11 1000 "infinite_cheese_machine" 2 44 4900
attr 195
bhvr 48
elas 30
fric 50
accg 3

A similar test move and mvsf failsafe, this time using the temporary variables we set just earlier as our X and Y locations.
doif tmvt va00 va01 = 1
mvto va00 va01
else
mvsf va00 va01
endi

Give it some velocity!
velo rand -10 10 rand -15 -20

Give it a tick. This starts the timer script for the food. As we're going to use the timer script to destroy the food, we will give it a longish timer. The relationship between the tick of the food and the tick of the vendor will determine whether your vendor tends to have a surplus of food at its base, or whether its automatically created food items are few and far between. I'm giving it a random tick between 5 and 10 minutes long. Hopefully that will be long enough to let creatures find it. Again, this is a matter of experimentation. Because this tick is longer than the vendor's timer (3 minutes), the vendor will usually have a small pile of food at its base.
tick rand 6000 12000

Make it smell like food. This will let creatures navigate to your foodstuff even when they are far away.
emit 8 0.35

Now that we've finished making the food, we need to go back to the start of our code and end the population count doif.
endi

Now we need to formally end the pull script.
endm




To make our vendor act like the C3 vendors, and feel like a C3 vendor for the creatures, we need to add a hit script that stimulates – I've decided not to make the hit script vend an item because we vend items so many other ways with this vendor, but it could vend an item with the hit script if you want.
Vendor Hit Script
scrp 2 23 10 3

Make a noise – this noise is C3-exclusive, so you might want to choose something else.
sndc "hit_"

Jump a bit.
velo 0 rand -20 -30

Stimulate with 'I have hit a machine' - your grendels will love hitting this vendor!
stim writ from 92 1

Finish the hit script.
endm


Now we're going to make our vendor vend food 'just because', on a timed basis, using the tick of 3 minutes that we set way back when we first injected the vendor.

Vendor Timer Script
scrp 2 23 10 9

This is to solve a potential problem, what if you're carrying the vendor from one place to another? So we put this in to stop the vendor from vending by itself if you're holding it. (This will also prevent it from automatically vending if you put it in a lift!)
doif carr = null

Locks the script so that nothing can interrupt it.
lock

This is the population range check, just the same as before:
rnge 300
esee 2 11 1000
addv va00 1
next

and making sure the target of the script is the vendor:
targ ownr

Counting how many are nearby, and deciding whether to vend or not.
doif va00 le 4

Get the coordinates for the bowl
setv va00 posl
addv va00 30
setv va01 post
addv va01 10

Instantaneously create new food:
inst
*cheesy-food
new: simp 2 11 1000 "infinite_cheese_machine" 2 44 4900
attr 195
bhvr 48
elas 30
fric 50
accg 3

Test if it can be moved to the coordinates we chose earlier, if not, move it safely somewhere closeby.

doif tmvt va00 va01 = 1
mvto va00 va01
else
mvsf va00 va01
endi

Give it some velocity!
velo rand -10 10 rand -15 -20

Give it a tick
tick rand 6000 12000

Make it smell
emit 8 0.35

End the 'count the food items' doif.
endi

End the 'am I being carried?' doif.
endi

End the timer script!
endm



Now we're pretty much finished with the vendor's story, so we have to make sure that the food knows exactly what it needs to do. It already knows when it can be created, so now we have to make sure it behaves itself when it's in the world.

For the timer script – this will fire only once, and we only want it to remove the food item, so it only has to be very simple. The script locks, and then it kills the ownr of the script.
*Food timer script
scrp 2 11 1000 9
lock
kill ownr
endm



Now for the important stuff - making sure the food is edible!

*****Food eat script
scrp 2 11 1000 12
lock
sndc "chwp"
stim writ from 79 1
pose 1
wait 20
kill ownr
endm


Makes the cheese make a noise when it falls down.

** Cheese Collision Script
scrp 2 11 1000 6
doif wall = down
snde "dr10"
endi
endm


Now that we've told the agents what to do when they're in the world, we have to tell them how to say 'goodbye' properly when they're removed.


*Remove script
rscr
*count all the vendors and kill them
enum 2 23 10
kill targ
next
*count all the food and kill them
enum 2 11 1000
kill targ
next
*remove all scripts from the world.
scrx 2 23 10 1
scrx 2 23 10 2
scrx 2 23 10 3
scrx 2 23 10 9
scrx 2 11 1000 9
scrx 2 11 1000 12
scrx 2 11 1000 6


Key Issues When Vending:

One of the key points with making one object create another object is Location, Location, Location. You need to get coordinates for the new object to appear, which is normally based on the position of the vendor object, so that it's easier for the player to see the correlation. This is covered in our object above by the code

setv va00 posl
addv va00 30
setv va01 post
addv va01 10


The other point when choosing a location is that you need to check that the new object can fit where you want to put it. If the vendor is placed somewhere very small (and the created object is very big) the coordinates for the new agent may not be a valid location and produce an error.

This is covered in our object above by the code:

doif tmvt va00 va01 = 1
mvto va00 va01
else
mvsf va00 va01
endi


Further Reading:
*Beginner Tutorial Part 1, Beginner Tutorial Part 2, Beginner Tutorial Part 3, Chocolatey Addendum by Moe.
*Balloon Maker Tutorial at the CDN.
*Basic Plant Script by Zareb and Liam.
*Mac Agenteering by SG - covers a bubble wand toy which makes bubbles.


Moving On:

Once you've mastered how to make one object produce another object, the possibilities are limitless - while vendors can produce anything that is desired - toys, devices, eggs; the concept is used in many other places in C3 and DS. Plants and seeds are a good example of this - the plant makes a seed, which, if it is not eaten, makes a plant. A lot of critters make critter eggs, which then in turn make more critters. :)

Another script that could be added is an ear script, to create a vendor that makes food in response to creatures complaining about hunger.

Randomisation could also be used to create more variety in the look of the foodstuffs that are vended.

 

Updated by Malkin on 11/11/2013 - + Further Reading.
Updated by Malkin on 4/21/2014 - updating with targ ownr information.
Updated by Malkin on 11/12/2014 - updating Creatures Wiki links.
Updated by Malkin on 4/28/2022 - updating a Guide to Mac Agenteering.

 
 
Hardman | 12/1/2014  log in to like post

I agree!
 
clohse | 11/11/2013  log in to like post  1

Awesome resource article!


downloads
cobs
adoptions
creaturelink
metarooms
breeds
 
gallery
art
wallpaper
screenshots
graphics
promos
sprites
dev
hack shack
script reservations
dev resources
active projects
dev forum
 
community
links
advice
chat
polls
resources
creatchi
 
forum
bookmarks
general
news
help
development
strangeo
survivor
mycaves
log in
register
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