Advertisement
Not a member of Pastebin yet?
Sign Up,
it unlocks many cool features!
- //
- // Created by Julia Sanguinetti on 2019-10-16.
- //
- #include <time.h>
- #include <cstdio>
- #include <cstdlib>
- #include <iostream>
- #include <string>
- #include <vector>
- using namespace std;
- // Constants
- const int WORLDSIZE = 20;
- const int INITIAL_ANTS = 20;
- const int INITIAL_DOODLEBUGS = 5;
- const int DOODLEBUG = 1;
- const int ANT = 2;
- const int ANT_BREED = 3;
- const int DOODLE_BREED = 8;
- const int DOODLE_STARVE = 3;
- // Declarations of classes
- class Organism;
- class Doodlebug;
- class Ant;
- // World class
- class World {
- public:
- // Constructor
- World();
- // Destructor
- ~World();
- Organism *getAt(int x, int y);
- void setAt(int x, int y, Organism *org);
- void display();
- void oneTurn();
- bool withinBoundaries(int x, int y);
- private:
- Organism *grid[WORLDSIZE][WORLDSIZE];
- void oneTurnForType(int type);
- };
- // Definition for the Organism base class
- class Organism {
- friend class World;
- public:
- // Constructors
- Organism();
- Organism(World *wrld, int x, int y);
- // Destructor
- virtual ~Organism() { world->setAt(x, y, nullptr); }
- // Methods
- virtual void breed() = 0;
- virtual void move() = 0;
- virtual int getType() = 0;
- virtual bool starve() = 0;
- protected:
- int x, y;
- bool moved;
- int breedCount;
- World *world;
- void basicMove();
- private:
- void moveIfPossible(int x, int y);
- };
- void Organism::moveIfPossible(int x, int y) {
- if (world->withinBoundaries(x, y) && world->getAt(x, y) == nullptr) {
- world->setAt(x, y, this);
- world->setAt(this->x, this->y, nullptr);
- this->x = x;
- this->y = y;
- }
- }
- void Organism::basicMove() {
- int dir = rand() % 4;
- // Try to move up, if not at an edge and empty spot
- if (dir == 0) {
- Organism::moveIfPossible(x, y + 1);
- }
- // Try to move down
- else if (dir == 1) {
- Organism::moveIfPossible(x, y - 1);
- }
- // Try to move left
- else if (dir == 2) {
- Organism::moveIfPossible(x - 1, y);
- }
- // Try to move right
- else {
- Organism::moveIfPossible(x + 1, y);
- }
- }
- // Constructor definition
- World::World() {
- int i, j;
- for (i = 0; i < WORLDSIZE; i++) {
- for (j = 0; j < WORLDSIZE; j++) grid[i][j] = nullptr;
- }
- }
- // Destructor definition
- World::~World() {
- // Release any allocated memory
- for (int i = 0; i < WORLDSIZE; i++) {
- for (int j = 0; j < WORLDSIZE; j++) {
- if (grid[i][j] != nullptr) delete grid[i][j];
- }
- }
- }
- bool World::withinBoundaries(int x, int y) {
- return (0 <= x) && (x < WORLDSIZE) && (0 <= y) && (y < WORLDSIZE);
- }
- // Member function definitions
- Organism *World::getAt(int x, int y) {
- if (withinBoundaries(x, y)) return grid[x][y];
- return nullptr;
- }
- // Method definition of setAt
- void World::setAt(int x, int y, Organism *org) { grid[x][y] = org; }
- // Method definition of display
- void World::display() {
- for (int j = 0; j < WORLDSIZE; j++) {
- for (int i = 0; i < WORLDSIZE; i++) {
- if (grid[i][j] == nullptr)
- cout << '-';
- else if (grid[i][j]->getType() == ANT)
- cout << 'o';
- else
- cout << "X";
- }
- cout << endl;
- }
- }
- void World::oneTurnForType(int type) {
- for (int i = 0; i < WORLDSIZE; i++) {
- for (int j = 0; j < WORLDSIZE; j++) {
- Organism *organism = grid[i][j];
- if (organism != nullptr && organism->getType() == type) {
- if (!organism->moved) {
- organism->moved = true;
- organism->move();
- organism->breed();
- }
- if (organism->getType() == DOODLEBUG && organism->starve()) {
- delete organism;
- }
- }
- }
- }
- }
- // Method definition of oneTurn
- void World::oneTurn() {
- // First reset all organism to not move
- for (int i = 0; i < WORLDSIZE; i++) {
- for (int j = 0; j < WORLDSIZE; j++) {
- if (grid[i][j] != nullptr) grid[i][j]->moved = false;
- }
- }
- oneTurnForType(DOODLEBUG);
- oneTurnForType(ANT);
- }
- // Default constructor of Organism
- Organism::Organism() {
- world = nullptr;
- moved = false;
- breedCount = 0;
- x = 0;
- y = 0;
- }
- Organism::Organism(World *wrld, int x, int y) {
- this->world = wrld;
- moved = true;
- breedCount = 0;
- this->x = x;
- this->y = y;
- wrld->setAt(x, y, this);
- }
- // Ant class
- class Ant : public Organism {
- public:
- friend class World;
- // Constructors
- Ant() = default;
- Ant(World *wrld, int x, int y) : Organism(wrld, x, y){};
- // Methods
- void breed() override;
- void move() override;
- int getType() override;
- bool starve() override { return false; }
- };
- // Method definition of move
- void Ant::move() { Organism::basicMove(); }
- // Method definition of getType
- int Ant::getType() { return ANT; }
- // Method definition of breed
- void Ant::breed() {
- breedCount++;
- if (breedCount == ANT_BREED) {
- breedCount = 0;
- // Try to make a new any either above, left, right, below
- if ((y > 0) && (world->getAt(x, y - 1) == nullptr))
- new Ant(world, x, y - 1);
- else if ((y < WORLDSIZE - 1) && (world->getAt(x, y + 1) == nullptr))
- new Ant(world, x, y + 1);
- else if ((x > 0) && (world->getAt(x - 1, y) == nullptr))
- new Ant(world, x - 1, y);
- else if ((x < WORLDSIZE - 1) && (world->getAt(x + 1, y) == nullptr))
- new Ant(world, x + 1, y);
- }
- }
- // Create a class Doodlebug
- class Doodlebug : public Organism {
- public:
- friend class World;
- public:
- Doodlebug();
- Doodlebug(World *world, int x, int y);
- void breed() override;
- void move() override;
- int getType() override;
- bool starve() override;
- private:
- int starveTricks;
- bool eatAndMoveIfPossible(int x, int y);
- };
- // Default constructor
- Doodlebug::Doodlebug() { starveTricks = 0; }
- // Constructor with parameters
- Doodlebug::Doodlebug(World *world, int x, int y) : Organism(world, x, y) {
- starveTricks = 0;
- }
- bool Doodlebug::eatAndMoveIfPossible(int x, int y) {
- if (world->withinBoundaries(x, y) && (world->getAt(x, y) != nullptr) &&
- (world->getAt(x, y)->getType() == ANT)) {
- delete world->getAt(x, y);
- world->setAt(x, y, this);
- world->setAt(this->x, this->y, nullptr);
- starveTricks = 0;
- this->x = x;
- this->y = y;
- return true;
- }
- return false;
- }
- // Member functions
- void Doodlebug::move() {
- bool ate = eatAndMoveIfPossible(x, y + 1);
- if (!ate) ate = eatAndMoveIfPossible(x + 1, y);
- if (!ate) ate = eatAndMoveIfPossible(x, y - 1);
- if (!ate) ate = eatAndMoveIfPossible(x - 1, y);
- if (ate) return;
- // Increment starve tick since didn't eat on this turn
- Organism::basicMove();
- starveTricks++;
- }
- // Method definition of getType
- int Doodlebug::getType() { return DOODLEBUG; }
- // Method definition of breed
- void Doodlebug::breed() {
- breedCount++;
- if (breedCount == DOODLE_BREED) {
- breedCount = 0;
- // Try to make a new ant either above, left, right, or down
- if ((y > 0) && (world->getAt(x, y - 1) == nullptr)) {
- new Doodlebug(world, x, y - 1);
- } else if ((y < WORLDSIZE - 1) && (world->getAt(x, y + 1) == nullptr)) {
- new Doodlebug(world, x, y + 1);
- } else if ((x > 0) && (world->getAt(x - 1, y) == nullptr)) {
- new Doodlebug(world, x - 1, y);
- } else {
- new Doodlebug(world, x + 1, y);
- }
- }
- }
- // Method definition of starve
- bool Doodlebug::starve() {
- // Starve if no food eaten in last DOODLE_STARVE time ticks
- return starveTricks >= DOODLE_STARVE;
- }
- int main() {
- // Seed random number generator
- srand(time(nullptr));
- World w;
- // Randomly create 100 ants
- int antCount = 0;
- while (antCount < INITIAL_ANTS) {
- int x = rand() % WORLDSIZE;
- int y = rand() % WORLDSIZE;
- // Check for empty spots
- if (w.getAt(x, y) == nullptr) {
- new Ant(&w, x, y);
- antCount++;
- }
- }
- // Randomly create 5 doodlebugs
- int doodleCount = 0;
- while (doodleCount < INITIAL_DOODLEBUGS) {
- int x = rand() % WORLDSIZE;
- int y = rand() % WORLDSIZE;
- // Check for empty spots
- if (w.getAt(x, y) == nullptr) {
- new Doodlebug(&w, x, y);
- doodleCount++;
- }
- }
- // Run simulation until user cancels
- do {
- w.display();
- w.oneTurn();
- cout << '\n' << "Press enter to continue...";
- } while (cin.get() == '\n');
- return 0;
- }
Advertisement
Add Comment
Please, Sign In to add comment
Advertisement