# # Gatherers -- a decentralized food gathering simulation # jon klein <jk@spiderland.org> # # This demo simulates a 3D decentralized food gathering algorithm. The # critters in the simulation move around randomly with two simple rules: # if they run into food and they're not carrying any, pick it up; if # they run into food and they are already carrying some, drop the piece # they're carrying. # # After a short while all the food in the world has been organized into # a large piles. Left to run long enough, all of the food will end up in # the same pile, though this takes quite some time. # # Though the process might be slow, the interesting feature of the simulation # is that the food can be gathered without any communication between the # agents. # @include "Mobile.tz" @include "Wanderer.tz" @include "Control.tz" @define COLLECTOR_COUNT 50. @define FOOD_COUNT 400. @define WANDER_RANGE (20, 20, 20). Controller Gatherers. Control : Gatherers { # The control object sets up the simulation. The "init" # method is called automatically when the object is # created. + variables: foodList (list). collectorShape, foodShape (Shape object). + to init: collectorShape = (new Sphere) init-with radius 1. foodShape = (new Sphere) init-with radius .5. COLLECTOR_COUNT new Collectors. foodList = FOOD_COUNT new Foods. foodList set-bitmap to 2. # this sim can run a bit slowly, but doesn't need a lot of # accuracy, so we can set up the integration step a bit. self set-integration-step to 0.05. self add-menu named "Randomize Food" for-method "randomize-food". self point-camera at (0, 0, 0) from (0, 0, -80). + to randomize-food: # randomize the location of all of the elements in foodList. foodList randomize-location. + to get-collector-shape: return collectorShape. + to get-food-shape: return foodShape. } Wanderer : Collector (aka Collectors) { # In this simulation we make use of the Wanderer class: we want some # arbitrary motion within a certain range, but aren't so picky about # the specifics. The built-in Wanderer class takes care of this. + variables: carrying (object). justCollided (int). + to init: # 1) register it in the world # 2) tell the engine to call its iteration function automatically # 3) set it's color (using a method in the Mobile object) # 4) set the wander range (using a method in Wanderer object) # 5) set up a collision handler self set-shape to (controller get-collector-shape). self set-color to (1.0, 1.0, 1.0). # to change to a 3D world, change the (20, 20, 0) below # to (20, 20, 20)... a similar change is required in the # Food object self set-wander-range to WANDER_RANGE. self randomize-location. self handle-collisions with-type "Food" with-method "collide". + to collide with food (object): newLoc (vector). # if the food we hit is being dragged by another collector, let it go if ( food get-owner ): return. # if we have collided too recently, skip this collision, we don't # want to pick things up and then drop them immediately. if (justCollided > 0): { justCollided = 2. return. } justCollided = 2. # if we're carrying food, drop it if carrying: { # this line was added to attempt to favor dropping food in # piles close to the center. the further we get from the # center, the lower the chance that this statement will be # true. newLoc = (food get-location). newLoc += random[(2, 2, 2)] - (1, 1, 1). carrying move to newLoc. carrying set-owner to 0. carrying = 0. return. } # otherwise, pick up the food. food set-owner to self. carrying = food. + to iterate: # if we're carrying something, keep it near us if carrying: carrying move to (self get-location) - (1, 0, 0). justCollided -= 1. # since we've subclassed Wanderer, it is in charge of our motion, # so we'll ask it to run it's own iteration method. super iterate. } Mobile : Food (aka Foods) { + variables: owner (object). + to init: self set-shape to (controller get-food-shape). self set-color to (.8, .2, .2). self randomize-location. + to randomize-location: self move to random[2 * WANDER_RANGE] - WANDER_RANGE. + to set-owner to o (object): owner = o. + to get-owner: return owner. }