Compare commits
5 Commits
master
...
dev/improv
Author | SHA1 | Date | |
---|---|---|---|
|
8d6935a0d3 | ||
|
cfcd99b0db | ||
|
4b80878d33 | ||
|
8736aee27c | ||
|
4404eb21e9 |
1
.gitignore
vendored
1
.gitignore
vendored
@ -1 +1,2 @@
|
|||||||
bin/*
|
bin/*
|
||||||
|
*.swp
|
||||||
|
6
Makefile
6
Makefile
@ -1,2 +1,6 @@
|
|||||||
azool:
|
azool:
|
||||||
g++ src/*.cc -I./include -o bin/azool -Werror -Weffc++ -std=c++11
|
mkdir -p bin
|
||||||
|
g++ src/*.cc -I./include -o bin/azool -Werror -Weffc++ -std=c++11 -DBOOST_ALLOW_DEPRECATED_HEADERS -DBOOST_BIND_GLOBAL_PLACEHOLDERS
|
||||||
|
|
||||||
|
clean:
|
||||||
|
rm bin/*
|
||||||
|
@ -4,6 +4,7 @@
|
|||||||
#include <ostream>
|
#include <ostream>
|
||||||
#include <cstring>
|
#include <cstring>
|
||||||
#include <random>
|
#include <random>
|
||||||
|
#include <boost/property_tree/ptree.hpp>
|
||||||
#include "tile_utils.h"
|
#include "tile_utils.h"
|
||||||
|
|
||||||
class GameBoard {
|
class GameBoard {
|
||||||
@ -17,13 +18,17 @@ public:
|
|||||||
|
|
||||||
GameBoard(int nPlayers=2);
|
GameBoard(int nPlayers=2);
|
||||||
friend std::ostream& operator<<(std::ostream& out, const GameBoard& board);
|
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 takeTilesFromFactory(int factoryIdx, azool::TileColor color, int& numTiles);
|
||||||
bool takeTilesFromPool(azool::TileColor color, int& numTiles, bool& poolPenalty);
|
bool takeTilesFromPool(azool::TileColor color, int& numTiles, bool& poolPenalty);
|
||||||
void returnTilesToBag(int numTiles, azool::TileColor color);
|
void returnTilesToBag(int numTiles, azool::TileColor color);
|
||||||
void dealTiles();
|
void dealTiles();
|
||||||
int numFactories() { return tileFactories.size(); }
|
std::string handleRequest(const std::string&);
|
||||||
bool endOfRound() {
|
boost::property_tree::ptree serializeBoard() const;
|
||||||
|
int numFactories() {
|
||||||
|
return tileFactories.size();
|
||||||
|
}
|
||||||
|
bool endOfRound() const {
|
||||||
// round ends when the pool and tile factories are empty
|
// round ends when the pool and tile factories are empty
|
||||||
for (int ii = 0; ii < azool::NUMCOLORS; ++ii) {
|
for (int ii = 0; ii < azool::NUMCOLORS; ++ii) {
|
||||||
if (pool[ii] > 0) return false;
|
if (pool[ii] > 0) return false;
|
||||||
@ -37,6 +42,7 @@ private:
|
|||||||
// - vector of factories?
|
// - vector of factories?
|
||||||
std::vector<Factory> tileFactories;
|
std::vector<Factory> tileFactories;
|
||||||
int maxNumFactories;
|
int maxNumFactories;
|
||||||
|
int myNumPlayers;
|
||||||
int pool[azool::NUMCOLORS]; // stores the count of each color currently in the pool; initialize to 0s
|
int pool[azool::NUMCOLORS]; // stores the count of each color currently in the pool; initialize to 0s
|
||||||
bool whiteTileInPool; // initialize to true
|
bool whiteTileInPool; // initialize to true
|
||||||
std::vector<azool::TileColor> tileBag; // initialize to 20 of each color
|
std::vector<azool::TileColor> tileBag; // initialize to 20 of each color
|
||||||
|
@ -15,10 +15,19 @@ public:
|
|||||||
void placeTiles(int rowIdx, azool::TileColor color, int numTiles);
|
void placeTiles(int rowIdx, azool::TileColor color, int numTiles);
|
||||||
void endRound(bool& fullRow);
|
void endRound(bool& fullRow);
|
||||||
void finalizeScore();
|
void finalizeScore();
|
||||||
int getScore() const { return myScore; }
|
std::string sendRequest(const std::string&);
|
||||||
|
int getScore() const {
|
||||||
|
return myScore;
|
||||||
|
}
|
||||||
std::string printMyBoard() const;
|
std::string printMyBoard() const;
|
||||||
bool tookPenalty() const { return myTookPoolPenaltyThisRound; }
|
bool tookPenalty() const {
|
||||||
const std::string getPlayerName() const { return myName; }
|
return myTookPoolPenaltyThisRound;
|
||||||
|
}
|
||||||
|
int getScorePenalty() const;
|
||||||
|
const std::string getPlayerName() const {
|
||||||
|
return myName;
|
||||||
|
}
|
||||||
|
void sendRequest(/*string or stringstream?*/);
|
||||||
|
|
||||||
private:
|
private:
|
||||||
Player(const Player&) = delete;
|
Player(const Player&) = delete;
|
||||||
|
@ -1,23 +1,29 @@
|
|||||||
#ifndef TILE_UTILS_H_
|
#ifndef TILE_UTILS_H_
|
||||||
#define TILE_UTILS_H_
|
#define TILE_UTILS_H_
|
||||||
namespace azool {
|
namespace azool {
|
||||||
enum TileColor {
|
enum TileColor {
|
||||||
NONE = -1,
|
NONE = -1,
|
||||||
RED = 0,
|
RED = 0,
|
||||||
BLUE,
|
BLUE,
|
||||||
GREEN,
|
GREEN,
|
||||||
YELLOW,
|
YELLOW,
|
||||||
BLACK,
|
WHITE,
|
||||||
NUMCOLORS
|
NUMCOLORS
|
||||||
};
|
};
|
||||||
const std::string TileColorStrings[NUMCOLORS] = {
|
const std::string TileColorStrings[NUMCOLORS] = {
|
||||||
"red",
|
"\x1B[1;41mR\x1B[0m",//"red",
|
||||||
"blue",
|
"\x1B[1;44mB\x1B[0m",//"blue",
|
||||||
"green",
|
"\x1B[1;42mG\x1B[0m",//"green",
|
||||||
"yellow",
|
"\x1B[1;30;103mY\x1B[0m",//"yellow",
|
||||||
"black"
|
"\x1B[1;30;107mW\x1B[0m",//"white"
|
||||||
};
|
};
|
||||||
|
|
||||||
const char TileColorSyms[NUMCOLORS] = { 'r', 'b', 'g', 'y', 'k' };
|
const char TileColorSyms[NUMCOLORS] = { 'r', 'b', 'g', 'y', 'w' };
|
||||||
|
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_
|
#endif // TILE_UTILS_H_
|
||||||
|
106
src/GameBoard.cc
106
src/GameBoard.cc
@ -1,18 +1,23 @@
|
|||||||
#include "GameBoard.h"
|
#include "GameBoard.h"
|
||||||
#include <algorithm>
|
#include <algorithm>
|
||||||
#include <chrono>
|
#include <chrono>
|
||||||
|
#include <boost/property_tree/json_parser.hpp>
|
||||||
|
#include <iostream>
|
||||||
|
|
||||||
|
namespace pt = boost::property_tree;
|
||||||
|
|
||||||
GameBoard::GameBoard(int numPlayers) :
|
GameBoard::GameBoard(int numPlayers) :
|
||||||
tileFactories(),
|
tileFactories(),
|
||||||
|
myNumPlayers(numPlayers),
|
||||||
maxNumFactories(numPlayers*2+1),
|
maxNumFactories(numPlayers*2+1),
|
||||||
pool(),
|
pool(),
|
||||||
whiteTileInPool(true),
|
whiteTileInPool(true),
|
||||||
tileBag(),
|
tileBag(),
|
||||||
lastRound(false),
|
lastRound(false),
|
||||||
rng(std::default_random_engine(
|
rng(std::default_random_engine(
|
||||||
std::chrono::system_clock::now().time_since_epoch().count())) {
|
std::chrono::system_clock::now().time_since_epoch().count())) {
|
||||||
resetBoard();
|
resetBoard();
|
||||||
} // GameBoard::GameBoard
|
} // GameBoard::GameBoard
|
||||||
|
|
||||||
std::ostream& operator<<(std::ostream& out, const GameBoard& board) {
|
std::ostream& operator<<(std::ostream& out, const GameBoard& board) {
|
||||||
// user will input 1-indexed value, even though we 0-index internally
|
// user will input 1-indexed value, even though we 0-index internally
|
||||||
@ -37,9 +42,10 @@ std::ostream& operator<<(std::ostream& out, const GameBoard& board) {
|
|||||||
return out;
|
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
|
// check if color exists on specified factory
|
||||||
bool retVal = factoryIdx < tileFactories.size() and
|
bool retVal = factoryIdx < tileFactories.size() and
|
||||||
|
factoryIdx > -1 and
|
||||||
tileFactories[factoryIdx].tileCounts[color] > 0;
|
tileFactories[factoryIdx].tileCounts[color] > 0;
|
||||||
return retVal;
|
return retVal;
|
||||||
}
|
}
|
||||||
@ -72,12 +78,12 @@ bool GameBoard::takeTilesFromPool(azool::TileColor color, int& numTiles, bool& p
|
|||||||
poolPenalty = whiteTileInPool;
|
poolPenalty = whiteTileInPool;
|
||||||
whiteTileInPool = false;
|
whiteTileInPool = false;
|
||||||
return true;
|
return true;
|
||||||
}
|
} // GameBoard::takeTilesFromPool
|
||||||
void GameBoard::returnTilesToBag(int numTiles, azool::TileColor color) {
|
void GameBoard::returnTilesToBag(int numTiles, azool::TileColor color) {
|
||||||
for (int ii = 0; ii < numTiles; ++ii) {
|
for (int ii = 0; ii < numTiles; ++ii) {
|
||||||
tileBag.emplace_back(color);
|
tileBag.emplace_back(color);
|
||||||
}
|
}
|
||||||
}
|
} // GameBoard::returnTilesToBag
|
||||||
|
|
||||||
// random shuffle then read from the beginning of the vector?
|
// random shuffle then read from the beginning of the vector?
|
||||||
void GameBoard::dealTiles() {
|
void GameBoard::dealTiles() {
|
||||||
@ -102,6 +108,94 @@ void GameBoard::dealTiles() {
|
|||||||
}
|
}
|
||||||
} // 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
|
||||||
|
|
||||||
|
std::string GameBoard::handleRequest(const std::string& instring) {
|
||||||
|
std::stringstream iss(instring);
|
||||||
|
pt::ptree inTree;
|
||||||
|
pt::read_json(iss, inTree);
|
||||||
|
pt::ptree outTree;
|
||||||
|
std::string req_type = inTree.get<std::string>("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<int>("factory_idx", -1);
|
||||||
|
int numTiles = 0;
|
||||||
|
azool::TileColor color = static_cast<azool::TileColor>(inTree.get<int>("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<azool::TileColor>(inTree.get<int>("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<int>("num_tiles_returned", 0);
|
||||||
|
azool::TileColor color = static_cast<azool::TileColor>(inTree.get<int>("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);
|
||||||
|
std::string output = oss.str();
|
||||||
|
return output;
|
||||||
|
// send output string over socket
|
||||||
|
} // GameBoard::handleRequest
|
||||||
|
|
||||||
void GameBoard::resetBoard() {
|
void GameBoard::resetBoard() {
|
||||||
memset(pool, 0, azool::NUMCOLORS*sizeof(int));
|
memset(pool, 0, azool::NUMCOLORS*sizeof(int));
|
||||||
tileBag.clear();
|
tileBag.clear();
|
||||||
|
242
src/Player.cc
242
src/Player.cc
@ -2,6 +2,8 @@
|
|||||||
#include <iostream>
|
#include <iostream>
|
||||||
#include <cstring>
|
#include <cstring>
|
||||||
#include <sstream>
|
#include <sstream>
|
||||||
|
#include <boost/property_tree/json_parser.hpp>
|
||||||
|
namespace pt = boost::property_tree;
|
||||||
|
|
||||||
Player::Player(GameBoard* const board, std::string name) :
|
Player::Player(GameBoard* const board, std::string name) :
|
||||||
myGrid(),
|
myGrid(),
|
||||||
@ -11,13 +13,13 @@ Player::Player(GameBoard* const board, std::string name) :
|
|||||||
myScore(0),
|
myScore(0),
|
||||||
myNumPenaltiesForRound(0),
|
myNumPenaltiesForRound(0),
|
||||||
myTookPoolPenaltyThisRound(false) {
|
myTookPoolPenaltyThisRound(false) {
|
||||||
int gridSize = azool::NUMCOLORS * azool::NUMCOLORS;
|
int gridSize = azool::NUMCOLORS * azool::NUMCOLORS;
|
||||||
memset(myGrid, 0, gridSize*sizeof(bool));
|
memset(myGrid, 0, gridSize*sizeof(bool));
|
||||||
for (int ii = 0; ii < azool::NUMCOLORS; ++ii) {
|
for (int ii = 0; ii < azool::NUMCOLORS; ++ii) {
|
||||||
myRows[ii].first = 0;
|
myRows[ii].first = 0;
|
||||||
myRows[ii].second = azool::NONE;
|
myRows[ii].second = azool::NONE;
|
||||||
} // initialize rows
|
} // initialize rows
|
||||||
} // Player::Player
|
} // Player::Player
|
||||||
|
|
||||||
bool Player::checkValidMove(azool::TileColor color, int rowIdx) const {
|
bool Player::checkValidMove(azool::TileColor color, int rowIdx) const {
|
||||||
// check if valid move
|
// check if valid move
|
||||||
@ -41,10 +43,24 @@ bool Player::checkValidMove(azool::TileColor color, int rowIdx) const {
|
|||||||
} // Player::checkValidMove
|
} // Player::checkValidMove
|
||||||
|
|
||||||
bool Player::takeTilesFromFactory(int factoryIdx, azool::TileColor color, int rowIdx) {
|
bool Player::takeTilesFromFactory(int factoryIdx, azool::TileColor color, int rowIdx) {
|
||||||
// call game board -> takeTiles(factoryIdx, color)
|
// checkValidMove first - can't undo request to boardptr
|
||||||
int numTiles = 0;
|
if (!checkValidMove(color, rowIdx)) {
|
||||||
if (checkValidMove(color, rowIdx) and
|
return false;
|
||||||
myBoardPtr->takeTilesFromFactory(factoryIdx, color, numTiles)) {
|
}
|
||||||
|
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<bool>("success", false);
|
||||||
|
int numTiles = response.get<int>("num_tiles_returned", 0);
|
||||||
|
if (success) {
|
||||||
placeTiles(rowIdx, color, numTiles);
|
placeTiles(rowIdx, color, numTiles);
|
||||||
return true;
|
return true;
|
||||||
}
|
}
|
||||||
@ -53,12 +69,22 @@ bool Player::takeTilesFromFactory(int factoryIdx, azool::TileColor color, int ro
|
|||||||
|
|
||||||
bool Player::takeTilesFromPool(azool::TileColor color, int rowIdx) {
|
bool Player::takeTilesFromPool(azool::TileColor color, int rowIdx) {
|
||||||
// call game board -> takeTilesFromPool
|
// call game board -> takeTilesFromPool
|
||||||
int numTiles = 0;
|
|
||||||
bool poolPenalty = false;
|
|
||||||
if (!checkValidMove(color, rowIdx)) {
|
if (!checkValidMove(color, rowIdx)) {
|
||||||
return false;
|
return false;
|
||||||
}
|
}
|
||||||
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<bool>("success", false);
|
||||||
|
int numTiles = response.get<int>("num_tiles_returned", 0);
|
||||||
|
bool poolPenalty = response.get<bool>("pool_penalty", false);
|
||||||
|
if (!success) {
|
||||||
return false; // couldn't get that tile from the pool
|
return false; // couldn't get that tile from the pool
|
||||||
}
|
}
|
||||||
if (poolPenalty) {
|
if (poolPenalty) {
|
||||||
@ -98,18 +124,22 @@ void Player::endRound(bool& fullRow) {
|
|||||||
myGrid[rowIdx][col] = true;
|
myGrid[rowIdx][col] = true;
|
||||||
myScore += scoreTile(rowIdx, col);
|
myScore += scoreTile(rowIdx, col);
|
||||||
// return extra tiles -- rowIdx = the number of leftover tiles
|
// return extra tiles -- rowIdx = the number of leftover tiles
|
||||||
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
|
// reset rows for next turn
|
||||||
myRows[rowIdx].first = 0;
|
myRows[rowIdx].first = 0;
|
||||||
myRows[rowIdx].second = azool::NONE;
|
myRows[rowIdx].second = azool::NONE;
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
if (myNumPenaltiesForRound >= PenaltyPoints.size()) {
|
myScore -= getScorePenalty();
|
||||||
myScore -= PenaltyPoints[PenaltyPoints.size() - 1];
|
myScore = std::max(myScore, 0); // let's not allow negatives
|
||||||
}
|
|
||||||
else {
|
|
||||||
myScore -= PenaltyPoints[myNumPenaltiesForRound];
|
|
||||||
}
|
|
||||||
// reset for next turn
|
// reset for next turn
|
||||||
// FOR THIS REASON
|
// FOR THIS REASON
|
||||||
// main loop needs to check who took penalty BEFORE calling this function
|
// main loop needs to check who took penalty BEFORE calling this function
|
||||||
@ -134,6 +164,12 @@ void Player::endRound(bool& fullRow) {
|
|||||||
} // iter over rows in grid
|
} // iter over rows in grid
|
||||||
} // Player::endRound
|
} // 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) {
|
int Player::scoreTile(int tileRow, int tileCol) {
|
||||||
// search horizontally and vertically for points
|
// search horizontally and vertically for points
|
||||||
int tileScore = 1;
|
int tileScore = 1;
|
||||||
@ -235,10 +271,11 @@ void Player::finalizeScore() {
|
|||||||
} // Player::finalizeScore
|
} // Player::finalizeScore
|
||||||
|
|
||||||
std::string Player::printMyBoard() const {
|
std::string Player::printMyBoard() const {
|
||||||
|
// pt::ptree request;
|
||||||
|
// request.put("req_type", azool::REQ_TYPE_GET_BOARD);
|
||||||
std::ostringstream oss;
|
std::ostringstream oss;
|
||||||
oss << "*******************************\n";
|
oss << "*******************************\n";
|
||||||
oss << "PLAYER: " << myName << "\n";
|
oss << "PLAYER: " << myName << "\n";
|
||||||
oss << *myBoardPtr << "\n\n";
|
|
||||||
for (int ii = 0; ii < azool::NUMCOLORS; ++ii) {
|
for (int ii = 0; ii < azool::NUMCOLORS; ++ii) {
|
||||||
oss << ii+1 << ") ";
|
oss << ii+1 << ") ";
|
||||||
for (int jj = azool::NUMCOLORS; jj > (ii+1); --jj) {
|
for (int jj = azool::NUMCOLORS; jj > (ii+1); --jj) {
|
||||||
@ -250,7 +287,7 @@ std::string Player::printMyBoard() const {
|
|||||||
oss << "_";
|
oss << "_";
|
||||||
}
|
}
|
||||||
else if (jj < myRows[ii].first) {
|
else if (jj < myRows[ii].first) {
|
||||||
oss << azool::TileColorSyms[myRows[ii].second];
|
oss << azool::TileColorSyms[myRows[ii].second];
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
// print grid row
|
// print grid row
|
||||||
@ -259,7 +296,7 @@ std::string Player::printMyBoard() const {
|
|||||||
// color = row + column % 5
|
// color = row + column % 5
|
||||||
char color = (ii + jj) % 5;
|
char color = (ii + jj) % 5;
|
||||||
if (myGrid[ii][jj]) {
|
if (myGrid[ii][jj]) {
|
||||||
oss << static_cast<char>(azool::TileColorSyms[color] - 32) << "|";
|
oss << azool::TileColorStrings[color] << "|";
|
||||||
}
|
}
|
||||||
else {
|
else {
|
||||||
oss << azool::TileColorSyms[color] << "|";
|
oss << azool::TileColorSyms[color] << "|";
|
||||||
@ -267,15 +304,34 @@ std::string Player::printMyBoard() const {
|
|||||||
}
|
}
|
||||||
oss << "\n";
|
oss << "\n";
|
||||||
} // iterate over rows
|
} // iterate over rows
|
||||||
oss << "Penalties: " << myNumPenaltiesForRound << "\n";
|
oss << "Penalties: " << myNumPenaltiesForRound;
|
||||||
|
if (myTookPoolPenaltyThisRound) {
|
||||||
|
oss << "*";
|
||||||
|
}
|
||||||
|
if (myNumPenaltiesForRound > 0) {
|
||||||
|
oss << " (-" << getScorePenalty() << ")";
|
||||||
|
}
|
||||||
|
oss << "\n";
|
||||||
oss << "Score: " << myScore << "\n";
|
oss << "Score: " << myScore << "\n";
|
||||||
|
oss << "-------------------------------\n";
|
||||||
return oss.str();
|
return oss.str();
|
||||||
// TODO(feature) - print penalty tiles (?)
|
// TODO(feature) - print penalty tiles (?)
|
||||||
} // Player::printMyBoard
|
} // Player::printMyBoard
|
||||||
|
|
||||||
bool Player::discardFromFactory(int factoryIdx, azool::TileColor color) {
|
bool Player::discardFromFactory(int factoryIdx, azool::TileColor color) {
|
||||||
int numTiles = -1;
|
pt::ptree request;
|
||||||
if (myBoardPtr->takeTilesFromFactory(factoryIdx, color, numTiles)) {
|
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<bool>("success", false);
|
||||||
|
int numTiles = response.get<int>("num_tiles_returned", 0);
|
||||||
|
if (success) {
|
||||||
myNumPenaltiesForRound += numTiles;
|
myNumPenaltiesForRound += numTiles;
|
||||||
return true;
|
return true;
|
||||||
}
|
}
|
||||||
@ -283,9 +339,19 @@ bool Player::discardFromFactory(int factoryIdx, azool::TileColor color) {
|
|||||||
} // Player::discardFromFactory
|
} // Player::discardFromFactory
|
||||||
|
|
||||||
bool Player::discardFromPool(azool::TileColor color) {
|
bool Player::discardFromPool(azool::TileColor color) {
|
||||||
bool poolPenalty = false;
|
pt::ptree request;
|
||||||
int numTiles = -1;
|
request.put("req_type", azool::REQ_TYPE_DRAW_FROM_POOL);
|
||||||
if (myBoardPtr->takeTilesFromPool(color, numTiles, poolPenalty)) {
|
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<bool>("success", false);
|
||||||
|
int numTiles = response.get<int>("num_tiles_returned", 0);
|
||||||
|
bool poolPenalty = response.get<bool>("pool_penalty", false);
|
||||||
|
if (success) {
|
||||||
if (poolPenalty) {
|
if (poolPenalty) {
|
||||||
myNumPenaltiesForRound++;
|
myNumPenaltiesForRound++;
|
||||||
}
|
}
|
||||||
@ -295,60 +361,78 @@ bool Player::discardFromPool(azool::TileColor color) {
|
|||||||
return false;
|
return false;
|
||||||
} // Player::discardFromPool
|
} // 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 {
|
namespace {
|
||||||
int promptForFactoryIdx(int maxNumFactories) {
|
int promptForFactoryIdx(int maxFactIdx) {
|
||||||
static const char* promptFactoryIdxDraw = "Which factory? enter index\n";
|
static const char* promptFactoryIdxDraw = "Which factory? enter index\n";
|
||||||
char factInput; // TODO can we safely say there will never be more than 9 possible?
|
char factInput; // TODO can we safely say there will never be more than 9 possible?
|
||||||
std::cout << promptFactoryIdxDraw << std::flush;
|
std::cout << promptFactoryIdxDraw << std::flush;
|
||||||
std::cin >> factInput;
|
std::cin >> factInput;
|
||||||
int factIdx = std::atoi(&factInput);
|
int factIdx = std::atoi(&factInput);
|
||||||
if (factIdx < 1 or factIdx > maxNumFactories) {
|
if (factIdx < 1 or factIdx > maxFactIdx) {
|
||||||
return -1;
|
return -1;
|
||||||
}
|
|
||||||
return factIdx;
|
|
||||||
}
|
}
|
||||||
azool::TileColor promptForColor() {
|
return factIdx;
|
||||||
static const char* promptColorDraw = "Which color? [r|b|g|y|k]\n";
|
}
|
||||||
char colorInput = '\0';
|
azool::TileColor promptForColor() {
|
||||||
std::cout << promptColorDraw << std::flush;
|
static const char* promptColorDraw = "Which color? [r|b|g|y|w]\n";
|
||||||
std::cin >> colorInput;
|
char colorInput = '\0';
|
||||||
switch(colorInput) {
|
std::cout << promptColorDraw << std::flush;
|
||||||
case 'r':
|
std::cin >> colorInput;
|
||||||
return azool::RED;
|
switch(colorInput) {
|
||||||
break;
|
case 'r':
|
||||||
case 'b':
|
return azool::RED;
|
||||||
return azool::BLUE;
|
break;
|
||||||
break;
|
case 'b':
|
||||||
case 'g':
|
return azool::BLUE;
|
||||||
return azool::GREEN;
|
break;
|
||||||
break;
|
case 'g':
|
||||||
case 'y':
|
return azool::GREEN;
|
||||||
return azool::YELLOW;
|
break;
|
||||||
break;
|
case 'y':
|
||||||
case 'k':
|
return azool::YELLOW;
|
||||||
return azool::BLACK;
|
break;
|
||||||
break;
|
case 'w':
|
||||||
default:
|
return azool::WHITE;
|
||||||
return azool::NONE;
|
break;
|
||||||
} // end switch
|
default:
|
||||||
return azool::NONE;
|
return azool::NONE;
|
||||||
|
} // end switch
|
||||||
|
return azool::NONE;
|
||||||
|
}
|
||||||
|
int promptForRow() {
|
||||||
|
static const char* promptRowPlacement = "Place on which row? enter number [1-5]\n";
|
||||||
|
char rowInput;
|
||||||
|
std::cout << promptRowPlacement << std::flush;
|
||||||
|
std::cin >> rowInput;
|
||||||
|
int rowIdx = std::atoi(&rowInput);
|
||||||
|
if (rowIdx < 1 or rowIdx > azool::NUMCOLORS) {
|
||||||
|
return -1;
|
||||||
}
|
}
|
||||||
int promptForRow() {
|
return rowIdx;
|
||||||
static const char* promptRowPlacement = "Place on which row? enter number [1-5]\n";
|
}
|
||||||
char rowInput;
|
|
||||||
std::cout << promptRowPlacement << std::flush;
|
|
||||||
std::cin >> rowInput;
|
|
||||||
int rowIdx = std::atoi(&rowInput);
|
|
||||||
if (rowIdx < 1 or rowIdx > azool::NUMCOLORS) {
|
|
||||||
return -1;
|
|
||||||
}
|
|
||||||
return rowIdx;
|
|
||||||
}
|
|
||||||
} // anonymous namespace
|
} // anonymous namespace
|
||||||
|
|
||||||
void Player::takeTurn() {
|
void Player::takeTurn() {
|
||||||
// print game board, handle user input
|
// print game board, handle user input
|
||||||
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<bool>("end_of_round");
|
||||||
|
// max idx for input - users use 1-indexing
|
||||||
|
int maxFactIdx = response.get<int>("num_factories");
|
||||||
|
if (endOfRound) return;
|
||||||
|
std::cout << *myBoardPtr << "\n\n";
|
||||||
std::cout << printMyBoard();
|
std::cout << printMyBoard();
|
||||||
static const char* promptDrawInput = "What would you like to do?\n"
|
static const char* promptDrawInput = "What would you like to do?\n"
|
||||||
"[f] take from factory "
|
"[f] take from factory "
|
||||||
@ -366,7 +450,7 @@ void Player::takeTurn() {
|
|||||||
char drawType;
|
char drawType;
|
||||||
std::cin >> drawType;
|
std::cin >> drawType;
|
||||||
if (drawType == 'f') {
|
if (drawType == 'f') {
|
||||||
int factIdx = promptForFactoryIdx(myBoardPtr->numFactories());
|
int factIdx = promptForFactoryIdx(maxFactIdx);
|
||||||
// draw from factory
|
// draw from factory
|
||||||
if (factIdx == -1) {
|
if (factIdx == -1) {
|
||||||
std::cout << invalidEntryMessage << std::flush;
|
std::cout << invalidEntryMessage << std::flush;
|
||||||
@ -413,7 +497,7 @@ void Player::takeTurn() {
|
|||||||
char discardFrom = '\0';
|
char discardFrom = '\0';
|
||||||
std::cin >> discardFrom;
|
std::cin >> discardFrom;
|
||||||
if (discardFrom == 'f') {
|
if (discardFrom == 'f') {
|
||||||
int factIdx = promptForFactoryIdx(myBoardPtr->numFactories());
|
int factIdx = promptForFactoryIdx(maxFactIdx);
|
||||||
// draw from factory
|
// draw from factory
|
||||||
if (factIdx == -1) {
|
if (factIdx == -1) {
|
||||||
std::cout << invalidEntryMessage << std::flush;
|
std::cout << invalidEntryMessage << std::flush;
|
||||||
@ -445,6 +529,7 @@ void Player::takeTurn() {
|
|||||||
} // discard from pool
|
} // discard from pool
|
||||||
}
|
}
|
||||||
else if (drawType == 'P') {
|
else if (drawType == 'P') {
|
||||||
|
std::cout << *myBoardPtr << "\n\n";
|
||||||
std::cout << printMyBoard();
|
std::cout << printMyBoard();
|
||||||
}
|
}
|
||||||
else {
|
else {
|
||||||
@ -452,6 +537,7 @@ void Player::takeTurn() {
|
|||||||
}
|
}
|
||||||
} // while !fullinput
|
} // while !fullinput
|
||||||
// options: take tile from pool or take tile from factory
|
// options: take tile from pool or take tile from factory
|
||||||
|
std::cout << "\033c" << std::flush;
|
||||||
std::cout << printMyBoard() << std::flush;
|
std::cout << printMyBoard() << std::flush;
|
||||||
// flush out any inputs still in the buffer
|
// flush out any inputs still in the buffer
|
||||||
std::cin.ignore(std::numeric_limits<std::streamsize>::max(), '\n');
|
std::cin.ignore(std::numeric_limits<std::streamsize>::max(), '\n');
|
||||||
|
17
src/main.cc
17
src/main.cc
@ -23,10 +23,12 @@ void playGame(GameBoard* game) {
|
|||||||
while (!game->endOfRound()) {
|
while (!game->endOfRound()) {
|
||||||
// TODO figure out how order will work for > 2 players
|
// TODO figure out how order will work for > 2 players
|
||||||
firstPlayer->takeTurn();
|
firstPlayer->takeTurn();
|
||||||
|
sleep(1);
|
||||||
secondPlayer->takeTurn();
|
secondPlayer->takeTurn();
|
||||||
|
sleep(1);
|
||||||
}
|
}
|
||||||
// check who took penalty
|
// check who took penalty
|
||||||
// nees to be done before claling player->endRound()
|
// needs to be done before calling player->endRound()
|
||||||
if (players[0]->tookPenalty()) {
|
if (players[0]->tookPenalty()) {
|
||||||
firstPlayer = players[0];
|
firstPlayer = players[0];
|
||||||
secondPlayer = players[1];
|
secondPlayer = players[1];
|
||||||
@ -41,15 +43,18 @@ void playGame(GameBoard* game) {
|
|||||||
secondPlayer = players[1];
|
secondPlayer = players[1];
|
||||||
}
|
}
|
||||||
std::cout << "End of round!" << std::endl;
|
std::cout << "End of round!" << std::endl;
|
||||||
|
std::cout << "\033c";
|
||||||
players[0]->endRound(p0EndsGame);
|
players[0]->endRound(p0EndsGame);
|
||||||
players[1]->endRound(p1EndsGame);
|
players[1]->endRound(p1EndsGame);
|
||||||
}
|
}
|
||||||
players[0]->finalizeScore();
|
std::cout << " Final scores:\n";
|
||||||
players[1]->finalizeScore();
|
|
||||||
std::cout << " Final scores:\n" << players[0]->getScore() << "\n" << players[1]->getScore() << "\n" << std::flush;
|
|
||||||
std::cout << players[0]->printMyBoard();
|
|
||||||
std::cout << players[1]->printMyBoard();
|
|
||||||
for (auto player : players) {
|
for (auto player : players) {
|
||||||
|
player->finalizeScore();
|
||||||
|
std::cout << player->getPlayerName() << ": " << player->getScore() << "\n" << std::flush;
|
||||||
|
}
|
||||||
|
// separate loops b/c we want scores to print before printing boards
|
||||||
|
for (auto player : players) {
|
||||||
|
std::cout << player->printMyBoard() << std::flush;
|
||||||
if (player) delete player;
|
if (player) delete player;
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
Loading…
x
Reference in New Issue
Block a user