Endgame-Analyzer/include/game_interface.h

148 lines
4.4 KiB
C
Raw Permalink Normal View History

#ifndef DYNAMIC_PROGRAM_GAME_INTERFACE_H
#define DYNAMIC_PROGRAM_GAME_INTERFACE_H
#include <cstddef>
#include <iosfwd>
#include <vector>
#include <memory>
2023-11-15 23:07:39 +01:00
#include "hanabi_types.hpp"
namespace Hanabi
{
2023-11-16 16:29:41 +01:00
/**
* A card together with an associated multiplicity
*/
struct CardMultiplicity
{
Card card;
unsigned multiplicity;
2024-01-14 18:04:27 +01:00
bool operator==(const CardMultiplicity &) const;
bool operator!=(const CardMultiplicity &) const;
};
struct HanabiStateConfig
{
/** What score to consider as a win. If left empty, automatically replaced by max score on construction. */
std::optional<uint8_t> score_goal;
/** The number of clues gained when a stack is finished or a card is discarded. Usually 1, 1/2 in clue starved. */
clue_t num_clues_gained_on_discard_or_stack_finished {1};
/**
* If set to true, only roughly half of the game states will be stored in the internal lookup table.
* This results in roughly halving memory consumption at the cost of roughly a factor 3-5 in execution speed
* (the slowdown is theoretically bounded to visiting at most 9 times the number of states if this option is activated).
* You should typically never need this, unless you are very specifically short on memory and.
* */
bool save_memory {false};
};
2023-11-16 16:20:04 +01:00
class HanabiStateIF
{
public:
virtual void give_clue() = 0;
2023-11-16 16:20:04 +01:00
virtual void discard(hand_index_t index) = 0;
2023-11-16 16:20:04 +01:00
virtual void play(hand_index_t index) = 0;
2023-11-16 16:20:04 +01:00
virtual void rotate_next_draw(const Card & card) = 0;
2023-11-16 16:29:41 +01:00
[[nodiscard]] virtual ActionType last_action_type() const = 0;
2023-11-16 16:20:04 +01:00
virtual void revert() = 0;
virtual void modify_clues(clue_t change) = 0;
2023-11-16 16:20:04 +01:00
virtual void set_clues(clue_t clues) = 0;
[[nodiscard]] virtual player_t turn() const = 0;
2023-11-16 16:20:04 +01:00
[[nodiscard]] virtual clue_t num_clues() const = 0;
2023-11-16 16:20:04 +01:00
2024-01-16 17:19:42 +01:00
[[nodiscard]] virtual unsigned num_strikes() const = 0;
[[nodiscard]] virtual unsigned score() const = 0;
2023-11-16 16:20:04 +01:00
[[nodiscard]] virtual std::vector<std::vector<Card>> hands() const = 0;
2023-11-16 16:20:04 +01:00
[[nodiscard]] virtual std::vector<Card> cur_hand() const = 0;
2023-11-16 16:20:04 +01:00
[[nodiscard]] virtual size_t draw_pile_size() const = 0;
2023-11-16 16:20:04 +01:00
[[nodiscard]] virtual bool is_trash(const Card & card) const = 0;
2024-01-12 14:27:16 +01:00
/** Returns whether the card is critical, assuming it is not trash already */
[[nodiscard]] virtual bool is_critical(const Card & card) const = 0;
2023-11-16 16:20:04 +01:00
[[nodiscard]] virtual bool is_playable(const Card & card) const = 0;
[[nodiscard]] virtual bool is_relative_state_initialized() const = 0;
2023-11-16 16:20:04 +01:00
[[nodiscard]] virtual hand_index_t find_card_in_hand(const Card & card) const = 0;
[[nodiscard]] virtual std::uint64_t enumerated_states() const = 0;
2023-11-16 16:20:04 +01:00
[[nodiscard]] virtual const map_type<unsigned long, std::uint64_t> & position_tablebase() const = 0;
virtual void init_backtracking_information() = 0;
2023-11-16 16:20:04 +01:00
virtual probability_t evaluate_state() = 0;
[[nodiscard]] virtual std::optional<probability_t> lookup() const = 0;
2023-11-16 16:20:04 +01:00
[[nodiscard]] virtual std::uint64_t unique_id() const = 0;
2023-11-16 16:20:04 +01:00
[[nodiscard]] virtual std::pair<std::vector<std::uint64_t>, std::vector<Card>> dump_unique_id_parts() const = 0;
virtual std::vector<std::pair<Action, std::optional<probability_t>>> get_reasonable_actions(bool evaluate_all = false, bool reasonable = true) = 0;
2023-11-16 16:20:04 +01:00
virtual std::vector<std::pair<CardMultiplicity, std::optional<probability_t>>>
possible_next_states(hand_index_t index, bool play) = 0;
virtual ~HanabiStateIF() = default;
protected:
2023-11-16 16:20:04 +01:00
virtual void print(std::ostream & os) const = 0;
2023-11-16 16:20:04 +01:00
friend std::ostream & operator<<(std::ostream &, HanabiStateIF const &);
};
2023-11-16 16:20:04 +01:00
std::ostream & operator<<(std::ostream & os, HanabiStateIF const & hanabi_state);
2023-11-15 23:23:21 +01:00
struct GameInfo
{
std::vector<Hanabi::Card> deck;
std::vector<Hanabi::Action> actions;
Hanabi::suit_t num_suits;
Hanabi::player_t num_players;
2024-01-09 02:21:01 +01:00
clue_t num_clues_gained_per_discard_or_stack_finished;
2023-11-15 23:23:21 +01:00
};
2023-11-16 16:20:04 +01:00
struct Game : private GameInfo
{
2023-11-15 23:23:21 +01:00
public:
Game(std::unique_ptr<HanabiStateIF> state, GameInfo game_info);
[[nodiscard]] unsigned cur_turn() const;
[[nodiscard]] unsigned num_turns() const;
void make_turn();
2023-11-16 16:20:04 +01:00
void revert_turn();
bool goto_draw_pile_size(size_t draw_pile_break);
2023-11-16 16:20:04 +01:00
bool goto_turn(size_t turn);
[[nodiscard]] bool holds_state() const;
std::unique_ptr<HanabiStateIF> state;
unsigned next_action;
};
}
#endif //DYNAMIC_PROGRAM_GAME_INTERFACE_H