package jadex.bdi.examples.puzzle;
import jadex.commons.SimplePropertyChangeSupport;
import java.beans.PropertyChangeListener;
import java.io.Serializable;
import java.util.ArrayList;
import java.util.List;
import java.util.Vector;
/**
* The View Board represents the puzzle board and the pegs.
*/
public class JackBoard implements IBoard, Serializable
{
protected Piece white_piece = new Piece(true);
protected Piece black_piece = new Piece(false);
protected ArrayList moves = new ArrayList();
public SimplePropertyChangeSupport pcs = new SimplePropertyChangeSupport(this);
/**
* Get a piece for a location.
*/
public Piece getPiece(Position pos)
{
int piece = get(pos.getX(), pos.getY());
if(piece==1)
return white_piece;
else if(piece==-1)
return black_piece;
else
return null;
}
/**
* Get possible moves.
* @return Get all possible move.
*/
public List getPossibleMoves()
{
List ret = new ArrayList();
List ts = moves(the_hole);
for(int i = 0; i<ts.size(); i++)
ret.add(new Move((Position)ts.get(i), the_hole));
return ret;
}
/**
* Do a move.
* @param move The move.
*/
public boolean move(Move move)
{
// todo: check?
int p = get(move.getStart());
set(0, move.getStart());
the_hole = move.getStart();
set(p, move.getEnd());
moves.add(move);
pcs.firePropertyChange("solution", null, move);
// pcs.firePropertyChange(IBoard.MOVE, null, move);
return true;
}
/**
* Takeback a move.
*/
public boolean takeback()
{
if(moves.size()==0)
return false;
Move move = (Move)moves.get(moves.size()-1);
int p = get(move.getEnd());
set(p, move.getStart());
set(0, move.getEnd());
the_hole = move.getEnd();
moves.remove(moves.size()-1);
pcs.firePropertyChange("solution", null, move);
// pcs.firePropertyChange(IBoard.TAKEBACK, null, move);
return true;
}
/**
* Test if it is a solution.
* @return True, if solution.
*/
public boolean isSolution()
{
return solution();
}
/**
* Get all moves made so far.
*/
public List getMoves()
{
return moves;
}
/**
* Get all moves made so far.
*/
public 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 boolean wasLastMoveWhite()
{
Move move = getLastMove();
return move==null || get(move.getEnd())==1;
}
/**
* Get the board size.
*/
public int getSize()
{
return 5;
}
/**
* Get the current board position.
*/
public List getCurrentPosition()
{
List ret = new ArrayList();
for(int y=0; y<5; y++)
{
for(int x=0; x<5; x++)
{
ret.add(getPiece(new Position(x, y)));
}
}
return ret;
}
/**
* Test if a position is free.
*/
public boolean isFreePosition(Position pos)
{
int x = pos.getX();
int y = pos.getY();
return get(x,y)==0;
}
/**
* The int [][] board represents the game board, with 0 marking
* the hole, and 4 marking out-of-limit coordinates. Otherwise
* there are "1" pieces and "-1" pieces. Note that we don't
* distinguish pieces individually in this representation.
*/
int[][] board = {
{
1,
1,
1,
4,
4},
{
1,
1,
1,
4,
4},
{
1,
1,
0,
-1,
-1},
{
4,
4,
-1,
-1,
-1},
{
4,
4,
-1,
-1,
-1}};
int last = 4;
Position the_hole = new Position(2, 2);
/**
* The static int [][] move_check_table represents available
* moves, as coordinate offsets and piece colour. E.g., with the
* hole in <x:y>, then a "-1" piece in <x+1:y> is eligible, as is
* a "-1" piece in <x+2,y> if there also is a "1" piece in
* <x+1:y>.
*/
// x, y, piece_col
static int[][] move_check_table = {
{
1,
0,
-1},
{
0,
1,
-1},
{
-1,
0,
1},
{
0,
-1,
1},
{
2,
0,
-1,
1,
0,
1},
{
0,
2,
-1,
0,
1,
1},
{
-2,
0,
1,
-1,
0,
-1},
{
0,
-2,
1,
0,
-1,
-1}};
/**
* The moves() method computes possible moves to <x:y>,
* represented by the Positiones of pieces to move.
*/
Vector moves(int x, int y)
{
Vector v = new Vector();
for(int i = 0; (i<move_check_table.length); i++)
check(v, move_check_table[i], x, y)
;
return v;
}
/**
* The check() method processes a move_check_table entry, and adds
* a Position to the Vector when the entry applies.
*/
void check(Vector v, int[] m, int x, int y)
{
int x1 = (x+m[0]);
int y1 = (y+m[1]);
if((get(x1, y1)==m[2]))
{
if(((m.length==3) || (get((x+m[3]), (y+m[4]))==m[5])))
{
Position s = new Position(x1, y1);
v.add(s);
}
}
}
int get(int x, int y)
{
if(((((x<0) || (x>= 5)) || (y<0)) || (y>= 5)))
return 4;
return board[x][y];
}
int get(Position s)
{
return get(s.x, s.y);
}
void set(int v, int x, int y)
{
board[x][y] = v;
}
void set(int v, Position s)
{
set(v, s.x, s.y);
}
boolean solution()
{
if((board[2][2]!=0))
return false;
for(int i = 0; (i<3); i++)
{
for(int j = 0; (j<3); j++)
{
if((board[i][j]>0))
return false;
}
}
return true;
}
Vector moves(Position hole)
{
return moves(hole.x, hole.y);
}
boolean isJumpMove(int x, int y)
{
int dx = Math.abs((the_hole.x-x));
int dy = Math.abs((the_hole.y-y));
return ((dx==2) || (dy==2));
}
boolean isJumpMove(Position s)
{
return isJumpMove(s.x, s.y);
}
//-------- 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);
}
}