Brownian tree: Difference between revisions

165,610 bytes added ,  2 months ago
m
No edit summary
 
(211 intermediate revisions by 61 users not shown)
Line 1:
[[Category:Raster graphics operations]]
[[Category:Geometry]]
{{Wikipedia|Brownian_tree}}
{{task|Fractals}}
[[File:Brownian_tree.jpg|450px||right]]
 
 
;Task:
Generate and draw a   [[wp:Brownian tree|Brownian Tree]].
 
[[Category:Raster graphics operations]]
{{task|Fractals}}Generate and draw a [[wp:Brownian tree|Brownian Tree]].
 
A Brownian Tree is generated as a result of an initial seed, followed by the interaction of two processes.
Line 10 ⟶ 16:
# When a particle collides with the seed or tree, its position is fixed, and it's considered to be part of the tree.
 
<br>Because of the lax rules governing the random nature of the particle's placement and motion, no two resulting trees are really expected to be the same, or even necessarily have the same general shape. <br><br>
=={{header|Action!}}==
Calculations on a real Atari 8-bit computer take quite long time. It is recommended to use an emulator capable with increasing speed of Atari CPU.
<syntaxhighlight lang="action!">BYTE FUNC CheckNeighbors(CARD x BYTE y)
IF Locate(x-1,y-1)=1 THEN RETURN (1) FI
IF Locate(x,y-1)=1 THEN RETURN (1) FI
IF Locate(x+1,y-1)=1 THEN RETURN (1) FI
IF Locate(x-1,y)=1 THEN RETURN (1) FI
IF Locate(x+1,y)=1 THEN RETURN (1) FI
IF Locate(x-1,y+1)=1 THEN RETURN (1) FI
IF Locate(x,y+1)=1 THEN RETURN (1) FI
IF Locate(x+1,y+1)=1 THEN RETURN (1) FI
RETURN (0)
 
PROC DrawTree()
DEFINE MAXW="255"
DEFINE MINX="1"
DEFINE MAXX="318"
DEFINE MINY="1"
DEFINE MAXY="190"
BYTE CH=$02FC
CARD x,l,r
BYTE y,t,b,w,h,dx,dy,m=[20]
 
x=160 y=96
Plot(x,y)
l=x-m r=x+m
t=y-m b=y+m
w=r-l+1 h=b-t+1
DO
DO
x=Rand(w)+l y=Rand(h)+t
UNTIL Locate(x,y)=0
OD
 
WHILE CheckNeighbors(x,y)=0
DO
DO
dx=Rand(3) dy=Rand(3)
UNTIL dx#2 OR dy#2
OD
 
IF dx=0 THEN
IF x>l THEN x==-1
ELSE x=r-1
FI
ELSEIF dx=1 THEN
IF x<r THEN x==+1
ELSE x=l+1
FI
FI
IF dy=0 THEN
IF y>t THEN y==-1
ELSE y=b-1
FI
ELSEIF dy=1 THEN
IF y<b THEN y==+1
ELSE y=t+1
FI
FI
OD
 
Plot(x,y)
IF l>MINX AND l+m>x AND w<MAXW THEN
l==-1 w==+1
FI
IF r<MAXX AND r-m<x AND w<MAXW THEN
r==+1 w==+1
FI
IF t>MINY AND t+m>y THEN
t==-1 h==+1
FI
IF b<MAXY AND b-m<y THEN
b==+1 h==+1
FI
 
Poke(77,0) ;turn off the attract mode
UNTIL CH#$FF ;until key pressed
OD
CH=$FF
RETURN
 
PROC Main()
BYTE COLOR1=$02C5,COLOR2=$02C6
 
Graphics(8+16)
Color=1
COLOR1=$0E
COLOR2=$02
 
DrawTree()
RETURN</syntaxhighlight>
{{out}}
[https://gitlab.com/amarok8bit/action-rosetta-code/-/raw/master/images/Brownian_tree.png Screenshot from Atari 8-bit computer]
=={{header|Ada}}==
{{libheader|SDLAda}}
<syntaxhighlight lang="ada">with Ada.Numerics.Discrete_Random;
 
with SDL.Video.Windows.Makers;
with SDL.Video.Renderers.Makers;
with SDL.Events.Events;
 
procedure Brownian_Tree is
 
Width : constant := 800;
Height : constant := 600;
Points : constant := 50_000;
 
subtype Width_Range is Integer range 1 .. Width;
subtype Height_Range is Integer range 1 .. Height;
type Direction is (N, NE, E, SE, S, SW, W, NW);
package Random_Width is new Ada.Numerics.Discrete_Random (Width_Range);
package Random_Height is new Ada.Numerics.Discrete_Random (Height_Range);
package Random_Direc is new Ada.Numerics.Discrete_Random (Direction);
 
Window : SDL.Video.Windows.Window;
Renderer : SDL.Video.Renderers.Renderer;
Event : SDL.Events.Events.Events;
 
Width_Gen : Random_Width.Generator;
Height_Gen : Random_Height.Generator;
Direc_Gen : Random_Direc.Generator;
 
function Poll_Quit return Boolean is
use type SDL.Events.Event_Types;
begin
while SDL.Events.Events.Poll (Event) loop
if Event.Common.Event_Type = SDL.Events.Quit then
return True;
end if;
end loop;
return False;
end Poll_Quit;
 
procedure Draw_Brownian_Tree is
Field : array (Width_Range, Height_Range) of Boolean := (others => (others => False));
X : Width_Range;
Y : Height_Range;
Direc : Direction;
 
procedure Random_Free (X : out Width_Range; Y : out Height_Range) is
begin
-- Find free random spot
loop
X := Random_Width.Random (Width_Gen);
Y := Random_Height.Random (Height_Gen);
exit when Field (X, Y) = False;
end loop;
end Random_Free;
 
begin
-- Seed
Field (Random_Width.Random (Width_Gen),
Random_Height.Random (Height_Gen)) := True;
 
for I in 0 .. Points loop
Random_Free (X, Y);
loop
-- If collide with wall then new random start
while
X = Width_Range'First or X = Width_Range'Last or
Y = Height_Range'First or Y = Height_Range'Last
loop
Random_Free (X, Y);
end loop;
exit when Field (X - 1, Y - 1) or Field (X, Y - 1) or Field (X + 1, Y - 1);
exit when Field (X - 1, Y) or Field (X + 1, Y);
exit when Field (X - 1, Y + 1) or Field (X, Y + 1) or Field (X + 1, Y + 1);
Direc := Random_Direc.Random (Direc_Gen);
case Direc is
when NW | N | NE => Y := Y - 1;
when SW | S | SE => Y := Y + 1;
when others => null;
end case;
case Direc is
when NW | W | SW => X := X - 1;
when SE | E | NE => X := X + 1;
when others => null;
end case;
end loop;
Field (X, Y) := True;
Renderer.Draw (Point => (SDL.C.int (X), SDL.C.int (Y)));
 
if I mod 100 = 0 then
if Poll_Quit then
return;
end if;
Window.Update_Surface;
end if;
end loop;
end Draw_Brownian_Tree;
 
begin
Random_Width.Reset (Width_Gen);
Random_Height.Reset (Height_Gen);
Random_Direc.Reset (Direc_Gen);
 
if not SDL.Initialise (Flags => SDL.Enable_Screen) then
return;
end if;
 
SDL.Video.Windows.Makers.Create (Win => Window,
Title => "Brownian tree",
Position => SDL.Natural_Coordinates'(X => 10, Y => 10),
Size => SDL.Positive_Sizes'(Width, Height),
Flags => 0);
SDL.Video.Renderers.Makers.Create (Renderer, Window.Get_Surface);
Renderer.Set_Draw_Colour ((0, 0, 0, 255));
Renderer.Fill (Rectangle => (0, 0, Width, Height));
Renderer.Set_Draw_Colour ((200, 200, 200, 255));
 
Draw_Brownian_Tree;
Window.Update_Surface;
 
loop
exit when Poll_Quit;
delay 0.050;
end loop;
Window.Finalize;
SDL.Finalise;
end Brownian_Tree;</syntaxhighlight>
=={{header|Applesoft BASIC}}==
Uses XDRAW to plot to Hi-res GRaphics, in fullscreen [POKE 49234,0] 280 x 192, effectively 140 x 192 because colors stretch over two pixels, using a single pixel shape. The POKEs create one shape in a shape table starting at address 768 and point addresses 232 and 233 to this address. Address 234 is the collision counter which is used to detect if the randomly placed seed has hit anything and if the moving seed has collided with the tree. Plotting the seed creates an animation effect of the seed moving around in it's Brownian way.<syntaxhighlight lang="applesoftbasic">0GOSUB2:FORQ=0TOTSTEP0:X=A:Y=B:FORO=0TOTSTEP0:XDRAWTATX,Y:X=INT(RND(T)*J)*Z:Y=INT(RND(T)*H):XDRAWTATX,Y:O=PEEK(C)>0:NEXTO:FORP=0TOTSTEP0:A=X:B=Y:R=INT(RND(T)*E):X=X+X(R):Y=Y+Y(R):IFX<0ORX>MORY<0ORY>NTHENNEXTQ
1 XDRAW T AT X,Y:P = NOT PEEK (C): XDRAW T AT A,B: NEXT P: XDRAW T AT X,Y:Q = A = 0 OR A = M OR B = 0 OR B = N: NEXT Q: END
2 T = 1:Z = 2:E = 8:C = 234
3 W = 280:A = W / 2:J = A
4 H = 192:B = H / 2:M = W - 2
5 N = H - 1:U = - 1:V = - 2
6 Y(0) = U:X(0) = V:Y(1) = U
7 Y(2) = U:X(2) = 2:X(3) = 2
8 Y(4) = 1:X(4) = 2:Y(5) = 1
9 X(6) = V:Y(6) = 1:X(7) = V
10 POKE 768,1: POKE 769,0
11 POKE 770,4: POKE 771,0
12 POKE 772,5: POKE 773,0
13 POKE 232,0: POKE 233,3
14 HGR : POKE 49234,0
15 ROT= 0: SCALE= 1: RETURN</syntaxhighlight>
=={{header|ATS}}==
 
[[File:Brownian tree.2023.05.07.18.48.00.png|thumb|alt=A brownian tree, black on white.]]
[[File:Brownian tree.2023.05.07.18.48.25.png|thumb|alt=A brownian tree, black on white.]]
[[File:Brownian tree.2023.05.07.18.49.01.png|thumb|alt=A brownian tree, black on white.]]
[[File:Brownian tree.2023.05.07.18.49.34.png|thumb|alt=A brownian tree, black on white.]]
 
The program outputs a Portable Arbitrary Map. Shown are some examples for 10000 particles on 300x300 grid.
 
<syntaxhighlight lang="ats">
(* This program pours all the particles onto the square at once, with
one of them as seed, and then lets the particles move around.
 
Compile with
patscc -std=gnu2x -D_GNU_SOURCE -g -O3 -DATS_MEMALLOC_LIBC brownian_tree_task.dats
 
You may need the -D_GNU_SOURCE to get a declaration of the
random(3) function. *)
(*------------------------------------------------------------------*)
 
%{^
#include <stdlib.h>
%}
 
#include "share/atspre_staload.hats"
 
#define NIL list_nil ()
#define :: list_cons
 
extern castfn lint2int : {i : int} lint i -<> int i
implement g1int2int<lintknd,intknd> i = lint2int i
 
extern fn random () : [i : nat] lint i = "mac#random"
extern fn srandom (seed : uint) : void = "mac#srandom"
extern fn atoi (s : string) : int = "mac#atoi"
 
(*------------------------------------------------------------------*)
 
datatype grid_position =
| Wall
| Empty
| Sticky
| Freely_moving
 
fn {}
grid_position_equal
(x : grid_position,
y : grid_position)
:<> bool =
case+ x of
| Wall () => (case+ y of Wall () => true | _ => false)
| Empty () => (case+ y of Empty () => true | _ => false)
| Sticky () => (case+ y of Sticky () => true | _ => false)
| Freely_moving () =>
(case+ y of Freely_moving () => true | _ => false)
 
fn {}
grid_position_notequal
(x : grid_position,
y : grid_position)
:<> bool =
~grid_position_equal (x, y)
 
overload = with grid_position_equal
overload <> with grid_position_notequal
 
(*------------------------------------------------------------------*)
 
abstype container (w : int, h : int) = ptr
 
local
 
typedef _container (w : int, h : int) =
'{M = matrixref (grid_position, w, h),
w = int w,
h = int h}
 
in (* local *)
 
assume container (w, h) = _container (w, h)
 
fn {}
container_make
{w, h : pos}
(w : int w,
h : int h)
: container (w, h) =
'{M = matrixref_make_elt<grid_position> (i2sz w, i2sz h, Empty),
w = w, h = h}
 
fn {}
container_width
{w, h : pos}
(C : container (w, h))
: int w =
C.w
 
fn {}
container_height
{w, h : pos}
(C : container (w, h))
: int h =
C.h
 
fn {}
container_get_at
{w, h : pos}
(C : container (w, h),
x : intBtwe (~1, w),
y : intBtwe (~1, h))
: grid_position =
let
macdef M = C.M
in
if (0 <= x) * (x < C.w) * (0 <= y) * (y < C.h) then
M[x, C.h, y]
else
Wall
end
 
fn
container_set_at
{w, h : pos}
(C : container (w, h),
x : intBtw (0, w),
y : intBtw (0, h),
gpos : grid_position)
: void =
let
macdef M = C.M
in
M[x, C.h, y] := gpos
end
 
end (* local *)
 
overload width with container_width
overload height with container_height
overload [] with container_get_at
overload [] with container_set_at
 
(*------------------------------------------------------------------*)
 
fn
random_direction () :
@(intBtwe (~1, 1), intBtwe (~1, 1)) =
let
val r1 = random ()
val r2 = random ()
val dx : intBtwe (0, 2) = g1i2i (r1 \nmod 3)
and dy : intBtwe (0, 2) = g1i2i (r2 \nmod 3)
in
@(pred dx, pred dy)
end
 
fn
in_sticky_position
{w, h : pos}
(C : container (w, h),
x : intBtw (0, w),
y : intBtw (0, h))
: bool =
(C[pred x, pred y] = Sticky () ||
C[pred x, y] = Sticky () ||
C[pred x, succ y] = Sticky () ||
C[succ x, pred y] = Sticky () ||
C[succ x, y] = Sticky () ||
C[succ x, succ y] = Sticky () ||
C[x, pred y] = Sticky () ||
C[x, succ y] = Sticky ())
 
fn
find_placement_for_another_particle
{w, h : pos}
(C : container (w, h))
: @(intBtw (0, w), intBtw (0, h)) =
let
val w = width C and h = height C
 
fun
loop () : @(intBtw (0, w), intBtw (0, h)) =
let
val r1 = random ()
val r2 = random ()
val x : intBtw (0, w) = g1i2i (r1 \nmod w)
and y : intBtw (0, h) = g1i2i (r2 \nmod h)
in
if C[x, y] <> Empty () then
loop ()
else
@(x, y)
end
in
loop ()
end
 
fn
move_particles
{w, h : pos}
(C : container (w, h),
particles : &List0 @(intBtw (0, w), intBtw (0, h)) >> _)
: void =
let
typedef coords = @(intBtw (0, w), intBtw (0, h))
 
fun
loop {n : nat} .<n>.
(particles : list (coords, n),
new_lst : List0 coords)
: List0 coords =
case+ particles of
| NIL => new_lst
| @(x0, y0) :: tl =>
let
val @(dx, dy) = random_direction ()
val x1 = x0 + dx and y1 = y0 + dy
in
if C[x1, y1] = Empty () then
let
val () = assertloc (0 <= x1)
val () = assertloc (x1 < width C)
val () = assertloc (0 <= y1)
val () = assertloc (y1 < height C)
in
C[x1, y1] := C[x0, y0];
C[x0, y0] := Empty ();
loop (tl, @(x1, y1) :: new_lst)
end
else
(* Our rule is: if there is anything where it WOULD have
moved to, then the particle does not move. *)
loop (tl, @(x0, y0) :: new_lst)
end
in
particles := loop (particles, NIL)
end
 
fn
find_which_particles_are_stuck
{w, h : pos}
(C : container (w, h),
particles : &List0 @(intBtw (0, w), intBtw (0, h)) >> _)
: void =
(* Our rule is: if a particle is next to something that ALREADY was
stuck, then it too is stuck. Otherwise it remains free. *)
let
typedef coords = @(intBtw (0, w), intBtw (0, h))
 
fun
loop {n : nat} .<n>.
(particles : list (coords, n),
new_lst : List0 coords)
: List0 coords =
case+ particles of
| NIL => new_lst
| @(x, y) :: tl =>
if in_sticky_position (C, x, y) then
begin
C[x, y] := Sticky ();
loop (tl, new_lst)
end
else
loop (tl, @(x, y) :: new_lst)
in
particles := loop (particles, NIL)
end
 
fn
pour_particles
{w, h : pos}
{n : nat}
(C : container (w, h),
n : int n,
free_particles : &List0 @(intBtw (0, w), intBtw (0, h))?
>> List0 @(intBtw (0, w), intBtw (0, h)))
: void =
if n = 0 then
free_particles := NIL
else
let
typedef coords = @(intBtw (0, w), intBtw (0, h))
 
fun
loop {i : nat | i <= n - 1}
.<(n - 1) - i>.
(particles : list (coords, i),
i : int i)
: list (coords, n - 1) =
if i = pred n then
particles
else
let
val @(x, y) = find_placement_for_another_particle C
in
C[x, y] := Freely_moving;
loop (@(x, y) :: particles, succ i)
end
 
val @(xseed, yseed) = find_placement_for_another_particle C
in
C[xseed, yseed] := Sticky ();
free_particles := loop (NIL, 0)
end
 
fn
go_until_all_particles_are_stuck
{w, h : pos}
(C : container (w, h),
free_particles : List0 @(intBtw (0, w), intBtw (0, h)))
: void =
let
typedef coords = @(intBtw (0, w), intBtw (0, h))
 
fun
loop (free_particles : &List0 coords >> _) : void =
case+ free_particles of
| NIL => ()
| _ :: _ =>
begin
move_particles (C, free_particles);
find_which_particles_are_stuck (C, free_particles);
loop free_particles
end
 
var free_particles : List0 coords = free_particles
in
find_which_particles_are_stuck (C, free_particles);
loop free_particles
end
 
fn
build_a_tree {w, h : pos}
{n : nat}
(w : int w,
h : int h,
n : int n)
: container (w, h) =
let
val C = container_make (w, h)
var free_particles : List0 @(intBtw (0, w), intBtw (0, h))
in
pour_particles (C, n, free_particles);
go_until_all_particles_are_stuck (C, free_particles);
C
end
 
fn
write_a_PAM_image
{w, h : pos}
(outf : FILEref,
C : container (w, h),
seed : uint)
: void =
let
val w = width C and h = height C
 
fun
count_particles
{x, y : nat | x <= w; y <= h}
.<h - y, w - x>.
(x : int x,
y : int y,
n : int)
: int =
if y = h then
n
else if x = w then
count_particles (0, succ y, n)
else if C[x, y] = Empty () then
count_particles (succ x, y, n)
else
count_particles (succ x, y, succ n)
 
fun
loop {x, y : nat | x <= w; y <= h}
.<h - y, w - x>.
(x : int x,
y : int y)
: void =
if y = h then
()
else if x = w then
loop (0, succ y)
else
begin
fprint_val<char>
(outf, if C[x, y] = Empty () then '\1' else '\0');
loop (succ x, y)
end
in
fprintln! (outf, "P7");
fprintln! (outf, "# Number of particles = ",
count_particles (0, 0, 0));
fprintln! (outf, "# Seed = ", seed);
fprintln! (outf, "WIDTH ", width C);
fprintln! (outf, "HEIGHT ", height C);
fprintln! (outf, "DEPTH 1");
fprintln! (outf, "MAXVAL 1");
fprintln! (outf, "TUPLTYPE BLACKANDWHITE");
fprintln! (outf, "ENDHDR");
loop (0, 0)
end
 
(*------------------------------------------------------------------*)
 
implement
main0 (argc, argv) =
let
val args = list_vt2t (listize_argc_argv (argc, argv))
val nargs = argc
in
if nargs <> 5 then
begin
fprintln! (stderr_ref, "Usage: ", args[0],
" width height num_particles seed");
exit 1
end
else
let
val w = g1ofg0 (atoi (args[1]))
and h = g1ofg0 (atoi (args[2]))
and num_particles = g1ofg0 (atoi (args[3]))
and seed = g1ofg0 (atoi (args[4]))
in
if (w < 1) + (h < 1) + (num_particles < 0) + (seed < 0) then
begin
fprintln! (stderr_ref, "Illegal command line argument.");
exit 1
end
else
let
val seed : uint = g0i2u seed
val () = srandom seed
val C = build_a_tree (w, h, num_particles)
in
write_a_PAM_image (stdout_ref, C, seed)
end
end
end
 
(*------------------------------------------------------------------*)
</syntaxhighlight>
 
=={{header|AutoHotkey}}==
{{works with|AutoHotkey_L}}
Takes a little while to run, be patient.
Requires the [http://www.autohotkey.com/forum/topic32238.html GDI+ Standard Library by Tic]
<syntaxhighlight lang="ahk">SetBatchLines -1
Process, Priority,, high
size := 400
D := .08
num := size * size * d
field:= Object()
field[size//2, size//2] := true ; set the seed
lost := 0
 
Loop % num
{
x := Rnd(1, size), y := Rnd(1, size)
Loop
{
oldX := X, oldY := Y
x += Rnd(-1, 1), y += Rnd(1, -1)
If ( field[x, y] )
{
field[oldX, oldY] := true
break
}
If ( X > Size ) or ( Y > Size) or ( X < 1 ) or ( Y < 1 )
{
lost++
break
}
}
}
 
pToken := Gdip_startup()
pBitmap := Gdip_CreateBitmap(size, size)
loop %size%
{
x := A_index
Loop %size%
{
If ( field[x, A_Index] )
{
Gdip_SetPixel(pBitmap, x, A_Index, 0xFF0000FF)
}
}
}
Gdip_SaveBitmapToFile(pBitmap, "brownian.png")
Gdip_DisposeImage(pBitmap)
Gdip_Shutdown(pToken)
Run brownian.png
 
MsgBox lost %lost%
 
Rnd(min, max){
Random, r, min, max
return r
}</syntaxhighlight>Sample output file [http://www.autohotkey.net/~crazyfirex/Images/brownian.png here]
 
=={{header|BBC BASIC}}==
{{works with|BBC BASIC for Windows}}
<syntaxhighlight lang="bbcbasic"> SYS "SetWindowText", @hwnd%, "Brownian Tree"
SIZE = 400
VDU 23,22,SIZE;SIZE;8,16,16,0
GCOL 10
REM set the seed:
PLOT SIZE, SIZE
OFF
REPEAT
REM set particle's initial position:
REPEAT
X% = RND(SIZE)-1
Y% = RND(SIZE)-1
UNTIL POINT(2*X%,2*Y%) = 0
REPEAT
oldX% = X%
oldY% = Y%
X% += RND(3) - 2
Y% += RND(3) - 2
UNTIL POINT(2*X%,2*Y%)
IF X%>=0 IF X%<SIZE IF Y%>=0 IF Y%<SIZE PLOT 2*oldX%,2*oldY%
UNTIL FALSE
</syntaxhighlight>
[[File:Brownian_BBC.gif]]
=={{header|C}}==
{{libheader|FreeImage}}
<langsyntaxhighlight lang="c">#include <string.h>
#include <stdlib.h>
#include <time.h>
Line 78 ⟶ 854:
FreeImage_Save(FIF_BMP, img, "brownian_tree.bmp", 0);
FreeImage_Unload(img);
}</langsyntaxhighlight>
 
'''Bold text'''
===Alternative Version===
{{trans|D}}
This version writes the image as Portable Bit Map to stdout and doesn't move already set particles.
<syntaxhighlight lang="c">#include <stdio.h>
#include <stdlib.h>
#include <time.h>
#include <stdbool.h>
 
#define SIDE 600
#define NUM_PARTICLES 10000
 
bool W[SIDE][SIDE];
 
int main() {
srand((unsigned)time(NULL));
W[SIDE / 2][SIDE / 2] = true;
 
for (int i = 0; i < NUM_PARTICLES; i++) {
unsigned int x, y;
OVER: do {
x = rand() % (SIDE - 2) + 1;
y = rand() % (SIDE - 2) + 1;
} while (W[y][x]);
 
while (W[y-1][x-1] + W[y-1][x] + W[y-1][x+1] +
W[y][x-1] + W[y][x+1] +
W[y+1][x-1] + W[y+1][x] + W[y+1][x+1] == 0) {
unsigned int dxy = rand() % 8;
if (dxy > 3) dxy++;
x += (dxy % 3) - 1;
y += (dxy / 3) - 1;
if (x < 1 || x >= SIDE - 1 || y < 1 || y >= SIDE - 1)
goto OVER;
}
 
W[y][x] = true;
}
 
printf("P1\n%d %d\n", SIDE, SIDE);
for (int r = 0; r < SIDE; r++) {
for (int c = 0; c < SIDE; c++)
printf("%d ", W[r][c]);
putchar('\n');
}
return 0;
}</syntaxhighlight>
Run-time about 12.4 seconds with SIDE=600, NUM_PARTICLES=10000.
=={{header|C sharp|C#}}==
{{works with|C#|3.0}}
{{libheader|System.Drawing}}
<langsyntaxhighlight lang="csharp">using System;
using System.Drawing;
 
Line 132 ⟶ 957:
}
}
}</langsyntaxhighlight>
=={{header|C++}}==
[[File:brownianTree_cpp.png|300px]]
 
For an animated version based on this same code see: [[Brownian tree/C++ animated]]
=={{header|D}}==
<syntaxhighlight lang="cpp">#include <windows.h>
D V.2, from the C version, writes a Portable Bit Map image to the stdout.
#include <iostream>
#include <string>
 
//--------------------------------------------------------------------
A more efficient version generates particles in a disk not too much larger than the current tree.
using namespace std;
<lang d>import std.c.stdlib: rand, srand;
import std.c.time: time;
import std.stdio: printf, putchar;
 
//--------------------------------------------------------------------
enum int WORLD_WIDTH = 800;
enum states { SEED, GROWING, MOVING, REST };
enum int WORLD_HEIGHT = WORLD_WIDTH;
enum treeStates { NONE, MOVER, TREE };
enum int NUM_PARTICLES = 10_000;
const int MAX_SIDE = 480, MAX_MOVERS = 511, MAX_CELLS = 15137;
 
//--------------------------------------------------------------------
static assert(NUM_PARTICLES > 0);
class point
static assert((WORLD_WIDTH * WORLD_HEIGHT * 0.7) > NUM_PARTICLES);
{
public:
point() { x = y = 0; }
point( int a, int b ) { x = a; y = b; }
void set( int a, int b ) { x = a; y = b; }
 
int x, y;
alias ubyte[WORLD_WIDTH][WORLD_HEIGHT] TWorld;
};
//--------------------------------------------------------------------
class movers
{
public:
point pos;
bool moving;
movers() : moving( false ){}
};
//--------------------------------------------------------------------
class myBitmap
{
public:
myBitmap() : pen( NULL ) {}
~myBitmap()
{
DeleteObject( pen );
DeleteDC( hdc );
DeleteObject( bmp );
}
 
bool create( int w, int h )
void dla(ref TWorld world) {
{
// put the tree seed
BITMAPINFO bi;
world[WORLD_HEIGHT / 2][WORLD_WIDTH / 2] = 1;
ZeroMemory( &bi, sizeof( bi ) );
 
bi.bmiHeader.biSize = sizeof( bi.bmiHeader );
foreach (_; 0 .. NUM_PARTICLES) {
bi.bmiHeader.biBitCount = sizeof( DWORD ) * 8;
// set particle's initial position
bi.bmiHeader.biCompression = BI_RGB;
int px = rand() % WORLD_WIDTH;
bi.bmiHeader.biPlanes = 1;
int py = rand() % WORLD_HEIGHT;
bi.bmiHeader.biWidth = w;
bi.bmiHeader.biHeight = -h;
 
HDC dc = GetDC( GetConsoleWindow() );
while (true) { // move particle
bmp = CreateDIBSection( dc, &bi, DIB_RGB_COLORS, &pBits, NULL, 0 );
// randomly choose a direction
if( !bmp ) return false;
int dx = rand() % 3 - 1; // offsets
int dy = rand() % 3 - 1;
 
hdc = CreateCompatibleDC( dc );
if (dx + px < 0 || dx + px >= WORLD_WIDTH ||
SelectObject( hdc, bmp );
dy + py < 0 || dy + py >= WORLD_HEIGHT) {
ReleaseDC( GetConsoleWindow(), dc );
// plop the particle into some other random location
 
px = rand() % WORLD_WIDTH;
width = w; height = h;
py = rand() % WORLD_HEIGHT;
 
} else if (world[py + dy][px + dx]) {
return true;
// bumped into something, particle set
}
world[py][px] = 1;
 
break;
void } else {clear()
{
// move particle
ZeroMemory( pBits, width * height * sizeof( DWORD ) );
py += dy;
}
px += dx;
 
}
void setPenColor( DWORD clr )
{
if( pen ) DeleteObject( pen );
pen = CreatePen( PS_SOLID, 1, clr );
SelectObject( hdc, pen );
}
 
void saveBitmap( string path )
{
BITMAPFILEHEADER fileheader;
BITMAPINFO infoheader;
BITMAP bitmap;
DWORD* dwpBits;
DWORD wb;
HANDLE file;
 
GetObject( bmp, sizeof( bitmap ), &bitmap );
 
dwpBits = new DWORD[bitmap.bmWidth * bitmap.bmHeight];
ZeroMemory( dwpBits, bitmap.bmWidth * bitmap.bmHeight * sizeof( DWORD ) );
ZeroMemory( &infoheader, sizeof( BITMAPINFO ) );
ZeroMemory( &fileheader, sizeof( BITMAPFILEHEADER ) );
 
infoheader.bmiHeader.biBitCount = sizeof( DWORD ) * 8;
infoheader.bmiHeader.biCompression = BI_RGB;
infoheader.bmiHeader.biPlanes = 1;
infoheader.bmiHeader.biSize = sizeof( infoheader.bmiHeader );
infoheader.bmiHeader.biHeight = bitmap.bmHeight;
infoheader.bmiHeader.biWidth = bitmap.bmWidth;
infoheader.bmiHeader.biSizeImage = bitmap.bmWidth * bitmap.bmHeight * sizeof( DWORD );
 
fileheader.bfType = 0x4D42;
fileheader.bfOffBits = sizeof( infoheader.bmiHeader ) + sizeof( BITMAPFILEHEADER );
fileheader.bfSize = fileheader.bfOffBits + infoheader.bmiHeader.biSizeImage;
 
GetDIBits( hdc, bmp, 0, height, ( LPVOID )dwpBits, &infoheader, DIB_RGB_COLORS );
 
file = CreateFile( path.c_str(), GENERIC_WRITE, 0, NULL,
CREATE_ALWAYS, FILE_ATTRIBUTE_NORMAL, NULL );
WriteFile( file, &fileheader, sizeof( BITMAPFILEHEADER ), &wb, NULL );
WriteFile( file, &infoheader.bmiHeader, sizeof( infoheader.bmiHeader ), &wb, NULL );
WriteFile( file, dwpBits, bitmap.bmWidth * bitmap.bmHeight * 4, &wb, NULL );
CloseHandle( file );
 
delete [] dwpBits;
}
 
HDC getDC() { return hdc; }
int getWidth() { return width; }
int getHeight() { return height; }
 
private:
HBITMAP bmp;
HDC hdc;
HPEN pen;
void *pBits;
int width, height;
};
//--------------------------------------------------------------------
class brownianTree
{
public:
brownianTree()
{
_bmp.create( MAX_SIDE, MAX_SIDE );
init();
}
 
void init()
{
_cellCount = 0;
ZeroMemory( _grid, sizeof( _grid ) );
_bmp.clear();
_state = SEED;
}
 
bool mainLoop()
{
switch( _state )
{
case REST: saveTree(); return false;
case SEED: doSeed(); break;
case GROWING: startMovers(); break;
case MOVING: moveMovers();
}
return true;
}
 
myBitmap* getBmp() { return &_bmp; }
 
private:
void saveTree()
{
for( int y = 0; y < MAX_SIDE; y++ )
for( int x = 0; x < MAX_SIDE; x++ )
if( _grid[x][y] == TREE )
SetPixel( _bmp.getDC(), x, y, RGB( 255, 120, 0 ) );
 
_bmp.saveBitmap( "f:\\rc\\tree.bmp" );
}
 
void doSeed()
{
int x = MAX_SIDE - MAX_SIDE / 2, y = MAX_SIDE / 4;
_grid[rand() % x + y][rand() % x + y] = TREE;
_cellCount++;
_state = GROWING;
}
 
void addMover( movers* m )
{
m->moving = true;
int x = MAX_SIDE - MAX_SIDE / 2, y = MAX_SIDE / 4, a, b;
while( true )
{
a = rand() % x + y; b = rand() % x + y;
if( _grid[a][b] == NONE ) break;
}
 
m->pos.set( a, b );
_grid[a][b] = MOVER;
}
 
void startMovers()
{
movers* m;
for( int c = 0; c < MAX_MOVERS; c++ )
{
m = &_movers[c];
addMover( m );
}
_state = MOVING;
}
 
void addToTree( movers* m )
{
m->moving = false;
_grid[m->pos.x][m->pos.y] = TREE;
if( ++_cellCount >= MAX_CELLS ) _state = REST;
 
COORD c = { 0, 1 };
SetConsoleCursorPosition( GetStdHandle( STD_OUTPUT_HANDLE ), c );
cout << "Cells added: " << _cellCount
<< " from " << MAX_CELLS << " => "
<< static_cast<float>( 100 * _cellCount ) /
static_cast<float>( MAX_CELLS )
<< "% ";
}
 
bool moveIt( movers* m )
{
point f[8]; int ff = 0;
for( int y = -1; y < 2; y++ )
{
for( int x = -1; x < 2; x++ )
{
if( !x && !y ) continue;
int a = m->pos.x + x, b = m->pos.y + y;
if( a < 0 || b < 0 || a >= MAX_SIDE || b >= MAX_SIDE )
{
addToTree( m );
return true;
}
switch( _grid[a][b] )
{
case TREE:
addToTree( m );
return true;
case NONE:
f[ff++].set( a, b );
}
}
}
 
if( ff < 1 ) return false;
 
_grid[m->pos.x][m->pos.y] = NONE;
m->pos = f[rand() % ff];
_grid[m->pos.x][m->pos.y] = MOVER;
 
return false;
}
}
 
void moveMovers()
void toPBM(ref TWorld world) {
{
printf("P1\n"); // Type=Portable bitmap, Encoding=ASCII
movers* mm;
printf("%d %d\n", WORLD_WIDTH, WORLD_HEIGHT);
for( int m = 0; m < MAX_MOVERS; m++ )
foreach (ref line; world) {
{
foreach (pixel; line)
mm = &_movers[m];
putchar(pixel ? '1' : '0');
if( !mm->moving ) putchar('\n')continue;
if( moveIt( mm ) && _cellCount < MAX_CELLS ) addMover( mm );
}
}
 
states _state;
BYTE _grid[MAX_SIDE][MAX_SIDE];
myBitmap _bmp;
int _cellCount;
movers _movers[MAX_MOVERS];
};
//--------------------------------------------------------------------
int main( int argc, char* argv[] )
{
ShowWindow( GetConsoleWindow(), SW_MAXIMIZE );
srand( GetTickCount() );
 
brownianTree tree;
 
DWORD now = GetTickCount();
while( tree.mainLoop() );
 
now = GetTickCount() - now;
cout << endl << endl << "It took "
<< now / 1000
<< " seconds to complete the task!" << endl << endl;
 
BitBlt( GetDC( GetConsoleWindow() ), 20, 90, MAX_SIDE, MAX_SIDE,
tree.getBmp()->getDC(), 0, 0, SRCCOPY );
 
system( "pause" );
return 0;
}
//--------------------------------------------------------------------</syntaxhighlight>
=={{header|Common Lisp}}==
When the random walk lands on a set pixel it sets the pixel at the previous position.
An alternate method sets a pixel if the current position is vacant and at least one neighbour is set.
The former produces denser trees than the latter. If compiled with SBCL, providing a command line argument will invoke the latter method.
Requires Quicklisp library manager and the CL-GD package for producing PNG images.
<syntaxhighlight lang="lisp">;;; brownian.lisp
;;; sbcl compile: first load and then (sb-ext:save-lisp-and-die "brownian" :executable t :toplevel #'brownian::main)
(ql:quickload "cl-gd")
 
(defpackage #:brownian
void main() {
(:use #:cl #:cl-gd))
srand(cast(uint)time(null));
(in-package #:brownian)
TWorld world;
 
dla(world);
(defvar *size* 512)
toPBM(world);
(defparameter bitmap (make-array *size*))
}</lang>
(dotimes (i *size*)
One output, WORLD_WIDTH=40, WORLD_HEIGHT=14, NUM_PARTICLES=30:
(setf (svref bitmap i) (make-array *size* :element-type 'bit)))
<pre>P1
 
40 14
;;; is pixel at coord set? returns coord if so otherwise nil if not set or invalid
0000000000000000000000000000000000000000
;;; type:pair->pair|nil
0000000000000000000000000000000000000000
(defun set-p (coord)
0000000000000000000000000000000000000000
(and coord (= (sbit (svref bitmap (car coord)) (cdr coord)) 1) coord))
0000000000000000000000000000000000000000
 
0000000000000000000010000000000000000000
;;; valid coord predicate, return its arg if valid or nil otherwise
0000000000000000000101100010000000000000
;;; type:pair->pair|nil
0000000000000000000111001100000000000000
(defun coord-p (coord)
0000000000000000000011011000000000000000
(and ((lambda (v hi) (and (>= v 0) (< v hi))) (car coord) *size*)
0000000000000001101011111000000000000000
((lambda (v hi) (and (>= v 0) (< v hi))) (cdr coord) *size*)
0000000000000001011110011000000000000000
coord))
0000000000000000100000000000000000000000
 
0000000000000000000000000000000000000000
;;; valid coord predicate for the ith neighbour, return its arg if valid or nil otherwise
0000000000000000000000000000000000000000
;;; type:pair->pair|nil
0000000000000000000000000000000000000000</pre>
(defun coordi-p (coord i)
(coord-p (cons (+ (car coord) (nth i '(-1 -1 -1 0 0 1 1 1)))
(+ (cdr coord) (nth i '(-1 0 1 -1 1 -1 0 1))))))
 
;;; random walk until out of bounds or hit occupied pixel
;;; assumes start is valid vacant coord, return start or nil if off-grid
;;; type:pair->pair|nil
(defun random-walk (start)
(let ((next (coordi-p start (random 8))))
(if (set-p next) start
(and next (random-walk next)))))
 
;;; random walk until out of bounds or or adjacent to occupied pixel
;;; assumes start is valid vacant coord, return start or nil if off-grid
;;; type:pair->pair|nil
(defun random-walk2 (start)
(if (some #'set-p
(remove-if #'null (mapcar (lambda (i) (coordi-p start i)) '(0 1 2 3 4 5 6 7))))
start
(let ((next (coordi-p start (random 8))))
(and next (random-walk2 next)))))
 
(defparameter use-walk2 nil)
(defun main ()
(setf *random-state* (make-random-state t)) ;; randomize
(when (cdr sb-ext:*posix-argv*) (setf use-walk2 t)) ;; any cmd line arg -> use alt walk algorithm
(with-image* (*size* *size*)
(allocate-color 0 0 0) ; background color
 
;;; set the desired number of pixels in image as a pct (10%) of total
(let ((target (truncate (* 0.10 (* *size* *size*))))
(green (allocate-color 104 156 84)))
(defun write-pixel (coord)
(set-pixel (car coord) (cdr coord) :color green)
(setf (sbit (svref bitmap (car coord)) (cdr coord)) 1)
coord)
;; initial point set
(write-pixel (cons (truncate (/ *size* 2)) (truncate (/ *size* 2))))
;; iterate until target # of pixels are set
(do ((i 0 i)
(seed (cons (random *size*) (random *size*)) (cons (random *size*) (random *size*))))
((= i target) )
(let ((newcoord (and (not (set-p seed)) (if use-walk2 (random-walk2 seed) (random-walk seed)))))
(when newcoord
(write-pixel newcoord)
(incf i)
;; report every 5% of progress
(when (zerop (rem i (round (* target 0.05))))
(format t "~A% done.~%" (round (/ i target 0.01))))))))
(write-image-to-file "brownian.png"
:compression-level 6 :if-exists :supersede)))
</syntaxhighlight>
=={{header|D}}==
Uses the module of the Grayscale Image task. Partial {{trans|PureBasic}}
<syntaxhighlight lang="d">void main() {
import core.stdc.stdio, std.random, grayscale_image;
 
enum uint side = 600; // Square world side.
enum uint num_particles = 10_000;
static assert(side > 2 && num_particles < (side ^^ 2 * 0.7));
 
auto rng = unpredictableSeed.Xorshift;
ubyte[side][side] W; // World.
W[side / 2][side / 2] = 1; // Set tree root.
 
foreach (immutable _; 0 .. num_particles) {
// Random initial particle position.
OVER: uint x, y;
do {
x = uniform(1, side - 1, rng);
y = uniform(1, side - 1, rng);
} while (W[y][x]); // Assure the chosen cell is empty.
 
while (W[y-1][x-1] + W[y-1][x] + W[y-1][x+1] +
W[y][x-1] + W[y][x+1] +
W[y+1][x-1] + W[y+1][x] + W[y+1][x+1] == 0) {
// Randomly choose a direction (Moore neighborhood).
uint dxy = uniform(0, 8, rng);
if (dxy > 3) dxy++; // To avoid the center.
x += (dxy % 3) - 1;
y += (dxy / 3) - 1;
if (x < 1 || x >= side - 1 || y < 1 || y >= side - 1)
goto OVER;
}
 
W[y][x] = 1; // Touched, set the cell.
}
 
ubyte[] data = (&W[0][0])[0 .. side ^^ 2]; // Flat view.
data[] += 255;
Image!ubyte.fromData(data, side, side).savePGM("brownian_tree.pgm");
}</syntaxhighlight>
World side = 600, num_particles = 10_000, cropped (about 20 seconds run-time with dmd, about 4.3 seconds with ldc2):
<center>[[File:Dla_10000_d.png]]</center>
=={{header|Delphi}}==
<langsyntaxhighlight lang="delphi">const
SIZE = 256;
NUM_PARTICLES = 1000;
Line 271 ⟶ 1,444:
FreeAndNil(B);
end;
end;</langsyntaxhighlight>
=={{header|EasyLang}}==
 
[https://easylang.dev/show/#cod=dZHLboMwEEX3/oqzLoqxiahUCfIjiAUlRrVK7IjQFv6+snmkqpKFrfH1eM6dcet7PxxRaLTojaOrajKleAm7uPhvQ67IlRhMO6JkHpboKr3lkKCVqinRwlHyppQSPx+2N1gKnIDBXE0zCoCJkqFxZ+vG+PiAjvr8RP9yo+3pqnmHTQFYU5xihhSwwHR0EBmekmkpG8J5JSd3xJED2Qp+KNuOiQKFH5i3YOJURhdRXOKYDe+DaT5XvtwqPLC9eYQ42smTkgWb6QoO0/oz6EXqqtnfK/n/pWzoYT90WC7+jH6lZPMH7frTMiPBkuLin2/Xt96Y654un7QlhRS/ Run it]
 
<syntaxhighlight>
color3 0 1 1
len f[] 200 * 200
move 50 50
rect 0.5 0.5
f[100 * 200 + 100] = 1
n = 9000
while i < n
repeat
x = randint 200 - 1
y = randint 200 - 1
until f[y * 200 + x + 1] <> 1
.
while 1 = 1
xo = x
yo = y
x += randint 3 - 2
y += randint 3 - 2
if x < 0 or y < 0 or x >= 200 or y >= 200
break 1
.
if f[y * 200 + x + 1] = 1
move xo / 2 yo / 2
rect 0.5 0.5
f[yo * 200 + xo + 1] = 1
i += 1
if i mod 16 = 0
color3 0.2 + i / n 1 1
sleep 0
.
break 1
.
.
.
</syntaxhighlight>
 
=={{header|Evaldraw}}==
 
Based on the C version. Shows the brownian tree animate. Color each particle based on the time it settled. Dont overwrite existing particles.
 
[[File:Brownian tree from initial particle at center.gif|thumb|alt=Brownian trees form patterns similar to dendrites in nature|Animated brownian tree over the coarse of circa 1000 frames]]
 
<syntaxhighlight lang="c">
enum{SIZE=256, PARTICLES_PER_FRAME=10, PARTICLE_OK, GIVE_UP};
static world[SIZE][SIZE];
()
{
// set the seed
if (numframes==0) world[SIZE/2][SIZE/2] = 1;
t = klock();
simulate_brownian_tree(t);
 
cls(0);
for (y = 0; y < SIZE; y++){
for (x = 0; x < SIZE; x++){
cell = world[y][x];
if ( cell ) {
s = 100; // color scale
setcol(128+(s*cell % 128), 128+(s*.7*cell % 128), 128+(s*.1*cell % 128) );
setpix(x,y);
}
}
}
moveto(0,SIZE+15);
setcol(0xffffff);
printf("%g frames", numframes);
}
 
plop_particle(&px, &py) {
for (try=0; try<1000; try++) {
px = int(rnd*SIZE);
py = int(rnd*SIZE);
if (world[py][px] == 0) return PARTICLE_OK;
}
return GIVE_UP;
}
 
simulate_brownian_tree(time){
for(iter=0; iter<PARTICLES_PER_FRAME; iter++) // Rate of particle creation
{
// set particle's initial position
px=0; py=0;
if ( plop_particle(px,py) == GIVE_UP ) return;
 
while (1) { // Keep iterating until we bump into a solid particle
// randomly choose a direction
dx = int(rnd * 3) - 1;
dy = int(rnd * 3) - 1;
if (dx + px < 0 || dx + px >= SIZE || dy + py < 0 || dy + py >= SIZE)
{
// Restart if outside of screen
if ( plop_particle(px,py) == GIVE_UP ) return;
}else if (world[py + dy][px + dx]){
// bumped into something
world[py][px] = time;
break;
}else{
py += dy;
px += dx;
}
}
}
}
 
</syntaxhighlight>
 
=={{header|Factor}}==
This example sets four spawn points, one in each corner of the image, giving the result a vague x-shaped appearance. For visual reasons, movement is restricted to diagonals. So be careful if you change the seed or spawns — they should all fall on the same diagonal.
headerUSING: accessors images images.loader kernel literals math
math.vectors random sets ;
FROM: sets => in? ;
EXCLUDE: sequences => move ;
IN: rosetta-code.brownian-tree
 
CONSTANT: size 512
CONSTANT: num-particles 30000
CONSTANT: seed { 256 256 }
CONSTANT: spawns { { 10 10 } { 502 10 } { 10 502 } { 502 502 } }
CONSTANT: bg-color B{ 0 0 0 255 }
CONSTANT: fg-color B{ 255 255 255 255 }
 
: in-bounds? ( loc -- ? )
dup { 0 0 } ${ size 1 - dup } vclamp = ;
 
: move ( loc -- loc' )
dup 2 [ { 1 -1 } random ] replicate v+ dup in-bounds?
[ nip ] [ drop ] if ;
 
: grow ( particles -- particles' )
spawns random dup
[ 2over swap in? ] [ drop dup move swap ] until nip
swap [ adjoin ] keep ;
 
: brownian-data ( -- seq )
HS{ $ seed } clone num-particles 1 - [ grow ] times { }
set-like ;
 
: blank-bitmap ( -- bitmap )
size sq [ bg-color ] replicate B{ } concat-as ;
 
: init-img ( -- img )
<image>
${ size size } >>dim
BGRA >>component-order
ubyte-components >>component-type
blank-bitmap >>bitmap ;
 
: brownian-img ( -- img )
init-img dup brownian-data
[ swap [ fg-color swap first2 ] dip set-pixel-at ] with each
;
 
: save-brownian-tree-image ( -- )
brownian-img "brownian.png" save-graphic-image ;
 
MAIN: save-brownian-tree-image</syntaxhighlight>
{{out}}
[https://i.imgur.com/qDVylB9.png image]
=={{header|Fantom}}==
 
<langsyntaxhighlight lang="fantom">
using fwt
using gfx
Line 377 ⟶ 1,713:
}
}
</syntaxhighlight>
</lang>
 
=={{header|Fortran}}==
{{works with|Fortran|95 and later}}
Line 386 ⟶ 1,721:
For RCImageBasic and RCImageIO, see [[Basic bitmap storage/Fortran]] and [[Write ppm file#Fortran]]
 
<langsyntaxhighlight lang="fortran">program BrownianTree
use RCImageBasic
use RCImageIO
Line 491 ⟶ 1,826:
end subroutine draw_brownian_tree
 
end program</langsyntaxhighlight>
=={{header|FreeBASIC}}==
<syntaxhighlight lang="freebasic">' version 16-03-2017
' compile with: fbc -s gui
 
Const As ULong w = 400
Const As ULong w1 = w -1
 
Dim As Long x, y, lastx, lasty
Dim As Long count, max = w * w \ 4
 
ScreenRes w, w, 8 ' windowsize 400 * 400, 8bit
' hit any key to stop or mouseclick on close window [X]
WindowTitle "hit any key to stop and close the window"
 
Palette 0, 0 ' black
Palette 1, RGB( 1, 1, 1) ' almost black
Palette 2, RGB(255, 255, 255) ' white
Palette 3, RGB( 0, 255, 0) ' green
 
Line (0, 0) - (w1, w1), 0, BF ' make field black
Line (0, 0) - (w1, w1), 1, B ' draw border in almost black color
 
Randomize Timer
x = Int(Rnd * 11) - 5
y = Int(Rnd * 11) - 5
 
PSet(w \ 2 + x, w \ 2 + y), 3 ' place seed near center
 
Do
Do ' create new particle
x = Int(Rnd * w1) + 1
y = Int(Rnd * w1) + 1
Loop Until Point(x, y) = 0 ' black
PSet(x, y), 2
 
Do
lastx = x
lasty = y
Do
x = lastx + Int(Rnd * 3) -1
y = lasty + Int(Rnd * 3) -1
Loop Until Point(x, y) <> 1
 
If Point(x, y) = 3 Then
PSet(lastx, lasty), 3
Exit Do ' exit do loop and create new particle
End If
 
PSet(lastx, lasty), 0
PSet(x,y), 2
 
If Inkey <> "" Or Inkey = Chr(255) + "k" Then
End
End If
Loop
 
count += 1
Loop Until count > max
 
Beep : Sleep 5000
End</syntaxhighlight>
=={{header|Gnuplot}}==
{{Works with|gnuplot|5.0 (patchlevel 3) and above}}
 
===Plotting helper file for load command===
'''plotff.gp''' - Plotting from any data-file with 2 columns (space delimited), and writing to png-file.<br>
Especially useful to plot colored fractals using points.
<syntaxhighlight lang="gnuplot">
## plotff.gp 11/27/16 aev
## Plotting from any data-file with 2 columns (space delimited), and writing to png-file.
## Especially useful to plot colored fractals using points.
## Note: assign variables: clr, filename and ttl (before using load command).
reset
set terminal png font arial 12 size 640,640
ofn=filename.".png"
set output ofn
unset border; unset xtics; unset ytics; unset key;
set size square
dfn=filename.".dat"
set title ttl font "Arial:Bold,12"
plot dfn using 1:2 with points pt 7 ps 0.5 lc @clr
set output
</syntaxhighlight>
 
===Versions #1 - #4. Plotting from PARI/GP generated dat-files===
'''Note:''' dat-files are [[http://rosettacode.org/wiki/Brownian_tree#PARI.2FGP| PARI/GP]] generated output files.
[[File:BT1gp.png|right|thumb|Output BT1gp.png]]
[[File:BT2gp.png|right|thumb|Output BT2gp.png]]
[[File:BT3gp.png|right|thumb|Output BT3gp.png]]
[[File:BT41gp.png|right|thumb|Output BT41gp.png]]
[[File:BT42gp.png|right|thumb|Output BT42gp.png]]
[[File:BT43gp.png|right|thumb|Output BT43gp.png]]
 
<syntaxhighlight lang="gnuplot">
## BTff.gp 11/27/16 aev
## Plotting 6 Brownian tree pictures.
## dat-files are PARI/GP generated output files:
## http://rosettacode.org/wiki/Brownian_tree#PARI.2FGP
#cd 'C:\gnupData'
 
##BT1
clr = '"dark-green"'
filename = "BTAH1"
ttl = "Brownian Tree v.#1"
load "plotff.gp"
 
##BT2
clr = '"brown"'
filename = "BTOC1"
ttl = "Brownian Tree v.#2"
load "plotff.gp"
 
##BT3
clr = '"navy"'
filename = "BTSE1"
ttl = "Brownian Tree v.#3"
load "plotff.gp"
 
##BT41
clr = '"red"'
filename = "BTPB1"
ttl = "Brownian Tree v.#4-1"
load "plotff.gp"
 
##BT42
clr = '"red"'
filename = "BTPB2"
ttl = "Brownian Tree v.#4-2"
load "plotff.gp"
 
##BT43
clr = '"red"'
filename = "BTPB3"
ttl = "Brownian Tree v.#4-3"
load "plotff.gp"
</syntaxhighlight>
{{Output}}
<pre>
1. All BTff.gp commands.
2. All plotted png-files:
BT1gp.png, BT2gp.png, BT3gp.png, BT41gp.png, BT43gp.png, BT43gp.png.
</pre>
=={{header|Go}}==
[[file:GoTree.png|right|thumb|Output png]]
The interpretation here of "collide" in the case of a new particle generated on top of a pixel of the existing tree is not to ignore the particle, but to find a place for it nearby. This properly increases the brightness of the area, reflecting that a particle was generated in the area. Visually, it appears to strengthen existing spines of the tree.
 
Using standard image library:
<syntaxhighlight lang="go">package main
 
import (
"fmt"
"image"
"image/color"
"image/png"
"math/rand"
"os"
)
 
const w = 400 // image width
const h = 300 // image height
const n = 15000 // number of particles to add
const frost = 255 // white
 
var g *image.Gray
 
func main() {
g = image.NewGray(image.Rectangle{image.Point{0, 0}, image.Point{w, h}})
// off center seed position makes pleasingly asymetrical tree
g.SetGray(w/3, h/3, color.Gray{frost})
generate:
for a := 0; a < n; {
// generate random position for new particle
rp := image.Point{rand.Intn(w), rand.Intn(h)}
if g.At(rp.X, rp.Y).(color.Gray).Y == frost {
// position is already set. find a nearby free position.
for {
rp.X += rand.Intn(3) - 1
rp.Y += rand.Intn(3) - 1
// execpt if we run out of bounds, consider the particle lost.
if !rp.In(g.Rect) {
continue generate
}
if g.At(rp.X, rp.Y).(color.Gray).Y != frost {
break
}
}
} else {
// else particle is in free space. let it wander
// until it touches tree
for !hasNeighbor(rp) {
rp.X += rand.Intn(3) - 1
rp.Y += rand.Intn(3) - 1
// but again, if it wanders out of bounds consider it lost.
if !rp.In(g.Rect) {
continue generate
}
}
}
// x, y now specify a free position toucing the tree.
g.SetGray(rp.X, rp.Y, color.Gray{frost})
a++
// progress indicator
if a%100 == 0 {
fmt.Println(a, "of", n)
}
}
f, err := os.Create("tree.png")
if err != nil {
fmt.Println(err)
return
}
err = png.Encode(f, g)
if err != nil {
fmt.Println(err)
}
f.Close()
}
 
var n8 = []image.Point{
{-1, -1}, {-1, 0}, {-1, 1},
{0, -1}, {0, 1},
{1, -1}, {1, 0}, {1, 1}}
 
func hasNeighbor(p image.Point) bool {
for _, n := range n8 {
o := p.Add(n)
if o.In(g.Rect) && g.At(o.X, o.Y).(color.Gray).Y == frost {
return true
}
}
return false
}</syntaxhighlight>
Nearly the same, version below works with code from the bitmap task:
<syntaxhighlight lang="go">package main
 
// Files required to build supporting package raster are found in:
// * Bitmap
// * Grayscale image
// * Write a PPM file
 
import (
"fmt"
"math/rand"
"raster"
)
 
const w = 400 // image width
const h = 300 // image height
const n = 15000 // number of particles to add
const frost = 65535 // white
 
var g *raster.Grmap
 
func main() {
g = raster.NewGrmap(w, h)
// off center seed position makes pleasingly asymetrical tree
g.SetPx(w/3, h/3, frost)
var x, y int
generate:
for a := 0; a < n; {
// generate random position for new particle
x, y = rand.Intn(w), rand.Intn(h)
switch p, ok := g.GetPx(x, y); p {
case frost:
// position is already set. find a nearby free position.
for p == frost {
x += rand.Intn(3) - 1
y += rand.Intn(3) - 1
p, ok = g.GetPx(x, y)
 
// execpt if we run out of bounds, consider the particle lost.
if !ok {
continue generate
}
}
default:
// else particle is in free space. let it wander
// until it touches tree
for !hasNeighbor(x, y) {
x += rand.Intn(3) - 1
y += rand.Intn(3) - 1
// but again, if it wanders out of bounds consider it lost.
_, ok = g.GetPx(x, y)
if !ok {
continue generate
}
}
}
// x, y now specify a free position toucing the tree.
g.SetPx(x, y, frost)
a++
// progress indicator
if a%100 == 0 {
fmt.Println(a, "of", n)
}
}
g.Bitmap().WritePpmFile("tree.ppm")
}
 
var n8 = [][]int{
{-1, -1}, {-1, 0}, {-1, 1},
{ 0, -1}, { 0, 1},
{ 1, -1}, { 1, 0}, { 1, 1}}
 
func hasNeighbor(x, y int) bool {
for _, n := range n8 {
if p, ok := g.GetPx(x+n[0], y+n[1]); ok && p == frost {
return true
}
}
return false
}</syntaxhighlight>
=={{header|Haskell}}==
 
The modules <code>[[Bitmap#Haskell|Bitmap]]</code>, <code>[[Bitmap/Write a PPM file#Haskell|Bitmap.Netpbm]]</code>, and <code>[[Bitmap/Histogram#Haskell|Bitmap.BW]]</code> are on Rosetta Code. The commented-out type signatures require [http://hackage.haskell.org/trac/haskell-prime/wiki/ScopedTypeVariables scoped type variables] in order to function.
 
<langsyntaxhighlight lang="haskell">import Control.Monad
import Control.Monad.ST
import Data.STRef
Line 542 ⟶ 2,188:
liftM2 (,) [1 .. width - 2] [0, height - 1]
off = black
on = white</langsyntaxhighlight>
=={{header|Icon}} and {{header|Unicon}}==
[[File:Brownian_tree_unicon.png|400px|thumb|right|400x400 PA=70% SA=50% D=8%]]
In this version the seed is randomly set within an inner area and particles are injected in an outer ring.
 
<syntaxhighlight lang="icon">link graphics,printf
 
procedure main() # brownian tree
 
Density := .08 # % particles to area
SeedArea := .5 # central area to confine seed
ParticleArea := .7 # central area to exclude particles appearing
Height := Width := 400 # canvas
 
Particles := Height * Width * Density
Field := list(Height)
every !Field := list(Width)
 
Size := sprintf("size=%d,%d",Width,Height)
Fg := sprintf("fg=%s",?["green","red","blue"])
Label := sprintf("label=Brownian Tree %dx%d PA=%d%% SA=%d%% D=%d%%",
Width,Height,ParticleArea*100,SeedArea*100,Density*100)
WOpen(Label,Size,Fg,"bg=black") | stop("Unable to open Window")
 
sx := Height * SetInside(SeedArea)
sy := Width * SetInside(SeedArea)
Field[sx,sy] := 1
DrawPoint(sx,sy) # Seed the field
 
Lost := 0
 
every 1 to Particles do {
repeat {
px := Height * SetOutside(ParticleArea)
py := Width * SetOutside(ParticleArea)
if /Field[px,py] then
break # don't materialize in the tree
}
repeat {
dx := delta()
dy := delta()
if not ( xy := Field[px+dx,py+dy] ) then {
Lost +:= 1
next # lost try again
}
if \xy then
break # collision
px +:= dx # move to clear spot
py +:= dy
}
Field[px,py] := 1
DrawPoint(px,py) # Stick the particle
}
printf("Brownian Tree Complete: Particles=%d Lost=%d.\n",Particles,Lost)
WDone()
end
 
procedure delta() #: return a random 1 pixel perturbation
return integer(?0 * 3) - 1
end
 
procedure SetInside(core) #: set coord inside area
return core * ?0 + (1-core)/2
end
 
procedure SetOutside(core) #: set coord outside area
pt := ?0 * (1 - core)
pt +:= ( pt > (1-core)/2, core)
return pt
end</syntaxhighlight>
 
{{libheader|Icon Programming Library}}
[http://www.cs.arizona.edu/icon/library/src/procs/graphics.icn graphics.icn provides graphics]
[http://www.cs.arizona.edu/icon/library/src/procs/printf.icn printf.icn provides printf]
=={{header|J}}==
 
<langsyntaxhighlight lang="j">brtr=:4 :0
seed=. ?x
clip=. 0 >. (<:x) <."1 ]
Line 564 ⟶ 2,283:
end.
field
)</langsyntaxhighlight>
 
Example use:
 
<langsyntaxhighlight lang="j"> require'viewmat'
viewmat 480 640 brtr 30000</langsyntaxhighlight>
 
Note that building a brownian tree like this takes a while and would be more interesting if this were animated.
 
=={{header|Java}}==
{{libheader|Swing}} {{libheader|AWT}}
<langsyntaxhighlight lang="java">import java.awt.Graphics;
import java.awt.image.BufferedImage;
import java.util.*;
Line 646 ⟶ 2,364:
}
}
}</langsyntaxhighlight>
 
This is an alternate version which is a port of most of the code here.
=={{header|JavaScript}} + &lt;canvas>==
This code does not use a GUI and saves the output to image.png.
<syntaxhighlight lang="java">import java.awt.Point;
import java.awt.image.BufferedImage;
import java.io.File;
import java.io.IOException;
 
import javax.imageio.ImageIO;
 
public class BasicBrownianTree {
 
private int pixelsLost;
private Point p;
private Point nextP;
private int pixelCount;
private int width;
private int height;
private int color;
private BufferedImage img;
 
public BasicBrownianTree( int argb, int size, double density ) {
pixelsLost = 0;
p = new Point();
nextP = new Point();
width = size;
height = size;
color = argb;
pixelCount = (int) ( width * height * density );
img = new BufferedImage( width, height, BufferedImage.TYPE_INT_ARGB );
}
 
public void generate() {
// print text to the console
System.out.println( "Drawing " + pixelCount + " pixels" );
int background = img.getRGB( 0, 0 );
img.setRGB( width / 2, height / 2, color );
 
for( int i = 0; i < pixelCount; i++ ) {
p.x = (int) ( Math.random() * width );
p.y = (int) ( Math.random() * height );
 
while ( true ) {
int dx = (int) ( Math.random() * 3 ) - 1;
int dy = (int) ( Math.random() * 3 ) - 1;
nextP.setLocation( p.x + dx, p.y + dy );
// handle out-of-bounds
if ( nextP.x < 0 || nextP.x >= width || nextP.y < 0
|| nextP.y >= height ) {
// increment the number of pixels lost and escape the loop
pixelsLost++;
break;
}
if ( img.getRGB( nextP.x, nextP.y ) != background ) {
img.setRGB( p.x, p.y, color );
break;
}
p.setLocation( nextP );
}
// Print a message every 2%
if ( i % ( pixelCount / 50 ) == 0 ) {
System.out.println( "Done with " + i + " pixels" );
}
}
// We're done. Let the user know how many pixels were lost
System.out.println( "Finished. Pixels lost = " + pixelsLost );
}
 
public BufferedImage getImage() {
return img;
}
 
public int getWidth() {
return width;
}
 
public int getHeight() {
return height;
}
 
public static void main( String[] args ) {
// create the new generator
BasicBrownianTree generator = new BasicBrownianTree( 0x664444ff, 400, 0.4 );
// generate the image
generator.generate();
try {
// save the image to the file "image.png"
ImageIO.write( generator.getImage(), "png", new File( "image.png" ) );
} catch ( IOException e ) {
e.printStackTrace();
}
}
}</syntaxhighlight>
=={{header|JavaScript}}==
===Using canvas===
[http://switchb.org/kpreid/2010/brownian-tree/ Live version] <!-- If changing this example, add note this link is outdated -->
<langsyntaxhighlight lang="javascript">function brownian(canvasId, messageId) {
var canvas = document.getElementById(canvasId);
var ctx = canvas.getContext("2d");
Line 762 ⟶ 2,573:
test(x-1,y+1) || test(x,y+1) || test(x+1,y+1)) && progress > 0);
if (progress <= 0) {
document.getElementById(messageId).appendChild(document.createTextNode("Stopped for lack of room."));
document.createTextNode("Stopped for lack of room."));
clearInterval(animation);
break;
Line 777 ⟶ 2,589:
}, 1);
 
}</langsyntaxhighlight>
 
<langsyntaxhighlight lang="html"><html>
<head>
<script src="brownian.js"></script>
Line 787 ⟶ 2,599:
<div id="message"></div>
</body>
</html></langsyntaxhighlight>
=={{header|Julia}}==
{{works with|Julia|0.6}}
This solution puts the seed in the center of the canvas. Motes are generated randomly in space and do a simple drunkard's walk until they hit the tree or leave the canvas (unless the sides are made <tt>side</tt>). The Motes are colorized according to their &theta; in polar coordinates.
 
<syntaxhighlight lang="julia">using Images, FileIO
 
function main(h::Integer, w::Integer, side::Bool=false)
W0 = w >> 1
H0 = h >> 1
@inline function motecolor(x::Integer, y::Integer)
h = clamp(180 * (atan2(y - H0, x - W0) / π + 1.0), 0.0, 360.0)
return HSV(h, 0.5, 0.5)
end
 
img = zeros(RGB{N0f8}, h, w)
img[H0, W0] = RGB(1, 1, 1)
free = trues(h, w)
free[H0, W0] = false
for i in eachindex(img)
x = rand(1:h)
y = rand(1:w)
free[x, y] || continue
mc = motecolor(x, y)
for j in 1:1000
xp = x + rand(-1:1)
yp = y + rand(-1:1)
contained = checkbounds(Bool, img, xp, yp)
if contained && free[xp, yp]
x, y = xp, yp
continue
else
if side || (contained && !free[xp, yp])
free[x, y] = false
img[x, y] = mc
end
break
end
end
end
return img
end
 
imgnoside = main(256, 256)
imgwtside = main(256, 256, true)
save("data/browniantree_noside.jpg", imgnoside)
save("data/browniantree_wtside.jpg", imgwtside)</syntaxhighlight>
=={{header|Kotlin}}==
{{trans|Java}}
<syntaxhighlight lang="scala">// version 1.1.2
 
import java.awt.Graphics
import java.awt.image.BufferedImage
import java.util.*
import javax.swing.JFrame
class BrownianTree : JFrame("Brownian Tree"), Runnable {
private val img: BufferedImage
private val particles = LinkedList<Particle>()
 
private companion object {
val rand = Random()
}
 
private inner class Particle {
private var x = rand.nextInt(img.width)
private var y = rand.nextInt(img.height)
 
/* returns true if either out of bounds or collided with tree */
fun move(): Boolean {
val dx = rand.nextInt(3) - 1
val dy = rand.nextInt(3) - 1
if ((x + dx < 0) || (y + dy < 0) || (y + dy >= img.height) ||
(x + dx >= img.width)) return true
x += dx
y += dy
if ((img.getRGB(x, y) and 0xff00) == 0xff00) {
img.setRGB(x - dx, y - dy, 0xff00)
return true
}
return false
}
}
init {
setBounds(100, 100, 400, 300)
defaultCloseOperation = EXIT_ON_CLOSE
img = BufferedImage(width, height, BufferedImage.TYPE_INT_RGB)
img.setRGB(img.width / 2, img.height / 2, 0xff00)
}
 
override fun paint(g: Graphics) {
g.drawImage(img, 0, 0, this)
}
 
override fun run() {
(0 until 20000).forEach { particles.add(Particle()) }
while (!particles.isEmpty()) {
val iter = particles.iterator()
while (iter.hasNext()) {
if (iter.next().move()) iter.remove()
}
repaint()
}
}
}
 
fun main(args: Array<String>) {
val b = BrownianTree()
b.isVisible = true
Thread(b).start()
}</syntaxhighlight>
=={{header|Liberty BASIC}}==
<langsyntaxhighlight lang="lb">'[RC]Brownian motion tree
nomainwin
dim screen(600,600)
Line 872 ⟶ 2,795:
timer 0
close #1
end</langsyntaxhighlight>
=={{header|Locomotive Basic}}==
{{trans|ZX Spectrum Basic}}
This program is ideally run in [https://benchmarko.github.io/CPCBasic/cpcbasic.html CPCBasic] and should finish after about 20 to 25 minutes (Chrome, desktop CPU). At normal CPC speed, it would probably take several days to run when set to 10000 particles.
<syntaxhighlight lang="locobasic">10 MODE 1:DEFINT a-z:RANDOMIZE TIME:np=10000
20 INK 0,0:INK 1,26:BORDER 0
30 PLOT 320,200
40 FOR i=1 TO np
50 GOSUB 1000
60 IF TEST(x+1,y+1)+TEST(x,y+1)+TEST(x+1,y)+TEST(x-1,y-1)+TEST(x-1,y)+TEST(x,y-1)<>0 THEN 100
70 x=x+RND*2-1: y=y+RND*2-1
80 IF x<1 OR x>640 OR y<1 OR y>400 THEN GOSUB 1000
90 GOTO 60
100 PLOT x,y
110 NEXT
120 END
1000 ' Calculate new position
1010 x=RND*640
1020 y=RND*400
1030 RETURN</syntaxhighlight>
=={{header|Lua}}==
The output is stored in as a ppm-image. The source code of these output-functions is located at http://rosettacode.org/wiki/Bitmap/Write_a_PPM_file#Lua, http://rosettacode.org/wiki/Grayscale_image#Lua, http://rosettacode.org/wiki/Basic_bitmap_storage#Lua.
[[Bitmap/Write a PPM file#Lua]],
<lang lua>function SetSeed( f )
[[Grayscale image#Lua]],
[[Basic bitmap storage#Lua]].
<syntaxhighlight lang="lua">function SetSeed( f )
for i = 1, #f[1] do -- the whole boundary of the scene is used as the seed
f[1][i] = 1
Line 941 ⟶ 2,886:
end
end
Write_PPM( "brownian_tree.ppm", ConvertToColorImage(f) )</langsyntaxhighlight>
=={{header|Mathematica}}/{{header|Wolfram Language}}==
 
=={{header|Mathematica}}==
There is a [http://demonstrations.wolfram.com/DiffusionLimitedAggregation/ prettier version] at the Mathematica demo site. Its source code is also available there but it is not mine.
 
Loose {{trans|D}}
<langsyntaxhighlight Mathematicalang="mathematica">canvasdim = 1000;
n = 0.35*canvasdim^2;
canvas = ConstantArray[0, {canvasdim, canvasdim}];
Line 972 ⟶ 2,916:
{i, (particle + ds), MatrixPlot@canvas}
]
MatrixPlot[canvas,FrameTicks->None,ColorFunction->"DarkRainbow",ColorRules->{0 -> None}]</langsyntaxhighlight>
 
Result:
 
[[File:BrownianTree.png]]
=={{header|Nim}}==
{{libheader|imageman}}
 
<syntaxhighlight lang="nim">import random
import imageman
 
const
Size = 400 # Area size.
MaxXY = Size - 1 # Maximum possible value for x and y.
NPart = 25_000 # Number of particles.
Background = ColorRGBU [byte 0, 0, 0] # Background color.
Foreground = ColorRGBU [byte 50, 150, 255] # Foreground color.
 
randomize()
var image = initImage[ColorRGBU](Size, Size)
image.fill(Background)
image[Size div 2, Size div 2] = Foreground
 
for _ in 1..NPart:
 
block ProcessParticle:
while true: # Repeat until the particle is freezed.
 
# Choose position of particle.
var x, y = rand(MaxXY)
if image[x, y] == Foreground:
continue # Not free. Try again.
 
# Move the particle.
while true:
 
# Choose a motion.
let dx, dy = rand(-1..1)
inc x, dx
inc y, dy
if x notin 0..MaxXY or y notin 0..MaxXY:
break # Out of limits. Try again.
 
# Valid move.
if image[x, y] == Foreground:
# Not free. Freeze the particle at its previous position.
image[x - dx, y - dy] = Foreground
break ProcessParticle # Done. Process next particle.
 
# Save into a PNG file.
image.savePNG("brownian.png", compression = 9)</syntaxhighlight>
=={{header|OCaml}}==
{{trans|D}}
 
<langsyntaxhighlight lang="ocaml">let world_width = 800400
let world_height = 800400
let num_particles = 10_00020_000
let () =
Line 991 ⟶ 2,980:
let dla ~world =
(* particle values *)
let px = ref 0
and py = ref 0 in
(* put the tree seed *)
world.(world_height / 2).(world_width / 2) <- 1;
for i = 1 to num_particles do
(* looping helper function *)
let rec aux px py =
(* randomly choose a direction *)
let dx = (Random.int 3) - 1 (* offsets *)
and dy = (Random.int 3) - 1 in
 
if dx + px < 0 || dx + px >= world_width ||
dy + py < 0 || dy + py >= world_height then
(* plop the particle into some other random location *)
aux (Random.int world_width) (Random.int world_height)
else if world.(py + dy).(px + dx) <> 0 then
(* bumped into something, particle set *)
world.(py).(px) <- 1
else
aux (px + dx) (py + dy)
in
(* set particle's initial position *)
px :=aux (Random.int world_width;) (Random.int world_height)
py := Random.int world_height;
try
while (true) do (* move particle *)
(* randomly choose a direction *)
let dx = (Random.int 3) - 1 (* offsets *)
and dy = (Random.int 3) - 1 in
if (dx + !px < 0 || dx + !px >= world_width ||
dy + !py < 0 || dy + !py >= world_height) then begin
(* plop the particle into some other random location *)
px := Random.int world_width;
py := Random.int world_height;
end
else if (world.(!py + dy).(!px + dx) <> 0) then begin
(* bumped into something, particle set *)
world.(!py).(!px) <- 1;
raise Exit;
end
else begin
py := !py + dy;
px := !px + dx;
end
done
with Exit -> ()
done
Line 1,032 ⟶ 3,008:
Printf.printf "%d %d\n" world_width world_height;
Array.iter (fun line ->
Array.iter (fun pixel -> print_int pixel) line;
print_newline()
) world
Line 1,041 ⟶ 3,017:
dla ~world;
to_pbm ~world;
;;</langsyntaxhighlight>
 
better to compile to native code to get a faster program:
 
<pre>$ ocamlopt -o brownian_tree.opt brownian_tree.ml
$ ./brownian_tree.opt | display -</pre>
=={{header|Octave}}==
{{trans|C}}
 
<langsyntaxhighlight lang="octave">function r = browniantree(xsize, ysize = xsize, numparticle = 1000)
r = zeros(xsize, ysize, "uint8");
r(unidrnd(xsize), unidrnd(ysize)) = 1;
Line 1,072 ⟶ 3,052:
r = browniantree(200);
r( r > 0 ) = 255;
jpgwrite("browniantree.jpg", r, 100); % image package</langsyntaxhighlight>
=={{header|PARI/GP}}==
All versions #1 - #4 are based on using 4 small plotting helper functions, which are allowing to unify
all upgraded BrownianTreeX() functions and make them shorter.<br>
Note: all pictures are still almost the same after upgrading.
{{Works with|PARI/GP|2.9.1 and above}}
 
===Plotting helper functions===
<syntaxhighlight lang="parigp">
\\ 2 old plotting helper functions 3/2/16 aev
\\ insm(): Check if x,y are inside matrix mat (+/- p deep).
insm(mat,x,y,p=0)={my(xz=#mat[1,],yz=#mat[,1]);
return(x+p>0 && x+p<=xz && y+p>0 && y+p<=yz && x-p>0 && x-p<=xz && y-p>0 && y-p<=yz)}
\\ plotmat(): Simple plotting using a square matrix mat (filled with 0/1).
plotmat(mat)={
my(xz=#mat[1,],yz=#mat[,1],vx=List(),vy=vx,x,y);
for(i=1,yz, for(j=1,xz, if(mat[i,j]==0, next, listput(vx,i); listput(vy,j))));
print(" *** matrix(",xz,"x",yz,") ",#vy, " DOTS");
plothraw(Vec(vx),Vec(vy));
}
\\ 2 new plotting helper functions 11/27/16 aev
\\ wrtmat(): Writing file fn containing X,Y coordinates from matrix mat.
\\ Created primarily for using file in Gnuplot, also for re-plotting.
wrtmat(mat, fn)={
my(xz=#mat[1,],yz=#mat[,1],ws,d=0);
for(i=1,yz, for(j=1,xz, if(mat[i,j]==0, next, d++; ws=Str(i," ",j); write(fn,ws))));
print(" *** matrix(",xz,"x",yz,") ",d, " DOTS put in ",fn);
}
\\ plotff(): Plotting from a file written by the wrtmat().
\\ Saving possibly huge generation time if re-plotting needed.
plotff(fn)={
my(F,nf,vx=List(),vy=vx,Vr);
F=readstr(fn); nf=#F;
print(" *** Plotting from: ", fn, " - ", nf, " DOTS");
for(i=1,nf, Vr=stok(F[i],","); listput(vx,eval(Vr[1])); listput(vy,eval(Vr[2])));
plothraw(Vec(vx),Vec(vy));
}
</syntaxhighlight>
===Version #1. Translated from AutoHotkey.===
{{trans|AutoHotkey}}
[[File:BTAH1.png|right|thumb|Output BTAH1.png]]
 
<syntaxhighlight lang="parigp">
\\ Brownian tree v.#1. Translated from AutoHotkey
\\ 3/8/2016, upgraded 11/27/16 aev
\\ Where: size - size of a square matrix; lim - limit of testing dots;
\\ fn - file name (fn=""-only plot, fn!=""-only writing file)..
BrownianTree1(size,lim, fn="")={
my(Myx=matrix(size,size),sz=size-1,sz2=sz\2,x,y,ox,oy);
x=sz2; y=sz2; Myx[y,x]=1; \\ seed in center
print(" *** BT1 SEED: ",x,"/",y);
for(i=1,lim,
x=random(sz)+1; y=random(sz)+1;
while(1,
ox=x; oy=y;
x+=random(3)-1; y+=random(3)-1;
if(insm(Myx,x,y)&&Myx[y,x],
if(insm(Myx,ox,oy), Myx[oy,ox]=1; break));
if(!insm(Myx,x,y), break);
);\\wend
);\\ fend i
if(fn=="", plotmat(Myx), wrtmat(Myx, fn));
}
\\ Executing 1 or 2 lines below:
 
BrownianTree1(400,15000); \\BTAH1.png
 
{BrownianTree1(400,15000,"c:\\pariData\\BTAH1.dat");
plotff("c:\\pariData\\BTAH1.dat");} \\BTAH1.png
</syntaxhighlight>
 
{{Output}}
<pre>
> BrownianTree1(400,15000); \\BTAH1.png
*** BT1 SEED: 199/199
*** matrix(400x400) 3723 DOTS
*** last result computed in 25min, 53,141 ms.
 
*** BT1 SEED: 199/199
*** matrix(400x400) 3723 DOTS put in c:\pariData\BTAH1.dat
*** Plotting from: c:\pariData\BTAH1.dat - 3723 DOTS
</pre>
 
===Version #2. Translated from Octave.===
{{trans|Octave}}
Octave: {{trans|C}}
[[File:BTOC1.png|right|thumb|Output BTOC1.png]]
 
<syntaxhighlight lang="parigp">
\\ Brownian tree v.#2. Translated from Octave
\\ 3/8/2016, upgraded 11/27/16 aev
\\ Where: size - size of a square matrix; lim - limit of testing dots;
\\ fn - file name (fn=""-only plot, fn!=""-only writing file)..
BrownianTree2(size,lim, fn="")={
my(Myx=matrix(size,size),sz=size-1,dx,dy,x,y);
x=random(sz); y=random(sz); Myx[y,x]=1; \\ random seed
print(" *** BT2 SEED: ",x,"/",y);
for(i=1,lim,
x=random(sz)+1; y=random(sz)+1;
while(1,
dx=random(3)-1; dy=random(3)-1;
if(!insm(Myx,x+dx,y+dy), x=random(sz)+1; y=random(sz)+1,
if(Myx[y+dy,x+dx], Myx[y,x]=1; break, x+=dx; y+=dy));
);\\wend
);\\fend i
if(fn=="", plotmat(Myx), wrtmat(Myx, fn));
}
\\ Executing 1 or 2 lines below:
 
BrownianTree2(1000,3000); \\BTOC1.png
 
{BrownianTree2(1000,3000,"c:\\pariData\\BTOC1.dat");
plotff("c:\\pariData\\BTOC1.dat");} \\BTOC1.png
</syntaxhighlight>
 
{{Output}}
<pre>
> BrownianTree2(1000,3000); \\BTOC1.png
*** BT2 SEED: 697/753
*** matrix(1000x1000) 2984 DOTS
*** last result computed in 4h, 35min, 24,781 ms.
 
*** BT2 SEED: 434/407
*** matrix(1000x1000) 2981 DOTS put in c:\pariData\BTOC1.dat
*** Plotting from: c:\pariData\BTOC1.dat - 2981 DOTS
</pre>
 
===Version #3. Translated from Seed7.===
{{trans|Seed7}}
[[File:BTSE1.png|right|thumb|Output BTSE1.png]]
 
<syntaxhighlight lang="parigp">
\\ Brownian tree v.#3. Translated from Seed7
\\ 3/8/2016, upgraded 11/27/16 aev
\\ Where: size - size of a square matrix; lim - limit of testing dots;
\\ fn - file name (fn=""-only plot, fn!=""-only writing file)..
BrownianTree3(size,lim, fn="")={
my(Myx=matrix(size,size),sz=size-2,x,y,dx,dy,b=0);
x=random(sz); y=random(sz); Myx[y,x]=1; \\ random seed
print("*** BT3 SEED: ", x,"/",y);
for(i=1,lim,
x=random(sz); y=random(sz);
b=0; \\ bumped not
while(!b,
dx=random(3)-1; dy=random(3)-1;
if(!insm(Myx,x+dx,y+dy), x=random(sz); y=random(sz),
if(Myx[y+dy,x+dx]==1, Myx[y,x]=1; b=1, x+=dx; y+=dy);
);
);\\wend
);\\fend i
if(fn=="", plotmat(Myx), wrtmat(Myx, fn));
}
\\ Executing 1 or 2 lines below:
 
BrownianTree3(400,5000); \\BTSE1.png
 
{BrownianTree3(400,5000,"c:\\pariData\\BTSE1.dat");
plotff("c:\\pariData\\BTSE1.dat");} \\BTSE1.png
</syntaxhighlight>
 
{{Output}}
<pre>
> BrownianTree3(400,5000); \\BTSE1.png
*** BT3 SEED: 367/60
*** matrix(400x400) 4797 DOTS
*** last result computed in 57min, 57,375 ms.
 
*** BT3 SEED: 46/293
*** matrix(400x400) 4841 DOTS put in c:\pariData\BTSE1.dat
*** Plotting from: c:\pariData\BTSE1.dat - 4841 DOTS
</pre>
 
===Version #4. Translated from PureBasic.===
{{trans|PureBasic}}
[[File:BTPB1.png|right|thumb|Output BTPB1.png]]
[[File:BTPB2.png|right|thumb|Output BTPB2.png]]
[[File:BTPB3.png|right|thumb|Output BTPB3.png]]
 
<syntaxhighlight lang="parigp">
\\ Brownian tree v.#4. Translated from PureBasic
\\ 3/8/2016, upgraded 11/27/16 aev
\\ Where: size - size of a square matrix; lim - limit of testing dots;
\\ fn - file name (fn=""-only plot, fn!=""-only writing file)..
\\ s=1/2(random seed/seed in the center); p=0..n (level of the "deep" checking).
BrownianTree4(size,lim, fn="",s=1,p=0)={
my(Myx=matrix(size,size),sz=size-3,x,y);
\\ seed s=1 for BTPB1, s=2 for BTPB2, BTPB3
if(s==1,x=random(sz); y=random(sz), x=sz\2; y=sz\2); Myx[y,x]=1;
print(" *** BT4 SEED: ",x,"/",y);
for(i=1,lim,
if(!(i==1&&s==2), x=random(sz)+1; y=random(sz)+1);
while(insm(Myx,x,y,1)&&
(Myx[y+1,x+1]+Myx[y+1,x]+Myx[y+1,x-1]+Myx[y,x+1]+
Myx[y-1,x-1]+Myx[y,x-1]+Myx[y-1,x]+Myx[y-1,x+1])==0,
x+=random(3)-1; y+=random(3)-1;
\\ p=0 for BTPB1, BTPB2; p=5 for BTPB3
if(!insm(Myx,x,y,p), x=random(sz)+1; y=random(sz)+1;);
);\\wend
Myx[y,x]=1;
);\\fend i
if(fn=="", plotmat(Myx), wrtmat(Myx, fn));
}
\\ Executing 1 or 2 lines below:
 
BrownianTree4(200,4000); \\BTPB1.png
 
{BrownianTree4(200,4000,"c:\\pariData\\BTPB1.dat");
plotff("c:\\pariData\\BTPB1.dat");} \\BTPB1.png
 
BrownianTree4(200,4000,,2); \\BTPB2.png
 
{BrownianTree4(200,4000,"c:\\pariData\\BTPB2.dat",2);
plotff("c:\\pariData\\BTPB2.dat");} \\BTPB2.png
 
BrownianTree4(200,4000,,2,5); \\BTPB3.png
 
{BrownianTree4(200,4000,"c:\\pariData\\BTPB3.dat",2,5);
plotff("c:\\pariData\\BTPB3.dat");} \\BTPB3.png
</syntaxhighlight>
 
{{Output}}
<pre>
> BrownianTree4(200,4000); \\BTPB1.png
*** BT4 SEED: 133/133
*** matrix(200x200) 3813 DOTS
*** last result computed in 49,923 ms.
 
*** BT4 SEED: 184/104
*** matrix(200x200) 3805 DOTS put in c:\pariData\BTPB1.dat
*** Plotting from: c:\pariData\BTPB1.dat - 3805 DOTS
> BrownianTree4(200,4000,,2); \\BTPB2.png
*** BT4 SEED: 98/98
*** matrix(200x200) 3820 DOTS
*** last result computed in 40,047 ms.
*** BT4 SEED: 98/98
*** matrix(200x200) 3814 DOTS put in c:\pariData\BTPB2.dat
*** Plotting from: c:\pariData\BTPB2.dat - 3814 DOTS
> BrownianTree4(200,4000,,2,5); \\BTPB3.png
*** BT4 SEED: 98/98
*** matrix(200x200) 3622 DOTS
*** last result computed in 1min, 16,390 ms.
*** BT4 SEED: 98/98
*** matrix(200x200) 3641 DOTS put in c:\pariData\BTPB3.dat
*** Plotting from: c:\pariData\BTPB3.dat - 3641 DOTS
</pre>
=={{header|Perl}}==
[[File:brownian-00.png|thumb]][[File:brownian-05.png|thumb]][[File:brownian-11.png|thumb]]
Simulation code. Showing three sample images with different STEP and ATTRACT parameters, to demonstrate how sensitive the result is to them.
 
Code runs until the tree reached specified radius. Output is written to "test.eps" of wherever the current directory is.
<syntaxhighlight lang="perl">use strict;
use warnings;
 
use constant PI => 2*atan2(1,0); # π
use constant STEP => 0.5; # How far particle moves each step. Affects both speed and accuracy greatly
use constant STOP_RADIUS => 100; # When the tree reaches this far from center, end
 
# At each step, move this much towards center. Bigger numbers help the speed because
# particles are less likely to wander off, but greatly affects tree shape.
# Should be between 0 and 1 ish. Set to 0 for pain.
use constant ATTRACT => 0.2;
 
my @particles = map([ map([], 0 .. 2 * STOP_RADIUS) ], 0 .. 2 * STOP_RADIUS);
push @{ $particles[STOP_RADIUS][STOP_RADIUS] }, [0, 0];
my($r_start, $max_dist) = (3, 0);
 
sub dist2 {
no warnings 'uninitialized';
my ($dx, $dy) = ($_[0][0] - $_[1][0], $_[0][1] - $_[1][1]);
$dx * $dx + $dy * $dy
}
 
sub move {
my $p = shift;
# moved too far, kill particle
# return if dist2($p, [0, 0]) > 2 * $r_start * $r_start;
$p->[0] += 2 * $r_start while $p->[0] < -$r_start;
$p->[0] -= 2 * $r_start while $p->[0] > $r_start;
$p->[1] += 2 * $r_start while $p->[1] < -$r_start;
$p->[1] -= 2 * $r_start while $p->[1] > $r_start;
 
my ($ix, $iy) = (int($p->[0]), int($p->[1]));
my $dist = 2 * $r_start * $r_start;
my $nearest;
 
# see if the particle is close enough to stick to an exist one
for ($ix - 1 .. $ix + 1) {
my $idx = STOP_RADIUS + $_;
next if $idx > 2 * STOP_RADIUS || $idx < 0;
my $xs = $particles[ $idx ];
for ($iy - 1 .. $iy + 1) {
my $idx = STOP_RADIUS + $_;
next if $idx > 2 * STOP_RADIUS || $idx < 0;
for (@{ $xs->[ $idx ] }) {
my $d = dist2($p, $_);
next if $d > 2;
next if $d > $dist;
 
$dist = $d;
$nearest = $_;
}
}
}
 
# yes, found one
if ($nearest) {
my $displace = [ $p->[0] - $nearest->[0],
$p->[1] - $nearest->[1] ];
my $angle = atan2($displace->[1], $displace->[0]);
$p->[0] = $nearest->[0] + cos($angle);
$p->[1] = $nearest->[1] + sin($angle);
 
push @{$particles[$ix + STOP_RADIUS][$iy + STOP_RADIUS]}, [ @$p ];
$dist = sqrt dist2($p);
 
if ($dist + 10 > $r_start && $r_start < STOP_RADIUS + 10) {
$r_start = $dist + 10
}
if (int($dist + 1) > $max_dist) {
$max_dist = int($dist + 1);
# write_eps();
# system('pstopnm -portrait -xborder 0 -yborder 0 test.eps 2> /dev/null');
# system('pnmtopng test.eps001.ppm 2>/dev/null > test.png');
return 3 if $max_dist >= STOP_RADIUS;
}
return 2;
}
 
# random walk
my $angle = rand(2 * PI);
$p->[0] += STEP * cos($angle);
$p->[1] += STEP * sin($angle);
 
# drag particle towards center by some distance
my $nudge;
if (sqrt(dist2($p, [0, 0])) > STOP_RADIUS + 1) {
$nudge = 1;
} else {
$nudge = STEP * ATTRACT;
}
 
if ($nudge) {
$angle = atan2($p->[1], $p->[0]);
$p->[0] -= $nudge * cos($angle);
$p->[1] -= $nudge * sin($angle);
}
 
return 1;
}
 
my $count;
PARTICLE: while () {
my $a = rand(2 * PI);
my $p = [ $r_start * cos($a), $r_start * sin($a) ];
while (my $m = move $p) {
if ($m == 1) { next }
elsif ($m == 2) { $count++; last }
elsif ($m == 3) { last PARTICLE }
else { last }
}
print STDERR "$count $max_dist/@{[int($r_start)]}/@{[STOP_RADIUS]}\r" unless $count% 7;
}
 
sub write_eps {
my $size = 128;
my $p = $size / (STOP_RADIUS * 1.05);
my $b = STOP_RADIUS * $p;
if ($p < 1) {
$size = STOP_RADIUS * 1.05;
$p = 1;
$b = STOP_RADIUS;
}
my $hp = $p / 2;
 
open OUT, '>', 'test.eps';
print OUT <<~"HEAD";
%!PS-Adobe-3.0 EPSF-3.0
%%BoundingBox: 0 0 @{[$size*2, $size*2]}
$size $size translate
/l{ rlineto }def
/c{ $hp 0 360 arc fill }def
-$size -$size moveto
$size 2 mul 0 l
0 $size 2 mul l
-$size 2 mul 0 l
closepath
0 setgray fill
0 setlinewidth .1 setgray 0 0 $b 0 360 arc stroke
.8 setgray /TimesRoman findfont 16 scalefont setfont
-$size 10 add $size -16 add moveto
(Step = @{[STEP]} Attract = @{[ATTRACT]}) show
0 1 0 setrgbcolor newpath
HEAD
 
for (@particles) {
for (@$_) {
printf OUT "%.3g %.3g c ", map { $_ * $p } @$_ for @$_;
}
}
print OUT "\n%%EOF";
close OUT;
}
 
write_eps();</syntaxhighlight>
 
=={{header|Phix}}==
As-is, runs in about 2s, but can be very slow when bigger or (even worse) resize-able.
{{libheader|Phix/pGUI}}
<!--<syntaxhighlight lang="phix">(phixonline)-->
<span style="color: #000080;font-style:italic;">-- demo\rosetta\BrownianTree.exw</span>
<span style="color: #008080;">include</span> <span style="color: #000000;">pGUI</span><span style="color: #0000FF;">.</span><span style="color: #000000;">e</span>
<span style="color: #004080;">Ihandle</span> <span style="color: #000000;">dlg</span><span style="color: #0000FF;">,</span> <span style="color: #000000;">canvas</span>
<span style="color: #004080;">cdCanvas</span> <span style="color: #000000;">cddbuffer</span><span style="color: #0000FF;">,</span> <span style="color: #000000;">cdcanvas</span>
<span style="color: #008080;">function</span> <span style="color: #000000;">redraw_cb</span><span style="color: #0000FF;">(</span><span style="color: #004080;">Ihandle</span> <span style="color: #000080;font-style:italic;">/*ih*/</span><span style="color: #0000FF;">,</span> <span style="color: #004080;">integer</span> <span style="color: #000080;font-style:italic;">/*posx*/</span><span style="color: #0000FF;">,</span> <span style="color: #004080;">integer</span> <span style="color: #000080;font-style:italic;">/*posy*/</span><span style="color: #0000FF;">)</span>
<span style="color: #004080;">integer</span> <span style="color: #000000;">x</span><span style="color: #0000FF;">,</span><span style="color: #000000;">y</span><span style="color: #0000FF;">,</span><span style="color: #000000;">ox</span><span style="color: #0000FF;">,</span><span style="color: #000000;">oy</span>
<span style="color: #004080;">integer</span> <span style="color: #0000FF;">{</span><span style="color: #000000;">width</span><span style="color: #0000FF;">,</span> <span style="color: #000000;">height</span><span style="color: #0000FF;">}</span> <span style="color: #0000FF;">=</span> <span style="color: #7060A8;">IupGetIntInt</span><span style="color: #0000FF;">(</span><span style="color: #000000;">canvas</span><span style="color: #0000FF;">,</span> <span style="color: #008000;">"DRAWSIZE"</span><span style="color: #0000FF;">)</span>
<span style="color: #004080;">sequence</span> <span style="color: #000000;">grid</span> <span style="color: #0000FF;">=</span> <span style="color: #7060A8;">repeat</span><span style="color: #0000FF;">(</span><span style="color: #7060A8;">repeat</span><span style="color: #0000FF;">(</span><span style="color: #000000;">0</span><span style="color: #0000FF;">,</span><span style="color: #000000;">width</span><span style="color: #0000FF;">),</span><span style="color: #000000;">height</span><span style="color: #0000FF;">)</span>
<span style="color: #004080;">integer</span> <span style="color: #000000;">xy</span> <span style="color: #0000FF;">=</span> <span style="color: #7060A8;">floor</span><span style="color: #0000FF;">(</span><span style="color: #000000;">width</span><span style="color: #0000FF;">*</span><span style="color: #000000;">height</span><span style="color: #0000FF;">*</span><span style="color: #000000;">0.8</span><span style="color: #0000FF;">)</span>
<span style="color: #000080;font-style:italic;">--atom t = time()+1</span>
<span style="color: #000000;">grid</span><span style="color: #0000FF;">[</span><span style="color: #7060A8;">floor</span><span style="color: #0000FF;">(</span><span style="color: #000000;">width</span><span style="color: #0000FF;">/</span><span style="color: #000000;">2</span><span style="color: #0000FF;">)][</span><span style="color: #7060A8;">floor</span><span style="color: #0000FF;">(</span><span style="color: #000000;">height</span><span style="color: #0000FF;">/</span><span style="color: #000000;">2</span><span style="color: #0000FF;">)]</span> <span style="color: #0000FF;">=</span> <span style="color: #000000;">1</span>
<span style="color: #7060A8;">cdCanvasActivate</span><span style="color: #0000FF;">(</span><span style="color: #000000;">cddbuffer</span><span style="color: #0000FF;">)</span>
<span style="color: #7060A8;">cdCanvasClear</span><span style="color: #0000FF;">(</span><span style="color: #000000;">cddbuffer</span><span style="color: #0000FF;">)</span>
<span style="color: #008080;">for</span> <span style="color: #000000;">i</span><span style="color: #0000FF;">=</span><span style="color: #000000;">1</span> <span style="color: #008080;">to</span> <span style="color: #000000;">xy</span> <span style="color: #008080;">do</span>
<span style="color: #000000;">x</span> <span style="color: #0000FF;">=</span> <span style="color: #7060A8;">rand</span><span style="color: #0000FF;">(</span><span style="color: #000000;">width</span><span style="color: #0000FF;">)</span> <span style="color: #000000;">y</span> <span style="color: #0000FF;">=</span> <span style="color: #7060A8;">rand</span><span style="color: #0000FF;">(</span><span style="color: #000000;">height</span><span style="color: #0000FF;">)</span>
<span style="color: #000000;">ox</span> <span style="color: #0000FF;">=</span> <span style="color: #000000;">x</span> <span style="color: #000000;">oy</span> <span style="color: #0000FF;">=</span> <span style="color: #000000;">y</span>
<span style="color: #008080;">while</span> <span style="color: #000000;">x</span><span style="color: #0000FF;">>=</span><span style="color: #000000;">1</span> <span style="color: #008080;">and</span> <span style="color: #000000;">x</span><span style="color: #0000FF;"><=</span><span style="color: #000000;">width</span>
<span style="color: #008080;">and</span> <span style="color: #000000;">y</span><span style="color: #0000FF;">>=</span><span style="color: #000000;">1</span> <span style="color: #008080;">and</span> <span style="color: #000000;">y</span><span style="color: #0000FF;"><=</span><span style="color: #000000;">height</span> <span style="color: #008080;">do</span>
<span style="color: #008080;">if</span> <span style="color: #000000;">grid</span><span style="color: #0000FF;">[</span><span style="color: #000000;">y</span><span style="color: #0000FF;">][</span><span style="color: #000000;">x</span><span style="color: #0000FF;">]</span> <span style="color: #008080;">then</span>
<span style="color: #000000;">grid</span><span style="color: #0000FF;">[</span><span style="color: #000000;">oy</span><span style="color: #0000FF;">][</span><span style="color: #000000;">ox</span><span style="color: #0000FF;">]</span> <span style="color: #0000FF;">=</span> <span style="color: #000000;">1</span>
<span style="color: #7060A8;">cdCanvasPixel</span><span style="color: #0000FF;">(</span><span style="color: #000000;">cddbuffer</span><span style="color: #0000FF;">,</span> <span style="color: #000000;">ox</span><span style="color: #0000FF;">,</span> <span style="color: #000000;">oy</span><span style="color: #0000FF;">,</span> <span style="color: #000000;">#00FF00</span><span style="color: #0000FF;">)</span>
<span style="color: #008080;">exit</span>
<span style="color: #008080;">end</span> <span style="color: #008080;">if</span>
<span style="color: #000000;">ox</span> <span style="color: #0000FF;">=</span> <span style="color: #000000;">x</span> <span style="color: #000000;">x</span> <span style="color: #0000FF;">+=</span> <span style="color: #7060A8;">rand</span><span style="color: #0000FF;">(</span><span style="color: #000000;">3</span><span style="color: #0000FF;">)-</span><span style="color: #000000;">2</span>
<span style="color: #000000;">oy</span> <span style="color: #0000FF;">=</span> <span style="color: #000000;">y</span> <span style="color: #000000;">y</span> <span style="color: #0000FF;">+=</span> <span style="color: #7060A8;">rand</span><span style="color: #0000FF;">(</span><span style="color: #000000;">3</span><span style="color: #0000FF;">)-</span><span style="color: #000000;">2</span>
<span style="color: #008080;">end</span> <span style="color: #008080;">while</span>
<span style="color: #000080;font-style:italic;">-- -- if making the canvas bigger/resizeable,
-- -- put this in so that you can kill it.
-- if time()&gt;=t then
-- ?{i,xy}
-- t = time()+1
-- end if</span>
<span style="color: #008080;">end</span> <span style="color: #008080;">for</span>
<span style="color: #7060A8;">cdCanvasFlush</span><span style="color: #0000FF;">(</span><span style="color: #000000;">cddbuffer</span><span style="color: #0000FF;">)</span>
<span style="color: #008080;">return</span> <span style="color: #004600;">IUP_DEFAULT</span>
<span style="color: #008080;">end</span> <span style="color: #008080;">function</span>
<span style="color: #008080;">function</span> <span style="color: #000000;">map_cb</span><span style="color: #0000FF;">(</span><span style="color: #004080;">Ihandle</span> <span style="color: #000000;">ih</span><span style="color: #0000FF;">)</span>
<span style="color: #000000;">cdcanvas</span> <span style="color: #0000FF;">=</span> <span style="color: #7060A8;">cdCreateCanvas</span><span style="color: #0000FF;">(</span><span style="color: #004600;">CD_IUP</span><span style="color: #0000FF;">,</span> <span style="color: #000000;">ih</span><span style="color: #0000FF;">)</span>
<span style="color: #000000;">cddbuffer</span> <span style="color: #0000FF;">=</span> <span style="color: #7060A8;">cdCreateCanvas</span><span style="color: #0000FF;">(</span><span style="color: #004600;">CD_DBUFFER</span><span style="color: #0000FF;">,</span> <span style="color: #000000;">cdcanvas</span><span style="color: #0000FF;">)</span>
<span style="color: #7060A8;">cdCanvasSetBackground</span><span style="color: #0000FF;">(</span><span style="color: #000000;">cddbuffer</span><span style="color: #0000FF;">,</span> <span style="color: #004600;">CD_WHITE</span><span style="color: #0000FF;">)</span>
<span style="color: #7060A8;">cdCanvasSetForeground</span><span style="color: #0000FF;">(</span><span style="color: #000000;">cddbuffer</span><span style="color: #0000FF;">,</span> <span style="color: #004600;">CD_RED</span><span style="color: #0000FF;">)</span>
<span style="color: #008080;">return</span> <span style="color: #004600;">IUP_DEFAULT</span>
<span style="color: #008080;">end</span> <span style="color: #008080;">function</span>
<span style="color: #7060A8;">IupOpen</span><span style="color: #0000FF;">()</span>
<span style="color: #000000;">canvas</span> <span style="color: #0000FF;">=</span> <span style="color: #7060A8;">IupCanvas</span><span style="color: #0000FF;">(</span><span style="color: #004600;">NULL</span><span style="color: #0000FF;">)</span>
<span style="color: #7060A8;">IupSetAttribute</span><span style="color: #0000FF;">(</span><span style="color: #000000;">canvas</span><span style="color: #0000FF;">,</span> <span style="color: #008000;">"RASTERSIZE"</span><span style="color: #0000FF;">,</span> <span style="color: #008000;">"200x200"</span><span style="color: #0000FF;">)</span> <span style="color: #000080;font-style:italic;">-- fixed size</span>
<span style="color: #7060A8;">IupSetCallback</span><span style="color: #0000FF;">(</span><span style="color: #000000;">canvas</span><span style="color: #0000FF;">,</span> <span style="color: #008000;">"MAP_CB"</span><span style="color: #0000FF;">,</span> <span style="color: #7060A8;">Icallback</span><span style="color: #0000FF;">(</span><span style="color: #008000;">"map_cb"</span><span style="color: #0000FF;">))</span>
<span style="color: #000000;">dlg</span> <span style="color: #0000FF;">=</span> <span style="color: #7060A8;">IupDialog</span><span style="color: #0000FF;">(</span><span style="color: #000000;">canvas</span><span style="color: #0000FF;">,</span> <span style="color: #008000;">"RESIZE=NO"</span><span style="color: #0000FF;">)</span>
<span style="color: #7060A8;">IupSetAttribute</span><span style="color: #0000FF;">(</span><span style="color: #000000;">dlg</span><span style="color: #0000FF;">,</span> <span style="color: #008000;">"TITLE"</span><span style="color: #0000FF;">,</span> <span style="color: #008000;">"Brownian Tree"</span><span style="color: #0000FF;">)</span>
<span style="color: #7060A8;">IupSetCallback</span><span style="color: #0000FF;">(</span><span style="color: #000000;">canvas</span><span style="color: #0000FF;">,</span> <span style="color: #008000;">"ACTION"</span><span style="color: #0000FF;">,</span> <span style="color: #7060A8;">Icallback</span><span style="color: #0000FF;">(</span><span style="color: #008000;">"redraw_cb"</span><span style="color: #0000FF;">))</span>
<span style="color: #7060A8;">IupShow</span><span style="color: #0000FF;">(</span><span style="color: #000000;">dlg</span><span style="color: #0000FF;">)</span>
<span style="color: #008080;">if</span> <span style="color: #7060A8;">platform</span><span style="color: #0000FF;">()!=</span><span style="color: #004600;">JS</span> <span style="color: #008080;">then</span>
<span style="color: #7060A8;">IupMainLoop</span><span style="color: #0000FF;">()</span>
<span style="color: #7060A8;">IupClose</span><span style="color: #0000FF;">()</span>
<span style="color: #008080;">end</span> <span style="color: #008080;">if</span>
<!--</syntaxhighlight>-->
=={{header|PicoLisp}}==
<langsyntaxhighlight PicoLisplang="picolisp">(load "@lib/simul.l")
 
(de brownianTree (File Size Cnt)
Line 1,093 ⟶ 3,547:
(for This L
(prin (if (: pix) 1 0)) )
(prinl) ) ) ) )</langsyntaxhighlight>
Use:
<pre>(brownianTree "img.pbm" 300 9000)
(call 'display "img.pbm")</pre>
=={{header|Processing}}==
<syntaxhighlight lang="java">boolean SIDESTICK = false;
boolean[][] isTaken;
 
void setup() {
size(512, 512);
background(0);
isTaken = new boolean[width][height];
isTaken[width/2][height/2] = true;
}
 
void draw() {
int x = floor(random(width));
int y = floor(random(height));
if (isTaken[x][y]) {
return;
}
while (true) {
int xp = x + floor(random(-1, 2));
int yp = y + floor(random(-1, 2));
boolean iscontained = (
0 <= xp && xp < width &&
0 <= yp && yp < height
);
if (iscontained && !isTaken[xp][yp]) {
x = xp;
y = yp;
continue;
} else {
if (SIDESTICK || (iscontained && isTaken[xp][yp])) {
isTaken[x][y] = true;
set(x, y, #FFFFFF);
}
break;
}
}
if (frameCount > width * height) {
noLoop();
}
}</syntaxhighlight>
 
==={{header|Processing Python mode}}===
 
{{trans|Processing}}
 
<syntaxhighlight lang="python">SIDESTICK = False
 
def setup() :
global is_taken
size(512, 512)
background(0)
is_taken = [[False] * height for _ in range(width)]
is_taken[width/2][height/2] = True
 
 
def draw() :
x = floor(random(width))
y = floor(random(height))
if is_taken[x][y]:
return
while True:
xp = x + floor(random(-1, 2))
yp = y + floor(random(-1, 2))
is_contained = 0 <= xp < width and 0 <= yp < height
if is_contained and not is_taken[xp][yp]:
x = xp
y = yp
continue
else:
if SIDESTICK or (is_contained and is_taken[xp][yp]):
is_taken[x][y] = True
set(x, y, color(255))
break
if frameCount > width * height:
noLoop()</syntaxhighlight>
=={{header|PureBasic}}==
<langsyntaxhighlight PureBasiclang="purebasic">#Window1 = 0
#Image1 = 0
#ImgGadget = 0
Line 1,137 ⟶ 3,666:
Event = WaitWindowEvent()
Until Event = #PB_Event_CloseWindow
EndIf</langsyntaxhighlight>[[File:BrownianTree.pb.png]]
 
 
=={{header|Python}}==
{{libheader|pygame}}
<langsyntaxhighlight lang="python">import pygame, sys, os
from pygame.locals import *
from random import randint
Line 1,242 ⟶ 3,769:
while True:
input(pygame.event.get())
pygame.display.flip()</langsyntaxhighlight>
=={{header|R}}==
All versions #1 - #4 are based on using 2 small plotting helper functions, which are allowing to unify
all gpBrownianTreeX() functions and make them shorter.<br>
;Note:
* All pictures are ready to be uploaded when it would be allowed again.
{{trans|PARI/GP}}
{{Works with|R|3.3.1 and above}}
[[File:BT1R.png|right|thumb|Output BT1R.png]]
[[File:BT2R.png|right|thumb|Output BT2R.png]]
[[File:BT2aR.png|right|thumb|Output BT2aR.png]]
[[File:BT3R.png|right|thumb|Output BT3R.png]]
[[File:BT4R.png|right|thumb|Output BT4R.png]]
===Plotting helper functions===
;Note:
* All plotting helper functions are using a square matrix mat or 2 vectors X,Y from the dump file created by plotmat()
* The file names used are without extension (which will be added as ".png", ".dmp" and ".dat" when needed).
* Requesting dump file is useful if the generating/plotting time
is big. Having a dump file makes it easy and fast to repeat plotting
with different colors, titles, etc.
* If number of generated dots is very big then plotting from a dump
file could be very slow too. Actually, plotv2() shows almost "pure" plotting time.
 
<syntaxhighlight lang="r">
# plotmat(): Simple plotting using a square matrix mat (filled with 0/1). v. 8/31/16
# Where: mat - matrix; fn - file name; clr - color; ttl - plot title;
# dflg - writing dump file flag (0-no/1-yes): psz - picture size.
plotmat <- function(mat, fn, clr, ttl, dflg=0, psz=600) {
m <- nrow(mat); d <- 0;
X=NULL; Y=NULL;
pf = paste0(fn, ".png"); df = paste0(fn, ".dmp");
for (i in 1:m) {
for (j in 1:m) {if(mat[i,j]==0){next} else {d=d+1; X[d] <- i; Y[d] <- j;} }
};
cat(" *** Matrix(", m,"x",m,")", d, "DOTS\n");
# Dumping if requested (dflg=1).
if (dflg==1) {dump(c("X","Y"), df); cat(" *** Dump file:", df, "\n")};
# Plotting
plot(X,Y, main=ttl, axes=FALSE, xlab="", ylab="", col=clr, pch=20);
dev.copy(png, filename=pf, width=psz, height=psz);
# Cleaning
dev.off(); graphics.off();
}
 
# plotv2(): Simple plotting using 2 vectors (dumped into ".dmp" file by plotmat()).
# Where: fn - file name; clr - color; ttl - plot title; psz - picture size.
# v. 8/31/16
plotv2 <- function(fn, clr, ttl, psz=600) {
cat(" *** START:", date(), "clr=", clr, "psz=", psz, "\n");
cat(" *** File name -", fn, "\n");
pf = paste0(fn, ".png"); df = paste0(fn, ".dmp");
source(df);
d <- length(X);
cat(" *** Source dump-file:", df, d, "DOTS\n");
cat(" *** Plot file -", pf, "\n");
# Plotting
plot(X, Y, main=ttl, axes=FALSE, xlab="", ylab="", col=clr, pch=20);
# Writing png-file
dev.copy(png, filename=pf, width=psz, height=psz);
# Cleaning
dev.off(); graphics.off();
cat(" *** END:", date(), "\n");
}
</syntaxhighlight>
 
===Versions #1- #4.===
All functions are translated from [[Brownian_tree#PARI.2FGP| PARI/GP]].
;Note:
* All generating functions are using a square matrix mat to fill it with 0/1.
 
====Version #1.====
<syntaxhighlight lang="r">
# Generate and plot Brownian tree. Version #1.
# 7/27/16 aev
# gpBrownianTree1(m, n, clr, fn, ttl, dflg, psz)
# Where: m - defines matrix m x m; n - limit of the number of moves;
# fn - file name (.ext will be added); ttl - plot title; dflg - 0-no dump,
# 1-dump: psz - picture size.
gpBrownianTree1 <- function(m, n, clr, fn, ttl, dflg=0, psz=600)
{
cat(" *** START:", date(), "m=",m, "n=",n, "clr=",clr, "psz=", psz, "\n");
M <- matrix(c(0), ncol=m, nrow=m, byrow=TRUE);
# Seed in center
x <- m%/%2; y <- m%/%2;
M[x,y]=1;
pf=paste0(fn, ".png");
cat(" *** Plot file -", pf, "\n");
# Main loops
for (i in 1:n) {
if(i>1) {
x <- sample(1:m, 1, replace=FALSE)
y <- sample(1:m, 1, replace=FALSE)}
while(1) {
ox = x; oy = y;
x <- x + sample(-1:1, 1, replace=FALSE);
y <- y + sample(-1:1, 1, replace=FALSE);
if(x<=m && y<=m && x>0 && y>0 && M[x,y])
{if(ox<=m && oy<=m && ox>0 && oy>0) {M[ox,oy]=1; break}}
if(!(x<=m && y<=m && x>0 && y>0)) {break}
}
}
plotmat(M, fn, clr, ttl, dflg, psz);
cat(" *** END:",date(),"\n");
}
gpBrownianTree1(400,15000,"red", "BT1R", "Brownian Tree v.1", 1);
</syntaxhighlight>
 
{{Output}}
<pre>
> gpBrownianTree1(400,15000,"red", "BT1R", "Brownian Tree v.1", 1);
*** START: Mon Sep 05 13:07:27 2016 m= 400 n= 15000 clr= red psz= 600
*** Plot file - BT1R.png
*** Matrix( 400 x 400 ) 3639 DOTS
*** Dump file: BT1R.dmp
*** END: Mon Sep 05 14:06:55 2016
</pre>
 
====Version #2.====
<syntaxhighlight lang="r">
# Generate and plot Brownian tree. Version #2.
# 7/27/16 aev
# gpBrownianTree2(m, n, clr, fn, ttl, dflg, psz)
# Where: m - defines matrix m x m; n - limit of the number of moves;
# fn - file name (.ext will be added); ttl - plot title; dflg - 0-no dump,
# 1-dump; psz - picture size.
gpBrownianTree2 <- function(m, n, clr, fn, ttl, dflg=0, psz=600)
{
cat(" *** START:", date(), "m=",m, "n=",n, "clr=",clr, "psz=", psz, "\n");
M <- matrix(c(0), ncol=m, nrow=m, byrow=TRUE);
# Random seed always
x <- sample(1:m, 1, replace=FALSE); y <- sample(1:m, 1, replace=FALSE);
M[x,y]=1;
pf=paste0(fn,".png");
cat(" *** Plot file -",pf,"Seed:",x,"/",y,"\n");
# Main loops
for (i in 1:n) {
if(i>1) {
x <- sample(1:m, 1, replace=FALSE)
y <- sample(1:m, 1, replace=FALSE)}
while(1) {
dx <- sample(-1:1, 1, replace=FALSE);
dy <- sample(-1:1, 1, replace=FALSE);
nx=x+dx; ny=y+dy;
if(!(nx<=m && ny<=m && nx>0 && ny>0)) {
x <- sample(1:m, 1, replace=FALSE); y <- sample(1:m, 1, replace=FALSE)}
else {if(M[nx,ny]) {M[x,y]=1; break}
else{x=nx; y=ny;}}
}
}
plotmat(M, fn, clr, ttl, dflg, psz);
cat(" *** END:",date(),"\n");
}
gpBrownianTree2(400,5000,"brown", "BT2R", "Brownian Tree v.2", 1);
 
## Rename BT2R.dmp to BT2aR.dmp
plotv2("BT2aR", "orange", "Brownian Tree v.2a", 640)
</syntaxhighlight>
 
{{Output}}
 
<pre>
> gpBrownianTree2(400,5000,"brown", "BT2R", "Brownian Tree v.2", 1);
*** START: Mon Sep 05 20:11:02 2016 m= 400 n= 5000 clr= brown psz= 600
*** Plot file - BT2R.png Seed: 371 / 135
*** Matrix( 400 x 400 ) 4824 DOTS
*** Dump file: BT2R.dmp
*** END: Mon Sep 05 22:32:09 2016
> plotv2("BT2aR", "orange", "Brownian Tree v.2a", 640)
*** START: Mon Sep 05 22:21:26 2017 clr= orange psz= 640
*** File name - BT2aR
*** Source dump-file: BT2aR.dmp 4824 DOTS
*** Plot file - BT2aR.png
*** END: Mon Sep 05 22:21:27 2017
</pre>
 
====Version #3.====
<syntaxhighlight lang="r">
# Generate and plot Brownian tree. Version #3.
# 7/27/16 aev
# gpBrownianTree3(m, n, clr, fn, ttl, dflg, seed, psz):
# Where: m - defines matrix m x m; n - limit of the number of moves;
# fn - file name (.ext will be added); ttl - plot title; dflg - 0-no dump,
# 1-dump; seed - 0-center, 1-random: psz - picture size.
gpBrownianTree3 <- function(m, n, clr, fn, ttl, dflg=0, seed=0, psz=600)
{
cat(" *** START:", date(),"m=",m,"n=",n,"clr=",clr, "psz=",psz, "\n");
M <- matrix(c(0), ncol=m, nrow=m, byrow=TRUE);
# Random seed
if(seed==1)
{x <- sample(1:m, 1, replace=FALSE);y <- sample(1:m, 1, replace=FALSE)}
# Seed in center
else {x <- m%/%2; y <- m%/%2}
M[x,y]=1;
pf=paste0(fn,". png");
cat(" *** Plot file -", pf, "Seed:",x,"/",y, "\n");
# Main loops
for (i in 1:n) {
if(i>1) {
x <- sample(1:m, 1, replace=FALSE)
y <- sample(1:m, 1, replace=FALSE)}
b <- 0;
while(b==0) {
dx <- sample(-1:1, 1, replace=FALSE)
dy <- sample(-1:1, 1, replace=FALSE)
if(!(x+dx<=m && y+dy<=m && x+dx>0 && y+dy>0))
{ x <- sample(1:m, 1, replace=FALSE)
y <- sample(1:m, 1, replace=FALSE)
}
else{if(M[x+dx,y+dy]==1) {M[x,y]=1; b=1}
else {x=x+dx; y=y+dy;} }
}
}
plotmat(M, fn, clr, ttl, dflg, psz);
cat(" *** END:", date(), "\n");
}
gpBrownianTree3(400,5000,"dark green", "BT3R", "Brownian Tree v.3", 1);
</syntaxhighlight>
 
{{Output}}
 
<pre>
> gpBrownianTree3(400,5000,"dark green", "BT3R", "Brownian Tree v.3", 1);
*** START: Mon Sep 05 10:06:18 2016 m= 400 n= 5000 clr= dark green psz= 600
*** Plot file - BT3R. png Seed: 200 / 200
*** Matrix( 400 x 400 ) 4880 DOTS
*** Dump file: BT3R.dmp
*** END: Mon Sep 05 11:21:54 2016
</pre>
 
====Version #4.====
<syntaxhighlight lang="r">
# Generate and plot Brownian tree. Version #4.
# 7/27/16 aev
# gpBrownianTree4(m, n, clr, fn, ttl, dflg, seed, psz)
# Where: m - defines matrix m x m; n - limit of the number of moves;
# fn - file name (.ext will be added); ttl - plot title; dflg - 0-no dump,
# 1-dump; seed - 0-center, 1-random: psz - picture size.
gpBrownianTree4 <- function(m, n, clr, fn, ttl, dflg=0, seed=0, psz=600)
{
cat(" *** START:", date(), "m=",m, "n=",n, "clr=",clr, "psz=",psz, "\n");
M <- matrix(c(0), ncol=m, nrow=m, byrow=TRUE);
# Random seed
if(seed==1)
{x <- sample(1:m, 1, replace=FALSE);y <- sample(1:m, 1, replace=FALSE)}
# Seed in center
else {x <- m%/%2; y <- m%/%2}
M[x,y]=1;
pf=paste0(fn,".png");
cat(" *** Plot file -",pf,"Seed:",x,"/",y,"\n");
# Main loops
for (i in 1:n) {
if(i>1) {
x <- sample(1:m, 1, replace=FALSE)
y <- sample(1:m, 1, replace=FALSE)}
while((x<=m && y<=m && x>0 && y>0)) {
if(!(x+1<=m && y+1<=m && x-1>0 && y-1>0)) {break;}
b=M[x+1,y+1]+M[x,y+1]+M[x-1,y+1]+M[x+1,y];
b=b+M[x-1,y-1]+M[x-1,y]+M[x,y-1]+M[x+1,y-1];
if(b!=0) {break;}
x <- x + sample(-1:1, 1, replace=FALSE)
y <- y + sample(-1:1, 1, replace=FALSE)
if(!(x<=m && y<=m && x>0 && y>0))
{ x <- sample(1:m, 1, replace=FALSE)
y <- sample(1:m, 1, replace=FALSE)
}
}
M[x,y]=1;
}
plotmat(M, fn, clr, ttl, dflg, psz);
cat(" *** END:",date(),"\n");
}
gpBrownianTree4(400,15000,"navy", "BT4R", "Brownian Tree v.4", 1);
</syntaxhighlight>
 
{{Output}}
 
<pre>
> gpBrownianTree4(400,15000,"navy", "BT4R", "Brownian Tree v.4", 1);
*** START: Mon Sep 05 11:12:39 2016 m= 400 n= 15000 clr= navy psz= 600
*** Plot file - BT4R.png Seed: 200 / 200
*** Matrix( 400 x 400 ) 14327 DOTS
*** Dump file: BT4R.dmp
*** END: Mon Sep 05 11:50:47 2016
</pre>
=={{header|Racket}}==
<syntaxhighlight lang="racket">#lang racket
(require 2htdp/image)
 
;; The unsafe fixnum ops are faster than the checked ones,
;; but if you get anything wrong with them, they'll bite.
;; If you experience any problems reactivate the
;; (require racket/fixnum) and instead of the unsafe requirement
;; below...
 
;; we have tested this...
#;(require racket/fixnum)
;; so we can use this...
(require racket/require
(only-in racket/fixnum make-fxvector in-fxvector)
(filtered-in
(? (name) (regexp-replace #rx"unsafe-" name ""))
racket/unsafe/ops))
 
;;; This implementation uses a 1d, mutable, fixnum vector
;;; there's a lot of work done making the tree, so this optimisation
;;; at the expense of clarity has been made. Sorry, guys!
(define (brownian-tree w h collisions n-particles seed-tree
generate-particle walk-particle)
(define w*h (fx* w h))
(define V (make-fxvector w*h))
(define (collision? x.y) (fx> (fxvector-ref V x.y) 0))
;; The main loop
(define (inner-b-t collisions particles)
(cond
[(fx= 0 collisions) V]
[else
(define-values (new-particles new-collisions)
(for/fold
((prtcls null)
(clsns 0))
((x.y particles)
#:break (fx= collisions clsns))
(define new-particle (walk-particle x.y w h w*h))
(cond
[(not new-particle) ; it died!
(values (cons (generate-particle V w h w*h) prtcls) clsns)]
[(collision? new-particle)
(fxvector-set! V x.y 1)
(values (cons (generate-particle V w h w*h) prtcls) (add1 clsns))]
[else
(values (cons new-particle prtcls) clsns)])))
(when (fx> new-collisions 0)
(define remain (fx- collisions new-collisions))
(unless (fx= (exact-floor (* 10 (log collisions)))
(exact-floor (* 10 (log (fxmax 1 remain)))))
(eprintf "~a (e^~a)~%" remain (log (fxmax 1 remain))))
(log-info "~a new collisions: ~a remain~%" new-collisions remain))
(inner-b-t (fxmax 0 (fx- collisions new-collisions)) new-particles)]))
;; Seed the tree
(seed-tree V w h)
(inner-b-t collisions
(build-list n-particles
(lambda (x) (generate-particle V w h w*h)))))
 
;; See below for why we do the (fxremainder ...) test
(define (uniform-particle-generator v w h w*h)
(define x.y (random w*h))
(define valid-x.y?
(and
(fx= (fxvector-ref v x.y) 0) ; start on empty cell
(fx> (fxremainder x.y w) 0))) ; not on left edge
; if it's valid take it otherwise regenerate
(if valid-x.y? x.y (uniform-particle-generator v w h w*h)))
 
;; The boundaries to the walker are to remain within the limits of
;; the vector... however, unless we stop particles going off the
;; east/west edges, the tree will be formed on a cylinder as the
;; particles wrap. So we kill particles that reach the left edge
;; either by decrement from the right or by incrementing and wrapping.
;; This is is tested with (= 0 (remainder x.y w)).
(define (brownian-particle-walker x.y w h w*h)
(define dx (fx- (random 3) 1))
(define dy (fx- (random 3) 1))
(define new-x.y (fx+ x.y (fx+ dx (fx* w dy))))
(and (fx> new-x.y 0) (fx< new-x.y w*h)
(fx> (fxremainder new-x.y w) 0)
new-x.y))
 
;; These seed functions modify v however you want!
(define (seed-middle v w h)
(fxvector-set! v (+ (quotient w 2) (* w (quotient h 2))) 1))
 
(define (seed-circle v w h)
(for ((a (in-range 0 360 120)))
(define x (exact-floor (* w 1/8 (+ 4 (sin (* pi 1/180 a))))))
(define y (exact-floor (* h 1/8 (+ 4 (cos (* pi 1/180 a))))))
(fxvector-set! v (+ x (* w y)) 1)))
 
;; SCALE is a general purpose knob for modifying the size of the problem
;; complexity increases with the sqaure of SCALE (at least)
(define SCALE 1)
(define tree-W (* SCALE 320))
(define tree-H (* SCALE 240))
(define tree-W.H (* tree-W tree-H))
;; play with tree-PARTICLES -- small values will lead to a smaller tree
;; as the tree moves towards the edges, more particles might affect its shape
(define tree-PARTICLES (quotient tree-W.H 4))
;; these are the particles that are bimbling around at any one time. If it's
;; too low, you might get bored waiting for a collision... if it's too high
;; you might get inappropriate collisions
(define working-PARTICLES (quotient tree-W.H 300))
 
(define b-t (time
(brownian-tree
tree-W tree-H tree-PARTICLES working-PARTICLES
seed-middle
uniform-particle-generator
brownian-particle-walker)))
 
(define (b-t-value->color c) (case c ((1) "black") (else "white")))
(define img (color-list->bitmap
(for*/list ((x (in-fxvector b-t)))
(b-t-value->color x))
tree-W tree-H))
 
img
(save-image img "brownian-tree.png")</syntaxhighlight>
=={{header|Raku}}==
(formerly Perl 6)
 
[[File:Brownian_tree_perl6.png|thumb]]
 
This solution spawns new Particles at a growing square border and displays the Tree every 50 particles and at the end using unicode UPPER/LOWER HALF BLOCK and FULL BLOCK.
 
{{works with|Rakudo|2015.12}}
 
<syntaxhighlight lang="raku" line>constant size = 100;
constant particlenum = 1_000;
 
 
constant mid = size div 2;
 
my $spawnradius = 5;
my @map;
 
sub set($x, $y) {
@map[$x][$y] = True;
}
 
sub get($x, $y) {
return @map[$x][$y] || False;
}
 
set(mid, mid);
my @blocks = " ","\c[UPPER HALF BLOCK]", "\c[LOWER HALF BLOCK]","\c[FULL BLOCK]";
 
sub infix:<█>($a, $b) {
@blocks[$a + 2 * $b]
}
 
sub display {
my $start = 0;
my $end = size;
say (for $start, $start + 2 ... $end -> $y {
(for $start..$end -> $x {
if abs(($x&$y) - mid) < $spawnradius {
get($x, $y) █ get($x, $y+1);
} else {
" "
}
}).join
}).join("\n")
}
 
for ^particlenum -> $progress {
my Int $x;
my Int $y;
my &reset = {
repeat {
($x, $y) = (mid - $spawnradius..mid + $spawnradius).pick, (mid - $spawnradius, mid + $spawnradius).pick;
($x, $y) = ($y, $x) if (True, False).pick();
} while get($x,$y);
}
reset;
 
while not get($x-1|$x|$x+1, $y-1|$y|$y+1) {
$x = ($x-1, $x, $x+1).pick;
$y = ($y-1, $y, $y+1).pick;
if (False xx 3, True).pick {
$x = $x >= mid ?? $x - 1 !! $x + 1;
$y = $y >= mid ?? $y - 1 !! $y + 1;
}
if abs(($x | $y) - mid) > $spawnradius {
reset;
}
}
set($x,$y);
if $spawnradius < mid && abs(($x|$y) - mid) > $spawnradius - 5 {
$spawnradius = $spawnradius + 1;
}
}
 
display;</syntaxhighlight>
=={{header|REXX}}==
A large part of the REXX program's prologue was to handle the various options. <br>
 
With a little more REXX code, a &nbsp; ''petri dish'' &nbsp; option could be added, that is, when a particle hits the edge, <br>
it "bounces" back. &nbsp; Also, the field could then be displayed as a round area &nbsp; (like a petri dish).
 
Program note: &nbsp; to keep things simple, the (system) command to clear the screen was hard-coded as &nbsp; '''CLS'''.
<syntaxhighlight lang="rexx">/*REXX program animates and displays Brownian motion of dust in a field (with one seed).*/
mote = '·' /*character for a loose mote (of dust).*/
hole = ' ' /* " " an empty spot in field.*/
seedPos = 0 /*if =0, then use middle of the field.*/
/* " -1, " " a random placement.*/
/*otherwise, place the seed at seedPos.*/
/*use RANDSEED for RANDOM repeatability*/
parse arg sd sw motes tree randSeed . /*obtain optional arguments from the CL*/
if sd=='' | sd=="," then sd= 0 /*Not specified? Then use the default.*/
if sw=='' | sw=="," then sw= 0 /* " " " " " " */
if motes=='' | motes=="," then motes= '18%' /*The % dust motes in the field, */
/* [↑] either a # ─or─ a # with a %.*/
if tree=='' | tree==mote then tree= "*" /*the character used to show the tree. */
if length(tree)==2 then tree=x2c(tree) /*tree character was specified in hex. */
if datatype(randSeed,'W') then call random ,,randSeed /*if an integer, use the seed.*/
/* [↑] set the first random number. */
if sd==0 | sw==0 then _= scrsize() /*Note: not all REXXes have SCRSIZE BIF*/
if sd==0 then sd= word(_, 1) - 2 /*adjust usable depth for the border.*/
if sw==0 then sw= word(_, 2) - 1 /* " " width " " " */
seedAt= seedPos /*assume a seed position (initial pos).*/
if seedPos== 0 then seedAt= (sw % 2) (sd % 2) /*if it's a zero, start in the middle.*/
if seedPos==-1 then seedAt= random(1, sw) random(1,sd) /*if negative, use random.*/
parse var seedAt xs ys . /*obtain the X and Y seed coördinates*/
/* [↓] if right─most ≡ '%', then use %*/
if right(motes, 1)=='%' then motes= sd * sw * strip(motes, , '%') % 100
@.= hole /*create the Brownian field, all empty.*/
do j=1 for motes /*sprinkle a # of dust motes randomly.*/
rx= random(1, sw); ry= random(1, sd); @.rx.ry= mote
end /*j*/ /* [↑] place a mote at random in field*/
/*plant a seed from which the tree will grow from*/
@.xs.ys= tree /*dust motes that affix themselves to the tree. */
call show; loX= 1; hiX= sw /*show field before we mess it up again*/
loY= 1; hiY= sd /*used to optimize the mote searching.*/
/*▒▒▒▒▒▒▒▒▒▒▒▒▒▒▒▒▒▒▒▒▒▒▒▒▒▒▒▒▒▒▒▒▒▒▒▒▒▒▒▒▒▒▒▒▒▒▒▒▒ soooo, this is Brownian motion.*/
do Brownian=1 until \motion; call show /*show Brownion motion until no motion.*/
minx= loX; maxX= hiX; loX= sw; hiX= 1 /*as the tree grows, the search for the*/
minY= loY; maxY= hiY; loY= sd; hiy= 1 /*dust motes gets faster due to croping*/
call BM /*invoke the Brownian movement routine.*/
if loX>1 & hiX<sw & loY>1 & hiY<sd then iterate /*Need cropping? No, then keep moving*/
call crop /*delete motes (moved off petri field).*/
end /*Brownian*/ /*▒▒▒▒▒▒▒▒▒▒▒▒▒▒▒▒▒▒▒▒▒▒▒▒▒▒▒▒▒▒▒▒▒▒▒▒▒▒▒▒▒▒▒▒▒▒▒▒▒▒▒▒▒▒▒▒▒▒▒▒*/
exit 0 /*stick a fork in it, we're all done. */
/*──────────────────────────────────────────────────────────────────────────────────────*/
crop: do yc=-1 to sd+1 by sd+2; do xc=-1 to sw+1; @.xc.yc= hole; end /*xc*/
end /*yc*/
do xc=-1 to sw+1 by sw+2; do yc=-1 to sd+1; @.xc.yc= hole; end /*yc*/
end /*xc*/; return
/*──────────────────────────────────────────────────────────────────────────────────────*/
show: 'CLS'; motion= 0; do ys=sd for sd by -1; aRow=
do xs=1 for sw; aRow= aRow || @.xs.ys
end /*xs*/
say aRow
end /*ys*/; return
/*──────────────────────────────────────────────────────────────────────────────────────*/
BM: do x =minX to maxX; xm= x - 1; xp= x + 1 /*two handy─dandy values. */
do y=minY to maxY; if @.x.y\==mote then iterate /*Not a mote: keep looking.*/
if x<loX then loX=x; if x>hiX then hiX= x /*faster than hiX=max(X,hiX)*/
if y<loY then loY=y; if y>hiY then hiY= y /* " " hiY=max(y,hiY)*/
if @.xm.y ==tree then do; @.x.y= tree; iterate; end /*there a neighbor of tree? */
if @.xp.y ==tree then do; @.x.y= tree; iterate; end /* " " " " " */
ym= y - 1
if @.x.ym ==tree then do; @.x.y= tree; iterate; end /* " " " " " */
if @.xm.ym==tree then do; @.x.y= tree; iterate; end /* " " " " " */
if @.xp.ym==tree then do; @.x.y= tree; iterate; end /* " " " " " */
yp = y + 1
if @.x.yp ==tree then do; @.x.y= tree; iterate; end /* " " " " " */
if @.xm.yp==tree then do; @.x.y= tree; iterate; end /* " " " " " */
if @.xp.yp==tree then do; @.x.y= tree; iterate; end /* " " " " " */
motion= 1 /* [↓] Brownian motion is coming. */
xb= x + random(1, 3) - 2 /* apply Brownian motion for X. */
yb= y + random(1, 3) - 2 /* " " " " Y. */
if @.xb.yb\==hole then iterate /*can the mote actually move to there ?*/
@.x.y= hole /*"empty out" the old mote position. */
@.xb.yb= mote /*move the mote (or possibly not). */
if xb<loX then loX= max(1, xb); if xb>hiX then hiX= min(sw, xb)
if yb<loY then loY= max(1, yb); if yb>hiY then hiY= min(sd, yb)
end /*y*/ /* [↑] limit mote's movement to field.*/
end /*x*/; return</syntaxhighlight>
This REXX program makes use of &nbsp; '''scrsize''' &nbsp; REXX program (or BIF) which is used to determine the screen size of the terminal (console).
 
The &nbsp; '''SCRSIZE.REX''' &nbsp; REXX program is included at &nbsp; ───► &nbsp; [[SCRSIZE.REX]].
 
{{out|final output|text=&nbsp; when using the following inputs (screen size was 160&times;160): &nbsp; &nbsp; <tt> , &nbsp; , &nbsp; , &nbsp; fe </tt>}}
 
(Shown at one─sixth size.)
<pre style="font-size:17%;font-weight:bold;">
■ ■ ■
■ ■ ■ ■
■ ■ ■ ■
■■ ■
■■ ■ ■■
■ ■ ■ ■
■ ■■ ■■ ■ ■
■ ■ ■ ■ ■
■ ■ ■ ■
■ ■ ■ ■■ ■ ■ ■
■ ■ ■ ■ ■ ■ ■ ■
■ ■ ■ ■ ■ ■ ■ ■ ■ ■■
■ ■ ■ ■ ■■ ■■ ■ ■■■ ■ ■■
■ ■ ■ ■ ■ ■ ■■ ■■ ■
■ ■ ■ ■ ■ ■ ■
■ ■■ ■ ■■
■ ■ ■ ■ ■
■■ ■■
■■■ ■
■ ■ ■
■ ■ ■ ■
■ ■ ■■ ■
■ ■ ■■ ■ ■
■ ■ ■ ■ ■
■ ■■ ■ ■■ ■■ ■
■■ ■ ■ ■ ■ ■ ■ ■ ■
■ ■ ■■ ■ ■ ■ ■ ■ ■ ■■
■■ ■ ■ ■ ■■ ■ ■ ■ ■ ■ ■■
■ ■■ ■ ■ ■ ■ ■ ■ ■ ■ ■ ■ ■ ■
■ ■ ■ ■ ■ ■■ ■ ■ ■ ■■ ■ ■■
■■ ■ ■■ ■■ ■■■ ■ ■ ■ ■ ■ ■ ■
■ ■ ■ ■■ ■ ■ ■ ■ ■ ■■ ■ ■■■■ ■ ■■
■ ■ ■ ■ ■ ■ ■ ■■ ■ ■ ■ ■ ■ ■
■ ■ ■ ■ ■ ■ ■ ■ ■ ■ ■■ ■ ■ ■
■■ ■ ■ ■ ■■■ ■ ■■ ■ ■ ■ ■■ ■■ ■■ ■ ■■
■■ ■ ■ ■ ■■■ ■■■ ■ ■ ■ ■ ■ ■ ■■ ■ ■■■■
■ ■ ■ ■■ ■ ■■■ ■ ■ ■■■ ■ ■■ ■■ ■ ■■
■ ■ ■■■ ■ ■ ■ ■ ■ ■ ■ ■ ■ ■ ■■
■ ■ ■ ■ ■ ■ ■ ■ ■ ■ ■ ■ ■
■ ■ ■■ ■ ■ ■ ■ ■ ■ ■ ■ ■ ■■ ■ ■ ■ ■ ■■■ ■ ■ ■
■ ■ ■ ■ ■■ ■■ ■ ■ ■ ■■ ■■ ■ ■ ■■■ ■ ■ ■ ■ ■
■■ ■■ ■■ ■ ■ ■ ■ ■■ ■ ■ ■ ■■ ■ ■ ■ ■ ■■ ■■ ■ ■■
■ ■ ■■ ■ ■■ ■ ■■ ■ ■ ■■ ■ ■ ■■ ■ ■
■■ ■ ■■ ■ ■ ■■ ■■ ■ ■■■ ■■
■■■ ■ ■ ■ ■ ■ ■ ■ ■ ■ ■ ■ ■■ ■■ ■
■ ■ ■ ■ ■ ■ ■ ■ ■ ■ ■■ ■■ ■ ■■ ■ ■
■ ■ ■ ■■ ■■■ ■ ■ ■ ■ ■■ ■ ■ ■ ■ ■ ■ ■ ■ ■ ■
■■■■■■■ ■ ■■■■ ■■ ■■ ■ ■ ■ ■ ■ ■ ■ ■ ■■ ■ ■■
■■ ■ ■■■ ■ ■ ■■■■ ■ ■ ■■■■■ ■■■ ■ ■ ■ ■
■ ■ ■■■ ■ ■ ■ ■■ ■ ■ ■ ■ ■ ■
■ ■ ■ ■ ■ ■ ■ ■ ■ ■ ■ ■■■
■■ ■ ■ ■ ■ ■ ■■ ■ ■ ■ ■■ ■■■
■ ■ ■ ■ ■ ■ ■■■ ■ ■ ■■ ■
■ ■ ■■■■■ ■ ■■ ■ ■ ■■ ■■ ■
■ ■ ■■ ■ ■ ■ ■ ■ ■■ ■ ■ ■
■ ■ ■ ■ ■ ■ ■ ■ ■
■ ■■■ ■ ■ ■ ■ ■
■ ■ ■ ■ ■ ■ ■ ■
■ ■■ ■ ■ ■ ■ ■■
■ ■ ■ ■■■ ■ ■
■ ■ ■■ ■■■ ■ ■■ ■ ■ ■■■
■ ■ ■ ■■ ■ ■ ■■■■
■ ■ ■■■ ■■ ■ ■■ ■ ■ ■■ ■
■ ■ ■■■ ■ ■ ■ ■ ■ ■ ■ ■ ■ ■ ■ ■ ■
■ ■ ■ ■ ■ ■■ ■ ■■ ■ ■■■ ■ ■■ ■ ■■ ■■ ■ ■ ■
■ ■■ ■ ■■ ■ ■ ■ ■ ■■ ■ ■ ■ ■ ■ ■ ■■ ■
■ ■ ■ ■■ ■ ■ ■ ■ ■■ ■ ■ ■ ■ ■ ■ ■ ■ ■ ■
■ ■■ ■ ■ ■ ■ ■ ■■ ■ ■ ■ ■ ■■ ■ ■ ■ ■
■ ■ ■■■ ■ ■ ■ ■ ■■■ ■ ■ ■
■ ■ ■ ■ ■■■ ■ ■ ■ ■ ■ ■
■■ ■ ■ ■ ■ ■ ■■ ■■ ■ ■ ■ ■■ ■ ■
■ ■ ■ ■ ■■■ ■ ■ ■ ■■ ■ ■ ■■ ■ ■ ■ ■ ■ ■ ■
■■ ■ ■ ■ ■■ ■ ■■ ■ ■ ■ ■ ■ ■■ ■■
■ ■ ■ ■■ ■ ■■■ ■ ■ ■ ■ ■ ■■■ ■ ■
■ ■ ■■■ ■ ■ ■ ■ ■ ■ ■
■ ■ ■ ■■ ■■ ■■ ■■ ■ ■
■ ■ ■ ■ ■ ■ ■ ■ ■ ■■■■■■
■ ■ ■ ■ ■ ■ ■ ■ ■ ■ ■ ■
■ ■ ■■ ■■ ■ ■■ ■ ■■ ■
■ ■ ■ ■■ ■ ■ ■ ■■ ■ ■
■ ■ ■ ■■ ■ ■ ■ ■ ■ ■ ■■■ ■■ ■
■ ■ ■ ■ ■ ■ ■ ■■ ■ ■ ■■ ■ ■
■ ■■ ■ ■ ■ ■ ■ ■■ ■ ■■ ■
■ ■ ■ ■ ■ ■ ■ ■■ ■ ■ ■
■ ■■ ■ ■ ■■ ■■ ■ ■ ■ ■■■■ ■■
■ ■ ■ ■ ■ ■ ■ ■ ■ ■ ■ ■ ■
■ ■ ■ ■ ■ ■ ■ ■■ ■ ■ ■ ■
■■■ ■ ■ ■ ■ ■ ■ ■ ■
■ ■ ■ ■ ■ ■ ■ ■ ■ ■■
■■ ■ ■ ■ ■ ■ ■ ■ ■■
■ ■ ■ ■ ■ ■ ■ ■■ ■
■ ■ ■ ■■■ ■ ■ ■■ ■■
■■ ■ ■ ■ ■ ■ ■ ■ ■ ■
■■ ■ ■ ■ ■ ■ ■ ■
■■ ■ ■ ■■ ■■■ ■
■ ■■ ■ ■ ■■■ ■ ■
■ ■■ ■■ ■ ■ ■ ■ ■
■ ■ ■■ ■ ■ ■ ■ ■ ■
■ ■ ■■ ■ ■ ■ ■■
■■ ■ ■■■■ ■■ ■
■ ■ ■ ■ ■ ■ ■
■ ■ ■ ■ ■ ■
■ ■■ ■ ■ ■
■ ■ ■ ■
■ ■ ■ ■ ■
■ ■ ■ ■ ■■
■ ■ ■ ■ ■ ■
■ ■ ■
■ ■
</pre>
=={{header|Ring}}==
<syntaxhighlight lang="ring">
# Project : Brownian tree
 
load "stdlib.ring"
load "guilib.ring"
 
paint = null
 
new qapp
{
win1 = new qwidget() {
setwindowtitle("")
setgeometry(100,100,800,600)
label1 = new qlabel(win1) {
setgeometry(10,10,800,600)
settext("")
}
new qpushbutton(win1) {
setgeometry(150,500,100,30)
settext("draw")
setclickevent("draw()")
}
show()
}
exec()
}
 
func draw
p1 = new qpicture()
color = new qcolor() {
setrgb(0,0,255,255)
}
pen = new qpen() {
setcolor(color)
setwidth(1)
}
paint = new qpainter() {
begin(p1)
color = new qcolor()
color.setrgb(255,0,0,255)
pen = new qpen() {
setcolor(color)
setwidth(1)}
setpen(pen)
 
browniantree()
 
endpaint()
}
label1 { setpicture(p1) show() }
return
 
func browniantree()
numparticles = 3000
canvas = newlist(210,210)
canvas[randomf() * 100][randomf() * 200] = 1
for i = 1 to numparticles
x = floor((randomf() * 199)) + 1
y = floor((randomf() * 199)) + 1
if x = 1
x = 2
ok
if y = 1
y = 2
ok
while canvas[x+1][y+1]+canvas[x][y+1]+canvas[x+1][y]+canvas[x-1][y-1]+canvas[x-1][y]+canvas[x][y-1] = 0
x = x + floor((randomf() * 2)) + 1
y = y + floor((randomf() * 2)) + 1
if x = 1
x = 2
ok
if y = 1
y = 2
ok
if x < 1 or x > 200 or y < 1 or y > 200
x = floor((randomf() * 199)) + 1
y = floor((randomf() * 199)) + 1
if x = 1
x = 2
ok
if y = 1
y = 2
ok
ok
end
canvas[x][y] = 1
paint.drawpoint(x,y)
paint.drawpoint(x,y+1)
paint.drawpoint(x,y+2)
next
 
func randomf()
decimals(10)
str = "0."
for i = 1 to 10
nr = random(9)
str = str + string(nr)
next
return number(str)
</syntaxhighlight>
Output:
 
[https://www.dropbox.com/s/a22tu6wf0ibu502/BrownianTree.jpg?dl=0 Brownian tree]
=={{header|Ruby}}==
{{libheader|RMagick}}
<langsyntaxhighlight lang="ruby">require 'rubygems'
require 'RMagick'
 
Line 1,301 ⟶ 4,621:
 
draw.draw img
img.write "brownian_tree.bmp"</langsyntaxhighlight>
=={{header|Run BASIC}}==
[[File:BrownianTreeKokenge.png|thumb|right|]]
<syntaxhighlight lang="runbasic">numParticles = 3000
dim canvas(201,201)
graphic #g, 200,200
#g fill("blue")
canvas(rnd(1) * 100 , rnd(1) * 200) = 1 'start point
for i = 1 To numParticles
x = (rnd(1) * 199) + 1
y = (rnd(1) * 199) + 1
while canvas(x+1, y+1)+canvas(x, y+1)+canvas(x+1, y)+canvas(x-1, y-1)+canvas(x-1, y)+canvas(x, y-1) = 0
x = x + (rnd(1)* 2) + 1
y = y + (rnd(1)* 2) + 1
If x < 1 Or x > 200 Or y < 1 Or y > 200 then
x = (rnd(1) * 199) + 1
y = (rnd(1) * 199) + 1
end if
wend
canvas(x,y) = 1
#g "color green ; set "; x; " "; y
next i
render #g
#g "flush"</syntaxhighlight>
=={{header|Rust}}==
{{trans|D}}
{{libheader|rand}}
{{libheader|image}}
<syntaxhighlight lang="rust">
extern crate image;
extern crate rand;
 
use image::ColorType;
 
use std::cmp::{min, max};
use std::env;
use std::path::Path;
use std::process;
use rand::Rng;
 
fn help() {
println!("Usage: brownian_tree <output_path> <mote_count> <edge_length>");
}
 
fn main() {
let args: Vec<String> = env::args().collect();
let mut output_path = Path::new("out.png");
let mut mote_count: u32 = 10000;
let mut width: usize = 512;
let mut height: usize = 512;
 
match args.len() {
1 => {}
4 => {
output_path = Path::new(&args[1]);
mote_count = args[2].parse::<u32>().unwrap();
width = args[3].parse::<usize>().unwrap();
height = width;
}
_ => {
help();
process::exit(0);
}
}
 
assert!(width >= 2);
 
// Base 1d array
let mut field_raw = vec![0u8; width * height];
populate_tree(&mut field_raw, width, height, mote_count);
 
// Balance image for 8-bit grayscale
let our_max = field_raw.iter().fold(0u8, |champ, e| max(champ, *e));
let fudge = std::u8::MAX / our_max;
let balanced: Vec<u8> = field_raw.iter().map(|e| e * fudge).collect();
 
match image::save_buffer(output_path,
&balanced,
width as u32,
height as u32,
ColorType::L8) {
Err(e) => println!("Error writing output image:\n{}", e),
Ok(_) => println!("Output written to:\n{}", output_path.to_str().unwrap()),
}
}
 
 
fn populate_tree(raw: &mut Vec<u8>, width: usize, height: usize, mc: u32) {
// Vector of 'width' elements slices
let mut field_base: Vec<_> = raw.as_mut_slice().chunks_mut(width).collect();
// Addressable 2d vector
let field: &mut [&mut [u8]] = field_base.as_mut_slice();
 
// Seed mote
field[width / 2][height / 2] = 1;
 
let mut rng = rand::thread_rng();
 
for i in 0..mc {
if i % 100 == 0 {
println!("{}", i)
}
 
let mut x=rng.gen_range(1usize..width-1);
let mut y=rng.gen_range(1usize..height-1);
 
// Increment field value when motes spawn on top of the structure
if field[x][y] > 0 {
field[x][y] = min(field[x][y] as u32 + 1, std::u8::MAX as u32) as u8;
continue;
}
 
loop {
let contacts = field[x - 1][y - 1] + field[x][y - 1] + field[x + 1][y - 1] +
field[x - 1][y] + field[x + 1][y] +
field[x - 1][y + 1] + field[x][y + 1] +
field[x + 1][y + 1];
 
if contacts > 0 {
field[x][y] = 1;
break;
} else {
let xw = rng.gen_range(-1..2) + x as i32;
let yw = rng.gen_range(-1..2) + y as i32;
if xw < 1 || xw >= (width as i32 - 1) || yw < 1 || yw >= (height as i32 - 1) {
break;
}
x = xw as usize;
y = yw as usize;
}
}
}
}</syntaxhighlight>
For a 512 x 512 field and 100k motes, run time is around 200 s on ~2019 hardware (Ryzen 5 3600X).
<center>[[File:Rust-Brownian-512-20k.png]]</center>
=={{header|Scala}}==
===Java Swing Interoperability===
<syntaxhighlight lang="scala">import java.awt.Graphics
import java.awt.image.BufferedImage
 
import javax.swing.JFrame
 
import scala.collection.mutable.ListBuffer
 
object BrownianTree extends App {
val rand = scala.util.Random
 
class BrownianTree extends JFrame("Brownian Tree") with Runnable {
setBounds(100, 100, 400, 300)
val img = new BufferedImage(getWidth, getHeight, BufferedImage.TYPE_INT_RGB)
 
override def paint(g: Graphics): Unit = g.drawImage(img, 0, 0, this)
 
override def run(): Unit = {
class Particle(var x: Int = rand.nextInt(img.getWidth),
var y: Int = rand.nextInt(img.getHeight)) {
 
/* returns false if either out of bounds or collided with tree */
def move: Boolean = {
val (dx, dy) = (rand.nextInt(3) - 1, rand.nextInt(3) - 1)
if ((x + dx < 0) || (y + dy < 0) ||
(y + dy >= img.getHeight) || (x + dx >= img.getWidth)) false
else {
x += dx
y += dy
if ((img.getRGB(x, y) & 0xff00) == 0xff00) {
img.setRGB(x - dx, y - dy, 0xff00)
false
} else true
}
}
}
 
var particles = ListBuffer.fill(20000)(new Particle)
while (particles.nonEmpty) {
particles = particles.filter(_.move)
repaint()
}
}
 
setDefaultCloseOperation(javax.swing.WindowConstants.EXIT_ON_CLOSE)
img.setRGB(img.getWidth / 2, img.getHeight / 2, 0xff00)
setVisible(true)
}
 
new Thread(new BrownianTree).start()
}</syntaxhighlight>
=={{header|Scheme}}==
{{works with|Guile}}
<syntaxhighlight lang="scheme">; Save bitmap to external file
(define (save-pbm bitmap filename)
(define f (open-output-file filename))
(simple-format f "P1\n~A ~A\n"
(list-ref (array-dimensions bitmap) 0)
(list-ref (array-dimensions bitmap) 1))
(do ((c 0 (+ c 1))) ((eqv? c (list-ref (array-dimensions bitmap) 1)))
(do ((r 0 (+ r 1))) ((eqv? r (list-ref (array-dimensions bitmap) 0)))
(display (array-ref bitmap r c) f))
(newline f))
(close-output-port f)
)
 
; Return a random coordinate in the bitmap that isn't filled yet along with a direction
(define (new-particle bitmap)
(define x (random (list-ref (array-dimensions bitmap) 0)))
(define y (random (list-ref (array-dimensions bitmap) 1)))
(define dx (- (random 3) 1))
(define dy (- (random 3) 1))
;Repeat until we find an unused location
(if (> (array-ref bitmap x y) 0)
(new-particle bitmap)
(list (list x y) (list dx dy))))
 
; Check neighboring coordinates to see if a collision occured
(define (collision-check bitmap p)
(define c #f)
(define oob #f)
(define x (list-ref (car p) 0))
(define y (list-ref (car p) 1))
(define dx (list-ref (cadr p) 0))
(define dy (list-ref (cadr p) 1))
(define w (list-ref (array-dimensions bitmap) 0))
(define h (list-ref (array-dimensions bitmap) 1))
; If the particle hasn't gone out of bounds keep checking for a collision
(if (or (> 0 x) (> 0 y) (<= w x) (<= h y))
(set! oob #t)
(do ((x (- (list-ref (car p) 0) 1) (+ x 1))) ((eqv? x (+ (list-ref (car p) 0) 2)))
(do ((y (- (list-ref (car p) 1) 1) (+ y 1))) ((eqv? y (+ (list-ref (car p) 1) 2)))
; Check existing neighbors for collisions
(if (and (<= 0 x) (<= 0 y) (> w x) (> h y))
(if (not (zero? (array-ref bitmap x y)))
(set! c #t))))))
(if oob
#f ; Return false if out of bounds
(if c
p ; Return the point of collision if a collision occured
(if (and (zero? dx) (zero? dy))
#f ; Return false if particle is motionless with no collision
(collision-check bitmap (particle-move p))))))
 
; Plot a particle on the bitmap
(define (particle-plot! bitmap p)
(array-set! bitmap 1 (list-ref (car p) 0) (list-ref (car p) 1)))
 
; Move a particle along its slope
(define (particle-move p)
(list (list
(+ (list-ref (car p) 0) (list-ref (cadr p) 0))
(+ (list-ref (car p) 1) (list-ref (cadr p) 1)))
(cadr p)))
 
; Grow a brownian tree
(define (grow-brownian-tree! bitmap collisions)
(define w (list-ref (array-dimensions bitmap) 0))
(define h (list-ref (array-dimensions bitmap) 1))
 
; Generate a new particle at a random location
(define p (new-particle bitmap))
 
; Find a collision or lack of one and plot it on the bitmap
(set! p (collision-check bitmap p))
(if p (begin
; Display collision number and the place it happened
(display collisions)(display ": ")(display (car p))(newline)
(set! collisions (- collisions 1))
; Plot the point
(particle-plot! bitmap p)))
 
; If we're done say so
(if (zero? collisions)
(display "Done\n"))
 
; Keep going until we have enough collisions
; or have filled the bitmap
(if (and (< 0 collisions) (memq 0 (array->list (array-contents bitmap))))
(grow-brownian-tree! bitmap collisions)))
 
; Plot a random point to seed the brownian tree
(define (seed-brownian-tree! bitmap)
(define p (new-particle bitmap))
(particle-plot! bitmap p))
 
;;; Example usage ;;;
; Seed the random number generator
(let ((time (gettimeofday)))
(set! *random-state*
(seed->random-state (+ (car time) (cdr time)))))
 
; Generate a tree with 320*240 collisions on a bitmap of the size 640x480
; The bitmap is zeroed to start and written with a one where a collision occurs
(define bitmap (make-array 0 640 480))
(seed-brownian-tree! bitmap)
(grow-brownian-tree! bitmap (* 320 240))
 
; Save to a portable bitmap file
(save-pbm bitmap "brownian-tree.pbm")</syntaxhighlight>
[[File:Scheme-guile-brownian-tree-large.png]]
=={{header|Seed7}}==
[[File:browniantree.png|300px|thumb|right|Simple brownian tree produced with Seed7 program]]
The program below generates a small brownian tree. You can watch how it grows.
 
<syntaxhighlight lang="seed7">$ include "seed7_05.s7i";
include "draw.s7i";
include "keybd.s7i";
 
const integer: SIZE is 300;
const integer: SCALE is 1;
 
const proc: genBrownianTree (in integer: fieldSize, in integer: numParticles) is func
local
var array array integer: world is 0 times 0 times 0;
var integer: px is 0;
var integer: py is 0;
var integer: dx is 0;
var integer: dy is 0;
var integer: i is 0;
var boolean: bumped is FALSE;
begin
world := fieldSize times fieldSize times 0;
world[rand(1, fieldSize)][rand(1, fieldSize)] := 1; # Set the seed
for i range 1 to numParticles do
# Set particle's initial position
px := rand(1, fieldSize);
py := rand(1, fieldSize);
bumped := FALSE;
repeat
# Randomly choose a direction
dx := rand(-1, 1);
dy := rand(-1, 1);
if dx + px < 1 or dx + px > fieldSize or dy + py < 1 or dy + py > fieldSize then
# Plop the particle into some other random location
px := rand(1, fieldSize);
py := rand(1, fieldSize);
elsif world[py + dy][px + dx] <> 0 then
# Bumped into something
world[py][px] := 1;
rect(SCALE * pred(px), SCALE * pred(py), SCALE, SCALE, white);
flushGraphic;
bumped := TRUE;
else
py +:= dy;
px +:= dx;
end if;
until bumped;
end for;
end func;</syntaxhighlight>
 
Original source: [http://seed7.sourceforge.net/algorith/graphic.htm#brownian_tree]
 
=={{header|SequenceL}}==
'''SequenceL Code:'''<br>
<syntaxhighlight lang="sequencel">import <Utilities/Random.sl>;
import <Utilities/Sequence.sl>;
 
POINT ::= (X: int, Y: int);
RET_VAL ::= (World: int(2), Rand: RandomGenerator<int, int>, Point: POINT);
 
randomWalk(x, y, world(2), rand) :=
let
randX := getRandom(rand);
randY := getRandom(randX.Generator);
nextX := x + (randX.Value mod 3) - 1;
nextY := y + (randY.Value mod 3) - 1;
newStartX := (randX.Value mod (size(world) - 2)) + 2;
newStartY := (randY.Value mod (size(world) - 2)) + 2;
numNeighbors := world[y-1,x-1] + world[y-1,x] + world[y-1,x+1] +
world[y,x-1] + world[y,x+1] +
world[y+1,x-1] + world[y+1,x] + world[y+1,x+1];
outOfBounds := nextX <= 1 or nextY <= 1 or nextX >= size(world) or nextY >= size(world);
in
randomWalk(newStartX, newStartY, world, randY.Generator) when world[y,x] = 1 or outOfBounds
else
(X: x, Y: y) when numNeighbors > 0
else
randomWalk(nextX, nextY, world, randY.Generator);
 
step(rand, world(2)) :=
let
walkSeed := getRandom(rand);
newParticle := randomWalk(size(world)/2,size(world)/2, world, seedRandom(walkSeed.Value));
 
newWorld[j] :=
world[j] when j /= newParticle.Y
else
setElementAt(world[j], newParticle.X, 1);
in
(World: newWorld, Rand: walkSeed.Generator, Point: newParticle);
initialWorld(worldSize, seed) :=
let
world[i,j] := 1 when i = worldSize / 2 and j = worldSize / 2 else 0
foreach i within 1 ... worldSize,
j within 1 ... worldSize;
in
(World: world, Rand: seedRandom(seed), Point: (X: worldSize / 2, Y: worldSize / 2));</syntaxhighlight>
 
'''C++ Driver Code:'''<br>
{{libheader|CImg}}
<syntaxhighlight lang="c">#include <time.h>
#include <cstdlib>
#include "CImg.h"
#include "SL_Generated.h"
 
using namespace std;
using namespace cimg_library;
 
int main(int argc, char ** argv)
{
int threads = 0;
int worldSize = 300; if(argc > 1) worldSize = atoi(argv[1]);
int seed = time(NULL); if(argc > 2) seed = atoi(argv[2]);
int scale = 2; if(argc > 3) scale = atoi(argv[3]);
 
sl_init(threads);
 
_sl_RET_VAL current;
_sl_RET_VAL result;
 
const unsigned char black[] = {0};
 
CImg<unsigned char> visu(worldSize * scale, worldSize * scale, 1, 1, 0);
CImgDisplay draw_disp(visu);
cout << "Brownian Tree in SequenceL" << endl << "Threads: " << threads << endl;
draw_disp.set_title("Brownian Tree in SequenceL: %d Threads", threads);
visu.fill(255);
sl_initialWorld(worldSize, seed, threads, current);
while(!draw_disp.is_closed())
{
visu.draw_circle((current.Point.val().Y - 1) * scale, (current.Point.val().X - 1) * scale, scale/2, black, 1);
visu.display(draw_disp);
sl_step(current.Rand.val(), current.World, threads, result);
current = result;
draw_disp.wait(1);
}
 
sl_done();
 
return 0;
}</syntaxhighlight>
 
{{out}}
[http://i.imgur.com/OrB9tLI.gifv Output Video]
=={{header|Sidef}}==
{{trans|Raku}}
<syntaxhighlight lang="ruby">const size = 100
const mid = size>>1
const particlenum = 1000
 
var map = []
var spawnradius = 5
 
func set(x, y) {
map[x][y] = 1
}
 
func get(x, y) {
map[x][y] \\ 0
}
 
set(mid, mid)
 
var blocks = [
" ",
"\N{UPPER HALF BLOCK}",
"\N{LOWER HALF BLOCK}",
"\N{FULL BLOCK}"
]
 
func block(a, b) {
blocks[2*b + a]
}
 
func display {
0..size `by` 2 -> map {|y|
0..size -> map {|x|
if ([x, y].all { .-mid < spawnradius }) {
block(get(x, y), get(x, y+1))
} else { " " }
}.join
}.join("\n").say
}
 
for progress in (^particlenum) {
var (x=0, y=0)
 
var reset = {
do {
(x, y) = (
(mid-spawnradius .. mid+spawnradius -> pick),
[mid-spawnradius, mid+spawnradius] -> pick
)
(x, y) = (y, x) if (1.rand < 0.5)
} while(get(x, y))
}
 
reset.run
 
while ([[-1, 0, 1]]*2 -> cartesian.any {|pair|
get(x+pair[0], y+pair[1])
} -> not) {
x = [x-1, x, x+1].pick
y = [y-1, y, y+1].pick
 
if (1.rand < 0.25) {
x = (x >= mid ? (x-1) : (x+1))
y = (y >= mid ? (y-1) : (y+1))
}
 
if ([x,y].any { .-mid > spawnradius }) {
reset.run
}
}
 
set(x, y)
display() if (progress %% 50)
 
if ((spawnradius < mid) && [x,y].any { .-mid > spawnradius-5 }) {
++spawnradius
}
}
 
display()</syntaxhighlight>
{{out}}
<pre>
▄ ▄▀ ▄ ▀▄
▀█▄▄▀ █ █▄█▀ ▄ █▄ ▀▄█ █
▄▀ ▀▄█ █ ▄▀ ▄▀ █ ▄ ▄▀ ▀ ▀ ▄ ▄▀
▀▀▄ ▄▀ █▄▀█ ▀█ ▄ ▄▀ ▄█▄▄
▄▄▄▀ ▄▀ ▀▀ ▀ ▀▄ ▀▄▀ ▀ ▀▀▄▀ ▀
▄▀ ▀▄▀▄ ▄ ▄▄▀ █▄▄ ▄ ▄ █
█▄ ▄▀█ █ ▄ █▀ ▀▄█▀
██▀ ▄▀▄▄▀▄ ▀▀█ ▄▀█ █ ▀
▀▄ ▀▄ ▀▀█ ▀▄ ▄▄▄ █▀ ▀▄▀▀
▄ █▄▄▄▀ █▄▄▀ ▄▀▀▄ █▄▀▄ ▄▀▀▄ ▀▄▄█ ▄ ▄
▀▀█▄▀ ▀▄▄ ▀▄▀ ██▄ ▀▄▀ █▀▄▄ ▄▄█ ▀▀
▀▄▀▄█ ▄ ▄▀ ▄█ ▀█▀▄ ▄▀ ▄▀▄▀ █▀ █▀▀ ▄ ▄▀
▄█ ▄▀▀▀▄ ▄ ▀▄ █ ▄ █ ▄ ▀█▀▄▀ █ ▄▄█▀▀ ▀▄▀
▀█▄▀▀▄▀▄ ▀▄▄▀▀ ▄▄ ▀▄▀ ▀▄ ▄█▀█ ▀▄ ▄ ▄▄▀
▄▄▀ ▀ █▄ ▀▀▄▀ ▄█ █ ▀▄▄ ▄ ▄█ ▀▄▀ █
▄ ▄ ▄▄▀▄▀ ▄ ▄▄▄█ ▄█ ▄▀ █▀██▀▄ ▄▀ ▄▀ ▄▄ ▀▀ ▄▀ ▄
▄▄▄▄▀ ▀▄ ▀▀▄ ▀ ▀▀▄ ▀ ▀█▀ ▀█▄▀ ▄ ▄▀▀ █▄▄ ▄▄▀▄▄▀ ▄▀
▀▄▄▄ █▀ ▀▀▄█ ▀▄▀▄▄ ▀▄▄▄ ▄█ ▀█▀▀▄▄ █ ▄▀▄▄ ▄▄ ▄▀ ▄▀
▀▄▀ ▄▀ ▄▄▄▄▀▄▄▄▄ ██▄ ▄▄▀▄▀▄▄▀ ▄▀ ▄▄▄▀▄▄█▄▄▀▀ █ ▄▄▀▄█▄ ▄ █▄▄▄
▀▄ █▀ ▀█▄▀ █▄▀ ▀▀ ▀█▄▀ ▀▄▄█▀ ▀▄▀█▄▄▀▀▄ ▀ ▄█▄█▀█ ▀ █ ▀█▄▀▀▄▀▀ ▄▀
▀▀ ▀ ▄ ▀▄▀ ▀▄ ▄▄▀ ▀ ▄▀ ▀ ▀▄ ▄▀ ▀▄ ▄ ▀ █▄▄
▄▄█ ▀█▀ ▄ ▄▀█ ▀ █ ██ ▄▀ ▀▄▀ ▄▀▄▀▄▀█ ▀ ▀
▀▀ █ ▄ ▀█▀ █ ▄▀ ▄▄█▀ ▀▀▄ ▀ █ ▄▀▄ ▄
▀▀▄▄ ▀▄ █ ▄▀▄ █ ▀█▄█ ▀▄▄▀▄▄ ▀ ▀ ▀▀▄
▄█▄ ▀▄▀▄▄ ▄▀▀ ▀ ▀▄ ▄▀ ▄▀▄ █ █▄ ▄▀
▄▀▄█▀ █ █▀█ ▄ ▄▀ ▀▄▀ ▄█▀ █▄▄▀▀▄
▄ ▄▀▄▄█ ▀▄ ▄▀▄ ▀ ▀▀▄▀ █ ▀ ▄█ ▀▄▀▄ █
▀▄▀ ▀▀█ █▄▄ ▀ ▄▀ █▀ ▀ ▀▄▀▀▄▄▀ █ ▄▀ ▀▄ ▀▄
▀▀ ▀ ██▀ ▀▄ ▄█ ▄▄▀▄▀ █▀ ▀
▄▀ █ ▀▄ ▄▀ ▀▄ ▄█ ▀▀
▀▄ ▀█▄ ▄▄▀▄ ▄▀▀▀▄▄▄
▀ ▀ ▀ ▄▀ █▀ ▄
▄▄▀█▄▀▄
▄▀▄ █ ▀
▄▀▄▄▄▀
▀ █ █
▀█
</pre>
=={{header|Simula}}==
<syntaxhighlight lang="simula">BEGIN
INTEGER NUM_PARTICLES;
INTEGER LINES, COLUMNS;
INTEGER SEED;
 
NUM_PARTICLES := 1000;
LINES := 46;
COLUMNS := 80;
SEED := ININT;
BEGIN
PROCEDURE DRAW_BROWNIAN_TREE(WORLD); INTEGER ARRAY WORLD;
BEGIN
INTEGER PX, PY; COMMENT PARTICLE VALUES ;
INTEGER DX, DY; COMMENT OFFSETS ;
INTEGER I;
 
COMMENT SET THE SEED ;
PX := RANDINT(0,LINES-1,SEED);
PY := RANDINT(0,COLUMNS-1,SEED);
WORLD(PX,PY) := 1;
FOR I := 0 STEP 1 UNTIL NUM_PARTICLES - 1 DO BEGIN
COMMENT SET PARTICLE'S INITIAL POSITION ;
PX := RANDINT(0,LINES-1,SEED);
PY := RANDINT(0,COLUMNS-1,SEED);
WHILE TRUE DO BEGIN
COMMENT RANDOMLY CHOOSE A DIRECTION ;
DX := RANDINT(-1,1,SEED);
DY := RANDINT(-1,1,SEED);
IF DX + PX < 0 OR DX + PX >= LINES
OR DY + PY < 0 OR DY + PY >= COLUMNS THEN
BEGIN
COMMENT PLOP THE PARTICLE INTO SOME OTHER RANDOM LOCATION ;
PX := RANDINT(0,LINES-1,SEED);
PY := RANDINT(0,COLUMNS-1,SEED);
END ELSE IF WORLD(PX + DX, PY + DY) <> 0 THEN BEGIN
COMMENT BUMPED INTO SOMETHING ;
WORLD(PX, PY) := 1;
GO TO BREAK;
END ELSE BEGIN
PY := PY + DY;
PX := PX + DX;
END IF;
END WHILE;
BREAK:
END FOR;
END DRAW_BROWNIAN_TREE;
 
INTEGER ARRAY WORLD(0:LINES-1,0:COLUMNS-1);
INTEGER I,J;
 
DRAW_BROWNIAN_TREE(WORLD);
 
FOR I := 0 STEP 1 UNTIL LINES-1 DO
BEGIN
FOR J := 0 STEP 1 UNTIL COLUMNS-1 DO
BEGIN
OUTCHAR(IF WORLD(I,J)=0 THEN '.' ELSE '*');
END;
OUTIMAGE;
END;
 
END;
END.</syntaxhighlight>
{{in}}
<pre>656565</pre>
{{out}}
<pre>
................................................................................
................................................................................
................................................................................
................................................................................
................................................................................
................................................................................
................................................................................
.........*.......***............*.*...**........................................
..........*......**..*.......*.****....*........................................
...........*******...**..*.*.*****....***.......................................
..........*.******....**.*.**.***....*.*........................................
.............****.****..**...***..*******............**.*.*.....................
..........*.*...**.*******...***...*****............***.****....................
...........*....*****.****..*..*****..***.*....*...*.*.****.....................
................*.****.*...****..*****.*****...*..******..*.....................
................*.********..**.*.*****.**.**..*.*.*****.***.....................
.........*...*...*.******..*.***.***...**********..**********...................
.........**.*......*******...********.*****.*****...**.*****.*.*................
..........**.*..*..***.*****.**.***.***.***.****.*.***.****.*.**................
..........*.*.****.**..**************.*..****.******.*..*******.................
...........*******.*.************.***********.****.*....*******.................
...........*.********..***.***.****.********.****.**....****.*..................
..........**..*****.**.***.*.***.*..*.**.**.********............................
...............*.*********..********..*.....**.****.*...........................
..............***.****.*****.*.***.*.**...*..*...***.*..........................
.........*...***.*.*..*****.***.********...**........*..........................
..........****...***.**.****************..**.**.*****...........................
.........***.***..****.*..******.******..***********............................
........***.**********....****.**.************.**.*.............................
........*.****.*..*******.***..**.**********.****..*............................
.......*........*.*.*...****..****.*******.*.***.*..............................
.......*.......*.......*****...**..****.****..***...............................
....................***.******..**..**.*****.....**.............................
.....................************.**..****.***..................................
...................*****.*.*.*.*****.**.******..................................
....................*.*.***...*****.**....**....................................
....................*.*****.....**.*..*..****...................................
......................*.***.....***......*****..................................
.........................*.*......****....**.**..*..............................
.................................*.......*..*.***.*.*...........................
..................................*.........******.*............................
..............................................**................................
................................................................................
................................................................................
................................................................................
................................................................................
</pre>
=={{header|Sinclair ZX81 BASIC}}==
Requires at least 2k of RAM. If you have more, you can plot it on a larger grid—up to and including full-screen, provided you don't mind spending literally hours watching the first few dots maunder about without hitting anything.
<syntaxhighlight lang="basic"> 10 DIM A$(20,20)
20 LET A$(10,10)="1"
30 FOR Y=42 TO 23 STEP -1
40 FOR X=0 TO 19
50 PLOT X,Y
60 NEXT X
70 NEXT Y
80 UNPLOT 9,33
90 FOR I=1 TO 80
100 LET X=INT (RND*18)+2
110 LET Y=INT (RND*18)+2
120 IF A$(X,Y)="1" THEN GOTO 100
130 UNPLOT X-1,43-Y
140 IF A$(X+1,Y+1)="1" OR A$(X+1,Y)="1" OR A$(X+1,Y-1)="1" OR A$(X,Y+1)="1" OR A$(X,Y-1)="1" OR A$(X-1,Y+1)="1" OR A$(X-1,Y)="1" OR A$(X-1,Y-1)="1" THEN GOTO 230
150 PLOT X-1,43-Y
160 LET X=X+INT (RND*3)-1
170 LET Y=Y+INT (RND*3)-1
180 IF X=1 THEN LET X=19
190 IF X=20 THEN LET X=2
200 IF Y=1 THEN LET Y=19
210 IF Y=20 THEN LET Y=2
220 GOTO 130
230 LET A$(X,Y)="1"
240 NEXT I</syntaxhighlight>
{{out}}
Screenshot [http://www.edmundgriffiths.com/zx81browniantree.jpg here].
=={{header|Tcl}}==
{{libheader|Tk}}
<langsyntaxhighlight lang="tcl">package require Tcl 8.5
package require Tk
 
Line 1,356 ⟶ 5,390:
update
makeBrownianTree 1000
brownianTree write tree.ppm</langsyntaxhighlight>
=={{header|TI-83 BASIC}}==
<syntaxhighlight lang="ti83b">:StoreGDB 0
:ClrDraw
:FnOff
:AxesOff
:Pxl-On(31,47)
:For(I,1,50)
:randInt(1,93)→X
:randInt(1,61)→Y
:1→A
:While A
:randInt(1,4)→D
:Pxl-Off(Y,X)
:If D=1 and Y≥2
:Y-1→Y
:If D=2 and X≤92
:X+1→X
:If D=3 and Y≤60
:Y+1→Y
:If D=4 and X≥2
:X-1→X
:Pxl-On(Y,X)
:If pxl-Test(Y+1,X) or pxl-Test(Y+1,X+1) or pxl-Test(Y+1,X-1) or pxl-Test(Y,X+1) or pxl-Test(Y,X-1) or pxl-Test(Y-1,X) or pxl-Test(Y-1,X-1) or pxl-Test(Y-1,X+1)
:0→A
:End
:End
:Pause
:RecallGDB 0</syntaxhighlight>
 
=={{header|Visual Basic.NETUiua}}==
Uiua Pad will show well-shaped arrays as images directly. If running locally you can uncomment the final few lines to save it as a file instead. (Running local is ~10 times faster too.)
 
The main move loop passes round a pair of points: here and previous position, so when we hit a set cell we can just back up one.
 
<syntaxhighlight lang="Uiua">
S ← 80
# Create SxS grid, and set the centre point as seed.
⍜⊡(+1)↯2⌊÷2S ↯ S_S 0
 
RandInt ← ⌊×⚂
RandPoint ← ([⍥(RandInt S)2])
# Update the pair to be a new adjacent [[Here] [Last]]
Move ← ⊟∵(-1+⌊RandInt 3).⊢
In ← /××⊃(≥0)(<S) # Is this point in bounds?
# Given a grid return a free point pair and that grid.
SeedPair ← ⊟.⍢(RandPoint ◌)(=1⊡) RandPoint
# Find next adjacent position, or new seed if out of bounds.
Next ← ⟨SeedPair ◌|∘⟩:⟜(In ⊢)Move
# Start from a new Seed Pair and move until you hit the tree. Add the prior pos to the tree.
JoinTree ← ⍜⊡(+1)◌°⊟⍢Next (=0⊡⊢) SeedPair
# Do it multiple times.
⍜now⍥JoinTree500
 
# ◌
# &ime "png"
# &fwa "BrownianTree.png"
</syntaxhighlight>
 
Or if you like your code terse :-)
 
<syntaxhighlight lang="Uiua">
S ← 80
⍜⊡(+1)↯2⌊÷2S↯S_S0
Rp ← (⊟⍥(⌊×⚂S)2)
Sd ← ⊟.⍢(Rp◌)(=1⊡) Rp
Nx ← ⟨Sd◌|∘⟩:⟜(/××⊃(≥0)(<S)⊢)⊟∵(-1+⌊×⚂3).⊢
⍜now⍥(⍜⊡(+1)◌°⊟⍢Nx(=0⊡⊢)Sd)500
</syntaxhighlight>
{{out}}
[[File:UiuaBrownianTree.png|thumb|center||Sample with higher values than provided code]]
 
=={{header|Visual Basic .NET}}==
Windows Forms Application.
 
<langsyntaxhighlight lang="vbnet">
Imports System.Drawing.Imaging
 
Line 1,491 ⟶ 5,595:
End Sub
End Class
</syntaxhighlight>
</lang>
{{out|Final output}}
[[File:SH_BrownianTree.jpg]]
=={{header|Wren}}==
{{libheader|DOME}}
{{trans|Go}}
As you'd expect, not very fast so have halved Go's parameters to draw the tree in around 45 seconds.
<syntaxhighlight lang="wren">import "graphics" for Canvas, Color
import "dome" for Window
import "random" for Random
 
var Rand = Random.new()
Final output:
 
var N8 = [
[[File:SH_BrownianTree.jpg]]
[-1, -1], [-1, 0], [-1, 1],
[ 0, -1], [ 0, 1],
[ 1, -1], [ 1, 0], [ 1, 1]
]
 
class BrownianTree {
construct new(width, height, particles) {
Window.title = "Brownian Tree"
Window.resize(width, height)
Canvas.resize(width, height)
_w = width
_h = height
_n = particles
}
 
init() {
Canvas.cls(Color.brown)
// off center seed position makes pleasingly asymetrical tree
Canvas.pset(_w/3, _h/3, Color.white)
var x = 0
var y = 0
var a = 0
while (a < _n) {
// generate random position for new particle
x = Rand.int(_w)
y = Rand.int(_h)
var outer = false
var p = Canvas.pget(x, y)
if (p == Color.white) {
// as position is already set, find a nearby free position.
while (p == Color.white) {
x = x + Rand.int(3) - 1
y = y + Rand.int(3) - 1
var ok = x >= 0 && x < _w && y >= 0 && y < _h
if (ok) {
p = Canvas.pget(x, y)
} else { // out of bounds, consider particle lost
outer = true
a = a + 1
break
}
}
} else {
// else particle is in free space
// let it wonder until it touches tree
while (!hasNeighbor(x, y)) {
x = x + Rand.int(3) - 1
y = y + Rand.int(3) - 1
var ok = x >= 0 && x < _w && y >= 0 && y < _h
if (ok) {
p = Canvas.pget(x, y)
} else { // out of bounds, consider particle lost
outer = true
a = a + 1
break
}
}
}
if (outer) continue
// x, y now specify a free position touching the tree
Canvas.pset(x, y, Color.white)
a = a + 1
// progress indicator
if (a % 100 == 0) System.print("%(a) of %(_n)")
a = a + 1
}
}
 
hasNeighbor(x, y) {
for (n in N8) {
var xn = x + n[0]
var yn = y + n[1]
var ok = xn >= 0 && xn < _w && yn >= 0 && yn < _h
if (ok && Canvas.pget(xn, yn) == Color.white) return true
}
return false
}
 
update() {}
 
draw(alpha) {}
}
 
var Game = BrownianTree.new(200, 150, 7500)</syntaxhighlight>
 
=={{header|XPL0}}==
[[File:BrownXPL0.gif|right]]
<syntaxhighlight lang="xpl0">include c:\cxpl\codes; \intrinsic 'code' declarations
def W=128, H=W; \width and height of field
int X, Y;
[SetVid($13); \set 320x200 graphic video mode
Point(W/2, H/2, 6\brown\); \place seed in center of field
loop [repeat X:= Ran(W); Y:= Ran(H); \inject particle
until ReadPix(X,Y) = 0; \ in an empty location
loop [Point(X, Y, 6\brown\); \show particle
if ReadPix(X-1,Y) or ReadPix(X+1,Y) or \particle collided
ReadPix(X,Y-1) or ReadPix(X,Y+1) then quit;
Point(X, Y, 0\black\); \erase particle
X:= X + Ran(3)-1; \(Brownian) move particle
Y:= Y + Ran(3)-1;
if X<0 or X>=W or Y<0 or Y>=H then quit; \out of bounds
];
if KeyHit then [SetVid(3); quit]; \restore text mode
];
]</syntaxhighlight>
=={{header|zkl}}==
This grows rather slowly, so I've added a circle for barnacles to attach to. It looks like tendrils growing from the center to the circle and vice versa. The tree type is similar to that shown in the XPLO and Visual Basic .NET solutions.
Also, the image is written to disk as each particle attaches so EventViewer will auto update to show the progression.
 
Uses the PPM class from http://rosettacode.org/wiki/Bitmap/Bresenham%27s_line_algorithm#zkl
[[File:Brownian.zkl.jpg|250px|thumb|right]]
<syntaxhighlight lang="zkl">w:=h:=400; numParticles:=20_000;
bitmap:=PPM(w+2,h+2,0); // add borders as clip regions
 
bitmap[w/2,h/2]=0xff|ff|ff; // plant seed
bitmap.circle(w/2,h/2,h/2,0x0f|0f|0f); // plant seeds
 
fcn touching(x,y,bitmap){ // is (x,y) touching another pixel?
// (x,y) isn't on the border/edge of bitmap so no edge conditions
var [const] box=T(T(-1,-1),T(0,-1),T(1,-1),
T(-1, 0), T(1, 0),
T(-1, 1),T(0, 1),T(1, 1));
box.filter1('wrap([(a,b)]){ bitmap[a+x,b+y] }); //-->False: not touching, (a,b) if is
}
 
while(numParticles){
c:=(0x1|00|00).random(0x1|00|00|00) + (0x1|00).random(0x1|00|00) + (0x1).random(0x1|00);
reg x,y;
do{ x=(1).random(w); y=(1).random(h); }while(bitmap[x,y]); // find empty spot
while(1){ // stagger around until bump into a particle, then attach barnicle
if(touching(x,y,bitmap)){
bitmap[x,y]=c;
bitmap.write(f:=File("brownianTree.zkl.ppm","wb")); // tell ImageViewer to update image
numParticles-=1;
break;
}
x+=(-1).random(2); y+=(-1).random(2); // [-1,0,1]
if( not ((0<x<w) and (0<y<h)) ){ // next to border --> color border
bitmap[x,y]=c;
break;
}
}
}
bitmap.writeJPGFile("brownianTree.zkl.jpg"); // the final image</syntaxhighlight>
=={{header|ZX Spectrum Basic}}==
{{trans|Run BASIC}}
Very, very slow on a ZX Spectrum (even emulate and at maximum speed). Best use SpecBAS, changing the value of the variable np to 6000.
<syntaxhighlight lang="zxbasic">10 LET np=1000
20 PAPER 0: INK 4: CLS
30 PLOT 128,88
40 FOR i=1 TO np
50 GO SUB 1000
60 IF NOT ((POINT (x+1,y+1)+POINT (x,y+1)+POINT (x+1,y)+POINT (x-1,y-1)+POINT (x-1,y)+POINT (x,y-1))=0) THEN GO TO 100
70 LET x=x+RND*2-1: LET y=y+RND*2-1
80 IF x<1 OR x>254 OR y<1 OR y>174 THEN GO SUB 1000
90 GO TO 60
100 PLOT x,y
110 NEXT i
120 STOP
1000 REM Calculate new pos
1010 LET x=RND*254
1020 LET y=RND*174
1030 RETURN
</syntaxhighlight>
130

edits