package jadex.bdibpmn.examples.puzzle;
import jadex.commons.SimplePropertyChangeSupport;
import java.beans.PropertyChangeListener;
import java.io.Serializable;
import java.util.ArrayList;
import java.util.Collections;
import java.util.HashMap;
import java.util.List;
/**
* The board containing places, pieces and played moves.
*/
public class Board implements IBoard, Serializable
{
//-------- attributes --------
/** The moves. */
protected ArrayList moves;
/** The pieces. */
protected HashMap pieces;
/** The size. */
protected int size;
/** The hole position. */
protected Position hole_pos;
/** The helper object for bean events. */
//public ConcurrentPropertyChangeSupport pcs;
public SimplePropertyChangeSupport pcs;
//-------- constructors --------
/**
* Create a new board.
*/
public Board()
{
this(5);
}
/**
* Create a new board.
*/
public Board(int size)
{
this.moves = new ArrayList();
this.pieces = new HashMap();
this.size = size;
//this.pcs = new ConcurrentPropertyChangeSupport(this);
this.pcs = new SimplePropertyChangeSupport(this);
// Initialize the board with pieces.
int middle = size/2;
this.hole_pos = new Position(middle, middle);
for(int x=0; x<size; x++)
{
for(int y=0; y<size; y++)
{
if(!(x==middle && y==middle))
{
if(x<=middle && y<=middle)
{
//System.out.println("w: "+x+" "+y+" ");
pieces.put(new Position(x, y), new Piece(true));
}
else if(x>=middle && y>=middle)
{
//System.out.println("b: "+x+" "+y+" ");
pieces.put(new Position(x, y), new Piece(false));
}
}
}
}
}
/**
* Get a piece for a location.
*/
public synchronized Piece getPiece(Position pos)
{
return (Piece)pieces.get(pos);
}
/**
* Get possible moves.
* @return Get all possible move.
*/
public synchronized List getPossibleMoves()
{
List ret = new ArrayList();
int hx = hole_pos.getX();
int hy = hole_pos.getY();
int[] cols = new int[]{-1,-1,1,1,-1,-1,1,1};
Position[] fig_pos = new Position[]{
new Position(hx+1, hy), // b
new Position(hx, hy+1), // b
new Position(hx-1, hy), // w
new Position(hx, hy-1), // w
new Position(hx+2, hy), // b
new Position(hx, hy+2), // b
new Position(hx-2, hy), // w
new Position(hx, hy-2) // w
};
for(int i=0; i<fig_pos.length; i++)
{
int white = cols[i];
boolean jump = i>=fig_pos.length/2;
Piece piece = getPiece(fig_pos[i]);
if(piece!=null)
{
int white_piece = piece.isWhite()?1 : -1;
if(white_piece==white)
{
if(!jump)
{
assert isPossibleMove(new Move(fig_pos[i], hole_pos));
ret.add(new Move(fig_pos[i], hole_pos));
}
else
{
Piece jp = getPiece(fig_pos[i-fig_pos.length/2]);
if(jp!=null && jp.isWhite()!=piece.isWhite())
{
assert isPossibleMove(new Move(fig_pos[i], hole_pos));
ret.add(new Move(fig_pos[i], hole_pos));
}
}
}
}
}
//assert ret.equals(getOldPossibleMoves()):ret+" "+getOldPossibleMoves();
//System.out.println("PosMovs: "+ret);
return ret;
}
/**
* Do a move.
* @param move The move.
*/
public boolean move(Move move)
{
synchronized(this)
{
if(!isPossibleMove(move))
return false;
Piece piece = getPiece(move.getStart());
pieces.remove(move.getStart());
pieces.put(move.getEnd(), piece);
moves.add(move);
hole_pos = move.getStart();
}
// Fire property change outside of synchronization to avoid deadlocks.
// pcs.firePropertyChange(MOVE, null, move);
pcs.firePropertyChange("solution", null, move); // Hack!!! Change for every move required for GUI.
return true;
}
/**
* Takeback a move.
*/
public boolean takeback()
{
Move move;
synchronized(this)
{
if(moves.size()==0)
return false;
move = (Move)moves.get(moves.size()-1);
Piece piece = getPiece(move.getEnd());
pieces.remove(move.getEnd());
pieces.put(move.getStart(), piece);
moves.remove(moves.size()-1);
hole_pos = move.getEnd();
}
// Fire property change outside of synchronization to avoid deadlocks.
// pcs.firePropertyChange(TAKEBACK, null, move);
pcs.firePropertyChange("solution", null, move); // Hack!!! Change for every move required for GUI.
return true;
}
/**
* Test if it is a solution.
* @return True, if solution.
*/
public synchronized boolean isSolution()
{
int middle = size/2;
if(!isFreePosition(new Position(middle, middle)))
return false;
boolean ret = true;
for(int y=0; y<size && ret; y++)
{
for(int x=0; x<size && ret; x++)
{
if(!(x==middle && y==middle))
{
if(x<=middle && y<=middle && getPiece(new Position(x, y)).isWhite())
ret = false;
else if(x>=middle && y>=middle && !getPiece(new Position(x, y)).isWhite())
ret = false;
}
}
}
return ret;
}
/**
* Get all moves made so far.
*/
public synchronized List getMoves()
{
return Collections.unmodifiableList(moves);
}
/**
* Get all moves made so far.
*/
public synchronized Move getLastMove()
{
return moves.size()>0? (Move)moves.get(moves.size()-1): null;
}
/**
* Test if the last move was with a white piece.
* When no move was made, it return true.
* @return True, is last move was with white piece.
*/
public synchronized boolean wasLastMoveWhite()
{
boolean ret = true;
if(moves.size()>0)
{
Move last = (Move)moves.get(moves.size()-1);
ret = getPiece(last.getEnd()).isWhite();
}
return ret;
}
/**
* Test if aposition is free.
*/
public synchronized boolean isFreePosition(Position pos)
{
int middle = size/2;
int x = pos.getX();
int y = pos.getY();
// There is no piece on the square and the square is
// on the board and it is no forbidden position.
return pieces.get(pos)==null
&& (x>=0 && y>=0 && x<size && y<size)
&& (x<=middle && y<=middle || x>=middle && y>=middle);
}
/**
* Get a piece for a location.
*/
protected boolean isPossibleMove(Move move)
{
// Check if on start position is a piece.
// Check if the end position is free.
Piece piece = getPiece(move.getStart());
if(piece==null || !isFreePosition(move.getEnd()))
return false;
int turn = piece.isWhite()? 1: -1;
int xs = move.getStart().getX();
int ys = move.getStart().getY();
int xe = move.getEnd().getX();
int ye = move.getEnd().getY();
// Check if normal move and check if jump move.
boolean normalmove = ((xe-xs)*turn==1 && ye-ys==0) || ((ye-ys)*turn==1 && xe-xs==0);
Position xin = new Position(xs+turn, ys);
Position yin = new Position(xs, ys+turn);
boolean jumpmove = ((xe-xs)*turn==2 && ye-ys==0 && !isFreePosition(xin) && getPiece(xin).isWhite()!=piece.isWhite())
|| ((ye-ys)*turn==2 && xe-xs==0 && !isFreePosition(yin) && getPiece(yin).isWhite()!=piece.isWhite());
if(!normalmove && !jumpmove)
return false;
/*if(!(((xe-xs)*turn==1 && ye-ys==0) || ((ye-ys)*turn==1 && xe-xs==0))
&& !(((xe-xs)*turn==2 && ye-ys==0 && isFreePosition(new Position(xs+turn, ys)))
|| ((ye-ys)*turn==2 && xe-xs==0 && isFreePosition(new Position(xs, ys+turn)))))
return false;*/
return true;
}
/**
* Get the board size.
*/
public int getSize()
{
return size;
}
/**
* Get the current board position.
*/
public synchronized List getCurrentPosition()
{
List ret = new ArrayList();
for(int y=0; y<size; y++)
{
for(int x=0; x<size; x++)
{
ret.add(getPiece(new Position(x, y)));
}
}
return ret;
}
/**
* Get the string representation.
* @return The string representation.
* /
public String toString()
{
StringBuffer sbuf = new StringBuffer();
for(int y=0; y<size; y++)
{
for(int x=0; x<size; x++)
{
sbuf.append("x="+x+" y="+y+" :"+getPiece(new Position(x, y)));
}
}
return sbuf.toString();
}*/
//-------- property methods --------
/**
* Add a PropertyChangeListener to the listener list.
* The listener is registered for all properties.
* @param listener The PropertyChangeListener to be added.
*/
public void addPropertyChangeListener(PropertyChangeListener listener)
{
pcs.addPropertyChangeListener(listener);
}
/**
* Remove a PropertyChangeListener from the listener list.
* This removes a PropertyChangeListener that was registered
* for all properties.
* @param listener The PropertyChangeListener to be removed.
*/
public void removePropertyChangeListener(PropertyChangeListener listener)
{
pcs.removePropertyChangeListener(listener);
}
/**
* Main for testing.
*/
public static void main(String[] args)
{
Board board = new Board(5);
//System.out.println(board);
List moves = board.getPossibleMoves();
System.out.println(moves);
board.move((Move)moves.get(0));
moves = board.getPossibleMoves();
System.out.println(moves);
board.move((Move)moves.get(0));
System.out.println(board.isPossibleMove(new Move(new Position(2, 0), new Position(2, 2))));
System.out.println(board.isPossibleMove(new Move(new Position(4, 2), new Position(5,2))));
board.move((Move)moves.get(0));
System.out.println(board.getPossibleMoves());
}
}