NobleLand
From PodcastWiki
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++; } } */
