package checkers;
import java.awt.EventQueue;
import java.awt.Point;
import java.awt.event.MouseEvent;
import java.awt.event.MouseListener;
import java.awt.event.MouseMotionListener;
import java.util.LinkedList;
import java.util.List;
/**
* handles board events, human and AI moves, delivers events to BoardListeners
*/
public class BoardController
{
private class BoardMouseAdapter implements MouseListener, MouseMotionListener
{
@Override
public void mousePressed(MouseEvent e)
{
if(e.getButton() == MouseEvent.BUTTON1 && isHumanMove())
{
int x = e.getX() / 32;
int y = e.getY() / 32;
if(getBoard().inBounds(x, y) && getBoard().getPlayer(x, y) == getBoard().turnHolder)
{
view.currentMove = new BoardView.CurrentMoveState();
view.currentMove.piece = new Point(x, y);
view.currentMove.position = e.getPoint();
view.currentMove.offset = new Point(x * 32 - view.currentMove.position.x, y * 32 - view.currentMove.position.y);
view.currentMove.possibleMoves = getBoard().getMoves(view.currentMove.piece);
view.repaint();
}
}
}
@Override
public void mouseReleased(MouseEvent e)
{
if(e.getButton() == MouseEvent.BUTTON1 && isHumanMove() && view.currentMove != null)
{
int x = (e.getX() + view.currentMove.offset.x + 16) / 32;
int y = (e.getY() + view.currentMove.offset.y + 16) / 32;
Move move = getBoard().getMove(view.currentMove.piece, new Point(x, y));
if(move != null)
makeMove(move);
else
view.currentMove = null;
view.repaint();
}
}
@Override
public void mouseMoved(MouseEvent e)
{
}
@Override
public void mouseClicked(MouseEvent e)
{
}
@Override
public void mouseEntered(MouseEvent e)
{
}
@Override
public void mouseExited(MouseEvent e)
{
}
@Override
public void mouseDragged(MouseEvent e)
{
if(isHumanMove() && view.currentMove != null)
{
view.currentMove.position.setLocation(e.getX(), e.getY());
view.repaint();
}
}
}
private final Player[] players = new Player[] { new HumanPlayer(), new HumanPlayer() };
private final BoardView view;
private Thread backgroundThread;
private final List<BoardListener> boardListeners = new LinkedList<BoardListener>();
public BoardController(BoardView view)
{
this.view = view;
BoardMouseAdapter mouse_adapter = new BoardMouseAdapter();
view.addMouseListener(mouse_adapter);
view.addMouseMotionListener(mouse_adapter);
}
public Board getBoard()
{
return view.getBoard();
}
public boolean isHumanMove()
{
return getCurrentPlayer().isHuman();
}
private Player getCurrentPlayer()
{
return players[getBoard().turnHolder > 0 ? 1 : 0];
}
void requestMove()
{
interruptBackgroundThread();
if(isHumanMove())
return;
if(getBoard().getMoves().isEmpty())
return;
backgroundThread = new Thread(new Runnable()
{
@Override
public void run()
{
Move move = getCurrentPlayer().getMove(getBoard());
view.animateMove(move);
makeMove(move);
}
});
backgroundThread.start();
}
void makeMove(final Move move)
{
for(BoardListener listener : boardListeners)
{
listener.onMove(getBoard(), move);
}
getBoard().makeMove(move);
view.repaint();
EventQueue.invokeLater(new Runnable()
{
@Override
public void run()
{
requestMove();
}
});
}
private void interruptBackgroundThread()
{
if(backgroundThread != null)
{
try
{
backgroundThread.interrupt();
backgroundThread.join();
}
catch(InterruptedException e)
{
throw new Error(e);
}
}
}
public void newGame()
{
if(backgroundThread != null)
interruptBackgroundThread();
view.setBoard(new Board());
for(BoardListener listener : boardListeners)
{
listener.onNewGame(getBoard());
}
}
public void setPlayer(int id, Player player)
{
boolean repeatRequestMove = isHumanMove();
players[(id + 1) / 2] = player;
if(repeatRequestMove)
requestMove();
}
public void addBoardListener(BoardListener listener)
{
boardListeners.add(listener);
}
}