cg@myrias.UUCP (03/09/87)
Generating good-looking pseudo-random scenery (terrain) has interested me
for a while (I'm into computer game playing as well as compilers). A couple
of years ago I tried to generate scenery using a "volcano" type generator
(lead on by the "Empire" manual). I got one going, but it was VERY slow. I
eventually came up with a method that touches each point only once, and
uses only small integer calculations. The first version I did (in Draco of
course) for the Spectrum card (128 x 192 x 2) in my Compupro CP/M system.
Here follows a version I whipped up for the Amiga. It's in Draco, so you
won't be able to compile it (also you don't have the include files :-( ).
So, following it is the uuencoded object. It takes a few seconds to produce
the image, so have patience.
Chris Gray (ubc-vision,sask)!alberta!myrias!cg
-------------------cut here--------file: sc.d---------------------------
#include:intuition/miscellaneous.g
#include:intuition/screen.g
#include:intuition/window.g
#include:intuition/intuitext.g
#include:intuition/requester.g
#include:graphics/gfx.g
#include:graphics/view.g
#include:graphics/rastport.g
#include:libraries/dos.g
/*
* sc.d - fractalish terrain generator.
*
* Date: March 5, 1987 (original version sometime in 1985)
* Author: Chris Gray
* Language: Draco
* System: Amiga
*/
/*
* The nature of the terrain can be changed by playing with the numbers
* in 'Range'. If you change SIZE, you must also change the number of
* values given for 'Range'. The created terrain with SIZE = 8 is 256 pixels
* by 256 pixels, which doesn't fit on a non-interlaced screen, so only the
* top 200 pixels are displayed. The terrain is a torus, i.e. wraps around
* both vertically and horizontally.
*/
/*
* Feel free to use this algorithm in any games you write, so long as you
* give me credit for it. (I THINK I invented it, since I've never heard of
* anything similar, and other programs I've seen use much slower methods.)
*/
uint
SIZE = 8,
COUNT = 1 << SIZE,
SCREEN_WIDTH = 320,
SCREEN_HEIGHT = 200,
SCREEN_DEPTH = 5,
COLOURS = 1 << SCREEN_DEPTH,
WINDOW_WIDTH = if COUNT < SCREEN_WIDTH then COUNT else SCREEN_WIDTH fi,
WINDOW_HEIGHT = if COUNT < SCREEN_HEIGHT then COUNT else SCREEN_HEIGHT fi;
[SIZE] uint Range = (32, 32, 32, 22, 14, 8, 4, 2);
[COLOURS] uint ColourMap = (
0x00f, 0x050, 0x070, 0x0a0, 0x0c0, 0x0e0, 0x4f4, 0x8f8,
0xdf0, 0xff0, 0xfd0, 0xfb0, 0xf90, 0xf70, 0xe50, 0xe33,
0xe11, 0xf01, 0xf03, 0xf05, 0xf07, 0xf09, 0xf0b, 0xf0d,
0xf1f, 0xf3f, 0xf5f, 0xf7f, 0xf9f, 0xfbf, 0xfdf, 0xfff
);
*Screen_t Screen;
*Window_t Window;
uint Seed;
[COUNT, COUNT] int Cell;
/*
* random - return a random number 0 - passed range.
*/
proc random(uint rang)uint:
if rang = 0 then
0
else
Seed := Seed * 17137 + 4287;
Seed := (Seed >> 8) >< (Seed << 8);
Seed % rang
fi
corp;
/*
* set - set a given spot in Cell.
*/
proc set(uint l, c, size; int height)void:
uint rang;
rang := Range[size];
height := height + random(rang) - (rang + 1) / 2;
Cell[l, c] := height;
corp;
/*
* grow - grow the basic scenery heights.
*/
proc grow()void:
uint l, c, i, step, nextStep, l1, l2, c1, c2;
Cell[0, 0] := 0;
step := COUNT;
for i from 0 upto SIZE - 1 do
nextStep := step / 2;
for l from 0 by step upto COUNT - 1 do
l1 := l + nextStep;
l2 := l + step;
if l2 = COUNT then
l2 := 0;
fi;
for c from 0 by step upto COUNT - 1 do
c1 := c + nextStep;
c2 := c + step;
if c2 = COUNT then
c2 := 0;
fi;
set(l, c1, i, (Cell[l, c] + Cell[l, c2] + 1) / 2);
set(l1, c, i, (Cell[l, c] + Cell[l2, c] + 1) / 2);
set(l1, c1, i, (Cell[l, c] + Cell[l, c2] +
Cell[l2, c] + Cell[l2, c2] + 2) / 4);
od;
od;
step := nextStep;
od;
corp;
/*
* display - display the resulting scenery.
*/
proc display()void:
uint l, c;
int height;
for l from 0 upto WINDOW_HEIGHT - 1 do
for c from 0 upto WINDOW_WIDTH - 1 do
height := Cell[l, c];
SetAPen(Window*.w_RPort,
if height < 0 then
0
elif height >= COLOURS then
COLOURS - 1
else
height
fi);
pretend(WritePixel(Window*.w_RPort, c, l), void);
od;
od;
corp;
/*
* main program.
*/
proc main()void:
NewWindow_t newWindow;
DateStamp_t ds;
IntuiText_t bodyText, positiveText, negativeText;
bodyText := IntuiText_t(COLOURS - 1, 0, 0, 51, 5, nil, nil, nil);
bodyText.it_IText := "Done";
positiveText := IntuiText_t(COLOURS - 1, 0, 0, 7, 3, nil, nil, nil);
positiveText.it_IText := "Next";
negativeText := IntuiText_t(COLOURS - 1, 0, 0, 7, 3, nil, nil, nil);
negativeText.it_IText := "Quit";
if OpenIntuitionLibrary(0) ~= nil then
if OpenGraphicsLibrary(0) ~= nil then
if OpenDosLibrary(0) ~= nil then
Screen := OpenScreen(&NewScreen_t(
0, 0, SCREEN_WIDTH, SCREEN_HEIGHT, SCREEN_DEPTH, 0, 1,
0x0, CUSTOMSCREEN, nil, nil, nil, nil));
if Screen ~= nil then
LoadRGB4(&Screen*.sc_ViewPort, &ColourMap[0], COLOURS);
newWindow := NewWindow_t(
0, 0, WINDOW_WIDTH, WINDOW_HEIGHT,
FREEPEN, FREEPEN,
0x0, BORDERLESS | ACTIVATE | NOCAREREFRESH,
nil, nil, nil, nil, nil, 0, 0, 0, 0,
CUSTOMSCREEN);
newWindow.nw_Screen := Screen;
Window := OpenWindow(&newWindow);
if Window ~= nil then
DateStamp(&ds);
Seed := (ds.ds_Minute >< ds.ds_Tick) | 1;
while
grow();
display();
AutoRequest(Window, &bodyText, &positiveText,
&negativeText, 0x0, 0x0, 150, 50)
do
od;
CloseWindow(Window);
fi;
CloseScreen(Screen);
fi;
CloseDosLibrary();
fi;
CloseGraphicsLibrary();
fi;
CloseIntuitionLibrary();
fi;
corp;
-------------------cut here--------file: sc.uue-------------------------
begin 644 sc
M```#\P`````````#``````````(````"``"`!@```BD```/I`````D[Y````
M```````#[`````$````"`````@````````/R```#ZP``@`8```/R```#Z0``
M`BDCP````!(CR````!9.^0``!#0`````````````2.<_/DIO`#!F```(0H=@
M``!&/CD````(SOQ"\=Y\$+\SQP````@^.0````C@3SPY````".%.O4<SQP``
M``@^.0````@"AP``__^.[P`P2$<"AP``__\@!TS??/PB7U2/3M$``$CG/SY5
MCT'Z`&)-T#XO`#0"AP``___CCSZV>``^+P`R/Q=.N0```!P\`-Y&/!=21N).
MGD8_1P`R/B\`.`*'``#__^&//"\`-@*&``#__]Z&XX\@?`````HQKP`R>`!4
MCTS??/PB7U"/3M$`(``@`"``%@`.``@`!``"``!(YS\^GOP`$D)Y````"C]\
M`0``"D)'/T<`#'X',"\`##]```RP1V(``BX\+P`*XDX_1@`(0D8_1@`0/"\`
M"CH\`/\P+P`0/T``$+!%8@`!^#@O`!#8;P`(/T0`!C@O`!#8;P`*/T0`!`QO
M`0``!&8```9";P`$0D0_1``.."\`"C8\`/\P+P`./T``#K!#8@`!K#0O``[4
M;P`(/T(``C0O``[4;P`*/H(,5P$`9@``!$)7/R\`$#\O``0_+P`0-"\`%@*"
M``#__^&*+P<^+P`8`H<``/__U(?CBB!\````"C0P*``^+P`:`H<``/__X8\O
M!CPO``X"A@``___>AN./('P````*U'!X`%)"XD(L'RX?/P).N0```(`_+P`&
M/R\`$#\O`!`T+P`6`H(``/__X8HO!SXO`!@"AP``___4A^.*('P````*-#`H
M`#XO``X"AP``___ACR\&/"\`'`*&``#__]Z&XX\@?`````K4<'@`4D+B0BP?
M+A\_`DZY````@#\O``8_+P`$/R\`$#0O`!8"@@``___ABB\'/B\`&`*'``#_
M_]2'XXH@?`````HT,"@`/B\`&@*'``#__^&/+P8\+P`.`H8``/__WH;CCR!\
M````"M1P>``^+P`2`H<``/__X8\\+P`<`H8``/__WH;CCR!\````"M1P>``^
M+P`2`H<``/__X8\\+P`.`H8``/__WH;CCR!\````"M1P>`!40N1"+!\N'S\"
M3KD```"`,"\`#M!$9`#^3C`O`!#01F0`_@(_;P`(``HP+P`,4D!D`/W,WOP`
M$DS??/Q.=4CG/SY=CT)'/T<`!#X\`,<P+P`$/T``!+!'8@``LD)&/T8``CP\
M`/\P+P`"/T```K!&8@``D#HO``0"A0``___AC3@O``("A```___:A..-('P`
M```*/K!8`"QY````!"\N`#)*;P`$;```"$*%8```&`QO`"``!&T```AZ'V``
M``@Z+P`$2,4O!4ZY```'1"QY````!"\N`#(Z+P`&`H4``/__+P4Z+P`,`H4`
M`/__+P5.N0``!R`:`#`O``)20&0`_VHP+P`$4D!D`/](7(],WWS\3G4``$CG
M/SZ>_`!X3>\`*&$4'P`````S``4````````````````@7TO0<!0<W5.`9OIA
M!D1O;F4``"!?+T@`-$WO`!1A%!\`````!P`#````````````````(%]+T'`4
M'-U3@&;Z809.97AT```@7R](`"!-UT'Z_\Y+T'`4'-U3@&;Z8091=6ET```@
M7R](``PO/`````!.N0``!V`L0"`.9P`!DB\\`````$ZY```&L"Q`(`YG``%X
M+SP`````3KD```A(+$`@#F<``5YA(``````!0`#(``4``0````\`````````
M````````````(%]-T"\.3KD```?<+$`CS@`````L>0````"]_`````!G``$2
M+'D`````3>X`+"\.0?H!'DW0+PXO/````"!.N0``!OQ-[P!(83```````0``
MR/__```````"&`````````````````````````````````````````\@7TO0
M<#`<W5.`9OHO>0``````9DWO`$@O#DZY```']"Q`(\X````$+'D````$O?P`
M````9P``>$WO`#PO#DZY```(C"XO`$`L+P!$O8=\`8Z&,\<````(3KD```#\
M3KD```-<+SD````$3>\`+"\.3>\`'"\.3>\`#"\.+SP`````+SP`````+SP`
M``"6+SP````R3KD```@,'@!*!V8`_[@O.0````1.N0``!\0O.0````!.N0``
M!ZQ.N0``"'1.N0``!N1.N0``!Y3>_`!X3-]\_$YU``\`4`!P`*``P`#@!/0(
M^`WP#_`/T`^P#Y`/<`Y0#C,.$0\!#P,/!0\'#PD/"P\-#Q\//P]?#W\/GP^_
M#]\/_R)?(!\O"4/Z`!@O#BQY````!$ZN_=@L7R/```(`#$YU9W)A<&AI8W,N
M;&EB<F%R>0`````B>0`"``PO#BQY````!$ZN_F(L7TYU```O#B!O`!`B;P`,
M("\`""QY``(`#$ZN_T`L7R)?WOP`#$[1```O#B)O`!`@+P`,(B\`""QY``(`
M#$ZN_KPL7R)?WOP`#$[1```O#B)O``P@+P`(+'D``@`,3J[^JBQ?(E]0CT[1
M(E\@'R\)0_H`&"\.+'D````$3J[]V"Q?(\```@`03G5I;G1U:71I;VXN;&EB
M<F%R>0```")Y``(`$"\.+'D````$3J[^8BQ?3G4``"\.(&\`""QY``(`$$ZN
M_[XL7R)?6(].T2\.(&\`""QY``(`$$ZN_[@L7R)?6(].T2\.(&\`""QY``(`
M$$ZN_SHL7R)?6(].T2\.(&\`""QY``(`$$ZN_S0L7R)?6(].T4CG#`X@;P`T
M(F\`,"1O`"PF;P`H("\`)"(O`"`D+P`<)B\`&"QY``(`$$ZN_J1,WW`P(E_>
M_``@3M$``")?(!\O"4/Z`!@O#BQY````!$ZN_=@L7R/```(`%$YU9&]S+FQI
M8G)A<GD`(GD``@`4+PXL>0````1.KOYB+%].=0``+PXB+P`(+'D``@`43J[_
M0"Q?(E]8CT[1```#[````"P````!```(E```"'8```AB```(,@``!_P```?D
M```'S```![0```>6```'>@``!U````<P```'#```!N8```;*```%[@``!CX`
M``8````%Q```!;X```9*```%J```!48```4V```%,````^X```.X```#K@``
M`Q8```+R```"S@```J@```)F```"0````?X```'8```!!@```-0```!<````
M5@```$P```!$````/@```#`````8`````@``!,H```9B```%]```!6````7Z
M```%V@``!2@```6V```&4```!D0```8P```$\@``!E8```3>```&7````^@`
G``00```"$@```GH```,J````I`````X````(`````@````````/R
`
end