/////////////////////////////////////////////////////////////////////////// // 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. // /////////////////////////////////////////////////////////////////////////// // Reference land types list _landReference = [ "Green", 1, "Black", 2, "Brown", 3 ]; // Reference genomes list _genotypeReference = [ "BB", 1, "Bb", 2, "bB", 3, "bb", 4 ]; vector _iPos = ZERO_VECTOR; integer _comChannel = 0; integer _mouseID = 1; string _landType = ""; integer _allelesB = 0; integer _allelesb = 0; // Owner key. key _owner = NULL_KEY; // A quicksort, providing a stable map between two sets of elements. list dualQuicksort(list a, list b) { if(llGetListLength(a) <= 1) return a+b; float pivot_a = llList2Float(a, llGetListLength(a)/2); string pivot_b = llList2String(b, llGetListLength(b)/2); a = llDeleteSubList(a, llGetListLength(a)/2, llGetListLength(a)/2); b = llDeleteSubList(b, llGetListLength(b)/2, llGetListLength(b)/2); list less = []; list less_b = []; list more = []; list more_b = []; integer i = 0; do { if(llList2Float(a, i) > pivot_a) { less += llList2List(a, i, i); less_b += llList2List(b, i, i); } else { more += llList2List(a, i, i); more_b += llList2List(b, i, i); } } while(++i<llGetListLength(a)*2); return dualQuicksort(less, less_b) + [ pivot_a ] + [ pivot_b ] + dualQuicksort(more, more_b); } vector circlePoint() { float y = llPow(-1, 1 + (integer) llFrand(2)) * llFrand(6); float z = llPow(-1, 1 + (integer) llFrand(2)) * llFrand(6); if(llPow(y,2) + llPow(z,2) <= 36) return _iPos + <0.2, y, z>; return circlePoint(); } // Returns the next random coordinates. //vector nextCoordinates() { // float r = llFrand(10); // float a = llFrand(TWO_PI); // float b = llFrand(TWO_PI); // return <_iPos.x, _iPos.y + r * llCos(a), _iPos.z + r * llSin(b)>; // // use circle instead... // //return _iPos + <r * llCos(a) * llCos(b), r * llCos(a) * llSin(b), r * llSin(a)>; //} default { state_entry() { _allelesB = 0; _allelesb = 0; _mouseID = 1; _owner = llGetOwner(); _iPos = llGetPos(); _comChannel = ((integer)("0x"+llGetSubString(_owner,-8,-1)) & 0x3FFFFFFF) ^ 0xBFFFFFFF; llListen(_comChannel+3, "", "[K] Brown Moth", ""); llListen(_comChannel+3, "", "[K] Black Moth", ""); } link_message(integer sender_num, integer num, string str, key id) { list opt = llParseString2List(str, [",", ":"], []); integer itra = llGetListLength(opt)-1; do { if(llList2String(opt, itra) == "PGS_STOP") { _allelesB = 0; _allelesb = 0; _mouseID = 1; jump next_msg; } if(llList2String(opt, itra) == "LAND") { _landType = llList2String(opt, itra+1); jump next_msg; } if(llList2String(opt, itra) == "GENOME") { list alleles = llParseString2List(llList2String(opt, itra+1), [], ["B", "b"]); integer itrb=llGetListLength(alleles)-1; do { if(llList2String(alleles, itrb) == "b") { ++_allelesb; jump next_allele; } if(llList2String(alleles, itrb) == "B") { ++_allelesB; jump next_allele; } @next_allele; } while(--itrb>=0); jump next_msg; } @next_msg; } while(--itra>=0); } listen(integer channel, string name, key id, string message) { list opt = llParseString2List(message, [",", ":"], []); if(llList2String(opt, 0) == "BLK_DEATH" || llList2String(opt, 0) == "BWN_DEATH") { integer itra = llGetListLength(opt)-1; do { if(llList2String(opt, itra) == "GENOME") { list alleles_death = llParseString2List(llList2String(opt, itra+1), [], ["B", "b"]); integer itrb=llGetListLength(alleles_death)-1; do { if(llList2String(alleles_death, itrb) == "b") { --_allelesb; jump next; } if(llList2String(alleles_death, itrb) == "B") { --_allelesB; jump next; } @next; } while(--itrb>=0); } } while(--itra>=0); float p = (float)((float)_allelesB/ (float)(_allelesB + _allelesb)); float q = (float)((float)_allelesb/(float)(_allelesB + _allelesb)); list sortedp = dualQuicksort([ llPow(p, 2), p*q, p*q, llPow(q, 2) ], [ "BB", "Bb", "bB", "bb" ]); list alleles = llList2ListStrided(llDeleteSubList(sortedp, 0, 0), 0, llGetListLength(sortedp)-1, 2); list alleles_prob = llList2ListStrided(sortedp, 0, llGetListLength(sortedp)-1, 2); //llSay(0, llDumpList2String(alleles, "|")); //llSay(0, llDumpList2String(alleles_prob, "|")); //llSay(0, "Probabilities add up to: " + (string)llListStatistics(LIST_STAT_SUM, alleles_prob)); float rnd = llFrand(1); //llSay(0, "Random number is: " + (string)rnd); float cum = 0; string genotype = ""; itra = llGetListLength(alleles)-1; do { cum += llList2Float(alleles_prob, itra); if(cum >= rnd) { genotype = llList2String(alleles, itra); jump draw; } } while(--itra>-1); @draw; //llSay(0, "Cumultative draw value was: " + (string)cum); //llSay(0, "Drew: " + genotype); if(genotype == "bb") { llRezObject("[K] Brown Moth", circlePoint(), ZERO_VECTOR, ZERO_ROTATION, (integer)("5" + (string)(llList2Integer(_genotypeReference, llListFindList(_genotypeReference, (list)genotype)+1)) + "6" + (string)(llList2Integer(_landReference, llListFindList(_landReference, (list)_landType)+1)) + (string)_mouseID)); llMessageLinked(LINK_SET, 0, "BWN_BIRTH:" + (string)_mouseID + ",GENOME:" + genotype + ",LAND:" + _landType + ",CURRENT_P:" + (string)p + ",CURRENT_Q:" + (string)q, ""); ++_mouseID; llRegionSay(_comChannel+1, (string)_iPos); return; } llRezObject("[K] Black Moth", circlePoint(), ZERO_VECTOR, ZERO_ROTATION, (integer)("5" + (string)(llList2Integer(_genotypeReference, llListFindList(_genotypeReference, (list)genotype)+1)) + "6" + (string)(llList2Integer(_landReference, llListFindList(_landReference, (list)_landType)+1)) + (string)_mouseID)); llMessageLinked(LINK_SET, 0, "BLK_BIRTH:" + (string)_mouseID + ",GENOME:" + genotype + ",LAND:" + _landType + ",CURRENT_P:" + (string)p + ",CURRENT_Q:" + (string)q, ""); ++_mouseID; llRegionSay(_comChannel+1, (string)_iPos); return; } } changed(integer change) { if(change & CHANGED_OWNER) llResetScript(); } on_rez(integer num) { llResetScript(); } }