package org.darkhelm.dragonchess.server.piece;
import java.util.ArrayList;
import java.util.List;
import org.darkhelm.dragonchess.server.board.BoardDef;
import org.darkhelm.dragonchess.server.board.BoardPiece;
import org.darkhelm.dragonchess.server.board.BoardSet;
import org.darkhelm.dragonchess.shared.Position;
import org.darkhelm.dragonchess.shared.enums.Boards;
import org.darkhelm.dragonchess.shared.enums.MoveTypes;
import org.darkhelm.dragonchess.shared.enums.Teams;
import org.darkhelm.dragonchess.shared.pieces.Move;
/**
* Contains a single move a piece can perform.
*
* @author Xlorep DarkHelm
*
*/
public class UnblockableMove extends PieceMove {
private int board;
private int horiz;
private int vert;
public UnblockableMove() {
this(0, 0, 0, MoveTypes.MOVE);
}
public UnblockableMove(int board, int horiz, int vert, MoveTypes type) {
setBoard(board);
setHoriz(horiz);
setVert(vert);
setType(type);
}
public UnblockableMove clone() {
return new UnblockableMove(getBoard(), getHoriz(), getVert(), getType());
}
/**
* @return the change in boards this move causes the piece to do. Negative
* means go down boards, positive means go up boards.
*/
public int getBoard() {
return board;
}
/**
* @param board
* the change in boards for the piece that this move performs.
* Negative means go down boards, positive means go up boards.
*/
private void setBoard(int board) {
this.board = board;
}
/**
* @return the change horizontally (left - right) this move causes the piece
* to do. Negative means go left, positive means go right.
*/
public int getHoriz() {
return horiz;
}
/**
* @param horiz
* the horizontal (left - right) change for the piece that this
* move performs. Negative means go left, positive means go
* right.
*/
private void setHoriz(int horiz) {
this.horiz = horiz;
}
/**
* @return the change vertically (toward or away from your side's home on a
* single board) this move causes the piece to do. Negative means go
* down (toward your side's home), positive means go up (away from
* your side's home).
*/
public int getVert() {
return vert;
}
/**
* @param vert
* the vertical (toward or away from your side's home on a single
* board) change for the piece that this move performs. Negative
* means go down (toward your side's home), positive means go up
* (away from your side's home).
*/
private void setVert(int vert) {
this.vert = vert;
}
/*
* (non-Javadoc)
*
* @see java.lang.Object#hashCode()
*/
@Override
public int hashCode() {
final int prime = 31;
int result = 1;
result = prime * result + getBoard();
result = prime * result + getHoriz();
result = prime * result
+ ((getType() == null) ? 0 : getType().hashCode());
result = prime * result + getVert();
return result;
}
/*
* (non-Javadoc)
*
* @see java.lang.Object#equals(java.lang.Object)
*/
@Override
public boolean equals(Object obj) {
if (this == obj)
return true;
if (obj == null)
return false;
if (getClass() != obj.getClass())
return false;
UnblockableMove other = (UnblockableMove) obj;
if (getBoard() != other.getBoard())
return false;
if (getHoriz() != other.getHoriz())
return false;
if (getType() != other.getType())
return false;
if (getVert() != other.getVert())
return false;
return true;
}
public List<Position> getFreeze(Teams team, BoardDef board,
int horizPos, int vertPos) {
List<Position> ret = new ArrayList<Position>();
// Only for the FREEZE move type.
if (getType() != MoveTypes.FREEZE) {
return ret;
}
// Define variables.
int horizDest = getHoriz() + horizPos;
int vertDest = team.side(getVert()) + vertPos;
int boardMove = board.getType().ordinal() - getBoard();
int score = 0;
// All moves must actually go to somewhere on the board set.
if (!Boards.inRange(boardMove, horizDest, vertDest)) {
return ret;
}
// Clone the current board set for this move.
BoardSet set = board.getSet().clone();
// Figure out which board the move is going to.
BoardDef boardDest = set.getBoard(Boards.values()[boardMove]);
// Check what is at the destination.
BoardPiece destPiece = boardDest.get(vertDest, horizDest);
// Destination piece is on the same team.
if (destPiece != null && destPiece.getTeam() == team) {
return ret;
// Destination piece is on the other team.
} else if (destPiece != null) {
PieceDef destPieceDef = PieceDef.get(destPiece.getType());
score = destPieceDef.getValue();
}
// If there is a piece that can be "captured" it can be frozen.
if (score > 0) {
ret.add(Position.create(boardDest.getType(), horizDest, vertDest));
}
return ret;
}
private List<Move> getHomeMoves(Teams team, BoardDef board, int horizPos, int vertPos, boolean check) {
List<Move> ret = new ArrayList<Move>();
BoardPiece bPiece = board.get(vertPos, horizPos);
for(Position pos : board.getSet().getHomes(bPiece)) {
long hash = 0;
// Clone the current board set for this move.
BoardSet set = board.getSet().clone();
// Figure out which board the move is going to.
BoardDef boardDest = set.getBoard(pos.getBoard());
// Check what is at the destination.
BoardPiece destPiece = boardDest.get(pos.getVert(), pos.getHoriz());
// If the home position is not empty, skip.
if(destPiece != null) {
continue;
}
// Perform move on cloned board set.
set.move(board.getType(), horizPos, vertPos, pos.getBoard(),
pos.getHoriz(), pos.getVert());
// check validation.
if (!check && set.isCheck(team.other())) {
continue;
}
// get the board set's hash for this move.
hash = set.hash();
// Load the move into the returned array.
ret.add(new Move(hash, 0, pos.getBoard(), pos.getHoriz(), pos.getVert(),
MoveTypes.MOVE));
}
return ret;
}
@Override
protected List<Move> getAllMoves(Teams team, BoardDef board, int horizPos,
int vertPos, boolean check) {
List<Move> ret = new ArrayList<Move>();
// FREEZE moves are not handled here. They are special cases.
if (getType() == MoveTypes.FREEZE) {
return ret;
}
// HOME moves are done differently.
if(getType() == MoveTypes.HOME) {
return getHomeMoves(team, board, horizPos, vertPos, check);
}
// Define variables.
int horizDest = getHoriz() + horizPos;
int vertDest = team.side(getVert()) + vertPos;
int boardMove = board.getType().ordinal() - getBoard();
int score = 0;
long hash = 0;
// All moves must actually go to somewhere on the board set.
if (!Boards.inRange(boardMove, horizDest, vertDest)) {
return ret;
}
// Clone the current board set for this move.
BoardSet set = board.getSet().clone();
// Figure out which board the move is going to.
BoardDef boardDest = set.getBoard(Boards.values()[boardMove]);
// Check what is at the destination.
BoardPiece destPiece = boardDest.get(vertDest, horizDest);
// Destination piece is on the same team.
if (destPiece != null && destPiece.getTeam() == team) {
return ret;
// Destination piece is on the other team.
} else if (destPiece != null) {
PieceDef destPieceDef = PieceDef.get(destPiece.getType());
score = destPieceDef.getValue();
}
// FROM_AFAR only makes sense with capture moves.
if (getType() == MoveTypes.FROM_AFAR && score == 0) {
return ret;
}
// Perform move on cloned board set.
set.move(board.getType(), horizPos, vertPos, boardDest.getType(),
horizDest, vertDest);
// FROM_AFAR doesn't need to worry about check validation.
if (getType() != MoveTypes.FROM_AFAR && !check
&& set.isCheck(team.other())) {
return ret;
}
// get the board set's hash for this move.
hash = set.hash();
MoveTypes type = null;
// Define what the type of the move is.
if (getType() == MoveTypes.FROM_AFAR) {
type = getType();
} else if (score == 0) {
type = MoveTypes.MOVE;
} else {
type = MoveTypes.CAPTURE;
}
// Load the move into the returned array.
ret.add(new Move(hash, score, boardDest.getType(), horizDest, vertDest,
type));
return ret;
}
}