def move_grid_lines_along_axis(lines, axis_name, delta, unit_rect, area_rect):
    """Move vectors so they are always inside grid area.

    lines
        An iterable of pygame.math.Vector2 pairs
        representing the start and end points of a line.
    axis_name
        String which equals either 'x' or 'y'.
    delta
        Integer. The amount of movement in pixels.
    unit_rect
        pygame.Rect instance representing an unit in the
        grid.
    area_rect
        pygame.Rect instance representing the area covered
        by the grid.

    The vectors are scrolled relative to delta, the amount
    of movement in pixels. We say we scroll the vectors
    'relative to' delta because the lines aren't exactly
    moved by the exact amount, but rather by the remainder
    of such amount in relation to the respective unit rect
    dimension (width for x axis and height for y axis).

    This is because lines which go out of the grid area
    are 'warped' to the opposite side of the grid area as to
    appear that the grid is moving indefinitely, thus
    there's no need to move by all the amount, just the
    fraction of it which represents the true movement
    performed.

    ####### extra explanation

    If you're still struggling to grasp the concept,
    you can simulate it by using an instance of
    collections.deque. Try creating the following deque:

    d = deque([1, 0, 0, 0, 0])

    now notice that it doesn't matter if you rotate it
    5, 50 or 500 units (try using the rotate method of
    the deque), the integer 1 always end up in the
    same position.

    Also try rotating it by 1 unit and then by 6 units.
    It always end up only "walking" one position, right?
    Thus, in the end, if you use the remainder of the
    rotation relative to the deque length (5 in this case)
    you obtain the number of positions effectively walked.

    for instance:
      48 % 5 = 3; that is, walking 48 steps is equivalent
                  of walking 3 in terms of final position;
      50 % 5 = 0; that is, walking 50 steps is equivalent
                  of walking no steps at all as far as
                  the final position is concerned;
    """
    ### based on axis_name, define attributes or raise error

    if axis_name == "x":
        length_attr = "width"
    elif axis_name == "y":
        length_attr = "height"
    else:
        raise ValueError("axis_name must be 'x' or 'y'.")

    ### store variables/alias

    t = getattr(area_rect, length_attr)  # total_length
    u = getattr(unit_rect, length_attr)  # unit_length
    d = delta

    ### if movement is greater or equal to an unit length,
    ### decrease movement to remainder; otherwise
    ### just use movement as is.

    if d > 0:
        amount = d % u if d >= u else d
    else:
        amount = d % -u if -d >= u else d

    ### for each in each line, perform movement;
    ### also perform offsets if needed.
    for line in lines:
        for vector in line:
            ## perform movement
            v = getattr(vector, axis_name)  # v 'means' value
            setattr(vector, axis_name, v + amount)

            ## perform offset if needed

            v = getattr(vector, axis_name)

            # if vector reaches or surpasses the edge of
            # the total length, move it back by one total
            # length
            if v >= t:
                setattr(vector, axis_name, v + -t)

            # if, on the contrary, vector goes back beyond
            # the origin, move it forward by one total
            # length
            elif v < 0:
                setattr(vector, axis_name, v + t)
Move vectors so they are always inside grid area.

    lines
        An iterable of pygame.math.Vector2 pairs
        representing the start and end points of a line.
    axis_name
        String which equals either 'x' or 'y'.
    delta
        Integer. The amount of movement in pixels.
    unit_rect
        pygame.Rect instance representing an unit in the
        grid.
    area_rect
        pygame.Rect instance representing the area covered
        by the grid.

    The vectors are scrolled relative to delta, the amount
    of movement in pixels. We say we scroll the vectors
    'relative to' delta because the lines aren't exactly
    moved by the exact amount, but rather by the remainder
    of such amount in relation to the respective unit rect
    dimension (width for x axis and height for y axis).

    This is because lines which go out of the grid area
    are 'warped' to the opposite side of the grid area as to
    appear that the grid is moving indefinitely, thus
    there's no need to move by all the amount, just the
    fraction of it which represents the true movement
    performed.

    ####### extra explanation

    If you're still struggling to grasp the concept,
    you can simulate it by using an instance of
    collections.deque. Try creating the following deque:

    d = deque([1, 0, 0, 0, 0])

    now notice that it doesn't matter if you rotate it
    5, 50 or 500 units (try using the rotate method of
    the deque), the integer 1 always end up in the
    same position.

    Also try rotating it by 1 unit and then by 6 units.
    It always end up only "walking" one position, right?
    Thus, in the end, if you use the remainder of the
    rotation relative to the deque length (5 in this case)
    you obtain the number of positions effectively walked.

    for instance:
      48 % 5 = 3; that is, walking 48 steps is equivalent
                  of walking 3 in terms of final position;
      50 % 5 = 0; that is, walking 50 steps is equivalent
                  of walking no steps at all as far as
                  the final position is concerned;
    
nodezator/our3rdlibs/grid/main.py