void airbear::hatch(){ Serial.begin(115200); memoryStatus(); delay(5000); while(!vs1053.begin()){ } SD.begin(CARDCS); // initialise the SD card vs1053.setVolume(5,5); // Set volume for left, right channels. lower numbers == louder volume! vs1053.useInterrupt(DREQ); // DREQ int vs1053.playFullFile("Sounds/orbstart.mp3"); neopixelbegin(); setBrightness(MatrixBrightness); pinMode(heartpin,INPUT); pinMode(circlepin,INPUT); pinMode(crosspin,INPUT); pinMode(squarepin,INPUT); connection(); tail4 = PositionRandomizer(random(7)); tail3 = PositionRandomizer(tail4); tail2 = PositionRandomizer(tail3); tail1 = PositionRandomizer(tail2); head = PositionRandomizer(tail1); memoryStatus(); }
void airbear::spirit(uint8_t r,uint8_t g,uint8_t b){ //TODO take in struct parameter for properties?, add notifications refresh(); tail4 = tail3; tail3 = tail2; tail2 = tail1; tail1 = head; head = PositionRandomizer(head); setNPixel(tail4,r,g,b); setNPixel(tail3,r,g,b); setNPixel(tail2,r,g,b); setNPixel(tail1,r,g,b); setNPixel(head,0,10,10); delay(100); }
namespace Gaming { const unsigned int Game::NUM_INIT_AGENT_FACTOR =4; const unsigned int Game::NUM_INIT_RESOURCE_FACTOR =2; const unsigned Game::MIN_WIDTH = 3; const unsigned Game::MIN_HEIGHT = 3; const double Game::STARTING_AGENT_ENERGY = 20; const double Game::STARTING_RESOURCE_CAPACITY = 10; PositionRandomizer Game::__posRandomizer = PositionRandomizer(); void Game::populate() { std::default_random_engine gen; std::uniform_int_distribution<int> d(0, __width * __height); __numInitAgents = (__width * __height) / NUM_INIT_AGENT_FACTOR; __numInitResources = (__width * __height) / NUM_INIT_RESOURCE_FACTOR; unsigned int numStrategic = __numInitAgents / 2; unsigned int numSimple = __numInitAgents - numStrategic; unsigned int numAdvantages = __numInitResources / 4; unsigned int numFoods = __numInitResources - numAdvantages; while (numStrategic > 0) { int i = d(gen); // random index in the grid vector if (__grid[i] == nullptr) { // is position empty Position pos(i / __width, i % __width); __grid[i] = new Strategic(*this, pos, Game::STARTING_AGENT_ENERGY); numStrategic --; } } while (numSimple > 0) { int i = d(gen); if (__grid[i] == nullptr) { Position pos(i / __width, i % __width); __grid[i] = new Simple(*this, pos, Game::STARTING_AGENT_ENERGY); numSimple --; } } while (numAdvantages > 0) { int i = d(gen); if (__grid[i] == nullptr) { Position pos(i / __width, i % __width); __grid[i] = new Advantage(*this, pos, Game::STARTING_RESOURCE_CAPACITY); numAdvantages --; } } while (numFoods > 0) { int i = d(gen); if (__grid[i] == nullptr) { Position pos(i / __width, i % __width); __grid[i] = new Food(*this, pos, Game::STARTING_RESOURCE_CAPACITY); numFoods --; } } } //constructor,copy constucter, overloaded constucter Game::Game() : Game(3,3) { } Game::Game(unsigned width, unsigned height, bool manual) : __grid(width*height,nullptr), __round(0), __status(NOT_STARTED) { __width = width; __height = height; __numInitAgents = (__width * __height) /NUM_INIT_AGENT_FACTOR; __numInitResources = (__width * __height) /NUM_INIT_RESOURCE_FACTOR; __verbose = false; if (width < MIN_WIDTH || height < MIN_HEIGHT) throw InsufficientDimensionsEx(MIN_WIDTH, MIN_HEIGHT, width, height); if (! manual) void populate(); } Game::~Game() { } //getters unsigned int Game::getNumPieces() const { unsigned int numPieces = 0; for (auto it = __grid.begin(); it != __grid.end(); ++it) { if (*it != nullptr) numPieces++; } return numPieces; } unsigned int Game::getNumAgents() const { unsigned int numAgents = 0; for (auto it = __grid.begin(); it != __grid.end(); ++it) { Agent *agent = dynamic_cast<Agent*>(*it); if (agent) numAgents ++; } return numAgents; } unsigned int Game::getNumSimple() const { unsigned int numAgents = 0; for (auto it = __grid.begin(); it != __grid.end(); ++it) { Simple *simple = dynamic_cast<Simple*>(*it); if (simple) numAgents ++; } return numAgents; } unsigned int Game::getNumStrategic() const { unsigned int numAgents = 0; for (auto it = __grid.begin(); it != __grid.end(); ++it) { Strategic *strategic = dynamic_cast<Strategic*>(*it); if (strategic) numAgents ++; } return numAgents; } unsigned int Game::getNumResources() const { unsigned int numResources = 0; for (auto it = __grid.begin(); it != __grid.end(); ++it) { Resource *resource = dynamic_cast<Resource*>(*it); if (resource) numResources ++; } return numResources; } const Piece *Game::getPiece(unsigned int x, unsigned int y) const { int place = x *__width +y; if (y >= __width || x >= __height) throw OutOfBoundsEx(__width, __height, x, y); if (__grid[place] == nullptr) throw PositionEmptyEx(x, y); return __grid[place]; } //grid population methods void Game::addSimple(const Position &position) { int place = position.y + position.x * __width; if (position.y >= __width || position.x >= __height) throw OutOfBoundsEx(__width, __height, position.x, position.y); if (__grid[place]) throw PositionNonemptyEx(position.x, position.y); __grid[place] = new Simple(*this, position, STARTING_AGENT_ENERGY); } void Game::addSimple(const Position &position, double energy) { int place = position.y + position.x * __width; if (position.y >= __width || position.x >= __height) throw OutOfBoundsEx(__width, __height, position.x, position.y); if (__grid[place]) throw PositionNonemptyEx(position.x, position.y); __grid[place] = new Simple(*this, position, energy); } void Game::addSimple(unsigned x, unsigned y) { int place = y + x * __width; if (y >= __width || x >= __height) throw OutOfBoundsEx(__width, __height, x, y); if (__grid[place]) throw PositionNonemptyEx(x, y); __grid[place] = new Simple(*this, Position(x, y), STARTING_AGENT_ENERGY); } void Game::addSimple(unsigned y, unsigned x, double energy) { int place = y + x * __width; if (y >= __width || x >= __height) throw OutOfBoundsEx(__width, __height, x, y); if (__grid[place]) throw PositionNonemptyEx(x, y); __grid[place] = new Simple(*this, Position(x, y), energy); } void Game::addStrategic(const Position &position, Strategy *s) { int place = position.y + position.x * __width; if (position.y >= __width || position.x >= __height) throw OutOfBoundsEx(__width, __height, position.x, position.y); if (__grid[place]) throw PositionNonemptyEx(position.x, position.y); __grid[place] = new Strategic(*this, position, STARTING_AGENT_ENERGY, s); } void Game::addStrategic(unsigned x, unsigned y, Strategy *s) { int place = y + x * __width; if (y >= __width || x >= __height) throw OutOfBoundsEx(__width, __height, x, y); if (__grid[place]) throw PositionNonemptyEx(x, y); __grid[place] = new Strategic(*this, Position(x, y), STARTING_AGENT_ENERGY, s); } void Game::addFood(const Position &position) { int place = position.y + position.x * __width; if (position.y >= __width || position.x >= __height) throw OutOfBoundsEx(__width, __height, position.x, position.y); if (__grid[place]) throw PositionNonemptyEx(position.x, position.y); __grid[place] = new Food(*this, position, STARTING_RESOURCE_CAPACITY); } void Game::addFood(unsigned x, unsigned y) { int place = y + x * __width; if (y >= __width || x >= __height) throw OutOfBoundsEx(__width, __height, x, y); if (__grid[place]) throw PositionNonemptyEx(x, y); __grid[place] = new Food(*this, Position(x, y), STARTING_RESOURCE_CAPACITY); } void Game::addAdvantage(const Position &position) { int place = position.y + position.x * __width; if (position.y >= __width || position.x >= __height) throw OutOfBoundsEx(__width, __height, position.x, position.y); if (__grid[place]) throw PositionNonemptyEx(position.x, position.y); __grid[place] = new Advantage(*this, position, STARTING_RESOURCE_CAPACITY); } void Game::addAdvantage(unsigned x, unsigned y) { int place = y + (x * __width); if (y >= __width || x >= __height) throw OutOfBoundsEx(__width, __height, x, y); if (__grid[place]) throw PositionNonemptyEx(x, y); __grid[place] = new Advantage(*this, Position(x, y), STARTING_RESOURCE_CAPACITY); } const Surroundings Game::getSurroundings(const Position &pos) const { Surroundings Sur; unsigned int x,y; unsigned int i = 0; // Checks surrounding from a piece using grid from -1 -> 1. returns the surroundings of a peice. for (int row =-1; row <=1; ++row) { x = pos.x+row; for (int col =-1; col <=1; ++col) { y=pos.y+col; if( x>=__height || y >=__width) { Sur.array[i] = INACCESSIBLE; i++; } else if(__grid[x*__width+y]== nullptr) { Sur.array[i] = EMPTY; i++; } else { Sur.array[i]=getPiece(x,y)->getType(); i++; } } } Sur.array[4]=SELF; return Sur; } const ActionType Game::reachSurroundings(const Position &from, const Position &to) { ActionType Move = STAY; unsigned int x,y; //Moving the piece a certain surrounding depending on position, returing the actiontype. x = (from.x - to.x); y = (from.y - to.y); if(x ==1 && y ==1) return Move = NW; else if(x ==1 && y ==0) return Move = N; else if(x ==1 && y ==-1) return Move = NE; else if(x ==0 && y ==-1) return Move = E; else if(x ==-1 && y ==-1) return Move = SE; else if(x ==-1 && y ==0) return Move = S; else if(x ==-1 && y ==1) return Move = SW; else if(x ==0 && y ==1) return Move = W; return Move; } bool Game::isLegal(const ActionType &ac, const Position &pos) const { int x = pos.x, y = pos.y; switch(ac) { //each case makes sure your move stays legal. case NW: x--; y--; break; case N: x--; break; case NE: x--; y++; break; case W: y--; break; case STAY: return true; case E: y++; break; case SW: x++; y--; break; case S: x++; break; case SE: x++; y++; break; } return (x >= 0 && x < __height && y >= 0 && y < __width); } const Position Game::move(const Position &pos, const ActionType &ac) const { //make sure its a legal action. if(!isLegal(ac, pos)) return pos; int x = pos.x, y = pos.y; switch(ac) { //each case is the position in the surroundings array. case NW: x--; y--; break; case N: x--; break; case NE: x--; y++; break; case W: y--; break; case STAY: return pos; //don't change the position case E: y++; break; case SW: x++; y--; break; case S: x++; break; case SE: x++; y++; break; } return Position(x,y); } void Game::round() { __status = PLAYING; ActionType ac; Position pos; for(int i =0; i<__grid.size(); ++i) { if(__grid[i]!= nullptr && ! __grid[i]->getTurned()) { __grid[i]->setTurned(true); //Moving pieces and getting the surroundings during each round. ac = __grid[i]->takeTurn(getSurroundings(__grid[i]->getPosition())); pos = move(__grid[i]->getPosition(), ac); int place = pos.x * __width + pos.y; //If theres a piece on the grid check to see if its a valid piece, then move te piece to the correct pos. // If piece is valid, delete it then replace it with the other piece. if (__grid[place] != nullptr) { __grid[i]->operator*(*(__grid[place])); if (__grid[i]->isViable()) { delete __grid[place]; __grid[place] = __grid[i]; __grid[i]->setPosition(pos); __grid[i] = nullptr; } else if (__grid[place]->isViable()) { delete __grid[i]; __grid[i] = nullptr; } else { delete __grid[place]; delete __grid[i]; __grid[place]=nullptr; __grid[i]=nullptr; } } else { __grid[i]->setPosition(pos); __grid[place] = __grid[i]; __grid[i] = nullptr; } } } //Aging pieces and deleting pieces on the grid for end of round. for(int i = 0; i < __grid.size(); ++i) if(__grid[i] != NULL) { __grid[i]->setTurned(false); __grid[i]->age(); if(!__grid[i]->isViable()) { delete __grid[i]; __grid[i] = NULL; } } __round++; } void Game::play(bool verbose) { while(getNumResources() > 0 && getNumPieces() > 1) round(); } std::ostream &operator<<(std::ostream &os, const Game &game) { os << "Round " << game.getRound() << std::endl; for (int i = 0; i < game.__height; ++i) { for (int j = 0; j < game.__width; ++j) { if (game.__grid[j + (i * (game.__width - 1))] == nullptr) os << "[ ]"; else os << std::setw(5) << game.__grid[j + (i * (game.__width - 1))] << "]"; } os << std::endl; } os << "Status: " << game.getStatus() << std::endl; switch(game.__status) { case (0): os << "Not Started"; break; case (1): os << "Playing..."; break; case (2): os << "Over!"; break; } os<<std::endl<<std::endl; return os; } }
namespace Gaming { const unsigned int Game::NUM_INIT_AGENT_FACTOR = 4; const unsigned int Game::NUM_INIT_RESOURCE_FACTOR = 2; PositionRandomizer Game::__posRandomizer = PositionRandomizer(); const unsigned Game::MIN_WIDTH =3; const unsigned Game::MIN_HEIGHT = 3; const double Game::STARTING_AGENT_ENERGY = 20; const double Game::STARTING_RESOURCE_CAPACITY = 10; void Game::populate() { int __numInitAgents = (__width * __height )/NUM_INIT_AGENT_FACTOR; int __numInitResources = (__width * __height)/NUM_INIT_RESOURCE_FACTOR; unsigned numStrategic = __numInitAgents/2; unsigned numSimple = __numInitAgents - numStrategic; unsigned numAdvantages = __numInitResources/4; unsigned numFoods = __numInitResources - numAdvantages; std::default_random_engine gen; std::uniform_int_distribution<int> d(0, __width * __height -1); while(numFoods > 0) { int i = d(gen); if(__grid[i] == NULL and i!= (__width * __height)) { Position pos(i / __width, i % __width); __grid[i] = new Food(*this, pos, Game::STARTING_RESOURCE_CAPACITY); numFoods--; } } while(numStrategic > 0) { int i = d(gen); if(__grid[i] == NULL and i!= (__width * __height)) { Position pos(i / __width, i % __width); __grid[i] = new Strategic(*this, pos, Game::STARTING_AGENT_ENERGY); numStrategic--; } } while(numSimple > 0) { int i = d(gen); if(__grid[i] == NULL and i!= (__width * __height)) { Position pos(i / __width, i % __width); __grid[i] = new Simple(*this, pos, Game::STARTING_AGENT_ENERGY); numSimple--; } } while(numAdvantages > 0) { int i = d(gen); if(__grid[i] == NULL and i!= (__width * __height)) { Position pos(i / __width, i % __width); __grid[i] = new Advantage(*this, pos, Game::STARTING_RESOURCE_CAPACITY); numAdvantages--; } } } //PublicPublic //Constructor Game::Game(): __width(Game::MIN_WIDTH), __height(Game::MIN_HEIGHT) { for(unsigned int i = 0; i < __width*__height; i++) __grid.push_back(NULL); __status= NOT_STARTED; __verbose= false; __round = 0; } Game::Game(unsigned int width, unsigned int height, bool manual): __width(width), __height(height) { if(height < Game::MIN_HEIGHT || width < Game::MIN_WIDTH) throw InsufficientDimensionsEx(Game::MIN_WIDTH, Game::MIN_HEIGHT, width, height); __status= NOT_STARTED; __verbose=false; __round=0; for(unsigned int i = 0; i < width*height; i++) __grid.push_back(NULL); if(!manual) populate(); } //Destrct Game::~Game() { for(auto i = __grid.begin(); i != __grid.end(); ++i) if(*i != NULL) delete *i; } unsigned int Game::getNumPieces() const { unsigned int num = 0; for(auto i = __grid.begin(); i != __grid.end(); i++) if(*i != NULL) num++; return num; } unsigned int Game::getNumAgents() const { unsigned int num = 0; for(auto i = __grid.begin(); i != __grid.end(); i++) { Agent* test = dynamic_cast<Agent*>(*i); if(test) num++; } return num; } unsigned int Game::getNumSimple() const { unsigned int num = 0; for(auto i = __grid.begin(); i != __grid.end(); i++) { Simple* test = dynamic_cast<Simple*>(*i); if(test) num++; } return num; } unsigned int Game::getNumStrategic() const { unsigned int num = 0; for(auto i = __grid.begin(); i != __grid.end(); ++i) { Strategic* test = dynamic_cast<Strategic*>(*i); if(test) num++; } return num; } unsigned int Game::getNumResources() const { unsigned int num = 0; for(auto i = __grid.begin(); i != __grid.end(); ++i) { Resource* test = dynamic_cast<Resource*>(*i); if(test) num++; } return num; } const Piece* Game::getPiece(unsigned int x, unsigned int y) const { if(y >= __width || x >=__height) throw OutOfBoundsEx(__height, __width, x, y); if (__grid[y + (x * __width)] == nullptr) throw PositionEmptyEx(x, y); return __grid[y + (x * __width)]; } void Game::addSimple(const Position &position) { int i = position.x * __width + position.y; if( position.y >= __width|| position.x >= __height) throw OutOfBoundsEx(__height, __width, position.x, position.y); if(__grid[i]) throw PositionNonemptyEx(position.x, position.y); __grid[i] = new Simple(*this, position, Game::STARTING_AGENT_ENERGY); } void Game::addSimple(const Position &position, double energy) { int i = position.x * __width + position.y; if(position.y >=__width || position.x >= __height) throw OutOfBoundsEx(__height, __width, position.x, position.y); if(__grid[i]) throw PositionNonemptyEx(position.x, position.y); __grid[i] = new Simple(*this, position, energy); } void Game::addSimple(unsigned int x, unsigned int y) { int i = x * __width + y; if( y >= __width || x >= __height) throw OutOfBoundsEx(__height, __width, x, y); if(__grid[i]) throw PositionNonemptyEx(x, y); __grid[i] = new Simple(*this, Position(x,y), Game::STARTING_AGENT_ENERGY); } void Game::addSimple(unsigned int x, unsigned int y, double energy) { int i = x * __width + y; if(y >= __width || x >=__height) throw OutOfBoundsEx(__height, __width, x, y); if(__grid[i]) throw PositionNonemptyEx(x, y); __grid[i] = new Simple(*this, Position(x,y), energy); } void Game::addStrategic(const Position &p, Strategy *s) { int i = p.x * __width + p.y; if(p.y >__width || p.x >= __height) throw OutOfBoundsEx(__height, __width, p.x, p.y); if(__grid[i]) throw PositionNonemptyEx(p.x, p.y); __grid[i] = new Strategic(*this, p, Game::STARTING_AGENT_ENERGY, s); } void Game::addStrategic(unsigned int x, unsigned int y, Strategy *s) { int i = x * __width + y; if(y >= __width || x>=__height) throw OutOfBoundsEx(__height, __width, x, y); if(__grid[i]) throw PositionNonemptyEx(x, y); __grid[i] = new Strategic(*this, Position(x,y), Game::STARTING_AGENT_ENERGY, s); } void Game::addFood(const Position &p) { int i = p.x * __width + p.y; if(p.y >__width || p.x >= __height) throw OutOfBoundsEx(__height, __width, p.x, p.y); if(__grid[i]) throw PositionNonemptyEx(p.x, p.y); __grid[i] = new Food(*this, p, Game::STARTING_RESOURCE_CAPACITY); } void Game::addFood(unsigned int x, unsigned int y) { int i = x * __width + y; if(y >= __width || x>=__height) throw OutOfBoundsEx(__height, __width, x, y); if(__grid[i]) throw PositionNonemptyEx(x, y); __grid[i] = new Food(*this, Position(x,y), Game::STARTING_RESOURCE_CAPACITY); } void Game::addAdvantage(const Position &p) { int i = p.x * __width + p.y; if(p.y >__width || p.x >= __height) throw OutOfBoundsEx(__height, __width, p.x, p.y); if(__grid[i]) throw PositionNonemptyEx(p.x, p.y); __grid[i] = new Advantage(*this, p, Game::STARTING_RESOURCE_CAPACITY); } void Game::addAdvantage(unsigned int x, unsigned int y) { int i = x * __width + y; if(y >= __width || x>=__height) throw OutOfBoundsEx(__height, __width, x, y); if(__grid[i]) throw PositionNonemptyEx(x, y); __grid[i] = new Advantage(*this, Position(x,y), Game::STARTING_RESOURCE_CAPACITY); } const Surroundings Game::getSurroundings(const Position &pos) const { Surroundings surround; //initial for(int i = 0; i < 9; ++i) surround.array[i] = EMPTY; for(int row = -1; row < 2; row++) { for (int col = -1; col < 2; col++) { if (pos.x + row < 0 || pos.x + row >= __height || pos.y + col < 0 || pos.y + col >= __width) surround.array[col + 3 * row + 4] = INACCESSIBLE; else if (__grid[pos.y + col + __width * (pos.x + row)]) surround.array[col + 3 * row + 4] = __grid[pos.y + col + __width * (pos.x + row)]->getType(); } } surround.array[4] = SELF; return surround; } //static stuff const ActionType Game::reachSurroundings(const Position &from, const Position &to) { int x = to.x - from.x, y = to.y - from.y; if(x == -1 && y == 0) //Go up one return N; if(x == -1 && y == -1) //Go up one and go left one return NW; if(x == 0 && y == -1) //Go left one return W; if(x == -1 && y == 1) //Go up one and go right one return NE; if(x == 1 && y == 0) //Go down one return S; if(x == 1 && y == -1) //Go down one and go left one return SW; if(x == 0 && y == 1) //Go right one return E; if(x == 1 && y == 1) //Go down one and go right one return SE; return STAY; } bool Game::isLegal(const ActionType &ac, const Position &pos) const { int x = pos.x; int y = pos.y; switch(ac) { case N: x--; break; case NW: x--; y--; break; case W: y--; break; case NE: x--; y++; break; case S: x++; break; case SW: x++; y--; break; case E: y++; break; case SE: x++; y++; break; case STAY: break; } //check if still inside if (x >=0 && x < __height && y >= 0 && y < __width ) return true; return false; } const Position Game::move(const Position &pos, const ActionType &ac) const { if(!isLegal(ac, pos)) return pos; int x = pos.x, y = pos.y; switch(ac) { case N: x--; break; case NW: x--; y--; break; case W: y--; break; case NE: x--; y++; break; case S: x++; break; case SW: x++; y--; break; case E: y++; break; case SE: x++; y++; break; case STAY: break; } return Position(x,y); } void Game::round() { __status = PLAYING; for(int i = 0; i < __grid.size(); ++i) if(__grid[i] != NULL && !(__grid[i]->getTurned())) { __grid[i]->setTurned(true); ActionType ac = __grid[i]->takeTurn(getSurroundings(__grid[i]->getPosition())); if(ac == STAY) continue; Position moved = move(__grid[i]->getPosition(), ac); int j = moved.x * __width + moved.y; if(__grid[j] != NULL) { __grid[i]->operator*(*__grid[j]); if(__grid[i]->isViable()) { delete __grid[j]; __grid[j] = __grid[i]; __grid[i]->setPosition(moved); __grid[i] = NULL; } else if(__grid[j]->isViable()) { delete __grid[i]; __grid[i] = NULL; } else { delete __grid[i]; delete __grid[j]; __grid[i] = NULL; __grid[j] = NULL; } } else { __grid[i]->setPosition(moved); __grid[j] = __grid[i]; __grid[i] = NULL; } } for(int i = 0; i < __grid.size(); ++i) if(__grid[i] != NULL) { __grid[i]->setTurned(false); __grid[i]->age(); if(!__grid[i]->isViable()) { delete __grid[i]; __grid[i] = NULL; } } __round++; } void Game::play(bool verbose) { __status = PLAYING; if(verbose) { __verbose = verbose; while(getNumResources()) { std::cout << *this << std::endl; round(); } __status = OVER; std::cout << *this << std::endl; } else { while(getNumResources()) round(); __status = OVER; } } std::ostream& operator<<(std::ostream &os, const Game &game) { os << "Round " << game.__round <<std::endl; int index = 0; for(auto i = game.__grid.begin(); i != game.__grid.end(); ++i) { if(index % game.__width == 0) os << std::endl; os << '['; if(!*i) os << " "; else os << **i; os << ']'; index++; } os << std::endl << "Status: "; switch(game.__status) { case(Game::Status::NOT_STARTED): os << "Not Started!"; break; case(Game::Status::PLAYING): os << "Playing..."; break; case(Game::Status::OVER): os << "Over!"; break; } os << std::endl << std::endl; return os; } }
namespace Gaming { const unsigned int Game::NUM_INIT_AGENT_FACTOR = 4; const unsigned int Game::NUM_INIT_RESOURCE_FACTOR = 2; const unsigned Game::MIN_WIDTH = 3; const unsigned Game::MIN_HEIGHT = 3; const double Game::STARTING_AGENT_ENERGY = 20; const double Game::STARTING_RESOURCE_CAPACITY = 10; PositionRandomizer Game::__posRandomizer = PositionRandomizer(); void Game::populate() { __numInitAgents = (__width * __height) / NUM_INIT_AGENT_FACTOR; __numInitResources = (__width * __height) / NUM_INIT_RESOURCE_FACTOR; unsigned int numStrategic = __numInitAgents / 2; unsigned int numSimple = __numInitAgents - numStrategic; unsigned int numAdvantages = __numInitResources / 4; unsigned int numFoods = __numInitResources - numAdvantages; std::default_random_engine gen; std::uniform_int_distribution<int> d(0, __width * __height); while (numStrategic > 0) { int i = d(gen); if (__grid[i] == nullptr) { Position pos(i / __width, i % __width); __grid[i] = nullptr; __grid[i] = new Strategic(*this, pos, Game::STARTING_AGENT_ENERGY); numStrategic--; } } while (numSimple > 0) { int i = d(gen); if (__grid[i] == nullptr) { Position pos(i / __width, i % __width); __grid[i] = nullptr; __grid[i] = new Simple(*this, pos, Game::STARTING_AGENT_ENERGY); numSimple--; } } while (numFoods > 0) { int i = d(gen); if (__grid[i] == nullptr) { Position pos(i / __width, i % __width); __grid[i] = new Food(*this, pos, STARTING_RESOURCE_CAPACITY); numFoods--; } } while (numAdvantages > 0) { int i = d(gen); if (__grid[i] == nullptr) { Position pos(i / __width, i % __width); __grid[i] = new Advantage(*this, pos, STARTING_RESOURCE_CAPACITY); numAdvantages--; } } } Game::Game() : __grid(MIN_WIDTH * MIN_HEIGHT, nullptr) { __numInitAgents = 0; __numInitResources = 0; __width = MIN_WIDTH; __height = MIN_HEIGHT; __round = 0; __status = NOT_STARTED; __verbose = false; } Game::Game(unsigned width, unsigned height, bool manual) : __grid(width * height, nullptr) { if (width < MIN_WIDTH || height < MIN_HEIGHT) { throw InsufficientDimensionsEx(MIN_WIDTH, MIN_HEIGHT, width, height); } __width = width; __height = height; __round = 0; __status = NOT_STARTED; __verbose = false; if (!manual) { populate(); } } Game::~Game() { for (int i = 0; i < __grid.size(); i++) { if (__grid[i] != nullptr) { delete __grid[i]; } } } unsigned int Game::getNumPieces() const { unsigned int pieces = 0; for (int i = 0; i < __grid.size(); i++) { if (__grid[i] != nullptr) pieces++; } return pieces; } unsigned int Game::getNumAgents() const { unsigned int agent = 0; for (int i = 0; i < __grid.size(); i++) { if (__grid[i] != nullptr && (__grid[i]->getType() == SIMPLE || __grid[i]->getType() == STRATEGIC)) agent++; } return agent; } unsigned int Game::getNumSimple() const { unsigned int simple = 0; for (int i = 0; i < __grid.size(); i++) { if (__grid[i] != nullptr && __grid[i]->getType() == SIMPLE) simple++; } return simple; } unsigned int Game::getNumStrategic() const { unsigned int strategy = 0; for (int i = 0; i < __grid.size(); i++) { if (__grid[i] != nullptr && __grid[i]->getType() == STRATEGIC) strategy++; } return strategy; } unsigned int Game::getNumResources() const { unsigned int resource = 0; for (int i = 0; i < __grid.size(); i++) { if (__grid[i] != nullptr && (__grid[i]->getType() == FOOD || __grid[i]->getType() == ADVANTAGE)) resource++; } return resource; } const Piece *Game::getPiece(unsigned int x, unsigned int y) const { if (y >= __width || x >= __height) { throw OutOfBoundsEx(__width, __height, x, y); } if (__grid[x * __width + y] == nullptr) { throw PositionEmptyEx(x, y); } int location = x * __width + y; return __grid[location]; } void Game::addSimple(const Position &position) { if (position.x >= __height || position.y >= __width) { throw OutOfBoundsEx(__width, __height, position.x, position.y); } if (__grid[position.x * __width + position.y]) { throw PositionNonemptyEx(position.x, position.y); } int location = position.x * __width + position.y; __grid[location] = new Simple(*this, position, STARTING_AGENT_ENERGY); } void Game::addSimple(const Position &position, double energy) { if (position.x >= __height || position.y >= __width) { throw OutOfBoundsEx(__width, __height, position.x, position.y); } if (__grid[position.x * __width + position.y]) { throw PositionNonemptyEx(position.x, position.y); } int location = position.x * __width + position.y; __grid[location] = new Simple(*this, position, energy); } void Game::addSimple(unsigned x, unsigned y) { Position p(x, y); this->addSimple(p); } void Game::addSimple(unsigned x, unsigned y, double energy) { Position p(x, y); this->addSimple(p, energy); } void Game::addStrategic(const Position &position, Strategy *s) { if ((position.x * __width + position.y) > __grid.size()) { throw OutOfBoundsEx(__width, __height, position.x, position.y); } if ((__grid[position.x * __width + position.y]) != nullptr) { throw PositionNonemptyEx(position.x, position.y); } int location = position.x * __width + position.y; __grid[location] = new Strategic(*this, position, STARTING_AGENT_ENERGY, s); } void Game::addStrategic(unsigned x, unsigned y, Strategy *s) { Position p(x, y); this->addStrategic(p, s); } void Game::addFood(const Position &position) { if ((position.x * __width + position.y) > __grid.size()) { throw OutOfBoundsEx(__width, __height, position.x, position.y); } if ((__grid[position.x * __width + position.y]) != nullptr) { throw PositionNonemptyEx(position.x, position.y); } int location = position.x * __width + position.y; __grid[location] = new Food(*this, position, STARTING_RESOURCE_CAPACITY); } void Game::addFood(unsigned x, unsigned y) { Position p(x, y); this->addFood(p); } void Game::addAdvantage(const Position &position) { if ((position.x * __width + position.y) > __grid.size()) { throw OutOfBoundsEx(__width, __height, position.x, position.y); } if (__grid[position.x * __width + position.y] != nullptr) { throw PositionNonemptyEx(position.x, position.y); } int location = position.x * __width + position.y; __grid[location] = new Advantage(*this, position, STARTING_RESOURCE_CAPACITY); } void Game::addAdvantage(unsigned x, unsigned y) { Position p(x, y); this->addAdvantage(p); } const Surroundings Game::getSurroundings(const Position &pos) const { Surroundings temp; int i = 0; for (int x = -1; x < 2; x++) { for (int y = -1; y < 2; y++) { if ((pos.x + x) < 0 || (pos.y + y) < 0 || (pos.x + x) > (__height - 1) || (pos.y + y) > (__width - 1)) temp.array[i] = INACCESSIBLE; else if (y == 0 && x == 0) temp.array[i] = SELF; else if (__grid[(pos.x + x) * __width + (pos.y + y)] == nullptr) temp.array[i] = EMPTY; else temp.array[i] = __grid[(pos.x + x) * __width + (pos.y + y)]->getType(); i++; } } return temp; } const ActionType Game::reachSurroundings(const Position &from, const Position &to) { if ((from.x + 1) < to.x || (from.y + 1) < to.y || (from.x - 1) > to.x || (from.y - 1) > to.y) return STAY; else { if (to.x > from.x) { if (to.y > from.y) return SE; else if (to.y < from.y) return SW; else return S; } else if (to.x < from.x) { if (to.y > from.y) return NE; else if (to.y < from.y) return NW; else return N; } else { if (to.y > from.y) return E; else if (to.y < from.y) return W; else return STAY; } } } bool Game::isLegal(const ActionType &ac, const Position &pos) const { Surroundings s = getSurroundings(pos); int direction; switch (ac) { case N: direction = 1; break; case NE: direction = 2; break; case NW: direction = 0; break; case E: direction = 5; break; case W: direction = 3; break; case SE: direction = 8; break; case SW: direction = 6; break; case S: direction = 7; break; case STAY: direction = 4; } if (s.array[direction] != INACCESSIBLE) return true; return false; } const Position Game::move(const Position &pos, const ActionType &ac) const { if (isLegal(ac, pos)) { Position p(pos); switch (ac) { case N: p.x -= 1; break; case NE: p.x -= 1; p.y += 1; break; case NW: p.x -= 1; p.y -= 1; break; case E: p.y += 1; break; case W: p.y -= 1; break; case SE: p.x += 1; p.y += 1; break; case SW: p.x += 1; p.y -= 1; break; case S: p.x += 1; break; } return p; } } void Game::round() { if (__verbose && __round == 0) __status = Status::PLAYING; for (int count = 0; count < __grid.size(); ++count) { if (__grid[count] != nullptr && !__grid[count]->getTurned() && __grid[count]->isViable()) { Agent *a = dynamic_cast<Agent *>(__grid[count]); if (a) { __grid[count]->setTurned(true); Position p = __grid[count]->getPosition(); Surroundings s = getSurroundings(p); ActionType act = __grid[count]->takeTurn(s); if (act != STAY) { Position newp = move(p, act); int i = (newp.x * __width + newp.y); (*__grid[count]) * (*__grid[i]); if (!__grid[count]->isViable()) { delete __grid[count]; __grid[count] = nullptr; } else { __grid[count]->setPosition(newp); if (__grid[i] == nullptr) { __grid[i] = __grid[count]; __grid[count] = nullptr; } else { delete __grid[i]; __grid[i] = __grid[count]; __grid[count] = nullptr; } } if (!__grid[i]->isViable()) { delete __grid[i]; __grid[i] = nullptr; } } } } } for (int i = 0; i < __grid.size(); ++i) { if (__grid[i] != nullptr) { if (__grid[i]->isViable()) { __grid[i]->setTurned(false); __grid[i]->age(); } else { delete __grid[i]; __grid[i] = nullptr; } } } if (getNumResources() < 1) { __status = Status::OVER; } __round++; } void Game::play(bool verbose) { while (getStatus() != OVER) { if (verbose) std::cout << *this; round(); } } std::ostream &operator<<(std::ostream &os, const Game &game) { os << "Round " << game.__round << std::endl; for (int h = 0; h < game.__height; h++) { for (int w = 0; w < game.__width; w++) { os << "["; if (game.__grid[h * game.__width + w] != nullptr) os << *(game.__grid[h * game.__width + w]); else os << " "; os << "]"; } os << std::endl; } os << "Status: " << game.__status << std::endl; } }
namespace Gaming { PositionRandomizer Game::__posRandomizer = PositionRandomizer(); const unsigned int Game::NUM_INIT_AGENT_FACTOR = 4; const unsigned int Game::NUM_INIT_RESOURCE_FACTOR = 2; const unsigned int Game::MIN_WIDTH = 3; const unsigned int Game::MIN_HEIGHT = 3; const double Game::STARTING_AGENT_ENERGY = 20; const double Game::STARTING_RESOURCE_CAPACITY = 10; // populate the grid (used in automatic random initialization of a Game) void Game::populate() { __numInitAgents = (__width * __height) / NUM_INIT_AGENT_FACTOR; __numInitResources = (__width * __height) / NUM_INIT_RESOURCE_FACTOR; unsigned int numStrategic = __numInitAgents / 2; unsigned int numSimple = __numInitAgents - numStrategic; unsigned int numAdvantages = __numInitResources / 4; unsigned int numFoods = __numInitResources - numAdvantages; default_random_engine gen; uniform_int_distribution<int> d(0, __width * __height - 1); while (numStrategic > 0) { int i = d(gen); // (!= nullptr) if (i != (__width * __height)&&__grid[i] == nullptr ) { Position pos(i / __width, i % __width); __grid[i] = new Strategic(*this, pos, STARTING_AGENT_ENERGY); numStrategic --; } } while (numSimple > 0) { int i = d(gen); // (nullptr) if (i != (__width* __height)&&__grid[i] == nullptr) { Position pos(i / __width, i % __width); __grid[i] = new Simple(*this, pos, STARTING_AGENT_ENERGY); numSimple --; } } while (numFoods > 0) { int i = d(gen); if (i != (__width * __height) && __grid[i] == nullptr) { Position pos(i / __width, i % __width); __grid[i] = new Food(*this, pos, STARTING_RESOURCE_CAPACITY); numFoods--; } } while (numAdvantages > 0) { int i = d(gen); if (i != (__width * __height) && __grid[i] == nullptr) { Position pos(i / __width, i % __width); __grid[i] = new Advantage(*this, pos, STARTING_RESOURCE_CAPACITY); numAdvantages--; } } } // Constructor Game::Game(): __width(3), __height(3) { __numInitAgents = 0; __numInitResources = 0; __width = 3; __height = 3; __round = 0; __status = NOT_STARTED ; __verbose = false; for (int i = 0; i < __width*__height; i++) { __grid.push_back(nullptr) ; } } // note: manual population by default Game::Game(unsigned width, unsigned height, bool manual): __width(width), __height(height) { if (height < MIN_HEIGHT || width < MIN_WIDTH) { throw InsufficientDimensionsEx(MIN_WIDTH, MIN_HEIGHT, width, height); } __numInitAgents = 0; __numInitResources = 0; __width = width; __height = height; __verbose = false; __status = NOT_STARTED; __round = 0; for (int i = 0; i < __width*__height; i++) { __grid.push_back(nullptr) ; } if(!manual) { populate(); } } Game::~Game() { for (int i = 0; i < __grid.size(); i++) { if (__grid[i] != nullptr) { delete __grid[i]; } } } // getters unsigned int Game::getNumPieces() const { return getNumAgents() +getNumResources(); } unsigned int Game::getNumAgents() const { return getNumSimple() +getNumStrategic(); } unsigned int Game::getNumSimple() const { unsigned int numAgents = 0; for (int i = 0; i < __grid.size(); i++) { if(__grid[i]!= nullptr) { if (__grid[i]->getType() == SIMPLE) { numAgents++; } } } return numAgents; } unsigned int Game::getNumStrategic() const { unsigned int numAgents = 0; for (int i = 0; i < __grid.size(); i++) { if (__grid[i]!= nullptr) { if (__grid[i]->getType() == STRATEGIC) { numAgents++; } } } return numAgents; } unsigned int Game::getNumResources() const { unsigned int numAgents=0; for (int i = 0; i < __grid.size(); i++) { if(__grid[i] != nullptr) { if (__grid[i] -> getType() == FOOD || __grid[i] -> getType() == ADVANTAGE) { numAgents++; } } } return numAgents; } const Piece *Game::getPiece(unsigned int x, unsigned int y) const { if(__grid[((x*__width) + y)] != nullptr) { return __grid[((x*__width) + y)]; } throw PositionEmptyEx(x,y); } // grid population methods void Game::addSimple(const Position &position) { if ((position.x*__width + position.y) > __grid.size()) { throw OutOfBoundsEx(__width, __height, position.x, position.y); } if (__grid[position.x * __width + position.y] != nullptr) { throw PositionNonemptyEx(position.x, position.y); } __grid[position.x * __width + position.y] = new Simple(*this, position,STARTING_AGENT_ENERGY); } // used for testing only void Game::addSimple(const Position &position, double energy) { Simple *s = new Simple(*this,position,energy); if((position.x*__width + position.y)>__grid.size()) { throw OutOfBoundsEx(__width,__height,position.x,position.y); } if((__grid[position.x*__width + position.y])!=nullptr) { throw PositionNonemptyEx(position.x,position.y); } __grid[position.x*__width + position.y] = s; } void Game::addSimple(unsigned x, unsigned y) { Position p(x,y); this->addSimple(p); } void Game::addStrategic(const Position &position, Strategy *s) { Strategic *t = new Strategic(*this, position, STARTING_AGENT_ENERGY, s); if((position.x*__width + position.y)>__grid.size()) { throw OutOfBoundsEx(__width, __height, position.x, position.y); } if((__grid[position.x*__width + position.y])!=nullptr) { throw PositionNonemptyEx(position.x, position.y); } __grid[position.x*__width + position.y] = t; } void Game::addStrategic(unsigned x, unsigned y, Strategy *s) { Position p(x,y); this->addStrategic(p,s); } void Game::addFood(const Position &position) { Food *f = new Food(*this, position, STARTING_RESOURCE_CAPACITY); if((position.x*__width + position.y) > __grid.size()) { throw OutOfBoundsEx(__width, __height, position.x, position.y); } if((__grid[position.x*__width + position.y])!=nullptr) { throw PositionNonemptyEx(position.x,position.y); } __grid[position.x*__width + position.y] = f; } void Game::addFood(unsigned x, unsigned y) { Position p(x,y); this->addFood(p); } void Game::addAdvantage(const Position &position) { Advantage *a = new Advantage(*this,position,STARTING_RESOURCE_CAPACITY); if((position.x*__width + position.y)>__grid.size()) { throw OutOfBoundsEx(__width,__height,position.x,position.y); } if((__grid[position.x*__width + position.y])!=nullptr) { throw PositionNonemptyEx(position.x,position.y); } __grid[position.x*__width + position.y] = a; } void Game::addAdvantage(unsigned x, unsigned y) { Position p(x,y); this->addAdvantage(p); } const Surroundings Game::getSurroundings(const Position &pos) const { Surroundings temp; int tempX = pos.x-1; for (int count = 0; count < 3; ++count) { int tempY = pos.y-1; for (int i = 0; i < 3; i++) { if(((tempX * __width) + tempY)==((pos.x*__width) +pos.y)) { temp.array[(count * 3) + i] = SELF; } else if(tempX < 0 ||tempX >__height-1 || tempY<0 || tempY > __width-1) { temp.array[(count * 3) + i] = INACCESSIBLE; } else if (__grid[(tempX * __width) + tempY] == nullptr) { temp.array[(count * 3) + i] = EMPTY; } else { temp.array[(count * 3) + i] = __grid[(tempX * __width) + tempY]->getType(); } tempY++; } tempX++; } return temp; } // gameplay methods const ActionType Game::reachSurroundings(const Position &from, const Position &to) { ActionType temp = STAY; int xDiff = to.x-from.x; int yDiff = to.y-from.y; if(xDiff == - 1 && yDiff == - 1) { temp = NW; } else if(xDiff == - 1 && yDiff == 0) { temp = N; } else if(xDiff == - 1 && yDiff == 1) { temp = NE; } else if(xDiff == 0 && yDiff == - 1) { temp = W; } else if(xDiff == 0 && yDiff == 0) { temp = STAY; } else if(xDiff == 0 && yDiff == 1) { temp = E; } else if(xDiff == 1 && yDiff == - 1) { temp = SW; } else if(xDiff == 1 && yDiff == 0) { temp = S; } else if(xDiff == 1 && yDiff == 1) { temp = SE; } return temp; } bool Game::isLegal(const ActionType &ac, const Position &pos) const { int x, y; x = pos.x; y = pos.y; switch (ac) { case E: y++; break; case NE: y++; x--; break; case N: x--; break; case NW: y--; x--; break; case W: y--; break; case SW: y--; x++; break; case S: x++; break; case SE: x++; y++; break; default: break; } Position p((unsigned )x, (unsigned)y); if (p.y < __width && p.x < __height ) return true; return false; } // note: assumes legal, use with isLegal() const Position Game::move(const Position &pos, const ActionType &ac) const { if (isLegal(ac, pos)) { int x, y; x = pos.x; y = pos.y; switch (ac) { case E: y++; break; case NE: y++; x--; break; case N: x--; break; case NW: y--; x--; break; case W: y--; break; case SW: y--; x++; break; case S: x++; break; case SE: x++; y++; break; default: break; } Position p((unsigned )x, (unsigned)y); return p; } return pos; } // play a single round void Game::round() { if(__round == 0 && __verbose) { __status = PLAYING; std::cout << std::endl << *this; } for (int count = 0; count < __grid.size(); ++count) { if(__grid[count]!= nullptr) { if(__grid[count]->isViable()) { if (! __grid[count]->getTurned()) { Agent * agent = dynamic_cast<Agent*>(__grid[count]); if(agent) { __grid[count]->setTurned(true); Position currPosition = __grid[count]->getPosition(); Surroundings s = getSurroundings(currPosition); ActionType aT = __grid[count]->takeTurn(s); if (aT != STAY) { Position newPosition = move(currPosition, aT); int newPosIndex = (newPosition.x * __width + newPosition.y); (*__grid[count]) * (*__grid[newPosIndex]); if(! __grid[count]->isViable()) { delete __grid[count]; __grid[count]= nullptr; } else { __grid[count]->setPosition(newPosition); if (__grid[newPosIndex] != nullptr) { delete __grid[newPosIndex]; __grid[newPosIndex] = __grid[count]; __grid[count] = nullptr; } else { __grid[newPosIndex] = __grid[count]; __grid[count] = nullptr; } } if(! __grid[newPosIndex]->isViable()) { delete __grid[newPosIndex]; __grid[newPosIndex]= nullptr; } } } } } } } for (int i = 0; i < __grid.size(); i++) { if(__grid[i] != nullptr) { if (!__grid[i]->isViable()) { delete __grid[i]; __grid[i] = nullptr; } else { __grid[i]->setTurned(false); __grid[i]->age(); } } } if(getNumPieces()< 2 || getNumResources() < 1) { __status = OVER; } ++__round; if(__verbose) { std::cout << std::endl << *this; } } // play game until over void Game::play(bool verbose) { __verbose = verbose; round(); if(getNumPieces()>1 && getNumResources() > 0) { play(verbose); } } // Print as follows the state of the game after the last round: // // Round 1: // [F0 ][ ][T1 ] // [W2 ][ ][F3 ] // [ ][S4 ][ ] // Status: Playing... // // Round 5: // [ ][ ][ ] // [ ][T1 ][ ] // [ ][ ][ ] // Status: Over! // std::ostream &operator<< (std::ostream &os, const Game &game) { os << "Round " << game.__round << std::endl; for (int count = 0; count < game.__height; count++) { for (int i = 0; i < game.__width; i++) { os << '[' << std::setw(5) <<std::left << *game.__grid[count*game.__width+i] << ']'; } os << std::endl; } if(game.__status == Game::NOT_STARTED) { os << "Status: Not Started..."; } else if(game.__status == Game::PLAYING) { os << "Status: Playing..."; } else { os << "Status: Over!"; } return os; } Game::Game(const Game &another) { } }
namespace Gaming { const unsigned int Game::NUM_INIT_AGENT_FACTOR = 4; const unsigned int Game::NUM_INIT_RESOURCE_FACTOR = 2; const unsigned Game::MIN_WIDTH = 3; const unsigned Game::MIN_HEIGHT = 3; const double Game::STARTING_AGENT_ENERGY = 20; const double Game::STARTING_RESOURCE_CAPACITY = 10; PositionRandomizer Game::__posRandomizer = PositionRandomizer(); // PRIVATE void Game::populate() { // populate the grid (used in automatic random initialization of a Game) std::default_random_engine gen; std::uniform_int_distribution<int> d(0, __width * __height); __numInitAgents = (__width * __height) / NUM_INIT_AGENT_FACTOR; __numInitResources = (__width * __height) / NUM_INIT_RESOURCE_FACTOR; unsigned int numStrategic = __numInitAgents / 2; unsigned int numSimple = __numInitAgents - numStrategic; unsigned int numAdvantages = __numInitResources / 4; unsigned int numFoods = __numInitResources - numAdvantages; while (numStrategic > 0) { int i = d(gen); if (i != (__width * __height) && __grid[i] == nullptr) { Position pos(i / __width, i % __width); __grid[i] = new Strategic(*this, pos, STARTING_AGENT_ENERGY); numStrategic--; } } while (numSimple > 0) { int i = d(gen); if (i != (__width * __height) && __grid[i] == nullptr) { Position pos(i / __width, i % __width); __grid[i] = new Simple(*this, pos, STARTING_AGENT_ENERGY); numSimple--; } } while (numFoods > 0) { int i = d(gen); if (i != (__width * __height) && __grid[i] == nullptr) { Position pos(i / __width, i % __width); __grid[i] = new Food(*this, pos, STARTING_RESOURCE_CAPACITY); numFoods--; } } while (numAdvantages > 0) { int i = d(gen); if (i != (__width * __height) && __grid[i] == nullptr) { Position pos(i / __width, i % __width); __grid[i] = new Advantage(*this, pos, STARTING_RESOURCE_CAPACITY); numAdvantages--; } } } //PUBLIC //Constructors / Destructor Game::Game() : __width(3), __height(3) { for (unsigned i = 0; i < (__width * __height); ++i) { __grid.push_back(nullptr); } __status = NOT_STARTED; __verbose = false; __round = 0; } Game::Game(unsigned width, unsigned height, bool manual) : __width(width), __height(height) { // note: manual population by default if (width < MIN_WIDTH || height < MIN_HEIGHT) { throw InsufficientDimensionsEx(MIN_WIDTH, MIN_HEIGHT, width, height); } __status = NOT_STARTED; __verbose = false; __round = 0; for (unsigned i = 0; i < (__width * __height); ++i) { __grid.push_back(nullptr); } if (!manual) { populate(); } } Game::~Game() { for (auto it = __grid.begin(); it != __grid.end(); ++it) { if (*it != nullptr) { delete *it; } } } // Accessors unsigned int Game::getNumPieces() const { unsigned int numPieces = 0; for (auto it = __grid.begin(); it != __grid.end(); ++it) { if (*it != nullptr) numPieces++; } return numPieces; } unsigned int Game::getNumAgents() const { unsigned int numAgents = 0; for (auto it = __grid.begin(); it != __grid.end(); ++it) { Agent *simple = dynamic_cast<Agent*>(*it); if (simple) numAgents++; } return numAgents; } unsigned int Game::getNumSimple() const { unsigned int numAgents = 0; for (auto it = __grid.begin(); it != __grid.end(); ++it) { Simple *simple = dynamic_cast<Simple*>(*it); if (simple) numAgents ++; } return numAgents; } unsigned int Game::getNumStrategic() const { unsigned int numAgents = 0; for (auto it = __grid.begin(); it != __grid.end(); ++it) { Strategic *simple = dynamic_cast<Strategic*>(*it); if (simple) numAgents ++; } return numAgents; } unsigned int Game::getNumResources() const { unsigned int numAgents = 0; for (auto it = __grid.begin(); it != __grid.end(); ++it) { Resource *simple = dynamic_cast<Resource*>(*it); if (simple) numAgents++; } return numAgents; } const Piece *Game::getPiece(unsigned int x, unsigned int y) const { if (y >= __width || x >= __height) throw OutOfBoundsEx(__width, __height, x, y); if (__grid[y + (x * __width)] == nullptr) throw PositionEmptyEx(x, y); return __grid[y + (x * __width)]; } // grid population methods void Game::addSimple(const Position &position) { int index = position.y + (position.x * __width); if (position.y >= __width || position.x >= __height) throw OutOfBoundsEx(__width, __height, position.x, position.y); if (__grid[index]) throw PositionNonemptyEx(position.x, position.y); __grid[index] = new Simple(*this, position, STARTING_AGENT_ENERGY); } void Game::addSimple(const Position &position, double energy) { // used for testing only int index = position.y + (position.x * __width); if (position.y >= __width || position.x >= __height) throw OutOfBoundsEx(__width, __height, position.x, position.y); if (__grid[index]) throw PositionNonemptyEx(position.x, position.y); __grid[index] = new Simple(*this, position, energy); } void Game::addSimple(unsigned x, unsigned y) { int index = y + (x * __width); if (y >= __width || x >= __height) throw OutOfBoundsEx(__width, __height, x, y); if (__grid[index]) throw PositionNonemptyEx(x, y); __grid[index] = new Simple(*this, Position(x, y), STARTING_AGENT_ENERGY); } void Game::addSimple(unsigned y, unsigned x, double energy) { int index = y + (x * __width); if (y >= __width || x >= __height) throw OutOfBoundsEx(__width, __height, x, y); if (__grid[index]) throw PositionNonemptyEx(x, y); __grid[index] = new Simple(*this, Position(x, y), energy); } void Game::addStrategic(const Position &position, Strategy *s) { int index = position.y + (position.x * __width); if (position.y >= __width || position.x >= __height) throw OutOfBoundsEx(__width, __height, position.x, position.y); if (__grid[index]) throw PositionNonemptyEx(position.x, position.y); __grid[index] = new Strategic(*this, position, STARTING_AGENT_ENERGY, s); } void Game::addStrategic(unsigned x, unsigned y, Strategy *s) { int index = y + (x * __width); if (y >= __width || x >= __height) throw OutOfBoundsEx(__width, __height, x, y); if (__grid[index]) throw PositionNonemptyEx(x, y); __grid[index] = new Strategic(*this, Position(x, y), STARTING_AGENT_ENERGY, s); } void Game::addFood(const Position &position) { int index = position.y + (position.x * __width); if (position.y >= __width || position.x >= __height) throw OutOfBoundsEx(__width, __height, position.x, position.y); if (__grid[index]) throw PositionNonemptyEx(position.x, position.y); __grid[index] = new Food(*this, position, STARTING_RESOURCE_CAPACITY); } void Game::addFood(unsigned x, unsigned y) { int index = y + (x * __width); if (y >= __width || x >= __height) throw OutOfBoundsEx(__width, __height, x, y); if (__grid[index]) throw PositionNonemptyEx(x, y); __grid[index] = new Food(*this, Position(x, y), STARTING_RESOURCE_CAPACITY); } void Game::addAdvantage(const Position &position) { int index = position.y + (position.x * __width); if (position.y >= __width || position.x >= __height) throw OutOfBoundsEx(__width, __height, position.x, position.y); if (__grid[index]) throw PositionNonemptyEx(position.x, position.y); __grid[index] = new Advantage(*this, position, STARTING_RESOURCE_CAPACITY); } void Game::addAdvantage(unsigned x, unsigned y) { int index = y + (x * __width); if (y >= __width || x >= __height) throw OutOfBoundsEx(__width, __height, x, y); if (__grid[index]) throw PositionNonemptyEx(x, y); __grid[index] = new Advantage(*this, Position(x, y), STARTING_RESOURCE_CAPACITY); } const Surroundings Game::getSurroundings(const Position &pos) const { //std::cout << "Getting surroundings..." << std::endl; Surroundings sur; for (int i = 0; i < 9; ++i) { sur.array[i] = EMPTY; } for (int row = -1; row <= 1; ++row) { for (int col = -1; col <= 1; ++col) { if (pos.x + row >= 0 && pos.x + row < __height && pos.y + col >= 0 && pos.y + col < __width) { // In bounds unsigned int index = pos.y + col + ((pos.x + row) * __width); //Piece *piece = __grid[pos.y + y + ((pos.x + x) * __width)]; if (__grid[index]) sur.array[col + 1 + ((row + 1) * 3)] = __grid[index]->getType(); } else { // Out of bounds sur.array[col + 1 + ((row + 1) * 3)] = INACCESSIBLE; } } } sur.array[4] = SELF; return sur; } // gameplay methods const ActionType Game::reachSurroundings(const Position &from, const Position &to) { // note: STAY by default int x; int y; x = to.x - from.x; y = to.y - from.y; x++; y++; unsigned int index = (y + (x * 3)); switch (index) { case 0: return NW; case 1: return N; case 2: return NE; case 3: return W; case 4: return STAY; case 5: return E; case 6: return SW; case 7: return S; case 8: return SE; default: return STAY; } } bool Game::isLegal(const ActionType &ac, const Position &pos) const { int x, y; x = pos.x; y = pos.y; switch (ac) { case E: y++; break; case NE: y++; x--; break; case N: x--; break; case NW: y--; x--; break; case W: y--; break; case SW: y--; x++; break; case S: x++; break; case SE: x++; y++; break; default: break; } Position p((unsigned )x, (unsigned)y); if (p.x < __height && p.y < __width) return true; return false; } const Position Game::move(const Position &pos, const ActionType &ac) const { // note: assumes legal, use with isLegal() if (isLegal(ac, pos)) { int x, y; x = pos.x; y = pos.y; switch (ac) { case E: y++; break; case NE: y++; x--; break; case N: x--; break; case NW: y--; x--; break; case W: y--; break; case SW: y--; x++; break; case S: x++; break; case SE: x++; y++; break; default: break; } Position p((unsigned )x, (unsigned)y); return p; //__grid[(unsigned)y + ((unsigned)x * __height)] = __grid[pos.y + (pos.x * __width)]; //__grid[pos.y + (pos.x * __width)] = nullptr; } return pos; } void Game::round() { // play a single round //__status = PLAYING; //std::cout << "Round started" << std::endl; std::set<Piece*> pieces; for (auto it = __grid.begin(); it != __grid.end(); ++it) { if (*it) { pieces.insert(pieces.end(), *it); //pieces.insert(*it); (*it)->setTurned(false); } } // Take turns for (auto it = pieces.begin(); it != pieces.end(); ++it) { if (!(*it)->getTurned()) { (*it)->setTurned(true); (*it)->age(); ActionType ac = (*it)->takeTurn(getSurroundings((*it)->getPosition())); //std::cout << "------- Game::round -------" << std::endl; //std::cout << "Action: " << ac << std::endl; Position pos0 = (*it)->getPosition(); //std::cout << "Pos0: " << pos0.x << "x" << pos0.y << std::endl; Position pos1 = move(pos0, ac); //std::cout << "Pos1: " << pos1.x << "x" << pos1.y << std::endl; if (pos0.x != pos1.x || pos0.y != pos1.y) { Piece *p = __grid[pos1.y + (pos1.x * __width)]; if (p) { (*(*it)) * (*p); if ((*it)->getPosition().x != pos0.x || (*it)->getPosition().y != pos0.y) { // piece moved __grid[pos1.y + (pos1.x * __width)] = (*it); __grid[pos0.y + (pos0.x * __width)] = p; } } else { // empty move (*it)->setPosition(pos1); __grid[pos1.y + (pos1.x * __width)] = (*it); __grid[pos0.y + (pos0.x * __width)] = nullptr; //std::cout << "position updated of piece" << std::endl; } } } } // Update positions and delete // Delete invalid first for (unsigned int i = 0; i < __grid.size(); ++i) { //if (__grid[i]) std::cout << "Piece viable: " << __grid[i]->isViable() << std::endl; if (__grid[i] && !(__grid[i]->isViable())) { delete __grid[i]; __grid[i] = nullptr; } //if (__grid[i]) __grid[i]->age(); } // Update positions of remaining /*for (unsigned int i = 0; i < __grid.size(); ++i) { Piece *currentPiece = __grid[i]; if (currentPiece) { Position pos = currentPiece->getPosition(); if (__grid[pos.y + (pos.x * __width)] != currentPiece) { __grid[pos.y + (pos.x * __width)] = currentPiece; __grid[i] = nullptr; //std::cout << "place in __grid changed of a piece" << std::endl; } } i++; }*/ // Check game over if (getNumResources() <= 0) { __status = Status::OVER; } __round++; } void Game::play(bool verbose) { // play game until over __verbose = verbose; __status = PLAYING; std::cout << *this; while (__status != OVER) { round(); if (verbose) std::cout << *this; } if (!verbose) std::cout << *this; } std::ostream &operator<<(std::ostream &os, const Game &game) { os << "Round " << game.__round << std::endl; int column = 0; for (auto it = game.__grid.begin(); it != game.__grid.end(); ++it) { if (*it == nullptr) { os << "[" << std::setw(6) << "]"; } else { //os ; std::stringstream ss; ss << "[" << **it; std::string str; std::getline(ss, str); //os << str << std::setw(3) << "]"; os << str << "]"; //os << std::setw(4) << "[" << **it; //os << "]"; //os ; } if (++column == game.__width) { column = 0; os << std::endl; } } os << "Status: "; switch (game.getStatus()) { case Game::Status::NOT_STARTED: std::cout << "Not Started..." << std::endl; break; case Game::Status::PLAYING: std::cout << "Playing..." << std::endl; break; default: std::cout << "Over!" << std::endl; break; } return os; } }
namespace Gaming { const unsigned int Game::NUM_INIT_AGENT_FACTOR = 4; const unsigned int Game::NUM_INIT_RESOURCE_FACTOR = 2; const unsigned Game::MIN_WIDTH = 3; const unsigned Game::MIN_HEIGHT = 3; const double Game::STARTING_AGENT_ENERGY = 20; const double Game::STARTING_RESOURCE_CAPACITY = 10; PositionRandomizer Game::__posRandomizer = PositionRandomizer(); void Game::populate() { __numInitAgents = (__width * __height) / NUM_INIT_AGENT_FACTOR; __numInitResources = (__width * __height) / NUM_INIT_RESOURCE_FACTOR; std::default_random_engine gen; std::uniform_int_distribution<int> d(0, __width * __height); unsigned int numStrategic = __numInitAgents/2; unsigned int numSimple = __numInitAgents - numStrategic; unsigned int numAdvantages = __numInitResources/4; unsigned int numFoods = __numInitResources - numAdvantages; while (numStrategic > 0) { int i = d(gen); if (__grid[i] == nullptr) { Position pos(i / __width, i % __width); __grid[i] = new Strategic(*this, pos, STARTING_AGENT_ENERGY); numStrategic--; } } while (numSimple > 0) { int i = d(gen); if (__grid[i] == nullptr) { Position pos(i / __width, i % __width); __grid[i] = new Simple(*this, pos, STARTING_AGENT_ENERGY); numSimple--; } } while (numAdvantages > 0) { int i = d(gen); if (__grid[i] == nullptr) { Position pos(i / __width, i % __width); __grid[i] = new Advantage(*this, pos, STARTING_RESOURCE_CAPACITY); numAdvantages--; } } while (numFoods > 0) { int i = d(gen); if (__grid[i] == nullptr) { Position pos(i / __width, i % __width); __grid[i] = new Food(*this, pos, STARTING_RESOURCE_CAPACITY); numFoods--; } } } Game::Game() { __width = MIN_WIDTH; __height = MIN_HEIGHT; __status = NOT_STARTED; __round = 0; __verbose = false; for(int i = 0; i < (__width*__height); ++i) { __grid.push_back(nullptr); } } Game::Game(unsigned width, unsigned height, bool manual){ if (width < MIN_WIDTH || height < MIN_HEIGHT) { throw InsufficientDimensionsEx(MIN_WIDTH, MIN_HEIGHT, width, height); } __width = width; __height = height; __status = NOT_STARTED; __round = 0; __verbose = false; for (int i = 0; i < (__width * __height); ++i) { __grid.push_back(nullptr); } if (manual == false) { populate(); } } Game::~Game() { for (int i = 0; i < __grid.size(); ++i) { if (__grid[i]){ delete __grid[i]; } } } unsigned int Game::getNumPieces() const { return getNumAgents()+getNumResources(); } unsigned int Game::getNumAgents() const { return getNumSimple()+getNumStrategic(); } unsigned int Game::getNumSimple() const { unsigned int numAgents = 0; for (auto it = __grid.begin(); it != __grid.end(); ++it) { Simple *simple = dynamic_cast<Simple*>(*it); if (simple) { numAgents++; } } return numAgents; } unsigned int Game::getNumStrategic() const { unsigned int numAgents = 0; for (auto it = __grid.begin(); it != __grid.end(); ++it) { Strategic *strategic = dynamic_cast<Strategic*>(*it); if (strategic) { numAgents++; } } return numAgents; } unsigned int Game::getNumResources() const { unsigned int numAgents = 0; for (auto it = __grid.begin(); it != __grid.end(); ++it) { Resource *resource = dynamic_cast<Resource*>(*it); if (resource) { numAgents++; } } return numAgents; } const Piece *Game::getPiece(unsigned int x, unsigned int y) const { if (__grid[(x * __width)+y] == nullptr) { throw PositionEmptyEx(x, y); } return __grid[y + (x * __width)]; } void Game::addSimple(const Position &position) { if (position.y >= __width || position.x >= __height) { throw OutOfBoundsEx(__width, __height, position.x, position.y); } if (__grid[(position.x * __width)+position.y]) { throw PositionNonemptyEx(position.x, position.y); } __grid[(position.x * __width)+position.y] = new Simple(*this, position, STARTING_AGENT_ENERGY); } void Game::addSimple(const Position &position, double energy) { if (position.y >= __width || position.x >= __height) { throw OutOfBoundsEx(__width, __height, position.x, position.y); } if (__grid[(position.x * __width)+position.y]) { throw PositionNonemptyEx(position.x, position.y); } __grid[(position.x * __width)+position.y] = new Simple(*this, position, energy); } void Game::addSimple(unsigned x, unsigned y) { if (y >= __width || x >= __height) { throw OutOfBoundsEx(__width, __height, x, y); } if (__grid[(x*__width)+y]) { throw PositionNonemptyEx(x, y); } __grid[(x*__width)+y] = new Simple(*this, Position(x, y), STARTING_AGENT_ENERGY); } void Game::addSimple(unsigned y, unsigned x, double energy) { if (y >= __width || x >= __height) { throw OutOfBoundsEx(__width, __height, x, y); } if (__grid[(x*__width)+y]) { throw PositionNonemptyEx(x, y); } __grid[(x*__width)+y] = new Simple(*this, Position(x, y), energy); } void Game::addStrategic(const Position &position, Strategy *s) { if (position.y >= __width || position.x >= __height) { throw OutOfBoundsEx(__width, __height, position.x, position.y); } if (__grid[(position.x * __width)+position.y]) { throw PositionNonemptyEx(position.x, position.y); } __grid[(position.x * __width)+position.y] = new Strategic(*this, position, STARTING_AGENT_ENERGY, s); } void Game::addStrategic(unsigned x, unsigned y, Strategy *s) { if (y >= __width || x >= __height) { throw OutOfBoundsEx(__width, __height, x, y); } if (__grid[(x*__width)+y]) { throw PositionNonemptyEx(x, y); } __grid[(x*__width)+y] = new Strategic(*this, Position(x, y), STARTING_AGENT_ENERGY, s); } void Game::addFood(const Position &position) { if (position.y >= __width || position.x >= __height) { throw OutOfBoundsEx(__width, __height, position.x, position.y); } if (__grid[(position.x * __width)+position.y]) { throw PositionNonemptyEx(position.x, position.y); } __grid[(position.x * __width)+position.y] = new Food(*this, position, STARTING_RESOURCE_CAPACITY); } void Game::addFood(unsigned x, unsigned y) { if (y >= __width || x >= __height) { throw OutOfBoundsEx(__width, __height, x, y); } if (__grid[(x * __width)+y]) { throw PositionNonemptyEx(x, y); } __grid[(x * __width)+y] = new Food(*this, Position(x, y), STARTING_RESOURCE_CAPACITY); } void Game::addAdvantage(const Position &position) { if (position.y >= __width || position.x >= __height) { throw OutOfBoundsEx(__width, __height, position.x, position.y); } if (__grid[(position.x *__width)+position.y]) { throw PositionNonemptyEx(position.x, position.y); } __grid[(position.x *__width)+position.y] = new Advantage(*this, position, STARTING_RESOURCE_CAPACITY); } void Game::addAdvantage(unsigned x, unsigned y) { if (y >= __width || x >= __height) { throw OutOfBoundsEx(__width, __height, x, y); } if (__grid[(x *__width)+y]) { throw PositionNonemptyEx(x, y); } __grid[(x *__width)+y] = new Advantage(*this, Position(x, y), STARTING_RESOURCE_CAPACITY); } const Surroundings Game::getSurroundings(const Position &pos) const { Surroundings s; int x, y; for (int i = 0; i < 9; ++i) { s.array[i] = EMPTY; } for (int j = -1; j <= 1; ++j) { x = pos.x + j; for (int k = -1; k <= 1; ++k) { y = pos.y + k; if (x >= 0 && x < __height && y >= 0 && y < __width) { unsigned int index = y + (x * __width); if (__grid[index]) s.array[k + 1 + ((j + 1) * 3)] = __grid[index]->getType(); } else { s.array[k + 1 + ((j + 1) * 3)] = INACCESSIBLE; } } } s.array[4] = SELF; return s; } const ActionType Game::reachSurroundings(const Position &from, const Position &to) { // note: STAY by default int x = (to.x-from.x)+1; int y = (to.y-from.y)+1; int i = (x * 3) + y; switch (i) { case 0: return NW; break; case 1: return N; break; case 2: return NE; break; case 3: return W; break; case 4: return STAY; break; case 5: return E; break; case 6: return SW; break; case 7: return S; break; case 8: return SE; break; default : break; } } bool Game::isLegal(const ActionType &ac, const Position &pos) const { int x = (pos.x); int y = (pos.y); switch (ac) { case NW: y--; x--; break; case N: x--; break; case NE: y++; x--; break; case W: y--; break; case E: y++; break; case SW: y--; x++; break; case S: x++; break; case SE: x++; y++; break; default : break; } if (x < __height && y < __width){ return true; } else { return false; } } const Position Game::move(const Position &pos, const ActionType &ac) const { // note: assumes legal, use with isLegal() if (isLegal(ac, pos)) { int x = (pos.x); int y = (pos.y); switch (ac) { case NW: y--; x--; break; case N: x--; break; case NE: y++; x--; break; case W: y--; break; case E: y++; break; case SW: y--; x++; break; case S: x++; break; case SE: x++; y++; break; default : break; } Position p(x, y); return p; } } void Game::round() { std::set<Piece*> pc; __status = PLAYING; for(int i = 0; i < __grid.size(); i++) { if(__grid[i] != nullptr){ if(!(__grid[i]->isViable())){ __grid[i] = nullptr; } } } for (auto it = __grid.begin(); it != __grid.end(); ++it) { if(*it != nullptr){ pc.insert(pc.end(), *it); (*it)->setTurned(false); } } for (auto it = pc.begin(); it != pc.end(); ++it) { Position p1 = (*it)->getPosition(); ActionType a = (*it)->takeTurn(getSurroundings(p1)); Position p2 = move(p1, a); if (!(*it)->getTurned()) { (*it)->age(); (*it)->setTurned(true); if(p1.x != p2.x || p1.y != p2.y){ if((*it)->getPosition().x != p1.x || (*it)->getPosition().y != p1.y){ __grid[p2.y + (p2.x * __width)] = (*it); __grid[p1.y + (p1.x * __width)] = __grid[p2.y + (p2.x * __width)]; } else{ (*it)->setPosition(p2); __grid[p2.y + (p2.x * __width)] = (*it); __grid[p1.y + (p1.x * __width)] = nullptr; } } } } __round++; } void Game::play(bool verbose) { __verbose = verbose; __status = PLAYING; round(); if (getNumResources() > 0) { if (getNumPieces() > 0) { play(verbose); } } } std::ostream &operator<<(std::ostream &os, const Game &game) { } }
namespace Gaming{ //provided by ivo from PA4 read me const unsigned int Game::NUM_INIT_AGENT_FACTOR = 4; const unsigned int Game::NUM_INIT_RESOURCE_FACTOR = 2; const unsigned Game::MIN_WIDTH = 3; const unsigned Game::MIN_HEIGHT = 3; const double Game::STARTING_AGENT_ENERGY = 20; const double Game::STARTING_RESOURCE_CAPACITY = 10; PositionRandomizer Game::__posRandomizer = PositionRandomizer(); //used for populating grid (used in automatic random initialization of a Game) void Game::populate() { // simple pseudo-random number generator // sufficient for our casual purposes std::default_random_engine gen; std::uniform_int_distribution<int> d(0, __width * __height-1); __numInitAgents = (__width * __height) / NUM_INIT_AGENT_FACTOR; __numInitResources = (__width * __height) / NUM_INIT_RESOURCE_FACTOR; unsigned int numStrategic = __numInitAgents / 2; unsigned int numSimple = __numInitAgents - numStrategic; unsigned int numAdvantage = __numInitResources / 4; unsigned int numFood = __numInitResources - numAdvantage; // populate Strategic agents while (numStrategic > 0) { int i = d(gen); // random index in the grid vector if (__grid[i] == nullptr) { // is position empty Position pos(i / __width, i % __width); __grid[i] = new Strategic(*this, pos, Game::STARTING_AGENT_ENERGY); //used strategic numStrategic --; } } //creates a variable called num simle //populate simple agents while(numSimple >0){ int i = d(gen); //random index from the grid vector if(__grid[i] == nullptr){ //is emptry equals nullptr Position pos(i / __width, i % __width); __grid[i] = new Simple(*this, pos, Game::STARTING_AGENT_ENERGY); //used simple numSimple--; } } // Note: you can reuse the generator while(numFood > 0){ int i = d(gen); if(__grid[i] == nullptr){ Position pos(i / __width, i % __width); __grid[i] = new Food(*this, pos,Game::STARTING_RESOURCE_CAPACITY); //used food numFood--; } } while(numAdvantage > 0){ int i = d(gen); if(__grid[i] == nullptr){ Position pos(i / __width, i % __width); __grid[i] = new Advantage(*this, pos, Game::STARTING_RESOURCE_CAPACITY); //used Resource numAdvantage--; } } } //shiek //default constructor for game class Game::Game() { __width = MIN_WIDTH; __height = MIN_HEIGHT; __status = NOT_STARTED; // __verbose = false; //__round =0; //will make a __grid of 3 x 3 for(int i = 0; i <(__width*__height);i++){ __grid.push_back(nullptr); //will push null ptr to each element in the vector } } // note: manual population by default Game::Game(unsigned width, unsigned height, bool manual) { if (width < MIN_WIDTH || height < MIN_HEIGHT) throw InsufficientDimensionsEx(MIN_WIDTH, MIN_HEIGHT, width, height); __width = width; __height = height; __status = NOT_STARTED; //__verbose = false; // __round = 0; for(int i = 0; i < __width * __height; i++) { __grid.push_back(nullptr); } if(!manual) populate(); } //destructor for Game class Game::~Game() { for(auto it = __grid.begin(); it != __grid.end();it++) { if(*it != nullptr) delete *it; } } //will search the whole board of pieces unsigned int Game::getNumPieces() const { //used the num grt simple function but instead used if statment to for spots that arent nullptr unsigned int numPieces = 0; //will kepp count of how many pieces we have for (auto it = __grid.begin(); it != __grid.end(); ++it) { if(*it != nullptr){ //if *it is not equal to nullptr then we increment numPieces since thats populated by a piece numPieces++; //increment } } return numPieces; //after all ietrations we return the number of pieces } //will get the amoutn of agents on the board unsigned int Game::getNumAgents() const { unsigned int numAgents = 0; for(auto it = __grid.begin(); it != __grid.end(); it++){ Agent *agent = dynamic_cast<Agent*>(*it); if(agent) numAgents++; } return numAgents; } //gets the amounnt of simple agents on the board unsigned int Game::getNumSimple() const { // dynamic_cast returns a pointer of the argument type // or NULL if the derived type of the object is not of // the argument type unsigned int numSimple = 0; for (auto it = __grid.begin(); it != __grid.end(); ++it) { Simple *simple = dynamic_cast<Simple*>(*it); if (simple) numSimple ++; } return numSimple; } unsigned int Game::getNumStrategic() const { unsigned int numStrategic = 0; for(auto it = __grid.begin(); it != __grid.end(); ++it){ Strategic *strategic = dynamic_cast<Strategic*>(*it); if(strategic) numStrategic++; } return numStrategic; } unsigned int Game::getNumResources() const { unsigned int numResource = 0; for(auto it = __grid.begin(); it != __grid.end(); it++){ Resource *resource = dynamic_cast<Resource*>(*it); if(resource) numResource++; } return numResource; } const Piece *Game::getPiece(unsigned int x, unsigned int y) const { //TODO would i return the piece that is at that location?? int location = y +(x* __width); //will look for this location on the grid if (x < 0 || x >= __height || y < 0 || y >= __width) throw OutOfBoundsEx(__width, __height, x, y); if (__grid[location] == nullptr) throw PositionEmptyEx(x, y); return __grid[location]; //returns the location on the grid } void Game::addSimple(const Position &position) { //exception for out of bounds int location = position.y + (position.x * __width); if(position.x < 0 || position.x >= __height || position.y < 0 || position.y >= __width){ throw OutOfBoundsEx(__width,__height,position.x,position.y); } if(__grid[location]) throw PositionNonemptyEx(position.x,position.y); __grid[location] = new Simple(*this, position,STARTING_AGENT_ENERGY); } void Game::addSimple(const Position &position, double energy) { //exception for out of bounds int location = position.y + (position.x * __width); if(position.x < 0 || position.x >= __height || position.y < 0 || position.y >= __width){ throw OutOfBoundsEx(__width,__height,position.x,position.y); } if(__grid[location]) throw PositionNonemptyEx(position.x,position.y); __grid[location] = new Simple(*this, position,energy); } void Game::addSimple(unsigned x, unsigned y) { Position pos(x, y); int location = y + (x * __width); if (x < 0 || x >= __height || y < 0 || y >= __width) throw OutOfBoundsEx(__width, __height, x, y); if (__grid[location]) throw PositionNonemptyEx(x, y); __grid[location] = new Simple(*this, pos, STARTING_AGENT_ENERGY); } void Game::addSimple(unsigned x, unsigned y, double energy) { //exception for out of bounds Position pos(x,y); int location = y + (x * __width); if (x < 0 || x >= __height || y < 0 || y >= __width) throw OutOfBoundsEx(__width, __height, x, y); if (__grid[location]) throw PositionNonemptyEx(x, y); __grid[location] = new Simple(*this, pos,energy); } void Game::addStrategic(const Position &position, Strategy *s) { int location = position.y + (position.x * __width); if (position.x < 0 || position.x >= __height || position.y < 0 || position.y >= __width) throw OutOfBoundsEx(__width, __height, position.x, position.y); if (__grid[location]) throw PositionNonemptyEx(position.x, position.y); __grid[location] = new Strategic(*this, position, STARTING_AGENT_ENERGY, s); } void Game::addStrategic(unsigned x, unsigned y, Strategy *s) { Position pos(x,y); int location = y + (x * __width); if (x < 0 || x >= __height || y < 0 || y >= __width) throw OutOfBoundsEx(__width, __height, x, y); if (__grid[location]) throw PositionNonemptyEx(x, y); __grid[location] = new Strategic(*this, pos, STARTING_AGENT_ENERGY,s); } void Game::addFood(const Position &position) { int location = position.y + (position.x * __width); if (position.x < 0 || position.x >= __height || position.y < 0 || position.y >= __width) throw OutOfBoundsEx(__width, __height, position.x, position.y); if (__grid[location]) throw PositionNonemptyEx(position.x, position.y); __grid[location] = new Food(*this, position,STARTING_RESOURCE_CAPACITY); } void Game::addFood(unsigned x, unsigned y) { Position pos(x,y); int location = y + (x * __width); if (x < 0 || x >= __height || y < 0 || y >= __width) throw OutOfBoundsEx(__width, __height, x, y); if (__grid[location]) throw PositionNonemptyEx(x, y); __grid[location] = new Food(*this, pos,STARTING_RESOURCE_CAPACITY); } void Game::addAdvantage(const Position &position) { int location = position.y + (position.x * __width); if (position.x < 0 || position.x >= __height || position.y < 0 || position.y >= __width) throw OutOfBoundsEx(__width, __height, position.x, position.y); if (__grid[location]) throw PositionNonemptyEx(position.x, position.y); __grid[location] = new Advantage(*this, position, STARTING_RESOURCE_CAPACITY); } void Game::addAdvantage(unsigned x, unsigned y) { Position pos(x,y); int location = y +(x *__width); if (x < 0 || x >= __height || y < 0 || y >= __width) throw OutOfBoundsEx(__width, __height, x, y); if (__grid[location]) throw PositionNonemptyEx(x, y); __grid[location] = new Advantage(*this, pos, STARTING_RESOURCE_CAPACITY); } const Surroundings Game::getSurroundings(const Position &pos) const { if(pos.x < 0 || pos.x >= __height || pos.y >= __width) throw OutOfBoundsEx(__width,__height,pos.x,pos.y); //todo check why surround has no been initialized Surroundings surround; // a array of class Surroundings //Todo Fill the array with empty members except for self whivh is at 4 for(int i = 0; i < 9; i++){ //i is less than nine since theres only 8 elements if(i == 4){ surround.array[i] = SELF; } else surround.array[i] = EMPTY; //sets all elements to enum Empty } //Position search; //will search for a postion PieceType p; //what piece we will find int pos1, pos2, counter =0; //search.x = pos.x - 1; // x and y that are passe into the function as pos //search.y = pos.y -1; for(int i = -1; i < 2;i++){ //will traverse the i colms and j the rows of the grid pos1 = pos.x + i; //finds the x cordinate for(int j = -1; j < 2; j++) { pos2 = pos.y + j; //will find the y cordinate //base condtion where the position is outside the grid if (pos1 < 0 || pos1 >= __height || pos2 < 0 || pos2 >= __width) { surround.array[counter] = INACCESSIBLE; //will set that position as inaccesible } else { if (__grid[pos2 + (pos1 * __width)] && counter !=4) { //base condition where it checks if that part of the grid has a object in it p = __grid[pos2 + (pos1 * __width)]->getType(); //will get the type of piece or object that is at that part of the grid and will set that equal to our piece type variable p surround.array[counter] = p; } } counter++; //will increment counter since the task did not find a move } } //todo check if this works return surround; //will return the Surroundings } const ActionType Game::reachSurroundings(const Position &from, const Position &to) { //base condition //if(from.x == to.x && from.y == to.y){ if(from.x == to.x && from.y == to.y){ return STAY; //means that the piece stayed } //WHERE THE PIECE MOVES (N,S,E,W,NE,NW,SE,SW)////////////////// //todo check which one works for N //if(to.x == from.x && to.y == from.y == to.y -1) //return N if(to.x == from.x -1 && to.y == from.y) return N; //moved up one on grid else if(to.x == from.x+1 && to.y == from.y) return S; //moved down one on grid else if(to.x == from.x && to.y == from.y+1) return E; //moved right on the grid else if(to.x == from.x + 1 && to.y == from.y + 1) return SE; //moved down one and right one on the grid else if(to.x == from.x-1 && to.y == from.y +1) return NE; //moved up one and right one on the grid else if(to.x == from.x && to.y == from.y-1) return W; //moved left one on the grid else if(to.x == from.x -1 && to.y == from.y - 1) return NW; //moved up one and left one else if(to.x == from.x +1 && to.y == from.y -1) return SW; //moved down one and left one on the grid ///////////END OF WHERE THE PiECE MOVES ON THE GRID//////////////// } bool Game::isLegal(const ActionType &ac, const Position &pos) const { //exceptiond if (pos.x < 0 || pos.x >= __height || pos.y < 0 || pos.y >= __width) throw OutOfBoundsEx(__width, __height, pos.x, pos.y); Surroundings surround; surround = getSurroundings(pos); //surround will be qual to the surroudings recieved from whats passed into th function pos bool isLeg = false; //or maybe false IDK //todo switch statments or if statments where we will make each case in tha surrounds either true or false //PASS action type into the switch switch(ac){ case N: if (surround.array[1] != INACCESSIBLE) isLeg = true; break; case NE: if (surround.array[2] != INACCESSIBLE) isLeg = true; break; case NW: if (surround.array[0] != INACCESSIBLE) isLeg = true; break; case E: if (surround.array[5] != INACCESSIBLE) isLeg = true; break; case W: if (surround.array[3] != INACCESSIBLE) isLeg = true; break; case SE: if (surround.array[8] != INACCESSIBLE) isLeg = true; break; case SW: if (surround.array[6] != INACCESSIBLE) isLeg = true; break; case S: if (surround.array[7] != INACCESSIBLE) isLeg = true; break; case STAY: isLeg = true; break; } //each case will be for what direction it moves in the switch statement //todo//// return isLeg; //if its true or false } //we assume legal and use isLegal const Position Game::move(const Position &pos, const ActionType &ac) const { Position shino(pos.x, pos.y); if(isLegal(ac,pos)){ switch(ac){ //when it goes left its ++ and right its -- for x //y goes down when its ++ and goes up when -- case N: shino.x--; //y goes up one break; case NE: shino.x--; //y goes up one and right one shino.y++; break; case NW: shino.y--; //y goes up one and left one shino.x--; break; case W: shino.y--; //x gors lrft onr break; case E: shino.y++; //x goes right one break; case S: shino.x++; //y goes down one break; case SE: shino.y++; //y goes down one and x goes righ one shino.x++; break; case SW: shino.x++; //y goes down and x goes left one shino.y--; break; case STAY: //we leave STAY blank since the piece does not move ta all break; } } return shino; // dont forget to down throw } void Game::round() { //using the set example algorithm from the read me std::set<Piece*> board; Position pos, Newpos; ActionType action; Piece* pptr; int location; for (auto it = __grid.begin(); it < __grid.end(); ++it) { if (*it != nullptr) { board.insert(board.end(),*it); (*it)->setTurned(false); //resets the pieces so that they can take a turn this will reset after each round } } for (auto it = board.begin(); it != board.end(); ++it) { if ((*it)->isViable()&& (*it)->getTurned()) { (*it)->age(); (*it)->setTurned(true); pos = (*it)->getPosition(); //will pass a pieces position or location in action = (*it)->takeTurn(getSurroundings(pos)); //piece takes a turn for each Newpos = this->move(pos, action); //passes the new location into the new variabale location = Newpos.y + (Newpos.x * __width); pptr = __grid[location]; if(pos.x != Newpos.x && pos.y != Newpos.y){ //checks if new pos and the current pos arent n the same location if (pptr != nullptr) { //this happens if the piece wants to move to annother spot hwere there is another piece in it soit will challnege or cosume if its a resource (*(*it)* *pptr); //this means that the pieces interact and we will pass some if statmnts if ((*it)->isViable()) { //if it didn't get consumed we pass it set new position (*it)->setPosition(Newpos); __grid[Newpos.y + (Newpos.x * __width)] = *it; //will change the grid and set equal to it and also set it equal to nullptr __grid[pos.y + (pos.x * __width)] = nullptr; } else { //when a resource gets consumed you set that location = to null ptr __grid[pos.y + (pos.x * __width)] = nullptr; } } } else { __grid[Newpos.y + (Newpos.x * __width)] = *it; //else to the other staments if the position is emoyty } } } for (int i = 0; i < __grid.size(); ++i) { //if (!__grid[i]->isViable() && __grid[i] != nullptr) { if(__grid[i] != nullptr && !__grid[i]->isViable()){ delete __grid[i]; __grid[i] = nullptr; } } if (getNumResources() == 0) this->__status = OVER; //we need to increment the round after it is over __round++; } void Game::play(bool verbose) { __status = PLAYING; //returns the stauts that the game is playing __verbose = verbose; //returns verbose when its verbose lol if(__verbose) { std::cout << this; //will print out the location of the piece from the grid } while (__status != OVER) { round(); //if the status of the game is not over the game will comtimue to play through if (__verbose) //this will show what was going on the game when the game eas not over std::cout << *this; } if (__verbose) std::cout << this; //this will print out the location aka the cordinates of the pieces when the game is finished } std::ostream &operator<<(std::ostream &os, const Game &game) { //todo work on print int x = game.__width, y = game.__height; os << "Round: " << game.__round << std::endl; for (int i = 0; i < x; ++i) { for (int j = 0; j < y; ++j) { if (game.__grid[j + (i * (game.__width - 1))] == nullptr) os << "[ ]"; else os << std::setw(5) << game.__grid[j + (i * (game.__width - 1))] << "]"; } os << std::endl; } os << "Status: " << game.getStatus() << std::endl; return os; } }
namespace Gaming { const unsigned int Game::NUM_INIT_AGENT_FACTOR = 4; const unsigned int Game::NUM_INIT_RESOURCE_FACTOR = 2; const unsigned Game::MIN_WIDTH = 3; const unsigned int Game::MIN_HEIGHT = 3; const double Game::STARTING_AGENT_ENERGY = 20; const double Game::STARTING_RESOURCE_CAPACITY = 10; PositionRandomizer Game::__posRandomizer = PositionRandomizer(); void Game::populate() { std::default_random_engine gen; std::uniform_int_distribution<int> d(0, __width * __height); __numInitAgents = (__width * __height) / NUM_INIT_AGENT_FACTOR; __numInitResources = (__width * __height) / NUM_INIT_RESOURCE_FACTOR; unsigned int numStrategic = __numInitAgents / 2; unsigned int numSimple = __numInitAgents - numStrategic; unsigned int numAdvantages = __numInitResources / 4; unsigned int numFoods = __numInitResources - numAdvantages; while (numStrategic > 0) { int i = d(gen); if (i != (__width * __height) && __grid[i] == nullptr) { Position pos(i / __width, i % __width); __grid[i] = new Strategic(*this, pos, STARTING_AGENT_ENERGY); numStrategic--; } } while (numSimple > 0) { int i = d(gen); if (i != (__width * __height) && __grid[i] == nullptr) { Position pos(i / __width, i % __width); __grid[i] = new Simple(*this, pos, STARTING_AGENT_ENERGY); numSimple--; } } while (numFoods > 0) { int i = d(gen); if (i != (__width * __height) && __grid[i] == nullptr) { Position pos(i / __width, i % __width); __grid[i] = new Food(*this, pos, STARTING_RESOURCE_CAPACITY); numFoods--; } } while (numAdvantages > 0) { int i = d(gen); if (i != (__width * __height) && __grid[i] == nullptr) { Position pos(i / __width, i % __width); __grid[i] = new Advantage(*this, pos, STARTING_RESOURCE_CAPACITY); numAdvantages--; } } } Game::Game():__width(3), __height(3) { for (unsigned i = 0; i < (__width * __height); ++i) { __grid.push_back(nullptr); } __status = NOT_STARTED; __verbose = false; __round = 0; } Game::Game(unsigned width, unsigned height, bool manual) { if (width < MIN_WIDTH || height < MIN_HEIGHT) { throw InsufficientDimensionsEx(MIN_WIDTH, MIN_HEIGHT, width, height); } __status = NOT_STARTED; __verbose = false; __round = 0; __width = width; __height = height; for (unsigned i = 0; i < (__width * __height); ++i) { __grid.push_back(nullptr); } if (!manual) { populate(); } } Game::~Game() { for (auto position = __grid.begin(); position != __grid.end(); ++position) { if (*position != nullptr) { delete *position; } } } //getters unsigned int Game::getNumPieces() const { int numPieces = 0; for (auto position = __grid.begin(); position != __grid.end(); ++position) { if (*position != nullptr) { numPieces++; } } return numPieces; } unsigned int Game::getNumAgents() const { unsigned int agents = 0; for (auto simA = __grid.begin(); simA != __grid.end(); ++simA) { Agent *simple = dynamic_cast<Agent*>(*simA); if (simple) agents++; } return agents; } unsigned int Game::getNumSimple() const { unsigned int simples = 0; for (auto simA = __grid.begin(); simA != __grid.end(); ++simA) { Simple *simple = dynamic_cast<Simple*>(*simA); if (simple) simples++; } return simples; } unsigned int Game::getNumStrategic() const { unsigned int strategic = 0; for (auto strat = __grid.begin(); strat != __grid.end(); ++strat) { Strategic *simple = dynamic_cast<Strategic*>(*strat); if (simple) strategic++; } return strategic; } unsigned int Game::getNumResources() const { unsigned int resources = 0; for (auto resource = __grid.begin(); resource != __grid.end(); ++resource) { Resource *simple = dynamic_cast<Resource*>(*resource); if (simple) resources++; } return resources; } const Piece * Game::getPiece(unsigned int x, unsigned int y) const { if (y >= __width || x >= __height) { throw OutOfBoundsEx(__width, __height, x, y); } if (__grid[y + (x * __width)] == nullptr) { throw PositionEmptyEx(x, y); } return __grid[y + (x * __width)]; } //Population void Game::addSimple(const Position &position) { int index = position.y + (position.x * __width); if (position.y >= __width || position.x >= __height) { throw OutOfBoundsEx(__width, __height, position.x, position.y); } if (__grid[index]) { throw PositionNonemptyEx(position.x, position.y); } __grid[index] = new Simple(*this, position, STARTING_AGENT_ENERGY); } void Game::addSimple(const Position &position, double energy) { int index = position.y + (position.x * __width); if (position.y >= __width || position.x >= __height) { throw OutOfBoundsEx(__width, __height, position.x, position.y); } if (__grid[index]) { throw PositionNonemptyEx(position.x, position.y); } __grid[index] = new Simple(*this, position, energy); } void Game::addSimple(unsigned x, unsigned y) { int index = y + (x * __width); if (y >= __width || x >= __height) { throw OutOfBoundsEx(__width, __height, x, y); } if (__grid[index]) { throw PositionNonemptyEx(x, y); } __grid[index] = new Simple(*this, Position(x, y), STARTING_AGENT_ENERGY); } void Game::addSimple(unsigned y, unsigned x, double energy) { int index = y + (x * __width); if (y >= __width || x >= __height) { throw OutOfBoundsEx(__width, __height, x, y); } if (__grid[index]) { throw PositionNonemptyEx(x, y); } __grid[index] = new Simple(*this, Position(x, y), energy); } void Game::addStrategic(const Position &position, Strategy *s) { int index = position.y + (position.x * __width); if (position.y >= __width || position.x >= __height) { throw OutOfBoundsEx(__width, __height, position.x, position.y); } if (__grid[index]) { throw PositionNonemptyEx(position.x, position.y); } __grid[index] = new Strategic(*this, position, STARTING_AGENT_ENERGY, s); } void Game::addStrategic(unsigned x, unsigned y, Strategy *s) { int index = y + (x * __width); if (y >= __width || x >= __height) { throw OutOfBoundsEx(__width, __height, x, y); } if (__grid[index]) { throw PositionNonemptyEx(x, y); } __grid[index] = new Strategic(*this, Position(x, y), STARTING_AGENT_ENERGY, s); } void Game::addFood(const Position &position) { int index = position.y + (position.x * __width); if (position.y >= __width || position.x >= __height) { throw OutOfBoundsEx(__width, __height, position.x, position.y); } if (__grid[index]) { throw PositionNonemptyEx(position.x, position.y); } __grid[index] = new Food(*this, position, STARTING_RESOURCE_CAPACITY); } void Game::addFood(unsigned x, unsigned y) { int index = y + (x * __width); if (y >= __width || x >= __height) { throw OutOfBoundsEx(__width, __height, x, y); } if (__grid[index]) { throw PositionNonemptyEx(x, y); } __grid[index] = new Food(*this, Position(x, y), STARTING_RESOURCE_CAPACITY); } void Game::addAdvantage(const Position & position) { int index = position.y + (position.x * __width); if (position.y >= __width || position.x >= __height) { throw OutOfBoundsEx(__width, __height, position.x, position.y); } if (__grid[index]) { throw PositionNonemptyEx(position.x, position.y); } __grid[index] = new Advantage(*this, position, STARTING_RESOURCE_CAPACITY); } void Game::addAdvantage(unsigned x, unsigned y) { int index = y + (x * __width); if (y >= __width || x >= __height) { throw OutOfBoundsEx(__width, __height, x, y); } if (__grid[index]) { throw PositionNonemptyEx(x, y); } __grid[index] = new Advantage(*this, Position(x, y), STARTING_RESOURCE_CAPACITY); } const Surroundings Game::getSurroundings(const Position & pos) const { Surroundings sur; for (int i = 0; i < 9; ++i) { sur.array[i] = EMPTY; } for (int row = -1; row <= 1; ++row) { for (int col = -1; col <= 1; ++col) { if (pos.x + row >= 0 && pos.x + row < __height && pos.y + col >= 0 && pos.y + col < __width) { unsigned int index = pos.y + col + ((pos.x + row) * __width); if (__grid[index]) { sur.array[col + 1 + ((row + 1) * 3)] = __grid[index]->getType(); } } else { sur.array[col + 1 + ((row + 1) * 3)] = INACCESSIBLE; } } } sur.array[4] = SELF; return sur; } //Methods const ActionType Game::reachSurroundings(const Position & from, const Position & to) { int x; int y; x = to.x - from.x; y = to.y - from.y; x++; y++; unsigned int index = (y + (x * 3)); switch (index) { case 0: return NW; case 1: return N; case 2: return NE; case 3: return W; case 4: return STAY; case 5: return E; case 6: return SW; case 7: return S; case 8: return SE; default: return STAY; } } bool Game::isLegal(const ActionType & ac, const Position & pos) const { int x, y; x = pos.x; y = pos.y; switch (ac) { case N: x--; break; case NE: y++; x--; break; case E: y++; break; case SE: x++; y++; break; case S: x++; break; case SW: y--; x++; break; case W: y--; break; case NW: y--; x--; break; default: break; } Position newP((unsigned)x, (unsigned)y); if (newP.x < __height &&newP.y < __width) { return true; } else { return false; } } const Position Game::move(const Position & pos, const ActionType & ac) const { if (isLegal(ac, pos)) { int x, y; x = pos.x; y = pos.y; switch (ac) { case N: x--; break; case NE: y++; x--; break; case E: y++; break; case SE: x++; y++; break; case S: x++; break; case SW: y--; x++; break; case W: y--; break; case NW: y--; x--; break; default: break; } Position newP((unsigned)x, (unsigned)y); return newP; } return pos; } void Game::round() { std::set<Piece*> gamePieces; for (auto reset = __grid.begin(); reset != __grid.end(); ++reset) { if (*reset) { gamePieces.insert(gamePieces.end(), *reset); (*reset)->setTurned(false); } } for (auto turn = gamePieces.begin(); turn != gamePieces.end(); ++turn) { if (!(*turn)->getTurned()) { (*turn)->setTurned(true); (*turn)->age(); ActionType ac = (*turn)->takeTurn(getSurroundings((*turn)->getPosition())); Position pBefore = (*turn)->getPosition(); Position pAfter = move(pBefore, ac); if (pBefore.x != pAfter.x || pBefore.y != pAfter.y) { Piece *p = __grid[pAfter.y + (pAfter.x * __width)]; if (p) { (*(*turn)) * (*p); if ((*turn)->getPosition().x != pBefore.x || (*turn)->getPosition().y != pBefore.y) { __grid[pAfter.y + (pAfter.x * __width)] = (*turn); __grid[pBefore.y + (pBefore.x * __width)] = p; } } else { (*turn)->setPosition(pAfter); __grid[pAfter.y + (pAfter.x * __width)] = (*turn); __grid[pBefore.y + (pBefore.x * __width)] = nullptr; } } } } for (unsigned int i = 0; i < __grid.size(); ++i) { if (__grid[i] && !(__grid[i]->isViable())) { delete __grid[i]; __grid[i] = nullptr; } } if (getNumResources() <= 0) { __status = Status::OVER; } __round++; } void Game::play(bool verbose) { __verbose = verbose; __status = PLAYING; std::cout << *this; while (__status != OVER) { round(); if (verbose) { std::cout << *this; } } if (!verbose) { std::cout << *this; } } std::ostream & operator<<(std::ostream & os, const Game & game) { int column = 0; os << "Round " << game.getRound() << ":" << "\n"; for (auto place = game.__grid.begin(); place != game.__grid.end(); place++) { if (*place == nullptr) { os << "[" << std::setw(5) << "]"; } else { std::stringstream ss; ss << "[" << **place; std::string objectIn; std::getline(ss, objectIn); os << objectIn << "]"; } if (++column == game.getWidth()) { column = 0; os << "\n"; } } os << "Status: "; switch (game.getStatus()) { case Game::Status::NOT_STARTED: std::cout << "Not Started..." << std::endl; break; case Game::Status::PLAYING: std::cout << "Playing..." << std::endl; break; default: std::cout << "Over!" << std::endl; break; } return os; } }