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
\documentclass{article}
%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%
% PACKAGES
\usepackage{graphicx} %images
\usepackage[hidelinks]{hyperref}
\usepackage[utf8]{inputenc}
%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%
\title{\textbf{Jeu des pingouins: documentation utilisateur}}
\author{Francesco Bariatti \and Adrien Gasté \and Mikaël Le \and Romain Lebouc}
\date{2015-2016}
\begin{document}
\pagenumbering{gobble}
\maketitle
\newpage
\tableofcontents
\newpage
\pagenumbering{arabic}
\section{Introduction}
C'est un projet étudiant tiré d'un jeu déjà existant. Composé de deux parties: IA et GUI (c++ et javafx)
\subsection{Règles du jeu}
TODO NB: on ne gagne pas les points où il y a le dernier pingouin
\newpage
\section{Installation}
Le projet est dispo sous git, il faut le compiler à partir des sources.
\subsection{Dépendances}
\paragraph{IA} g++ sup ou égale 4.9
\paragraph{GUI} Java au moins 1.8 (javafx) et si on execute dans une IDE, niveau de langage au moins 8 (nécessité d'avoir lambda). Le jar json doit être dans le java build path.
\subsection{Compilation et lancement}
Allocator.hpp + executer et regarder la ram.
mcts.hpp pour changer le temps
à partir du dossier principal, make, vérifier qu'il y a theturk, le lancer pour voir la ram.
Lancer gui/main/main.java. Faire gaffe au son.
\section{Utilisation}
Quand on lance le main, interface graphique, on peut charger du json (il apparait tour par tour dans la console).
Si debut aléatoire: comment ajouter les pingouins.
Pour jouer click pour selectionner et click pour bouger.
Il faut attendre que le pc joue.
\section{Contact}
Si vous trouvé des bugs, n'hesitez pas à ouvrir des issues sur gitlab
\end{document}
\ No newline at end of file
......@@ -10,16 +10,16 @@
# Compiler for the AI: g++ >= 4.9
CC = g++
# JAVA ENVIRONMENT FOR THE GUI
# Java compiler >= 1.8
JAVAC = javac
# Java jar utility
JAR = jar
# Java executable used for the run target >= 1.8
JAVA = java
# Java compiler >= 1.8 (usually javac)
JAVAC := javac
# Java jar utility (usually jar)
JAR := jar
# Java application launcher >= 1.8 (usually java)
JAVA := java
all: ai gui
clean: aiclean guiclean
clean: cleanai cleangui
# ============================================ AI (C++) =============================================
#Root directory for the AI module
......@@ -47,8 +47,8 @@ AIOobjects=$(addprefix $(AIOutputDir)/, $(AISourceFile:.cpp=.o))
# ==== RULES ====
# Main rule for creating the executable
ai: aioutputdir $(AIExecutable)
aioutputdir:
ai: $(AIOutputDir) $(AIExecutable)
$(AIOutputDir):
mkdir -p $(AIOutputDir)
$(AIExecutable): $(AIOobjects)
......@@ -61,48 +61,68 @@ $(AIOutputDir)/%.o: %.cpp
-include $(AIOobjects:.o=.d)
# Deletes .o, .d and the executable
aiclean:
cleanai:
rm -f $(AIOutputDir)/*.o $(AIOutputDir)/*.d $(AIExecutable)
# ============================================ GUI (Java) =============================================
#Root directory of the GUI module
GUIRoot = GUI
# Output directory
GUIOutputDir = $(GUIRoot)/bin
# Name of the output jar
GUIOutputJar = $(GUIOutputDir)/penguin.jar
# Directory with all the java sources
GUISourceDir = $(GUIRoot)/src
vpath %.java $(GUISourceDir)
# Path to the JSON lib
GUIJSONJar = $(GUIRoot)/json-20160212.jar
# Classes needed in the projet (in the form: package/className)
GUIClasses = model/GameState model/Move model/Player model/Tile view/TileView controller/Controller controller/UpdateThread main/Main
# Resources that will be included in the jar (they will be appended to the jar creation command. See man for the -C option that will allow to specify a relative path inside the jar)
GUIJarResources = -C $(GUISourceDir) view/view.fxml -C $(GUISourceDir) resource/clic.wav -C $(GUISourceDir) resource/pingu_theme.wav
# Output directory of compiled classes
GUIClassesOutDir = $(GUIOutputDir)/classes
# Classpath used for compiling
GUICompileClasspath = $(GUIJSONJar):$(GUIClassesOutDir)
# Classpath used for running
GUIRunClasspath = $(GUIOutputJar):$(GUIJSONJar)
GUIRoot := GUI
# Output root directory
GUIOutDir := $(GUIRoot)/out
# Jar output file name
GUIJarFile := $(GUIOutDir)/penguin.jar
# Compiled classes output directory
GUIOutClassDir := $(GUIOutDir)/classes
# Sources root directory: all your sources will be under this directory (packages and classes)
GUISrcDir := $(GUIRoot)/src
# Packages that will be compiled and included in the jar: every class in these packages will be compiled, if you have classes in a package and in a subpackage as well you must specify both. Example: main package package/subpackage
GUIPackages := main model view controller
# Additional classes tha will be compiled and included in the jar: useful for packages that contains classes that you don't want to include. Otherwise, just use the Packages variable. Specify the path inside the source root WITH EXTENSION. Example: main/Main.java package/subpackage/MyClass.java
GUIAdditionalClasses :=
# Entry point (main class) for jar file. In the form package/subpackage/Class
GUIJAREntryPoint := main.Main
# Additional resources that will be copied in jar file. In the form -C path/to/the/parent/folder resource/path (resource/path will also be the path of the resourc inside the jar)
GUIJARResources := -C $(GUISrcDir) resource/ -C $(GUISrcDir) view/view.fxml
# Classpath option for compilation or execution: colon (:) separated list, must prepend -classpath flag. Example: -classpath Library.jar:Library/Include
GUIClassPath := -classpath $(GUIRoot)/json-20160212.jar
# Compiler additional flags
GUIJAVACFlags :=
# JAR additional flags
GUIJARFlags :=
# Run arguments
GUIRunArgs := $(AIExecutable)
# ==== RULES ====
# Main rule for creating the jar of the GUI: it needs the output folder and all the compiled classes
gui: guioutputdir $(addsuffix .class, $(GUIClasses))
$(JAR) cvfe $(GUIOutputJar) main.Main -C $(GUIClassesOutDir) ./ $(GUIJarResources)
guioutputdir:
mkdir -p $(GUIOutputDir)
# Rule for compiling a java class
%.class: %.java guiclassesoutdir
$(JAVAC) -sourcepath $(GUISourceDir) -classpath $(GUICompileClasspath) -d $(GUIClassesOutDir) $<
guiclassesoutdir:
mkdir -p $(GUIClassesOutDir)
# ========== AUTOMATICALLY GENERATED VARIABLES ==========
# Searching for java files inside the $(Packages): for every package we search for java files and later we strip the leading source folder that is not necessary
GUIClassesSources := $(patsubst $(GUISrcDir)/%, %, $(foreach package, $(GUIPackages), $(wildcard $(GUISrcDir)/$(package)/*.java)))
GUIClassesSources := $(GUIClassesSources) $(GUIAdditionalClasses)
# We tell make to search for java sources inside the source directory
vpath %.java $(GUISrcDir)
# ========== RULES ==========
gui: $(GUIJarFile)
# You need all compiled version of classes to make jar file
$(GUIJarFile): $(addprefix $(GUIOutClassDir)/, $(GUIClassesSources:.java=.class)) $(GUIOutDir)
$(JAR) cvfe $(GUIJarFile) $(GUIJAREntryPoint) -C $(GUIOutClassDir) ./ $(GUIJARResources) $(GUIJARFlags)
$(GUIOutDir):
mkdir -p $(GUIOutDir)
# To compile a class you need the source code and the output folder
$(GUIOutClassDir)/%.class: $(GUISrcDir)/%.java $(GUIOutClassDir)
$(JAVAC) -sourcepath $(GUISrcDir) -d $(GUIOutClassDir) $(GUIClassPath) $(GUIJAVACFlags) $<
$(GUIOutClassDir):
mkdir -p $(GUIOutClassDir)
run:
$(JAVA) -classpath $(GUIRunClasspath) main.Main $(AIExecutable)
@$(JAVA) $(GUIClassPath):$(GUIJarFile) main.Main $(GUIRunArgs)
guicleanjar:
-rm -f $(GUIJarFile)
guicleanclass:
-rm -f $(addprefix $(GUIOutClassDir)/, $(GUIClassesSources:.java=.class))
guiclean:
rm -r $(GUIOutputDir)
cleangui: guicleanjar guicleanclass
# PINGOUINS
Le jeu des pingouins!
## Objectif
Créer une Intelligence Artificielle qui soit capable de jouer au [jeu des pingouins](http://www.jeuxavolonte.asso.fr/regles/pingouin.pdf) grâce à l'algorithme *Montecarlo Tree Search*
# Penguin game
Implementation of the Penguin Game with an AI that uses MonteCarlo Tree Search algorithm.
## Auteurs
Le groupe K d'études pratiques de 3INFO
## Prerequisites
- g++ >= 4.9
- java >= 1.8
## Compiling/launching
Compile the project by running `make`
Run the project by running `make run`
## Documentation
A documentation (french only) is available in the `Doc` folder. It explains how to use the program and how it is implemented.
## License
This project is licensed under the MIT License. License information and authors attributions can be found in `LICENSE.txt`
## Authors
A group of students from INSA Rennes
- Francesco Bariatti
- Adrien Gasté
- Mikael Le
- Romain Lebouc
And their teacher
- Pascal Garcia
# Fonctions Test
Fonctions qui servent pour tester le programme: ces fonctions sont appelées par le programme principal.
## play()
Jouer une partie joueur vs joueur, sert pour tester si les règles sont bien implementées dans le programme
## playout()
Jouer une partie joueur vs ordi: programme final. Comment ça marche ?
- Créer une instance du jeu
- Créer une instance du mcts pour ce jeu: `auto mctsPlayer = mcts::make_mcts_two_players(JEU, 5000, 0.3, 4); `
- 5000: temps de reflexion en ms pour chaque tour du jeu
- 0.3 Facteur d'exploration (?)
- 4 nombre de visites avant expansion: un noeud sera visité 4 fois avant que son expansion soit faite dans l'arbre
- Tant que le jeu n'est pas fini, si c'est le tour de l'ordi
- Soit dire à l'ordi ce qu'on a choisi comme coup(?), soit lui faire un `mctsPlayer.reset()` qui efface tout l'arbre.
- Demander à l'ordi de choisir un coup `mctsPlayer.select_move();`
- Jouer ce coup
- Quand le jeu est fini dire à l'humain qu'il a perdu (parce que le MCTS est trop fort)
\ No newline at end of file
# Game interface (game/game.hpp)
Interface qui décrit un jeu, un jeu doit implémenter les fonctions décrites dans cette interface
Comment implementer l'interface: squelette du fichier .h du jeu
```C++
namespace game
{
struct JEU_state //structure qui décrit un état du jeu
{
[...]
}
class JEU : public game<JEU_state>
{
public:
JEU();
JEU(const JEU& J) = default;
JEU& operator=(const JEU& J) = 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);
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:
[... Methodes utiles pour le jeu mais pas nécessaires pour le MCTS ...]
};
std::ostream& operator<<(std::ostream& os, const JEU& J);
}
```
## Explication des différentes fonctions:
### bool end_of_game()
Est-ce que le jeu est terminé ? Soit parce que quelqu'un a gagné, soit parce que c'est égalité
### int value (int player)
Quelle est la valeur pour le joueur `player` dans l'état actuel du jeu ? Normalement 1 veut dire qu'il a gagné, -1 qu'il a perdu, 0 c'est égalité
### bool won/lost/draw(int player)
Est-ce que le joueur `player` a gagné/perdu/fait égalité ?
### int current_player()
C'est à quel joueur de jouer maintenant ? (Au début ce sera le joueur 0)
### int number_of_moves()
Nombre de coups que le joueur qui doit jouer maintenant peut jouer.
### play(int move)
Jouer le coup numéro `move` parmi les coups possibles: mets à jour l'état.
`move` represente la position du coup parmi tous les coups possibles, ce n'est pas la réprésentation du coup.
### undo(int move)
Pas implementé.
### string player_to_string(int player)
Representation d'un joueur de façon comprehensible par un humain
### string move_to_string(int move)
Representation d'un coup de façon comprehensible par un humain (par exemple B7).
`move` est l'indice du coup parmi tous les coups possibles
### string to_string()
Representation de l'état actuel du jeu (c'est à dire, dessiner l'état actuel du jeu)
### playout(engine, max_depth)
Joue le jeu en choisissant des coups au hasard jusqu'à la fin du jeu.
### get/set_state()
Retourne/charge l'état
### Les autres
Non utilisées
## Fonction play(int move)
Elle doit jouer le coup numéro `move` parmi les coups possibles. Algorithme:
- Recuperer quel coup est le coup numéro `move` dans la liste des coups possibles
- Mettre à jour le bon bitboard selon quel jouer doit jouer maintenant
- Ajouter 1 au nombre de coups joués jusqu'à maintenant (si nécessaire)
- Vérifier si un joueur a gagné et mettre à jour l'état
- Mettre à jour la liste de tous les coups possibles
## Fonction playout
```C++
void JEU::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);
}
}
```
Choisit un coup au hasard parmi les coups possibles et le joue.
Calcul des coups possibles à partir de la case i :
Vers direction A :
tantQue ((i+7) < 60 && i%15 != 0 && (i+7) estLibre)
{
i += 7;
ajout i dans listeCoupsPossibles;
}
finTantQue
Vers B :
tantQue (i%15 != 0 && i%15 != 8 && (i-1) estLibre)
{
i --;
ajout i dans listeCoupsPossibles;
}
finTantQue
Vers C :
tantQue ((i-8) >0 && i%15 != 0 && (i-8) estLibre)
{
i -= 8;
ajout i dans listeCoupsPossibles;
}
finTantQue
Vers D :
tantQue ((i-7) >0 && i%15 != 7 && (i-7) estLibre)
{
i -= 7;
ajout i dans listeCoupsPossibles;
}
finTantQue
Vers E :
tantQue (i%15 != 7 && i%15 != 14 && (i+1) estLibre)
{
i ++;
ajout i dans listeCoupsPossibles;
}
finTantQue
Vers F :
tantQue ((i+8) <60 && i%15 != 7 && (i+8) estLibre)
{
i += 8;
ajout i dans listeCoupsPossibles;
}
finTantQue
PLateau:
60 cases hexagonales verticales(sommet vers le bas)
Ligne du bas: 8 cases
Ligne du haut: 7 cases
8 lignes au total
Chaque ligne numerotée à partir de la droite. Le 0 est en bas à droite, le 59 en haut à gauche
Cases:
La direction A est vers le haut à droite (+7)
La direction B est vers la droite (-1)
La direction C est vers le bas à droite (-8)
etc...
==> Nom des joueurs : Red, Blue
Le premier joueur est Red
Nombre maximum de coups possibles par direction : 7
Structure 1 pingouin (bitlist sur 32 bits) :
+ + + + + +
| ??|Nb coups possibles ...|Nb coups possibles| Nombre total | Position sur |
| |direction F |direction A | de coups | le plateau (0-59) |
+------------------------------------------------------------+-------------------+
2 | 3 bits 3 bits | 6 bits 6 bits
| |
| |
+-----------------------------------------+
18 bits
==> 8 structures pingouin
Vocabulaire :
Obstacle = Trou ou Pingouin
==> 3 bitboards pour les poissons
Bitboards Points : {
1POISSON
2POISSONS
3POISSONS
}
=> 1POISSON|2POISSONS|3POISSONS = BITB_TROUS (0=trou)
Bitboard obstacles {
1 s'il y a un obstacle
0 sinon
}
==> ~Bitboard trous (OR 1 << Pos. pingouin1) (OR 1 << Pos. pingouin2)...(OR 1 << Pos. pingouin8)