From 3baa7157dc445a795df7fe29123fa8353e31994e Mon Sep 17 00:00:00 2001
From: biglyderv <eggseggsarecool+git@gmail.com>
Date: Tue, 25 Mar 2025 19:50:41 -0400
Subject: [PATCH 01/50] fix inv bug

---
 src/main.c | 2 +-
 1 file changed, 1 insertion(+), 1 deletion(-)

diff --git a/src/main.c b/src/main.c
index 341b347..4990570 100644
--- a/src/main.c
+++ b/src/main.c
@@ -71,8 +71,8 @@ int main(int argc, char *argv[]) {
     fptr = fopen(inv_file, "a");
     if (fptr == NULL)
       continue;
-    fwrite("\n",sizeof(char),1,fptr);
     fwrite(res_str, sizeof(char), strlen(res_str), fptr);
+    fwrite("\n",sizeof(char),1,fptr);
     fclose(fptr);
   }
 

From e6a00cf17b31a8a2bffe7a3fe9801e18d9483f4a Mon Sep 17 00:00:00 2001
From: biglyderv <eggseggsarecool+git@gmail.com>
Date: Tue, 25 Mar 2025 20:19:51 -0400
Subject: [PATCH 02/50] add inventory paging, more elements

---
 bin/combos.txt | 28 ++++++++++++++++++++++++++++
 src/command.c  | 34 +++++++++++++++++++++++++++++++---
 2 files changed, 59 insertions(+), 3 deletions(-)

diff --git a/bin/combos.txt b/bin/combos.txt
index a71a4bd..93c91df 100644
--- a/bin/combos.txt
+++ b/bin/combos.txt
@@ -9,3 +9,31 @@ wildfire;fire;fire
 smoke;fire;water
 puddle;water;water
 elements;air;earth;fire;water
+dirt;dust;earth
+clay;dirt;wind
+cobble;air;lava
+stone;cobble;earth
+gravel;cobble;wind
+blue;fire;heat
+steam;heat;water
+energy;steam;steam
+sky;air;wind
+sky;air;cloud
+space;sky;air
+space;sky;sky
+void;space;space
+zero;energy;void
+numbers;elements;zero
+one;numbers;numbers
+color;blue;numbers
+spectrum;color;numbers
+pond;puddle;earth
+pond;puddle;puddle
+lake;pond;water
+lake;pond;pond
+sea;lake;lake
+sea;lake;water
+ocean;sea;sea
+ocean;sea;land
+planet;ocean;earth
+planet;ocean;land
diff --git a/src/command.c b/src/command.c
index 4320d63..36d64dd 100644
--- a/src/command.c
+++ b/src/command.c
@@ -7,6 +7,20 @@
 
 #define MAX_BUF_LENGTH 1024
 #define MAX_COMBO_LENGTH 1024
+struct pager {
+  int page;
+  int i;
+};
+
+long stoi(const char *s) {
+  long i;
+  i = 0;
+  while (*s >= '0' && *s <= '9') {
+    i = i * 10 + (*s - '0');
+    s++;
+  }
+  return i;
+}
 
 int fix_delim(char *command, char *needle) {
   char *delim = strstr(command, needle);
@@ -33,6 +47,11 @@ int inv_handler(const void *key, unsigned long long size,
                 unsigned long long val, void *usr)
 #endif
 {
+  struct pager *i = usr;
+  i->i++;
+  if (i->i < i->page * 10 || i->i >= (i->page + 1) * 10) {
+    return 0;
+  }
   if (val == 0)
     return 0;
   char *key2 = (char *)key;
@@ -53,9 +72,18 @@ int slash_command(char *command, hashmap *inv) {
     return 0;
   }
 
-  if (strcmp(command, "inv\n") == 0) {
-    printf("Your inventory:\n");
-    hashmap_iterate(inv, inv_handler, "inv");
+  char *invs = "inv ";
+
+  if (strncmp(command, invs, strlen(invs)) == 0) {
+    int page = stoi(&command[strlen(invs)]);
+    printf("Your inventory (page %i):\n", page);
+    struct pager i = {.page = page - 1, .i = -1};
+    hashmap_iterate(inv, inv_handler, &i);
+  } else if (strncmp(command, invs, strlen(invs) - 1) == 0) {
+    int page = 1;
+    printf("Your inventory (page %i):\n", page);
+    struct pager i = {.page = page - 1, .i = -1};
+    hashmap_iterate(inv, inv_handler, &i);
   }
   return 1;
 }

From 8878053ee09aa4348eac2226c181c090eb6dbb90 Mon Sep 17 00:00:00 2001
From: biglyderv <eggseggsarecool+git@gmail.com>
Date: Tue, 25 Mar 2025 20:56:40 -0400
Subject: [PATCH 03/50] fix malformed combos

---
 bin/combos.txt | 11 ++++++-----
 1 file changed, 6 insertions(+), 5 deletions(-)

diff --git a/bin/combos.txt b/bin/combos.txt
index 93c91df..6d3ad1f 100644
--- a/bin/combos.txt
+++ b/bin/combos.txt
@@ -19,7 +19,7 @@ steam;heat;water
 energy;steam;steam
 sky;air;wind
 sky;air;cloud
-space;sky;air
+space;air;sky
 space;sky;sky
 void;space;space
 zero;energy;void
@@ -27,13 +27,14 @@ numbers;elements;zero
 one;numbers;numbers
 color;blue;numbers
 spectrum;color;numbers
-pond;puddle;earth
+pond;earth;puddle
 pond;puddle;puddle
 lake;pond;water
 lake;pond;pond
 sea;lake;lake
 sea;lake;water
 ocean;sea;sea
-ocean;sea;land
-planet;ocean;earth
-planet;ocean;land
+ocean;land;sea
+planet;earth;ocean
+planet;land;ocean
+star;fire;sky

From c02e8aa59aef93ceeda6a40ffd9d8799c209577e Mon Sep 17 00:00:00 2001
From: biglyderv <eggseggsarecool+git@gmail.com>
Date: Tue, 25 Mar 2025 21:25:31 -0400
Subject: [PATCH 04/50] attempt hotloading if element doesn't exist

---
 bin/combos.txt |  1 +
 src/main.c     | 10 +++++++++-
 2 files changed, 10 insertions(+), 1 deletion(-)

diff --git a/bin/combos.txt b/bin/combos.txt
index 6d3ad1f..25d42eb 100644
--- a/bin/combos.txt
+++ b/bin/combos.txt
@@ -38,3 +38,4 @@ ocean;land;sea
 planet;earth;ocean
 planet;land;ocean
 star;fire;sky
+pollution;air;dust
diff --git a/src/main.c b/src/main.c
index 4990570..a74ee7d 100644
--- a/src/main.c
+++ b/src/main.c
@@ -56,6 +56,14 @@ int main(int argc, char *argv[]) {
     uintptr_t result;
     hashmap_get(elements, command_re, strlen(command_re), &result);
 
+    // todo: better
+    if (result == 0) {
+      load_elements(elements, combo_file, 0) ||
+          load_elements(elements, "bin/" combo_file, 0);
+
+      hashmap_get(elements, command_re, strlen(command_re), &result);
+    }
+
     if (result == 0) {
       printf("You didn't make anything.\n");
       continue;
@@ -72,7 +80,7 @@ int main(int argc, char *argv[]) {
     if (fptr == NULL)
       continue;
     fwrite(res_str, sizeof(char), strlen(res_str), fptr);
-    fwrite("\n",sizeof(char),1,fptr);
+    fwrite("\n", sizeof(char), 1, fptr);
     fclose(fptr);
   }
 

From e6165f3af8d2df949528478b72e621b3208f7421 Mon Sep 17 00:00:00 2001
From: biglyderv <eggseggsarecool+git@gmail.com>
Date: Wed, 26 Mar 2025 01:20:38 -0400
Subject: [PATCH 05/50] garbage collection

---
 src/command.c | 18 ++++++++++--------
 src/loader.c  |  8 +++++---
 src/main.c    | 25 +++++++++++++++++--------
 src/map.c     | 10 +++++++++-
 src/map.h     |  4 +++-
 src/writer.c  |  0
 6 files changed, 44 insertions(+), 21 deletions(-)
 delete mode 100644 src/writer.c

diff --git a/src/command.c b/src/command.c
index 36d64dd..2a8b217 100644
--- a/src/command.c
+++ b/src/command.c
@@ -74,17 +74,19 @@ int slash_command(char *command, hashmap *inv) {
 
   char *invs = "inv ";
 
+  int page;
+  
   if (strncmp(command, invs, strlen(invs)) == 0) {
-    int page = stoi(&command[strlen(invs)]);
-    printf("Your inventory (page %i):\n", page);
-    struct pager i = {.page = page - 1, .i = -1};
-    hashmap_iterate(inv, inv_handler, &i);
+    page = stoi(&command[strlen(invs)]);
   } else if (strncmp(command, invs, strlen(invs) - 1) == 0) {
-    int page = 1;
-    printf("Your inventory (page %i):\n", page);
-    struct pager i = {.page = page - 1, .i = -1};
-    hashmap_iterate(inv, inv_handler, &i);
+    page = 1;
+  } else {
+    return 0;
   }
+
+  printf("Your inventory (page %i):\n", page);
+  struct pager i = {.page = page - 1, .i = -1};
+  hashmap_iterate(inv, inv_handler, &i);
   return 1;
 }
 
diff --git a/src/loader.c b/src/loader.c
index 91a01ae..77e4ea7 100644
--- a/src/loader.c
+++ b/src/loader.c
@@ -20,13 +20,15 @@ int load_elements(hashmap *m, char *table, int use_inv) {
 
   while (1) {
     str = calloc(MAX_FILE_SIZE, sizeof(char));
-    if (!fgets(str, MAX_FILE_SIZE, fptr))
+    if (!fgets(str, MAX_FILE_SIZE, fptr)) {
+      free(str);
       break;
+    }
 
     did_something = 1;
 
     if (use_inv) {
-      hashmap_set(m, str, strlen(str) - 1, (uintptr_t)1);
+      hashmap_set(m, str, strlen(str) - 1, (uintptr_t)1, 0);
       continue;
     }
 
@@ -34,7 +36,7 @@ int load_elements(hashmap *m, char *table, int use_inv) {
     combo[0] = '\0';
     combo++;
 
-    hashmap_set(m, combo, strlen(combo) - 1, (uintptr_t)str);
+    hashmap_set(m, combo, strlen(combo) - 1, (uintptr_t)str, 1);
   }
 
   if (!did_something) {
diff --git a/src/main.c b/src/main.c
index a74ee7d..7ebb4d1 100644
--- a/src/main.c
+++ b/src/main.c
@@ -12,6 +12,20 @@
 #define MAX_BUF_LENGTH 1024
 #define MAX_COMBO_LENGTH 1024
 
+void init_tables(hashmap *elements, hashmap *inv, int do_inv) {
+
+  load_elements(elements, "../elem_data/" combo_file, 0) ||
+      load_elements(elements, combo_file, 0) ||
+      load_elements(elements, "bin/" combo_file, 0);
+
+  if (!do_inv)
+    return;
+
+  load_elements(elements, "../elem_data/" inv_base_file, 1) ||
+      load_elements(inv, inv_base_file, 1) ||
+      load_elements(inv, "bin/" inv_base_file, 1);
+}
+
 int main(int argc, char *argv[]) {
   hashmap *elements = hashmap_create();
   hashmap *inv = hashmap_create();
@@ -20,10 +34,7 @@ int main(int argc, char *argv[]) {
   char *command_re = calloc(MAX_BUF_LENGTH, sizeof(char));
   char **sort_tmp = calloc(MAX_COMBO_LENGTH, sizeof(char **));
 
-  load_elements(elements, combo_file, 0) ||
-      load_elements(elements, "bin/" combo_file, 0);
-  load_elements(inv, inv_base_file, 1) ||
-      load_elements(inv, "bin/" inv_base_file, 1);
+  init_tables(elements, inv, 1);
 
   load_elements(inv, inv_file, 1);
 
@@ -56,10 +67,8 @@ int main(int argc, char *argv[]) {
     uintptr_t result;
     hashmap_get(elements, command_re, strlen(command_re), &result);
 
-    // todo: better
     if (result == 0) {
-      load_elements(elements, combo_file, 0) ||
-          load_elements(elements, "bin/" combo_file, 0);
+      init_tables(elements, inv, 0);
 
       hashmap_get(elements, command_re, strlen(command_re), &result);
     }
@@ -71,7 +80,7 @@ int main(int argc, char *argv[]) {
 
     char *res_str = (char *)result;
 
-    hashmap_set(inv, res_str, strlen(res_str), (uintptr_t)1);
+    hashmap_set(inv, res_str, strlen(res_str), (uintptr_t)1, 0);
     printf("You made %s!\n", res_str);
 
     FILE *fptr;
diff --git a/src/map.c b/src/map.c
index a93b2b4..59deeb2 100644
--- a/src/map.c
+++ b/src/map.c
@@ -5,6 +5,7 @@
 //
 
 #include "map.h"
+#include <stdint.h>
 #include <stdlib.h>
 #include <string.h>
 
@@ -167,7 +168,8 @@ static struct bucket *find_entry(hashmap *m, const void *key, size_t ksize,
   }
 }
 
-int hashmap_set(hashmap *m, const void *key, size_t ksize, uintptr_t val) {
+int hashmap_set(hashmap *m, const void *key, size_t ksize, uintptr_t val,
+                int free_old) {
   if (m->count + 1 > HASHMAP_MAX_LOAD * m->capacity) {
     if (hashmap_resize(m) == -1)
       return -1;
@@ -186,6 +188,12 @@ int hashmap_set(hashmap *m, const void *key, size_t ksize, uintptr_t val) {
     entry->ksize = ksize;
     entry->hash = hash;
   }
+
+  if (free_old && entry->value != 0 && entry->value != val &&
+      strcmp((char *)entry->value, (char *)val) == 0) {
+    free((char *)val);
+    return 0;
+  }
   entry->value = val;
   return 0;
 }
diff --git a/src/map.h b/src/map.h
index b6543a9..775b62d 100644
--- a/src/map.h
+++ b/src/map.h
@@ -2,6 +2,7 @@
 //  map.h
 //
 //  Created by Mashpoe on 1/15/21.
+//  Modifications by BiglyDerv
 //
 
 #ifndef map_h
@@ -63,7 +64,8 @@ void hashmap_free(hashmap *map);
 // you must copy it yourself if you want to guarantee its lifetime,
 // or if you intend to call `hashmap_key_free`.
 // returns -1 on error.
-int hashmap_set(hashmap *map, const void *key, size_t ksize, uintptr_t value);
+int hashmap_set(hashmap *map, const void *key, size_t ksize, uintptr_t value,
+                int free_old);
 
 // adds an entry if it doesn't exist, using the value of `*out_in`.
 // if it does exist, it sets value in `*out_in`, meaning the value
diff --git a/src/writer.c b/src/writer.c
deleted file mode 100644
index e69de29..0000000

From 34d2d97c820b69982f2f847bbff753007510b994 Mon Sep 17 00:00:00 2001
From: biglyderv <eggseggsarecool+git@gmail.com>
Date: Wed, 26 Mar 2025 21:19:01 -0400
Subject: [PATCH 06/50] add suggestions

---
 .gitignore    |   4 +-
 src/command.c | 134 +++++++++++++++++++++++++++++++++++++++++++++++++-
 src/command.h |   4 +-
 src/loader.c  |   7 ++-
 src/main.c    |  42 +++++++++++-----
 src/map.c     |   1 +
 6 files changed, 177 insertions(+), 15 deletions(-)

diff --git a/.gitignore b/.gitignore
index d23d186..6ffd8c6 100644
--- a/.gitignore
+++ b/.gitignore
@@ -1,3 +1,5 @@
 /bin/elem
 /bin/elem.exe
-/inv.txt
\ No newline at end of file
+/inv.txt
+/inv_users.txt
+/polls.txt
\ No newline at end of file
diff --git a/src/command.c b/src/command.c
index 2a8b217..1375bdd 100644
--- a/src/command.c
+++ b/src/command.c
@@ -7,11 +7,26 @@
 
 #define MAX_BUF_LENGTH 1024
 #define MAX_COMBO_LENGTH 1024
+#define poll_file "polls.txt"
+#define polls_lock_file "polls_lock.txt"
+#define combo_file "combos.txt"
+#define UPVOTE_IN 2
+
 struct pager {
   int page;
   int i;
 };
 
+struct verifier {
+  char *name;
+  char *sugg;
+};
+
+struct succ {
+  char *sugg;
+  int *points;
+};
+
 long stoi(const char *s) {
   long i;
   i = 0;
@@ -64,6 +79,123 @@ int inv_handler(const void *key, unsigned long long size,
   return 1;
 }
 
+#if !defined(_WIN32) && (defined(__unix__) || defined(__unix) ||               \
+                         (defined(__APPLE__) && defined(__MACH__)))
+
+int polls_handler(const void *key, unsigned long size, unsigned long val,
+                  void *usr)
+#else
+int polls_handler(const void *key, unsigned long long size,
+                  unsigned long long val, void *usr)
+#endif
+{
+  struct verifier *verified = (struct verifier *)usr;
+
+  if (((char*) val)[strlen(((char *)val)) - 1] == '\n') {
+    ((char *)val)[strlen(((char *)val)) - 1] = '\0';
+  }
+
+  if (strncmp(verified->name, key, strlen(verified->name)) == 0 &&
+      strcmp(verified->sugg, (char *)val) == 0)
+    return -1;
+
+  return 0;
+}
+
+#if !defined(_WIN32) && (defined(__unix__) || defined(__unix) ||               \
+                         (defined(__APPLE__) && defined(__MACH__)))
+
+int success_handler(const void *key, unsigned long size, unsigned long val,
+                    void *usr)
+#else
+int success_handler(const void *key, unsigned long long size,
+                    unsigned long long val, void *usr)
+#endif
+{
+  struct succ *verified = (struct succ *)usr;
+
+  if ((char *)val != verified->sugg) {
+    //((char *)val)[strlen(((char *)val)) - 1] = '\0';
+  }
+
+  if (strcmp(verified->sugg, (char *)val) == 0) {
+    verified->points[0]++;
+  }
+
+  return 0;
+}
+
+int suggest_command(char *command, char *command_re, hashmap *polls,
+                    char *name) {
+  if (command[0] == '/') {
+    command++;
+  } else {
+    return 0;
+  }
+
+  char *invs = "suggest ";
+
+  char *page;
+
+  if (strncmp(command, invs, strlen(invs)) == 0) {
+    page = &command[strlen(invs)];
+  } else {
+    return 0;
+  }
+  page[strlen(page) - 1] = '\0';
+
+  char *val = calloc(MAX_BUF_LENGTH, sizeof(char));
+  sprintf(val, "%s;%s", page, command_re);
+
+  char *key = calloc(MAX_BUF_LENGTH, sizeof(char));
+  sprintf(key, "%s_%i", name, (int)rand());
+
+  struct verifier verified = {.name = name, .sugg = val};
+
+  if (hashmap_iterate(polls, polls_handler, (void *)&verified) == -1) {
+    printf("You already suggested this!\n");
+    return 1;
+  }
+
+  hashmap_set(polls, key, strlen(key), (uintptr_t)val, 1);
+
+  int point_thing = 0;
+
+  struct succ succer = {.sugg = val, .points = &point_thing};
+  hashmap_iterate(polls, success_handler, (void *)&succer);
+
+  if (point_thing == UPVOTE_IN) {
+
+    printf("Poll was added into the game!\n");
+    FILE *fptr;
+
+    fptr = fopen("../elem_data/" combo_file, "a");
+    if (fptr == NULL)
+      return 1;
+    fwrite(val, sizeof(char), strlen(val), fptr);
+    fwrite("\n", sizeof(char), 1, fptr);
+    fclose(fptr);
+    return 1;
+  }
+
+  printf("Suggested %s = %s.\n", command_re, page);
+
+  // todo: clean old polls
+
+  FILE *fptr;
+
+  fptr = fopen("../elem_data/" poll_file, "a");
+  if (fptr == NULL)
+    return 1;
+  fwrite(key, sizeof(char), strlen(key), fptr);
+  fwrite(";", sizeof(char), 1, fptr);
+  fwrite(val, sizeof(char), strlen(val), fptr);
+  fwrite("\n", sizeof(char), 1, fptr);
+  fclose(fptr);
+
+  return 1;
+}
+
 int slash_command(char *command, hashmap *inv) {
 
   if (command[0] == '/') {
@@ -75,7 +207,7 @@ int slash_command(char *command, hashmap *inv) {
   char *invs = "inv ";
 
   int page;
-  
+
   if (strncmp(command, invs, strlen(invs)) == 0) {
     page = stoi(&command[strlen(invs)]);
   } else if (strncmp(command, invs, strlen(invs) - 1) == 0) {
diff --git a/src/command.h b/src/command.h
index d5c61f4..a91b2ea 100644
--- a/src/command.h
+++ b/src/command.h
@@ -1,3 +1,5 @@
 #include "map.h"
 int get_command(char *command, char *command_re, char **sort_tmp);
-int slash_command(char *command, hashmap *inv);
\ No newline at end of file
+int slash_command(char *command, hashmap *inv);
+int suggest_command(char *command, char *command_re, hashmap *polls,
+                    char *name);
\ No newline at end of file
diff --git a/src/loader.c b/src/loader.c
index 77e4ea7..190d34a 100644
--- a/src/loader.c
+++ b/src/loader.c
@@ -27,7 +27,7 @@ int load_elements(hashmap *m, char *table, int use_inv) {
 
     did_something = 1;
 
-    if (use_inv) {
+    if (use_inv == 1) {
       hashmap_set(m, str, strlen(str) - 1, (uintptr_t)1, 0);
       continue;
     }
@@ -36,6 +36,11 @@ int load_elements(hashmap *m, char *table, int use_inv) {
     combo[0] = '\0';
     combo++;
 
+    if (use_inv == 2) {
+      hashmap_set(m, str, strlen(str) - 1, (uintptr_t)combo, 0);
+      continue;
+    }
+
     hashmap_set(m, combo, strlen(combo) - 1, (uintptr_t)str, 1);
   }
 
diff --git a/src/main.c b/src/main.c
index 7ebb4d1..11deef3 100644
--- a/src/main.c
+++ b/src/main.c
@@ -8,44 +8,63 @@
 #define inv_file "inv.txt"
 #define inv_base_file "inv_base.txt"
 #define combo_file "combos.txt"
+#define poll_file "polls.txt"
+#define polls_lock_file "polls_lock.txt"
 
 #define MAX_BUF_LENGTH 1024
 #define MAX_COMBO_LENGTH 1024
 
-void init_tables(hashmap *elements, hashmap *inv, int do_inv) {
-
-  load_elements(elements, "../elem_data/" combo_file, 0) ||
-      load_elements(elements, combo_file, 0) ||
+void init_tables(hashmap *elements, hashmap *inv, hashmap *polls, int do_inv) {
+  load_elements(elements, "../elem_data/" combo_file, 0);
+  load_elements(elements, combo_file, 0) ||
       load_elements(elements, "bin/" combo_file, 0);
 
+  load_elements(polls, "../elem_data/" poll_file, 2);
+
   if (!do_inv)
     return;
 
   load_elements(elements, "../elem_data/" inv_base_file, 1) ||
       load_elements(inv, inv_base_file, 1) ||
       load_elements(inv, "bin/" inv_base_file, 1);
+
+  load_elements(inv, inv_file, 1);
 }
 
 int main(int argc, char *argv[]) {
+  char *name;
+  if (argc < 2) {
+    name = "guest";
+  } else {
+    name = argv[1];
+  }
+
   hashmap *elements = hashmap_create();
   hashmap *inv = hashmap_create();
+  hashmap *polls = hashmap_create();
 
   char *command = calloc(MAX_BUF_LENGTH, sizeof(char));
   char *command_re = calloc(MAX_BUF_LENGTH, sizeof(char));
   char **sort_tmp = calloc(MAX_COMBO_LENGTH, sizeof(char **));
 
-  init_tables(elements, inv, 1);
+  int wasCombination = 0;
 
-  load_elements(inv, inv_file, 1);
+  init_tables(elements, inv, polls, 1);
 
-  printf("Welcome to Elemental on Command Line!\n");
+  printf("%s, welcome to Elemental on Command Line!\n", name);
   while (1) {
     // todo: separate into functions
 
     printf("\n");
     fgets(command, MAX_BUF_LENGTH - 1, stdin);
-    int slashRan = slash_command(command, inv);
-    if (slashRan)
+
+    if (wasCombination && suggest_command(command, command_re, polls, name)) {
+      wasCombination = 0;
+      continue;
+    }
+    wasCombination = 0;
+
+    if (slash_command(command, inv))
       continue;
 
     int combos = get_command(command, command_re, sort_tmp);
@@ -68,13 +87,14 @@ int main(int argc, char *argv[]) {
     hashmap_get(elements, command_re, strlen(command_re), &result);
 
     if (result == 0) {
-      init_tables(elements, inv, 0);
+      init_tables(elements, inv, polls, 0);
 
       hashmap_get(elements, command_re, strlen(command_re), &result);
     }
 
     if (result == 0) {
-      printf("You didn't make anything.\n");
+      wasCombination = 1;
+      printf("You didn't make anything; use /suggest to suggest an element.\n");
       continue;
     }
 
diff --git a/src/map.c b/src/map.c
index 59deeb2..5f362bd 100644
--- a/src/map.c
+++ b/src/map.c
@@ -2,6 +2,7 @@
 //  map.h
 //
 //  Created by Mashpoe on 1/15/21.
+//  Modifications by BiglyDerv
 //
 
 #include "map.h"

From 0fd6e738d9380ae0460bcbe6926c259bd98b4086 Mon Sep 17 00:00:00 2001
From: biglyderv <eggseggsarecool+git@gmail.com>
Date: Wed, 26 Mar 2025 22:15:43 -0400
Subject: [PATCH 07/50] force elements to be lowercase

---
 src/command.c | 5 -----
 src/main.c    | 7 +++++++
 2 files changed, 7 insertions(+), 5 deletions(-)

diff --git a/src/command.c b/src/command.c
index 1375bdd..321dc7a 100644
--- a/src/command.c
+++ b/src/command.c
@@ -1,5 +1,4 @@
 #include "map.h"
-#include <ctype.h>
 #include <stdint.h>
 #include <stdio.h>
 #include <stdlib.h>
@@ -243,10 +242,6 @@ int get_command(char *command, char *command_re, char **sort_tmp) {
 
   command[cl - 1] = '\0';
 
-  for (int i = 0; i < cl - 1; i++) {
-    command[i] = tolower(command[i]);
-  }
-
   sort_tmp[0] = command;
   int combos = 0;
   for (int i = 1; i < MAX_COMBO_LENGTH; i++) {
diff --git a/src/main.c b/src/main.c
index 11deef3..7809deb 100644
--- a/src/main.c
+++ b/src/main.c
@@ -1,5 +1,6 @@
 #include "command.h"
 #include "loader.h"
+#include <ctype.h>
 #include <stdint.h>
 #include <stdio.h>
 #include <stdlib.h>
@@ -58,6 +59,12 @@ int main(int argc, char *argv[]) {
     printf("\n");
     fgets(command, MAX_BUF_LENGTH - 1, stdin);
 
+    int cl = strlen(command);
+
+    for (int i = 0; i < cl - 1; i++) {
+      command[i] = tolower(command[i]);
+    }
+
     if (wasCombination && suggest_command(command, command_re, polls, name)) {
       wasCombination = 0;
       continue;

From 99bb41d542072deb9aa77949bed3b025daacddc1 Mon Sep 17 00:00:00 2001
From: biglyderv <eggseggsarecool+git@gmail.com>
Date: Wed, 26 Mar 2025 23:43:25 -0400
Subject: [PATCH 08/50] add guide

---
 README.md | 13 ++++++++++++-
 1 file changed, 12 insertions(+), 1 deletion(-)

diff --git a/README.md b/README.md
index d331afb..cb89545 100644
--- a/README.md
+++ b/README.md
@@ -1,2 +1,13 @@
 # Elemental on CLI 
-Elemental combination game written in C.
\ No newline at end of file
+Elemental combination game written in C.
+
+## Single-player
+A single-player example pack is provided as an example in ``combos.txt``. This can be customized by the user, although internal limitations require the combination string to be in alphabetical order.
+
+## Multi-player
+To set up multi-player mode, create a directory ``elem-data`` and create separate directories for each user that plays.
+
+The game can now be played with the following syntax, inside your user directory.
+```sh
+./bin/elem your_username
+```
\ No newline at end of file

From 1de63b1f14c6831ca61e6d7487ab6c76f8ccae28 Mon Sep 17 00:00:00 2001
From: biglyderv <eggseggsarecool+git@gmail.com>
Date: Wed, 26 Mar 2025 23:47:21 -0400
Subject: [PATCH 09/50] some fixes to grammar

---
 README.md | 6 +++---
 1 file changed, 3 insertions(+), 3 deletions(-)

diff --git a/README.md b/README.md
index cb89545..635d86b 100644
--- a/README.md
+++ b/README.md
@@ -1,5 +1,5 @@
-# Elemental on CLI 
-Elemental combination game written in C.
+# Elemental on Command Line
+This is an elemental combination game written in C, with optional multi-player support.
 
 ## Single-player
 A single-player example pack is provided as an example in ``combos.txt``. This can be customized by the user, although internal limitations require the combination string to be in alphabetical order.
@@ -9,5 +9,5 @@ To set up multi-player mode, create a directory ``elem-data`` and create separat
 
 The game can now be played with the following syntax, inside your user directory.
 ```sh
-./bin/elem your_username
+elem your_username
 ```
\ No newline at end of file

From cb2ec2873a74de2894b1b97b69d743a117273fb0 Mon Sep 17 00:00:00 2001
From: biglyderv <eggseggsarecool+git@gmail.com>
Date: Wed, 26 Mar 2025 23:49:52 -0400
Subject: [PATCH 10/50] yes

---
 README.md | 9 +++++----
 1 file changed, 5 insertions(+), 4 deletions(-)

diff --git a/README.md b/README.md
index 635d86b..a7f7a8c 100644
--- a/README.md
+++ b/README.md
@@ -2,12 +2,13 @@
 This is an elemental combination game written in C, with optional multi-player support.
 
 ## Single-player
-A single-player example pack is provided as an example in ``combos.txt``. This can be customized by the user, although internal limitations require the combination string to be in alphabetical order.
+A single-player example pack is provided as an example in ``bin/combos.txt``. This can be customized by the user, although internal limitations require the combination string to be in alphabetical order.
 
 ## Multi-player
-To set up multi-player mode, create a directory ``elem-data`` and create separate directories for each user that plays.
+To set up multi-player mode, create a directory ``../elem-data`` with a copy of ``bin/inv_base.txt``.  Also, create separate directories for each user that plays.
 
-The game can now be played with the following syntax, inside your user directory.
+The game can now be played with the following syntax, inside your user directory:
 ```sh
-elem your_username
+cd ../your_user_dir
+../elemental-command-line/bin/elem your_username
 ```
\ No newline at end of file

From aab88a6c194f01986095f2b6fad122738a5178f5 Mon Sep 17 00:00:00 2001
From: biglyderv <eggseggsarecool+git@gmail.com>
Date: Wed, 26 Mar 2025 23:55:56 -0400
Subject: [PATCH 11/50] typo simulator

---
 README.md | 2 +-
 1 file changed, 1 insertion(+), 1 deletion(-)

diff --git a/README.md b/README.md
index a7f7a8c..9b62a50 100644
--- a/README.md
+++ b/README.md
@@ -5,7 +5,7 @@ This is an elemental combination game written in C, with optional multi-player s
 A single-player example pack is provided as an example in ``bin/combos.txt``. This can be customized by the user, although internal limitations require the combination string to be in alphabetical order.
 
 ## Multi-player
-To set up multi-player mode, create a directory ``../elem-data`` with a copy of ``bin/inv_base.txt``.  Also, create separate directories for each user that plays.
+To set up multi-player mode, create a directory ``../elem_data`` with a copy of ``bin/inv_base.txt``.  Also, create separate directories for each user that plays.
 
 The game can now be played with the following syntax, inside your user directory:
 ```sh

From dffdf200cc8ed18b2992acc982c0c479053f37cd Mon Sep 17 00:00:00 2001
From: biglyderv <eggseggsarecool+git@gmail.com>
Date: Thu, 27 Mar 2025 07:34:20 -0400
Subject: [PATCH 12/50] optimize for filesize

---
 Makefile      |  2 +-
 src/command.c |  7 +------
 src/loader.c  |  2 +-
 src/main.c    |  9 +--------
 src/main.h    | 11 +++++++++++
 5 files changed, 15 insertions(+), 16 deletions(-)
 create mode 100644 src/main.h

diff --git a/Makefile b/Makefile
index 29d7bb4..5baff72 100644
--- a/Makefile
+++ b/Makefile
@@ -2,4 +2,4 @@ CC?=gcc
 BIN?=bin/elem
 
 make: src/main.c
-	$(CC) -o $(BIN) src/map.c src/loader.c src/command.c src/main.c
\ No newline at end of file
+	$(CC) -ffunction-sections -fdata-sections -Wl,--gc-sections -Os -o $(BIN) src/map.c src/loader.c src/command.c src/main.c
\ No newline at end of file
diff --git a/src/command.c b/src/command.c
index 321dc7a..0392267 100644
--- a/src/command.c
+++ b/src/command.c
@@ -4,12 +4,7 @@
 #include <stdlib.h>
 #include <string.h>
 
-#define MAX_BUF_LENGTH 1024
-#define MAX_COMBO_LENGTH 1024
-#define poll_file "polls.txt"
-#define polls_lock_file "polls_lock.txt"
-#define combo_file "combos.txt"
-#define UPVOTE_IN 2
+#include "main.h"
 
 struct pager {
   int page;
diff --git a/src/loader.c b/src/loader.c
index 190d34a..1a3eba4 100644
--- a/src/loader.c
+++ b/src/loader.c
@@ -4,7 +4,7 @@
 #include <stdlib.h>
 #include <string.h>
 
-#define MAX_FILE_SIZE 1024 * 16
+#include "main.h"
 
 int load_elements(hashmap *m, char *table, int use_inv) {
   FILE *fptr;
diff --git a/src/main.c b/src/main.c
index 7809deb..561a50e 100644
--- a/src/main.c
+++ b/src/main.c
@@ -6,14 +6,7 @@
 #include <stdlib.h>
 #include <string.h>
 
-#define inv_file "inv.txt"
-#define inv_base_file "inv_base.txt"
-#define combo_file "combos.txt"
-#define poll_file "polls.txt"
-#define polls_lock_file "polls_lock.txt"
-
-#define MAX_BUF_LENGTH 1024
-#define MAX_COMBO_LENGTH 1024
+#include "main.h"
 
 void init_tables(hashmap *elements, hashmap *inv, hashmap *polls, int do_inv) {
   load_elements(elements, "../elem_data/" combo_file, 0);
diff --git a/src/main.h b/src/main.h
new file mode 100644
index 0000000..02691b9
--- /dev/null
+++ b/src/main.h
@@ -0,0 +1,11 @@
+#define inv_file "inv.txt"
+#define inv_base_file "inv_base.txt"
+#define combo_file "combos.txt"
+#define poll_file "polls.txt"
+#define polls_lock_file "polls_lock.txt"
+
+#define MAX_BUF_LENGTH 1024
+#define MAX_COMBO_LENGTH 1024
+#define UPVOTE_IN 2
+#define MAX_FILE_SIZE 1024 * 16
+long stoi(const char *s);
\ No newline at end of file

From 0e3dd1a83f7b18cf853a7eee0dc933c46b17f457 Mon Sep 17 00:00:00 2001
From: biglyderv <eggseggsarecool+git@gmail.com>
Date: Thu, 27 Mar 2025 09:51:49 -0400
Subject: [PATCH 13/50] 32-bit support, compile wrapper

---
 .gitignore    |  4 +++-
 src/command.c | 35 ++++-------------------------------
 wrap.sh       |  5 +++++
 3 files changed, 12 insertions(+), 32 deletions(-)
 create mode 100755 wrap.sh

diff --git a/.gitignore b/.gitignore
index 6ffd8c6..7ac3b40 100644
--- a/.gitignore
+++ b/.gitignore
@@ -1,5 +1,7 @@
 /bin/elem
 /bin/elem.exe
+/bin/elem_32.exe
 /inv.txt
 /inv_users.txt
-/polls.txt
\ No newline at end of file
+/polls.txt
+/elem.tar.gz
\ No newline at end of file
diff --git a/src/command.c b/src/command.c
index 0392267..bdd3e1f 100644
--- a/src/command.c
+++ b/src/command.c
@@ -46,16 +46,7 @@ int sort_comp(const void *a, const void *b) {
   return strcmp(*(char **)a, *(char **)b);
 }
 
-#if !defined(_WIN32) && (defined(__unix__) || defined(__unix) ||               \
-                         (defined(__APPLE__) && defined(__MACH__)))
-
-int inv_handler(const void *key, unsigned long size, unsigned long val,
-                void *usr)
-#else
-int inv_handler(const void *key, unsigned long long size,
-                unsigned long long val, void *usr)
-#endif
-{
+int inv_handler(const void *key, size_t size, uintptr_t val, void *usr) {
   struct pager *i = usr;
   i->i++;
   if (i->i < i->page * 10 || i->i >= (i->page + 1) * 10) {
@@ -73,19 +64,10 @@ int inv_handler(const void *key, unsigned long long size,
   return 1;
 }
 
-#if !defined(_WIN32) && (defined(__unix__) || defined(__unix) ||               \
-                         (defined(__APPLE__) && defined(__MACH__)))
-
-int polls_handler(const void *key, unsigned long size, unsigned long val,
-                  void *usr)
-#else
-int polls_handler(const void *key, unsigned long long size,
-                  unsigned long long val, void *usr)
-#endif
-{
+int polls_handler(const void *key, size_t size, uintptr_t val, void *usr) {
   struct verifier *verified = (struct verifier *)usr;
 
-  if (((char*) val)[strlen(((char *)val)) - 1] == '\n') {
+  if (((char *)val)[strlen(((char *)val)) - 1] == '\n') {
     ((char *)val)[strlen(((char *)val)) - 1] = '\0';
   }
 
@@ -96,16 +78,7 @@ int polls_handler(const void *key, unsigned long long size,
   return 0;
 }
 
-#if !defined(_WIN32) && (defined(__unix__) || defined(__unix) ||               \
-                         (defined(__APPLE__) && defined(__MACH__)))
-
-int success_handler(const void *key, unsigned long size, unsigned long val,
-                    void *usr)
-#else
-int success_handler(const void *key, unsigned long long size,
-                    unsigned long long val, void *usr)
-#endif
-{
+int success_handler(const void *key, size_t size, uintptr_t val, void *usr) {
   struct succ *verified = (struct succ *)usr;
 
   if ((char *)val != verified->sugg) {
diff --git a/wrap.sh b/wrap.sh
new file mode 100755
index 0000000..0ef25f0
--- /dev/null
+++ b/wrap.sh
@@ -0,0 +1,5 @@
+make
+CC=x86_64-w64-mingw32-gcc BIN=./bin/elem.exe make
+CC=i686-w64-mingw32-gcc BIN=./bin/elem_32.exe make
+rm ./elem.tar.gz
+tar -cvf ./elem.tar.gz bin
\ No newline at end of file

From fe1de151ffe5538fa7678487983aff9bf5700f52 Mon Sep 17 00:00:00 2001
From: biglyderv <eggseggsarecool+git@gmail.com>
Date: Thu, 27 Mar 2025 15:56:47 -0400
Subject: [PATCH 14/50] optimization on memory

---
 src/command.c |  5 +++++
 src/loader.c  | 11 +++++++----
 src/main.c    |  1 +
 src/main.h    |  2 +-
 4 files changed, 14 insertions(+), 5 deletions(-)

diff --git a/src/command.c b/src/command.c
index bdd3e1f..b3b52f5 100644
--- a/src/command.c
+++ b/src/command.c
@@ -111,6 +111,11 @@ int suggest_command(char *command, char *command_re, hashmap *polls,
   }
   page[strlen(page) - 1] = '\0';
 
+  if (strstr(page,"\n") || strstr(page,";") || strstr(page,",") || strstr(page,"+")) {
+    printf("This element contains illegal characters.\n");
+    return 1;
+  }
+
   char *val = calloc(MAX_BUF_LENGTH, sizeof(char));
   sprintf(val, "%s;%s", page, command_re);
 
diff --git a/src/loader.c b/src/loader.c
index 1a3eba4..ab1a071 100644
--- a/src/loader.c
+++ b/src/loader.c
@@ -32,12 +32,15 @@ int load_elements(hashmap *m, char *table, int use_inv) {
       continue;
     }
 
-    char *combo = strstr(str, ";");
-    combo[0] = '\0';
-    combo++;
+    char *combo_o = strstr(str, ";");
+    combo_o[0] = '\0';
+    combo_o++;
+
+    char *combo = calloc(strlen(combo_o)+1,sizeof(char));
+    strcpy(combo,combo_o);
 
     if (use_inv == 2) {
-      hashmap_set(m, str, strlen(str) - 1, (uintptr_t)combo, 0);
+      hashmap_set(m, str, strlen(str) - 1, (uintptr_t)combo, 1);
       continue;
     }
 
diff --git a/src/main.c b/src/main.c
index 561a50e..4ca5f1f 100644
--- a/src/main.c
+++ b/src/main.c
@@ -25,6 +25,7 @@ void init_tables(hashmap *elements, hashmap *inv, hashmap *polls, int do_inv) {
   load_elements(inv, inv_file, 1);
 }
 
+// todo: sanitize, valgrind, look through todos
 int main(int argc, char *argv[]) {
   char *name;
   if (argc < 2) {
diff --git a/src/main.h b/src/main.h
index 02691b9..199f669 100644
--- a/src/main.h
+++ b/src/main.h
@@ -7,5 +7,5 @@
 #define MAX_BUF_LENGTH 1024
 #define MAX_COMBO_LENGTH 1024
 #define UPVOTE_IN 2
-#define MAX_FILE_SIZE 1024 * 16
+#define MAX_FILE_SIZE 1024
 long stoi(const char *s);
\ No newline at end of file

From 15f6ca97158f3f212145bf19284e11c8eedc39d5 Mon Sep 17 00:00:00 2001
From: biglyderv <eggseggsarecool+git@gmail.com>
Date: Thu, 27 Mar 2025 18:00:30 -0400
Subject: [PATCH 15/50] remove inv duping

---
 src/main.c | 9 +++++++++
 1 file changed, 9 insertions(+)

diff --git a/src/main.c b/src/main.c
index 4ca5f1f..849deca 100644
--- a/src/main.c
+++ b/src/main.c
@@ -101,6 +101,15 @@ int main(int argc, char *argv[]) {
 
     char *res_str = (char *)result;
 
+    uintptr_t result2;
+
+    hashmap_get(inv, res_str, strlen(res_str), &result2);
+
+    if (result2 == 1) {
+      printf("You made %s, but you already have it.\n", res_str);
+      continue;
+    }
+
     hashmap_set(inv, res_str, strlen(res_str), (uintptr_t)1, 0);
     printf("You made %s!\n", res_str);
 

From c278da17050705d44a15a52da885ca93379ce513 Mon Sep 17 00:00:00 2001
From: biglyderv <eggseggsarecool+git@gmail.com>
Date: Thu, 27 Mar 2025 22:12:19 -0400
Subject: [PATCH 16/50] add detailed help and polls commands

---
 src/command.c | 69 ++++++++++++++++++++++++++++++++++++++++-----------
 src/command.h |  4 ++-
 src/main.c    |  8 ++++--
 3 files changed, 63 insertions(+), 18 deletions(-)

diff --git a/src/command.c b/src/command.c
index b3b52f5..8c3a5d1 100644
--- a/src/command.c
+++ b/src/command.c
@@ -6,9 +6,12 @@
 
 #include "main.h"
 
+// huge cleanup operation soon
+
 struct pager {
   int page;
   int i;
+  int is_poll;
 };
 
 struct verifier {
@@ -55,11 +58,21 @@ int inv_handler(const void *key, size_t size, uintptr_t val, void *usr) {
   if (val == 0)
     return 0;
   char *key2 = (char *)key;
+  char* val2 = (char*) val;
+
+  if (i->is_poll) {
+    if (val2[strlen(val2) - 1] == '\n') {
+      printf("- %s suggested %s", key2, val2);
+    } else {
+      printf("-  %s suggested  %s\n", key2, val2);
+    }
+    return 1;
+  }
 
   if (key2[strlen(key2) - 1] == '\n') {
-    printf("- %s", (char *)key);
+    printf("- %s", key2);
   } else {
-    printf("- %s\n", (char *)key);
+    printf("- %s\n", key2);
   }
   return 1;
 }
@@ -94,13 +107,7 @@ int success_handler(const void *key, size_t size, uintptr_t val, void *usr) {
 
 int suggest_command(char *command, char *command_re, hashmap *polls,
                     char *name) {
-  if (command[0] == '/') {
-    command++;
-  } else {
-    return 0;
-  }
-
-  char *invs = "suggest ";
+  char *invs = "/suggest ";
 
   char *page;
 
@@ -111,7 +118,8 @@ int suggest_command(char *command, char *command_re, hashmap *polls,
   }
   page[strlen(page) - 1] = '\0';
 
-  if (strstr(page,"\n") || strstr(page,";") || strstr(page,",") || strstr(page,"+")) {
+  if (strstr(page, "\n") || strstr(page, ";") || strstr(page, ",") ||
+      strstr(page, "+")) {
     printf("This element contains illegal characters.\n");
     return 1;
   }
@@ -168,15 +176,46 @@ int suggest_command(char *command, char *command_re, hashmap *polls,
   return 1;
 }
 
-int slash_command(char *command, hashmap *inv) {
+int help_command(char *command) {
+  char *invs = "/help";
 
-  if (command[0] == '/') {
-    command++;
+  int page;
+
+  if (strncmp(command, invs, strlen(invs)) == 0) {
+
+    printf("Available "
+           "commands:\n- elem1;elem2...\n- elem1+elem2...\n- elem1,elem2...\n- "
+           "/help\n- /inv [page]\n- /suggest [combo]\n- /polls [page]\n");
   } else {
     return 0;
   }
 
-  char *invs = "inv ";
+  return 1;
+}
+
+int polls_command(char *command, hashmap *polls) {
+
+  char *invs = "/polls ";
+
+  int page;
+
+  if (strncmp(command, invs, strlen(invs)) == 0) {
+    page = stoi(&command[strlen(invs)]);
+  } else if (strncmp(command, invs, strlen(invs) - 1) == 0) {
+    page = 1;
+  } else {
+    return 0;
+  }
+
+  printf("Current polls (page %i):\n", page);
+  struct pager i = {.page = page - 1, .i = -1, .is_poll = 1};
+  hashmap_iterate(polls, inv_handler, &i);
+  return 1;
+}
+
+int slash_command(char *command, hashmap *inv) {
+
+  char *invs = "/inv ";
 
   int page;
 
@@ -189,7 +228,7 @@ int slash_command(char *command, hashmap *inv) {
   }
 
   printf("Your inventory (page %i):\n", page);
-  struct pager i = {.page = page - 1, .i = -1};
+  struct pager i = {.page = page - 1, .i = -1, .is_poll = 1};
   hashmap_iterate(inv, inv_handler, &i);
   return 1;
 }
diff --git a/src/command.h b/src/command.h
index a91b2ea..24d7e36 100644
--- a/src/command.h
+++ b/src/command.h
@@ -2,4 +2,6 @@
 int get_command(char *command, char *command_re, char **sort_tmp);
 int slash_command(char *command, hashmap *inv);
 int suggest_command(char *command, char *command_re, hashmap *polls,
-                    char *name);
\ No newline at end of file
+                    char *name);
+int help_command(char *command);
+int polls_command(char *command, hashmap *polls);
\ No newline at end of file
diff --git a/src/main.c b/src/main.c
index 849deca..b4c6f9c 100644
--- a/src/main.c
+++ b/src/main.c
@@ -8,6 +8,8 @@
 
 #include "main.h"
 
+// todo: polls, help commands, spacing in combos
+
 void init_tables(hashmap *elements, hashmap *inv, hashmap *polls, int do_inv) {
   load_elements(elements, "../elem_data/" combo_file, 0);
   load_elements(elements, combo_file, 0) ||
@@ -25,7 +27,6 @@ void init_tables(hashmap *elements, hashmap *inv, hashmap *polls, int do_inv) {
   load_elements(inv, inv_file, 1);
 }
 
-// todo: sanitize, valgrind, look through todos
 int main(int argc, char *argv[]) {
   char *name;
   if (argc < 2) {
@@ -64,7 +65,10 @@ int main(int argc, char *argv[]) {
       continue;
     }
     wasCombination = 0;
-
+    if (help_command(command))
+      continue;
+    if (polls_command(command, polls))
+      continue;
     if (slash_command(command, inv))
       continue;
 

From a6451e4904c81a692241ac31945a1c986c9b7a5e Mon Sep 17 00:00:00 2001
From: biglyderv <eggseggsarecool+git@gmail.com>
Date: Fri, 28 Mar 2025 01:36:28 -0400
Subject: [PATCH 17/50] don't continue on empty strings

---
 src/main.c | 13 ++++++++++++-
 1 file changed, 12 insertions(+), 1 deletion(-)

diff --git a/src/main.c b/src/main.c
index b4c6f9c..78a67b4 100644
--- a/src/main.c
+++ b/src/main.c
@@ -48,14 +48,25 @@ int main(int argc, char *argv[]) {
   init_tables(elements, inv, polls, 1);
 
   printf("%s, welcome to Elemental on Command Line!\n", name);
+  int newline = 1;
   while (1) {
     // todo: separate into functions
 
-    printf("\n");
+    if (newline) {
+
+      printf("\n");
+    }
     fgets(command, MAX_BUF_LENGTH - 1, stdin);
 
     int cl = strlen(command);
 
+    if (cl < 2) {
+      newline = 0;
+      continue;
+    } else {
+      newline = 1;
+    }
+
     for (int i = 0; i < cl - 1; i++) {
       command[i] = tolower(command[i]);
     }

From 79e380eddbb723e28eae309f5327523f2363b9b7 Mon Sep 17 00:00:00 2001
From: biglyderv <eggseggsarecool+git@gmail.com>
Date: Fri, 28 Mar 2025 01:54:00 -0400
Subject: [PATCH 18/50] fix flushing bug

---
 src/main.c | 2 +-
 1 file changed, 1 insertion(+), 1 deletion(-)

diff --git a/src/main.c b/src/main.c
index 78a67b4..c4adde9 100644
--- a/src/main.c
+++ b/src/main.c
@@ -51,9 +51,9 @@ int main(int argc, char *argv[]) {
   int newline = 1;
   while (1) {
     // todo: separate into functions
+    fflush(stdout);
 
     if (newline) {
-
       printf("\n");
     }
     fgets(command, MAX_BUF_LENGTH - 1, stdin);

From 6ef90f930d33f7f4b784a031ead30f7a0738ad09 Mon Sep 17 00:00:00 2001
From: biglyderv <eggseggsarecool+git@gmail.com>
Date: Fri, 28 Mar 2025 02:17:42 -0400
Subject: [PATCH 19/50] fix inv bug

---
 README.md     | 2 +-
 src/command.c | 4 ++--
 src/main.c    | 2 +-
 3 files changed, 4 insertions(+), 4 deletions(-)

diff --git a/README.md b/README.md
index 9b62a50..f95e7a8 100644
--- a/README.md
+++ b/README.md
@@ -5,7 +5,7 @@ This is an elemental combination game written in C, with optional multi-player s
 A single-player example pack is provided as an example in ``bin/combos.txt``. This can be customized by the user, although internal limitations require the combination string to be in alphabetical order.
 
 ## Multi-player
-To set up multi-player mode, create a directory ``../elem_data`` with a copy of ``bin/inv_base.txt``.  Also, create separate directories for each user that plays.
+To set up multi-player mode, create a directory ``../elem_data``.  Also, create separate directories for each user that plays.
 
 The game can now be played with the following syntax, inside your user directory:
 ```sh
diff --git a/src/command.c b/src/command.c
index 8c3a5d1..b1b733a 100644
--- a/src/command.c
+++ b/src/command.c
@@ -58,7 +58,7 @@ int inv_handler(const void *key, size_t size, uintptr_t val, void *usr) {
   if (val == 0)
     return 0;
   char *key2 = (char *)key;
-  char* val2 = (char*) val;
+  char *val2 = (char *)val;
 
   if (i->is_poll) {
     if (val2[strlen(val2) - 1] == '\n') {
@@ -69,7 +69,7 @@ int inv_handler(const void *key, size_t size, uintptr_t val, void *usr) {
     return 1;
   }
 
-  if (key2[strlen(key2) - 1] == '\n') {
+  if (strlen(key2) > 0 && key2[strlen(key2) - 1] == '\n') {
     printf("- %s", key2);
   } else {
     printf("- %s\n", key2);
diff --git a/src/main.c b/src/main.c
index c4adde9..6570974 100644
--- a/src/main.c
+++ b/src/main.c
@@ -20,7 +20,7 @@ void init_tables(hashmap *elements, hashmap *inv, hashmap *polls, int do_inv) {
   if (!do_inv)
     return;
 
-  load_elements(elements, "../elem_data/" inv_base_file, 1) ||
+  load_elements(inv, "../elem_data/" inv_base_file, 1) ||
       load_elements(inv, inv_base_file, 1) ||
       load_elements(inv, "bin/" inv_base_file, 1);
 

From 26770efc64fbf41b8cd770e3a225453d8d2c3937 Mon Sep 17 00:00:00 2001
From: biglyderv <eggseggsarecool+git@gmail.com>
Date: Fri, 28 Mar 2025 02:31:01 -0400
Subject: [PATCH 20/50] fix weird inv segfault

---
 src/command.c | 2 +-
 1 file changed, 1 insertion(+), 1 deletion(-)

diff --git a/src/command.c b/src/command.c
index b1b733a..ac5e0a1 100644
--- a/src/command.c
+++ b/src/command.c
@@ -228,7 +228,7 @@ int slash_command(char *command, hashmap *inv) {
   }
 
   printf("Your inventory (page %i):\n", page);
-  struct pager i = {.page = page - 1, .i = -1, .is_poll = 1};
+  struct pager i = {.page = page - 1, .i = -1, .is_poll = 0};
   hashmap_iterate(inv, inv_handler, &i);
   return 1;
 }

From 4b3b6c9111ee88ed02c8408d04b9f04bd69ea16c Mon Sep 17 00:00:00 2001
From: biglyderv <eggseggsarecool+git@gmail.com>
Date: Fri, 28 Mar 2025 16:37:38 -0400
Subject: [PATCH 21/50] don't say anything when there is no combo

---
 src/main.c | 5 ++++-
 1 file changed, 4 insertions(+), 1 deletion(-)

diff --git a/src/main.c b/src/main.c
index 6570974..e7b52b3 100644
--- a/src/main.c
+++ b/src/main.c
@@ -47,7 +47,7 @@ int main(int argc, char *argv[]) {
 
   init_tables(elements, inv, polls, 1);
 
-  printf("%s, welcome to Elemental on Command Line!\n", name);
+  printf("%s, welcome to Elemental on Command Line!\nType /help for commands.\n", name);
   int newline = 1;
   while (1) {
     // todo: separate into functions
@@ -85,6 +85,9 @@ int main(int argc, char *argv[]) {
 
     int combos = get_command(command, command_re, sort_tmp);
 
+    if (combos < 2)
+      continue;
+
     int failed = 0;
     for (int i = 0; i < combos; i++) {
       uintptr_t result;

From 177f9025e04ef1dea3aeeb4ca0e1e2fecfd6c2ca Mon Sep 17 00:00:00 2001
From: biglyderv <eggseggsarecool+git@gmail.com>
Date: Sat, 29 Mar 2025 02:51:38 -0400
Subject: [PATCH 22/50] clean up the poll command output

---
 src/command.c | 9 +++++++--
 src/main.c    | 2 +-
 src/main.h    | 1 +
 3 files changed, 9 insertions(+), 3 deletions(-)

diff --git a/src/command.c b/src/command.c
index ac5e0a1..7b60c8f 100644
--- a/src/command.c
+++ b/src/command.c
@@ -61,11 +61,16 @@ int inv_handler(const void *key, size_t size, uintptr_t val, void *usr) {
   char *val2 = (char *)val;
 
   if (i->is_poll) {
+    char *key3 = calloc(strlen(key2)+1,sizeof(char));
+    memcpy(key3,key2,strstr(key2,"_") - key2);
+
     if (val2[strlen(val2) - 1] == '\n') {
-      printf("- %s suggested %s", key2, val2);
+      printf("- %s suggested %s", key3, val2);
     } else {
-      printf("-  %s suggested  %s\n", key2, val2);
+      printf("-  %s suggested  %s\n", key3, val2);
     }
+
+    free(key3);
     return 1;
   }
 
diff --git a/src/main.c b/src/main.c
index e7b52b3..3d94128 100644
--- a/src/main.c
+++ b/src/main.c
@@ -8,7 +8,7 @@
 
 #include "main.h"
 
-// todo: polls, help commands, spacing in combos
+// todo: polls, help commands, spacing in combos, clean init_tables
 
 void init_tables(hashmap *elements, hashmap *inv, hashmap *polls, int do_inv) {
   load_elements(elements, "../elem_data/" combo_file, 0);
diff --git a/src/main.h b/src/main.h
index 199f669..7761ac3 100644
--- a/src/main.h
+++ b/src/main.h
@@ -3,6 +3,7 @@
 #define combo_file "combos.txt"
 #define poll_file "polls.txt"
 #define polls_lock_file "polls_lock.txt"
+#define lb_file "lb.txt"
 
 #define MAX_BUF_LENGTH 1024
 #define MAX_COMBO_LENGTH 1024

From 745a306b04099d3e4f167b56d3018f32f7a21c64 Mon Sep 17 00:00:00 2001
From: biglyderv <eggseggsarecool+git@gmail.com>
Date: Sat, 29 Mar 2025 04:59:17 -0400
Subject: [PATCH 23/50] don't show polls that passed

---
 src/command.c | 19 +++++++++++++++----
 src/command.h |  2 +-
 src/main.c    |  2 +-
 3 files changed, 17 insertions(+), 6 deletions(-)

diff --git a/src/command.c b/src/command.c
index 7b60c8f..a234faf 100644
--- a/src/command.c
+++ b/src/command.c
@@ -12,6 +12,7 @@ struct pager {
   int page;
   int i;
   int is_poll;
+  hashmap *cmd;
 };
 
 struct verifier {
@@ -61,8 +62,18 @@ int inv_handler(const void *key, size_t size, uintptr_t val, void *usr) {
   char *val2 = (char *)val;
 
   if (i->is_poll) {
-    char *key3 = calloc(strlen(key2)+1,sizeof(char));
-    memcpy(key3,key2,strstr(key2,"_") - key2);
+    char *key3 = calloc(strlen(key2) + 1, sizeof(char));
+    memcpy(key3, key2, strstr(key2, "_") - key2);
+
+    char *val3 = strstr(val2, ";") + 1;
+    uintptr_t result;
+
+    hashmap_get(i->cmd, val3, strlen(val3) - 1, &result);
+
+    if (result != 0) {
+      free(key3);
+      return 1;
+    }
 
     if (val2[strlen(val2) - 1] == '\n') {
       printf("- %s suggested %s", key3, val2);
@@ -198,7 +209,7 @@ int help_command(char *command) {
   return 1;
 }
 
-int polls_command(char *command, hashmap *polls) {
+int polls_command(char *command, hashmap *polls, hashmap *cmd) {
 
   char *invs = "/polls ";
 
@@ -213,7 +224,7 @@ int polls_command(char *command, hashmap *polls) {
   }
 
   printf("Current polls (page %i):\n", page);
-  struct pager i = {.page = page - 1, .i = -1, .is_poll = 1};
+  struct pager i = {.page = page - 1, .i = -1, .is_poll = 1, .cmd = cmd};
   hashmap_iterate(polls, inv_handler, &i);
   return 1;
 }
diff --git a/src/command.h b/src/command.h
index 24d7e36..f2f2ec4 100644
--- a/src/command.h
+++ b/src/command.h
@@ -4,4 +4,4 @@ int slash_command(char *command, hashmap *inv);
 int suggest_command(char *command, char *command_re, hashmap *polls,
                     char *name);
 int help_command(char *command);
-int polls_command(char *command, hashmap *polls);
\ No newline at end of file
+int polls_command(char *command, hashmap *polls, hashmap *cmd);
\ No newline at end of file
diff --git a/src/main.c b/src/main.c
index 3d94128..2ad9aa7 100644
--- a/src/main.c
+++ b/src/main.c
@@ -78,7 +78,7 @@ int main(int argc, char *argv[]) {
     wasCombination = 0;
     if (help_command(command))
       continue;
-    if (polls_command(command, polls))
+    if (polls_command(command, polls, elements))
       continue;
     if (slash_command(command, inv))
       continue;

From 9dc0c0684e07502244883bd769a971a28ee533aa Mon Sep 17 00:00:00 2001
From: biglyderv <eggseggsarecool+git@gmail.com>
Date: Sat, 29 Mar 2025 05:00:37 -0400
Subject: [PATCH 24/50] proper paging

---
 src/command.c | 14 ++++++++++----
 1 file changed, 10 insertions(+), 4 deletions(-)

diff --git a/src/command.c b/src/command.c
index a234faf..0a0a97c 100644
--- a/src/command.c
+++ b/src/command.c
@@ -52,10 +52,6 @@ int sort_comp(const void *a, const void *b) {
 
 int inv_handler(const void *key, size_t size, uintptr_t val, void *usr) {
   struct pager *i = usr;
-  i->i++;
-  if (i->i < i->page * 10 || i->i >= (i->page + 1) * 10) {
-    return 0;
-  }
   if (val == 0)
     return 0;
   char *key2 = (char *)key;
@@ -75,6 +71,11 @@ int inv_handler(const void *key, size_t size, uintptr_t val, void *usr) {
       return 1;
     }
 
+    i->i++;
+    if (i->i < i->page * 10 || i->i >= (i->page + 1) * 10) {
+      return 0;
+    }
+
     if (val2[strlen(val2) - 1] == '\n') {
       printf("- %s suggested %s", key3, val2);
     } else {
@@ -85,6 +86,11 @@ int inv_handler(const void *key, size_t size, uintptr_t val, void *usr) {
     return 1;
   }
 
+  i->i++;
+  if (i->i < i->page * 10 || i->i >= (i->page + 1) * 10) {
+    return 0;
+  }
+
   if (strlen(key2) > 0 && key2[strlen(key2) - 1] == '\n') {
     printf("- %s", key2);
   } else {

From 242041da34896f223decc51c35e4fd2c79f66625 Mon Sep 17 00:00:00 2001
From: biglyderv <eggseggsarecool+git@gmail.com>
Date: Sat, 29 Mar 2025 21:47:26 -0400
Subject: [PATCH 25/50] show inventory and poll totals

---
 src/command.c | 2 ++
 1 file changed, 2 insertions(+)

diff --git a/src/command.c b/src/command.c
index 0a0a97c..9e0f929 100644
--- a/src/command.c
+++ b/src/command.c
@@ -232,6 +232,7 @@ int polls_command(char *command, hashmap *polls, hashmap *cmd) {
   printf("Current polls (page %i):\n", page);
   struct pager i = {.page = page - 1, .i = -1, .is_poll = 1, .cmd = cmd};
   hashmap_iterate(polls, inv_handler, &i);
+  printf("Total: %i\n", i.i + 1);
   return 1;
 }
 
@@ -252,6 +253,7 @@ int slash_command(char *command, hashmap *inv) {
   printf("Your inventory (page %i):\n", page);
   struct pager i = {.page = page - 1, .i = -1, .is_poll = 0};
   hashmap_iterate(inv, inv_handler, &i);
+  printf("Total: %i\n", i.i + 1);
   return 1;
 }
 

From 5b9254211fa148eb9294d495b091bfe3d3ab0485 Mon Sep 17 00:00:00 2001
From: biglyderv <eggseggsarecool+git@gmail.com>
Date: Sun, 30 Mar 2025 01:07:00 -0400
Subject: [PATCH 26/50] improve paging logic, remove unused map code

---
 src/command.c | 68 ++++++++++++++++--------------------
 src/main.c    |  2 +-
 src/map.c     | 95 ---------------------------------------------------
 src/map.h     | 56 ------------------------------
 4 files changed, 31 insertions(+), 190 deletions(-)

diff --git a/src/command.c b/src/command.c
index 9e0f929..d3aa4a0 100644
--- a/src/command.c
+++ b/src/command.c
@@ -127,17 +127,31 @@ int success_handler(const void *key, size_t size, uintptr_t val, void *usr) {
   return 0;
 }
 
-int suggest_command(char *command, char *command_re, hashmap *polls,
-                    char *name) {
-  char *invs = "/suggest ";
-
-  char *page;
-
+char *handle_pages(char *command, char *invs) {
   if (strncmp(command, invs, strlen(invs)) == 0) {
-    page = &command[strlen(invs)];
+    return &command[strlen(invs)];
   } else {
     return 0;
   }
+}
+
+int handle_pages_int(char *command, char *invs) {
+  if (strncmp(command, invs, strlen(invs)) == 0) {
+    return stoi(&command[strlen(invs)]);
+  } else if (strncmp(command, invs, strlen(invs) - 1) == 0) {
+    return 1;
+  } else {
+    return 0;
+  }
+}
+
+int suggest_command(char *command, char *command_re, hashmap *polls,
+                    char *name) {
+
+  char *page = handle_pages(command, "/suggest ");
+
+  if (!page)
+    return 0;
   page[strlen(page) - 1] = '\0';
 
   if (strstr(page, "\n") || strstr(page, ";") || strstr(page, ",") ||
@@ -199,35 +213,21 @@ int suggest_command(char *command, char *command_re, hashmap *polls,
 }
 
 int help_command(char *command) {
-  char *invs = "/help";
+  char *page = handle_pages(command, "/help");
 
-  int page;
-
-  if (strncmp(command, invs, strlen(invs)) == 0) {
-
-    printf("Available "
-           "commands:\n- elem1;elem2...\n- elem1+elem2...\n- elem1,elem2...\n- "
-           "/help\n- /inv [page]\n- /suggest [combo]\n- /polls [page]\n");
-  } else {
+  if (!page)
     return 0;
-  }
-
+  printf("Available "
+         "commands:\n- elem1;elem2...\n- elem1+elem2...\n- elem1,elem2...\n- "
+         "/help\n- /inv [page]\n- /suggest [combo]\n- /polls [page]\n");
   return 1;
 }
 
 int polls_command(char *command, hashmap *polls, hashmap *cmd) {
 
-  char *invs = "/polls ";
-
-  int page;
-
-  if (strncmp(command, invs, strlen(invs)) == 0) {
-    page = stoi(&command[strlen(invs)]);
-  } else if (strncmp(command, invs, strlen(invs) - 1) == 0) {
-    page = 1;
-  } else {
+  int page = handle_pages_int(command, "/polls ");
+  if (page == 0)
     return 0;
-  }
 
   printf("Current polls (page %i):\n", page);
   struct pager i = {.page = page - 1, .i = -1, .is_poll = 1, .cmd = cmd};
@@ -238,17 +238,9 @@ int polls_command(char *command, hashmap *polls, hashmap *cmd) {
 
 int slash_command(char *command, hashmap *inv) {
 
-  char *invs = "/inv ";
-
-  int page;
-
-  if (strncmp(command, invs, strlen(invs)) == 0) {
-    page = stoi(&command[strlen(invs)]);
-  } else if (strncmp(command, invs, strlen(invs) - 1) == 0) {
-    page = 1;
-  } else {
+  int page = handle_pages_int(command, "/inv ");
+  if (page == 0)
     return 0;
-  }
 
   printf("Your inventory (page %i):\n", page);
   struct pager i = {.page = page - 1, .i = -1, .is_poll = 0};
diff --git a/src/main.c b/src/main.c
index 2ad9aa7..615b201 100644
--- a/src/main.c
+++ b/src/main.c
@@ -8,7 +8,7 @@
 
 #include "main.h"
 
-// todo: polls, help commands, spacing in combos, clean init_tables
+// todo: spacing in combos, clean init_tables
 
 void init_tables(hashmap *elements, hashmap *inv, hashmap *polls, int do_inv) {
   load_elements(elements, "../elem_data/" combo_file, 0);
diff --git a/src/map.c b/src/map.c
index 5f362bd..6f0aad3 100644
--- a/src/map.c
+++ b/src/map.c
@@ -199,67 +199,6 @@ int hashmap_set(hashmap *m, const void *key, size_t ksize, uintptr_t val,
   return 0;
 }
 
-int hashmap_get_set(hashmap *m, const void *key, size_t ksize,
-                    uintptr_t *out_in) {
-  if (m->count + 1 > HASHMAP_MAX_LOAD * m->capacity) {
-    if (hashmap_resize(m) == -1)
-      return -1;
-  }
-
-  uint32_t hash = hash_data(key, ksize);
-  struct bucket *entry = find_entry(m, key, ksize, hash);
-  if (entry->key == NULL) {
-    m->last->next = entry;
-    m->last = entry;
-    entry->next = NULL;
-
-    ++m->count;
-
-    entry->value = *out_in;
-    entry->key = key;
-    entry->ksize = ksize;
-    entry->hash = hash;
-
-    return 0;
-  }
-  *out_in = entry->value;
-  return 1;
-}
-
-int hashmap_set_free(hashmap *m, const void *key, size_t ksize, uintptr_t val,
-                     hashmap_callback c, void *usr) {
-  if (m->count + 1 > HASHMAP_MAX_LOAD * m->capacity) {
-    if (hashmap_resize(m) == -1)
-      return -1;
-  }
-
-  uint32_t hash = hash_data(key, ksize);
-  struct bucket *entry = find_entry(m, key, ksize, hash);
-  if (entry->key == NULL) {
-    m->last->next = entry;
-    m->last = entry;
-    entry->next = NULL;
-
-    ++m->count;
-
-    entry->key = key;
-    entry->ksize = ksize;
-    entry->hash = hash;
-    entry->value = val;
-    // there was no overwrite, exit the function.
-    return 0;
-  }
-  // allow the callback to free entry data.
-  // use old key and value so the callback can free them.
-  // the old key and value will be overwritten after this call.
-  int error = c(entry->key, ksize, entry->value, usr);
-
-  // overwrite the old key pointer in case the callback frees it.
-  entry->key = key;
-  entry->value = val;
-  return error;
-}
-
 int hashmap_get(hashmap *m, const void *key, size_t ksize, uintptr_t *out_val) {
   uint32_t hash = hash_data(key, ksize);
   struct bucket *entry = find_entry(m, key, ksize, hash);
@@ -270,40 +209,6 @@ int hashmap_get(hashmap *m, const void *key, size_t ksize, uintptr_t *out_val) {
   return entry->key != NULL ? 1 : 0;
 }
 
-// doesn't "remove" the element per se, but it will be ignored.
-// the element will eventually be removed when the map is resized.
-void hashmap_remove(hashmap *m, const void *key, size_t ksize) {
-  uint32_t hash = hash_data(key, ksize);
-  struct bucket *entry = find_entry(m, key, ksize, hash);
-
-  if (entry->key != NULL) {
-
-    // "tombstone" entry is signified by a NULL key with a nonzero value
-    // element removal is optional because of the overhead of tombstone checks
-    entry->key = NULL;
-    entry->value = 0xDEAD; // I mean, it's a tombstone...
-
-    ++m->tombstone_count;
-  }
-}
-
-void hashmap_remove_free(hashmap *m, const void *key, size_t ksize,
-                         hashmap_callback c, void *usr) {
-  uint32_t hash = hash_data(key, ksize);
-  struct bucket *entry = find_entry(m, key, ksize, hash);
-
-  if (entry->key != NULL) {
-    c(entry->key, entry->ksize, entry->value, usr);
-
-    // "tombstone" entry is signified by a NULL key with a nonzero value
-    // element removal is optional because of the overhead of tombstone checks
-    entry->key = NULL;
-    entry->value = 0xDEAD; // I mean, it's a tombstone...
-
-    ++m->tombstone_count;
-  }
-}
-
 int hashmap_size(hashmap *m) { return m->count - m->tombstone_count; }
 
 int hashmap_iterate(hashmap *m, hashmap_callback c, void *user_ptr) {
diff --git a/src/map.h b/src/map.h
index 775b62d..ca305c8 100644
--- a/src/map.h
+++ b/src/map.h
@@ -11,10 +11,6 @@
 #define hashmap_str_lit(str) (str), sizeof(str) - 1
 #define hashmap_static_arr(arr) (arr), sizeof(arr)
 
-// removal of map elements is disabled by default because of its slight
-// overhead. if you want to enable this feature, uncomment the line below:
-// #define __HASHMAP_REMOVABLE
-
 #include <stddef.h>
 #include <stdint.h>
 
@@ -44,69 +40,17 @@ struct hashmap {
   struct bucket *last;
 };
 
-// hashmaps can associate keys with pointer values or integral types.
 typedef struct hashmap hashmap;
 
-// a callback type used for iterating over a map/freeing entries:
-// `int <function name>(const void* key, size_t size, uintptr_t value, void*
-// usr)` `usr` is a user pointer which can be passed through `hashmap_iterate`.
 typedef int (*hashmap_callback)(const void *key, size_t ksize, uintptr_t value,
                                 void *usr);
 
 hashmap *hashmap_create(void);
-
-// only frees the hashmap object and buckets.
-// does not call free on each element's `key` or `value`.
-// to free data associated with an element, call `hashmap_iterate`.
 void hashmap_free(hashmap *map);
-
-// does not make a copy of `key`.
-// you must copy it yourself if you want to guarantee its lifetime,
-// or if you intend to call `hashmap_key_free`.
-// returns -1 on error.
 int hashmap_set(hashmap *map, const void *key, size_t ksize, uintptr_t value,
                 int free_old);
-
-// adds an entry if it doesn't exist, using the value of `*out_in`.
-// if it does exist, it sets value in `*out_in`, meaning the value
-// of the entry will be in `*out_in` regardless of whether or not
-// it existed in the first place.
-// returns -1 on error.
-// returns 1 if the entry already existed, returns 0 otherwise.
-int hashmap_get_set(hashmap *map, const void *key, size_t ksize,
-                    uintptr_t *out_in);
-
-// similar to `hashmap_set()`, but when overwriting an entry,
-// you'll be able properly free the old entry's data via a callback.
-// unlike `hashmap_set()`, this function will overwrite the original key
-// pointer, which means you can free the old key in the callback if applicable.
-int hashmap_set_free(hashmap *map, const void *key, size_t ksize,
-                     uintptr_t value, hashmap_callback c, void *usr);
-
 int hashmap_get(hashmap *map, const void *key, size_t ksize,
                 uintptr_t *out_val);
-
-#ifdef __HASHMAP_REMOVABLE
-void hashmap_remove(hashmap *map, const void *key, size_t ksize);
-
-// same as `hashmap_remove()`, but it allows you to free an entry's data first
-// via a callback.
-void hashmap_remove_free(hashmap *m, const void *key, size_t ksize,
-                         hashmap_callback c, void *usr);
-#endif
-
 int hashmap_size(hashmap *map);
-
-// iterate over the map, calling `c` on every element.
-// goes through elements in the order they were added.
-// the element's key, key size, value, and `usr` will be passed to `c`.
-// if `c` returns -1 the iteration is aborted.
-// returns the last result of `c`
 int hashmap_iterate(hashmap *map, hashmap_callback c, void *usr);
-
-// dumps bucket info for debugging.
-// allows you to see how many collisions you are getting.
-// `0` is an empty bucket, `1` is occupied, and `x` is removed.
-// void bucket_dump(hashmap *m);
-
 #endif // map_h

From d356b5423ea16707af547b467e46cb364e58ea3d Mon Sep 17 00:00:00 2001
From: biglyderv <eggseggsarecool+git@gmail.com>
Date: Sun, 30 Mar 2025 02:43:52 -0400
Subject: [PATCH 27/50] parse users differently

---
 src/command.c | 4 ++--
 src/main.c    | 2 +-
 2 files changed, 3 insertions(+), 3 deletions(-)

diff --git a/src/command.c b/src/command.c
index d3aa4a0..b82ee50 100644
--- a/src/command.c
+++ b/src/command.c
@@ -77,9 +77,9 @@ int inv_handler(const void *key, size_t size, uintptr_t val, void *usr) {
     }
 
     if (val2[strlen(val2) - 1] == '\n') {
-      printf("- %s suggested %s", key3, val2);
+      printf("- user:%s suggested %s", key3, val2);
     } else {
-      printf("-  %s suggested  %s\n", key3, val2);
+      printf("-  user:%s suggested  %s\n", key3, val2);
     }
 
     free(key3);
diff --git a/src/main.c b/src/main.c
index 615b201..716398c 100644
--- a/src/main.c
+++ b/src/main.c
@@ -47,7 +47,7 @@ int main(int argc, char *argv[]) {
 
   init_tables(elements, inv, polls, 1);
 
-  printf("%s, welcome to Elemental on Command Line!\nType /help for commands.\n", name);
+  printf("user:%s, welcome to Elemental on Command Line!\nType /help for commands.\n", name);
   int newline = 1;
   while (1) {
     // todo: separate into functions

From e6c412e6613a4c605ec8190df41bb1a33363ff85 Mon Sep 17 00:00:00 2001
From: biglyderv <eggseggsarecool+git@gmail.com>
Date: Mon, 31 Mar 2025 21:38:33 -0400
Subject: [PATCH 28/50] reduce size allocated for blocks

---
 src/loader.c | 15 ++++++++++-----
 1 file changed, 10 insertions(+), 5 deletions(-)

diff --git a/src/loader.c b/src/loader.c
index ab1a071..6154167 100644
--- a/src/loader.c
+++ b/src/loader.c
@@ -15,16 +15,21 @@ int load_elements(hashmap *m, char *table, int use_inv) {
     return 0;
 
   char *str;
+  char *str2;
 
   int did_something = 0;
 
   while (1) {
-    str = calloc(MAX_FILE_SIZE, sizeof(char));
-    if (!fgets(str, MAX_FILE_SIZE, fptr)) {
-      free(str);
+    str2 = calloc(MAX_FILE_SIZE, sizeof(char));
+    if (!fgets(str2, MAX_FILE_SIZE, fptr)) {
+      free(str2);
       break;
     }
 
+    str = calloc(strlen(str2) + 1, sizeof(char));
+    strcpy(str, str2);
+    free(str2);
+
     did_something = 1;
 
     if (use_inv == 1) {
@@ -36,8 +41,8 @@ int load_elements(hashmap *m, char *table, int use_inv) {
     combo_o[0] = '\0';
     combo_o++;
 
-    char *combo = calloc(strlen(combo_o)+1,sizeof(char));
-    strcpy(combo,combo_o);
+    char *combo = calloc(strlen(combo_o) + 1, sizeof(char));
+    strcpy(combo, combo_o);
 
     if (use_inv == 2) {
       hashmap_set(m, str, strlen(str) - 1, (uintptr_t)combo, 1);

From f1bc13d4e2322997aa5619fb582e907866e3dbe6 Mon Sep 17 00:00:00 2001
From: biglyderv <eggseggsarecool+git@gmail.com>
Date: Tue, 1 Apr 2025 21:10:25 -0400
Subject: [PATCH 29/50] add paths

---
 src/command.c | 57 +++++++++++++++++++++++++++++++++++++++++++++++++++
 src/command.h |  4 +++-
 src/main.c    | 19 +++++++++++++----
 3 files changed, 75 insertions(+), 5 deletions(-)

diff --git a/src/command.c b/src/command.c
index b82ee50..caf88ce 100644
--- a/src/command.c
+++ b/src/command.c
@@ -3,6 +3,7 @@
 #include <stdio.h>
 #include <stdlib.h>
 #include <string.h>
+#include <sys/types.h>
 
 #include "main.h"
 
@@ -236,6 +237,62 @@ int polls_command(char *command, hashmap *polls, hashmap *cmd) {
   return 1;
 }
 
+int path_command(char *command, hashmap *elements_rev, hashmap *already_done,
+                 int top) {
+  char *page;
+  if (top) {
+    page = handle_pages(command, "/path ");
+    if (page == 0)
+      return 0;
+  } else {
+    page = command;
+  }
+
+  page[strlen(page) - 1] = '\0';
+  if (strlen(page) == 0) return 1;
+
+  if (top) {
+    printf("Path of %s:\n", page);
+    hashmap_free(already_done);
+    already_done = hashmap_create();
+  }
+
+  uintptr_t result;
+  hashmap_get(already_done, page, strlen(page), &result);
+
+  if (result != 0)
+    return 1;
+  hashmap_set(already_done, page, strlen(page), (uintptr_t)1, 0);
+
+  hashmap_get(elements_rev, page, strlen(page) - 1, &result);
+
+  if (result == 0 || strlen((char *)result) < 1)
+    return 1;
+
+  printf("%s: %s", command, (char *)result);
+
+  // todo: refactor;
+  char *tmp = (char *)result, *tmp2 = 0;
+
+  int combos = 0;
+  for (int i = 1; i < MAX_COMBO_LENGTH; i++) {
+    combos = i;
+    tmp2 = tmp;
+    tmp = strstr(tmp, ";");
+    if (tmp == 0 || tmp2 == tmp)
+      break;
+    if (strlen(tmp) < 2) {
+      break;
+    }
+    tmp[0] = '\0';
+    tmp++;
+
+    path_command(tmp, elements_rev, already_done, 0);
+  }
+
+  return 1;
+}
+
 int slash_command(char *command, hashmap *inv) {
 
   int page = handle_pages_int(command, "/inv ");
diff --git a/src/command.h b/src/command.h
index f2f2ec4..906c249 100644
--- a/src/command.h
+++ b/src/command.h
@@ -4,4 +4,6 @@ int slash_command(char *command, hashmap *inv);
 int suggest_command(char *command, char *command_re, hashmap *polls,
                     char *name);
 int help_command(char *command);
-int polls_command(char *command, hashmap *polls, hashmap *cmd);
\ No newline at end of file
+int polls_command(char *command, hashmap *polls, hashmap *cmd);
+int path_command(char *command, hashmap *elements_rev, hashmap *already_done,
+    int top);
\ No newline at end of file
diff --git a/src/main.c b/src/main.c
index 716398c..d756e2a 100644
--- a/src/main.c
+++ b/src/main.c
@@ -10,11 +10,16 @@
 
 // todo: spacing in combos, clean init_tables
 
-void init_tables(hashmap *elements, hashmap *inv, hashmap *polls, int do_inv) {
+void init_tables(hashmap *elements, hashmap *inv, hashmap *polls,
+                 hashmap *elements_rev, int do_inv) {
   load_elements(elements, "../elem_data/" combo_file, 0);
   load_elements(elements, combo_file, 0) ||
       load_elements(elements, "bin/" combo_file, 0);
 
+  load_elements(elements_rev, "../elem_data/" combo_file, 2);
+  load_elements(elements_rev, combo_file, 2) ||
+      load_elements(elements_rev, "bin/" combo_file, 2);
+
   load_elements(polls, "../elem_data/" poll_file, 2);
 
   if (!do_inv)
@@ -36,6 +41,8 @@ int main(int argc, char *argv[]) {
   }
 
   hashmap *elements = hashmap_create();
+  hashmap *elements_rev = hashmap_create();
+  hashmap *already_done = hashmap_create();
   hashmap *inv = hashmap_create();
   hashmap *polls = hashmap_create();
 
@@ -45,9 +52,11 @@ int main(int argc, char *argv[]) {
 
   int wasCombination = 0;
 
-  init_tables(elements, inv, polls, 1);
+  init_tables(elements, inv, polls, elements_rev, 1);
 
-  printf("user:%s, welcome to Elemental on Command Line!\nType /help for commands.\n", name);
+  printf("user:%s, welcome to Elemental on Command Line!\nType /help for "
+         "commands.\n",
+         name);
   int newline = 1;
   while (1) {
     // todo: separate into functions
@@ -82,6 +91,8 @@ int main(int argc, char *argv[]) {
       continue;
     if (slash_command(command, inv))
       continue;
+    if (path_command(command, elements_rev, already_done, 1))
+      continue;
 
     int combos = get_command(command, command_re, sort_tmp);
 
@@ -106,7 +117,7 @@ int main(int argc, char *argv[]) {
     hashmap_get(elements, command_re, strlen(command_re), &result);
 
     if (result == 0) {
-      init_tables(elements, inv, polls, 0);
+      init_tables(elements, inv, polls, elements_rev, 0);
 
       hashmap_get(elements, command_re, strlen(command_re), &result);
     }

From 060963039c3844c74b8fa796b85af5fdfcb7e230 Mon Sep 17 00:00:00 2001
From: biglyderv <eggseggsarecool+git@gmail.com>
Date: Tue, 1 Apr 2025 21:14:53 -0400
Subject: [PATCH 30/50] fix weird skips

---
 src/command.c | 7 ++++++-
 1 file changed, 6 insertions(+), 1 deletion(-)

diff --git a/src/command.c b/src/command.c
index caf88ce..080b915 100644
--- a/src/command.c
+++ b/src/command.c
@@ -249,7 +249,8 @@ int path_command(char *command, hashmap *elements_rev, hashmap *already_done,
   }
 
   page[strlen(page) - 1] = '\0';
-  if (strlen(page) == 0) return 1;
+  if (strlen(page) == 0)
+    return 1;
 
   if (top) {
     printf("Path of %s:\n", page);
@@ -287,6 +288,10 @@ int path_command(char *command, hashmap *elements_rev, hashmap *already_done,
     tmp[0] = '\0';
     tmp++;
 
+    if (i == 1) {
+      path_command(tmp2, elements_rev, already_done, 0);
+    }
+
     path_command(tmp, elements_rev, already_done, 0);
   }
 

From 053b04133ae0267bcb4acc5c8cfe45368c0695b5 Mon Sep 17 00:00:00 2001
From: biglyderv <eggseggsarecool+git@gmail.com>
Date: Tue, 1 Apr 2025 22:00:06 -0400
Subject: [PATCH 31/50] fix paths

---
 src/command.c | 62 +++++++++++++++++++++++++++++++++------------------
 1 file changed, 40 insertions(+), 22 deletions(-)

diff --git a/src/command.c b/src/command.c
index 080b915..08e6278 100644
--- a/src/command.c
+++ b/src/command.c
@@ -239,18 +239,23 @@ int polls_command(char *command, hashmap *polls, hashmap *cmd) {
 
 int path_command(char *command, hashmap *elements_rev, hashmap *already_done,
                  int top) {
-  char *page;
+  char *page2;
   if (top) {
-    page = handle_pages(command, "/path ");
-    if (page == 0)
+    page2 = handle_pages(command, "/path ");
+    if (page2 == 0)
       return 0;
   } else {
-    page = command;
+    page2 = command;
   }
 
-  page[strlen(page) - 1] = '\0';
-  if (strlen(page) == 0)
+  char *page = malloc(strlen(page2) + 1);
+  strcpy(page, page2);
+  if (page[strlen(page) - 1]  == '\n') {
+    page[strlen(page) - 1] = '\0';
+  }
+  if (strlen(page) == 0) {
     return 1;
+  }
 
   if (top) {
     printf("Path of %s:\n", page);
@@ -260,41 +265,54 @@ int path_command(char *command, hashmap *elements_rev, hashmap *already_done,
 
   uintptr_t result;
   hashmap_get(already_done, page, strlen(page), &result);
-
-  if (result != 0)
+  
+  if (result != 0) {
     return 1;
+  }
   hashmap_set(already_done, page, strlen(page), (uintptr_t)1, 0);
 
   hashmap_get(elements_rev, page, strlen(page) - 1, &result);
 
-  if (result == 0 || strlen((char *)result) < 1)
+  if (result == 0 || strlen((char *)result) < 1) {
     return 1;
-
-  printf("%s: %s", command, (char *)result);
+  }
 
   // todo: refactor;
   char *tmp = (char *)result, *tmp2 = 0;
+  if (tmp[strlen(tmp)-1] == '\n') {
+    tmp[strlen(tmp) - 1] = '\0';
+  }
 
   int combos = 0;
   for (int i = 1; i < MAX_COMBO_LENGTH; i++) {
     combos = i;
     tmp2 = tmp;
-    tmp = strstr(tmp, ";");
-    if (tmp == 0 || tmp2 == tmp)
-      break;
-    if (strlen(tmp) < 2) {
-      break;
+    if (tmp2[0] == ';') {
+      tmp2++;
     }
-    tmp[0] = '\0';
-    tmp++;
-
-    if (i == 1) {
-      path_command(tmp2, elements_rev, already_done, 0);
+      tmp = strstr(tmp2, ";");
+    if (tmp == 0) {
+      tmp = &tmp2[strlen(tmp2)];
     }
 
-    path_command(tmp, elements_rev, already_done, 0);
+    char *tmp23 = malloc(strlen(tmp2) - strlen(tmp) + 2);
+    memcpy(tmp23, &tmp2[0], strlen(tmp2) - strlen(tmp) + 2);
+    tmp23[strlen(tmp2) - strlen(tmp) + 1] = '\0';
+    char *strstrd = strstr(tmp23, ";");
+    if (strstrd != 0) {
+      strstrd[0] = '\0';
+    }
+
+    path_command(tmp23, elements_rev, already_done, 0);
+
+    if (strlen(tmp23) < 1) {
+      break;
+    }
+    free(tmp23);
   }
 
+  printf("<- %s\n-> %s\n", (char*) result, (char *)page);
+  
   return 1;
 }
 

From 7a63fcb376a7711e3a5bc76755838dcd63d17d8b Mon Sep 17 00:00:00 2001
From: biglyderv <eggseggsarecool+git@gmail.com>
Date: Wed, 2 Apr 2025 01:28:18 -0400
Subject: [PATCH 32/50] don't show paths of elements you don't have

---
 src/command.c | 12 ++++++++++--
 src/command.h |  2 +-
 src/main.c    |  3 ++-
 3 files changed, 13 insertions(+), 4 deletions(-)

diff --git a/src/command.c b/src/command.c
index 08e6278..91e2290 100644
--- a/src/command.c
+++ b/src/command.c
@@ -238,7 +238,7 @@ int polls_command(char *command, hashmap *polls, hashmap *cmd) {
 }
 
 int path_command(char *command, hashmap *elements_rev, hashmap *already_done,
-                 int top) {
+                 int top, hashmap* inv) {
   char *page2;
   if (top) {
     page2 = handle_pages(command, "/path ");
@@ -263,7 +263,15 @@ int path_command(char *command, hashmap *elements_rev, hashmap *already_done,
     already_done = hashmap_create();
   }
 
+
   uintptr_t result;
+  hashmap_get(inv, page, strlen(page), &result);
+
+  if (top && result != 1) {
+    printf("You don't have %s.\n", page);
+    return 1;
+  }
+
   hashmap_get(already_done, page, strlen(page), &result);
   
   if (result != 0) {
@@ -303,7 +311,7 @@ int path_command(char *command, hashmap *elements_rev, hashmap *already_done,
       strstrd[0] = '\0';
     }
 
-    path_command(tmp23, elements_rev, already_done, 0);
+    path_command(tmp23, elements_rev, already_done, 0, inv);
 
     if (strlen(tmp23) < 1) {
       break;
diff --git a/src/command.h b/src/command.h
index 906c249..f3694b6 100644
--- a/src/command.h
+++ b/src/command.h
@@ -6,4 +6,4 @@ int suggest_command(char *command, char *command_re, hashmap *polls,
 int help_command(char *command);
 int polls_command(char *command, hashmap *polls, hashmap *cmd);
 int path_command(char *command, hashmap *elements_rev, hashmap *already_done,
-    int top);
\ No newline at end of file
+                 int top, hashmap *inv);
\ No newline at end of file
diff --git a/src/main.c b/src/main.c
index d756e2a..440670c 100644
--- a/src/main.c
+++ b/src/main.c
@@ -91,7 +91,8 @@ int main(int argc, char *argv[]) {
       continue;
     if (slash_command(command, inv))
       continue;
-    if (path_command(command, elements_rev, already_done, 1))
+
+    if (path_command(command, elements_rev, already_done, 1, inv))
       continue;
 
     int combos = get_command(command, command_re, sort_tmp);

From ed50d4daba3494b1ab31a6693f8971d75bc14915 Mon Sep 17 00:00:00 2001
From: biglyderv <eggseggsarecool+git@gmail.com>
Date: Wed, 2 Apr 2025 20:32:44 -0400
Subject: [PATCH 33/50] reverse path order

---
 src/loader.c | 12 +++++++++++-
 src/main.c   |  6 +++---
 2 files changed, 14 insertions(+), 4 deletions(-)

diff --git a/src/loader.c b/src/loader.c
index 6154167..9fddf64 100644
--- a/src/loader.c
+++ b/src/loader.c
@@ -44,7 +44,17 @@ int load_elements(hashmap *m, char *table, int use_inv) {
     char *combo = calloc(strlen(combo_o) + 1, sizeof(char));
     strcpy(combo, combo_o);
 
-    if (use_inv == 2) {
+    if (use_inv == 3) {
+      uintptr_t result;
+      hashmap_get(m, str, strlen(str) - 1, &result);
+
+      char *res = (char *)result;
+
+      if (res != 0 && strcmp(res, combo) == 0)
+        continue;
+    }
+
+    if (use_inv == 2 || use_inv == 3) {
       hashmap_set(m, str, strlen(str) - 1, (uintptr_t)combo, 1);
       continue;
     }
diff --git a/src/main.c b/src/main.c
index 440670c..584ac29 100644
--- a/src/main.c
+++ b/src/main.c
@@ -16,9 +16,9 @@ void init_tables(hashmap *elements, hashmap *inv, hashmap *polls,
   load_elements(elements, combo_file, 0) ||
       load_elements(elements, "bin/" combo_file, 0);
 
-  load_elements(elements_rev, "../elem_data/" combo_file, 2);
-  load_elements(elements_rev, combo_file, 2) ||
-      load_elements(elements_rev, "bin/" combo_file, 2);
+  load_elements(elements_rev, "../elem_data/" combo_file, 3);
+  load_elements(elements_rev, combo_file, 3) ||
+      load_elements(elements_rev, "bin/" combo_file, 3);
 
   load_elements(polls, "../elem_data/" poll_file, 2);
 

From e22c9d42dae1a0f1744d6261d9e0244ae5b01850 Mon Sep 17 00:00:00 2001
From: biglyderv <eggseggsarecool+git@gmail.com>
Date: Wed, 2 Apr 2025 20:37:18 -0400
Subject: [PATCH 34/50] fix

---
 src/loader.c | 2 +-
 1 file changed, 1 insertion(+), 1 deletion(-)

diff --git a/src/loader.c b/src/loader.c
index 9fddf64..67c3efe 100644
--- a/src/loader.c
+++ b/src/loader.c
@@ -50,7 +50,7 @@ int load_elements(hashmap *m, char *table, int use_inv) {
 
       char *res = (char *)result;
 
-      if (res != 0 && strcmp(res, combo) == 0)
+      if (res != 0)
         continue;
     }
 

From 735915db895307cf8e772d0c207ad9d285607196 Mon Sep 17 00:00:00 2001
From: biglyderv <eggseggsarecool+git@gmail.com>
Date: Thu, 3 Apr 2025 11:18:32 -0400
Subject: [PATCH 35/50] strip useless debug symbols

---
 wrap.sh | 9 +++++----
 1 file changed, 5 insertions(+), 4 deletions(-)

diff --git a/wrap.sh b/wrap.sh
index 0ef25f0..a15f60a 100755
--- a/wrap.sh
+++ b/wrap.sh
@@ -1,5 +1,6 @@
 make
-CC=x86_64-w64-mingw32-gcc BIN=./bin/elem.exe make
-CC=i686-w64-mingw32-gcc BIN=./bin/elem_32.exe make
-rm ./elem.tar.gz
-tar -cvf ./elem.tar.gz bin
\ No newline at end of file
+CC=x86_64-w64-mingw32-gcc BIN=bin/elem.exe make
+CC=i686-w64-mingw32-gcc BIN=bin/elem_32.exe make
+rm elem.tar.gz
+tar -cvf elem.tar.gz bin
+strip --strip-all bin/elem
\ No newline at end of file

From 988ac26e447c4b5b8c0181bb78f27ff873a0b795 Mon Sep 17 00:00:00 2001
From: biglyderv <eggseggsarecool+git@gmail.com>
Date: Thu, 3 Apr 2025 11:49:48 -0400
Subject: [PATCH 36/50] allow suggesting polls of elems you don't have, and
 allow suggestion correction

---
 src/command.c | 42 ++++++++++++++++++++++++------------------
 src/command.h |  2 +-
 src/main.c    | 22 ++++++++++++++--------
 3 files changed, 39 insertions(+), 27 deletions(-)

diff --git a/src/command.c b/src/command.c
index 91e2290..e03572f 100644
--- a/src/command.c
+++ b/src/command.c
@@ -117,8 +117,10 @@ int polls_handler(const void *key, size_t size, uintptr_t val, void *usr) {
 int success_handler(const void *key, size_t size, uintptr_t val, void *usr) {
   struct succ *verified = (struct succ *)usr;
 
-  if ((char *)val != verified->sugg) {
-    //((char *)val)[strlen(((char *)val)) - 1] = '\0';
+  char *val2 = (char*) val;
+
+  if ((char *)val != verified->sugg && val2[strlen(val2) - 1] == '\n') {
+    val2[strlen(val2) - 1] = '\0';
   }
 
   if (strcmp(verified->sugg, (char *)val) == 0) {
@@ -146,8 +148,8 @@ int handle_pages_int(char *command, char *invs) {
   }
 }
 
-int suggest_command(char *command, char *command_re, hashmap *polls,
-                    char *name) {
+int suggest_command(char *command, char *command_re, hashmap *polls, char *name,
+                    int was_combination) {
 
   char *page = handle_pages(command, "/suggest ");
 
@@ -167,8 +169,17 @@ int suggest_command(char *command, char *command_re, hashmap *polls,
   char *key = calloc(MAX_BUF_LENGTH, sizeof(char));
   sprintf(key, "%s_%i", name, (int)rand());
 
-  struct verifier verified = {.name = name, .sugg = val};
+  int point_thing = 0;
 
+  struct succ succer = {.sugg = val, .points = &point_thing};
+  hashmap_iterate(polls, success_handler, (void *)&succer);
+
+  if (was_combination == 2 && point_thing == 0) {
+    printf("You cannot create unique polls with elements you do not have.\n");
+    return 1;
+  }
+
+  struct verifier verified = {.name = name, .sugg = val};
   if (hashmap_iterate(polls, polls_handler, (void *)&verified) == -1) {
     printf("You already suggested this!\n");
     return 1;
@@ -176,13 +187,9 @@ int suggest_command(char *command, char *command_re, hashmap *polls,
 
   hashmap_set(polls, key, strlen(key), (uintptr_t)val, 1);
 
-  int point_thing = 0;
-
-  struct succ succer = {.sugg = val, .points = &point_thing};
-  hashmap_iterate(polls, success_handler, (void *)&succer);
+  point_thing++;
 
   if (point_thing == UPVOTE_IN) {
-
     printf("Poll was added into the game!\n");
     FILE *fptr;
 
@@ -238,7 +245,7 @@ int polls_command(char *command, hashmap *polls, hashmap *cmd) {
 }
 
 int path_command(char *command, hashmap *elements_rev, hashmap *already_done,
-                 int top, hashmap* inv) {
+                 int top, hashmap *inv) {
   char *page2;
   if (top) {
     page2 = handle_pages(command, "/path ");
@@ -250,7 +257,7 @@ int path_command(char *command, hashmap *elements_rev, hashmap *already_done,
 
   char *page = malloc(strlen(page2) + 1);
   strcpy(page, page2);
-  if (page[strlen(page) - 1]  == '\n') {
+  if (page[strlen(page) - 1] == '\n') {
     page[strlen(page) - 1] = '\0';
   }
   if (strlen(page) == 0) {
@@ -263,7 +270,6 @@ int path_command(char *command, hashmap *elements_rev, hashmap *already_done,
     already_done = hashmap_create();
   }
 
-
   uintptr_t result;
   hashmap_get(inv, page, strlen(page), &result);
 
@@ -273,7 +279,7 @@ int path_command(char *command, hashmap *elements_rev, hashmap *already_done,
   }
 
   hashmap_get(already_done, page, strlen(page), &result);
-  
+
   if (result != 0) {
     return 1;
   }
@@ -287,7 +293,7 @@ int path_command(char *command, hashmap *elements_rev, hashmap *already_done,
 
   // todo: refactor;
   char *tmp = (char *)result, *tmp2 = 0;
-  if (tmp[strlen(tmp)-1] == '\n') {
+  if (tmp[strlen(tmp) - 1] == '\n') {
     tmp[strlen(tmp) - 1] = '\0';
   }
 
@@ -298,7 +304,7 @@ int path_command(char *command, hashmap *elements_rev, hashmap *already_done,
     if (tmp2[0] == ';') {
       tmp2++;
     }
-      tmp = strstr(tmp2, ";");
+    tmp = strstr(tmp2, ";");
     if (tmp == 0) {
       tmp = &tmp2[strlen(tmp2)];
     }
@@ -319,8 +325,8 @@ int path_command(char *command, hashmap *elements_rev, hashmap *already_done,
     free(tmp23);
   }
 
-  printf("<- %s\n-> %s\n", (char*) result, (char *)page);
-  
+  printf("<- %s\n-> %s\n", (char *)result, (char *)page);
+
   return 1;
 }
 
diff --git a/src/command.h b/src/command.h
index f3694b6..bba66a4 100644
--- a/src/command.h
+++ b/src/command.h
@@ -2,7 +2,7 @@
 int get_command(char *command, char *command_re, char **sort_tmp);
 int slash_command(char *command, hashmap *inv);
 int suggest_command(char *command, char *command_re, hashmap *polls,
-                    char *name);
+                    char *name, int was_combination);
 int help_command(char *command);
 int polls_command(char *command, hashmap *polls, hashmap *cmd);
 int path_command(char *command, hashmap *elements_rev, hashmap *already_done,
diff --git a/src/main.c b/src/main.c
index 584ac29..69f9365 100644
--- a/src/main.c
+++ b/src/main.c
@@ -50,7 +50,7 @@ int main(int argc, char *argv[]) {
   char *command_re = calloc(MAX_BUF_LENGTH, sizeof(char));
   char **sort_tmp = calloc(MAX_COMBO_LENGTH, sizeof(char **));
 
-  int wasCombination = 0;
+  int was_combination = 0;
 
   init_tables(elements, inv, polls, elements_rev, 1);
 
@@ -80,11 +80,11 @@ int main(int argc, char *argv[]) {
       command[i] = tolower(command[i]);
     }
 
-    if (wasCombination && suggest_command(command, command_re, polls, name)) {
-      wasCombination = 0;
+    if (was_combination &&
+        suggest_command(command, command_re, polls, name, was_combination)) {
       continue;
     }
-    wasCombination = 0;
+    was_combination = 0;
     if (help_command(command))
       continue;
     if (polls_command(command, polls, elements))
@@ -111,9 +111,6 @@ int main(int argc, char *argv[]) {
       }
     }
 
-    if (failed)
-      continue;
-
     uintptr_t result;
     hashmap_get(elements, command_re, strlen(command_re), &result);
 
@@ -123,12 +120,21 @@ int main(int argc, char *argv[]) {
       hashmap_get(elements, command_re, strlen(command_re), &result);
     }
 
+    if (result == 0 && failed) {
+      was_combination = 2;
+      printf("Use /suggest to upvote a pre-existing combination.\n");
+      continue;
+    }
+
     if (result == 0) {
-      wasCombination = 1;
+      was_combination = 1;
       printf("You didn't make anything; use /suggest to suggest an element.\n");
       continue;
     }
 
+    if (failed)
+      continue;
+
     char *res_str = (char *)result;
 
     uintptr_t result2;

From f55db7a7fd829d3e14043ed8312442df19376776 Mon Sep 17 00:00:00 2001
From: biglyderv <eggseggsarecool+git@gmail.com>
Date: Thu, 3 Apr 2025 13:29:03 -0400
Subject: [PATCH 37/50] fix polls randomly coiming back

---
 src/main.c | 2 +-
 1 file changed, 1 insertion(+), 1 deletion(-)

diff --git a/src/main.c b/src/main.c
index 69f9365..a82e4d2 100644
--- a/src/main.c
+++ b/src/main.c
@@ -20,7 +20,7 @@ void init_tables(hashmap *elements, hashmap *inv, hashmap *polls,
   load_elements(elements_rev, combo_file, 3) ||
       load_elements(elements_rev, "bin/" combo_file, 3);
 
-  load_elements(polls, "../elem_data/" poll_file, 2);
+  load_elements(polls, "../elem_data/" poll_file, 3);
 
   if (!do_inv)
     return;

From bab758e93f70e34e0cf428b0b2041c523ee7956f Mon Sep 17 00:00:00 2001
From: biglyderv <eggseggsarecool+git@gmail.com>
Date: Thu, 3 Apr 2025 13:46:08 -0400
Subject: [PATCH 38/50] avoid  duping polls

---
 src/command.c | 17 ++++++++++++-----
 1 file changed, 12 insertions(+), 5 deletions(-)

diff --git a/src/command.c b/src/command.c
index e03572f..24a7776 100644
--- a/src/command.c
+++ b/src/command.c
@@ -80,7 +80,7 @@ int inv_handler(const void *key, size_t size, uintptr_t val, void *usr) {
     if (val2[strlen(val2) - 1] == '\n') {
       printf("- user:%s suggested %s", key3, val2);
     } else {
-      printf("-  user:%s suggested  %s\n", key3, val2);
+      printf("- user:%s suggested %s\n", key3, val2);
     }
 
     free(key3);
@@ -103,21 +103,28 @@ int inv_handler(const void *key, size_t size, uintptr_t val, void *usr) {
 int polls_handler(const void *key, size_t size, uintptr_t val, void *usr) {
   struct verifier *verified = (struct verifier *)usr;
 
-  if (((char *)val)[strlen(((char *)val)) - 1] == '\n') {
-    ((char *)val)[strlen(((char *)val)) - 1] = '\0';
+  char *val2 = (char *)val;
+  char *val3 = malloc(strlen(val2) + 1);
+  strcpy(val3, val2);
+
+  if (val3[strlen(val3) - 1] == '\n') {
+    val3[strlen(val3) - 1] = '\0';
   }
 
   if (strncmp(verified->name, key, strlen(verified->name)) == 0 &&
-      strcmp(verified->sugg, (char *)val) == 0)
+      strcmp(verified->sugg, val3) == 0) {
+    free(val3);
     return -1;
+  }
 
+  free(val3);
   return 0;
 }
 
 int success_handler(const void *key, size_t size, uintptr_t val, void *usr) {
   struct succ *verified = (struct succ *)usr;
 
-  char *val2 = (char*) val;
+  char *val2 = (char *)val;
 
   if ((char *)val != verified->sugg && val2[strlen(val2) - 1] == '\n') {
     val2[strlen(val2) - 1] = '\0';

From 1f70dd700061a609c1a1154cd6c600cd97e71a8e Mon Sep 17 00:00:00 2001
From: biglyderv <eggseggsarecool+git@gmail.com>
Date: Thu, 3 Apr 2025 13:48:03 -0400
Subject: [PATCH 39/50] ugh

---
 src/command.c | 10 +++++++---
 1 file changed, 7 insertions(+), 3 deletions(-)

diff --git a/src/command.c b/src/command.c
index 24a7776..4ac7293 100644
--- a/src/command.c
+++ b/src/command.c
@@ -125,15 +125,19 @@ int success_handler(const void *key, size_t size, uintptr_t val, void *usr) {
   struct succ *verified = (struct succ *)usr;
 
   char *val2 = (char *)val;
+  char *val3 = malloc(strlen(val2) + 1);
+  strcpy(val3, val2);
 
-  if ((char *)val != verified->sugg && val2[strlen(val2) - 1] == '\n') {
-    val2[strlen(val2) - 1] = '\0';
+  if (val3[strlen(val3) - 1] == '\n') {
+    val3[strlen(val3) - 1] = '\0';
   }
 
-  if (strcmp(verified->sugg, (char *)val) == 0) {
+  if (strcmp(verified->sugg, val3) == 0) {
     verified->points[0]++;
   }
 
+  free(val3);
+
   return 0;
 }
 

From 090d4d5d8d8d41501586e905139a14fb05bf97b6 Mon Sep 17 00:00:00 2001
From: biglyderv <eggseggsarecool+git@gmail.com>
Date: Sat, 5 Apr 2025 15:49:21 -0400
Subject: [PATCH 40/50] i put this in the wrong place so now it doesn't
 actually reduce the size

---
 wrap.sh | 4 ++--
 1 file changed, 2 insertions(+), 2 deletions(-)

diff --git a/wrap.sh b/wrap.sh
index a15f60a..dce3017 100755
--- a/wrap.sh
+++ b/wrap.sh
@@ -1,6 +1,6 @@
 make
 CC=x86_64-w64-mingw32-gcc BIN=bin/elem.exe make
 CC=i686-w64-mingw32-gcc BIN=bin/elem_32.exe make
+strip --strip-all bin/elem
 rm elem.tar.gz
-tar -cvf elem.tar.gz bin
-strip --strip-all bin/elem
\ No newline at end of file
+tar -cvf elem.tar.gz bin
\ No newline at end of file

From 5a6bb6e982afc8ec0bc65368c2550bea773b10c3 Mon Sep 17 00:00:00 2001
From: biglyderv <eggseggsarecool+git@gmail.com>
Date: Mon, 7 Apr 2025 11:04:24 -0400
Subject: [PATCH 41/50] improve the guide

---
 README.md | 8 ++++++++
 1 file changed, 8 insertions(+)

diff --git a/README.md b/README.md
index f95e7a8..773e060 100644
--- a/README.md
+++ b/README.md
@@ -1,10 +1,18 @@
 # Elemental on Command Line
 This is an elemental combination game written in C, with optional multi-player support.
 
+## Clients
+- [PenguinMod client](https://studio.penguinmod.com/?fps=200&clones=Infinity&offscreen&size=850x480#7218964246) for playing the game online with a fancy interface
+- [Discord client](https://discord.gg/DKZTWyWH3B) for playing the game publicly with other Discord members
+- [Web client](https://elem.dervland.net/) for a demo of the multiplayer version
+- [Original client](#multi-player) for developers, administrators, and command line fans
+
 ## Single-player
 A single-player example pack is provided as an example in ``bin/combos.txt``. This can be customized by the user, although internal limitations require the combination string to be in alphabetical order.
 
 ## Multi-player
+*This guide is outdated!*
+
 To set up multi-player mode, create a directory ``../elem_data``.  Also, create separate directories for each user that plays.
 
 The game can now be played with the following syntax, inside your user directory:

From 6b5452c923af2404080143a30b2ef0d234c4b6d4 Mon Sep 17 00:00:00 2001
From: biglyderv <eggseggsarecool+git@gmail.com>
Date: Wed, 9 Apr 2025 12:12:49 -0400
Subject: [PATCH 42/50] clarity; link to the releases page

---
 README.md | 2 +-
 1 file changed, 1 insertion(+), 1 deletion(-)

diff --git a/README.md b/README.md
index 773e060..7aa5d8d 100644
--- a/README.md
+++ b/README.md
@@ -5,7 +5,7 @@ This is an elemental combination game written in C, with optional multi-player s
 - [PenguinMod client](https://studio.penguinmod.com/?fps=200&clones=Infinity&offscreen&size=850x480#7218964246) for playing the game online with a fancy interface
 - [Discord client](https://discord.gg/DKZTWyWH3B) for playing the game publicly with other Discord members
 - [Web client](https://elem.dervland.net/) for a demo of the multiplayer version
-- [Original client](#multi-player) for developers, administrators, and command line fans
+- [Original client](https://git.dervland.net/elemental/elemental-on-terminal/releases) for developers, administrators, and command line fans
 
 ## Single-player
 A single-player example pack is provided as an example in ``bin/combos.txt``. This can be customized by the user, although internal limitations require the combination string to be in alphabetical order.

From d0553e657548d77d8dd94d7765b9e5da80df38f5 Mon Sep 17 00:00:00 2001
From: biglyderv <eggseggsarecool+git@gmail.com>
Date: Wed, 9 Apr 2025 12:14:48 -0400
Subject: [PATCH 43/50] redirect guide

---
 README.md | 10 +---------
 1 file changed, 1 insertion(+), 9 deletions(-)

diff --git a/README.md b/README.md
index 7aa5d8d..b2904f8 100644
--- a/README.md
+++ b/README.md
@@ -11,12 +11,4 @@ This is an elemental combination game written in C, with optional multi-player s
 A single-player example pack is provided as an example in ``bin/combos.txt``. This can be customized by the user, although internal limitations require the combination string to be in alphabetical order.
 
 ## Multi-player
-*This guide is outdated!*
-
-To set up multi-player mode, create a directory ``../elem_data``.  Also, create separate directories for each user that plays.
-
-The game can now be played with the following syntax, inside your user directory:
-```sh
-cd ../your_user_dir
-../elemental-command-line/bin/elem your_username
-```
\ No newline at end of file
+To set up multi-player mode, use the guide with the [Web proxy](https://git.dervland.net/elemental/elemental-to-web).
\ No newline at end of file

From 881d3602e7b5db3e430e065f5066a090065641c9 Mon Sep 17 00:00:00 2001
From: biglyderv <eggseggsarecool+git@gmail.com>
Date: Sat, 12 Apr 2025 09:44:14 -0400
Subject: [PATCH 44/50] clean up I/O database

---
 .gitignore    |  3 ++-
 src/command.c | 22 +++++--------------
 src/command.h |  2 +-
 src/loader.c  | 61 +++++++++++++++++++++++++++++++++++++++++++++++----
 src/loader.h  |  3 ++-
 src/main.c    | 34 +++++++++++-----------------
 src/main.h    | 12 +++++-----
 7 files changed, 87 insertions(+), 50 deletions(-)

diff --git a/.gitignore b/.gitignore
index 7ac3b40..97fedc6 100644
--- a/.gitignore
+++ b/.gitignore
@@ -4,4 +4,5 @@
 /inv.txt
 /inv_users.txt
 /polls.txt
-/elem.tar.gz
\ No newline at end of file
+/elem.tar.gz
+/combos.txt
\ No newline at end of file
diff --git a/src/command.c b/src/command.c
index 4ac7293..c89104e 100644
--- a/src/command.c
+++ b/src/command.c
@@ -4,7 +4,7 @@
 #include <stdlib.h>
 #include <string.h>
 #include <sys/types.h>
-
+#include "loader.h"
 #include "main.h"
 
 // huge cleanup operation soon
@@ -159,7 +159,7 @@ int handle_pages_int(char *command, char *invs) {
   }
 }
 
-int suggest_command(char *command, char *command_re, hashmap *polls, char *name,
+int suggest_command(char *command, char *command_re, hashmap *polls, hashmap *combos, char *name,
                     int was_combination) {
 
   char *page = handle_pages(command, "/suggest ");
@@ -204,12 +204,9 @@ int suggest_command(char *command, char *command_re, hashmap *polls, char *name,
     printf("Poll was added into the game!\n");
     FILE *fptr;
 
-    fptr = fopen("../elem_data/" combo_file, "a");
-    if (fptr == NULL)
-      return 1;
-    fwrite(val, sizeof(char), strlen(val), fptr);
-    fwrite("\n", sizeof(char), 1, fptr);
-    fclose(fptr);
+    hashmap_set(combos, command_re, strlen(command_re), (uintptr_t)page, 0);
+
+    write_elements(combos, "../elem_data/" COMBO_FILE, 0);
     return 1;
   }
 
@@ -219,14 +216,7 @@ int suggest_command(char *command, char *command_re, hashmap *polls, char *name,
 
   FILE *fptr;
 
-  fptr = fopen("../elem_data/" poll_file, "a");
-  if (fptr == NULL)
-    return 1;
-  fwrite(key, sizeof(char), strlen(key), fptr);
-  fwrite(";", sizeof(char), 1, fptr);
-  fwrite(val, sizeof(char), strlen(val), fptr);
-  fwrite("\n", sizeof(char), 1, fptr);
-  fclose(fptr);
+  write_elements(polls, "../elem_data/" POLL_FILE, 3);
 
   return 1;
 }
diff --git a/src/command.h b/src/command.h
index bba66a4..cdd78bf 100644
--- a/src/command.h
+++ b/src/command.h
@@ -2,7 +2,7 @@
 int get_command(char *command, char *command_re, char **sort_tmp);
 int slash_command(char *command, hashmap *inv);
 int suggest_command(char *command, char *command_re, hashmap *polls,
-                    char *name, int was_combination);
+                    hashmap *combos, char *name, int was_combination);
 int help_command(char *command);
 int polls_command(char *command, hashmap *polls, hashmap *cmd);
 int path_command(char *command, hashmap *elements_rev, hashmap *already_done,
diff --git a/src/loader.c b/src/loader.c
index 67c3efe..28668f5 100644
--- a/src/loader.c
+++ b/src/loader.c
@@ -6,7 +6,56 @@
 
 #include "main.h"
 
-int load_elements(hashmap *m, char *table, int use_inv) {
+struct write_struct {
+  FILE *fptr;
+  int mode;
+};
+
+int entry_handler(const void *key, size_t size, uintptr_t val, void *usr) {
+  struct write_struct *usr2 = (struct write_struct *)usr;
+
+  char *val2 = (char *)val;
+  char *key2 = (char *)key;
+
+  if (usr2->mode == 0) {
+    fwrite(val2, sizeof(char), strlen(val2), usr2->fptr);
+    fwrite(";", sizeof(char), 1, usr2->fptr);
+    fwrite(key2, sizeof(char), strlen(key2), usr2->fptr);
+    if (key2[strlen(key2) - 1] != '\n') {
+      fwrite("\n", sizeof(char), 1, usr2->fptr);
+    }
+  } else if (usr2->mode == 1) {
+    fwrite(key2, sizeof(char), strlen(key2), usr2->fptr);
+    fwrite("\n", sizeof(char), 1, usr2->fptr);
+  } else  {
+    fwrite(key2, sizeof(char), strlen(key2), usr2->fptr);
+    fwrite(";", sizeof(char), 1, usr2->fptr);
+    fwrite(val2, sizeof(char), strlen(val2), usr2->fptr);
+    if (val2[strlen(val2) - 1] != '\n') {
+      fwrite("\n", sizeof(char), 1, usr2->fptr);
+    }
+  }
+
+  return 1;
+}
+
+void write_elements(hashmap *m, char *table, int mode) {
+  FILE *fptr;
+
+  fptr = fopen(table, "w");
+
+  if (fptr == NULL)
+    return;
+
+  struct write_struct writer = {.fptr = fptr, .mode = mode};
+
+  hashmap_iterate(m, entry_handler, (void *)&writer);
+  //fwrite("\n", sizeof(char), 1, fptr);
+
+  fclose(fptr);
+}
+
+int load_elements(hashmap *m, char *table, int mode) {
   FILE *fptr;
 
   fptr = fopen(table, "r");
@@ -19,6 +68,8 @@ int load_elements(hashmap *m, char *table, int use_inv) {
 
   int did_something = 0;
 
+  int lines_get = 0;
+
   while (1) {
     str2 = calloc(MAX_FILE_SIZE, sizeof(char));
     if (!fgets(str2, MAX_FILE_SIZE, fptr)) {
@@ -26,13 +77,15 @@ int load_elements(hashmap *m, char *table, int use_inv) {
       break;
     }
 
+    lines_get++;
+
     str = calloc(strlen(str2) + 1, sizeof(char));
     strcpy(str, str2);
     free(str2);
 
     did_something = 1;
 
-    if (use_inv == 1) {
+    if (mode == 1) {
       hashmap_set(m, str, strlen(str) - 1, (uintptr_t)1, 0);
       continue;
     }
@@ -44,7 +97,7 @@ int load_elements(hashmap *m, char *table, int use_inv) {
     char *combo = calloc(strlen(combo_o) + 1, sizeof(char));
     strcpy(combo, combo_o);
 
-    if (use_inv == 3) {
+    if (mode == 3) {
       uintptr_t result;
       hashmap_get(m, str, strlen(str) - 1, &result);
 
@@ -54,7 +107,7 @@ int load_elements(hashmap *m, char *table, int use_inv) {
         continue;
     }
 
-    if (use_inv == 2 || use_inv == 3) {
+    if (mode == 2 || mode == 3) {
       hashmap_set(m, str, strlen(str) - 1, (uintptr_t)combo, 1);
       continue;
     }
diff --git a/src/loader.h b/src/loader.h
index 116d3ad..ad57b8d 100644
--- a/src/loader.h
+++ b/src/loader.h
@@ -1,2 +1,3 @@
 #include "map.h"
-int load_elements(hashmap *m, char *table, int use_inv);
\ No newline at end of file
+int load_elements(hashmap *m, char *table, int mode);
+void write_elements(hashmap *m, char *table, int mode);
\ No newline at end of file
diff --git a/src/main.c b/src/main.c
index a82e4d2..67e3c96 100644
--- a/src/main.c
+++ b/src/main.c
@@ -12,24 +12,24 @@
 
 void init_tables(hashmap *elements, hashmap *inv, hashmap *polls,
                  hashmap *elements_rev, int do_inv) {
-  load_elements(elements, "../elem_data/" combo_file, 0);
-  load_elements(elements, combo_file, 0) ||
-      load_elements(elements, "bin/" combo_file, 0);
+  load_elements(elements, "../elem_data/" COMBO_FILE, 0);
+  load_elements(elements, COMBO_FILE, 0) ||
+      load_elements(elements, "bin/" COMBO_FILE, 0);
 
-  load_elements(elements_rev, "../elem_data/" combo_file, 3);
-  load_elements(elements_rev, combo_file, 3) ||
-      load_elements(elements_rev, "bin/" combo_file, 3);
+  load_elements(elements_rev, "../elem_data/" COMBO_FILE, 3);
+  load_elements(elements_rev, COMBO_FILE, 3) ||
+      load_elements(elements_rev, "bin/" COMBO_FILE, 3);
 
-  load_elements(polls, "../elem_data/" poll_file, 3);
+  load_elements(polls, "../elem_data/" POLL_FILE, 3);
 
   if (!do_inv)
     return;
 
-  load_elements(inv, "../elem_data/" inv_base_file, 1) ||
-      load_elements(inv, inv_base_file, 1) ||
-      load_elements(inv, "bin/" inv_base_file, 1);
+  load_elements(inv, "../elem_data/" INV_BASE_FILE, 1) ||
+      load_elements(inv, INV_BASE_FILE, 1) ||
+      load_elements(inv, "bin/" INV_BASE_FILE, 1);
 
-  load_elements(inv, inv_file, 1);
+  load_elements(inv, INV_FILE, 1);
 }
 
 int main(int argc, char *argv[]) {
@@ -81,7 +81,7 @@ int main(int argc, char *argv[]) {
     }
 
     if (was_combination &&
-        suggest_command(command, command_re, polls, name, was_combination)) {
+        suggest_command(command, command_re, polls, elements, name, was_combination)) {
       continue;
     }
     was_combination = 0;
@@ -148,15 +148,7 @@ int main(int argc, char *argv[]) {
 
     hashmap_set(inv, res_str, strlen(res_str), (uintptr_t)1, 0);
     printf("You made %s!\n", res_str);
-
-    FILE *fptr;
-
-    fptr = fopen(inv_file, "a");
-    if (fptr == NULL)
-      continue;
-    fwrite(res_str, sizeof(char), strlen(res_str), fptr);
-    fwrite("\n", sizeof(char), 1, fptr);
-    fclose(fptr);
+    write_elements(inv, INV_FILE, 1);
   }
 
   // free(command);
diff --git a/src/main.h b/src/main.h
index 7761ac3..9e1ac77 100644
--- a/src/main.h
+++ b/src/main.h
@@ -1,9 +1,9 @@
-#define inv_file "inv.txt"
-#define inv_base_file "inv_base.txt"
-#define combo_file "combos.txt"
-#define poll_file "polls.txt"
-#define polls_lock_file "polls_lock.txt"
-#define lb_file "lb.txt"
+#define INV_FILE "inv.txt"
+#define INV_BASE_FILE "inv_base.txt"
+#define COMBO_FILE "combos.txt"
+#define POLL_FILE "polls.txt"
+#define POLLS_LOCK_FILE "polls_lock.txt"
+#define LB_FILE "lb.txt"
 
 #define MAX_BUF_LENGTH 1024
 #define MAX_COMBO_LENGTH 1024

From be291628b81efe26989c2a25f59d9f169a0d4f39 Mon Sep 17 00:00:00 2001
From: biglyderv <eggseggsarecool+git@gmail.com>
Date: Mon, 14 Apr 2025 20:36:53 -0400
Subject: [PATCH 45/50] fix weird interference with polls

---
 src/command.c | 3 +++
 src/main.c    | 8 ++++++--
 2 files changed, 9 insertions(+), 2 deletions(-)

diff --git a/src/command.c b/src/command.c
index c89104e..aab75ef 100644
--- a/src/command.c
+++ b/src/command.c
@@ -1,4 +1,5 @@
 #include "map.h"
+#include <time.h>
 #include <stdint.h>
 #include <stdio.h>
 #include <stdlib.h>
@@ -177,6 +178,8 @@ int suggest_command(char *command, char *command_re, hashmap *polls, hashmap *co
   char *val = calloc(MAX_BUF_LENGTH, sizeof(char));
   sprintf(val, "%s;%s", page, command_re);
 
+  srand(time(NULL));
+
   char *key = calloc(MAX_BUF_LENGTH, sizeof(char));
   sprintf(key, "%s_%i", name, (int)rand());
 
diff --git a/src/main.c b/src/main.c
index 67e3c96..0028bb7 100644
--- a/src/main.c
+++ b/src/main.c
@@ -1,5 +1,6 @@
 #include "command.h"
 #include "loader.h"
+#include "map.h"
 #include <ctype.h>
 #include <stdint.h>
 #include <stdio.h>
@@ -87,8 +88,11 @@ int main(int argc, char *argv[]) {
     was_combination = 0;
     if (help_command(command))
       continue;
-    if (polls_command(command, polls, elements))
-      continue;
+    if (polls_command(command, polls, elements)) {
+      hashmap_free(polls);
+      polls = hashmap_create();
+      init_tables(elements, inv, polls, elements_rev, 0);
+    }
     if (slash_command(command, inv))
       continue;
 

From 9b196f0b1328589fdb148df9640551f7c16c5c34 Mon Sep 17 00:00:00 2001
From: biglyderv <eggseggsarecool+git@gmail.com>
Date: Thu, 17 Apr 2025 09:27:13 -0400
Subject: [PATCH 46/50] fix weird newline issue

---
 src/loader.c | 4 +++-
 1 file changed, 3 insertions(+), 1 deletion(-)

diff --git a/src/loader.c b/src/loader.c
index 28668f5..a41a19d 100644
--- a/src/loader.c
+++ b/src/loader.c
@@ -26,7 +26,9 @@ int entry_handler(const void *key, size_t size, uintptr_t val, void *usr) {
     }
   } else if (usr2->mode == 1) {
     fwrite(key2, sizeof(char), strlen(key2), usr2->fptr);
-    fwrite("\n", sizeof(char), 1, usr2->fptr);
+    if (key2[strlen(key2) - 1] != '\n') {
+      fwrite("\n", sizeof(char), 1, usr2->fptr);
+    }
   } else  {
     fwrite(key2, sizeof(char), strlen(key2), usr2->fptr);
     fwrite(";", sizeof(char), 1, usr2->fptr);

From fac2179c233ba65bda87447154bdeb6ab4376128 Mon Sep 17 00:00:00 2001
From: biglyderv <eggseggsarecool+git@gmail.com>
Date: Thu, 17 Apr 2025 09:43:20 -0400
Subject: [PATCH 47/50] hopefully fix the paging issue

---
 src/command.c | 7 ++++++-
 1 file changed, 6 insertions(+), 1 deletion(-)

diff --git a/src/command.c b/src/command.c
index aab75ef..749cbdc 100644
--- a/src/command.c
+++ b/src/command.c
@@ -143,8 +143,13 @@ int success_handler(const void *key, size_t size, uintptr_t val, void *usr) {
 }
 
 char *handle_pages(char *command, char *invs) {
+  char *data;
+  char *data2;
   if (strncmp(command, invs, strlen(invs)) == 0) {
-    return &command[strlen(invs)];
+    data = &command[strlen(invs)];
+    data2 = malloc(strlen(data) + 1);
+    memcpy(data2,data,strlen(data) + 1);
+    return data2;
   } else {
     return 0;
   }

From 692688dbbdcc635ba075d9c9db73c30bd8d54127 Mon Sep 17 00:00:00 2001
From: biglyderv <eggseggsarecool+git@gmail.com>
Date: Sun, 20 Apr 2025 20:10:50 -0400
Subject: [PATCH 48/50] fix url

---
 README.md | 2 +-
 1 file changed, 1 insertion(+), 1 deletion(-)

diff --git a/README.md b/README.md
index b2904f8..c7ad847 100644
--- a/README.md
+++ b/README.md
@@ -4,7 +4,7 @@ This is an elemental combination game written in C, with optional multi-player s
 ## Clients
 - [PenguinMod client](https://studio.penguinmod.com/?fps=200&clones=Infinity&offscreen&size=850x480#7218964246) for playing the game online with a fancy interface
 - [Discord client](https://discord.gg/DKZTWyWH3B) for playing the game publicly with other Discord members
-- [Web client](https://elem.dervland.net/) for a demo of the multiplayer version
+- [Web client](https://elem.dervland.net/game/) for a demo of the multiplayer version
 - [Original client](https://git.dervland.net/elemental/elemental-on-terminal/releases) for developers, administrators, and command line fans
 
 ## Single-player

From c7cbcd39ad805c66f20f21753fffb54c14ce7ebb Mon Sep 17 00:00:00 2001
From: biglyderv <eggseggsarecool+git@gmail.com>
Date: Sun, 20 Apr 2025 20:11:10 -0400
Subject: [PATCH 49/50] nvm

---
 README.md | 2 +-
 1 file changed, 1 insertion(+), 1 deletion(-)

diff --git a/README.md b/README.md
index c7ad847..b2904f8 100644
--- a/README.md
+++ b/README.md
@@ -4,7 +4,7 @@ This is an elemental combination game written in C, with optional multi-player s
 ## Clients
 - [PenguinMod client](https://studio.penguinmod.com/?fps=200&clones=Infinity&offscreen&size=850x480#7218964246) for playing the game online with a fancy interface
 - [Discord client](https://discord.gg/DKZTWyWH3B) for playing the game publicly with other Discord members
-- [Web client](https://elem.dervland.net/game/) for a demo of the multiplayer version
+- [Web client](https://elem.dervland.net/) for a demo of the multiplayer version
 - [Original client](https://git.dervland.net/elemental/elemental-on-terminal/releases) for developers, administrators, and command line fans
 
 ## Single-player

From 40e38578bb60457997ef6d3f6c69e611bb7ebd1c Mon Sep 17 00:00:00 2001
From: biglyderv <eggseggsarecool+git@gmail.com>
Date: Sun, 20 Apr 2025 20:16:30 -0400
Subject: [PATCH 50/50] c

---
 README.md | 2 +-
 1 file changed, 1 insertion(+), 1 deletion(-)

diff --git a/README.md b/README.md
index b2904f8..d5d6b6f 100644
--- a/README.md
+++ b/README.md
@@ -4,7 +4,7 @@ This is an elemental combination game written in C, with optional multi-player s
 ## Clients
 - [PenguinMod client](https://studio.penguinmod.com/?fps=200&clones=Infinity&offscreen&size=850x480#7218964246) for playing the game online with a fancy interface
 - [Discord client](https://discord.gg/DKZTWyWH3B) for playing the game publicly with other Discord members
-- [Web client](https://elem.dervland.net/) for a demo of the multiplayer version
+- [Web client](https://elem.dervland.net/index.html) for a demo of the multiplayer version
 - [Original client](https://git.dervland.net/elemental/elemental-on-terminal/releases) for developers, administrators, and command line fans
 
 ## Single-player