giorgiemccombe
    • Create new note
    • Create a note from template
      • Sharing URL Link copied
      • /edit
      • View mode
        • Edit mode
        • View mode
        • Book mode
        • Slide mode
        Edit mode View mode Book mode Slide mode
      • Customize slides
      • Note Permission
      • Read
        • Only me
        • Signed-in users
        • Everyone
        Only me Signed-in users Everyone
      • Write
        • Only me
        • Signed-in users
        • Everyone
        Only me Signed-in users Everyone
      • Engagement control Commenting, Suggest edit, Emoji Reply
    • Invite by email
      Invitee

      This note has no invitees

    • Publish Note

      Share your work with the world Congratulations! 🎉 Your note is out in the world Publish Note

      Your note will be visible on your profile and discoverable by anyone.
      Your note is now live.
      This note is visible on your profile and discoverable online.
      Everyone on the web can find and read all notes of this public team.
      See published notes
      Unpublish note
      Please check the box to agree to the Community Guidelines.
      View profile
    • Commenting
      Permission
      Disabled Forbidden Owners Signed-in users Everyone
    • Enable
    • Permission
      • Forbidden
      • Owners
      • Signed-in users
      • Everyone
    • Suggest edit
      Permission
      Disabled Forbidden Owners Signed-in users Everyone
    • Enable
    • Permission
      • Forbidden
      • Owners
      • Signed-in users
    • Emoji Reply
    • Enable
    • Versions and GitHub Sync
    • Note settings
    • Note Insights New
    • Engagement control
    • Make a copy
    • Transfer ownership
    • Delete this note
    • Save as template
    • Insert from template
    • Import from
      • Dropbox
      • Google Drive
      • Gist
      • Clipboard
    • Export to
      • Dropbox
      • Google Drive
      • Gist
    • Download
      • Markdown
      • HTML
      • Raw HTML
Menu Note settings Note Insights Versions and GitHub Sync Sharing URL Create Help
Create Create new note Create a note from template
Menu
Options
Engagement control Make a copy Transfer ownership Delete this note
Import from
Dropbox Google Drive Gist Clipboard
Export to
Dropbox Google Drive Gist
Download
Markdown HTML Raw HTML
Back
Sharing URL Link copied
/edit
View mode
  • Edit mode
  • View mode
  • Book mode
  • Slide mode
Edit mode View mode Book mode Slide mode
Customize slides
Note Permission
Read
Only me
  • Only me
  • Signed-in users
  • Everyone
Only me Signed-in users Everyone
Write
Only me
  • Only me
  • Signed-in users
  • Everyone
Only me Signed-in users Everyone
Engagement control Commenting, Suggest edit, Emoji Reply
  • Invite by email
    Invitee

    This note has no invitees

  • Publish Note

    Share your work with the world Congratulations! 🎉 Your note is out in the world Publish Note

    Your note will be visible on your profile and discoverable by anyone.
    Your note is now live.
    This note is visible on your profile and discoverable online.
    Everyone on the web can find and read all notes of this public team.
    See published notes
    Unpublish note
    Please check the box to agree to the Community Guidelines.
    View profile
    Engagement control
    Commenting
    Permission
    Disabled Forbidden Owners Signed-in users Everyone
    Enable
    Permission
    • Forbidden
    • Owners
    • Signed-in users
    • Everyone
    Suggest edit
    Permission
    Disabled Forbidden Owners Signed-in users Everyone
    Enable
    Permission
    • Forbidden
    • Owners
    • Signed-in users
    Emoji Reply
    Enable
    Import from Dropbox Google Drive Gist Clipboard
       Owned this note    Owned this note      
    Published Linked with GitHub
    • Any changes
      Be notified of any changes
    • Mention me
      Be notified of mention me
    • Unsubscribe
    # 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

    Import from clipboard

    Paste your markdown or webpage here...

    Advanced permission required

    Your current role can only read. Ask the system administrator to acquire write and comment permission.

    This team is disabled

    Sorry, this team is disabled. You can't edit this note.

    This note is locked

    Sorry, only owner can edit this note.

    Reach the limit

    Sorry, you've reached the max length this note can be.
    Please reduce the content or divide it to more notes, thank you!

    Import from Gist

    Import from Snippet

    or

    Export to Snippet

    Are you sure?

    Do you really want to delete this note?
    All users will lose their connection.

    Create a note from template

    Create a note from template

    Oops...
    This template has been removed or transferred.
    Upgrade
    All
    • All
    • Team
    No template.

    Create a template

    Upgrade

    Delete template

    Do you really want to delete this template?
    Turn this template into a regular note and keep its content, versions, and comments.

    This page need refresh

    You have an incompatible client version.
    Refresh to update.
    New version available!
    See releases notes here
    Refresh to enjoy new features.
    Your user state has changed.
    Refresh to load new user state.

    Sign in

    Forgot password

    or

    By clicking below, you agree to our terms of service.

    Sign in via Facebook Sign in via Twitter Sign in via GitHub Sign in via Dropbox Sign in with Wallet
    Wallet ( )
    Connect another wallet

    New to HackMD? Sign up

    Help

    • English
    • 中文
    • Français
    • Deutsch
    • 日本語
    • Español
    • Català
    • Ελληνικά
    • Português
    • italiano
    • Türkçe
    • Русский
    • Nederlands
    • hrvatski jezik
    • język polski
    • Українська
    • हिन्दी
    • svenska
    • Esperanto
    • dansk

    Documents

    Help & Tutorial

    How to use Book mode

    Slide Example

    API Docs

    Edit in VSCode

    Install browser extension

    Contacts

    Feedback

    Discord

    Send us email

    Resources

    Releases

    Pricing

    Blog

    Policy

    Terms

    Privacy

    Cheatsheet

    Syntax Example Reference
    # Header Header 基本排版
    - Unordered List
    • Unordered List
    1. Ordered List
    1. Ordered List
    - [ ] Todo List
    • Todo List
    > Blockquote
    Blockquote
    **Bold font** Bold font
    *Italics font* Italics font
    ~~Strikethrough~~ Strikethrough
    19^th^ 19th
    H~2~O H2O
    ++Inserted text++ Inserted text
    ==Marked text== Marked text
    [link text](https:// "title") Link
    ![image alt](https:// "title") Image
    `Code` Code 在筆記中貼入程式碼
    ```javascript
    var i = 0;
    ```
    var i = 0;
    :smile: :smile: Emoji list
    {%youtube youtube_id %} Externals
    $L^aT_eX$ LaTeX
    :::info
    This is a alert area.
    :::

    This is a alert area.

    Versions and GitHub Sync
    Get Full History Access

    • Edit version name
    • Delete

    revision author avatar     named on  

    More Less

    Note content is identical to the latest version.
    Compare
      Choose a version
      No search result
      Version not found
    Sign in to link this note to GitHub
    Learn more
    This note is not linked with GitHub
     

    Feedback

    Submission failed, please try again

    Thanks for your support.

    On a scale of 0-10, how likely is it that you would recommend HackMD to your friends, family or business associates?

    Please give us some advice and help us improve HackMD.

     

    Thanks for your feedback

    Remove version name

    Do you want to remove this version name and description?

    Transfer ownership

    Transfer to
      Warning: is a public team. If you transfer note to this team, everyone on the web can find and read this note.

        Link with GitHub

        Please authorize HackMD on GitHub
        • Please sign in to GitHub and install the HackMD app on your GitHub repo.
        • HackMD links with GitHub through a GitHub App. You can choose which repo to install our App.
        Learn more  Sign in to GitHub

        Push the note to GitHub Push to GitHub Pull a file from GitHub

          Authorize again
         

        Choose which file to push to

        Select repo
        Refresh Authorize more repos
        Select branch
        Select file
        Select branch
        Choose version(s) to push
        • Save a new version and push
        • Choose from existing versions
        Include title and tags
        Available push count

        Pull from GitHub

         
        File from GitHub
        File from HackMD

        GitHub Link Settings

        File linked

        Linked by
        File path
        Last synced branch
        Available push count

        Danger Zone

        Unlink
        You will no longer receive notification when GitHub file changes after unlink.

        Syncing

        Push failed

        Push successfully