ServerGame starts a game at the server and then until end of the game repeats to get the game status and the current board from the server (Server.getBoard()), passes it to the player (Player.setBoard()) and commands the player to return a move (Player.move()) which is sent to the server again.
Board is the abstract representation of the status of a two player strategic game. Its subclasses must define all rules of the specific game (Board.getPossibleMove(), Board.isValidMove(), Board.isFinished()). Action represents a player's action which usually will contain a Move, but could be retirement or requesting a new game as well (if it is a human player).
The task of a Strategy (used by ComputerPlayer) is to calculate the "best" move on a given board. It may contain an "innerStrategy" to do parts of its work. meisterpropper for instance uses an OpeningStrategy that tries to find a move in its opening database. If it fails, it calls its inner strategy IterDepthStrategy that performs iterative deepening using aspiration window search (AspirationStrategy) with help of an alpha-beta search algorithm (NegaMaxStrategy) :-).
Last piece of the jigsaw puzzle: estimating the quality of a given board (rating).
To support multiple criterias when rating a board and different rating functions
for different game phases, the actual Rater can be composed of multiple
Raters like the LinearRater that combines several ratings into a
weighted sum. The PhasesRater contains a set of raters for the different
phases of a game.
public boolean isValidMove(int row, int col) { int arow, acol; byte piece; if (board[row][col] != NONE) return false; // look in upper direction arow = row-1; if (arow>0 && isEnemyPieceAt(arow, col)) { for(;;) { --arow; if (arow<0 || (piece = board[arow][col]) == NONE) break; if (isOwnPiece(turn,piece)) return true; } } // look in lower direction arow = row+1; if (arow<rows-1 && isEnemyPieceAt(arow, col)) { for(;;) { ++arow; if (arow>=rows || (piece = board[arow][col]) == NONE) break; if (isOwnPiece(turn,piece)) return true; } } // look in left direction acol = col-1; if (acol>0 && isEnemyPieceAt(row, acol)) { for(;;) { --acol; if (acol<0 || (piece = board[row][acol]) == NONE) break; if (isOwnPiece(turn,piece)) return true; } } // look in right direction acol = col+1; if (acol<cols-1 && isEnemyPieceAt(row, acol)) { for(;;) { ++acol; if (acol>=cols || (piece = board[row][acol]) == NONE) break; if (isOwnPiece(turn,piece)) return true; } } // look in left upper direction arow = row-1; acol = col-1; if (arow>0 && acol>0 && isEnemyPieceAt(arow, acol)) { for(;;) { --arow; --acol; if (arow<0 || acol<0 || (piece = board[arow][acol]) == NONE) break; if (isOwnPiece(turn,piece)) return true; } } // look in right upper direction arow = row+1; acol = col-1; if (arow<rows-1 && acol>0 && isEnemyPieceAt(arow, acol)) { for(;;) { ++arow; --acol; if (arow>=rows || acol<0 || (piece = board[arow][acol]) == NONE) break; if (isOwnPiece(turn,piece)) return true; } } // look in right lower direction arow = row+1; acol = col+1; if (arow<rows-1 && acol<cols-1 && isEnemyPieceAt(arow, acol)) { for(;;) { ++arow; ++acol; if (arow>=rows || acol>=cols || (piece = board[arow][acol]) == NONE) break; if (isOwnPiece(turn,piece)) return true; } } // look in left lower direction arow = row-1; acol = col+1; if (arow>0 && acol<cols-1 && isEnemyPieceAt(arow, acol)) { for(;;) { --arow; ++acol; if (arow<0 || acol>=cols || (piece = board[arow][acol]) == NONE) break; if (isOwnPiece(turn,piece)) return true; } } return false; }