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 (37)
Showing
with 710 additions and 10 deletions
......@@ -20,3 +20,6 @@ GUI/GUI.iml
*.blg
*.nav
*.snm
*.layout
*.cbp
test/*
ai_vs_ai=1
ai_think_time=5000
<<<<<<< HEAD
ai_vs_ai_game_count=100
heuristic_ai_1=movement_freedom
=======
ai_vs_ai_game_count=10
heuristic_ai_1=points
>>>>>>> 26387090f3eb3945d1382de1d372737abf83c5d0
heuristic_ai_2=default
send_game_to_gui=1
#include "config.hpp"
#include <iostream>
#include <fstream>
#include <algorithm>
#include "movement_freedom_heuristic.hpp"
#include "number_direction_freedom_heuristic.hpp"
#include "points_heuristic.hpp"
#include "go_left_up_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();
}else if(value == "direction_freedom") {
*h = new mcts::number_direction_freedom_heuristic();
}else if(value == "points") {
std::cout << "POINTS" << std::endl;
*h = new mcts::points_heuristic();
}else if(value == "movement_freedom") {
*h = new mcts::movement_freedom_heuristic();
}else 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
#include "penguin.hpp"
#include <sstream>
#include <random>
#include <algorithm>
using namespace std;
namespace game
......@@ -63,6 +64,13 @@ namespace game
state.nb_moves_blue = 1; //We create an artificial move so that the mcts works
}
}
penguin::penguin(bool b)
{
if(b)
{
set_state(penguin::random_start_state());
}
}
shared_ptr<game<penguin_state>> penguin::do_copy() const
{
......@@ -358,6 +366,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
{
......@@ -428,4 +454,59 @@ namespace game
os << pen.to_string();
return os;
}
penguin_state penguin::random_start_state()
{
std::random_device rd;
std::default_random_engine generator(rd());
std::uniform_int_distribution<int> distribution(0,59);
std::vector<int> free;
free.resize(60);
for(int i = 0; i < 60; i++)
{
free[i] = i;
}
int max1Fish = 30, max2Fish = 20;
penguin_state s = {};
s.current_player_red = true;
s.score_red = 0;
s.score_blue = 0;
s.one_fish = 0;
s.two_fish = 0;
s.three_fish = 0;
for(int i = 0; i < 60; i++)
{
distribution = std::uniform_int_distribution<int>(0,free.size() -1 );
int rand = distribution(generator);
int tile =free[rand];
free.erase(std::remove(free.begin(),free.end(),tile),free.end());
if(i < max1Fish) {
s.one_fish |= (long) 1 << tile;
} else if( i < max1Fish + max2Fish) {
s.two_fish |= (long) 1 << tile;
} else {
s.three_fish |= (long) 1 << tile;
}
}
uint32_t* tab_peng = s.peng_red;
std::vector<int> pengPos;
pengPos.reserve(8);
distribution = std::uniform_int_distribution<int>(0,59);
for(int i = 0; i < 8; i++)
{
if(i == 4) tab_peng = s.peng_blue;
int pos = distribution(generator);
while(std::find(pengPos.begin(),pengPos.end(),pos) != pengPos.end())
{
pos = distribution(generator);
}
pengPos.push_back(pos);
tab_peng[i%4] = pos;
}
return s;
}
}
......@@ -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)
......@@ -47,6 +49,7 @@ namespace game
{
public:
penguin();
penguin(bool);
penguin(const penguin& pen) = default;
penguin& operator=(const penguin& pen) = default;
bool end_of_game() const; //Is the game ended? (draw or won)
......@@ -61,7 +64,7 @@ namespace game
std::string player_to_string(std::uint8_t player) const; //String representation of a player
std::string move_to_string(std::uint16_t m) const; //String representation of a move (for example, A1)
json to_JSON() const;
std::string to_string() const; //String representation of the entire game
std::string to_string() const; //String representatcion of the entire game
std::set<int> to_input_vector() const;
void from_input_vector(const std::set<int>& input);
penguin_state get_state(); //Return the state
......@@ -69,6 +72,13 @@ 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;
static penguin_state random_start_state();
private:
penguin_state state;
......
#include "test_statistics.hpp"
#include <iostream>
#include <fstream>
#include <sstream>
#include <iomanip>
#include <sys/types.h>
#include <sys/stat.h>
#include <unistd.h>
#include <ctime>
std::string get_test_results_directory()
{
std::ostringstream ss;
ss << "test/";
auto t = std::time(nullptr);
auto tm = *std::localtime(&t);
ss << std::put_time(&tm,"%d-%m-%Y") << "-";
struct stat s;
for(int i = 1;;++i)
{
std::string number_to_string = std::to_string(i);
std::string dir = ss.str() + number_to_string;
if(stat(dir.c_str(),&s) == -1)
return dir;
}
}
std::string get_test_results_file_name()
{
char hostname[100];
if(gethostname(hostname,100) == 0)
{
return std::string(hostname) + ".stats";
}else return nullptr;
}
bool save_stats(std::string dir, int win_v1,int win_v2, int draws)
{
struct stat s;
if(stat("test",&s) == -1)
{
mkdir("test",0700);
}
std::string filename(get_test_results_file_name());
if(stat(dir.c_str(),&s) == -1)
{
mkdir(dir.c_str(),0700);
}
std::string relative_path(dir+"/" +filename);
FILE* f = fopen(relative_path.c_str(),"w");
if(f == nullptr)
{
return false;
}
fprintf(f,"%d %d %d",win_v1,win_v2,draws);
fclose(f);
return true;
}
#ifndef __STATISTICS_TEST_HPP__
#define __STATISTICS_TEST_HPP__
#include <string>
std::string get_test_results_directory();
std::string get_test_results_file_name();
bool save_stats(std::string,int,int,int);
#endif
#include "go_left_up_heuristic.hpp"
using namespace std;
namespace mcts
{
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 __LEFT_UP__HEURISTIC_HPP__
#define __LEFT_UP_HEURISTIC_HPP__
#include "penguin.hpp"
#include "penguin_heuristic.hpp"
namespace mcts
{
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
#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
#include <iostream>
#include "penguin_heuristic.hpp"
#include "movement_freedom_heuristic.hpp"
#include "penguin.hpp"
#define MAX_NB_MOVES 60.0f
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 (MARCHE ?)
played->play(move);
game::penguin_state state = played->get_state();
uint32_t* penguins_r = state.peng_red;
uint32_t* penguins_b = state.peng_blue;
float nb_moves_r = 0;
float nb_moves_b = 0;
for(int i=0; i< 4; i++) {
nb_moves_r += PENGUIN_TOT_MOVES(penguins_r[i]);
nb_moves_b += PENGUIN_TOT_MOVES(penguins_b[i]);
}
float res = -(nb_moves_r - nb_moves_b)/MAX_NB_MOVES;
return res;
//TEST SOLUTION 2 (MARCHE ?)
/*
game::penguin_state state = played->get_state();
uint32_t* penguins = state.peng_red;
float nb_moves_before = 0;
for(int i=0; i< 4; i++) {
nb_moves_before += PENGUIN_TOT_MOVES(penguins[i]);
}
played->play(move);
state = played->get_state();
penguins = state.peng_red;
float nb_moves = 0;
for(int i=0; i< 4; i++) {
nb_moves += PENGUIN_TOT_MOVES(penguins[i]);
}
float res = -(nb_moves - nb_moves_before)/MAX_NB_MOVES;
return res;
*/
//TEST SOLUTION 3 (MARCHE ?)
/*
played->play(move);
game::penguin_state state = played->get_state();
uint32_t* penguins = state.peng_red;
float nb_moves = 0;
for(int i=0; i< 4; i++) {
nb_moves += PENGUIN_TOT_MOVES(penguins[i]);
}
float res = -(2.0f*nb_moves / MAX_NB_MOVES - 1.0f);
return res;
*/
//TEST SOLUTION 4 (MARCHE PAS, METHODES PRIVATE)
/*
played->play(move);
game::penguin_state state = played->get_state();
uint64_t obstacles = played->create_obstacles_bitboard();
uint32_t* penguins = state.peng_red;
float nb_moves = 0;
for(int i = 0; i < 4; i++)
nb_moves += played->update_penguin_moves(&penguins[i], obstacles);
float res = -(2.0f*nb_moves / MAX_NB_MOVES - 1.0f);
return res;
*/
//TEST SOLUTION 5 (MARCHE PAS, DONNE NB MOVES DU BLEU)
/*
played->play(move);
float nb_moves = (float)played->number_of_moves();
float res = -(2.0f*nb_moves / MAX_NB_MOVES - 1.0f);
return res;
*/
}
int movement_freedom_heuristic::get_count(const game::penguin& game, uint8_t move) const
{
return 50;
}
}
#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 "number_direction_freedom_heuristic.hpp"
#include "penguin.hpp"
using namespace std;
//Count the number of direction in which a penguin can move
uint8_t number_of_direction_penguin(uint32_t penguin){
uint8_t res = 0 ;
if(PENGUIN_MOVES_A(penguin)>0) res++;
if(PENGUIN_MOVES_B(penguin)>0) res++;
if(PENGUIN_MOVES_C(penguin)>0) res++;
if(PENGUIN_MOVES_D(penguin)>0) res++;
if(PENGUIN_MOVES_E(penguin)>0) res++;
if(PENGUIN_MOVES_F(penguin)>0) res++;
return res;
}
namespace mcts
{
float number_direction_freedom_heuristic::get_value(const game::penguin& game, uint8_t move) const
{
std::shared_ptr<game::penguin> played = game::copy(game);
//game::penguin_state before_state = played->get_state();
played->play(move);
game::penguin_state after_state = played->get_state();
uint32_t* penguins;
/*if(before_state.current_player_red){ //If the player is red
penguins = before_state.peng_red;
}else{ //if the player is blue
penguins = before_state.peng_blue;
}
//For each penguins, count the number of direction it can move
int8_t number_of_direction_before = 0;
for(int8_t i=0; i< 4; i++) {
number_of_direction_before+= number_of_direction_penguin(penguins[i]);
}
*/
if(after_state.current_player_red){ //If the player was red
penguins = after_state.peng_red;
}else{ //if the player was blue
penguins = after_state.peng_blue;
}
uint8_t number_of_direction_after = 0;
for(uint8_t i=0; i< 4; i++) {
number_of_direction_after+= number_of_direction_penguin(penguins[i]);
}
//std::cout << "number of direction : " << "("+std::to_string(number_of_direction_after)+" : "
// + std::to_string((number_of_direction_after - 12.0)/12.0)+")" <<std::endl;
// Return a float between -1.0 and 1.0 related to the change of the number of direction in which you can play before and after the move
return (-(number_of_direction_after - 12.0)/12.0);
//return (-(number_of_direction_after - number_of_direction_before)/12.0);
}
int number_direction_freedom_heuristic::get_count(const game::penguin& game, uint8_t move) const
{
return 100000000;
}
}
#ifndef __PENGUIN_HEURISTIC_DIRECTION_FREEDOM_HPP__
#define __PENGUIN_HEURISTIC_DIRECTION_FREEDOM_HPP__
#include "penguin.hpp"
#include "heuristic.hpp"
#include "penguin_heuristic.hpp"
namespace mcts
{
class number_direction_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;
}
}
#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;
};
};
#endif
#include "points_heuristic.hpp"
#include <iostream>
namespace mcts
{
float points_heuristic::get_value(const game::penguin& game, uint8_t move) const
{
const std::shared_ptr<game::penguin> played = game::copy(game);
const game::penguin_state old_state = played->get_state();
played->play(move);
const game::penguin_state new_state = played->get_state();
const bool current_player_is_red = old_state.current_player_red;
int old_score = old_state.score_red;
int new_score = new_state.score_red;
if(!current_player_is_red) {
old_score = old_state.score_blue;
new_score = new_state.score_blue;
}
return (-2.f + (new_score - old_score));
}
int points_heuristic::get_count(const game::penguin& game, uint8_t move) const
{
return 10000; ;
}
}
#ifndef __POINTS_HEURISTIC_HPP__
#define __POINTS_HEURISTIC_HPP__
#include "penguin_heuristic.hpp"
namespace mcts
{
class points_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
......@@ -15,7 +15,7 @@
* Copyright (c) 2007-2010 Baptiste Lepilleur
*/
#include <iostream>
#include "penguin.hpp"
#include "test_two_players_game.hpp"
#include "test_fast_log.hpp"
......@@ -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);
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));
std::cout << "COUCOU" << std::endl;
mcts::run_test_mcts_two_players(game::penguin(),h1,h2);
//util::test_bits(200000000);
return 0;
return 0;
}