diff --git a/deck.cpp b/deck.cpp index 5a7d5176..3b823533 100644 --- a/deck.cpp +++ b/deck.cpp @@ -290,6 +290,24 @@ void Deck::set_vip_cards(const std::string& deck_string) } } +void Deck::set_allowed_candidates(const std::string& deck_string) +{ + auto && id_marks = string_to_ids(all_cards, deck_string, "allowed-candidates"); + for (const auto & cid : id_marks.first) + { + allowed_candidates.insert(cid); + } +} + +void Deck::set_disallowed_candidates(const std::string& deck_string) +{ + auto && id_marks = string_to_ids(all_cards, deck_string, "disallowed-candidates"); + for (const auto & cid : id_marks.first) + { + disallowed_candidates.insert(cid); + } +} + void Deck::set_given_hand(const std::string& deck_string) { auto && id_marks = string_to_ids(all_cards, deck_string, "hand"); diff --git a/deck.h b/deck.h index 3ab5f41e..9eac02a9 100644 --- a/deck.h +++ b/deck.h @@ -67,6 +67,8 @@ class Deck std::string deck_string; std::set vip_cards; + std::set allowed_candidates; + std::set disallowed_candidates; std::vector given_hand; std::vector fort_cards; @@ -123,6 +125,8 @@ class Deck void resolve(); void shrink(const unsigned deck_len); void set_vip_cards(const std::string& deck_string_); + void set_allowed_candidates(const std::string& deck_string_); + void set_disallowed_candidates(const std::string& deck_string_); void set_given_hand(const std::string& deck_string_); void add_forts(const std::string& deck_string_); diff --git a/read.cpp b/read.cpp index d7ab04df..734b55a8 100644 --- a/read.cpp +++ b/read.cpp @@ -16,6 +16,23 @@ #include "cards.h" #include "deck.h" +// trim from start +static inline std::string <rim(std::string &s) { + s.erase(s.begin(), std::find_if(s.begin(), s.end(), std::not1(std::ptr_fun(std::isspace)))); + return s; +} + +// trim from end +static inline std::string &rtrim(std::string &s) { + s.erase(std::find_if(s.rbegin(), s.rend(), std::not1(std::ptr_fun(std::isspace))).base(), s.end()); + return s; +} + +// trim from both ends +static inline std::string &trim(std::string &s) { + return ltrim(rtrim(s)); +} + template Iterator advance_until(Iterator it, Iterator it_end, Functor f) { while(it != it_end) @@ -310,6 +327,7 @@ unsigned read_card_abbrs(Cards& all_cards, const std::string& filename) { std::string abbr_string; getline(abbr_file, abbr_string); + trim(abbr_string); ++num_line; if(abbr_string.size() == 0 || strncmp(abbr_string.c_str(), "//", 2) == 0) { @@ -370,6 +388,7 @@ unsigned load_custom_decks(Decks& decks, Cards& all_cards, const std::string & f { std::string deck_string; getline(decks_file, deck_string); + trim(deck_string); ++num_line; if(deck_string.size() == 0 || strncmp(deck_string.c_str(), "//", 2) == 0) { @@ -462,6 +481,7 @@ void read_owned_cards(Cards& all_cards, std::map& owned_card { std::string card_spec; getline(owned_file, card_spec); + trim(card_spec); ++num_line; if(card_spec.size() == 0 || strncmp(card_spec.c_str(), "//", 2) == 0) { diff --git a/tyrant_optimize.cpp b/tyrant_optimize.cpp index a2c516cb..6e9b4b56 100644 --- a/tyrant_optimize.cpp +++ b/tyrant_optimize.cpp @@ -912,7 +912,10 @@ void hill_climbing(unsigned num_min_iterations, unsigned num_iterations, Deck* d std::shuffle(non_commander_cards.begin(), non_commander_cards.end(), re); for(const Card* card_candidate: non_commander_cards) { - if (card_candidate && (card_candidate->m_fusion_level < use_fused_card_level || (use_top_level_card && card_candidate->m_level < card_candidate->m_top_level_card->m_level))) + if (card_candidate && (card_candidate->m_fusion_level < use_fused_card_level || (use_top_level_card && card_candidate->m_level < card_candidate->m_top_level_card->m_level)) + && ! d1->allowed_candidates.count(card_candidate->m_id)) + { continue; } + if (card_candidate && d1->disallowed_candidates.count(card_candidate->m_id)) { continue; } d1->commander = best_commander; d1->cards = best_cards; @@ -1076,7 +1079,10 @@ void hill_climbing_ordered(unsigned num_min_iterations, unsigned num_iterations, std::shuffle(non_commander_cards.begin(), non_commander_cards.end(), re); for(const Card* card_candidate: non_commander_cards) { - if (card_candidate && (card_candidate->m_fusion_level < use_fused_card_level || (use_top_level_card && card_candidate->m_level < card_candidate->m_top_level_card->m_level))) + if (card_candidate && (card_candidate->m_fusion_level < use_fused_card_level || (use_top_level_card && card_candidate->m_level < card_candidate->m_top_level_card->m_level)) + && ! d1->allowed_candidates.count(card_candidate->m_id)) + { continue; } + if (card_candidate && d1->disallowed_candidates.count(card_candidate->m_id)) { continue; } // Various checks to check if the card is accepted assert(!card_candidate || card_candidate->m_type != CardType::commander); @@ -1227,6 +1233,9 @@ int main(int argc, char** argv) std::string opt_forts, opt_enemy_forts; std::string opt_hand, opt_enemy_hand; std::string opt_vip; + std::string opt_allow_candidates; + std::string opt_disallow_candidates; + std::string opt_disallow_recipes; std::string opt_quest; std::string opt_target_score; std::vector fn_suffix_list{"",}; @@ -1440,6 +1449,21 @@ int main(int argc, char** argv) opt_vip = argv[argIndex + 1]; argIndex += 1; } + else if(strcmp(argv[argIndex], "allow-candidates") == 0) + { + opt_allow_candidates = argv[argIndex + 1]; + argIndex += 1; + } + else if(strcmp(argv[argIndex], "disallow-candidates") == 0) + { + opt_disallow_candidates = argv[argIndex + 1]; + argIndex += 1; + } + else if(strcmp(argv[argIndex], "disallow-recipes") == 0) + { + opt_disallow_recipes = argv[argIndex + 1]; + argIndex += 1; + } else if(strcmp(argv[argIndex], "hand") == 0) // set initial hand for test { opt_hand = argv[argIndex + 1]; @@ -1692,6 +1716,40 @@ int main(int argc, char** argv) return 0; } + try + { + your_deck->set_allowed_candidates(opt_allow_candidates); + } + catch(const std::runtime_error& e) + { + std::cerr << "Error: allow-candidates " << opt_allow_candidates << ": " << e.what() << std::endl; + return 0; + } + + try + { + your_deck->set_disallowed_candidates(opt_disallow_candidates); + } + catch(const std::runtime_error& e) + { + std::cerr << "Error: disallow-candidates " << opt_disallow_candidates << ": " << e.what() << std::endl; + return 0; + } + + try + { + auto && id_dis_recipes = string_to_ids(all_cards, opt_disallow_recipes, "disallowed-recipes"); + for (auto & cid : id_dis_recipes.first) + { + all_cards.cards_by_id[cid]->m_recipe_cards.clear(); + } + } + catch(const std::runtime_error& e) + { + std::cerr << "Error: disallow-recipes " << opt_disallow_recipes << ": " << e.what() << std::endl; + return 0; + } + if (!opt_quest.empty()) { try