@Override
	@Nullable
	public final ChessMovement movePiece(final Position from, final Position to) {
		checkState(!isFinished());
		checkNotNull(from);
		checkNotNull(to);
		
		for (final ChessMovement movement : getPossibleMovements()) {
			if (!from.equals(movement.getFrom()) || !to.equals(movement.getTo()))
				continue;
			
			chessBoard.setPieceAt(to, chessBoard.setPieceAt(from, null));
			
			if (chessBoard.getPieceAt(to) instanceof ChessPawn && (to.getRow() == 1 || to.getRow() == chessBoard.getNumberOfRows())) {
				chessBoard.setPieceAt(to, new ChessQueen(currentTurn));
			}
			
			currentTurn = currentTurn.other();
			possibleMovementsCache = null;
			
			if (movement.is(Special.MATE)) {
				setWinner(movement.getSourcePiece().getColor());
			}
			
			movements.add(movement);
			
			return movement;
		}
		
		return null;
	}