public class MinimaxAlgorithm implements IAlgorithm{

	@Override
	public Move algorithm(CalculationContext context, Model model, Player whosTurn) {
		if(context == null || model == null) {
			throw new IllegalArgumentException();
		}
		//set initial values to start recursion:
		return minimax(context, model, whosTurn, 0);
	}

	Move minimax(CalculationContext context, Model model, Player whosTurn, int currentDepth) {
		//check if reached target-depth
		if(context.getDepth()==currentDepth){
			Move move = new Move();
			move.setValue(evaluateModel(context, model));
			return move;
		}
		
		//get all possible moves:
		List<Move> successors = getSuccessors(context, model, whosTurn);
		//if there is no possible move, set min or max value
		if(successors.isEmpty()){
			Move move = new Move();
			int value = context.getPlayer() == whosTurn ? Integer.MIN_VALUE : Integer.MAX_VALUE; 
			move.setValue(value);
			return move;
		}
		
		double value = 0;
		Move selectedMove = null;
		for (Move move : successors) {
			model.tryMove(move); // make move
			
			//recursion:
			Move minimax = minimax(context, model, whosTurn.opposite(), currentDepth+1);
			if(selectedMove == null                                                 //to set initial move
				|| (context.getPlayer() == whosTurn && minimax.getValue()> value)   //max value is desired for computer
				|| (context.getPlayer() != whosTurn && minimax.getValue()< value)){ //min value is desired for opponent
				
				value = minimax.getValue();
				move.next = minimax;
				selectedMove = move;
			}
			
			model.undoTryMove(move); // remove move back
		}
		selectedMove.setValue(value);
		return selectedMove;
	}

	private double evaluateModel(CalculationContext context, Model model) {
		IEvaluation evaluationFunction = context.getEvaluationFunction();
		return evaluationFunction.evaluate(model,context.getPlayer());
	}
	
	private List<Move> getSuccessors(CalculationContext context, Model model, Player whosTurn) {
		ISuccessor successor = context.getSuccessorFunction();
		List<Move> successors = successor.getSuccessors(model, whosTurn);
		return successors;
	}

	@Override
	public String getName() {
		return "Min-Max Algorithm";
	}

} public class CalculationContext{

	private int depth;
	private Player player;
	private IEvaluation evaluationFunction;
	private ISuccessor successorFunction;
	private IAlgorithm algorithm;


	public void setDepth(int depth) {
		this.depth = depth;
	}

	public int getDepth() {
		return depth;
	}

	public void setEvaluationFunction(IEvaluation evaluation) {
		this.evaluationFunction = evaluation;
	}

	public IEvaluation getEvaluationFunction() {
		return evaluationFunction;
	}

	public Player getPlayer() {
		return player;
	}

	public void setPlayer(Player player) {
		this.player = player;
	}

	public void setSuccessorFunction(ISuccessor successor) {
		this.successorFunction = successor;
	}

	public ISuccessor getSuccessorFunction() {
		return successorFunction;
	}

	public void setAlgorithm(IAlgorithm algorithm) {
		this.algorithm = algorithm;
	}

	public IAlgorithm getAlgorithm() {
		return algorithm;
	}

}
 public class Model {
	
	public SquareState state[][];
	private GameCenter callBack;

	public void baslat(){
		SquareState ilk[][] = {
				{SquareState.WHITE,SquareState.BLANK,SquareState.WHITE,SquareState.BLANK,SquareState.WHITE,SquareState.BLANK,SquareState.WHITE,SquareState.BLANK},
				{SquareState.BLANK,SquareState.WHITE,SquareState.BLANK,SquareState.WHITE,SquareState.BLANK,SquareState.WHITE,SquareState.BLANK,SquareState.WHITE},
				{SquareState.WHITE,SquareState.BLANK,SquareState.WHITE,SquareState.BLANK,SquareState.WHITE,SquareState.BLANK,SquareState.WHITE,SquareState.BLANK},
				{SquareState.BLANK,SquareState.BLANK,SquareState.BLANK,SquareState.BLANK,SquareState.BLANK,SquareState.BLANK,SquareState.BLANK,SquareState.BLANK},
				{SquareState.BLANK,SquareState.BLANK,SquareState.BLANK,SquareState.BLANK,SquareState.BLANK,SquareState.BLANK,SquareState.BLANK,SquareState.BLANK},
				{SquareState.BLANK,SquareState.BLACK,SquareState.BLANK,SquareState.BLACK,SquareState.BLANK,SquareState.BLACK,SquareState.BLANK,SquareState.BLACK},
				{SquareState.BLACK,SquareState.BLANK,SquareState.BLACK,SquareState.BLANK,SquareState.BLACK,SquareState.BLANK,SquareState.BLACK,SquareState.BLANK},
				{SquareState.BLANK,SquareState.BLACK,SquareState.BLANK,SquareState.BLACK,SquareState.BLANK,SquareState.BLACK,SquareState.BLANK,SquareState.BLACK},
		};
		state = ilk;
	}

	public void bos(){
		SquareState[][] bos = new SquareState[8][8];
		for (int i = 0; i < bos.length; i++) {
			for (int j = 0; j < bos[i].length; j++) {
				bos[i][j] = SquareState.BLANK;
			}
		}
		state = bos;
	}
	
	public void tryMove(Move move) {
		state[move.toX][move.toY]=state[move.fromX][move.fromY];
		state[move.fromX][move.fromY] = SquareState.BLANK;
		if(move.must){
			move.eat = state[(move.toX+move.fromX)/2][(move.toY+move.fromY)/2];
			state[(move.toX+move.fromX)/2][(move.toY+move.fromY)/2] = SquareState.BLANK;
		}
		if(move.toX>move.fromX)
			if(move.toX == 7 && (state[move.toX][move.toY]==SquareState.BLACK || state[move.toX][move.toY]==SquareState.WHITE)){
				state[move.toX][move.toY]=state[move.toX][move.toY].convertKing();
				move.convert = true;
			}
		if(move.toX<move.fromX)
			if(move.toX == 0 && (state[move.toX][move.toY]==SquareState.BLACK || state[move.toX][move.toY]==SquareState.WHITE)){
				state[move.toX][move.toY]=state[move.toX][move.toY].convertKing();
				move.convert = true;
			}
		if(move.nextMustMove != null)
			tryMove(move.nextMustMove);
	}

	public void doMove(Move move) {
		state[move.toX][move.toY]=state[move.fromX][move.fromY];
		state[move.fromX][move.fromY] = SquareState.BLANK;
		if(Math.abs(move.toX-move.fromX)>1){
			move.eat = state[(move.toX+move.fromX)/2][(move.toY+move.fromY)/2];
			state[(move.toX+move.fromX)/2][(move.toY+move.fromY)/2] = SquareState.BLANK;
		}
		if(move.toX>move.fromX)
			if(move.toX == 7 )
				state[move.toX][move.toY]=state[move.toX][move.toY].convertKing();
		if(move.toX<move.fromX)
			if(move.toX == 0 )
				state[move.toX][move.toY]=state[move.toX][move.toY].convertKing();
		if(move.nextMustMove != null)
			doMove(move.nextMustMove);
		else
			callBack.update();
	}
	
	
	public void undoTryMove(Move move) {
		if(move.nextMustMove != null)
			undoTryMove(move.nextMustMove);
		undoTryMoveHelper(move);
	}

	private void undoTryMoveHelper(Move move) {
		state[move.fromX][move.fromY]=state[move.toX][move.toY];
		state[move.toX][move.toY] = SquareState.BLANK;
		if(move.eat != null){
			state[(move.toX+move.fromX)/2][(move.toY+move.fromY)/2] = move.eat;
		}
		if(move.toX>move.fromX)
			if(move.toX == 7 && move.convert)
				state[move.fromX][move.fromY]=state[move.fromX][move.fromY].convertNormal();
		if(move.toX<move.fromX)
			if(move.toX == 0 && move.convert)
				state[move.fromX][move.fromY]=state[move.fromX][move.fromY].convertNormal();
	}
	
	public void setCallback(GameCenter gameCenter){
		this.callBack = gameCenter;
	}
}
 public class Move {
	private double value = Double.NEGATIVE_INFINITY;
	public int fromX;
	public int fromY;
	public int toX;
	public int toY;
	public boolean must = false;
	public SquareState eat;
	public Move next;
	public boolean convert;
	public Move nextMustMove;

	public double getValue() {
		return value;
	}

	public void setValue(double value) {
		this.value = value;
	}

}
 public enum Player {
	WHITE,
	BLACK;

	public Player opposite() {
		return this==WHITE ? BLACK : WHITE;
	}
}
 public class EnhancedWeightenedMenCountEvaluation implements IEvaluation{
	
	/*friendly*/ final static int MEN_WEIGHT = 8;
	/*friendly*/ final static int KING_WEIGHT = 12;
	/*friendly*/ final static int WMEN_WEIGHT = 7;
	/*friendly*/ final static int WKING_WEIGHT = 11;

	@Override
	public double evaluate(Model m, Player player) {
		int count = 0;
		SquareState[][] state = m.state;
		for (int i = 0; i < state.length; i++) {
			for (int j = 0; j < state[i].length; j++) {
				SquareState currentSquare = state[i][j];
				if(currentSquare == null){
					String msg = String.format("Cell [%d,%d] is null", i,j);
					throw new IllegalStateException(msg);
				}
				switch (currentSquare) {
				case BLACK:
					count += MEN_WEIGHT;
					break;
				case KING_BLACK:
					count += KING_WEIGHT;
					break;
				case WHITE:
					count -= WMEN_WEIGHT;
					break;
				case KING_WHITE:
					count -= WKING_WEIGHT;
					break;
				default:
					break;
				}
			}
		}
		return count * (player==Player.BLACK ? 1:-1);
	}

}
 public class ConfigurationModel {

	private List<IAlgorithm> algorithms = new LinkedList<IAlgorithm>();
	{
		algorithms.add(new GreedyAlgorithm());
		algorithms.add(new MinimaxAlgorithm());
		algorithms.add(new AlphaBetaAlgorithm());
	}
	
	private IAlgorithm selectedAlgorithm = null;
	
	private Integer[] depth = new Integer[] {3, 4, 5, 6, 7};
	
	private int selectedDepth = 3;
	
	private List<IEvaluation> evaluations = new LinkedList<IEvaluation>();
	{
		evaluations.add(new MenCountEvaluation());
		evaluations.add(new WeightenedMenCountEvaluation());
		evaluations.add(new RatioWeightenedCountEvaluation());
		evaluations.add(new EnhancedWeightenedMenCountEvaluation());
		evaluations.add(new PlayableWeightenedMenCountEvaluation());
	}
	
	private IEvaluation selectedEvaluation;

	public List<IAlgorithm> getAlgorithms() {
		return algorithms;
	}

	public void setAlgorithms(List<IAlgorithm> algorithms) {
		this.algorithms = algorithms;
	}

	public IAlgorithm getSelectedAlgorithm() {
		return selectedAlgorithm;
	}

	public void setSelectedAlgorithm(IAlgorithm selectedAlgorithm) {
		this.selectedAlgorithm = selectedAlgorithm;
	}
	
	public Integer[] getDepth() {
		return depth;
	}

	public void setDepth(Integer[] depth) {
		this.depth = depth;
	}

	public int getSelectedDepth() {
		return selectedDepth;
	}

	public void setSelectedDepth(int selectedDepth) {
		this.selectedDepth = selectedDepth;
	}

	public List<IEvaluation> getEvaluations() {
		return evaluations;
	}

	public void setEvaluations(List<IEvaluation> evaluations) {
		this.evaluations = evaluations;
	}

	public IEvaluation getSelectedEvaluation() {
		return selectedEvaluation;
	}

	public void setSelectedEvaluation(IEvaluation selectedEvaluation) {
		this.selectedEvaluation = selectedEvaluation;
	}
	
	public String[] getAlgorithmNames(){
		String[] array = new String[algorithms.size()];
		for (int i = 0; i < algorithms.size(); i++) {
			array[i] = algorithms.get(i).getName();
		}
		return array;
	}

	public String[] getEvaluationNames() {
		String[] array = new String[evaluations.size()];
		for (int i = 0; i < evaluations.size(); i++) {
			array[i] = evaluations.get(i).getClass().getSimpleName();
		}
		return array;
	}

	public void setSelectedAlgorithmName(String selectedItem) {
		for (int i = 0; i < algorithms.size(); i++) {
			if(algorithms.get(i).getName().equals(selectedItem)){
				selectedAlgorithm = algorithms.get(i);
				break;
			}
		}
	}

	public void setSelectedEvaluationName(String selectedItem) {
		for (int i = 0; i < evaluations.size(); i++) {
			if(evaluations.get(i).getClass().getSimpleName().equals(selectedItem)){
				selectedEvaluation = evaluations.get(i);
				break;
			}
		}
	}
} @SuppressWarnings("serial")
public class MainView extends JFrame{
	
	public MainView(String title) {
		super(title);
		initGame();
		init();
	}

	private void init() {
		JMenu jmenu = new JMenu("Game");
		
		JMenuItem jMenuItem0 = new JMenuItem("New Game");
		jMenuItem0.addActionListener(new ActionListener(){
			@Override
			public void actionPerformed(ActionEvent event) {
				gameCenter.initNewGame();
			}			
		});
		jmenu.add(jMenuItem0);
		
		JMenuItem jMenuItem1 = new JMenuItem("Configuration");
		jMenuItem1.addActionListener(new ConfigurationItemListener());
		jmenu.add(jMenuItem1);

//		JMenuItem jMenuItem2 = new JMenuItem("Black");
//		jMenuItem2.addActionListener(new ConfigurationItemListener());
//		jmenu.add(jMenuItem2);


		JMenu jmenu2 = new JMenu("About");
		
		JMenuItem jMenuItem3 = new JMenuItem("Pathfinders");
		jMenuItem3.addActionListener(new ActionListener(){
			@Override
			public void actionPerformed(ActionEvent e) {
				String str = "GROUP MEMBERS: \nH. Özge Bacak - e160021@metu.edu.tr\nHacer Çatal - e164175@metu.edu.tr\nYusuf Karagöl - e159582@metu.edu.tr";
				JOptionPane.showMessageDialog(MainView.this, str , "Pathfinders", JOptionPane.INFORMATION_MESSAGE);
			}			
		});
		jmenu2.add(jMenuItem3);
		
		JMenuBar jmenubar = new JMenuBar();
		jmenubar.add(jmenu);
		jmenubar.add(jmenu2);
		
		this.setJMenuBar(jmenubar);
	}


	private class ConfigurationItemListener implements ActionListener{
		@Override
		public void actionPerformed(ActionEvent action) {
			ConfigurationPanel panel = new ConfigurationPanel(MainView.this);
			panel.setConfigurationModel(new ConfigurationModel());
			configurationFrame = new JFrame("Game Configuration");
			configurationFrame.setDefaultCloseOperation(JFrame.DISPOSE_ON_CLOSE);
			configurationFrame.setContentPane(panel);
			configurationFrame.pack();
			configurationFrame.setResizable(false);
			configurationFrame.setVisible(true);
		}
	}
	
	private JFrame configurationFrame;

	private void initGame() {
		gameCenter = new GameCenter();
		try {
			Board board = new Board();
			gameCenter.setBoard(board);
			gameCenter.setCallback(this);
			this.add(board);
		} catch (IOException e) {
			System.err.println(e.getMessage());
			System.exit(-1);
		}
	}

	public static void main(String args[]){
		MainView mainView = new MainView("Pathfinders Checkers");
		mainView.setDefaultCloseOperation(JFrame.EXIT_ON_CLOSE);
		mainView.setResizable(false);
		mainView.setVisible(true);
		mainView.setSize(602,652);
	}
	
	private GameCenter gameCenter;

	public void configurationUpdated(ConfigurationModel newConfigurationModel) {
		gameCenter.configurationChanged(newConfigurationModel);
		if(configurationFrame != null)
			configurationFrame.dispose();
	}

	public void gameFinished(boolean amI) {
		String msg = amI ? "I win!" : "You Win!";
		JOptionPane.showMessageDialog(this, msg , "Game Finished!", JOptionPane.INFORMATION_MESSAGE);
	}
} public class Successors  implements ISuccessor{
	
	@Override
	public List<Move> getSuccessors(Model model, Player player) {
		LinkedList<Move> list = new LinkedList<Move>();
		SquareState[][] state = model.state;
		for (int i=0; i<state.length; i++){
			for (int j=0; j<state[i].length; j++){
				if(state[i][j].owner == player)
					handleStone(list, model, i, j);
			}
		}
		handleList(list);
		return list;
	}

	private boolean handleList(LinkedList<Move> list) {
		boolean hasMust = false;
		for (Move move : list) {
			if(move.must){
				hasMust = true;
				break;
			}
		}
		if(hasMust){
			LinkedList<Move> linkedList = new LinkedList<Move>(list);
			for (Move move : linkedList) {
				if(!move.must){
					list.remove(move);
				}
			}
		}
		return hasMust;
	}
	

	public void handleStone(LinkedList<Move> list, Model model, int i, int j){
		SquareState[][] state = model.state;
		if(state[i][j] == SquareState.BLANK)
			return;
		List<Move> eatList = eatMoveList(model, i, j);
		if(eatList != null && eatList.size()>0){
			list.addAll(eatList);
		}else{
			List<Move> moveList = normalMoveList(model, i, j);
			list.addAll(moveList);
		}
	}

	private List<Move> normalMoveList(Model model, int i, int j) {
		LinkedList<Move> moveList = new LinkedList<Move>();
		SquareState[][] state = model.state;
		SquareState currentSquare = state[i][j];
		Direction[] directions = getDirections(currentSquare);
		for (Direction direction : directions) {
			SquareState next = null;
			int toX = -1, toY = -1;
			switch (direction) {
				case RIGHT_BUTTOM:
					next = rightButtom(state, i, j);
					toX = i-1;
					toY = j+1;
					break;
				case RIGHT_FORWARD:
					next = rightForward(state, i, j);
					toX = i+1;
					toY = j+1;
					break;
				case LEFT_BUTTOM:
					next = leftButtom(state, i, j);
					toX = i-1;
					toY = j-1;
					break;
				case LEFT_FORWARD:
					next = leftForward(state, i, j);
					toX = i+1;
					toY = j-1;
					break;
				default: 
					throw new IllegalStateException("No default value");
			}
			boolean canGo = next==SquareState.BLANK;
			if(canGo){
				Move move = createNormalMove(i, j, toX, toY);
				moveList.add(move);
			}
		}
		
		return moveList;
	}

	//Gelen elemanın (i,j) bir taş olduğunu kabullenir.
	private List<Move> eatMoveList(Model model, int i, int j) {
		LinkedList<Move> eatList = new LinkedList<Move>();
		SquareState[][] state = model.state;
		SquareState currentSquare = state[i][j];
		Direction[] directions = getDirections(currentSquare);
		for (Direction direction : directions) {
			SquareState twoNext = null, next = null;
			int toX = -1, toY = -1;
			switch (direction) {
				case RIGHT_BUTTOM:
					twoNext = twoRightButtom(state, i, j);
					next = rightButtom(state, i, j);
					toX = i-2;
					toY = j+2;
					break;
				case RIGHT_FORWARD:
					twoNext = twoRightForward(state, i, j);
					next = rightForward(state, i, j);
					toX = i+2;
					toY = j+2;
					break;
				case LEFT_BUTTOM:
					twoNext = twoLeftButtom(state, i, j);
					next = leftButtom(state, i, j);
					toX = i-2;
					toY = j-2;
					break;
				case LEFT_FORWARD:
					twoNext = twoLeftForward(state, i, j);
					next = leftForward(state, i, j);
					toX = i+2;
					toY = j-2;
					break;
				default:
					throw new IllegalStateException("No default value");
			}
			if(twoNext != null && next != null){
				boolean canEat = next.owner != null && 
						next.owner != currentSquare.owner && 
						twoNext == SquareState.BLANK;
				if(canEat){
					Move move = createEatMove(i, j, toX, toY);
					model.tryMove(move);
					List<Move> nextList = eatMoveList(model, toX, toY);
					if(nextList != null && nextList.size()>0){
						for (Move nextMove : nextList) {
							Move currentMove = createEatMove(i, j, toX, toY);
							currentMove.nextMustMove = nextMove;
							//currentMove.convert = move.convert;
							eatList.add(currentMove);
						}
					}else{
						Move currentMove = createEatMove(i, j, toX, toY);
						currentMove.nextMustMove = null;
						//currentMove.convert = move.convert;
						eatList.add(currentMove);						
					}
					model.undoTryMove(move);
				}
			}
		}
		return eatList;
	}

	private Move createNormalMove(int i, int j, int toX, int toY) {
		Move move = createMove(i, j, toX, toY);
		move.must = false;
		return move;
	}

	private Move createEatMove(int i, int j, int toX, int toY) {
		Move move = createMove(i, j, toX, toY);
		move.must = true;
		return move;
	}

	private Move createMove(int i, int j, int toX, int toY) {
		Move move = new Move();
		move.fromX = i;
		move.fromY = j;
		move.toX = toX;
		move.toY = toY;
		return move;
	}
	
	private Direction[] getDirections(SquareState squareState) {
		if(squareState.owner == null)
			return null;
		if(squareState.isKing()){
			return kingDirections;
		}
		if(squareState.owner == Player.WHITE){
			return whiteDirections;
		}
		if(squareState.owner == Player.BLACK){
			return blackDirections;
		}
		throw new IllegalStateException("bu durum gerçekleşemez!");
	}

	enum Direction{
		RIGHT_FORWARD,
		LEFT_FORWARD,
		RIGHT_BUTTOM,
		LEFT_BUTTOM
	}
	
	private final static Direction[] kingDirections = Direction.values();
	private final static Direction[] whiteDirections = new Direction[]{Direction.RIGHT_FORWARD, Direction.LEFT_FORWARD};
	private final static Direction[] blackDirections = new Direction[]{Direction.RIGHT_BUTTOM, Direction.LEFT_BUTTOM};
	
	
	//iki sol altın değerini getirir
	private SquareState twoLeftButtom(SquareState[][] state, int i, int j) {
		if(i-2>=0 &&  j-2 >= 0){
			return state[i-2][j-2];
		}
		return null;
	}

	//sol altın değerini getirir
	private SquareState leftButtom(SquareState[][] state, int i, int j) {
		if(i-1>=0 &&  j-1 >= 0){
			return state[i-1][j-1];
		}
		return null;
	}

	//iki sağ altın değerini getirir
	private SquareState twoRightButtom(SquareState[][] state, int i, int j) {
		if(buttomCheck(state, i)){
			return null;
		}
		if( i-2 >= 0 && j+2 < state[i].length){
			return state[i-2][j+2];
		}
		return null;
	}

	//sağ altın değerini getirir
	private SquareState rightButtom(SquareState[][] state, int i, int j) {
		if(buttomCheck(state, i)){
			return null;
		}
		if(i-1>=0 &&  j+1 < state[i].length){
			return state[i-1][j+1];
		}
		return null;
	}

	private SquareState twoRightForward(SquareState[][] state, int i, int j) {
		if( i+2 < state.length && j+2 < state[i].length){
			return state[i+2][j+2];
		}
		return null;
	}
	
	private SquareState twoLeftForward(SquareState[][] state, int i, int j) {
		if( i+2 < state.length && j-2 >= 0){
			return state[i+2][j-2];
		}
		return null;
	}


	//sol önün değerini getirir..
	private SquareState leftForward(SquareState[][] state, int i, int j) {
		if(forwardCheck(state, i)){
			return null;
		}
		if(j-1 >= 0){
			return state[i+1][j-1];
		}
		return null;
	}
	
	//sağ önün değerini getirir..
	private SquareState rightForward(SquareState[][] state, int i, int j) {
		if(forwardCheck(state, i)){
			return null;
		}			
		if(j+1 < state[i].length){
			return state[i+1][j+1];
		}
		return null;
	}

	//ileriye gidebilir mi?
	private boolean forwardCheck(SquareState[][] state, int i) {
		return i+1 >= state.length;
	}
	
	//ileriye gidebilir mi?
	private boolean buttomCheck(SquareState[][] state, int i) {
		return i-1 < 0;
	}
}
 @SuppressWarnings("serial")
public class Board extends JPanel {

	private Image board = null;
	private Image white = null;
	private Image black = null;
	private Image kingWhite = null;
	private Image kingBlack = null;
	
	private Model model;

	public Image getBoard() {
		return board;
	}

	public void setBoard(Image board) {
		this.board = board;
	}

	public Board() throws IOException {
		File f = new File("./img/board.jpg");
		board = ImageIO.read(f);
		
		f = new File("./img/white.gif");
		black = ImageIO.read(f);
		
		f = new File("./img/black.gif");
		white = ImageIO.read(f);
		
		f = new File("./img/kingWhite.gif");
		kingBlack = ImageIO.read(f);
		
		f = new File("./img/kingBlack.gif");
		kingWhite = ImageIO.read(f);
		
		addMouseListener(new BoardMouseListener());
		addMouseMotionListener(new BoardMouseMotionListener());
	}

	@Override
	public void paint(Graphics g) {
		super.paint(g);
		g.drawImage(board, 0, 0, getHeight(), getWidth(), null);
		
		SquareState [][] matrix = model.state;
		
		for (int i = matrix.length-1; i >=0; i--) {
			for (int j = 0; j < matrix[i].length; j++) {
				Image img = null;
				switch(matrix[i][j]){
					case BLACK:
						img = black;
						break;
					case WHITE:
						img = white;
						break;
					case KING_BLACK:
						img = kingBlack;
						break;
					case KING_WHITE:
						img = kingWhite;
						break;
				}
				if(img != null){
					double p = getHeight() / 8;
					g.drawImage(img, (int)(p*j+p*0.15), (int)(p*(7-i)+p*0.15), (int)(p*0.7), (int)(p*0.7), null);
				}
			}
		}
	}
	
	private class BoardMouseListener implements MouseListener{

		@Override
		public void mouseClicked(MouseEvent event) {
			// TODO Auto-generated method stub
		}

		@Override
		public void mouseEntered(MouseEvent event) {
			// TODO Auto-generated method stub			
		}

		@Override
		public void mouseExited(MouseEvent event) {
			// TODO Auto-generated method stub			
		}
		
		private int _x,_y;
		private LinkedList<Move> possibleMoves;

		@Override
		public void mousePressed(MouseEvent event) {
			double width = Board.this.getWidth();
			double height = Board.this.getHeight();
			
			int x = (int)(event.getX() / (width / 8)) + 1;
			int y = (int)((height - event.getY()) / (height/ 8)) + 1;
			
			//System.err.println("Su noktada basildi:"+ x + " - " + y);
			
			_x=x;
			_y=y;
			
			Successors successors = new Successors();
			LinkedList<Move> moves = new LinkedList<Move>();
			successors.handleStone(moves, model, _y-1, _x-1);
			possibleMoves = moves;
		}

		@Override
		public void mouseReleased(MouseEvent event) {
			if(possibleMoves.size()==0)
				return;
			double width = Board.this.getWidth();
			double height = Board.this.getHeight();
			
			int x = (int)(event.getX() / (width / 8)) + 1;
			int y = (int)((height - event.getY()) / (height/ 8)) + 1;
			
			//System.err.println("Su noktada birakildi:"+ x + " - " + y);
			Move currentMove = null;
			for (Move move : possibleMoves) {
				if(move.toX == y-1 && move.toY == x-1){
					currentMove = move;
					break;
				}
			}
//			Move move  = new Move();
//			move.fromX = _y-1;
//			move.fromY = _x-1;
//			move.toX = y-1;
//			move.toY = x-1;
//			if(move.fromX == move.toX && move.fromY == move.toY)
//				return;
			if(currentMove==null)
				return;
			model.doMove(currentMove);
		}
		
	}
	
	private class BoardMouseMotionListener implements MouseMotionListener{

		@Override
		public void mouseDragged(MouseEvent arg0) {
			// TODO Auto-generated method stub
			
		}

		@Override
		public void mouseMoved(MouseEvent arg0) {
			// TODO Auto-generated method stub
			
		}
		
	}
	
//	public static Board init(Model model) throws IOException {
//		Board b = new Board();
//		b.model = model;
//		JFrame frame = new JFrame();
//		frame.setDefaultCloseOperation(JFrame.EXIT_ON_CLOSE);
//		frame.setBounds(2, 2, 610, 636);
//		frame.add(b);
//		frame.setResizable(false);
//		frame.setVisible(true);
//		return b;
//	}

	public void setModel(Model model) {
		this.model = model;
	}
}

import java.util.List;
import checkers.algorithm.MinimaxAlgorithm;
import checkers.domain.CalculationContext;
import checkers.domain.Model;
import checkers.domain.Move;
import checkers.domain.Player;
import checkers.evaluation.EnhancedWeightenedMenCountEvaluation;
import checkers.gui.ConfigurationModel;
import checkers.gui.MainView;
import checkers.rules.Successors;
import checkers.sandbox.Board;
package checkers.controller;



/**
 * Oyuna ait tüm bilgileri tutan kesim. 
 * 
 */
public class GameCenter {
	
	/**
	 * Oyunun tahtası
	 */
	private Model model;

//	/**
//	 * Tahtada yapılan değişiklikleri dinleyecek sınıflar
//	 */
//	private List<ModelListener> listeners = new LinkedList<ModelListener>();

	private Engine blackPlayer;
	
	//private Engine whitePlayer;

	private Board board;

	private boolean lock=true;
	
//	public void center(){
//		while(true){
//			//whitePlayer.playTurn(model);
//			while(lock){
//				try {
//					Thread.sleep(50);
//				} catch (InterruptedException e) {
//					// TODO Auto-generated catch block
//					e.printStackTrace();
//				}
//			}
//			blackPlayer.playTurn(model);
//		}
//	}
	
	public void update(){
		if(gameFinished)
			return;
		lock=!lock;
		if(!lock){
			List<Move> listBlack = successors.getSuccessors(model, Player.BLACK);