From 9887d104b80f1dd04eec4e757a6ebdbdca08cde2 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Maximilian=20Ke=C3=9Fler?= Date: Thu, 16 Nov 2023 15:14:31 +0100 Subject: [PATCH] better interface for cli --- include/state_explorer.h | 2 +- src/command_line_interface.cpp | 3 +- src/state_explorer.cpp | 68 +++++++++++++++++----------------- 3 files changed, 36 insertions(+), 37 deletions(-) diff --git a/include/state_explorer.h b/include/state_explorer.h index 5af2c43..f6ced08 100644 --- a/include/state_explorer.h +++ b/include/state_explorer.h @@ -5,7 +5,7 @@ #include "game_interface.h" namespace Hanabi { - void cli(const std::shared_ptr& game); + void cli(Game const & game); } diff --git a/src/command_line_interface.cpp b/src/command_line_interface.cpp index b748e82..5d3686e 100644 --- a/src/command_line_interface.cpp +++ b/src/command_line_interface.cpp @@ -173,8 +173,7 @@ namespace Hanabi { if (parms.interactive.value_or(!parms.quiet)) { quiet_os << "\nDropping into interactive command line to explore result (type 'help'):" << std::endl; - auto game_shared = std::shared_ptr(game.state.release()); - cli(game_shared); + cli(game); } } return 0; diff --git a/src/state_explorer.cpp b/src/state_explorer.cpp index f56b7c3..c65da65 100644 --- a/src/state_explorer.cpp +++ b/src/state_explorer.cpp @@ -89,8 +89,8 @@ namespace Hanabi { return static_cast(std::ceil(std::log10(probability))); } - bool ask_for_card_and_rotate_draw(const std::shared_ptr& game, hand_index_t index, bool play) { - const auto next_states = game->possible_next_states(index, play); + bool ask_for_card_and_rotate_draw(HanabiStateIF & state, hand_index_t index, bool play) { + const auto next_states = state.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 @@ -104,7 +104,7 @@ namespace Hanabi { 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)) { + if (state.is_trash(card_multiplicity.card) or (play and state.cur_hand()[index] == card_multiplicity.card)) { states_to_show.front().first.multiplicity += card_multiplicity.multiplicity; states_to_show.front().second = probability; } else { @@ -147,14 +147,14 @@ namespace Hanabi { return false; } - auto selected_draw_it = std::find_if(next_states.begin(), next_states.end(), [&drawn_card, &game](const std::pair>& pair) { - return (game->is_trash(pair.first.card) and drawn_card == Cards::trash) or pair.first.card == drawn_card; + auto selected_draw_it = std::find_if(next_states.begin(), next_states.end(), [&drawn_card, &state](const std::pair>& pair) { + return (state.is_trash(pair.first.card) and drawn_card == Cards::trash) or pair.first.card == drawn_card; }); if (selected_draw_it == next_states.end()){ std::cout << "That card is not in the draw pile, aborting." << std::endl; return false; }; - game->rotate_next_draw(selected_draw_it->first.card); + state.rotate_next_draw(selected_draw_it->first.card); return true; } @@ -162,7 +162,7 @@ namespace Hanabi { std::cout << "Use 'quit' to exit the interactive shell." << std::endl << "> "; } - void cli(const std::shared_ptr& game) { + void cli(Game const & game) { std::signal(SIGINT, signal_handler); // Set up GNU readline rl_attempted_completion_function = cli_command_completion; @@ -193,11 +193,11 @@ namespace Hanabi { } if (prompt.starts_with("dump-id-parts")) { - for (const auto val: game->dump_unique_id_parts().first) { + for (const auto val: game.state->dump_unique_id_parts().first) { std::cout << val << ", "; } std::cout << std::endl; - for (const auto card: game->dump_unique_id_parts().second) { + for (const auto card: game.state->dump_unique_id_parts().second) { std::cout << card << " "; } std::cout << std::endl; @@ -229,8 +229,8 @@ namespace Hanabi { } if (prompt.starts_with("state")) { - std::cout << *game << std::endl; - const std::optional prob = game->lookup(); + std::cout << *game.state << std::endl; + const std::optional prob = game.state->lookup(); std::cout << "Winning chance: "; print_probability(std::cout, prob) << std::endl; continue; @@ -238,7 +238,7 @@ namespace Hanabi { if (prompt.starts_with("evaluate")) { std::cout << "Evaluating current game state, this might take a while." << std::endl; - game->evaluate_state(); + game.state->evaluate_state(); std::cout << "Evaluated state." << std::endl; continue; } @@ -263,14 +263,14 @@ namespace Hanabi { } std::cout << "Reverting " << turns_to_revert << " turn(s)." << std::endl; while(turns_to_revert--) { - game->revert(); + game.state->revert(); depth--; } continue; } if (prompt.starts_with("id")) { - std::cout << game->unique_id() << std::endl; + std::cout << game.state->unique_id() << std::endl; continue; } @@ -284,24 +284,24 @@ namespace Hanabi { std::cout << "Could not parse card " << prompt.substr(5,2) << std::endl; continue; } - const hand_index_t index = game->find_card_in_hand(card); + const hand_index_t index = game.state->find_card_in_hand(card); if (index == hand_index_t(-1)) { std::cout << "This card is not in the current players hand, aborting." << std::endl; continue; } - if (!ask_for_card_and_rotate_draw(game, index, true)) { + if (!ask_for_card_and_rotate_draw(*game.state, index, true)) { continue; } - game->play(index); + game.state->play(index); depth++; continue; } if (prompt.starts_with("discard")) { - const auto hand = game->cur_hand(); + const auto hand = game.state->cur_hand(); hand_index_t trash_index = invalid_hand_idx; for(hand_index_t index = 0; index < hand.size(); index++) { - if (game->is_trash(hand[index])) { + if (game.state->is_trash(hand[index])) { trash_index = index; break; } @@ -310,30 +310,30 @@ namespace Hanabi { std::cout << "No trash in hand found, discarding not supported." << std::endl; continue; } - if (game->num_clues() == max_num_clues) { + if (game.state->num_clues() == max_num_clues) { std::cout << "You cannot discard at " << max_num_clues << " clues." << std::endl; continue; } - if (!ask_for_card_and_rotate_draw(game, trash_index, false)) { + if (!ask_for_card_and_rotate_draw(*game.state, trash_index, false)) { continue; } - game->discard(trash_index); + game.state->discard(trash_index); depth++; continue; } if (prompt.starts_with("clue")) { - if (game->num_clues() == 0) { + if (game.state->num_clues() == 0) { std::cout << "You cannot give a clue at 0 clues." << std::endl; continue; } - game->give_clue(); + game.state->give_clue(); depth++; continue; } if (prompt.starts_with("actions")) { - auto reasonable_actions = game->get_reasonable_actions(); + auto reasonable_actions = game.state->get_reasonable_actions(); int max_rational_digit_len = std::accumulate( reasonable_actions.begin(), reasonable_actions.end(), @@ -356,14 +356,14 @@ namespace Hanabi { } if (prompt.starts_with("opt")) { - const auto reasonable_actions = game->get_reasonable_actions(); + const auto reasonable_actions = game.state->get_reasonable_actions(); if(reasonable_actions.empty()) { std::cout << "Game is over, no actions to take." << std::endl; continue; } Action best_action; std::optional best_probability; - for (const auto &[action, probability] : game->get_reasonable_actions()) { + for (const auto &[action, probability] : game.state->get_reasonable_actions()) { if (!best_probability.has_value() or (probability.has_value() and probability.value() > best_probability.value())) { best_action = action; best_probability = probability; @@ -374,23 +374,23 @@ namespace Hanabi { switch(best_action.type) { case ActionType::play: std::cout << "Playing " << best_action.card << std::endl; - index = game->find_card_in_hand(best_action.card); - if(!ask_for_card_and_rotate_draw(game,index,true)) { + index = game.state->find_card_in_hand(best_action.card); + if(!ask_for_card_and_rotate_draw(*game.state,index,true)) { continue; }; - game->play(game->find_card_in_hand(best_action.card)); + game.state->play(game.state->find_card_in_hand(best_action.card)); break; case ActionType::discard: std::cout << "Discarding" << std::endl; - index = game->find_card_in_hand(best_action.card); - if(!ask_for_card_and_rotate_draw(game, index, false)) { + index = game.state->find_card_in_hand(best_action.card); + if(!ask_for_card_and_rotate_draw(*game.state, index, false)) { continue; }; - game->discard(game->find_card_in_hand(best_action.card)); + game.state->discard(game.state->find_card_in_hand(best_action.card)); break; case ActionType::clue: std::cout << "Giving a clue" << std::endl; - game->give_clue(); + game.state->give_clue(); break; default: break;