removed useless _ folders
This commit is contained in:
3
Go_Game/Go_Game.sol
Normal file
3
Go_Game/Go_Game.sol
Normal file
@@ -0,0 +1,3 @@
|
||||
<Solution name="Go_Game">
|
||||
<Project name="Go_Game" path="Go_Game\Go_Game.prj" active="true"/>
|
||||
</Solution>
|
||||
26
Go_Game/Go_Game/Go_Game.prj
Normal file
26
Go_Game/Go_Game/Go_Game.prj
Normal file
@@ -0,0 +1,26 @@
|
||||
<Project name="Go_Game" guid="D7F616C9-6C00-1014-B904-200204C60A89">
|
||||
<Object name="Object" guid="D7F617C2-6C00-1014-B904-200204C60A89">
|
||||
<Script name="Go_Game_1.lsl" guid="D7F66231-6C00-1014-B904-200204C60A89">
|
||||
</Script>
|
||||
<Script name="Go_Game_2.lsl" guid="D7F683B0-6C00-1014-B904-200204C60A89">
|
||||
</Script>
|
||||
<Script name="Go_Game_3.lsl" guid="D7F6A5B8-6C00-1014-B904-200204C60A89">
|
||||
</Script>
|
||||
<Script name="Go_Game_4.lsl" guid="D7F6DBF4-6C00-1014-B904-200204C60A89">
|
||||
</Script>
|
||||
<Script name="Go_Game_5.lsl" guid="D7F7103F-6C00-1014-B904-200204C60A89">
|
||||
</Script>
|
||||
<Script name="Go_Game_6.lsl" guid="D7F73344-6C00-1014-B904-200204C60A89">
|
||||
</Script>
|
||||
<Script name="Go_Game_7.lsl" guid="D7F755BB-6C00-1014-B904-200204C60A89">
|
||||
</Script>
|
||||
<Script name="Go_Game_8.lsl" guid="D7F77462-6C00-1014-B904-200204C60A89">
|
||||
</Script>
|
||||
<Script name="Go_Game_9.lsl" guid="D7F7C68D-6C00-1014-B904-200204C60A89">
|
||||
</Script>
|
||||
<Script name="Go_Game_10.lsl" guid="D7F7E183-6C00-1014-B904-200204C60A89">
|
||||
</Script>
|
||||
<Script name="Go_Game_11.lsl" guid="D7F7FA5F-6C00-1014-B904-200204C60A89">
|
||||
</Script>
|
||||
</Object>
|
||||
</Project>
|
||||
109
Go_Game/Go_Game/Object/Go_Game_1.lsl
Normal file
109
Go_Game/Go_Game/Object/Go_Game_1.lsl
Normal file
@@ -0,0 +1,109 @@
|
||||
// :CATEGORY:Games
|
||||
// :NAME:Go_Game
|
||||
// :AUTHOR:Jonathan Shaftoe
|
||||
// :CREATED:2010-01-10 05:20:56.000
|
||||
// :EDITED:2013-09-18 15:38:54
|
||||
// :ID:357
|
||||
// :NUM:480
|
||||
// :REV:1.0
|
||||
// :WORLD:Second Life
|
||||
// :DESCRIPTION:
|
||||
// This is my first (and perhaps only) large scale LSL project. I don't have time to do anything more with it, so I'm going to release it into the wild for others to use, adapt, play with as the like. I only ask that noone sells the original as posted here, as that would be a bit greedy.
|
||||
//
|
||||
// So, what is it? A fully functional Go board, which allows two players to play a game of Go and score up at the end. It uses various tricks, such as XYText style textures for the pieces on the board, and a squidgy double-click square selector device thing to keep the number of prims required to a minimum.
|
||||
//
|
||||
// There are several components and scripts, so it's all a bit complex to put together, and it's not as well commented as perhaps it should be, but I'll do my best to write some useful instructions.
|
||||
//
|
||||
// The board looks very basic. My talents do not lie in making things look pretty. All textures are linked to ones I've created. It would be trivial to put together some nicer textures and change the relevent keys. The code does the basic setting up of size/shape/colour of all parts of the game.
|
||||
//
|
||||
// A large number of link messages are used to glue all the various bits and pieces together. I didn't document this as well as I should, and it's all a bit random as things which grow whilst coded tend to be. For my own benefit I eventually put together a little file documenting very briefly each message, so I'll include that here too.
|
||||
//
|
||||
// As to the rules of the game of Go, there are plenty of websites out there that can explain it better than I can. However, I will say this, it is an extremely interesting and deep game that you can enjoy quickly, but study for years and not come close to mastering.
|
||||
//
|
||||
// First up, GoButtonScript
|
||||
// :CODE:
|
||||
// GoButtonScript
|
||||
|
||||
// Jonathan Shaftoe
|
||||
|
||||
// A simple button used on the Go board, can be one of Pass, Done, Info, Resign or Reset
|
||||
|
||||
// Drop into a basic prim, call it GoButton, then store in your inventory for later.
|
||||
|
||||
|
||||
|
||||
key gPlayer; // Current player whose turn it is.
|
||||
|
||||
float gSize; // scaling constant.
|
||||
|
||||
integer gType; // which type of button we are. 1 - pass, 2 - done, 3 - reset, 4 - resign, 5 - info
|
||||
|
||||
|
||||
|
||||
set_size(string str) {
|
||||
|
||||
gSize = (float)str;
|
||||
|
||||
llSetScale(<0.2 * gSize, 0.1 * gSize, 0.01 * gSize>);
|
||||
|
||||
}
|
||||
|
||||
|
||||
|
||||
default {
|
||||
|
||||
state_entry() {
|
||||
|
||||
llSetPrimitiveParams([
|
||||
|
||||
PRIM_TYPE, PRIM_TYPE_BOX, PRIM_HOLE_DEFAULT, <0, 1, 0>, 0.0, ZERO_VECTOR, <1, 1, 0>, ZERO_VECTOR,
|
||||
|
||||
PRIM_SIZE, <0.2, 0.1, 0.01>,
|
||||
|
||||
PRIM_TEXTURE, ALL_SIDES, "5748decc-f629-461c-9a36-a35a221fe21f", <1, 1, 0>, <0, 0, 0>, 0.0,
|
||||
|
||||
PRIM_COLOR, ALL_SIDES, <0.8, 0.6, 0.5>, 1.0
|
||||
|
||||
]);
|
||||
|
||||
llSitTarget(ZERO_VECTOR, ZERO_ROTATION);
|
||||
|
||||
llSetObjectName("GoButton");
|
||||
|
||||
}
|
||||
|
||||
|
||||
|
||||
on_rez(integer start_param) {
|
||||
|
||||
if (start_param > 0) {
|
||||
|
||||
gType = start_param;
|
||||
|
||||
if (gType == 1) {
|
||||
|
||||
llSetTouchText("Pass");
|
||||
|
||||
// llSetText("Pass", <0, 0, 0>, 1.0);
|
||||
|
||||
llSetObjectDesc("Go Game Pass Button.");
|
||||
|
||||
llSetTexture("f8919345-d4ab-613f-c594-5cdafcf6f8a1", 0);
|
||||
|
||||
} else if (gType == 2) {
|
||||
|
||||
llSetTouchText("Done");
|
||||
|
||||
// llSetText("Done", <0, 0, 0>, 1.0);
|
||||
|
||||
llSetObjectDesc("Go Game Done Button.");
|
||||
|
||||
llSetTexture("9db6cc17-c2bc-04e9-bc5e-659e0b20d82f", 0);
|
||||
|
||||
} else if (gType == 3) {
|
||||
|
||||
llSetTouchText("Reset");
|
||||
|
||||
// llSetText("Reset", <0, 0, 0>, 1.0);
|
||||
|
||||
llSetObjectDesc("Go Game Reset Button");
|
||||
37
Go_Game/Go_Game/Object/Go_Game_10.lsl
Normal file
37
Go_Game/Go_Game/Object/Go_Game_10.lsl
Normal file
@@ -0,0 +1,37 @@
|
||||
// :CATEGORY:Games
|
||||
// :NAME:Go_Game
|
||||
// :AUTHOR:Jonathan Shaftoe
|
||||
// :CREATED:2010-01-10 05:20:56.000
|
||||
// :EDITED:2013-09-18 15:38:54
|
||||
// :ID:357
|
||||
// :NUM:489
|
||||
// :REV:1.0
|
||||
// :WORLD:Second Life
|
||||
// :DESCRIPTION:
|
||||
// Here is the text of the Go Info notecard given out by the info button. This should be saved as a notecard called Go Info and dropped in the inventory of the go game prim.
|
||||
// :CODE:
|
||||
Hello and welcome to Jonathan's Go game.
|
||||
|
||||
|
||||
|
||||
Go is an ancient game from Asia with simple rules but complex gameplay. Two players, white and black, take turns to place a stone on a board. If a group of one colour is completely surrounded by a group of another, it is removed from the board. Note that stones are placed on the junctions of lines, not in the spaces between them, and that diagonals do not count. Once both players agree that there is no further advantage in playing any further stones, the one with the greatest score wins.
|
||||
|
||||
|
||||
|
||||
A full description of the rules of Go is beyond the scope of a notecard. There are many websites with descriptions and tutorials, for example:
|
||||
|
||||
|
||||
|
||||
http://www.britgo.org/
|
||||
|
||||
|
||||
|
||||
There are two types of scoring in common use, Japanese or Territory scoring, and Chinese or Area scoring. I've implemented Territory scoring. In practice there is little difference between the two.
|
||||
|
||||
|
||||
|
||||
Though the basic rules are implemented, there are some unusual circumstances which aren't covered, for example triple ko or seki. In the unlikely event of these occuring, you'll have to sort out how to handle it between yourselves.
|
||||
|
||||
|
||||
|
||||
I have designed the board to be hopefully as intuitive to use as possible. Before starting a game, the size of the game board can be set by clicking anywhere on the board and selecting from the three commonly used sizes on offer. A 9x9 game can be played relatively quickly, but loses the deeper levels of strategy involved in a larger game. It is a good choice for beginners. A 19x19 game is a proper full sized game, and can take upwards of two hours to complete. 13x13 is a midpoint between the two.
|
||||
63
Go_Game/Go_Game/Object/Go_Game_11.lsl
Normal file
63
Go_Game/Go_Game/Object/Go_Game_11.lsl
Normal file
@@ -0,0 +1,63 @@
|
||||
// :CATEGORY:Games
|
||||
// :NAME:Go_Game
|
||||
// :AUTHOR:Jonathan Shaftoe
|
||||
// :CREATED:2010-01-10 05:20:56.000
|
||||
// :EDITED:2013-09-18 15:38:54
|
||||
// :ID:357
|
||||
// :NUM:490
|
||||
// :REV:1.0
|
||||
// :WORLD:Second Life
|
||||
// :DESCRIPTION:
|
||||
// And finally, here's some documentation I did for myself on the many link messages used. If you're going to try to figure out how it all works or change the code, this will probably be invaluable!
|
||||
// :CODE:
|
||||
// Messages
|
||||
|
||||
// 0. From MainScript to Button, Sensor - sets current player, black or white, and resets Sensor to zoom1
|
||||
|
||||
// 1. From MainScript, to JoinButton, Button. Sets SIZE
|
||||
|
||||
// 2. From MainScript, to ?. Sets SIZE and gGameSize (depricated?)
|
||||
|
||||
// 1 & 2 From JoinButton to MainScript - sets who's playing black/white
|
||||
|
||||
// 3. From MainScript, to Tile, Sensor, sets gGameSize, gX/YSensors and SIZE, sent with set_size
|
||||
|
||||
// 4. From Sensor to Logic, turn attempt made, coordinates passed.
|
||||
|
||||
// 5. From Sensor to Sensor. coordinates of zoom from zoom1 to zoom2.
|
||||
|
||||
// 10. From Button, to Logic, player pressed 'pass'
|
||||
|
||||
// 11. From Button to Main, player pressed 'done'
|
||||
|
||||
// 12. From Button to Main, player pressed 'reset'
|
||||
|
||||
// 13. From Button to Main, player pressed 'resign'
|
||||
|
||||
// 14. From Button to Main, player pressed 'info'
|
||||
|
||||
// 15. From Logic, to Tile, endgame disputed, reset tile to previous state
|
||||
|
||||
// 20. From Sensor to Sensor, go to waiting state, move attempted
|
||||
|
||||
// 21. From Logic to Sensor, go back from waiting state to zoom2, attempt to move failed.
|
||||
|
||||
// 100. From Main to Logic, sets gGameSize and SIZE, sent with every set_size
|
||||
|
||||
// 101. From Logic, to Main, sets whose turn and whether we're in endgame.
|
||||
|
||||
// 102. From Logic to Main, entering endgame after two passes
|
||||
|
||||
// 103. From Main to Logic, sets current player/endgame state
|
||||
|
||||
// 104. From Main to Logic, whether player disputes endgame/dead groups or not
|
||||
|
||||
// 105. From Logic to Main and Sensors, doing scoring (so sensors hide)
|
||||
|
||||
// 106. From Logic to Main, from scoring to gameover
|
||||
|
||||
// 201. From Logic to Tile, display piece, x, y, colour (1, 2) passed (displays immediately) or 0 to remove (doesn't display until ..).
|
||||
|
||||
// 202. From Logic to Tile, display result of removes from 201 messages.
|
||||
|
||||
// 203. From Logic to Tile, clears backup states (for endgame disputes) as agreed.
|
||||
109
Go_Game/Go_Game/Object/Go_Game_2.lsl
Normal file
109
Go_Game/Go_Game/Object/Go_Game_2.lsl
Normal file
@@ -0,0 +1,109 @@
|
||||
// :CATEGORY:Games
|
||||
// :NAME:Go_Game
|
||||
// :AUTHOR:Jonathan Shaftoe
|
||||
// :CREATED:2010-01-10 05:20:56.000
|
||||
// :EDITED:2013-09-18 15:38:54
|
||||
// :ID:357
|
||||
// :NUM:481
|
||||
// :REV:1.0
|
||||
// :WORLD:Second Life
|
||||
// :DESCRIPTION:
|
||||
// Next up, GoJoinButtonScript
|
||||
// :CODE:
|
||||
// GoJoinButtonScript
|
||||
|
||||
// Jonathan Shaftoe
|
||||
|
||||
// A simple button used for players to join the Go game, and also to start the game.
|
||||
|
||||
// Gets disabled and hidden once game is in progress.
|
||||
|
||||
// Drop into a simple prim, call it GoJoinButton, then store in your inventory for later.
|
||||
|
||||
|
||||
|
||||
integer gColour; // what colour are we, 1 - black, 2 - white
|
||||
|
||||
float gSize; // scaling constant
|
||||
|
||||
string gPlayAs; // Play as Black or Play as White
|
||||
|
||||
vector gPlayAsCol; // Actual colour, black or white.
|
||||
|
||||
|
||||
|
||||
set_size() {
|
||||
|
||||
llSetScale(<0.2 * gSize, 0.2 * gSize, 0.1 * gSize>);
|
||||
|
||||
}
|
||||
|
||||
|
||||
|
||||
default {
|
||||
|
||||
state_entry() {
|
||||
|
||||
llSetPrimitiveParams([
|
||||
|
||||
PRIM_TYPE, PRIM_TYPE_SPHERE, PRIM_HOLE_DEFAULT, <0, 0.5, 0>, 0.0, ZERO_VECTOR, <0, 1, 0>,
|
||||
|
||||
PRIM_SIZE, <0.4, 0.4, 0.1>,
|
||||
|
||||
PRIM_TEXTURE, ALL_SIDES, "5748decc-f629-461c-9a36-a35a221fe21f", <1, 1, 0>, <0, 0, 0>, 0.0,
|
||||
|
||||
PRIM_COLOR, ALL_SIDES, <0.5, 0.5, 0.5>, 1.0
|
||||
|
||||
]);
|
||||
|
||||
llSetTouchText("Join Game");
|
||||
|
||||
llSetObjectDesc("Go Game Join Button.");
|
||||
|
||||
llSetObjectName("GoJoinButton");
|
||||
|
||||
llSitTarget(ZERO_VECTOR, ZERO_ROTATION);
|
||||
|
||||
}
|
||||
|
||||
|
||||
|
||||
on_rez(integer start_param) {
|
||||
|
||||
if (start_param > 0) {
|
||||
|
||||
gColour = start_param;
|
||||
|
||||
if (gColour == 1) {
|
||||
|
||||
llSetColor(<0, 0, 0>, ALL_SIDES);
|
||||
|
||||
gPlayAs = "Play as Black";
|
||||
|
||||
gPlayAsCol = <0, 0, 0>;
|
||||
|
||||
} else if (gColour == 2) {
|
||||
|
||||
llSetColor(<1, 1, 1>, ALL_SIDES);
|
||||
|
||||
gPlayAs = "Play as White";
|
||||
|
||||
gPlayAsCol = <1, 1, 1>;
|
||||
|
||||
}
|
||||
|
||||
}
|
||||
|
||||
}
|
||||
|
||||
|
||||
|
||||
link_message(integer sender, integer num, string str, key id) {
|
||||
|
||||
if (num == 1) {
|
||||
|
||||
gSize = (float)str;
|
||||
|
||||
set_size();
|
||||
|
||||
state enabled;
|
||||
237
Go_Game/Go_Game/Object/Go_Game_3.lsl
Normal file
237
Go_Game/Go_Game/Object/Go_Game_3.lsl
Normal file
@@ -0,0 +1,237 @@
|
||||
// :CATEGORY:Games
|
||||
// :NAME:Go_Game
|
||||
// :AUTHOR:Jonathan Shaftoe
|
||||
// :CREATED:2010-01-10 05:20:56.000
|
||||
// :EDITED:2013-09-18 15:38:54
|
||||
// :ID:357
|
||||
// :NUM:482
|
||||
// :REV:1.0
|
||||
// :WORLD:Second Life
|
||||
// :DESCRIPTION:
|
||||
// That's the simple stuff done. Now things get more complicated, you need to create two grids, one of 'tiles' (prim textures to display the pieces on the board), and one of 'sensors' (to detect clicks when specifying where you want to play).
|
||||
//
|
||||
// First off sensors, here's the GoSensorScript
|
||||
// :CODE:
|
||||
// GoSensorScript
|
||||
|
||||
// Jonathan Shaftoe
|
||||
|
||||
// Script for each individual Go Sensor, used to detect mouse clicks to allow the player to select
|
||||
|
||||
// where they want to play. Uses a two click mechanism to reduce prim usage, a grid of these sensors
|
||||
|
||||
// moves over the board. For example, using a 19x19 board, 20 sensors in a 4x5 grid are used to allow
|
||||
|
||||
// the player to select the square they want to play in. To start with, the 4x5 grid covers the
|
||||
|
||||
// whole board, each sensor covering 20 squares. When one is clicked on, the sensors rearrange to
|
||||
|
||||
// just be over the 20 squares that were under the sensor clicked, then allowing the player to
|
||||
|
||||
// select an individual square. It's hard to explain, but when you see it working it'll be much
|
||||
|
||||
// more sense.
|
||||
|
||||
// Create a single prim, call it GoSensor, then drop this script in. Then see GoSensorGridScript.
|
||||
|
||||
|
||||
|
||||
integer gIndex; // which sensor in the grid am I
|
||||
|
||||
float gSize; // global scaling factor
|
||||
|
||||
|
||||
|
||||
integer gXSensors; // how many sensors across in grid to cover board
|
||||
|
||||
integer gYSensors; // how many sensors up/down in grid to cover board
|
||||
|
||||
|
||||
|
||||
integer gXSquares; // how many squares on the board across covered by a sensor
|
||||
|
||||
integer gYSquares; // how many squares on the board up/down covered by a sensor
|
||||
|
||||
|
||||
|
||||
integer gGameSize; // size of game board, will be 9, 13 or 19
|
||||
|
||||
|
||||
|
||||
integer gXPosBase; // x coordinate of sensor in grid
|
||||
|
||||
integer gYPosBase; // y coordinate of sensor in grid
|
||||
|
||||
|
||||
|
||||
integer gXPos; // x position of sensor in grid
|
||||
|
||||
integer gYPos; // y position of sensor in grid
|
||||
|
||||
|
||||
|
||||
integer gZoomPosX; // x coordinate when zoomed in (after first click by player)
|
||||
|
||||
integer gZoomPosY; // y coordinate when zoomed in
|
||||
|
||||
|
||||
|
||||
float gSquareSize; // Size of an individual square on the board.
|
||||
|
||||
|
||||
|
||||
key gPlayer; // player whose turn it currently is.
|
||||
|
||||
|
||||
|
||||
hide() {
|
||||
|
||||
llSetScale(<0.01, 0.01, 0.01>);
|
||||
|
||||
llSetPos(<0, 0, - 0.01>);
|
||||
|
||||
}
|
||||
|
||||
|
||||
|
||||
default {
|
||||
|
||||
state_entry() {
|
||||
|
||||
llSetPrimitiveParams([
|
||||
|
||||
PRIM_TYPE, PRIM_TYPE_BOX, PRIM_HOLE_DEFAULT, <0, 1, 0>, 0.0, ZERO_VECTOR, <1, 1, 0>, ZERO_VECTOR,
|
||||
|
||||
PRIM_SIZE, <0.5, 0.5, 0.5>,
|
||||
|
||||
PRIM_TEXTURE, ALL_SIDES, "5748decc-f629-461c-9a36-a35a221fe21f", <1, 1, 0>, <0, 0, 0>, 0.0,
|
||||
|
||||
PRIM_COLOR, ALL_SIDES, <0, 0, 1>, 0.25
|
||||
|
||||
]);
|
||||
|
||||
llSetObjectName("GoSensor");
|
||||
|
||||
llSetTouchText("Play here");
|
||||
|
||||
llSetObjectDesc("Go Game sensor - click once to select region to play in, then again for exact position.");
|
||||
|
||||
llSitTarget(ZERO_VECTOR, ZERO_ROTATION);
|
||||
|
||||
}
|
||||
|
||||
|
||||
|
||||
on_rez(integer start_param) {
|
||||
|
||||
gIndex = start_param;
|
||||
|
||||
state ready;
|
||||
|
||||
}
|
||||
|
||||
|
||||
|
||||
changed(integer change) {
|
||||
|
||||
if (change & CHANGED_LINK)
|
||||
|
||||
if (llGetLinkNumber() == 0)
|
||||
|
||||
llDie(); // so i die
|
||||
|
||||
}
|
||||
|
||||
}
|
||||
|
||||
|
||||
|
||||
// Do setup, hide sensor and wait for message
|
||||
|
||||
state ready {
|
||||
|
||||
state_entry() {
|
||||
|
||||
}
|
||||
|
||||
|
||||
|
||||
link_message(integer sender, integer num, string str, key id) {
|
||||
|
||||
if (num == 3) {
|
||||
|
||||
hide();
|
||||
|
||||
list params = llParseString2List(str, [","], []);
|
||||
|
||||
gGameSize = llList2Integer(params, 0);
|
||||
|
||||
gXSensors = llList2Integer(params, 1);
|
||||
|
||||
gYSensors = llList2Integer(params, 2);
|
||||
|
||||
gSize = llList2Float(params, 3);
|
||||
|
||||
|
||||
|
||||
gXSquares = llCeil((float)gGameSize / gXSensors);
|
||||
|
||||
gYSquares = llCeil((float)gGameSize / gYSensors);
|
||||
|
||||
|
||||
|
||||
gXPosBase = (gIndex % gXSensors);
|
||||
|
||||
gYPosBase = (gIndex / gXSensors);
|
||||
|
||||
|
||||
|
||||
if ((gXPosBase + gYPosBase) % 2 == 0) { // Alternating colours for checkerboard effect
|
||||
|
||||
llSetColor(<1, 0, 0>, ALL_SIDES);
|
||||
|
||||
} else {
|
||||
|
||||
llSetColor(<0, 1, 0>, ALL_SIDES);
|
||||
|
||||
}
|
||||
|
||||
|
||||
|
||||
gXPos = gXPosBase * gXSquares;
|
||||
|
||||
gYPos = gYPosBase * gYSquares;
|
||||
|
||||
|
||||
|
||||
if (gGameSize - gXPos < gXSquares) {
|
||||
|
||||
gXSquares = gGameSize - gXPos;
|
||||
|
||||
}
|
||||
|
||||
if (gGameSize - gYPos < gYSquares) {
|
||||
|
||||
gYSquares = gGameSize - gYPos;
|
||||
|
||||
}
|
||||
|
||||
gSquareSize = gSize / gGameSize;
|
||||
|
||||
} else if (num == 0) {
|
||||
|
||||
gPlayer = id;
|
||||
|
||||
state zoom1;
|
||||
|
||||
}
|
||||
|
||||
}
|
||||
|
||||
|
||||
|
||||
changed(integer change) {
|
||||
|
||||
if (change & CHANGED_LINK)
|
||||
|
||||
if (llGetLinkNumber() == 0)
|
||||
66
Go_Game/Go_Game/Object/Go_Game_4.lsl
Normal file
66
Go_Game/Go_Game/Object/Go_Game_4.lsl
Normal file
@@ -0,0 +1,66 @@
|
||||
// :CATEGORY:Games
|
||||
// :NAME:Go_Game
|
||||
// :AUTHOR:Jonathan Shaftoe
|
||||
// :CREATED:2010-01-10 05:20:56.000
|
||||
// :EDITED:2013-09-18 15:38:54
|
||||
// :ID:357
|
||||
// :NUM:483
|
||||
// :REV:1.0
|
||||
// :WORLD:Second Life
|
||||
// :DESCRIPTION:
|
||||
// And here's the GoSensorGridScript
|
||||
// :CODE:
|
||||
// GoSensorGridScript
|
||||
|
||||
// Jonathan Shaftoe
|
||||
|
||||
// Creates the sensor grid by rezzing 19 sensors (to make 20, including the one we're in) and
|
||||
|
||||
// giving each one a unique index. Script removes itself once done. Will take a few seconds
|
||||
|
||||
// to run, as rezzing has a built in delay. Requires link permission as all the created
|
||||
|
||||
// sensors are linked together.
|
||||
|
||||
// To use, rez a previously created GoSensor (see GoSensorScript), then put a GoSensor
|
||||
|
||||
// in that GoSensor's inventory, then drop this script in. Wait until it has done its stuff,
|
||||
|
||||
// then take the resulting GoSensorGrid into your inventory for later.
|
||||
|
||||
|
||||
|
||||
// If you only wanted to support smaller game boards and use less prims, you could change
|
||||
|
||||
// totalSensors below to the relevent number. For a 9x9 board, you would only need 9
|
||||
|
||||
// sensors, so make totalSensors 8 - for a 13x13 board, you need 16 sensors, so make
|
||||
|
||||
// totalSensors 15.
|
||||
|
||||
|
||||
|
||||
integer gNumSensors = 0; // how many have we made
|
||||
|
||||
integer gCountRez = 0; // how many are still waiting to be linked.
|
||||
|
||||
|
||||
|
||||
default
|
||||
|
||||
{
|
||||
|
||||
state_entry()
|
||||
|
||||
{
|
||||
|
||||
llSetObjectName("GoSensorGrid");
|
||||
|
||||
llRequestPermissions(llGetOwner(), PERMISSION_CHANGE_LINKS);
|
||||
|
||||
}
|
||||
|
||||
|
||||
|
||||
run_time_permissions(integer perms) {
|
||||
|
||||
241
Go_Game/Go_Game/Object/Go_Game_5.lsl
Normal file
241
Go_Game/Go_Game/Object/Go_Game_5.lsl
Normal file
@@ -0,0 +1,241 @@
|
||||
// :CATEGORY:Games
|
||||
// :NAME:Go_Game
|
||||
// :AUTHOR:Jonathan Shaftoe
|
||||
// :CREATED:2010-01-10 05:20:56.000
|
||||
// :EDITED:2013-09-18 15:38:54
|
||||
// :ID:357
|
||||
// :NUM:484
|
||||
// :REV:1.0
|
||||
// :WORLD:Second Life
|
||||
// :DESCRIPTION:
|
||||
// Now for the tiles to display textures, first GoTileScript
|
||||
// :CODE:
|
||||
// GoTileScript
|
||||
|
||||
// Jonathan Shaftoe
|
||||
|
||||
// A tile prim for displaying textures on the board to show where pieces are. Each tile is a squashed
|
||||
|
||||
// flattened cube, to create 3 square faces in a row, like XYText. Each face displays a texture which
|
||||
|
||||
// shows 4 game pieces. Using rotation and flipping, just 20 textures are required to display all
|
||||
|
||||
// 81 possible states of 4 squares on the board being either empty, black or white.
|
||||
|
||||
// The tile prims are made into a tile grid, in the same way as the sensors.
|
||||
|
||||
// Create a single prim, drop this script and the GoTileFaceScript in, then take the resulting
|
||||
|
||||
// GoTile object into your inventory and see GoTileGridScript
|
||||
|
||||
|
||||
|
||||
integer gGameSize; // size of game board, 9, 13 or 19
|
||||
|
||||
integer gIndex; // which tile in the grid are we
|
||||
|
||||
float gSize; // scaling factor
|
||||
|
||||
|
||||
|
||||
integer TILEWIDTH = 6; // absolute values for making us the right shape
|
||||
|
||||
integer TILEHEIGHT = 2;
|
||||
|
||||
|
||||
|
||||
integer gRotated = 0; // are we one of the rotated tiles used down the edge to conserve prim count
|
||||
|
||||
|
||||
|
||||
integer gXPosBase; // Our logical coordinates within the grid
|
||||
|
||||
integer gYPosBase;
|
||||
|
||||
|
||||
|
||||
integer gXPos; // Our actual physical coordinates
|
||||
|
||||
integer gYPos;
|
||||
|
||||
|
||||
|
||||
float gSquareSize; // Size of an individual square on the board.
|
||||
|
||||
|
||||
|
||||
integer gFace0Modified = 0; // has one of the three faces been modified and need re-texturing
|
||||
|
||||
integer gFace1Modified = 0;
|
||||
|
||||
integer gFace2Modified = 0;
|
||||
|
||||
|
||||
|
||||
list gStates = []; // The state of this tile. Each face is a string in the list, each
|
||||
|
||||
// string is 4 characters of 0 - blank, 1 - black, 2 - white
|
||||
|
||||
list gStatesBackup = []; // backup copy of game state used for undoing changes during endgame
|
||||
|
||||
integer gGotBackup = 0; // do we have a backup.
|
||||
|
||||
string TRANSPARENT = "701917a8-d614-471f-13dd-5f4644e36e3c";
|
||||
|
||||
|
||||
|
||||
add_turn(integer face, integer x, integer y, string colour) {
|
||||
|
||||
string current = llList2String(gStates, face);
|
||||
|
||||
// llWhisper(0, "Got add turn, face: " + (string) face + " coords " + (string)x + ", " + (string)y + " and current state: " + current + ". Index is: " + (string)gIndex);
|
||||
|
||||
string newstr;
|
||||
|
||||
integer pos = (y * 2) + x;
|
||||
|
||||
if (pos == 0) {
|
||||
|
||||
newstr = colour + llGetSubString(current, 1, 3);
|
||||
|
||||
} else if (pos == 3) {
|
||||
|
||||
newstr = llGetSubString(current, 0, 2) + colour;
|
||||
|
||||
} else {
|
||||
|
||||
newstr = llGetSubString(current, 0, pos - 1) + colour + llGetSubString(current, pos + 1, 3);
|
||||
|
||||
}
|
||||
|
||||
// llWhisper(0, "New state is: " + newstr);
|
||||
|
||||
gStates = llListInsertList(llDeleteSubList(gStates, face, face), [newstr], face);
|
||||
|
||||
}
|
||||
|
||||
|
||||
|
||||
show_face(integer face) {
|
||||
|
||||
string statestr = llList2String(gStates, face);
|
||||
|
||||
llMessageLinked(llGetLinkNumber(), 301, statestr, (string)(face + 10 * gRotated));
|
||||
|
||||
}
|
||||
|
||||
|
||||
|
||||
default {
|
||||
|
||||
state_entry() {
|
||||
|
||||
llSetPrimitiveParams([
|
||||
|
||||
PRIM_TYPE, PRIM_TYPE_BOX, PRIM_HOLE_DEFAULT, <0, 1, 0>, 0.0, ZERO_VECTOR, <0.333333, 1, 0>, ZERO_VECTOR,
|
||||
|
||||
PRIM_SIZE, <1.5, 0.5, 0.01>,
|
||||
|
||||
PRIM_TEXTURE, ALL_SIDES, "5748decc-f629-461c-9a36-a35a221fe21f", <1, 1, 0>, <0, 0, 0>, 0.0,
|
||||
|
||||
PRIM_COLOR, ALL_SIDES, <1, 1, 1>, 1.0
|
||||
|
||||
]);
|
||||
|
||||
llSetObjectName("GoTile");
|
||||
|
||||
llSetTouchText("");
|
||||
|
||||
llSetObjectDesc("Go Game board tile");
|
||||
|
||||
llSitTarget(ZERO_VECTOR, ZERO_ROTATION);
|
||||
|
||||
|
||||
|
||||
}
|
||||
|
||||
|
||||
|
||||
on_rez(integer start_param) {
|
||||
|
||||
gIndex = start_param;
|
||||
|
||||
// llSetText((string)gIndex, <0, 0, 0>, 1.0);
|
||||
|
||||
state ready;
|
||||
|
||||
}
|
||||
|
||||
|
||||
|
||||
changed(integer change) {
|
||||
|
||||
if (change & CHANGED_LINK)
|
||||
|
||||
if (llGetLinkNumber() == 0)
|
||||
|
||||
llDie(); // so i die
|
||||
|
||||
}
|
||||
|
||||
}
|
||||
|
||||
|
||||
|
||||
state ready {
|
||||
|
||||
link_message(integer sender, integer num, string str, key id) {
|
||||
|
||||
if (num == 3) {
|
||||
|
||||
list params = llParseString2List(str, [","], []);
|
||||
|
||||
gGameSize = llList2Integer(params, 0);
|
||||
|
||||
gSize = llList2Float(params, 3);
|
||||
|
||||
|
||||
|
||||
integer vertical_strips = 0;
|
||||
|
||||
integer xTiles = gGameSize / TILEWIDTH;
|
||||
|
||||
integer yTiles = gGameSize / TILEHEIGHT;
|
||||
|
||||
if (yTiles * TILEHEIGHT < gGameSize) {
|
||||
|
||||
yTiles++;
|
||||
|
||||
}
|
||||
|
||||
if (xTiles * TILEWIDTH + 2 < gGameSize) {
|
||||
|
||||
xTiles++;
|
||||
|
||||
} else {
|
||||
|
||||
vertical_strips = xTiles + 1;
|
||||
|
||||
}
|
||||
|
||||
integer extra_index = gIndex - (xTiles * yTiles);
|
||||
|
||||
if (extra_index >= vertical_strips) {
|
||||
|
||||
// hide us away, not needed
|
||||
|
||||
llSetScale(<0.01, 0.01, 0.01>);
|
||||
|
||||
llSetPos(<0, 0, -.01>);
|
||||
|
||||
llSetText("", <0,0,0>, 1.0);
|
||||
|
||||
gXPos = -10;
|
||||
|
||||
gYPos = -10;
|
||||
|
||||
} else {
|
||||
|
||||
if (extra_index >= 0 && extra_index < vertical_strips) {
|
||||
|
||||
gXPosBase = xTiles;
|
||||
178
Go_Game/Go_Game/Object/Go_Game_6.lsl
Normal file
178
Go_Game/Go_Game/Object/Go_Game_6.lsl
Normal file
@@ -0,0 +1,178 @@
|
||||
// :CATEGORY:Games
|
||||
// :NAME:Go_Game
|
||||
// :AUTHOR:Jonathan Shaftoe
|
||||
// :CREATED:2010-01-10 05:20:56.000
|
||||
// :EDITED:2013-09-18 15:38:54
|
||||
// :ID:357
|
||||
// :NUM:485
|
||||
// :REV:1.0
|
||||
// :WORLD:Second Life
|
||||
// :DESCRIPTION:
|
||||
// Due to script length restrictions, it wouldn't all fit in one, so there's another script required here, GoTileFaceScript
|
||||
// :CODE:
|
||||
// GoTileFaceScript
|
||||
|
||||
// Jonathan Shaftoe
|
||||
|
||||
// Texture-handling side of functionality required by GoTiles. Wouldn't all fit in one
|
||||
|
||||
// script due to script size limits. Also has problems with runtime size, hence the way
|
||||
|
||||
// the lists are joined together in bits. Contains a mapping from all of the possible
|
||||
|
||||
// game states of a 2x2 grid of squares, each of which being 0 - empty 1 - black or
|
||||
|
||||
// 2 - white, to the texture to be used to display it, and with what rotation/flipping.
|
||||
|
||||
// Also, each of the three faces on a tile has a different rotation to apply to make
|
||||
|
||||
// things all be the right way around.
|
||||
|
||||
// Some heavy borrowing from XYText in here - thank you!
|
||||
|
||||
// For usage, see GoTileScript
|
||||
|
||||
|
||||
|
||||
|
||||
|
||||
// List of 20 textures used to display board pieces.
|
||||
|
||||
list gTextureIndex = ["701917a8-d614-471f-13dd-5f4644e36e3c",
|
||||
|
||||
"b51f6506-2156-a8ea-15f5-172d80add211",
|
||||
|
||||
"d48ab9c0-c49d-e009-a893-84bd7326de84",
|
||||
|
||||
"3823e129-e09f-b0fb-8717-90bc88e8ef46",
|
||||
|
||||
"0f3113bb-39c2-e0b9-475e-00e59afd85b0",
|
||||
|
||||
"bc806a54-3b0e-8f96-c105-d9da31160be5",
|
||||
|
||||
"58b6e53a-8b13-726f-24e7-ec94798bc9c4",
|
||||
|
||||
"760aa9bf-c25f-6880-2292-0c3c56421985",
|
||||
|
||||
"633464b2-2d1b-b050-2af9-f6dd2427465f",
|
||||
|
||||
"9f71ccc5-63e1-f5f0-6407-43577019f408",
|
||||
|
||||
"ad62bcb5-a607-21da-66eb-15548aad6b0a",
|
||||
|
||||
"d56bad91-3d05-e90e-080f-31224b353c42",
|
||||
|
||||
"00e8a3c3-996e-ed81-5e37-a86b099a9be7",
|
||||
|
||||
"5b206598-0c5d-352f-14e2-d18b520919a6",
|
||||
|
||||
"cf839003-eaf4-4af3-abe9-5d8bf3f28f0a",
|
||||
|
||||
"ab6e5d0b-16b9-3aee-b898-8c532c5e691c",
|
||||
|
||||
"e05ef3e7-f2a3-4b8c-f4ea-86d8b00a1c20",
|
||||
|
||||
"b5014c6e-d0b6-c6c7-6c25-d532fe08476f",
|
||||
|
||||
"15c19f1d-ee3f-22ba-541c-c44c62ea75c7",
|
||||
|
||||
"3f563f39-1c4d-297a-3956-cc174a9209e6",
|
||||
|
||||
"6879b0ca-a295-dd20-1e08-cc60da377a1a"];
|
||||
|
||||
|
||||
|
||||
// Will contain complete list, put together from parts below. Striped list of 4 items,
|
||||
|
||||
// first is game state represented as a string, second is index into texture list for
|
||||
|
||||
// which texture to use, third is mirroring/flipping required of texture, fourth is
|
||||
|
||||
// rotation.
|
||||
|
||||
list gStateList = [];
|
||||
|
||||
|
||||
|
||||
// Index of prim faces for each of the three faces we're using to display textures
|
||||
|
||||
list gFaceIndex = [4, 0, 2];
|
||||
|
||||
// hack for apparent bug, can't just negate PI_BY_TWO.
|
||||
|
||||
float MINUS_PI_BY_TWO = -1.5707963267948966192313216916398;
|
||||
|
||||
// rotation needed for each of the three faces.
|
||||
|
||||
list gFaceRotations = [PI_BY_TWO, 0, MINUS_PI_BY_TWO];
|
||||
|
||||
|
||||
|
||||
// parts used to create gStateList, see boave.
|
||||
|
||||
list part1 = ["0000", 0, <1, 1, 0>, 0.0,
|
||||
|
||||
"1000", 1, <1, -1, 0>, 0.0,
|
||||
|
||||
"0100", 1, <-1, -1, 0>, 0.0,
|
||||
|
||||
"0010", 1, <1, 1, 0>, 0.0,
|
||||
|
||||
"0001", 1, <-1, 1, 0>, 0.0,
|
||||
|
||||
"2000", 2, <1, -1, 0>, 0.0,
|
||||
|
||||
"0200", 2, <-1, -1, 0>, 0.0,
|
||||
|
||||
"0020", 2, <1, 1, 0>, 0.0,
|
||||
|
||||
"0002", 2, <-1, 1, 0>, 0.0,
|
||||
|
||||
"1200", 3, <1, -1, 0>, 0.0,
|
||||
|
||||
"2100", 3, <-1, -1, 0>, 0.0,
|
||||
|
||||
"0012", 3, <1, 1, 0>, 0.0,
|
||||
|
||||
"0021", 3, <-1, 1, 0>, 0.0,
|
||||
|
||||
"1020", 3, <1, 1, 0>, PI_BY_TWO,
|
||||
|
||||
"2010", 3, <-1, 1, 0>, PI_BY_TWO];
|
||||
|
||||
list part2 = [
|
||||
|
||||
"0102", 3, <1, -1, 0>, PI_BY_TWO,
|
||||
|
||||
"0201", 3, <-1, -1, 0>, PI_BY_TWO,
|
||||
|
||||
"1002", 4, <1, -1, 0>, 0.0,
|
||||
|
||||
"0120", 4, <-1, -1, 0>, 0.0,
|
||||
|
||||
"2001", 4, <-1, 1, 0>, 0.0,
|
||||
|
||||
"0210", 4, <1, 1, 0>, 0.0,
|
||||
|
||||
"1100", 5, <1, -1, 0>, 0.0,
|
||||
|
||||
"0011", 5, <1, 1, 0>, 0.0,
|
||||
|
||||
"1010", 5, <1, 1, 0>, PI_BY_TWO,
|
||||
|
||||
"0101", 5, <1, -1, 0>, PI_BY_TWO,
|
||||
|
||||
"1001", 6, <-1, 1, 0>, 0.0,
|
||||
|
||||
"0110", 6, <1, 1, 0>, 0.0,
|
||||
|
||||
"2200", 7, <1, -1, 0>, 0.0,
|
||||
|
||||
"0022", 7, <1, 1, 0>, 0.0,
|
||||
|
||||
"2020", 7, <1, 1, 0>, PI_BY_TWO];
|
||||
|
||||
list part3 = [
|
||||
|
||||
"0202", 7, <1, -1, 0>, PI_BY_TWO,
|
||||
|
||||
67
Go_Game/Go_Game/Object/Go_Game_7.lsl
Normal file
67
Go_Game/Go_Game/Object/Go_Game_7.lsl
Normal file
@@ -0,0 +1,67 @@
|
||||
// :CATEGORY:Games
|
||||
// :NAME:Go_Game
|
||||
// :AUTHOR:Jonathan Shaftoe
|
||||
// :CREATED:2010-01-10 05:20:56.000
|
||||
// :EDITED:2013-09-18 15:38:54
|
||||
// :ID:357
|
||||
// :NUM:486
|
||||
// :REV:1.0
|
||||
// :WORLD:Second Life
|
||||
// :DESCRIPTION:
|
||||
// As with the sensors, we need a utility script to create the grid, GoTileGridScript.
|
||||
// :CODE:
|
||||
// GoTileGridScript
|
||||
|
||||
// Jonathan Shaftoe
|
||||
|
||||
// Utility script to create a linked grid of GoTile prims, each with a unique index.
|
||||
|
||||
// To use, rez a previously created GoTile from your inventory (see GoTileScript), then
|
||||
|
||||
// put a GoTile into the inventory of the one you rezzed, then put this script into it.
|
||||
|
||||
// It will spend a while rezing and linking all the GoTiles required, then once finished
|
||||
|
||||
// the script will delete itself from the object, now called GoTileGrid, which you take
|
||||
|
||||
// into your inventory and save for later.
|
||||
|
||||
|
||||
|
||||
// By default, this creates 33 sensors to make a total of 34, needed to cover a 19x19 board.
|
||||
|
||||
// If you only want to support smaller board sizes, you can reduce the totalTiles variable
|
||||
|
||||
// below to reduce the prim usage. For example, a 9x9 board just uses 10 tiles, so you can
|
||||
|
||||
// set totalTiles to 9.
|
||||
|
||||
|
||||
|
||||
|
||||
|
||||
integer gNumTiles = 0; // how many have we created
|
||||
|
||||
integer gCountRez = 0; // how many are waiting to be rezzed and linked.
|
||||
|
||||
|
||||
|
||||
default
|
||||
|
||||
{
|
||||
|
||||
state_entry()
|
||||
|
||||
{
|
||||
|
||||
llSetObjectName("GoTileGrid");
|
||||
|
||||
llRequestPermissions(llGetOwner(), PERMISSION_CHANGE_LINKS);
|
||||
|
||||
}
|
||||
|
||||
|
||||
|
||||
run_time_permissions(integer perms) {
|
||||
|
||||
state start;
|
||||
452
Go_Game/Go_Game/Object/Go_Game_8.lsl
Normal file
452
Go_Game/Go_Game/Object/Go_Game_8.lsl
Normal file
@@ -0,0 +1,452 @@
|
||||
// :CATEGORY:Games
|
||||
// :NAME:Go_Game
|
||||
// :AUTHOR:Jonathan Shaftoe
|
||||
// :CREATED:2010-01-10 05:20:56.000
|
||||
// :EDITED:2013-09-18 15:38:54
|
||||
// :ID:357
|
||||
// :NUM:487
|
||||
// :REV:1.0
|
||||
// :WORLD:Second Life
|
||||
// :DESCRIPTION:
|
||||
// You should now have a GoButton, a GoJoinButton, a GoSensorGrid and a GoTileGrid. Create a prim, drop an instance of each of those objects into its inventory, then finally put in the following two scripts which contain the main game logic, and you should have yourself a working Go board.
|
||||
//
|
||||
// First off is the GoGameLogicScript which contains most of the actual game logic for handling captures and the like.
|
||||
// :CODE:
|
||||
// GoGameLogicScript
|
||||
|
||||
// Jonathan Shaftoe
|
||||
|
||||
// Contains most of the game logic code for the Go game. It's big and it's nasty. It uses recursion
|
||||
|
||||
// to do group capture detection, so can be slow.
|
||||
|
||||
// For usage, see GoGameMainScript
|
||||
|
||||
|
||||
|
||||
integer gGameSize = 9; // size of the game board, can be 9, 13 or 19
|
||||
|
||||
|
||||
|
||||
integer gBlackScore; // current scores (captured stones)
|
||||
|
||||
integer gWhiteScore;
|
||||
|
||||
|
||||
|
||||
integer gDeadWhite; // count of dead stones in endgame
|
||||
|
||||
integer gDeadBlack;
|
||||
|
||||
|
||||
|
||||
string gGameStatePrev; // Previous game state, used to check for Ko
|
||||
|
||||
string gGameState; // Game state - string representing the current state of the game board.
|
||||
|
||||
string gCurrentGame; // Another copy of the game state, used to store current state when working out
|
||||
|
||||
// captures.
|
||||
|
||||
|
||||
|
||||
list gGroup = []; // list of indexes of stones in (possibly captured) group.
|
||||
|
||||
integer gGroupLiberties; // How many liberties the currently being checked group has
|
||||
|
||||
integer gLibertyX; // coordinates of found liberty. We only care if there are no liberties, one liberty
|
||||
|
||||
integer gLibertyY; // or more than one (number if more than one doesn't matter), so we store the first
|
||||
|
||||
// found liberty here, then subsequently found liberties we check if they're the same
|
||||
|
||||
// as this one, and if not then we know we have more than one.
|
||||
|
||||
integer gSearchColour; // Are we looking for black or white stones
|
||||
|
||||
|
||||
|
||||
integer gTurn; // Whose turn is it, black or white
|
||||
|
||||
integer gLastWasPass; // So we know if we get two passes in a row
|
||||
|
||||
integer gTurnPreEndgame; // For turn handling during endgame
|
||||
|
||||
|
||||
|
||||
integer gGotAtari; // If we've found at least one group with only one liberty left after a stone
|
||||
|
||||
// is played, then we have an atari
|
||||
|
||||
|
||||
|
||||
list gToDelete; // list of indexes of stones to be removed due to capture (can be more than one group)
|
||||
|
||||
|
||||
|
||||
integer gGroupType; // type of group check being done, to avoid having to pass it through recursive calls.
|
||||
|
||||
// 0 - suicide check, 1 - normal turn check, 2 - endgame dead group marking, 3 - endgame scoring.
|
||||
|
||||
float gSize=4.0; // global scale factor.
|
||||
|
||||
|
||||
|
||||
set_player(integer turn, integer endgame, integer send_message) {
|
||||
|
||||
gTurn = turn;
|
||||
|
||||
if (send_message == 1) {
|
||||
|
||||
llMessageLinked(LINK_ROOT, 101, (string)gTurn, (key)((string)endgame));
|
||||
|
||||
}
|
||||
|
||||
}
|
||||
|
||||
|
||||
|
||||
integer get_board_state(integer x, integer y) {
|
||||
|
||||
integer index = x + 1 + ((y + 1) * (gGameSize + 2));
|
||||
|
||||
string num = llGetSubString(gGameState, index, index);
|
||||
|
||||
return (integer)num;
|
||||
|
||||
}
|
||||
|
||||
|
||||
|
||||
set_board_state(integer x, integer y, integer newstate) {
|
||||
|
||||
integer index = x + 1 + ((y + 1) * (gGameSize + 2));
|
||||
|
||||
string before = llGetSubString(gGameState, 0, index - 1);
|
||||
|
||||
string after = llGetSubString(gGameState, index + 1, llStringLength(gGameState) - 1);
|
||||
|
||||
gGameState = before + (string)newstate + after;
|
||||
|
||||
}
|
||||
|
||||
|
||||
|
||||
// Sets gameboard size and initialises gameState. Note 3s used around edge to make
|
||||
|
||||
// group detection easier (no boundary conditions, 3 is neither 1 (black) or 2 (white))
|
||||
|
||||
set_size(integer size) {
|
||||
|
||||
gGameSize = size;
|
||||
|
||||
if (gGameSize == 9) {
|
||||
|
||||
gGameState = "33333333333" +
|
||||
|
||||
"30000000003" +
|
||||
|
||||
"30000000003" +
|
||||
|
||||
"30000000003" +
|
||||
|
||||
"30000000003" +
|
||||
|
||||
"30000000003" +
|
||||
|
||||
"30000000003" +
|
||||
|
||||
"30000000003" +
|
||||
|
||||
"30000000003" +
|
||||
|
||||
"30000000003" +
|
||||
|
||||
"33333333333";
|
||||
|
||||
} else if (gGameSize == 13) {
|
||||
|
||||
gGameState = "333333333333333" +
|
||||
|
||||
"300000000000003" +
|
||||
|
||||
"300000000000003" +
|
||||
|
||||
"300000000000003" +
|
||||
|
||||
"300000000000003" +
|
||||
|
||||
"300000000000003" +
|
||||
|
||||
"300000000000003" +
|
||||
|
||||
"300000000000003" +
|
||||
|
||||
"300000000000003" +
|
||||
|
||||
"300000000000003" +
|
||||
|
||||
"300000000000003" +
|
||||
|
||||
"300000000000003" +
|
||||
|
||||
"300000000000003" +
|
||||
|
||||
"300000000000003" +
|
||||
|
||||
"333333333333333";
|
||||
|
||||
} else if (gGameSize == 19) {
|
||||
|
||||
gGameState = "333333333333333333333" +
|
||||
|
||||
"300000000000000000003" +
|
||||
|
||||
"300000000000000000003" +
|
||||
|
||||
"300000000000000000003" +
|
||||
|
||||
"300000000000000000003" +
|
||||
|
||||
"300000000000000000003" +
|
||||
|
||||
"300000000000000000003" +
|
||||
|
||||
"300000000000000000003" +
|
||||
|
||||
"300000000000000000003" +
|
||||
|
||||
"300000000000000000003" +
|
||||
|
||||
"300000000000000000003" +
|
||||
|
||||
"300000000000000000003" +
|
||||
|
||||
"300000000000000000003" +
|
||||
|
||||
"300000000000000000003" +
|
||||
|
||||
"300000000000000000003" +
|
||||
|
||||
"300000000000000000003" +
|
||||
|
||||
"300000000000000000003" +
|
||||
|
||||
"300000000000000000003" +
|
||||
|
||||
"300000000000000000003" +
|
||||
|
||||
"300000000000000000003" +
|
||||
|
||||
"333333333333333333333";
|
||||
|
||||
}
|
||||
|
||||
}
|
||||
|
||||
|
||||
|
||||
// functions below for doing recursive group detection. This is NOT efficient.
|
||||
|
||||
// on a 19x19 board, you can run out of script execution stack space if there are big
|
||||
|
||||
// groups. Could be improved.
|
||||
|
||||
|
||||
|
||||
recurse_check_util(integer x, integer y, integer dir) {
|
||||
|
||||
integer neighbour = get_board_state(x, y);
|
||||
|
||||
if (neighbour == gSearchColour) {
|
||||
|
||||
recurse_check(x, y, dir);
|
||||
|
||||
} else if (neighbour == 0 && gGroupType != 2) {
|
||||
|
||||
if (x != gLibertyX || y != gLibertyY) {
|
||||
|
||||
gLibertyX = x;
|
||||
|
||||
gLibertyY = y;
|
||||
|
||||
gGroupLiberties++;
|
||||
|
||||
}
|
||||
|
||||
} else if ((neighbour == 2 || neighbour == 1) && gGroupType == 3) {
|
||||
|
||||
if (gGroupLiberties != neighbour) {
|
||||
|
||||
gGroupLiberties += neighbour;
|
||||
|
||||
}
|
||||
|
||||
}
|
||||
|
||||
}
|
||||
|
||||
|
||||
|
||||
recurse_check(integer x, integer y, integer dir) {
|
||||
|
||||
if (gGroupType == 1 && gGroupLiberties >= 2) {
|
||||
|
||||
return;
|
||||
|
||||
}
|
||||
|
||||
if (gGroupType == 0 && gGroupLiberties == 1) {
|
||||
|
||||
return;
|
||||
|
||||
}
|
||||
|
||||
if (llListFindList(gGroup, [x + (y * gGameSize)]) != -1) {
|
||||
|
||||
return;
|
||||
|
||||
}
|
||||
|
||||
gGroup = gGroup + [x + (y * gGameSize)];
|
||||
|
||||
if (dir != 0) {
|
||||
|
||||
recurse_check_util(x - 1, y, 1);
|
||||
|
||||
}
|
||||
|
||||
if (dir != 1) {
|
||||
|
||||
recurse_check_util(x + 1, y, 0);
|
||||
|
||||
}
|
||||
|
||||
if (dir != 2) {
|
||||
|
||||
recurse_check_util(x, y - 1, 3);
|
||||
|
||||
}
|
||||
|
||||
if (dir != 3) {
|
||||
|
||||
recurse_check_util(x, y + 1, 2);
|
||||
|
||||
}
|
||||
|
||||
}
|
||||
|
||||
|
||||
|
||||
integer check_captures(integer x, integer y, integer dir, integer type) {
|
||||
|
||||
integer groupSize = 0;
|
||||
|
||||
gGroup = [];
|
||||
|
||||
gGroupLiberties = 0;
|
||||
|
||||
gLibertyX = -1;
|
||||
|
||||
gLibertyY = -1;
|
||||
|
||||
gGroupType = type;
|
||||
|
||||
recurse_check(x, y, dir);
|
||||
|
||||
|
||||
|
||||
// if type == 0 then we're checking for a suicide play.
|
||||
|
||||
if (type == 3 || gGroupLiberties == 0) {
|
||||
|
||||
groupSize = llGetListLength(gGroup);
|
||||
|
||||
}
|
||||
|
||||
if (type == 1) { // finding captured groups in normal gameplay
|
||||
|
||||
if (gGroupLiberties == 1) {
|
||||
|
||||
gGotAtari = 1;
|
||||
|
||||
} else if (gGroupLiberties == 0) {
|
||||
|
||||
integer i = 0;
|
||||
|
||||
while (i < groupSize) {
|
||||
|
||||
integer index = llList2Integer(gGroup, i);
|
||||
|
||||
integer remx = index % gGameSize;
|
||||
|
||||
integer remy = index / gGameSize;
|
||||
|
||||
set_board_state(remx, remy, 0);
|
||||
|
||||
i++;
|
||||
|
||||
}
|
||||
|
||||
gToDelete = gToDelete + gGroup;
|
||||
|
||||
}
|
||||
|
||||
} else if (type == 2) { // marking dead groups in endgame
|
||||
|
||||
integer i = 0;
|
||||
|
||||
while (i < groupSize) {
|
||||
|
||||
integer index = llList2Integer(gGroup, i);
|
||||
|
||||
integer remx = index % gGameSize;
|
||||
|
||||
integer remy = index / gGameSize;
|
||||
|
||||
set_board_state(remx, remy, 0);
|
||||
|
||||
i++;
|
||||
|
||||
gToDelete = gToDelete + gGroup;
|
||||
|
||||
}
|
||||
|
||||
} else if (type == 3) { // counting territory space in endgame - gGroupLiberties used to store colour of neighbouring stones to work out territory owner. If both colours are found then they're added so result will be 3 (or more)
|
||||
|
||||
integer i = 0;
|
||||
|
||||
while (i < groupSize) {
|
||||
|
||||
integer index = llList2Integer(gGroup, i);
|
||||
|
||||
integer remx = index % gGameSize;
|
||||
|
||||
integer remy = index / gGameSize;
|
||||
|
||||
set_board_state(remx, remy, 3);
|
||||
|
||||
i++;
|
||||
|
||||
}
|
||||
|
||||
if (gGroupLiberties == 1) {
|
||||
|
||||
gBlackScore += groupSize;
|
||||
|
||||
} else if (gGroupLiberties == 2) {
|
||||
|
||||
gWhiteScore += groupSize;
|
||||
|
||||
}
|
||||
|
||||
}
|
||||
|
||||
|
||||
|
||||
return groupSize;
|
||||
|
||||
}
|
||||
|
||||
|
||||
|
||||
440
Go_Game/Go_Game/Object/Go_Game_9.lsl
Normal file
440
Go_Game/Go_Game/Object/Go_Game_9.lsl
Normal file
@@ -0,0 +1,440 @@
|
||||
// :CATEGORY:Games
|
||||
// :NAME:Go_Game
|
||||
// :AUTHOR:Jonathan Shaftoe
|
||||
// :CREATED:2010-01-10 05:20:56.000
|
||||
// :EDITED:2013-09-18 15:38:54
|
||||
// :ID:357
|
||||
// :NUM:488
|
||||
// :REV:1.0
|
||||
// :WORLD:Second Life
|
||||
// :DESCRIPTION:
|
||||
// And now for the GoGameMainScript, which does all the gluing together of all the other scripts, and handles players joining/leaving the game and the like.
|
||||
// :CODE:
|
||||
// GoGameMainScript
|
||||
|
||||
// Jonathan Shaftoe
|
||||
|
||||
// This is the main controlling script which sorts out rezzing all the objects and moving
|
||||
|
||||
// them around and sending messages to the other bits and pieces. It's big and it's messy.
|
||||
|
||||
// To use, create a single prim, drop into it a previously created GoButton, GoJoinButton,
|
||||
|
||||
// GoSensorGrid and GoTileGrid, then drop in the GoGaneLogicScript, then finally drop in this
|
||||
|
||||
// script. If you want the info button to give out a notecard, create one called Go Info and
|
||||
|
||||
// drop that into the inventory of the prim too (actually, it'll probably error if you don't
|
||||
|
||||
// do this, so.. )
|
||||
|
||||
|
||||
|
||||
// Channel used for listens, used for dialogs.
|
||||
|
||||
integer CHANNEL = 85483;
|
||||
|
||||
// Size of go board, 9, 13 or 19. This is just what it initialises to, can be changed
|
||||
|
||||
// during game setup
|
||||
|
||||
integer gGameSize = 9;
|
||||
|
||||
|
||||
|
||||
// Store the current listener, so we can remove it.
|
||||
|
||||
integer gListener;
|
||||
|
||||
// This is a general scaling multiplier, allowing you either to create a small dinky Go Board, or a
|
||||
|
||||
// large one. The maximum size that will work is 9.0, as beyond that linking of things fails. I've
|
||||
|
||||
// not experimented with the smallest workable size.
|
||||
|
||||
float SIZE = 3.0;
|
||||
|
||||
|
||||
|
||||
// Keys and names of the players playing each colour
|
||||
|
||||
key gBlackPlayer;
|
||||
|
||||
key gWhitePlayer;
|
||||
|
||||
string gBlackName;
|
||||
|
||||
string gWhiteName;
|
||||
|
||||
// Current player, whose turn it is.
|
||||
|
||||
key gPlayer;
|
||||
|
||||
|
||||
|
||||
// How many sensors we have, and the size of grid being used.
|
||||
|
||||
integer gXSensors;
|
||||
|
||||
integer gYSensors;
|
||||
|
||||
|
||||
|
||||
// Current scores
|
||||
|
||||
integer gBlackScore = 0;
|
||||
|
||||
integer gWhiteScore = 0;
|
||||
|
||||
|
||||
|
||||
// Used for counting rezzes, so we know when everything has been rezzedd
|
||||
|
||||
integer gCountRez;
|
||||
|
||||
|
||||
|
||||
// Whose turn it is, 0 is black, 1 is white.
|
||||
|
||||
integer gTurn = 0;
|
||||
|
||||
|
||||
|
||||
// How long since last turn (for reset)
|
||||
|
||||
string gLastTurnDate;
|
||||
|
||||
float gLastTurnTime;
|
||||
|
||||
|
||||
|
||||
// for the alpha part of coords, so we know what to call each square in messages. Note
|
||||
|
||||
// absence of I to avoid confusion with 1.
|
||||
|
||||
string COORDS = "ABCDEFGHJKLMNOPQRST";
|
||||
|
||||
|
||||
|
||||
|
||||
|
||||
set_player(integer turn, integer endgame, integer send_message) {
|
||||
|
||||
vector colour;
|
||||
|
||||
integer score = 0;
|
||||
|
||||
string name;
|
||||
|
||||
gTurn = turn;
|
||||
|
||||
if (gTurn == 0) {
|
||||
|
||||
gPlayer = gBlackPlayer;
|
||||
|
||||
score = gBlackScore;
|
||||
|
||||
colour = <0, 0, 0>;
|
||||
|
||||
name = gBlackName;
|
||||
|
||||
} else {
|
||||
|
||||
gPlayer = gWhitePlayer;
|
||||
|
||||
score = gWhiteScore;
|
||||
|
||||
colour = <1, 1, 1>;
|
||||
|
||||
name = gWhiteName;
|
||||
|
||||
}
|
||||
|
||||
llMessageLinked(LINK_ALL_CHILDREN, 0, "", gPlayer);
|
||||
|
||||
if (endgame == 0) {
|
||||
|
||||
llSetText(name + "'s turn (prisoners: " + (string)score + ").", colour, 1.0);
|
||||
|
||||
} else if (endgame == 1) {
|
||||
|
||||
llSetText(name + "'s turn to remove dead groups (prisoners: " + (string)score + ").", colour, 1.0);
|
||||
|
||||
llInstantMessage(gPlayer, "Select opponent's dead groups then click done.");
|
||||
|
||||
}
|
||||
|
||||
if (send_message == 1) {
|
||||
|
||||
llMessageLinked(LINK_ROOT, 103, (string)gTurn, (string)endgame);
|
||||
|
||||
}
|
||||
|
||||
gLastTurnDate = llGetDate();
|
||||
|
||||
gLastTurnTime = llGetGMTclock();
|
||||
|
||||
}
|
||||
|
||||
|
||||
|
||||
set_size(integer size) {
|
||||
|
||||
gGameSize = size;
|
||||
|
||||
if (gGameSize == 9) {
|
||||
|
||||
gXSensors = 3;
|
||||
|
||||
gYSensors = 3;
|
||||
|
||||
llSetTexture("a9878863-732f-09af-b908-09070ea9b213", 0);
|
||||
|
||||
} else if (gGameSize == 13) {
|
||||
|
||||
gXSensors = 4;
|
||||
|
||||
gYSensors = 4;
|
||||
|
||||
llSetTexture("a0973434-028b-3323-b572-8347095e6c3c", 0);
|
||||
|
||||
} else if (gGameSize == 19) {
|
||||
|
||||
gXSensors = 4;
|
||||
|
||||
gYSensors = 5;
|
||||
|
||||
llSetTexture("9575b5cf-72ec-14bf-e400-320f9008bbd9", 0);
|
||||
|
||||
}
|
||||
|
||||
llSetScale(<(gGameSize + 1.0) * SIZE / gGameSize, (gGameSize + 1.0) * SIZE / gGameSize, 0.01 * SIZE>);
|
||||
|
||||
llMessageLinked(LINK_ALL_CHILDREN, 3, (string)gGameSize + "," + (string)gXSensors + "," + (string)gYSensors + "," + (string)SIZE, "");
|
||||
|
||||
llMessageLinked(LINK_ROOT, 100, (string)gGameSize, (string)SIZE);
|
||||
|
||||
}
|
||||
|
||||
|
||||
|
||||
// State we start in, but don't stay in long. Need permission to link to do set-up.
|
||||
|
||||
default {
|
||||
|
||||
state_entry() {
|
||||
|
||||
llSetPrimitiveParams([
|
||||
|
||||
PRIM_TYPE, PRIM_TYPE_BOX, PRIM_HOLE_DEFAULT, <0, 1, 0>, 0.0,
|
||||
|
||||
ZERO_VECTOR, <1, 1, 0>, ZERO_VECTOR,
|
||||
|
||||
PRIM_SIZE, <1 * SIZE, 1 * SIZE, 0.01 * SIZE>,
|
||||
|
||||
PRIM_TEXTURE, ALL_SIDES, "5748decc-f629-461c-9a36-a35a221fe21f", <1, 1, 0>, <0, 0, 0>, 0.0,
|
||||
|
||||
PRIM_COLOR, ALL_SIDES, <0.8, 0.6, 0.5>, 1.0
|
||||
|
||||
]);
|
||||
|
||||
llSetObjectName("Jonathan's Go Board");
|
||||
|
||||
llSetObjectDesc("Jonathan's Go Board");
|
||||
|
||||
llSitTarget(ZERO_VECTOR, ZERO_ROTATION);
|
||||
|
||||
llRequestPermissions(llGetOwner(), PERMISSION_CHANGE_LINKS);
|
||||
|
||||
}
|
||||
|
||||
|
||||
|
||||
run_time_permissions(integer perms) {
|
||||
|
||||
llBreakAllLinks();
|
||||
|
||||
state initialising;
|
||||
|
||||
}
|
||||
|
||||
}
|
||||
|
||||
|
||||
|
||||
// Initialisation state, rezzing all the buttons we need
|
||||
|
||||
state initialising {
|
||||
|
||||
state_entry() {
|
||||
|
||||
gCountRez = 7;
|
||||
|
||||
llRezObject("GoButton", llGetPos() + <SIZE * (0.5 + 0.2), SIZE * .45, SIZE * .02>, ZERO_VECTOR, llGetRot(), 1);
|
||||
|
||||
llRezObject("GoButton", llGetPos() + <SIZE * (0.5 + 0.2), SIZE * .25, SIZE * .02>, ZERO_VECTOR, llGetRot(), 2);
|
||||
|
||||
llRezObject("GoButton", llGetPos() + <SIZE * (0.5 + 0.2), SIZE * -.25, SIZE * .02>, ZERO_VECTOR, llGetRot(), 4);
|
||||
|
||||
llRezObject("GoButton", llGetPos() + <SIZE * (0.5 + 0.2), SIZE * -.45, SIZE * .02>, ZERO_VECTOR, llGetRot(), 3);
|
||||
|
||||
llRezObject("GoButton", llGetPos() + <SIZE * (0.5 + 0.2), 0, SIZE * .02>, ZERO_VECTOR, llGetRot(), 5);
|
||||
|
||||
llRezObject("GoJoinButton", llGetPos() + <0, SIZE * 0.5, 0.1 * SIZE>, ZERO_VECTOR, llGetRot(), 1);
|
||||
|
||||
llRezObject("GoJoinButton", llGetPos() + <0, SIZE * -0.5, 0.1 * SIZE>, ZERO_VECTOR, llGetRot(), 2);
|
||||
|
||||
}
|
||||
|
||||
|
||||
|
||||
object_rez(key id) {
|
||||
|
||||
llCreateLink(id, TRUE);
|
||||
|
||||
gCountRez--;
|
||||
|
||||
if (gCountRez == 0) {
|
||||
|
||||
llMessageLinked(LINK_ALL_CHILDREN, 1, (string)SIZE, "");
|
||||
|
||||
state setup_sensors;
|
||||
|
||||
}
|
||||
|
||||
}
|
||||
|
||||
}
|
||||
|
||||
|
||||
|
||||
// Initialization state 2, seting up the sensor and tile grids.
|
||||
|
||||
state setup_sensors {
|
||||
|
||||
state_entry() {
|
||||
|
||||
gCountRez = 2;
|
||||
|
||||
|
||||
|
||||
llRezObject("GoSensorGrid", llGetPos() + <0, 0, 0.005 * SIZE + .01>, ZERO_VECTOR, llGetRot(), 0);
|
||||
|
||||
llRezObject("GoTileGrid", llGetPos() + <0, 0, 0.005 * SIZE + 0.1>, ZERO_VECTOR, llGetRot(), 0);
|
||||
|
||||
}
|
||||
|
||||
|
||||
|
||||
object_rez(key id) {
|
||||
|
||||
llCreateLink(id, TRUE);
|
||||
|
||||
gCountRez--;
|
||||
|
||||
if (gCountRez == 0) {
|
||||
|
||||
set_size(9);
|
||||
|
||||
state awaiting_start;
|
||||
|
||||
}
|
||||
|
||||
}
|
||||
|
||||
}
|
||||
|
||||
|
||||
|
||||
// All initialised, waiting for players to join the game, plus can change game board size.
|
||||
|
||||
|
||||
|
||||
state awaiting_start {
|
||||
|
||||
state_entry() {
|
||||
|
||||
llSetTouchText("Game Size");
|
||||
|
||||
llSetText("Go Game - awaiting players", <0, 0, 0>, 1.0);
|
||||
|
||||
}
|
||||
|
||||
|
||||
|
||||
state_exit() {
|
||||
|
||||
llSetTimerEvent(0);
|
||||
|
||||
}
|
||||
|
||||
|
||||
|
||||
touch_start(integer num) {
|
||||
|
||||
llDialog(llDetectedKey(0), "Set size of Go game board.\nCurrently set to: " + (string)gGameSize + "x" + (string)gGameSize, ["9x9", "13x13", "19x19"], CHANNEL);
|
||||
|
||||
llListenRemove(gListener);
|
||||
|
||||
gListener = llListen(CHANNEL, "", llDetectedKey(0), "");
|
||||
|
||||
// Make sure we timeout the listen, in case they ignore the dialog
|
||||
|
||||
llSetTimerEvent(60 * 2);
|
||||
|
||||
}
|
||||
|
||||
|
||||
|
||||
listen(integer channel, string name, key id, string message) {
|
||||
|
||||
if (message == "9x9") {
|
||||
|
||||
set_size(9);
|
||||
|
||||
} else if (message == "13x13") {
|
||||
|
||||
set_size(13);
|
||||
|
||||
} else if (message == "19x19") {
|
||||
|
||||
set_size(19);
|
||||
|
||||
}
|
||||
|
||||
llWhisper(0, "Go board set to size: " + (string)gGameSize + "x" + (string)gGameSize);
|
||||
|
||||
llListenRemove(gListener);
|
||||
|
||||
llSetTimerEvent(0);
|
||||
|
||||
}
|
||||
|
||||
|
||||
|
||||
timer() {
|
||||
|
||||
llListenRemove(gListener);
|
||||
|
||||
llSetTimerEvent(0);
|
||||
|
||||
}
|
||||
|
||||
|
||||
|
||||
link_message(integer sender, integer num, string str, key id) {
|
||||
|
||||
if (num == 1) {
|
||||
|
||||
gBlackPlayer = id;
|
||||
|
||||
gBlackName = llKey2Name(id);
|
||||
|
||||
llWhisper(0, gBlackName + " will play black.");
|
||||
|
||||
} else if (num == 2) {
|
||||
|
||||
gWhitePlayer = id;
|
||||
|
||||
gWhiteName = llKey2Name(id);
|
||||
|
||||
Reference in New Issue
Block a user