User:BUTTONpUSHER Jones/pet protocol/.pet

From Second Life Wiki
Jump to navigation Jump to search

integer DEBUG = FALSE; // if TRUE, chat results to the owner.
integer DEBUG2 = TRUE; // for debugging the current piece of code I'm working on.

string gBehavior_0; // this pet's behavior
string gBehavior_1; // one other pet's behavior
list glBehaviors_MRU = [0,0,0  ,0,0,0  ,0,0,0  ,0,0,0  ,0,0,0  ,0,0,0  ,0,0,0  ,0,0,0  ,0,0,0  ,0,0,0]; // last 10 pet keys and their fight/flee parameters "ID, fight, flee"
// string gCurrentAction; delete?
list gActions; // Action probabilities
list gObey; // obey values for threat, neutral, prey, owner, other avatar
list glCurrentMessage; // the most recently received message
float gTime = 0; //sum of all action probabilities
integer gL1; // listen handler for owner
integer gL2; // listen handler for pet introduction channel
integer gL3; // listen handler for group channel
integer gL4; // listen handler for pet's private channel
integer gIntroduction_channel = 9000;
integer gGroup_channel = 1; //this value should be defined in the read_behavior function;
integer gPet_channel;
key gOwner;

// get_pet_channel grabs the numbers in the last 9 digits of this pet's key. We will use this integer as this pet's private chat channel.
integer get_pet_channel(key ID_key)
{
    integer temp_ID = (integer)llDumpList2String(llParseString2List(llGetSubString(ID_key, 28, 37), ["-","a","b","c","d","e","f"], []), "");
    return temp_ID;
}

initialize()
{
gOwner = llGetOwner();
llListenRemove(gL1);
llListenRemove(gL2);
llListenRemove(gL3);
//integer llListen(integer channel, string name, key id, string msg);
gL1 = llListen (0, "", gOwner,"");
gL2 = llListen (gIntroduction_channel, "", "", "");
gL3 = llListen (gGroup_channel, "", "", "");
gPet_channel = get_pet_channel(llGetKey());

// llWhisper(0, (string)gPet_key + " "+ (string)llGetKey());
gL4 = llListen (gPet_channel, "", "", "");
gTime = 0;
llSetTimerEvent(10); //move this to a better place. This is how often we send our Behavior to the introduction channel.
read_behavior();
}

//string get_param_value (string)
//{
    
    
read_behavior()
{
// read behavior from notecard, email, or XML-RPC
read_notecard();
// hard-coded these values for now
gBehavior_0 = "fight|0.3 + flee|0.4 + type|dog + subtype|beagle + action|watching + target|master + group|6500";
if(DEBUG)llOwnerSay(":.pet: " + (string)gBehavior_0);

gActions = [
    40,"sleep",
    1,"speak",
    20,"follow + target|owner",
    10,"evade + target|owner + offsetR| <-0,0,0> + distance|4.5",
    30,"command + action|eat + target|owner",
    10,"command + action|stay",
    50,"command + action|follow + target|mykey + offsetR|<-5,0,0>"
    ];

// the following sums the probabilities of the possible actions
    integer i;
    integer max = llGetListLength(gActions);
    for (i=0;i<max;i+=2)
    {
        gTime = gTime + llList2Float(gActions, i);
//        llWhisper(0,(string)gTime);
    }

gObey = [1.0, 0.5, 0.1, 0.9, 0.5];

}

read_notecard()
{
// Read description
// Read actions list
}

write_behavior() {// IM's or emails owner the current behavior
}


//////////////////////////////////////////////////////////////////////////
// CHOOSE BEHAVIOR
// mod: mood modifier:
//      < 1 will only do the first mod% of the behaviors
//      = 1 will do behaviors exactly as specified (will do a behavior every time)
//      > 1 has increasing chance of doing nothing
// time: the sum of all 'chances' much faster to calculate this ahead of time then as you go
// behaviors: A list that looks like [chance, "behavior_command", chance, "behavior_command"
//        ex: [0.4, "bark", 0.2, "sit"] or [4, "bark", 2, "sit"]
// Num and target are sent with the link message.  Perhaps always call this with the key of
// any currently targeted animal?  Will work fine if 0 and "" are used respectively.
//
// Example call, although behavior should be a list stored in a variable made from reading a notecard...
// choose_behavior(1,0.6,[0.4,"sleep",0.2,"bark"],0,"");
choose_behavior(float mod, float time, list behaviors, integer num, key target)
{
    float choice = llFrand(time * mod);
//    llWhisper(0,"time = "+(string)time);
//    llWhisper(0,"choice = "+(string)choice);
    integer i;
    integer max = llGetListLength(behaviors);
    for (i=0;i<max;i+=2)
    {
        if (choice < (float)llList2String(behaviors,i))
        {
            //Do this action!
            llMessageLinked(LINK_SET,num,llList2String(behaviors,i+1),target);
//            llWhisper(0,llList2String(behaviors,i+1));
llSetText(llList2String(behaviors,i+1), <0.5,0.5,1>,1);
            return;
        }
        else
        {
            choice -= llList2Float(behaviors,i);
        }
    }
}


introduce()
{
    llSay(gIntroduction_channel, "introduction + "+gBehavior_0);    
}

//////////////////////////////////////////////////////////////////////////
// OBEY function
// Any incoming commands are sent to this function. This script determines
// if the command will be obeyed based on values from the pet's behavior
// setup. If the command will be obeyed, it will be sent out to the other
// scripts in the pet.
// There are 5 parameters for the obey variable, 
// (threat, neutral, prey, owner, other avatar),
// each ranging from 0 to 1. 
// If the parameter is 0, the pet will never obey a command from something
// in that class, if it's 1 the pet will always obey that command.
integer obey ( string command, string string_this_pet, key commander )
{
//gBehavior_0 = "fight|0.3 + flee|0.4 + type|dog + subtype|beagle + action|watching + target|master + group|6500";
    list list_this_pet = llParseString2List(string_this_pet, ["|", "+", " "], []);
if(DEBUG)llOwnerSay(":.pet: " + "list_this_pet is "+llDumpList2String(list_this_pet, ","));
//integer llSubStringIndex(string source, string pattern)
    float this_pet_flee = llList2Float(list_this_pet, (llListFindList(list_this_pet, ["flee"])+1));
    float this_pet_fight = llList2Float(list_this_pet, (llListFindList(list_this_pet, ["fight"])+1));
//check that we actually have a flee & fight value for commander in our MRU. if not, assume commander has fight of 0, flee of 1.
    float commander_flee = 1;
    float commander_fight = 0;
    integer obey = FALSE;
//NEED COMMANDER'S KEY
//THEN SEARCH THE MRU FOR THE KEY
integer commander_in_MRU = llListFindList(glBehaviors_MRU, [(string)commander]);
    if ( commander_in_MRU != -1 )
    {
if(DEBUG)llOwnerSay(":.pet: " + "commander_in_MRU is "+(string)commander_in_MRU);
//IF THE COMMANDER'S KEY IS IN OUR MRU
//READ THE FIGHT AND FLEE FROM OUR MRU
        commander_fight = llList2Float(glBehaviors_MRU, (commander_in_MRU+1));
if(DEBUG)llOwnerSay(":.pet: " + "llListFindList(list_this_pet) is "+(string)(llListFindList(list_this_pet, ["flee"])+1));

        commander_flee = llList2Float(glBehaviors_MRU, commander_in_MRU+2 );
//***to do*** make sure numbers are between 0.0 and 1.0
    }
;

//llSay(0, "glBehaviors_MRU is "+llDumpList2String(glBehaviors_MRU, ","));
if(DEBUG)llOwnerSay(":.pet: " + "this_pet_flee is "+(string)this_pet_flee+" & this_pet_fight is "+(string)this_pet_fight);
if(DEBUG)llOwnerSay(":.pet: " + "commander_flee is "+(string)commander_flee+" & commander_fight is "+(string)commander_fight);

        
    // owner
//    else if ( other == gOwner )
    {
//        if (llList2Float(commander,4) > llFrand(1)) // calculate chance of obeying the command
//            llMessageLinked(command);
    }
    
    
    
    //other
//    else if ( other != gOwner )
    {
//        if (llList2Float(commander,5) > llFrand(1)) // calculate chance of obeying the command
//            llMessageLinked(command);
    }

    // test if commander is a threat
    if ( commander_fight > this_pet_fight )
    {
llSay(0, (string)commander_fight +">"+ (string)this_pet_flee);
        if (llList2Float(gObey,0) > llFrand(1)) // calculate chance of obeying the command
        {
            llMessageLinked(-4, 0, command, NULL_KEY);
            obey = TRUE;
            llSay(0, "commander_fight > this_pet_flee. obey is "+(string)obey);
        }
    }


    
    // prey
//    else if ( this_pet.fight > commander.flee )
    {
//        if (llList2Float(commander,3) > llFrand(1)) // calculate chance of obeying the command
//            llMessageLinked(command);
    }
    
    

    // neutral
//    if ( commander.fight > this_pet.flee )
    {
//        if (llList2Float(obey,2) > llFrand(1)) // calculate chance of obeying the command
//            llMessageLinked(command);
    }
    
    
    
    


    return obey;
}

default
{
    state_entry()
    {
        initialize();
    }
    
    on_rez(integer start_param)
    {
        initialize();
    }

   listen(integer channel, string name, key id, string message)
   {
//  if id = gOwner
//  if id = pet_key
//  if id = pet_group
//    list lPet_key = [(string)get_pet_channel(id)];
//***to do***do a bounds check before converting to list?
    list glCurrentMessage = llParseString2List(message, ["|", "+", " "], []);
//gBehavior_1 = 
llSetText(llKey2Name(id)+": "+(string)message, <1,0,0>,1);
llSleep(0.01);
llSetText(llKey2Name(id)+": "+(string)message, <1,1,1>,1);
//llWhisper(0,(string)message);
//llSay(0, llList2String(glCurrentMessage, 0));
if (llList2String(glCurrentMessage, 0) == "command")
    obey(message, gBehavior_0, id); // decide if this pet should obey the command
// (respond to requests)
// (respond to questions)
// (make note of introductions)
if (llList2String(glCurrentMessage, 0) == "introduction")
{
// glBehaviors_MRU = [ "a",  "0",  "0",  "0",  "0",  "0",  "0",  "b",  "9916", "h" ];
    integer Pet_key_in_MRU = llListFindList(glBehaviors_MRU, [(string)id]); // find where this pet is in our contact list
//llWhisper(0,"lPet_key "+(string)lPet_key+" is at '"+(string)Pet_key_in_MRU+"'");

//==================
//llSay(0, "glBehaviors_MRU is "+llDumpList2String(glBehaviors_MRU, ","));
//==================


// 1) See if the pet is already in the list
// 2) If they are in the list, remove them from the list and add them to the front of the list
// 3) if they are not in the list, add them to the front of the list and delete whatever is at the end of the list
    if (Pet_key_in_MRU == -1)  // if the pet is not in our contact list, add it and it's fight/flee parameters to the front of the list and delete the last pet on the list
    {
            // find the fight/flee parameters
            list temp_list = llParseString2List(message, ["|"," + "], []);
float fight_value = llList2Float(temp_list, (llListFindList(temp_list, ["fight"])+1));
float flee_value =  llList2Float(temp_list, (llListFindList(temp_list, ["flee"])+1));
//        llInstantMessage(llGetOwner(), "fight_value = '"+(string)fight_value+"'");
//        llInstantMessage(llGetOwner(), "flee_value = '"+(string)flee_value+"'");
glBehaviors_MRU = [(string)id, fight_value, flee_value]+glBehaviors_MRU;

glBehaviors_MRU = llDeleteSubList(glBehaviors_MRU, 27, 29);

//glBehaviors_MRU = ["A", "5", "orange"]+glBehaviors_MRU;
//    llInstantMessage(llGetOwner(), "glBehaviors_MRU = '"+(string)glBehaviors_MRU+"'");
//        llInstantMessage(llGetOwner(), "lPet_key = '"+(string)llget_param_value("fight|")+"'");
    }
    else 
    {
            // find the fight/flee parameters
    list temp_list = llParseString2List(message, ["|"," + "], []);
    float fight_value = llList2Float(temp_list, (llListFindList(temp_list, ["fight"])+1));
    float flee_value =  llList2Float(temp_list, (llListFindList(temp_list, ["flee"])+1));
glBehaviors_MRU = llDeleteSubList(glBehaviors_MRU, Pet_key_in_MRU, Pet_key_in_MRU+2);
glBehaviors_MRU = [(string)id, fight_value, flee_value]+glBehaviors_MRU;
     
    }
    
    }

    }
    
    changed(integer change)
    {
// read_notecard;
    }
    
    timer()
    {
// if not in the middle of behavior??
introduce();
//choose_behavior(float mod, float time, list behaviors, integer num, key target)
choose_behavior(1,gTime,gActions,0,"");

// stay_close_to_owner();
    }

}