---
# System prepended metadata

title: DESIGN.md
tags: [nuggets]

---

# CS50 Nuggets
## Design Spec
### Team XVI, Spring 2024


According to the [Requirements Spec](REQUIREMENTS.md), the Nuggets game requires two standalone programs: a client and a server.
Our design also includes map and visability modules.
We describe each program and module separately.
We do not describe the `support` library nor the modules that enable features that go beyond the spec.
We avoid repeating information that is provided in the requirements spec.

Division of labor:

Michael: Client-server interaction

Zach: Client

Dylan: Map 

Will: Visibility


## Client

The *client* acts in one of two modes:

 1. *spectator*, the passive spectator mode described in the requirements spec.
 2. *player*, the interactive game-playing mode described in the requirements spec.

### User interface

See the requirements spec for both the command-line and interactive UI.

The client will recieve their variation of a map in a string.
They process only messages recieved to the server, and do no calculations on their own.

Each player shall have their own map module, which stores visibility of both the rooms, and gold/players.

```
  one player might receive a map string that shows such:
  
  +----------+
  |....@...*.|               
  |..*.......############### 
  |.....*....|                 
  +---------#+                       
            #                       
            #  +-----------+         
            ####...........##### 
               |...........|
               +-----------+
   
  while another player might receive such:
  
                               +---------+
                    ############.........|
                               +-----#---+
                                     #
                                     #
            #  +-----------+         #
            ####....*......##############
               |.*......@..|
               +-----------+
```

The game can be joined through usage roughly as such:

```
$ ./client hostname port [playername]
```

specifying the program, the game, and the port.

### Inputs and outputs

The client recieves a single string containing their variation of the map. Its job is to parse the string and output to `stdout`. We output solely `keystrokes`, which must read instantaneously to the server. The client shall not display any visuals that have not been sent from the server.

### Functional decomposition into modules

We expect 4 primary functions in a server feedback loop:

* _validating arguments_
    * confirm user parameters are valid
* _initializing client_
    * check if server address is valid
    * send initial play or spectate messages to server
*  _handle input_
    * send a message `KEY k` to server
* _handle message_
    * a function which parses the message string recieved from server
    * utilize a suitable visualization library to refresh and display information

### Pseudo code for logic/algorithmic flow

    validate user parameters
    initialize a client-server connection
    
    distinguish between player and spectator
    
    try and communicate with server
        recieve an initial level of visibility from server
        
    get the resolution of the window to display the map
        hold until proper resolution is met
    
    continually check for keystrokes
        synchronous
    continually recieve strings from server
        synchronous
        display to stdout
        
    free and cleanup

### Major data structures

The client may benefit from a data structure to hold information of the _user_. Values such as `player name`, `gold status`, `representative letter`, etc. will be stored in the struct and passed between handling input and message. The client also recieves a string of characters derived from a  data structure of a _2D_ `array`. More information on cells in map module.

### Testing Plan

The client will largely handle the most preliminary edge cases, and the highest level "almost complete" testing. Ensuring users input the right seed, cannot join if there are too many players, etc. should all be tested first. 

When the game is nearing a finished state, fuzz testing of random players with random inputs, joining and leaving mid game, etc. should all be tested last.

---

## Server (Michael)
### User interface

See the requirements spec for the command-line interface.
There is no interaction with the user.


### Inputs and outputs

Inputs and outputs are handled through messages sent through a message module, which handles networking.

Optional logs can be written to `stdout` or a file.


### Functional decomposition into modules

We isolate map logic into the map module.
The server asks the map module to do map things
like trying to move players and building 
map strings for specific players.
The server knows which players are associated with
which addresses; the map module doesn't know anything about addresses.

### Pseudo code for logic/algorithmic flow


The server will run as follows:

	execute from a command line per the requirement spec
	parse the command line, validate parameters
	call initializeGame() to set up data structures
	initialize the 'message' module
	print the port number on which we wait
	call message_loop(), to await clients
	call gameOver() to inform all clients the game has ended
	clean up



`initializeGame`: set up the map

`message_loop`: relies on `messageHandler`

`messageHandler`: parses and validates the recieved message and calls the function corresponding to the message.
- if the command is KEY, it will validate the key as a move command or quit and call the correct function. It will not allow a server to call move.
- the individual functions called by messageHandler will decide what message to send back to the clients



### Major data structures

- Map, provided by map module

### Testing

We will use the sample client provided from CS50 instruction team to test the message handling.


---

## Map Module (Dylan)

This module will contain a map data structure manipulated by the server. The map is a 2D array of gridpoints, which are themselves a data structure that contains relevant information.

### Functional decomposition

`map_load` - initializes a map struct and loads in map data from map input

`map_distrbute_gold` - distributes gold across the map randomly

`map_add_player` - adds player to the map

`map_move` - attempts to move a player

`map_get_location` - returns the gridpoint at a certain location

`map_update_visibility` - updates the seen of gridpoints in the map

### Pseudo code for logic/algorithmic flow

Psuedocode for `map_load`

	array
	open file
	for i, line in file
		for j, char in line
			array[i][j] = new gridpoint with char

Pseudocode for `map_distribute_gold`

	gridpoint
        gridpoint is floor
            if(random = true)
                add gold to point
                    
Pseudocode of `map_update_visibility`

    for point in visibility:
        map[point.y][point.x]->seen.add(player)

### Major data structures


To store location information, we expect a new `gridpoint` data structure, which holds the initial map character, as provided, the player in the location, if any, the gold amount, if any, and players that have seen the gridpoint.

We also expext a new `map` data structure to store the global state of the game. This includes the static environment, such as the walls and tunnels, and also dynamic objects, such as players and gold. The map will allow for the movement of players, the collection of gold, and the getting of all map information.

The map information is stored in a 2 dimensional array of gridpoints, with coordinates in the array corresponding gridpoint, sized according to the dimensions of the inputted map. Player locations and gold locations and sizes are each stored in their own array

### Testing
The map module can be tested by loading a variety of maps.
For each map, the following should be tested for multiple random seeds:
* Loading gold
* Loading in players
* Moving players around
* Managing visibility to each player at each location
* Getting the location

By putting in specific inputs (such as loading two players next to each other and testing collision case), we can adequately test many cases. Additionally, using random seeds to find edge cases will allow us to identify edge cases.

---

## Visibility Module (Will)

This module will preform the necessary logic and calculations to determine the extent of the map that is visible to a user. It will recieve a map data structure containing gridpoints from the server, and for each 

### Functional decomposition

We expect two primary functions:

*getVisibility*, which calculates which gridpoints should be visible to a particular player. 

*clearVisibility*, which resets the gridpoints that are visible while retaining those that have been seen. 

### Pseudo code for logic/algorithmic flow


#### getVisibility

pseudocode:
    
    mark player's location as visible and seen
    iterate through each gridpt in the map
        get the horizontal distance from player to gridpt
        get the vertical distance from player to gridpt
        get the slope (dy/dx)
        iterate through each row between player and gridpt
            calculate the column (with decimals) from row
            if the this row is a gridpt (column is an integer)
                if the gridpt is a room, does not block visibility
                    mark as visible and keep moving
                otherwise, it is a wall or tunnel
                    mark as visible, but move to next tile
            otherwise, round down column and check both col and col +1
            if one or both are room spaces, not blocking visibility
                mark as visible and keep moving
            otherwise, this is a wall and is blocking visibility
                mark as visible, but move to next tile
                
        iterate through each column between player and gridpt
            calculate the row (with decimals) from column
            if the this column is a gridpt (row is an integer)
                 if the gridpt is a room, does not block visibility
                    mark as visible and keep moving
                otherwise, it is a wall or tunnel
                    mark as visible, but stop checking along this line
            otherwise, round down row and check both row and row +1
            if one or both are room spaces, not blocking visibility
                mark as visible and keep moving
            otherwise, this is a wall and is blocking visibility
                mark as visible, but move to next tile
        
        if we made it to here, then the gridpoint is visible!
        
 ### clearVisibility
 
     for each gridpoint in the map:
         if a gridpoint was visible, mark it as seen
         mark visibility as false
                
### Major data structures

We expect to employ a Gridpoint data structure, defined above, that contains the contents of a particular gridpoint in the map. This will contain the type of gridpoint, and will also document whether a point is visible and if it has already been seen.

We expect to map gridpoint visibility to each player via an array. Setting visibility to true or false will therefore involve getting the index corresponding to the player.

### Testing

We intend to test this module with a script that builds a small room and places a single player at predefined location. We will calculate the visibility and print the resulting map. We will step the player in one direction and recalculate the visibility. We will print the new visibility. Then we will print the tiles that have been seen. 

---

## System Testing

We will use the shell script created by the 
CS50 instruction team to test the system with random inputs.

We will also stress test by trying to have too many clients, reaching max number, killing clients and trying to rejoin.