/* * This file is part of RuneOptimizer. * * RuneOptimizer is free software: you can redistribute it and/or modify it * under the terms of the GNU General Public License as published by the Free * Software Foundation, either version 3 of the License, or (at your option) * any later version. * * RuneOptimizer is distributed in the hope that it will be useful, but WITHOUT * ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or * FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License for * more details. * * You should have received a copy of the GNU General Public License along with * RuneOptimizer. If not, see . */ /** * @file optimize.h * * Declarations of the functions and data typer related to the optimixe command. * * This file declares all the functions and data types used by the optimize * command implemented in {@link optimize.c}. */ #pragma once #include "../runeoptimizer.h" /** * Hard limit on the number of results */ #define MAX_RESULTS 5000 /** * Limit on runes per slot for the optimizations. * * Number format. */ #define LIMIT_RUNES_PER_SLOT 500 /** * Hard limit on the number of teams or units that can be excluded from * optimization. */ #define MAX_EXCLUSIONS 128 /** * Maximum number of sets. * * Maximum for the requested sets option. */ #define MAX_SETS 3 /** * A rune. * * Contains usefull information to operate with runes. */ typedef struct Rune { /** * The rune ID. * * Unit ID, as given by Com2Us. */ unsigned char id[RUNE_ID_LEN]; /** * The slot of the rune * * Can be [1-6]. */ unsigned char slot; /** * Rune set id. * * Identifier of the set the rune belongs to. */ unsigned char set; /** * ID of the unit the rune is assigned to. * * NULL if the rune is not assigned. */ unsigned char unit[UNIT_ID_LEN]; /** * HP% stat. * * HP% given by the rune, in any of it's stats. */ unsigned char hp_percent; /** * ATK% stat. * * ATK% given by the rune, in any of it's stats. */ unsigned char atk_percent; /** * DEF% stat. * * DEF% given by the rune, in any of it's stats. */ unsigned char def_percent; /** * HP stat. * * HP given by the rune, in any of it's stats. */ unsigned short hp_flat; /** * ATK stat. * * ATK given by the rune, in any of it's stats. */ unsigned char atk_flat; /** * DEF stat. * * DEF given by the rune, in any of it's stats. */ unsigned char def_flat; /** * SPD stat. * * SPD given by the rune, in any of it's stats. */ unsigned char spd; /** * CRR stat. * * CRR given by the rune, in any of it's stats. */ unsigned char crr; /** * CRD stat. * * CRD given by the rune, in any of it's stats. */ unsigned char crd; /** * RES stat. * * RES given by the rune, in any of it's stats. */ unsigned char res; /** * ACC stat. * * ACC given by the rune, in any of it's stats. */ unsigned char acc; } Rune; /** * Stats of a unit. * * Can be used for base stats or for current stats. */ typedef struct Stats { /** * HP stat. * * Unit health. Unit gets defeated in battle when it reaches 0. */ unsigned int hp; /** * ATK stat. * * Unit attack power. Retermines how much damage it does. */ unsigned short atk; /** * DEF stat. * * Unit defense. Reduces incoming damage. */ unsigned short def; /** * SPD stat. * * Unit speed. Determines turn order. */ unsigned short spd; /** * CRR stat. * * Chance of landing a critical hit. Capped at 100. */ unsigned short crr; /** * CRD stat. * * Extra damage done when landing a critical hit. */ unsigned short crd; /** * RES stat. * * Chance of resisting a harmful effect. Cant be lower than 15. */ unsigned short res; /** * ACC stat. * * Chance of landing a harmfull effect. Effective cap is 85. */ unsigned short acc; /** * EHP stat. * * EHP is a complex stat that depends on {@link hp} and {@link def}. See * {@link calculate_ehp} for more details. */ unsigned int ehp; /** * DMG stat. * * DMG is a complex stat that depends on {@link atk} and {@link crr} and * {@link crr}. See {@link calculate_ehp} for more details. */ unsigned short dmg; } Stats; /** * Indicates ponderations for stats. * * Ponderations are used to give more or less weight to a stat when calculating * a {@link Result}.rating. * * @todo Implement ponderations. */ typedef struct Stat_Ponderation { /** * HP ponderation. * * Weight given to the HP stat. */ float hp; /** * ATK ponderation. * * Weight given to the ATK stat. */ float atk; /** * DEF ponderation. * * Weight given to the DEF stat. */ float def; /** * SPD ponderation. * * Weight given to the SPD stat. */ float spd; /** * CRR ponderation. * * Weight given to the CRR stat. */ float crr; /** * CRD ponderation. * * Weight given to the CRD stat. */ float crd; /** * RES ponderation. * * Weight given to the RES stat. */ float res; /** * ACC ponderation. * * Weight given to the ACC stat. */ float acc; } Stat_Ponderation; /** * A result of the optimization. * * {@link optimize_thread} loads one for each combination that match all the * criteria passed to the optimizer. */ typedef struct Result { /** * Runes. * * The runes that compose the result. */ unsigned char rune_ids[RUNE_SLOTS][RUNE_ID_LEN]; /** * The rating of the result. * * Calculated by comparing each stat (except EHP and DMG) with the unit * current stats. */ signed int rating; /** * Result stats. * * The stats the unit would have with the result runes equipped. */ struct Stats stats; } Result; typedef struct Optimizer_Output{ // TODO: Document, maybe separate unsigned char verbose; unsigned char quiet; unsigned char debug; unsigned char format; unsigned char output; } Optimizer_Output; typedef struct Optimizer_Options{ // TODO: Document, maybe separate unsigned char help; unsigned char threads; } Optimizer_Options; /** * Options for the optimizer. * * The options that can be passed to the optimizer via arguments. Default values * are assigned in {@link optimize_set_default_options}, and the argument values * are set in {@link optimize_parse_arguments}. */ typedef struct Optimizer_Filters { /** * Unit ID. * * Mandatory, has no default value. Must be de first parameter passed to the * optimizer. For a while, it may contain a Unit name so the size is * increased. */ unsigned char id[UNIT_NAME_LEN]; /** * Rune to consider the levels at during optimization. * * The level option argument is -l or --level, and the value can be * 'current', '12', or '15', for {@link LVCURR}, {@link LV12}, or * {@link LV15}, respectively. If not specifier, the default value is * {@link LVCURR}. * * At current level, the optimization will be done considering the rune as * is, but at levels 12 or 15, if the rune is currently in a lower level, * the main stat will be considered to have the value it would have if the * rune was at that level. */ unsigned char level; /** * Sets of runes that the unit must have. * * These are the sets of runes that the unit must have after optimization. * Any combination of runes that doesn't conform at least these sets will * be discarded. * * The parameter to set this option is -e or --sets, and the sets have to be * passed by name, lowercase, separated by commas. This option is mandatory * and at least one set needs to be passed. Sets can be repeated, but the * sum of runes in every set cant be more than 6. Only the first three sets * passed will be read, the rest will be ignored. * * Some examples: * * @code * --sets violent,energy :OK, optimize for violent,energy * --sets violent,rage :ERROR, too many runes. * --sets shield :OK, optimize for at least one blade * set. * --sets will,will,will :OK, optimize for three will sets. * --sets VioLenT :ERROR, unrecognized set (lowercase!) * --sets will,rage,blade,swift: :OK, check for will,rage,blade (swift * is ignored!) * @endcode */ unsigned char sets[MAX_SETS]; /** * Indicates if the sets in {@link sets} amount for 6 runes. * * This is not a configurable option, but a handy flag. The default value is * {@link FALSE} and will be checked in {@link optimize}. */ unsigned char full_set; /** * Other sets of runes that can be used. * * When the sets passed in th eoption {@link sets} don't amount to 6 runes, * more sets can be indicated here. If so, only runes of the selected sets * will be used to fill the remaining slots, but unless {@link broken_sets} * is set, its not guaranteed that full sets will be formed. * * The parameter to set this option is -i or --opt-sets, and the sets have * to be passed by name, lowercase, separated by commas. This option is * optional, but if used, at least one set needs to be passed. Repeated sets * are ignored, and setting the same that in {@link sets} will have no * effect. It can take as many as rune sets are, but optimization times * increase exponencially for every set. */ unsigned char optional_sets[DIFFERENT_SETS]; /** * Stats allowed in the even slots. * * Use this option to indicate wich stats are allowed to be used in slots 2, * 4 and 6. Only the runes with a main stat in this list will be considered * during the optimization. The parameter is -t or --stats, and the stats * have to be passed separated by commas. * * Accepted values are 'hp', * 'hpflat', 'atk', 'atkflat', 'def', 'defflat', 'spd', 'crr', 'crd', 'res' * and 'acc'. As many as the user want can be passed, and repeated ones will * be ignored. */ unsigned char stats[DIFFERENT_STATS]; /** * Min stats for the unit. * * During optimization, only the runes that leave the unit with at least * this stats will be considered a match. These are optional parameters and, * except min EHP and min DMG, which default to 0, the rest of stat * minimum default to the unit's current values. * * The parameters to set these valuesare: * *
     * -h | --min_hp  N
     * -a | --min_atk N
     * -d | --min_def N
     * -s | --min_spd N
     * -c | --min_crr N
     * -d | --min_crd N
     * -r | --min_res N
     * -f | --min_acc N
     * -p | --min_ehp N
     * -m | --min_dmg N
     * 
*/ Stats *min_stats; /** * Option to format the optput for the GUI. * * This is not intended to be used by the user. It changes the output format * to be consumed by the GUI. To set it, the parameter -g or --gui must be * passed (it takes no options). */ unsigned char gui; /** * Flag to use only unassigned runes. * * If this option is set to {@link TRUE}, only runes in storage (i.e. not * assigned to any unit will be considered during optimization). Runes * assigned to the unit being currently optimizad will of course be * considered even with this option. * * The parameter to set this option is -o or --storage, and it takes no * options. */ unsigned char storage; /** * List of teams to ignore during optimization. * * For every team indicated here, no rune of it's units will be considered * during optimization. If the unit currently being optimized is in one of * these teams, the unit's runes will still be considered. * * The parameter for this option is -x or --no-teams, followed by a comma * separated list of team IDs (not names). If more teams that * {@link MAX_EXCLUSIONS} are indicated, the last ones wil be ignored. */ unsigned char excluded_teams[MAX_EXCLUSIONS][TEAM_ID_LEN]; /** * Indicates how many teams are excluded. * * This is not a configurable option, but a handy counter. The default value * is 0, and will be set when {@link excluded_teams} is populated. */ unsigned char total_excluded_teams; /** * List of units to ignore during optimization. * * For every unit indicated here, it's units will be considered during * optimization. If the unit currently being optimized is in the list, it's * runes will still be considered. * * The parameter for this option is -u or --no-units, followed by a comma * separated list of unit IDs (not names). If more units that * {@link MAX_EXCLUSIONS} are indicated, the last ones wil be ignored. If is * not enough, consider making a team and exclude with * {@link excluded_teams}. */ unsigned char excluded_units[MAX_EXCLUSIONS][UNIT_ID_LEN]; /** * Indicates how many units are excluded. * * This is not a configurable option, but a handy counter. The default value * is 0, and will be set when {@link excluded_units} is populated. */ unsigned char total_excluded_units; /** * Option to enable broken sets. * * If {@link sets} doesn't amount for six runes, this option will discard * any result that is not formed by complete sets. The default value is * {@link FALSE}. To set it, use the parameter -k or --broken (it takes no * options). */ unsigned char broken_sets; /** * Number of thread to be used during optimization. * * Calculation of rune combinations can be done in separateed threads. Each * thread shares the same amount of work as the others, so the more threads, * the faster the optimzation is! The default value is 1, and can be set * passing the parameter -b or --threads, followed by a numeric value. No * more than 8 threads can be used. */ unsigned char threads; /** * Weights for each stat. * * To calculate the rating of a results, different stats can be weighted * differently. The higher the ponderation of a stat, the more effect will * it have in the rating. Default values are 1 for every stat, and the value * can be a float between 0 and 2. * * @todo Implement * @todo Once implemented, document the argument ot use. * @todo Once implemented, document here if EHP and DMG can be weighted. */ Stat_Ponderation ponderation; /** * Output mode for the optimization data. */ unsigned char output_mode; } Optimizer_Filters; /** * Data package used by the optimizer. * * This is the data that {@link optimize_thread} takes. Each thread must have * it's own data package. */ typedef struct Optimizer_Data { /** * Numeric ID of the thread. * * Usually, the spawing order. */ unsigned int thread_id; /** * List of runes. * * These are the runes to test during optimization. The 0 index is not used * and can be empty or have garbage. */ Rune runes[RUNE_SLOTS + 1][LIMIT_RUNES_PER_SLOT]; /** * Runes counter for each slot. * * Indicates the size of each {@link runes}. Index 0 is not used. */ unsigned int count[RUNE_SLOTS + 1]; /** * List of results. * * The thread saves every succesfull combination here. */ Result results[MAX_RESULTS]; /** * Number of results. * * The total number of results the thread has found. */ unsigned int total_results; /** * The options passed to the optimizer. * */ Optimizer_Options *options; /** * The filters passed to the optimizer. * * The threads also needs to know some of these options. */ Optimizer_Filters *filters; /** * The output options passed to the optimizer. * * The threads also needs to know some of these options. */ Optimizer_Output *output; /** * Max testable combinations. * * Not just for this thread, but the sum of combinations to test by every * thread. */ unsigned long long max_combinations; /** * Tested combinations. * * Number of tested combinations at any given point in time. */ unsigned long long tested_combinations; /** * Set count calculated from the options passed to the optimizer. * * A set count to compare every rune combination against. */ Rune_Set_Count requested_set_count; /** * The optimized unit * * The unit being optimized, with all the info previously loaded. */ Unit *unit; /** * Optimization start time * * The time the optimization started in ISO format: * YYYY-MM-DDTHH:MM:SS */ char start_time[20]; } Optimizer_Data; /** * Starts the optimization process. * * Validates the arguments, gets the neccessary runes and starts the * optimization process. On error, it will print a message to stderr. * * @param[in] argc Number of argument passed to the optimizer command. As a * rule, it must me two less than the argc received by the {@link main} * function of the program. * @param[in] argv Arguments passed to the optimizer. As a rule, they must be * the same than the argv received by the {@link main} function of the program * without the first two. The first of them must be a unit ID or name. Apart * from that, only two of them are mandatory: --stats / -t and --sets / -e. * @return {@link SUCCESS} if the optimization was done coreclty, or an error * defined in {@link error.h} if there were problems with any of them. */ int optimize(int argc, char *argv[]);