5 Commits

Author SHA1 Message Date
f59f9975fa c'est le désespoir 2026-02-06 01:27:28 +01:00
aa2dbc0c87 ajout bot 2026-02-05 18:03:16 +01:00
0df6b74d54 corrections monte_carlo 2026-02-05 17:59:42 +01:00
vaisse
4b2b37a04a j'ai écrit des trucs, mais il faut encore tester 2026-02-03 11:54:49 +01:00
2dfc6014e0 Merge pull request 'AUTOPLAY' (#13) from AUTOPLAY into master
Reviewed-on: #13
Reviewed-by: Clement JANNAIRE <clement.jannaire@etu.u-pec.fr>
Reviewed-by: Riad KARA-MOSTEFA <riad.kara-mostefa@etu.u-pec.fr>
2026-01-30 09:37:05 +01:00
2 changed files with 177 additions and 5 deletions

View File

@@ -0,0 +1,40 @@
package fr.iut_fbleau.HexGame;
import fr.iut_fbleau.GameAPI.AbstractGamePlayer;
import fr.iut_fbleau.GameAPI.AbstractPly;
import fr.iut_fbleau.GameAPI.IBoard;
import fr.iut_fbleau.GameAPI.Player;
import java.util.ArrayList;
import java.util.Iterator;
import java.util.List;
import java.util.Random;
public class RandomBot extends AbstractGamePlayer {
private final Random rng;
public RandomBot(Player me, Random rng) {
super(me);
this.rng = rng;
}
public RandomBot(Player me, long seed) {
this(me, new Random(seed));
}
@Override
public AbstractPly giveYourMove(IBoard board) {
List<AbstractPly> legal = new ArrayList<>();
Iterator<AbstractPly> it = board.iterator();
while (it.hasNext()) {
legal.add(it.next());
}
if (legal.isEmpty()) {
throw new IllegalStateException("No legal move available (board is full?)");
}
return legal.get(rng.nextInt(legal.size()));
}
}

View File

@@ -3,6 +3,7 @@ package fr.iut_fbleau.HexGame;
import fr.iut_fbleau.GameAPI.*;
import java.util.EnumMap;
import java.util.LinkedList;
import java.util.Random;
public class Simulation extends AbstractGame {
@@ -10,7 +11,8 @@ public class Simulation extends AbstractGame {
//ATTRIBUTS
private HexPly bestmove;
private float bestoutcome;
private int MAXDEPTH = 6;
private int MAXDEPTH = 9;
private int EVALDEPTH = 10;
private LinkedList<Integer[]> taken = new LinkedList<Integer[]>();
//ATTRIBUTS QUE JE NE VOUDRAIS PAS CRÉER IDÉALEMENT
@@ -25,13 +27,52 @@ public class Simulation extends AbstractGame {
}
//METHODES
/*Le jeu de Hex ne peut jamais finir avec le résultat null. En utilisant cette propriété, on peut avoir cet algorithme simplifié du monte-carlo*/
private float MonteCarlo(HexBoard position, Player current){
RandomBot simplay = new RandomBot(current, new Random().nextLong());
HexBoard simpos = position;
LinkedList<Integer[]> ctaken = taken;
HexPly testmove;
float wins = 0;
float losses = 0;
int count = 0;
for(int i=0; i<EVALDEPTH; i++){
while(!simpos.isGameOver()){
count++;
testmove = (HexPly) simplay.giveYourMove(simpos);
if(!ctaken.contains(new Integer[]{testmove.getRow(), testmove.getCol()}) && simpos.isLegal(testmove)){
ctaken.add(new Integer[]{testmove.getRow(), testmove.getCol()});
simpos.doPly(testmove);
if(simpos.getResult()==Result.LOSS){
losses++;
} else if(simpos.getResult()==Result.WIN){
wins++;
}
}
}
//System.out.println("count:"+count);
for (int j=0; j<count; j++) {
simpos.undoPly();
}
ctaken = taken;
count = 0;
}
System.out.println(" wins : "+wins+"/losses : "+losses);
System.out.println(" eval : "+(wins-losses)/EVALDEPTH);
return (wins-losses)/EVALDEPTH;
}
private float explMAX(HexBoard position, int depth){
if (position.getResult()==Result.LOSS) {
return -1.0f;
} else if (position.getResult()==Result.WIN){
return 1.0f;
} else if (depth==MAXDEPTH) {
return 0f;
return MonteCarlo(position, Player.PLAYER1);
} else {
float bestcase = -1.0f;
HexPly bestcasemove;
@@ -73,7 +114,7 @@ public class Simulation extends AbstractGame {
} else if (position.getResult()==Result.WIN){
return 1.0f;
} else if (depth==MAXDEPTH) {
return 0f;
return MonteCarlo(position, Player.PLAYER2);
} else {
float bestcase = 1.0f;
HexPly bestcasemove;
@@ -109,6 +150,97 @@ public class Simulation extends AbstractGame {
}
}
private float explMAXAB(HexBoard position, int depth, float A, float B){
if (position.getResult()==Result.LOSS) {
return -1.0f;
} else if (position.getResult()==Result.WIN){
return 1.0f;
} else if (depth==MAXDEPTH) {
return MonteCarlo(position, Player.PLAYER1);
} else {
float bestcase = A;
HexPly bestcasemove;
HexPly testmove;
for (int i=0; i<position.getSize(); i++) {
for (int j=0; j<position.getSize(); j++) {
if(depth==0){
//System.out.println("MAX New Line :");
}
Integer[] t = new Integer[]{i, j};
testmove = new HexPly(Player.PLAYER1, i, j);
if(!taken.contains(t) && position.isLegal(testmove)){
//System.out.println(" MAX test move : "+Integer.toString(i)+","+Integer.toString(j));
taken.add(t);
position.doPly(testmove);
float val = explMINAB(position, depth+1, bestcase, B);
if (val >= bestcase) {
//System.out.println(" MAX new best case");
bestcase = val;
bestcasemove = testmove;
if (depth==0) {
this.bestoutcome = bestcase;
this.bestmove = bestcasemove;
}
if(bestcase>=B){
return bestcase;
}
}
position.undoPly();
taken.remove(t);
}
}
}
return bestcase;
}
}
private float explMINAB(HexBoard position, int depth, float A, float B){
if (position.getResult()==Result.LOSS) {
return -1.0f;
} else if (position.getResult()==Result.WIN){
return 1.0f;
} else if (depth==MAXDEPTH) {
return MonteCarlo(position, Player.PLAYER2);
} else {
float bestcase = B;
HexPly bestcasemove;
HexPly testmove;
for (int i=0; i<position.getSize(); i++) {
for (int j=0; j<position.getSize(); j++) {
if(depth==0){
//System.out.println("MIN New Line :");
}
Integer[] t = new Integer[]{i, j};
testmove = new HexPly(Player.PLAYER2, i, j);
if(!taken.contains(t) && position.isLegal(testmove)){
//System.out.println(" MIN test move : "+Integer.toString(i)+","+Integer.toString(j));
taken.add(t);
position.doPly(testmove);
float val = explMAXAB(position, depth+1, A, bestcase);
if (val <= bestcase) {
//System.out.println(" MIN new best case");
bestcase = val;
bestcasemove = testmove;
if (depth==0) {
this.bestoutcome = bestcase;
this.bestmove = bestcasemove;
}
if(bestcase<=A){
return bestcase;
}
}
position.undoPly();
taken.remove(t);
}
}
}
return bestcase;
}
}
private AbstractPly GiveBestMove(IBoard board) {
if (!(board instanceof HexBoard)) {
throw new IllegalArgumentException("Ce joueur attend un HexBoard.");
@@ -116,9 +248,9 @@ public class Simulation extends AbstractGame {
HexBoard hb = (HexBoard) board;
float bestcase;
if(hb.getCurrentPlayer()==Player.PLAYER1){
bestcase = explMAX(hb, 0);
bestcase = explMAXAB(hb, 0, -1.0f, 1.0f);
} else {
bestcase = explMIN(hb, 0);
bestcase = explMINAB(hb, 0, -1.0f, 1.0f);
}
return this.bestmove;
}