Ver Fonte

Initial commit. Basic algorithm. It finds results.

Iñigo Valentin há 4 anos atrás
commit
4cf6a8449d
2 ficheiros alterados com 937 adições e 0 exclusões
  1. 1 0
      .gitignore
  2. 936 0
      src/RuneOptimizer.c

+ 1 - 0
.gitignore

@@ -0,0 +1 @@
+data.sqlite

+ 936 - 0
src/RuneOptimizer.c

@@ -0,0 +1,936 @@
+#include <stdio.h>
+#include <string.h>
+#include <sqlite3.h>
+
+// Rune set definitions
+#define ENERGY 1
+#define GUARD 2
+#define SWIFT 3
+#define BLADE 4
+#define RAGE 5
+#define FOCUS 6
+#define ENDURE 7
+#define FATAL 8
+#define DESPAIR 10
+#define VAMPIRE 11
+#define VIOLENT 13
+#define NEMESIS 14
+#define WILL 15
+#define SHIELD 16
+#define REVENGE 17
+#define DESTROY 18
+#define FIGHT 19
+#define DETERMINATION 20
+#define ENHANCE 21
+#define ACCURACY 22
+#define TOLERANCE 23
+
+// Rune stat definitions
+#define HP_FLAT 1
+#define HP_PERCENT 2
+#define ATK_FLAT 3
+#define ATK_PERCENT 4
+#define DEF_FLAT 5
+#define DEF_PERCENT 6
+#define SPD 8
+#define CRR 9
+#define CRD 10
+#define RES 11
+#define ACC 12
+
+struct Unit {
+    unsigned char id[12];
+    unsigned char name[50];
+    unsigned short base_hp;
+    unsigned short base_atk;
+    unsigned short base_def;
+    unsigned short base_spd;
+    unsigned short base_crr;
+    unsigned short base_crd;
+    unsigned short base_acc;
+    unsigned short base_res;
+    unsigned short current_hp;
+    unsigned short current_atk;
+    unsigned short current_def;
+    unsigned short current_spd;
+    unsigned short current_crr;
+    unsigned short current_crd;
+    unsigned short current_acc;
+    unsigned short current_res;
+};
+
+struct Rune {
+    unsigned char id[12];
+    unsigned char slot;
+    unsigned char set;
+    unsigned char unit[12];
+    unsigned char hp_percent;
+    unsigned char atk_percent;
+    unsigned char def_percent;
+    unsigned short hp_flat;
+    unsigned char atk_flat;
+    unsigned char def_flat;
+    unsigned char spd;
+    unsigned char crr;
+    unsigned char crd;
+    unsigned char acc;
+    unsigned char res;
+};
+
+struct Stats {
+    unsigned short hp;
+    unsigned short atk;
+    unsigned short def;
+    unsigned short spd;
+    unsigned short crr;
+    unsigned short crd;
+    unsigned short acc;
+    unsigned short res;
+};
+
+struct Rune_Set_Count {
+    unsigned short energy;
+    unsigned short guard;
+    unsigned short swift;
+    unsigned short blade;
+    unsigned short rage;
+    unsigned short focus;
+    unsigned short endure;
+    unsigned short fatal;
+    unsigned short despair;
+    unsigned short vampire;
+    unsigned short violent;
+    unsigned short nemesis;
+    unsigned short will;
+    unsigned short shield;
+    unsigned short revenge;
+    unsigned short destroy;
+    unsigned short fight;
+    unsigned short determination;
+    unsigned short enhance;
+    unsigned short accuracy;
+    unsigned short tolerance;
+};
+typedef struct Result {
+    unsigned char rune_ids[6][12];
+    signed int rating;
+} Result;
+
+void show_help();
+int optimize(int argc, char *argv[]);
+int open_databse();
+int unit_callback(void *, int, char **, char **);
+int db_status;
+sqlite3 *db;
+
+int main(int argc, char *argv[]){
+    // Parse the arguments
+   if (argc < 2){
+        printf("No options specified\n");
+        return 0;
+    }
+    int command = -1;
+    if (strcmp(argv[1], "update") == 0){
+        printf("Updating is still unimplemented\n");
+        return 0;
+    }
+    else if (strcmp(argv[1], "optimize") == 0){
+        //printf("Starting optimization...\n");
+        int result = optimize(argc, argv);
+        if (result != 0){
+            printf("Errors in optimization: %d\n", result);
+            return result;
+        }
+    }
+    else if (strcmp(argv[1], "help") == 0){
+        show_help();
+        return 0;
+    }
+    else{
+        printf("Invalid option specified: %s\n", argv[1]);
+        return 0;
+    }
+
+   return 0;
+}
+
+int open_database(){
+    int db_status = sqlite3_open("../data.sqlite", &db);
+
+    if (db_status != SQLITE_OK) {
+
+        printf("Cannot open database: %s\n", sqlite3_errmsg(db));
+        sqlite3_close(db);
+
+        return 1;
+    }
+    else{
+        return 0;
+    }
+}
+
+void show_help(){
+    printf("Sample help text\n");
+}
+
+int optimize(int argc, char *argv[]){
+    if (argc < 3){
+        printf("No unit specified for optimization\n");
+        return -1;
+    }
+    // Read the unit from the databse
+    open_database();
+
+    sqlite3_stmt *res;
+    char *sql = "SELECT "
+      "id, name, "
+      "base_hp, base_atk, base_def, base_spd, base_crr, base_crd, base_res, base_acc, "
+      "current_hp, current_atk, current_def, current_spd, current_crr, current_crd, current_res, current_acc "
+      "FROM units WHERE id = ? OR name = ?";
+    db_status = sqlite3_prepare_v2(db, sql, -1, &res, 0);
+
+    if (db_status == SQLITE_OK) {
+        sqlite3_bind_text(res, 1, argv[2], strlen(argv[2]), NULL);
+        sqlite3_bind_text(res, 2, argv[2], strlen(argv[2]), NULL);
+    }
+    else {
+        printf("Failed to execute statement to select unit: %s\n", sqlite3_errmsg(db));
+        return -2;
+    }
+
+    int step = sqlite3_step(res);
+
+    struct Unit unit;
+
+    if (step == SQLITE_ROW) {
+        strcpy(unit.id, sqlite3_column_text(res, 0));
+        strcpy(unit.name, sqlite3_column_text(res, 1));
+        unit.base_hp = sqlite3_column_int(res, 2);
+        unit.base_atk = sqlite3_column_int(res, 3);
+        unit.base_def = sqlite3_column_int(res, 4);
+        unit.base_spd = sqlite3_column_int(res, 5);
+        unit.base_crr = sqlite3_column_int(res, 6);
+        unit.base_crd = sqlite3_column_int(res, 7);
+        unit.base_res = sqlite3_column_int(res, 8);
+        unit.base_acc = sqlite3_column_int(res, 9);
+        unit.current_hp = sqlite3_column_int(res, 10);
+        unit.current_atk = sqlite3_column_int(res, 11);
+        unit.current_def = sqlite3_column_int(res, 12);
+        unit.current_spd = sqlite3_column_int(res, 13);
+        unit.current_crr = sqlite3_column_int(res, 14);
+        unit.current_crd = sqlite3_column_int(res, 15);
+        unit.current_res = sqlite3_column_int(res, 16);
+        unit.current_acc = sqlite3_column_int(res, 17);
+
+    }
+    else{
+        printf("Unit not found: %s\n", sqlite3_errmsg(db));
+        return -3;
+    }
+
+    printf(" --------------------------\n");
+    printf(" | %*s |\n", -22, unit.name);
+    printf(" | ID: %*s |\n", -18, unit.id);
+    printf(" --------------------------\n");
+    printf(" | STAT | BASE   | CURR.  |\n");
+    printf(" --------------------------\n");
+    printf(" | HP:  | %*d  | %*d  |\n", 5, unit.base_hp, 5, unit.current_hp);
+    printf(" | ATK: | %*d  | %*d  |\n", 5, unit.base_atk, 5, unit.current_atk);
+    printf(" | DEF: | %*d  | %*d  |\n", 5, unit.base_def, 5, unit.current_def);
+    printf(" | SPD: | %*d  | %*d  |\n", 5, unit.base_spd, 5, unit.current_spd);
+    printf(" | CRR: | %*d\% | %*d\% |\n", 5, unit.base_crr, 5, unit.current_crr);
+    printf(" | CRD: | %*d\% | %*d\% |\n", 5, unit.base_crd, 5, unit.current_crd);
+    printf(" | RES: | %*d\% | %*d\% |\n", 5, unit.base_res, 5, unit.current_res);
+    printf(" | ACC: | %*d\% | %*d\% |\n", 5, unit.base_acc, 5, unit.current_acc);
+    printf(" --------------------------\n");
+
+    struct Stats min_stats;
+    // TODO: DEBUG: Read from parameters
+    min_stats.hp = unit.current_hp *1;
+    min_stats.atk = unit.current_atk *1;
+    min_stats.def = unit.current_def *1;
+    min_stats.spd = unit.current_spd *1;
+    min_stats.crr = unit.current_crr *1;
+    min_stats.crd = unit.current_crd *1;
+    min_stats.res = unit.current_res *1;
+    min_stats.acc = unit.current_acc *1;
+
+    // TODO: DEBUG: Read from parameters
+    int sets[3] = {RAGE, BLADE, 0};
+    // TODO: DEBUG: Read from parameters
+    int requested_stats[3] = {ATK_PERCENT, CRD, ATK_PERCENT};
+
+    // Calculate required rune count
+    struct Rune_Set_Count requested_set_count;
+    requested_set_count.energy = 0;
+    requested_set_count.guard = 0;
+    requested_set_count.swift = 0;
+    requested_set_count.blade = 0;
+    requested_set_count.rage = 0;
+    requested_set_count.focus = 0;
+    requested_set_count.endure = 0;
+    requested_set_count.fatal = 0;
+    requested_set_count.despair = 0;
+    requested_set_count.vampire = 0;
+    requested_set_count.violent = 0;
+    requested_set_count.nemesis = 0;
+    requested_set_count.will = 0;
+    requested_set_count.shield = 0;
+    requested_set_count.revenge = 0;
+    requested_set_count.destroy = 0;
+    requested_set_count.fight = 0;
+    requested_set_count.determination = 0;
+    requested_set_count.enhance = 0;
+    requested_set_count.accuracy = 0;
+    requested_set_count.tolerance = 0;
+    printf("Requested sets:\n");
+    for (int i = 0; i < 2; i ++){
+        switch (sets[i]){
+            case ENERGY:
+                printf("    - ENERGY\n");
+                requested_set_count.energy += 2;
+                break;
+            case GUARD:
+                printf("    - GUARD\n");
+                requested_set_count.guard += 2;
+                break;
+            case SWIFT:
+                printf("    - SWIFT\n");
+                requested_set_count.swift += 4;
+                break;
+            case BLADE:
+                printf("    - BLADE\n");
+                requested_set_count.blade += 2;
+                break;
+            case RAGE:
+                printf("    - RAGE\n");
+                requested_set_count.rage += 4;
+                break;
+            case FOCUS:
+                printf("    - FOCUS\n");
+                requested_set_count.focus += 2;
+                break;
+            case ENDURE:
+                printf("    - ENDURE\n");
+                requested_set_count.endure += 2;
+                break;
+            case FATAL:
+                printf("    - FATAL\n");
+                requested_set_count.fatal += 4;
+                break;
+            case DESPAIR:
+                printf("    - DESPAIR\n");
+                requested_set_count.despair += 2;
+                break;
+            case VAMPIRE:
+                printf("    - VAMPIRE\n");
+                requested_set_count.vampire += 4;
+                break;
+            case VIOLENT:
+                printf("    - VIOLENT\n");
+                requested_set_count.violent += 4;
+                break;
+            case NEMESIS:
+                printf("    - NEMESIS\n");
+                requested_set_count.nemesis += 2;
+                break;
+            case WILL:
+                printf("    - WILL\n");
+                requested_set_count.will += 2;
+                break;
+            case SHIELD:
+                printf("    - SHIELD\n");
+                requested_set_count.shield += 2;
+                break;
+            case REVENGE:
+                printf("    - REVENGE\n");
+                requested_set_count.revenge += 2;
+                break;
+            case DESTROY:
+                printf("    - DESTROY\n");
+                requested_set_count.destroy += 2;
+                break;
+            case FIGHT:
+                printf("    - FIGHT\n");
+                requested_set_count.fight += 2;
+                break;
+            case DETERMINATION:
+                printf("    - DETERMINATION\n");
+                requested_set_count.determination += 2;
+                break;
+            case ENHANCE:
+                printf("    - ENHANCE\n");
+                requested_set_count.enhance += 2;
+                break;
+            case ACCURACY:
+                printf("    - ACCURACY\n");
+                requested_set_count.accuracy += 2;
+                break;
+            case TOLERANCE:
+                printf("    - TOLERANCE\n");
+                requested_set_count.tolerance += 2;
+                break;
+        }
+    }
+
+    // TODO: Debug: Get this from parameters
+    int requested_level = 15;
+    char requested_level_column[] = "lv15_";
+
+    // Create queries for each slot
+    char query_odd[2500] = "SELECT id, unit, type, ";
+    strcat(query_odd, requested_level_column);
+    strcat(query_odd, "hp_flat, ");
+    strcat(query_odd, requested_level_column);
+    strcat(query_odd, "atk_flat, ");
+    strcat(query_odd, requested_level_column);
+    strcat(query_odd, "def_flat, ");
+    strcat(query_odd, requested_level_column);
+    strcat(query_odd, "hp_percent, ");
+    strcat(query_odd, requested_level_column);
+    strcat(query_odd, "atk_percent, ");
+    strcat(query_odd, requested_level_column);
+    strcat(query_odd, "def_percent, ");
+    strcat(query_odd, requested_level_column);
+    strcat(query_odd, "spd, ");
+    strcat(query_odd, requested_level_column);
+    strcat(query_odd, "crr, ");
+    strcat(query_odd, requested_level_column);
+    strcat(query_odd, "crd, ");
+    strcat(query_odd, requested_level_column);
+    strcat(query_odd, "res, ");
+    strcat(query_odd, requested_level_column);
+    strcat(query_odd, "acc FROM runes WHERE slot = ? AND type IN (");
+    char cur_set[2];
+    char stat_set[2];
+    if (sets[0] != 0){
+        sprintf(cur_set, "%d", sets[0]);
+        strcat(query_odd, cur_set);
+        strcat(query_odd, ", ");
+    }
+    if (sets[1] != 0){
+        sprintf(cur_set, "%d", sets[1]);
+        strcat(query_odd, cur_set);
+        strcat(query_odd, ", ");
+    }
+    if (sets[2] != 0){
+        sprintf(cur_set, "%d", sets[2]);
+        strcat(query_odd, cur_set);
+        strcat(query_odd, ", ");
+    }
+    strcat(query_odd, "-1) ");
+    // TODO: Add team stuff
+
+
+    //printf("- QUERY ODD: %s\n", query_odd);
+
+
+
+
+    char query_even[1500] = "SELECT id, unit, type, ";
+    strcat(query_even, requested_level_column);
+    strcat(query_even, "hp_flat, ");
+    strcat(query_even, requested_level_column);
+    strcat(query_even, "atk_flat, ");
+    strcat(query_even, requested_level_column);
+    strcat(query_even, "def_flat, ");
+    strcat(query_even, requested_level_column);
+    strcat(query_even, "hp_percent, ");
+    strcat(query_even, requested_level_column);
+    strcat(query_even, "atk_percent, ");
+    strcat(query_even, requested_level_column);
+    strcat(query_even, "def_percent, ");
+    strcat(query_even, requested_level_column);
+    strcat(query_even, "spd, ");
+    strcat(query_even, requested_level_column);
+    strcat(query_even, "crr, ");
+    strcat(query_even, requested_level_column);
+    strcat(query_even, "crd, ");
+    strcat(query_even, requested_level_column);
+    strcat(query_even, "res, ");
+    strcat(query_even, requested_level_column);
+    strcat(query_even, "acc FROM runes WHERE slot = ? AND type IN (");
+    if (sets[0] != 0){
+        sprintf(cur_set, "%d", sets[0]);
+        strcat(query_even, cur_set);
+        strcat(query_even, ", ");
+    }
+    if (sets[1] != 0){
+        sprintf(cur_set, "%d", sets[1]);
+        strcat(query_even, cur_set);
+        strcat(query_even, ", ");
+    }
+    if (sets[2] != 0){
+        sprintf(cur_set, "%d", sets[2]);
+        strcat(query_even, cur_set);
+        strcat(query_even, ", ");
+    }
+    strcat(query_even, "-1) AND main_stat IN (");
+
+    if (requested_stats[0] != 0){
+        sprintf(stat_set, "%d", requested_stats[0]);
+        strcat(query_even, stat_set);
+        strcat(query_even, ", ");
+    }
+    if (requested_stats[1] != 0){
+        sprintf(stat_set, "%d", requested_stats[1]);
+        strcat(query_even, stat_set);
+        strcat(query_even, ", ");
+    }
+    if (requested_stats[2] != 0){
+        sprintf(stat_set, "%d", requested_stats[2]);
+        strcat(query_even, stat_set);
+        strcat(query_even, ", ");
+    }
+
+    strcat(query_even, "-1) ");
+    // TODO: Add team stuff
+
+
+
+    int rune_count[7];
+    /*char query_even_count[1500] = "SELECT count(*) AS c FROM(";
+    strcat(query_even_count, query_even);
+    strcat(query_even_count, ")");
+    char query_odd_count[1500] = "SELECT count(*) AS c FROM(";
+    strcat(query_odd_count, query_odd);
+    strcat(query_odd_count, ")");
+
+    sqlite3_stmt *rune_counts[7];
+
+    db_status = sqlite3_prepare_v2(db, query_odd_count, -1, &rune_counts[1], 0);
+    if (db_status != SQLITE_OK) {
+        printf("Error counting runes for slot 1: %s\n", sqlite3_errmsg(db));
+        return -6;
+    }
+    sqlite3_bind_int(rune_counts[1], 1, 1);
+    db_status = sqlite3_prepare_v2(db, query_odd_count, -1, &rune_counts[3], 0);
+    if (db_status != SQLITE_OK) {
+        printf("Error counting runes for slot 3: %s\n", sqlite3_errmsg(db));
+        return -6;
+    }
+    sqlite3_bind_int(rune_counts[3], 1, 3);
+    db_status = sqlite3_prepare_v2(db, query_odd_count, -1, &rune_counts[5], 0);
+    if (db_status != SQLITE_OK) {
+        printf("Error counting runes for slot 5: %s\n", sqlite3_errmsg(db));
+        return -6;
+    }
+    sqlite3_bind_int(rune_counts[5], 1, 5);
+    db_status = sqlite3_prepare_v2(db, query_even_count, 2500, &rune_counts[2], 0);
+    if (db_status != SQLITE_OK) {
+        printf("Error counting runes for slot 2: %s\n", sqlite3_errmsg(db));
+        return -6;
+    }
+    sqlite3_bind_int(rune_counts[2], 1, 2);
+    db_status = sqlite3_prepare_v2(db, query_even_count, 2500, &rune_counts[4], 0);
+    if (db_status != SQLITE_OK) {
+        printf("Error counting runes for slot 4: %s\n", sqlite3_errmsg(db));
+        return -6;
+    }
+    sqlite3_bind_int(rune_counts[4], 1, 4);
+    db_status = sqlite3_prepare_v2(db, query_even_count, -1, &rune_counts[6], 0);
+    if (db_status != SQLITE_OK) {
+        printf("Error counting runes for slot 6: %s\n", sqlite3_errmsg(db));
+        return -6;
+    }
+    sqlite3_bind_int(rune_counts[6], 1, 6);
+
+    int max_rune_count = 0;
+    for (int i = 1; i < 7; i ++){
+        int step = sqlite3_step(rune_counts[i]);
+        if (step == SQLITE_ROW) {
+            printf("  - Available runes in slot %d: %d\n", i, sqlite3_column_int(rune_counts[i], 0));
+            if (sqlite3_column_int(rune_counts[i], 0) == 0){
+                printf("  - No availbale runes for slot %d\n", i);
+                return 1;
+            }
+            else{
+                rune_count[i] = sqlite3_column_int(rune_counts[i], 0);
+                if (rune_count[i] > max_rune_count){
+                    max_rune_count = rune_count[i];
+                }
+            }
+        }
+    }*/
+
+    sqlite3_stmt *stmt_runes[7];
+    struct Rune runes[7][600];
+    db_status = sqlite3_prepare_v2(db, query_odd, -1, &stmt_runes[1], 0);
+    if (db_status != SQLITE_OK) {
+        printf("Error getting runes for slot 1: %s\n", sqlite3_errmsg(db));
+        return -7;
+    }
+    sqlite3_bind_int(stmt_runes[1], 1, 1);
+    db_status = sqlite3_prepare_v2(db, query_odd, -1, &stmt_runes[3], 0);
+    if (db_status != SQLITE_OK) {
+        printf("Error getting runes for slot 3: %s\n", sqlite3_errmsg(db));
+        return -7;
+    }
+    sqlite3_bind_int(stmt_runes[3], 1, 3);
+    db_status = sqlite3_prepare_v2(db, query_odd, -1, &stmt_runes[5], 0);
+    if (db_status != SQLITE_OK) {
+        printf("Error getting runes for slot 5: %s\n", sqlite3_errmsg(db));
+        return -7;
+    }
+    sqlite3_bind_int(stmt_runes[5], 1, 5);
+    db_status = sqlite3_prepare_v2(db, query_odd, -1, &stmt_runes[2], 0);
+    if (db_status != SQLITE_OK) {
+        printf("Error getting runes for slot 2: %s\n", sqlite3_errmsg(db));
+        return -7;
+    }
+    sqlite3_bind_int(stmt_runes[2], 1, 2);
+    db_status = sqlite3_prepare_v2(db, query_odd, -1, &stmt_runes[4], 0);
+    if (db_status != SQLITE_OK) {
+        printf("Error getting runes for slot 4: %s\n", sqlite3_errmsg(db));
+        return -7;
+    }
+    sqlite3_bind_int(stmt_runes[4], 1, 4);
+    db_status = sqlite3_prepare_v2(db, query_odd, -1, &stmt_runes[6], 0);
+    if (db_status != SQLITE_OK) {
+        printf("Error getting runes for slot 6: %s\n", sqlite3_errmsg(db));
+        return -7;
+    }
+    sqlite3_bind_int(stmt_runes[6], 1, 6);
+
+
+    // Get and populate all the runes
+    for (int i = 1; i < 7; i ++){
+        int j = 0;
+        //printf("BEGIN SLOT %d\n", i);
+        while (1 == 1){
+            int status = sqlite3_step(stmt_runes[i]);
+            //printf("STATUS:  %d   ", status);
+            if (status == SQLITE_ROW){
+                //printf("  - (%d) Slot %d, Rune ID %s\n", j, i, sqlite3_column_text(stmt_runes[i], 0));
+                strcpy(runes[i][j].id, sqlite3_column_text(stmt_runes[i], 0));
+                strcpy(runes[i][j].unit, sqlite3_column_text(stmt_runes[i], 1));
+                runes[i][j].set = sqlite3_column_int(stmt_runes[i], 2);
+                runes[i][j].hp_flat = sqlite3_column_int(stmt_runes[i], 3);
+                runes[i][j].atk_flat = sqlite3_column_int(stmt_runes[i], 4);
+                runes[i][j].def_flat = sqlite3_column_int(stmt_runes[i], 5);
+                runes[i][j].hp_percent = sqlite3_column_int(stmt_runes[i], 6);
+                runes[i][j].atk_percent = sqlite3_column_int(stmt_runes[i], 7);
+                runes[i][j].def_percent = sqlite3_column_int(stmt_runes[i], 8);
+                runes[i][j].spd = sqlite3_column_int(stmt_runes[i], 9);
+                runes[i][j].crr = sqlite3_column_int(stmt_runes[i], 10);
+                runes[i][j].crd = sqlite3_column_int(stmt_runes[i], 11);
+                runes[i][j].res = sqlite3_column_int(stmt_runes[i], 12);
+                runes[i][j].acc = sqlite3_column_int(stmt_runes[i], 13);
+                j ++;
+            }
+            else{
+                break;
+            }
+        }
+
+        rune_count[i] = j;
+    }
+
+    for (int i = 1; i < 7; i ++){
+        printf("  - Available runes in slot %d: %d\n", i, rune_count[i]);
+        if (rune_count[i] == 0){
+            printf("  - No availbale runes for slot %d\n", i);
+            return 1;
+        }
+    }
+    unsigned long max_combinations =
+      rune_count[1] *
+      rune_count[2] *
+      rune_count[3] *
+      rune_count[4] *
+      rune_count[5] *
+      rune_count[6];
+    printf("  - Combinations to try: %d\n", max_combinations);
+
+    // Now its time to loop all 6 reels of runes and try to match combos
+    int index[7] = {0, 0, 0, 0, 0, 0};
+    unsigned long tested_combinations = 0;
+    unsigned long valid_sets = 0;
+    unsigned long result_count = 0;
+    Result results[1000];
+    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]
+    ){
+        if (tested_combinations % 10000000 == 0 && tested_combinations != 0){
+            printf("10M loops: TOTAL: %d\n", tested_combinations);
+        }
+        //printf("loop %d\n", tested_combinations);
+        struct Rune_Set_Count set_count;
+        set_count.energy = 0;
+        set_count.guard = 0;
+        set_count.swift = 0;
+        set_count.blade = 0;
+        set_count.rage = 0;
+        set_count.focus = 0;
+        set_count.endure = 0;
+        set_count.fatal = 0;
+        set_count.despair = 0;
+        set_count.vampire = 0;
+        set_count.violent = 0;
+        set_count.nemesis = 0;
+        set_count.will = 0;
+        set_count.shield = 0;
+        set_count.revenge = 0;
+        set_count.destroy = 0;
+        set_count.fight = 0;
+        set_count.determination = 0;
+        set_count.enhance = 0;
+        set_count.accuracy = 0;
+        set_count.tolerance = 0;
+        for (int i = 1; i < 7; i ++){
+            switch (runes[i][index[i]].set){
+                case ENERGY:
+                    set_count.energy ++;
+                    break;
+                case GUARD:
+                    set_count.guard ++;
+                    break;
+                case SWIFT:
+                    set_count.swift ++;
+                    break;
+                case BLADE:
+                    set_count.blade ++;
+                    break;
+                case RAGE:
+                    set_count.rage ++;
+                    break;
+                case FOCUS:
+                    set_count.focus ++;
+                    break;
+                case ENDURE:
+                    set_count.endure ++;
+                    break;
+                case FATAL:
+                    set_count.fatal ++;
+                    break;
+                case DESPAIR:
+                    set_count.despair ++;
+                    break;
+                case VAMPIRE:
+                    set_count.vampire ++;
+                    break;
+                case VIOLENT:
+                    set_count.violent ++;
+                    break;
+                case NEMESIS:
+                    set_count.nemesis ++;
+                    break;
+                case WILL:
+                    set_count.will ++;
+                    break;
+                case SHIELD:
+                    set_count.shield ++;
+                    break;
+                case REVENGE:
+                    set_count.revenge ++;
+                    break;
+                case DESTROY:
+                    set_count.destroy ++;
+                    break;
+                case FIGHT:
+                    set_count.fight ++;
+                    break;
+                case DETERMINATION:
+                    set_count.determination ++;
+                    break;
+                case ENHANCE:
+                    set_count.enhance ++;
+                    break;
+                case ACCURACY:
+                    set_count.accuracy ++;
+                    break;
+                case TOLERANCE:
+                    set_count.tolerance ++;
+                    break;
+            }
+        }
+        // Compare with requested sets
+        if (
+            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
+        ){
+            valid_sets ++;
+            //printf("Valid set found: TOTAL: %d\n", 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;
+            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.atk += unit.base_hp * runes[i][index[i]].atk_percent / 100;
+                stats.def += unit.base_hp * 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;
+            }
+            // Compare with minimum requeriments
+            if (
+                stats.hp >= min_stats.hp &&
+                stats.atk >= min_stats.atk &&
+                stats.def >= min_stats.def &&
+                stats.spd >= min_stats.spd &&
+                stats.crr >= min_stats.crr &&
+                stats.crd >= min_stats.crd &&
+                stats.res >= min_stats.res &&
+                stats.acc >= min_stats.acc
+            ){
+                for (int i = 1; i < 7; i ++)
+                strcpy(results[result_count].rune_ids[i - 1], runes[i][index[i]].id);
+                result_count ++;
+                //printf("Result found: %d\n", results);
+            }
+            results[result_count].rating = 0;
+            results[result_count].rating += ((stats.hp - unit.current_hp) / 15);
+            results[result_count].rating += (stats.atk - unit.current_atk);
+            results[result_count].rating += (stats.def - unit.current_def);
+            results[result_count].rating += (stats.spd - unit.current_spd);
+            results[result_count].rating += (stats.crr - unit.current_crr);
+            results[result_count].rating += (stats.crd - unit.current_crd);
+            results[result_count].rating += (stats.res - unit.current_res);
+            results[result_count].rating += (stats.acc - unit.current_acc);
+        }
+        else{
+            //printf("NO valid set found: TOTAL: %d\n", valid_sets);
+        }
+
+
+
+
+        // Loop action
+        // First, form a set and check if mathces the requested;
+
+
+
+
+
+
+        // Loop control
+        //printf("  - Looping index 6: %d / %d\n", index[6], rune_count[6]);
+        tested_combinations ++;
+        index[6] ++;
+        if (index[6] == rune_count[6]){
+           //printf("  - Looping index 5: %d / %d\n", index[5], rune_count[5]);
+            index[6] = 0;
+            index[5] ++;
+        }
+        if (index[5] == rune_count[5]){
+            //printf("  - Looping index 4: %d / %d\n", index[4], rune_count[4]);
+            index[5] = 0;
+            index[4] ++;
+        }
+        if (index[4] == rune_count[4]){
+            //printf("  - Looping index 3: %d / %d\n", index[3], rune_count[3]);
+            index[4] = 0;
+            index[3] ++;
+        }
+        if (index[3] == rune_count[3]){
+            //printf("  - Looping index 2: %d / %d\n", index[2], rune_count[2]);
+            index[3] = 0;
+            index[2] ++;
+        }
+        if (index[2] == rune_count[2]){
+            //printf("  - Looping index 1: %d / %d\n", index[1], rune_count[1]);
+            index[2] = 0;
+            index[1] ++;
+        }
+
+        /*printf("  - CHECK index 1: %d / %d\n", index[1], rune_count[1]);
+        printf("  - CHECK index 2: %d / %d\n", index[2], rune_count[2]);
+        printf("  - CHECK index 3: %d / %d\n", index[3], rune_count[3]);
+        printf("  - CHECK index 4: %d / %d\n", index[4], rune_count[4]);
+        printf("  - CHECK index 5: %d / %d\n", index[5], rune_count[5]);
+        printf("  - CHECK index 6: %d / %d\n", index[6], rune_count[6]);*/
+    }
+    printf("Valid sets found: TOTAL: %d\n", valid_sets);
+    printf("Results found: TOTAL: %d\n", result_count);
+
+//"base_hp, base_atk, base_def, base_spd, base_crr, base_crd, base_res, base_acc, "
+//      "current_hp, current_atk, current_def, current_spd, current_crr, current_crd, current_res, current_acc "
+//      "FROM units WHERE id = ? OR name = ?";
+
+    printf("ENDING\n");
+
+    sqlite3_finalize(res);
+    sqlite3_close(db);
+
+    /*
+
+    rc = sqlite3_exec(db, sql, callback, 0, &err_msg);
+
+    if (rc != SQLITE_OK ) {
+
+        fprintf(stderr, "Failed to select data\n");
+        fprintf(stderr, "SQL error: %s\n", err_msg);
+
+        sqlite3_free(err_msg);
+        sqlite3_close(db);
+
+        return 1;
+    }
+
+    sqlite3_close(db);
+
+    */
+    return 0;
+}
+
+int unit_callback(void *NotUsed, int argc, char **argv, char **azColName) {
+
+    NotUsed = 0;
+
+    for (int i = 0; i < argc; i++) {
+
+        printf("%s = %s\n", azColName[i], argv[i] ? argv[i] : "NULL");
+    }
+
+    printf("\n");
+
+    return 0;
+}
+
+int md_comparator(const void *v1, const void *v2){
+    const Result *p1 = (Result *)v1;
+    const Result *p2 = (Result *)v2;
+    if (p1->rating < p2->rating)
+        return -1;
+    else if (p1->rating > p2->rating)
+        return +1;
+    else
+        return 0;
+}