Beispiel #1
0
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();
}
Beispiel #2
0
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);

}
Beispiel #3
0
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;
    }
    
}
Beispiel #4
0
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;

    }

}
Beispiel #5
0
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;
    }


}
Beispiel #6
0
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) {

    }


}
Beispiel #7
0
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;
    }
}
Beispiel #8
0
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;
    }
}
Beispiel #10
0
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;
		
	}

}