Commit 1085d15b authored by Vivien Kraus's avatar Vivien Kraus
Browse files

Play truly at random

If I were to use a random perceptron, random bid would be either pass
or double keep (because the only feature that would vary would be the
strength strategy, which is linear).
parent d5318d1d
......@@ -187,29 +187,115 @@ Copyright © 2019 Vivien Kraus\nThis is free software; see the source for copyin
}
}
static TarotPerceptron *
random_perceptron (const TarotPerceptron * base)
static TarotGameEvent *
random_move (const TarotGame * game)
{
TarotPerceptron *ret = tarot_perceptron_dup (base);
size_t n_parameters;
double *parameters;
size_t size_shuffled;
tarot_perceptron_save_alloc (ret, &n_parameters, &parameters);
/* We shuffle the weights */
for (size_shuffled = 1; size_shuffled < n_parameters; size_shuffled++)
TarotBid mini_bid;
int decl_allowed;
TarotPlayer next;
TarotNumber mini_call;
size_t n_cards;
size_t n_prio;
size_t n_additional;
TarotCard *prio;
TarotCard *additional;
if (tarot_game_get_hint_bid (game, &next, &mini_bid) == TAROT_GAME_OK)
{
uint8_t position_data[sizeof (size_t)];
TarotBid acceptable[5] = { TAROT_PASS };
size_t n_acceptable = 1;
TarotBid consider;
size_t position;
double hold = parameters[size_shuffled];
uint8_t position_data[sizeof (position)];
for (consider = mini_bid; consider <= TAROT_DOUBLE_KEEP; consider++)
{
acceptable[n_acceptable++] = consider;
}
yarrow256_random (&generator, sizeof (position_data), position_data);
memcpy (&position, position_data, sizeof (size_t));
position %= (size_shuffled + 1);
parameters[size_shuffled] = parameters[position];
parameters[position] = hold;
memcpy (&position, position_data, sizeof (position));
position %= n_acceptable;
return tarot_game_event_alloc_bid (acceptable[position]);
}
else if (tarot_game_get_hint_decl (game, &next, &decl_allowed) ==
TAROT_GAME_OK)
{
uint8_t no_decl;
/* Even in high-exploration scenarios, we want to avoid slam
* declarations. */
yarrow256_random (&generator, sizeof (no_decl), &no_decl);
no_decl %= 16;
if (no_decl == 0 && decl_allowed)
{
return tarot_game_event_alloc_decl (1);
}
else
{
return tarot_game_event_alloc_decl (0);
}
}
else if (tarot_game_get_hint_call (game, &next, &mini_call) ==
TAROT_GAME_OK)
{
static const TarotSuit suits[] = {
TAROT_HEARTS, TAROT_CLUBS, TAROT_DIAMONDS, TAROT_SPADES
};
uint8_t suit_i;
TarotCard c;
yarrow256_random (&generator, sizeof (suit_i), &suit_i);
suit_i %= (sizeof (suits) / sizeof (suits[0]));
if (tarot_of (mini_call, suits[suit_i], &c) != 0)
{
assert (0);
}
return tarot_game_event_alloc_call (c);
}
tarot_perceptron_load (ret, 0, n_parameters, parameters);
free (parameters);
return ret;
else
if (tarot_game_get_hint_discard_alloc
(game, &next, &n_cards, &n_prio, &prio, &n_additional,
&additional) == TAROT_GAME_OK)
{
TarotCard selected[78];
size_t n_selected = 0;
size_t n_selectable = n_prio;
TarotCard *selectable = prio;
size_t i;
if (n_prio < n_cards)
{
n_selectable = n_additional;
selectable = additional;
for (n_selected = 0; n_selected < n_prio; n_selected++)
{
selected[n_selected] = prio[n_selected];
}
}
for (i = n_selected; i < n_cards; i++)
{
size_t position;
uint8_t position_data[sizeof (position)];
yarrow256_random (&generator, sizeof (position), position_data);
memcpy (&position, position_data, sizeof (position));
position %= n_selectable;
selected[i] = selectable[position];
selectable[position] = selectable[--n_selectable];
}
free (prio);
free (additional);
return tarot_game_event_alloc_discard (n_cards, selected);
}
else if (tarot_game_get_hint_card_alloc (game, &next, &n_prio, &prio) ==
TAROT_GAME_OK)
{
TarotCard selected;
size_t position;
uint8_t position_data[sizeof (position)];
yarrow256_random (&generator, sizeof (position), position_data);
memcpy (&position, position_data, sizeof (position));
position %= n_prio;
selected = prio[position];
free (prio);
return tarot_game_event_alloc_card (selected);
}
assert (0);
return NULL;
}
static void
......@@ -286,26 +372,27 @@ self_learn (TarotPerceptron * perceptron)
unsigned long behavior_max = (unsigned long) (-1);
double behavior_dbl;
double max_dbl = behavior_max;
TarotPerceptron *p_generator = perceptron;
double score;
const TarotGameEvent *next;
TarotGameEvent *next;
yarrow256_random (&generator, sizeof (behavior_data),
behavior_data);
memcpy (&behavior, behavior_data, sizeof (behavior));
behavior_dbl = behavior;
if (behavior_dbl / max_dbl < exploration)
{
p_generator = random_perceptron (perceptron);
next = random_move (game);
}
next = tarot_perceptron_best (p_generator, game, &score);
if (tarot_game_add_event (game, next) != TAROT_GAME_OK)
else
{
assert (0);
next =
tarot_game_event_dup (tarot_perceptron_best
(perceptron, game, &score));
}
if (p_generator != perceptron)
if (tarot_game_add_event (game, next) != TAROT_GAME_OK)
{
tarot_perceptron_free (p_generator);
assert (0);
}
tarot_game_event_free (next);
}
}
metric = tarot_perceptron_validate (perceptron, game);
......
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