NobleLand

From PodcastWiki

Jump to: navigation, search

NobleLand was a submission of Noble Ape source code in Java to DarwinAtHome to allow Noble Ape's landscape generation algorithm to be used with DarwinAtHome.

The original code submission from November 25, 2006, is shown below.

/****************************************************************
 
  NobleLand.java
  
  =============================================================
  Copyright 1996-2006 Tom Barbalet. All rights reserved.
  
  This is an open source license. Please contact Tom Barbalet 
  <tom at nobleape dot com> for commercial licensing options.
  
  Redistribution and use in source and binary forms, with or 
  without modification, are permitted provided that the 
  following conditions are met:
  
    1. Redistributions of source code must retain the above 
  copyright notice, this list of conditions and the following 
  disclaimer. 
    2. Redistributions in binary form must reproduce the 
  above copyright notice, this list of conditions and the 
  following disclaimer in the documentation and/or other 
  materials provided with the distribution.
    3. Redistributions in any form must be accompanied by 
  information on how to obtain complete source code for this 
  software and any accompanying software that uses this 
  software. The source code must either be included in the 
  distribution or be available for no more than the cost of 
  distribution plus a nominal fee, and must be freely 
  redistributable under reasonable conditions. For an executable 
  file, complete source code means the source code for all modules 
  it contains. It does not include source code for modules or 
  files that typically accompany the major components of the 
  operating system on which the executable file runs.
  
  THIS SOFTWARE IS PROVIDED BY TOM BARBALET "AS IS" AND ANY 
  EXPRESSED OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED 
  TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR
  A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL TOM 
  BARBALET, NOBLE APE OR ITS CONTRIBUTORS BE LIABLE FOR ANY 
  DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR 
  CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, 
  PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, 
  DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED 
  AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT 
  LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) 
  ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF 
  ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
  
  =============================================================
  
  This software and Noble Ape are a continuing work of Tom 
  Barbalet, begun on 13 June 1996. No apes or cats were harmed 
  in the writing of this software.
  
****************************************************************/

public class NobleLand {
  public int      generator[];
  public int      resolution_bits;
  public int      multiplier;

  private byte    map[];

/*
    dim = 256 x 2^resolution_bits;

    +--- dim ---+
    |           |
   dim         dim
    |           |
    +--- dim ---+
  
  Initialized code below for 1024 x 1024 array of height points
  
  Landscape is normally defined at a byte worth of height values
  
  Multiplier allows for (256 * multiplier) possible values spread smoothly
  
 */

  public void NobleLand()
  {
    generator = new int[2];
    map = new byte[(256 * 256)];
  
    generator[0] = 0;
    generator[1] = 0;
    
    resolution_bits = 2;
    multiplier = 1;
  }

  private int Bilinear(int z00, int z01, int z10, int z11, int px, int py, int resolution_bits)
  {
    int  and_value = (1 << resolution_bits) - 1;
    int  mic_x = px & and_value;
    int  mic_y = py & and_value;
    
    z10 = z10 - z00;
    z11 = z11 - z01 - z10;

    z01 = (z01 - z00) << resolution_bits;  
    z10 = z10 << resolution_bits;
  
    return z00 + (((z01 * mic_x) + (z10 * mic_y) + (z11 * mic_x * mic_y) ) >> (resolution_bits<<1));
  }


  private int Random(int local[])
  {
    int tmp0 = local[0];
    int tmp = local[1];
    
    if ((tmp == 0) && (tmp0 == 0)) {
      tmp0 = 0x95f2;
      tmp = 0x4dab;
    }
    
    local[0] = tmp & 0xffff;
    
    if ((tmp0 & 1) == 1)
      local[1] = (tmp ^ (tmp0 >> 1) ^ 0xd028) & 0xffff;
    else
      local[1] = (tmp ^ (tmp0 >> 1)) & 0xffff;
      
    return (tmp);
  }



  /*
  
  Init needs to be run at least once following the generator numbers being set - ideally externally
  
  The generator numbers are 16-bit values

    The generator is based in constantly refining binary spaces with each binary space having a +/- value

  +-+-+---+--- ---+
  +-+-+   |       |
  +-+-+---+       
  |   |   |       |
  +---+---+       
  |               |
  |               |
  |               |
  +---------------+

  */

  public void  Init()
  {
    byte    scratch[] = new byte[(256 * 256)];
    int      random[] = new int[2];
    int      refine = 0;
    
    random[0] = (generator[0] & 0xffff);
    random[1] = (generator[1] & 0xffff);

    while (refine < (256 * 256))
    {
      map[ refine ] = (byte) 128;
      refine++;
    }

    refine = 0;
    while (refine < 7) {
      int  major = (64 >> refine); /* major starts coarse */
      int  minor = (1 << refine);  /* minor starts fine */
      int  py = 0;
      
      while (py < minor) {
        int  px = 0;
        while (px < minor) {
          int  val1 = ((px << 2) + (py << 10));
          int  ty = 0;
          
          int  tseed = Random(random);
          
          while (ty < 4) {
            int  tx = 0;
            while (tx < 4) {
              int  val2 = (tseed >> (tx | (ty << 2)));
              int  val3 = ((((val2 & 1) << 1)-1) * 20);
              int  my = 0;
              val2 = (tx | (ty << 8));
              while (my < major) {
                int  mx = 0;
                while (mx < major) {            
                  int  point = ((mx | (my << 8)) + (major * (val1 + val2)));
                  if ((refine&2) == 2) { /* on 2, 3, 6, 7 */ 
                    int  pointx = (point & 255);
                    int  pointy = (point >> 8);
                    /* rotate 45 degrees */
                    point = (((pointx + pointy) & 255) | (((256 + pointx - pointy) & 255) << 8));
                  }
                  map[point] = (byte)(map[point] + val3);
                  mx++;
                }
                my++;
              }
              tx++;
            }
            ty++;
          }
          px++;
        }
        py++;
      }
      
      /* This is a four times rounder which blurbs the harsh edges and adds wrap around gradiation */
      minor = 0;
      while (minor < 4) {
        byte  front[];
        byte  back[];
        int  sy = 0;
        if ((minor&1) == 0) {
          front = map;
          back = scratch;
        } else {
          front = scratch;
          back = map;
        }
        while (sy < 256) {
          int  sx = 0;
          while (sx < 256) {
            int  sum = 0;
            int  ty = 0;
            while (ty < 3) {
              int  tx = 0;
              while (tx < 3) {
                sum = sum + front[((sx + 255 + tx) & 255) | (((sy + 255 + ty) & 255) << 8)];
                tx++;
              }
              ty++;
            }
            back[sx | (sy << 8)] = (byte)(sum / 9);
            sx ++;
          }
          sy ++;
        }
        minor ++;
      }
      refine ++;
    } 
  }

  public int Height(int px, int py)
  {    
    int    macro_x0 = ((px >> resolution_bits) & 255);
    int    macro_x1 = ((macro_x0 + 1) & 255);
    
    int    macro_y = ((py >> resolution_bits) & 255);
    
    int    macro_y0 = ( macro_y ) << 8;
    int    macro_y1 = ((macro_y + 1) & 255) << 8;

    int    z00 = multiplier * map[ macro_x0 | macro_y0 ];
    int    z01 = multiplier * map[ macro_x1 | macro_y0 ];
    int    z10 = multiplier * map[ macro_x0 | macro_y1 ];
    int    z11 = multiplier * map[ macro_x1 | macro_y1 ];

    return Bilinear(z00, z01, z10, z11, px, py, resolution_bits);
  }
}


/*

  Some example source

  {
    int      px, py;
    int      created_land[] = new int[ 2048 * 2048 ];
    NobleLand  noble_land = new NobleLand();
    
    noble_land->generator[0] = 0xf3de;
    noble_land->generator[1] = 0x3a56;
    noble_land->resolution_bits = 3;
    noble_land->multiplier = 128; // ranges from 0 to 32,640 (theoretically) (32,640 = 255 * 128)

    noble_land->Init();
    
    py = 0;
    while( py < 2048 )
    {
      px = 0;
      while( px < 2048 )
      {
        created_land[ px | ( py << 11 ) ] = noble_land->Height(px, py);
        px++;
      }
      py++;
    }
    
  }

 */
Personal tools