integer SET_POS = 10;
integer REPORT_POSITION = 20;
integer REQUEST_MOVE = 30;

default
{
        touch_start(integer total_number)
    {
        // As soon as the tile is touched, send a message to the frame telling it that we may need to move (whether the tile actually moves or not depends on the position of the gap)
         llMessageLinked (1, REQUEST_MOVE, "", NULL_KEY);           
    }
   
     link_message(integer sender_num, integer command, string str, key id)
    {
      // We need to respond to one of two commands: Either SET_POS or REPORT_POSITION. Note that SET_POS is always sent by the Frame, but REPORT_POSITION may come from the frame or from another tile
        if (command == SET_POS)
        {
            vector local_pos = llGetLocalPos();

            if (str == "1")
            {
                local_pos = <-0.5, 0.5, local_pos.z>;
            }
            if (str == "2")
            {
                local_pos = <0, 0.5, local_pos.z>;
            }
            if (str == "3")
            {
                local_pos = <0.5, 0.5, local_pos.z>;
            }
            if (str == "4")
            {
                local_pos = <-0.5, 0, local_pos.z>;
            }
            if (str == "5")
            {
                local_pos = <0, 0, local_pos.z>;
            }
            if (str == "6")
            {
                local_pos = <0.5, 0, local_pos.z>;
            }
            if (str == "7")
            {
                local_pos = <-0.5, -0.5, local_pos.z>;
            }
            if (str == "8")
            {
                local_pos = <0, -0.5, local_pos.z>;
            }
            if (str == "9")
            {
                local_pos = <0.5, -0.5, local_pos.z>;
            }               
            llSetPos(local_pos);
        }
       
        if (command == REPORT_POSITION)
        {
            vector local_pos = llGetLocalPos();
            string position = "0";           
         
            if (local_pos.x == -0.5 & local_pos.y == 0.5)
            {
                position = "1";
            }
           
            if (local_pos.x == 0 & local_pos.y == 0.5)
            {
                position = "2";
            }
           
            if (local_pos.x == 0.5 & local_pos.y == 0.5)
            {
                position = "3";
            }
           
            if (local_pos.x == -0.5 & local_pos.y == 0)
            {
                position = "4";
            }
           
            if (local_pos.x == 0 & local_pos.y == 0)
            {
                position = "5";
            }

            if (local_pos.x == 0.5 & local_pos.y == 0)
            {
                position = "6";
            }
           
            if (local_pos.x == -0.5 & local_pos.y == -0.5)
            {
                position = "7";
            }
           
            if (local_pos.x == 0 & local_pos.y == -0.5)
            {
                position = "8";
            }

            if (local_pos.x == 0.5 & local_pos.y == -0.5)
            {
                position = "9";
            }             

            llMessageLinked(1, REPORT_POSITION, position, NULL_KEY); // Report position to game controller

            integer this_tile = (integer)llGetSubString(llGetObjectName(), 5, 5);
           
            if (this_tile < 9)
            {
                llMessageLinked(this_tile + 2, REPORT_POSITION, "", NULL_KEY); // Report position to next tile, if this isn't the last tile. Note that tile 1 is prim number 2 in the set, so we need to add 2 to get to the next tile number (rather than just adding 1).
            }
           
        }
       
    }
}