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.enums.Boards;
import org.darkhelm.dragonchess.shared.enums.Directions;
import org.darkhelm.dragonchess.shared.enums.MoveTypes;
import org.darkhelm.dragonchess.shared.enums.Teams;
import org.darkhelm.dragonchess.shared.pieces.Move;
/**
* Schema fragment(s) for this class:
*
* <pre>
* <xs:complexType xmlns:ns="http://dragonchess.darkhelm.org/xml/schema/piece_data.xsd" xmlns:xs="http://www.w3.org/2001/XMLSchema" name="blockable-move">
* <xs:attribute type="ns:blockable-direction" use="required" name="dir"/>
* <xs:attribute type="xs:int" default="1" name="dist"/>
* <xs:attribute type="ns:blockable-move-type" use="optional" default="MOVE_CAPTURE" name="type"/>
* <xs:attribute type="ns:blockable-diagonal-check" name="check"/>
* </xs:complexType>
* </pre>
*/
public class BlockableMove extends PieceMove {
private Directions dir;
private int dist;
private Directions check;
public BlockableMove() {
this(null, 0, null, null);
}
public BlockableMove(Directions dir, int dist, MoveTypes type,
Directions check) {
setDir(dir);
setDist(dist);
setType(type);
setCheck(check);
}
public BlockableMove clone() {
return new BlockableMove(getDir(), getDist(), getType(), getCheck());
}
/**
* Get the 'dir' attribute value.
*
* @return value
*/
public Directions getDir() {
return dir;
}
/**
* Set the 'dir' attribute value.
*
* @param dir
*/
public void setDir(Directions dir) {
this.dir = dir;
}
/**
* Get the 'dist' attribute value.
*
* @return value
*/
public int getDist() {
return dist;
}
/**
* Set the 'dist' attribute value.
*
* @param dist
*/
public void setDist(int dist) {
this.dist = dist;
}
/**
* Get the 'check' attribute value.
*
* @return value
*/
public Directions getCheck() {
return check;
}
/**
* Set the 'check' attribute value.
*
* @param check
*/
public void setCheck(Directions check) {
this.check = check;
}
/*
* (non-Javadoc)
*
* @see java.lang.Object#hashCode()
*/
@Override
public int hashCode() {
final int prime = 31;
int result = 1;
result = prime * result
+ ((getCheck() == null) ? 0 : getCheck().hashCode());
result = prime * result
+ ((getDir() == null) ? 0 : getDir().hashCode());
result = prime * result + getDist();
result = prime * result
+ ((getType() == null) ? 0 : getType().hashCode());
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;
BlockableMove other = (BlockableMove) obj;
if (getCheck() != other.getCheck())
return false;
if (getDir() != other.getDir())
return false;
if (getDist() != other.getDist())
return false;
if (getType() != other.getType())
return false;
return true;
}
@Override
protected List<Move> getAllMoves(Teams team, BoardDef board, int horizPos,
int vertPos, boolean check) {
List<Move> ret = new ArrayList<Move>();
// Loop through each step of a move...
for (int distCount = 1; distCount <= getDist(); distCount++) {
// Define variables.
int horizDest = distCount * getDir().getHoriz() + horizPos;
int vertDest = team.side(distCount * getDir().getVert()) + vertPos;
int boardMove = board.getType().ordinal() - getDir().getBoard();
int score = 0;
long hash = 0;
// Move *must* be on the board set.
if (!Boards.inRange(boardMove, horizDest, vertDest)) {
break;
}
// Make a clone of the current board set to calculate the move with.
BoardSet set = board.getSet().clone();
// Figure out which board to work with.
BoardDef boardDest = set.getBoard(Boards.values()[boardMove]);
// Diagonal step checking: The in-between steps for diagonal
// movements must be empty if doing this check.
if (getCheck() != null) {
int horizCheck = horizDest - getDir().getHoriz()
+ getCheck().getHoriz();
int vertCheck = vertDest - getDir().getVert()
+ getCheck().getVert();
int boardCheck = boardMove - getDir().getBoard()
+ getCheck().getBoard();
BoardDef boardCheckDest = set
.getBoard(Boards.values()[boardCheck]);
if (boardCheckDest.get(vertCheck, horizCheck) != null) {
break;
}
}
// Figure out what piece (if any) is at the destination location.
BoardPiece destPiece = boardDest.get(vertDest, horizDest);
// Destination piece is the same team.
if (destPiece != null && destPiece.getTeam() == team) {
break;
// Destination piece is the other team.
} else if (destPiece != null) {
PieceDef destPieceDef = PieceDef.get(destPiece.getType());
score = destPieceDef.getValue();
}
// CAPTURE can only capture, MOVE can only move.
if ((score == 0 && getType() == MoveTypes.CAPTURE)
|| (score > 0 && getType() == MoveTypes.MOVE)) {
break;
}
// Perform the move on the cloned board set.
set.move(board.getType(), horizPos, vertPos, boardDest.getType(),
horizDest, vertDest);
// Validate for check condition -- the move cannot place your own
// king in check.
if (!check && set.isCheck(team.other())) {
continue;
}
// Get the hash for the board set for this move.
hash = set.hash();
MoveTypes type = null;
// The user will be told if the move captures or just moves the
// piece.
if (score == 0) {
type = MoveTypes.MOVE;
} else {
type = MoveTypes.CAPTURE;
}
// Move is added to the return list.
ret.add(new Move(hash, score, boardDest.getType(), horizDest,
vertDest, type));
// If a capture is performed, stop.
if (score > 0) {
break;
}
}
return ret;
}
}