diff --git a/.gitignore b/.gitignore
index 97fedc6..d23d186 100644
--- a/.gitignore
+++ b/.gitignore
@@ -1,8 +1,3 @@
 /bin/elem
 /bin/elem.exe
-/bin/elem_32.exe
-/inv.txt
-/inv_users.txt
-/polls.txt
-/elem.tar.gz
-/combos.txt
\ No newline at end of file
+/inv.txt
\ No newline at end of file
diff --git a/Makefile b/Makefile
index 5baff72..29d7bb4 100644
--- a/Makefile
+++ b/Makefile
@@ -2,4 +2,4 @@ CC?=gcc
 BIN?=bin/elem
 
 make: src/main.c
-	$(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
+	$(CC) -o $(BIN) src/map.c src/loader.c src/command.c src/main.c
\ No newline at end of file
diff --git a/README.md b/README.md
index d5d6b6f..d331afb 100644
--- a/README.md
+++ b/README.md
@@ -1,14 +1,2 @@
-# 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/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
-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, use the guide with the [Web proxy](https://git.dervland.net/elemental/elemental-to-web).
\ No newline at end of file
+# Elemental on CLI 
+Elemental combination game written in C.
\ No newline at end of file
diff --git a/src/command.c b/src/command.c
index 749cbdc..2a8b217 100644
--- a/src/command.c
+++ b/src/command.c
@@ -1,30 +1,15 @@
 #include "map.h"
-#include <time.h>
+#include <ctype.h>
 #include <stdint.h>
 #include <stdio.h>
 #include <stdlib.h>
 #include <string.h>
-#include <sys/types.h>
-#include "loader.h"
-#include "main.h"
-
-// huge cleanup operation soon
 
+#define MAX_BUF_LENGTH 1024
+#define MAX_COMBO_LENGTH 1024
 struct pager {
   int page;
   int i;
-  int is_poll;
-  hashmap *cmd;
-};
-
-struct verifier {
-  char *name;
-  char *sugg;
-};
-
-struct succ {
-  char *sugg;
-  int *points;
 };
 
 long stoi(const char *s) {
@@ -52,303 +37,56 @@ int sort_comp(const void *a, const void *b) {
   return strcmp(*(char **)a, *(char **)b);
 }
 
-int inv_handler(const void *key, size_t size, uintptr_t val, void *usr) {
+#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
+{
   struct pager *i = usr;
-  if (val == 0)
-    return 0;
-  char *key2 = (char *)key;
-  char *val2 = (char *)val;
-
-  if (i->is_poll) {
-    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;
-    }
-
-    i->i++;
-    if (i->i < i->page * 10 || i->i >= (i->page + 1) * 10) {
-      return 0;
-    }
-
-    if (val2[strlen(val2) - 1] == '\n') {
-      printf("- user:%s suggested %s", key3, val2);
-    } else {
-      printf("- user:%s suggested %s\n", key3, val2);
-    }
-
-    free(key3);
-    return 1;
-  }
-
   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;
 
-  if (strlen(key2) > 0 && key2[strlen(key2) - 1] == '\n') {
-    printf("- %s", key2);
+  if (key2[strlen(key2) - 1] == '\n') {
+    printf("- %s", (char *)key);
   } else {
-    printf("- %s\n", key2);
+    printf("- %s\n", (char *)key);
   }
   return 1;
 }
 
-int polls_handler(const void *key, size_t size, uintptr_t val, void *usr) {
-  struct verifier *verified = (struct verifier *)usr;
-
-  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, 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 *val3 = malloc(strlen(val2) + 1);
-  strcpy(val3, val2);
-
-  if (val3[strlen(val3) - 1] == '\n') {
-    val3[strlen(val3) - 1] = '\0';
-  }
-
-  if (strcmp(verified->sugg, val3) == 0) {
-    verified->points[0]++;
-  }
-
-  free(val3);
-
-  return 0;
-}
-
-char *handle_pages(char *command, char *invs) {
-  char *data;
-  char *data2;
-  if (strncmp(command, invs, strlen(invs)) == 0) {
-    data = &command[strlen(invs)];
-    data2 = malloc(strlen(data) + 1);
-    memcpy(data2,data,strlen(data) + 1);
-    return data2;
-  } 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, hashmap *combos, char *name,
-                    int was_combination) {
-
-  char *page = handle_pages(command, "/suggest ");
-
-  if (!page)
-    return 0;
-  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);
-
-  srand(time(NULL));
-
-  char *key = calloc(MAX_BUF_LENGTH, sizeof(char));
-  sprintf(key, "%s_%i", name, (int)rand());
-
-  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;
-  }
-
-  hashmap_set(polls, key, strlen(key), (uintptr_t)val, 1);
-
-  point_thing++;
-
-  if (point_thing == UPVOTE_IN) {
-    printf("Poll was added into the game!\n");
-    FILE *fptr;
-
-    hashmap_set(combos, command_re, strlen(command_re), (uintptr_t)page, 0);
-
-    write_elements(combos, "../elem_data/" COMBO_FILE, 0);
-    return 1;
-  }
-
-  printf("Suggested %s = %s.\n", command_re, page);
-
-  // todo: clean old polls
-
-  FILE *fptr;
-
-  write_elements(polls, "../elem_data/" POLL_FILE, 3);
-
-  return 1;
-}
-
-int help_command(char *command) {
-  char *page = handle_pages(command, "/help");
-
-  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) {
-
-  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};
-  hashmap_iterate(polls, inv_handler, &i);
-  printf("Total: %i\n", i.i + 1);
-  return 1;
-}
-
-int path_command(char *command, hashmap *elements_rev, hashmap *already_done,
-                 int top, hashmap *inv) {
-  char *page2;
-  if (top) {
-    page2 = handle_pages(command, "/path ");
-    if (page2 == 0)
-      return 0;
-  } else {
-    page2 = command;
-  }
-
-  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);
-    hashmap_free(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) {
-    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;
-  }
-
-  // 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;
-    if (tmp2[0] == ';') {
-      tmp2++;
-    }
-    tmp = strstr(tmp2, ";");
-    if (tmp == 0) {
-      tmp = &tmp2[strlen(tmp2)];
-    }
-
-    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, inv);
-
-    if (strlen(tmp23) < 1) {
-      break;
-    }
-    free(tmp23);
-  }
-
-  printf("<- %s\n-> %s\n", (char *)result, (char *)page);
-
-  return 1;
-}
-
 int slash_command(char *command, hashmap *inv) {
 
-  int page = handle_pages_int(command, "/inv ");
-  if (page == 0)
+  if (command[0] == '/') {
+    command++;
+  } else {
     return 0;
+  }
+
+  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 {
+    return 0;
+  }
 
   printf("Your inventory (page %i):\n", page);
-  struct pager i = {.page = page - 1, .i = -1, .is_poll = 0};
+  struct pager i = {.page = page - 1, .i = -1};
   hashmap_iterate(inv, inv_handler, &i);
-  printf("Total: %i\n", i.i + 1);
   return 1;
 }
 
@@ -373,6 +111,10 @@ 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/command.h b/src/command.h
index cdd78bf..d5c61f4 100644
--- a/src/command.h
+++ b/src/command.h
@@ -1,9 +1,3 @@
 #include "map.h"
 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,
-                    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,
-                 int top, hashmap *inv);
\ No newline at end of file
+int slash_command(char *command, hashmap *inv);
\ No newline at end of file
diff --git a/src/loader.c b/src/loader.c
index a41a19d..77e4ea7 100644
--- a/src/loader.c
+++ b/src/loader.c
@@ -4,60 +4,9 @@
 #include <stdlib.h>
 #include <string.h>
 
-#include "main.h"
+#define MAX_FILE_SIZE 1024 * 16
 
-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);
-    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);
-    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) {
+int load_elements(hashmap *m, char *table, int use_inv) {
   FILE *fptr;
 
   fptr = fopen(table, "r");
@@ -66,53 +15,26 @@ int load_elements(hashmap *m, char *table, int mode) {
     return 0;
 
   char *str;
-  char *str2;
 
   int did_something = 0;
 
-  int lines_get = 0;
-
   while (1) {
-    str2 = calloc(MAX_FILE_SIZE, sizeof(char));
-    if (!fgets(str2, MAX_FILE_SIZE, fptr)) {
-      free(str2);
+    str = calloc(MAX_FILE_SIZE, sizeof(char));
+    if (!fgets(str, MAX_FILE_SIZE, fptr)) {
+      free(str);
       break;
     }
 
-    lines_get++;
-
-    str = calloc(strlen(str2) + 1, sizeof(char));
-    strcpy(str, str2);
-    free(str2);
-
     did_something = 1;
 
-    if (mode == 1) {
+    if (use_inv) {
       hashmap_set(m, str, strlen(str) - 1, (uintptr_t)1, 0);
       continue;
     }
 
-    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 (mode == 3) {
-      uintptr_t result;
-      hashmap_get(m, str, strlen(str) - 1, &result);
-
-      char *res = (char *)result;
-
-      if (res != 0)
-        continue;
-    }
-
-    if (mode == 2 || mode == 3) {
-      hashmap_set(m, str, strlen(str) - 1, (uintptr_t)combo, 1);
-      continue;
-    }
+    char *combo = strstr(str, ";");
+    combo[0] = '\0';
+    combo++;
 
     hashmap_set(m, combo, strlen(combo) - 1, (uintptr_t)str, 1);
   }
diff --git a/src/loader.h b/src/loader.h
index ad57b8d..116d3ad 100644
--- a/src/loader.h
+++ b/src/loader.h
@@ -1,3 +1,2 @@
 #include "map.h"
-int load_elements(hashmap *m, char *table, int mode);
-void write_elements(hashmap *m, char *table, int mode);
\ No newline at end of file
+int load_elements(hashmap *m, char *table, int use_inv);
\ No newline at end of file
diff --git a/src/main.c b/src/main.c
index 0028bb7..7ebb4d1 100644
--- a/src/main.c
+++ b/src/main.c
@@ -1,109 +1,55 @@
 #include "command.h"
 #include "loader.h"
-#include "map.h"
-#include <ctype.h>
 #include <stdint.h>
 #include <stdio.h>
 #include <stdlib.h>
 #include <string.h>
 
-#include "main.h"
+#define inv_file "inv.txt"
+#define inv_base_file "inv_base.txt"
+#define combo_file "combos.txt"
 
-// todo: spacing in combos, clean init_tables
+#define MAX_BUF_LENGTH 1024
+#define MAX_COMBO_LENGTH 1024
 
-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);
+void init_tables(hashmap *elements, hashmap *inv, int do_inv) {
 
-  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(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(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(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[]) {
-  char *name;
-  if (argc < 2) {
-    name = "guest";
-  } else {
-    name = argv[1];
-  }
-
   hashmap *elements = hashmap_create();
-  hashmap *elements_rev = hashmap_create();
-  hashmap *already_done = 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 **));
 
-  int was_combination = 0;
+  init_tables(elements, inv, 1);
 
-  init_tables(elements, inv, polls, elements_rev, 1);
+  load_elements(inv, inv_file, 1);
 
-  printf("user:%s, welcome to Elemental on Command Line!\nType /help for "
-         "commands.\n",
-         name);
-  int newline = 1;
+  printf("Welcome to Elemental on Command Line!\n");
   while (1) {
     // todo: separate into functions
-    fflush(stdout);
 
-    if (newline) {
-      printf("\n");
-    }
+    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]);
-    }
-
-    if (was_combination &&
-        suggest_command(command, command_re, polls, elements, name, was_combination)) {
-      continue;
-    }
-    was_combination = 0;
-    if (help_command(command))
-      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;
-
-    if (path_command(command, elements_rev, already_done, 1, inv))
+    int slashRan = slash_command(command, inv);
+    if (slashRan)
       continue;
 
     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;
@@ -115,44 +61,36 @@ int main(int argc, char *argv[]) {
       }
     }
 
+    if (failed)
+      continue;
+
     uintptr_t result;
     hashmap_get(elements, command_re, strlen(command_re), &result);
 
     if (result == 0) {
-      init_tables(elements, inv, polls, elements_rev, 0);
+      init_tables(elements, inv, 0);
 
       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) {
-      was_combination = 1;
-      printf("You didn't make anything; use /suggest to suggest an element.\n");
+      printf("You didn't make anything.\n");
       continue;
     }
 
-    if (failed)
-      continue;
-
     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);
-    write_elements(inv, INV_FILE, 1);
+
+    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);
   }
 
   // free(command);
diff --git a/src/main.h b/src/main.h
deleted file mode 100644
index 9e1ac77..0000000
--- a/src/main.h
+++ /dev/null
@@ -1,12 +0,0 @@
-#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
-#define UPVOTE_IN 2
-#define MAX_FILE_SIZE 1024
-long stoi(const char *s);
\ No newline at end of file
diff --git a/src/map.c b/src/map.c
index 6f0aad3..59deeb2 100644
--- a/src/map.c
+++ b/src/map.c
@@ -2,7 +2,6 @@
 //  map.h
 //
 //  Created by Mashpoe on 1/15/21.
-//  Modifications by BiglyDerv
 //
 
 #include "map.h"
@@ -199,6 +198,67 @@ 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);
@@ -209,6 +269,40 @@ 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 ca305c8..775b62d 100644
--- a/src/map.h
+++ b/src/map.h
@@ -11,6 +11,10 @@
 #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>
 
@@ -40,17 +44,69 @@ 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
diff --git a/wrap.sh b/wrap.sh
deleted file mode 100755
index dce3017..0000000
--- a/wrap.sh
+++ /dev/null
@@ -1,6 +0,0 @@
-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
\ No newline at end of file