OpenScrabble Programming Guide ------------------------------ for v05 NOTE: If anyone can quickly translate this document into HTML, I would appreciate it. Table of Contents: I. Aims of the OpenScrabble Engine II. Engine Organization III. Example Interface for the Engine IV. Afterword I. Aims of the OpenScrabble Engine ---------------------------------- The OpenScrabble Engine is a compilation of data structures that do all the backend stuff of a scrabble game: tile, board, bag, and player maintenance. The Engine will also provide an AI player, and leaves expansion for different player types: local human, network human, etc. The expectation is that the open source nature will allow it to proliferate on several platforms, perhaps even bridging people of different operating systems through network games. The nature of scr_Server even allows a computer to host a bunch of games at the same time. II. Engine Organization ----------------------- Well, I've been programming this Engine for a few weeks now, so now my verbalization ability has to catch up with the programming. Here goes: Overlying Structure of the Engine: notes: All OpenScrabble objects are denoted by the "scr_" prefix (a letter in parentheses shows another heading for the object somewhere else) (a letter by the function indicates a detailed explanation of the parameters and return types of the function, as well as its role) (a) scr_LocalServer (derived from scr_Server) contains the following: (b) scr_Board (c) scr_Bag (d) scr_Dictionary (e) scr_Player(s) (f) scr_Move * The distinction between scr_LocalServer and scr_Server is that the former is used when the game is hosted on the local machine The latter is the base class of all scr_*Server types. There could be an scr_RemoteServer for example. This polymorphism is to provide a seamless interface for network clients and such scr_Server is the "daddy" object of the Engine. It has functions for managing the players (ie distributing score, tiles) and orchestrates the interactions between the players and the other objects. The way it processes the players is in sequential order, going from one player to the next as the scr_Player::Run function is completed. The player it currently recognizes (ie is expecting input from) is the CurPlayer. Interface programmers must know the following member functions: //soon to be added different constructors for initializing a new game in //different ways (ie saved games, etc). (aa) void CreatePlayer(PLAYERTYPE type); (ab) void GetCopyOfBoard(char board[][]); (ac) int SubmitMove(scr_Move* move); (ad) int GetCurPlayerScore(); (ae) void CopyCurPlayerTiles(char* tiles); (af) int HowManyInBag(); (ag) void RunGame(); (ah) void RequestCurPlayerDrop(); (ai) int BoardSize(); (aj) int GetNumberTilesInRack(); (b) scr_Board has an array of struct Square which has letters and other important fields Although pretty obvious from the name, scr_Board contains a number of fields in its implementation to facilitate move checking and scoring (which will be important for the AI). For those interested in hacking the code, I will provide more details in a later version of the document on how the board file is set up (it may still be volatile, might switch text mode to binary mode) and what the different fields of the Square mean. The interface programmer doesn't need to use this object. (c) scr_Bag scr_Bag manages the acquisition, storage, and distribution of tiles. Foreign language programmers may have an interest in this, as the Bag may need to be adapted for different languages. Interface programmers need not worry about this. (d) scr_Dictionary If you looked at the code for scr_Dictionary, its probably looks pretty cryptic. That's because I forgot to comment it. Basically, though, the dictionary has a trie structure of up to 31 nodes (English only uses 26 though). The current word list uses about 640K of memory for over 100000 words. Foreign language programmers will get more support later. Interface programmers might down the road have some interest in it so the player can do his own string matching (there is no real programming interface for the dictionary now, there will be later). (e) scr_Player scr_Player is an inherited type. Its never used in its native form, only in its derivatives. There is only one derivative at this time: scr_HPlayer. The way the scr_Server allows an scr_Player type to play is by running its scr_XPlayer::GetData() function. Interface programmers need to pay special attention to this one: their whole interface is executed from this function. This is achieved by running and extern(?) function in the scr_HPlayer::GetData() function. Take a look at the example interface provided. Another important function is scr_Player::Update(). This function allows a player to know what another player's move was. This is important in that it allows network players to know what the remote player's move was, and also to inform the AI player of another player's move. (ea) int GetData(); (eb) int Update(scr_Move* move, int score); (ec) int InformFinalScores(int* scores); (ed) int InformInitialStats(int numplayer); (f) scr_Move scr_Move is a handy little class for sending the scr_Server a player move. This object should be generated dynamically because how its initialized determines what type of move it is. When its ready to be sent, send it to the scr_Server using SubmitMove(). More information on the constructors in the function listing. Don't forget to delete it afterwards. (fa) scr_Move(int x, int y, int dx, char* input); (fb) scr_Move(char* input); (fc) scr_Move(); (aa) void scr_Server::CreatePlayer(PLAYERTYPE type); CreatePlayer() adds another player to the game. The order of players is determined by the order of how CreatePlayer() is called. Player 0 (first player) would therefore have to be in the first CreatePlayer() call, Player 1 in the second, etc. PLAYERTYPE is an enumerated type. The following types available are: HUMAN. (ab) void scr_Server::GetCopyOfBoard(char board[][]); GetCopyOfBoard simplifies the process of acquiring the board from the scr_Server. It takes as a parameter an NxN char array where N is of the appropriate boardsize. It then copies a representation of the board to the parameter. The interface then handles the information from there. Here is the legend of what each character represents: '_' : empty board space '@' : double word score '#' : triple word score '2' : double letter score '3' : triple letter score lower case letter: normal letter upper case letter: letter that was once a blank (ac) int scr_Server::SubmitMove(scr_Move* move); SubmitMove sends the player's move to the server so it can update the board and get the player more tiles. The output value of SubmitMove is dependent on how the scr_Move pointer it is passed was instantiated. if the (p) method was used: the return value of SubmitMove is the score, unless the move is invalid; then the return value is -1; if the (q) method was used: the return value of the SubmitMove is whether the scr_Server was successful in trading the tiles; 1= success, 0= no success (bag had too few tiles or the input had tiles that were not in the player's rack) if the (r) method was used: the return value is 1; the move is a pass (ad) int scr_Server::GetCurPlayerScore(); This function returns the score of the player the scr_Server currently recognizes. (ae) void scr_Server::CopyCurPlayerTiles(char* tiles); This function creates a character representation of the player's tiles (ie returns them in standard ASCII format) the letters are always lowercase, but the blank is represented by a '*'. (af) int scr_Server::HowManyInBag(); This function returns the number of tiles currently in the Server's Bag. (ag) int scr_Server::RunGame(); RunGame is the crux of the OpenScrabble game. Not only does it begin the OpenScrabble game, but it allows the execution to be controlled by the scr_Server (ie, the scr_Server can determine which player should play when). Call this function when a game is ready to be played. The return type of this function is the noumber of the player that won. (ah) void scr_Server::RequestCurPlayerDrop(); This allows the CurPlayer to leave the game. The player will be deleted from the list, and his tiles will be discarded from the game or returned to the bag, depending on how the switch is set (the switch right now is set internally; an interface for controlling game variables like that will be available in a later release). If the number of players reaches 1, the game will terminate and the last player will be the victor. (ai) int BoardSize(); This returns N if board is NxN (aj) int NumberTilesInRack(); Returns number of tiles used in a rack. (ea) int scr_Player::GetData(); This is a virtual function that allows the interface maker or a network player maker to route the move input from the appropriate player. Simply use an external function to acquire the necessary data. Return value means the function was successful. Interface makers should put an external function in this function to handle data input. (eb) int scr_Player::Update(scr_Move* move, int score); This function handles a copy of the CurPlayer's move to all other player's, along with how much the move was worth. Interface makers need to know what they are going to do with the updated information (ec) int scr_Player::InformFinalScores(int* scores); When the game ends, the server will send out the final scores of the game (after the score is adjusted for the player's tiles) by running each player's copy of this function. Interface makers need to handle it. (ed) int scr_Player::InformInitialStats(int score); When the game begins, the scr_Server will inform all the players of initial setting, such as the number of people playing. This function will probably grow as more features are added. (fa) scr_Move::scr_Move(int x, int y, int dx, char* input); This particular constructor allows the interface to create a scrabble move based on the actual player's input. x and y are the coordinates of the move (must be 0-15), dx is the way it reads (0 horizontal, 1 vertical) and input is the word being made (all in lowercase, unless there is a blank, then that letter is UPPERCASE). (fb) scr_Move::scr_Move(char* remove); This constructor takes as its input the tiles the player wants to remove. The string is a series of letters that are in the player's rack. Use the same format for the string as input in (fa) (fc) scr_Move::scr_Move(); The default constructor makes the move a pass. III. Example Interface for the Engine ------------------------------------- The source files you need to look at are OpenScrabble.cpp and scr_HPlayer.cpp. They should be sufficiently commented to be of use. IV. Afterword ------------- OpenScrabble is still in its infancy. Although it has working support for many things, the programming interface may continue to have some evolution as people request more features and more feature are added. I will do my best to keep all version of the engine backwards compatible with others, but during the first few revisions of the project, the Engine functionality may shift a little. Bear with me during this time, and please excuse my dust. If there are any inconsistencies between the code and this document, please inform me. I will fix it right away.