Title: Animal Farm 5th edition: 13 April 2003 ;*** CONSTANT PARAMETERS ;-- sheeps layout parameters make "SHEEP_START [190 25] make "SHEEP_GAP 30 make "SHEEP_SIDE 40 ;-- barn & food layout parameters make "FOOD_SIDE 25 make "BARN_NAME "Barn make "BARN_COLOR [100 100 0] make "BARN_LOCATION [78 340] make "BARN_WIDTH 156 make "BARN_HEIGHT 680 ;-- scene's background color ([red green blue], each color element range is 0-255) make "SCENE_COLOR [188 182 129] ;-- each sheep will find all food that is placed in a vertical (Y+) ;-- order above it, using the rule (abs (food.x-sheep.x))<:DX make "DX 10 ;*** GLOBAL VARIABLES ;-- two lists, holding sheep and food scene object names make "sheep [] make "food [] ;*** GENERAL UTILITY SUBROUTINES ;-- return the given list without the given item to removeFromList :item :list ;-- return given list's length ;-- (this is a workarround cause the "Scene" component [unfortunately] redefines the "length" primitive to return length quantity of a scene object) to len :list ;-- returns the folder where this microworld's file exists to myMicroworldFolder ;*** SCENE UTILITY SUBROUTINES ************************************ ;-- returns the x part of a scene object's location, given the object's name to getLocationX :name ;-- returns the y part of a scene object's location, given the object's name to getLocationY :name ;-- returns the width of a scene object, given the object's name to getWidth :name ;-- returns the height of a scene object, given the object's name to getHeight :name ;-- make a scene object (using a SquareBox) ;-- initialize object with given name, location (x,y), side (=width=height) ;-- set object image using given image filename (relative path to microworld's folder) ;-- "refresh" parameter controls whether scene will be refreshed or not (use for batch creation of many sheep/food objects) to makeIcon :name :x :y :side :imageName :refresh ;-- remove given name from given list and remove scene object with that name to removeIcon :name :list ;-- return a given list of scene object names, sorted by the object locations' y part ;-- (used to have sheep start eating food above them from bottom to top) to sortIconsByY :icons ;-- return a given list of scene object names, sorted by the object locations' x part ;-- (used to have new sheep added to the right of the rightmost sheep) to sortIconsByX :icons ;-- return a given list of scene object names, sorted by the object locations ;-- (used to have new sheep added to the right of the rightmost sheep) to sortIconsByXY :icons ;*** MICROWORLD SUBROUTINES ;~~~> BARN <~~~ ;-- create and initialize barn object to makeBarn ;-- return list with names of food objects inside the barn to getFoodInBarn ;~~~> SHEEP <~~~ ;-- make sheep with given name and location (x,y) to makeSheep :name :x :y ;-- make some sheep given a starting location (startX,startY) and a count ;-- for naming use given base name, appending an index to it (starting from startNameIndex) ;-- return list with those new sheep names to MakeSomeSheep :startX :startY :count :baseName :startNameIndex ;-- return last (rightmost) sheep's name to getLastSheep ;-- remove last sheep in sheep names' list and remove that from the scene too to removeLastSheep ;-- add a given number of sheep to the right of the rightmost sheep ;-- if no sheep exist, start at SHEEP_START location to addSheep :count ;-- add one more sheep to addNewSheep ;~~~ FOOD ~~~ ;-- make food with given name and location (x,y) ;-- "refresh" parameter controls whether scene will be refreshed or not (use for batch creation of many food objects) to makeFood :name :x :y :refresh ;-- make some food given a count ;-- for naming use given base name, appending an index to it (starting from startNameIndex) ;-- return list with those new food names to MakeSomeFood :count :baseName :startNameIndex ;-- visually store list of given food inside the barn to storeFood :food ;-- add given count of new food (into the barn) to addFood :count ;-- add one new portion of food (into the barn) to addNewFood ;-- remove food with given name to removeFood :foodName ;-- remove bottom-most food from those inside the barn ;-- if none inside barn, remove the bottomright-most food from any outside the barn to removeLastFood ;~~~ SHEEP FEEDING ~~~ ;-- place food with given name over sheep with given name, at given vertical index ;-- (location depends on x,y part of sheep's location and on FOOD_SIZE and this index) to placeFood :sheepName :foodName :index ;-- feed: place given count of food from given list above sheep with given name to feedOneSheep :sheepName :theFood :count ;-- stores all food back in the barn, then equally feeds all sheep: ;-- all sheep get (integer (:footCount/:sheepCount)) food and any remaining ;-- food (it's the modulo of the integer division) remains in the barn to feedSheep ;-- return list with names of food objects above sheep with given name ;-- using the rule (abs (food.x-sheep.x))<:DX to select a sheep's food to getSheepFood :theSheep ;-- sheep with given name eats (removes) the bottom-most food above it to eatOneSheepFood :sheepName ;-- all sheep eat the bottom-most food above them to eatFood ;*** SCENE SETUP ;-- set up scene with given number of sheep and food portions ;-- food portions get stored in the barn to setupScene :sheepCount :foodCount ;-- (re)initialize scene, creating as many sheep and food the user has specified ;-- food portions get stored in the barn ;-- reset day counter to 1 to reset ;*** SHEEP EATING SIMULATION ;-- increase day counter (no other actions/side-effects done) to newDay ;-- check if user wants to stop the automatic feeding (see if related checkbox has been checked) to feedingStopped ;-- sheeps start eating, eat bottom-most food above them every day to startSimulation ;*** TEST: SETUP SCENE WITH 4 SHEEP AND 10 FOOD PORTIONS setupScene 4 10