Newer
Older
#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));
g.play(move);
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]);
}
// It count also the penguins so in this implementation it start at 8 + 1 for each move done
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