Commit 87b8a259 authored by Vivien Kraus's avatar Vivien Kraus
Browse files

Add a fuzzy AI

This is a combination of the random AI and a perceptron.  This will
let us tune the solo difficulty.
parent 2d9f4c50
......@@ -2494,6 +2494,13 @@ save its training iterations.
Create an AI that will give random scores and cannot learn.
#+end_deftypefun
#+attr_texinfo: :options {TarotAi *} tarot_ai_alloc_fuzzy (double @var{fuzziness}, size_t @var{seed_size}, const void *@var{seed}, const TarotAi *@var{base})
#+begin_deftypefun
Create an AI that will play as the weighted sum of a uniform random
predictor (with a weight of /fuzziness/) and /base/ (with a weight of
1 - /fuzziness/).
#+end_deftypefun
#+attr_texinfo: :options {TarotAi *} tarot_ai_dup (const TarotAi *@var{ai})
#+begin_deftypefun
Return an allocated copy of /ai/.
......
......@@ -99,6 +99,18 @@ tarot_ai_alloc_random (size_t seed_size, const void *seed)
ai_random_dup, ai_random_destruct);
}
TarotAi *
tarot_ai_alloc_fuzzy (double fuzziness, size_t seed_size, const void *seed,
const TarotAi * base)
{
TarotAi *ai1 = tarot_ai_alloc_random (seed_size, seed);
TarotAi *ret =
tarot_ai_alloc (NULL, eval_noop, learn_noop, dup_noop, destruct_noop);
ai_construct_barycenter (ret, fuzziness, ai1, 1 - fuzziness, base);
tarot_ai_free (ai1);
return ret;
}
void
tarot_ai_free (TarotAi * ai)
{
......
......@@ -60,6 +60,13 @@ extern "C"
*/
TarotAi *tarot_ai_alloc_random (size_t seed_size, const void *seed);
/**
* tarot_ai_alloc_fuzzy: (constructor)
* @seed: (array length=seed_size) (element-type char):
*/
TarotAi *tarot_ai_alloc_fuzzy (double fuzziness, size_t seed_size,
const void *seed, const TarotAi * base);
void tarot_ai_free (TarotAi * ai);
/**
......
......@@ -68,6 +68,10 @@ extern "C"
static void ai_perceptron_destruct (void *state);
static void ai_construct_barycenter (TarotAi * ai, double w1,
const TarotAi * ai1, double w2,
const TarotAi * ai2);
static void ai_eval (TarotAi * ai, const TarotGame * base,
size_t n_candidates, TarotGameEvent ** candidates,
size_t start, size_t max, double *scores);
......
......@@ -48,13 +48,19 @@ ai_construct (TarotAi * ai, void *user_data,
}
static inline void
ai_copy (TarotAi * ai, const TarotAi * source)
ai_copy_fresh (TarotAi * ai, const TarotAi * source)
{
ai_destruct (ai);
ai_construct (ai, source->dup (source->user_data), source->eval,
source->learn, source->dup, source->destruct);
}
static inline void
ai_copy (TarotAi * ai, const TarotAi * source)
{
ai_destruct (ai);
ai_copy_fresh (ai, source);
}
static inline void
ai_destruct (TarotAi * ai)
{
......@@ -71,6 +77,7 @@ ai_random_eval (void *state, const TarotGame * base, size_t n_candidates,
{
size_t max_size_t = (size_t) -1;
double maximum_value = max_size_t;
const double amplitude = 100;
size_t value;
uint8_t buffer[sizeof (value)];
size_t i;
......@@ -79,9 +86,11 @@ ai_random_eval (void *state, const TarotGame * base, size_t n_candidates,
(void) candidates;
for (i = 0; i < max && i + start < n_candidates; i++)
{
double unif;
yarrow256_random (prng, sizeof (buffer), buffer);
memcpy (&value, buffer, sizeof (buffer));
scores[i] = value / maximum_value;
unif = value / maximum_value;
scores[i] = (unif * 2 * amplitude) - amplitude;
}
}
......@@ -148,6 +157,77 @@ ai_perceptron_destruct (void *state)
tarot_perceptron_free (perceptron);
}
struct ai_barycenter_2
{
double w1;
TarotAi ai1;
double w2;
TarotAi ai2;
};
static inline void
ai_barycenter_2_eval (void *state, const TarotGame * base,
size_t n_candidates, TarotGameEvent ** candidates,
size_t start, size_t max, double *scores)
{
size_t i;
struct ai_barycenter_2 *couple = (struct ai_barycenter_2 *) state;
double *s1, *s2;
s1 = xcalloc (max, sizeof (double));
s2 = xcalloc (max, sizeof (double));
ai_eval (&(couple->ai1), base, n_candidates, candidates, start, max, s1);
ai_eval (&(couple->ai2), base, n_candidates, candidates, start, max, s2);
for (i = 0; i < max; i++)
{
scores[i] = couple->w1 * s1[i] + couple->w2 * s2[i];
}
free (s1);
free (s2);
}
static inline void
ai_barycenter_2_learn (void *state, const TarotGame * base,
const TarotGameEvent * event, double final_score)
{
struct ai_barycenter_2 *couple = (struct ai_barycenter_2 *) state;
ai_learn (&(couple->ai1), base, event, final_score);
ai_learn (&(couple->ai2), base, event, final_score);
}
static inline void *
ai_barycenter_2_dup (void *state)
{
struct ai_barycenter_2 *couple = (struct ai_barycenter_2 *) state;
struct ai_barycenter_2 *ret = xmalloc (sizeof (struct ai_barycenter_2));
ret->w1 = couple->w1;
ret->w2 = couple->w2;
ai_copy_fresh (&(ret->ai1), &(couple->ai1));
ai_copy_fresh (&(ret->ai2), &(couple->ai2));
return ret;
}
static inline void
ai_barycenter_2_destruct (void *state)
{
struct ai_barycenter_2 *couple = (struct ai_barycenter_2 *) state;
ai_destruct (&(couple->ai1));
ai_destruct (&(couple->ai2));
free (couple);
}
static inline void
ai_construct_barycenter (TarotAi * ai, double w1, const TarotAi * ai1,
double w2, const TarotAi * ai2)
{
struct ai_barycenter_2 *state = xmalloc (sizeof (struct ai_barycenter_2));
state->w1 = w1;
state->w2 = w2;
ai_copy_fresh (&(state->ai1), ai1);
ai_copy_fresh (&(state->ai2), ai2);
ai_construct (ai, state, ai_barycenter_2_eval, ai_barycenter_2_learn,
ai_barycenter_2_dup, ai_barycenter_2_destruct);
}
static inline void
ai_eval (TarotAi * ai, const TarotGame * base, size_t n_candidates,
TarotGameEvent ** candidates, size_t start, size_t max,
......
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