Tic Tac Toe

De DigiWiki.

(Différences entre les versions)
(Page créée avec « The object we are scripting is composed of 9 cubes with an X/O texture pre-set and a back pane prim as the root prim. The link order of the child prims is assumed to be in an… »)
Ligne 1 : Ligne 1 :
-
The object we are scripting is composed of 9 cubes with an X/O texture pre-set and a back pane prim as the root prim. The link order of the child prims is assumed to be in any sequential reading order (left to right, top to bottom or similar).
 
-
 
-
 
-
Root Prim
 
-
 
-
The root prim is populated with the scripts below:
 
-
 
-
RootNanny (processes upload requests onto the child prims and manages object name)
 
-
 
<lsl>
<lsl>
-
// Message constants
+
// One-Prim Noughts and Crosses - OpenSim LSL script by Warin Cascabel (26 February 2009)
-
integer MSG_RESET = 0;
+
//
-
integer MSG_LINK_QUERY = 10;
+
// Please note:
-
integer MSG_LINK_REPLY = 11;
+
// As this script makes use of OpenSim-specific extensions to the Linden Scripting Language.
-
 
+
// This script will NOT work in Second Life.
-
// Globals to propagate
+
-
string version = "1.5";
+
-
integer pin = 321;
+
-
 
+
-
 
+
-
// State
+
-
integer current_link_nr;
+
-
// Stuff to send out
+
// Internal variables.
-
list remote_scripts = [ "TouchDisplay", "LinkNanny" ];
+
list Spaces = [-1,-1,-1,-1,-1,-1,-1,-1,-1];   // Keeps track of what's in which space of the board. -1=empty, 0=O, 1=X
 +
integer GameOver = 0;      // If nonzero, signals which row, column or diagonal has the win (or -1 for a draw)
 +
integer WhoseTurn = 1;    // Whose turn is it next? 0=O, 1=X
-
request_next_object_id(integer link_nr)
+
// DrawBoard()
 +
// Builds the dynamic texture command based on the contents of the Spaces list and the GameOver variable.   
 +
DrawBoard()
{
{
-
     // Send message, transmitting pin, hoping to get back objectid
+
     string dl;                                                 // holds the draw list
-
    llMessageLinked(link_nr, MSG_LINK_QUERY, (string)pin, NULL_KEY);
+
     integer i;                                                 // iterator for our for loop
-
               
+
     integer x;                                                 // holds the horizontal coordinate of each space
-
    // Set timer in case link isn't replying
+
     integer y;                                                 // holds the vertical coordinate of each space
-
     llSetTimerEvent(2); // 2 secs seems generous
+
-
}
+
-
 
+
-
default
+
-
{
+
-
     state_entry()
+
-
    {
+
-
        string name = llGetObjectName();
+
-
        integer space = llSubStringIndex(name, " v");
+
-
        if (space < 0) llSetObjectName(name + " v" + version);
+
-
        else llSetObjectName(llDeleteSubString(name, space+2, -1) + version);
+
-
        llListen(1, "", llGetOwner(), "update");
+
-
     }
+
-
 
+
-
    listen(integer channel, string name, key id, string message)
+
-
    {
+
-
        state uploading;
+
-
    }
+
-
}
+
-
 
+
-
state uploading
+
-
{
+
-
    state_entry()
+
-
    {
+
-
        current_link_nr = llGetNumberOfPrims();
+
-
        // Check if it's more than one
+
-
        if (1 < current_link_nr)
+
-
        {
+
-
            // avatars sitting on us get added at the end, so subtract...
+
-
            while (llGetAgentSize(llGetLinkKey(current_link_nr)))
+
-
                --current_link_nr;
+
-
            request_next_object_id(current_link_nr);
+
-
        }
+
-
    }
+
      
      
-
     link_message(integer from, integer msg_id, string str, key id)
+
     dl = osSetPenColor("", "white" );                          // Set the background to solid white
-
     {
+
     dl = osMovePen( dl, 0, 0 );
-
        if (from == current_link_nr && msg_id == MSG_LINK_REPLY)
+
    dl = osDrawFilledRectangle( dl, 128, 128 );
-
        {
+
    dl = osSetPenColor( dl, "black" );                         // Draw the grid in black
-
            llSetTimerEvent(0); // Cancel timeout
+
    dl = osSetPenSize( dl, 2 );
-
            integer i;
+
    dl = osDrawLine( dl, 43, 3, 43, 125 );
-
            for (i = 0; i < llGetListLength(remote_scripts); ++i)
+
    dl = osDrawLine( dl, 86, 3, 86, 125 );
-
            {
+
    dl = osDrawLine( dl, 3, 43, 125, 43 );
-
                string script = llList2String(remote_scripts, i);
+
    dl = osDrawLine( dl, 3, 86, 125, 86 );
-
                llSay(0, "Uploading '"+script+"' to link nr "+(string)current_link_nr);
+
     dl = osSetPenSize( dl, 6 );                                // Increase the pen size for our Xs and Os.
-
                llRemoteLoadScriptPin(id, script, pin, TRUE, 0);
+
-
            }
+
-
            current_link_nr--;
+
-
            if (1 < current_link_nr)
+
-
            {
+
-
                request_next_object_id(current_link_nr);
+
-
            }
+
-
            else
+
-
            {
+
-
                llSay(0, "Done uploading remote scripts.");
+
-
                state default;
+
-
            }
+
-
        }
+
-
     }
+
      
      
-
     timer()
+
     for (i = 0; i < 9; ++i)                                     // For each element in the Spaces list:
     {
     {
-
         llSay(0, "Failed to receive reply from link nr "+(string)current_link_nr);
+
         integer who = llList2Integer( Spaces, i );             // Get its value
-
         current_link_nr--;
+
         if (who > -1)                                          // Do nothing if it's -1 (empty)
-
        if (1 < current_link_nr)
+
         {
         {
-
             request_next_object_id(current_link_nr);
+
             x = (i % 3) * 43 + 21;                             // Calculate the center of the square
-
        }
+
            y = (i / 3) * 43 + 21;
-
        else
+
            if (who == 0)                                       // If it's an O:
-
        {
+
-
            llSay(0, "Done uploading remote scripts.");
+
-
            state default;
+
-
        }
+
-
    }
+
-
}
+
-
</lsl>
+
-
 
+
-
Controller (game logic)
+
-
 
+
-
<lsl>
+
-
// Message constants
+
-
integer MSG_RESET      = 0;
+
-
integer MSG_TOUCH      = 1;
+
-
integer MSG_SET_X      = 2;
+
-
integer MSG_SET_O      = 3;
+
-
integer MSG_IDLE      = 4;
+
-
integer MSG_IDLE_TOUCH = 5;
+
-
integer MSG_WIN        = 6;
+
-
 
+
-
// Game timeout
+
-
integer GAME_TIMEOUT = 20;
+
-
 
+
-
// Game state
+
-
key player_x;
+
-
key player_o;
+
-
string turn;
+
-
string game;
+
-
 
+
-
string at(integer u, integer v)
+
-
{
+
-
    integer p = u*3+v;
+
-
    return llGetSubString(game, p, p);
+
-
}
+
-
 
+
-
// return TRUE if game ends
+
-
integer game_ends(string player, integer move)
+
-
{
+
-
    game = llInsertString(llDeleteSubString(game, move, move), move, player);
+
-
    llSay(0, "game = "+game);
+
-
 
+
-
    // Check if this made three in a row
+
-
    integer u = move / 3;
+
-
    integer v = move % 3;
+
-
    integer i;
+
-
    integer c;
+
-
   
+
-
    // check horizontal
+
-
    c = 0;
+
-
    for (i = 0; i < 3; i++) if (at(i, v) == player) c++;
+
-
    if (c == 3)
+
-
    {
+
-
        for (i = 0; i < 3; i++) llMessageLinked(2 + 3*i + v, MSG_WIN, "", NULL_KEY);
+
-
        return TRUE;
+
-
    }
+
-
   
+
-
    // check vertical
+
-
    c = 0;
+
-
    for (i = 0; i < 3; i++) if (at(u, i) == player) c++;
+
-
    if (c == 3)
+
-
    {
+
-
        for (i = 0; i < 3; i++) llMessageLinked(2 + 3*u + i, MSG_WIN, "", NULL_KEY);
+
-
        return TRUE;
+
-
    }
+
-
   
+
-
    // check if we are on one diagonal
+
-
    c = 0;
+
-
    if (u == v) for (i = 0; i < 3; i++) if (at(i, i) == player) c++;
+
-
    if (c == 3)
+
-
    {
+
-
        for (i = 0; i < 3; i++) llMessageLinked(2 + 4*i, MSG_WIN, "", NULL_KEY);
+
-
        return TRUE;
+
-
    }
+
-
   
+
-
    // check if we are on the other diagonal
+
-
    c = 0;
+
-
    if (u + v == 2) for (i = 0; i < 3; i++) if (at(i, 2-i) == player) c++;
+
-
    if (c == 3)
+
-
    {
+
-
        for (i = 0; i < 3; i++) llMessageLinked(4 + 2*i, MSG_WIN, "", NULL_KEY);
+
-
        return TRUE;
+
-
    }
+
-
   
+
-
    // Check if there are any spaces left
+
-
    if (llSubStringIndex(game, "-") < 0) return TRUE;
+
-
 
+
-
    // Game goes on
+
-
    return FALSE;
+
-
}
+
-
 
+
-
default
+
-
{
+
-
    state_entry()
+
-
    {
+
-
        player_x = NULL_KEY;
+
-
        player_o = NULL_KEY;
+
-
        game = "---------";
+
-
        turn = "x";
+
-
 
+
-
        llMessageLinked(LINK_ALL_CHILDREN, MSG_RESET, "", NULL_KEY);
+
-
        state playing;
+
-
    }
+
-
}
+
-
 
+
-
state playing
+
-
{
+
-
    link_message(integer from, integer msg_id, string str, key id)
+
-
    {
+
-
        if (msg_id == MSG_TOUCH)
+
-
        {
+
-
            llSay(0, "touch from "+(string)from);
+
-
            if (turn == "x" && NULL_KEY == player_x)
+
             {
             {
-
                 llSetTimerEvent(0);
+
                 dl = osSetPenColour( dl, "lime" );             // Select a bright green pen color
-
                llMessageLinked(from, MSG_SET_X, "", NULL_KEY);
+
                 dl = osMovePen( dl, x-17, y-17 );               // Move the pen to the upper left corner of the square
-
                 player_x = id;
+
                 dl = osDrawEllipse( dl, 35, 35 );               // Draw the O
-
                if (game_ends(turn, from-2)) state idle;
+
-
                 turn = "o";
+
-
                llSetTimerEvent(GAME_TIMEOUT);
+
             }
             }
-
             else if (turn == "o" && NULL_KEY == player_o)
+
             else                                               // If it's an X:
             {
             {
-
                 llSetTimerEvent(0);
+
                 dl = osSetPenColour( dl, "blue" );             // Select a bright blue pen color
-
                llMessageLinked(from, MSG_SET_O, "", NULL_KEY);
+
                 dl = osDrawLine( dl, x-17, y-17, x+17, y+17 ); // Draw the first line of the X
-
                 player_o = id;
+
                 dl = osDrawLine( dl, x-17, y+17, x+17, y-17 ); // Draw the second line of the X
-
                if (game_ends(turn, from-2)) state idle;
+
-
                turn = "x";
+
-
                llSetTimerEvent(GAME_TIMEOUT);
+
-
            }
+
-
            else if (turn == "x" && id == player_x)
+
-
            {
+
-
                llSetTimerEvent(0);
+
-
                llMessageLinked(from, MSG_SET_X, "", NULL_KEY);
+
-
                 if (game_ends(turn, from-2)) state idle;
+
-
                turn = "o";
+
-
                llSetTimerEvent(GAME_TIMEOUT);
+
-
            }
+
-
            else if (turn == "o" && id == player_o)
+
-
            {
+
-
                llSetTimerEvent(0);
+
-
                llMessageLinked(from, MSG_SET_O, "", NULL_KEY);
+
-
                if (game_ends(turn, from-2)) state idle;
+
-
                turn = "x";
+
-
                llSetTimerEvent(GAME_TIMEOUT);
+
             }
             }
         }
         }
     }
     }
-
     timer()
+
     if (GameOver > 0) // if GameOver is 1 or more, we will draw a red line through the winning row, column or diagonal
     {
     {
-
         llSetTimerEvent(0);
+
         dl = osSetPenColor( dl, "orangered" );                             // Select an orange-red color
-
         state idle;
+
         if (GameOver == 1) dl = osDrawLine( dl, 5, 21, 125, 21 );          // Draw a horizontal, vertical or diagonal line,
 +
        else if (GameOver == 2) dl = osDrawLine( dl, 3, 64, 125, 64 );    // based on the value of GameOver. This is
 +
        else if (GameOver == 3) dl = osDrawLine( dl, 3, 107, 125, 107 );  // really kind of kludgy, but it gets the job
 +
        else if (GameOver == 4) dl = osDrawLine( dl, 21, 3, 21, 125 );    // done.
 +
        else if (GameOver == 5) dl = osDrawLine( dl, 64, 3, 64, 125 );
 +
        else if (GameOver == 6) dl = osDrawLine( dl, 107, 3, 107, 125 );
 +
        else if (GameOver == 7) dl = osDrawLine( dl, 3, 3, 125, 125 );
 +
        else if (GameOver == 8) dl = osDrawLine( dl, 125, 3, 3, 125 );
     }
     }
 +
    osSetDynamicTextureData( "", "vector", dl, "width:128,height:128,alpha:false", 0 ); // Draw the dynamic texture
}
}
-
state idle
+
// CheckForWin() - returns an integer value of -1 for a draw, 0 if there are still moves that can be made, or a positive
 +
//                integer specifying which row, column or diagonal contains the win. This is REALLY kludgy.
 +
//
 +
integer CheckForWin()
{
{
-
     state_entry()
+
     integer s1 = llList2Integer( Spaces, 0 ); // Get each space's value into its own integer for use in the tests below,
-
     {
+
     integer s2 = llList2Integer( Spaces, 1 ); // which calls llList2Integer() 9 times (instead of the 33 times that it
-
        llSay(0, "state idle");
+
    integer s3 = llList2Integer( Spaces, 2 ); // would take to call the function for each space in the tests below).
-
        llMessageLinked(LINK_ALL_CHILDREN, MSG_IDLE, "", NULL_KEY);
+
    integer s4 = llList2Integer( Spaces, 3 );
-
     }
+
    integer s5 = llList2Integer( Spaces, 4 );
 +
    integer s6 = llList2Integer( Spaces, 5 );
 +
     integer s7 = llList2Integer( Spaces, 6 );
 +
    integer s8 = llList2Integer( Spaces, 7 );
 +
    integer s9 = llList2Integer( Spaces, 8 );
      
      
-
     link_message(integer from, integer msg_id, string str, key id)
+
     if ((s1 != -1) && (s1 == s2) && (s1 == s3)) return 1; // Top row
-
     {
+
     if ((s4 != -1) && (s4 == s5) && (s4 == s6)) return 2; // Middle row
-
        if (msg_id == MSG_IDLE_TOUCH) state default;
+
    if ((s7 != -1) && (s7 == s8) && (s7 == s9)) return 3; // Bottom row
-
    }
+
    if ((s1 != -1) && (s1 == s4) && (s1 == s7)) return 4; // Left column
-
}
+
     if ((s2 != -1) && (s2 == s5) && (s2 == s8)) return 5; // Middle column
-
</lsl>
+
    if ((s3 != -1) && (s3 == s6) && (s3 == s9)) return 6; // Right column
-
 
+
    if ((s1 != -1) && (s1 == s5) && (s1 == s9)) return 7; // Top left to bottom right
-
Child Prims
+
     if ((s3 != -1) && (s3 == s5) && (s3 == s7)) return 8; // Top right to bottom left
-
 
+
-
The child prims all have the same set of scripts:
+
-
 
+
-
LinkNanny (answers queries from the RootNanny and manages the upload pin)
+
-
 
+
-
<lsl>
+
-
// Message constants
+
-
integer MSG_RESET = 0;
+
-
integer MSG_LINK_QUERY = 10;
+
-
integer MSG_LINK_REPLY = 11;
+
-
 
+
-
default
+
-
{
+
-
     state_entry()
+
-
    {
+
-
        // If we are in the the root prim...
+
-
        if (llGetLinkNumber() < 2)
+
-
        {
+
-
            // ... disable ourselves
+
-
            llSetScriptState(llGetScriptName(), FALSE);
+
-
            llSleep(2);
+
-
        }
+
-
     }
+
      
      
-
     link_message(integer from, integer msg_id, string str, key id)
+
     if ((s1 == -1) || (s2 == -1) || (s3 == -1) || (s4 == -1) || (s5 == -1) ||
-
    {
+
        (s6 == -1) || (s7 == -1) || (s8 == -1) || (s9 == -1)) return 0; // At least one space is open
-
        if (msg_id == MSG_LINK_QUERY)
+
     return -1; // No more moves can be made, but nobody won.
-
        {
+
-
            // Set pin given
+
-
            llSetRemoteScriptAccessPin((integer)str);
+
-
            // Tell caller who we are
+
-
            llMessageLinked(from, MSG_LINK_REPLY, "", llGetKey());
+
-
        }
+
-
     }
+
}
}
-
</lsl>
 
-
 
-
TouchDisplay (handles clicks, displays game elements)
 
-
 
-
<lsl>
 
-
// Locations of various bits on the texture
 
-
float e_pos_s = 0.75;
 
-
float e_pos_t = 0.75;
 
-
float x_pos_s = 0.75;
 
-
float x_pos_t = 0.25;
 
-
float o_pos_s = 0.25;
 
-
float o_pos_t = 0.25;
 
-
 
-
// Face on wjich the texture lives
 
-
integer DISPLAY_FACE = 4;
 
-
vector  RED  = <1,0,0>;
 
-
vector  WHITE = <1,1,1>;
 
-
 
-
// Message constants
 
-
integer MSG_RESET      = 0;
 
-
integer MSG_TOUCH      = 1;
 
-
integer MSG_SET_X      = 2;
 
-
integer MSG_SET_O      = 3;
 
-
integer MSG_IDLE      = 4;
 
-
integer MSG_IDLE_TOUCH = 5;
 
-
integer MSG_WIN        = 6;
 
default
default
{
{
-
     state_entry()
+
     state_entry()     // Start the game.
     {
     {
-
         // If we are in the the root prim...
+
         DrawBoard()// Draw an empty board.
-
        if (llGetLinkNumber() < 2)
+
-
        {
+
-
            // ... disable ourselves
+
-
            llSetScriptState(llGetScriptName(), FALSE);
+
-
            llSleep(2);
+
-
        }
+
-
       
+
-
        // Reset color and texture
+
-
        llSetColor(WHITE, DISPLAY_FACE);
+
-
        llOffsetTexture(e_pos_s, e_pos_t, DISPLAY_FACE);
+
-
    }
+
-
 
+
-
    touch_start(integer touching_agents)
+
-
    {
+
-
        while (touching_agents--)
+
-
        {
+
-
            llMessageLinked(LINK_ROOT, MSG_TOUCH, "", llDetectedKey(touching_agents));
+
-
        } 
+
     }
     }
      
      
-
     link_message(integer from, integer msg_id, string str, key id)
+
     // The actual game logic all happens in touch_start(). It retrieves the coordinates of where on the front face the user
-
     {
+
     // touched, and from that calculates which space was touched. If it's empty, it fills it in with an X or an O, depending
-
        if (msg_id == MSG_SET_X) state x;
+
     // on whose turn it is, checks to see if there's a winner, and redraws the game board.
-
        if (msg_id == MSG_SET_O) state o;
+
     touch_start( integer numTouchers )
-
        if (msg_id == MSG_IDLE) state idle;
+
-
    }
+
-
}
+
-
 
+
-
state x
+
-
{
+
-
    state_entry()
+
-
    {
+
-
        llOffsetTexture(x_pos_s, x_pos_t, DISPLAY_FACE);
+
-
    }
+
-
 
+
-
    link_message(integer from, integer msg_id, string str, key id)
+
-
     {
+
-
        if (msg_id == MSG_RESET) state default;
+
-
        if (msg_id == MSG_IDLE) state idle;
+
-
        if (msg_id == MSG_WIN) llSetColor(RED, DISPLAY_FACE);
+
-
    }
+
-
}
+
-
 
+
-
state o
+
-
{
+
-
    state_entry()
+
-
    {
+
-
        llOffsetTexture(o_pos_s, o_pos_t, DISPLAY_FACE);
+
-
    }
+
-
 
+
-
    link_message(integer from, integer msg_id, string str, key id)
+
-
    {
+
-
        if (msg_id == MSG_RESET) state default;
+
-
        if (msg_id == MSG_IDLE) state idle;
+
-
        if (msg_id == MSG_WIN) llSetColor(RED, DISPLAY_FACE);
+
-
    }
+
-
}
+
-
 
+
-
state idle
+
-
{
+
-
    link_message(integer from, integer msg_id, string str, key id)
+
-
    {
+
-
        if (msg_id == MSG_RESET) state default;
+
-
    }
+
-
 
+
-
     touch_start(integer touching_agents)
+
     {
     {
-
         llMessageLinked(LINK_ROOT, MSG_IDLE_TOUCH, "", NULL_KEY);
+
         if (llDetectedTouchFace( 0 ) != 1) return;                            // Only accept touches from the "front" face.
 +
        if (GameOver) llResetScript();                                        // If the game's over, start a new one.
 +
        vector v = llDetectedTouchST( 0 );                                    // Get X,Y coords of the touch on the face.
 +
        integer index = llFloor( v.x * 3.0 ) + (3 * llFloor( (1-v.y) * 3.0 )); // Turn that into index into the Spaces list.
 +
        if (llList2Integer( Spaces, index ) >= 0) return;                      // If space is already filled, ignore touch.
 +
        Spaces = llListReplaceList( Spaces, [ WhoseTurn ], index, index );    // Set the value of the space to X or O.
 +
        WhoseTurn = 1 - WhoseTurn;                                            // Swap whose turn it will be next.
 +
        GameOver = CheckForWin();                                              // See if anybody won yet
 +
        DrawBoard();                                                           // Draw the new board.
     }
     }
}
}
</lsl>
</lsl>

Version du 7 octobre 2012 à 10:47

// One-Prim Noughts and Crosses - OpenSim LSL script by Warin Cascabel (26 February 2009)
//
// Please note:
// As this script makes use of OpenSim-specific extensions to the Linden Scripting Language.
// This script will NOT work in Second Life.
 
// Internal variables.
list Spaces = [-1,-1,-1,-1,-1,-1,-1,-1,-1];    // Keeps track of what's in which space of the board. -1=empty, 0=O, 1=X
integer GameOver = 0;      // If nonzero, signals which row, column or diagonal has the win (or -1 for a draw)
integer WhoseTurn = 1;     // Whose turn is it next? 0=O, 1=X
 
// DrawBoard()
// Builds the dynamic texture command based on the contents of the Spaces list and the GameOver variable.     
DrawBoard()
{
    string dl;                                                  // holds the draw list
    integer i;                                                  // iterator for our for loop
    integer x;                                                  // holds the horizontal coordinate of each space
    integer y;                                                  // holds the vertical coordinate of each space
 
    dl = osSetPenColor("", "white" );                           // Set the background to solid white
    dl = osMovePen( dl, 0, 0 );
    dl = osDrawFilledRectangle( dl, 128, 128 );
    dl = osSetPenColor( dl, "black" );                          // Draw the grid in black
    dl = osSetPenSize( dl, 2 );
    dl = osDrawLine( dl, 43, 3, 43, 125 );
    dl = osDrawLine( dl, 86, 3, 86, 125 );
    dl = osDrawLine( dl, 3, 43, 125, 43 );
    dl = osDrawLine( dl, 3, 86, 125, 86 );
    dl = osSetPenSize( dl, 6 );                                 // Increase the pen size for our Xs and Os.
 
    for (i = 0; i < 9; ++i)                                     // For each element in the Spaces list:
    {
        integer who = llList2Integer( Spaces, i );              // Get its value
        if (who > -1)                                           // Do nothing if it's -1 (empty)
        {
            x = (i % 3) * 43 + 21;                              // Calculate the center of the square
            y = (i / 3) * 43 + 21;
            if (who == 0)                                       // If it's an O:
            {
                dl = osSetPenColour( dl, "lime" );              // Select a bright green pen color
                dl = osMovePen( dl, x-17, y-17 );               // Move the pen to the upper left corner of the square
                dl = osDrawEllipse( dl, 35, 35 );               // Draw the O
            }
            else                                                // If it's an X:
            {
                dl = osSetPenColour( dl, "blue" );              // Select a bright blue pen color
                dl = osDrawLine( dl, x-17, y-17, x+17, y+17 );  // Draw the first line of the X
                dl = osDrawLine( dl, x-17, y+17, x+17, y-17 );  // Draw the second line of the X
            }
        }
    }
 
    if (GameOver > 0) // if GameOver is 1 or more, we will draw a red line through the winning row, column or diagonal
    {
        dl = osSetPenColor( dl, "orangered" );                             // Select an orange-red color
        if (GameOver == 1) dl = osDrawLine( dl, 5, 21, 125, 21 );          // Draw a horizontal, vertical or diagonal line,
        else if (GameOver == 2) dl = osDrawLine( dl, 3, 64, 125, 64 );     // based on the value of GameOver. This is
        else if (GameOver == 3) dl = osDrawLine( dl, 3, 107, 125, 107 );   // really kind of kludgy, but it gets the job
        else if (GameOver == 4) dl = osDrawLine( dl, 21, 3, 21, 125 );     // done.
        else if (GameOver == 5) dl = osDrawLine( dl, 64, 3, 64, 125 );
        else if (GameOver == 6) dl = osDrawLine( dl, 107, 3, 107, 125 );
        else if (GameOver == 7) dl = osDrawLine( dl, 3, 3, 125, 125 );
        else if (GameOver == 8) dl = osDrawLine( dl, 125, 3, 3, 125 );
    }
    osSetDynamicTextureData( "", "vector", dl, "width:128,height:128,alpha:false", 0 ); // Draw the dynamic texture
}
 
// CheckForWin() - returns an integer value of -1 for a draw, 0 if there are still moves that can be made, or a positive
//                 integer specifying which row, column or diagonal contains the win. This is REALLY kludgy.
//
integer CheckForWin()
{
    integer s1 = llList2Integer( Spaces, 0 ); // Get each space's value into its own integer for use in the tests below,
    integer s2 = llList2Integer( Spaces, 1 ); // which calls llList2Integer() 9 times (instead of the 33 times that it
    integer s3 = llList2Integer( Spaces, 2 ); // would take to call the function for each space in the tests below).
    integer s4 = llList2Integer( Spaces, 3 );
    integer s5 = llList2Integer( Spaces, 4 );
    integer s6 = llList2Integer( Spaces, 5 );
    integer s7 = llList2Integer( Spaces, 6 );
    integer s8 = llList2Integer( Spaces, 7 );
    integer s9 = llList2Integer( Spaces, 8 );
 
    if ((s1 != -1) && (s1 == s2) && (s1 == s3)) return 1; // Top row
    if ((s4 != -1) && (s4 == s5) && (s4 == s6)) return 2; // Middle row
    if ((s7 != -1) && (s7 == s8) && (s7 == s9)) return 3; // Bottom row
    if ((s1 != -1) && (s1 == s4) && (s1 == s7)) return 4; // Left column
    if ((s2 != -1) && (s2 == s5) && (s2 == s8)) return 5; // Middle column
    if ((s3 != -1) && (s3 == s6) && (s3 == s9)) return 6; // Right column
    if ((s1 != -1) && (s1 == s5) && (s1 == s9)) return 7; // Top left to bottom right
    if ((s3 != -1) && (s3 == s5) && (s3 == s7)) return 8; // Top right to bottom left
 
    if ((s1 == -1) || (s2 == -1) || (s3 == -1) || (s4 == -1) || (s5 == -1) || 
        (s6 == -1) || (s7 == -1) || (s8 == -1) || (s9 == -1)) return 0; // At least one space is open
    return -1; // No more moves can be made, but nobody won.
}
 
default
{
    state_entry()     // Start the game.
    {
        DrawBoard();  // Draw an empty board.
    }
 
    // The actual game logic all happens in touch_start(). It retrieves the coordinates of where on the front face the user
    // touched, and from that calculates which space was touched. If it's empty, it fills it in with an X or an O, depending
    // on whose turn it is, checks to see if there's a winner, and redraws the game board.
    touch_start( integer numTouchers )
    {
        if (llDetectedTouchFace( 0 ) != 1) return;                             // Only accept touches from the "front" face.
        if (GameOver) llResetScript();                                         // If the game's over, start a new one.
        vector v = llDetectedTouchST( 0 );                                     // Get X,Y coords of the touch on the face.
        integer index = llFloor( v.x * 3.0 ) + (3 * llFloor( (1-v.y) * 3.0 )); // Turn that into index into the Spaces list.
        if (llList2Integer( Spaces, index ) >= 0) return;                      // If space is already filled, ignore touch.
        Spaces = llListReplaceList( Spaces, [ WhoseTurn ], index, index );     // Set the value of the space to X or O.
        WhoseTurn = 1 - WhoseTurn;                                             // Swap whose turn it will be next.
        GameOver = CheckForWin();                                              // See if anybody won yet
        DrawBoard();                                                           // Draw the new board.
    }
}
Outils personnels
donate
Google Ads