Generate a heightmap using diamond-square algorithm.

  Modification of the algorithm in
  https://github.com/FLHerne/mapgen/blob/master/diamondsquare.py

  Args:
    mapsize: side length of the heightmap, must be a power of two.
    wibbledecay: integer, decay factor.

  Returns:
    numpy 2d array, side length 'mapsize', of floats in [0,255].

def plasma_fractal(mapsize=512, wibbledecay=3):
  """Generate a heightmap using diamond-square algorithm.

  Modification of the algorithm in
  https://github.com/FLHerne/mapgen/blob/master/diamondsquare.py

  Args:
    mapsize: side length of the heightmap, must be a power of two.
    wibbledecay: integer, decay factor.

  Returns:
    numpy 2d array, side length 'mapsize', of floats in [0,255].
  """
  if mapsize & (mapsize - 1) != 0:
    raise ValueError('mapsize must be a power of two.')
  maparray = np.empty((mapsize, mapsize), dtype=np.float_)
  maparray[0, 0] = 0
  stepsize = mapsize
  wibble = 100

  def wibbledmean(array):
    return array / 4 + wibble * np.random.uniform(-wibble, wibble, array.shape)

  def fillsquares():
    """For each square, calculate middle value as mean of points + wibble."""
    cornerref = maparray[0:mapsize:stepsize, 0:mapsize:stepsize]
    squareaccum = cornerref + np.roll(cornerref, shift=-1, axis=0)
    squareaccum += np.roll(squareaccum, shift=-1, axis=1)
    maparray[stepsize // 2:mapsize:stepsize, stepsize //
             2:mapsize:stepsize] = wibbledmean(squareaccum)

  def filldiamonds():
    """For each diamond, calculate middle value as meanof points + wibble."""
    mapsize = maparray.shape[0]
    drgrid = maparray[stepsize // 2:mapsize:stepsize, stepsize //
                      2:mapsize:stepsize]
    ulgrid = maparray[0:mapsize:stepsize, 0:mapsize:stepsize]
    ldrsum = drgrid + np.roll(drgrid, 1, axis=0)
    lulsum = ulgrid + np.roll(ulgrid, -1, axis=1)
    ltsum = ldrsum + lulsum
    maparray[0:mapsize:stepsize, stepsize //
             2:mapsize:stepsize] = wibbledmean(ltsum)
    tdrsum = drgrid + np.roll(drgrid, 1, axis=1)
    tulsum = ulgrid + np.roll(ulgrid, -1, axis=0)
    ttsum = tdrsum + tulsum
    maparray[stepsize //
             2:mapsize:stepsize, 0:mapsize:stepsize] = wibbledmean(ttsum)

  while stepsize >= 2:
    fillsquares()
    filldiamonds()
    stepsize //= 2
    wibble /= wibbledecay

  maparray -= maparray.min()
  return maparray / maparray.max()