docs: def scroll(self, x, y):
          """Scroll the contents of the console in the direction of x,y.
  
          Uncovered areas will be cleared to the default background color.
          Does not move the virutal cursor.
  
          Args:
              x (int): Distance to scroll along the x-axis.
              y (int): Distance to scroll along the y-axis.
  
          Returns:
              Iterator[Tuple[int, int]]: An iterator over the (x, y) coordinates
              of any tile uncovered after scrolling.
  
          .. seealso:: :any:`set_colors`
          """
          assert isinstance(x, _INTTYPES), "x must be an integer, got %s" % repr(x)
          assert isinstance(y, _INTTYPES), "y must be an integer, got %s" % repr(x)
          def getSlide(x, length):
              """get the parameters needed to scroll the console in the given
              direction with x
              returns (x, length, srcx)
              """
              if x > 0:
                  srcx = 0
                  length -= x
              elif x < 0:
                  srcx = abs(x)
                  x = 0
                  length -= srcx
              else:
                  srcx = 0
              return x, length, srcx
          def getCover(x, length):
              """return the (x, width) ranges of what is covered and uncovered"""
              cover = (0, length) # everything covered
              uncover = None  # nothing uncovered
              if x > 0: # left side uncovered
                  cover = (x, length - x)
                  uncover = (0, x)
              elif x < 0: # right side uncovered
                  x = abs(x)
                  cover = (0, length - x)
                  uncover = (length - x, x)
              return cover, uncover
  
          width, height = self.get_size()
          if abs(x) >= width or abs(y) >= height:
              return self.clear() # just clear the console normally
  
          # get the ranges of the areas that will be uncovered
          coverX, uncoverX = getCover(x, width)
          coverY, uncoverY = getCover(y, height)
          # so at this point we know that coverX and coverY makes a rect that
          # encases the area that we end up blitting to.  uncoverX/Y makes a
          # rect in the corner of the uncovered area.  So we need to combine
          # the uncoverX/Y with coverY/X to make what's left of the uncovered
          # area.  Explaining it makes it mush easier to do now.
  
          # But first we need to blit.
          x, width, srcx = getSlide(x, width)
          y, height, srcy = getSlide(y, height)
          self.blit(self, x, y, width, height, srcx, srcy)
          if uncoverX: # clear sides (0x20 is space)
              self.draw_rect(uncoverX[0], coverY[0], uncoverX[1], coverY[1],
                             0x20, self._fg, self._bg)
          if uncoverY: # clear top/bottom
              self.draw_rect(coverX[0], uncoverY[0], coverX[1], uncoverY[1],
                             0x20, self._fg, self._bg)
          if uncoverX and uncoverY: # clear corner
              self.draw_rect(uncoverX[0], uncoverY[0], uncoverX[1], uncoverY[1],
                             0x20, self._fg, self._bg)