diff --git a/SerialPrograms/Source/PokemonLZA/Options/PokemonLZA_DonutBerriesOption.cpp b/SerialPrograms/Source/PokemonLZA/Options/PokemonLZA_DonutBerriesOption.cpp index d6df37e402..a21f50a64d 100644 --- a/SerialPrograms/Source/PokemonLZA/Options/PokemonLZA_DonutBerriesOption.cpp +++ b/SerialPrograms/Source/PokemonLZA/Options/PokemonLZA_DonutBerriesOption.cpp @@ -14,74 +14,232 @@ namespace PokemonLZA{ const EnumDropdownDatabase& flavor_power_enum_database(){ static EnumDropdownDatabase database{ + {Flavor_Powers::any, "any", "Any Power"}, + + {Flavor_Powers::sparkling_any, "sparkling-any", "Sparkling: *"}, + {Flavor_Powers::sparkling_all, "sparkling-all", "Sparkling: All Types"}, + {Flavor_Powers::sparkling_normal, "sparkling-normal", "Sparkling: Normal"}, + {Flavor_Powers::sparkling_fire, "sparkling-fire", "Sparkling: Fire"}, + {Flavor_Powers::sparkling_water, "sparkling-water", "Sparkling: Water"}, + {Flavor_Powers::sparkling_electric, "sparkling-electric", "Sparkling: Electric"}, + {Flavor_Powers::sparkling_grass, "sparkling-grass", "Sparkling: Grass"}, + {Flavor_Powers::sparkling_ice, "sparkling-ice", "Sparkling: Ice"}, + {Flavor_Powers::sparkling_fighting, "sparkling-fighting", "Sparkling: Fighting"}, + {Flavor_Powers::sparkling_poison, "sparkling-poison", "Sparkling: Poison"}, + {Flavor_Powers::sparkling_ground, "sparkling-ground", "Sparkling: Ground"}, + {Flavor_Powers::sparkling_flying, "sparkling-flying", "Sparkling: Flying"}, + {Flavor_Powers::sparkling_psychic, "sparkling-psychic", "Sparkling: Psychic"}, + {Flavor_Powers::sparkling_bug, "sparkling-bug", "Sparkling: Bug"}, + {Flavor_Powers::sparkling_rock, "sparkling-rock", "Sparkling: Rock"}, + {Flavor_Powers::sparkling_ghost, "sparkling-ghost", "Sparkling: Ghost"}, + {Flavor_Powers::sparkling_dragon, "sparkling-dragon", "Sparkling: Dragon"}, + {Flavor_Powers::sparkling_dark, "sparkling-dark", "Sparkling: Dark"}, + {Flavor_Powers::sparkling_steel, "sparkling-steel", "Sparkling: Steel"}, + {Flavor_Powers::sparkling_fairy, "sparkling-fairy", "Sparkling: Fairy"}, + {Flavor_Powers::alpha, "alpha", "Alpha"}, {Flavor_Powers::humungo, "humungo", "Humungo"}, {Flavor_Powers::teensy, "teensy", "Teensy"}, - {Flavor_Powers::sparkling, "sparkling", "Sparkling"}, - {Flavor_Powers::atk, "atk", "Attack"}, - {Flavor_Powers::spatk, "spatk", "Sp. Atk"}, - {Flavor_Powers::move, "move", "Move"}, - {Flavor_Powers::speed, "speed", "Speed"}, - {Flavor_Powers::bighaul, "bighaul", "Big Haul"}, - {Flavor_Powers::item, "item", "Item"}, - {Flavor_Powers::megacharge, "megacharge", "Mega Charge"}, - {Flavor_Powers::megaconserve,"megaconserve","Mega Conserve"}, - {Flavor_Powers::def, "def", "Defense"}, - {Flavor_Powers::spdef, "spdef", "Sp. Def"}, - {Flavor_Powers::resistance, "resistance", "Resistance"}, - {Flavor_Powers::encounter, "encounter", "Encounter"}, - {Flavor_Powers::catching, "catching", "Catching"}, - }; - return database; -} -const EnumDropdownDatabase& pokemon_power_enum_database(){ - static EnumDropdownDatabase database{ - {Power_Pokemon_Types::all, "all", "All Types"}, - {Power_Pokemon_Types::normal, "normal", "Normal"}, - {Power_Pokemon_Types::fire, "fire", "Fire"}, - {Power_Pokemon_Types::water, "water", "Water"}, - {Power_Pokemon_Types::electric, "electric", "Electric"}, - {Power_Pokemon_Types::grass, "grass", "Grass"}, - {Power_Pokemon_Types::ice, "ice", "Ice"}, - {Power_Pokemon_Types::fighting, "fighting", "Fighting"}, - {Power_Pokemon_Types::poison, "poison", "Poison"}, - {Power_Pokemon_Types::ground, "ground", "Ground"}, - {Power_Pokemon_Types::flying, "flying", "Flying"}, - {Power_Pokemon_Types::psychic, "psychic", "Psychic"}, - {Power_Pokemon_Types::bug, "bug", "Bug"}, - {Power_Pokemon_Types::rock, "rock", "Rock"}, - {Power_Pokemon_Types::ghost, "ghost", "Ghost"}, - {Power_Pokemon_Types::dragon, "dragon", "Dragon"}, - {Power_Pokemon_Types::dark, "dark", "Dark"}, - {Power_Pokemon_Types::steel, "steel", "Steel"}, - {Power_Pokemon_Types::fairy, "fairy", "Fairy"}, - }; - return database; -} -const EnumDropdownDatabase& item_power_enum_database(){ - static EnumDropdownDatabase database{ - {Power_Item_Types::berries, "berries", "Berries"}, - {Power_Item_Types::candies, "candies", "Candies"}, - {Power_Item_Types::treasure, "treasure", "Treasure"}, - {Power_Item_Types::pokeballs, "pokeballs", "Poke Balls"}, - {Power_Item_Types::special, "special", "Special"}, - {Power_Item_Types::coins, "coins", "Coins"}, + + {Flavor_Powers::item_any, "item-any", "Item: *"}, + {Flavor_Powers::item_berries, "item-berries", "Item: Berries"}, + {Flavor_Powers::item_candies, "item-candies", "Item: Candies"}, + {Flavor_Powers::item_treasure, "item-treasure", "Item: Treasure"}, + {Flavor_Powers::item_pokeballs, "item-pokeballs", "Item: Poké Balls"}, + {Flavor_Powers::item_special, "item-special", "Item: Special"}, + {Flavor_Powers::item_coins, "item-coins", "Item: Coins"}, + {Flavor_Powers::bighaul, "big-haul", "Big Haul"}, + {Flavor_Powers::megacharge, "mega-charge", "Mega Charge"}, + {Flavor_Powers::megaconserve, "mega-conserve", "Mega Conserve"}, + + {Flavor_Powers::catching_any, "catching-any", "Catching: *"}, + {Flavor_Powers::catching_all, "catching-all", "Catching: All Types"}, + {Flavor_Powers::catching_normal, "catching-normal", "Catching: Normal"}, + {Flavor_Powers::catching_fire, "catching-fire", "Catching: Fire"}, + {Flavor_Powers::catching_water, "catching-water", "Catching: Water"}, + {Flavor_Powers::catching_electric, "catching-electric", "Catching: Electric"}, + {Flavor_Powers::catching_grass, "catching-grass", "Catching: Grass"}, + {Flavor_Powers::catching_ice, "catching-ice", "Catching: Ice"}, + {Flavor_Powers::catching_fighting, "catching-fighting", "Catching: Fighting"}, + {Flavor_Powers::catching_poison, "catching-poison", "Catching: Poison"}, + {Flavor_Powers::catching_ground, "catching-ground", "Catching: Ground"}, + {Flavor_Powers::catching_flying, "catching-flying", "Catching: Flying"}, + {Flavor_Powers::catching_psychic, "catching-psychic", "Catching: Psychic"}, + {Flavor_Powers::catching_bug, "catching-bug", "Catching: Bug"}, + {Flavor_Powers::catching_rock, "catching-rock", "Catching: Rock"}, + {Flavor_Powers::catching_ghost, "catching-ghost", "Catching: Ghost"}, + {Flavor_Powers::catching_dragon, "catching-dragon", "Catching: Dragon"}, + {Flavor_Powers::catching_dark, "catching-dark", "Catching: Dark"}, + {Flavor_Powers::catching_steel, "catching-steel", "Catching: Steel"}, + {Flavor_Powers::catching_fairy, "catching-fairy", "Catching: Fairy"}, + {Flavor_Powers::encounter, "encounter", "Encounter"}, + + {Flavor_Powers::move_any, "move-any", "Move: *"}, + {Flavor_Powers::move_normal, "move-normal", "Move: Normal"}, + {Flavor_Powers::move_fire, "move-fire", "Move: Fire"}, + {Flavor_Powers::move_water, "move-water", "Move: Water"}, + {Flavor_Powers::move_electric, "move-electric", "Move: Electric"}, + {Flavor_Powers::move_grass, "move-grass", "Move: Grass"}, + {Flavor_Powers::move_ice, "move-ice", "Move: Ice"}, + {Flavor_Powers::move_fighting, "move-fighting", "Move: Fighting"}, + {Flavor_Powers::move_poison, "move-poison", "Move: Poison"}, + {Flavor_Powers::move_ground, "move-ground", "Move: Ground"}, + {Flavor_Powers::move_flying, "move-flying", "Move: Flying"}, + {Flavor_Powers::move_psychic, "move-psychic", "Move: Psychic"}, + {Flavor_Powers::move_bug, "move-bug", "Move: Bug"}, + {Flavor_Powers::move_rock, "move-rock", "Move: Rock"}, + {Flavor_Powers::move_ghost, "move-ghost", "Move: Ghost"}, + {Flavor_Powers::move_dragon, "move-dragon", "Move: Dragon"}, + {Flavor_Powers::move_dark, "move-dark", "Move: Dark"}, + {Flavor_Powers::move_steel, "move-steel", "Move: Steel"}, + {Flavor_Powers::move_fairy, "move-fairy", "Move: Fairy"}, + {Flavor_Powers::atk, "atk", "Attack"}, + {Flavor_Powers::spatk, "spatk", "Sp. Atk"}, + {Flavor_Powers::speed, "speed", "Speed"}, + + {Flavor_Powers::resistance_any, "resistance-any", "Resistance: *"}, + {Flavor_Powers::resistance_normal, "resistance-normal", "Resistance: Normal"}, + {Flavor_Powers::resistance_fire, "resistance-fire", "Resistance: Fire"}, + {Flavor_Powers::resistance_water, "resistance-water", "Resistance: Water"}, + {Flavor_Powers::resistance_electric, "resistance-electric", "Resistance: Electric"}, + {Flavor_Powers::resistance_grass, "resistance-grass", "Resistance: Grass"}, + {Flavor_Powers::resistance_ice, "resistance-ice", "Resistance: Ice"}, + {Flavor_Powers::resistance_fighting, "resistance-fighting", "Resistance: Fighting"}, + {Flavor_Powers::resistance_poison, "resistance-poison", "Resistance: Poison"}, + {Flavor_Powers::resistance_ground, "resistance-ground", "Resistance: Ground"}, + {Flavor_Powers::resistance_flying, "resistance-flying", "Resistance: Flying"}, + {Flavor_Powers::resistance_psychic, "resistance-psychic", "Resistance: Psychic"}, + {Flavor_Powers::resistance_bug, "resistance-bug", "Resistance: Bug"}, + {Flavor_Powers::resistance_rock, "resistance-rock", "Resistance: Rock"}, + {Flavor_Powers::resistance_ghost, "resistance-ghost", "Resistance: Ghost"}, + {Flavor_Powers::resistance_dragon, "resistance-dragon", "Resistance: Dragon"}, + {Flavor_Powers::resistance_dark, "resistance-dark", "Resistance: Dark"}, + {Flavor_Powers::resistance_steel, "resistance-steel", "Resistance: Steel"}, + {Flavor_Powers::resistance_fairy, "resistance-fairy", "Resistance: Fairy"}, + {Flavor_Powers::def, "def", "Defense"}, + {Flavor_Powers::spdef, "spdef", "Sp. Def"}, }; return database; -} +}; + const EnumDropdownDatabase& power_level_enum_database(){ static EnumDropdownDatabase database{ - {Power_Level::one, "one", "Lv. 1"}, - {Power_Level::two, "two", "Lv. 2"}, - {Power_Level::three, "three", "Lv. 3"}, + {Power_Level::any, "any", "Any Level"}, + {Power_Level::one, "one", "Lv. 1"}, + {Power_Level::two, "two", "Lv. 2"}, + {Power_Level::three, "three", "Lv. 3"}, + {Power_Level::one_two, "one_two", "Lv. 1 or 2"}, + {Power_Level::two_three, "two_three", "Lv. 2 or 3"}, }; return database; } std::string FlavorPowerTableEntry::to_str() const{ + std::string result; + result += "Limit: " + std::to_string(limit) + ", "; + result += get_single_flavor_power_string(1) + ", "; + result += get_single_flavor_power_string(2) + ", "; + result += get_single_flavor_power_string(3); + return result; +} + +std::vector FlavorPowerTableEntry::get_entry_flavor_power_strings() const{ + std::vector powers; + for (int c = 1; c <= 3; c++){ + std::string power_string = get_single_flavor_power_string(c); + powers.push_back(power_string); + } + return powers; +} + +std::string FlavorPowerTableEntry::get_single_flavor_power_string(int power_index) const{ std::string selected_power; + Flavor_Powers power; + Power_Level level; + + switch (power_index){ + case 1: + power = power_1; + level = level_1; + break; + case 2: + power = power_2; + level = level_2; + break; + case 3: + power = power_3; + level = level_3; + break; + default: + return "INVALID"; + } switch (power){ + case Flavor_Powers::any: + selected_power += "any-power-"; + break; + + case Flavor_Powers::sparkling_any: + selected_power += "sparkling-power-any-"; + break; + case Flavor_Powers::sparkling_all: + selected_power += "sparkling-power-all-types-"; + break; + case Flavor_Powers::sparkling_normal: + selected_power += "sparkling-power-normal-"; + break; + case Flavor_Powers::sparkling_fire: + selected_power += "sparkling-power-fire-"; + break; + case Flavor_Powers::sparkling_water: + selected_power += "sparkling-power-water-"; + break; + case Flavor_Powers::sparkling_electric: + selected_power += "sparkling-power-electric-"; + break; + case Flavor_Powers::sparkling_grass: + selected_power += "sparkling-power-grass-"; + break; + case Flavor_Powers::sparkling_ice: + selected_power += "sparkling-power-ice-"; + break; + case Flavor_Powers::sparkling_fighting: + selected_power += "sparkling-power-fighting-"; + break; + case Flavor_Powers::sparkling_poison: + selected_power += "sparkling-power-poison-"; + break; + case Flavor_Powers::sparkling_ground: + selected_power += "sparkling-power-ground-"; + break; + case Flavor_Powers::sparkling_flying: + selected_power += "sparkling-power-flying-"; + break; + case Flavor_Powers::sparkling_psychic: + selected_power += "sparkling-power-psychic-"; + break; + case Flavor_Powers::sparkling_bug: + selected_power += "sparkling-power-bug-"; + break; + case Flavor_Powers::sparkling_rock: + selected_power += "sparkling-power-rock-"; + break; + case Flavor_Powers::sparkling_ghost: + selected_power += "sparkling-power-ghost-"; + break; + case Flavor_Powers::sparkling_dragon: + selected_power += "sparkling-power-dragon-"; + break; + case Flavor_Powers::sparkling_dark: + selected_power += "sparkling-power-dark-"; + break; + case Flavor_Powers::sparkling_steel: + selected_power += "sparkling-power-steel-"; + break; + case Flavor_Powers::sparkling_fairy: + selected_power += "sparkling-power-fairy-"; + break; + case Flavor_Powers::alpha: selected_power += "alpha-power-"; break; @@ -91,8 +249,158 @@ std::string FlavorPowerTableEntry::to_str() const{ case Flavor_Powers::teensy: selected_power += "teensy-power-"; break; - case Flavor_Powers::sparkling: - selected_power += "sparkling-power-"; + + case Flavor_Powers::item_any: + selected_power += "item-power-any-"; + break; + case Flavor_Powers::item_berries: + selected_power += "item-power-berries-"; + break; + case Flavor_Powers::item_candies: + selected_power += "item-power-candies-"; + break; + case Flavor_Powers::item_treasure: + selected_power += "item-power-treasure-"; + break; + case Flavor_Powers::item_pokeballs: + selected_power += "item-power-pokeballs-"; + break; + case Flavor_Powers::item_special: + selected_power += "item-power-special-"; + break; + case Flavor_Powers::item_coins: + selected_power += "item-power-coins-"; + break; + case Flavor_Powers::bighaul: + selected_power += "big-haul-power-"; + break; + case Flavor_Powers::megacharge: + selected_power += "mega-charge-power-"; + break; + case Flavor_Powers::megaconserve: + selected_power += "mega-conserve-power-"; + break; + + case Flavor_Powers::catching_any: + selected_power += "catching-power-any-"; + break; + case Flavor_Powers::catching_all: + selected_power += "catching-power-all-"; + break; + case Flavor_Powers::catching_normal: + selected_power += "catching-power-normal-"; + break; + case Flavor_Powers::catching_fire: + selected_power += "catching-power-fire-"; + break; + case Flavor_Powers::catching_water: + selected_power += "catching-power-water-"; + break; + case Flavor_Powers::catching_electric: + selected_power += "catching-power-electric-"; + break; + case Flavor_Powers::catching_grass: + selected_power += "catching-power-grass-"; + break; + case Flavor_Powers::catching_ice: + selected_power += "catching-power-ice-"; + break; + case Flavor_Powers::catching_fighting: + selected_power += "catching-power-fighting-"; + break; + case Flavor_Powers::catching_poison: + selected_power += "catching-power-poison-"; + break; + case Flavor_Powers::catching_ground: + selected_power += "catching-power-ground-"; + break; + case Flavor_Powers::catching_flying: + selected_power += "catching-power-flying-"; + break; + case Flavor_Powers::catching_psychic: + selected_power += "catching-power-psychic-"; + break; + case Flavor_Powers::catching_bug: + selected_power += "catching-power-bug-"; + break; + case Flavor_Powers::catching_rock: + selected_power += "catching-power-rock-"; + break; + case Flavor_Powers::catching_ghost: + selected_power += "catching-power-ghost-"; + break; + case Flavor_Powers::catching_dragon: + selected_power += "catching-power-dragon-"; + break; + case Flavor_Powers::catching_dark: + selected_power += "catching-power-dark-"; + break; + case Flavor_Powers::catching_steel: + selected_power += "catching-power-steel-"; + break; + case Flavor_Powers::catching_fairy: + selected_power += "catching-power-fairy-"; + break; + case Flavor_Powers::encounter: + selected_power += "encounter-power-"; + break; + + case Flavor_Powers::move_any: + selected_power += "move-power-any-"; + break; + case Flavor_Powers::move_normal: + selected_power += "move-power-normal-"; + break; + case Flavor_Powers::move_fire: + selected_power += "move-power-fire-"; + break; + case Flavor_Powers::move_water: + selected_power += "move-power-water-"; + break; + case Flavor_Powers::move_electric: + selected_power += "move-power-electric-"; + break; + case Flavor_Powers::move_grass: + selected_power += "move-power-grass-"; + break; + case Flavor_Powers::move_ice: + selected_power += "move-power-ice-"; + break; + case Flavor_Powers::move_fighting: + selected_power += "move-power-fighting-"; + break; + case Flavor_Powers::move_poison: + selected_power += "move-power-poison-"; + break; + case Flavor_Powers::move_ground: + selected_power += "move-power-ground-"; + break; + case Flavor_Powers::move_flying: + selected_power += "move-power-flying-"; + break; + case Flavor_Powers::move_psychic: + selected_power += "move-power-psychic-"; + break; + case Flavor_Powers::move_bug: + selected_power += "move-power-bug-"; + break; + case Flavor_Powers::move_rock: + selected_power += "move-power-rock-"; + break; + case Flavor_Powers::move_ghost: + selected_power += "move-power-ghost-"; + break; + case Flavor_Powers::move_dragon: + selected_power += "move-power-dragon-"; + break; + case Flavor_Powers::move_dark: + selected_power += "move-power-dark-"; + break; + case Flavor_Powers::move_steel: + selected_power += "move-power-steel-"; + break; + case Flavor_Powers::move_fairy: + selected_power += "move-power-fairy-"; break; case Flavor_Powers::atk: selected_power += "attack-power-"; @@ -100,23 +408,66 @@ std::string FlavorPowerTableEntry::to_str() const{ case Flavor_Powers::spatk: selected_power += "sp-atk-power-"; break; - case Flavor_Powers::move: - selected_power += "move-power-"; - break; case Flavor_Powers::speed: selected_power += "speed-power-"; break; - case Flavor_Powers::bighaul: - selected_power += "big-haul-power-"; + + case Flavor_Powers::resistance_any: + selected_power += "resistance-power-any-"; break; - case Flavor_Powers::item: - selected_power += "item-power-"; + case Flavor_Powers::resistance_normal: + selected_power += "resistance-power-normal-"; break; - case Flavor_Powers::megacharge: - selected_power += "mega-power-charging-"; + case Flavor_Powers::resistance_fire: + selected_power += "resistance-power-fire-"; break; - case Flavor_Powers::megaconserve: - selected_power += "mega-power-conservation-"; + case Flavor_Powers::resistance_water: + selected_power += "resistance-power-water-"; + break; + case Flavor_Powers::resistance_electric: + selected_power += "resistance-power-electric-"; + break; + case Flavor_Powers::resistance_grass: + selected_power += "resistance-power-grass-"; + break; + case Flavor_Powers::resistance_ice: + selected_power += "resistance-power-ice-"; + break; + case Flavor_Powers::resistance_fighting: + selected_power += "resistance-power-fighting-"; + break; + case Flavor_Powers::resistance_poison: + selected_power += "resistance-power-poison-"; + break; + case Flavor_Powers::resistance_ground: + selected_power += "resistance-power-ground-"; + break; + case Flavor_Powers::resistance_flying: + selected_power += "resistance-power-flying-"; + break; + case Flavor_Powers::resistance_psychic: + selected_power += "resistance-power-psychic-"; + break; + case Flavor_Powers::resistance_bug: + selected_power += "resistance-power-bug-"; + break; + case Flavor_Powers::resistance_rock: + selected_power += "resistance-power-rock-"; + break; + case Flavor_Powers::resistance_ghost: + selected_power += "resistance-power-ghost-"; + break; + case Flavor_Powers::resistance_dragon: + selected_power += "resistance-power-dragon-"; + break; + case Flavor_Powers::resistance_dark: + selected_power += "resistance-power-dark-"; + break; + case Flavor_Powers::resistance_steel: + selected_power += "resistance-power-steel-"; + break; + case Flavor_Powers::resistance_fairy: + selected_power += "resistance-power-fairy-"; break; case Flavor_Powers::def: selected_power += "defense-power-"; @@ -124,106 +475,15 @@ std::string FlavorPowerTableEntry::to_str() const{ case Flavor_Powers::spdef: selected_power += "sp-def-power-"; break; - case Flavor_Powers::resistance: - selected_power += "resistance-power-"; + default: + selected_power += "INVALID-"; break; - case Flavor_Powers::encounter: - selected_power += "encounter-power-"; - break; - case Flavor_Powers::catching: - selected_power += "catching-power-"; - break; - } - - if (power == Flavor_Powers::catching || power == Flavor_Powers::sparkling || power == Flavor_Powers::move || power == Flavor_Powers::resistance) { - switch (pokemon_type) { - case Power_Pokemon_Types::all: - if (power == Flavor_Powers::move || power == Flavor_Powers::resistance) { - selected_power += "all-types-INVALID-SELECTION-"; - break; - } - selected_power += "all-types-"; - break; - case Power_Pokemon_Types::normal: - selected_power += "normal-"; - break; - case Power_Pokemon_Types::fire: - selected_power += "fire-"; - break; - case Power_Pokemon_Types::water: - selected_power += "water-"; - break; - case Power_Pokemon_Types::electric: - selected_power += "electric-"; - break; - case Power_Pokemon_Types::grass: - selected_power += "grass-"; - break; - case Power_Pokemon_Types::ice: - selected_power += "ice-"; - break; - case Power_Pokemon_Types::fighting: - selected_power += "fighting-"; - break; - case Power_Pokemon_Types::poison: - selected_power += "poison-"; - break; - case Power_Pokemon_Types::ground: - selected_power += "ground-"; - break; - case Power_Pokemon_Types::flying: - selected_power += "flying-"; - break; - case Power_Pokemon_Types::psychic: - selected_power += "psychic-"; - break; - case Power_Pokemon_Types::bug: - selected_power += "bug-"; - break; - case Power_Pokemon_Types::rock: - selected_power += "rock-"; - break; - case Power_Pokemon_Types::ghost: - selected_power += "ghost-"; - break; - case Power_Pokemon_Types::dragon: - selected_power += "dragon-"; - break; - case Power_Pokemon_Types::dark: - selected_power += "dark-"; - break; - case Power_Pokemon_Types::steel: - selected_power += "steel-"; - break; - case Power_Pokemon_Types::fairy: - selected_power += "fairy-"; - break; - } - } - else if (power == Flavor_Powers::item) { - switch (item_type) { - case Power_Item_Types::berries: - selected_power += "berries-"; - break; - case Power_Item_Types::candies: - selected_power += "candies-"; - break; - case Power_Item_Types::treasure: - selected_power += "treasure-"; - break; - case Power_Item_Types::pokeballs: - selected_power += "poke-balls-"; - break; - case Power_Item_Types::special: - selected_power += "special-"; - break; - case Power_Item_Types::coins: - selected_power += "coins-"; - break; - } } switch (level) { + case Power_Level::any: + selected_power += "any"; + break; case Power_Level::one: selected_power += "1"; break; @@ -233,8 +493,16 @@ std::string FlavorPowerTableEntry::to_str() const{ case Power_Level::three: selected_power += "3"; break; + case Power_Level::one_two: + selected_power += "12"; + break; + case Power_Level::two_three: + selected_power += "23"; + break; + default: + selected_power += "INVALID"; + break; } - return selected_power; } @@ -304,64 +572,47 @@ std::vector> DonutBerriesTable::make_defaults( -FlavorPowerTableRow::~FlavorPowerTableRow(){ - power.remove_listener(*this); -} FlavorPowerTableRow::FlavorPowerTableRow(EditableTableOption& parent_table) : EditableTableRow(parent_table) - , power(flavor_power_enum_database(), LockMode::LOCK_WHILE_RUNNING, Flavor_Powers::alpha) - , type_pokemon(pokemon_power_enum_database(), LockMode::LOCK_WHILE_RUNNING, Power_Pokemon_Types::all) - , type_item(item_power_enum_database(), LockMode::LOCK_WHILE_RUNNING, Power_Item_Types::berries) - , level(power_level_enum_database(), LockMode::LOCK_WHILE_RUNNING, Power_Level::three) + , limit(LockMode::LOCK_WHILE_RUNNING, 1, 999, 1, 1) + , power_1(flavor_power_enum_database(), LockMode::LOCK_WHILE_RUNNING, Flavor_Powers::alpha) + , level_1(power_level_enum_database(), LockMode::LOCK_WHILE_RUNNING, Power_Level::three) + , power_2(flavor_power_enum_database(), LockMode::LOCK_WHILE_RUNNING, Flavor_Powers::any) + , level_2(power_level_enum_database(), LockMode::LOCK_WHILE_RUNNING, Power_Level::any) + , power_3(flavor_power_enum_database(), LockMode::LOCK_WHILE_RUNNING, Flavor_Powers::any) + , level_3(power_level_enum_database(), LockMode::LOCK_WHILE_RUNNING, Power_Level::any) { - PA_ADD_OPTION(power); - PA_ADD_OPTION(type_pokemon); - PA_ADD_OPTION(type_item); - PA_ADD_OPTION(level); - - FlavorPowerTableRow::on_config_value_changed(this); - power.add_listener(*this); + PA_ADD_OPTION(limit); + PA_ADD_OPTION(power_1); + PA_ADD_OPTION(level_1); + PA_ADD_OPTION(power_2); + PA_ADD_OPTION(level_2); + PA_ADD_OPTION(power_3); + PA_ADD_OPTION(level_3); } std::unique_ptr FlavorPowerTableRow::clone() const{ std::unique_ptr ret(new FlavorPowerTableRow(parent())); - ret->power.set(power); - ret->type_pokemon.set(type_pokemon); - ret->type_item.set(type_item); - ret->level.set(level); + ret->limit.set(limit); + ret->power_1.set(power_1); + ret->level_1.set(level_1); + ret->power_2.set(power_2); + ret->level_2.set(level_2); + ret->power_3.set(power_3); + ret->level_3.set(level_3); return ret; } FlavorPowerTableEntry FlavorPowerTableRow::snapshot() const{ - return FlavorPowerTableEntry{power, type_pokemon, type_item, level}; -} -void FlavorPowerTableRow::on_config_value_changed(void* object){ - Flavor_Powers power = this->power; - - type_item.set_visibility( - power == Flavor_Powers::item - ? ConfigOptionState::ENABLED - : ConfigOptionState::HIDDEN - ); - - bool req_poke_types = - power == Flavor_Powers::sparkling || - power == Flavor_Powers::catching || - power == Flavor_Powers::move || - power == Flavor_Powers::resistance; - - type_pokemon.set_visibility( - req_poke_types - ? ConfigOptionState::ENABLED - : ConfigOptionState::HIDDEN - ); + return FlavorPowerTableEntry{limit, power_1, level_1, power_2, level_2, power_3, level_3}; } FlavorPowerTable::FlavorPowerTable() : EditableTableOption_t( - "Flavor Powers Table:
" - "Add all desired flavor powers to this table. " - "The program will check the powers of any baked donut and compare them against the selected items in the table. " - "Be sure to set the correct Number of Powers to Match above." - "
Note: \"All Types\" means the All Types Power in-game.", + "Donuts Table:
" + "Add all desired donuts to this table. " + "The program will check the powers of a made donut and compare the powers to each row in the table." + "
A keep limit can be set for each donut. Make sure you have enough berries to make this many donuts!" + "
Note that a donut with a power level of 3 will be included in the limit for donuts of \"Lv. 2 or 3\"" + "
Note: \"All Types\" means the All Types Power in-game. \"*\" means match any type for the specified power", LockMode::LOCK_WHILE_RUNNING, make_defaults() ) @@ -371,10 +622,13 @@ std::vector FlavorPowerTable::snapshot(){ } std::vector FlavorPowerTable::make_header() const{ return { - "Flavor Power ", - "Pokemon Type ", - "Item Type ", - "Level ", + "Keep Limit", + "Flavor Power 1 ", + "Level 1 ", + "Flavor Power 2 ", + "Level 2 ", + "Flavor Power 3 ", + "Level 3 ", }; } std::vector> FlavorPowerTable::make_defaults(){ diff --git a/SerialPrograms/Source/PokemonLZA/Options/PokemonLZA_DonutBerriesOption.h b/SerialPrograms/Source/PokemonLZA/Options/PokemonLZA_DonutBerriesOption.h index 7fe6df59dd..41963fd5c3 100644 --- a/SerialPrograms/Source/PokemonLZA/Options/PokemonLZA_DonutBerriesOption.h +++ b/SerialPrograms/Source/PokemonLZA/Options/PokemonLZA_DonutBerriesOption.h @@ -17,69 +17,134 @@ namespace NintendoSwitch{ namespace PokemonLZA{ enum class Flavor_Powers { + // Subjective ordering by group + any, + + sparkling_any, + sparkling_all, + sparkling_normal, + sparkling_fire, + sparkling_water, + sparkling_electric, + sparkling_grass, + sparkling_ice, + sparkling_fighting, + sparkling_poison, + sparkling_ground, + sparkling_flying, + sparkling_psychic, + sparkling_bug, + sparkling_rock, + sparkling_ghost, + sparkling_dragon, + sparkling_dark, + sparkling_steel, + sparkling_fairy, + alpha, humungo, teensy, - sparkling, - atk, - spatk, - move, - speed, + + item_any, + item_berries, + item_candies, + item_treasure, + item_pokeballs, + item_special, + item_coins, bighaul, - item, megacharge, megaconserve, - def, - spdef, - resistance, + + catching_any, + catching_all, + catching_normal, + catching_fire, + catching_water, + catching_electric, + catching_grass, + catching_ice, + catching_fighting, + catching_poison, + catching_ground, + catching_flying, + catching_psychic, + catching_bug, + catching_rock, + catching_ghost, + catching_dragon, + catching_dark, + catching_steel, + catching_fairy, encounter, - catching, -}; -enum class Power_Pokemon_Types { - all, //Accept only the All type (ex. Sparkling Power: All Types (Lv. 3)) Applies to catching and sparkling, but not move or resist - normal, - fire, - water, - electric, - grass, - ice, - fighting, - poison, - ground, - flying, - psychic, - bug, - rock, - ghost, - dragon, - dark, - steel, - fairy, -}; + move_any, + move_normal, + move_fire, + move_water, + move_electric, + move_grass, + move_ice, + move_fighting, + move_poison, + move_ground, + move_flying, + move_psychic, + move_bug, + move_rock, + move_ghost, + move_dragon, + move_dark, + move_steel, + move_fairy, + atk, + spatk, + speed, -enum class Power_Item_Types { - berries, - candies, - treasure, - pokeballs, - special, - coins, + resistance_any, + resistance_normal, + resistance_fire, + resistance_water, + resistance_electric, + resistance_grass, + resistance_ice, + resistance_fighting, + resistance_poison, + resistance_ground, + resistance_flying, + resistance_psychic, + resistance_bug, + resistance_rock, + resistance_ghost, + resistance_dragon, + resistance_dark, + resistance_steel, + resistance_fairy, + def, + spdef, }; enum class Power_Level{ + any, one, two, three, + one_two, + two_three, }; struct FlavorPowerTableEntry{ - Flavor_Powers power; - Power_Pokemon_Types pokemon_type; - Power_Item_Types item_type; - Power_Level level; + uint16_t limit; + Flavor_Powers power_1; + Power_Level level_1; + Flavor_Powers power_2; + Power_Level level_2; + Flavor_Powers power_3; + Power_Level level_3; std::string to_str() const; + std::vector get_entry_flavor_power_strings() const; + std::string get_single_flavor_power_string(int power_index) const; }; @@ -113,20 +178,19 @@ class DonutBerriesTable : public EditableTableOption_t{ //Donut Flavor Power selection class FlavorPowerTableRow : public EditableTableRow, public ConfigOption::Listener{ public: - ~FlavorPowerTableRow(); FlavorPowerTableRow(EditableTableOption& parent_table); virtual std::unique_ptr clone() const override; FlavorPowerTableEntry snapshot() const; private: - virtual void on_config_value_changed(void* object) override; - -private: - EnumDropdownCell power; - EnumDropdownCell type_pokemon; - EnumDropdownCell type_item; - EnumDropdownCell level; + SimpleIntegerCell limit; + EnumDropdownCell power_1; + EnumDropdownCell level_1; + EnumDropdownCell power_2; + EnumDropdownCell level_2; + EnumDropdownCell power_3; + EnumDropdownCell level_3; }; diff --git a/SerialPrograms/Source/PokemonLZA/Programs/Farming/PokemonLZA_DonutMaker.cpp b/SerialPrograms/Source/PokemonLZA/Programs/Farming/PokemonLZA_DonutMaker.cpp index 14e193e597..22d2216501 100644 --- a/SerialPrograms/Source/PokemonLZA/Programs/Farming/PokemonLZA_DonutMaker.cpp +++ b/SerialPrograms/Source/PokemonLZA/Programs/Farming/PokemonLZA_DonutMaker.cpp @@ -60,16 +60,19 @@ class DonutMaker_Descriptor::Stats : public StatsTracker{ public: Stats() : matched(m_stats["Donuts Matched"]) + , kept(m_stats["Donuts Kept"]) , resets(m_stats["Resets"]) , errors(m_stats["Errors"]) { // TODO: Add more stats here m_display_order.emplace_back("Donuts Matched"); + m_display_order.emplace_back("Donuts Kept"); m_display_order.emplace_back("Resets"); m_display_order.emplace_back("Errors", HIDDEN_IF_ZERO); } std::atomic& matched; + std::atomic& kept; std::atomic& resets; std::atomic& errors; }; @@ -87,18 +90,12 @@ DonutMaker::DonutMaker() true ) , BERRIES("Berries:
The berries used to make the donut. Minimum 3 berries, maximum 8 berries.") - , NUM_POWER_REQUIRED( - "Number of Powers to Match:
How many of a donut's powers must be in the the table below. Minimum 1, maximum 3. " - "
Ex. For a target donut of Big Haul Lv.3, Berry Lv.3, and any or none for the 3rd power, set the number as 2." - "
Then, in the flavor powers table, make sure to add Big Haul Lv.3 and Berry Lv. 3.", + , MAX_KEEPERS( + "Maximum Number of Donuts to Keep:
" + "This takes precedent over the limits set in the Donuts table." + "
Make sure you have enough berries to make this many donuts. The program will fail when not given enough berries.", LockMode::LOCK_WHILE_RUNNING, - 1, 1, 3 - ) - , NUM_DONUTS( - "Number of Donuts:
The program continues resetting and making donuts of required powers until this many donuts of required powers are made." - "
Make sure you have enough berries to make this many donuts. The program will fail when not given enough berries.", - LockMode::LOCK_WHILE_RUNNING, - 1, 1, 999 + 1, 1, 999 ) , GO_HOME_WHEN_DONE(false) , NOTIFICATION_DONUT_FOUND( @@ -117,33 +114,93 @@ DonutMaker::DonutMaker() { PA_ADD_OPTION(LANGUAGE); PA_ADD_OPTION(BERRIES); - PA_ADD_OPTION(NUM_POWER_REQUIRED); - PA_ADD_OPTION(NUM_DONUTS); + PA_ADD_OPTION(MAX_KEEPERS); PA_ADD_OPTION(FLAVOR_POWERS); PA_ADD_OPTION(GO_HOME_WHEN_DONE); PA_ADD_OPTION(NOTIFICATIONS); } +// Split flavor power notation into its individual tokens +std::vector get_flavor_power_tokens(const std::string& power_string){ + std::vector tokens; + size_t start = 0; + size_t end = power_string.find('-'); + while (end != std::string::npos){ + tokens.push_back(power_string.substr(start, end - start)); + start = end + 1; + end = power_string.find('-', start); + } + tokens.push_back(power_string.substr(start)); + return tokens; +} + +// Check if all flavor tokens are in the donut flavor tokens +// Apply some extra logic for "any" token and the special level tokens +bool flavor_tokens_are_subset(const std::vector& subset, const std::vector& superset){ + for (const std::string& token : subset){ + if (token == "any"){ + continue; + } + else if (token == "12"){ + if (std::find(superset.begin(), superset.end(), "1") == superset.end() && std::find(superset.begin(), superset.end(), "2") == superset.end()){ + return false; + } + } + else if (token == "23"){ + if (std::find(superset.begin(), superset.end(), "2") == superset.end() && std::find(superset.begin(), superset.end(), "3") == superset.end()){ + return false; + } + } + else if (std::find(superset.begin(), superset.end(), token) == superset.end()){ + return false; + } + } + return true; +} + +// Check if a donut matches an individual table entry +bool donut_matches_powers(SingleSwitchProgramEnvironment& env, std::vector& donut_powers, const std::vector& target_powers){ + for (const std::string& target_power : target_powers){ + std::vector target_tokens = get_flavor_power_tokens(target_power); + bool matched = false; + for (const std::string& donut_power : donut_powers){ + env.log("Comparing target power " + target_power + " with donut power " + donut_power); + std::vector donut_tokens = get_flavor_power_tokens(donut_power); + if (flavor_tokens_are_subset(target_tokens, donut_tokens)){ + env.log("Power matched!"); + matched = true; + break; + } + } + if (!matched){ + return false; + } + } + return true; +} + // Read flavor power and check if they match user requirement. +// Keep or discard the donut depending on the user defined limit. // Return true if the user requirement is fulfilled. -bool DonutMaker::match_powers(SingleSwitchProgramEnvironment& env, ProControllerContext& context) { +bool DonutMaker::match_powers(SingleSwitchProgramEnvironment& env, ProControllerContext& context, std::vector& match_counts) { DonutMaker_Descriptor::Stats& stats = env.current_stats(); env.log("Reading in table of desired powers."); - std::vector power_table; + + std::vector> powers_table; std::vector> wanted_powers_table = FLAVOR_POWERS.copy_snapshot(); for (const std::unique_ptr& row : wanted_powers_table){ FlavorPowerTableEntry table_line = row->snapshot(); - power_table.push_back(table_line.to_str()); + powers_table.push_back(table_line.get_entry_flavor_power_strings()); env.log(table_line.to_str()); } //TODO: Validate powers? The "All Types" type only applies to catching and sparkling powers. Move and resist do not have "All Types" //Are people even going to target move and resist power? Big Haul/Item Berry/Alpha/Sparkling seems more likely. - env.log("Reading powers and counting up hits."); - uint8_t num_hits = 0; + env.log("Checking donut powers against table."); VideoSnapshot screen = env.console.video().snapshot(); - for (int i = 0; i < 3; i++) { + std::vector donut_results; + for (int i = 0; i < 3; i++){ FlavorPowerDetector read_power(env.logger(), COLOR_GREEN, LANGUAGE, i); const std::string power = read_power.detect_power(screen); if (power.empty()){ @@ -151,19 +208,35 @@ bool DonutMaker::match_powers(SingleSwitchProgramEnvironment& env, ProController continue; } env.add_overlay_log(std::format("{}: {}", i+1, power)); - - if ((std::find(power_table.begin(), power_table.end(), power) != power_table.end())) { - num_hits++; - } + donut_results.push_back(power); } - if (num_hits >= NUM_POWER_REQUIRED) { + bool match_found = false; + bool should_keep = false; + for (size_t i = 0; i < powers_table.size(); i++){ + if (donut_matches_powers(env, donut_results, powers_table[i])){ + match_found = true; + match_counts[i]++; + if (match_counts[i] <= FLAVOR_POWERS.snapshot()[i].limit){ + env.log("Keeping donut: " + std::to_string(match_counts[i]) + " / " + std::to_string(FLAVOR_POWERS.snapshot()[i].limit) + " for table entry " + std::to_string(i+1)); + should_keep = true; + } + } + } + if (match_found){ + env.log("Match found!"); stats.matched++; env.update_stats(); - send_program_status_notification(env, NOTIFICATION_DONUT_FOUND, "Match found!", screen, true); - return true; + if (should_keep){ + stats.kept++; + env.update_stats(); + send_program_status_notification(env, NOTIFICATION_DONUT_FOUND, "Match found! Keeping donut.", screen, true); + return true; + } else { + env.log("Matched donut exceeds all keep limits."); + } } - + env.log("Discarding donut."); return false; } @@ -502,8 +575,24 @@ void save_donut(SingleSwitchProgramEnvironment& env, ProControllerContext& conte // fast_travel_to_index(env, context, 0, 3000ms); } +// Check if all user defined limits are reached or the global max keepers limit is reached +bool DonutMaker::should_stop(SingleSwitchProgramEnvironment& env, ProControllerContext& context, const std::vector& match_counts){ + int total_kept = 0; + bool limit_reached = true; + for (size_t i = 0; i < match_counts.size(); i++){ + if (match_counts[i] < FLAVOR_POWERS.snapshot()[i].limit){ + limit_reached = false; + } + total_kept += match_counts[i]; + } + if (total_kept >= MAX_KEEPERS){ + return true; + } + return limit_reached; +} + // Return true if a donut match is found -bool DonutMaker::donut_iteration(SingleSwitchProgramEnvironment& env, ProControllerContext& context){ +bool DonutMaker::donut_iteration(SingleSwitchProgramEnvironment& env, ProControllerContext& context, std::vector& match_counts) { DonutMaker_Descriptor::Stats& stats = env.current_stats(); move_to_ansha(env, context); @@ -525,8 +614,8 @@ bool DonutMaker::donut_iteration(SingleSwitchProgramEnvironment& env, ProControl // Add berries from menu and make a donut. Stop at flavor power screen. add_berries_and_make_donut(env, context); - // Read flavor power and check if they match user requirement: - if (match_powers(env, context)){ + // Read flavor power and check if they match user requirement and should be kept: + if (match_powers(env, context, match_counts)){ return true; } @@ -556,14 +645,16 @@ void DonutMaker::program(SingleSwitchProgramEnvironment& env, ProControllerConte pbf_mash_button(context, BUTTON_B, 200ms); reset_map_filter_state(env, context); + + std::vector match_counts(FLAVOR_POWERS.snapshot().size(), 0); while(true){ - const bool found_match = donut_iteration(env, context); + const bool should_keep = donut_iteration(env, context, match_counts); stats.resets++; env.update_stats(); send_program_status_notification(env, NOTIFICATION_STATUS); - if (found_match){ - if (stats.matched.load() >= NUM_DONUTS){ + if (should_keep){ + if (should_stop(env, context, match_counts)){ break; } save_donut(env, context); diff --git a/SerialPrograms/Source/PokemonLZA/Programs/Farming/PokemonLZA_DonutMaker.h b/SerialPrograms/Source/PokemonLZA/Programs/Farming/PokemonLZA_DonutMaker.h index c115afbd4a..c80087c65b 100644 --- a/SerialPrograms/Source/PokemonLZA/Programs/Farming/PokemonLZA_DonutMaker.h +++ b/SerialPrograms/Source/PokemonLZA/Programs/Farming/PokemonLZA_DonutMaker.h @@ -36,19 +36,19 @@ class DonutMaker : public SingleSwitchProgramInstance{ virtual void program(SingleSwitchProgramEnvironment& env, ProControllerContext& context) override; private: - bool match_powers(SingleSwitchProgramEnvironment& env, ProControllerContext& context); + bool match_powers(SingleSwitchProgramEnvironment& env, ProControllerContext& context, std::vector& match_counts); + bool should_stop(SingleSwitchProgramEnvironment& env, ProControllerContext& context, const std::vector& match_counts); void animation_to_donut(SingleSwitchProgramEnvironment& env, ProControllerContext& context); void add_berries_and_make_donut(SingleSwitchProgramEnvironment& env, ProControllerContext& context); void open_berry_menu_from_ansha(SingleSwitchProgramEnvironment& env, ProControllerContext& context); - bool donut_iteration(SingleSwitchProgramEnvironment& env, ProControllerContext& context); + bool donut_iteration(SingleSwitchProgramEnvironment& env, ProControllerContext& context, std::vector& match_counts); private: OCR::LanguageOCROption LANGUAGE; DonutBerriesTable BERRIES; - SimpleIntegerOption NUM_POWER_REQUIRED; + SimpleIntegerOption MAX_KEEPERS; FlavorPowerTable FLAVOR_POWERS; - SimpleIntegerOption NUM_DONUTS; GoHomeWhenDoneOption GO_HOME_WHEN_DONE; EventNotificationOption NOTIFICATION_DONUT_FOUND;