Skip to content
Snippets Groups Projects

Compare revisions

Changes are shown as if the source revision was being merged into the target revision. Learn more about comparing revisions.

Source

Select target project
No results found

Target

Select target project
  • francesco-bariatti/pingouins
  • Samuel.Felton/pingouins
  • Lucas.Clement/pingouins
3 results
Show changes
Showing with 0 additions and 1523 deletions
import javafx.scene.shape.*;
public class Case {
private int rang; //N de la case (bottom right = 0, top left = 59)
private int nbFish;//Nb de poissons sur la case (0 si vide)
private boolean bluePenguin; //true s'il y a un pinguin bleu sur la case
private boolean redPenguin; //true s'il y a un pinguin rouge sur la case
public Case(int rang, int nbFish, boolean bluePenguin, boolean redPenguin) {
super();
this.rang = rang;
this.nbFish = nbFish;
this.bluePenguin = bluePenguin;
this.redPenguin = redPenguin;
}
public Case(int rang) { //Constructeur de case vide
super();
this.rang = rang;
nbFish=0;
bluePenguin=false;
redPenguin=false;
}
}
import java.net.URL;
import java.util.ResourceBundle;
import javafx.event.EventHandler;
import javafx.fxml.FXML;
import javafx.fxml.Initializable;
import javafx.scene.input.MouseEvent;
import javafx.scene.layout.BorderPane;
import javafx.scene.paint.Color;
import javafx.scene.shape.Polygon;
public class Controller implements Initializable {
@FXML
private Polygon case0;
@FXML
private Polygon case1;
@FXML
private Polygon case2;
@FXML
private Polygon case3;
@FXML
private Polygon case4;
@FXML
private Polygon case5;
@FXML
private Polygon case6;
@FXML
private Polygon case7;
@FXML
private Polygon case8;
@FXML
private Polygon case9;
@FXML
private Polygon case10;
@FXML
private Polygon case11;
@FXML
private Polygon case12;
@FXML
private Polygon case13;
@FXML
private Polygon case14;
@FXML
private Polygon case15;
@FXML
private Polygon case16;
@FXML
private Polygon case17;
@FXML
private Polygon case18;
@FXML
private Polygon case19;
@FXML
private Polygon case20;
@FXML
private Polygon case21;
@FXML
private Polygon case22;
@FXML
private Polygon case23;
@FXML
private Polygon case24;
@FXML
private Polygon case25;
@FXML
private Polygon case26;
@FXML
private Polygon case27;
@FXML
private Polygon case28;
@FXML
private Polygon case29;
@FXML
private Polygon case30;
@FXML
private Polygon case31;
@FXML
private Polygon case32;
@FXML
private Polygon case33;
@FXML
private Polygon case34;
@FXML
private Polygon case35;
@FXML
private Polygon case36;
@FXML
private Polygon case37;
@FXML
private Polygon case38;
@FXML
private Polygon case39;
@FXML
private Polygon case40;
@FXML
private Polygon case41;
@FXML
private Polygon case42;
@FXML
private Polygon case43;
@FXML
private Polygon case44;
@FXML
private Polygon case45;
@FXML
private Polygon case46;
@FXML
private Polygon case47;
@FXML
private Polygon case48;
@FXML
private Polygon case49;
@FXML
private Polygon case50;
@FXML
private Polygon case51;
@FXML
private Polygon case52;
@FXML
private Polygon case53;
@FXML
private Polygon case54;
@FXML
private Polygon case55;
@FXML
private Polygon case56;
@FXML
private Polygon case57;
@FXML
private Polygon case58;
@FXML
private Polygon case59;
@FXML
private BorderPane panneauPrincipal;
@Override
public void initialize(URL location, ResourceBundle resources) {
case0.setOnMouseClicked(new MyClickHandler());
case1.setOnMouseClicked(new MyClickHandler());
case2.setOnMouseClicked(new MyClickHandler());
case3.setOnMouseClicked(new MyClickHandler());
case4.setOnMouseClicked(new MyClickHandler());
case5.setOnMouseClicked(new MyClickHandler());
case6.setOnMouseClicked(new MyClickHandler());
case7.setOnMouseClicked(new MyClickHandler());
case8.setOnMouseClicked(new MyClickHandler());
case9.setOnMouseClicked(new MyClickHandler());
case10.setOnMouseClicked(new MyClickHandler());
case11.setOnMouseClicked(new MyClickHandler());
case12.setOnMouseClicked(new MyClickHandler());
case13.setOnMouseClicked(new MyClickHandler());
case14.setOnMouseClicked(new MyClickHandler());
case15.setOnMouseClicked(new MyClickHandler());
case16.setOnMouseClicked(new MyClickHandler());
case17.setOnMouseClicked(new MyClickHandler());
case18.setOnMouseClicked(new MyClickHandler());
case19.setOnMouseClicked(new MyClickHandler());
case20.setOnMouseClicked(new MyClickHandler());
case21.setOnMouseClicked(new MyClickHandler());
case22.setOnMouseClicked(new MyClickHandler());
case23.setOnMouseClicked(new MyClickHandler());
case24.setOnMouseClicked(new MyClickHandler());
case25.setOnMouseClicked(new MyClickHandler());
case26.setOnMouseClicked(new MyClickHandler());
case27.setOnMouseClicked(new MyClickHandler());
case28.setOnMouseClicked(new MyClickHandler());
case29.setOnMouseClicked(new MyClickHandler());
case30.setOnMouseClicked(new MyClickHandler());
case31.setOnMouseClicked(new MyClickHandler());
case32.setOnMouseClicked(new MyClickHandler());
case33.setOnMouseClicked(new MyClickHandler());
case34.setOnMouseClicked(new MyClickHandler());
case35.setOnMouseClicked(new MyClickHandler());
case36.setOnMouseClicked(new MyClickHandler());
case37.setOnMouseClicked(new MyClickHandler());
case38.setOnMouseClicked(new MyClickHandler());
case39.setOnMouseClicked(new MyClickHandler());
case40.setOnMouseClicked(new MyClickHandler());
case41.setOnMouseClicked(new MyClickHandler());
case42.setOnMouseClicked(new MyClickHandler());
case43.setOnMouseClicked(new MyClickHandler());
case44.setOnMouseClicked(new MyClickHandler());
case45.setOnMouseClicked(new MyClickHandler());
case46.setOnMouseClicked(new MyClickHandler());
case47.setOnMouseClicked(new MyClickHandler());
case48.setOnMouseClicked(new MyClickHandler());
case49.setOnMouseClicked(new MyClickHandler());
case50.setOnMouseClicked(new MyClickHandler());
case51.setOnMouseClicked(new MyClickHandler());
case52.setOnMouseClicked(new MyClickHandler());
case53.setOnMouseClicked(new MyClickHandler());
case54.setOnMouseClicked(new MyClickHandler());
case55.setOnMouseClicked(new MyClickHandler());
case56.setOnMouseClicked(new MyClickHandler());
case57.setOnMouseClicked(new MyClickHandler());
case58.setOnMouseClicked(new MyClickHandler());
case59.setOnMouseClicked(new MyClickHandler());
case0.setOnMouseEntered(new MyHexEnteredHandler());
case1.setOnMouseEntered(new MyHexEnteredHandler());
case2.setOnMouseEntered(new MyHexEnteredHandler());
case3.setOnMouseEntered(new MyHexEnteredHandler());
case4.setOnMouseEntered(new MyHexEnteredHandler());
case5.setOnMouseEntered(new MyHexEnteredHandler());
case6.setOnMouseEntered(new MyHexEnteredHandler());
case7.setOnMouseEntered(new MyHexEnteredHandler());
case8.setOnMouseEntered(new MyHexEnteredHandler());
case9.setOnMouseEntered(new MyHexEnteredHandler());
case10.setOnMouseEntered(new MyHexEnteredHandler());
case11.setOnMouseEntered(new MyHexEnteredHandler());
case12.setOnMouseEntered(new MyHexEnteredHandler());
case13.setOnMouseEntered(new MyHexEnteredHandler());
case14.setOnMouseEntered(new MyHexEnteredHandler());
case15.setOnMouseEntered(new MyHexEnteredHandler());
case16.setOnMouseEntered(new MyHexEnteredHandler());
case17.setOnMouseEntered(new MyHexEnteredHandler());
case18.setOnMouseEntered(new MyHexEnteredHandler());
case19.setOnMouseEntered(new MyHexEnteredHandler());
case20.setOnMouseEntered(new MyHexEnteredHandler());
case21.setOnMouseEntered(new MyHexEnteredHandler());
case22.setOnMouseEntered(new MyHexEnteredHandler());
case23.setOnMouseEntered(new MyHexEnteredHandler());
case24.setOnMouseEntered(new MyHexEnteredHandler());
case25.setOnMouseEntered(new MyHexEnteredHandler());
case26.setOnMouseEntered(new MyHexEnteredHandler());
case27.setOnMouseEntered(new MyHexEnteredHandler());
case28.setOnMouseEntered(new MyHexEnteredHandler());
case29.setOnMouseEntered(new MyHexEnteredHandler());
case30.setOnMouseEntered(new MyHexEnteredHandler());
case31.setOnMouseEntered(new MyHexEnteredHandler());
case32.setOnMouseEntered(new MyHexEnteredHandler());
case33.setOnMouseEntered(new MyHexEnteredHandler());
case34.setOnMouseEntered(new MyHexEnteredHandler());
case35.setOnMouseEntered(new MyHexEnteredHandler());
case36.setOnMouseEntered(new MyHexEnteredHandler());
case37.setOnMouseEntered(new MyHexEnteredHandler());
case38.setOnMouseEntered(new MyHexEnteredHandler());
case39.setOnMouseEntered(new MyHexEnteredHandler());
case40.setOnMouseEntered(new MyHexEnteredHandler());
case41.setOnMouseEntered(new MyHexEnteredHandler());
case42.setOnMouseEntered(new MyHexEnteredHandler());
case43.setOnMouseEntered(new MyHexEnteredHandler());
case44.setOnMouseEntered(new MyHexEnteredHandler());
case45.setOnMouseEntered(new MyHexEnteredHandler());
case46.setOnMouseEntered(new MyHexEnteredHandler());
case47.setOnMouseEntered(new MyHexEnteredHandler());
case48.setOnMouseEntered(new MyHexEnteredHandler());
case49.setOnMouseEntered(new MyHexEnteredHandler());
case50.setOnMouseEntered(new MyHexEnteredHandler());
case51.setOnMouseEntered(new MyHexEnteredHandler());
case52.setOnMouseEntered(new MyHexEnteredHandler());
case53.setOnMouseEntered(new MyHexEnteredHandler());
case54.setOnMouseEntered(new MyHexEnteredHandler());
case55.setOnMouseEntered(new MyHexEnteredHandler());
case56.setOnMouseEntered(new MyHexEnteredHandler());
case57.setOnMouseEntered(new MyHexEnteredHandler());
case58.setOnMouseEntered(new MyHexEnteredHandler());
case59.setOnMouseEntered(new MyHexEnteredHandler());
}
//public Polygon getPolygonFromCoordinates(double x, double y){ }
//Action de click sur case
private class MyClickHandler implements EventHandler<MouseEvent> {
@Override
public void handle (MouseEvent event){
Polygon poly = (Polygon)event.getSource();
poly.setFill(Color.GOLD);
}
}
private class MyHexEnteredHandler implements EventHandler<MouseEvent> {
@Override
public void handle (MouseEvent event){
Polygon poly = (Polygon)event.getSource();
poly.setFill(Color.GOLD);
}
}
}
import javafx.application.Application;
import javafx.fxml.FXMLLoader;
import javafx.stage.Stage;
import javafx.scene.Scene;
import javafx.scene.layout.BorderPane;
public class Main extends Application {
@Override
public void start(Stage primaryStage) {
try {
FXMLLoader loader = new FXMLLoader();
loader.setLocation(Main.class.getResource("view.fxml"));
BorderPane root = (BorderPane) loader.load();
Scene scene = new Scene(root,1024,680);
primaryStage.setScene(scene);
primaryStage.show();
} catch(Exception e) {
e.printStackTrace();
}
}
public static void main(String[] args) {
launch(args);
}
}
\ No newline at end of file
public class Plateau {
private Case[] grille;
//Constructeur de grille vide (0 fish, 0 penguins)
public Plateau(){
grille = new Case[60];
for (int i=0; i<60 ; i++){
grille[i]= new Case(i);
}
}
}
#include "connect4.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>> connect4::cross_hash_values = create_hash_values();
vector<vector<uint64_t>> connect4::circle_hash_values = create_hash_values();
connect4::connect4()
{
}
shared_ptr<game<connect4_state>> connect4::do_copy() const
{
return shared_ptr<connect4>(new connect4(*this));
}
connect4_state connect4::get_state()
{
return state;
}
void connect4::set_state(const connect4_state& s)
{
state = s;
}
bool connect4::end_of_game() const
{
return state.first_player_win || state.second_player_win || state.total_moves == 42;
}
bool connect4::won(std::uint8_t player) const
{
if (player == 0) return state.first_player_win;
return state.second_player_win;
}
bool connect4::lost(std::uint8_t player) const
{
if (player == 0) return state.second_player_win;
return state.first_player_win;
}
bool connect4::draw(std::uint8_t player) const
{
if (state.first_player_win || state.second_player_win) return false;
return state.total_moves == 42;
}
uint8_t connect4::current_player() const
{
return state.total_moves & 1 ? CIRCLE : CROSS;
}
// uint8_t connect4::current_player_representation() const
// {
// return state.total_moves & 1 ? CIRCLE_REPRESENTATION : CROSS_REPRESENTATION;
// }
// uint8_t connect4::player_representation_to_player(uint8_t player) const
// {
// return player == CIRCLE_REPRESENTATION ? CIRCLE : (player == CROSS_REPRESENTATION ? CROSS : -1);
// }
int connect4::value(uint8_t player) const
{
if (player == CROSS)
{
return state.first_player_win ? 1 : (state.second_player_win ? -1 : 0);
}
else if (player == CIRCLE)
{
return state.second_player_win ? 1 : (state.first_player_win ? -1 : 0);
}
return 0;
}
uint16_t connect4::number_of_moves() const
{
return state.nb_moves;
}
bool connect4::get(uint64_t bitboard, uint8_t col, uint8_t row) const
{
return bitboard & (1LL << ((col << 3) + row));
//return (state.board[i] >> (j << 1)) & 3;
}
#define set(bitboard, col, row) (bitboard |= (1LL << (((col) << 3) + (row))))
// bool connect4::vertical(uint8_t position, uint8_t free, uint8_t player) const
// {
// return free >= 3 && get(position, free - 1) == player && get(position, free - 2) == player && get(position, free - 3) == player;
// }
// bool connect4::horizontal(uint8_t position, uint8_t free, uint8_t player) const
// {
// uint8_t sum = 0;
// if (position >= 1 && get(position - 1, free) == player)
// {
// ++sum;
// if (position >= 2 && get(position - 2, free) == player)
// {
// ++sum;
// if (position >= 3 && get(position - 3, free) == player) ++sum;
// }
// }
// if (position <= 5 && get(position + 1, free) == player)
// {
// ++sum;
// if (position <= 4 && get(position + 2, free) == player)
// {
// ++sum;
// if (position <= 3 && get(position + 3, free) == player) ++sum;
// }
// }
// return sum >= 3;
// }
// bool connect4::diagonal(uint8_t position, uint8_t free, uint8_t player) const
// {
// uint8_t sum = 0;
// if (position >= 1 && free <= 4 && get(position - 1, free + 1) == player)
// {
// ++sum;
// if (position >= 2 && free <= 3 && get(position - 2, free + 2) == player)
// {
// ++sum;
// if (position >= 3 && free <= 2 && get(position - 3, free + 3) == player) ++sum;
// }
// }
// if (position <= 5 && free >= 1 && get(position + 1, free - 1) == player)
// {
// ++sum;
// if (position <= 4 && free >= 2 && get(position + 2, free - 2) == player)
// {
// ++sum;
// if (position <= 3 && free >= 3 && get(position + 3, free - 3) == player) ++sum;
// }
// }
// return sum >= 3;
// }
// bool connect4::other_diagonal(uint8_t position, uint8_t free, uint8_t player) const
// {
// uint8_t sum = 0;
// if (position >= 1 && free >= 1 && get(position - 1, free - 1) == player)
// {
// ++sum;
// if (position >= 2 && free >= 2 && get(position - 2, free - 2) == player)
// {
// ++sum;
// if (position >= 3 && free >= 3 && get(position - 3, free - 3) == player) ++sum;
// }
// }
// if (position <= 5 && free <= 4 && get(position + 1, free + 1) == player)
// {
// ++sum;
// if (position <= 4 && free <= 3 && get(position + 2, free + 2) == player)
// {
// ++sum;
// if (position <= 3 && free <= 2 && get(position + 3, free + 3) == player) ++sum;
// }
// }
// return sum >= 3;
// }
// void connect4::update_win(uint8_t position, uint8_t free)
// {
// uint8_t player = current_player_representation();
// bool win =
// vertical(position, free, player)
// ||
// horizontal(position, free, player)
// ||
// diagonal(position, free, player)
// ||
// other_diagonal(position, free, player);
// if (win)
// {
// if (player == CROSS_REPRESENTATION) state.first_player_win = true;
// else state.second_player_win = true;
// }
// }
void connect4::update_win()
{
if (has_won(state.cross_bitboard)) state.first_player_win = true;
else if (has_won(state.circle_bitboard)) state.second_player_win = true;
}
bool connect4::has_won(uint64_t bitboard)
{
int64_t y = bitboard & (bitboard >> 7);
if (y & (y >> 2 * 7)) // check \ diagonal
return true;
y = bitboard & (bitboard >> 8);
if (y & (y >> 2 * 8)) // check horizontal -
return true;
y = bitboard & (bitboard >> 9);
if (y & (y >> 2 * 9)) // check / diagonal
return true;
y = bitboard & (bitboard >> 1);
if (y & (y >> 2)) // check vertical |
return true;
return false;
}
void connect4::update_moves(uint16_t move)
{
--state.nb_moves;
uint32_t prefix = state.moves >> ((move + 1) * 3);
uint8_t shift = 32 - move * 3;
state.moves = (uint32_t)((uint64_t)state.moves << shift) >> shift;
state.moves |= prefix << (move * 3);
}
void connect4::play(uint16_t m)
{
uint8_t position = ((state.moves >> (m * 3)) & 7);
uint8_t p = position * 3;
uint8_t f = (state.free >> p) & 7;
// state.hash_value ^= current_player() == CIRCLE ? circle_hash_values[position][f] : cross_hash_values[position][f];
// state.board[position] |= current_player_representation() << (f << 1);
if (current_player() == CROSS)
{
set(state.cross_bitboard, position, f);
}
else
{
set(state.circle_bitboard, position, f);
}
update_win();
++f;
state.free = (state.free & ~(((uint32_t)7) << p)) | (f << p);
if (f == 6)
{
update_moves(m);
}
++state.total_moves;
}
string connect4::player_to_string(uint8_t player) const
{
return player == CROSS ? "X" : (player == CIRCLE ? "O" : " ");
}
string connect4::move_to_string(uint16_t m) const
{
uint8_t position = ((state.moves >> (m * 3)) & 7);
return std::to_string(position);
}
set<int> connect4::to_input_vector() const
{
set<int> res;
int k = 0;
if (current_player()) res.insert(k++);
for (int col = 0; col < 7; ++col)
{
for (int row = 0; row < 6; ++row)
{
if (get(state.cross_bitboard, col, row)) res.insert(k++);
}
}
for (int col = 0; col < 7; ++col)
{
for (int row = 0; row < 6; ++row)
{
if (get(state.circle_bitboard, col, row)) res.insert(k++);
}
}
return res;
}
void connect4::from_input_vector(const std::set<int>& input)
{
state = connect4_state();
for (int index : input)
{
if (index == 1) continue;
if (index <= 43)
{
index -= 2;
state.cross_bitboard |= 1LL << (index + (index / 6) * 2);
}
else
{
index -= 44;
state.circle_bitboard |= 1LL << (index + (index / 6) * 2);
}
state.total_moves += 1;
}
}
string connect4::to_string() const
{
stringbuf buffer;
ostream os(&buffer);
for (int y = 5; y >= 0; --y)
{
for (int k = 0; k < 7; ++k) os << "+-";
os << "+" << endl;
for (int x = 0; x < 7; ++x)
{
os << "|" << (get(state.cross_bitboard, x, y) ? player_to_string(CROSS) : (get(state.circle_bitboard, x, y) ? player_to_string(CIRCLE) : " "));
}
os << "|" << endl;
}
for (int k = 0; k < 7; ++k) os << "+-";
os << "+" << endl;
for (int k = 0; k < 7; ++k) os << " " << k;
os << endl;
return buffer.str();
}
// void connect4::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 connect4::hash() const
{
return state.hash_value;
}
std::uint64_t connect4::hash(std::uint16_t m) const
{
uint8_t position = ((state.moves >> (m * 3)) & 7);
uint8_t p = position * 3;
uint8_t f = (state.free >> p) & 7;
return state.hash_value ^ (current_player() == CIRCLE ? circle_hash_values[position][f] : cross_hash_values[position][f]);
}
ostream& operator<<(ostream& os, const connect4& c4)
{
os << c4.to_string() << endl;
return os;
}
}
#ifndef __CONNECT4_HPP__
#define __CONNECT4_HPP__
#include "game.hpp"
#include <random>
#include <array>
#include <iostream>
#include <memory>
namespace game
{
struct connect4_state
{
uint64_t cross_bitboard = 0;
uint64_t circle_bitboard = 0;
// std::array<uint16_t, 7> board{};
std::uint32_t moves = 0x1AC688;
std::uint32_t free = 0;
uint64_t hash_value = 0;
std::uint16_t nb_moves = 7;
uint8_t total_moves = 0;
bool first_player_win = false;
bool second_player_win = false;
};
class connect4 : public game<connect4_state>
{
public:
connect4();
connect4(const connect4& c4) = default;
connect4& operator=(const connect4& c4) = default;
bool end_of_game() const;
int value(std::uint8_t player) const;
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);
connect4_state get_state();
void set_state(const connect4_state& state);
std::shared_ptr<game<connect4_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;
// inline bool vertical(uint8_t position, uint8_t free, uint8_t player) const;
// inline bool horizontal(uint8_t position, uint8_t free, uint8_t player) const;
// inline bool diagonal(uint8_t position, uint8_t free, uint8_t player) const;
// inline bool other_diagonal(uint8_t position, uint8_t free, uint8_t player) const;
// inline uint8_t current_player_representation() const;
// inline uint8_t player_representation_to_player(uint8_t player) const;
const uint8_t CROSS = 0;
const uint8_t CIRCLE = 1;
// const uint8_t CROSS_REPRESENTATION = 1;
// const uint8_t CIRCLE_REPRESENTATION = 2;
connect4_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 connect4& c4);
}
#endif
#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
{
return state.first_player_win || state.second_player_win || state.total_moves == 9;
}
bool morpion::won(std::uint8_t player) const
{
if (player == CROSS) return state.first_player_win;
return state.second_player_win;
}
bool morpion::lost(std::uint8_t player) const
{
if (player == CIRCLE) return state.first_player_win;
return state.second_player_win;
}
bool morpion::draw(std::uint8_t player) const
{
if (state.first_player_win || state.second_player_win) return false;
return state.total_moves == 9;
}
uint8_t morpion::current_player() const
{
return state.total_moves & 1 ? CIRCLE : CROSS; // CROSS even, CIRCLE odd
}
int morpion::value(uint8_t player) const
{
if (player == CROSS) {
return state.first_player_win ? 1 : (state.second_player_win ? -1 : 0);
}
else if (player == CIRCLE) {
return state.second_player_win ? 1 : (state.first_player_win ? -1 : 0);
}
return 0;
}
/* Number of moves that you can play */
uint16_t morpion::number_of_moves() const
{
return 9 - state.total_moves;
}
uint16_t morpion::number_moves_played() const
{
return state.total_moves;
}
bool morpion::get(uint16_t bitboard, uint8_t col, uint8_t row) const
{
return bitboard & (1LL << (3*row)) << col;
}
//#define set(bitboard, col, row) (bitboard |= (1LL << (((col) << 3) + (row))))
void morpion::update_win()
{
if(has_won(state.cross_bitboard))
state.first_player_win = true;
else if(has_won(state.circle_bitboard))
state.second_player_win = true;
}
bool morpion::has_won(uint16_t bitboard)
{
if(((bitboard | ROW0_MASK) == ALL_ONES) || ((bitboard | ROW1_MASK) == ALL_ONES) || ((bitboard | ROW2_MASK) == ALL_ONES)) // Check horizontal ---
return true;
if(((bitboard | COL0_MASK) == ALL_ONES) || ((bitboard | COL1_MASK) == ALL_ONES) || ((bitboard | COL2_MASK) == ALL_ONES)) // Check vertical |
return true;
if(((bitboard | DIA0_MASK) == ALL_ONES) || ((bitboard | DIA1_MASK) == ALL_ONES)) // Chack diagonal \ /
return true;
return false;
}
void morpion::update_moves()
{
uint16_t free_bitboard = ~(state.cross_bitboard | state.circle_bitboard);
//free_bitboard &= ALL_ONES; //When we complements, all unused bits in uint_16 are complemented to. ALL_ONES is a mask in which we have ones in the position used by the bitboard
//cout << "Free bitboard: " << (free_bitboard & ALL_ONES) << endl;
state.possible_moves = 0;
uint16_t mask = 256; //256 = 100 000 000
for(int i = 8; i >=0; i--)
{
if(free_bitboard & mask)
{
state.possible_moves = state.possible_moves << 4;
state.possible_moves |= i;
}
mask = mask >> 1;
}
//cout << "Possible moves: " << state.possible_moves << endl;
}
//Play the mth move in the possible moves list.
void morpion::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);
else
state.circle_bitboard |= (((uint16_t) 1) << move);
//State update
state.total_moves++;
update_win();
update_moves();
return;
}
/**
* player_to_string
* Retourne X si le joueur joue les croix, O s'il joue les ronds,
* et un espace sinon.
*/
string morpion::player_to_string(uint8_t player) const
{
return player == CROSS ? "X" : (player == CIRCLE ? "O" : " ");
}
string morpion::move_to_string(uint16_t m) const
{
return std::to_string((state.possible_moves >> (4 * m)) & 0xf);
}
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
{
string result = "-------\n";
for (int row = 2; row >= 0; row--)
{
result += "|";
for (int col = 2; col >= 0; col--)
{
if(((state.cross_bitboard >> (3*row)) >> col) & 1)
result += player_to_string(CROSS)+"|";
else if (((state.circle_bitboard >> (3*row)) >> col) & 1)
result += player_to_string(CIRCLE)+"|";
else
result += std::to_string(row * 3 + col) + "|";
}
result += "\n-------\n";
}
return result;
}
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;
}
}
#ifndef __MORPION_HPP__
#define __MORPION_HPP__
#include "game.hpp"
#include <random>
#include <array>
#include <iostream>
#include <memory>
namespace game
{
struct morpion_state
{
uint16_t cross_bitboard = 0; //bitboard with the played moves of the cross
uint16_t circle_bitboard = 0; //bitboard with the played moves of the circle
uint8_t total_moves = 0; //Total played moves (<= 9)
uint64_t possible_moves = 0x876543210; //List of possible moves left
bool first_player_win = false; //First player is always the cross
bool second_player_win = false; //Second player is always the circle
};
class morpion : public game<morpion_state>
{
public:
morpion();
morpion(const morpion& mor) = default;
morpion& operator=(const morpion& mor) = default;
bool end_of_game() const; //Is the game ended? (draw or won)
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; //The player that has to play next (at the beginning, the first player)
std::uint16_t number_of_moves() const; //Number of moves that you can play
std::uint16_t number_moves_played() const; //Number of moves played until now
void play(std::uint16_t m); //Play the move m (updates the state). m is the position on the board of where you want to play
void undo(std::uint16_t m) {}
std::string player_to_string(std::uint8_t player) const; //String representation of a player
std::string move_to_string(std::uint16_t m) const; //String representation of a move (for example, A1)
std::string to_string() const; //String representation of the entire game
std::set<int> to_input_vector() const;
void from_input_vector(const std::set<int>& input);
morpion_state get_state(); //Return the state
void set_state(const morpion_state& state); //Replace the current state with the one passed as a parameter
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(); //Check if someone won and update the state
inline bool has_won(uint16_t bitboard); //Check if the player whose bitboard was passed as a param has won
inline bool get(uint16_t bitboard, uint8_t i, uint8_t j) const; //Get a case of the board
inline void update_moves(); //Update the list of all possible moves
const uint8_t CROSS = 0;
const uint8_t CIRCLE = 1;
morpion_state state;
//WIN CONSTANTS
const uint16_t ROW0_MASK = 504;
const uint16_t ROW1_MASK = 455;
const uint16_t ROW2_MASK = 63;
const uint16_t COL0_MASK = 438;
const uint16_t COL1_MASK = 365;
const uint16_t COL2_MASK = 219;
const uint16_t DIA0_MASK = 238;
const uint16_t DIA1_MASK = 427;
const uint16_t ALL_ONES = 511;
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
#include "connect4.hpp"
#include "test_connect4.hpp"
#include <iostream>
#include <map>
using namespace std;
namespace game
{
test_connect4::test_connect4()
{
playout();
play();
}
void test_connect4::playout()
{
mt19937 mt;
connect4 c4;
cout << "playout" << endl;
for (int i = 0; i < 100; ++i)
{
uint8_t player = c4.current_player();
auto state = c4.get_state();
c4.playout(mt);
cout << "value: " << c4.value(player) << endl << c4 << endl;
c4.set_state(state);
string wait;
getline(cin, wait);
}
}
void test_connect4::play()
{
connect4 c4;
int player = 0;
cout << "play one game" << endl;
while (!c4.end_of_game())
{
cout << c4 << endl;
cout << c4.player_to_string(player) << " move: ";
map<string, int> m;
for (int i = 0; i < c4.number_of_moves(); ++i)
{
m[c4.move_to_string(i)] = i;
}
string move;
cin >> move;
c4.play(m[move]);
player = 1 - player;
}
cout << c4 << 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";
else cout << "draw";
cout << endl;
}
}
#ifndef __TEST_CONNECT4_HPP__
#define __TEST_CONNECT4_HPP__
namespace game
{
class test_connect4
{
void playout();
void play();
public:
test_connect4();
};
}
#endif
#include "test_connect4.hpp"
#include "connect4.hpp"
#include "morpion.hpp"
#include "penguin.hpp"
#include "test_two_players_game.hpp"
#include "test_monte_carlo.hpp"
#include "test_fast_log.hpp"
#include "test_allocator.hpp"
#include "test_mcts_two_players.hpp"
#include "test_minmax.hpp"
#include "test_bits.hpp"
#include "learning.hpp"
#include <omp.h>
using namespace std;
int main(int argc, char *argv[])
{
// game::test_connect4();
// util::test_fast_log(100000000);
// mcts::test_allocator(10, 2);
// omp_set_num_threads(8);
// game::run_test_two_players_game(game::connect4());
//mcts::run_test_mcts_two_players(game::connect4());
//game::run_test_two_players_game(game::morpion());
//mcts::run_test_mcts_two_players(game::morpion());
//game::run_test_two_players_game(game::penguin());
mcts::run_test_mcts_two_players(game::penguin());
// minmax::test_minmax();
//util::test_bits(200000000);
//game::connect4 c4;
// util::learning::display_file(c4, "learning_examples.txt");
return 0;
}
#include "connect4_heuristic.hpp"
namespace minmax
{
double connect4_heuristic::value(const connect4& c4) const
{
const connect4_state& state = c4.get_state();
return 0;
}
}
#ifndef __CONNECT4_HEURISTIC_HPP__
#define __CONNECT4_HEURISTIC_HPP__
#include <connect4.hpp>
namespace minmax
{
class connect4_heuristic : public heuristic<connect4>
{
double value(const connect4& c4) const;
};
}
#endif
#ifndef __HEURISTIC_HPP__
#define __HEURISTIC_HPP__
namespace minmax
{
template <typename Game>
class heuristic
{
public:
virtual double value(const Game& game) const = 0;
};
template <typename Game>
class null_heuristic : public heuristic<Game>
{
double value(const Game& game) const;
};
template <typename Game>
double null_heuristic<Game>::value(const Game& game) const
{
return 0;
}
}
#endif
#ifndef __MINMAX_HPP__
#define __MINMAX_HPP__
#include <chrono>
#include <vector>
#include "game.hpp"
#include "heuristic.hpp"
#include <iostream>
#include <limits>
namespace minmax
{
struct cannot_prove : std::exception
{
const char* what() const noexcept { return "cannot prove the game theoritical value"; }
};
template <typename Game>
class minmax
{
protected:
Game& game;
std::chrono::milliseconds milliseconds;
const heuristic<Game>& h;
std::vector<uint16_t> principal_variation;
std::chrono::steady_clock::time_point start;
public:
minmax(Game& game, uint32_t milliseconds, const heuristic<Game>& h = null_heuristic<Game>())
: game(game), milliseconds(milliseconds), h(h)
{
}
int prove();
double solve();
uint16_t select_move();
private:
long prove(int depth);
double solve(int depth);
};
template <typename Game>
minmax<Game> make_minmax(Game& game, uint32_t milliseconds, const heuristic<Game>& h = null_heuristic<Game>())
{
return minmax<Game>(game, milliseconds, h);
}
template <typename Game>
double minmax<Game>::solve()
{
return 0;
}
template <typename Game>
double minmax<Game>::solve(int depth)
{
return 0;
}
template <typename Game>
uint16_t minmax<Game>::select_move()
{
return 0;
}
const long UNKNOWN = std::numeric_limits<long>::max();
template <typename Game>
int minmax<Game>::prove()
{
start = std::chrono::steady_clock::now();
uint16_t nb_moves = game.number_of_moves();
long value[nb_moves];
std::fill_n(value, nb_moves, UNKNOWN);
int depth = 3;
auto state = game.get_state();
try
{
int nb_proved_moves = 0, nb_draws = 0;
while (true)
{
for (uint16_t move = 0; move < nb_moves; ++move)
{
if (value[move] != UNKNOWN) continue;
game.play(move);
value[move] = prove(depth);
game.set_state(state);
if (value[move] == -1) return 1;
if (value[move] == 0) ++nb_draws;
if (value[move] != UNKNOWN) ++nb_proved_moves;
}
if (nb_proved_moves == nb_moves)
{
if (nb_draws != 0) return 0;
return -1;
}
++depth;
}
}
catch (cannot_prove fail)
{
game.set_state(state);
}
throw cannot_prove();
}
template <typename Game>
long minmax<Game>::prove(int depth)
{
if (game.end_of_game()) return game.value(game.current_player());
if (depth == 0) return UNKNOWN;
if ((depth & 3) && std::chrono::steady_clock::now() >= start + milliseconds) throw cannot_prove();
uint16_t nb_moves = game.number_of_moves();
auto state = game.get_state();
int nb_proved_moves = 0, nb_draws = 0;
for (uint16_t move = 0; move < nb_moves; ++move)
{
game.play(move);
long v = prove(depth - 1);
game.set_state(state);
if (v == -1) return 1;
if (v == 0) ++nb_draws;
if (v != UNKNOWN) ++nb_proved_moves;
}
if (nb_proved_moves == nb_moves)
{
if (nb_draws != 0) return 0;
return -1;
}
return UNKNOWN;
}
}
#endif
#include "minmax.hpp"
#include "test_minmax.hpp"
#include "connect4.hpp"
#include <iostream>
#include <iomanip>
#include <map>
using namespace std;
using namespace game;
namespace minmax
{
test_minmax::test_minmax()
{
play();
}
template <typename Game>
int test_minmax::select_move(Game& game)
{
cout << game.player_to_string(game.current_player()) << " move: ";
map<string, int> m;
for (int i = 0; i < game.number_of_moves(); ++i)
{
m[game.move_to_string(i)] = i;
}
string move;
getline(cin, move);
game.play(m[move]);
return m[move];
}
void test_minmax::play()
{
connect4 c4;
auto minimax = make_minmax(c4, 2000);
cout << "play one game" << endl;
cout << c4 << endl;
while (!c4.end_of_game())
{
cout << "try to prove? (y/n)" << endl;
string ans;
getline(cin, ans);
if (ans == "y")
{
try
{
int v = minimax.prove();
if (v == 1) cout << "won position" << endl;
if (v == -1) cout << "lost position" << endl;
if (v == 0) cout << "drawn position" << endl;
}
catch (exception fail)
{
cout << "unable to prove" << endl;
}
}
select_move(c4);
cout << c4 << 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";
else cout << "draw";
cout << endl;
}
}
#ifndef __TEST_MINMAX_HPP__
#define __TEST_MINMAX_HPP__
namespace minmax
{
class test_minmax
{
void play();
template <typename Game>
int select_move(Game& game);
public:
test_minmax();
};
}
#endif
#!/usr/bin/env python3
#-*- encoding: utf-8 -*-
import drawState
import subprocess
import json
import os
if __name__ == "__main__":
programname = os.path.join(os.path.dirname(__file__), "../bin/theturk")
program = subprocess.Popen(programname, stdin = subprocess.PIPE, stdout = subprocess.PIPE, universal_newlines = True, bufsize = 1)
try:
program.stdin.write("h\n")
while True:
#READ
readloop = True
comments = []
json_data = ""
brackets_count = 0
while readloop:
line = program.stdout.readline()
#print(line)
line = line.replace("who's first? (h)uman/(c)omputer ", "")
line = line.replace("Red move: ", "")
line = line.replace("Blue move: ", "")
if line.startswith("{"): #Reading json
json_data = line
else:
comments.append(line)
if line == "\n":
readloop = False
#PRINT STATE
print("Comments: {}".format(''.join(comments)))
state = json.loads(json_data)
drawState.drawBitboard(state["bitboards"]["onefish"],state["bitboards"]["twofish"],state["bitboards"]["threefish"])
print("Red penguins (Red score: {}, Total moves: {} [0..{}])".format(state["score"]["red"], state["nb_moves"]["red"], state["nb_moves"]["red"]-1))
for i in range(4):
drawState.drawPenguin(state["penguins"]["red"][i])
print("Blue penguins (Blue score: {}, Total moves: {} [0..{}])".format(state["score"]["blue"], state["nb_moves"]["blue"], state["nb_moves"]["blue"] -1))
for i in range(4):
drawState.drawPenguin(state["penguins"]["blue"][i])
#PLAY NEXT MOVE
if state["current_player"] == "Red":
move = input("Enter Red move: ")
else:
move = input("Enter Blue move: ")
program.stdin.write(move+"\n")
program.stdin.flush()
except BrokenPipeError:
print("Game end")
except KeyboardInterrupt:
print("\nMay the fish be with you.")
finally:
program.kill()