Commit fcb7a574 authored by Vivien Kraus's avatar Vivien Kraus
Browse files

Implement the tarot-mcts command

This command will play the next move as the MCTS for a given game.
parent 3e88a65f
......@@ -47,6 +47,7 @@
/doc/players-and-cards.c
/doc/tarot-deal.man
/doc/tarot-figures
/doc/tarot-mcts.man
/doc/tarot-status.man
/doc/tarot-tune
/doc/tarot.info
......
......@@ -19,11 +19,13 @@
dist_man6_MANS += \
%reldir%/tarot.man \
%reldir%/tarot-status.man \
%reldir%/tarot-deal.man
%reldir%/tarot-deal.man \
%reldir%/tarot-mcts.man
MAINTAINERCLEANFILES += \
$(srcdir)/%reldir%/tarot.man \
$(srcdir)/%reldir%/tarot-status.man \
$(srcdir)/%reldir%/tarot-deal.man
$(srcdir)/%reldir%/tarot-deal.man \
$(srcdir)/%reldir%/tarot-mcts.man
help2man_verbose = $(help2man_verbose_@AM_V@)
help2man_verbose_ = $(help2man_verbose_@AM_DEFAULT_V@)
......@@ -40,3 +42,7 @@ $(srcdir)/%reldir%/tarot-status.man: src/tarot-app/tarot_status.c
$(srcdir)/%reldir%/tarot-deal.man: src/tarot-app/tarot_deal.c
$(MAKE) $(AM_MAKEFLAGS) src/tarot-app/tarot-deal
$(help2man_verbose) ./pre-inst-env help2man tarot-deal > $@
$(srcdir)/%reldir%/tarot-mcts.man: src/tarot-app/tarot_mcts.c
$(MAKE) $(AM_MAKEFLAGS) src/tarot-app/tarot-mcts
$(help2man_verbose) ./pre-inst-env help2man tarot-mcts > $@
......@@ -8,8 +8,8 @@ msgid ""
msgstr ""
"Project-Id-Version: tarot 0.4.2.83-ebdc-dirty\n"
"Report-Msgid-Bugs-To: vivien@planete-kraus.eu\n"
"POT-Creation-Date: 2019-08-24 19:22+0200\n"
"PO-Revision-Date: 2019-08-24 19:02+0200\n"
"POT-Creation-Date: 2019-08-24 20:29+0200\n"
"PO-Revision-Date: 2019-08-24 20:30+0200\n"
"Last-Translator: Vivien Kraus <vivien@planete-kraus.eu>\n"
"Language-Team: French\n"
"Language: fr\n"
......@@ -1227,6 +1227,22 @@ msgstr "- %s\n"
msgid "Error: invalid game.\n"
msgstr "Erreur : partie invalide.\n"
#: src/tarot-app/program_commons.c:157
msgid "GiB"
msgstr "GiB"
#: src/tarot-app/program_commons.c:163
msgid "MiB"
msgstr "MiB"
#: src/tarot-app/program_commons.c:169
msgid "KiB"
msgstr "KiB"
#: src/tarot-app/program_commons.c:175
msgid "B"
msgstr "B"
#~ msgid "Hello, world!\n"
#~ msgstr "Bonjour, le monde !\n"
......
......@@ -23,3 +23,4 @@ include %reldir%/run-with-c-locale.am
include %reldir%/tarot-program-commons.am
include %reldir%/tarot-status.am
include %reldir%/tarot-deal.am
include %reldir%/tarot-mcts.am
......@@ -149,30 +149,37 @@ static size_t
parse_unit (const char *str, char **end)
{
char *my_end = (char *) str;
char *test;
if (parse_whitespace (my_end, &my_end))
{
return parse_unit (my_end, end);
}
if (strncmp (my_end, _ ("GiB")) == 0)
test = _ ("GiB");
if (strncmp (my_end, test, strlen (test)) == 0)
{
*end = my_end + strlen (_ ("GiB"));
*end = my_end + strlen (test);
return UNIT_GiB;
}
if (strncmp (my_end, _ ("MiB")) == 0)
test = _ ("MiB");
if (strncmp (my_end, test, strlen (test)) == 0)
{
*end = my_end + strlen (_ ("MiB"));
*end = my_end + strlen (test);
return UNIT_MiB;
}
if (strncmp (my_end, _ ("KiB")) == 0)
test = _ ("KiB");
if (strncmp (my_end, test, strlen (test)) == 0)
{
*end = my_end + strlen (_ ("KiB"));
*end = my_end + strlen (test);
return UNIT_KiB;
}
if (strncmp (my_end, _ ("B")) == 0)
test = _ ("B");
if (strncmp (my_end, test, strlen (test)) == 0)
{
*end = my_end + strlen (_ ("B"));
*end = my_end + strlen (test);
return UNIT_B;
}
*end = my_end;
return UNIT_B;
}
static int
......
# tarot-mcts.am
#
# Copyright (C) 2019 Vivien Kraus <vivien@planete-kraus.eu>
#
# This program is free software: you can redistribute it and/or
# modify it under the terms of the GNU General Public License as
# published by the Free Software Foundation, either version 3 of the
# License, or (at your option) any later version.
#
# This program is distributed in the hope that it will be useful, but
# WITHOUT ANY WARRANTY; without even the implied warranty of
# MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
# General Public License for more details.
#
# You should have received a copy of the GNU General Public License
# along with this program. If not, see
# <http://www.gnu.org/licenses/>.
bin_PROGRAMS += %reldir%/tarot-mcts
%canon_reldir%_tarot_mcts_SOURCES = \
%reldir%/tarot_mcts.c
%canon_reldir%_tarot_mcts_LDADD = \
%reldir%/libprogram-commons.la \
lib/libgnu.la \
src/libtarot/libtarot.la \
$(LTLIBINTL) \
$(LTLIBTHREAD) \
@INTL_MACOSX_LIBS@
/*
* tarot_mcts.c
*
* Copyright (C) 2019 Vivien Kraus <vivien@planete-kraus.eu>
*
* This program is free software: you can redistribute it and/or
* modify it under the terms of the GNU General Public License as
* published by the Free Software Foundation, either version 3 of the
* License, or (at your option) any later version.
*
* This program is distributed in the hope that it will be useful, but
* WITHOUT ANY WARRANTY; without even the implied warranty of
* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
* General Public License for more details.
*
* You should have received a copy of the GNU General Public License
* along with this program. If not, see
* <http://www.gnu.org/licenses/>.
*/
#include "program_commons.h"
#include <tuneconfig.h>
static char *default_seed = "default";
static size_t mem = 2 * 1024 * 1024;
static char **seed = &default_seed;
static size_t n_iterations = TUNE_ITERATIONS;
static double parameter = TUNE_PARAMETER;
static double simulation_random = TUNE_SIMULATION_RANDOM;
static double simulation_agreed = TUNE_SIMULATION_AGREED;
static void parse_options (int argc, char *argv[]);
static void check_error (TarotMctsError err);
int
main (int argc, char *argv[])
{
TarotGame *game = NULL;
char *output;
TarotMcts *mcts = NULL;
const TarotGameEvent *event = NULL;
TarotGameEvent *dog_event;
size_t n_cards;
TarotCard *cards;
tarot_program_setup ();
parse_options (argc, argv);
game = tarot_program_read_game ();
mcts = tarot_mcts_alloc (mem);
tarot_mcts_seed (mcts, strlen (*seed), *seed);
tarot_mcts_set_parameter (mcts, parameter);
tarot_mcts_set_simulation_random (mcts, simulation_random);
tarot_mcts_set_simulation_agreed (mcts, simulation_agreed);
check_error (tarot_mcts_set_base (mcts, game));
check_error (tarot_mcts_run (mcts, n_iterations));
event = tarot_mcts_get_best (mcts);
if (tarot_game_add_event (game, event) != TAROT_GAME_OK)
{
abort ();
}
if (tarot_game_can_autoreveal_alloc (game, &n_cards, &cards))
{
dog_event = tarot_game_event_alloc_dog (n_cards, cards);
if (tarot_game_add_event (game, dog_event) != TAROT_GAME_OK)
{
abort ();
}
}
output = tarot_game_save_to_xml_alloc (game);
printf ("%s", output);
return EXIT_SUCCESS;
}
static void
parse_options (int argc, char *argv[])
{
int c;
char *end;
while (1)
{
static struct option long_options[] =
{
{N_ ("help"), no_argument, 0, 'h'},
{N_ ("version"), no_argument, 0, 'v'},
{N_ ("max-memory"), required_argument, 0, 'm'},
{N_ ("seed"), required_argument, 0, 's'},
{N_ ("n-iterations"), required_argument, 0, 'i'},
{N_ ("mcts-parameter"), required_argument, 0, 'p'},
{N_ ("parameter-random"), required_argument, 0, 'r'},
{N_ ("parameter-agreed"), required_argument, 0, 'a'},
{0, 0, 0, 0}
};
int option_index = 0;
for (option_index = 0; long_options[option_index].name != NULL; option_index++)
{
long_options[option_index].name = _ (long_options[option_index].name);
}
option_index = 0;
c = getopt_long (argc, argv, "hvm:s:i:p:r:a:", long_options, &option_index);
if (c == -1)
break;
switch (c)
{
case 0:
break;
case 'h':
printf (_ ("Usage: tarot-mcts [OPTIONS]... < GAME\n\
Play as the MCTS in GAME. Options:\n\
- -h, --help: print this message and exit;\n\
- -v, --version: print the program version and exit;\n\
- -m SZ, --max-memory=SZ: define the maximum memory (default: %lu B).\n\
You can use the following suffixes: 'GiB', 'MiB', 'KiB', or 'B'.\n\
By default, numbers will be treated as bytes;\n\
- -s SEED, --seed=\"SEED\": set the seed for the random deal. SEED\n\
must not be empty;\n\
- -i N, --n-iterations=N: set the number of iterations. The higher\n\
the better. Default: %lu;\n\
- -p X, --mcts-parameter=X: set the MCTS parameter (default: %f);\n\
- -r X, --parameter-random=X: set the fraction of simulations that are\n\
drawn uniformly (default: %f);\n\
- -a X, --parameter-agreed=X: set the fraction of simulations that are\n\
negociated between all players (default: %f);\n\
\n\
If the seed leads to a petit sec, then the deal fails. So in case of\n\
a failure you may want to retry for a few different seeds.\n\
"), mem, n_iterations, parameter, simulation_random, simulation_agreed);
exit (EXIT_SUCCESS);
break;
case 'v':
printf (_ ("%s (libtarot %s)\n\
\n\
Copyright © 2019 Vivien Kraus\nThis is free software; see the source for copying conditions. There is NO warranty; not even for MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.\n"),
"tarot-mcts",
tarot_libtarot_version ());
exit (EXIT_SUCCESS);
break;
case 'm':
mem = tarot_strtosz (optarg, &end);
if (strcmp (end, optarg) == 0)
{
fprintf (stderr, _ ("Error: the memory limit should be a size in bytes, not '%s'.\n"),
optarg);
exit (EXIT_FAILURE);
}
else if (strcmp (end, "") != 0)
{
fprintf (stderr, _ ("Error: the memory limit (%lu bytes) has an unexpected suffix, '%s': '%s'.\n"),
mem, end, optarg);
exit (EXIT_FAILURE);
}
break;
case 's':
*seed = strdup (optarg);
if (strlen (*seed) == 0)
{
fprintf (stderr, _ ("Error: the seed must not be empty. The default is usually \"default\".\n"));
exit (EXIT_FAILURE);
}
break;
case 'i':
n_iterations = strtoul (optarg, &end, 10);
if (strcmp (end, optarg) == 0)
{
fprintf (stderr, _ ("Error: the number of iterations should be a number, not '%s'.\n"),
optarg);
exit (EXIT_FAILURE);
}
else if (strcmp (end, "") != 0)
{
fprintf (stderr, _ ("Error: the number of iterations (%lu) has an unexpected suffix, '%s': '%s'.\n"),
n_iterations, end, optarg);
exit (EXIT_FAILURE);
}
break;
case 'p':
parameter = strtod (optarg, &end);
if (strcmp (end, optarg) == 0)
{
fprintf (stderr, _ ("Error: the MCTS parameter should be a number, not '%s'.\n"),
optarg);
exit (EXIT_FAILURE);
}
else if (strcmp (end, "") != 0)
{
fprintf (stderr, _ ("Error: the MCTS parameter (%f) has an unexpected suffix, '%s': '%s'.\n"),
parameter, end, optarg);
exit (EXIT_FAILURE);
}
break;
case 'r':
simulation_random = strtod (optarg, &end);
if (strcmp (end, optarg) == 0)
{
fprintf (stderr, _ ("Error: the random parameter should be a number, not '%s'.\n"),
optarg);
exit (EXIT_FAILURE);
}
else if (strcmp (end, "") != 0)
{
fprintf (stderr, _ ("Error: the random parameter (%f) has an unexpected suffix, '%s': '%s'.\n"),
simulation_random, end, optarg);
exit (EXIT_FAILURE);
}
if (simulation_random < 0 || simulation_random > 1)
{
fprintf (stderr, _ ("Error: the random parameter shoul be between 0 and 1, not %f.\n"),
simulation_random);
}
break;
case 'a':
simulation_agreed = strtod (optarg, &end);
if (strcmp (end, optarg) == 0)
{
fprintf (stderr, _ ("Error: the agreement parameter should be a number, not '%s'.\n"),
optarg);
exit (EXIT_FAILURE);
}
else if (strcmp (end, "") != 0)
{
fprintf (stderr, _ ("Error: the agreement parameter (%f) has an unexpected suffix, '%s': '%s'.\n"),
simulation_agreed, end, optarg);
exit (EXIT_FAILURE);
}
if (simulation_agreed < 0 || simulation_agreed > 1)
{
fprintf (stderr, _ ("Error: the agreement parameter shoul be between 0 and 1, not %f.\n"),
simulation_agreed);
}
break;
case '?':
/* getopt_long already printed an error message. */
exit (EXIT_FAILURE);
break;
default:
abort ();
}
}
if (optind < argc)
{
fprintf (stderr, _ ("Error: extra arguments:\n"));
while (optind < argc)
fprintf (stderr, _ ("- %s\n"), argv[optind++]);
exit (EXIT_FAILURE);
}
}
static void
check_error (TarotMctsError err)
{
switch (err)
{
case TAROT_MCTS_NONEXT:
fprintf (stderr, _ ("Error: no player needs to play in this game.\n"));
exit (EXIT_FAILURE);
case TAROT_MCTS_UNKNOWNNEXT:
fprintf (stderr, _ ("Error: we don't know the cards of the next player.\n"));
exit (EXIT_FAILURE);
case TAROT_MCTS_NODATA:
fprintf (stderr, _ ("Error: too few experiments. Please use more iterations.\n"));
exit (EXIT_FAILURE);
case TAROT_MCTS_NOMEM:
fprintf (stderr, _ ("Error: memory exceeded. Please pass --max-memory=SIZE.\n"));
exit (EXIT_FAILURE);
}
}
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