Merge branch 'main' into cpr-fetch-content

This commit is contained in:
Maximilian Keßler 2024-01-14 18:05:08 +01:00
commit 759386f21b
Signed by: max
GPG Key ID: BCC5A619923C0BA5
8 changed files with 78 additions and 36 deletions

View File

@ -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")

View File

@ -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

View File

@ -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;

View File

@ -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);
}

View File

@ -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)
{

View File

@ -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);

View File

@ -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));
}
}

View File

@ -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())