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 (60)
Showing
with 915 additions and 4 deletions
......@@ -20,3 +20,6 @@ GUI/GUI.iml
*.blg
*.nav
*.snm
*.layout
*.cbp
test/*
ai_vs_ai=1
ai_think_time=5000
ai_vs_ai_game_count=100
heuristic_ai_1=default
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"
#include "zone_heuristic.hpp"
#include "generalization_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 == "general"){
*h = new mcts::generalization_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 == "zone") {
*h = new mcts::zone_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
......@@ -62,6 +63,17 @@ namespace game
state.canPlay_blue = false;
state.nb_moves_blue = 1; //We create an artificial move so that the mcts works
}
//std::cout << penguin_board(BLUE) << std::endl;
//std::cout << penguin_board(RED) << std::endl;
}
penguin::penguin(bool b)
{
if(b)
{
set_state(penguin::random_start_state());
}
}
shared_ptr<game<penguin_state>> penguin::do_copy() const
......@@ -358,6 +370,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 +458,138 @@ 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;
}
uint64_t penguin::penguin_board(bool color) const
{
//A penguin alone on the case 0 correspond to a bitboard which value is 1
uint64_t board = 0ULL;
const uint32_t* tab = color ? state.peng_blue : state.peng_red;
for (int i = 0; i<4 ; i++){
board |= (uint64_t) 1 << (tab[i] & 63 );
}
return board;
}
uint64_t penguin::penguin_move_board(const uint32_t& pen) const
{
uint64_t board = 0;
//Direction A
for(uint i=1; i<= PENGUIN_MOVES_A(pen); i++){
board |= ((uint64_t)1 << (PENGUIN_POS(pen) + i*7));
}
//Direction B
for(uint i=1; i<= PENGUIN_MOVES_B(pen); i++){
board |= ((uint64_t)1 << (PENGUIN_POS(pen) + i*(-1)));
}
//Direction C
for(uint i=1; i<= PENGUIN_MOVES_C(pen); i++){
board |= ((uint64_t)1 << (PENGUIN_POS(pen) + i*(-8)));
}
//Direction D
for(uint i=1; i<= PENGUIN_MOVES_D(pen); i++){
board |= ((uint64_t)1 << (PENGUIN_POS(pen) + i*(-7)));
}
//Direction E
for(uint i=1; i<= PENGUIN_MOVES_E(pen); i++){
board |= ((uint64_t)1 << (PENGUIN_POS(pen) + i*1));
}
//Direction F
for(uint i=1; i<= PENGUIN_MOVES_A(pen); i++){
board |= ((uint64_t)1 << (PENGUIN_POS(pen) + i*8));
}
return board;
}
uint8_t penguin::turns_played() const
{
uint8_t played = 0;
uint64_t obstacles = (~(state.one_fish | state.two_fish | state.three_fish));
while(obstacles > 0) {
if(obstacles % 2 == 1) ++played;
obstacles /= 2;
}
return played;
}
uint32_t penguin::move_to_pos(uint16_t m)
{
uint32_t result = 0;
uint32_t* peng;
uint16_t rel_move = m;
int i = 0;
if(state.current_player_red) {
for(i = 0; (i < 3) && (PENGUIN_TOT_MOVES(state.peng_red[i]) <= rel_move); i ++) //While we didn't find the penguin
rel_move -= PENGUIN_TOT_MOVES(state.peng_red[i]);
peng = &state.peng_red[i];
}
else {
for(i = 0; (i < 3) && (PENGUIN_TOT_MOVES(state.peng_blue[i]) <= rel_move); i ++) //While we didn't find the penguin
rel_move -= PENGUIN_TOT_MOVES(state.peng_blue[i]);
peng = &state.peng_blue[i];
}
result = PENGUIN_POS(*peng) << 16;
play(m);
result |= PENGUIN_POS(*peng);
return result;
}
}
......@@ -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,12 +72,25 @@ 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();
std::uint64_t penguin_board(bool) const; // true for position of blue penguin, else false
uint64_t penguin_move_board(const uint32_t& pen) const; //Bitboard of possible move of the penguin
uint8_t turns_played() const;
int update_penguin_moves(uint32_t* p, uint64_t obstacles);
uint64_t create_obstacles_bitboard();
uint32_t move_to_pos(uint16_t m);
private:
penguin_state state;
void move_penguin(uint32_t* p, uint16_t rel_move);
uint64_t create_obstacles_bitboard();
int update_penguin_moves(uint32_t* p, uint64_t obstacles);
const uint8_t RED = 0;
const uint8_t BLUE = 1;
......
#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
#ifndef __PENGUIN_GENERAL_HEURISTIC_HPP__
#define __PENGUIN_GENERAL_HEURISTIC_HPP__
#include "penguin.hpp"
#include "heuristic.hpp"
#include "penguin_heuristic.hpp"
#include <algorithm>
#define MAX_NB_MOVES 60.0f
//Count the number of direction in which a penguin can move
uint8_t number_of_direction_penguin_general(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
{
class generalization_heuristic : public penguin_heuristic
{
public:
float get_value(const game::penguin& game, uint8_t move) const
{
float X_free_move=0.35, X_num_dir=0.15, X_points=0.2, X_zone=0.3;
game::penguin g = *(game::copy(game));
auto old_state = g.get_state();
g.play(move);
auto played_state = g.get_state();
uint32_t* penguins = played_state.current_player_red ? played_state.peng_red : played_state.peng_blue;
uint32_t* other_peng = played_state.current_player_red ? played_state.peng_blue : played_state.peng_red;
//Movement Freedom Heuristic
float nb_moves_us = 0;
float nb_moves_other = 0;
for(int i=0; i< 4; i++) {
nb_moves_us += PENGUIN_TOT_MOVES(penguins[i]);
nb_moves_other += PENGUIN_TOT_MOVES(other_peng[i]);
}
float res_movement_freedom = -(nb_moves_us - nb_moves_other)/MAX_NB_MOVES;
//Number Direction Freedom Heuristic
uint8_t nb = 0;
for(int i = 0; i < 4; ++i) {
nb += number_of_direction_penguin_general(penguins[i]);
}
float res_number_direction_freedom = (-12.f + (float)nb)/12.f;
//Points Heuristic
const uint32_t* peng;
uint16_t rel_move = move;
float res_points =0.f;
int i = 0;
if(old_state.current_player_red)
{
for(i = 0; (i < 3) && (PENGUIN_TOT_MOVES(old_state.peng_red[i]) <= rel_move); i ++)
rel_move -= PENGUIN_TOT_MOVES(old_state.peng_red[i]);
peng = &new_state.peng_red[i];
}
else
{
for(i = 0; (i < 3) && (PENGUIN_TOT_MOVES(old_state.peng_blue[i]) <= rel_move); i ++)
rel_move -= PENGUIN_TOT_MOVES(old_state.peng_blue[i]);
peng = &new_state.peng_blue[i];
}
if((new_state.one_fish >> PENGUIN_POS(*peng)) & 1) res_points=1;
else if((new_state.two_fish >> PENGUIN_POS(*peng)) & 1) res_points=0;
else res_points=-1;
//Zone Heuristic
uint64_t moves_this = 0;
uint64_t moves_other = 0;
for(int i = 0; i < 4; ++i) {
moves_this |= g.penguin_move_board(penguins[i]);
moves_other |= g.penguin_move_board(other_peng[i]);
}
uint64_t this_owned_moves = moves_this & ~(moves_other);
uint64_t other_owned_moves = moves_other & ~(moves_this);
int count_this = 0;
int count_other = 0;
for(int i = 0; i < 60; i++) {
count_this += (this_owned_moves>>i) & 1 ;
count_other += (other_owned_moves>>i) & 1 ;
}
float res_zone = clamp((float)(count_this - count_other) / (count_this + 1), -1.f, 1.f);
//Final Result
return (X_free_move * res_movement_freedom
+ X_num_dir * res_number_direction_freedom
+ X_points * res_points
+ X_zone * res_zone);
}
int get_count(const game::penguin& game, uint8_t move) const
{
game::penguin g = *(game::copy(game));
auto old_state = g.get_state();
uint64_t obstacles = (~(old_state.one_fish | old_state.two_fish | old_state.three_fish));
for(int i = 0; i < 4; i++){
obstacles |= ((uint64_t) 1) << PENGUIN_POS(old_state.peng_red[i]);
obstacles |= ((uint64_t) 1) << PENGUIN_POS(old_state.peng_blue[i]);
}
int nbr_obstacles = 0;
// It count also the penguins so in this implementation it start at 8 + 1 for each move done
for (int i =0; i<60; i++){
if((obstacles >> i) & 1) nbr_obstacles++;
}
return ((int)ceil(500.0/nbr_obstacles));
}
private:
float clamp(float v, float l, float h) const
{
return std::max(std::min(h,v),l);
}
};
};
#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* tab_peng = after_state.peng_red;
uint8_t nb = 0;
if(!after_state.current_player_red) {
tab_peng = after_state.peng_blue;
}
for(int i = 0; i < 4; ++i) {
nb += number_of_direction_penguin(tab_peng[i]);
}
return (-12.f + (float)nb)/12.f;
}
int number_direction_freedom_heuristic::get_count(const game::penguin& game, uint8_t move) const
{
return 10000000 / (game.turns_played() + 1);
}
}
#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 uint32_t* peng;
uint16_t rel_move = move;
int i = 0;
if(old_state.current_player_red)
{
for(i = 0; (i < 3) && (PENGUIN_TOT_MOVES(old_state.peng_red[i]) <= rel_move); i ++)
rel_move -= PENGUIN_TOT_MOVES(old_state.peng_red[i]);
peng = &new_state.peng_red[i];
}
else
{
for(i = 0; (i < 3) && (PENGUIN_TOT_MOVES(old_state.peng_blue[i]) <= rel_move); i ++)
rel_move -= PENGUIN_TOT_MOVES(old_state.peng_blue[i]);
peng = &new_state.peng_blue[i];
}
if((new_state.one_fish >> PENGUIN_POS(*peng)) & 1) return -(-1);
else if((new_state.two_fish >> PENGUIN_POS(*peng)) & 1) return 0;
else return -1;
}
int points_heuristic::get_count(const game::penguin& game, uint8_t move) const
{
return 100000; ;
}
}
#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