From d1cbcd4ea78e6f4ba14f581c820ad087434ef656 Mon Sep 17 00:00:00 2001
From: Francesco Bariatti <francesco.bariatti@insa-rennes.fr>
Date: Mon, 29 Feb 2016 16:15:14 +0100
Subject: [PATCH] Created function play

---
 src/game/penguin.cpp | 296 +++++++++++++++++++++++++++++++++++++++++--
 src/game/penguin.hpp |   9 +-
 2 files changed, 289 insertions(+), 16 deletions(-)

diff --git a/src/game/penguin.cpp b/src/game/penguin.cpp
index b454264..421dce6 100644
--- a/src/game/penguin.cpp
+++ b/src/game/penguin.cpp
@@ -7,6 +7,33 @@ namespace game
 {
 	penguin::penguin()
 	{
+		//Update moves on all penguins
+		uint64_t obstacles = (~(state.one_fish | state.two_fish | state.three_fish));
+		obstacles |= ((uint64_t) 1) << (state.p1_red & 63);
+		obstacles |= ((uint64_t) 1) << (state.p2_red & 63);
+		obstacles |= ((uint64_t) 1) << (state.p3_red & 63);
+		obstacles |= ((uint64_t) 1) << (state.p4_red & 63);
+		obstacles |= ((uint64_t) 1) << (state.p1_blue & 63);
+		obstacles |= ((uint64_t) 1) << (state.p2_blue & 63);
+		obstacles |= ((uint64_t) 1) << (state.p3_blue & 63);
+		obstacles |= ((uint64_t) 1) << (state.p4_blue & 63);
+		
+		state.nb_moves_red = 0;
+		state.nb_moves_blue = 0;
+		state.nb_moves_red += update_moves(&state.p1_red, obstacles);
+		state.nb_moves_red += update_moves(&state.p2_red, obstacles);
+		state.nb_moves_red += update_moves(&state.p3_red, obstacles);
+		state.nb_moves_red += update_moves(&state.p4_red, obstacles);
+		state.nb_moves_blue += update_moves(&state.p1_blue, obstacles);
+		state.nb_moves_blue += update_moves(&state.p2_blue, obstacles);
+		state.nb_moves_blue += update_moves(&state.p3_blue, obstacles);
+		state.nb_moves_blue += update_moves(&state.p4_blue, obstacles);
+		
+		//Change player if the other one can play
+		if(state.current_player_red && state.nb_moves_blue > 0)
+			state.current_player_red = false;
+		else if(state.current_player_red == false && state.nb_moves_red > 0)
+			state.current_player_red = true;
 	}
 
 	shared_ptr<game<penguin_state>> penguin::do_copy() const
@@ -68,24 +95,267 @@ namespace game
 		return 0;
 	}
 	
+	/* The penguin that will move if we want to play the #move_number move in the list of possible moves.
+	 * What this function does:
+	 *		Find the penguin that will move.
+	 * 		Change its total number of moves so that it is relative to that penguin's possible moves and not relative to ALL the penguins' moves.
+	 * 		Return a pointer to that penguin
+	 * */
+	uint32_t* penguin::penguin_that_moves(uint16_t move_number)
+	{
+		if(state.current_player_red)
+		{
+			if(((state.p1_red >> 6) & 63) > move_number)
+			{
+				uint32_t* p = &state.p1_red;
+				(*p) = (*p) & 0xFFFFF03F; //Reset move number for the penguin to 0
+				(*p) = (*p) | ((uint32_t) move_number) << 6;
+				return p;
+			}
+			move_number -= (state.p1_red >> 6) & 63;
+			
+			if(((state.p2_red >> 6) & 63) > move_number)
+			{
+				uint32_t* p = &state.p2_red;
+				(*p) = (*p) & 0xFFFFF03F; //Reset move number for the penguin to 0
+				(*p) = (*p) | ((uint32_t) move_number) << 6;
+				return p;
+			}
+			move_number -= (state.p2_red >> 6) & 63;
+			
+			if(((state.p3_red >> 6) & 63) > move_number)
+			{
+				uint32_t* p = &state.p3_red;
+				(*p) = (*p) & 0xFFFFF03F; //Reset move number for the penguin to 0
+				(*p) = (*p) | ((uint32_t) move_number) << 6;
+				return p;
+			}
+			move_number -= (state.p3_red >> 6) & 63;
+			
+			uint32_t* p = &state.p4_red;
+			(*p) = (*p) & 0xFFFFF03F; //Reset move number for the penguin to 0
+			(*p) = (*p) | ((uint32_t) move_number) << 6;
+			return p;
+		}
+		else
+		{
+			if(((state.p1_blue >> 6) & 63) > move_number)
+			{
+				uint32_t* p = &state.p1_blue;
+				(*p) = (*p) & 0xFFFFF03F; //Reset move number for the penguin to 0
+				(*p) = (*p) | ((uint32_t) move_number) << 6;
+				return p;
+			}
+			move_number -= (state.p1_blue >> 6) & 63;
+			
+			if(((state.p2_blue >> 6) & 63) > move_number)
+			{
+				uint32_t* p = &state.p2_blue;
+				(*p) = (*p) & 0xFFFFF03F; //Reset move number for the penguin to 0
+				(*p) = (*p) | ((uint32_t) move_number) << 6;
+				return p;
+			}
+			move_number -= (state.p2_blue >> 6) & 63;
+			
+			if(((state.p3_blue >> 6) & 63) > move_number)
+			{
+				uint32_t* p = &state.p3_blue;
+				(*p) = (*p) & 0xFFFFF03F; //Reset move number for the penguin to 0
+				(*p) = (*p) | ((uint32_t) move_number) << 6;
+				return p;
+			}
+			move_number -= (state.p3_blue >> 6) & 63;
+			
+			uint32_t* p = &state.p4_blue;
+			(*p) = (*p) & 0xFFFFF03F; //Reset move number for the penguin to 0
+			(*p) = (*p) | ((uint32_t) move_number) << 6;
+			return p;
+		}
+	}
+	
+	void penguin::move_penguin(uint32_t* p)
+	{
+		uint8_t move_number = ((*p) >> 6) & 63; //Move number for the current penguin
+		uint32_t penguin_copy = (*p) >> 12;
+		//Direction A
+		if((penguin_copy & 7) >= move_number)
+		{
+			//Move direction A
+			(*p) = (7 * move_number) + ((*p) & 63);
+			return;
+		}
+		move_number -= penguin_copy & 7;
+		penguin_copy = penguin_copy >> 3;
+		if((penguin_copy & 7) >= move_number)
+		{
+			//Move direction B
+			(*p) = (-1 * move_number) + ((*p) & 63);
+			return;
+		}
+		move_number -= penguin_copy & 7;
+		penguin_copy = penguin_copy >> 3;
+		if((penguin_copy & 7) >= move_number)
+		{
+			//Move direction C
+			(*p) = (-8 * move_number) + ((*p) & 63);
+			return;
+		}
+		move_number -= penguin_copy & 7;
+		penguin_copy = penguin_copy >> 3;
+		if((penguin_copy & 7) >= move_number)
+		{
+			//Move direction D
+			(*p) = (-7 * move_number) + ((*p) & 63);
+			return;
+		}
+		move_number -= penguin_copy & 7;
+		penguin_copy = penguin_copy >> 3;
+		if((penguin_copy & 7) >= move_number)
+		{
+			//Move direction E
+			(*p) = (1 * move_number) + ((*p) & 63);
+			return;
+		}
+		move_number -= penguin_copy & 7;
+		penguin_copy = penguin_copy >> 3;
+		//Move direction F
+		(*p) = (8 * move_number) + ((*p) & 63);
+	}
+	
+	int penguin::update_moves(uint32_t* p, uint64_t obstacles)
+	{
+	#define IsFree(i) (((obstacles >> (i)) & 1) == 0)
+		int pos = (*p) & 63;
+		(*p) = pos; //Reset the penguin to all zeros except the position
+		int i = pos;
+		uint32_t nbmoves = 0;
+		uint32_t total_moves = 0;
+		
+		//Direction A
+		while(((i+7) < 60) && (i%15 != 0) && IsFree(i+7))
+		{
+			i += 7;
+			nbmoves++; total_moves++;
+		}
+		(*p) = (*p) | nbmoves << 12;
+		//Direction B
+		nbmoves = 0;
+		i = pos;
+		while((i%15 != 0) && (i%15 != 8) && IsFree(i-1))
+		{
+			i --;
+			nbmoves++; total_moves++;
+		}
+		(*p) = (*p) | nbmoves << 15;
+		//Direction C
+		nbmoves = 0;
+		i = pos;
+		while((i-8 > 0) && (i%15 != 0) && IsFree(i-8))
+		{
+			i -= 8;
+			nbmoves++; total_moves++;
+		}
+		(*p) = (*p) | nbmoves << 18;
+		//Direction D
+		nbmoves = 0;
+		i = pos;
+		while((i-7 > 0) && (i%15 != 7) && IsFree(i-7))
+		{
+			i -= 7;
+			nbmoves++; total_moves++;
+		}
+		(*p) = (*p) | nbmoves << 21;
+		//Direction E
+		nbmoves = 0;
+		i = pos;
+		while((i%15 != 7) && (i%15 != 14) && IsFree(i+1))
+		{
+			i ++;
+			nbmoves++; total_moves++;
+		}
+		(*p) = (*p) | nbmoves << 24;
+		//Direction F
+		nbmoves = 0;
+		i = pos;
+		while((i+8 < 60) && (i%15 != 7) && IsFree(i+8))
+		{
+			i += 8;
+			nbmoves++; total_moves++;
+		}
+		(*p) = (*p) | nbmoves << 27;
+		
+		(*p) = (*p) | total_moves << 6;
+		return total_moves;
+	}
+	
 	//Play the mth move in the possible moves list.
 	void penguin::play(uint16_t m)
 	{   
-		/*uint64_t possible_moves = state.possible_moves;
-		possible_moves = possible_moves >> 4*m; //A move is coded with 4 bit
-		uint16_t move = possible_moves & 15; //15 = 1111
-		//cout << "You choose the possible move number " << m << endl;
-		//cout << "You choose move " << move << endl;
-		if (current_player() == CROSS)
-			state.cross_bitboard |= (((uint16_t) 1) << move);
+		//Find which penguin will move
+		uint32_t* p = penguin_that_moves(m);
+		uint8_t position = (*p) & 63;
+		
+		//Find the value of the tile the penguin is on and update score
+		if ((state.one_fish >> position) & 1)
+		{
+			if(current_player() == RED)
+				state.score_red += 1;
+			else
+				state.score_blue += 1;
+			//We replace this tile with an empty one (0 in the bitboard)
+			state.one_fish = state.one_fish & ~(((uint64_t) 1) << position);
+		}
+		else if ((state.two_fish >> position) & 1)
+		{
+			
+			if(current_player() == RED)
+				state.score_red += 2;
+			else
+				state.score_blue += 2;
+			//We replace this tile with an empty one (0 in the bitboard)
+			state.two_fish = state.two_fish & ~(((uint64_t) 1) << position);
+		}
 		else
-			state.circle_bitboard |= (((uint16_t) 1) << move);
+		{
+			if(current_player() == RED)
+				state.score_red += 3;
+			else
+				state.score_blue += 3;
+			//We replace this tile with an empty one (0 in the bitboard)
+			state.three_fish = state.three_fish & ~(((uint64_t) 1) << position);
+		}
+		
+		//Move the current penguin
+		move_penguin(p);
+		
+		//Update moves on all penguins
+		uint64_t obstacles = (~(state.one_fish | state.two_fish | state.three_fish));
+		obstacles |= ((uint64_t) 1) << (state.p1_red & 63);
+		obstacles |= ((uint64_t) 1) << (state.p2_red & 63);
+		obstacles |= ((uint64_t) 1) << (state.p3_red & 63);
+		obstacles |= ((uint64_t) 1) << (state.p4_red & 63);
+		obstacles |= ((uint64_t) 1) << (state.p1_blue & 63);
+		obstacles |= ((uint64_t) 1) << (state.p2_blue & 63);
+		obstacles |= ((uint64_t) 1) << (state.p3_blue & 63);
+		obstacles |= ((uint64_t) 1) << (state.p4_blue & 63);
+		
+		state.nb_moves_red = 0;
+		state.nb_moves_blue = 0;
+		state.nb_moves_red += update_moves(&state.p1_red, obstacles);
+		state.nb_moves_red += update_moves(&state.p2_red, obstacles);
+		state.nb_moves_red += update_moves(&state.p3_red, obstacles);
+		state.nb_moves_red += update_moves(&state.p4_red, obstacles);
+		state.nb_moves_blue += update_moves(&state.p1_blue, obstacles);
+		state.nb_moves_blue += update_moves(&state.p2_blue, obstacles);
+		state.nb_moves_blue += update_moves(&state.p3_blue, obstacles);
+		state.nb_moves_blue += update_moves(&state.p4_blue, obstacles);
+		
+		//Change player if the other one can play
+		if(state.current_player_red && state.nb_moves_blue > 0)
+			state.current_player_red = false;
+		else if(state.current_player_red == false && state.nb_moves_red > 0)
+			state.current_player_red = true;
 		
-		//State update
-		state.total_moves++;
-		update_win();
-		update_moves();
-		return;*/
 	}
 	
 	string penguin::player_to_string(uint8_t player) const
diff --git a/src/game/penguin.hpp b/src/game/penguin.hpp
index c9c8c0a..a74bb82 100644
--- a/src/game/penguin.hpp
+++ b/src/game/penguin.hpp
@@ -28,7 +28,7 @@ namespace game
 		int score_red = 0;
 		int score_blue = 0;
 		
-		bool current_player_red = true; //True if red must play now
+		bool current_player_red = false; //True if red must play now
 		
 		int nb_moves_red = 0; //Number of moves the red player can play
 		int nb_moves_blue = 0;
@@ -62,9 +62,12 @@ namespace game
 			
 		private:
 			penguin_state state;
+			uint32_t* penguin_that_moves(uint16_t move_number);
+			void move_penguin(uint32_t* p);
+			int update_moves(uint32_t* p, uint64_t obstacles);
 			
-			uint8_t RED = 0;
-			uint8_t BLUE = 1;
+			const uint8_t RED = 0;
+			const uint8_t BLUE = 1;
 			
 	};
 	std::ostream& operator<<(std::ostream& os, const penguin& pen);
-- 
GitLab