Bladeren bron

Teams and units can be excluded from the optimization.

Iñigo Valentin 4 jaren geleden
bovenliggende
commit
e6991fcfec

+ 36 - 34
src/RuneOptimizer/help/help.c

@@ -41,39 +41,41 @@ void show_help(){
     printf("    RuneOptimizer optimize [unit] [options]\n");
     printf("\n      [unit] can be a unit ID or a unit name (case sensitive)\n");
     printf("\n      Options: \n\n");
-    printf("        -h | --min_hp <NUM>         Minumum HP to consider in the optimization.\n");
-    printf("                                    It defaults to the unit's current value.\n");
-    printf("        -a | --min_atk <NUM>        Minumum ATK to consider in the optimization.\n");
-    printf("                                    It defaults to the unit's current value.\n");
-    printf("        -d | --min_def <NUM>        Minumum DEF to consider in the optimization.\n");
-    printf("                                    It defaults to the unit's current value.\n");
-    printf("        -s | --min_spd <NUM>        Minumum SPD to consider in the optimization.\n");
-    printf("                                    It defaults to the unit's current value.\n");
-    printf("        -c | --min_crr <NUM>        Minumum CRIT RATE to consider in the optimization.\n");
-    printf("                                    It defaults to the unit's current value.\n");
-    printf("        -d | --min_crd <NUM>        Minumum CRIT DAMAGE to consider in the optimization.\n");
-    printf("                                    It defaults to the unit's current value.\n");
-    printf("        -r | --min_res <NUM>        Minumum RES to consider in the optimization.\n");
-    printf("                                    It defaults to the unit's current value.\n");
-    printf("        -f | --min_acc <NUM>        Minumum ACC to consider in the optimization.\n");
-    printf("                                    It defaults to the unit's current value.\n");
-    printf("        -p | --min_ehp <NUM>        Minumum effective HP to consider in the optimization.\n");
-    printf("                                    It defaults to 0.\n");
-    printf("        -m | --min_dmg <NUM>        Minumum computed damage to consider in the optimization.\n");
-    printf("                                    It defaults to 0.\n");
-    printf("        -l | --level <LV>           Level to consider the runes during the optimization.\n");
-    printf("                                    It only affects the rune main stats. Valid values are\n");
-    printf("                                    'current', '12' and '15'. Default is 'current'\n");
-    printf("        -t | --stats <ST1>,<ST2>... Stats than can be selected as mains for slots 2, 4 and 6.\n");
-    printf("                                    Only the selected stats will be included, so this option\n");
-    printf("                                    is mandatory. Accepted values are 'hp', 'atk', 'def',\n");
-    printf("                                    'hpflat', 'atkflat', 'defflat', 'spd', 'crr', 'crd',\n");
-    printf("                                    'res' and 'acc'. Values must be comma-separated, and up\n");
-    printf("                                    to 12 can be included.\n");
-    printf("        -e | --sets <S1>,<S2>...    Rune sets that than can be considered during the optimization.\n");
-    printf("                                    Only the selected sets will be included, so this option is\n");
-    printf("                                    mandatory. Accepted values  the rune net names, lowercase.\n");
-    printf("                                    Values must be comma-separated, and up to 3 can be included.\n");
-    printf("        -g | --gui                  Formats the output to be consumed by the GUI.\n");
+    printf("        -h | --min_hp <NUM>          Minumum HP to consider in the optimization.\n");
+    printf("                                     It defaults to the unit's current value.\n");
+    printf("        -a | --min_atk <NUM>         Minumum ATK to consider in the optimization.\n");
+    printf("                                     It defaults to the unit's current value.\n");
+    printf("        -d | --min_def <NUM>         Minumum DEF to consider in the optimization.\n");
+    printf("                                     It defaults to the unit's current value.\n");
+    printf("        -s | --min_spd <NUM>         Minumum SPD to consider in the optimization.\n");
+    printf("                                     It defaults to the unit's current value.\n");
+    printf("        -c | --min_crr <NUM>         Minumum CRIT RATE to consider in the optimization.\n");
+    printf("                                     It defaults to the unit's current value.\n");
+    printf("        -d | --min_crd <NUM>         Minumum CRIT DAMAGE to consider in the optimization.\n");
+    printf("                                     It defaults to the unit's current value.\n");
+    printf("        -r | --min_res <NUM>         Minumum RES to consider in the optimization.\n");
+    printf("                                     It defaults to the unit's current value.\n");
+    printf("        -f | --min_acc <NUM>         Minumum ACC to consider in the optimization.\n");
+    printf("                                     It defaults to the unit's current value.\n");
+    printf("        -p | --min_ehp <NUM>         Minumum effective HP to consider in the optimization.\n");
+    printf("                                     It defaults to 0.\n");
+    printf("        -m | --min_dmg <NUM>         Minumum computed damage to consider in the optimization.\n");
+    printf("                                     It defaults to 0.\n");
+    printf("        -l | --level <LV>            Level to consider the runes during the optimization.\n");
+    printf("                                     It only affects the rune main stats. Valid values are\n");
+    printf("                                     'current', '12' and '15'. Default is 'current'\n");
+    printf("        -t | --stats <ST1>,<ST2>...  Stats than can be selected as mains for slots 2, 4 and 6.\n");
+    printf("                                     Only the selected stats will be included, so this option\n");
+    printf("                                     is mandatory. Accepted values are 'hp', 'atk', 'def',\n");
+    printf("                                     'hpflat', 'atkflat', 'defflat', 'spd', 'crr', 'crd',\n");
+    printf("                                     'res' and 'acc'. Values must be comma-separated, and up\n");
+    printf("                                     to 12 can be included.\n");
+    printf("        -e | --sets <S1>,<S2>...     Rune sets that than can be considered during the optimization.\n");
+    printf("        -o | --storage               Use only runes not assigned to units.\n");
+    printf("        -x | --no-teams <T1>,<T2>... Exclude runes assigned to units in selected teams.\n");
+    printf("                                     Team IDs can be supplied, comma-separated.\n");
+    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");
     return;
 }

+ 265 - 46
src/RuneOptimizer/optimize/optimize.c

@@ -29,18 +29,24 @@
  * @return SUCCESS or an error code.
  */
 int parse_optimization_arguments(
-  int argc,  char *argv[], char id[64],             char *level,
-  int *sets, int *stats,   struct Stats *min_stats, char *gui
-
+  int argc,  char argv[][128], char id[64],             char *level,
+  int *sets, int *stats,   struct Stats *min_stats, char *gui,
+  char *storage, char excluded_teams[64][64], char excluded_units[64][64]
 ){
+
     // Get unit identifier
-    if (argc < 3){
+    if (argc < 1){
         fprintf(stderr, "No unit specified for optimization\n");
         return ERROR_INPUT_NO_UNIT;
     }
-    strcpy(id, argv[2]);
+    strcpy(id, argv[0]);
+
+    // Assign default values for non-value arguments
+    *storage = 0;
+    *gui = 0;
+
     // Loop command line arguments
-    for (int i = 3; i < argc; i ++){
+    for (int i = 1; i < argc; i ++){
 
         // Rune level arguments
         if (strcmp("--level", argv[i]) == 0 || strcmp("-l", argv[i]) == 0){
@@ -76,6 +82,68 @@ int parse_optimization_arguments(
             }
         }
 
+        // Excluded teams
+        else if (
+          strcmp("--no-teams", argv[i]) == 0 || strcmp("-x", argv[i]) == 0
+        ){
+            if (i < argc - 1){
+                // Separate string by commas
+                int j = 0;
+                // Returns first token
+                char opt_list[64];
+                strcpy(opt_list, argv[i + 1]);
+                char *token = strtok(opt_list, ",");
+
+                // Keep printing tokens while one of the
+                // delimiters present in the list, or until its complete
+                while (token != NULL && j < 3){
+                    strcpy(excluded_teams[j], token);
+                    token = strtok(NULL, ",");
+                    j ++;
+                }
+                // Advance one position in argument reading
+                i ++;
+            }
+            else{
+                fprintf(
+                  stderr,
+                  "Argument %s requires a comma-separated list of values.\n",
+                  argv[i]
+                );
+                return ERROR_INPUT_NO_SET;
+            }
+        }
+
+        // Excluded units
+        else if (
+          strcmp("--no-units", argv[i]) == 0 || strcmp("-u", argv[i]) == 0
+        ){
+            if (i < argc - 1){
+                // Separate string by commas
+                int j = 0;
+                // Returns first token
+                char *token = strtok(argv[i + 1], ",");
+
+                // Keep printing tokens while one of the
+                // delimiters present in the list, or until its complete
+                while (token != NULL && j < 3){
+                    strcpy(excluded_units[j], token);
+                    token = strtok(NULL, ",");
+                    j ++;
+                }
+                // Advance one position in argument reading
+                i ++;
+            }
+            else{
+                fprintf(
+                  stderr,
+                  "Argument %s requires a comma-separated list of values.\n",
+                  argv[i]
+                );
+                return ERROR_INPUT_NO_SET;
+            }
+        }
+
         // Rune sets argument
         else if (strcmp("--sets", argv[i]) == 0 || strcmp("-e", argv[i]) == 0){
             if (i < argc - 1){
@@ -163,7 +231,7 @@ int parse_optimization_arguments(
             else{
                 fprintf(
                   stderr,
-                  "Argument %s requires a list of values separated by commas.\n",
+                  "Argument %s requires a comma-separated list of values.\n",
                   argv[i]
                 );
                 return ERROR_INPUT_NO_SET;
@@ -225,13 +293,19 @@ int parse_optimization_arguments(
                 i ++;
             }
             else{
-                fprintf(stderr, "Argument %s requires a list of values separated by commas.\n", argv[i]);
+                fprintf(
+                  stderr,
+                  "Argument %s requires a comma-separated list of values.\n",
+                  argv[i]
+                );
                 return ERROR_INPUT_NO_STAT;
             }
         }
 
         // Minimum stats arguments.
-        else if (strcmp("--min-hp", argv[i]) == 0 || strcmp("-h", argv[i]) == 0){
+        else if (
+          strcmp("--min-hp", argv[i]) == 0 || strcmp("-h", argv[i]) == 0
+        ){
             if (i < argc - 1){
                 unsigned short stat_tmp = atoi(argv[i + 1]);
                 if (stat_tmp == 1){
@@ -242,11 +316,15 @@ int parse_optimization_arguments(
                 i ++;
             }
             else{
-                fprintf(stderr, "Argument %s requires a numeric value.\n", argv[i]);
+                fprintf(
+                  stderr, "Argument %s requires a numeric value.\n", argv[i]
+                );
                 return ERROR_INPUT_NO_HP;
             }
         }
-        else if (strcmp("--min-atk", argv[i]) == 0 || strcmp("-a", argv[i]) == 0){
+        else if (
+          strcmp("--min-atk", argv[i]) == 0 || strcmp("-a", argv[i]) == 0
+        ){
             if (i < argc - 1){
                 unsigned short stat_tmp = atoi(argv[i + 1]);
                 if (stat_tmp == 1){
@@ -257,11 +335,15 @@ int parse_optimization_arguments(
                 i ++;
             }
             else{
-                fprintf(stderr, "Argument %s requires a numeric value.\n", argv[i]);
+                fprintf(
+                  stderr, "Argument %s requires a numeric value.\n", argv[i]
+                );
                 return ERROR_INPUT_NO_ATK;
             }
         }
-        else if (strcmp("--min-def", argv[i]) == 0 || strcmp("-d", argv[i]) == 0){
+        else if (
+          strcmp("--min-def", argv[i]) == 0 || strcmp("-d", argv[i]) == 0
+        ){
             if (i < argc - 1){
                 unsigned short stat_tmp = atoi(argv[i + 1]);
                 if (stat_tmp == 1){
@@ -272,11 +354,15 @@ int parse_optimization_arguments(
                 i ++;
             }
             else{
-                fprintf(stderr, "Argument %s requires a numeric value.\n", argv[i]);
+                fprintf(
+                  stderr, "Argument %s requires a numeric value.\n", argv[i]
+                );
                 return ERROR_INPUT_NO_DEF;
             }
         }
-        else if (strcmp("--min-spd", argv[i]) == 0 || strcmp("-s", argv[i]) == 0){
+        else if (
+          strcmp("--min-spd", argv[i]) == 0 || strcmp("-s", argv[i]) == 0
+        ){
             if (i < argc - 1){
                 unsigned short stat_tmp = atoi(argv[i + 1]);
                 if (stat_tmp == 1){
@@ -287,11 +373,15 @@ int parse_optimization_arguments(
                 i ++;
             }
             else{
-                fprintf(stderr, "Argument %s requires a numeric value.\n", argv[i]);
+                fprintf(
+                  stderr, "Argument %s requires a numeric value.\n", argv[i]
+                );
                 return ERROR_INPUT_NO_SPD;
             }
         }
-        else if (strcmp("--min-crr", argv[i]) == 0 || strcmp("-c", argv[i]) == 0){
+        else if (
+          strcmp("--min-crr", argv[i]) == 0 || strcmp("-c", argv[i]) == 0
+        ){
             if (i < argc - 1){
                 unsigned short stat_tmp = atoi(argv[i + 1]);
                 if (stat_tmp == 1){
@@ -305,11 +395,15 @@ int parse_optimization_arguments(
                 i ++;
             }
             else{
-                fprintf(stderr, "Argument %s requires a numeric value.\n", argv[i]);
+                fprintf(
+                  stderr, "Argument %s requires a numeric value.\n", argv[i]
+                );
                 return ERROR_INPUT_NO_CRR;
             }
         }
-        else if (strcmp("--min-crd", argv[i]) == 0 || strcmp("-d", argv[i]) == 0){
+        else if (
+          strcmp("--min-crd", argv[i]) == 0 || strcmp("-d", argv[i]) == 0
+        ){
             if (i < argc - 1){
                 unsigned short stat_tmp = atoi(argv[i + 1]);
                 if (stat_tmp == 1){
@@ -320,11 +414,15 @@ int parse_optimization_arguments(
                 i ++;
             }
             else{
-                fprintf(stderr, "Argument %s requires a numeric value.\n", argv[i]);
+                fprintf(
+                  stderr, "Argument %s requires a numeric value.\n", argv[i]
+                );
                 return ERROR_INPUT_NO_CRD;
             }
         }
-        else if (strcmp("--min-res", argv[i]) == 0 || strcmp("-r", argv[i]) == 0){
+        else if (
+          strcmp("--min-res", argv[i]) == 0 || strcmp("-r", argv[i]) == 0
+        ){
             if (i < argc - 1){
                 unsigned short stat_tmp = atoi(argv[i + 1]);
                 if (stat_tmp == 1){
@@ -338,11 +436,15 @@ int parse_optimization_arguments(
                 i ++;
             }
             else{
-                fprintf(stderr, "Argument %s requires a numeric value.\n", argv[i]);
+                fprintf(
+                  stderr, "Argument %s requires a numeric value.\n", argv[i]
+                );
                 return ERROR_INPUT_NO_RES;
             }
         }
-        else if (strcmp("--min-acc", argv[i]) == 0 || strcmp("-f", argv[i]) == 0){
+        else if (
+          strcmp("--min-acc", argv[i]) == 0 || strcmp("-f", argv[i]) == 0
+        ){
             if (i < argc - 1){
                 unsigned short stat_tmp = atoi(argv[i + 1]);
                 if (stat_tmp == 1){
@@ -356,11 +458,15 @@ int parse_optimization_arguments(
                 i ++;
             }
             else{
-                fprintf(stderr, "Argument %s requires a numeric value.\n", argv[i]);
+                fprintf(
+                  stderr, "Argument %s requires a numeric value.\n", argv[i]
+                );
                 return ERROR_INPUT_NO_ACC;
             }
         }
-        else if (strcmp("--min-ehp", argv[i]) == 0 || strcmp("-p", argv[i]) == 0){
+        else if (
+          strcmp("--min-ehp", argv[i]) == 0 || strcmp("-p", argv[i]) == 0
+        ){
             if (i < argc - 1){
                 unsigned int stat_tmp = atoi(argv[i + 1]);
                 if (stat_tmp == 1){
@@ -371,11 +477,15 @@ int parse_optimization_arguments(
                 i ++;
             }
             else{
-                fprintf(stderr, "Argument %s requires a numeric value.\n", argv[i]);
+                fprintf(
+                  stderr, "Argument %s requires a numeric value.\n", argv[i]
+                );
                 return ERROR_INPUT_NO_EHP;
             }
         }
-        else if (strcmp("--min-dmg", argv[i]) == 0 || strcmp("-m", argv[i]) == 0){
+        else if (
+          strcmp("--min-dmg", argv[i]) == 0 || strcmp("-m", argv[i]) == 0
+        ){
             if (i < argc - 1){
                 unsigned short stat_tmp = atoi(argv[i + 1]);
                 if (stat_tmp == 1){
@@ -386,11 +496,18 @@ int parse_optimization_arguments(
                 i ++;
             }
             else{
-                fprintf(stderr, "Argument %s requires a numeric value.\n", argv[i]);
+                fprintf(
+                  stderr, "Argument %s requires a numeric value.\n", argv[i]
+                );
                 return ERROR_INPUT_NO_DMG;
             }
         }
-
+        // Storage option?
+        else if (
+          strcmp("--storage", argv[i]) == 0 || strcmp("-o", argv[i]) == 0
+        ){
+            *storage = 1;
+        }
         // GUI invoked?
         else if (strcmp("--gui", argv[i]) == 0 || strcmp("-g", argv[i]) == 0){
             *gui = 1;
@@ -454,7 +571,8 @@ int retrieveUnit(char id[64], struct Unit *unit){
     unit->base_res = sqlite3_column_int(res, 8);
     unit->base_acc = sqlite3_column_int(res, 9);
     unit->base_ehp = calculate_ehp(unit->base_hp, unit->base_def);
-    unit->base_dmg = calculate_dmg(unit->base_atk, unit->base_crr, unit->base_crd);
+    unit->base_dmg =
+      calculate_dmg(unit->base_atk, unit->base_crr, unit->base_crd);
     unit->current_hp = sqlite3_column_int(res, 10);
     unit->current_atk = sqlite3_column_int(res, 11);
     unit->current_def = sqlite3_column_int(res, 12);
@@ -464,7 +582,8 @@ int retrieveUnit(char id[64], struct Unit *unit){
     unit->current_res = sqlite3_column_int(res, 16);
     unit->current_acc = sqlite3_column_int(res, 17);
     unit->current_ehp = calculate_ehp(unit->current_hp, unit->current_def);
-    unit->current_dmg = calculate_dmg(unit->current_atk, unit->current_crr, unit->current_crd);
+    unit->current_dmg =
+      calculate_dmg(unit->current_atk, unit->current_crr, unit->current_crd);
 
     // Close db connection
     sqlite3_finalize(res);
@@ -602,9 +721,16 @@ char calculateRequiredSetCount(
  * @param[in] level Level to consider runes at.
  * @param[in] sets Requested sets.
  * @param[in] stats Requested sets for even slots.
+ * @param[in] excluded_teams List of teams whose unit's runes to exclude.
+ * @param[in] excluded_units List of units whose runes to exclude.
+ * @param[in] storage 1 to select only unassigned runes.
  * @param[out] query String with the query.
  */
-void createQueryForEvenSlots(char level, int* sets, int* stats, char query[1500]){
+void createQueryForEvenSlots(
+  char level, int* sets, int* stats,
+  char excluded_teams[64][64], char excluded_units[64][64],
+  char storage, char unit_id[64], char query[2500]
+){
     char column[10];
     if (level == 12) strcpy(column, "lv12_");
     else if (level == 15) strcpy(column, "lv15_");
@@ -661,8 +787,33 @@ void createQueryForEvenSlots(char level, int* sets, int* stats, char query[1500]
         }
     }
     strcat(query, "-1) ");
-    // TODO: Add team stuff
-    //printf("EVEN QUERY: %s\n", query);
+    if (storage == 1){
+        // They are not null, are empty!
+        strcat(query, " AND (unit = '' OR unit = '");
+        strcat(query, unit_id);
+        strcat(query, "') ");
+    }
+    // Excluded teams
+    strcat(query, " AND (unit = '' OR unit = '");
+    strcat(query, unit_id);
+    strcat(query, "' OR unit NOT IN (SELECT unit FROM units_teams WHERE team IN(");
+    for (int i = 0; i < 64 && excluded_teams[i][0] != '\0'; i ++){
+        strcat(query, "'");
+        strcat(query, excluded_teams[i]);
+        strcat(query, "',");
+    }
+    strcat(query, "'-1'))) ");
+    // Excluded units
+    strcat(query, " AND (unit = '' OR unit = '");
+    strcat(query, unit_id);
+    strcat(query, "' OR unit NOT IN (");
+    for (int i = 0; i < 64 && excluded_units[i][0] != '\0'; i ++){
+        strcat(query, "'");
+        strcat(query, excluded_units[i]);
+        strcat(query, "',");
+    }
+    strcat(query, "'-1')) ");
+    //printf("QUERY: %s\n", query);
     return;
 }
 
@@ -671,9 +822,17 @@ void createQueryForEvenSlots(char level, int* sets, int* stats, char query[1500]
  *
  * @param[in] level Level to consider runes at.
  * @param[in] sets Requested sets.
+ * @param[in] excluded_teams List of teams whose unit's runes to exclude.
+ * @param[in] excluded_units List of units whose runes to exclude.
+ * @param[in] storage 1 to select only unassigned runes.
+ * @param[in] unit_id ID of the unit being optimized.
  * @param[out] query String with the query.
  */
-void createQueryForOddSlots(char level, int* sets, char query[1500]){
+void createQueryForOddSlots(
+  char level, int* sets,
+  char excluded_teams[64][64], char excluded_units[64][64],
+  char storage, char unit_id[64], char query[2500]
+){
     char column[10];
     if (level == 12) strcpy(column, "lv12_");
     else if (level == 15) strcpy(column, "lv15_");
@@ -719,7 +878,33 @@ void createQueryForOddSlots(char level, int* sets, char query[1500]){
         strcat(query, ", ");
     }
     strcat(query, "-1) ");
-    // TODO: Add team stuff
+    if (storage == 1){
+        // They are not null, are empty!
+        strcat(query, " AND (unit = '' OR unit = '");
+        strcat(query, unit_id);
+        strcat(query, "') ");
+    }
+    // Excluded teams
+    strcat(query, " AND (unit = '' OR unit = '");
+    strcat(query, unit_id);
+    strcat(query, "' OR unit NOT IN (SELECT unit FROM units_teams WHERE team IN(");
+    for (int i = 0; i < 64 && excluded_teams[i][0] != '\0'; i ++){
+        strcat(query, "'");
+        strcat(query, excluded_teams[i]);
+        strcat(query, "',");
+    }
+    strcat(query, "'-1'))) ");
+    // Excluded units
+    strcat(query, " AND (unit = '' OR unit = '");
+    strcat(query, unit_id);
+    strcat(query, "' OR unit NOT IN (");
+    for (int i = 0; i < 64 && excluded_units[i][0] != '\0'; i ++){
+        strcat(query, "'");
+        strcat(query, excluded_units[i]);
+        strcat(query, "',");
+    }
+    strcat(query, "'-1')) ");
+    //printf("QUERY: %s\n", query);
     return;
 }
 
@@ -1193,10 +1378,20 @@ int optimize(int argc, char *argv[]){
 
     int status = SUCCESS;
 
+    // Create custom argument array
+    // If I don't do this, in the function parse_optimization_arguments,
+    // every 7th (index 6, index 15...) are missing. NULL.
+    // I don't know why. It's driving me crazy.
+    char args[argc - 2][128];
+    for (int i = 0; i < argc - 2; i ++){
+        strcpy(args[i], argv[i + 2]);
+    }
+
     // Initialize values for the data to be read form arguments.
     char id[64];
     char requested_level = 0;
     char gui = 0;
+    char storage = 0;
     int sets[3] = {0, 0, 0};
     int requested_stats[12] = {0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0};
     struct Stats min_stats;
@@ -1213,11 +1408,18 @@ int optimize(int argc, char *argv[]){
     min_stats.acc = 1;
     min_stats.ehp = 1;
     min_stats.dmg = 1;
+    char excluded_teams[64][64];
+    char excluded_units[64][64];
+    for (int i = 0; i < 128; i++){
+        excluded_teams[i][0] = '\0';
+        excluded_units[i][0] = '\0';
+    }
 
     // Parse arguments from the command line.
     status = parse_optimization_arguments(
-      argc, argv,            id,         &requested_level,
-      sets, requested_stats, &min_stats, &gui
+      argc - 2, args,            id,         &requested_level,
+      sets, requested_stats, &min_stats, &gui,
+      &storage, excluded_teams, excluded_units
     );
     if (SUCCESS != status){
         return status;
@@ -1249,14 +1451,19 @@ int optimize(int argc, char *argv[]){
     // Create queries for the database.
     char query_even[2500];
     char query_odd[2500];
-    createQueryForEvenSlots(requested_level, sets, requested_stats, query_even);
-    createQueryForOddSlots(requested_level, sets, query_odd);
+    createQueryForEvenSlots(
+      requested_level, sets, requested_stats, excluded_teams,
+      excluded_units, storage, id, query_even
+    );
+    createQueryForOddSlots(
+      requested_level, sets, excluded_teams,
+      excluded_units, storage, id, query_odd
+    );
 
     // Get runes from database.
     struct Rune runes[7][600];
-    unsigned int rune_count[7];
+    unsigned int rune_count[7] = {0, 0, 0, 0, 0, 0, 0};
     get_runes(query_even, query_odd, runes, rune_count);
-
     // If any slot doesn't have matching runes, we can stop now.
     for (int i = 1; i < 7; i ++){
         if (rune_count[i] == 0){
@@ -1289,7 +1496,10 @@ int optimize(int argc, char *argv[]){
 
     // Now its time to loop all 6 'reels' of runes and try to match combos
     if (gui != 1){
-        printf("\n\n__Optimization progress___________________________\n", max_combinations);
+        printf(
+          "\n\n__Optimization progress___________________________\n",
+          max_combinations
+        );
     }
     // Initialize arrys and some counters
     int index[7] = {0, 0, 0, 0, 0, 0};
@@ -1534,7 +1744,8 @@ int optimize(int argc, char *argv[]){
                 // One rating point per stat increase over current stats.
                 // Save for HP, with takes 15 for a raing point
                 results[result_count].rating = 0;
-                results[result_count].rating += ((stats.hp - unit.current_hp) / 15);
+                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);
@@ -1643,12 +1854,20 @@ unsigned int calculate_ehp(unsigned int hp, unsigned short def){
  * @param[in] crd CRD stat.
  * @return Calculated DMG.
  */
-unsigned short calculate_dmg(unsigned short atk, unsigned short crr, unsigned short crd){
+unsigned short calculate_dmg(
+  unsigned short atk, unsigned short crr, unsigned short crd
+){
     unsigned short dmg = 0;
     float crr_capped = (float) crr;
     if (crr_capped > 100.0f){
         crr_capped = 100.0f;
     }
-    dmg = ceil((((float) atk) * (100.0f - crr_capped) / 100.0f) + ((((float) atk) + (((float) atk) * ((float) crd) / 100.0f)) * crr_capped / 100.0f));
+    dmg = ceil(
+      (((float) atk) * (100.0f - crr_capped) / 100.0f) +
+      (
+        (((float) atk) + (((float) atk) * ((float) crd) / 100.0f)) *
+        crr_capped / 100.0f
+      )
+    );
     return dmg;
 }

+ 27 - 6
src/RuneOptimizer/optimize/optimize.h

@@ -157,13 +157,16 @@ char set_names[][24] = {
  * @param[out] sets List of requested sets.
  * @param[out] stats List of requested stats.
  * @param[out] min_stats Minimum stats for the optimization.
+ * @param[out] storage 1 to use only runes from storage.
+ * @param[in] excluded_teams List of teams whose unit's runes to exclude.
+ * @param[in] excluded_units List of units whose runes to exclude.
  * @param[out] gui 1 to format the output for the GUI
  * @return SUCCESS or an error code.
  */
 int parse_optimization_arguments(
-  int argc,  char *argv[], char id[64],             char *level,
-  int *sets, int *stats,   struct Stats *min_stats, char *gui
-
+  int argc,  char argv[][128], char id[64],             char *level,
+  int *sets, int *stats,   struct Stats *min_stats, char *gui,
+  char *storage, char excluded_teams[64][64], char excluded_units[64][64]
 );
 
 /**
@@ -194,18 +197,34 @@ char calculateRequiredSetCount(
  * @param[in] level Level to consider runes at.
  * @param[in] sets Requested sets.
  * @param[in] stats Requested sets for even slots.
+ * @param[in] excluded_teams List of teams whose unit's runes to exclude.
+ * @param[in] excluded_units List of units whose runes to exclude.
+ * @param[in] storage 1 to select only unassigned runes.
+ * @param[in] unit_id ID of the unit being optimized
  * @param[out] query String with the query.
  */
-void createQueryForEvenSlots(char level, int* sets, int* stats, char query[1500]);
+void createQueryForEvenSlots(
+  char level, int* sets, int* stats,
+  char excluded_teams[64][64], char excluded_units[64][64],
+  char storage, char unit_id[64], char query[2500]
+);
 
 /**
  * Generates the query to get the runes from the databas for odd slots.
  *
  * @param[in] level Level to consider runes at.
  * @param[in] sets Requested sets.
+ * @param[in] excluded_teams List of teams whose unit's runes to exclude.
+ * @param[in] excluded_units List of units whose runes to exclude.
+ * @param[in] storage 1 to select only unassigned runes.
+ * @param[in] unit_id ID of the unit being optimized
  * @param[out] query String with the query.
  */
-void createQueryForOddSlots(char level, int* sets, char query[1500]);
+void createQueryForOddSlots(
+  char level, int* sets,
+  char excluded_teams[64][64], char excluded_units[64][64],
+  char storage, char unit_id[64], char query[2500]
+);
 
 /**
  * Gets the list of runes to test during the optimization from the database.
@@ -302,4 +321,6 @@ unsigned int calculate_ehp(unsigned int hp, unsigned short def);
  * @param[in] crd CRD stat.
  * @return Calculated DMG.
  */
-unsigned short calculate_dmg(unsigned short atk, unsigned short crr, unsigned short crd);
+unsigned short calculate_dmg(
+  unsigned short atk, unsigned short crr, unsigned short crd
+);

+ 6 - 1
src/RuneOptimizer/team/team.c

@@ -51,7 +51,12 @@ int list_teams(int argc, char *argv[]){
     while (1 == 1){
         int status = sqlite3_step(stmt_teams);
         if (status == SQLITE_ROW){
-            printf(" | %*s | %*s | %*d |\n", 4, sqlite3_column_text(stmt_teams, 0), -32, sqlite3_column_text(stmt_teams, 1), 4, sqlite3_column_int(stmt_teams, 2));
+            printf(
+              " | %*s | %*s | %*d |\n",
+              4, sqlite3_column_text(stmt_teams, 0),
+              -32, sqlite3_column_text(stmt_teams, 1),
+              4, sqlite3_column_int(stmt_teams, 2)
+            );
 
         }
         else{