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