Wizardry and Steamworks & BIO-SE Carbon Credits Simulator Field Area d Mouse Area |-----| _ - ***** *_| 1m | ***** |_| d | ***** | ***** 1m - ***** A(*) A(B) s scalar(d) * d v= - => v = ------------- t t Mouse visits all the locations on the field in time t. We assume that all locations contain plants and that, initially, the surface of the plant is equal to the surface of the mouse. A plant grows every 3600s. It has to grow 4 times to reach full maturity. Thus, a plant reaches maturity after: M(P) = 4 * 3600s = 14400s Hence, HAS to take at LEAST 14400s to visit all the locations on the field in order to give any plant the chance to reach full maturity. Thus, the speed that the mouse should move at is given by: scalar(d) * d (1) v = ------------- 14400s We know that the top speed of the mouse is approximately 3.6(1)m/s. However the mice will not always run at their top speed. On average we select the midpoint as being the average speed: V(mouse) = 1.8m/s Substituting, we obtain how large the area of the field must be so that a mouse moving at the average speed of 1.8m/s will cover the entire area of the field as well as giving an arbitrary plant a chance to reach full maturity: scalar(d) * d = 1.8m/s * 14400s Favorably, taking the geometry of the field as being a square, we can obtain the length length of one of the side of the field: --------------- d = / V(mouse) * t ~= 160.996m v Which represents the MAXIMAL length of the side of the square so that an arbitrary plant gets a chance to reach maturity. That is because the model assumes that a mouse will visit a new location every time the mouse moves. Coming back to the field of plants: * * * * * * * * * * * * * * * 1 P(*) = ---------- * * * * * N pts And given an uniform selection of points every point where a plant can be found stands an equal chance to be selected on the next draw. When the mouse visits that point, it eats the plant so that point becomes visited. d |---------|_ * * * * * | | * * * * * | | d * * * * * | Consumed | ---------> * * * * - We know that the total number of valid nodes is: (2) N(nodes) = d^2 In order to draw a particular point from the field we need N/N trials. To draw another unique point we need N/(N-1) trials. Generalizing the total number of trials before the field has been entirely sweeped using the uniform selection of points is given by: (3) TT = N(nodes) * H(N(nodes)) where H is the harmonic series from 1 to N points on the field: N +----- \ 1 1 1 H(N)= + - = 1 + ----- + ------ + ... / n (i+1) (i+2) +----- i=1 Example 1 That means that given the length d of the square field, we can calculate how many trials are needed (a mouse travelling from point to point) before the entire field has been swept of plants. (2) N(nodes)= d^2 (3) TT = N(nodes) * H(N(nodes)) By choosing the length of the side of the square d, we obtain the number of points the mouse will visit on the field before we can be sure that the whole field has been swept of plants. Example 2 We can calculate the average velocity of the mouse so that an arbitrary plant will be given the chance to reach maturity before it is eaten by a traveling mouse. scalar(d) * d V = ------------- t where t is the time a plant takes to reach full maturity and d is length of the side of the square field. Example 3 As a completion to Example 1, given a square field with the legnth of the side of the square d and a plant placed arbitrarily on the field, we can calculate the probability if that plant to be eaten by the mouse 1 P(*) = ----- N N = d^2 As we can see from our numeric calculations the length of the side of the square should AT LEAST be 138.821m, giving us an area of appoximatively: 25914 m^2 ~= 26 km^2 So that a mouse traveling at an average uniform speed of 1.8m/s would give an arbitrary plant the chance to grow to full maturity, instead of consuming it before that. Comments Ironically, the errors that will occurr will be due to physical model and the coding itself rather than the mathematical model. For instance, there is no rationale behind the movements of the mouse and the next hop generator selects random destinations for the mouse based on uniformly scattered plots accross the field. The only parameters as seen from above are reduced to: * average uniform mouse speed * length of the side of the square field * time for a plant to reach full maturity. Similarly, the physical movement is simulated through dampening which implies an acceleration or decelaration which might incur errors leading to results that should not be interpreted as a consequence of a particular biological event. More precisely, given a fixed choice of d, a fixed choice of the velocity v and a choice of a time t, one can trigger a resource exhaustion, where all the plants are consumed before they reach maturity. However, that is not due to some biological process but rather a consequence of carefully selected values. Under the current abstraction, the choice of the geometric shape of the field or mice is irrelevant. Even if we could choose to repeat the calculations in a circular field, the only difference is that the calculations will be different but they will still be under the constraints of the abstracted model.
/////////////////////////////////////////////////////////////////////////// // Copyright (C) Wizardry and Steamworks 2011 - License: GNU GPLv3 // // Please see: http://www.gnu.org/licenses/gpl.html for legal details, // // rights of fair usage, the disclaimer and warranty conditions. // /////////////////////////////////////////////////////////////////////////// ////////////////////////////////////////////////////////// // CONFIGURATION // ////////////////////////////////////////////////////////// // The minimum distance in meters when the // primitive will consider that it has reached // its next destination. float TARGET_AFFINITY = .2; /////////////////////////////////////////////////////////////////////////// // INTERNALS // /////////////////////////////////////////////////////////////////////////// vector origin = ZERO_VECTOR; float radius = 0; integer fuel = 0; integer tid; vector wasCirclePoint() { float x = llPow(-1, 1 + (integer) llFrand(2)) * llFrand(radius*2); float y = llPow(-1, 1 + (integer) llFrand(2)) * llFrand(radius*2); if(llPow(x,2) + llPow(y,2) <= llPow(radius,2)) { llOwnerSay((string)<x,y,0>); return <x, y, 0>; } return wasCirclePoint(); } moveTo(vector destination) { llTargetRemove(tid); tid = llTarget(destination, TARGET_AFFINITY); llLookAt(destination, .6, .6); float distance = llVecDist(llGetPos(), destination); llOwnerSay("time:" + (string)(distance/.1151)); if(distance/.1151 > .05) { llMoveToTarget(destination, distance/.1151); return; } llMoveToTarget(destination, .05); } key owner = NULL_KEY; key objCol = NULL_KEY; default { state_entry() { llSetStatus(STATUS_PHYSICS, FALSE); llSetText("Primsect\n" + (string)fuel + "$", <1,1,1>, 1);› tid = (integer)("0x"+llGetSubString((string)owner,-8,-1)) ^ 0xBFFFFFFF; llOwnerSay("listening: " + (string)tid); tid = llListen(tid, "[K] Soil", "", ""); } on_rez(integer param) { owner = llGetOwner(); } listen(integer channel, string name, key id, string message) { list chat = llParseString2List(message, ["="], [""]); if(llList2String(chat, 0) != "@center") return; llListenRemove(tid); list para = llParseString2List(llList2String(chat, 1), ["|"], [""]); origin.x = llList2Float(para, 0); origin.y = llList2Float(para, 1); origin.z = llList2Float(para, 2) + 1; llSetPos(origin); radius = llList2Float(para, 3); state wander; } } state wander { state_entry() { llSetStatus(STATUS_PHYSICS, TRUE); llSetForce(<0,0,9.81> * llGetMass(), 0); llSetStatus(STATUS_ROTATE_X|STATUS_ROTATE_Y|STATUS_ROTATE_Z, FALSE); llVolumeDetect(TRUE); llCollisionFilter("[K] Grass", "", 1); moveTo(origin + wasCirclePoint()); } collision(integer num) { if(llDetectedKey(0) == objCol) return; objCol = llDetectedKey(0); fuel += llList2Integer(llGetObjectDetails(objCol, [OBJECT_DESC]), 0)/10; llSetText("Primsect\n" + (string)fuel + "$", <1,1,1>, 1); } at_target(integer tnum, vector targetpos, vector ourpos) { //if(tnum != tid) return; llOwnerSay("REACHED TARGET"); moveTo(origin + wasCirclePoint()); } }
/////////////////////////////////////////////////////////////////////////// // Copyright (C) Wizardry and Steamworks 2011 - License: GNU GPLv3 // // Please see: http://www.gnu.org/licenses/gpl.html for legal details, // // rights of fair usage, the disclaimer and warranty conditions. // /////////////////////////////////////////////////////////////////////////// /////////////////////////////////////////////////////////////////////////// // INTERNALS // /////////////////////////////////////////////////////////////////////////// vector origin = ZERO_VECTOR; vector scale = ZERO_VECTOR; vector wasCirclePoint(float radius) { float x = llPow(-1, 1 + (integer) llFrand(2)) * llFrand(radius*2); float y = llPow(-1, 1 + (integer) llFrand(2)) * llFrand(radius*2); if(llPow(x,2) + llPow(y,2) <= llPow(radius,2)) return <x, y, 0>; return wasCirclePoint(radius); } key owner = NULL_KEY; integer chan = 0; default { state_entry() { origin = llGetPos(); scale = llGetScale(); chan = (integer)("0x"+llGetSubString((string)owner,-8,-1)) ^ 0xBFFFFFFF; chan = llListen(chan, "[K] Grass", "", ""); llSetTimerEvent(1); } on_rez(integer param) { owner = llGetOwner(); } listen(integer channel, string name, key id, string message) { list chat = llParseString2List(message, ["="], [""]); if(llList2String(chat, 0) != "@spawn") return; llListenRemove(chan); list para = llParseString2List(llList2String(chat, 1), ["|"], [""]); vector objOrigin = ZERO_VECTOR; objOrigin.x = llList2Float(para, 0); objOrigin.y = llList2Float(para, 1); objOrigin.z = origin.z; llRezObject("[K] Primsect", origin + wasCirclePoint(.6), ZERO_VECTOR, ZERO_ROTATION, 1); } touch_start(integer total_number) { llRezObject("[K] Primsect", origin + wasCirclePoint(scale.x/2), ZERO_VECTOR, ZERO_ROTATION, 1); } timer() { integer chan = (integer)("0x"+llGetSubString((string)owner,-8,-1)) ^ 0xBFFFFFFF; llRegionSay(chan, "@center=" + (string)origin.x + "|" + (string)origin.y + "|" + (string)origin.z + "|" + (string)(scale.x/2)); } }
/////////////////////////////////////////////////////////////////////////// // Copyright (C) Wizardry and Steamworks 2011 - License: GNU GPLv3 // // Please see: http://www.gnu.org/licenses/gpl.html for legal details, // // rights of fair usage, the disclaimer and warranty conditions. // /////////////////////////////////////////////////////////////////////////// ////////////////////////////////////////////////////////// // CONFIGURATION // ////////////////////////////////////////////////////////// // The delay in seconds to wait b // before the object grows another // GROWTH_PER_INTERVAL meters. float GROWTH_INTERVAL = 3600; ////////////////////////////////////////////////////////// // INTERNALS // ////////////////////////////////////////////////////////// integer fuel = 10; vector pos = ZERO_VECTOR; key owner = NULL_KEY; integer chan = 0; default { state_entry() { pos = llGetPos(); chan = (integer)("0x"+llGetSubString((string)owner,-8,-1)) ^ 0xBFFFFFFF; state growth; } on_rez(integer param) { owner = llGetOwner(); } } state growth { state_entry() { llCollisionFilter("[K] Primsect", "", 1); llSetObjectDesc((string)fuel); llSetText("Grass\n" + (string)fuel + "$", <1,1,1>, 1); llSetTimerEvent(GROWTH_INTERVAL); } collision(integer num) { llRegionSay(chan, "@consumed=" + (string)pos.x + "|" + (string)pos.y); llOwnerSay("Bye bye..."); } timer() { vector size = llGetScale(); if(size.z >= .5) { llRegionSay(chan, "@spawn=" + (string)pos.x + "|" + (string)pos.y); llSetTimerEvent(GROWTH_INTERVAL*4); return; } size += <.1, .1, .1>; llSetScale(<size.x, size.y, size.z>); pos.z += .05; llSetPos(<pos.x, pos.y, pos.z>); fuel += 10; llSetObjectDesc((string)fuel); llSetText((string)fuel + "$", <1,1,1>, 1); } }
For the contact, copyright, license, warranty and privacy terms for the usage of this website please see the contact, license, privacy, copyright.