Update
[less_retarded_wiki.git] / procgen.md
blob821c67ef8bccec707cfb03d10e6b51920688a27c
1 # Procedural Generation
3 Procedural generation (procgen, also PCG -- *procedural content generation* -- not to be confused with [procedural programming](imperative.md), but see also [RNG](rng.md)) refers to creation of [data](data.md) (and in rarer cases maybe even [programs](program.md)), such as [art](art.md) assets in [games](game.md) or test data for data processing software, by using [algorithms](algorithm.md), [mathematical](math.md) formulas and [randomness](randomness.md) rather than creating them manually or measuring them in the [real world](irl.md) (e.g. by taking photographs, 3D scans etc.). This can be used for example for automatic generation of [textures](texture.md), texts, [music](music.md), game levels or 3D models but also practically anything else, e.g. test [databases](database.md), animations or even computer programs. Such data are also called *synthetic*. Procedural art currently doesn't reach artistic qualities of a skilled human artist, but it can be [good enough](good_enough.md) or even necessary (e.g. for creating extremely large worlds), it may be preferred e.g. for its extreme save of storage memory, it can help add detail to human work, be a good filler, a substitute, an addition to or a basis for manually created art. Procedural generation has many advantages such as saving space (instead of large data we only store small code of the algorithm that generates it), saving artist's time (once we have an algorithm we can generate a lot data extremely quickly), parameterization (we can tweak parameters of the algorithm to control the result or create animation, often in real-time), increasing resolution practically to infinity or extending data to more dimensions (e.g. [3D textures](3d_texture.md)). It's also [fun](fun.md) for the programmer. Procedural generation can also be used as a helper and guidance, e.g. an artist may use a procedurally generated game level as a starting point and fine tune it manually, or vice versa, procedural algorithm may create a level by algorithmically assembling manually created building blocks.
5 Procedural generation basically means randomly generating things with some added cleverness, i.e. some kind of algorithm and parameter tuning. Randomly generating something isn't that hard, provided we have a good (pseudo)random number generator -- for example to generate random loot in an RPG game may be as simple as generating a single random number representing the item ID -- this isn't yet procedural generation. The process becomes procedural generation if we throw in more rules and cleverness: for example once we start randomly generating cities so that their layout makes some sense (i.e. there are no unreachable streets, buildings in middle of the roads etc.). While doing this it's important to retain in mind all the rules of handling randomness with computers, i.e. we don't really want to employ true randomness but rather [deterministic](determinism.md) [pseudorandomness](pseudorandomness.md)! The whole thing, no matter how big, will be generated just from a single seed number. The same seed must always generate the same thing. And so on and so forth.
7 ```
8 xc,.....,:cco,,,';,;o:':l:kkkxoooxkkc:',..'.xocxxx  ,,:lccoxxkkkx;',;:;lck ,;;, xcl;::,':xkkkxxoccl;,'
9 kx:,:'.'.'':;'...ooXkxl:xXXxocccccokkxkx;;',l:cXoX  :,::lcoxxkkXKKK:'',;lx :,,;.xc;:'',KKKXkkxxocl::,,
10 kcc;:':','.......::XkXckkxkxocccooxkkXkXXxco:clkkX  lll:,:lcoxxxkXKXc'',;o :;;; ol,''lXKXkkxxocl:,:lll
11 xx;;:'lo;.........;ckxxXkxxoooccooxkkkkkkoXkoxokxk  ccoll:,;loccoxXxoo;.,l,:::;,l:.;ooxXxoccol;,:;locc
12 x:'.:,;xl'.......',;;xXkkxxxxoooooxkkkkkXxXkkxkkkk  xxxocll::loooxXxocoo:..,;:,'.,xocoxXxoool::llcoxoo
13 o:,:xXXkk:.........:'Kkxxxkkkkxxxkxkkkkxkokcl',XxX  xkXxxxccl;;cxkXxolccoo, ,: ,ooccloxXkxc;;lccxxkXkx
14 :''cokkkX,........','0kxoxkxkkkkkkkxkkkkkXo:..,ll;  kkXkxxcoxcl;cxKxo;llccol',loccll;oxKxcllcxocxxkKkk
15 ..;'';l,'........lXkXXxxxxkkxxkkkkkkx;;occ,.....'.  ,o0XkkoxxxxoccXkx;;;llccooccll;;;xkXccoxxoxokkX0x,
16 ..'''.........,',0kxoooxxxoocoxkkkkx:,:',:,.......  ':;XKKkkkkkXKXXxloccllccooccllccoloXXKXkkkkkKKK;:.
17 ..:c::.....':olc'Kxocooxxxoocoxkkkx;'.'c:;'.......  :,'.:kooccllllclkkK;::::;;;:::;KXXccllllccock;'',,
18 kkKXkoc;cXxKKXXxcXkxoxkkkkkkkxokxxk;..;':'.....,lc  ;;:,'.loccll;;;kko:xoc..''..cok:okk;;;llccol'',::;
19 xxxxxxxkkkXkkkkkxkxoooxxkkkcl:;xkk;.........';kKkk  cccl;:,'loccll;l:;xkKccllllccKXxl:l;lllcoc'':;lccc
20 ooxxxkokkkkkkxxxkxxooxxkc::';:,,cl'','.....c0kkooc  ''''.':, 'oocclc;:,:cKWMkxMWMc:'::cllcox,.':,.''''
21 cooooxk;'xkxxkkkxkkxoxoc;kXc'',,,'',,......cXxcccc  ::l;;:;:;'.;oocol:.'oX0oK0o0Xx, :locool'';;::;:l::
22 oxkkxk;.'oXkxkkkxkxkkx',;okxccx;';c:.'.....xXxxooo  :lc:;;;::''lcoool:.'okKo0Mo0Xx,.:loooo;'';:;;;,ll,
23 ;,:,'''.'lkkxxxooxxok''',:oXkxkkkko'...;;,:,cccxcl  ''''',:, 'oocclc;:',c0WWxxMW0c:'::cllcoo' ,::'''''
24 ..........;;;XkxxXc,;.....oKxoocook,'.:::;'l:,c'..  cccl;:,'loccll;l:;xkKccccccccXXxl,l;llccol'':;lccc
25 .............lxlc:o:'.....'Xkxooookx:,'...::kXo'..  ;;:,'.;occll;;;kxo:koo......coX:oxk;;;llcco;.',:;;
26 ............',::;Xkol......cXkoocoxkl,''xx:,kX,...  :,'.:kccccllllllXkKl::::;;::::;KkXccllllcccok:.',,
27 ..........,cKl,;,xxl.....,,kkkxooxookXXXkkkk;,::..  ',;kKXxkkkkkXXXolocc;lcccoccllccolcXkXkkkkkxXKX;,.
28 '........'kXxkk;,;,,..,'l',cXkxxooxxooxkkkkco,:l,x  'o0XkkoxxxkxocXkk;;;llccooccll;;;xkXooxxxxxokkX0o'
29 ,,''''...:xkxkk,;;',':,;c,'ookkkxxxxocooxxxkX:c;::  kkKkxxcooollcxKko;llccoc,'loccll;oxKxcllcxocxxkKkk
30 xkcll,'..'xXxko;',l;:'.cxl,:okkkkkxoooooooooxkoxcl  xkXkxxccl;;cxkXxollcoo, ,, ,oocllcxXkxc;;lccxxkXkx
31 oxxl;.'..,cXkkc:'olxc.'l;':ckXkkkkxooooooooxkocccl  xxxoccl::lcooxXxocco;..:l;:..,xccoxXxoool::llcoxxo
32 ':'',,l;clolxllooxxxX:...',0xxxoooxxkkkkkxxol.....  ccoll:,;loccooXxool',;::::;:;,.;ooxXooccol;,:llocc
33 .','''clcl:',;;ccxokkc....oKxoooooxkkkoc:;,.......  lll:,:lcoxxxkXKXo,.,;o :;;: o;,''cXKXkxxxocl:,:lll
34 '......',,,:oxxXooo;,'..'lMkokkxxxkx:.,..''llocl:.  ;:::;coxxkkXXK0:'',;lx :,,;.xc;,'':0KXXkkxxocl::,:
35 :'......';l;o;'';,:''.'ox:,cxkXkkkkoc,......:lxxx;  ',:;lcooxkkkkl',:,;lcx ,l;:.xcl;:::';xkkkxoocl;:,'
36 ```
38 *Some procedural textures.*
40 As [neural](neural_net.md) [AI](ai.md) approaches human level of creativity, we may see computers actually replacing many artists in near [future](future.md), however it is debatable whether AI generated content should be called procedural generation as AI models are quite different from the traditional hand-made procedural algorithms -- AI art is still seen as a separate approach than traditional procedural generation. For this we'll only be considering the traditional approach from now on.
42 [Minecraft](minecraft.md) (or, for the real chads, [Minetest](minetest.md)) is a popular, relatively recent example of a [game](game.md) completely based on procedural generation, in which the world is wholly procedurally generated, which allows it to have near-[infinite](infinity.md) worlds -- size of such a world is in practice limited only by ranges of [data types](data_type.md) rather than available storage memory. [Roguelikes](roguelike.md) also heavily utilize procgen. However this is nothing new, for example the old game called Daggerfall was known for its extremely vast procedurally generated world, and even much older games used this approach (perhaps more so that there was so little storage memory available). Some amount of procedural generation can be seen probably in most mainstream games, e.g. clouds, vegetation or NPCs are often made procedurally.
44 For its extreme potential for saving space procedural generation is popular a lot in [demoscene](demo.md) where programmers try to create as small programs as possible. German programmers made a full fledged 3D shooter called [.kkrieger](kkrieger.md) that fits into just 96 kB! It was thanks to heavy use of procedural generation for the whole game content. [Bytebeat](bytebeat.md) is a simple method of generating procedural "8bit" music, it is used e.g. in [Anarch](anarch.md). Procedural generation is generally popular in indie game dev thanks to offering a way of generating huge amounts of content quickly and without having to pay artists.
46 We may see procgen as being similar to [compression](compression.md) algorithms: we have large data and are looking for an algorithm that's much smaller while being able to reproduce the data (but here we normally go the other way around, we start with the algorithm and see what data it produces rather than searching for an algorithm that produces given data). [John Carmack](john_carmack.md) himself called procgen "basically a shitty compression".
48 Using **[fractals](fractal.md)** (e.g. those in a form of [L-system](l_system.md)) is a popular technique in procgen because fractals basically perfectly fit the definition perfectly: a fractal is defined by a simple equation or a set of a few rules that yield an infinitely complex shape. Nature is also full of fractals such as clouds, mountain or trees, so fractals look organic.
50 There are also other techniques such as [wave function](wave_function.md) collapse which is used especially in tile map generation. Here we basically have some constraints set (such as which tiles can be neighbors) and then consider the initial map a [superposition](superposition.md) of all possible maps that satisfy these constraints -- we then set a random tile (chosen from those with lowest [entropy](entropy.md), i.e. fewest possible options) to a random specific value and propagate the consequences of it to other tiles causing a cascading effect of collapsing the whole map into one of the possible solutions.
52 A good example to think of is generating procedural [textures](texture.md) -- similar techniques may also be used to create procedural terrain [heightmaps](heightmap.md) etc. This is generally done by first generating a basis image or multiple images, e.g. with **[noise](noise.md) functions** such as [Perlin noise](perlin_noise.md) (it gives us a grayscale image that looks a bit like clouds). We then further process this base image(s) and combine the results in various ways, for example we may use different transformations, [modulations](modulation.md), blending, adding color using [color ramps](color_ramp.md) etc. The whole texture is therefore described by a [graph](graph.md) in which nodes represent the operations we apply; this can literally be done visually in software like [Blender](blender.md) (see its [shader](shader.md) editor). The nice thing is that we can now for example generalize the texture to 3 dimensions, i.e. not only have a flat image, but have a whole volume of a texture that can extremely easily be mapped to 3D objects simply by intersecting it with their surfaces which will yield a completely smooth texturing without any seams; this is quite often used along with [raytracing](raytracing.md) -- we can texture an object by simply taking the coordinates of the ray hit as the 3D texture coordinates, it's that simple. Or we can animate a 2D texture by doing a moving cross section of 3D texture. We can also write the algorithm so that the generated texture has no seams if repeated side-by-side (by using modular "wrap-around" coordinates). We can also generate the texture at any arbitrary resolution as we have a continuous mathematical description of it; we may perform an infinite zoom into it if we want. As if that's not enough, we can also generate almost infinitely many slightly different versions of this texture by simply changing the [seed](seed.md) of [pseudorandom](pseudorandom.md) generator we use.
54 We use procedural generation mainly in two ways:
56 - **offline/explicit**: We pre-generate the data before we run the program, i.e. we let the algorithm create our art, save it to a file and then use it as we would use traditionally created art.
57 - **realtime/implicit**: We generate the data on the fly and only parts of it that we currently need (this of course requires an algorithm that is able to generate any part of the data independently of its other parts; for example for a procedural texture each pixel's color should only be determined by its coordinates). For example with a procedural texture mapped onto a 3D model, we would only compute the texture pixels ([texels](texel.md)) that we are actually drawing: this has the advantage of giving an infinite resolution of the texture because no matter how close-up we view the model, we can always compute exactly the pixels we need. This would typically be implemented inside a fragment/pixel [shader](shader.md) program. This is also used in the voxel games that generate the world only in the area the player currently occupies.
59 Indeed we may also do something "in between", e.g. generate procedural assets into temporary files or RAM [caches](cache.md) at run time and depending on the situation, for example when purely realtime generation of such assets would be too slow.
61 ## Notable Techniques/Concepts
63 The following are some techniques and concepts often used in procedural generation:
65 - **[noise](noise.md)**: Noise is often used as a basis for generation or for modulation, it can be seen as kind of "RNG taken to the next level" -- noise is greatly random but also usually has some structure, for example it may resemble smoke or water ripples. There are great many types of noise and algorithms for its generation; the simplest [white noise](white_noise.md) is actually not very useful, more common are various forms of fractal noise, often used noises are [Perlin noise](perlin_noise.md), [simplex noise](simplex_noise.md) etc., other ones are [Voronoi](voronoi.md) diagrams, coin flip noise, midpoint displacement, spot noise, cosine noise, fault formation, Brownian motion etcetc.
66 - **[random number generators](rng.md)**: To make random decisions we use random number generators -- here we actually don't have to have the best generators, we aren't dealing with "security" or anything critical, however the generator should at least have a great period so that it's not limited to just generating few different results, and its useful to be able to choose [probability distribution](probability_distribution.md).
67 - **[modulation](modulation.md)**: Using previously generated procedural data, for example noise, to somehow affect another data -- for example imagine we already have some basic procedural texture but want to make it more interesting by randomly displacing its individual pixels to warp it a little bit. If we use a simple random number generator for each pixel, the result will just look too chaotic, so it's better if we e.g. use two additional Perlin noise textures, which together say for each pixel by what distance and angle we'll displace the pixel. As Perlin noise is more continuous, gradual noise, then also the distortion will be kind of continuous and nice. A famous example of this is marble texture that can be generated by horizontally modulating a texture of vertical black and white stripes with Perlin noise.
68 - **simulations resembling natural/biological phenomena**: E.g. [cellular automata](cellular_automaton.md), [particle systems](particle_system.md), erosion simulation, [agent systems](agent_system.md) (letting virtual "workers" collaborate on creating something) ...
69 - **[fractals](fractal.md)**: Fractals can resemble nature, they create "content" on all scales and are very simple to define. Popular types of fractals are e.g. [L-systems](l_system.md) that draw fractals with [turtle graphics](turtle_graphics.md).
70 - **coloring**: To get colors from simple numeric values we may use e.g. color mapping of the values to some [palette](palette.md) or using three different arrays as [RGB](rgb.md) channels. We may also use [flood fill](flood_fill.md) and other things of course.
71 - **[state search](state_search.md)**: This is an approach similar to e.g. how computers play games such as [chess](chess.md). Imagine we for example want to generate a procedural city: any constructed city represents a state and these states are connected (e.g. one state leads to another by placing a building somewhere), forming a [graph](graph.md) (sometimes even a [tree](tree.md)) of states: the state space. The idea is to create an evaluation function that takes any given state (any specific city) and says how "good" it is (e.g. how realistic it looks, i.e. for example there shouldn't be more hospitals than actual houses of people, buildings should be reachable by roads etc.); then we also implement a search function (e.g. [minimax](minimax.md), [monte carlo](monte_carlo.md), ...) that uses the evaluation function to search for some good enough state we take as the result. [Evolutionary](evolutionary.md) search is often used here.
72 - **constructive approach**: The "obvious" approach, an algorithm that simply constructs something according to some rules from start to finish, without performing advanced things like evaluating the quality of the generated output, letting different outputs compete, combining several different outputs etc. Example may be for example [recursive](recursion.md) [space partitioning](space_partitioning.md) for the creation of game dungeons.
73 - **wave function collapse**: Analogy to quantum mechanics, often used for generating tile maps.
74 - **combining intermediate results**: For example when creating procedural textures we may actually create two separate textures and then somehow [blend](blending.md) them together to get a more interesting result.
75 - **wrap-around coordinates**: Wrap around (modular) coordinates help us make tiling data.
76 - **mathematical [functions](function.md)**: Nice structures can be generated just by combining basic mathematical functions such as [sine](sin.md), [cosine](cos.md), [square root](sqrt.md), minimum/maximum, [logarithm](log.md) etc. We take these functions and make an expression that transforms input coordinates (i.e. for example *x*, *y* and *time* for an animated picture) to the final generated value. The functions may be composed (put on input of other functions), added, multiplied etc.
77 - **higher [dimensionality](dimension.md)**: Equations used for procedural generation are often generalized to higher dimensions so that we can for example create smooth animation by taking the extra dimension as time.
78 - **[filters](filter.md)**: We may utilize traditional graphic filters such as Gaussian blur, [median](median.md) blur, general [convolution](convolution.md), color adjustments etc.
79 - **[stochastic](stochastic.md) models**: Stochastic mathematical models describe the generated result in terms of probabilities, which is convenient for us as we can take the model and just use random number generators to make decisions with given probabilities to obtain a specific result. For example [Markov chains](markov_chain.md) can be used to easily generate random procedural text by knowing probabilities with which any word is followed by another word, this may also be used to generate linear game levels etc. Similarly we may utilize various non-[deterministic](determinism.md) finite state automata, [decision trees](decision_tree.md) etc.
80 - **constraint solving**: Many times the problem of procedural generation can be described as a constraint solving problem, i.e. we have a set of constraints such as "we want 10 to 20 rooms" and "each room must be reachable from other rooms" and then we want to find a solution that just satisfies the constraints (without somehow rating how good the solution is). The advantage of formulating the problem this way is that there exist a number of algorithms for solving such problems, e.g. [ASP](asp.md), some heuristic searches etc.
81 - ...
83 ## Examples
85 Here are some cool [ASCII renderings](ascii_art.md) of procedurally generated pictures:
87 ```
88 ....,':..:.,.c;:,,.,'M0....',:c.,c,'o:xcx.',.'l:,;'.:.,
89 ...''.'..:.,.;,''x0Xoc;:::::;lo.':o,c;;c..:l.,''..,...,
90 .',......',;':',oKxl:'.........',;cX:o0k.'l':''......,.
91 .;........''';l.:x;,Kkocl;::::;lcxX':cX;'o',,.........,
92 .:.'........'l;.Kc:Xol:,'.......'':;ck0c'.l',.'.......'
93 l.'.''.....'.:..XlXo;,'..xooccooxkXKMW.'.:,:..,'..',.,,
94 ...,;,....,.:,.olcxl:'.cl;::,,,::;;coklxolcl..',';'::,'
95 '':c:.;'.:'l,..oxo:;,.l:,''......'',:.,...'',;;c..c:o;c
96 x.''.l':k'.l,..oc;;;,;:''.....xxkXK0xKxxxxxk.''''',:.,'
97 xlc00lkl,.xc;.Xxl::,,:,'...;;;llccol;l;;lllxxxxxkkK;ck'
98 c:kX:x:klWKxl.KXc;,,'.'..,,,,,,::;,,,,:,:,cooxkK,:;cxKW
99 oo':o,kl,Kxl:'MKk;;,'....''..''''''''','''',,:;coX0,;oX
100 c.,o,Xc,.kc;,.Kkoc;:'...............''',,:;c..',;ck.';o
101 .:.:.o:'.xl:'..xc;:,''..................'',:lo..,:ck.:c
102 ;.l'.l,..o;,'..ol;,''..............'',;...',:lx..,lx.,c
103 'x:.xl,..o;:'...l:,''......  ......'',:l...':;o..,lx.:x
104 .c,.xl,..xl:,'...;,''..............'',;lo..',;o..,l.'l.
105 .c:.kc:,..ol:,''..................'',:;cx..':lx.':o.:.:
106 0o;'.kc;,'..c;:,,'''...............':;cokK.,;ck.,cX,o,.
107 'Xo;,0Xoc;:,,'''','''''''''..''....',;;kKM':lxK,lk,o:'o
108 :WKxc;:,Kkxooc,:,:,,,,;::,,,,,,..'.',,;cXK.lxKWlk:x:Xk:
109 :'kc;Kkkxxxxxlll;;l;loccll;;;...',:,,::lxX.;cx.,lkl00cl
110 :',.:,'''''.kxxxxxKx0KXkxx.....'':;,;;;co..,l.'k:'l.''.
111 oc;o:c..c;;,''...,.:,''......'',:l.,;:oxo..,l':.';.:c:'
112 ,',::';','..lcloxlkoc;;::,,,::;lc.':lxclo.,:.,....,;,..
113 ',,.,'..',..:,:.'.WMKXkxooccoox..',;oXlX..:.'.....''.'.
114 ;'.......'.,'l.'c0kc;:''.......',:loX:cK.;l'........'.:
115 ,,.........,,'o';Xc:'Xxcl;::::;lcokK,;x:.l;'''........;
116 ..,......'':'l'.k0o:Xc;,'.........':lxKo,':';,'......,'
117 .,...,..'',.l:..c;;c,o:'.ol;:::::;coX0x'',;.,.:..'.''..
119 0KXXkkxxooooccccccoxo;:,'...',:;lcoxXWKXkkxxxooooccccco
120 XMXxxooocccclllllllllcl:,'...',:;lcokK0Xxxoooccclllllll
121 kK0Xxocccllll;;;;;;;;;;l;,'..'',:;lcxk0Kkooccclll;;;;;;
122 xXMKkocllll;;;;:::::::::;;,'..',:;lcoxXMXxoclll;;;;;:::
123 okKKkxclll;;;;:::::::,:::;:'..'',:;loxXMXkocll;;;;:::::
124 okK0kxcll;;;;:::::::,,,::::,...',:;lcxX0Kkocll;;;;:::::
125 xk0Kkoclll;;;;:::::::::::;:'..',,:;coxXWXxoclll;;;;::::
126 xXWXxocclll;;;;;;:::::;;l:,...',:;lcokK0kxocclll;;;;;::
127 k0Kkxooccclllll;;;;;;lll:,'..',:;lcoxXMXkooocccllll;;;;
128 K0Xkxxxoooccccclllccoc;:,'..',,:;lcxk0Kkkxxooocccccllll
129 W0KXXkkxxxoooooooxkol;,''..',,:;lcokKM0KXXkkxxxooooooox
130 K0MM0KXXXkkkkkXK0kcl:,''..'',:;lcokXXK0W00KXXXkkkkkXKMx
131 kXXK00WMM00MW0k0xcl:,''..'',:;lcoxxxkkXKK0MWM000MMKkXol
132 xkkkXXXKKKXXxkKxcl;:,'...',,:;lccooxxxkkXXXKKKKXkxXXoc;
133 xxxkkkkkkkxoxMkol;:,''..'',:;llcccoooxxxkkkkkkkxckKxcl;
134 oxxxxkkkkxolk0xcl;:,'...'',:;llcccooooxxxxkkkxxooKXxcl;
135 oxxxkkkkkxxck0kol;:,'...'',:;llcccoooxxxxkkkkkxocXKxcl;
136 xxkkkXXXXXkxcKXoc;:,''...',::;lccoooxxxkkkXXXXXkxxWkol;
137 kkXXKK000000XkKkol;:,'...'',:;lcooxxxkkXXKK00000KXoMxcl
138 XKK0W00KKXXXXK0XXol;:,'. .',::;lcxkkXXK0MM0KKKXXXKKWXkc
139 0W0KKXkkkxxxxxxxkKxc;:,'...',:;;coxXK0M0KXXkkkxxxxxxxkM
140 0KXkkxxxooooccccccoxol:,'...',:;lcoxXMKXkkxxxoooccccccc
141 XMXkxooocccllllllllllcc;,'...',:;lcokK0Xxxoooccclllllll
142 kK0Xxocccllll;;;;;;;;;;l;,'..'',:;lcxk0Kkxoccllll;;;;;;
143 xX0Kkocllll;;;;:::::::::;;,'..',:;lcoxXMXxoclll;;;;;:::
144 okKKkxclll;;;;:::::::,:::;:'..'',:;loxXMXkocll;;;;:::::
145 okK0kxclll;;;:::::::,,,::::,...',:;lcxX0Kkocll;;;;:::::
146 xk0Kkoclll;;;;:::::::::::;:'..',,:;coxXWXxoclll;;;;::::
147 xXWXxoccllll;;;;;:::::;;c:,...',:;lcokK0kxocclll;;;;;::
148 k0Kkxooccclllll;;;;;;lcl:,'..',:;lcoxXWXxooocccllll;;;;
150 ;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;
151 ll;;;;;;;;;;;;llllll;;;;;;;;;;;;llcxolllcXocl;;;;;;;;;;
152 .',ol;;;;;;lol:,,,,,;Kl;;;;;;lo:'...........',ll;;;;;;l
153 ....:c;;;;lc,'.......':c;;;;ll'....':;ll:,'....,o;;;;lK
154 ;'...;l;;;l;'.........,o;;;;x'...,xl;;;;;;ll'...:l;;;ll
155 c:...'c;;;;o,'.......'cl;;;l:...'xl;;;;;;;;l;'..'0;;;;c
156 x,...';l;;;;lcc:,,:;xl;;;;;K'...';cl;;;;;;lx,'...:l;;;;
157 '.....';l;;;;;;;;;;;;;;;;lW,.....',;xoookc:,'....':c;;;
158 .......',:ocll;;;;;;llck;,'..........''''.........',:co
159 ...........''''''''''''...............................'
160 .......................................................
161 '''.............................'',,:::::,,,''.........
162 ;lcl,'......',:;;l;:,''......':xl;;;;;;;;;;;lcc,'......
163 ;;;;l;'...':Wll;;;;;lo;'....,x;;;;;;;;;;;;;;;;;ll'....,
164 l;;;;l,...,kl;;;;;;;;;c:...'k;;;;lo:,'''',ll;;;;l:...'l
165 :c;;;;c'..'ll;;;;;;;;;o,...:l;;;lc'.......',o;;;;o'..';
166 :o;;;;l,...':ol;;;;lll,...'X;;;;l;'.......',Xl;;;l:...'
167 xl;;;;;c:'.....'''''.....'ol;;;;;cl,''''',:Wl;;;;;l:'..
168 ;;;;;;;;lo;,'........'':xl;;;;;;;;;llccccll;;;;;;;;lcl,
169 ;;;;;;;;;;;;llllllllll;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;
170 ;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;
171 ;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;
172 :coll;;;;;;;;;;;;;;;;;;;;;;;;;lck;,,'''''',:lxll;;;;;;;
173 ...';l;;;;;;lloxllckcl;;;;;;lW,'..............':c;;;;;;
174 '....:l;;;;lo,'....',;c;;;;;X'...',ocllllo;,....,c;;;;l
175 l;'..'0;;;;c:'......',k;;;;l,...,o;;;;;;;;;ll'..'l;;;;l
176 ;c,...:l;;;;o:''...',ol;;;;o'..'cl;;;;;;;;;;c:...,c;;;;
177 lX,...'ll;;;;;llcccl;;;;;;o,...';l;;;;;;;;;lo,...';l;;;
178 ;,'....':cl;;;;;;;;;;;;;lc,.....':Kcllllllcl,'....':xl;
179 '........'',;cKoccoxo;:,'........''',,,,,,''.... ...'',
182 These were created in extremely simple way, without even using any [noise](noise.md) -- each picture here has each pixel computed by plugging the *x* and *y* coordinate to a quite simple equation using basic functions like [sine](sin.md), [square root](sqrt.md), absolute value, triangle wave etc. More complex methods will probably iteratively apply various filters, they may employ things like [cellular automata](cellular_automaton.md) and so on, however here you see even a very [simple](kiss.md) approach may often be [good enough](good_enough.md). The [C](c.md) code to generate the pictures above is following (for simplicity using [floats](float.md) and math.h, which in serious programs should be avoided):
184 { NOTE: The equations for the functions were made by me when I was playing around with another project. I have uploaded them to Wikimedia Commons, you can find actual png pictures there. ~drummyfish }
187 #include <stdio.h>
188 #include <math.h>
190 #define W 55
191 #define H 30
193 // helper stuff:
194 char palette[] = "WM0KXkxocl;:,'. ";
196 double min(double a, double b) { return a < b ? a : b; }
197 double max(double a, double b) { return a > b ? a : b; }
198 double absMy(double x) { return x < 0 ? -1 * x : x; }
199 double gauss(double x) { return exp((-1 * x * x) / 2); }
201 double tri(double x)
203   x = absMy(x);
205   int whole = x;
206   double frac = x - whole;
208   return whole % 2 ? 1 - frac : frac;
211 void drawFunction(double (*f)(double, double), double xFrom, double yFrom,
212   double xTo, double yTo)
214   double v1 = 0xffffffff, v2 = -1 * v1;
215   double sX = (xTo - xFrom) / W, sY = (yTo - yFrom) / H;
217   for (int y = 0; y < H; ++y)
218     for (int x = 0; x < W; ++x)
219     {
220       double v = f(xFrom + x * sX,yFrom + y * sY);
222       if (v > v2)
223         v2 = v;
225       if (v < v1)
226         v1 = v;
227     }
229   v2 -= v1;
231   if (v2 == 0)
232     v2 = 0.0001;
234   for (int y = 0; y < H; ++y)
235   {
236     for (int x = 0; x < W; ++x)
238     putchar(palette[(int) (15 *
239       ((min(v2,max(0,f(xFrom + x * sX,yFrom + y * sY) - v1))) / v2))]);
241     putchar('\n');
242   }
245 // ==== ACTUAL INTERESTING FUNCTIONS HERE ===
247 double fSnakes(double x, double y)
249   return sqrt(tri(x + sqrt(tri(x + 0.4 * sin(y*3)))));
252 double fYinYang(double x, double y)
254   double r = sin(1.2 * y + 2.5 * sin(x) + 2 * cos(2.25 * y) * sin(x));
255   return log(2 * sqrt(absMy(r)) - r);
258 double fSwirl(double x, double y)
260   return gauss(
261     fmod((x * x),(absMy(sin(x + y)) + 0.001)) + 
262     fmod((y * y),(absMy(sin(x - y)) + 0.001)));
265 int main(void)
267   drawFunction(fSwirl,-2,-2,2,2);
268   putchar('\n');
269   drawFunction(fSnakes,-1,-1,2,2);
270   putchar('\n');
271   drawFunction(fYinYang,-4,-4,4,4);
275 Now let's take a look at some iterative algorithm: an extremely simple dungeon generator. This is so called *constructive* algorithm, a simple kind of method that simply "constructs" something according to given rules, without evaluating how good it's work actually is etc. All it's going to do is just randomly choose a cardinal direction (up, right, down, left), draw a line of random length, and repeat the same from the line's endpoint, until predefined number of lines has been drawn (a kind of [random walk](random_walk.md)). Here is the C code:
278 #include <stdio.h>
280 #define W 30            // world width
281 #define H 30            // world height
283 char world[H * W];      // 2D world array
285 unsigned int r = 12345; // random seed here
287 unsigned int random()
289   r = r * 321 + 29;
290   return r >> 4;
293 void generateWorld()
295   int steps = 100;      // draw this many lines
296   int pos = 0;
297   int add = 1;          // movement offset
298   int nextLineIn = 1;
300   for (int i = 0; i < H * W; ++i)
301     world[i] = ' ';
303   while (steps)
304   {
305     world[pos] = 'X';
306     nextLineIn--;
308     int nextPos = pos + add;
310     if (nextPos < 0 || nextPos >= W * H || // going over world edge?
311       (add == 1 && nextPos % W == 0) ||
312       (add == -1 && nextPos % W == W - 1))
313       nextLineIn = 0;
314     else
315       pos = nextPos;
317     if (nextLineIn <= 0)
318     {
319       steps--;
320       nextLineIn = W / 5 + random() % (W / 3);
321       add = (random() & 0x10) ? W : 1;
323       if (rand() & 0x80)
324         add *= -1;
325     }
326   }
329 int main(void)
331   generateWorld();
333   for (int i = 0; i < H * W; ++i) // draw
334   {
335     char c = world[i];
337     putchar(c);
338     putchar(c);
340     if ((i + 1) % W == 0)
341       putchar('\n');
342   }
344   return 0;
348 And here is one possible output of the program:
351 XXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXX
352 XXXX  XXXX              XX  XXXXXXXXXXXXXXXXXXXXXXXXXXXXX
353 XXXX  XXXX  XXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXX
354 XXXX  XXXX  XX          XX  XXXX  XX          XX        X
355 XXXX  XXXX  XX          XX  XXXX  XX          XX        X
356 XXXX  XXXXXXXXXXXXXXXXXXXXXXXXXXXXXX          XX        X
357 XXXX  XXXX  XX      XX  XX  XXXX  XX          XX        X
358 XXXX  XXXX  XX      XX  XX  XXXX  XX                    X
359 XXXX  XXXX  XX      XX  XX  XXXX  XX                    X
360 XXXX  XXXXXXXXXXXXXXXXXXXXXXXXXXXXXX                    X
361 XX      XX  XX      XX  XX  XXXX  XX                    X
362 XX      XX  XX      XX  XX  XXXX  XX                    X
363 XXXXXXXXXXXXXX      XX  XX  XXXX                        X
364 XX      XX  XX      XX  XX  XXXX                        X
365 XXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXX                        X
366 XXXXXXXXXXXXXXXXXXXXXX        XX                        X
367 XX  XX      XX      XX        XX                        X
368 XX  XX      XX      XX        XX                        X
369 XX  XX      XX      XX        XX                        X
370 XX  XXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXX                    X
371 XX  XX      XX      XX        XX                        X
372 XX  XX      XX      XX        XX                        X
373 XXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXX        X
374 XX  XX      XX      XX        XX              XX        X
375 XX  XX      XXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXX
376 XX  XX      XX      XX        XX              XX        X
377     XX      XX      XX        XXXXXXXXXXXXXXXXXXXXXXXXXXX
378     XX      XX      XX                        XX
379             XX      XX                        XX
380             XXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXX  XX
383 TODO: some example with noise
385 ## See Also
387 - [algorithmic art](algorithmic_art.md)