// take a step in the simulation // Move all of the critters and handle collisions. void CritterModel::step() { moveCount++; std::cout << "\n Beginning simulation move #" << moveCount << std::endl; // it's not quite fair to the critters in the lower right section // of the map, but it's easy to track the progress, iterate // through the map moving each critter for(unsigned int x = 0; x < width; x++) { for(unsigned int y = 0; y < height; y++) { Critter *currCritter = grid[x][y]; // if there's no critter here, move on if(currCritter == NULL || currCritter->hasGone()) { continue; } //update the critter about some state of it's world that //it may care about: currCritter->setAlive(true); currCritter->setX(x); currCritter->setY(y); currCritter->setWidth(width); currCritter->setHeight(height); Critter *neighbor = discoverNeighbor(NORTH, x, y, NULL, NULL); currCritter->setNeighbor(NORTH, neighbor == NULL ? EMPTY_NEIGHBOR : neighbor->getChar()); neighbor = discoverNeighbor(SOUTH, x, y, NULL, NULL); currCritter->setNeighbor(SOUTH, neighbor == NULL ? EMPTY_NEIGHBOR : neighbor->getChar()); neighbor = discoverNeighbor(EAST, x, y, NULL, NULL); currCritter->setNeighbor(EAST, neighbor == NULL ? EMPTY_NEIGHBOR : neighbor->getChar()); neighbor = discoverNeighbor(WEST, x, y, NULL, NULL); currCritter->setNeighbor(WEST, neighbor == NULL ? EMPTY_NEIGHBOR : neighbor->getChar()); currCritter->beginTurn(); // move the critter! grid[x][y] = NULL; Direction move = currCritter->getMove(); unsigned int newX, newY; neighbor = discoverNeighbor(move, x, y, &newX, &newY); if(neighbor == NULL) { grid[newX][newY] = currCritter; currCritter->setX(newX); currCritter->setY(newY); } else if(currCritter->getChar() != neighbor->getChar()) { // two critters of different kinds, fight! // Note: we use the getChar method of your critters to // determine if your critters are "the same". This // models the idea that the critter looks at the other // critter to determine whether it should fight. Also // as a bonus, you could try to be sneaky about hiding // from your neighbors! currCritter->setX(newX); currCritter->setY(newY); if(DEBUG) { std::cout << currCritter->getChar() << " versus " << neighbor->getChar() << ": "; } Attack attack = currCritter->fight(neighbor->getChar()); Attack defend = neighbor->fight(currCritter->getChar()); Critter *winner; // do rock paper scissors here if(attack == defend) { // coin flip for tie winner = rand() % 2 == 0 ? currCritter : neighbor; } else { switch(attack) { case ROAR: // only a POUNCE defense wins (SCRATCH or FORFEIT will be a win) winner = defend == POUNCE ? neighbor : currCritter; break; case POUNCE: // only a SCRATCH defense wins (ROAR or FORFEIT will be a win) winner = defend == SCRATCH ? neighbor : currCritter; break; case SCRATCH: // only a ROAR defense loses (POUNCE or FORFEIT will be a win) winner = defend == ROAR ? neighbor : currCritter; break; default: // FORFEIT // dead winner = neighbor; break; } } Critter *loser = currCritter == winner ? neighbor : currCritter; if(DEBUG) { std::cout << winner->getChar() << " wins!" << std::endl; } winner->win(); loser->lose(); loser->setAlive(false); delete loser; grid[newX][newY] = winner; } else { // don't move onto your sibling! newX = x; newY = y; grid[newX][newY] = currCritter; } // make sure that currCritter isn't dead, and if not, mark it and // let it know that its turn is over. if(grid[newX][newY] == currCritter) { currCritter->setMark(); currCritter->endTurn(); } } } for(unsigned int x = 0; x < width; x++) { for(unsigned int y = 0; y < height; y++) { Critter *currCritter = grid[x][y]; // if there's no critter here, move on if(currCritter == NULL) { continue; } currCritter->clearMark(); } } }