content: package com.chess.engine.pieces;
  
  import com.chess.engine.Alliance;
  import com.chess.engine.board.Board;
  import com.chess.engine.board.Move;
  
  import java.util.Collection;
  
  public abstract class Piece {
  
      final PieceType pieceType;
      final Alliance pieceAlliance;
      final int piecePosition;
      private final boolean isFirstMove;
      private final int cachedHashCode;
  
      Piece(final PieceType type,
            final Alliance alliance,
            final int piecePosition,
            final boolean isFirstMove) {
          this.pieceType = type;
          this.piecePosition = piecePosition;
          this.pieceAlliance = alliance;
          this.isFirstMove = isFirstMove;
          this.cachedHashCode = computeHashCode();
      }
  
      public PieceType getPieceType() {
          return this.pieceType;
      }
  
      public Alliance getPieceAllegiance() {
          return this.pieceAlliance;
      }
  
      public int getPiecePosition() {
          return this.piecePosition;
      }
  
      public boolean isFirstMove() {
          return this.isFirstMove;
      }
  
      public int getPieceValue() {
          return this.pieceType.getPieceValue();
      }
  
      public abstract int locationBonus();
  
      public abstract Piece getMovedPiece(Move move);
  
      public abstract Collection<Move> calculateLegalMoves(final Board board);
  
      @Override
      public boolean equals(final Object other) {
          if (this == other) {
              return true;
          }
          if (!(other instanceof Piece)) {
              return false;
          }
          final Piece otherPiece = (Piece) other;
          return this.piecePosition == otherPiece.piecePosition && this.pieceType == otherPiece.pieceType &&
                 this.pieceAlliance == otherPiece.pieceAlliance && this.isFirstMove == otherPiece.isFirstMove;
      }
  
      @Override
      public int hashCode() {
          return this.cachedHashCode;
      }
  
      private int computeHashCode() {
          int result = this.pieceType.hashCode();
          result = 31 * result + this.pieceAlliance.hashCode();
          result = 31 * result + this.piecePosition;
          result = 31 * result + (this.isFirstMove ? 1 : 0);
          return result;
      }
  
      public enum PieceType {
  
          PAWN(100, "P"),
          KNIGHT(300, "N"),
          BISHOP(330, "B"),
          ROOK(500, "R"),
          QUEEN(900, "Q"),
          KING(1000 , "K");
  
          private final int value;
          private final String pieceName;
  
          public int getPieceValue() {
              return this.value;
          }
  
          @Override
          public String toString() {
              return this.pieceName;
          }
  
          PieceType(final int val,
                    final String pieceName) {
              this.value = val;
              this.pieceName = pieceName;
          }
  
      }
  
  }