CLI: sort by probability when asking for draw
Also better alignment of output in list of drawable cards
This commit is contained in:
parent
129f8ceaec
commit
3fd64bc70f
1 changed files with 38 additions and 20 deletions
|
@ -1,6 +1,9 @@
|
|||
#include <cstdio>
|
||||
#include <cmath>
|
||||
#include <csignal>
|
||||
#include <iomanip>
|
||||
#include <readline/readline.h>
|
||||
#include <ranges>
|
||||
#include <readline/history.h>
|
||||
#include <iostream>
|
||||
#include <memory>
|
||||
|
@ -84,44 +87,59 @@ namespace Hanabi {
|
|||
}
|
||||
}
|
||||
|
||||
int representation_length(probability_t probability) {
|
||||
return 1 + static_cast<int>(std::ceil(std::log10(probability.denominator()))) + \
|
||||
static_cast<int>(std::ceil(std::log10(probability.numerator())));
|
||||
}
|
||||
|
||||
bool ask_for_card_and_rotate_draw(const std::shared_ptr<HanabiStateIF>& game, hand_index_t index, bool play) {
|
||||
const auto next_states = game->possible_next_states(index, play);
|
||||
|
||||
if (next_states.size() <= 1) {
|
||||
// No need to ask for anything if draw contains only one possible type of card
|
||||
return true;
|
||||
}
|
||||
|
||||
std::vector<std::pair<CardMultiplicity, std::optional<probability_t>>> states_to_show;
|
||||
states_to_show.push_back({{Hanabi::Cards::trash, 0}, 0});
|
||||
|
||||
std::cout << "Choose drawn card: " << std::endl;
|
||||
unsigned num_trash = 0;
|
||||
std::optional<probability_t> trash_discard_prob = 0;
|
||||
int max_rational_digit_len = 0;
|
||||
for(const auto &[card_multiplicity, probability]: next_states) {
|
||||
// If the card is played, we can treat it as a trash draw as well
|
||||
if (game->is_trash(card_multiplicity.card) or (play and game->cur_hand()[index] == card_multiplicity.card)) {
|
||||
num_trash += card_multiplicity.multiplicity;
|
||||
trash_discard_prob = probability;
|
||||
states_to_show.front().first.multiplicity += card_multiplicity.multiplicity;
|
||||
states_to_show.front().second = probability;
|
||||
} else {
|
||||
std::cout << card_multiplicity.card << " (" << card_multiplicity.multiplicity;
|
||||
std::cout << " copie(s) in draw) " << probability << std::endl;
|
||||
states_to_show.emplace_back(card_multiplicity, probability);
|
||||
}
|
||||
if (probability.has_value()) {
|
||||
max_rational_digit_len = std::max(max_rational_digit_len, representation_length(probability.value()));
|
||||
}
|
||||
}
|
||||
|
||||
if (num_trash > 0) {
|
||||
std::cout << Cards::trash << " (" << num_trash << " copie(s) in draw) " << trash_discard_prob << std::endl;
|
||||
// Get rid of the trash collecting entry at the front
|
||||
if (states_to_show.front().first.multiplicity == 0) {
|
||||
states_to_show.front() = std::move(states_to_show.back());
|
||||
states_to_show.pop_back();
|
||||
}
|
||||
|
||||
std::ranges::sort(states_to_show, [](const auto &left, const auto &right) {
|
||||
return left.second > right.second;
|
||||
});
|
||||
|
||||
for (const auto &[card_multiplicity, probability]: states_to_show) {
|
||||
std::cout << card_multiplicity.card << " (" << card_multiplicity.multiplicity;
|
||||
std::cout << " copie(s) in draw) " << std::setw(max_rational_digit_len) << probability << std::endl;
|
||||
}
|
||||
|
||||
std::stringstream prompt;
|
||||
prompt << "draw? [";
|
||||
if (num_trash > 0) {
|
||||
prompt << Cards::trash;
|
||||
} else {
|
||||
prompt << next_states.front().first.card;
|
||||
}
|
||||
prompt << "] ";
|
||||
prompt << "draw? [" << states_to_show.front().first.card << "] ";
|
||||
const std::string card_str = read_line_memory_safe(prompt.str().c_str());
|
||||
const Card drawn_card = [&card_str, &num_trash, &next_states](){
|
||||
|
||||
const Card drawn_card = [&card_str, &states_to_show](){
|
||||
if (card_str.empty()) {
|
||||
if (num_trash > 0) {
|
||||
return Cards::trash;
|
||||
}
|
||||
return next_states.front().first.card;
|
||||
return states_to_show.front().first.card;
|
||||
}
|
||||
return parse_card(card_str);
|
||||
}();
|
||||
|
|
Loading…
Reference in a new issue