private void initSectorVals(int GS) {
    //
    //  Set up the requisite data stores first-
    final Vec3D seedVals[][] = new Vec3D[GS][GS] ;
    final int seedSize = (mapSize / DETAIL_RESOLUTION) + 1 ;
    final HeightMap sectorMap = new HeightMap(seedSize) ;
    final float heightVals[][] = sectorMap.value() ;
    sectorVal = new byte[GS][GS] ;
    //
    //  We then generate seed values for each sector, and sort by height.
    final Sorting <Vec3D> sorting = new Sorting <Vec3D> () {
      public int compare(Vec3D a, Vec3D b) {
        if (a == b) return 0 ;
        return a.z > b.z ? 1 : -1 ;
      }
    } ;
    for (Coord c : Visit.grid(0, 0, GS, GS, 1)) {
      final Vec3D v = seedVals[c.x][c.y] = new Vec3D() ;
      final float val = (Rand.num() < typeNoise) ?
        ((Rand.num() < typeNoise) ? Rand.num() : heightVals[c.x][c.y]) :
        ((Rand.num() * typeNoise) + (heightVals[c.x][c.y] * (1 - typeNoise))) ;
      v.set(c.x, c.y, val) ;
      sorting.add(v) ;
    }
    //
    //  We then determine how many sectors of each habitat are required,
    //  compile the IDs sequentially by height, and assign to their sectors.
    float sumAmounts = 0, sumToNext = 0 ;
    for (int i = habitats.length ; i-- > 0 ;) sumAmounts += habitatAmounts[i] ;
    final byte typeAssigned[] = new byte[sorting.size()] ;
    byte currentTypeID = -1 ;
    for (int i = 0 ; i < typeAssigned.length ; i++) {
      final float indexInSum = i * sumAmounts / typeAssigned.length ;
      if (indexInSum >= sumToNext) {
        currentTypeID++ ;
        sumToNext += habitatAmounts[currentTypeID] ;
      }
      typeAssigned[i] = currentTypeID ;
    }
    int count = 0 ; for (Vec3D v : sorting) {
      sectorVal[(int) v.x][(int) v.y] = typeAssigned[count++] ;
    }
  }