def next_player(table, from_seat, step=1, hascards=False):
    """ Attempts to find the index of the next valid player from the from_seat.
        If step is -1 it will search backwards on the table. Step can only be
        1 or -1. We can also specify to search for the next player with cards
        by setting hascards to True. If no player is found after searching
        the length of the table, an exception is raised.
    """
    if from_seat < -1 or from_seat >= len(table):
        raise ValueError('from_seat is out of bounds!')
    if abs(step) != 1:
        raise ValueError('step needs to be 1 or -1.')

    length = len(table)
    for i in range(1, length + 1):
        _seat = (from_seat + (i * step)) % length
        s = table.seats[_seat]

        if s.vacant():
            continue
        elif hascards and not s.has_hand():
            continue
        return _seat

    raise Exception('Error finding player!')