stochastic simulation, predator/prey

Dependencies:   mbed

World.cpp

Committer:
manitou
Date:
2019-12-23
Revision:
0:fc1335b7b54f

File content as of revision 0:fc1335b7b54f:

#include "mbed.h"

#include "World.h"
#include "Ant.h"
#include "Bug.h"

extern Timer tmr;
#define micros tmr.read_us

#define CELL 9

int nabors[NABORS];


///////////////////
// Public functions
///////////////////

// Default constructor: creates and initializes the world
// the seed is used for seeding the random behaviour.
World::World(unsigned int seed) {
  srand(seed);             // seed the random generator
  steps = 0;
  step_us = 0;
  for(int i=0; i < NABORS; i++) nabors[i] =i;
  // Create an empty world
  for (int i = 0; i < ROWS; i++) {
    for (int j = 0; j < COLS; j++) {
      grid[i][j] = NULL;
    }
  }
  // creates the ants = 3
  createOrganisms(ANT, INITIAL_ANTS);
  // creates the bugs = 8
  createOrganisms(BUG, INITIAL_BUGS);
}

// Deallocate memory allocated to organisms in this world.
World::~World() {
  for (int i = 0; i < ROWS; i++) {
    for (int j = 0; j < COLS; j++) {
      if (grid[i][j] != NULL) {
        delete grid[i][j];
      }
    }
  }
}

// Return the organism at the given coordinates
// If the coordinates are not valid, returns NULL
Organism* World::getAt(int x, int y) const {
  if ((x >= 0) && (x < ROWS) && (y >= 0) && (y < COLS)) {
    return grid[x][y];
  } else {
    return NULL;
  }
}

// Sets the entry at x,y to the value passed in.
void World::setAt(int x, int y, Organism* org) {
  if ((x >= 0) && (x < ROWS) && (y >= 0) && (y < COLS)) {
    grid[x][y] = org;
  }
}

// Displays the world in ASCII.
void World::print() const {

  printf("\n");
  for (int i = 0; i < ROWS; i++) {
    for (int j = 0; j < COLS; j++) {
      if (grid[i][j] == NULL) {
        printf( ".");
      } else {
        printf("%c", grid[i][j]->representation());
      }
    }
    printf("\n");
  }
  // cout << "Ants: " << numAnts << " Bugs: " << numBugs << endl;
  printf("Ants: %d  Bugs: %d steps %d  %d us\n",counter<Ant>::objects_alive,counter<Bug>::objects_alive,steps,step_us);
  #if 0
  Serial.print("Ants: "); Serial.print(counter<Ant>::objects_alive);
  Serial.print("  Bugs: "); Serial.print(counter<Bug>::objects_alive);
  Serial.print("  steps: "); Serial.print(steps);
  Serial.print(" "); Serial.print(step_us); Serial.println(" us");
  #endif
}

// for serialplotter
void World::plot() const {
  //Serial.print("Ants: "); Serial.print(counter<Ant>::objects_alive);
  //Serial.print("  Bugs: "); Serial.println(counter<Bug>::objects_alive);
  //Serial.println(step_us);
}



void World::simulateOneStep() {
  // The main routine that simulates one turn in the world:
  // 1. move bugs
  // 2. move ants
  // 3. make bugs starve (which happends under a certain condition)
  // 4. make the organisms breed (again which happens under a certain
  // condition).

  steps++;
  step_us = micros();
    // shuffle nabors
  for (int i=0; i< NABORS; i++) {
    int n = rand() % NABORS;
    int tmp = nabors[n];
    nabors[n] = nabors[i];
    nabors[i] = tmp;
  }
  // Reset all organisms to not moved
  resetOrganisms();

  // Move the bugs
  moveOrganism(BUG);

  // Move the ants
  moveOrganism(ANT);

  // Make the bugs starve
  cleanup();

  //Make them breed
  breedOrganisms();
  step_us = micros() - step_us;
}

Position World::randomPosition() const {    // returns a random number in the range 0 to MAX-1
  Position p;
  p.x = rand() % ROWS;
  p.y = rand() % COLS;
  return p;
}


Move World::randomMove() const {
  return static_cast<Move>(rand() % 4);
}

////////////////////
// Private functions
////////////////////

void World::createOrganisms(OrganismType orgType, int count) {
  int orgCount = 0;
  while (orgCount < count) {
    Position p = randomPosition();

    // Only put ant in empty spot
    if (grid[p.x][p.y] == NULL) {
      orgCount++;
      if (orgType == ANT) {
        new Ant(this, p.x, p.y);   // Create an Ant and put it into the world
      }
      else if (orgType == BUG) {
        new Bug(this, p.x, p.y);   // Create a Bug and put it into the world
      }
    }
  }
}

// Reset all organisms to not moved
void World::resetOrganisms() {
  for (int i = 0; i < ROWS; i++)
  {
    for (int j = 0; j < COLS; j++)
    {
      if (grid[i][j] != NULL)
      {
        grid[i][j]->setMoved(false);
      }
    }
  }
}

// Move all organisms of type aType
void World::moveOrganism(OrganismType aType) {
  for (int i = 0; i < ROWS; i++)
  {
    for (int j = 0; j < COLS; j++)
    {
      if (grid[i][j] != NULL)
      {
        if (grid[i][j]->getType() == aType && !(grid[i][j]->hasMoved()))
        {
          grid[i][j]->move();
        }
      }
    }
  }
}

// Remove all dead organisms from this world.
void World::cleanup() {
  for (int i = 0; i < ROWS; i++) {
    for (int j = 0; j < COLS; j++) {
      // Kill off any organisms that haven't eaten recently
      if ((grid[i][j] != NULL) && grid[i][j]->isDead()) {
        delete grid[i][j];
        grid[i][j] = NULL;
      }
    }
  }
}

// Make the organisms breed
void World::breedOrganisms() {
  for (int i = 0; i < ROWS; i++)
  {
    for (int j = 0; j < COLS; j++)
    {
      if (grid[i][j] != NULL)
      {
        grid[i][j]->breed();
      }
    }
  }
}