Bladeren bron

Merge branch 'MULTITHREADS'

Iñigo Valentin 4 jaren geleden
bovenliggende
commit
11463183c0

+ 1 - 1
Makefile

@@ -22,7 +22,7 @@ CFLAGS=
 OPTS_DEBUG=-Wall -g
 OPTS_TEST=
 OPTS=-O3
-LIBS=-lsqlite3 -lm -ljson-c
+LIBS=-lsqlite3 -lm -ljson-c -lpthread
 OUT=bin/RuneOptimizer
 OUT_DEBUG=bin/RuneOptimizer_DEBUG
 TEST_SRC=src/test/RuneOptimizerTest.c

+ 1 - 0
src/RuneOptimizer/RuneOptimizer.c

@@ -31,6 +31,7 @@
 #include <json-c/json.h>
 #include <sys/types.h>
 #include <sys/stat.h>
+#include <pthread.h>
 #include "RuneOptimizer.h"
 #include "error/error.h"
 #include "db/db.c"

+ 1 - 0
src/RuneOptimizer/help/help.c

@@ -122,5 +122,6 @@ void cmd_help(){
     printf("        -u | --no-units <U1>,<U2>... Exclude runes assigned to units in selected units.\n");
     printf("                                     Unit IDs can be supplied, comma-separated.\n");
     printf("        -g | --gui                   Formats the output to be consumed by the GUI.\n");
+    printf("        -b | --threads <NUM>         Use <NUM> threads for optimizaton (1-8).\n");
     return;
 }

+ 176 - 129
src/RuneOptimizer/optimize/optimize.c

@@ -112,6 +112,7 @@ void optimize_set_default_options(Optimizer_Options *options){
     options->total_excluded_teams = 0,
     options->total_excluded_units = 0;
     options->broken_sets = FALSE;
+    options->threads = 2;
 }
 
 int cmd_optimize(int argc, char *argv[]){
@@ -161,12 +162,12 @@ int cmd_optimize(int argc, char *argv[]){
         options.full_set = TRUE;
     }
     // Create queries for the database.
-    char query_even[2500];
-    char query_odd[2500];
-    optimize_query_for_even_slots(&options, query_even);
+    char query_even[3500];
+    char query_odd[3500];
     optimize_query_for_odd_slots(&options, query_odd);
-    //printf("\nQ ODD:\n\n%s\n\n\n\n", query_odd);
+    optimize_query_for_even_slots(&options, query_even);
     //printf("\nQ EVEN:\n\n%s\n\n\n\n", query_even);
+    //printf("\nQ ODD:\n\n%s\n\n\n\n", query_odd);
 
     // Get runes from database.
     struct Rune runes[7][600];
@@ -210,37 +211,110 @@ int cmd_optimize(int argc, char *argv[]){
         fflush(stdout);
     }
 
+    Optimizer_Data opt_data[options.threads];
+    for (int t = 0; t < options.threads; t++){
+        for (int i = 1; i < 7; i ++){
+            opt_data[t].count[i] = rune_count[i];
+            for (int j = 0; j < rune_count[i]; j ++){
+                opt_data[t].runes[i][j] = runes[i][j];
+            }
+            opt_data[t].thread_id = t;
+            opt_data[t].start_at = t * rune_count[1] / options.threads;
+            opt_data[t].end_at = (t + 1) * rune_count[1] / options.threads;
+        }
+        opt_data[t].total_results = 0;
+        opt_data[t].options = options;
+        opt_data[t].max_combinations = max_combinations;
+        opt_data[t].requested_set_count = requested_set_count;
+        opt_data[t].unit = unit;
+    }
+
+    pthread_t thread[options.threads];
+    for (int t = 0; t < options.threads; t++){
+        //printf("Before Thread\n");
+        pthread_create(&thread[t], NULL, optimize_thread, &opt_data[t]);
+    }
+    for (int t = 0; t < options.threads; t++){
+        pthread_join(thread[t], NULL);
+    }
+
+    // Process results
+    if (options.gui == FALSE){
+        printf("\n");
+    }
+    int result_count = 0;
+    Result results[MAX_RESULTS];
+    int results_pos = 0;
+    for (int t = 0; t < options.threads; t++){
+        result_count += opt_data[t].total_results;
+        for (int i = 0; i < opt_data[t].total_results; i ++){
+            results[results_pos] = opt_data[t].results[i];
+            results_pos ++;
+        }
+    }
+    if (result_count > 0){
+        // Yay! Some combinations matched te criteria.
+        if (options.gui == FALSE){
+            printf("\n\n%d results found\n", result_count);
+        }
+
+        // Sort results
+        optimize_sort_results(results, result_count);
+        if (options.gui == FALSE){
+            // Preview the best option
+            optimize_print_result(&unit, &results[0]);
+        }
+        else{
+            // Create the output
+            optimize_print_gui(results, result_count);
+        }
+    }
+    else{
+        if (options.gui == FALSE){
+            printf("No results found\n");
+        }
+        else{
+            printf("{\"result_count\":0,\"results\":[]}\n");
+        }
+    }
+
+}
+void *optimize_thread(void *data){
+
+    Optimizer_Data *opt_data = data;
+
     // Initialize arrys and some counters
-    int index[7] = {0, 0, 0, 0, 0, 0};
+    int index[7] = {0, opt_data->start_at, 0, 0, 0, 0};
     unsigned long tested_combinations = 0;
     unsigned long valid_sets = 0;
     unsigned long result_count = 0;
     Rune_Set_Count set_count;
-    Result results[MAX_RESULTS];
+    //Result results[MAX_RESULTS];
     while(
-        index[1] < rune_count[1] &&
-        index[2] < rune_count[2] &&
-        index[3] < rune_count[3] &&
-        index[4] < rune_count[4] &&
-        index[5] < rune_count[5] &&
-        index[6] < rune_count[6] &&
+        index[1] < opt_data->count[1] && index[1] < opt_data->end_at &&
+        index[2] < opt_data->count[2] &&
+        index[3] < opt_data->count[3] &&
+        index[4] < opt_data->count[4] &&
+        index[5] < opt_data->count[5] &&
+        index[6] < opt_data->count[6] &&
         result_count < MAX_RESULTS // Hard limit
     ){
         // Progress bar, 50 characters to 100%
         if (
           (tested_combinations + 1) %
-          (unsigned long)(max_combinations / 50)
+          (unsigned long)((opt_data->max_combinations) / 50)
           == 0
         ){
-            if (options.gui == FALSE){
+            if (opt_data->options.gui == FALSE){
                 printf("#");
+                //printf("%d", opt_data->thread_id);
             }
             else{
                 // For GUI flushing, newlines are required
                 printf(
                   "%d\n",
                   (unsigned long)( (tested_combinations + 1) /
-                  (unsigned long)(max_combinations / 20)));
+                  (unsigned long)(opt_data->max_combinations / 20)));
             }
             // Line buffered! need to flush after every char.
             fflush(stdout);
@@ -269,7 +343,7 @@ int cmd_optimize(int argc, char *argv[]){
         set_count.accuracy = 0;
         set_count.tolerance = 0;
         for (int i = 1; i < 7; i ++){
-            switch (runes[i][index[i]].set){
+            switch (opt_data->runes[i][index[i]].set){
                 case ENERGY:        set_count.energy ++;        break;
                 case GUARD:         set_count.guard ++;         break;
                 case SWIFT:         set_count.swift ++;         break;
@@ -296,72 +370,72 @@ int cmd_optimize(int argc, char *argv[]){
 
         // Compare with requested sets
         // TODO: Here, validate broken sets too
-        if (options.broken_sets == FALSE){
+        if (opt_data->options.broken_sets == FALSE){
 
         }
         if (
             (
-              options.broken_sets == TRUE ||
+              opt_data->options.broken_sets == TRUE ||
               optimize_contains_broken(&set_count) == FALSE
             ) &&
-            set_count.energy >= requested_set_count.energy &&
-            set_count.guard >= requested_set_count.guard &&
-            set_count.swift >= requested_set_count.swift &&
-            set_count.blade >= requested_set_count.blade &&
-            set_count.rage >= requested_set_count.rage &&
-            set_count.focus >= requested_set_count.focus &&
-            set_count.endure >= requested_set_count.endure &&
-            set_count.fatal >= requested_set_count.fatal &&
-            set_count.despair >= requested_set_count.despair &&
-            set_count.vampire >= requested_set_count.vampire &&
-            set_count.violent >= requested_set_count.violent &&
-            set_count.nemesis >= requested_set_count.nemesis &&
-            set_count.will >= requested_set_count.will &&
-            set_count.shield >= requested_set_count.shield &&
-            set_count.revenge >= requested_set_count.revenge &&
-            set_count.destroy >= requested_set_count.destroy &&
-            set_count.fight >= requested_set_count.fight &&
-            set_count.determination >= requested_set_count.determination &&
-            set_count.enhance >= requested_set_count.enhance &&
-            set_count.accuracy >= requested_set_count.accuracy &&
-            set_count.tolerance >= requested_set_count.tolerance
+            set_count.energy >= opt_data->requested_set_count.energy &&
+            set_count.guard >= opt_data->requested_set_count.guard &&
+            set_count.swift >= opt_data->requested_set_count.swift &&
+            set_count.blade >= opt_data->requested_set_count.blade &&
+            set_count.rage >= opt_data->requested_set_count.rage &&
+            set_count.focus >= opt_data->requested_set_count.focus &&
+            set_count.endure >= opt_data->requested_set_count.endure &&
+            set_count.fatal >= opt_data->requested_set_count.fatal &&
+            set_count.despair >= opt_data->requested_set_count.despair &&
+            set_count.vampire >= opt_data->requested_set_count.vampire &&
+            set_count.violent >= opt_data->requested_set_count.violent &&
+            set_count.nemesis >= opt_data->requested_set_count.nemesis &&
+            set_count.will >= opt_data->requested_set_count.will &&
+            set_count.shield >= opt_data->requested_set_count.shield &&
+            set_count.revenge >= opt_data->requested_set_count.revenge &&
+            set_count.destroy >= opt_data->requested_set_count.destroy &&
+            set_count.fight >= opt_data->requested_set_count.fight &&
+            set_count.determination >= opt_data->requested_set_count.determination &&
+            set_count.enhance >= opt_data->requested_set_count.enhance &&
+            set_count.accuracy >= opt_data->requested_set_count.accuracy &&
+            set_count.tolerance >= opt_data->requested_set_count.tolerance
         ){
             // The current runes form a valid set.
             valid_sets ++;
 
             // Calculate new stats
             struct Stats stats;
-            stats.hp = unit.base_hp;
-            stats.atk = unit.base_atk;
-            stats.def = unit.base_def;
-            stats.spd = unit.base_spd;
-            stats.crr = unit.base_crr;
-            stats.crd = unit.base_crd;
-            stats.res = unit.base_res;
-            stats.acc = unit.base_acc;
+            stats.hp = opt_data->unit.base_hp;
+            stats.atk = opt_data->unit.base_atk;
+            stats.def = opt_data->unit.base_def;
+            stats.spd = opt_data->unit.base_spd;
+            stats.crr = opt_data->unit.base_crr;
+            stats.crd = opt_data->unit.base_crd;
+            stats.res = opt_data->unit.base_res;
+            stats.acc = opt_data->unit.base_acc;
             for (int i = 1; i < 7; i ++){
-                stats.hp += runes[i][index[i]].hp_flat;
-                stats.atk += runes[i][index[i]].atk_flat;
-                stats.def += runes[i][index[i]].def_flat;
-                stats.hp += unit.base_hp * runes[i][index[i]].hp_percent / 100;
+                stats.hp += opt_data->runes[i][index[i]].hp_flat;
+                stats.atk += opt_data->runes[i][index[i]].atk_flat;
+                stats.def += opt_data->runes[i][index[i]].def_flat;
+                stats.hp += opt_data->unit.base_hp * opt_data->runes[i][index[i]].hp_percent / 100;
                 stats.atk +=
-                  unit.base_atk * runes[i][index[i]].atk_percent / 100;
+                  opt_data->unit.base_atk * opt_data->runes[i][index[i]].atk_percent / 100;
                 stats.def +=
-                  unit.base_def * runes[i][index[i]].def_percent / 100;
-                stats.spd += runes[i][index[i]].spd;
-                stats.crr += runes[i][index[i]].crr;
-                stats.crd += runes[i][index[i]].crd;
-                stats.res += runes[i][index[i]].res;
-                stats.acc += runes[i][index[i]].acc;
+                  opt_data->unit.base_def * opt_data->runes[i][index[i]].def_percent / 100;
+                stats.spd += opt_data->runes[i][index[i]].spd;
+                stats.crr += opt_data->runes[i][index[i]].crr;
+                stats.crd += opt_data->runes[i][index[i]].crd;
+                stats.res += opt_data->runes[i][index[i]].res;
+                stats.acc += opt_data->runes[i][index[i]].acc;
             }
 
             // Set stats
             if (set_count.energy >= 2) // +15% Base HP per set of 2
-                stats.hp += unit.base_hp * 0.15 * (set_count.energy % 2);
+                stats.hp += opt_data->unit.base_hp * 0.15 * (set_count.energy % 2);
             if (set_count.guard >= 2) // +15% base DEF per set of 2
-                stats.def += unit.base_def * 0.15 * (set_count.guard % 2);
+                stats.def += opt_data->unit.base_def * 0.15 * (set_count.guard % 2);
             if (set_count.swift >= 4) // +25% base SPD per set of 4
-                stats.spd += unit.base_spd * 0.25;
+                stats.spd += opt_data->unit.base_spd * 0.25;
             if (set_count.blade >= 2) // +12% CRR per set of 2
                 stats.crr += 12;
             if (set_count.rage >= 4) // +40% CRD per set of 4
@@ -371,14 +445,14 @@ int cmd_optimize(int argc, char *argv[]){
             if (set_count.endure >= 2) // +20% RES per set of 2
                 stats.res += 20;
             if (set_count.fatal >= 4) // +35% base ATK per set of 4
-                stats.atk += unit.base_atk * 0.35;
+                stats.atk += opt_data->unit.base_atk * 0.35;
             if (set_count.fight >= 2) // +8% base ATK per set of 2
-                stats.atk += unit.base_atk * 0.08 * (set_count.fight % 2);
+                stats.atk += opt_data->unit.base_atk * 0.08 * (set_count.fight % 2);
             if (set_count.determination >= 2) // +8% base DEF per set of 2
                 stats.def +=
-                  unit.base_def * 0.08 * (set_count.determination % 2);
+                  opt_data->unit.base_def * 0.08 * (set_count.determination % 2);
             if (set_count.enhance >= 2) // +8% base HP per set of 2
-                stats.hp += unit.base_hp * 0.08 * (set_count.enhance % 2);
+                stats.hp += opt_data->unit.base_hp * 0.08 * (set_count.enhance % 2);
             if (set_count.accuracy >= 2) // +10% ACC per set of 2
                 stats.acc += 20;
             if (set_count.tolerance >= 2) // +10% RES per set of 2
@@ -395,35 +469,35 @@ int cmd_optimize(int argc, char *argv[]){
 
             // Compare with minimum requeriments
             if (
-                stats.hp >= options.min_stats->hp &&
-                stats.atk >= options.min_stats->atk &&
-                stats.def >= options.min_stats->def &&
-                stats.spd >= options.min_stats->spd &&
-                stats.crr >= options.min_stats->crr &&
-                stats.crd >= options.min_stats->crd &&
-                stats.res >= options.min_stats->res &&
-                stats.acc >= options.min_stats->acc &&
-                stats.ehp >= options.min_stats->ehp &&
-                stats.dmg >= options.min_stats->dmg
+                stats.hp >= opt_data->options.min_stats->hp &&
+                stats.atk >= opt_data->options.min_stats->atk &&
+                stats.def >= opt_data->options.min_stats->def &&
+                stats.spd >= opt_data->options.min_stats->spd &&
+                stats.crr >= opt_data->options.min_stats->crr &&
+                stats.crd >= opt_data->options.min_stats->crd &&
+                stats.res >= opt_data->options.min_stats->res &&
+                stats.acc >= opt_data->options.min_stats->acc &&
+                stats.ehp >= opt_data->options.min_stats->ehp &&
+                stats.dmg >= opt_data->options.min_stats->dmg
             ){
                 // This is a valid sets and all stats are above the minimum.
                 // Create a result with rune indexes, stats, and rating.
                 for (int i = 1; i < 7; i ++){
                     strcpy(
-                      results[result_count].rune_ids[i - 1],
-                      runes[i][index[i]].id
+                      opt_data->results[result_count].rune_ids[i - 1],
+                      opt_data->runes[i][index[i]].id
                     );
                 }
-                results[result_count].stats.hp = stats.hp;
-                results[result_count].stats.atk = stats.atk;
-                results[result_count].stats.def = stats.def;
-                results[result_count].stats.spd = stats.spd;
-                results[result_count].stats.crr = stats.crr;
-                results[result_count].stats.crd = stats.crd;
-                results[result_count].stats.res = stats.res;
-                results[result_count].stats.acc = stats.acc;
-                results[result_count].stats.ehp = stats.ehp;
-                results[result_count].stats.dmg = stats.dmg;
+                opt_data->results[result_count].stats.hp = stats.hp;
+                opt_data->results[result_count].stats.atk = stats.atk;
+                opt_data->results[result_count].stats.def = stats.def;
+                opt_data->results[result_count].stats.spd = stats.spd;
+                opt_data->results[result_count].stats.crr = stats.crr;
+                opt_data->results[result_count].stats.crd = stats.crd;
+                opt_data->results[result_count].stats.res = stats.res;
+                opt_data->results[result_count].stats.acc = stats.acc;
+                opt_data->results[result_count].stats.ehp = stats.ehp;
+                opt_data->results[result_count].stats.dmg = stats.dmg;
 
                 // Calculate rating, based on the difference between the
                 // stats with this set and the current stats.
@@ -440,22 +514,22 @@ int cmd_optimize(int argc, char *argv[]){
                 // ACC: 1 rating point per 1.52 points
                 float rating = 0.0f;
                 rating +=
-                  (float) ((int) stats.hp  - (int) unit.current_hp ) / 58.29f;
+                  (float) ((int) stats.hp  - (int) opt_data->unit.current_hp ) / 58.29f;
                 rating +=
-                  (float) ((int) stats.atk - (int) unit.current_atk) /  1.50f;
+                  (float) ((int) stats.atk - (int) opt_data->unit.current_atk) /  1.50f;
                 rating +=
-                  (float) ((int) stats.def - (int) unit.current_def) /  1.50f;
+                  (float) ((int) stats.def - (int) opt_data->unit.current_def) /  1.50f;
                 rating +=
-                  (float) ((int) stats.spd - (int) unit.current_spd) /  1.00f;
+                  (float) ((int) stats.spd - (int) opt_data->unit.current_spd) /  1.00f;
                 rating +=
-                  (float) ((int) stats.crr - (int) unit.current_crr) /  1.38f;
+                  (float) ((int) stats.crr - (int) opt_data->unit.current_crr) /  1.38f;
                 rating +=
-                  (float) ((int) stats.crd - (int) unit.current_crd) /  1.90f;
+                  (float) ((int) stats.crd - (int) opt_data->unit.current_crd) /  1.90f;
                 rating +=
-                  (float) ((int) stats.res - (int) unit.current_res) /  1.52f;
+                  (float) ((int) stats.res - (int) opt_data->unit.current_res) /  1.52f;
                 rating +=
-                  (float) ((int) stats.acc - (int) unit.current_acc) /  1.52f;
-                results[result_count].rating = (int) rating;
+                  (float) ((int) stats.acc - (int) opt_data->unit.current_acc) /  1.52f;
+                opt_data->results[result_count].rating = (int) rating;
 
                 // Account for found result
                 result_count ++;
@@ -465,23 +539,23 @@ int cmd_optimize(int argc, char *argv[]){
         // Loop control. Rotate the reels 'right to left'
         tested_combinations ++;
         index[6] ++;
-        if (index[6] == rune_count[6]){
+        if (index[6] == opt_data->count[6]){
             index[6] = 0;
             index[5] ++;
         }
-        if (index[5] == rune_count[5]){
+        if (index[5] == opt_data->count[5]){
             index[5] = 0;
             index[4] ++;
         }
-        if (index[4] == rune_count[4]){
+        if (index[4] == opt_data->count[4]){
             index[4] = 0;
             index[3] ++;
         }
-        if (index[3] == rune_count[3]){
+        if (index[3] == opt_data->count[3]){
             index[3] = 0;
             index[2] ++;
         }
-        if (index[2] == rune_count[2]){
+        if (index[2] == opt_data->count[2]){
             index[2] = 0;
             index[1] ++;
         }
@@ -491,33 +565,6 @@ int cmd_optimize(int argc, char *argv[]){
         //    break;
         //}
     }
-    if (options.gui == FALSE){
-        printf("\n");
-    }
-    if (result_count > 0){
-        // Yay! Some combinations matched te criteria.
-        if (options.gui == FALSE){
-            printf("\n\n%d results found\n", result_count);
-        }
-
-        // Sort results
-        optimize_sort_results(results, result_count);
-        if (options.gui == FALSE){
-            // Preview the best option
-            optimize_print_result(&unit, &results[0]);
-        }
-        else{
-            // Create the output
-            optimize_print_gui(results, result_count);
-        }
-    }
-    else{
-        if (options.gui == FALSE){
-            printf("No results found\n");
-        }
-        else{
-            printf("{\"result_count\":0,\"results\":[]}\n");
-        }
-    }
+    opt_data->total_results = result_count;
     return SUCCESS;
 }

+ 28 - 3
src/RuneOptimizer/optimize/optimize.h

@@ -134,11 +134,29 @@ typedef struct Optimizer_Options {
     unsigned char excluded_units[MAX_EXCLUSIONS][16];
     unsigned char total_excluded_units;
     unsigned char broken_sets;
+    unsigned char threads;
     // TODO: unimplemented options;
     Stat_Ponderation ponderation;
 
 } Optimizer_Options;
 
+/**
+ * Data package used by optimize_thread.
+ */
+typedef struct Optimizer_Data {
+    unsigned int thread_id;
+    Rune runes[7][1000];
+    unsigned int count[7];
+    unsigned char start_at;
+    unsigned char end_at;
+    Result results[MAX_RESULTS];
+    unsigned int total_results;
+    Optimizer_Options options;
+    unsigned long long max_combinations;
+    Rune_Set_Count requested_set_count;
+    Unit unit;
+} Optimizer_Data;
+
 /**
  * Names for run stats.
  * 
@@ -161,6 +179,13 @@ const char set_names[][25] = {
   "DESTROY", "FIGHT",   "DETERMINATION", "ENHANCE", "ACCURACY", "TOLERANCE"
 };
 
+/**
+ * Function to be executed by each thread of the optimizer.
+ *
+ * @param[in|out] vargp Must be a Optimizer_Data pointer casted to void.
+ */
+void *optimize_thread(void *vargp);
+
 /**
  * Calculates how many runes of each type it takes to satisfy a lst of up to
  * three sets.
@@ -199,7 +224,7 @@ int optimize_fetch_unit(char id[64], struct Unit *unit);
  * @return SUCCESS or an error code.
  */
 int optimize_get_runes(
-  char query_even[1500], char query_odd[1500],
+  char query_even[3500], char query_odd[3500],
   struct Rune runes[7][600], int rune_count[7]
 );
 
@@ -261,7 +286,7 @@ int optimize_print_gui(Result results[5000], int result_count);
  * @param[out] query String with the query.
  */
 void optimize_query_for_even_slots(
-    Optimizer_Options *options, char query[2500]
+    Optimizer_Options *options, char query[3500]
 );
 
 /**
@@ -270,7 +295,7 @@ void optimize_query_for_even_slots(
  * @param[in] options Options passed to the optimizer.
  * @param[out] query String with the query.
  */
-void optimize_query_for_odd_slots(Optimizer_Options *options, char query[2500]);
+void optimize_query_for_odd_slots(Optimizer_Options *options, char query[3500]);
 
 /**
  * Sorts the result array.

+ 17 - 0
src/RuneOptimizer/optimize/optimize_parse_arguments.c

@@ -507,6 +507,23 @@ int optimize_parse_arguments(
         else if (strcmp("--gui", argv[i]) == 0 || strcmp("-g", argv[i]) == 0){
             options->gui = TRUE;
         }
+        else if (
+          strcmp("--threads", argv[i]) == 0 || strcmp("-b", argv[i]) == 0
+        ){
+            if (i < argc - 1){
+                unsigned char threads_tmp = atoi(argv[i + 1]);
+                if (threads_tmp < 1) threads_tmp = 1;
+                else if (threads_tmp > 8) threads_tmp = 8;
+                options->threads = threads_tmp;
+                i ++; // Advance one position in argument reading
+            }
+            else{
+                fprintf(
+                  stderr, "Argument %s requires a numeric value [1-8].\n", argv[i]
+                );
+                return ERROR_INPUT_OPTIMIZE_NO_ACC;
+            }
+        }
 
     }
     return SUCCESS;

+ 7 - 6
src/RuneOptimizer/optimize/optimize_query.c

@@ -22,9 +22,10 @@
  */
 
 void optimize_query_for_even_slots(
-    Optimizer_Options *options, char query[2500]
+    Optimizer_Options *options, char query[3500]
 ){
-    char stat_set[2];
+    char stat_set[3];
+    int y;
     optimize_query_for_odd_slots(options, query);
     strcat(query, "  AND main_stat IN (");
     for (int i = 0; i < 13; i ++){
@@ -36,14 +37,14 @@ void optimize_query_for_even_slots(
     }
     query[strlen(query) - 2] = '\0'; // Remove last coma
     strcat(query, ") -- Main stats\n");
-    //printf("QUERY: %s\n", query);
+    //printf("\n\nQUERY: %s\n\n", query);
     return;
 }
 
-void optimize_query_for_odd_slots(Optimizer_Options *options, char query[2500]){
+void optimize_query_for_odd_slots(Optimizer_Options *options, char query[3500]){
     char column[10];
-    char cur_set[2];
-    char stat_set[2];
+    char cur_set[3];
+    char stat_set[3];
     if (options->level == 12) strcpy(column, "lv12_");
     else if (options->level == 15) strcpy(column, "lv15_");
     else strcpy(column, "current_");