001: package org.millstone.examples.gogame;
002:
003: import java.util.Iterator;
004: import java.util.LinkedList;
005:
006: public class Game {
007:
008: // States for the positions on the game board.
009: /** Empty position. */
010: public static final int EMPTY = 0;
011: /** Black stone. */
012: public static final int BLACK = 1;
013: /** White stone */
014: public static final int WHITE = 2;
015:
016: // Two-dimentionel array holding the current state of the game.
017: private int[][] state;
018:
019: // List of listeners listening to game events.
020: private LinkedList listeners = new LinkedList();
021:
022: // Names of the players.
023: private String blackPlayer;
024: private String whitePlayer;
025:
026: // Number of moves made so far.
027: private int moves = 0;
028:
029: // Number of captured stones
030: private int captured[] = { 0, 0, 0 };
031:
032: /** Creates a new game with the specified board size and player names.
033: */
034: public Game(int boardSize, String blackPlayer, String whitePlayer) {
035:
036: // Assign player names.
037: this .blackPlayer = blackPlayer;
038: this .whitePlayer = whitePlayer;
039:
040: // Initialize board.
041: state = new int[boardSize][boardSize];
042: for (int i = 0; i < boardSize; i++)
043: for (int j = 0; j < boardSize; j++)
044: state[i][j] = EMPTY;
045: }
046:
047: /** Gets the current state of the game as a two-dimentional array
048: * representing the board, with the states Game.EMPTY, Game.BLACK
049: * and Game.WHITE.
050: */
051: public int[][] getState() {
052: return state;
053: }
054:
055: /** Adds a black or white stone to the specified position on the
056: * board.
057: */
058: public void addStone(int i, int j, boolean isBlack) {
059: if (state[i][j] == EMPTY) {
060: state[i][j] = isBlack ? BLACK : WHITE;
061: moves++;
062: removeDeadStonesAround(i, j);
063: for (Iterator li = listeners.iterator(); li.hasNext();)
064: ((Game.Listener) li.next()).stoneIsAdded(this , i, j,
065: isBlack);
066: }
067: }
068:
069: /** Adds a listener to the list of listeners
070: */
071: public void addGameListener(Game.Listener listener) {
072: listeners.add(listener);
073: }
074:
075: /** Removes a listener from the list of listeners.
076: */
077: public void removeGameListener(Game.Listener listener) {
078: listeners.remove(listener);
079: }
080:
081: /** Interface for implementing a listener listening to Go-game events.
082: */
083: public interface Listener {
084: /** Called whenever a stone is added to the game.
085: */
086: public void stoneIsAdded(Game game, int i, int j,
087: boolean isBlack);
088: }
089:
090: /** This function returns the state of the game as a string.
091: */
092: public String toString() {
093: return blackPlayer
094: + " (Black) vs. "
095: + whitePlayer
096: + " (White) ("
097: + state.length
098: + "x"
099: + state[0].length
100: + ", "
101: + moves
102: + " moves done"
103: + (captured[WHITE] > 0 ? (", Black has captured "
104: + captured[WHITE] + " stones") : "")
105: + (captured[BLACK] > 0 ? (", White has captured "
106: + captured[BLACK] + " stones") : "") + ")";
107: }
108:
109: /** Gets the black player's name.
110: */
111: public String getBlackPlayer() {
112: return blackPlayer;
113: }
114:
115: /** Gets the number of moves so far.
116: */
117: public int getMoves() {
118: return moves;
119: }
120:
121: /** Gets the white player's name.
122: */
123: public String getWhitePlayer() {
124: return whitePlayer;
125: }
126:
127: /** Remove dead stones. Removes stones that are dead as
128: * defined by the rules of go. The state is only checked for
129: * the four stones surrounding the last stone added */
130: private void removeDeadStonesAround(int lastx, int lasty) {
131:
132: // Remove possible victims of attack
133: removeIfDead(lastx - 1, lasty, lastx, lasty);
134: removeIfDead(lastx + 1, lasty, lastx, lasty);
135: removeIfDead(lastx, lasty + 1, lastx, lasty);
136: removeIfDead(lastx, lasty - 1, lastx, lasty);
137:
138: // Remove stones on suicide
139: removeIfDead(lastx, lasty, -1, -1);
140: }
141:
142: /** Remove area, if it is dead. This fairly complicated algorithm
143: * tests if area starting from (x,y) is dead and removes it in
144: * such case. The last stone (lastx,lasty) is always alive. */
145: private void removeIfDead(int x, int y, int lastx, int lasty) {
146:
147: // Only check the stones on the board
148: int width = state.length;
149: int height = state[0].length;
150: if (x < 0 || y < 0 || x >= width || y >= width)
151: return;
152:
153: // Not dead if empty of same color than the last stone
154: int color = state[x][y];
155: if (color == EMPTY
156: || (lastx >= 0 && lasty >= 0 && color == state[lastx][lasty]))
157: return;
158:
159: // Check areas by growing
160: int checked[][] = new int[state.length][state[0].length];
161: checked[x][y] = color;
162: while (true) {
163: boolean stillGrowing = false;
164: for (int i = 0; i < width; i++)
165: for (int j = 0; j < height; j++)
166: for (int o = 0; o < 4; o++)
167: if (checked[i][j] == EMPTY) {
168: int nx = i;
169: int ny = j;
170: switch (o) {
171: case 0:
172: nx++;
173: break;
174: case 1:
175: nx--;
176: break;
177: case 2:
178: ny++;
179: break;
180: case 3:
181: ny--;
182: break;
183: }
184: if (nx >= 0 && ny >= 0 && nx < width
185: && ny < height
186: && checked[nx][ny] == color) {
187: checked[i][j] = state[i][j];
188: if (checked[i][j] == color)
189: stillGrowing = true;
190: else if (checked[i][j] == EMPTY)
191:
192: // Freedom found
193: return;
194: }
195:
196: }
197: // If the area stops growing and no freedoms found,
198: // it is dead. Remove it
199: if (!stillGrowing) {
200: for (int i = 0; i < width; i++)
201: for (int j = 0; j < height; j++)
202: if (checked[i][j] == color) {
203: state[i][j] = EMPTY;
204: captured[color]++;
205: }
206: return;
207: }
208: }
209: }
210:
211: /** Get the number of white stones captures */
212: public int getCapturedWhiteStones() {
213: return captured[WHITE];
214: }
215:
216: /** Get the number of black stones captures */
217: public int getCapturedBlackStones() {
218: return captured[BLACK];
219: }
220: }
221:
222: /* This Millstone sample code is public domain. *
223: * For more information see www.millstone.org. */
|