From d6ad720a3a029b41df727ec406b2688f7bc02da0 Mon Sep 17 00:00:00 2001
From: Francesco Bariatti <francesco.bariatti@insa-rennes.fr>
Date: Mon, 18 Apr 2016 14:42:56 +0200
Subject: [PATCH] When a player can not play, a boolean is set, possible moves
 is set to 1  and the game accepts whatever value as a move.

---
 src/game/penguin.cpp               | 129 +++++++++++++++--------------
 src/game/penguin.hpp               |   9 +-
 src/mcts/test_mcts_two_players.hpp |   2 +-
 3 files changed, 75 insertions(+), 65 deletions(-)

diff --git a/src/game/penguin.cpp b/src/game/penguin.cpp
index 94fe0e4..d0b6943 100644
--- a/src/game/penguin.cpp
+++ b/src/game/penguin.cpp
@@ -28,12 +28,6 @@ namespace game
 		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
@@ -53,7 +47,7 @@ namespace game
 
 	bool penguin::end_of_game() const
 	{
-		return state.nb_moves_red == 0 && state.nb_moves_blue == 0;
+		return state.canPlay_red == false && state.canPlay_blue == false;
 	}
 
 	bool penguin::won(std::uint8_t player) const
@@ -290,42 +284,45 @@ namespace game
 	//Play the mth move in the possible moves list.
 	void penguin::play(uint16_t m)
 	{
-		//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 ((state.current_player_red == true && state.canPlay_red) || ((state.current_player_red == false) && state.canPlay_blue))
 		{
+			//Find which penguin will move
+			uint32_t* p = penguin_that_moves(m);
+			uint8_t position = (*p) & 63;
 
-			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
-		{
-			if(current_player() == RED)
-				state.score_red += 3;
+			//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.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);
-		}
+			{
+				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);
+			//Move the current penguin
+			move_penguin(p);
+		}
 
 		//Update moves on all penguins of the next player
 		uint64_t obstacles = (~(state.one_fish | state.two_fish | state.three_fish));
@@ -343,35 +340,45 @@ namespace game
 		
 		if (state.current_player_red) //Red just played
 		{
-			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);
-			if (state.nb_moves_blue == 0) //If Blue can not move we update moves for red
+			if(state.canPlay_blue)
 			{
-				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);
+				if (state.nb_moves_blue == 0)
+				{
+					state.canPlay_blue = false;
+					state.nb_moves_blue = 1; //We create an artificial move so that the mcts works
+				}
 			}
 			else
-			{ state.current_player_red = false; }
+			{
+				state.nb_moves_blue = 1;
+			}
+			
+			state.current_player_red = false;
 		}
 		else //Blue just played
 		{
-			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);
-			if (state.nb_moves_red == 0)
+			if(state.canPlay_red)
 			{
-				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);
+				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);
+				if (state.nb_moves_red == 0)
+				{
+					state.canPlay_red = false;
+					state.nb_moves_red = 1;
+				}
 			}
 			else
-			{ state.current_player_red = true; }
+			{
+				state.nb_moves_red = 1;
+			}
+			
+			state.current_player_red = true;
 		}
 	}
 
@@ -419,8 +426,8 @@ namespace game
 
 		json_state["current_player"] = state.current_player_red ? "Red" : "Blue";
 		
-		json_state["nb_moves"]["red"] = state.nb_moves_red;
-		json_state["nb_moves"]["blue"] = state.nb_moves_blue;
+		json_state["can_play"]["red"] = state.canPlay_red;
+		json_state["can_play"]["blue"] = state.canPlay_blue;
 
 		return json_state;
 	}
diff --git a/src/game/penguin.hpp b/src/game/penguin.hpp
index c97f01b..a0e1ebf 100644
--- a/src/game/penguin.hpp
+++ b/src/game/penguin.hpp
@@ -27,13 +27,16 @@ namespace game
 		uint32_t p3_blue = 43;
 		uint32_t p4_blue = 49;
 		
-		int score_red = 6;
-		int score_blue = 3;
+		int score_red = 0;
+		int score_blue = 0;
 		
-		bool current_player_red = false; //True if red must play now
+		bool current_player_red = true; //True if red must play now. Red always starts
 		
 		int nb_moves_red = 0; //Number of moves the red player can play
 		int nb_moves_blue = 0;
+		
+		bool canPlay_red = true;
+		bool canPlay_blue = true;
 	};
 	
 	class penguin : public game<penguin_state>
diff --git a/src/mcts/test_mcts_two_players.hpp b/src/mcts/test_mcts_two_players.hpp
index 974a57e..a6ffd89 100644
--- a/src/mcts/test_mcts_two_players.hpp
+++ b/src/mcts/test_mcts_two_players.hpp
@@ -69,7 +69,7 @@ namespace mcts
   void test_mcts_two_players<Game>::play(Game g)
   {
     //    ProfilerStart("theturk.prof");
-    auto the_turk = make_mcts_two_players(g, 20000, 0.4, 8);
+    auto the_turk = make_mcts_two_players(g, 2000, 0.4, 8);
     std::cout << "play one game" << std::endl;
     std::cout << "who's first? (h)uman/(c)omputer ";
     std::string ans;
-- 
GitLab