Skip to content
Snippets Groups Projects

Compare revisions

Changes are shown as if the source revision was being merged into the target revision. Learn more about comparing revisions.

Source

Select target project
No results found

Target

Select target project
  • francesco-bariatti/pingouins
  • Samuel.Felton/pingouins
  • Lucas.Clement/pingouins
3 results
Show changes
Commits on Source (10)
......@@ -20,3 +20,5 @@ GUI/GUI.iml
*.blg
*.nav
*.snm
*.layout
*.cbp
ai_vs_ai=1
ai_think_time=5000
ai_vs_ai_game_count=100
heuristic_ai_1=movement_freedom
heuristic_ai_2=default
send_game_to_gui=1
#include "config.hpp"
#include <iostream>
#include <fstream>
#include <algorithm>
#include "movement_freedom_heuristic.hpp"
namespace game {
config::config(std::string& filename) : ai_vs_ai(false), think_time(5000), game_count(100), heuristic_ai_1(nullptr), heuristic_ai_2(nullptr)
{
std::ifstream file;
std::string line;
file.open(filename);
if(file.is_open()){
while(std::getline(file,line)) {
line.erase(std::remove_if(line.begin(),line.end(),[](char c) {return std::isspace(c);}),
line.end());
size_t indexEqual = line.find_first_of('=');
const std::string& lvalue = line.substr(0,indexEqual);
const std::string& rvalue = line.substr(indexEqual+1);
handle_line(lvalue,rvalue);
}
file.close();
}
if(heuristic_ai_1 == nullptr) {
std::cout << "H1";
heuristic_ai_1 = new mcts::penguin_heuristic();
}
if(heuristic_ai_2 == nullptr) {
heuristic_ai_2 = new mcts::penguin_heuristic();
}
}
void config::handle_line(const std::string& option_name, const std::string& option_value)
{
if(option_name == "ai_vs_ai") {
set_game_mode(option_value);
} else if(option_name == "ai_think_time") {
set_think_time(option_value);
} else if(option_name == "ai_vs_ai_game_count") {
set_game_count(option_value);
} else if (option_name == "heuristic_ai_1") {
set_heuristic(option_value,1);
} else if (option_name == "heuristic_ai_2") {
set_heuristic(option_value,2);
} else if(option_name == "send_game_to_gui"){
set_send_game(option_value);
} else {
std::cerr << "Unknown option : " << option_name << std::endl;
}
}
void config::set_game_mode(const std::string& value)
{
int v = std::stoi(value);
ai_vs_ai = v;
}
void config::set_think_time(const std::string& value)
{
int v = std::stoi(value);
think_time = v;
}
void config::set_game_count(const std::string& value)
{
int v = std::stoi(value);
game_count = v;
}
void config::set_heuristic(const std::string& value, short player)
{
mcts::penguin_heuristic** h = player == 1 ? &heuristic_ai_1 : &heuristic_ai_2;
if(value == "left_up") {
*h = new mcts::go_left_up_heuristic();
}
if(value == "movement_freedom") {
*h = new mcts::movement_freedom_heuristic();
}
if(value == "default") {
*h = new mcts::penguin_heuristic();
} else {
std::cerr << "Unknown heuristic : " << value << std::endl;
}
}
void config::set_send_game(const std::string& value)
{
int v = std::stoi(value);
send_game_to_gui = v;
}
}
#ifndef __CONFIG_HPP__
#define __CONFIG_HPP__
#include <string>
#include "penguin_heuristic.hpp"
#include "penguin.hpp"
#define DEFAULT_FILENAME "AI.conf"
namespace game {
class config {
public:
const bool is_ai_vs_ai() {return ai_vs_ai;};
const bool should_send_game_to_gui(){return send_game_to_gui;};
const unsigned int get_think_time() { return think_time; };
const unsigned int get_game_count() { return game_count; };
const mcts::penguin_heuristic* get_heuristic(short player) {return player == 1 ? heuristic_ai_1 : heuristic_ai_2; };
~config() {delete heuristic_ai_1; delete heuristic_ai_2;}
static config& get_config()
{
static std::string s(DEFAULT_FILENAME);
static config c(s);
return c;
};
config(config const&) = delete;
void operator=(config const&) = delete;
private:
config(std::string& filename);
void handle_line(const std::string& option_name, const std::string& option_value);
void set_game_mode(const std::string& value);
void set_think_time(const std::string& value);
void set_game_count(const std::string& value);
void set_heuristic(const std::string& value, short player);
void set_send_game(const std::string& value);
bool ai_vs_ai, send_game_to_gui;
unsigned int think_time;
unsigned int game_count;
mcts::penguin_heuristic* heuristic_ai_1;
mcts::penguin_heuristic* heuristic_ai_2;
};
}
#endif
......@@ -358,6 +358,24 @@ namespace game
state.current_player_red = true;
}
}
const tile_content penguin::get_tile(std::uint8_t tile_index) const
{
for(int k = 0; k < 4; k++) {
if(PENGUIN_POS(state.peng_blue[k]) == tile_index)
return BLUE_PENGUIN;
if(PENGUIN_POS(state.peng_red[k]) == tile_index)
return RED_PENGUIN;
}
if(((state.one_fish >> (tile_index)) & 1) > 0)
return ONE_FISH;
if(((state.two_fish >> (tile_index)) & 1) > 0)
return TWO_FISH;
if(((state.three_fish >> tile_index) & 1) > 0)
return THREE_FISH;
return OBSTACLE;
}
string penguin::player_to_string(uint8_t player) const
{
......
......@@ -32,6 +32,8 @@ namespace game
bool canPlay_red = true;
bool canPlay_blue = true;
};
//Describes the possible content of a peguin game tile
enum tile_content {RED_PENGUIN,BLUE_PENGUIN,ONE_FISH,TWO_FISH,THREE_FISH,OBSTACLE};
// Useful macros to get values out of penguins
#define PENGUIN_POS(penguin) ((penguin) & 63)
......@@ -69,6 +71,12 @@ namespace game
std::shared_ptr<game<penguin_state>> do_copy() const;
std::uint64_t hash(std::uint16_t m) const;
std::uint64_t hash() const;
/**
Returns the content of a tile
i : the line, between 0 and 7
j : the column, between 0 and 7 if i is pair else between 0 and 8
*/
const tile_content get_tile(std::uint8_t tile_index) const;
private:
penguin_state state;
......
......@@ -23,20 +23,22 @@
#include "test_mcts_two_players.hpp"
#include "test_bits.hpp"
#include "learning.hpp"
#include "penguin_heuristic.hpp"
#include "config.hpp"
#include <omp.h>
using namespace std;
int main(int argc, char *argv[])
{
// util::test_fast_log(100000000);
// mcts::test_allocator(10, 2);
// omp_set_num_threads(8);
game::config& c = game::config::get_config();
//game::run_test_two_players_game(game::penguin());
mcts::run_test_mcts_two_players(game::penguin());
const mcts::penguin_heuristic& h1 = *(c.get_heuristic(1));
const mcts::penguin_heuristic& h2 = *(c.get_heuristic(2));
mcts::run_test_mcts_two_players(game::penguin(),h1,h2);
//util::test_bits(200000000);
return 0;
}
#ifndef __MCTS_SETTINGS_HPP__
#define __MCTS_SETTINGS_HPP__
// Allocated memory for the mcts. If not enough the program may crash
#define MCTS_ALLOCATOR_SIZE 1000000U
#define MCTS_ALLOCATOR_SIZE 100000000U
// Reflection time for every turn of the mcts (in ms)
#define MCTS_TURN_TIME 5000
......
#ifndef __HEURISTIC_HPP__
#define __HEURISTIC_HPP__
namespace mcts
{
template <typename Game>
class heuristic
{
public:
virtual float get_value(const Game& game, uint8_t move) const = 0;
virtual int get_count(const Game& game, uint8_t move) const = 0;
virtual ~heuristic(){};
};
template <typename Game>
class zero_knowledge : public heuristic<Game>
{
public:
float get_value(const Game& game, uint8_t move) const
{
return 0.f;
}
int get_count(const Game& game, uint8_t move) const
{
return 1;
}
};
}
#endif
......@@ -9,60 +9,68 @@
#include <fstream>
#include <vector>
#include "openings.hpp"
#include "heuristic.hpp"
namespace mcts
{
template <typename Game>
class mcts_two_players : public mcts<Game>
{
template <typename Game>
class mcts_two_players : public mcts<Game>
{
allocator alloc_;
const util::fast_log fast_log_;
const float C_;
const unsigned int nb_visits_before_expansion_;
const heuristic<Game>& heuristic_;
const bool new_version_;
inline node* select(const std::shared_ptr<Game>& game, std::mt19937& generator, node* parent);
inline void expand(const std::shared_ptr<Game>& game, node* n);
void think(const std::shared_ptr<Game>& game);
public:
mcts_two_players(Game& game, uint32_t milliseconds, float C, unsigned int nb_visits_before_expansion = 8, bool new_version = true);
public:
mcts_two_players(Game& game, uint32_t milliseconds, float C, unsigned int nb_visits_before_expansion = 8,
const heuristic<Game>& heuristic = zero_knowledge<Game>(), bool new_version = true);
void reset();
void init_with_openings(const openings& o);
inline uint16_t select_move();
void last_move(uint16_t move);
void last_moves(uint16_t computer, uint16_t other);
};
};
template <typename Game>
mcts_two_players<Game> make_mcts_two_players(Game& game, uint32_t milliseconds, float C, unsigned int nb_visits_before_expansion = 8, bool new_version = true)
{
return mcts_two_players<Game>(game, milliseconds, C, nb_visits_before_expansion, new_version);
}
template <typename Game>
mcts_two_players<Game> make_mcts_two_players(Game& game, uint32_t milliseconds, float C, unsigned int nb_visits_before_expansion = 8,
const heuristic<Game>& heuristic = zero_knowledge<Game>(),
bool new_version = true)
{
return mcts_two_players<Game>(game, milliseconds, C, nb_visits_before_expansion, heuristic, new_version);
}
template <typename Game>
mcts_two_players<Game>::mcts_two_players(Game& game, uint32_t milliseconds, float C, unsigned int nb_visits_before_expansion, bool new_version)
: mcts<Game>(game, milliseconds), C_(C), nb_visits_before_expansion_(nb_visits_before_expansion), new_version_(new_version)
{
template <typename Game>
mcts_two_players<Game>::mcts_two_players(Game& game, uint32_t milliseconds, float C, unsigned int nb_visits_before_expansion,
const heuristic<Game>& heuristic,
bool new_version)
: mcts<Game>(game, milliseconds), C_(C), nb_visits_before_expansion_(nb_visits_before_expansion),
heuristic_(heuristic), new_version_(new_version)
{
this->generators.assign(util::omp_util::get_num_threads(), std::mt19937());
this->root = alloc_.allocate(1);
}
}
template <typename Game>
void mcts_two_players<Game>::reset()
{
template <typename Game>
void mcts_two_players<Game>::reset()
{
alloc_.clear();
this->root = alloc_.allocate(1);
}
}
template <typename Game>
void mcts_two_players<Game>::init_with_openings(const openings& o)
{
template <typename Game>
void mcts_two_players<Game>::init_with_openings(const openings& o)
{
o.copy_to(this->root, alloc_);
}
}
template <typename Game>
node* mcts_two_players<Game>::select(const std::shared_ptr<Game>& game, std::mt19937& generator, node* parent)
{
template <typename Game>
node* mcts_two_players<Game>::select(const std::shared_ptr<Game>& game, std::mt19937& generator, node* parent)
{
using namespace std;
const unsigned int N = parent->get_statistics().count;
const float log_of_N = fast_log_.log(N);
......@@ -76,63 +84,63 @@ namespace mcts
unsigned int count;
float v;
for (uint16_t i = 0; i < nb_children; ++i)
{
{
node* child = children + k;
count = child->get_statistics().count;
v = -child->get_statistics().value + C_ * sqrt(log_of_N / count);
if (v > best_value_so_far)
{
{
best_value_so_far = v;
best_child_so_far = child;
best_move_so_far = k;
}
}
++k;
if (k == nb_children) k = 0;
}
}
if (best_child_so_far->is_proven())
{
{
if (best_child_so_far->is_lost()) parent->set_won();
else
{
{
bool all_won = true;
for (uint16_t i = 0; i < nb_children; ++i)
{
{
node* child = children + i;
if (!child->is_won())
{
{
all_won = false;
break;
}
}
}
}
if (all_won) parent->set_lost();
}
}
}
}
game->play(best_move_so_far);
return best_child_so_far;
}
}
template <typename Game>
void mcts_two_players<Game>::expand(const std::shared_ptr<Game>& game, node* n)
{
template <typename Game>
void mcts_two_players<Game>::expand(const std::shared_ptr<Game>& game, node* n)
{
unsigned int count = n->get_statistics().count;
if (count >= nb_visits_before_expansion_ && !n->test_and_set())
{
{
unsigned int nb_children = game->number_of_moves();
node* children = alloc_.allocate(nb_children);
for (unsigned int i = 0; i < nb_children; ++i)
{
{
node* child = children + i;
child->get_statistics_ref().count = 1;
child->get_statistics_ref().value = 0;
}
child->get_statistics_ref().count = heuristic_.get_count(*game, i);
child->get_statistics_ref().value = heuristic_.get_value(*game, i);
}
n->set_children(children);
n->set_number_of_children(nb_children);
}
}
}
}
template <typename Game>
void mcts_two_players<Game>::think(const std::shared_ptr<Game>& game)
{
template <typename Game>
void mcts_two_players<Game>::think(const std::shared_ptr<Game>& game)
{
using namespace std;
const chrono::steady_clock::time_point start = chrono::steady_clock::now();
chrono::steady_clock::time_point now;
......@@ -142,72 +150,72 @@ namespace mcts
vector<uint16_t> moves(200);
unsigned int nb_iter = 0;
do
{
{
int size = 1;
node* current = this->root;
visited[0] = current;
while (!game->end_of_game() && !current->is_leaf() && !current->is_proven())
{
{
current = select(game, generator, current);
visited[size++] = current;
}
}
int game_value = 0;
if (current->is_proven())
{
{
if (current->is_won()) game_value = 1;
else
{
{
game_value = -1;
}
}
}
}
else if (game->end_of_game())
{
{
int v = game->value_for_current_player();
if (v > 0)
{
{
game_value = 1;
if (new_version_) current->set_won();
}
}
else if (v < 0)
{
{
game_value = -1;
if (new_version_)
{
{
current->set_lost();
if (size > 1) visited[size - 2]->set_won();
}
}
}
}
}
}
else
{
{
uint8_t player = game->current_player();
expand(game, current);
game->playout(generator);
int v = game->value(player);
if (v > 0) game_value = 1;
else if (v < 0) game_value = -1;
}
}
for (int i = size - 1; i >= 0; --i)
{
{
visited[i]->update(game_value);
game_value = -game_value;
}
}
game->set_state(state);
++nb_iter;
if ((nb_iter & 0x3F) == 0) now = chrono::steady_clock::now();
}
}
while ((nb_iter & 0x3F) != 0 || now < start + this->milliseconds);
}
}
template <typename Game>
uint16_t mcts_two_players<Game>::select_move()
{
template <typename Game>
uint16_t mcts_two_players<Game>::select_move()
{
using namespace std;
if (!this->root->is_proven())
{
#pragma omp parallel
{
#pragma omp parallel
think(game::copy(this->game));
}
}
// std::ofstream ofs ("graph.gv", ofstream::out);
// util::display_node::node_to_dot(ofs, this->root, 1000, 50);
util::display_node::node_to_ascii(cout, this->root, 1);
......@@ -222,52 +230,52 @@ namespace mcts
node* children = this->root->get_children();
unsigned int c;
for (uint16_t i = 0; i < nb_children; ++i)
{
{
node *child = children + k;
if (child->is_lost())
{
{
best_move_so_far = k;
break;
}
}
c = children[k].get_statistics().count;
if (c > best_count_so_far)
{
{
best_count_so_far = c;
best_move_so_far = k;
}
}
++k;
if (k == nb_children) k = 0;
}
}
return best_move_so_far;
}
}
template <typename Game>
void mcts_two_players<Game>::last_moves(uint16_t computer, uint16_t other)
{
template <typename Game>
void mcts_two_players<Game>::last_moves(uint16_t computer, uint16_t other)
{
if (this->root->is_leaf() || this->root->get_children()[computer].is_leaf())
{
{
alloc_.clear();
this->root = alloc_.allocate(1);
}
}
else
{
{
this->root = alloc_.move(&this->root->get_children()[computer].get_children()[other]);
}
}
}
}
template <typename Game>
void mcts_two_players<Game>::last_move(uint16_t move)
{
template <typename Game>
void mcts_two_players<Game>::last_move(uint16_t move)
{
if (this->root->is_leaf())
{
{
alloc_.clear();
this->root = alloc_.allocate(1);
}
}
else
{
{
this->root = alloc_.move(&this->root->get_children()[move], 20);
}
}
}
}
}
......
#include <iostream>
#include "penguin_heuristic.hpp"
#include "movement_freedom_heuristic.hpp"
#include "penguin.hpp"
#define MAX_NB_MOVES 60
using namespace std;
namespace mcts
{
float movement_freedom_heuristic::get_value(const game::penguin& game, uint8_t move) const
{
std::shared_ptr<game::penguin> played = game::copy(game);
//TEST SOLUTION 1
played->play(move);
game::penguin_state state = played->get_state();
uint32_t* penguins = state.peng_blue;
if(!state.current_player_red) {
penguins = state.peng_red;
}
uint32_t nb_moves = 0;
for(int i=0; i< 4; i++) {
nb_moves += PENGUIN_TOT_MOVES(penguins[i]);
}
float res = 2.0f*(float)nb_moves / (float)MAX_NB_MOVES - 1.0f;
return res;
//TEST SOLUTION 2
/*
played->play(move);
uint32_t nb_moves = played->number_of_moves();
float res = 2.0f*(float)nb_moves / (float)MAX_NB_MOVES - 1.0f;
return res;
*/
//TEST SOLUTION 3
/*
played->play(move);
game::penguin_state state = played->get_state();
uint32_t nb_moves = state.nb_moves_blue;
if(!state.current_player_red) {
nb_moves = state.nb_moves_red;
}
float res = 2.0f*(float)nb_moves / (float)MAX_NB_MOVES - 1.0f;
return res;
*/
}
int movement_freedom_heuristic::get_count(const game::penguin& game, uint8_t move) const
{
return 100000000;
}
}
#ifndef __MOVEMENT_FREEDOM_HEURISTIC_HPP__
#define __MOVEMENT_FREEDOM_HEURISTIC_HPP__
#include "penguin.hpp"
#include "penguin_heuristic.hpp"
namespace mcts
{
class movement_freedom_heuristic : public penguin_heuristic
{
public:
float get_value(const game::penguin& game, uint8_t move) const;
int get_count(const game::penguin& game, uint8_t move) const;
};
};
#endif
#include "penguin_heuristic.hpp"
#include "penguin.hpp"
using namespace std;
namespace mcts
{
float penguin_heuristic::get_value(const game::penguin& game, uint8_t move) const
{
return 0.f;
}
int penguin_heuristic::get_count(const game::penguin& game, uint8_t move) const
{
return 1;
}
float go_left_up_heuristic::get_value(const game::penguin& game, uint8_t move) const
{
std::shared_ptr<game::penguin> played = game::copy(game);
played->play(move);
game::penguin_state state = played->get_state();
uint32_t* penguins = state.peng_blue;
if(!state.current_player_red) {
penguins = state.peng_red;
}
uint32_t sPos = 0;
for(int i=0; i< 4; i++) {
sPos+=PENGUIN_POS(penguins[i]);
}
double res = (double) (-(-118.0 + sPos) / 118.0);
return res;
}
int go_left_up_heuristic::get_count(const game::penguin& game, uint8_t move) const
{
return 100000000;
}
}
#ifndef __PENGUIN_HEURISTIC_HPP__
#define __PENGUIN_HEURISTIC_HPP__
#include "penguin.hpp"
#include "heuristic.hpp"
namespace mcts
{
class penguin_heuristic : public heuristic<game::penguin>
{
public:
virtual float get_value(const game::penguin& game, uint8_t move) const;
virtual int get_count(const game::penguin& game, uint8_t move) const;
};
class go_left_up_heuristic : public penguin_heuristic
{
public:
float get_value(const game::penguin& game, uint8_t move) const;
int get_count(const game::penguin& game, uint8_t move) const;
};
};
#endif
......@@ -10,67 +10,75 @@
#include <iomanip>
#include <set>
#include <fstream>
#include "heuristic.hpp"
#include "config.hpp"
namespace mcts
{
template <typename Game>
class test_mcts_two_players
{
template <typename Game>
class test_mcts_two_players
{
openings openings_;
void play(Game g);
void play(Game g, const heuristic<Game>& h);
void self_play(Game g);
void self_play(Game g, int n, bool with_openings = false);
void self_play(Game g, const heuristic<Game>& h1 = zero_knowledge<Game>(), const heuristic<Game>& h2 = zero_knowledge<Game>());
void self_play_learn_openings(Game g, int n);
void test_openings(Game g, int nb_learning, int nb_testing);
int select_move(Game& game);
public:
test_mcts_two_players(const Game& g);
};
public:
test_mcts_two_players(const Game& g, const heuristic<Game>& h1 = zero_knowledge<Game>(), const heuristic<Game>& h2 = zero_knowledge<Game>());
};
template <typename Game>
test_mcts_two_players<Game>::test_mcts_two_players(const Game& g) : openings_(g)
{
//self_play(g, 1000);
play(g);
//test_openings(g, 10000, 1000);
}
template <typename Game>
test_mcts_two_players<Game>::test_mcts_two_players(const Game& g, const heuristic<Game>& h, const heuristic<Game>& h2) : openings_(g)
{
game::config& config = game::config::get_config();
if(config.is_ai_vs_ai())
{
self_play(g, h,h2);
}
else
{
play(g, h);
}
}
template <typename Game>
void run_test_mcts_two_players(const Game& g)
{
test_mcts_two_players<Game>{g};
}
template <typename Game>
void run_test_mcts_two_players(const Game& g, const heuristic<Game>& h = zero_knowledge<Game>(),const heuristic<Game>& h2 = zero_knowledge<Game>())
{
test_mcts_two_players<Game> {g, h, h2};
}
template <typename Game>
void test_mcts_two_players<Game>::test_openings(Game g, int nb_learning, int nb_testing)
{
// self_play(g, nb_testing);
template <typename Game>
void test_mcts_two_players<Game>::test_openings(Game g, int nb_learning, int nb_testing)
{
//self_play(g, nb_testing);
self_play_learn_openings(g, nb_learning);
self_play(g, nb_testing, true);
}
}
template <typename Game>
int test_mcts_two_players<Game>::select_move(Game& game)
{
template <typename Game>
int test_mcts_two_players<Game>::select_move(Game& game)
{
std::cout << game.player_to_string(game.current_player()) << " move: ";
std::map<std::string, int> m;
for (int i = 0; i < game.number_of_moves(); ++i)
{
{
m[game.move_to_string(i)] = i;
}
}
std::string move;
getline(std::cin, move);
game.play(m[move]);
return m[move];
}
}
template <typename Game>
void test_mcts_two_players<Game>::play(Game g)
{
template <typename Game>
void test_mcts_two_players<Game>::play(Game g, const heuristic<Game>& h)
{
// ProfilerStart("theturk.prof");
auto the_turk = make_mcts_two_players(g, MCTS_TURN_TIME, 0.4, 8);
auto the_turk = make_mcts_two_players(g, MCTS_TURN_TIME, 0.4, 8, h);
std::cout << "play one game" << std::endl;
std::cout << "who's first? (h)uman/(c)omputer ";
std::string ans;
......@@ -78,41 +86,41 @@ namespace mcts
std::cout << g.to_string() << std::endl;
int human_last_move = -1, computer_last_move = -1;
while (!g.end_of_game())
{
{
if ((ans == "h" && g.current_player() == 0) || (ans == "c" && g.current_player() == 1))
{
{
human_last_move = select_move(g);
}
}
else
{
{
if (human_last_move != -1 && computer_last_move != -1)
{
{
the_turk.last_moves(computer_last_move, human_last_move);
}
}
uint16_t move = the_turk.select_move();
computer_last_move = move;
std::cout << g.player_to_string(g.current_player()) << " move: " << g.move_to_string(move) << std::endl;
g.play(move);
}
}
std::cout << g << std::endl;
}
}
if (g.won(0)) std::cout << g.player_to_string(0) << " won";
else if (g.won(1)) std::cout << g.player_to_string(1) << " won";
else std::cout << "draw";
std::cout << std::endl;
// ProfilerStop();
}
}
template <typename Game>
void test_mcts_two_players<Game>::self_play_learn_openings(Game g, int n)
{
template <typename Game>
void test_mcts_two_players<Game>::self_play_learn_openings(Game g, int n)
{
std::vector<uint16_t> moves(200);
auto state = g.get_state();
auto the_turk_1 = make_mcts_two_players(g, 1000, 0.6, 2);
auto the_turk_2 = make_mcts_two_players(g, 1000, 0.6, 2);
std::map<std::set<int>, std::pair<std::uint32_t, double>> learning_examples;
for (int i = 0; i < n; ++i)
{
{
std::cout << i << std::endl;
std::cout << openings_ << std::endl << std::endl;
moves.clear();
......@@ -124,144 +132,148 @@ namespace mcts
int the_turk_1_last_move = -1, the_turk_2_last_move = -1;
int k = 0;
while (!g.end_of_game())
{
{
if (k == 1) the_turk_2.last_move(the_turk_1_last_move);
if (k % 2 == 0)
{
{
if (the_turk_2_last_move != -1)
{
{
the_turk_1.last_moves(the_turk_1_last_move, the_turk_2_last_move);
}
}
std::uint16_t move = the_turk_1.select_move();
moves.push_back(move);
the_turk_1_last_move = move;
g.play(move);
}
}
else
{
{
if (the_turk_2_last_move != -1)
{
{
the_turk_2.last_moves(the_turk_2_last_move, the_turk_1_last_move);
}
}
std::uint16_t move = the_turk_2.select_move();
moves.push_back(move);
the_turk_2_last_move = move;
g.play(move);
}
}
++k;
}
std::cout << g.to_string() << std::endl;
}
std::cout << g.to_string() << std::endl;
int v = g.value(0);
std::cout << "value for first player " << v << std::endl;
g.set_state(state);
openings_.update(g, moves, v);
g.set_state(state);
for (std::uint16_t m : moves)
{
g.play(m);
v = -v;
std::set<int> input_vector = std::move(g.to_input_vector());
auto it = learning_examples.find(input_vector);
if (it == learning_examples.end())
{
learning_examples[input_vector] = std::make_pair(1, v);
}
else
{
it->second.second = (it->second.second * it->second.first + v) / (it->second.first + 1);
it->second.first += 1;
}
}
}
g.set_state(state);
for (std::uint16_t m : moves)
{
g.play(m);
v = -v;
std::set<int> input_vector = std::move(g.to_input_vector());
auto it = learning_examples.find(input_vector);
if (it == learning_examples.end())
{
learning_examples[input_vector] = std::make_pair(1, v);
}
else
{
it->second.second = (it->second.second * it->second.first + v) / (it->second.first + 1);
it->second.first += 1;
}
}
}
std::cout << "number of learning examples: " << learning_examples.size() << std::endl;
std::ofstream output("learning_examples.txt");
for (const auto& example : learning_examples)
{
output << example.second.second;
for (int index : example.first)
{
output << " " << index << ":" << 1;
}
output << std::endl;
}
{
output << example.second.second;
for (int index : example.first)
{
output << " " << index << ":" << 1;
}
output << std::endl;
}
output.close();
}
}
template <typename Game>
void test_mcts_two_players<Game>::self_play(Game g, int n, bool with_openings)
{
template <typename Game>
void test_mcts_two_players<Game>::self_play(Game g, const heuristic<Game>& h1, const heuristic<Game>& h2)
{
game::config& c = game::config::get_config();
auto state = g.get_state();
auto the_turk_v1 = make_mcts_two_players(g, 1000, 0.6, 2);
auto the_turk_v2 = make_mcts_two_players(g, 1000, 0.6, 2);
auto the_turk_v1 = make_mcts_two_players(g, c.get_think_time(), 0.6, 2, h1);
auto the_turk_v2 = make_mcts_two_players(g, c.get_think_time(), 0.6, 2, h2);
int nb_win_v1 = 0, nb_win_v2 = 0, nb_draw = 0;
for (int i = 0; i < n; ++i)
{
std::cout << i << std::endl;
for (unsigned int i = 0; i < c.get_game_count(); ++i)
{
std::cout << i << std::endl;
g.set_state(state);
the_turk_v1.reset();
the_turk_v2.reset();
if (with_openings) the_turk_v2.init_with_openings(openings_);
int the_turk_v1_last_move = -1, the_turk_v2_last_move = -1;
int k = 0;
int k = 0;
while (!g.end_of_game())
{
if (with_openings && k == 1 && i % 2 == 0) the_turk_v2.last_move(the_turk_v1_last_move);
++k;
{
++k;
// cout << c4 << endl;
if ((i % 2 == 0 && g.current_player() == 0) || (i % 2 == 1 && g.current_player() == 1))
{
{
if (the_turk_v1_last_move != -1 && the_turk_v2_last_move != -1)
{
{
the_turk_v1.last_moves(the_turk_v1_last_move, the_turk_v2_last_move);
}
}
std::uint16_t move = the_turk_v1.select_move();
the_turk_v1_last_move = move;
g.play(move);
}
}
else
{
{
if (the_turk_v1_last_move != -1 && the_turk_v2_last_move != -1)
{
{
the_turk_v2.last_moves(the_turk_v2_last_move, the_turk_v1_last_move);
}
}
std::uint16_t move = the_turk_v2.select_move();
the_turk_v2_last_move = move;
play(move);
}
}
g.play(move);
}
if(c.should_send_game_to_gui())
std::cout << g;
}
if (g.won(0))
{
{
if (i % 2 == 0)
{
{
/*cout << "v1 won" << endl;*/ ++nb_win_v1;
}
}
else
{
{
/*cout << "v2 won" << endl;*/ ++nb_win_v2;
}
}
}
}
else if (g.won(1))
{
{
if (i % 2 == 0)
{
{
/*cout << "v2 won" << endl;*/ ++nb_win_v2;
}
}
else
{
{
/*cout << "v1 won" << endl;*/ ++nb_win_v1;
}
}
}
}
else
{
{
/*cout << "draw" << endl;*/ ++nb_draw;
}
}
std::cout << std::setw(10) << "v1 nb wins: " << nb_win_v1 << " v2 nb wins: " << nb_win_v2 << " nb draws: " << nb_draw << std::endl;
}
}
}
}
template <typename Game>
void test_mcts_two_players<Game>::self_play(Game g)
{
template <typename Game>
void test_mcts_two_players<Game>::self_play(Game g)
{
auto the_turk_v1 = make_mcts_two_players(g, 1000, 1.2, 2);
auto the_turk_v2 = make_mcts_two_players(g, 1000, 1.2, 2);
std::cout << "play one game" << std::endl;
......@@ -271,36 +283,36 @@ namespace mcts
std::cout << g << std::endl;
int the_turk_v1_last_move = -1, the_turk_v2_last_move = -1;
while (!g.end_of_game())
{
{
if ((ans == "v1" && g.current_player() == 0) || (ans == "v2" && g.current_player() == 1))
{
{
if (the_turk_v1_last_move != -1 && the_turk_v2_last_move != -1)
{
{
the_turk_v1.last_moves(the_turk_v1_last_move, the_turk_v2_last_move);
}
}
std::uint16_t move = the_turk_v1.select_move();
the_turk_v1_last_move = move;
std::cout << g.player_to_string(g.current_player()) << " move: " << g.move_to_string(move) << std::endl;
g.play(move);
}
}
else
{
{
if (the_turk_v1_last_move != -1 && the_turk_v2_last_move != -1)
{
{
the_turk_v2.last_moves(the_turk_v2_last_move, the_turk_v1_last_move);
}
}
std::uint16_t move = the_turk_v2.select_move();
the_turk_v2_last_move = move;
std::cout << g.player_to_string(g.current_player()) << " move: " << g.move_to_string(move) << std::endl;
g.play(move);
}
std::cout << g << std::endl;
}
}
std::cout << g << std::endl;
}
if (g.won(0)) std::cout << g.player_to_string(0) << " won";
else if (g.won(1)) std::cout << g.player_to_string(1) << " won";
else std::cout << "draw";
std::cout << std::endl;
}
}
}
......
......@@ -35,7 +35,7 @@ AIInclude=-I $(AISRC)/game -I $(AISRC)/util -I $(AISRC)/monte_carlo -I $(AISRC)/
# Cpp source files
AISourceFile = omp_util.cpp fast_log.cpp display_node.cpp penguin.cpp test_two_players_game.cpp monte_carlo.cpp \
test_fast_log.cpp statistics.cpp node.cpp allocator.cpp test_allocator.cpp openings.cpp mcts_two_players.cpp \
test_mcts_two_players.cpp bits.cpp test_bits.cpp main.cpp
test_mcts_two_players.cpp bits.cpp test_bits.cpp penguin_heuristic.cpp movement_freedom_heuristic.cpp main.cpp config.cpp
# Directories in which make will search for files
vpath %.cpp $(AISRC)/game $(AISRC)/main $(AISRC)/util $(AISRC)/monte_carlo $(AISRC)/mcts $(AISRC)/gdl
# Flags passed to the compiler
......