Scrabble® [1]Back to Contents Prev: [2]Introduction Next: [3]Lexicon
Representation
_________________________________________________________________
Infrastructure Architecture
NOTE: The details in this section are meant to give the reader a broad
overview of the infrastructure design. It is not intended to be a
"developer's guide" or "SDK documentation". The infrastructure source
code is not publicly available, though it may be made so in the
future.
The game infrastructure's high level architecture was driven by 2
objectives:
1. Separation of user interface from game logic.
2. Wide accessibility (to facilitate testing and game record
gathering).
In order to meet these objectives, the infrastructure was designed as
a client-server pair, with the client implemented as a Java applet
(thus making it widely accessible via the Internet), and the server
implemented as a Java application (for portability). The client is
responsible for presenting UI, while the server handles maintenance of
game state and processing of computer play. Client and server
communicate via TCP/IP sockets, using an ASCII (for simplicity)
message protocol.
Testing the effectiveness of a computer game algorithm can be done by
pitting it against other algorithms and human players. While strictly
speaking the former does not require a graphical UI, it certainly
benefits from one, and the latter practically demands it.
Client Architecture
The client is a multi-threaded Java applet that displays a graphical
representation of the Scrabble® board and the player's letter rack.
Letter tiles can be moved as appropriate between the rack and board.
Command buttons allow the initiation of a new human-computer game,
submission of a human move, or initiation of a computer-computer game.
After each move, the client receives messages from the server
indicating the current state of the game in terms of score, board
configuration, rack contents, etc. and updates its display
accordingly. UI processing and network message processing are handled
on separate threads.
The only real game logic related processing that occurs at the client
end is determination of move position legality (i.e., whether newly
played tiles are all in the same row/column and have at least one
point of adjacency to already played tiles). There is no lexicon on
the client side, because there is no benefit to be gained for the cost
in download time and memory footprint. This means that move legality
in terms of word validity is checked at the server side.
Server Architecture
The server is a multi-threaded Java application that handles game
logic and computer play. The primary thread acts as a daemon, watching
for incoming network connections from new clients. A new
game-processing thread is created to handle each new client, and each
such thread maintains the game state for its particular client.
All game-processing threads share a single lexicon resource; any state
required for doing operations on the lexicon is maintained by the
appropriate game-processing thread. This minimizes memory overhead,
since the lexicon memory footprint can be quite dramatic (on the order
of several megabytes). The lexicon is used by the system for two
purposes: to validate human moves, and to support computer move
generation. Its interface is largely determined by the latter purpose;
the infrastructure only requires the lexicon to support a method
called recognize() in order to do human move validation, thus the rest
of the interface can and is customized to the particular needs of the
computer move generation algorithm(s).
Game state is represented by an object of class GameState, whose
primary member objects are of class BoardState, RackStates and
ComputerPlayer (in addition to various primitive members used to
maintain information like scores, current turn number, number of
players etc.). As the name suggests, the ComputerPlayer class
encapsulates the computer player's move generation and selection
algorithms; implementing different algorithms is simply a matter of
creating a new class similar to ComputerPlayer (perhaps even
inheriting from it), and accessing the BoardState and RackStates using
their defined interfaces. Due to time limitations, no attempt has been
made to formally define the interface between the computer player and
game state classes; the ad hoc interface currently in use is fairly
straight-forward and should be easily discernable from the source
code. The core game control loop looks something like:
for (;;) {
for (i=0; i < numPlayers ; ++i) {
if ( player[i].isHuman() ) {
player[i].blockOnMoveSubmission( gameState );
}
else {
player[i].computerPlayerMoves( gameState );
}
gameState.send();
}
}
Basically, players act on the game state (via messages from the client
for human players, or direct calls for computer players), and then the
updated state is sent out to all clients.
Message Protocol
The message protocol used to communicate between client and server is
ASCII string based; it was decided that the implementation simplicity
of an ASCII protocol was worth the cost in network traffic overhead.
Each message takes the form:
...
Source can be either C for client or S for server. Message types
include BOARDSTATE, RACKSTATE, NEWGAME, NEWGAME_ACK, etc. and can have
a variable number of parameters.
_________________________________________________________________
[4]Back to Contents Prev: [5]Introduction Next: [6]Lexicon
Representation
References
1. http://www.ece.uwaterloo.ca/~k2tam/Scrabble/contents.html
2. http://www.ece.uwaterloo.ca/~k2tam/Scrabble/intro.html
3. http://www.ece.uwaterloo.ca/~k2tam/Scrabble/lex.html
4. http://www.ece.uwaterloo.ca/~k2tam/Scrabble/contents.html
5. http://www.ece.uwaterloo.ca/~k2tam/Scrabble/intro.html
6. http://www.ece.uwaterloo.ca/~k2tam/Scrabble/lex.html