tom dunigan
/
antsnbugs
stochastic simulation, predator/prey
Diff: World.cpp
- 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(); + } + } + } +}