stochastic simulation, predator/prey

Dependencies:   mbed

Revision:
0:fc1335b7b54f
--- /dev/null	Thu Jan 01 00:00:00 1970 +0000
+++ b/World.cpp	Mon Dec 23 18:56:56 2019 +0000
@@ -0,0 +1,223 @@
+#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();
+      }
+    }
+  }
+}