package com.anttilip.chkm8.model.pieces;

import com.anttilip.chkm8.model.Board;
import com.anttilip.chkm8.model.Player;
import com.anttilip.chkm8.model.Position;

import java.util.List;

/**
 * Represents a pawn, extends the abstract Piece class.
 */
public class Pawn extends Piece {
    private boolean firstMove;
    private final Position[] moveDirections;
    private final int moveDirection;

    public Pawn(Position position, Player player) {
        super(position, player, false);
        this.firstMove = true;
        this.moveDirection = (this.player == Player.WHITE) ? 1 : -1;
        this.moveDirections = new Position[]{new Position(0, moveDirection)};
    }

    /**
     * Returns pawns allowed move direction.
     *
     * Pawns move direction depends on the player who controls the pawn.
     * @return Position array containing the move direciton.
     */
    @Override
    public Position[] getMoveDirections() {
        return this.moveDirections;
    }

    /**
     * Moves pawn to the given position.
     *
     * Pawn is special piece being able to do double moves, attacking moves and en passant moves.
     * @param newPosition Position that piece is moved to.
     * @param board Board that piece belongs to.
     */
    @Override
    public void move(Position newPosition, Board board) {
        this.firstMove = false;
        Position originalPosition = this.getPosition();
        this.position = newPosition;
        if (isInTheEnd()) {
            // If pawn is in the end, it is promoted to Queen
            // If promotion move was attacking move, kill the attacked piece
            if (board.getPiece(newPosition) != null) {
                board.getPiece(newPosition).kill(board);
            }
            board.getPieces().add(new Queen(this.position, this.player));
            this.kill(board);
        }
        // If move is double move, make en passant pawn
        if (Math.abs(newPosition.getY() - originalPosition.getY()) == 2) {
            int newPawnYDiff = (this.position.getY() > originalPosition.getY()) ? -1 : 1;
            Position enPassantPos = new Position(this.getPosition().getX(), this.getPosition().getY() + newPawnYDiff);
            board.setEnPassantPosition(enPassantPos);
        } else if (newPosition.equals(board.getEnPassantPosition())) {
            // Attacked en passant
            Piece originalPawn = board.getPiece(newPosition.getX(), newPosition.getY() + moveDirection * -1);
            originalPawn.kill(board);
        }
    }

    /**
     * Checks is piece is in the highest rank.
     * @return Boolean value of pawn being in the highest rank.
     */
    private boolean isInTheEnd() {
        return (this.player == Player.WHITE && this.position.getY() == Board.BOARD_SIZE - 1)
                || (this.player == Player.BLACK && this.position.getY() == 0);
    }

    public boolean isFirstMove() {
        return this.firstMove;
    }


    /**
     * Adds pawns special double, attacking and en passant moves to the given list.
     *
     * @param board Board that piece belongs to.
     * @param possibleMoves List of possible positions that piece can move to.
     */
    @Override
    public void getSpecialMoves(Board board, List<Position> possibleMoves) {
        // Double move
        Position doubleMove = this.position.copy().add(0, moveDirection * 2);
        if (this.firstMove && possibleMoves.contains(this.position.copy().add(0, moveDirection))) {
            if (!board.isOccupied(doubleMove)) {
                possibleMoves.add(doubleMove);
            }
        }

        // Attacking moves
        Position[] attackingMoves = {
            this.position.copy().add(1, moveDirection),
            this.position.copy().add(-1, moveDirection)
        };
        for (Position attackMove : attackingMoves) {
            // Regular attack move
            if (board.isOccupied(attackMove) && board.getPiece(attackMove).player != this.player) {
                possibleMoves.add(attackMove);
            }
            // En passant
            if (board.getEnPassantPosition() != null && board.getEnPassantPosition().equals(attackMove)) {
                possibleMoves.add(attackMove);
            }
        }
    }

    @Override
    public Piece copy() {
        Pawn copy = new Pawn(this.position, this.player);
        copy.firstMove = this.firstMove;
        return copy;
    }

    @Override
    public boolean equals(Object o) {
        if (!(o instanceof Pawn)) {
            return false;
        }
        Pawn other = (Pawn) o;
        return other.position.equals(this.position) && other.player == this.player && other.isFirstMove() == this.firstMove;
    }
}

@@ -1383,32 +1383,210 @@
 tMove = false;%0D%0A
+        // If move was a attacking move, remove now eaten piece%0D%0A        if (board.isOccupied(newPosition)) %7B%0D%0A            board.getPiece(newPosition).kill(board);%0D%0A        %7D%0D%0A%0D%0A
         Position

Fix bug where piece eaten by pawn doesn't die