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 : | ||
- | |||
- | |||
- | |||
- | |||
- | |||
- | |||
- | |||
- | |||
- | |||
<lsl> | <lsl> | ||
- | // | + | // 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 | + | 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 | + | 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 | default | ||
{ | { | ||
- | state_entry() | + | 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 ) | |
- | + | ||
- | + | ||
- | + | ||
- | + | ||
- | + | ||
- | + | ||
- | + | ||
- | + | ||
- | + | ||
- | + | ||
- | + | ||
- | + | ||
- | + | ||
- | + | ||
- | + | ||
- | + | ||
- | + | ||
- | + | ||
- | + | ||
- | + | ||
- | + | ||
- | + | ||
- | + | ||
- | + | ||
- | + | ||
- | + | ||
- | + | ||
- | + | ||
- | + | ||
- | + | ||
- | + | ||
- | + | ||
- | + | ||
- | + | ||
- | + | ||
- | + | ||
- | + | ||
- | + | ||
- | + | ||
- | + | ||
- | + | ||
- | touch_start(integer | + | |
{ | { | ||
- | + | 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. } }