From cfcd99b0db8dd905ec02dc5ffb86b3fef5f875b1 Mon Sep 17 00:00:00 2001 From: eay Date: Mon, 28 Aug 2023 08:05:30 -0700 Subject: [PATCH] use json serialization everywhere (staged for adding socket functionality) --- Makefile | 5 +- include/GameBoard.h | 6 +- include/Player.h | 2 + src/GameBoard.cc | 9 ++- src/Player.cc | 170 ++++++++++++++++++++++++++------------------ src/main.cc | 2 +- 6 files changed, 115 insertions(+), 79 deletions(-) diff --git a/Makefile b/Makefile index c590eed..4f920a2 100644 --- a/Makefile +++ b/Makefile @@ -1,3 +1,6 @@ azool: mkdir -p bin - g++ src/*.cc -I./include -o bin/azool -Werror -Weffc++ -std=c++11 + g++ src/*.cc -I./include -o bin/azool -Werror -Weffc++ -std=c++11 -DBOOST_ALLOW_DEPRECATED_HEADERS -DBOOST_BIND_GLOBAL_PLACEHOLDERS + +clean: + rm bin/* diff --git a/include/GameBoard.h b/include/GameBoard.h index af85a2e..491d67d 100644 --- a/include/GameBoard.h +++ b/include/GameBoard.h @@ -18,17 +18,17 @@ public: GameBoard(int nPlayers=2); friend std::ostream& operator<<(std::ostream& out, const GameBoard& board); - bool validFactoryRequest(int factoryIdx, azool::TileColor color); + bool validFactoryRequest(int factoryIdx, azool::TileColor color) const; bool takeTilesFromFactory(int factoryIdx, azool::TileColor color, int& numTiles); bool takeTilesFromPool(azool::TileColor color, int& numTiles, bool& poolPenalty); void returnTilesToBag(int numTiles, azool::TileColor color); void dealTiles(); - void handleRequest(std::stringstream); + std::string handleRequest(const std::string&); boost::property_tree::ptree serializeBoard() const; int numFactories() { return tileFactories.size(); } - bool endOfRound() { + bool endOfRound() const { // round ends when the pool and tile factories are empty for (int ii = 0; ii < azool::NUMCOLORS; ++ii) { if (pool[ii] > 0) return false; diff --git a/include/Player.h b/include/Player.h index b8b4ba6..29eaaad 100644 --- a/include/Player.h +++ b/include/Player.h @@ -15,6 +15,7 @@ public: void placeTiles(int rowIdx, azool::TileColor color, int numTiles); void endRound(bool& fullRow); void finalizeScore(); + std::string sendRequest(const std::string&); int getScore() const { return myScore; } @@ -22,6 +23,7 @@ public: bool tookPenalty() const { return myTookPoolPenaltyThisRound; } + int getScorePenalty() const; const std::string getPlayerName() const { return myName; } diff --git a/src/GameBoard.cc b/src/GameBoard.cc index 0e42c60..9b3185c 100644 --- a/src/GameBoard.cc +++ b/src/GameBoard.cc @@ -42,7 +42,7 @@ std::ostream& operator<<(std::ostream& out, const GameBoard& board) { return out; } -bool GameBoard::validFactoryRequest(int factoryIdx, azool::TileColor color) { +bool GameBoard::validFactoryRequest(int factoryIdx, azool::TileColor color) const { // check if color exists on specified factory bool retVal = factoryIdx < tileFactories.size() and factoryIdx > -1 and @@ -141,7 +141,8 @@ pt::ptree GameBoard::serializeBoard() const { return outTree; } // GameBoard::serializeBoard -void GameBoard::handleRequest(std::stringstream iss) { +std::string GameBoard::handleRequest(const std::string& instring) { + std::stringstream iss(instring); pt::ptree inTree; pt::read_json(iss, inTree); pt::ptree outTree; @@ -190,7 +191,9 @@ void GameBoard::handleRequest(std::stringstream iss) { outTree.put("req_type", req_type); // include request type in returned data std::stringstream oss; pt::write_json(oss, outTree); - // send oss over socket + std::string output = oss.str(); + return output; + // send output string over socket } // GameBoard::handleRequest void GameBoard::resetBoard() { diff --git a/src/Player.cc b/src/Player.cc index 3c267eb..452c402 100644 --- a/src/Player.cc +++ b/src/Player.cc @@ -2,6 +2,8 @@ #include #include #include +#include +namespace pt = boost::property_tree; Player::Player(GameBoard* const board, std::string name) : myGrid(), @@ -41,17 +43,24 @@ bool Player::checkValidMove(azool::TileColor color, int rowIdx) const { } // Player::checkValidMove bool Player::takeTilesFromFactory(int factoryIdx, azool::TileColor color, int rowIdx) { - // 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)) { + // checkValidMove first - can't undo request to boardptr + if (!checkValidMove(color, rowIdx)) { + return false; + } + pt::ptree request; + request.put("req_type", azool::REQ_TYPE_DRAW_FROM_FACTORY); + request.put("tile_color", color); + request.put("factory_idx", factoryIdx); + std::stringstream oss; + pt::write_json(oss, request); + // send request to board, recieve response + std::stringstream iss(sendRequest(oss.str())); + pt::ptree response; + pt::read_json(iss, response); + // std::cout << iss.str() << std::endl; + bool success = response.get("success", false); + int numTiles = response.get("num_tiles_returned", 0); + if (success) { placeTiles(rowIdx, color, numTiles); return true; } @@ -60,22 +69,22 @@ bool Player::takeTilesFromFactory(int factoryIdx, azool::TileColor color, int ro bool Player::takeTilesFromPool(azool::TileColor color, int rowIdx) { // call game board -> takeTilesFromPool - int numTiles = 0; - bool poolPenalty = false; 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)) { + pt::ptree request; + request.put("req_type", azool::REQ_TYPE_DRAW_FROM_POOL); + request.put("tile_color", color); + std::stringstream oss; + pt::write_json(oss, request); + // send request to board, recieve response + std::stringstream iss(sendRequest(oss.str())); + pt::ptree response; + pt::read_json(iss, response); + bool success = response.get("success", false); + int numTiles = response.get("num_tiles_returned", 0); + bool poolPenalty = response.get("pool_penalty", false); + if (!success) { return false; // couldn't get that tile from the pool } if (poolPenalty) { @@ -115,23 +124,22 @@ 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); + 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); + std::stringstream oss; + pt::write_json(oss, request); + // send request to gameboard...don't care abt response here (?) + sendRequest(oss.str()); + // myBoardPtr->returnTilesToBag(rowIdx, myRows[rowIdx].second); // reset rows for next turn myRows[rowIdx].first = 0; myRows[rowIdx].second = azool::NONE; } } - if (myNumPenaltiesForRound >= PenaltyPoints.size()) { - myScore -= PenaltyPoints[PenaltyPoints.size() - 1]; - } - else { - myScore -= PenaltyPoints[myNumPenaltiesForRound]; - } + myScore -= getScorePenalty(); + myScore = std::max(myScore, 0); // let's not allow negatives // reset for next turn // FOR THIS REASON // main loop needs to check who took penalty BEFORE calling this function @@ -156,6 +164,12 @@ void Player::endRound(bool& fullRow) { } // iter over rows in grid } // Player::endRound +int Player::getScorePenalty() const { + if (myNumPenaltiesForRound >= PenaltyPoints.size()) { + return PenaltyPoints[PenaltyPoints.size() - 1]; + } + return PenaltyPoints[myNumPenaltiesForRound]; +} int Player::scoreTile(int tileRow, int tileCol) { // search horizontally and vertically for points int tileScore = 1; @@ -258,7 +272,7 @@ void Player::finalizeScore() { std::string Player::printMyBoard() const { // pt::ptree request; - // request.put("req_type", REQ_TYPE_GET_BOARD); + // request.put("req_type", azool::REQ_TYPE_GET_BOARD); std::ostringstream oss; oss << "*******************************\n"; oss << "PLAYER: " << myName << "\n"; @@ -293,24 +307,25 @@ std::string Player::printMyBoard() const { } // iterate over rows oss << "Penalties: " << myNumPenaltiesForRound << "\n"; oss << "Score: " << myScore << "\n"; + oss << "-------------------------------\n"; return oss.str(); // TODO(feature) - print penalty tiles (?) } // Player::printMyBoard 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)) { + 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(oss, request); + // send request to board, recieve response + std::stringstream iss(sendRequest(oss.str())); + pt::ptree response; + pt::read_json(iss, response); + bool success = response.get("success", false); + int numTiles = response.get("num_tiles_returned", 0); + if (success) { myNumPenaltiesForRound += numTiles; return true; } @@ -318,19 +333,19 @@ 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)) { + pt::ptree request; + request.put("req_type", azool::REQ_TYPE_DRAW_FROM_POOL); + request.put("tile_color", color); + std::stringstream oss; + pt::write_json(oss, request); + // send request to board, recieve response + std::stringstream iss(sendRequest(oss.str())); + pt::ptree response; + pt::read_json(iss, response); + bool success = response.get("success", false); + int numTiles = response.get("num_tiles_returned", 0); + bool poolPenalty = response.get("pool_penalty", false); + if (success) { if (poolPenalty) { myNumPenaltiesForRound++; } @@ -340,6 +355,12 @@ bool Player::discardFromPool(azool::TileColor color) { return false; } // Player::discardFromPool +std::string Player::sendRequest(const std::string& inStr) { + // do the socket stuff here + std::string rxStr = myBoardPtr->handleRequest(inStr); + return rxStr; +} // Player::sendRequest + namespace { int promptForFactoryIdx(int maxFactIdx) { static const char* promptFactoryIdxDraw = "Which factory? enter index\n"; @@ -393,12 +414,19 @@ 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; + pt::ptree request; + request.put("req_type", azool::REQ_TYPE_GET_BOARD); + std::stringstream reqss; + pt::write_json(reqss, request); + // send request to board, recieve response + std::stringstream iss(sendRequest(reqss.str())); + pt::ptree response; + pt::read_json(iss, response); + bool endOfRound = response.get("end_of_round"); + // max idx for input - users use 1-indexing + int maxFactIdx = response.get("num_factories"); + if (endOfRound) return; + std::cout << *myBoardPtr << "\n\n"; std::cout << printMyBoard(); static const char* promptDrawInput = "What would you like to do?\n" "[f] take from factory " @@ -416,7 +444,7 @@ void Player::takeTurn() { char drawType; std::cin >> drawType; if (drawType == 'f') { - int factIdx = promptForFactoryIdx(myBoardPtr->numFactories()); + int factIdx = promptForFactoryIdx(maxFactIdx); // draw from factory if (factIdx == -1) { std::cout << invalidEntryMessage << std::flush; @@ -463,7 +491,7 @@ void Player::takeTurn() { char discardFrom = '\0'; std::cin >> discardFrom; if (discardFrom == 'f') { - int factIdx = promptForFactoryIdx(myBoardPtr->numFactories()); + int factIdx = promptForFactoryIdx(maxFactIdx); // draw from factory if (factIdx == -1) { std::cout << invalidEntryMessage << std::flush; diff --git a/src/main.cc b/src/main.cc index 970c8ff..4a3a992 100644 --- a/src/main.cc +++ b/src/main.cc @@ -26,7 +26,7 @@ void playGame(GameBoard* game) { secondPlayer->takeTurn(); } // check who took penalty - // needs to be done before claling player->endRound() + // needs to be done before calling player->endRound() if (players[0]->tookPenalty()) { firstPlayer = players[0]; secondPlayer = players[1];