From aefe25dacd950dd8991bf5294128d82e0abe329d Mon Sep 17 00:00:00 2001
From: Francesco Bariatti <francesco.bariatti@insa-rennes.fr>
Date: Wed, 14 Oct 2015 17:16:28 +0200
Subject: [PATCH] Created skel for morpion game. Functions are empty.

TODO: implementation of every function.
connect4.cpp and test_connect4.cpp were left in the sources of the
Makefile so the project could compile
---
 Makefile                           |   2 +-
 src/game/morpion.cpp               | 170 +++++++++++++++++++++++++++++
 src/game/morpion.hpp               |  63 +++++++++++
 src/mcts/test_mcts_two_players.cpp | 106 +++++++++---------
 4 files changed, 287 insertions(+), 54 deletions(-)
 create mode 100644 src/game/morpion.cpp
 create mode 100644 src/game/morpion.hpp

diff --git a/Makefile b/Makefile
index 210e189..2edead2 100644
--- a/Makefile
+++ b/Makefile
@@ -3,7 +3,7 @@ BIN=bin
 INCLUDE=-I src/game -I src/util -I src/monte_carlo -I src/mcts -I src/minmax
 CFLAGS=-g -O3 -ffast-math -fopenmp -c -Wall -std=c++11 $(INCLUDE)
 LDFLAGS=-fopenmp -std=c++11 #-lprofiler -Wl,-no_pie
-SOURCES=omp_util.cpp fast_log.cpp display_node.cpp connect4.cpp test_connect4.cpp monte_carlo.cpp test_monte_carlo.cpp test_fast_log.cpp\
+SOURCES=omp_util.cpp fast_log.cpp display_node.cpp morpion.cpp connect4.cpp test_connect4.cpp monte_carlo.cpp test_monte_carlo.cpp test_fast_log.cpp\
 statistics.cpp node.cpp allocator.cpp test_allocator.cpp openings.cpp mcts_two_players.cpp test_mcts_two_players.cpp test_minmax.cpp\
 bits.cpp test_bits.cpp main.cpp
 OBJECTS=$(addprefix $(BIN)/, $(SOURCES:.cpp=.o))
diff --git a/src/game/morpion.cpp b/src/game/morpion.cpp
new file mode 100644
index 0000000..738afac
--- /dev/null
+++ b/src/game/morpion.cpp
@@ -0,0 +1,170 @@
+#include "morpion.hpp"
+#include <sstream>
+
+using namespace std;
+
+namespace game
+{
+	static vector<vector<uint64_t>> create_hash_values()
+	{
+		default_random_engine generator;
+		uniform_int_distribution<uint64_t> distribution;
+		vector<vector<uint64_t>> res(7, vector<uint64_t>(6, 0));
+		for (int i = 0; i < 7; ++i) 
+		{
+			for (int j = 0; j < 6; ++j)
+			{
+				res[i][j] = distribution(generator);
+			}
+		}
+		return res;
+	}
+
+	vector<vector<uint64_t>> morpion::cross_hash_values = create_hash_values();
+	vector<vector<uint64_t>> morpion::circle_hash_values = create_hash_values();
+
+	morpion::morpion()
+	{
+	}
+
+	shared_ptr<game<morpion_state>> morpion::do_copy() const
+	{
+		return shared_ptr<morpion>(new morpion(*this));
+	}
+
+	morpion_state morpion::get_state()
+	{
+		return state;
+	}
+	
+	void morpion::set_state(const morpion_state& s)
+	{
+		state = s; 
+	}
+
+	bool morpion::end_of_game() const
+	{
+		//TODO: Implement
+		return false;
+	}
+
+	bool morpion::won(std::uint8_t player) const
+	{
+		//TODO: Implement
+		return false;
+	}
+	
+	bool morpion::lost(std::uint8_t player) const
+	{
+		//TODO: Implement
+		return false;
+	}
+
+	bool morpion::draw(std::uint8_t player) const
+	{
+		//TODO: Implement
+		return false;
+	}
+
+	uint8_t morpion::current_player() const
+	{
+		//TODO: Implement
+		return 0;
+	}
+
+	int morpion::value(uint8_t player) const
+	{
+		//TODO: Implement
+		return 0;
+	}
+
+	uint16_t morpion::number_of_moves() const
+	{
+		//TODO: Implement
+		return 0;
+	}
+
+	bool morpion::get(uint64_t bitboard, uint8_t col, uint8_t row) const
+	{
+		//TODO: Implement
+		return false;
+	}
+
+//#define set(bitboard, col, row) (bitboard |= (1LL << (((col) << 3) + (row))))
+
+	void morpion::update_win()
+	{
+		//TODO: Implement
+	}
+
+	bool morpion::has_won(uint64_t bitboard)
+	{
+		//TODO: Implement
+		return false;
+	}
+
+	void morpion::update_moves(uint16_t move)
+	{
+		//TODO: Implement
+	}
+
+	void morpion::play(uint16_t m)
+	{    
+		//TODO: Implement
+	}
+
+	string morpion::player_to_string(uint8_t player) const
+	{
+		//TODO: Implement
+		return "TODO";
+	}
+
+	string morpion::move_to_string(uint16_t m) const
+	{
+		//TODO: Implement
+		return "TODO";
+	}
+
+	set<int> morpion::to_input_vector() const
+	{
+		return set<int>();
+	}
+
+	void morpion::from_input_vector(const std::set<int>& input)
+	{
+	}
+
+	string morpion::to_string() const
+	{
+		//TODO: Implement
+		return "TODO";
+	}
+
+	void morpion::playout(mt19937& engine, int max_depth)
+	{
+		while (!end_of_game())
+		{
+			uniform_int_distribution<uint16_t> distribution(0, number_of_moves() - 1);
+			uint16_t move = distribution(engine);
+			play(move);
+		}
+	}
+
+	std::uint64_t morpion::hash() const
+	{
+		//TODO: Implement
+		return 0;
+	}
+
+	std::uint64_t morpion::hash(std::uint16_t m) const
+	{
+		//TODO: Implement
+		return 0;
+	}
+	
+	ostream& operator<<(ostream& os, const morpion& mor)
+	{
+		os << mor.to_string() << endl;
+		return os;
+	}
+}
diff --git a/src/game/morpion.hpp b/src/game/morpion.hpp
new file mode 100644
index 0000000..09517b0
--- /dev/null
+++ b/src/game/morpion.hpp
@@ -0,0 +1,63 @@
+#ifndef __MORPION_HPP__
+#define __MORPION_HPP__
+
+#include "game.hpp"
+#include <random>
+#include <array>
+#include <iostream>
+#include <memory>
+
+namespace game
+{
+	struct morpion_state
+	{
+		uint8_t total_moves = 0;
+		bool first_player_win = false;
+		bool second_player_win = false;
+	};
+	
+	class morpion : public game<morpion_state>
+	{
+		public:
+			morpion();
+			morpion(const morpion& mor) = default;
+			morpion& operator=(const morpion& mor) = default;
+			bool end_of_game() const;
+			int value(std::uint8_t player) const; //Returns if the player win, loose or nothing
+			bool won(std::uint8_t player) const;
+			bool lost(std::uint8_t player) const;
+			bool draw(std::uint8_t player) const;
+			uint8_t current_player() const;
+			std::uint16_t number_of_moves() const;
+			void play(std::uint16_t m);
+			void undo(std::uint16_t m) {}
+			std::string player_to_string(std::uint8_t player) const;
+			std::string move_to_string(std::uint16_t m) const;
+			std::string to_string() const;
+			void playout(std::mt19937& engine, int max_depth = -1);
+			std::set<int> to_input_vector() const;
+			void from_input_vector(const std::set<int>& input);
+			morpion_state get_state();
+			void set_state(const morpion_state& state);
+			std::shared_ptr<game<morpion_state>> do_copy() const;
+			std::uint64_t hash(std::uint16_t m) const;
+			std::uint64_t hash() const;
+			
+		private:
+			inline void update_win();
+			inline bool has_won(uint64_t bitboard);
+			inline void update_moves(uint16_t move);
+			inline bool get(uint64_t bitboard, uint8_t i, uint8_t j) const;
+
+			const uint8_t CROSS = 0;
+			const uint8_t CIRCLE = 1;
+
+			morpion_state state;
+
+			static std::vector<std::vector<uint64_t>> cross_hash_values;
+			static std::vector<std::vector<uint64_t>> circle_hash_values;
+	};
+	std::ostream& operator<<(std::ostream& os, const morpion& mor);
+}
+
+#endif
diff --git a/src/mcts/test_mcts_two_players.cpp b/src/mcts/test_mcts_two_players.cpp
index dbe95ec..931ccd3 100644
--- a/src/mcts/test_mcts_two_players.cpp
+++ b/src/mcts/test_mcts_two_players.cpp
@@ -1,6 +1,6 @@
 #include "mcts_two_players.hpp"
 #include "test_mcts_two_players.hpp"
-#include "connect4.hpp"
+#include "morpion.hpp"
 #include <iostream>
 #include <iomanip>
 #include <map>
@@ -12,7 +12,7 @@ using namespace game;
 
 namespace mcts
 {
-  test_mcts_two_players::test_mcts_two_players() : openings_(connect4())
+  test_mcts_two_players::test_mcts_two_players() : openings_(morpion())
   {
     //self_play(1000);
     play();
@@ -44,19 +44,19 @@ namespace mcts
   void test_mcts_two_players::play()
   {
     //    ProfilerStart("theturk.prof");
-    connect4 c4;
-    auto the_turk = make_mcts_two_players(c4, 5000, 0.3, 4);
+    morpion mor;
+    auto the_turk = make_mcts_two_players(mor, 5000, 0.3, 4);
     cout << "play one game" << endl;
     cout << "who's first? (h)uman/(c)omputer ";
     string ans;
     getline(cin, ans);
-    cout << c4 << endl;
+    cout << mor << endl;
     int human_last_move = -1, computer_last_move = -1;
-    while (!c4.end_of_game())
+    while (!mor.end_of_game())
       {
-        if ((ans == "h" && c4.current_player() == 0) || (ans == "c" && c4.current_player() == 1))
+        if ((ans == "h" && mor.current_player() == 0) || (ans == "c" && mor.current_player() == 1))
 	  {
-            human_last_move = select_move(c4);
+            human_last_move = select_move(mor);
 	  }
         else
 	  {
@@ -66,13 +66,13 @@ namespace mcts
 	      }
             uint16_t move = the_turk.select_move();
             computer_last_move = move;
-            cout << c4.player_to_string(c4.current_player()) << " move: " << c4.move_to_string(move) << endl;
-            c4.play(move);
+            cout << mor.player_to_string(mor.current_player()) << " move: " << mor.move_to_string(move) << endl;
+            mor.play(move);
 	  }
-        cout << c4 << endl;
+        cout << mor << endl;
       }
-    if (c4.value(0) == 1) cout << c4.player_to_string(0) << " won";
-    else if (c4.value(1) == 1) cout << c4.player_to_string(1) << " won";
+    if (mor.value(0) == 1) cout << mor.player_to_string(0) << " won";
+    else if (mor.value(1) == 1) cout << mor.player_to_string(1) << " won";
     else cout << "draw";
     cout << endl;
     //    ProfilerStop();
@@ -80,25 +80,25 @@ namespace mcts
 
   void test_mcts_two_players::self_play_learn_openings(int n)
   {
-    connect4 c4;
+    morpion mor;
     vector<uint16_t> moves(200);
-    auto state = c4.get_state();
-    auto the_turk_1 = make_mcts_two_players(c4, 1000, 0.6, 2);
-    auto the_turk_2 = make_mcts_two_players(c4, 1000, 0.6, 2);
+    auto state = mor.get_state();
+    auto the_turk_1 = make_mcts_two_players(mor, 1000, 0.6, 2);
+    auto the_turk_2 = make_mcts_two_players(mor, 1000, 0.6, 2);
     map<set<int>, pair<uint32_t, double>> learning_examples;
     for (int i = 0; i < n; ++i)
       {
         cout << i << endl;
         cout << openings_ << endl << endl;
         moves.clear();
-        c4.set_state(state);
+        mor.set_state(state);
         the_turk_1.reset();
         the_turk_1.init_with_openings(openings_);
         the_turk_2.reset();
         the_turk_2.init_with_openings(openings_);
         int the_turk_1_last_move = -1, the_turk_2_last_move = -1;
         int k = 0;
-        while (!c4.end_of_game())
+        while (!mor.end_of_game())
 	  {
             if (k == 1) the_turk_2.last_move(the_turk_1_last_move);
             if (k % 2 == 0)
@@ -110,7 +110,7 @@ namespace mcts
                 uint16_t move = the_turk_1.select_move();
                 moves.push_back(move);
                 the_turk_1_last_move = move;
-                c4.play(move);
+                mor.play(move);
 	      }
             else
 	      {
@@ -121,21 +121,21 @@ namespace mcts
                 uint16_t move = the_turk_2.select_move();
                 moves.push_back(move);
                 the_turk_2_last_move = move;
-                c4.play(move);
+                mor.play(move);
 	      }
             ++k;
 	  }
-	std::cout << c4 << std::endl;
-        int v = c4.value(0);
+	std::cout << mor << std::endl;
+        int v = mor.value(0);
         cout << "value for first player " << v << endl;
-        c4.set_state(state);
-        openings_.update(c4, moves, v);
-	c4.set_state(state);
+        mor.set_state(state);
+        openings_.update(mor, moves, v);
+	mor.set_state(state);
 	for (uint16_t m : moves) 
 	  {
-	    c4.play(m);
+	    mor.play(m);
 	    v = -v;
-	    set<int> input_vector = std::move(c4.to_input_vector());
+	    set<int> input_vector = std::move(mor.to_input_vector());
 	    auto it = learning_examples.find(input_vector);
 	    if (it == learning_examples.end())
 	      {
@@ -164,26 +164,26 @@ namespace mcts
 
   void test_mcts_two_players::self_play(int n, bool with_openings)
   {
-    connect4 c4;
-    auto state = c4.get_state();
-    auto the_turk_v1 = make_mcts_two_players(c4, 1000, 0.6, 2);
-    auto the_turk_v2 = make_mcts_two_players(c4, 1000, 0.6, 2);
+    morpion mor;
+    auto state = mor.get_state();
+    auto the_turk_v1 = make_mcts_two_players(mor, 1000, 0.6, 2);
+    auto the_turk_v2 = make_mcts_two_players(mor, 1000, 0.6, 2);
     int nb_win_v1 = 0, nb_win_v2 = 0, nb_draw = 0;
     for (int i = 0; i < n; ++i)
       {
         cout << i << endl;
-        c4.set_state(state);
+        mor.set_state(state);
         the_turk_v1.reset();
         the_turk_v2.reset();
 	if (with_openings) the_turk_v2.init_with_openings(openings_);
         int the_turk_v1_last_move = -1, the_turk_v2_last_move = -1;
 	int k = 0;
-        while (!c4.end_of_game())
+        while (!mor.end_of_game())
 	  {
             if (with_openings && k == 1 && i % 2 == 0) the_turk_v2.last_move(the_turk_v1_last_move);
 	    ++k;
-            //	    cout << c4 << endl;
-            if ((i % 2 == 0 && c4.current_player() == 0) || (i % 2 == 1 && c4.current_player() == 1))
+            //	    cout << mor << endl;
+            if ((i % 2 == 0 && mor.current_player() == 0) || (i % 2 == 1 && mor.current_player() == 1))
 	      {
                 if (the_turk_v1_last_move != -1 && the_turk_v2_last_move != -1)
 		  {
@@ -191,7 +191,7 @@ namespace mcts
 		  }
                 uint16_t move = the_turk_v1.select_move();
                 the_turk_v1_last_move = move;
-                c4.play(move);
+                mor.play(move);
 	      }
             else
 	      {
@@ -201,10 +201,10 @@ namespace mcts
 		  }
                 uint16_t move = the_turk_v2.select_move();
                 the_turk_v2_last_move = move;
-                c4.play(move);
+                mor.play(move);
 	      }
 	  }
-        if (c4.value(0) == 1)
+        if (mor.value(0) == 1)
 	  {
             if (i % 2 == 0)
 	      {
@@ -215,7 +215,7 @@ namespace mcts
                 /*cout << "v2 won" << endl;*/ ++nb_win_v2;
 	      }
 	  }
-        else if (c4.value(1) == 1)
+        else if (mor.value(1) == 1)
 	  {
             if (i % 2 == 0)
 	      {
@@ -236,18 +236,18 @@ namespace mcts
 
   void test_mcts_two_players::self_play()
   {
-    connect4 c4;
-    auto the_turk_v1 = make_mcts_two_players(c4, 1000, 1.2, 2);
-    auto the_turk_v2 = make_mcts_two_players(c4, 1000, 1.2, 2);
+    morpion mor;
+    auto the_turk_v1 = make_mcts_two_players(mor, 1000, 1.2, 2);
+    auto the_turk_v2 = make_mcts_two_players(mor, 1000, 1.2, 2);
     cout << "play one game" << endl;
     cout << "who's first? the_turk_(v1)/the_turk_(v2) ";
     string ans;
     getline(cin, ans);
-    cout << c4 << endl;
+    cout << mor << endl;
     int the_turk_v1_last_move = -1, the_turk_v2_last_move = -1;
-    while (!c4.end_of_game())
+    while (!mor.end_of_game())
       {
-        if ((ans == "v1" && c4.current_player() == 0) || (ans == "v2" && c4.current_player() == 1))
+        if ((ans == "v1" && mor.current_player() == 0) || (ans == "v2" && mor.current_player() == 1))
 	  {
             if (the_turk_v1_last_move != -1 && the_turk_v2_last_move != -1)
 	      {
@@ -255,8 +255,8 @@ namespace mcts
 	      }
             uint16_t move = the_turk_v1.select_move();
             the_turk_v1_last_move = move;
-            cout << c4.player_to_string(c4.current_player()) << " move: " << c4.move_to_string(move) << endl;
-            c4.play(move);
+            cout << mor.player_to_string(mor.current_player()) << " move: " << mor.move_to_string(move) << endl;
+            mor.play(move);
 	  }
         else
 	  {
@@ -266,13 +266,13 @@ namespace mcts
 	      }
             uint16_t move = the_turk_v2.select_move();
             the_turk_v2_last_move = move;
-            cout << c4.player_to_string(c4.current_player()) << " move: " << c4.move_to_string(move) << endl;
-            c4.play(move);
+            cout << mor.player_to_string(mor.current_player()) << " move: " << mor.move_to_string(move) << endl;
+            mor.play(move);
 	  }
-        cout << c4 << endl;
+        cout << mor << endl;
       }
-    if (c4.value(0) == 1) cout << c4.player_to_string(0) << " won";
-    else if (c4.value(1) == 1) cout << c4.player_to_string(1) << " won";
+    if (mor.value(0) == 1) cout << mor.player_to_string(0) << " won";
+    else if (mor.value(1) == 1) cout << mor.player_to_string(1) << " won";
     else cout << "draw";
     cout << endl;
   }
-- 
GitLab