/* * * HEATBUGS in MAML * (c) 1998, CEU Systems Laboratory * * This simulation is based on the following model: * * Heatbugs application. Copyright (C) 1996 Santa Fe Institute. * This library is distributed without any warranty; without even the * implied warranty of merchantability or fitness for a particular purpose. * See file LICENSE for details and terms of copying. * */ // This observer is to observe a Heatbugs model when the graphical interface // is running. We have graphical windows and data analysis stuff. //////////////////////////////////////////////////////////////////////////// // Taking the model to be observed $import "Model.maml"; //////////////////////////////////////////////////////////////////////////// @observe Model { @uses ; // We need this Swarm package for // the nice graphical tools we are // using // Variables of the observer @var: int displayFrequency; // The frequency of display refresh // Graphical gadgets @var: XColormap colormap; @var: ZoomRaster worldRaster; @var: EZGraph unhappyGraph; @var: Value2dDisplay heatDisplay; // Tool to display the heat space @var: Object2dDisplay heatbugDisplay; // Tool to display the agents //////////////////////////////////////////////////////////////////////////// // Extension of the agents' code with stuff connected to // the observation @extendAgent Heatbug { @var inline: Color bugColor; // New state variable // (color on the display) // Returns the value of the state variable (for the graph) @sub: (double) getUnhappiness { return unhappiness; } // Draws the bug on the display @sub: (void) drawSelfOn: (Raster) r { [r drawPointX: x Y: y Color: bugColor]; } // Setting the new state variable @sub: (void) setBugColor: (Color) c { bugColor = (int) c; } } // Observational extension of the model itself // (These subroutines provide access to some of the internal // variables of the model). @sub: (id) getHeatbugList { return groupOfHeatbug; } @sub: (Grid2d) getWorld { return world; } @sub: (HeatSpace) getHeat {return heat; } // A piece of bad code inherited from the original heatbugs model // It is supposed to create a new bug on the fly, but can only // add a pre-existing one again. @sub: (id) addHeatbug: (Heatbug) bug { [groupOfHeatbug addLast: bug]; return self; } // Another observational subroutin to be called by the user. (Through // this you can dynamically add bugs to be recorded on the graph of // unhappiness. @sub: (id) graphBug: (id) aBug { [unhappyGraph createSequence: "Bug" withFeedFrom: aBug andSelector: M(getUnhappiness)] ; return self ; } //////////////////////////////////////////////////////////////////////////// // Variables to be probed @probe: var "numBugs", var "diffuseConstant", var "worldXSize", var "worldYSize", var "minIdealTemp", var "maxIdealTemp", var "minOutputHeat", var "maxOutputHeat", var "randomMoveProbability",sub "addHeatbug:", var "displayFrequency", sub "graphBug:"; //////////////////////////////////////////////////////////////////////////// // The schedule of the observation @schedule cyclic (displayFrequency) { 0: @planDef seq { @to heatDisplay display; // Display the heat @to heatbugDisplay display; // And the bugs @to worldRaster drawSelf; // Refresh them on the screen @to unhappyGraph step; // Update the graph } } //////////////////////////////////////////////////////////////////////////// // Initialization of the observer @init: // Setting the default values of the parameters displayFrequency = 1; numBugs = 100; evaporationRate = 0.99; diffuseConstant = 1.0; worldXSize = 80; worldYSize = 80; minIdealTemp = 17000; maxIdealTemp = 31000; minOutputHeat = 3000; maxOutputHeat = 10000; randomMoveProbability = 0.0; // Building the probes and stopping the model to // let the user alter the parameters @buildProbes; [model probe]; [controlPanel setStateStopped]; // Initialize the model with the (possibly altered) parameters @initModel; // Creating the graphical gadgets // Creating the color scale @create XColormap colormap; { int i; // Red scale for the heat for (i = 0; i < 64; i++) [colormap setColor: i ToRed: (double)i / 63.0 Green: 0 Blue: 0]; // Colors for the bugs (normal/displayed on the graph) [colormap setColor: 64 ToName: "green"]; [colormap setColor: 65 ToName: "white"]; // Setting the color of all bugs to green initially [[model getHeatbugList] forEach: M(setBugColor:) : (void *) 64]; } // Creating the display window for the 'World' @create ZoomRaster worldRaster; [worldRaster setColormap: colormap]; [worldRaster setZoomFactor: 4]; [worldRaster setWidth: [[model getWorld] getSizeX] Height: [[model getWorld] getSizeY]]; [worldRaster setWindowTitle: "Heat World"]; [worldRaster pack]; // draw the window. // Creating the tool to display the heat cells @create Value2dDisplay heatDisplay { [heatDisplay setDisplayWidget: worldRaster Colormap: colormap]; [heatDisplay setDiscrete2dToDisplay: [model getHeat]]; [heatDisplay setDisplayMappingM: 512 C: 0]; // turn [0,32768) -> [0,64) } // Creating the tool to display the bugs @create Object2dDisplay heatbugDisplay { [heatbugDisplay setDisplayWidget: worldRaster]; [heatbugDisplay setDiscrete2dToDisplay: [model getWorld]]; [heatbugDisplay setObjectCollection: [model getHeatbugList]]; [heatbugDisplay setDisplayMessage: M(drawSelfOn:)]; // draw method } // Setting the right button click on the display to bring up an observer // window for the bug underneath [worldRaster setButton: ButtonRight Client: heatbugDisplay Message: M(makeProbeAtX:Y:)]; // Creating the graph gadget @create EZGraph unhappyGraph { [unhappyGraph setTitle: "unhappiness of bugs vs. time"]; [unhappyGraph setAxisLabelsX: "time" Y: "unhappiness"]; } [unhappyGraph createAverageSequence: "unhappiness" withFeedFrom: [model getHeatbugList] andSelector: M(getUnhappiness)] ; }