# Intermediate Programming Final Project

## Darius Irani (dirani2), Clara Liff (cliff2), Andrew Hellinger (ahellin1)

It was fun creating the final project. We hope you enjoy playing it. NOTE: This README is formatted in Markdown - the file is not
README.md because Gradescope would not accept this filename. You can view the formatted version of this file by adding the '.md'
extension. :)


## main

This file is repsonsible for initializing a new SkipBoGame or loading a saved game. The main method expects command line arguments; if
the number of arguments are anything besides 2 or 4 (valid arguments for loading or initializing a game, respectively), main will output
an error.

If the number of provided command line arguments are correct, this method will check the validity of each individual argument, assigning
their value to variables if they are valid. It begins with the `shuffle` argument - if the user input anything besides `true` or `false`,
main will print an error - otherwise, main will set the `shuffle` variable to be equal to what the user specified.

If the user input 4 arguments, they likely intended to initialize a new game. The method then checks the validity of the number of players
and stock size that the user entered, storing the numbers in `numPlayers` and `stockSize` respectively if they are valid. The program then
tries to open the specified deck - if it can't, it throws an error. Otherwise, the program initializes a game using the provided file.

If the user input 2 arguments, they likely intended to load a saved game. The method then tries to open the specified save file, throwing
an error if opening the file was unsuccessful. If successful, the method will initialize the game according to the save game data.


## SkipBoGame

SkipBoGame is a class which handles most of the higher-level operations that are required during the Skip Bo game. You can construct it by
specifying whether the draw pile needs to be shuffled and the number of players, or by specifying whether the deck needs to be shuffled,
number of players, and number of cards in the stock pile. It holds variables to store whether the draw pile should be shuffled, the draw
pile, an array of four build piles, a pile of completed build piles, a vector of players, and integers to track the number of players and
the current player. The class contains many functions to help process gameplay functionality, all of which are described in more detail
below.

### display()

This function displays draw and build piles and current player information.

### toString()

This function stores whether deck is shuffled, number of players, and current player into stringstream. The function then iterates over
players and inserts their string representations into the stringstream. finally, the function inserts information about draw pile into the
stringstream.

### readIn()

This function reads game data in from a save data file.

### saveGame()

This function writes game data to a save data file.

### dealCards()

If starting a new game, this function deals out cards one at a time to fill each player's stock piles.

### reDeck()

This function re-inserts cards into the draw pile, reshuffling the draw pile if in shuffle mode.

### fillHand()

This function fills the current player's hand with the specified number of cards.

### initializeGame()

This function performs the necessary operations to begin a new skipbo game. If the game is in shuffle mode, this function randomly
determine which player goes first (modulus operator allows us to wrap around array of players). We then assign a name to and construct
each player, then add them to the array of players. After all players have been created, we call the dealCards() function to fill the
hands of each player.

### addCardBackToStart()

This function adds a given card back to start pile if an invalid move is attempted. If the card was taken from the stock pile, add it back
there. If the card was taken from a discard pile, add it back there. If the card was taken from a player's hand, add it back there. If
none of these are the case, then the start command is invalid and we throw an error.

### holdOut()

This function sets aside full build piles by adding them to the completed_builds pile.

### startPile()

This function gets a card from the specified start pile. if the start pile is the stock pile, remove top card from there. If the player is
trying to take a card from the discard pile, first check whether the specified discard pile is empty - if it is empty, throw error.
Otherwise, remove the top card from specified discard pile. If the player is trying to take a card from their hand, remove card at that
position from their hand. If the start index is invalid, throw error.

### endPile()

This function tries to add card to specified end pile, and returns an integer to represent whether the player's turn is over. The function
first creates a map to easily convert from char to integer. If the user is trying to put a card in discard pile, first check whether the
card is originating from the stock pile - if so, throw an error. Otherwise, add the card to the specified discard pile and set stop to 1
to represent the end of player's turn.

If the player is trying to put card in build pile, first determine the value of the top build pile card, and verify that the card can be
validly added to the top of this build pile. If it can, add the card to the build pile. If the build pile is full after this addition,
call holdOut to remove the build pile.

If the end index is not valid, throw an error.

### moveCard()

This function moves a card from a start to an end pile. First, the function gets the integer value of input char. Then, the function tries
to get the card from the start pile and insert it onto the endpile. The function will catch an out_of_range exception which represents
invalid input by the user. The function also catches custom message exception. Finally, the function returns whether the player's turn is
over (if they discarded).

### playerMove()

This function runs until the player validly discards a card, allowing each player to complete their move. Outputs message to user and
stores their response, determines whether to move or discard based on first char of response. The program then tries to execute player's
requested move - if player wants to move a card, first check if response is missing start and end details - if so, throw error. If player
wants to discard, first check whether their hand is empty - if it is, draw more cards for the player. If first char of the player's
response is not 'm' or 'd,' it is invalid - throw an exception. At the end, return whether the player's turn is over.

### gameStatus()

This function asks the player if they would like to continue playing, taking appropriate action based on their response. If the player
would like to continue playing, end the loop, since no further action needs to be taken. If the player would like to save the game, prompt
the user for save file and then call `saveGame()` on the specified filename. If the player would like to quit, print a goodbye message and
end the program by throwing exception.

### playerTurn()

This function manages each player's turn, calling other helper functions to complete the necessary actions. If the current player's hand
is less than 5, fill their hand. Until the player discards, display current game status to player and call `playerMove()`. After each
move, check if the player's stock size is empty - if so, declare the current player as the winner and end the game. After the player's
turn is over, display current game status again.

### playGame

This function manages the entire game, keeping track of current player and calling helper functions to complete gameplay functionality.
The function first prints details about which player's turn is next, and asks player whether they would like to continue the game, calling
`gameStatus()` to manage whether the player would like to play, save, or quit. After the player's turn, the function increments the
current player, using modulus to wrap around the array to the first player if necessary. The function will catch any errors thrown by
`playerTurn()` or `gameStatus` and return to main.


## Card

This class stores data for each Card. Each card has an int value ranging from 0 to 12 inclusive. The class has a few functions detailed
below.

### getValue()

This function gets the value of the specified card.

### toString()

This function returns a string representation of the card for printing and saving.

### display()

This function displays information about the card value for live gameplay.



## DrawPile

This class stores data for the draw pile. Its constructor takes a boolean argument which represents whether the deck should be shuffled.
It also has an empty constructor which sets the deck to not be shuffled by default. The class has a few functions detailed below.

### size()

This function returns the current size of the DrawPile.

### addCard()

This function adds a card to the back of the deck.

### toString()

This function returns a string representation of the card for printing and saving.

### display()

This function displays information about the draw pile for live gameplay.

### getRand()

This function returns whether the deck is in shuffle mode.

### getTopCard()

This function returns and removes the top card of the draw pile.

### shufflePile()

This function shuffles the draw pile.

### addCompletedBuildPiles()

This function adds any completed build piles back to the bottom of the draw pile.


## FaceUpPile

This class represents the discard and stock piles for each player. Its constructor takes no arguments, allowing an empty pile to be built
initially. This class has multiple functions which are described below.

### size()

This function returns the current size of the FaceUpPile.

### addCard()

This function adds a card to the top of the FaceUpPile.

### toString()

This function returns a string representation of the FaceUpPile for printing and saving.

### display()

This function displays information about the FaceUpPile for live gameplay.

### getTopCard()

This function removes and returns the top card for the FaceUpPile.

### getFront()

This function removes and returns the bottom card of the FaceUpPile.

### resetPile()

This function clears all cards from the FaceUpPile.


## Hand

This class represents a player's hand. Its constructor takes no arguments, allowing an empty hand to be built. It has multiple methods,
detailed below.

### size()

This function returns the current size of the Hand.

### display()

This function displays information about the Hand for live gameplay.

### toString()

This function returns a string representation of the Hand for printing and saving.

### addCard()

This function adds a card to the Hand.

### getCard()

This function gets the card at the specified index.

### addCardAt()

This function adds a card at the specified index.


## Pile 

This class represents a pile of cards generically. This has an empty constructor which allows an empty Pile to be constructed. This class
has multiple functions which are detailed below.

### size()

This function returns the current number of Cards in the Pile.

### addCard()

This function adds a Card to the top of the Pile.

### toString()

This function returns a string representation of the Pile for printing and saving.

### readIn()

This function reads in Pile data from saved game data.

### readInFresh()

This function reads in Pile data from a starter file (for new games).

### display()

This function displays information about the Pile for live gameplay.


## Player

This class represents a Player and their associated data. The constructor requires a string to store as the player name. The class stores
data about the Player's name, stock pile, discard piles, and hand. The class has multiple functions, detailed below.

### readIn()

This function reads in save data for the Player. It first reads the Player's stock pile, then hand, then discard, calling appropriate
readIn() functions for each.

### toString()

This function returns a string representation of the Player for printing and saving.

### display()

This function displays information about the Player for live gameplay.

### addToHand()

This function adds the specified card to the Player's hand.

### addToDiscard()

This function adds the specified card to the Player's specified discard pile.

### addToStock()

This function adds the specified card to the Player's stock pile.

### getHand()

This getter function returns the Player's hand.

### getStock()

This getter function returns the Player's stock pile.

### getDiscard()

This getter function returns the array of the Player's discard piles. 