From 7279afeb4c324ac89b1b2c4349f25d9ad508bc42 Mon Sep 17 00:00:00 2001 From: biglyderv Date: Mon, 24 Mar 2025 21:53:39 -0400 Subject: [PATCH 01/57] fix sorting bug --- src/command.c | 2 +- src/main.c | 2 ++ 2 files changed, 3 insertions(+), 1 deletion(-) diff --git a/src/command.c b/src/command.c index 0b1b5a6..f4e0db4 100644 --- a/src/command.c +++ b/src/command.c @@ -44,7 +44,7 @@ char *get_command(char *command, char *command_re, char **sort_tmp) { int combos = 0; for (int i = 1; i < MAX_COMBO_LENGTH; i++) { combos = i; - sort_tmp[i] = strstr(command, ";"); + sort_tmp[i] = strstr(sort_tmp[i-1], ";"); if (sort_tmp[i] == 0) break; sort_tmp[i][0] = '\0'; diff --git a/src/main.c b/src/main.c index 463c8b7..2e5ed4d 100644 --- a/src/main.c +++ b/src/main.c @@ -26,6 +26,8 @@ int main(int argc, char *argv[]) { uintptr_t result; hashmap_get(elements, command_re, strlen(command_re), &result); + printf("%s\n",command_re); + if (result == 0) { printf("You didn't make anything.\n"); continue; From 88e49d7ec80bbafc3a26fe59f5535d29d90d7bc4 Mon Sep 17 00:00:00 2001 From: biglyderv Date: Mon, 24 Mar 2025 22:27:02 -0400 Subject: [PATCH 02/57] add inventory --- .gitignore | 4 ++-- Makefile | 2 +- combos.txt => bin/combos.txt | 0 bin/inv.txt | 4 ++++ src/command.c | 37 ++++++++++++++++++++++++++++++++---- src/command.h | 4 +++- src/loader.c | 7 ++++++- src/loader.h | 2 +- src/main.c | 36 ++++++++++++++++++++++++++++------- 9 files changed, 79 insertions(+), 17 deletions(-) rename combos.txt => bin/combos.txt (100%) create mode 100644 bin/inv.txt diff --git a/.gitignore b/.gitignore index ecf54ad..7024c52 100644 --- a/.gitignore +++ b/.gitignore @@ -1,2 +1,2 @@ -/elem -/elem.exe \ No newline at end of file +/bin/elem +/bin/elem.exe \ No newline at end of file diff --git a/Makefile b/Makefile index 75f31d0..29d7bb4 100644 --- a/Makefile +++ b/Makefile @@ -1,5 +1,5 @@ CC?=gcc -BIN?=elem +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 diff --git a/combos.txt b/bin/combos.txt similarity index 100% rename from combos.txt rename to bin/combos.txt diff --git a/bin/inv.txt b/bin/inv.txt new file mode 100644 index 0000000..07496fd --- /dev/null +++ b/bin/inv.txt @@ -0,0 +1,4 @@ +air +earth +fire +water diff --git a/src/command.c b/src/command.c index f4e0db4..4f2999a 100644 --- a/src/command.c +++ b/src/command.c @@ -1,3 +1,4 @@ +#include "map.h" #include #include #include @@ -22,8 +23,36 @@ int sort_comp(const void *a, const void *b) { return strcmp(*(char **)a, *(char **)b); } -char *get_command(char *command, char *command_re, char **sort_tmp) { - fgets(command, MAX_BUF_LENGTH - 1, stdin); +int inv_handler(const void *key, unsigned long size, unsigned long val, + void *usr) { + if (val == 0) + return 0; + char *key2 = (char *)key; + + if (key2[strlen(key2) - 1] == '\n') { + printf("- %s", (char *)key); + } else { + printf("- %s\n", (char *)key); + } + return 1; +} + +int slash_command(char *command, hashmap *inv) { + + if (command[0] == '/') { + command++; + } else { + return 0; + } + + if (strcmp(command, "inv\n") == 0) { + printf("Your inventory:\n"); + hashmap_iterate(inv, inv_handler, "inv"); + } + return 1; +} + +int get_command(char *command, char *command_re, char **sort_tmp) { while (1) { int get_out = 0; @@ -44,7 +73,7 @@ char *get_command(char *command, char *command_re, char **sort_tmp) { int combos = 0; for (int i = 1; i < MAX_COMBO_LENGTH; i++) { combos = i; - sort_tmp[i] = strstr(sort_tmp[i-1], ";"); + sort_tmp[i] = strstr(sort_tmp[i - 1], ";"); if (sort_tmp[i] == 0) break; sort_tmp[i][0] = '\0'; @@ -64,5 +93,5 @@ char *get_command(char *command, char *command_re, char **sort_tmp) { command_re_tmp += strlen(last); } - return command_re; + return combos; } \ No newline at end of file diff --git a/src/command.h b/src/command.h index aead233..d5c61f4 100644 --- a/src/command.h +++ b/src/command.h @@ -1 +1,3 @@ -char *get_command(char *command, char *command_re, char **sort_tmp); \ No newline at end of file +#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 diff --git a/src/loader.c b/src/loader.c index e712c63..1385fb5 100644 --- a/src/loader.c +++ b/src/loader.c @@ -6,7 +6,7 @@ #define MAX_FILE_SIZE 1024 * 16 -void load_elements(hashmap *m, char *table) { +void load_elements(hashmap *m, char *table, int use_inv) { FILE *fptr; fptr = fopen(table, "r"); @@ -18,6 +18,11 @@ void load_elements(hashmap *m, char *table) { if (!fgets(str, MAX_FILE_SIZE, fptr)) break; + if (use_inv) { + hashmap_set(m, str, strlen(str) - 2, (uintptr_t)1); + continue; + } + char *combo = strstr(str, ";"); combo[0] = '\0'; combo++; diff --git a/src/loader.h b/src/loader.h index 2f1bdde..40ac584 100644 --- a/src/loader.h +++ b/src/loader.h @@ -1,2 +1,2 @@ #include "map.h" -void load_elements(hashmap *m, char *table); \ No newline at end of file +void 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 2e5ed4d..6eb9252 100644 --- a/src/main.c +++ b/src/main.c @@ -1,9 +1,9 @@ +#include "command.h" +#include "loader.h" #include #include #include #include -#include "command.h" -#include "loader.h" #define MAX_BUF_LENGTH 1024 #define MAX_COMBO_LENGTH 1024 @@ -16,23 +16,45 @@ 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, "combos.txt"); + load_elements(elements, "bin/combos.txt", 0); + load_elements(inv, "bin/inv.txt", 1); + printf("Welcome to Elemental on Command Line!\n"); while (1) { // todo: separate into functions - command_re = get_command(command, command_re, sort_tmp); + printf("\n"); + fgets(command, MAX_BUF_LENGTH - 1, stdin); + int slashRan = slash_command(command,inv); + if (slashRan) continue; + + int combos = get_command(command, command_re, sort_tmp); + + int failed = 0; + for (int i = 0; i < combos; i++) { + uintptr_t result; + hashmap_get(inv, sort_tmp[i], strlen(sort_tmp[i]) - 1, &result); + if (result != 1) { + printf("You don't have %s.\n", sort_tmp[i]); + failed = 1; + continue; + } + } + + if (failed) continue; uintptr_t result; hashmap_get(elements, command_re, strlen(command_re), &result); - printf("%s\n",command_re); - if (result == 0) { printf("You didn't make anything.\n"); continue; } - printf("You made %s!\n", (char *)result); + + char *res_str = (char *)result; + + hashmap_set(inv, res_str, strlen(res_str) - 1, (uintptr_t)1); + printf("You made %s!\n", res_str); } // free(command); From 79fee676a499ccd7f55986a3e92bd4608d237aed Mon Sep 17 00:00:00 2001 From: biglyderv Date: Mon, 24 Mar 2025 23:55:55 -0400 Subject: [PATCH 03/57] fix segfault --- src/command.c | 9 +++++++++ 1 file changed, 9 insertions(+) diff --git a/src/command.c b/src/command.c index 4f2999a..c983385 100644 --- a/src/command.c +++ b/src/command.c @@ -63,10 +63,15 @@ int get_command(char *command, char *command_re, char **sort_tmp) { } int cl = strlen(command); + if (cl == 0) return 0; + command[cl - 1] = '\0'; for (int i = 0; i < cl - 1; i++) { command[i] = tolower(command[i]); + if ((i == 0 || i == cl - 1) && command[i] == ';') { + command[i] = ' '; + } } sort_tmp[0] = command; @@ -76,6 +81,10 @@ int get_command(char *command, char *command_re, char **sort_tmp) { sort_tmp[i] = strstr(sort_tmp[i - 1], ";"); if (sort_tmp[i] == 0) break; + if (strlen(sort_tmp[i]) < 2) { + sort_tmp[i][0] = '\0'; + break; + } sort_tmp[i][0] = '\0'; sort_tmp[i]++; } From 35005081b67f38ccf13066548f79af09fa011ac0 Mon Sep 17 00:00:00 2001 From: biglyderv Date: Mon, 24 Mar 2025 23:59:28 -0400 Subject: [PATCH 04/57] fix length segfault --- src/command.c | 12 +++++++----- 1 file changed, 7 insertions(+), 5 deletions(-) diff --git a/src/command.c b/src/command.c index c983385..5a90cd9 100644 --- a/src/command.c +++ b/src/command.c @@ -61,17 +61,19 @@ int get_command(char *command, char *command_re, char **sort_tmp) { if (!get_out) break; } + + if (command[0] == ';') { + command++; + } + int cl = strlen(command); - if (cl == 0) return 0; + if (cl < 2) return 0; command[cl - 1] = '\0'; for (int i = 0; i < cl - 1; i++) { command[i] = tolower(command[i]); - if ((i == 0 || i == cl - 1) && command[i] == ';') { - command[i] = ' '; - } } sort_tmp[0] = command; @@ -79,7 +81,7 @@ int get_command(char *command, char *command_re, char **sort_tmp) { for (int i = 1; i < MAX_COMBO_LENGTH; i++) { combos = i; sort_tmp[i] = strstr(sort_tmp[i - 1], ";"); - if (sort_tmp[i] == 0) + if (sort_tmp[i] == 0 || sort_tmp[i] == sort_tmp[i-1]) break; if (strlen(sort_tmp[i]) < 2) { sort_tmp[i][0] = '\0'; From f4be64fe198f277dbdd57ac96ad3225b2bc4565a Mon Sep 17 00:00:00 2001 From: biglyderv Date: Tue, 25 Mar 2025 01:29:28 -0400 Subject: [PATCH 05/57] fix compile bug on win32 --- src/command.c | 17 +++++++++++++---- 1 file changed, 13 insertions(+), 4 deletions(-) diff --git a/src/command.c b/src/command.c index 5a90cd9..4320d63 100644 --- a/src/command.c +++ b/src/command.c @@ -23,8 +23,16 @@ 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) { + void *usr) +#else +int inv_handler(const void *key, unsigned long long size, + unsigned long long val, void *usr) +#endif +{ if (val == 0) return 0; char *key2 = (char *)key; @@ -68,7 +76,8 @@ int get_command(char *command, char *command_re, char **sort_tmp) { int cl = strlen(command); - if (cl < 2) return 0; + if (cl < 2) + return 0; command[cl - 1] = '\0'; @@ -81,9 +90,9 @@ int get_command(char *command, char *command_re, char **sort_tmp) { for (int i = 1; i < MAX_COMBO_LENGTH; i++) { combos = i; sort_tmp[i] = strstr(sort_tmp[i - 1], ";"); - if (sort_tmp[i] == 0 || sort_tmp[i] == sort_tmp[i-1]) + if (sort_tmp[i] == 0 || sort_tmp[i] == sort_tmp[i - 1]) break; - if (strlen(sort_tmp[i]) < 2) { + if (strlen(sort_tmp[i]) < 2) { sort_tmp[i][0] = '\0'; break; } From 4bef1a220c54a58ea6d42ccc136d2bc2aedfc370 Mon Sep 17 00:00:00 2001 From: biglyderv Date: Tue, 25 Mar 2025 13:43:02 -0400 Subject: [PATCH 06/57] check both main dir and parent dir (temp fix) --- src/loader.c | 22 +++++++++++++++++++--- src/loader.h | 2 +- src/main.c | 15 +++++++++------ 3 files changed, 29 insertions(+), 10 deletions(-) diff --git a/src/loader.c b/src/loader.c index 1385fb5..949ce7d 100644 --- a/src/loader.c +++ b/src/loader.c @@ -6,21 +6,28 @@ #define MAX_FILE_SIZE 1024 * 16 -void load_elements(hashmap *m, char *table, int use_inv) { +int load_elements(hashmap *m, char *table, int use_inv) { FILE *fptr; fptr = fopen(table, "r"); + if (fptr == NULL) + return 0; + char *str; + int did_something = 0; + while (1) { str = calloc(MAX_FILE_SIZE, sizeof(char)); if (!fgets(str, MAX_FILE_SIZE, fptr)) break; + did_something = 1; + if (use_inv) { - hashmap_set(m, str, strlen(str) - 2, (uintptr_t)1); - continue; + hashmap_set(m, str, strlen(str) - 2, (uintptr_t)1); + continue; } char *combo = strstr(str, ";"); @@ -30,5 +37,14 @@ void load_elements(hashmap *m, char *table, int use_inv) { hashmap_set(m, combo, strlen(combo) - 1, (uintptr_t)str); } + + printf("%i\n",did_something); + + if (!did_something) { + free(str); + } + + return did_something; + // todo: properly free this } \ No newline at end of file diff --git a/src/loader.h b/src/loader.h index 40ac584..116d3ad 100644 --- a/src/loader.h +++ b/src/loader.h @@ -1,2 +1,2 @@ #include "map.h" -void load_elements(hashmap *m, char *table, int use_inv); \ 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 6eb9252..6ece10f 100644 --- a/src/main.c +++ b/src/main.c @@ -16,8 +16,9 @@ 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, "bin/combos.txt", 0); - load_elements(inv, "bin/inv.txt", 1); + load_elements(elements, "combos.txt", 0) || + load_elements(elements, "bin/combos.txt", 0); + load_elements(inv, "inv.txt", 1) || load_elements(inv, "bin/inv.txt", 1); printf("Welcome to Elemental on Command Line!\n"); while (1) { @@ -25,15 +26,16 @@ int main(int argc, char *argv[]) { printf("\n"); fgets(command, MAX_BUF_LENGTH - 1, stdin); - int slashRan = slash_command(command,inv); - if (slashRan) continue; + int slashRan = slash_command(command, inv); + if (slashRan) + continue; int combos = get_command(command, command_re, sort_tmp); int failed = 0; for (int i = 0; i < combos; i++) { uintptr_t result; - hashmap_get(inv, sort_tmp[i], strlen(sort_tmp[i]) - 1, &result); + hashmap_get(inv, sort_tmp[i], strlen(sort_tmp[i]) - 1, &result); if (result != 1) { printf("You don't have %s.\n", sort_tmp[i]); failed = 1; @@ -41,7 +43,8 @@ int main(int argc, char *argv[]) { } } - if (failed) continue; + if (failed) + continue; uintptr_t result; hashmap_get(elements, command_re, strlen(command_re), &result); From d5e55b54ee2fa5a87fe0fd635438d16f5e0b7bd1 Mon Sep 17 00:00:00 2001 From: biglyderv Date: Tue, 25 Mar 2025 19:48:55 -0400 Subject: [PATCH 07/57] add inv saving, fix bugs --- .gitignore | 3 ++- bin/{inv.txt => inv_base.txt} | 0 src/loader.c | 7 +++---- src/main.c | 26 +++++++++++++++++++++----- src/writer.c | 0 5 files changed, 26 insertions(+), 10 deletions(-) rename bin/{inv.txt => inv_base.txt} (100%) create mode 100644 src/writer.c diff --git a/.gitignore b/.gitignore index 7024c52..d23d186 100644 --- a/.gitignore +++ b/.gitignore @@ -1,2 +1,3 @@ /bin/elem -/bin/elem.exe \ No newline at end of file +/bin/elem.exe +/inv.txt \ No newline at end of file diff --git a/bin/inv.txt b/bin/inv_base.txt similarity index 100% rename from bin/inv.txt rename to bin/inv_base.txt diff --git a/src/loader.c b/src/loader.c index 949ce7d..91a01ae 100644 --- a/src/loader.c +++ b/src/loader.c @@ -26,7 +26,7 @@ int load_elements(hashmap *m, char *table, int use_inv) { did_something = 1; if (use_inv) { - hashmap_set(m, str, strlen(str) - 2, (uintptr_t)1); + hashmap_set(m, str, strlen(str) - 1, (uintptr_t)1); continue; } @@ -37,13 +37,12 @@ int load_elements(hashmap *m, char *table, int use_inv) { hashmap_set(m, combo, strlen(combo) - 1, (uintptr_t)str); } - - printf("%i\n",did_something); - if (!did_something) { free(str); } + fclose(fptr); + return did_something; // todo: properly free this diff --git a/src/main.c b/src/main.c index 6ece10f..341b347 100644 --- a/src/main.c +++ b/src/main.c @@ -5,6 +5,10 @@ #include #include +#define inv_file "inv.txt" +#define inv_base_file "inv_base.txt" +#define combo_file "combos.txt" + #define MAX_BUF_LENGTH 1024 #define MAX_COMBO_LENGTH 1024 @@ -16,9 +20,12 @@ 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, "combos.txt", 0) || - load_elements(elements, "bin/combos.txt", 0); - load_elements(inv, "inv.txt", 1) || load_elements(inv, "bin/inv.txt", 1); + 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); + + load_elements(inv, inv_file, 1); printf("Welcome to Elemental on Command Line!\n"); while (1) { @@ -35,7 +42,7 @@ int main(int argc, char *argv[]) { int failed = 0; for (int i = 0; i < combos; i++) { uintptr_t result; - hashmap_get(inv, sort_tmp[i], strlen(sort_tmp[i]) - 1, &result); + hashmap_get(inv, sort_tmp[i], strlen(sort_tmp[i]), &result); if (result != 1) { printf("You don't have %s.\n", sort_tmp[i]); failed = 1; @@ -56,8 +63,17 @@ int main(int argc, char *argv[]) { char *res_str = (char *)result; - hashmap_set(inv, res_str, strlen(res_str) - 1, (uintptr_t)1); + hashmap_set(inv, res_str, strlen(res_str), (uintptr_t)1); printf("You made %s!\n", res_str); + + FILE *fptr; + + fptr = fopen(inv_file, "a"); + if (fptr == NULL) + continue; + fwrite("\n",sizeof(char),1,fptr); + fwrite(res_str, sizeof(char), strlen(res_str), fptr); + fclose(fptr); } // free(command); diff --git a/src/writer.c b/src/writer.c new file mode 100644 index 0000000..e69de29 From 3baa7157dc445a795df7fe29123fa8353e31994e Mon Sep 17 00:00:00 2001 From: biglyderv Date: Tue, 25 Mar 2025 19:50:41 -0400 Subject: [PATCH 08/57] 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 Date: Tue, 25 Mar 2025 20:19:51 -0400 Subject: [PATCH 09/57] 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 Date: Tue, 25 Mar 2025 20:56:40 -0400 Subject: [PATCH 10/57] 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 Date: Tue, 25 Mar 2025 21:25:31 -0400 Subject: [PATCH 11/57] 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 Date: Wed, 26 Mar 2025 01:20:38 -0400 Subject: [PATCH 12/57] 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 #include #include @@ -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 Date: Wed, 26 Mar 2025 21:19:01 -0400 Subject: [PATCH 13/57] 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 Date: Wed, 26 Mar 2025 22:15:43 -0400 Subject: [PATCH 14/57] 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 #include #include #include @@ -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 #include #include #include @@ -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 Date: Wed, 26 Mar 2025 23:43:25 -0400 Subject: [PATCH 15/57] 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 Date: Wed, 26 Mar 2025 23:47:21 -0400 Subject: [PATCH 16/57] 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 Date: Wed, 26 Mar 2025 23:49:52 -0400 Subject: [PATCH 17/57] 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 Date: Wed, 26 Mar 2025 23:55:56 -0400 Subject: [PATCH 18/57] 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 Date: Thu, 27 Mar 2025 07:34:20 -0400 Subject: [PATCH 19/57] 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 #include -#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 #include -#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 #include -#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 Date: Thu, 27 Mar 2025 09:51:49 -0400 Subject: [PATCH 20/57] 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 Date: Thu, 27 Mar 2025 15:56:47 -0400 Subject: [PATCH 21/57] 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 Date: Thu, 27 Mar 2025 18:00:30 -0400 Subject: [PATCH 22/57] 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 Date: Thu, 27 Mar 2025 22:12:19 -0400 Subject: [PATCH 23/57] 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 Date: Fri, 28 Mar 2025 01:36:28 -0400 Subject: [PATCH 24/57] 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 Date: Fri, 28 Mar 2025 01:54:00 -0400 Subject: [PATCH 25/57] 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 Date: Fri, 28 Mar 2025 02:17:42 -0400 Subject: [PATCH 26/57] 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 Date: Fri, 28 Mar 2025 02:31:01 -0400 Subject: [PATCH 27/57] 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 Date: Fri, 28 Mar 2025 16:37:38 -0400 Subject: [PATCH 28/57] 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 Date: Sat, 29 Mar 2025 02:51:38 -0400 Subject: [PATCH 29/57] 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 Date: Sat, 29 Mar 2025 04:59:17 -0400 Subject: [PATCH 30/57] 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 Date: Sat, 29 Mar 2025 05:00:37 -0400 Subject: [PATCH 31/57] 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 Date: Sat, 29 Mar 2025 21:47:26 -0400 Subject: [PATCH 32/57] 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 Date: Sun, 30 Mar 2025 01:07:00 -0400 Subject: [PATCH 33/57] 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 #include @@ -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 (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 Date: Sun, 30 Mar 2025 02:43:52 -0400 Subject: [PATCH 34/57] 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 Date: Mon, 31 Mar 2025 21:38:33 -0400 Subject: [PATCH 35/57] 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 Date: Tue, 1 Apr 2025 21:10:25 -0400 Subject: [PATCH 36/57] 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 #include #include +#include #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 Date: Tue, 1 Apr 2025 21:14:53 -0400 Subject: [PATCH 37/57] 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 Date: Tue, 1 Apr 2025 22:00:06 -0400 Subject: [PATCH 38/57] 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 Date: Wed, 2 Apr 2025 01:28:18 -0400 Subject: [PATCH 39/57] 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 Date: Wed, 2 Apr 2025 20:32:44 -0400 Subject: [PATCH 40/57] 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 Date: Wed, 2 Apr 2025 20:37:18 -0400 Subject: [PATCH 41/57] 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 Date: Thu, 3 Apr 2025 11:18:32 -0400 Subject: [PATCH 42/57] 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 Date: Thu, 3 Apr 2025 11:49:48 -0400 Subject: [PATCH 43/57] 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 Date: Thu, 3 Apr 2025 13:29:03 -0400 Subject: [PATCH 44/57] 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 Date: Thu, 3 Apr 2025 13:46:08 -0400 Subject: [PATCH 45/57] 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 Date: Thu, 3 Apr 2025 13:48:03 -0400 Subject: [PATCH 46/57] 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 Date: Sat, 5 Apr 2025 15:49:21 -0400 Subject: [PATCH 47/57] 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 Date: Mon, 7 Apr 2025 11:04:24 -0400 Subject: [PATCH 48/57] 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 Date: Wed, 9 Apr 2025 12:12:49 -0400 Subject: [PATCH 49/57] 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 Date: Wed, 9 Apr 2025 12:14:48 -0400 Subject: [PATCH 50/57] 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 Date: Sat, 12 Apr 2025 09:44:14 -0400 Subject: [PATCH 51/57] 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 #include #include - +#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 Date: Mon, 14 Apr 2025 20:36:53 -0400 Subject: [PATCH 52/57] 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 #include #include #include @@ -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 #include #include @@ -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 Date: Thu, 17 Apr 2025 09:27:13 -0400 Subject: [PATCH 53/57] 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 Date: Thu, 17 Apr 2025 09:43:20 -0400 Subject: [PATCH 54/57] 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 Date: Sun, 20 Apr 2025 20:10:50 -0400 Subject: [PATCH 55/57] 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 Date: Sun, 20 Apr 2025 20:11:10 -0400 Subject: [PATCH 56/57] 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 Date: Sun, 20 Apr 2025 20:16:30 -0400 Subject: [PATCH 57/57] 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