Merge branch 'main' into cpr-fetch-content
This commit is contained in:
commit
759386f21b
8 changed files with 78 additions and 36 deletions
|
@ -1,7 +1,7 @@
|
|||
cmake_minimum_required(VERSION 3.16)
|
||||
project(endgame-analyzer CXX)
|
||||
|
||||
set(CMAKE_CXX_STANDARD 20)
|
||||
set(CMAKE_CXX_STANDARD 17)
|
||||
set(CMAKE_CXX_FLAGS "${CMAKE_CXX_FLAGS} -Wall -Wpedantic -Werror")
|
||||
set(CMAKE_CXX_FLAGS_RELEASE "${CMAKE_CXX_FLAGS_RELEASE} -O3")
|
||||
set(CMAKE_CXX_FLAGS_DEBUG "${CMAKE_CXX_FLAGS_DEBUG} -DGAME_STATE_NO_TABLEBASE_LOOKUP")
|
||||
|
|
|
@ -21,7 +21,8 @@ namespace Hanabi
|
|||
Card card;
|
||||
unsigned multiplicity;
|
||||
|
||||
bool operator==(const CardMultiplicity &) const = default;
|
||||
bool operator==(const CardMultiplicity &) const;
|
||||
bool operator!=(const CardMultiplicity &) const;
|
||||
};
|
||||
|
||||
class HanabiStateIF
|
||||
|
|
|
@ -56,7 +56,7 @@ namespace Hanabi
|
|||
|
||||
value_type & operator[](const Card & card);
|
||||
|
||||
auto operator<=>(const CardArray &) const = default;
|
||||
//auto operator<=>(const CardArray &) const = default;
|
||||
|
||||
private:
|
||||
using inner_array_t = typename InnerCardArray<T>::template array_t<starting_card_rank>;
|
||||
|
@ -132,7 +132,7 @@ namespace Hanabi
|
|||
std::vector<std::pair<CardMultiplicity, std::optional<probability_t>>>
|
||||
possible_next_states(hand_index_t index, bool play) final;
|
||||
|
||||
auto operator<=>(const HanabiState &) const = default;
|
||||
//auto operator<=>(const HanabiState &) const = default;
|
||||
|
||||
protected:
|
||||
void print(std::ostream & os) const final;
|
||||
|
|
|
@ -82,7 +82,7 @@ namespace Hanabi
|
|||
, _actions_log(), _relative_representation(), _position_tablebase()
|
||||
, _enumerated_states(0)
|
||||
{
|
||||
std::ranges::fill(_stacks, starting_card_rank);
|
||||
std::fill(_stacks.begin(), _stacks.end(), starting_card_rank);
|
||||
for (const Card & card: deck)
|
||||
{
|
||||
_draw_pile.push_back({card, 1});
|
||||
|
@ -347,8 +347,11 @@ namespace Hanabi
|
|||
}
|
||||
else
|
||||
{
|
||||
auto replaced_card_it = std::ranges::find(_relative_representation.card_positions_draw[discarded.local_index]
|
||||
, _turn);
|
||||
auto replaced_card_it = std::find(
|
||||
_relative_representation.card_positions_draw[discarded.local_index].begin(),
|
||||
_relative_representation.card_positions_draw[discarded.local_index].end(),
|
||||
_turn
|
||||
);
|
||||
ASSERT(replaced_card_it != _relative_representation.card_positions_draw[discarded.local_index].end());
|
||||
if (played)
|
||||
{
|
||||
|
@ -358,7 +361,10 @@ namespace Hanabi
|
|||
{
|
||||
*replaced_card_it = RelativeRepresentationData::discard_pile;
|
||||
}
|
||||
std::ranges::sort(_relative_representation.card_positions_draw[discarded.local_index]);
|
||||
std::sort(
|
||||
_relative_representation.card_positions_draw[discarded.local_index].begin(),
|
||||
_relative_representation.card_positions_draw[discarded.local_index].end()
|
||||
);
|
||||
}
|
||||
}
|
||||
}
|
||||
|
@ -392,11 +398,17 @@ namespace Hanabi
|
|||
if (!draw.card.initial_trash)
|
||||
{
|
||||
ASSERT(draw.card.in_starting_hand == false);
|
||||
auto new_card_it = std::ranges::find(_relative_representation.card_positions_draw[draw.card.local_index]
|
||||
, RelativeRepresentationData::draw_pile);
|
||||
auto new_card_it = std::find(
|
||||
_relative_representation.card_positions_draw[draw.card.local_index].begin(),
|
||||
_relative_representation.card_positions_draw[draw.card.local_index].end(),
|
||||
RelativeRepresentationData::draw_pile
|
||||
);
|
||||
ASSERT(new_card_it != _relative_representation.card_positions_draw[draw.card.local_index].end());
|
||||
*new_card_it = _turn;
|
||||
std::ranges::sort(_relative_representation.card_positions_draw[draw.card.local_index]);
|
||||
std::sort(
|
||||
_relative_representation.card_positions_draw[draw.card.local_index].begin(),
|
||||
_relative_representation.card_positions_draw[draw.card.local_index].end()
|
||||
);
|
||||
}
|
||||
}
|
||||
|
||||
|
@ -460,10 +472,17 @@ namespace Hanabi
|
|||
if (_relative_representation.initialized && !drawn.initial_trash)
|
||||
{
|
||||
ASSERT(drawn.in_starting_hand == false);
|
||||
auto drawn_card_it = std::ranges::find(_relative_representation.card_positions_draw[drawn.local_index], _turn);
|
||||
auto drawn_card_it = std::find(
|
||||
_relative_representation.card_positions_draw[drawn.local_index].begin(),
|
||||
_relative_representation.card_positions_draw[drawn.local_index].end(),
|
||||
_turn
|
||||
);
|
||||
ASSERT(drawn_card_it != _relative_representation.card_positions_draw[drawn.local_index].end());
|
||||
*drawn_card_it = RelativeRepresentationData::draw_pile;
|
||||
std::ranges::sort(_relative_representation.card_positions_draw[drawn.local_index]);
|
||||
std::sort(
|
||||
_relative_representation.card_positions_draw[drawn.local_index].begin(),
|
||||
_relative_representation.card_positions_draw[drawn.local_index].end()
|
||||
);
|
||||
}
|
||||
|
||||
_weighted_draw_pile_size++;
|
||||
|
@ -494,11 +513,17 @@ namespace Hanabi
|
|||
return RelativeRepresentationData::discard_pile;
|
||||
}
|
||||
}();
|
||||
auto hand_card_it = std::ranges::find(_relative_representation.card_positions_draw[discarded_card.local_index]
|
||||
, old_position);
|
||||
auto hand_card_it = std::find(
|
||||
_relative_representation.card_positions_draw[discarded_card.local_index].begin(),
|
||||
_relative_representation.card_positions_draw[discarded_card.local_index].end(),
|
||||
old_position
|
||||
);
|
||||
ASSERT(hand_card_it != _relative_representation.card_positions_draw[discarded_card.local_index].end());
|
||||
*hand_card_it = _turn;
|
||||
std::ranges::sort(_relative_representation.card_positions_draw[discarded_card.local_index]);
|
||||
std::sort(
|
||||
_relative_representation.card_positions_draw[discarded_card.local_index].begin(),
|
||||
_relative_representation.card_positions_draw[discarded_card.local_index].end()
|
||||
);
|
||||
}
|
||||
}
|
||||
|
||||
|
@ -917,7 +942,7 @@ namespace Hanabi
|
|||
return 0;
|
||||
}
|
||||
const auto id = unique_id();
|
||||
if (_position_tablebase.contains(id))
|
||||
if (_position_tablebase.count(id) == 1)
|
||||
{
|
||||
return _position_tablebase.at(id);
|
||||
}
|
||||
|
@ -969,7 +994,7 @@ namespace Hanabi
|
|||
return 0;
|
||||
}
|
||||
#ifndef GAME_STATE_NO_TABLEBASE_LOOKUP
|
||||
if (_position_tablebase.contains(id_of_state)) {
|
||||
if (_position_tablebase.count(id_of_state) == 1) {
|
||||
return _position_tablebase[id_of_state];
|
||||
}
|
||||
#endif
|
||||
|
@ -1334,7 +1359,7 @@ namespace Hanabi
|
|||
std::cout << "\n" << std::endl;
|
||||
}
|
||||
#endif
|
||||
if (_position_tablebase.contains(id))
|
||||
if (_position_tablebase.count(id) == 1)
|
||||
{
|
||||
ASSERT(_position_tablebase[id] == probability);
|
||||
}
|
||||
|
|
|
@ -51,7 +51,7 @@ namespace Hanabi
|
|||
constexpr rank_t starting_card_rank = 5;
|
||||
constexpr suit_t max_suit_index = 5;
|
||||
constexpr size_t max_card_duplicity = 3;
|
||||
constexpr clue_t max_num_clues = 8;
|
||||
const clue_t max_num_clues = 8;
|
||||
constexpr hand_index_t invalid_hand_idx = std::numeric_limits<hand_index_t>::max();
|
||||
|
||||
// We might want to change these at runtime to adapt to other variants.
|
||||
|
@ -75,6 +75,7 @@ namespace Hanabi
|
|||
* This is inlined as this is a runtime critical function when backtracking.
|
||||
*/
|
||||
inline bool operator==(const Card & other) const;
|
||||
inline bool operator!=(const Card & other) const;
|
||||
};
|
||||
|
||||
enum class ActionType : std::uint8_t
|
||||
|
@ -154,6 +155,11 @@ namespace Hanabi
|
|||
return suit == other.suit and rank == other.rank;
|
||||
}
|
||||
|
||||
bool Card::operator!=(const Card & other) const
|
||||
{
|
||||
return not (*this == other);
|
||||
}
|
||||
|
||||
template<typename T>
|
||||
std::ostream & print_probability(std::ostream & os, const std::optional<T> & prob)
|
||||
{
|
||||
|
|
|
@ -5,6 +5,16 @@
|
|||
namespace Hanabi
|
||||
{
|
||||
|
||||
bool CardMultiplicity::operator==(Hanabi::CardMultiplicity const & other) const
|
||||
{
|
||||
return card == other.card && multiplicity == other.multiplicity;
|
||||
}
|
||||
|
||||
bool CardMultiplicity::operator!=(Hanabi::CardMultiplicity const & other) const
|
||||
{
|
||||
return not (*this == other);
|
||||
}
|
||||
|
||||
std::ostream & operator<<(std::ostream & os, HanabiStateIF const & hanabi_state)
|
||||
{
|
||||
hanabi_state.print(os);
|
||||
|
|
|
@ -8,7 +8,7 @@ namespace Parsing
|
|||
template<class T>
|
||||
void extract(boost::json::object const & obj, T & t, std::string_view key)
|
||||
{
|
||||
t = value_to<T>(obj.at(key));
|
||||
t = boost::json::value_to<T>(obj.at(key));
|
||||
}
|
||||
}
|
||||
|
||||
|
|
|
@ -41,7 +41,7 @@ namespace Hanabi
|
|||
std::string text_str(text);
|
||||
for (auto & command: cli_commands)
|
||||
{
|
||||
if (command.starts_with(text_str) && state-- <= 0)
|
||||
if (command.find(text_str) == 0 && state-- <= 0)
|
||||
{
|
||||
return strdup(command.c_str());
|
||||
}
|
||||
|
@ -135,7 +135,7 @@ namespace Hanabi
|
|||
states_to_show.pop_back();
|
||||
}
|
||||
|
||||
std::ranges::sort(states_to_show, [](const auto & left, const auto & right) {
|
||||
std::sort(states_to_show.begin(), states_to_show.end(), [](const auto & left, const auto & right) {
|
||||
return left.second > right.second;
|
||||
});
|
||||
|
||||
|
@ -199,7 +199,7 @@ namespace Hanabi
|
|||
const std::string prompt = read_line_memory_safe("> ");
|
||||
add_history(prompt.c_str());
|
||||
|
||||
if (prompt.starts_with("help"))
|
||||
if (prompt.find("help") == 0)
|
||||
{
|
||||
std::cout << "state: print information on current game state." << std::endl;
|
||||
std::cout << "clue: give a clue." << std::endl;
|
||||
|
@ -224,7 +224,7 @@ namespace Hanabi
|
|||
continue;
|
||||
}
|
||||
|
||||
if (prompt.starts_with("dump-id-parts"))
|
||||
if (prompt.find("dump-id-parts") == 0)
|
||||
{
|
||||
for (const auto val: game.state->dump_unique_id_parts().first)
|
||||
{
|
||||
|
@ -239,7 +239,7 @@ namespace Hanabi
|
|||
continue;
|
||||
}
|
||||
|
||||
if (prompt.starts_with("quit") or prompt == "q")
|
||||
if (prompt.find("quit") == 0 or prompt == "q")
|
||||
{
|
||||
std::cout << "Quitting." << std::endl;
|
||||
clear_history();
|
||||
|
@ -247,7 +247,7 @@ namespace Hanabi
|
|||
break;
|
||||
}
|
||||
|
||||
if (prompt.starts_with("set-initials"))
|
||||
if (prompt.find("set-initials") == 0)
|
||||
{
|
||||
if (prompt.length() < 16)
|
||||
{
|
||||
|
@ -268,7 +268,7 @@ namespace Hanabi
|
|||
continue;
|
||||
}
|
||||
|
||||
if (prompt.starts_with("state"))
|
||||
if (prompt.find("state") == 0)
|
||||
{
|
||||
std::cout << *game.state << std::endl;
|
||||
const std::optional<probability_t> prob = game.state->lookup();
|
||||
|
@ -277,7 +277,7 @@ namespace Hanabi
|
|||
continue;
|
||||
}
|
||||
|
||||
if (prompt.starts_with("evaluate"))
|
||||
if (prompt.find("evaluate") == 0)
|
||||
{
|
||||
std::cout << "Evaluating current game state, this might take a while." << std::endl;
|
||||
game.state->evaluate_state();
|
||||
|
@ -285,7 +285,7 @@ namespace Hanabi
|
|||
continue;
|
||||
}
|
||||
|
||||
if (prompt.starts_with("revert"))
|
||||
if (prompt.find("revert") == 0)
|
||||
{
|
||||
if (depth == 0)
|
||||
{
|
||||
|
@ -319,13 +319,13 @@ namespace Hanabi
|
|||
continue;
|
||||
}
|
||||
|
||||
if (prompt.starts_with("id"))
|
||||
if (prompt.find("id") == 0)
|
||||
{
|
||||
std::cout << game.state->unique_id() << std::endl;
|
||||
continue;
|
||||
}
|
||||
|
||||
if (prompt.starts_with("play"))
|
||||
if (prompt.find("play") == 0)
|
||||
{
|
||||
const Card card = parse_card(prompt.substr(5, 2));
|
||||
if (prompt.length() < 7)
|
||||
|
@ -353,7 +353,7 @@ namespace Hanabi
|
|||
continue;
|
||||
}
|
||||
|
||||
if (prompt.starts_with("discard"))
|
||||
if (prompt.find("discard") == 0)
|
||||
{
|
||||
const auto hand = game.state->cur_hand();
|
||||
hand_index_t trash_index = invalid_hand_idx;
|
||||
|
@ -384,7 +384,7 @@ namespace Hanabi
|
|||
continue;
|
||||
}
|
||||
|
||||
if (prompt.starts_with("clue"))
|
||||
if (prompt.find("clue") == 0)
|
||||
{
|
||||
if (game.state->num_clues() == clue_t(0))
|
||||
{
|
||||
|
@ -396,7 +396,7 @@ namespace Hanabi
|
|||
continue;
|
||||
}
|
||||
|
||||
if (prompt.starts_with("actions"))
|
||||
if (prompt.find("actions") == 0)
|
||||
{
|
||||
auto reasonable_actions = game.state->get_reasonable_actions();
|
||||
int max_rational_digit_len = std::accumulate(
|
||||
|
@ -422,7 +422,7 @@ namespace Hanabi
|
|||
continue;
|
||||
}
|
||||
|
||||
if (prompt.starts_with("opt"))
|
||||
if (prompt.find("opt") == 0)
|
||||
{
|
||||
const auto reasonable_actions = game.state->get_reasonable_actions();
|
||||
if (reasonable_actions.empty())
|
||||
|
|
Loading…
Reference in a new issue