---
# System prepended metadata

title: CS50 Nuggets

---

# CS50 Nuggets
## Implementation Spec

In this document we reference the [Requirements Specification](REQUIREMENTS.md) and [Design Specification](DESIGN.md) and focus on the implementation-specific decisions.
The Lecture unit noted that an [implementation spec](https://www.cs.dartmouth.edu/~cs50/Lectures/units/design.html#implementation-spec) may include many topics; not all are relevant to Nuggets.
Here we focus on the core subset:

-  Data structures
-  Control flow: pseudo code for overall flow, and for each of the functions
-  Detailed function prototypes and their parameters
-  Error handling and recovery
-  Testing plan

## Data structures for Server, Grid, and Player-server

- We use an array (of size 26, the max number of players) to hold the player struct
- We create four types of data structs
    - a grid module, a two-dimensional array of characters to hold the map of the game and integer values for number of rows and number of columns.
    - a player module, which holds information about the clients who join the game (player ID, playername, goldcount, and address).
    - a global game struct in `server.c`, to store the state of the game. It's members include the following:
        -  a main grid struct
        -  an original grid struct that remains for reference, it contains no gold piles or players
        - an array of pointers to player structs 
        - an integer storing the current number of players that have joined
        - an integer storing the amount of gold remaining 
        - an integer storing the number of gold piles spawned on the main grid
    - a global client struct in `player.c`
        - A struct `client` that is similar to `game` but stores the host port number, host name, address struct, number of gridRows, number of gridCols, the player's unique display grid, gold remaining in the game, the goldCount for the client's purse, the temporary gold received each time a player collects gold, the client's X and Y location, their playername, and their letter.


## Control flow (server)

The Nuggets game is implemented in a program `server.c` and joined by players or spectators in a complementary program `player.c` (this is the client program).

### Global Variables (server)
Nuggets will have one global variable in `server.c`, a `game` struct which will store the main grid, original grid, array of pointers to player structs, number of players that have joined so far, amount of gold remaining, and the number of gold piles spawned onto the main grid.
```c
static struct game {
    grid_t* mainGrid;
    grid_t* origGrid;
    player_t** playerArray;
    int currPlayers;
    int goldRem;
    int numPiles;
} game;

```


### Global Constants
We will have several global constants for the game. 

`const int MaxNameLength = 50; ` 
`const int MaxPlayers = 26;`
`const int GoldTotal = 250;`  
`const int GoldMinNumPiles = 10;`
`const int GoldMaxNumPiles = 30;`

### ***Server***

### main
The main initializes the game struct members, calls`parseArgs`,`initializeGame`, initializes the logging module (`log_init`), initializes the message module (`message_init`), calls `message_loop`, terminates the message module (`message_done`), terminates the log module (`log_done`), deletes the malloced members of the game struct (each player, the player array, origGrid, and mainGrid), then exits 0.
Note: the output of the logging module is sent to a file named "log" created in main, while the output of the message module is sent to stderr.


### parseArgs
Validates command-line arguments. Verifies that either 1 or 2 arguments were received. For the mapFile, checks if it is the pathname of a file that can be read (we assume it's a valid map). For the optional seed parameter, we check if the seed is a valid integer and if it is a positive integer. If the seed is not provided, its value is unchanged and remains -1 (as it was initialized to in main). If any errors are encountered, print a relevant error message and exit nonzero.


Pseudocode:

    validate that either one or two arguments were received;
    create filepointer to mapFile;
    open the mapFile for reading;
    if unssuccessful, print error message and return non-zero exit status;
    close the fp;
    if seed received, 
        convert it to an integer;
        if seed is a negative integer
            print error message and return non-zero exit status;
    


### initializeGame 
Prepares the initial state of the game by 1) callibrating the random number generator (with a seed if provided), 2) loads teh map from the mapFile into the game grid structs (both origGrid and mainGrid), 3) spawns gold piles on mainGrid only. If any errors are encountered, prints relevant error message and exits non-zero.

Pseudocode:

    if seed exists
        call srand(seed) to generate the random sequence
    if the seed does not exist
        call srand(getpid()) 
    find dimensions of map from mapFile
    load the mapFile into mainGrid
    load the mapFile into origGrid
    spawn gold piles on mainGrid only


### message_loop
Given function that provides a continuous loop detecting input from stdin or on the network. We will not be using the timeout feature and will pass 0 for the timeout parameter and NULL for the handleTimeout handler function. We will also pass NULL to the handleInput handler function, as it will be implemented in player.c. We will also pass NULL to the arg parameter as all the relevant game information is stored in the gobal `game` struct. The server will implement a `handleMessage` function that will parse the received message and call appropriate helper functions.

### handleMessage
Helper function to handle messages received by `message_loop`. Parses the received message and calls the appropriate helper function to handle it, depending on the type of message received which is determined by the first word of the message. If a KEY message is received, calls`getPlayer` helper function to get the player struct associated with the address that sent the message (this is needed as a parameter in handleKey()). Each helper function will update the global game struct to reflect the new state of the game and send OK, DISPLAY, GRID, GOLD, and QUIT messages when appropriate. Each helper function, and by consequence `handleMessage`, will return true if all gold is collected meaning the game is over and`message_loop` should exit, and false otherwise. If a malformatted message is received, the server sends an ERROR message to the client, logs an error, and ignores the message.


Pseudocode:

    validate address
    check that gold remaining is not 0
    if message starts with PLAY
        call handlePlay
        if handlePlay returns true
            return true
    else if message starts with SPECTATE
        call getPlayer to get player struct associated with the address of the message sender
        call handleSpectate
        if handleSpectate returns true
            return true
    else if message starts with KEY
        call handleKey
        if handleKey returns true
            return true
    else if message malformatted
        send ERROR message to client
        log an error
        ignore the message
    return false
        
#### getPlayer
Helper function to return player struct associated with a given address, taken as a parameter. Returns this player struct if a match is found, returns NULL otherwise.

Pseudocode:

    loop through array of players
        call playerGetAddress to get the player address
        if player address and given address are equal (use message_eqAddr to compare addresses)
            return player struct
    return NULL
        

#### handlePlay
Helper function to handle PLAY messages, indicating a player wants to join the game. Takes a message string as a parameter. If there are already `MaxPlayers` players, sends the client a QUIT message indicating the game is full, and does not add that player. If the player's real name is empty, sends the client a QUIT message indicating this error. Otherwise, adds the player to the game by creating a new player struct and adding it to the array of players held in the global `game` struct. Formats `real name` by deleting characters after `MaxNameLength` characters and replacing with an underscore `_` any character for which both `isgraph()` and `isblank()` are false, and stores it in the player struct. Sends OK, DISPLAY, GRID, and GOLD messages to client.

Pseudocode:

    if there are already maxPlayers
        send client QUIT message
        return false
    else
        if the player's name is empty
            send client QUIT message
            return false
        if the player's name consists of only spaced
            send client QUIT message
            return false
        format realName
        generate new player's letter
        generate new player's random location
        create a new player struct with all this information
        add this new player struct to the playerArray at index currPlayers
        call sendOk
        call sendDisplay
        call sendGrid
        call sendGold
        increment currPlayers
        return false
    
#### handleSpectate
Helper function to handle SPECTATE messages, indicating a spectator wants to join the game. Takes spectator's address as a parameter. If there is already a specator, sends a QUIT message to the prior spectator and forgets it by deleting its struct. Creates a new spectator as a specialized player struct and adds it to the playerArray at the last index. Sends DISPLAY, GRID, and GOLD messages to spectator. Returns false.

Pseudocode:

    If spectator already exists
        send QUIT message to that spectator
        forget that prior spectator by deleting struct
    create a new spectator as a specialized player struct
    add this struct to the playerArray at index MaxPlayers
    send DISPLAY message to new spectator
    send GRID message to new spectator
    send GOLD message to new spectator
    return false


#### handleKey
Helper function to handle KEY messages, indicating a player has pressed a key. Takes a player struct and the message as parameters. Updates the global `game` struct according to how the keystroke affects the game. When a spectator quits, their struct is deleted from the playerArray. When a player quits, their letter is removed from the grid, but their struct is NOT deleted because their information will still be included in the end of game summary. When a keystroke causes a player to collect gold, sends GOLD message to that client, as well as a GOLD message to all other clients. When a keystroke causes a player to move, sends DISPLAY message to all clients. This function implements the sprinting versus stepping functionality by checking for a capital letter key. This function also handles player collisions, when a player's move causes it to step on another player, by swapping these two players's locations in this event. Returns true if all gold is picked up and game is over, returns false otherwise.

Pseudocode:
    
    if q
        if spectator
            send QUIT message
            delete struct
        if player
            send QUIT message
            remove player from grid
            send new display to all players
    else if upper case move key
        if spectator
            send error message
            return false
        while playerUpdateLocation is true
            move player
            if collision occurs
                swap player locations
            update grid
            if all gold collected
                call endGame()
                return true
            send display message to all players
            
    else if lower case move key
        if spectator
            send error message
            return false
        if playerUpdateLocation returns true
            move player
            if collision occurs
                swap player locations
            update grid
            if all gold collected
                call endGame()
                return true
            send display message to all
    else, its a malformatted message
        send an error
        log an error
    return false
        
#### sendOk
Helper function to send OK message to player once they are added to the game. Takes the player struct as input, constructs an OK message in the format "OK playerLetter", and calls `message_send` to send the message.

Pseudocode:

    get player address from player struct
    get player letter from player struct
    construct OK message using player letter
    call message_send using player address and constructed OK message as parameters
    

#### sendGrid
Helper function to send GRID message in the format "GRID nrown ncols". Takes player struct as a parameter.

Pseudocode:

    call grid_getNR to get number of rows
    call grid_getNC to get number of columns
    get address of player 
    construct a GRID message string (GRID nrows ncols)
    call message_send using player address and GRID message string as parameters
    
    
#### sendGold
Helper function to send GOLD message in the format "GOLD n p r" (where n is gold just collected by player, p is players total purse, r is gold remaining). It takes a boolean value as a parameter to indicate whether or not the player has just picked up gold and a player struct. Returns true if no gold remaining, indicating that message_loop should exit and the game should end. Returns false otherwise.

Pseudocode:

    if bool true
        generate random number to represent amount of gold collected
        save that number as n
        call playerIncrementGold using the player struct and n as parameters
        decrement the remaining gold member of the global game struct by n
        if remaining gold <= 0
            return true
    else
        n = 0;
            
    save remaining gold value as int r
    call playerGetGold to get purse, save it as int p
    construct GOLD message string (GOLD n p r)
    call message_send using the players address and the constructed GOLD message as parameters
    return false
        


    
#### sendDisplay
Helper function to send DISPLAY message in the format "DISPLAY\nstring" (where string is that players visible map). Takes a player struct as a parameter to have access to that player's address and visible map through the playerGetVisibility() function. 

Pseudocode:
    
    get player's address
    get player's visible map string by calling playerGetVisibility
    construct DISPLAY message (DISPLAY\nvisibleMapString)
    call message_send using player's address and DISPLAY message as parameters
    


### endGame()
Helper function to create and send the final quit message once game is over. An example of a formatted error message is given in the function header comment in `server.c`. This function includes two loops, one to calculate how many lines the message will be (based on the number of structs in the playerArray) in order to allocate enough memory for the message string, and a second loop to fill that string. The function then send the message to each player and frees this message string.

Pseudocode:

    initialize a numLines counter to 0
    loop through playerArray
        if a spot is not null, increment the numLines counter
    create the message string and allocate enough memory based on the number of the final numLines count
    loop through playerArray
        if a spot contains a player struct
            extract its letter, gold count, and realNmae
            add this info to the message string
    loop through playerArray
        send message to each player
    free message string

### nameDelete()
Itemfunc to use in player_delete(). Checks that the given name is not NULL, then frees it. This function should only be passed to player_delete() if a player is being deleted and should NOT be used when a spectator is being deleted (because no name string was malloced when creating the specialized spectator struct).

Pseudocode:

    if name is not NULL
        free name

### Control Flow (client)

### Global Variables
```c
static struct {
    char hostPort[maxPortSize];
    char hostName[maxHostSize];
    char visGrid[maxGridSize];
    char playerName[maxPlayerSize];
    char letter;
    addr_t server;
    int numRows;
    int numCols;
    int goldLeft;
    int purse;
    int goldReceived;
} client;

```

### Global Constants
`#define maxPortSize (5 + 1)            // 16-bit 0 to 65535 (5 chararacters)`
`#define maxHostSize (253 + 1)          // 253 ASCII characters`
`#define maxPlayerSize (65507 - 6 - 1)  // message_maxBytes - strlen("PLAY ") + 1`
`#define maxGridSize (65507 - 10 - 1)   // from ReqSpec: "NR x NC + 10 < message_MaxBytes."`

### ***Player***

### main
The `main` function initializes the logging module, and then calls `parseArgs`, `initializeNetwork`, `message_loop`, and `message_done`. Finally, it closes the logging module.


### parseArgs
Validates command-line arguments. Verifies that either two or three arguments were received (after ./player). Load hostname and port with first and second arguments. If third argument exists, set playername equal to it. If not, set playername for a spectator to null terminating character. If any issues, print message to stderr and exit nonzero.
Note: use strcpy() to set client char arrays with char*s.

Pseudocode:

    constant char pointer for program name for first argument for printing usage errors
    if number of args is not two or three,
        print usage message to stderr and exit nonzero
    else,
        set client.hostName to first arugment
        set client.hostPort to second arugment
        if number of args is 3,
            set client.playerName to third argument
        else,
            set client.playerName to '\0'
            
### initializeNetwork
Function to initialize the network components of the client struct and let server know if we are a Player or Spectator. If any trouble while trying to initialize network, print error message to stderr and exit nonzero.

Pseudocode:
    
    initialize the message module
    check that it worked, if not,
        print error and exit nonzero
    set &client.address with given hostName and hostPort
        if we join as a SPECTATOR,
            construct "PLAY playername" message
            send PLAY message
            initialize PLAY letter to 0
        else,
            print bad hostname/port error and exit nonzero

### message_loop
Given function that continually loops detecting input from player or on the network. We will not be using the timeout feature and will pass 0 for the timeout parameter and NULL for the handleTimeout handler function. However, unlike `server.c`, we will implement a `handleInput` handler function, which will read keyboard input (key presses) and call message_send to send a standardized message to the server (ex: “[playerAddress] inputted [key]”) for interpretation. Similarly to `server.c`, we will implement a `handleMessage` handler function, which will receive messages from the server and call helper functions to update our client's struct based on specific message prompts. We pass in NULL to the arg parameter because all the information and variables we need are stored and accessible via the client struct global variable.


### handleMessage
Helper function for `message_loop`, `handleMessage` will take a cursory glance at the message and call the appropriate helper function to handle it, depending on the type of message received which is determined by the first word of the message. For example, the server could send a `grid` message that client will need to display. Each helper function will update the global client struct to reflect the new state of the game. Each helper function will return true if `message_loop` should exit (e.g. if a fatal error occurs) and false otherwise. If a malformatted message is received from the server, the client prints the ERROR for the user, logs an error, and ignores the message.

Pseudocode:

    if client.server is not a valid address,
        log error
        return true
    if `from` is not the same address as client.server,
        log error
        return true
    if message starts with GOLD
        call handleGold
        if handleGold returns true
            return true
    else if message starts with GRID
        call handleGrid
        if handleGrid returns true
            return true
    else if message starts with DISPLAY
        call handleDisplay
        if handleDisplay returns true
            return true
    else if message starts with OK
        call handleOK
        if handleOK return true
            return true
    else if message starts with QUIT
        call handleQuit
        if handleQuit returns true
            return true
    else if message start with ERROR
        call handleError
        if handleError returns true
            return true
    else if message malformatted
        log the error
        ignore the message
    call update_display
    return false
        
#### handleGold
Helper function for `handleMessage` to deal with the server sending the client gold information. Does so by updating the global constant struct client's goldCount. A gold message is in the following format (GOLD n r p) where n is the amount of gold collected, p is the amount of gold in that player's purse, and r is in amount of gold remaining in the game.

Pseudocode:

    using sscanf on the message with format "GOLD %i %i %i",
        set client.goldReceived to first int
        set client.purse to second int
        set client.goldLeft to third int
    if sscanf did not successfully match each of the message parameters (its return value is not three),
        send ERROR message to server
        log error
        ignore the message
    else,
        return false

#### handleGrid
Helper function for `handleMessage` to deal with the server sending the client grid information. Does so by updating the global constant struct client's number of rows and number of columns. A grid message is in the following format (GRID nrows ncols).

Pseudocode:

    using sscanf on the message with the format "GRID %i %i",
        set client->numRows equal to first int
        set client->numCols equal to second int
    if sscanf did not successfully match each of the message parameters (its return value is not two),
        send ERROR message to server
        log error
        ignore the message
    else,
        call intialize_display()
        return false
    
#### initializeDisplay
Void helper function that calls the necessary ncurses functions to initialize the screen and all that is needed is an additional function `updateDisplay` to update the display for the player. Should only be called once when we first receive the GRID message.

Pseudocode:

    initialize the screen with initscr()
    accept keystrokes immediately with cbreak()
    don't echo characters to the screen with noecho()
    cache window size with getmaxyx(stdscr, int dimY, int dimX)
    while the screen is not large enough,
        prompt to resize with mvprintw and say to press enter once resized
        block until they press enter
        reset the window dimensions with getmaxyx()
    set colors
    
    

#### handleDisplay
Helper function for `handleMessage` to deal with the server sending the client a grid display. Does so by updating the global constant struct client's gridDisplay, calling updateDisplay, and then printing the visGrid string to the screen after the status display. A display message is in the following format (DISPLAY\nvisibleMapString).

Pseudocode:

    set client.visGrid equal to content
    updateDisplay to print display status line at the top
    print the actual visible grid on the second row (right below display status line)
    refresh the screen
    return false
    
#### updateDisplay
Void helper function used to update the display status line based off of received GOLD and GRID messages. Handle spectator and players differently as well as whether or not a piece of gold has just been stepped on or an error message has just been received. Use mvprintw and then refresh() to repaint the display status line.

Pseudocode:
    
    set cursor to 0,0
    clear line
    if spectator,
        print special displays status line for spectator
        refresh
    else player,
        if player letter has been set with OK message,
            if they did not just step on gold,
                print status line without new gold
            else,
                print status line with new gold
                reset goldReceived
            refresh

#### handleOk
Helper function for `handleMessage` to deal with the server sending the client an ok message with their letter. Does so by setting the global constant struct client's letter. An ok message is in the following format (OK L). Note: This presence or absence of this letter can then be used anywhere else to check if the player has been added to the game. 

Pseudocode:

    using sscanf on the message with the format "OK %c",
        set client->letter equal to the character^
    if sscanf did not successfully match the message parameter (its return value is not one),
        send ERROR message to server
        log error
        return true
    return false

#### handleQuit
Helper function for `handleMessage` to deal with the server sending the client a quit message followed by an explanation. Does so by printing the explantion followed by a newline, and returning true to break out of message_loop.

Pseudocode:
    
    exit curses
    print the explanation followed by a newline
    exit message_loop and the program (return true)
    
#### handleError
Helper function for `handleMessage` to deal with the server sending the client an error message followed by an explanation. Does so by presenting the explanation to the user of client on the display's status line.

Pseudocode:

    show the 'explanation' to the end of the display status line
    log the error
    return false

### handleInput
Helper function for `message_loop`, `handleInput` will take a cursory glance at keystroke input (single key presses) and send pressed keys to the server with a call to `message_send`. If a key is not recognized, print "unknown keystroke" to the display status line. For a player, valid keystrokes are `Q`, `h`, `l`, `j`, `k`, `y`, `u`, `b`, `n` (see requirements spec for what each key does). The corresponding Capitalized character for each of valid keystrokes just listed are also valid. For the spectator, all they can type is `Q`. We return true if any fatal errors occur or we want to break out of message_loop, else we return false to continue looping over stdin. Note: we assume that we are reading stdin in "character-oriented mode" 

Pseudocode:

    if client.server is not a valid address,
        log error
        return true
    read once from stdin into char
    if char is not EOF,
        create buffer for length of message
        add space for char and null char
        actually build the message
        call message_send with message
    else,
        call message_send with KEY Q
    return false
    
### message_done
Given function to shut down message module. For more information see message.h.

## Other modules

### game 

We create a game struct to store the main grid, an original grid that remains for reference, the array of players, and keep track of the amount of gold remaining. We will have one global variable of type `game_t`.

### client

We create a global client struct called `client` to store and update the information that is specific to each client, including the host port number, host name, host address, number of grid rows, number of grid columns, the player's unique display grid, gold remaining in the game, the gold count for the client's purse, the temporary gold received each time a player collects gold, the clients x location, the client's y location, their playername, and their letter.

### grid

We create a module `grid.c` to handle loading the map into the grid structure. The grid structure holds a 2D array of characters to represent the grid and an integer variable for the number of rows and two integer values to store the number of rows and columns. See `grid.h` for more in depth information on each function.

*See function prototypes in prototypes section below.*

Pseudocode for `grid_load`:

	check if grid is valid
    if it is not 
        return false
    if it is 
        allocate memory for gridarray and its components
        iterate through the map string and fill values of gridarray with characters
        return true
        
Pseudocode for `grid_loadEmptyGrid`:

    check if grid and parameters are valid
    if it is not 
        return false
    if it is 
        allocate memory for gridarray and its components
        for the number of rows
            allocate memory of length NC for string
            fill it with empty chars
        return true
    
Pseudocode for `grid_distribGold`:

	go to a certain number of random spots in grid (more than min parameter and less than max)
        add gold character there 
        return true if successful
    return false if not
    
Pseudocode for `grid_updateGrid`:

	Get players current location from player struct
    Remove their character from that current location 
    Go to the x and y position passed in parameter
    Check if there would be a collision with checkCollision
    If no collision
        put player character in that spot 
    If there is a collision
        call handleCollision function
        
Pseudocode for `grid_addPlayer`:

	validate parameters
        if invalid return false
    check if desired spot is a room
        if it is, add player char to (x,y) coords
        return true
    if it is not
        return false
        
Pseudocode for `grid_removePlayer`:

	validate parameters
        if invalid return false
    set spot in grid equal to spot in original grid
    return true
        
Pseudocode for `grid_pickUpGold`:

	go to x and y position defined in parameters
    if there is gold there
        remove the gold character from that position
        return true
    return false

Pseudocode for `grid_print`:

    iterate through the grid 
        print each string
    
Pseudocode for `grid_delete`:

    iterate through the grid 
        free each item
    free the grid
    
Rest of the funcitons are getters, just returns values.
    
### server-player

player holds x,y coordinates, name, port number
revealed map string variable, given a player what is their revealed map. Be a struct variable for player module.

We create a `player.c` module to hold information about each client who connects as a player/spectator.
`playerUpdateLocation` 
`playerIncrementGold` 
`playerGetVisibility` 
`playerGetLocation` 
`playerGetGold`
    
Initialization: 

    When a player is created, it's location is set to a random location on the map, it's gold is set to zero, and `revealed` initializes all gridpoints to false

Pseudocode `playerUpdateLocation`:

    read direction code (character inputted by player)
    check if can move in that direction
    if yes:
        update location (if lowercase, move one space. If uppercase, move as far as possible)
        return true
    if couldn't move, return false

Pseudocode for `playerIncrementGold`:

    increase gold count by inputted amount 

Pseudocode for `playerGetVisibility`: 

    create a new grid_t struct `tempMap` that is composed of empty spaces
    for each gridpoint `target` of the game's `map`:
        calculate slope from player's location 
        starting from the player, scan each gridpoint roughly on the line drawn 
            if a point along the way is a wall: 
                if the `target` point in `revealed` is false, do nothing (the point is already invisible)
                if the `target` point in `revealed` is true:
                    if the `target` point in `map` is a goldPoint or other play, convert it to a normal floor character in `tempMap`
            if no points along the way are a wall, set the corresponding `target` point on`tempMap` to the character of `map`
                if a `target` point became visible for the first time, set its corresponding point in `revealed` to true
    return `tempMap`
    convert `tempMap` to string 
    free(tempMap)
    send out string
        
    

Other methods are getters and setters


## Function prototypes

### server

Detailed descriptions of each function's interface is provided as a paragraph comment prior to each function's implementation in `server.c` and is not repeated here.

```c
typedef struct game_t* game;
int main(const int argc, char* argv[]);
static void parseArgs(const int argc, char* argv[],
                      char** mapFile, int* seed);
static void initializeGame(char* mapFile, int seed);
int message_init(FILE* logFP);
bool message_loop(void* arg, const float timeout,
                  bool (*handleTimeout)(void* arg),
                  bool (*handleInput)  (void* arg),
                  bool (*handleMessage)(void* arg,
                                        const addr_t from, 
                                        const char* message));
static bool handleMessage(void* arg, const addr_t from, const char* message);
static player_t* getPlayer(addr_t address);
static bool handlePlay(const char* message);
static bool handleSpectate(const addr_t from);
static bool handleKey(player_t* player, const char* message);
static bool sendGold(player_t* player, bool gotGold);
static void sendGrid(player_t* player);
static void sendDisplay(player_t* player);
static void sendOk(player_t* player);
void message_send(const addr_t to, const char* message);
void message_done(void);
```

### player

Detailed descriptions of each function's interface is provided as a paragraph comment prior to each function's implementation in `player.c` and is not repeated here.
```c
struct client;
int main(const int argc, char* argv[]);
static void parseArgs(const int argc, char* argv[]);
static void initializeNetwork();
bool message_loop(void* arg, const float timeout,
                  bool (*handleTimeout)(void* arg),
                  bool (*handleInput)  (void* arg),
                  bool (*handleMessage)(void* arg,
                                        const addr_t from, 
                                        const char* message));
static bool handleMessage(void* arg, const addr_t from, const char* message);
static bool handleGold(const char* content);
static bool handleGrid(const char* content);
static void initializeDisplay();
static bool handleDisplay(const char* content);
static void updateDisplay(const char* explanation);
static bool handleOk(const char* content);
static bool handleQuit(const char* content);
static bool handleError(const char* content);
static bool handleInput(void* arg);
```

### grid
Detailed descriptions of each function's interface is provided as a paragraph comment prior to each function's declaration in `grid.h` and is not repeated here.

```c
grid_t* grid_new(void);
bool grid_load(grid_t* grid, char* map, int NR, int NC);
bool grid_loadEmptyGrid(grid_t* grid, int NR, int NC);
int grid_distribGold(grid_t* grid, const int GoldMinNumPiles, const int GoldMaxNumPiles);
bool grid_addPlayer(grid_t* grid, char playerID, int x, int y);
bool grid_removePlayer(grid_t* grid, grid_t* origGrid, char playerID, int x, int y);
bool grid_updateGrid(grid_t* grid, grid_t* origGrid, int px, int py, char playerID, int x, int y);
void grid_print(FILE* fp, grid_t* grid);
void grid_delete(grid_t* grid);
char** grid_getGrid(grid_t* grid);
int grid_getNC(grid_t* grid);
int grid_getNR(grid_t* grid);
```
### server-player
```c 
player_t* player_new(bool spectator, addr_t add, char letter, char* playerName, int r, int c, grid_t* grid);
void player_delete(player_t* player, grid_t* grid, void(*itemdelete)(void* item));
bool playerUpdateLocation(player_t* player, grid_t* grid, char key);
void playerSetLocation(player_t* player, int r, int c);
void playerIncrementGold(player_t* player, int amount);
char* playerGetVisibility(player_t* player, grid_t* grid, grid_t* origGrid);
int playerGetR(player_t* player)
int playerGetC(player_t* player)
int playerGetGold(player_t* player)
addr_t playerGetAddress(player_t* player)
char playerGetLetter(player_t* player)
char* playerGetFullName(player_t* player)
void playerPrintLocation(player_t* player)
```

## Error handling and recovery

All the command-line parameters are rigorously checked before any data structures are allocated or work begins; problems result in a message printed to stderr and a non-zero exit status.

Out-of-memory errors are checked for and result in a message printed to stderr and a non-zero exit status.
We anticipate out-of-memory errors to be rare and thus allow the program to crash (cleanly) in this way.

All code uses defensive-programming tactics to catch and exit, e.g., if a function receives bad parameters.


## Testing plan

Here is an implementation-specific testing plan.

### Unit testing

There are four units (server, client, grid, player).

The server represents the whole game and is covered below. The client is relatively small and enables players or spectators to connect and interact with the game. 

We use `gridtest.c` to test the grid module. The gridtest will test the grid load function by loading a map of into the module, then testing functions such as the distributeGold and updateGrid function. After each test the function will use the gridprint method to print the grid to check if the tests were successful or not. Then gridtest will delete the grid.

### Integration/system testing

We write a script `testing.sh` that invokes the server and client several times, with a variety of command-line arguments with various erroneous arguments, testing each of the possible mistakes that can be made.
Verify correct behavior by studying the output.
See `testing.md` for more information.

For further testing we will write a "human script" or instructions on how to launch different kinds of games. This will be the main method of testing, playing the game and seeing if it functions correctly. 


- For testing, we plan on breaking down the unit testing based on our above plan for the division of work
    - Claire will use`gridtest.c` to test her grid module (*see above*)
    - Camden will use `playertest.c` to test his players module
    - Giorgie and Nick will work together to use a bash script `networktest.sh` to test the server and client programs
    - For the integration testing, we will do that together as a team in a meeting once our unit tests all check out
    - For the system test, Giorgie will create a simple bash script to test server with various invalid arguments and Nick will createa a similar bash script to test client with various invalid arguments