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