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