tom dunigan
/
antsnbugs
stochastic simulation, predator/prey
Revision 0:fc1335b7b54f, committed 2019-12-23
- Comitter:
- manitou
- Date:
- Mon Dec 23 18:56:56 2019 +0000
- Commit message:
- stochastic simulation
Changed in this revision
diff -r 000000000000 -r fc1335b7b54f Ant.cpp --- /dev/null Thu Jan 01 00:00:00 1970 +0000 +++ b/Ant.cpp Mon Dec 23 18:56:56 2019 +0000 @@ -0,0 +1,89 @@ +// +// Ant.cpp +// INHERITANCE_AND_POLYMORPHISM +// +// Created by Kristjan Thorsteinsson on 01/04/14. +// Copyright (c) 2014 Kristjan Thorsteinsson. All rights reserved. +// +#include <cstdlib> + +//#include <iostream> +#include "Ant.h" +#include "Organism.h" +#include "World.h" +using namespace std; + +Ant::Ant(World* aWorld, int xcoord, int ycoord) : Organism(aWorld, xcoord, ycoord) +{ + +} + +void Ant::move() +{ + breedTicks++; + Move mover = world->randomMove(); + switch (mover) { + case UP: + if (world->getAt(x, y + 1) == NULL && in_range(x, y + 1)) + { + movesTo(x, y + 1); + } + break; + case DOWN: + if (world->getAt(x, y - 1) == NULL && in_range(x, y - 1)) + { + movesTo(x, y - 1); + } + break; + case LEFT: + if (world->getAt(x - 1, y) == NULL && in_range(x - 1, y)) + { + movesTo(x - 1, y); + } + break; + case RIGHT: + if (world->getAt(x + 1, y) == NULL && in_range(x + 1, y)) + { + movesTo(x + 1, y); + } + break; + default: + break; + } +} + +void Ant::breed() +{ + if (breedTicks >= BREED_ANTS) + { + breedAtAdjacentCell(); + } +} + + +void Ant::generateOffspring(int whereX, int whereY) +{ + new Ant(this->world, whereX, whereY); + breedTicks = 0; +} + + +OrganismType Ant::getType() const +{ + return ANT; +} + +char Ant::representation() const +{ + return 'o'; +} + +int Ant::size() const +{ + return 10; +} + +bool Ant::in_range(int xx, int yy) +{ + return (xx >= 0) && (xx < ROWS) && (yy >= 0) && (yy < COLS); +}
diff -r 000000000000 -r fc1335b7b54f Ant.h --- /dev/null Thu Jan 01 00:00:00 1970 +0000 +++ b/Ant.h Mon Dec 23 18:56:56 2019 +0000 @@ -0,0 +1,44 @@ +// +// Ant.h +// INHERITANCE_AND_POLYMORPHISM +// +// Created by Kristjan Thorsteinsson on 01/04/14. +// Copyright (c) 2014 Kristjan Thorsteinsson. All rights reserved. +// + +#ifndef INHERITANCE_AND_POLYMORPHISM_Ant +#define INHERITANCE_AND_POLYMORPHISM_Ant + +//#include <iostream> +#include "Organism.h" +#include "World.h" +#include "Counter.h" + +class Ant : public Organism, public counter<Ant> +{ +public: + + Ant(World* aWorld, int xcoord, int ycoord); + // In the given world moves this organism. + void move(); + + // Makes this organism breed. + void breed(); + + // Returns the type of this organism. + OrganismType getType() const; + + // The character representation of this organism. + char representation() const; + + // The size of this organism. + int size() const; + + bool in_range(int xx, int yy); + +private: + + void generateOffspring(int whereX, int whereY); +}; + +#endif /* defined(__INHERITANCE_AND_POLYMORPHISM__Ant__) */
diff -r 000000000000 -r fc1335b7b54f Bug.cpp --- /dev/null Thu Jan 01 00:00:00 1970 +0000 +++ b/Bug.cpp Mon Dec 23 18:56:56 2019 +0000 @@ -0,0 +1,207 @@ +// +// Bug.cpp +// INHERITANCE_AND_POLYMORPHISM +// +// Created by Kristjan Thorsteinsson on 01/04/14. +// Copyright (c) 2014 Kristjan Thorsteinsson. All rights reserved. +// + +#include "Bug.h" +#include "Organism.h" +using namespace std; + +Bug::Bug(World* aWorld, int xcoord, int ycoord) : Organism(aWorld, xcoord, ycoord) +{ + starveTicks = 0; +} + + +void Bug::move() +{ + breedTicks++; + starveTicks++; + +#if 1 + // find an edible nabor + for (int i = 0; i < NABORS; i++) { + switch (nabors[i]) { + case 0: + if (world->getAt(x, y + 1) != NULL) + { + if (world->getAt(x, y + 1)->getType() == ANT) + { + starveTicks = 0; + delete world->getAt(x, y + 1); + movesTo(x, y + 1); + return; + } + } + break; + + case 1: + if (world->getAt(x, y - 1) != NULL) + { + if (world->getAt(x, y - 1)->getType() == ANT) + { + starveTicks = 0; + delete world->getAt(x, y - 1); + movesTo(x, y - 1); + return; + } + } + break; + + case 2: + if (world->getAt(x - 1, y) != NULL) + { + if (world->getAt(x - 1, y)->getType() == ANT) + { + starveTicks = 0; + delete world->getAt(x - 1, y); + movesTo(x - 1, y); + return; + } + } + break; + + case 3: + if (world->getAt(x + 1, y) != NULL) + { + if (world->getAt(x + 1, y)->getType() == ANT) + { + starveTicks = 0; + delete world->getAt(x + 1, y); + movesTo(x + 1, y); + return; + } + } + break; + + default: + break; + } + } // for nabors +#else + + if (world->getAt(x, y + 1) != NULL) + { + if (world->getAt(x, y + 1)->getType() == ANT) + { + starveTicks = 0; + delete world->getAt(x, y + 1); + movesTo(x, y + 1); + return; + } + } + + if (world->getAt(x, y - 1) != NULL) + { + if (world->getAt(x, y - 1)->getType() == ANT) + { + starveTicks = 0; + delete world->getAt(x, y - 1); + movesTo(x, y - 1); + return; + } + } + + if (world->getAt(x - 1, y) != NULL) + { + if (world->getAt(x - 1, y)->getType() == ANT) + { + starveTicks = 0; + delete world->getAt(x - 1, y); + movesTo(x - 1, y); + return; + } + } + if (world->getAt(x + 1, y) != NULL) + { + if (world->getAt(x + 1, y)->getType() == ANT) + { + starveTicks = 0; + delete world->getAt(x + 1, y); + movesTo(x + 1, y); + return; + } + } +#endif + + Move mover = world->randomMove(); + switch (mover) { + case UP: + if (world->getAt(x, y + 1) == NULL && in_range(x, y + 1)) + { + movesTo(x, y + 1); + } + break; + case DOWN: + if (world->getAt(x, y - 1) == NULL && in_range(x, y - 1)) + { + movesTo(x, y - 1); + } + break; + case LEFT: + if (world->getAt(x - 1, y) == NULL && in_range(x - 1, y)) + { + movesTo(x - 1, y); + } + break; + case RIGHT: + if (world->getAt(x + 1, y) == NULL && in_range(x + 1, y)) + { + movesTo(x + 1, y); + } + break; + default: + break; + } +} + +void Bug::generateOffspring(int whereX, int whereY) +{ + new Bug(this->world, whereX, whereY); + breedTicks = 0; +} + +void Bug::breed() +{ + if (breedTicks >= BREED_BUGS) + { + breedAtAdjacentCell(); + } + +} + +bool Bug::isDead() const +{ + if (starveTicks >= STARVE_BUGS) + { + return true; + } + else + { + return false; + } +} + +OrganismType Bug::getType() const +{ + return BUG; +} + + +char Bug::representation()const +{ + return 'X'; +} + +int Bug::size() const +{ + return 30; +} + +bool Bug::in_range(int xx, int yy) +{ + return (xx >= 0) && (xx < ROWS) && (yy >= 0) && (yy < COLS); +}
diff -r 000000000000 -r fc1335b7b54f Bug.h --- /dev/null Thu Jan 01 00:00:00 1970 +0000 +++ b/Bug.h Mon Dec 23 18:56:56 2019 +0000 @@ -0,0 +1,48 @@ +// +// Bug.h +// INHERITANCE_AND_POLYMORPHISM +// +// Created by Kristjan Thorsteinsson on 01/04/14. +// Copyright (c) 2014 Kristjan Thorsteinsson. All rights reserved. +// + +#ifndef INHERITANCE_AND_POLYMORPHISM_Bug +#define INHERITANCE_AND_POLYMORPHISM_Bug + +//#include <iostream> + +#include "World.h" +#include "Organism.h" +#include "Counter.h" + +class Bug : public Organism, public counter<Bug> +{ +public: + + Bug(World* aWorld, int xcoord, int ycoord); + // In the given world moves this organism. + void move(); + + // Makes this organism breed. + void breed(); + + // Returns the type of this organism. + OrganismType getType() const; + + // The character representation of this organism. + char representation() const; + + // The size of this organism. + int size() const; + // Returns true if organism is dead, false otherwise. + bool isDead() const; + + bool in_range(int xx, int yy); + +private: + + void generateOffspring(int whereX, int whereY); + int starveTicks; +}; + +#endif /* defined(__INHERITANCE_AND_POLYMORPHISM__Bug__) */
diff -r 000000000000 -r fc1335b7b54f Counter.h --- /dev/null Thu Jan 01 00:00:00 1970 +0000 +++ b/Counter.h Mon Dec 23 18:56:56 2019 +0000 @@ -0,0 +1,21 @@ +#ifndef MYCOUNTER +#define MYCOUNTER +template <typename T> +struct counter +{ + counter() + { + objects_created++; + objects_alive++; + } + + virtual ~counter() + { + --objects_alive; + } + static int objects_created; + static int objects_alive; +}; +template <typename T> int counter<T>::objects_created( 0 ); +template <typename T> int counter<T>::objects_alive( 0 ); +#endif
diff -r 000000000000 -r fc1335b7b54f Organism.cpp --- /dev/null Thu Jan 01 00:00:00 1970 +0000 +++ b/Organism.cpp Mon Dec 23 18:56:56 2019 +0000 @@ -0,0 +1,104 @@ +//#include <iostream> +#include "Organism.h" +#include "World.h" + +// Create an organism at the given coordinates in the given world. +Organism::Organism(World* aWorld, int xcoord, int ycoord) { + world = aWorld; + x = xcoord; + y = ycoord; + breedTicks = 0; + moved = false; + world->setAt(x, y, this); +} + +// flags the organism as moved or not +void Organism::setMoved(bool hasMoved) { + moved = hasMoved; +} + +// has the organism moved or not? +bool Organism::hasMoved() const { + return moved; +} + +// moves the organism from coordinates (x,y) to (xNew,yNew) +void Organism::movesTo(int xNew, int yNew) { + + world->setAt(xNew, yNew, world->getAt(x, y)); + + world->setAt(x, y, NULL); + + x = xNew; + y = yNew; + + world->getAt(x, y)->setMoved(true); +} + +// Breeds an organism at an adjacent cell. This method calls the +// generateOffspring() method. +void Organism::breedAtAdjacentCell() { +#if 1 + // find empty nabor for breeding + for (int i = 0; i < NABORS; i++) { + switch (nabors[i]) { + case 0: + if ((world->getAt(x, y + 1) == NULL) && in_range(x, y + 1)) + { + generateOffspring(x, y + 1); + return; + } + break; + case 1: + if ((world->getAt(x, y - 1) == NULL) && in_range(x, y - 1)) + { + generateOffspring(x, y - 1); + return; + } + break; + case 2: + if ((world->getAt(x - 1, y) == NULL) && in_range(x - 1, y)) + { + generateOffspring(x - 1, y); + return; + } + case 3: + if ((world->getAt(x + 1, y) == NULL) && in_range(x + 1, y)) + { + generateOffspring(x + 1, y); + return; + } + break; + default: + break; + } + } // nabor for +#else + if ((world->getAt(x, y + 1) == NULL) && in_range(x, y + 1)) + { + generateOffspring(x, y + 1); + } + else if ((world->getAt(x, y - 1) == NULL) && in_range(x, y - 1)) + { + generateOffspring(x, y - 1); + } + else if ((world->getAt(x - 1, y) == NULL) && in_range(x - 1, y)) + { + generateOffspring(x - 1, y); + } + else if ((world->getAt(x + 1, y) == NULL) && in_range(x + 1, y)) + { + generateOffspring(x + 1, y); + } +#endif +} + + +bool Organism::in_range(int xx, int yy) +{ + return (xx >= 0) && (xx < ROWS) && (yy >= 0) && (yy < COLS); +} +// Returns true if organism is dead, false otherwise. +bool Organism::isDead() const { + return false; +}
diff -r 000000000000 -r fc1335b7b54f Organism.h --- /dev/null Thu Jan 01 00:00:00 1970 +0000 +++ b/Organism.h Mon Dec 23 18:56:56 2019 +0000 @@ -0,0 +1,70 @@ +#ifndef ORGANISM_H +#define ORGANISM_H + +enum OrganismType {ANT, BUG}; + +// forward declaration +class World; + +class Organism { + public: + // Create an organism at the given coordinates. + Organism(World* aWorld, int xcoord, int ycoord); + virtual ~Organism() { } + + // In the given world moves this organism. + virtual void move() = 0; + + // Makes this organism breed. + virtual void breed() = 0; + + // Returns the type of this organism. + virtual OrganismType getType() const = 0; + + // Flags this organism as moved or not. + void setMoved(bool hasMoved); + + // The character representation of this organism. + virtual char representation() const = 0; + + // The size of this organism. + virtual int size() const = 0; + + // Has this organism moved in this time slot or not? + bool hasMoved() const; + + // Returns true if organism is dead, false otherwise. + virtual bool isDead() const; + + bool in_range(int xx, int yy); + + protected: + // Generates an offspring at the given position. + virtual void generateOffspring(int whereX, int whereY) = 0; + + // Moves this organism from coordinates (x,y) to (xNew,yNew). + void movesTo(int xNew, int yNew); + + // Breeds a new organism at an adjacent cell. Tries to produce one new + // organism in UP, DOWN, LEFT, or RIGHT cell (in that order). Makes + // sure not to breed off the grid. + void breedAtAdjacentCell(); + + // This organism's x position in the world. + int x; + + // This organism's y position in the world. + int y; + + // Has moved this turn? + bool moved; + + // Number of ticks since breeding. + int breedTicks; + + // A pointer to the world in which this organism lives. + World* world; + private: +}; + +#endif // ORGANISM_H
diff -r 000000000000 -r fc1335b7b54f World.cpp --- /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(); + } + } + } +}
diff -r 000000000000 -r fc1335b7b54f World.h --- /dev/null Thu Jan 01 00:00:00 1970 +0000 +++ b/World.h Mon Dec 23 18:56:56 2019 +0000 @@ -0,0 +1,114 @@ +#ifndef WORLD_H +#define WORLD_H +#include <stddef.h> + +#include "Organism.h" + +// The possible moves +enum Move {UP = 0, DOWN, LEFT, RIGHT}; + +// The size of this world +const int ROWS = 24, COLS = 32; + +// Number of initial ants +const int INITIAL_ANTS = 50; + +// Number of initial bugs +const int INITIAL_BUGS = 10; + +// Time steps between breeding of ants +const int BREED_ANTS = 3; + +// Time steps between breeding of bugs +const int BREED_BUGS = 8; + +// Time steps until bugs die if they have not eaten +const int STARVE_BUGS = 3; + +const int NABORS = 4; +extern int nabors[]; + +struct Position +{ + int x; + int y; +}; + +class World +{ + public: + // Constructor: creates and initializes this world. the seed is used for + // seeding the random behaviour. + World(unsigned int seed); + + // Destructor. + ~World(); + + // Returns the organism at the given coordinates. + Organism* getAt(int x, int y) const; + + // Sets the organism org at position (x,y). + void setAt(int x, int y, Organism* org); + + // Displays this world. + void display() const; + void print() const; + void plot() const; + + // Simulates one time step in this world. + void simulateOneStep(); + + // Returns a random position in the grid. + Position randomPosition() const; + + // Returns a random move (UP, DOWN, LEFT or RIGHT). + Move randomMove() const; + + private: + // The grid in which the organisms live. According the to image below, + // the correct iteration order through grid starts at the top left + // corner (i.e. grid[0][0]), loops through one column at a time and ends + // at the bottom right corner (i.e. grid[WORLDSIZE-1][WORLDSIZE-1]). + // + // grid[0, 0] , grid[1, 0], ..., grid[WORLDSIZE-1, 0] + // grid[0, 1] , grid[1, 1], ..., grid[WORLDSIZE-1, 1] + // . . + // . . + // . . + // grid[0, WORLDSIZE-2], grid[1, WORLDSIZE-2], ..., grid[WORLDSIZE-1, WORLDSIZE-2] + // grid[0, WORLDSIZE-1], grid[1, WORLDSIZE-1], ..., grid[WORLDSIZE-1, WORLDSIZE-1] + // + // (See e.g. the destructor for correct iteration through the grid) + Organism* grid[ROWS][COLS]; + unsigned long steps, step_us; + + // Randomly create `count` many organisms of type `orgType`. This + // method uses the parameterized constructor in Ant and Bug. + void createOrganisms(OrganismType orgType, int count); + + // Reset all organisms to not moved. This is necessary because later we + // iterate through the grid starting from the top left moving to the + // bottom right looking for an organism to move. Say if an organism + // moves down, we don't want to move the organism again when we reach + // it. + void resetOrganisms(); + + // Make every organisms in this world of type aType move. Make sure to + // to iterate through grid in order as specified above and only move an + // organism if it hasn't moved already. + void moveOrganism(OrganismType aType); + + // Remove all dead organism from this world. Iterates through the grid + // and uses the method Organism::isDead() to test if an organism is + // dead. For this assignment in this method, only starved bugs will be + // removed. + void cleanup(); + + // Make every organism in this world breed. Make sure to iterate + // through grid in order as specified above and to only breed organisms + // that have moved, since breeding places new organisms on the map we + // don't want to try and breed those. + void breedOrganisms(); +}; + +#endif // WORLD_H
diff -r 000000000000 -r fc1335b7b54f main.cpp --- /dev/null Thu Jan 01 00:00:00 1970 +0000 +++ b/main.cpp Mon Dec 23 18:56:56 2019 +0000 @@ -0,0 +1,37 @@ +// predator play stochastic simulation +// https://github.com/Kristjan93/Ants-and-bugs + +#include "mbed.h" + +#include "World.h" +Serial pc(USBTX, USBRX); +Timer tmr; +#define micros tmr.read_us + +main() +{ + tmr.start(); + + + printf("hit a key to step\n"); + + World myWorld(0); // seed analogRead(0) + + myWorld.print(); + // myWorld.display(); // TFT display + while (1) { +#if 1 + if (pc.readable() ) { + pc.getc(); + myWorld.simulateOneStep(); + myWorld.print(); + // myWorld.display(); // TFT display + } +#else + myWorld.simulateOneStep(); + myWorld.plot(); // for serialplotter + // myWorld.display(); // TFT display + wait(.3); +#endif + } +}
diff -r 000000000000 -r fc1335b7b54f mbed.bld --- /dev/null Thu Jan 01 00:00:00 1970 +0000 +++ b/mbed.bld Mon Dec 23 18:56:56 2019 +0000 @@ -0,0 +1,1 @@ +http://mbed.org/users/mbed_official/code/mbed/builds/f9eeca106725 \ No newline at end of file