diff --git a/.gitignore b/.gitignore index 36f971e..dc0fe94 100644 --- a/.gitignore +++ b/.gitignore @@ -1 +1,2 @@ bin/* +*.swp diff --git a/Makefile b/Makefile index 4230caa..c590eed 100644 --- a/Makefile +++ b/Makefile @@ -1,2 +1,3 @@ azool: + mkdir -p bin g++ src/*.cc -I./include -o bin/azool -Werror -Weffc++ -std=c++11 diff --git a/include/GameBoard.h b/include/GameBoard.h index 41b6114..af85a2e 100644 --- a/include/GameBoard.h +++ b/include/GameBoard.h @@ -4,6 +4,7 @@ #include #include #include +#include #include "tile_utils.h" class GameBoard { @@ -22,6 +23,8 @@ public: bool takeTilesFromPool(azool::TileColor color, int& numTiles, bool& poolPenalty); void returnTilesToBag(int numTiles, azool::TileColor color); void dealTiles(); + void handleRequest(std::stringstream); + boost::property_tree::ptree serializeBoard() const; int numFactories() { return tileFactories.size(); } @@ -39,6 +42,7 @@ private: // - vector of factories? std::vector tileFactories; int maxNumFactories; + int myNumPlayers; int pool[azool::NUMCOLORS]; // stores the count of each color currently in the pool; initialize to 0s bool whiteTileInPool; // initialize to true std::vector tileBag; // initialize to 20 of each color diff --git a/include/Player.h b/include/Player.h index 78ba517..b8b4ba6 100644 --- a/include/Player.h +++ b/include/Player.h @@ -25,6 +25,7 @@ public: const std::string getPlayerName() const { return myName; } + void sendRequest(/*string or stringstream?*/); private: Player(const Player&) = delete; diff --git a/include/tile_utils.h b/include/tile_utils.h index 58a749d..905fb1a 100644 --- a/include/tile_utils.h +++ b/include/tile_utils.h @@ -19,5 +19,11 @@ const std::string TileColorStrings[NUMCOLORS] = { }; const char TileColorSyms[NUMCOLORS] = { 'r', 'b', 'g', 'y', 'k' }; +const int MAXPLAYERS = 4; + +const std::string REQ_TYPE_DRAW_FROM_FACTORY = "DRAW_FROM_FACTORY"; +const std::string REQ_TYPE_DRAW_FROM_POOL = "DRAW_FROM_POOL"; +const std::string REQ_TYPE_RETURN_TO_BAG = "RETURN_TO_BAG"; +const std::string REQ_TYPE_GET_BOARD = "GET_BOARD"; } #endif // TILE_UTILS_H_ diff --git a/src/GameBoard.cc b/src/GameBoard.cc index ad4dab0..0e42c60 100644 --- a/src/GameBoard.cc +++ b/src/GameBoard.cc @@ -1,9 +1,14 @@ #include "GameBoard.h" #include #include +#include +#include + +namespace pt = boost::property_tree; GameBoard::GameBoard(int numPlayers) : tileFactories(), + myNumPlayers(numPlayers), maxNumFactories(numPlayers*2+1), pool(), whiteTileInPool(true), @@ -40,6 +45,7 @@ std::ostream& operator<<(std::ostream& out, const GameBoard& board) { bool GameBoard::validFactoryRequest(int factoryIdx, azool::TileColor color) { // check if color exists on specified factory bool retVal = factoryIdx < tileFactories.size() and + factoryIdx > -1 and tileFactories[factoryIdx].tileCounts[color] > 0; return retVal; } @@ -72,12 +78,12 @@ bool GameBoard::takeTilesFromPool(azool::TileColor color, int& numTiles, bool& p poolPenalty = whiteTileInPool; whiteTileInPool = false; return true; -} +} // GameBoard::takeTilesFromPool void GameBoard::returnTilesToBag(int numTiles, azool::TileColor color) { for (int ii = 0; ii < numTiles; ++ii) { tileBag.emplace_back(color); } -} +} // GameBoard::returnTilesToBag // random shuffle then read from the beginning of the vector? void GameBoard::dealTiles() { @@ -102,6 +108,91 @@ void GameBoard::dealTiles() { } } // GameBoard::dealTiles +pt::ptree GameBoard::serializeBoard() const { + pt::ptree outTree; + // factories + pt::ptree factTree; + int factCt = 1; + for (auto factory : tileFactories) { + std::stringstream factSS; + for (int ii = 0; ii < azool::NUMCOLORS; ++ii) { + for (int jj = 0; jj < factory.tileCounts[ii]; ++jj) { + factSS << azool::TileColorStrings[ii] << ","; + } + } + factTree.put(std::to_string(factCt), factSS.str()); + factCt++; + } + outTree.add_child("factories", factTree); + outTree.put("num_factories", tileFactories.size()); + // pool + pt::ptree poolTree; + for (int ii = 0; ii < azool::NUMCOLORS; ++ii) { + poolTree.put(azool::TileColorStrings[ii], pool[ii]); + } + if (whiteTileInPool) { + poolTree.put("penalty", -1); + } + else { + poolTree.put("penalty", 0); + } + outTree.add_child("pool", poolTree); + outTree.put("end_of_round", endOfRound()); + return outTree; +} // GameBoard::serializeBoard + +void GameBoard::handleRequest(std::stringstream iss) { + pt::ptree inTree; + pt::read_json(iss, inTree); + pt::ptree outTree; + std::string req_type = inTree.get("req_type"); + // check type of request; check that required parameters are present; etc + // return: json with results, status, error msg if any + if (req_type.compare(azool::REQ_TYPE_DRAW_FROM_FACTORY) == 0) { + int idx = inTree.get("factory_idx", -1); + int numTiles = 0; + azool::TileColor color = static_cast(inTree.get("tile_color")); + bool success = takeTilesFromFactory(idx, color, numTiles); + outTree.put("status", success ? "success" : "fail"); + outTree.put("success", success); + outTree.put("num_tiles_returned", numTiles); + if (!success) { + outTree.put("error_msg", "INVALID FACTORY REQUEST"); + } + } + else if (req_type.compare(azool::REQ_TYPE_DRAW_FROM_POOL) == 0) { + azool::TileColor color = static_cast(inTree.get("tile_color")); + int numTiles = 0; + bool penalty = false; + bool success = takeTilesFromPool(color, numTiles, penalty); + outTree.put("success", success); + outTree.put("status", success ? "success" : "fail"); + outTree.put("num_tiles_returned", numTiles); + outTree.put("pool_penalty", penalty); + if (!success) { + outTree.put("error_msg", "INVALID POOL REQUEST"); + } + } + else if (req_type.compare(azool::REQ_TYPE_RETURN_TO_BAG) == 0) { + int numTiles = inTree.get("num_tiles_returned", 0); + azool::TileColor color = static_cast(inTree.get("tile_color")); + returnTilesToBag(numTiles, color); + outTree.put("success", true); // no reason for this to fail + outTree.put("status", "success"); + } + else if (req_type.compare(azool::REQ_TYPE_GET_BOARD) == 0) { + outTree = serializeBoard(); + } + else { + // ERROR, BAD THINGS + outTree.put("error_msg", "INVALID REQUEST TYPE"); + } + outTree.put("req_type", req_type); // include request type in returned data + std::stringstream oss; + pt::write_json(oss, outTree); + // send oss over socket +} // GameBoard::handleRequest + void GameBoard::resetBoard() { memset(pool, 0, azool::NUMCOLORS*sizeof(int)); tileBag.clear(); diff --git a/src/Player.cc b/src/Player.cc index 93ee31a..3c267eb 100644 --- a/src/Player.cc +++ b/src/Player.cc @@ -41,7 +41,14 @@ bool Player::checkValidMove(azool::TileColor color, int rowIdx) const { } // Player::checkValidMove bool Player::takeTilesFromFactory(int factoryIdx, azool::TileColor color, int rowIdx) { - // call game board -> takeTiles(factoryIdx, color) + // pt::ptree request; + // request.put("req_type", azool::REQ_TYPE_DRAW_FROM_POOL); + // request.put("tile_color", color); + // request.put("factory_idx", factoryIdx); + // std::stringstream oss; + // pt::write_json(request, oss); + // send request to board + // recieve response int numTiles = 0; if (checkValidMove(color, rowIdx) and myBoardPtr->takeTilesFromFactory(factoryIdx, color, numTiles)) { @@ -58,6 +65,16 @@ bool Player::takeTilesFromPool(azool::TileColor color, int rowIdx) { if (!checkValidMove(color, rowIdx)) { return false; } + // pt::ptree request; + // request.put("req_type", azool::REQ_TYPE_DRAW_FROM_POOL); + // request.put("tile_color", color); + // std::stringstream oss; + // pt::write_json(request, oss); + // send request to board + // recieve response + // bool success = inTree.get("success"); + // int numTiles = inTree.get("num_tiles_returned"); + // bool poolPenalty = inTree.get("pool_penalty"); if (!myBoardPtr->takeTilesFromPool(color, numTiles, poolPenalty)) { return false; // couldn't get that tile from the pool } @@ -98,6 +115,11 @@ void Player::endRound(bool& fullRow) { myGrid[rowIdx][col] = true; myScore += scoreTile(rowIdx, col); // return extra tiles -- rowIdx = the number of leftover tiles + // pt::ptree request; + // request.put("req_type", azool::REQ_TYPE_RETURN_TO_BAG); + // request.put("num_tiles_returned", rowIdx); + // request.put("tile_color", myRows[rowIdx].second); + // send request to gameboard myBoardPtr->returnTilesToBag(rowIdx, myRows[rowIdx].second); // reset rows for next turn myRows[rowIdx].first = 0; @@ -235,6 +257,8 @@ void Player::finalizeScore() { } // Player::finalizeScore std::string Player::printMyBoard() const { + // pt::ptree request; + // request.put("req_type", REQ_TYPE_GET_BOARD); std::ostringstream oss; oss << "*******************************\n"; oss << "PLAYER: " << myName << "\n"; @@ -275,6 +299,17 @@ std::string Player::printMyBoard() const { bool Player::discardFromFactory(int factoryIdx, azool::TileColor color) { int numTiles = -1; + // pt::ptree request; + // request.put("req_type", azool::REQ_TYPE_DRAW_FROM_FACTORY); + // request.put("factory_idx", factoryIdx); + // request.put("tile_color", color); + // std::stringstream oss; + // pt::write_json(request, oss); + // send request to board + // recieve response + // bool success = inTree.get("success"); + // int numTiles = inTree.get("num_tiles_returned"); + // if (success) myNumPenaltiesForRound += numTiles; if (myBoardPtr->takeTilesFromFactory(factoryIdx, color, numTiles)) { myNumPenaltiesForRound += numTiles; return true; @@ -283,6 +318,16 @@ bool Player::discardFromFactory(int factoryIdx, azool::TileColor color) { } // Player::discardFromFactory bool Player::discardFromPool(azool::TileColor color) { + // pt::ptree request; + // request.put("req_type", azool::REQ_TYPE_DRAW_FROM_POOL); + // request.put("tile_color", color); + // std::stringstream oss; + // pt::write_json(request, oss); + // send request to board + // recieve response + // bool success = inTree.get("success"); + // int numTiles = inTree.get("num_tiles_returned"); + // bool poolPenalty = inTree.get("pool_penalty"); bool poolPenalty = false; int numTiles = -1; if (myBoardPtr->takeTilesFromPool(color, numTiles, poolPenalty)) { @@ -296,13 +341,13 @@ bool Player::discardFromPool(azool::TileColor color) { } // Player::discardFromPool namespace { -int promptForFactoryIdx(int maxNumFactories) { +int promptForFactoryIdx(int maxFactIdx) { static const char* promptFactoryIdxDraw = "Which factory? enter index\n"; char factInput; // TODO can we safely say there will never be more than 9 possible? std::cout << promptFactoryIdxDraw << std::flush; std::cin >> factInput; int factIdx = std::atoi(&factInput); - if (factIdx < 1 or factIdx > maxNumFactories) { + if (factIdx < 1 or factIdx > maxFactIdx) { return -1; } return factIdx; @@ -348,6 +393,11 @@ int promptForRow() { void Player::takeTurn() { // print game board, handle user input + // pt::ptree request; + // request.put("req_type", REQ_TYPE_GET_BOARD); + // bool endOfRound = inTree.get("end_of_round"); + // // max idx for input - users use 1-indexing + // int maxFactIdx = inTree.get("num_factories"); if (myBoardPtr->endOfRound()) return; std::cout << printMyBoard(); static const char* promptDrawInput = "What would you like to do?\n" diff --git a/src/main.cc b/src/main.cc index ac3ca5c..970c8ff 100644 --- a/src/main.cc +++ b/src/main.cc @@ -26,7 +26,7 @@ void playGame(GameBoard* game) { secondPlayer->takeTurn(); } // check who took penalty - // nees to be done before claling player->endRound() + // needs to be done before claling player->endRound() if (players[0]->tookPenalty()) { firstPlayer = players[0]; secondPlayer = players[1];