package fr.iut_fbleau.HexGame; import fr.iut_fbleau.GameAPI.*; import java.util.EnumMap; import java.util.LinkedList; public class Simulation extends AbstractGame { //ATTRIBUTS private HexPly bestmove; private float bestoutcome; private int MAXDEPTH = 9; private int EVALDEPTH = 10; private LinkedList taken = new LinkedList(); //ATTRIBUTS QUE JE NE VOUDRAIS PAS CRÉER IDÉALEMENT private IBoard simCurrentBoard; private EnumMap simmapPlayers; //CONSTRUCTEUR public Simulation(IBoard b, EnumMap m){ super(b, m); simCurrentBoard = b; simmapPlayers = m; } //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){ RandomBot simplay = new RandomBot(); HexBoard simpos = position.safeCopy(); LinkedList ctaken = taken; HexPly testmove; float wins = 0; float losses = 0; for(int i=0; i=losses){ return losses/wins; } else { return -(wins/losses); } } 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 MonteCarlo(position); } else { float bestcase = -1.0f; HexPly bestcasemove; HexPly testmove; for (int i=0; i= bestcase) { //System.out.println(" MAX new best case"); bestcase = val; bestcasemove = testmove; if (depth==0) { this.bestoutcome = bestcase; this.bestmove = bestcasemove; } } position.undoPly(); taken.remove(t); } } } return bestcase; } } private float explMIN(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 MonteCarlo(position); } else { float bestcase = 1.0f; HexPly bestcasemove; HexPly testmove; for (int i=0; i= 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); } 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."); } HexBoard hb = (HexBoard) board; float bestcase; if(hb.getCurrentPlayer()==Player.PLAYER1){ bestcase = explMAXAB(hb, 0, -1.0f, 1.0f); } else { bestcase = explMINAB(hb, 0, -1.0f, 1.0f); } return this.bestmove; } @Override public Result run(){ while(!simCurrentBoard.isGameOver()) { AbstractGamePlayer player = simmapPlayers.get(simCurrentBoard.getCurrentPlayer()); IBoard board = simCurrentBoard.safeCopy(); AbstractPly ply = GiveBestMove(board); HexPly concretePly = (HexPly) ply; if (simCurrentBoard.isLegal(ply)) { simCurrentBoard.doPly(ply); taken.add(new Integer[]{concretePly.getRow(), concretePly.getCol()}); System.out.println("Player "+player+" goes ("+concretePly.getRow()+","+concretePly.getCol()+")"); } else throw new IllegalStateException("Player "+ player + " is a bloody cheat. He tried playing : "+concretePly.getRow()+","+concretePly.getCol()+" I give up."); } return simCurrentBoard.getResult(); } }