Commit 709751f0 authored by Vivien Kraus's avatar Vivien Kraus

Explore the roots first

parent 410f1d38
Pipeline #106218 passed with stages
in 6 minutes and 18 seconds
......@@ -113,6 +113,7 @@ AC_SEARCH_LIBS([cos], [m])
# Checks for header files.
AC_HEADER_STDBOOL
AC_CHECK_HEADERS_ONCE([stdint.h limits.h sysexits.h math.h tgmath.h])
AC_CHECK_HEADER([float.h],, [AC_MSG_ERROR([float.h not found.])])
# Checks for typedefs, structures, and compiler characteristics.
AC_TYPE_SIZE_T
......
......@@ -1935,7 +1935,8 @@ game_iterator_next_value (TarotGameIterator * iterator)
game_n_players (&(iterator->handle))
&& game_get_discard_according_to (&(iterator->handle),
game_get_dealt (&
(iterator->handle)),
(iterator->
handle)),
&cards) == 0)
|| game_get_discard (&(iterator->handle), &cards) == 0)
{
......
......@@ -598,6 +598,10 @@ counter_and_game_impute (TarotCounter * counter,
{
current_solution.cards[i].assigned = n_players;
}
if (current_solution.n_remaining == 0)
{
return 0;
}
/* Shuffle the deal once, otherwise the first player would have more
hearts. */
for (i = 1; i < current_solution.n_remaining; i++)
......
......@@ -22,6 +22,8 @@
#include <tarot/mcts_private.h>
#include <tarot/mcts_tree_private.h>
#include <tarot/simulation.h>
#include <float.h>
#include <string.h>
/* #define DEBUG_MCTS */
......@@ -31,6 +33,9 @@
#define DEBUG(...)
#endif /* not DEBUG_MCTS */
/* Add a few starting positions, or all of them if they are enumerable. */
static int mcts_setup_root (TarotMcts * mcts);
static inline TarotMcts *
mcts_alloc ()
{
......@@ -103,7 +108,7 @@ mcts_set_base (TarotMcts * mcts, const TarotGame * base)
tarot_mcts_tree_free (mcts->tree);
mcts->tree = new_tree;
tarot_mcts_tree_get (mcts->tree, TREE_ROOT)->event = NULL;
return 0;
return mcts_setup_root (mcts);
}
static int
......@@ -176,6 +181,7 @@ one_iteration (TarotMcts * mcts, size_t n_simulations,
}
}
DEBUG (stderr, "%s:%d: Expanding node %lu\n", __FILE__, __LINE__, node);
assert (node != TREE_NULL);
if (mcts_expand (mcts, &node, next, next_player) != 0)
{
/* No memory for child */
......@@ -263,9 +269,17 @@ mcts_get_best (const TarotMcts * mcts, TarotGameEvent * event)
static double
compute_score (const TarotMctsNode * node, double n_simulations)
{
double win_ratio = node->sum_scores / ((double) node->n_simulations);
double exploration_ratio = 1 - (node->n_simulations / n_simulations);
return win_ratio + MAX_NEGATIVE_SCORE_TO_EXPLORE * exploration_ratio;
if (node->n_simulations == 0)
{
/* This is an unexplored root! */
return DBL_MAX;
}
else
{
double win_ratio = node->sum_scores / ((double) node->n_simulations);
double exploration_ratio = 1 - (node->n_simulations / n_simulations);
return win_ratio + MAX_NEGATIVE_SCORE_TO_EXPLORE * exploration_ratio;
}
}
static void
......@@ -301,15 +315,13 @@ search_best_select (const TarotMcts * mcts, TarotMctsTreeIterator node,
}
}
/* May return an invalid index, meaning we have to try a new event
directly from the root */
static inline TarotMctsTreeIterator
mcts_select (const TarotMcts * mcts, size_t n_simulations)
{
if (n_simulations != 0)
{
TarotMctsTreeIterator best = TREE_NULL;
double value_best = MAX_NEGATIVE_SCORE_TO_EXPLORE;
TarotMctsTreeIterator best = TREE_ROOT;
double value_best = -DBL_MAX;
search_best_select (mcts, TREE_ROOT, n_simulations, &best, &value_best);
return best;
}
......@@ -860,4 +872,251 @@ mcts_next_sibling (const TarotMcts * mcts, TarotMctsTreeIterator node)
return tarot_mcts_tree_next_sibling (mcts->tree, node);
}
static inline int
mcts_setup_bids (TarotMcts * mcts)
{
TarotPlayer who;
TarotBid mini;
TarotMctsTreeIterator root = TREE_NULL;
TarotGameEvent *event = tarot_game_event_alloc ();
TarotBid bid;
if (event == NULL)
{
return 1;
}
if (tarot_game_hint_bid (mcts->base, &who, &mini) != 0)
{
tarot_game_event_free (event);
return 1;
}
if (tarot_game_event_set_bid (event, TAROT_PASS) != 0)
{
tarot_game_event_free (event);
return 1;
}
if (mcts_expand (mcts, &root, event, who) != 0)
{
tarot_game_event_free (event);
return 1;
}
for (bid = mini; bid < TAROT_DOUBLE_KEEP; bid++)
{
root = TREE_NULL;
if (tarot_game_event_set_bid (event, bid) != 0)
{
tarot_game_event_free (event);
return 1;
}
if (mcts_expand (mcts, &root, event, who) != 0)
{
tarot_game_event_free (event);
return 1;
}
}
tarot_game_event_free (event);
return 0;
}
static int
mcts_setup_decls (TarotMcts * mcts)
{
TarotPlayer who;
int allowed;
TarotMctsTreeIterator root = TREE_NULL;
TarotGameEvent *event = tarot_game_event_alloc ();
if (event == NULL)
{
return 1;
}
if (tarot_game_hint_decl (mcts->base, &who, &allowed) != 0)
{
tarot_game_event_free (event);
return 1;
}
if (tarot_game_event_set_decl (event, 0) != 0)
{
tarot_game_event_free (event);
return 1;
}
if (mcts_expand (mcts, &root, event, who) != 0)
{
tarot_game_event_free (event);
return 1;
}
if (allowed)
{
root = TREE_NULL;
if (tarot_game_event_set_decl (event, 1) != 0)
{
tarot_game_event_free (event);
return 1;
}
if (mcts_expand (mcts, &root, event, who) != 0)
{
tarot_game_event_free (event);
return 1;
}
}
tarot_game_event_free (event);
return 0;
}
static int
mcts_setup_call (TarotMcts * mcts)
{
TarotPlayer who;
TarotNumber mini;
TarotMctsTreeIterator root = TREE_NULL;
TarotGameEvent *event = tarot_game_event_alloc ();
TarotNumber face;
if (event == NULL)
{
return 1;
}
if (tarot_game_hint_call (mcts->base, &who, &mini) != 0)
{
tarot_game_event_free (event);
return 1;
}
for (face = mini; face <= TAROT_KING; face++)
{
static TarotSuit suits[4] =
{ TAROT_HEARTS, TAROT_CLUBS, TAROT_DIAMONDS, TAROT_SPADES };
size_t j;
for (j = 0; j < 4; j++)
{
TarotCard c;
if (tarot_of (face, suits[j], &c) != 0)
{
assert (0);
}
root = TREE_NULL;
if (tarot_game_event_set_call (event, c) != 0)
{
tarot_game_event_free (event);
return 1;
}
if (mcts_expand (mcts, &root, event, who) != 0)
{
tarot_game_event_free (event);
return 1;
}
}
}
tarot_game_event_free (event);
return 0;
}
static int
mcts_setup_discard (TarotMcts * mcts)
{
TarotPlayer who;
TarotMctsTreeIterator root = TREE_NULL;
TarotCardArray *prio, *additional;
size_t n;
TarotGameEvent *event = tarot_game_event_alloc ();
struct yarrow256_ctx rng;
static const char *seed = "default";
size_t i;
yarrow256_init (&rng, 0, NULL);
yarrow256_seed (&rng, strlen (seed), (const uint8_t *) seed);
if (event == NULL)
{
return 1;
}
prio = tarot_card_array_alloc ();
additional = tarot_card_array_alloc ();
if (tarot_game_hint_discard (mcts->base, &who, &n, prio, additional) != 0)
{
tarot_game_event_free (event);
tarot_card_array_free (prio);
tarot_card_array_free (additional);
return 1;
}
for (i = 0; i < 16; i++)
{
select_next_move_discard (event, n, prio, additional, &rng);
root = TREE_NULL;
if (mcts_expand (mcts, &root, event, who) != 0)
{
tarot_card_array_free (prio);
tarot_card_array_free (additional);
tarot_game_event_free (event);
return 1;
}
}
tarot_card_array_free (prio);
tarot_card_array_free (additional);
tarot_game_event_free (event);
return 0;
}
static int
mcts_setup_card (TarotMcts * mcts)
{
TarotPlayer who;
TarotCardArray *playable = tarot_card_array_alloc ();
TarotMctsTreeIterator root = TREE_NULL;
TarotGameEvent *event = tarot_game_event_alloc ();
size_t i, n;
if (event == NULL)
{
return 1;
}
if (tarot_game_hint_card (mcts->base, &who, playable) != 0)
{
tarot_card_array_free (playable);
tarot_game_event_free (event);
return 1;
}
n = tarot_card_array_size (playable);
if (n == 0)
{
tarot_card_array_free (playable);
tarot_game_event_free (event);
return 1;
}
for (i = 0; i < n; i++)
{
root = TREE_NULL;
if (tarot_game_event_set_card
(event, tarot_card_array_get (playable, i)) != 0)
{
tarot_card_array_free (playable);
tarot_game_event_free (event);
return 1;
}
if (mcts_expand (mcts, &root, event, who) != 0)
{
tarot_card_array_free (playable);
tarot_game_event_free (event);
return 1;
}
}
tarot_card_array_free (playable);
tarot_game_event_free (event);
return 0;
}
static inline int
mcts_setup_root (TarotMcts * mcts)
{
switch (tarot_game_step (mcts->base))
{
case TAROT_BIDS:
return mcts_setup_bids (mcts);
case TAROT_DECLS:
return mcts_setup_decls (mcts);
case TAROT_CALL:
return mcts_setup_call (mcts);
case TAROT_DISCARD:
return mcts_setup_discard (mcts);
case TAROT_TRICKS:
return mcts_setup_card (mcts);
default:
break;
}
return 1;
}
#include <tarot/mcts_tree_private_impl.h>
Markdown is supported
0% or
You are about to add 0 people to the discussion. Proceed with caution.
Finish editing this message first!
Please register or to comment