From adb0b2b5da20aa418ba0b758236894d587e0c388 Mon Sep 17 00:00:00 2001
From: Nikola Petrov <nikola@petrovv.com>
Date: Sat, 4 Jan 2025 20:53:34 +0100
Subject: [PATCH] Start work on saving state of the manager

---
 inc/sys.hpp               |  1 +
 inc/values/Dna.hpp        | 10 ++--------
 inc/values/DnaManager.hpp |  1 +
 inc/values/mrand.hpp      | 11 ++++++++---
 src/App.cpp               |  1 -
 src/canvas/BackGround.cpp |  2 --
 src/canvas/Tree.cpp       |  1 -
 src/values/Dna.cpp        |  1 -
 src/values/DnaManager.cpp | 36 +++++++++++++++++++++++++++---------
 src/values/mrand.cpp      | 20 ++++++++------------
 10 files changed, 47 insertions(+), 37 deletions(-)

diff --git a/inc/sys.hpp b/inc/sys.hpp
index 3a6db59..3b92217 100644
--- a/inc/sys.hpp
+++ b/inc/sys.hpp
@@ -2,6 +2,7 @@
 
 namespace sys
 {
+  const char *transformFilePath(const char *filename);
   size_t saveDataToFile(const char *filename, const char *data, size_t size);
   size_t loadDataFromFile(const char *filename, char *data, size_t size);
   bool fileExists(const char *filename);
diff --git a/inc/values/Dna.hpp b/inc/values/Dna.hpp
index af2ee4d..11a0f7c 100644
--- a/inc/values/Dna.hpp
+++ b/inc/values/Dna.hpp
@@ -4,18 +4,12 @@
 #include <cinttypes>
 #include <array>
 
+#include "values/mrand.hpp"
+
 #define MAX_DEPTH 8
 #define MAX_POSIBLE_DEPTH 11
 static_assert(MAX_DEPTH <= MAX_POSIBLE_DEPTH);
 
-struct uint128
-{
-  uint32_t a;
-  uint32_t b;
-  uint32_t c;
-  uint32_t d;
-};
-
 struct Branch
 {
   uint8_t colorR;
diff --git a/inc/values/DnaManager.hpp b/inc/values/DnaManager.hpp
index 3d92148..2be2df1 100644
--- a/inc/values/DnaManager.hpp
+++ b/inc/values/DnaManager.hpp
@@ -28,6 +28,7 @@ public:
 
 private:
   uint128 randSeed;
+  uint128 id;
   std::vector<Dna> vector;
   std::list<Dna *> queued;
   std::list<Dna *> showed;
diff --git a/inc/values/mrand.hpp b/inc/values/mrand.hpp
index 32ed2b7..7832161 100644
--- a/inc/values/mrand.hpp
+++ b/inc/values/mrand.hpp
@@ -1,11 +1,16 @@
 #include <inttypes.h>
 
-struct uint128;
+struct uint128
+{
+  uint32_t a;
+  uint32_t b;
+  uint32_t c;
+  uint32_t d;
+};
 
 namespace mrand
 {
-  void setSeed(unsigned long long seed);
+  uint128 getState(unsigned long long seed);
   float getFloat(uint128 *state);
   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 0c8296f..6437890 100644
--- a/src/App.cpp
+++ b/src/App.cpp
@@ -3,7 +3,6 @@
 
 #include "App.hpp"
 #include "Math.hpp"
-#include "values/mrand.hpp"
 
 #include <raylib.h>
 #include <raymath.h>
diff --git a/src/canvas/BackGround.cpp b/src/canvas/BackGround.cpp
index ef9f32f..e057631 100644
--- a/src/canvas/BackGround.cpp
+++ b/src/canvas/BackGround.cpp
@@ -4,8 +4,6 @@
 #include "canvas/BackGroundColors.hpp"
 #include "canvas/Circle.hpp"
 #include "Math.hpp"
-#include "values/mrand.hpp"
-
 #include "stb_perlin.h"
 
 #include <raylib.h>
diff --git a/src/canvas/Tree.cpp b/src/canvas/Tree.cpp
index a8431c2..0880c39 100644
--- a/src/canvas/Tree.cpp
+++ b/src/canvas/Tree.cpp
@@ -2,7 +2,6 @@
 
 #include "canvas/Tree.hpp"
 #include "canvas/Circle.hpp"
-#include "values/mrand.hpp"
 #include "Math.hpp"
 
 #include <raylib.h>
diff --git a/src/values/Dna.cpp b/src/values/Dna.cpp
index 09251ce..e2eaf25 100644
--- a/src/values/Dna.cpp
+++ b/src/values/Dna.cpp
@@ -2,7 +2,6 @@
 #include <cstddef>
 
 #include "values/Dna.hpp"
-#include "values/mrand.hpp"
 
 #include <raymath.h>
 
diff --git a/src/values/DnaManager.cpp b/src/values/DnaManager.cpp
index efe4bd2..f3bccd5 100644
--- a/src/values/DnaManager.cpp
+++ b/src/values/DnaManager.cpp
@@ -1,28 +1,39 @@
 #include <ctime>
+#include <stdio.h>
+#include <unistd.h>
 
 #include "values/DnaManager.hpp"
-#include "values/mrand.hpp"
 #include "sys.hpp"
 
 #include <raylib.h>
 
 void DnaManager::init()
 {
-  mrand::setSeed(time(nullptr));
-
   if (sys::fileExists("id"))
   {
-    sys::loadDataFromFile("id", (char *)&randSeed, sizeof(uint128));
+    sys::loadDataFromFile("id", (char *)&id, sizeof(uint128));
   }
   else
   {
-    randSeed.a = mrand::getInt();
-    randSeed.b = mrand::getInt();
-    randSeed.c = mrand::getInt();
-    randSeed.d = mrand::getInt();
-    sys::saveDataToFile("id", (const char *)&randSeed, sizeof(uint128));
+    id = mrand::getState(time(nullptr));
+    sys::saveDataToFile("id", (const char *)&id, sizeof(uint128));
   }
 
+  if (sys::fileExists("data"))
+  {
+    const char *filename = sys::transformFilePath("data");
+
+    FILE *file = fopen(filename, "rb");
+    if (file == NULL)
+      return;
+
+    size_t ret = fread(&randSeed, 1, sizeof(uint128), file);
+    fclose(file);
+  }
+  else
+  {
+    randSeed = id;
+  }
   vector.resize(NUM_PER_GEN);
   for (std::size_t i = 0; i < NUM_PER_GEN; i++)
   {
@@ -33,6 +44,13 @@ void DnaManager::init()
 
 void DnaManager::deinit()
 {
+  const char *filename = sys::transformFilePath("data");
+
+  FILE *file = fopen(filename, "wb");
+  if (file == NULL)
+    return;
+  size_t ret = fwrite(&randSeed, 1, sizeof(uint128), file);
+  fclose(file);
 }
 
 Unit DnaManager::next()
diff --git a/src/values/mrand.cpp b/src/values/mrand.cpp
index ead20e1..89a1102 100644
--- a/src/values/mrand.cpp
+++ b/src/values/mrand.cpp
@@ -2,8 +2,6 @@
 #include <algorithm>
 #include "values/mrand.hpp"
 
-static uint32_t rprand_state[4] = {0};
-
 static inline uint32_t my_rotate_left(const uint32_t x, int k)
 {
   return (x << k) | (x >> (32 - k));
@@ -36,21 +34,19 @@ uint64_t rprand_splitmix64(uint64_t &rprand_seed)
 
 namespace mrand
 {
-  void setSeed(unsigned long long seed)
+  uint128 getState(unsigned long long seed)
   {
     uint64_t rprand_seed = (uint64_t)seed; // Set SplitMix64 seed for further use
 
+    uint128 rprand_state;
+
     // To generate the Xoshiro128** state, we use SplitMix64 generator first
     // We generate 4 pseudo-random 64bit numbers that we combine using their LSB|MSB
-    rprand_state[0] = (uint32_t)(rprand_splitmix64(rprand_seed) & 0xffffffff);
-    rprand_state[1] = (uint32_t)((rprand_splitmix64(rprand_seed) & 0xffffffff00000000) >> 32);
-    rprand_state[2] = (uint32_t)(rprand_splitmix64(rprand_seed) & 0xffffffff);
-    rprand_state[3] = (uint32_t)((rprand_splitmix64(rprand_seed) & 0xffffffff00000000) >> 32);
-  }
-
-  uint32_t getInt()
-  {
-    return my_rprand_xoshiro(rprand_state);
+    rprand_state.a = (uint32_t)(rprand_splitmix64(rprand_seed) & 0xffffffff);
+    rprand_state.b = (uint32_t)((rprand_splitmix64(rprand_seed) & 0xffffffff00000000) >> 32);
+    rprand_state.c = (uint32_t)(rprand_splitmix64(rprand_seed) & 0xffffffff);
+    rprand_state.d = (uint32_t)((rprand_splitmix64(rprand_seed) & 0xffffffff00000000) >> 32);
+    return rprand_state;
   }
 
   int getValue(int min, int max, uint128 *state)