2023-11-12 17:30:44 +01:00
|
|
|
#ifndef DYNAMIC_PROGRAM_COMMAND_LINE_INTERFACE_H
|
|
|
|
#define DYNAMIC_PROGRAM_COMMAND_LINE_INTERFACE_H
|
|
|
|
|
|
|
|
#include <variant>
|
|
|
|
#include <boost/optional.hpp>
|
2023-11-15 23:07:39 +01:00
|
|
|
#include "hanabi_types.hpp"
|
2023-11-12 17:30:44 +01:00
|
|
|
|
|
|
|
|
2023-11-16 16:20:04 +01:00
|
|
|
namespace Hanabi
|
|
|
|
{
|
|
|
|
enum class GameStateSpecType
|
|
|
|
{
|
|
|
|
turn = 0, draw_pile_size = 1, };
|
2023-11-12 17:30:44 +01:00
|
|
|
|
2023-11-16 16:20:04 +01:00
|
|
|
struct CLIParms
|
|
|
|
{
|
2023-11-15 16:53:49 +01:00
|
|
|
/**
|
|
|
|
* The data source for the game to be analysed.
|
|
|
|
* If of type int, assumed to be a game ID from hanab.live
|
|
|
|
* If of type string, assumed to be a (relative) filename to a game in hanab.live json format,
|
|
|
|
* see https://raw.githubusercontent.com/Hanabi-Live/hanabi-live/main/misc/example_game_with_comments.jsonc
|
|
|
|
* for a format specification.
|
|
|
|
*/
|
2023-11-16 16:20:04 +01:00
|
|
|
std::variant<int, std::string> game{};
|
2023-11-15 16:53:49 +01:00
|
|
|
|
|
|
|
/**
|
|
|
|
* Definition of a 'winning' game, i.e. what score (number of cards played) is considered
|
|
|
|
* to be winning.
|
|
|
|
* If std::nullopt, then the maximum score of the game will be used.
|
|
|
|
*/
|
2023-11-16 16:20:04 +01:00
|
|
|
boost::optional<uint8_t> score_goal{};
|
2023-11-15 16:53:49 +01:00
|
|
|
|
|
|
|
/**
|
|
|
|
* Whether game_state_spec denotes a turn number or draw pile size.
|
|
|
|
*/
|
2023-11-16 16:20:04 +01:00
|
|
|
GameStateSpecType game_state_spec_type{GameStateSpecType::draw_pile_size};
|
2023-11-15 16:53:49 +01:00
|
|
|
|
|
|
|
/**
|
|
|
|
* Either a turn number or a draw pile size, depending on game_state_spec_type.
|
|
|
|
* If this represents a draw pile size, we mean the first turn of the game where the draw pile
|
|
|
|
* had the given size, i.e. the turn immediately after drawing a card.
|
|
|
|
* If this represents a turn, we just mean the corresponding turn number, starting numbering at 1
|
|
|
|
* (since this is also the case on hanab.live)
|
|
|
|
* Thus, a turn number of 0 is undefined and a turn number of 1 corresponds to no actions taken in the game.
|
|
|
|
*/
|
2023-11-16 16:20:04 +01:00
|
|
|
unsigned game_state_spec{5};
|
2023-11-15 16:53:49 +01:00
|
|
|
|
|
|
|
/**
|
|
|
|
* Whether to launch an interactive exploration shell for the game state after performing analysis.
|
|
|
|
*/
|
2023-11-16 16:20:04 +01:00
|
|
|
boost::optional<bool> interactive{};
|
2023-11-15 16:53:49 +01:00
|
|
|
|
|
|
|
/**
|
|
|
|
* If true, deactivates non-essential output (to cout).
|
|
|
|
*/
|
2023-11-16 16:20:04 +01:00
|
|
|
bool quiet{false};
|
2023-11-15 16:53:49 +01:00
|
|
|
|
|
|
|
/**
|
|
|
|
* If this holds std::monostate, then all clue numbers are evaluated.
|
|
|
|
* Otherwise, the specified clue modifier is applied (relative to actual number of clues).
|
|
|
|
* Thus, setting this to 0 has no effect.
|
|
|
|
*/
|
2023-11-16 16:20:04 +01:00
|
|
|
std::variant<std::monostate, clue_t> clue_spec{static_cast<clue_t>(0)};
|
2023-11-15 16:53:49 +01:00
|
|
|
|
|
|
|
/**
|
2024-01-12 23:08:02 +01:00
|
|
|
* If true, then all states corresponding to smaller draw pile sizes are evaluated as well.
|
2023-11-15 16:53:49 +01:00
|
|
|
*/
|
2023-11-16 16:20:04 +01:00
|
|
|
bool recursive{false};
|
2024-01-12 23:08:02 +01:00
|
|
|
|
|
|
|
/**
|
|
|
|
* If true, lists all possible actions and their win probabilities in the specified
|
|
|
|
* and future game states, including suboptimal ones.
|
|
|
|
*/
|
|
|
|
bool list_actions{false};
|
2024-02-03 13:21:58 +01:00
|
|
|
|
|
|
|
/**
|
|
|
|
* If true, prints version information of the program and exits immediately.
|
|
|
|
*/
|
|
|
|
bool version_info{false};
|
2023-11-12 17:30:44 +01:00
|
|
|
};
|
|
|
|
|
2023-11-15 16:53:49 +01:00
|
|
|
/**
|
|
|
|
* @brief Get an output stream that is std::cout or a Null-Stream.
|
|
|
|
* @param quiet If true, NullStream is returned, otherwise std::cout
|
|
|
|
*/
|
2023-11-16 16:20:04 +01:00
|
|
|
std::ostream &quiet_ostream(bool quiet);
|
2023-11-12 17:30:44 +01:00
|
|
|
|
|
|
|
constexpr int download_failed = 1;
|
|
|
|
constexpr int state_unreachable = 2;
|
2024-01-13 14:36:36 +01:00
|
|
|
constexpr int out_of_memory = 3;
|
2023-11-12 17:30:44 +01:00
|
|
|
|
2023-11-15 16:53:49 +01:00
|
|
|
/**
|
|
|
|
* Parse parameters from command-line arguments.
|
|
|
|
* @param argc Number of arguments
|
|
|
|
* @param argv Array of C-Style strings, where argv[0] is ignored (as the program name).
|
|
|
|
*
|
|
|
|
* @note This is exactly the signature of the main() method
|
|
|
|
*/
|
2023-11-12 17:30:44 +01:00
|
|
|
std::optional<CLIParms> parse_parms(int argc, char *argv[]);
|
2023-11-15 16:53:49 +01:00
|
|
|
|
|
|
|
/**
|
|
|
|
* @brief Execute parsed parameters.
|
|
|
|
*/
|
2023-11-16 16:20:04 +01:00
|
|
|
int run_cli(CLIParms const &parms);
|
2023-11-12 17:30:44 +01:00
|
|
|
}
|
|
|
|
#endif //DYNAMIC_PROGRAM_COMMAND_LINE_INTERFACE_H
|