|
@@ -32,8 +32,10 @@
|
|
|
#include <math.h>
|
|
#include <math.h>
|
|
|
#include <stdint.h>
|
|
#include <stdint.h>
|
|
|
#include <getopt.h>
|
|
#include <getopt.h>
|
|
|
-#include <pthread.h>
|
|
|
|
|
|
|
+#include <threads.h>
|
|
|
#include <signal.h>
|
|
#include <signal.h>
|
|
|
|
|
+#include <stdbool.h>
|
|
|
|
|
+#include <stdint.h>
|
|
|
#include <time.h>
|
|
#include <time.h>
|
|
|
#include "../runeoptimizer.h"
|
|
#include "../runeoptimizer.h"
|
|
|
#include "../error/error.h"
|
|
#include "../error/error.h"
|
|
@@ -41,6 +43,9 @@
|
|
|
#include "optimize.h"
|
|
#include "optimize.h"
|
|
|
#include "output/output.h"
|
|
#include "output/output.h"
|
|
|
|
|
|
|
|
|
|
+#define likely(x) __builtin_expect(!!(x), 1)
|
|
|
|
|
+#define unlikely(x) __builtin_expect(!!(x), 0)
|
|
|
|
|
+
|
|
|
/**
|
|
/**
|
|
|
* Maximum arguments.
|
|
* Maximum arguments.
|
|
|
*
|
|
*
|
|
@@ -144,7 +149,7 @@ static int initialize_data(Optimizer_Data *data);
|
|
|
* @return {@link SUCCESS} if the unit info is loaded, or
|
|
* @return {@link SUCCESS} if the unit info is loaded, or
|
|
|
* {@link ERROR_DB_SELECT_UNIT} if the unit doesn't exist in the database.
|
|
* {@link ERROR_DB_SELECT_UNIT} if the unit doesn't exist in the database.
|
|
|
*/
|
|
*/
|
|
|
-static int read_unit(unsigned char id[UNIT_NAME_LEN], Unit *unit);
|
|
|
|
|
|
|
+static int read_unit(char *id, Unit *unit);
|
|
|
|
|
|
|
|
/**
|
|
/**
|
|
|
* Sets the default values for stat value filters.
|
|
* Sets the default values for stat value filters.
|
|
@@ -268,7 +273,7 @@ static int select_runes(
|
|
|
* @param[in,out] vargp Must be a Optimizer_Data pointer casted to void, where
|
|
* @param[in,out] vargp Must be a Optimizer_Data pointer casted to void, where
|
|
|
* the info will be read from and wrtitten to.
|
|
* the info will be read from and wrtitten to.
|
|
|
*/
|
|
*/
|
|
|
-static void *optimize_thread(void *vargp);
|
|
|
|
|
|
|
+static thrd_start_t optimize_thread(void *vargp);
|
|
|
|
|
|
|
|
/**
|
|
/**
|
|
|
* Sorts the result array.
|
|
* Sorts the result array.
|
|
@@ -293,19 +298,14 @@ static void sort_results(Result results[MAX_RESULTS], int total);
|
|
|
* @param set_count The set to check.
|
|
* @param set_count The set to check.
|
|
|
* @return {@link TRUE} if the set has any broken sets, {@link FALSE} otherwise.
|
|
* @return {@link TRUE} if the set has any broken sets, {@link FALSE} otherwise.
|
|
|
*/
|
|
*/
|
|
|
-static unsigned char contains_broken(Rune_Set_Count *set_count);
|
|
|
|
|
|
|
+__inline static bool contains_broken(Rune_Set_Count *set_count);
|
|
|
|
|
|
|
|
/**
|
|
/**
|
|
|
* Optimizer data package.
|
|
* Optimizer data package.
|
|
|
*
|
|
*
|
|
|
* Written by the threads.
|
|
* Written by the threads.
|
|
|
*/
|
|
*/
|
|
|
-static Optimizer_Data opt_data;
|
|
|
|
|
-
|
|
|
|
|
-/**
|
|
|
|
|
- * Mutex for writing to {@link opt_data}.
|
|
|
|
|
- */
|
|
|
|
|
-static pthread_mutex_t mutex;
|
|
|
|
|
|
|
+static Progress progress;
|
|
|
|
|
|
|
|
static int initialize_data(Optimizer_Data *data){
|
|
static int initialize_data(Optimizer_Data *data){
|
|
|
data->filters = malloc(sizeof(Optimizer_Filters));
|
|
data->filters = malloc(sizeof(Optimizer_Filters));
|
|
@@ -321,18 +321,20 @@ static int initialize_data(Optimizer_Data *data){
|
|
|
return ERROR_MEMORY;
|
|
return ERROR_MEMORY;
|
|
|
}
|
|
}
|
|
|
data->output->level = OUT_S;
|
|
data->output->level = OUT_S;
|
|
|
- data->output->quiet = FALSE;
|
|
|
|
|
- data->output->verbose = FALSE;
|
|
|
|
|
- data->output->debug = FALSE;
|
|
|
|
|
|
|
+ data->output->quiet = false;
|
|
|
|
|
+ data->output->verbose = false;
|
|
|
|
|
+ data->output->debug = false;
|
|
|
data->output->format = OUTPUT_HUMAN;
|
|
data->output->format = OUTPUT_HUMAN;
|
|
|
data->output->output = OUTPUT_SCREEN;
|
|
data->output->output = OUTPUT_SCREEN;
|
|
|
- data->options->threads = FALSE;
|
|
|
|
|
- data->options->help = FALSE;
|
|
|
|
|
|
|
+ data->options->threads = false;
|
|
|
|
|
+ data->options->next_thread_id = 0;
|
|
|
|
|
+ data->options->help = false;
|
|
|
strcpy((char *) data->filters->id, "");
|
|
strcpy((char *) data->filters->id, "");
|
|
|
data->filters->level = 0;
|
|
data->filters->level = 0;
|
|
|
for (int i = 0; i < MAX_SETS; i ++) data->filters->sets[i] = 0;
|
|
for (int i = 0; i < MAX_SETS; i ++) data->filters->sets[i] = 0;
|
|
|
- for (int i = 0; i < DIFFERENT_STATS; i ++) data->filters->stats[i] = FALSE;
|
|
|
|
|
- for (int i = 0; i < DIFFERENT_SETS; i ++) data->filters->optional_sets[i] = FALSE;
|
|
|
|
|
|
|
+ for (int i = 0; i < DIFFERENT_STATS; i ++) data->filters->stats[i] = false;
|
|
|
|
|
+ for (int i = 0; i < DIFFERENT_SETS; i ++)
|
|
|
|
|
+ data->filters->optional_sets[i] = false;
|
|
|
data->filters->min_stats = malloc(sizeof(Stats));
|
|
data->filters->min_stats = malloc(sizeof(Stats));
|
|
|
data->filters->min_stats->hp = 1;
|
|
data->filters->min_stats->hp = 1;
|
|
|
data->filters->min_stats->atk = 1;
|
|
data->filters->min_stats->atk = 1;
|
|
@@ -344,13 +346,12 @@ static int initialize_data(Optimizer_Data *data){
|
|
|
data->filters->min_stats->acc = 1;
|
|
data->filters->min_stats->acc = 1;
|
|
|
data->filters->min_stats->ehp = 1;
|
|
data->filters->min_stats->ehp = 1;
|
|
|
data->filters->min_stats->dmg = 1;
|
|
data->filters->min_stats->dmg = 1;
|
|
|
- data->filters->gui = FALSE;
|
|
|
|
|
- data->filters->storage = FALSE;
|
|
|
|
|
|
|
+ data->filters->storage = false;
|
|
|
data->filters->total_excluded_teams = 0,
|
|
data->filters->total_excluded_teams = 0,
|
|
|
data->filters->total_excluded_units = 0;
|
|
data->filters->total_excluded_units = 0;
|
|
|
- data->filters->broken_sets = FALSE;
|
|
|
|
|
- data->options->threads = 2;
|
|
|
|
|
- data->filters->full_set = FALSE;
|
|
|
|
|
|
|
+ data->filters->broken_sets = false;
|
|
|
|
|
+ data->options->threads = 1;
|
|
|
|
|
+ data->filters->full_set = false;
|
|
|
data->requested_set_count->energy = 0;
|
|
data->requested_set_count->energy = 0;
|
|
|
data->requested_set_count->guard = 0;
|
|
data->requested_set_count->guard = 0;
|
|
|
data->requested_set_count->swift = 0;
|
|
data->requested_set_count->swift = 0;
|
|
@@ -373,7 +374,7 @@ static int initialize_data(Optimizer_Data *data){
|
|
|
data->requested_set_count->accuracy = 0;
|
|
data->requested_set_count->accuracy = 0;
|
|
|
data->requested_set_count->tolerance = 0;
|
|
data->requested_set_count->tolerance = 0;
|
|
|
data->total_results = 0;
|
|
data->total_results = 0;
|
|
|
- data->tested_combinations = 0;
|
|
|
|
|
|
|
+ //data->tested_combinations = 0;
|
|
|
// Calculate start time
|
|
// Calculate start time
|
|
|
time_t t = time(NULL);
|
|
time_t t = time(NULL);
|
|
|
struct tm tm = *localtime(&t);
|
|
struct tm tm = *localtime(&t);
|
|
@@ -387,26 +388,26 @@ static int initialize_data(Optimizer_Data *data){
|
|
|
}
|
|
}
|
|
|
|
|
|
|
|
static void set_default_mins(Optimizer_Data *data){
|
|
static void set_default_mins(Optimizer_Data *data){
|
|
|
- if (opt_data.filters->min_stats->hp == 1)
|
|
|
|
|
- opt_data.filters->min_stats->hp = opt_data.unit->current_hp;
|
|
|
|
|
- if (opt_data.filters->min_stats->atk == 1)
|
|
|
|
|
- opt_data.filters->min_stats->atk = opt_data.unit->current_atk;
|
|
|
|
|
- if (opt_data.filters->min_stats->def == 1)
|
|
|
|
|
- opt_data.filters->min_stats->def = opt_data.unit->current_def;
|
|
|
|
|
- if (opt_data.filters->min_stats->spd == 1)
|
|
|
|
|
- opt_data.filters->min_stats->spd = opt_data.unit->current_spd;
|
|
|
|
|
- if (opt_data.filters->min_stats->crr == 1)
|
|
|
|
|
- opt_data.filters->min_stats->crr = opt_data.unit->current_crr;
|
|
|
|
|
- if (opt_data.filters->min_stats->crd == 1)
|
|
|
|
|
- opt_data.filters->min_stats->crd = opt_data.unit->current_crd;
|
|
|
|
|
- if (opt_data.filters->min_stats->res == 1)
|
|
|
|
|
- opt_data.filters->min_stats->res = opt_data.unit->current_res;
|
|
|
|
|
- if (opt_data.filters->min_stats->acc == 1)
|
|
|
|
|
- opt_data.filters->min_stats->acc = opt_data.unit->current_acc;
|
|
|
|
|
- if (opt_data.filters->min_stats->ehp == 1)
|
|
|
|
|
- opt_data.filters->min_stats->ehp = 0;
|
|
|
|
|
- if (opt_data.filters->min_stats->dmg == 1)
|
|
|
|
|
- opt_data.filters->min_stats->dmg = 0;
|
|
|
|
|
|
|
+ if (data->filters->min_stats->hp == 1)
|
|
|
|
|
+ data->filters->min_stats->hp = data->unit->current_hp;
|
|
|
|
|
+ if (data->filters->min_stats->atk == 1)
|
|
|
|
|
+ data->filters->min_stats->atk = data->unit->current_atk;
|
|
|
|
|
+ if (data->filters->min_stats->def == 1)
|
|
|
|
|
+ data->filters->min_stats->def = data->unit->current_def;
|
|
|
|
|
+ if (data->filters->min_stats->spd == 1)
|
|
|
|
|
+ data->filters->min_stats->spd = data->unit->current_spd;
|
|
|
|
|
+ if (data->filters->min_stats->crr == 1)
|
|
|
|
|
+ data->filters->min_stats->crr = data->unit->current_crr;
|
|
|
|
|
+ if (data->filters->min_stats->crd == 1)
|
|
|
|
|
+ data->filters->min_stats->crd = data->unit->current_crd;
|
|
|
|
|
+ if (data->filters->min_stats->res == 1)
|
|
|
|
|
+ data->filters->min_stats->res = data->unit->current_res;
|
|
|
|
|
+ if (data->filters->min_stats->acc == 1)
|
|
|
|
|
+ data->filters->min_stats->acc = data->unit->current_acc;
|
|
|
|
|
+ if (data->filters->min_stats->ehp == 1)
|
|
|
|
|
+ data->filters->min_stats->ehp = 0;
|
|
|
|
|
+ if (data->filters->min_stats->dmg == 1)
|
|
|
|
|
+ data->filters->min_stats->dmg = 0;
|
|
|
}
|
|
}
|
|
|
|
|
|
|
|
static int calculate_rune_count(Optimizer_Data *data){
|
|
static int calculate_rune_count(Optimizer_Data *data){
|
|
@@ -462,11 +463,12 @@ static int calculate_rune_count(Optimizer_Data *data){
|
|
|
fprintf(stderr, "Invalid rune set combination.\n");
|
|
fprintf(stderr, "Invalid rune set combination.\n");
|
|
|
return ERROR_INPUT_OPTIMIZE_INCOMPLETE_SETS;
|
|
return ERROR_INPUT_OPTIMIZE_INCOMPLETE_SETS;
|
|
|
}
|
|
}
|
|
|
- else if (RUNE_SLOTS == total) opt_data.filters->full_set = TRUE;
|
|
|
|
|
|
|
+ else if (RUNE_SLOTS == total) data->filters->full_set = TRUE;
|
|
|
return total;
|
|
return total;
|
|
|
}
|
|
}
|
|
|
|
|
|
|
|
extern int optimize(int argc, char *argv[]){
|
|
extern int optimize(int argc, char *argv[]){
|
|
|
|
|
+ Optimizer_Data opt_data;
|
|
|
int status = SUCCESS;
|
|
int status = SUCCESS;
|
|
|
char query_even[RUNE_QUERY_LEN];
|
|
char query_even[RUNE_QUERY_LEN];
|
|
|
char query_odd[RUNE_QUERY_LEN];
|
|
char query_odd[RUNE_QUERY_LEN];
|
|
@@ -499,22 +501,28 @@ extern int optimize(int argc, char *argv[]){
|
|
|
}
|
|
}
|
|
|
}
|
|
}
|
|
|
|
|
|
|
|
|
|
+ // initialize progression values
|
|
|
|
|
+ progress.percent = 0;
|
|
|
|
|
+ progress.tested = 0;
|
|
|
|
|
+ progress.total = opt_data.max_combinations;
|
|
|
|
|
+ progress.results = 0;
|
|
|
|
|
+
|
|
|
// Print summary with data collected so far.
|
|
// Print summary with data collected so far.
|
|
|
if (opt_data.output->level > OUT_Q) output_summary(&opt_data);
|
|
if (opt_data.output->level > OUT_Q) output_summary(&opt_data);
|
|
|
|
|
+ if (opt_data.output->quiet == FALSE) output_progress_human(&progress);
|
|
|
|
|
|
|
|
// Now its time to loop all 6 'reels' of runes and try to match combos
|
|
// Now its time to loop all 6 'reels' of runes and try to match combos
|
|
|
- pthread_t thread[opt_data.options->threads];
|
|
|
|
|
- for (char t = 0; t < opt_data.options->threads; t++){
|
|
|
|
|
- pthread_create(
|
|
|
|
|
- &thread[t], NULL, optimize_thread, (void *)(uintptr_t) t
|
|
|
|
|
|
|
+ mtx_init(&opt_data.mutex, mtx_plain);
|
|
|
|
|
+ thrd_t thread[opt_data.options->threads];
|
|
|
|
|
+ for (int t = 0; t < opt_data.options->threads; t++)
|
|
|
|
|
+ thrd_create(
|
|
|
|
|
+ &thread[t], (thrd_start_t) optimize_thread, (void *) &opt_data
|
|
|
);
|
|
);
|
|
|
- }
|
|
|
|
|
for (int t = 0; t < opt_data.options->threads; t++)
|
|
for (int t = 0; t < opt_data.options->threads; t++)
|
|
|
- pthread_join(thread[t], NULL);
|
|
|
|
|
|
|
+ thrd_join(thread[t], NULL);
|
|
|
|
|
+ progress.percent = 100;
|
|
|
if (opt_data.output->quiet == FALSE){
|
|
if (opt_data.output->quiet == FALSE){
|
|
|
- printf("\b\b\b\b\b\b\b\b\b\b\b\b\b\b\b\b\b\b\b\b\b\b\b\b\b\b\b");
|
|
|
|
|
- printf("[%3d%%] Results found: %5u", 100, opt_data.total_results);
|
|
|
|
|
- fflush(stdout);
|
|
|
|
|
|
|
+ output_progress_human(&progress);
|
|
|
printf("\n");
|
|
printf("\n");
|
|
|
}
|
|
}
|
|
|
sort_results(opt_data.results, opt_data.total_results);
|
|
sort_results(opt_data.results, opt_data.total_results);
|
|
@@ -972,7 +980,7 @@ static int parse_arguments(int argc, char *argv[], Optimizer_Data *data){
|
|
|
return SUCCESS;
|
|
return SUCCESS;
|
|
|
}
|
|
}
|
|
|
|
|
|
|
|
-static int read_unit(unsigned char id[UNIT_NAME_LEN], Unit *unit){
|
|
|
|
|
|
|
+static int read_unit(char *id, Unit *unit){
|
|
|
sqlite3_stmt *stmt_unit;
|
|
sqlite3_stmt *stmt_unit;
|
|
|
char *parameters[2] = {(char *) id, (char *) id};
|
|
char *parameters[2] = {(char *) id, (char *) id};
|
|
|
db_query(
|
|
db_query(
|
|
@@ -1284,27 +1292,24 @@ static int select_runes(
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
-static void *optimize_thread(void *tid){
|
|
|
|
|
- int thread_id = (int) (uintptr_t) tid;
|
|
|
|
|
- int start_at = thread_id * ceil((float) opt_data.count[1]
|
|
|
|
|
- / (float) opt_data.options->threads);
|
|
|
|
|
- int end_at = start_at + ceil((float) opt_data.count[1] / (float) opt_data.options->threads);
|
|
|
|
|
|
|
+static thrd_start_t optimize_thread(void *data_ptr){
|
|
|
|
|
+ Optimizer_Data *data = data_ptr;//(Optimizer_Data) (uintptr_t) data_ptr;
|
|
|
|
|
+ uint_fast64_t tested_combinations = 0;
|
|
|
|
|
+ mtx_lock(&data->mutex);
|
|
|
|
|
+ uint_fast8_t thread_id = data->options->next_thread_id;
|
|
|
|
|
+ data->options->next_thread_id ++;
|
|
|
|
|
+ mtx_unlock(&data->mutex);
|
|
|
|
|
+ uint_fast16_t start_at = thread_id * ceil((float) data->count[1]
|
|
|
|
|
+ / (float) data->options->threads);
|
|
|
|
|
+ uint_fast16_t end_at =
|
|
|
|
|
+ start_at
|
|
|
|
|
+ + ceil((float) data->count[1] / (float) data->options->threads);
|
|
|
|
|
|
|
|
// Initialize arrys and some counters
|
|
// Initialize arrys and some counters
|
|
|
- unsigned int index[RUNE_SLOTS + 1] = {0, start_at, 0, 0, 0, 0};
|
|
|
|
|
- unsigned long valid_sets = 0;
|
|
|
|
|
|
|
+ uint_fast16_t index[RUNE_SLOTS + 1] = {0, start_at, 0, 0, 0, 0};
|
|
|
Rune_Set_Count set_count;
|
|
Rune_Set_Count set_count;
|
|
|
- unsigned char progress_printed = FALSE;
|
|
|
|
|
- while(
|
|
|
|
|
- index[1] < end_at
|
|
|
|
|
- && index[1] < opt_data.count[1]
|
|
|
|
|
- && 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]
|
|
|
|
|
- && opt_data.total_results < MAX_RESULTS // Hard limit
|
|
|
|
|
- ){
|
|
|
|
|
|
|
+ struct Stats stats;
|
|
|
|
|
+ while(index[1] < end_at){
|
|
|
// Calculate rune sets at current indexes.
|
|
// Calculate rune sets at current indexes.
|
|
|
set_count.energy = 0;
|
|
set_count.energy = 0;
|
|
|
set_count.guard = 0;
|
|
set_count.guard = 0;
|
|
@@ -1327,8 +1332,8 @@ static void *optimize_thread(void *tid){
|
|
|
set_count.enhance = 0;
|
|
set_count.enhance = 0;
|
|
|
set_count.accuracy = 0;
|
|
set_count.accuracy = 0;
|
|
|
set_count.tolerance = 0;
|
|
set_count.tolerance = 0;
|
|
|
- for (int i = 1; i < RUNE_SLOTS + 1; i ++){
|
|
|
|
|
- switch (opt_data.runes[i][index[i]].set){
|
|
|
|
|
|
|
+ for (uint_fast8_t i = 1; i < RUNE_SLOTS + 1; i ++){
|
|
|
|
|
+ switch (data->runes[i][index[i]].set){
|
|
|
case ENERGY: set_count.energy ++; break;
|
|
case ENERGY: set_count.energy ++; break;
|
|
|
case GUARD: set_count.guard ++; break;
|
|
case GUARD: set_count.guard ++; break;
|
|
|
case SWIFT: set_count.swift ++; break;
|
|
case SWIFT: set_count.swift ++; break;
|
|
@@ -1354,76 +1359,74 @@ static void *optimize_thread(void *tid){
|
|
|
}
|
|
}
|
|
|
|
|
|
|
|
// Compare with requested sets
|
|
// Compare with requested sets
|
|
|
- if (
|
|
|
|
|
- (
|
|
|
|
|
- opt_data.filters->broken_sets == TRUE ||
|
|
|
|
|
- contains_broken(&set_count) == FALSE
|
|
|
|
|
- ) &&
|
|
|
|
|
- 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 &&
|
|
|
|
|
|
|
+ bool broken_state = true;
|
|
|
|
|
+ if (data->filters->broken_sets == false)
|
|
|
|
|
+ broken_state = !contains_broken(&set_count);
|
|
|
|
|
+ if (unlikely(
|
|
|
|
|
+ broken_state &&
|
|
|
|
|
+ set_count.energy >= data->requested_set_count->energy &&
|
|
|
|
|
+ set_count.guard >= data->requested_set_count->guard &&
|
|
|
|
|
+ set_count.swift >= data->requested_set_count->swift &&
|
|
|
|
|
+ set_count.blade >= data->requested_set_count->blade &&
|
|
|
|
|
+ set_count.rage >= data->requested_set_count->rage &&
|
|
|
|
|
+ set_count.focus >= data->requested_set_count->focus &&
|
|
|
|
|
+ set_count.endure >= data->requested_set_count->endure &&
|
|
|
|
|
+ set_count.fatal >= data->requested_set_count->fatal &&
|
|
|
|
|
+ set_count.despair >= data->requested_set_count->despair &&
|
|
|
|
|
+ set_count.vampire >= data->requested_set_count->vampire &&
|
|
|
|
|
+ set_count.violent >= data->requested_set_count->violent &&
|
|
|
|
|
+ set_count.nemesis >= data->requested_set_count->nemesis &&
|
|
|
|
|
+ set_count.will >= data->requested_set_count->will &&
|
|
|
|
|
+ set_count.shield >= data->requested_set_count->shield &&
|
|
|
|
|
+ set_count.revenge >= data->requested_set_count->revenge &&
|
|
|
|
|
+ set_count.destroy >= data->requested_set_count->destroy &&
|
|
|
|
|
+ set_count.fight >= data->requested_set_count->fight &&
|
|
|
set_count.determination >=
|
|
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
|
|
|
|
|
- ){
|
|
|
|
|
|
|
+ data->requested_set_count->determination &&
|
|
|
|
|
+ set_count.enhance >= data->requested_set_count->enhance &&
|
|
|
|
|
+ set_count.accuracy >= data->requested_set_count->accuracy &&
|
|
|
|
|
+ set_count.tolerance >= data->requested_set_count->tolerance
|
|
|
|
|
+ )){
|
|
|
// The current runes form a valid set.
|
|
// The current runes form a valid set.
|
|
|
- valid_sets ++;
|
|
|
|
|
|
|
|
|
|
// Calculate new stats
|
|
// Calculate new stats
|
|
|
- struct Stats stats;
|
|
|
|
|
- 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 < RUNE_SLOTS + 1; i ++){
|
|
|
|
|
- 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 = data->unit->base_hp;
|
|
|
|
|
+ stats.atk = data->unit->base_atk;
|
|
|
|
|
+ stats.def = data->unit->base_def;
|
|
|
|
|
+ stats.spd = data->unit->base_spd;
|
|
|
|
|
+ stats.crr = data->unit->base_crr;
|
|
|
|
|
+ stats.crd = data->unit->base_crd;
|
|
|
|
|
+ stats.res = data->unit->base_res;
|
|
|
|
|
+ stats.acc = data->unit->base_acc;
|
|
|
|
|
+ for (uint_fast8_t i = 1; i < RUNE_SLOTS + 1; i ++){
|
|
|
|
|
+ stats.hp += data->runes[i][index[i]].hp_flat;
|
|
|
|
|
+ stats.atk += data->runes[i][index[i]].atk_flat;
|
|
|
|
|
+ stats.def += data->runes[i][index[i]].def_flat;
|
|
|
stats.hp +=
|
|
stats.hp +=
|
|
|
- opt_data.unit->base_hp
|
|
|
|
|
- * opt_data.runes[i][index[i]].hp_percent / 100;
|
|
|
|
|
|
|
+ data->unit->base_hp
|
|
|
|
|
+ * data->runes[i][index[i]].hp_percent / 100;
|
|
|
stats.atk +=
|
|
stats.atk +=
|
|
|
- opt_data.unit->base_atk
|
|
|
|
|
- * opt_data.runes[i][index[i]].atk_percent / 100;
|
|
|
|
|
|
|
+ data->unit->base_atk
|
|
|
|
|
+ * data->runes[i][index[i]].atk_percent / 100;
|
|
|
stats.def +=
|
|
stats.def +=
|
|
|
- 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;
|
|
|
|
|
|
|
+ data->unit->base_def
|
|
|
|
|
+ * data->runes[i][index[i]].def_percent / 100;
|
|
|
|
|
+ stats.spd += data->runes[i][index[i]].spd;
|
|
|
|
|
+ stats.crr += data->runes[i][index[i]].crr;
|
|
|
|
|
+ stats.crd += data->runes[i][index[i]].crd;
|
|
|
|
|
+ stats.res += data->runes[i][index[i]].res;
|
|
|
|
|
+ stats.acc += data->runes[i][index[i]].acc;
|
|
|
}
|
|
}
|
|
|
|
|
|
|
|
// Set stats
|
|
// Set stats
|
|
|
if (set_count.energy >= 2) // +15% Base HP per set of 2
|
|
if (set_count.energy >= 2) // +15% Base HP per set of 2
|
|
|
stats.hp +=
|
|
stats.hp +=
|
|
|
- opt_data.unit->base_hp * 0.15 * (set_count.energy % 2);
|
|
|
|
|
|
|
+ data->unit->base_hp * 0.15 * (set_count.energy % 2);
|
|
|
if (set_count.guard >= 2) // +15% base DEF per set of 2
|
|
if (set_count.guard >= 2) // +15% base DEF per set of 2
|
|
|
stats.def +=
|
|
stats.def +=
|
|
|
- opt_data.unit->base_def * 0.15 * (set_count.guard % 2);
|
|
|
|
|
|
|
+ data->unit->base_def * 0.15 * (set_count.guard % 2);
|
|
|
if (set_count.swift >= 4) // +25% base SPD per set of 4
|
|
if (set_count.swift >= 4) // +25% base SPD per set of 4
|
|
|
- stats.spd += opt_data.unit->base_spd * 0.25;
|
|
|
|
|
|
|
+ stats.spd += data->unit->base_spd * 0.25;
|
|
|
if (set_count.blade >= 2) // +12% CRR per set of 2
|
|
if (set_count.blade >= 2) // +12% CRR per set of 2
|
|
|
stats.crr += 12;
|
|
stats.crr += 12;
|
|
|
if (set_count.rage >= 4) // +40% CRD per set of 4
|
|
if (set_count.rage >= 4) // +40% CRD per set of 4
|
|
@@ -1433,17 +1436,17 @@ static void *optimize_thread(void *tid){
|
|
|
if (set_count.endure >= 2) // +20% RES per set of 2
|
|
if (set_count.endure >= 2) // +20% RES per set of 2
|
|
|
stats.res += 20;
|
|
stats.res += 20;
|
|
|
if (set_count.fatal >= 4) // +35% base ATK per set of 4
|
|
if (set_count.fatal >= 4) // +35% base ATK per set of 4
|
|
|
- stats.atk += opt_data.unit->base_atk * 0.35;
|
|
|
|
|
|
|
+ stats.atk += data->unit->base_atk * 0.35;
|
|
|
if (set_count.fight >= 2) // +8% base ATK per set of 2
|
|
if (set_count.fight >= 2) // +8% base ATK per set of 2
|
|
|
stats.atk +=
|
|
stats.atk +=
|
|
|
- opt_data.unit->base_atk * 0.08 * (set_count.fight % 2);
|
|
|
|
|
|
|
+ data->unit->base_atk * 0.08 * (set_count.fight % 2);
|
|
|
if (set_count.determination >= 2) // +8% base DEF per set of 2
|
|
if (set_count.determination >= 2) // +8% base DEF per set of 2
|
|
|
stats.def +=
|
|
stats.def +=
|
|
|
- opt_data.unit->base_def * 0.08
|
|
|
|
|
|
|
+ data->unit->base_def * 0.08
|
|
|
* (set_count.determination % 2);
|
|
* (set_count.determination % 2);
|
|
|
if (set_count.enhance >= 2) // +8% base HP per set of 2
|
|
if (set_count.enhance >= 2) // +8% base HP per set of 2
|
|
|
stats.hp +=
|
|
stats.hp +=
|
|
|
- opt_data.unit->base_hp * 0.08 * (set_count.enhance % 2);
|
|
|
|
|
|
|
+ data->unit->base_hp * 0.08 * (set_count.enhance % 2);
|
|
|
if (set_count.accuracy >= 2) // +10% ACC per set of 2
|
|
if (set_count.accuracy >= 2) // +10% ACC per set of 2
|
|
|
stats.acc += 20;
|
|
stats.acc += 20;
|
|
|
if (set_count.tolerance >= 2) // +10% RES per set of 2
|
|
if (set_count.tolerance >= 2) // +10% RES per set of 2
|
|
@@ -1459,18 +1462,18 @@ static void *optimize_thread(void *tid){
|
|
|
stats.dmg = calculate_dmg(stats.atk, stats.crr, stats.crd);
|
|
stats.dmg = calculate_dmg(stats.atk, stats.crr, stats.crd);
|
|
|
|
|
|
|
|
// Compare with minimum requeriments
|
|
// Compare with minimum requeriments
|
|
|
- if (
|
|
|
|
|
- stats.hp >= opt_data.filters->min_stats->hp &&
|
|
|
|
|
- stats.atk >= opt_data.filters->min_stats->atk &&
|
|
|
|
|
- stats.def >= opt_data.filters->min_stats->def &&
|
|
|
|
|
- stats.spd >= opt_data.filters->min_stats->spd &&
|
|
|
|
|
- stats.crr >= opt_data.filters->min_stats->crr &&
|
|
|
|
|
- stats.crd >= opt_data.filters->min_stats->crd &&
|
|
|
|
|
- stats.res >= opt_data.filters->min_stats->res &&
|
|
|
|
|
- stats.acc >= opt_data.filters->min_stats->acc &&
|
|
|
|
|
- stats.ehp >= opt_data.filters->min_stats->ehp &&
|
|
|
|
|
- stats.dmg >= opt_data.filters->min_stats->dmg
|
|
|
|
|
- ){
|
|
|
|
|
|
|
+ if (unlikely(
|
|
|
|
|
+ stats.hp >= data->filters->min_stats->hp &&
|
|
|
|
|
+ stats.atk >= data->filters->min_stats->atk &&
|
|
|
|
|
+ stats.def >= data->filters->min_stats->def &&
|
|
|
|
|
+ stats.spd >= data->filters->min_stats->spd &&
|
|
|
|
|
+ stats.crr >= data->filters->min_stats->crr &&
|
|
|
|
|
+ stats.crd >= data->filters->min_stats->crd &&
|
|
|
|
|
+ stats.res >= data->filters->min_stats->res &&
|
|
|
|
|
+ stats.acc >= data->filters->min_stats->acc &&
|
|
|
|
|
+ stats.ehp >= data->filters->min_stats->ehp &&
|
|
|
|
|
+ stats.dmg >= data->filters->min_stats->dmg
|
|
|
|
|
+ )){
|
|
|
// Calculate rating, based on the difference between the
|
|
// Calculate rating, based on the difference between the
|
|
|
// stats with this set and the current stats.
|
|
// stats with this set and the current stats.
|
|
|
// This is calculated accounting for the proportions between
|
|
// This is calculated accounting for the proportions between
|
|
@@ -1486,97 +1489,92 @@ static void *optimize_thread(void *tid){
|
|
|
// ACC: 1 rating point per 1.52 points
|
|
// ACC: 1 rating point per 1.52 points
|
|
|
float rating = 0.0f;
|
|
float rating = 0.0f;
|
|
|
rating +=
|
|
rating +=
|
|
|
- (float) ((int) stats.hp - (int) opt_data.unit->current_hp )
|
|
|
|
|
|
|
+ (float) ((int) stats.hp - (int) data->unit->current_hp )
|
|
|
/ 58.29f;
|
|
/ 58.29f;
|
|
|
rating +=
|
|
rating +=
|
|
|
- (float) ((int) stats.atk - (int) opt_data.unit->current_atk)
|
|
|
|
|
|
|
+ (float) ((int) stats.atk - (int) data->unit->current_atk)
|
|
|
/ 1.50f;
|
|
/ 1.50f;
|
|
|
rating +=
|
|
rating +=
|
|
|
- (float) ((int) stats.def - (int) opt_data.unit->current_def)
|
|
|
|
|
|
|
+ (float) ((int) stats.def - (int) data->unit->current_def)
|
|
|
/ 1.50f;
|
|
/ 1.50f;
|
|
|
rating +=
|
|
rating +=
|
|
|
- (float) ((int) stats.spd - (int) opt_data.unit->current_spd)
|
|
|
|
|
|
|
+ (float) ((int) stats.spd - (int) data->unit->current_spd)
|
|
|
/ 1.00f;
|
|
/ 1.00f;
|
|
|
rating +=
|
|
rating +=
|
|
|
- (float) ((int) stats.crr - (int) opt_data.unit->current_crr)
|
|
|
|
|
|
|
+ (float) ((int) stats.crr - (int) data->unit->current_crr)
|
|
|
/ 1.38f;
|
|
/ 1.38f;
|
|
|
rating +=
|
|
rating +=
|
|
|
- (float) ((int) stats.crd - (int) opt_data.unit->current_crd)
|
|
|
|
|
|
|
+ (float) ((int) stats.crd - (int) data->unit->current_crd)
|
|
|
/ 1.90f;
|
|
/ 1.90f;
|
|
|
rating +=
|
|
rating +=
|
|
|
- (float) ((int) stats.res - (int) opt_data.unit->current_res)
|
|
|
|
|
|
|
+ (float) ((int) stats.res - (int) data->unit->current_res)
|
|
|
/ 1.52f;
|
|
/ 1.52f;
|
|
|
rating +=
|
|
rating +=
|
|
|
- (float) ((int) stats.acc - (int) opt_data.unit->current_acc)
|
|
|
|
|
|
|
+ (float) ((int) stats.acc - (int) data->unit->current_acc)
|
|
|
/ 1.52f;
|
|
/ 1.52f;
|
|
|
|
|
|
|
|
// This is a valid sets and all stats are above the minimum.
|
|
// This is a valid sets and all stats are above the minimum.
|
|
|
// Create a result with rune indexes, stats, and rating.
|
|
// Create a result with rune indexes, stats, and rating.
|
|
|
// Lock the mutex
|
|
// Lock the mutex
|
|
|
- pthread_mutex_lock(&mutex);
|
|
|
|
|
|
|
+ mtx_lock(&data->mutex);
|
|
|
for (int i = 1; i < RUNE_SLOTS + 1; i ++){
|
|
for (int i = 1; i < RUNE_SLOTS + 1; i ++){
|
|
|
strcpy(
|
|
strcpy(
|
|
|
- (char *) opt_data.results[
|
|
|
|
|
- opt_data.total_results
|
|
|
|
|
|
|
+ (char *) data->results[
|
|
|
|
|
+ data->total_results
|
|
|
].rune_ids[i - 1],
|
|
].rune_ids[i - 1],
|
|
|
- (const char *) opt_data.runes[i][index[i]].id
|
|
|
|
|
|
|
+ (const char *) data->runes[i][index[i]].id
|
|
|
);
|
|
);
|
|
|
}
|
|
}
|
|
|
- opt_data.results[opt_data.total_results].stats.hp = stats.hp;
|
|
|
|
|
- opt_data.results[opt_data.total_results].stats.atk = stats.atk;
|
|
|
|
|
- opt_data.results[opt_data.total_results].stats.def = stats.def;
|
|
|
|
|
- opt_data.results[opt_data.total_results].stats.spd = stats.spd;
|
|
|
|
|
- opt_data.results[opt_data.total_results].stats.crr = stats.crr;
|
|
|
|
|
- opt_data.results[opt_data.total_results].stats.crd = stats.crd;
|
|
|
|
|
- opt_data.results[opt_data.total_results].stats.res = stats.res;
|
|
|
|
|
- opt_data.results[opt_data.total_results].stats.acc = stats.acc;
|
|
|
|
|
- opt_data.results[opt_data.total_results].stats.ehp = stats.ehp;
|
|
|
|
|
- opt_data.results[opt_data.total_results].stats.dmg = stats.dmg;
|
|
|
|
|
- opt_data.results[opt_data.total_results].rating = (int) rating;
|
|
|
|
|
- opt_data.total_results ++;
|
|
|
|
|
- pthread_mutex_unlock(&mutex);
|
|
|
|
|
|
|
+ data->results[data->total_results].stats.hp = stats.hp;
|
|
|
|
|
+ data->results[data->total_results].stats.atk = stats.atk;
|
|
|
|
|
+ data->results[data->total_results].stats.def = stats.def;
|
|
|
|
|
+ data->results[data->total_results].stats.spd = stats.spd;
|
|
|
|
|
+ data->results[data->total_results].stats.crr = stats.crr;
|
|
|
|
|
+ data->results[data->total_results].stats.crd = stats.crd;
|
|
|
|
|
+ data->results[data->total_results].stats.res = stats.res;
|
|
|
|
|
+ data->results[data->total_results].stats.acc = stats.acc;
|
|
|
|
|
+ data->results[data->total_results].stats.ehp = stats.ehp;
|
|
|
|
|
+ data->results[data->total_results].stats.dmg = stats.dmg;
|
|
|
|
|
+ data->results[data->total_results].rating = (int) rating;
|
|
|
|
|
+ data->total_results ++;
|
|
|
|
|
+ progress.results ++;
|
|
|
|
|
+ mtx_unlock(&data->mutex);
|
|
|
}
|
|
}
|
|
|
}
|
|
}
|
|
|
|
|
|
|
|
// Loop control. Rotate the reels 'right to left'
|
|
// Loop control. Rotate the reels 'right to left'
|
|
|
- pthread_mutex_lock(&mutex);
|
|
|
|
|
- opt_data.tested_combinations ++;
|
|
|
|
|
|
|
+ tested_combinations ++;
|
|
|
|
|
+
|
|
|
|
|
|
|
|
// Update progress bar.
|
|
// Update progress bar.
|
|
|
- if (
|
|
|
|
|
- opt_data.output->quiet == FALSE
|
|
|
|
|
- && opt_data.tested_combinations % 500000 == 0
|
|
|
|
|
- ){
|
|
|
|
|
- printf("\b\b\b\b\b\b\b\b\b\b\b\b\b\b\b\b\b\b\b\b\b\b\b\b\b\b\b");
|
|
|
|
|
- printf(
|
|
|
|
|
- "[%3d%%] Results found: %5u",
|
|
|
|
|
- (int) (
|
|
|
|
|
- (
|
|
|
|
|
- (double) opt_data.tested_combinations
|
|
|
|
|
- / (double) opt_data.max_combinations
|
|
|
|
|
- )
|
|
|
|
|
- * 100.0f
|
|
|
|
|
- ),
|
|
|
|
|
- opt_data.total_results
|
|
|
|
|
|
|
+ if (unlikely(tested_combinations == PROGRESS_TICK)){
|
|
|
|
|
+ mtx_lock(&data->mutex);
|
|
|
|
|
+ progress.tested += tested_combinations;
|
|
|
|
|
+ progress.percent = (int) (
|
|
|
|
|
+ ((double) progress.tested * 100.0f)
|
|
|
|
|
+ / (double) progress.total
|
|
|
);
|
|
);
|
|
|
- fflush(stdout);
|
|
|
|
|
|
|
+ if (data->output->quiet == FALSE){
|
|
|
|
|
+ output_progress_human(&progress);
|
|
|
|
|
+ }
|
|
|
|
|
+ mtx_unlock(&data->mutex);
|
|
|
|
|
+ tested_combinations = 0;
|
|
|
}
|
|
}
|
|
|
|
|
|
|
|
- pthread_mutex_unlock(&mutex);
|
|
|
|
|
index[6] ++;
|
|
index[6] ++;
|
|
|
- if (index[6] == opt_data.count[6]){
|
|
|
|
|
|
|
+ if (index[6] == data->count[6]){
|
|
|
index[6] = 0; index[5] ++;
|
|
index[6] = 0; index[5] ++;
|
|
|
}
|
|
}
|
|
|
- if (index[5] == opt_data.count[5]){
|
|
|
|
|
|
|
+ if (index[5] == data->count[5]){
|
|
|
index[5] = 0; index[4] ++;
|
|
index[5] = 0; index[4] ++;
|
|
|
}
|
|
}
|
|
|
- if (index[4] == opt_data.count[4]){
|
|
|
|
|
|
|
+ if (index[4] == data->count[4]){
|
|
|
index[4] = 0; index[3] ++;
|
|
index[4] = 0; index[3] ++;
|
|
|
}
|
|
}
|
|
|
- if (index[3] == opt_data.count[3]){
|
|
|
|
|
|
|
+ if (index[3] == data->count[3]){
|
|
|
index[3] = 0; index[2] ++;
|
|
index[3] = 0; index[2] ++;
|
|
|
}
|
|
}
|
|
|
- if (index[2] == opt_data.count[2]){
|
|
|
|
|
|
|
+ if (index[2] == data->count[2]){
|
|
|
index[2] = 0; index[1] ++;
|
|
index[2] = 0; index[1] ++;
|
|
|
}
|
|
}
|
|
|
|
|
|
|
@@ -1584,31 +1582,36 @@ static void *optimize_thread(void *tid){
|
|
|
//if (result_count > 2)
|
|
//if (result_count > 2)
|
|
|
// break;
|
|
// break;
|
|
|
}
|
|
}
|
|
|
- pthread_exit(NULL);
|
|
|
|
|
|
|
+ mtx_lock(&data->mutex);
|
|
|
|
|
+ // Update current test count before exiting
|
|
|
|
|
+ progress.tested += tested_combinations;
|
|
|
|
|
+ mtx_unlock(&data->mutex);
|
|
|
|
|
+ // Thread ending
|
|
|
|
|
+ thrd_exit(EXIT_SUCCESS);
|
|
|
}
|
|
}
|
|
|
|
|
|
|
|
-static unsigned char contains_broken(Rune_Set_Count *set_count){
|
|
|
|
|
- if (set_count->energy % 2 != 0) return(TRUE);
|
|
|
|
|
- if (set_count->guard % 2 != 0) return(TRUE);
|
|
|
|
|
- if (set_count->swift % 4 != 0) return(TRUE);
|
|
|
|
|
- if (set_count->blade % 2 != 0) return(TRUE);
|
|
|
|
|
- if (set_count->rage % 4 != 0) return(TRUE);
|
|
|
|
|
- if (set_count->focus % 2 != 0) return(TRUE);
|
|
|
|
|
- if (set_count->endure % 2 != 0) return(TRUE);
|
|
|
|
|
- if (set_count->fatal % 4 != 0) return(TRUE);
|
|
|
|
|
- if (set_count->despair % 4 != 0) return(TRUE);
|
|
|
|
|
- if (set_count->vampire % 4 != 0) return(TRUE);
|
|
|
|
|
- if (set_count->violent % 4 != 0) return(TRUE);
|
|
|
|
|
- if (set_count->nemesis % 2 != 0) return(TRUE);
|
|
|
|
|
- if (set_count->will % 2 != 0) return(TRUE);
|
|
|
|
|
- if (set_count->shield % 2 != 0) return(TRUE);
|
|
|
|
|
- if (set_count->revenge % 2 != 0) return(TRUE);
|
|
|
|
|
- if (set_count->destroy % 2 != 0) return(TRUE);
|
|
|
|
|
- if (set_count->fight % 2 != 0) return(TRUE);
|
|
|
|
|
- if (set_count->determination % 2 != 0) return(TRUE);
|
|
|
|
|
- if (set_count->enhance % 2 != 0) return(TRUE);
|
|
|
|
|
- if (set_count->accuracy % 2 != 0) return(TRUE);
|
|
|
|
|
- if (set_count->tolerance % 2 != 0) return(TRUE);
|
|
|
|
|
|
|
+__inline static bool contains_broken(Rune_Set_Count *set_count){
|
|
|
|
|
+ if (set_count->energy % 2 != 0) return(true);
|
|
|
|
|
+ if (set_count->guard % 2 != 0) return(true);
|
|
|
|
|
+ if (set_count->swift % 4 != 0) return(true);
|
|
|
|
|
+ if (set_count->blade % 2 != 0) return(true);
|
|
|
|
|
+ if (set_count->rage % 4 != 0) return(true);
|
|
|
|
|
+ if (set_count->focus % 2 != 0) return(true);
|
|
|
|
|
+ if (set_count->endure % 2 != 0) return(true);
|
|
|
|
|
+ if (set_count->fatal % 4 != 0) return(true);
|
|
|
|
|
+ if (set_count->despair % 4 != 0) return(true);
|
|
|
|
|
+ if (set_count->vampire % 4 != 0) return(true);
|
|
|
|
|
+ if (set_count->violent % 4 != 0) return(true);
|
|
|
|
|
+ if (set_count->nemesis % 2 != 0) return(true);
|
|
|
|
|
+ if (set_count->will % 2 != 0) return(true);
|
|
|
|
|
+ if (set_count->shield % 2 != 0) return(true);
|
|
|
|
|
+ if (set_count->revenge % 2 != 0) return(true);
|
|
|
|
|
+ if (set_count->destroy % 2 != 0) return(true);
|
|
|
|
|
+ if (set_count->fight % 2 != 0) return(true);
|
|
|
|
|
+ if (set_count->determination % 2 != 0) return(true);
|
|
|
|
|
+ if (set_count->enhance % 2 != 0) return(true);
|
|
|
|
|
+ if (set_count->accuracy % 2 != 0) return(true);
|
|
|
|
|
+ if (set_count->tolerance % 2 != 0) return(true);
|
|
|
return(FALSE);
|
|
return(FALSE);
|
|
|
}
|
|
}
|
|
|
|
|
|
|
@@ -1631,15 +1634,7 @@ static void sort_results(Result results[MAX_RESULTS], int total){
|
|
|
|
|
|
|
|
static void handle_signal(int sig){
|
|
static void handle_signal(int sig){
|
|
|
if (sig == SIGUSR1){
|
|
if (sig == SIGUSR1){
|
|
|
- unsigned int progress;
|
|
|
|
|
- if (0 == opt_data.max_combinations) progress = 0;
|
|
|
|
|
- else progress =
|
|
|
|
|
- opt_data.tested_combinations * 100 / opt_data.max_combinations;
|
|
|
|
|
- printf(
|
|
|
|
|
- " Progress: %u%% (%llu / %llu)\n",
|
|
|
|
|
- progress, opt_data.tested_combinations, opt_data.max_combinations
|
|
|
|
|
- );
|
|
|
|
|
- fflush(stdout);
|
|
|
|
|
|
|
+ output_progress_json(&progress);
|
|
|
}
|
|
}
|
|
|
}
|
|
}
|
|
|
|
|
|