//*************************************************************** // Copyright 2008 Centre For Advanced Spatial Analysis, UCL // // Author: Joel Dearden, University College London // // Contact: j.dearden@ucl.ac.uk // // Joel Dearden, // Centre for Advanced Spatial Analysis, // University College London, // 1-19 Torrington Place, // London, // WC1E 7HB // // // This file is part of SLSegregationModel. // // SLSegregationModel is free software: you can redistribute it and/or modify // it under the terms of the GNU General Public License as published by // the Free Software Foundation, either version 3 of the License, or // (at your option) any later version. // // SLSegregationModel is distributed in the hope that it will be useful, // but WITHOUT ANY WARRANTY; without even the implied warranty of // MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the // GNU General Public License for more details. // // You should have received a copy of the GNU General Public License // along with SLSegregationModel. If not, see . // //*************************************************************** integer gridSize = 12; float offsetToGrid = 0.5; //metres (in X and Y directions from controller to nearest corner of grid) float houseSpacing = 0.6; //metres integer segPref = 50; //percentage of neighbours that an agent wants like itself integer buttonInput = -33022; integer chatToHouse = -92822; integer chatToAgent = -72728; integer chatFromAgent = -72729; float updateInterval = 1.0; //seconds integer totalAgents = 0; integer currentAgentID = 0; integer talkToGrapher = -77662; integer totalAgentMoves = 0; //adapted from: http://rpgstats.com/wiki/index.php?title=LlFrand integer randint(integer lower, integer higher) { integer range = higher - lower; integer result = llFloor(llFrand(range + 1)) + lower; return result; } createAgent(integer i, integer j, string type) { vector controllerPos = llGetPos(); vector createPos; createPos.x = controllerPos.x + offsetToGrid + (i * houseSpacing); createPos.y = controllerPos.y + offsetToGrid + (j * houseSpacing); createPos.z = controllerPos.z; llSay(chatToHouse, "mi:" + (string) createPos); llRezObject(type, createPos, <0,0,0>, ZERO_ROTATION, totalAgents); totalAgents++; } default { state_entry() { llOwnerSay("script_started: waiting for initial touch input"); } touch_start(integer total_number) { llSay(0, "Touched."); state build_houses; } } state build_houses { state_entry() { llOwnerSay("building houses..."); llSetText("Current Segregation Preference = " + (string)segPref, <1,1,1>, 1.0); integer i; integer j; vector controllerPos = llGetPos(); vector currentHousePos; currentHousePos.z = controllerPos.z; //same for all for(i = 0; i < gridSize; i++) { for(j = 0; j < gridSize; j++) { currentHousePos.x = controllerPos.x + offsetToGrid + (i * houseSpacing); currentHousePos.y = controllerPos.y + offsetToGrid + (j * houseSpacing); llRezObject("house", currentHousePos, <0,0,0>, ZERO_ROTATION, segPref); } } state populate_grid; } } state populate_grid { state_entry() { //reset grapher llSay(talkToGrapher, "NEW"); totalAgentMoves = 0; llOwnerSay("placing agents randomly in the grid..."); totalAgents = 0; //go through every square in the grid // //each one has equal chance of being blue, red or empty UNTIL.... // // -we run out of blue agents (DON'T PLACE ANY MORE) // -we run out of red agents (DON'T PLACE ANY MORE) // -we reach the minimum number of squares left to place agents (PLACE AN AGENT EVERY TIME) integer i; integer j; integer blueAgentsLeftToPlace = llFloor((gridSize * gridSize) / 3); integer redAgentsLeftToPlace = llFloor((gridSize * gridSize) / 3); integer housesLeft = gridSize * gridSize; for(i = 0; i < gridSize; i++) { for(j = 0; j < gridSize; j++) { //if we run out of blue agents DON'T PLACE ANY MORE if(blueAgentsLeftToPlace <= 0) { if(redAgentsLeftToPlace <= 0) { //no more red or blue agents left to place //all remaining houses should be empty } else { //no more blue agents left to place //if we reach the minimum number of squares left to place agents PLACE AN AGENT EVERY TIME if(housesLeft <= (redAgentsLeftToPlace)) { //red agent createAgent(i, j, "red_agent"); redAgentsLeftToPlace--; } else { //red agent or empty if(llFrand(1.0) > 0.5) { createAgent(i, j, "red_agent"); redAgentsLeftToPlace--; } else { //empty } } } } else { if(redAgentsLeftToPlace <= 0) { //no more red agents left to place //if we reach the minimum number of squares left to place agents PLACE AN AGENT EVERY TIME if(housesLeft <= (blueAgentsLeftToPlace)) { //blue agent createAgent(i, j, "blue_agent"); blueAgentsLeftToPlace--; } else { //blue agent or empty if(llFrand(1.0) > 0.5) { createAgent(i, j, "blue_agent"); blueAgentsLeftToPlace--; } else { //empty } } } else { //both types of agents still to place //if we reach the minimum number of squares left to place agents PLACE AN AGENT EVERY TIME if(housesLeft <= (redAgentsLeftToPlace + blueAgentsLeftToPlace)) { //red agent or blue agent if(llFrand(1.0) > 0.5) { createAgent(i, j, "red_agent"); redAgentsLeftToPlace--; } else { createAgent(i, j, "blue_agent"); blueAgentsLeftToPlace--; } } else { //red agent or blue agent or empty if(llFrand(1.0) < 0.33) { //empty } else { if(llFrand(1.0) > 0.5) { createAgent(i, j, "red_agent"); redAgentsLeftToPlace--; } else { createAgent(i, j, "blue_agent"); blueAgentsLeftToPlace--; } } } } } housesLeft--; } } //tell agents the segPref value llSay(chatToAgent, "sp:" + (string)segPref); //tell them a second time incase any missed the first message... llSay(chatToAgent, "sp:" + (string)segPref); //calculate the number of free houses in the grid (remains constant throughout) integer freeHouses = (gridSize * gridSize) - (llFloor((gridSize * gridSize) / 3) + llFloor((gridSize * gridSize) / 3)); llOwnerSay("broadcasting freeHouses=" + (string)freeHouses); //tell agents the freeHouses value llSay(chatToAgent, "fh:" + (string)freeHouses); //tell them a second time incase any missed the first message... llSay(chatToAgent, "fh:" + (string)freeHouses); state ready; } } state ready { state_entry() { llListen(buttonInput, "", NULL_KEY, ""); llOwnerSay("ready to run: waiting for RUNMODEL command"); } listen(integer channel, string name, key id, string message) { if(channel == buttonInput) { if(message == "RUNMODEL") { state running; } if(message == "NEWGRID") { state new_grid; } if(llGetSubString(message, 0, 2) == "SP:") { //set new seg pref segPref = (integer) llGetSubString(message, 3, -1); state new_seg_pref; } } } } state running { state_entry() { llListen(buttonInput, "", NULL_KEY, ""); llOwnerSay("now running: touch to reset board"); currentAgentID = 0; llListen(chatFromAgent, "", NULL_KEY, ""); llSetTimerEvent(updateInterval); } timer() { //timer fired //cancel timer llSetTimerEvent(0); //tell next agent to move llOwnerSay("telling agent to move"); llSay(chatToAgent, "tm:" + (string)currentAgentID); //tell them twice in case of lost chat message llSay(chatToAgent, "tm:" + (string)currentAgentID); } listen(integer channel, string name, key id, string message) { if(channel == buttonInput) { if(message == "NEWGRID") { state new_grid; } if(llGetSubString(message, 0, 2) == "SP:") { //set new seg pref segPref = (integer) llGetSubString(message, 3, -1); state new_seg_pref; } } if(channel == chatFromAgent) { if(llGetSubString(message, 0, 2) == "tcf") { //agent finished thinking / moving llOwnerSay("agent finished move"); //update happiness state of board llSay(chatToAgent, "uha"); //tell grapher totalAgentMoves++; llSay(talkToGrapher, "TM:" + (string)totalAgentMoves); //get ready for next agent move currentAgentID++; //wrap around ID range if(currentAgentID >= totalAgents) { currentAgentID = 0; } llSetTimerEvent(updateInterval); } } } } state new_seg_pref { state_entry() { llOwnerSay("segPref changed to " + (string)segPref); llOwnerSay("clearing agents and houses - there will be a delay of 10 seconds..."); //delete agents and houses llSay(chatToAgent, "die"); llSay(chatToHouse, "die"); //wait a bit llSleep(2); //catch any agents and houses that missed the first message... llSay(chatToAgent, "die"); llSay(chatToHouse, "die"); //wait grid to clear llSleep(8); state build_houses; } } state new_grid { state_entry() { llOwnerSay("clearing agents - there will be a delay of 10 seconds..."); //delete agents and tell houses to reset llSay(chatToAgent, "die"); llSay(chatToHouse, "rst"); //wait a bit llSleep(2); //catch any agents and houses that missed the first message... llSay(chatToAgent, "die"); llSay(chatToHouse, "rst"); //wait grid to clear llSleep(8); state populate_grid; } }