Skip to content
Snippets Groups Projects
generalization_heuristic.hpp 3.99 KiB
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));
			auto old_state = g.get_state();
			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);