This repository has been archived on 2021-02-18. You can view files and clone it, but cannot push or open issues or pull requests.
chess/src/main/java/dev/kske/chess/board/MoveNode.java

228 lines
6.0 KiB
Java

package dev.kske.chess.board;
import java.util.*;
import dev.kske.chess.board.Piece.Color;
/**
* Project: <strong>Chess</strong><br>
* File: <strong>MoveNode.java</strong><br>
* Created: <strong>02.10.2019</strong><br>
*
* @since Chess v0.5-alpha
* @author Kai S. K. Engelbart
*/
public class MoveNode {
/**
* The index of the white kingside casting in a casting rights array.
*/
public static final int WHITE_KINGSIDE = 0;
/**
* The index of the white queenside castling in a castling rights array.
*/
public static final int WHITE_QUEENSIDE = 1;
/**
* The index of the white kingside casting in a casting rights array.
*/
public static final int BLACK_KINGSIDE = 2;
/**
* The index of the white queenside castling in a castling rights array.
*/
public static final int BLACK_QUEENSIDE = 3;
/**
* The move on the board associated with this move node.
*/
public final Move move;
/**
* The piece captured by the move.
*/
public final Piece capturedPiece;
/**
* The castling rights present during the move.
*/
public final boolean[] castlingRights;
/**
* The en passant target position or {@code null} if the move is not an en
* passant move.
*/
public final Position enPassant;
/**
* The color active during the move.
*/
public final Color activeColor;
/**
* The number of moves performed since the beginning of the game.
*/
public final int fullmoveCounter;
/**
* The halfmoves performed since the last capture move or pawn move.
*/
public final int halfmoveClock;
private MoveNode parent;
private List<MoveNode> variations;
/**
* Creates a new {@link MoveNode}.
*
* @param move the logged {@link Move}
* @param capturedPiece the {@link Piece} captures by the logged
* {@link Move}
* @param castlingRights the castling rights present during the move
* @param enPassant the en passant {@link Position} valid after the
* logged
* {@link Move}, or {@code null} if there is none
* @param activeColor the {@link Color} active after the logged
* {@link Move}
* @param fullmoveCounter the number of moves made until the current move
* @param halfmoveClock the number of halfmoves since the last capture
* move or
* pawn move
*/
public MoveNode(
Move move, Piece capturedPiece, boolean castlingRights[],
Position enPassant, Color activeColor, int fullmoveCounter,
int halfmoveClock
) {
this.move = move;
this.capturedPiece = capturedPiece;
this.castlingRights = castlingRights;
this.enPassant = enPassant;
this.activeColor = activeColor;
this.fullmoveCounter = fullmoveCounter;
this.halfmoveClock = halfmoveClock;
}
/**
* Creates a (deep) copy of another {@link MoveNode}.
*
* @param other The {@link MoveNode} to copy
* @param copyVariations When this is set to {@code true} a deep copy is
* created, which
* considers subsequent variations
*/
public MoveNode(MoveNode other, boolean copyVariations) {
this(
other.move,
other.capturedPiece,
other.castlingRights.clone(),
other.enPassant,
other.activeColor,
other.fullmoveCounter,
other.halfmoveClock
);
if (copyVariations && other.variations != null) {
if (variations == null)
variations = new ArrayList<>();
for (MoveNode variation : other.variations) {
MoveNode copy = new MoveNode(variation, true);
copy.parent = this;
variations.add(copy);
}
}
}
/**
* Adds another {@link MoveNode} as a child node.
*
* @param variation The {@link MoveNode} to append to this {@link MoveNode}
*/
public void addVariation(MoveNode variation) {
if (variations == null)
variations = new ArrayList<>();
if (!variations.contains(variation)) {
variations.add(variation);
variation.parent = this;
}
}
/**
* @return A list of all variations associated with this {@link MoveNode}
*/
public List<MoveNode> getVariations() { return variations; }
/**
* @return {@code true} if this move node has any variations
*/
public boolean hasVariations() {
return variations != null && variations.size() > 0;
}
/**
* @return the parent node of this move node
*/
public MoveNode getParent() { return parent; }
/**
* Sets the parent node of this move node
*
* @param parent the parent node to set
*/
public void setParent(MoveNode parent) { this.parent = parent; }
/**
* @return {@code true} if this move node has a parent
*/
public boolean hasParent() {
return parent != null;
}
@Override
public String toString() {
return String.format(
"MoveNode[move=%s,capturedPiece=%s,castlingRights=%s,enPassant=%s,activeColor=%s,fullmoveCounter=%d,halfmoveClock=%d]",
move,
capturedPiece,
Arrays.toString(castlingRights),
enPassant,
activeColor,
fullmoveCounter,
halfmoveClock
);
}
@Override
public int hashCode() {
final int prime = 31;
int result = 1;
result = prime * result + Arrays.hashCode(castlingRights);
result = prime * result + Objects.hash(
activeColor,
capturedPiece,
enPassant,
fullmoveCounter,
halfmoveClock,
move
);
return result;
}
@Override
public boolean equals(Object obj) {
if (this == obj)
return true;
if (obj == null)
return false;
if (getClass() != obj.getClass())
return false;
MoveNode other = (MoveNode) obj;
return activeColor == other.activeColor
&& Objects.equals(capturedPiece, other.capturedPiece)
&& Arrays.equals(castlingRights, other.castlingRights) && Objects.equals(enPassant, other.enPassant)
&& fullmoveCounter == other.fullmoveCounter
&& halfmoveClock == other.halfmoveClock
&& Objects.equals(move, other.move);
}
}