Advertisement
Not a member of Pastebin yet?
Sign Up,
it unlocks many cool features!
- #define OLC_PGE_APPLICATION
- #include <iostream>
- #include <algorithm>
- #include <string>
- #include <vector>
- #include <time.h>
- #include "olcPixelGameEngine.h"
- using namespace std;
- class Food {
- public:
- int x, y;
- bool isCorpse = false;
- };
- class Unit {
- public:
- int x, y;
- int id;
- int hunger;
- pair<int, int> destination;
- int foodDestinationID;
- char sex;
- int multiplyCoolDown = 0;
- bool checkCoordByXIsFree(int whereToGo, int width, int **mat) {
- if (x + whereToGo < width
- and
- x + whereToGo >= 0
- and
- mat[x + whereToGo][y] != 1
- and
- mat[x + whereToGo][y] != 2) {
- return true;
- }
- else
- return false;
- }
- bool checkCoordByYIsFree(int whereToGo, int height, int **mat) {
- if (y + whereToGo < height
- and
- y + whereToGo >= 0
- and
- mat[x][y + whereToGo] != 1
- and
- mat[x][y + whereToGo] != 2) {
- return true;
- }
- else
- return false;
- }
- bool validCoord(int x, int y, int width, int height, int **mat) {
- if (x >= 0 and x < width and y >= 0 and y < height and mat[x][y] == 0)
- return true;
- else
- return false;
- }
- vector<Food> becomeCorpse(vector<Food> food) {
- Food corpse;
- corpse.x = this->x;
- corpse.y = this->y;
- corpse.isCorpse = true;
- food.push_back(corpse);
- return food;
- }
- void moveTowards(int width, int height, int **mat) {
- int xOrY[2] = { 0, 1 };
- int direction;
- bool flagX = false, flagY = false;
- int retryCount = 0;
- while (retryCount < 4) {
- int x_or_y = xOrY[rand() % 2];
- if (x - destination.first == 0)
- x_or_y = 1;
- if (y - destination.second == 0)
- x_or_y = 0;
- if (x_or_y == 0)
- if (x - destination.first < 0)
- direction = 1;
- else
- direction = -1;
- if (x_or_y == 1)
- if (y - destination.second < 0)
- direction = 1;
- else
- direction = -1;
- if (x_or_y == 0 and checkCoordByXIsFree(direction, width, mat) == true) {
- x += direction;
- flagX = true;
- }
- if (x_or_y == 1 and checkCoordByYIsFree(direction, height, mat) == true) {
- y += direction;
- flagY = true;
- }
- if (flagX == 0 and flagY == 0) {
- retryCount++;
- continue;
- }
- if (hunger > 0) {
- hunger--;
- return;
- }
- else {
- return;
- }
- }
- }
- vector<Unit> multiply(vector<Unit> Units, int width, int height, int **mat) {
- int retryCount = 0;
- char sex[2] = { 'f', 'm' };
- Unit unit;
- unit.hunger = 100;
- unit.multiplyCoolDown = 0;
- unit.x = x;
- unit.y = y;
- unit.sex = sex[rand() % 2];
- //unit.newBorn = true;
- Units.push_back(unit);
- //mat[unit.x][unit.y] = 1;
- return Units;
- }
- vector<Unit> findPair(vector<Unit> Units, int id, int width, int height, int** mat) {
- int minDist = INT_MAX;
- int destID = -1;
- for (int i = 0; i < Units.size(); i++) {
- int curDist = abs(x - Units[i].x) + abs(y - Units[i].y);
- if (Units[i].sex != Units[id].sex and Units[i].hunger > 85 and curDist < minDist) { //////// heavy variant to check all existing units, appropriate
- minDist = curDist; //only for small map size
- destID = i;
- }
- }
- //for (int i = Units[id].x - 20; i < Units[id].x + 20; i++) {
- // for (int j = Units[id].y - 20; i < Units[id].y + 20; j++) {
- // if (mat[i][j] == 1) {
- // int curDist = abs(Units[id].x - Units[i].x) + abs(y - Units[i].y);
- // }
- // }
- //}
- if (destID != -1) {
- Units[id].destination.first = Units[destID].x;
- Units[id].destination.second = Units[destID].y;
- }
- return Units;
- }
- vector<Unit> seekPair(vector<Unit> Units, int id, int width, int height, int** mat) {
- int dist;
- int unitIdle = 1;
- Units = findPair(Units, id, width, height, mat);
- if (Units[id].destination.first == 0 and Units[id].destination.second == 0) {
- Units[id].walk(width, height, mat);
- return Units;
- }
- if (abs(Units[id].x - Units[id].destination.first) + abs(Units[id].y - Units[id].destination.second) > 1 ) {
- Units[id].moveTowards(width, height, mat);
- unitIdle = 0;
- }
- for (int i = 0;i < Units.size();i++) {
- dist = abs(Units[id].x - Units[i].x) + abs(Units[id].y - Units[i].y);
- if (dist == 1 and Units[id].multiplyCoolDown >= 100 and Units[i].multiplyCoolDown >= 100 and Units[id].sex != Units[i].sex) {
- Units = multiply(Units, width, height, mat);
- Units[id].multiplyCoolDown = 0;
- Units[i].multiplyCoolDown = 0;
- unitIdle = 0;
- }
- }
- if (unitIdle == 1) {
- Units[id].walk(width, height, mat);
- return Units;
- }
- return Units;
- }
- pair<vector<Food>, vector<Food>> eat(vector<Food> food, vector<Food> eatenFood) {
- pair<vector<Food>, vector<Food>> foods;
- eatenFood.push_back(food[foodDestinationID]);
- food.erase(food.begin() + foodDestinationID);
- foods.first = food;
- foods.second = eatenFood;
- hunger = 100;
- return foods;
- }
- void findNearestFood(vector<Food> food) {
- int minDist = INT_MAX;
- if (food.size() == 0) {
- return;
- }
- for (int i = 0; i < food.size(); i++) {
- int curDist = abs(x - food[i].x) + abs(y - food[i].y);
- if (curDist < minDist) {
- minDist = curDist;
- destination.first = food[i].x;
- destination.second = food[i].y;
- foodDestinationID = i;
- }
- }
- }
- pair<vector<Food>, vector<Food>> seekFood(vector<Food> food, vector<Food> eatenFood, int width, int height, int** mat) {
- findNearestFood(food);
- pair<vector<Food>, vector<Food>> foods;
- foods.first = food;
- foods.second = eatenFood;
- int foodIdle = 1;
- if (abs(x - destination.first) + abs(y - destination.second) > 1) {
- moveTowards(width, height, mat);
- foodIdle = 0;
- return foods;
- }
- else if (abs(x - destination.first) + abs(y - destination.second) == 1) {
- foodIdle = 0;
- return eat(food, eatenFood);
- }
- if (foodIdle == 1) {
- return foods;
- }
- }
- //............................
- void walk(int width, int height, int **mat) {
- int upOrDown[2] = { -1, 1 };
- int leftOrRight[2] = { 0, 1 };
- bool flagX = 0, flagY = 0;
- int retryCount = 0;
- while (retryCount < 4) {
- int moveUpOrDown = upOrDown[rand() % 2];
- int moveLeftOrRight = leftOrRight[rand() % 2];;
- if (moveLeftOrRight == 0 and validCoord(x + moveUpOrDown, y, width, height, mat) == true) {
- x += moveUpOrDown;
- flagX = 1;
- }
- if (moveLeftOrRight == 1 and validCoord(x, y + moveUpOrDown, width, height, mat) == true) {
- y += moveUpOrDown;
- flagY = 1;
- }
- if (flagX == 0 and flagY == 0) {
- retryCount++;
- continue;
- }
- if (hunger > 0) {
- hunger--;
- return;
- }
- }
- }
- };
- class Karta {
- public:
- int height, width;
- int** mat;
- vector<Unit> Units;
- vector<Unit> unitsPrevPos;
- vector<Unit> newUnits;
- vector<Food> food;
- vector<Food> eatenFood;
- pair<vector<Food>, vector<Food>> foods;
- bool validCoord(int x, int y) {
- if (x >= 0 and x < width and y >= 0 and y < height and mat[x][y] == 0)
- return true;
- else
- return false;
- }
- void createMap(int w, int h, int unitsAmount) {
- mat = new int* [w];
- for (int i = 0; i < w; i++) {
- mat[i] = new int[h];
- }
- for (int i = 0; i < w; i++) {
- for (int j = 0; j < h; j++) {
- mat[i][j] = 0;
- }
- }
- height = h;
- width = w;
- spawnUnits(unitsAmount);
- }
- void spawnUnits(int amount) {
- for (int i = 0; i < amount; i++) {
- Unit unit;
- unit.x = rand() % width;
- unit.y = rand() % height;
- char Sex[2] = { 'm', 'f' };
- char sex = Sex[rand() % 2];
- unit.sex = sex;
- unit.hunger = 100;
- if (mat[unit.x][unit.y] == 0) {
- Units.push_back(unit);
- mat[unit.x][unit.y] = 1;
- }
- else {
- i--;
- continue;
- }
- }
- spawnFirstFood();
- }
- void spawnFirstFood() {
- for (int i = 0; i < Units.size() / 2; i++) {
- Food eda;
- eda.x = rand() % width;
- eda.y = rand() % height;
- if (mat[eda.x][eda.y] == 0) {
- food.push_back(eda);
- mat[eda.x][eda.y] = 2;
- }
- else {
- i--;
- continue;
- }
- }
- }
- void spawnFood(int ctr) {
- int retryCount = 0;
- while (retryCount < 4) {
- Food eda;
- Food newEda;
- eda = food[ctr % food.size()];
- int x_or_y[2] = { 0, 1 };
- int up_or_down[2] = { -1, 1 };
- int xOrY = x_or_y[rand() % 2];
- int upOrDown = up_or_down[rand() % 2];
- if (xOrY == 0) {
- if (upOrDown == -1) {
- newEda.x = eda.x - 1;
- newEda.y = eda.y;
- }
- if (upOrDown == 1) {
- newEda.x = eda.x + 1;
- newEda.y = eda.y;
- }
- }
- if (xOrY == 1) {
- if (upOrDown == -1) {
- newEda.x = eda.x;
- newEda.y = eda.y - 1;
- }
- if (upOrDown == 1) {
- newEda.x = eda.x;
- newEda.y = eda.y + 1;
- }
- }
- if (validCoord(newEda.x, newEda.y) == true) {
- food.push_back(newEda);
- mat[newEda.x][newEda.y] = 2;
- break;
- }
- else {
- retryCount++;
- continue;
- }
- }
- }
- int goLive(int ctr) {
- unitsPrevPos = Units;
- eatenFood.clear();
- if (ctr % 2 == 0) {
- spawnFood(ctr / 2);
- }
- for (int j = 0; j < Units.size(); j++) {
- Units[j].multiplyCoolDown++;
- if (Units[j].hunger > 50 and Units[j].multiplyCoolDown >= 100) {
- Units = Units[j].seekPair(Units, j, width, height, mat);
- if (unitsPrevPos.size() < Units.size()) {
- mat[Units.back().x][Units.back().y] = 1;
- }
- continue;
- }
- if (Units[j].hunger > 25) {
- Units[j].walk(width, height, mat);
- continue;
- }
- if (Units[j].hunger <= 25 and Units[j].hunger > 0) {
- foods = Units[j].seekFood(food, eatenFood, width, height, mat);
- food = foods.first;
- eatenFood = foods.second;
- continue;
- }
- if (Units[j].hunger == 0) {
- food = Units[j].becomeCorpse(food);
- mat[Units[j].x][Units[j].y] = 2;
- Units.erase(Units.begin() + j);
- }
- }
- for (int i = 0; i < unitsPrevPos.size(); i++) {
- mat[unitsPrevPos[i].x][unitsPrevPos[i].y] = 0;
- }
- for (int i = 0; i < Units.size(); i++) {
- mat[Units[i].x][Units[i].y] = 1;
- }
- for (int i = 0; i < eatenFood.size(); i++) {
- mat[eatenFood[i].x][eatenFood[i].y] = 0;
- }
- return ++ctr;
- }
- };
- class LifeSimulation : public olc::PixelGameEngine {
- public:
- LifeSimulation() {
- sAppName = "LifeSimulation";
- }
- Karta map;
- int ctr = 0;
- int rem = 0;
- float fOffsetX = 0.0f;
- float fOffsetY = 0.0f;
- float fScaleX = 1.0f;
- float fScaleY = 1.0f;
- float fStartPanX = 0.0f;
- float fStartPanY = 0.0f;
- float fSelectedCellX = 0.0f;
- float fSelectedCellY = 0.0f;
- bool OnUserCreate() override {
- int unitsAmount = 20;
- map.createMap(ScreenWidth(), ScreenHeight(), unitsAmount);
- for (int x = 0; x < ScreenWidth(); x++) {
- for (int y = 0; y < ScreenHeight(); y++) {
- Draw(x, y, olc::Pixel(0, 255, 0));
- }
- }
- fOffsetX = -ScreenWidth() / 2;
- fOffsetY = -ScreenHeight() / 2;
- return true;
- }
- void WorldToScreen(float fWorldX, float fWorldY, int& nScreenX, int& nScreenY)
- {
- nScreenX = (int)((fWorldX - fOffsetX) * fScaleX);
- nScreenY = (int)((fWorldY - fOffsetY) * fScaleY);
- }
- void ScreenToWorld(int nScreenX, int nScreenY, float& fWorldX, float& fWorldY)
- {
- fWorldX = ((float)nScreenX / fScaleX) + fOffsetX;
- fWorldY = ((float)nScreenY / fScaleY) + fOffsetY;
- }
- bool OnUserUpdate(float fElapsedTime) override {
- float fMouseX = (float)GetMouseX();
- float fMouseY = (float)GetMouseY();
- // For panning, we need to capture the screen location when the user starts
- // to pan...
- if (GetMouse(2).bPressed)
- {
- fStartPanX = fMouseX;
- fStartPanY = fMouseY;
- }
- // ...as the mouse moves, the screen location changes. Convert this screen
- // coordinate change into world coordinates to implement the pan. Simples.
- if (GetMouse(2).bHeld)
- {
- fOffsetX -= (fMouseX - fStartPanX) / fScaleX;
- fOffsetY -= (fMouseY - fStartPanY) / fScaleY;
- // Start "new" pan for next epoch
- fStartPanX = fMouseX;
- fStartPanY = fMouseY;
- }
- // For zoom, we need to extract the location of the cursor before and after the
- // scale is changed. Here we get the cursor and translate into world space...
- float fMouseWorldX_BeforeZoom, fMouseWorldY_BeforeZoom;
- ScreenToWorld(fMouseX, fMouseY, fMouseWorldX_BeforeZoom, fMouseWorldY_BeforeZoom);
- // ...change the scale as required...
- if (GetKey(olc::Key::UP).bHeld)
- {
- fScaleX *= 1.001f;
- fScaleY *= 1.001f;
- }
- if (GetKey(olc::Key::DOWN).bHeld)
- {
- fScaleX *= 0.999f;
- fScaleY *= 0.999f;
- }
- // ...now get the location of the cursor in world space again - It will have changed
- // because the scale has changed, but we can offset our world now to fix the zoom
- // location in screen space, because we know how much it changed laterally between
- // the two spatial scales. Neat huh? ;-)
- float fMouseWorldX_AfterZoom, fMouseWorldY_AfterZoom;
- ScreenToWorld(fMouseX, fMouseY, fMouseWorldX_AfterZoom, fMouseWorldY_AfterZoom);
- fOffsetX += (fMouseWorldX_BeforeZoom - fMouseWorldX_AfterZoom);
- fOffsetY += (fMouseWorldY_BeforeZoom - fMouseWorldY_AfterZoom);
- // Clear Screen
- FillRect(0, 0, ScreenWidth(), ScreenHeight(), olc::Pixel(0, 255, 0));
- // Clip
- float fWorldLeft, fWorldTop, fWorldRight, fWorldBottom;
- ScreenToWorld(0, 0, fWorldLeft, fWorldTop);
- ScreenToWorld(ScreenWidth(), ScreenHeight(), fWorldRight, fWorldBottom);
- for (int i = 0; i < map.Units.size(); i++) {
- if (map.Units[i].sex == 'm')
- Draw(map.Units[i].x, map.Units[i].y, olc::Pixel(0, 0, 255));
- if (map.Units[i].sex == 'f')
- Draw(map.Units[i].x, map.Units[i].y, olc::Pixel(255, 203, 219));
- }
- for (int i = 0; i < map.unitsPrevPos.size(); i++) {
- Draw(map.unitsPrevPos[i].x, map.unitsPrevPos[i].y, olc::Pixel(0, 255, 0));
- }
- for (int i = 0; i < map.food.size(); i++) {
- if (map.food[i].isCorpse == true)
- Draw(map.food[i].x, map.food[i].y, olc::Pixel(0, 0, 0));
- else
- Draw(map.food[i].x, map.food[i].y, olc::Pixel(255, 0, 0));
- }
- for (int i = 0; i < map.eatenFood.size(); i++) {
- Draw(map.eatenFood[i].x, map.eatenFood[i].y, olc::Pixel(0, 255, 0));
- }
- int curHunger = 0;
- if (GetMouse(1).bPressed) {
- int curHungerX = GetMouseX();
- int curHungerY = GetMouseY();
- for (int i = 0; i < map.Units.size(); i++) {
- if (map.Units[i].x == curHungerX and map.Units[i].y == curHungerY or
- map.Units[i].x == curHungerX + 1 and map.Units[i].y == curHungerY + 1 or
- map.Units[i].x == curHungerX - 1 and map.Units[i].y == curHungerY -1 or
- map.Units[i].x == curHungerX + 1 and map.Units[i].y == curHungerY or
- map.Units[i].x == curHungerX and map.Units[i].y == curHungerY + 1 or
- map.Units[i].x == curHungerX - 1 and map.Units[i].y == curHungerY or
- map.Units[i].x == curHungerX and map.Units[i].y == curHungerY - 1) {
- curHunger = map.Units[i].hunger;
- rem = i;
- break;
- }
- }
- }
- else {
- curHunger = map.Units[rem].hunger;
- }
- DrawStringDecal({ 0, 0 }, "Hunger: " + to_string(curHunger), olc::WHITE, { 0.5, 0.5 });
- DrawStringDecal({ 0, 5 }, "id: " + to_string(rem), olc::WHITE, { 0.5, 0.5 });
- ctr = map.goLive(ctr);
- Sleep(500);
- return true;
- }
- };
- int main()
- {
- int screenWidth = 100;
- int screenHeight = 100;
- int pixelSize = 8;
- LifeSimulation lifeSimulation;
- if (lifeSimulation.Construct(screenWidth, screenHeight, pixelSize, pixelSize)) {
- lifeSimulation.Start();
- }
- }
Advertisement
Add Comment
Please, Sign In to add comment
Advertisement