From 3122817eeea2a784af9b86078a4bfaf6c953dbb6 Mon Sep 17 00:00:00 2001 From: Nikola Petrov Date: Fri, 3 Jan 2025 16:34:05 +0100 Subject: [PATCH] Finish DnaManager --- inc/App.hpp | 2 + inc/values/Dna.hpp | 7 ++- inc/values/DnaManager.hpp | 14 ++++- inc/values/mrand.hpp | 4 +- src/App.cpp | 27 ++++++--- src/values/Dna.cpp | 53 ++++++++++++++++- src/values/DnaManager.cpp | 116 +++++++++++++++++++++++++++++++++++++- src/values/mrand.cpp | 12 ---- 8 files changed, 204 insertions(+), 31 deletions(-) diff --git a/inc/App.hpp b/inc/App.hpp index 96bdc35..b242e7e 100644 --- a/inc/App.hpp +++ b/inc/App.hpp @@ -13,6 +13,8 @@ public: void deinit(); private: + void upTex(Liked liked); + int screenWidth, screenHeight; Canvas canvas; RenderTexture2D canvasTexure = {0}; diff --git a/inc/values/Dna.hpp b/inc/values/Dna.hpp index 508af73..61363f1 100644 --- a/inc/values/Dna.hpp +++ b/inc/values/Dna.hpp @@ -53,7 +53,8 @@ struct Dna uint8_t colorSet; Branch branches[MAX_DEPTH]; }; - -void newDna(Dna &dna); - +void newDna(Dna *dna, uint128 *state); +void makeChild(Dna *p1, Dna *p2, Dna *c, uint128 *state); +void clone(Dna *p1, Dna *c, uint128 *state); +void mutate(Dna *dna, uint32_t num, uint128 *state); #endif /* DNA_H */ diff --git a/inc/values/DnaManager.hpp b/inc/values/DnaManager.hpp index a1df4ae..3d92148 100644 --- a/inc/values/DnaManager.hpp +++ b/inc/values/DnaManager.hpp @@ -1,4 +1,9 @@ #include "values/Dna.hpp" +#include +#include + +#define NUM_PER_GEN 10 +#define NUM_OF_MUT 1 enum Liked { @@ -22,5 +27,12 @@ public: void like(Unit unit); private: - Dna dna; + uint128 randSeed; + std::vector vector; + std::list queued; + std::list showed; + std::vector liked; + std::vector disliked; + + void newGen(); }; diff --git a/inc/values/mrand.hpp b/inc/values/mrand.hpp index d6aabdc..779482c 100644 --- a/inc/values/mrand.hpp +++ b/inc/values/mrand.hpp @@ -5,9 +5,9 @@ struct uint128; namespace mrand { void setSeed(unsigned long long seed); - int getValue(int min, int max); + // int getValue(int min, int max); float getFloat(uint128 *state); - float getFloat(); + // float getFloat(); int getValue(int min, int max, uint128 *state); uint32_t getInt(); } \ No newline at end of file diff --git a/src/App.cpp b/src/App.cpp index b5f70a7..4cbc492 100644 --- a/src/App.cpp +++ b/src/App.cpp @@ -27,6 +27,23 @@ void App::init(int screenWidth, int screenHeight) likeBox = {screenWidth - recPosX, posY, (float)recPosX, (float)screenWidth}; } +void App::upTex(Liked liked) +{ + unit.liked = liked; + manager.like(unit); + unit = manager.next(); + if (unit.dna != nullptr) + { + canvas.newGen(canvasTexure, unit.dna); + return; + } + + BeginTextureMode(canvasTexure); + ClearBackground(WHITE); + DrawText("NEXT GEN", 10, 10, 20, BLACK); + EndTextureMode(); +} + void App::update() { bool isDone = canvas.tick(canvasTexure); @@ -35,17 +52,11 @@ void App::update() Vector2 mouse = GetMousePosition(); if (CheckCollisionPointRec(mouse, disLikeBox)) { - unit.liked = Liked::no; - manager.like(unit); - unit = manager.next(); - canvas.newGen(canvasTexure, unit.dna); + upTex(Liked::no); } if (CheckCollisionPointRec(mouse, likeBox)) { - unit.liked = Liked::yes; - manager.like(unit); - unit = manager.next(); - canvas.newGen(canvasTexure, unit.dna); + upTex(Liked::yes); } } } diff --git a/src/values/Dna.cpp b/src/values/Dna.cpp index ee0f76e..288e458 100644 --- a/src/values/Dna.cpp +++ b/src/values/Dna.cpp @@ -6,12 +6,59 @@ #include -void newDna(Dna &dna) +void newDna(Dna *dna, uint128 *state) { - uint8_t *array = (uint8_t *)&dna; + uint8_t *array = (uint8_t *)dna; for (size_t i = 0; i < sizeof(Dna); i++) { - array[i] = mrand::getValue(0, 255); + array[i] = mrand::getValue(0, 255, state); } return; } + +void makeChild(Dna *p1, Dna *p2, Dna *c, uint128 *state) +{ + uint8_t *p1a = (uint8_t *)p1; + uint8_t *p2a = (uint8_t *)p2; + uint8_t *ca = (uint8_t *)c; + for (size_t i = 0; i < sizeof(Dna); i++) + { + int val = mrand::getValue(0, 1, state); + if (val == 0) + { + ca[i] = p1a[i]; + } + else + { + ca[i] = p2a[i]; + } + } +} + +void clone(Dna *p1, Dna *c, uint128 *state) +{ + uint8_t *p1a = (uint8_t *)p1; + + uint8_t *ca = (uint8_t *)c; + for (size_t i = 0; i < sizeof(Dna); i++) + { + int val = mrand::getValue(0, 1, state); + if (val == 0) + { + ca[i] = p1a[i]; + } + else + { + ca[i] = mrand::getValue(0, 255, state); + } + } +} +void mutate(Dna *dna, uint32_t num, uint128 *state) +{ + uint8_t *array = (uint8_t *)dna; + for (size_t i = 0; i < num; i++) + { + int pos = mrand::getValue(0, sizeof(Dna), state); + array[pos] = mrand::getValue(0, 255, state); + } +} diff --git a/src/values/DnaManager.cpp b/src/values/DnaManager.cpp index cbd6f6c..2b1b8c8 100644 --- a/src/values/DnaManager.cpp +++ b/src/values/DnaManager.cpp @@ -1,7 +1,19 @@ #include "values/DnaManager.hpp" +#include "values/mrand.hpp" void DnaManager::init() { + randSeed.a = mrand::getInt(); + randSeed.b = mrand::getInt(); + randSeed.c = mrand::getInt(); + randSeed.d = mrand::getInt(); + + vector.resize(NUM_PER_GEN); + for (std::size_t i = 0; i < NUM_PER_GEN; i++) + { + newDna(&vector[i], &randSeed); + queued.push_back(&vector[i]); + } } void DnaManager::deinit() @@ -10,10 +22,110 @@ void DnaManager::deinit() Unit DnaManager::next() { - newDna(dna); - return {&dna, Liked::tbd}; + if (queued.empty()) + { + return {nullptr, Liked::tbd}; + } + + Dna *ret = queued.front(); + queued.pop_front(); + showed.push_back(ret); + return {ret, Liked::tbd}; } void DnaManager::like(Unit unit) { + Dna *found = nullptr; + for (auto &&i : showed) + { + if (i == unit.dna) + found = unit.dna; + } + + if (found == nullptr) + { + TraceLog(LOG_ERROR, "NOT FOUND UNIT"); + return; + } + if (unit.liked == Liked::yes) + { + liked.push_back(found); + } + else if (unit.liked == Liked::no) + { + disliked.push_back(found); + } + else + { + TraceLog(LOG_ERROR, "LIKED WITH NO VAULE"); + return; + } + + showed.remove(found); + + if (showed.size() == 0 && queued.size() == 0) + { + newGen(); + } +} + +void DnaManager::newGen() +{ + if (liked.size() == 0) + { + for (std::size_t i = 0; i < NUM_PER_GEN; i++) + { + newDna(&vector[i], &randSeed); + queued.push_back(&vector[i]); + } + disliked.clear(); + return; + } + + for (auto &&i : liked) + { + queued.push_back(i); + } + + if (liked.size() == 1) + { + Dna *front = liked.front(); + + for (auto &&i : disliked) + { + clone(front, i, &randSeed); + queued.push_back(i); + } + + disliked.clear(); + liked.clear(); + return; + } + + if (liked.size() >= 2) + { + for (auto &&i : disliked) + { + size_t p1 = mrand::getValue(0, liked.size() - 1, &randSeed); + size_t p2 = mrand::getValue(0, liked.size() - 1, &randSeed); + while (p1 == p2) + { + p2 = mrand::getValue(0, liked.size(), &randSeed); + } + + Dna *p1p = liked[p1]; + Dna *p2p = liked[p2]; + makeChild(p1p, p2p, i, &randSeed); + queued.push_back(i); + } + } + + if (queued.size() == NUM_PER_GEN) + { + for (auto &&i : queued) + { + mutate(i, NUM_OF_MUT, &randSeed); + } + return; + } } \ No newline at end of file diff --git a/src/values/mrand.cpp b/src/values/mrand.cpp index 4b2c4b0..ead20e1 100644 --- a/src/values/mrand.cpp +++ b/src/values/mrand.cpp @@ -53,18 +53,6 @@ namespace mrand return my_rprand_xoshiro(rprand_state); } - int getValue(int min, int max) - { - int value = my_rprand_xoshiro(rprand_state) % (std::abs(max - min) + 1) + min; - - return value; - } - - float getFloat() - { - return my_rprand_xoshiro(rprand_state) / 4294967295.0f; - } - int getValue(int min, int max, uint128 *state) { int value = my_rprand_xoshiro((uint32_t *)state) % (std::abs(max - min) + 1) + min;