Jump to content

Chaos game

From Rosetta Code
Task
Chaos game
You are encouraged to solve this task according to the task description, using any language you may know.

The Chaos Game is a method of generating the attractor of an iterated function system (IFS).

One of the best-known and simplest examples creates a fractal, using a polygon and an initial point selected at random.


Task

Play the Chaos Game using the corners of an equilateral triangle as the reference points.   Add a starting point at random (preferably inside the triangle).   Then add the next point halfway between the starting point and one of the reference points.   This reference point is chosen at random.

After a sufficient number of iterations, the image of a Sierpinski Triangle should emerge.


See also



8086 Assembly

Translation of: BASIC

This program will run on a PC with CGA-compatible graphics. It will keep running until a key is pressed.

	cpu	8086
	bits	16
vmode:	equ	0Fh		; Get current video mode
time:	equ	2Ch		; Get current system time
CGALO:	equ	4		; Low-res (4-color) CGA mode
MDA:	equ	7		; MDA text mode
section	.text
	org	100h
	mov	ah,vmode	; Get current video mode
	int	10h
	cmp	al,MDA		; If MDA mode, no CGA supported, so stop
	jne	gr_ok
	ret
gr_ok:	push	ax		; Store old video mode on stack
	mov	ax,CGALO	; Switch to low-resolution CGA mode
	int	10h
	mov	ah,time		; Get system time
	int	21h
	mov	di,cx		; Store as RNG seed
	mov	bp,dx
genX:	call	random		; Generate random X coordinate
	cmp	al,200
	jae	genX
	mov	dh,al		; DH = X
genY:	call	random		; Generate random Y coordinate
	cmp	al,173
	jae	genY
	mov	dl,al		; DL = Y
mloop:	mov	ah,1		; Is a key pressed?
	int	16h
	jz	point		; If not, calculate another point
	pop	ax		; But if so, restore the old video mode
	cbw
	int	10h 
	ret			; And quit
point:	call	random		; Generate random direction
	and	al,3
	cmp	al,3
	je	point
	mov	ah,al		; Keep direction (for color later)
	dec	al		; Select direction
	jz	d2
	dec	al
	jz	d3
	shr	dh,1		; X /= 2
	shr	dl,1		; Y /= 2
	jmp	plot
d2:	mov	cl,ah		; Keep color in CL
	mov	si,100		; X = 100+(100-X)/2
	xor	ax,ax		; (doing intermediate math in 16 bits)
	mov	al,dh
	neg	ax
	add	ax,si
	shr	ax,1
	add	ax,si
	mov	dh,al
	mov	si,173		; Y = 173-(173-Y)/2
	xor	ax,ax		; (doing intermediate math in 16 bits)
	mov	al,dl
	neg	ax
	add	ax,si
	shr	ax,1
	neg	ax
	add	ax,si
	mov	dl,al
	mov	ah,cl		; Restore color
	jmp	plot
d3:	mov	cl,ah		; Keep color
	mov	si,200		; X = 200-(200-X)/2
	xor	ax,ax		; (doing intermediate math in 16 bits)
	mov	al,dh
	neg	ax
	add	ax,si
	shr	ax,1
	neg	ax
	add	ax,si
	mov	dh,al
	mov	ah,cl		; Restore color
	shr	dl,1		; Y /= 2
plot:	mov	cl,dl		; There's a plot function in the BIOS, but it's
	clc			; behind an INT and needs all the registers,
	rcr	cl,1		; so we'll do it by hand.
	sbb	bh,bh		; The even rows are at B800:NNNN, odd at BA00,
	xor	bl,bl		; CL (Y coord) is divided by two, and if odd
	and	bh,2		; we add 2(00) to B8(00) to get the right
	add	bh,0B8h		; segment.
	mov	ds,bx		; We can safely stick it in DS since we're not
	xor	bx,bx		; using any RAM otherwise. 80 bytes per line,
	mov	bl,cl		; so BX=Y * 80,
	xor	ch,ch		
	shl	bx,1		
	shl	bx,1
	add	bx,cx
	mov	cl,4
	shl	bx,cl
	mov	cl,dh		; and 4 pixels per byte, so BX += Y/4
	shr	cl,1
	shr	cl,1
	add	bx,cx
	inc	ah		; Add 1 to direction to get 1 of 3 colors
	mov	ch,dh		; See which pixel within the byte we're
	and	ch,3		; looking at
	mov	cl,3		; Leftmost pixel is in highest bits
	sub	cl,ch
	shl	cl,1		; Pixels are 2 bits wide
	shl	ah,cl 		; Shift AH into place
	or	[bx],ah		; Set the pixel in video memory
	jmp	mloop		; Next pixel
random:	xchg	bx,bp		; Load RNG state into byte-addressable
	xchg	cx,di 		; registers.
	inc	bl		; X++
	xor	bh,ch		; A ^= C
	xor	bh,bl		; A ^= X
	add	cl,bh		; B += A
	mov	al,cl		; C' = B
	shr	al,1		; C' >>= 1
	add	al,ch		; C' += C
	xor	al,bh		; C' ^= A
	mov	ch,al		; C = C'
	xchg	bx,bp		; Restore the registers
	xchg	cx,di
	ret

Action!

PROC Main()
  INT x,w=[220],h=[190]
  BYTE y,i,CH=$02FC,COLOR1=$02C5,COLOR2=$02C6

  Graphics(8+16)
  Color=1
  COLOR1=$0C
  COLOR2=$02

  x=Rand(w)
  y=Rand(h)
  DO
    i=Rand(3)
    IF i=0 THEN
      x==/2
      y==/2
    ELSEIF i=1 THEN
      x=w/2+(w/2-x)/2
      y=h-(h-y)/2
    ELSE
      x=w-(w-x)/2
      y=y/2
    FI
    Plot((320-w)/2+x,191-y)
  UNTIL CH#$FF
  OD
  CH=$FF
RETURN
Output:

Screenshot from Atari 8-bit computer

Ada

Uses the Alire Easy_Graphics package to generate GIF.

pragma Ada_2022;
with Ada.Numerics;  use Ada.Numerics;
with Ada.Numerics.Discrete_Random;
with Ada.Numerics.Elementary_Functions; use Ada.Numerics.Elementary_Functions;
with Easy_Graphics; use Easy_Graphics;

procedure Chaos_Game is
   Img : Easy_Image := New_Image ((1, 1), (512, 512), WHITE);
   
   procedure Chaos (Image        : in out Easy_Image;
                    Vertex_Count : Positive;
                    Radius       : Float;
                    Iters        : Positive) is
      type Vertex_Array is array (1 .. Vertex_Count) of Point;
      Vertices : Vertex_Array;
      subtype Vertex_Range is Integer range 1 .. Vertex_Count;
      package Rand_V is new Ada.Numerics.Discrete_Random (Vertex_Range);
      use Rand_V;
      Gen : Generator;
      Half_X  : constant Integer := X_Last (Image) / 2;
      Half_Y  : constant Integer := Y_Last (Image) / 2;
      Half_Pi : constant Float   := Float (Pi) / 2.0;
      Two_Pi  : constant Float   := Float (Pi) * 2.0;
      V       : Integer;
      X       : Integer := Half_X;
      Y       : Integer := Half_Y;
   begin
      for V in 1 .. Vertex_Count loop
         Vertices (V).X := Half_X + Integer (Float (Half_X) *
                           Cos (Half_Pi + (Float (V - 1)) * Two_Pi / Float (Vertex_Count)));
         Vertices (V).Y := Half_Y - Integer (Float (Half_Y) *
                           Sin (Half_Pi + (Float (V - 1)) * Two_Pi / Float (Vertex_Count)));
      end loop;
      for I in 1 .. Iters loop
         V := Random (Gen);
         X := X + Integer (Radius * Float (Vertices (V).X - X));
         Y := Y + Integer (Radius * Float (Vertices (V).Y - Y));
         Plot (Image, (X, Y), BLACK);
      end loop;
   end Chaos;

begin
   Chaos (Img, 3, 0.5, 250_000);
   Write_GIF (Img, "chaos_game.gif");
end Chaos_Game;
Output:
Sierpinski Triangle
Output from Ada version of Chaos Game

Amazing Hopper

Translation of: BASIC256

Considerar que Hopper no usa modos gráficos, y solo imprime el caracter ascii 219 achicando el tamaño de caracteres de la terminal, dado la ilusión de un modo gráfico "arcaico".

/* Chaos game - JAMBO hopper */

#include <jambo.h>

#define LIMITE  50000

Main
  ancho = 700, alto = 150
  x=0,y=0,color=0
  vertice=0, 
  c=0, Let( c := Utf8(Chr(219)))
  Let(x := Int(Rand(ancho)))
  Let(y := Int(Rand(alto)))

  mid ancho=0, Let( mid ancho:= Div(ancho,2))

  Cls
  i=LIMITE
  Void(pixeles)

  Loop
    Ceil(Rand(3)), On gosub( EQ1, EQ2, EQ3 )

    Set( Int(y), Int(x), color),Apndrow(pixeles)
    --i
  Back if (i) is not zero

  Canvas-term  
  Cls
  i=1
  Iterator(++i, Leq(i,LIMITE), Colorfore([i,3]Get(pixeles)), \
                             Locate( [i,1]Get(pixeles), [i,2]Get(pixeles) ), Print(c) )
  Pause

End
Subrutines
    EQ1:
          Let(x := Div(x, 2))
          Let(y := Div(y, 2))
          Let(color:=9), Return

    EQ2:
          Let(x := Add( mid ancho, Div(Sub(mid ancho, x), 2) ) )
          Let(y := Sub( alto, Div( Sub(alto, y), 2 )))
          Let(color:=10), Return
    EQ3:
          Let(x := Sub(ancho,  Div( Sub(ancho, x), 2)))
          Let(y := Div(y, 2))
          Let(color:=4), Return
Output:

BASIC

This should require minimal adaptation to work with any of the older Microsoft-style BASICs. Users of other dialects will need to replace lines 10 and 150 with the appropriate statements to select a graphics output mode (if necessary) and to plot a pixel at x,y in colour v; they should also add LET throughout and 170 END if their dialects require those things.

10 SCREEN 1
20 X = INT(RND(0) * 200)
30 Y = INT(RND(0) * 173)
40 FOR I=1 TO 20000
50 V = INT(RND(0) * 3) + 1
60 ON V GOTO 70,100,130
70 X = X/2
80 Y = Y/2
90 GOTO 150
100 X = 100 + (100-X)/2
110 Y = 173 - (173-Y)/2
120 GOTO 150
130 X = 200 - (200-X)/2
140 Y = Y/2
150 PSET X,Y,V
160 NEXT I

Applesoft BASIC

Adapted from the code given above.

10 HGR2
20 X = INT(RND(1) * 200)
30 Y = INT(RND(1) * 173)
40 FOR I=1 TO 20000
50 V = INT(RND(1) * 3) + 1
60 ON V GOTO 70,100,130
70 X = X/2
80 Y = Y/2
90 GOTO 150
100 X = 100 + (100-X)/2
110 Y = 173 - (173-Y)/2
120 GOTO 150
130 X = 200 - (200-X)/2
140 Y = Y/2
150 HCOLOR=V+4
160 HPLOT X,Y
170 NEXT I

BASIC256

#Chaos game

ancho = 500 : alto = 300
x = Int(Rand * ancho)
y = Int(Rand * alto)

Clg
FastGraphics
Graphsize ancho , alto

For iteracion = 1 To 30000
	vertice = Int(Rand * 3) + 1
	Begin Case
		Case vertice = 1
			x = x / 2
			y = y / 2
			Color red
		Case vertice = 2
			x = (ancho/2) + ((ancho/2)-x) / 2
			y = alto - (alto-y) / 2
			Color green
		Case vertice = 3
			x = ancho - (ancho-x) / 2
			y = y / 2
			Color blue
	End Case
	#Pset (x,y),vertice
	Plot (x,y)
Next iteracion
Refresh
ImgSave "chaos_game.jpg", "jpg"
End

GW-BASIC

Works with: PC-BASIC version any
Works with: BASICA
100 REM Chaos game
110 CLS
120 SCREEN 7    '320x200 EGA Color
130 X = INT(RND(1) * 200)
140 Y = INT(RND(1) * 173)
150 FOR I=1 TO 20000
160  V = INT(RND(1) * 3) + 1
170  ON V GOTO 180,210,240
180  X = X/2
190  Y = Y/2
200  GOTO 260
210  X = 100 + (100-X)/2
220  Y = 173 - (173-Y)/2
230  GOTO 260
240  X = 200 - (200-X)/2
250  Y = Y/2
260  PSET(X,Y),V
270 NEXT I
280 END

IS-BASIC

100 PROGRAM "ChaosGam.bas"
110 RANDOMIZE 
120 GRAPHICS HIRES 4
130 LET X=RND(800):LET Y=RND(600)
140 FOR I=1 TO 20000
150   LET VERTEX=RND(3)
160   SELECT CASE VERTEX
170   CASE 0
180     LET X=X/2
190     LET Y=Y/2
200   CASE 1
210     LET X=400+(400-X)/2
220     LET Y=600-(600-Y)/2
230   CASE 2
240     LET X=800-(800-X)/2
250     LET Y=Y/2
260   END SELECT 
270   SET INK VERTEX+1
280   PLOT X,Y
290 NEXT

Locomotive Basic

Adapted from the generic BASIC version. In CPCBasic this program completes in less than a second. But on a real CPC (or equivalent emulator), the same program takes over six minutes to run. So using CPCBasic is strongly advised. On CPCBasic, one can also use "mode 3" instead of mode 1 in line 10 and increase iterations to e.g. 2000000 in line 40, resulting in a higher-resolution image.

10 mode 1:randomize time:defint a-z
20 x = 640 * rnd
30 y = 400 * rnd
40 for i=1 to 20000
50 v = rnd * 2 + 1
60 on v goto 70,100,130
70 x = x/2
80 y = y/2
90 goto 150
100 x = 320 + (320-x)/2
110 y = 400 - (400-y)/2
120 goto 150
130 x = 640 - (640-x)/2
140 y = y/2
150 plot x,y,v
160 next i

MSX Basic

Works with: MSX BASIC version any
100 REM Chaos game
110 CLS
120 SCREEN 2
130 X = INT(RND(1) * 256)
140 Y = INT(RND(1) * 192)
150 FOR I=1 TO 20000
160  V = INT(RND(1) * 3) + 1
170  ON V GOTO 180,220,260
180  X = X/2
190  Y = Y/2
200  V = 8 'red
210  GOTO 290
220  X = 128 + (128-X)/2
230  Y = 192 - (192-Y)/2
240  V = 3 'green
250  GOTO 290
260  X = 256 - (256-X)/2
270  Y = Y/2
280  V = 7 'blue
290  PSET(X,Y),V
300 NEXT I
310 END

Sinclair ZX81 BASIC

Adapted from the other BASIC versions. Monochrome and low-resolution, of course. Works with only 1k of RAM. If you like, you can try changing line 30 to go round the loop a different number of times.

Note that ZX81 BASIC does not have an explicit computed GOTO; we can, however, actually compute the value of an expression and then GOTO it as a line number.

 10 LET X=RND*46
 20 LET Y=RND*40
 30 FOR I=1 TO 5000
 40 LET VERTEX=INT (RND*3)
 50 GOTO 60+VERTEX*30
 60 LET X=X/2
 70 LET Y=Y/2
 80 GOTO 140
 90 LET X=23+(23-X)/2
100 LET Y=40-(40-Y)/2
110 GOTO 140
120 LET X=46-(46-X)/2
130 LET Y=Y/2
140 PLOT X,42-Y
150 NEXT I
Output:

Screenshot here. As with most ZX81 graphics, you can obtain the very best results by making it quite small and looking at it from a long way away.

ZX Spectrum Basic

The final INK statement sets the foreground colour back to black.

 10 LET x=RND*200
 20 LET y=RND*173
 30 FOR i=1 TO 20000
 40 LET vertex=INT (RND*3)
 50 IF vertex=1 THEN GO TO 100
 60 IF vertex=2 THEN GO TO 130
 70 LET x=x/2
 80 LET y=y/2
 90 GO TO 150
100 LET x=100+(100-x)/2
110 LET y=173-(173-y)/2
120 GO TO 150
130 LET x=200-(200-x)/2
140 LET y=y/2
150 INK vertex+1
160 PLOT x,y
170 NEXT i
180 INK 0

C

Interactive code which asks the side length of the starting triangle and number of iterations as inputs, a larger number of iterations produces a more accurate approximation of the Sierpinski fractal. Requires the WinBGIm library.

#include<graphics.h>
#include<stdlib.h>
#include<stdio.h>
#include<math.h>
#include<time.h>

#define pi M_PI

int main(){
	
	time_t t;
	double side, vertices[3][3],seedX,seedY,windowSide;
	int i,iter,choice;
	
	printf("Enter triangle side length : ");
	scanf("%lf",&side);
	
	printf("Enter number of iterations : ");
	scanf("%d",&iter);
	
	windowSide = 10 + 2*side;

	initwindow(windowSide,windowSide,"Sierpinski Chaos");
	
	for(i=0;i<3;i++){
		vertices[i][0] = windowSide/2 + side*cos(i*2*pi/3);
		vertices[i][1] = windowSide/2 + side*sin(i*2*pi/3);
		putpixel(vertices[i][0],vertices[i][1],15);
	}
	
	srand((unsigned)time(&t));
	
	seedX = rand()%(int)(vertices[0][0]/2 + (vertices[1][0] + vertices[2][0])/4);
	seedY = rand()%(int)(vertices[0][1]/2 + (vertices[1][1] + vertices[2][1])/4);
	
	putpixel(seedX,seedY,15);
	
	for(i=0;i<iter;i++){
		choice = rand()%3;
		
		seedX = (seedX + vertices[choice][0])/2;
		seedY = (seedY + vertices[choice][1])/2;
		
		putpixel(seedX,seedY,15);
	}
	
	getch();
	
	closegraph();
	
	return 0;
}

C#

using System.Diagnostics;
using System.Drawing;

namespace RosettaChaosGame
{
    class Program
    {
        static void Main(string[] args)
        {
            var bm = new Bitmap(600, 600);

            var referencePoints = new Point[] {
                new Point(0, 600),
                new Point(600, 600),
                new Point(300, 81)
            };
            var r = new System.Random();
            var p = new Point(r.Next(600), r.Next(600));
            for (int count = 0; count < 10000; count++)
            {
                bm.SetPixel(p.X, p.Y, Color.Magenta);
                int i = r.Next(3);
                p.X = (p.X + referencePoints[i].X) / 2;
                p.Y = (p.Y + referencePoints[i].Y) / 2;
            }
            const string filename = "Chaos Game.png";
            bm.Save(filename);
            Process.Start(filename);
        }
    }
}

C++

This program will generate the Sierpinski Triangle and save it to your hard drive.

#include <windows.h>
#include <ctime>
#include <string>
#include <iostream>
 
const int BMP_SIZE = 600;

class myBitmap {
public:
    myBitmap() : pen( NULL ), brush( NULL ), clr( 0 ), wid( 1 ) {}
    ~myBitmap() {
        DeleteObject( pen ); DeleteObject( brush );
        DeleteDC( hdc ); DeleteObject( bmp );
    }
    bool create( int w, int h ) {
        BITMAPINFO bi;
        ZeroMemory( &bi, sizeof( bi ) );
        bi.bmiHeader.biSize        = sizeof( bi.bmiHeader );
        bi.bmiHeader.biBitCount    = sizeof( DWORD ) * 8;
        bi.bmiHeader.biCompression = BI_RGB;
        bi.bmiHeader.biPlanes      = 1;
        bi.bmiHeader.biWidth       =  w;
        bi.bmiHeader.biHeight      = -h;
 
        HDC dc = GetDC( GetConsoleWindow() );
        bmp = CreateDIBSection( dc, &bi, DIB_RGB_COLORS, &pBits, NULL, 0 );
        if( !bmp ) return false;
 
        hdc = CreateCompatibleDC( dc );
        SelectObject( hdc, bmp );
        ReleaseDC( GetConsoleWindow(), dc );
 
        width = w; height = h;
        return true;
    }
    void clear( BYTE clr = 0 ) {
        memset( pBits, clr, width * height * sizeof( DWORD ) );
    }
    void setBrushColor( DWORD bClr ) {
        if( brush ) DeleteObject( brush );
        brush = CreateSolidBrush( bClr );
        SelectObject( hdc, brush );
    }
    void setPenColor( DWORD c ) {
        clr = c; createPen();
    }
    void setPenWidth( int w ) {
        wid = w; createPen();
    }
    void saveBitmap( std::string path ) {
        BITMAPFILEHEADER fileheader;
        BITMAPINFO       infoheader;
        BITMAP           bitmap;
        DWORD            wb;
 
        GetObject( bmp, sizeof( bitmap ), &bitmap );
        DWORD* 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 );
 
        HANDLE 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() const     { return hdc; }
    int getWidth() const  { return width; }
    int getHeight() const { return height; }
private:
    void createPen() {
        if( pen ) DeleteObject( pen );
        pen = CreatePen( PS_SOLID, wid, clr );
        SelectObject( hdc, pen );
    }
    HBITMAP bmp; HDC    hdc;
    HPEN    pen; HBRUSH brush;
    void    *pBits; int    width, height, wid;
    DWORD    clr;
};
class chaos {
public:
    void start() {
        POINT org;
        fillPts(); initialPoint( org ); initColors();
        int cnt = 0, i;
        bmp.create( BMP_SIZE, BMP_SIZE );
        bmp.clear( 255 );

        while( cnt++ < 1000000 ) {
            switch( rand() % 6 ) {
                case 0: case 3: i = 0; break;
                case 1: case 5: i = 1; break;
                case 2: case 4: i = 2;
            }
            setPoint( org, myPoints[i], i );
        }
        // --- edit this path --- //
        bmp.saveBitmap( "F:/st.bmp" );
    }
private:
    void setPoint( POINT &o, POINT v, int i ) {
        POINT z;
        o.x = ( o.x + v.x ) >> 1; o.y = ( o.y + v.y ) >> 1;
        SetPixel( bmp.getDC(), o.x, o.y, colors[i] );
    }
    void fillPts() {
        int a = BMP_SIZE - 1;
        myPoints[0].x = BMP_SIZE >> 1; myPoints[0].y = 0;
        myPoints[1].x = 0; myPoints[1].y = myPoints[2].x = myPoints[2].y = a;
    }
    void initialPoint( POINT& p ) {
        p.x = ( BMP_SIZE >> 1 ) + rand() % 2 ? rand() % 30 + 10 : -( rand() % 30 + 10 );
        p.y = ( BMP_SIZE >> 1 ) + rand() % 2 ? rand() % 30 + 10 : -( rand() % 30 + 10 );
    }
    void initColors() {
        colors[0] = RGB( 255, 0, 0 );
        colors[1] = RGB( 0, 255, 0 );
        colors[2] = RGB( 0, 0, 255 );
    }
    
    myBitmap bmp;
    POINT myPoints[3];
    COLORREF colors[3];
};
int main( int argc, char* argv[] ) {
    srand( ( unsigned )time( 0 ) );
    chaos c; c.start();
    return 0;
}

Common Lisp

Library: opticl
(defpackage #:chaos
  (:use #:cl
        #:opticl))

(in-package #:chaos)

(defparameter *image-size* 600)
(defparameter *margin* 50)
(defparameter *edge-size* (- *image-size* *margin* *margin*))
(defparameter *iterations* 1000000)

(defun chaos ()
  (let ((image (make-8-bit-rgb-image *image-size* *image-size* :initial-element 255))
        (a (list (- *image-size* *margin*) *margin*))
        (b (list (- *image-size* *margin*) (- *image-size* *margin*)))
        (c (list (- *image-size* *margin* (round (* (tan (/ pi 3)) *edge-size*) 2))
                 (round *image-size* 2)))
        (point (list (+ (random *edge-size*) *margin*)
                     (+ (random *edge-size*) *margin*))))
    (dotimes (i *iterations*)
      (let ((ref (ecase (random 3)
                   (0 a)
                   (1 b)
                   (2 c))))
        (setf point (list (round (+ (first  point) (first  ref)) 2)
                          (round (+ (second point) (second ref)) 2))))
      (setf (pixel image (first point) (second point))
            (values 255 0 0)))
    (write-png-file "chaos.png" image)))

Delphi

Library: Vcl.Forms
unit main;

interface

uses
  Winapi.Windows, System.Classes, Vcl.Graphics, Vcl.Forms, Vcl.ExtCtrls,
  System.Generics.Collections;

type
  TColoredPoint = record
    P: TPoint;
    Index: Integer;
    constructor Create(PX, PY: Integer; ColorIndex: Integer);
  end;

  TForm1 = class(TForm)
    procedure FormCreate(Sender: TObject);
    procedure FormDestroy(Sender: TObject);
    procedure FormPaint(Sender: TObject);
  private
    Buffer: TBitmap;
    Points: array[0..2] of TPoint;
    Stack: TStack<TColoredPoint>;
    Tick: TTimer;
    procedure Run(Sender: TObject);
    procedure AddPoint;
    function HalfWayPoint(a: TColoredPoint; b: TPoint; index: Integer): TColoredPoint;
    { Private declarations }
  public
    { Public declarations }
  end;

const
  Colors: array[0..2] of Tcolor = (clRed, clGreen, clBlue);

var
  Form1: TForm1;

implementation

{$R *.dfm}

{ TColoredPoint }

constructor TColoredPoint.Create(PX, PY: Integer; ColorIndex: Integer);
begin
  self.P := Tpoint.Create(PX, PY);
  self.Index := ColorIndex;
end;

{ TForm1 }

procedure TForm1.FormCreate(Sender: TObject);
begin
  Buffer := TBitmap.Create;
  Stack := TStack<TColoredPoint>.Create;
  Tick := TTimer.Create(nil);
  Caption := 'Chaos Game';

  DoubleBuffered := True;

  ClientHeight := 640;
  ClientWidth := 640;
  var margin := 60;
  var size := ClientWidth - 2 * margin;

  Points[0] := TPoint.Create(ClientWidth div 2, margin);
  Points[1] := TPoint.Create(margin, size);
  Points[2] := TPoint.Create(margin + size, size);

  Stack.Push(TColoredPoint.Create(-1, -1, Colors[0]));

  Tick.Interval := 10;
  Tick.OnTimer := Run;
end;

function TForm1.HalfWayPoint(a: TColoredPoint; b: TPoint; index: Integer): TColoredPoint;
begin
  Result := TColoredPoint.Create((a.p.X + b.x) div 2, (a.p.y + b.y) div 2, index);
end;

procedure TForm1.AddPoint;
begin
  var colorIndex := Random(3);
  var p1 := Stack.Peek;
  var p2 := Points[colorIndex];
  Stack.Push(HalfWayPoint(p1, p2, colorIndex));
end;

procedure TForm1.Run(Sender: TObject);
begin
  if Stack.Count < 50000 then
  begin
    for var i := 0 to 999 do
      AddPoint;
    Invalidate;
  end;
end;

procedure TForm1.FormDestroy(Sender: TObject);
begin
  Tick.Free;
  Buffer.Free;
  Stack.Free;
end;

procedure TForm1.FormPaint(Sender: TObject);
begin
  for var p in Stack do
  begin
    with Canvas do
    begin
      Pen.Color := Colors[p.Index];
      Brush.Color := Colors[p.Index];
      Brush.Style := bsSolid;
      Ellipse(p.p.X - 1, p.p.y - 1, p.p.X + 1, p.p.y + 1);
    end;
  end;
end;
end.

EasyLang

Run it

color 900
x[] = [ 0 100 50 ]
y[] = [ 7 7 93 ]
x = randomf * 100
y = randomf * 100
for i = 1 to 100000
   move x y
   rect 0.3 0.3
   h = random 3
   x = (x + x[h]) / 2
   y = (y + y[h]) / 2
.

Emacs Lisp

Output
; Chaos game

(defun make-array (size)
  "Create an empty array with size*size elements."
  (setq m-array (make-vector size nil))
  (dotimes (i size)
    (setf (aref m-array i) (make-vector size 0)))
  m-array)

(defun chaos-next (p)
  "Return the next coordinates."
  (let* ((points (list (cons 1 0) (cons -1 0) (cons 0 (sqrt 3))))
 	 (v (elt points (random 3)))
         (x (car p))
         (y (cdr p))
         (x2 (car v))
         (y2 (cdr v)))
      (setq nx (/ (+ x x2) 2.0))
      (setq ny (/ (+ y y2) 2.0))
      (cons nx ny)))

(defun chaos-lines (arr size)
  "Turn array into a string for XPM conversion."
  (setq all "")
  (dotimes (y size)
    (setq line "")
    (dotimes (x size)
      (setq line (concat line (if (= (elt (elt arr y) x) 1) "*" "."))))
    (setq all (concat all "\"" line "\",\n")))
  all)

(defun chaos-show (arr size)
  "Convert size*size array to XPM image and show it."
  (insert-image (create-image (concat (format "/* XPM */
static char * chaos[] = {
\"%i %i 2 1\",
\".      c #000000\",
\"*      c #00ff00\"," size size)
    (chaos-lines arr size) "};") 'xpm t)))

(defun chaos (size scale max-iter)
  "Play the chaos game."
  (let ((arr (make-array size))
        (p (cons 0 0)))
    (dotimes (it max-iter)
      (setq p (chaos-next p))
      (setq x (round (+ (/ size 2) (* scale (car p)))))
      (setq y (round (+ (- size 10) (* -1 scale (cdr p)))))
      (setf (elt (elt arr y) x) 1))
    (chaos-show arr size)))

(chaos 400 180 50000)

F#

open System.Windows.Forms
open System.Drawing
open System

let sz = 300
let polygon = [Point(sz/2, int (float sz*(1.0-sin(Math.PI/3.0)))); Point(0, sz-1); Point(sz-1, sz-1)]

let bmp = new Bitmap(sz, sz)
let paint (p: Point) = bmp.SetPixel(p.X, p.Y, Color.Black)

let random = Random()
let seed = Point(int (random.NextDouble() * float sz), int (random.NextDouble() * float sz))
let midpoint (p1: Point) (p2: Point) = Point((p1.X + p2.X) / 2, (p1.Y + p2.Y) / 2)
let randomVertex() = polygon.[random.Next(polygon.Length)]
let step p _ =
    paint p
    midpoint p (randomVertex())
Seq.init 100000 id |> Seq.fold step seed

let f = new Form()
f.ClientSize <- bmp.Size
f.Paint.Add (fun args -> args.Graphics.DrawImage(bmp, Point(0, 0)))
f.Show()

Forth

Works with: gforth version 0.7.3


#! /usr/bin/gforth
\ Chaos Game

require random.fs

\ initialize the random number generator with a time-dependent seed
utime drop seed !

\ parses a number from a string
: parse-number ( -- n )
    s>number? invert throw drop
;


\ parse the width of the triangle, the number of steps and the output filename from the command-line

." width:  " next-arg parse-number dup  .    cr CONSTANT  WIDTH
." steps:  " next-arg parse-number dup  .    cr CONSTANT  STEPS
." output: " next-arg              2dup type cr 2CONSTANT OUT-FILE


\ height of the triangle: height = sqrt(3) / 2 * width
WIDTH 0 d>f 3e fsqrt f* 2e f/ fround f>d drop CONSTANT HEIGHT  \ height of the triangle: height = sqrt(3) / 2 * width


\ coordinates of the three corners of the triangle

0         CONSTANT X1
0         CONSTANT Y1
WIDTH     CONSTANT X2
0         CONSTANT Y2
WIDTH 2 / CONSTANT X3
HEIGHT    CONSTANT Y3


\ minimal and maximal x and y coordinates

X1 X2 X3 min min CONSTANT XMIN
X1 X2 X3 max max CONSTANT XMAX
Y1 Y2 Y3 min min CONSTANT YMIN
Y1 Y2 Y3 max max CONSTANT YMAX

XMAX XMIN - 1+ CONSTANT XSIZE
YMAX YMIN - 1+ CONSTANT YSIZE


\ initialize array for all possible points

XSIZE YSIZE *
dup CREATE ARR cells allot
ARR swap cells erase


\ address of the cell corresponding to point (x,y)
: addr? ( x y -- addr )
    XSIZE * + cells ARR +
;

\ scalar product of the 2-vectors
: sp ( x1 y1 x2 y2 -- n )
    swap >r * r> rot * +
;

\ is the point (x,y) on the left of the ray from (px,py) to (qx,qy)?
: left? ( px py qx qy x y -- f )
    { px py qx qy x y }
    py qy -
    qx px -
    x  px -
    y  py -
    sp 0>=
;

\ is the point (x,y) in the triangle?
: in-triangle? ( x y -- f )
    { x y }
    X1 Y1 X2 Y2 x y left?
    X2 Y2 X3 Y3 x y left?
    X3 Y3 X1 Y1 x y left?
    and and
;

\ generates a random number in [a,b]
: random-in-range ( a b -- n )
    over - 1+ random +
;

\ generates a random point in the triangle
: random-in-triangle ( -- x y )
    0 0
    BEGIN
        2drop
        XMIN XMAX random-in-range
        YMIN YMAX random-in-range
        2dup in-triangle?
    UNTIL
;

\ finds the middle of to points (px,py) and (qx,qy)
: middle ( px py qx qy -- x y )
    swap -rot
    + 2/ -rot
    + 2/ swap
;

\ plays the chaos game for a number of steps
: game ( n -- )
    random-in-triangle
    rot
    0 DO
        2dup addr? true swap !
        3 random CASE
            0 OF X1 Y1 ENDOF
            1 OF X2 Y2 ENDOF
            2 OF X3 Y3 ENDOF
        ENDCASE
        middle
    LOOP
    2drop
;

\ writes the result in pbm-format
: write-pbm ( -- )
    ." P1" cr
    XSIZE . YSIZE . cr
    YMIN 1- YMAX -DO
        XMAX 1+ XMIN DO
            i j addr? @ IF 1 . ELSE 0 . THEN
        LOOP
        cr
    1 -LOOP
;

\ writes the result to a pbm-file
: to-pbm ( c-addr u -- )
    w/o create-file throw ['] write-pbm over outfile-execute close-file throw
;

\ play the game and save the result
STEPS game OUT-FILE to-pbm

bye
Output:

playing a million steps on a triangle with base length 1000: ./chaos-game.fs 1000 1000000 chao-game.pbm:] [1]

Fortran

This FORTRAN code creates an output file which can be drawn with gnuplot.

PROGRAM CHAOS
 IMPLICIT NONE
 REAL, DIMENSION(3):: KA, KN ! Koordinates old/new
 REAL, DIMENSION(3):: DA, DB, DC ! Triangle
 INTEGER:: I, Z
 INTEGER, PARAMETER:: UT = 17
 ! Define corners of triangle
 DA = (/    0., 0.,   0. /)
 DB = (/  600., 0.,   0. /)
 DC = (/  500., 0., 400. /)
 ! Define starting point
 KA = (/  500., 0., 100. /)
 OPEN (UNIT = UT, FILE = 'aus.csv')
 DO I=1, 1000000
  Z = ZAHL()
  WRITE (UT, '(3(F12.6, ";"))') KA
  SELECT CASE (Z)
   CASE (1)
    CALL MITTELP(KA, DA, KN)
   CASE (2)
    CALL MITTELP(KA, DB, KN)
   CASE (3)
    CALL MITTELP(KA, DC, KN)
  END SELECT
  KA = KN
 END DO
 CLOSE (UT)
 CONTAINS
  ! Calculates center of two points
  SUBROUTINE MITTELP(P1, P2, MP)
   REAL, INTENT(IN), DIMENSION(3):: P1, P2
   REAL, INTENT(OUT), DIMENSION(3):: MP
   MP = (P1 + P2) / 2.
  END SUBROUTINE MITTELP
  ! Returns random number
  INTEGER FUNCTION ZAHL()
   REAL:: ZZ
   CALL RANDOM_NUMBER(ZZ)
   ZZ = ZZ * 3.
   ZAHL = FLOOR(ZZ) + 1
   IF (ZAHL .GT. 3) ZAHL = 3
  END FUNCTION ZAHL
END PROGRAM CHAOS

Gnuplot Code to draw file:

set terminal jpeg enhanced size 1600,960
set output 'chaos.jpg'
set nokey
set style line 1 lc rgb '#0060ad' lt 1 lw 3 pt 7 ps 0.3
plot 'aus.csv' using 1:3 with points ls 1 notitle

FreeBASIC

Translation of: BASIC256
' Chaos game
Const ancho = 320, alto = 240
Dim As Integer x, y, iteracion, vertice
x = Int(Rnd * ancho)
y = Int(Rnd * alto)

Screenres ancho, alto, 8
Cls

For iteracion = 1 To 30000
	vertice = Int(Rnd * 3) + 1
	Select Case vertice
    Case 1
        x = x / 2
        y = y / 2
        vertice = 4 'red
    Case 2
        x = (ancho/2) + ((ancho/2)-x) / 2
        y = alto - (alto-y) / 2
        vertice = 2 'green
    Case 3
        x = ancho - (ancho-x) / 2
        y = y / 2
        vertice = 1 'blue
    End Select
	Pset (x,y),vertice
Next iteracion
Sleep
End

Fōrmulæ

Fōrmulæ programs are not textual, visualization/edition of programs is done showing/manipulating structures but not text. Moreover, there can be multiple visual representations of the same program. Even though it is possible to have textual representation —i.e. XML, JSON— they are intended for storage and transfer purposes more than visualization and edition.

Programs in Fōrmulæ are created/edited online in its website.

In this page you can see and run the program(s) related to this task and their results. You can also change either the programs or the parameters they are called with, for experimentation, but remember that these programs were created with the main purpose of showing a clear solution of the task, and they generally lack any kind of validation.

Solution

Test case. Sierpiński triangle

FutureBasic

void local fn DoIt
  long w = 460, h = 400, i, x = rnd(w), y = rnd(h)
  for i = 1 to 50000
    select ( rnd(3)-1 )
      case 1
        x = w/2+(w/2-x)/2
        y = h-(h-y)/2
        pen ,fn ColorRed
      case 2
        x = w-(w-x)/2
        y = y/2
        pen ,fn ColorGreen
      case else
        x = x/2
        y = y/2
        pen ,fn ColorBlue
    end select
    line x-0.5,y-0.5,x+0.5,y+0.5
  next
end fn

window 1, @"Chaos Game", (0,0,460,400)
WindowSetBackgroundColor( 1, fn ColorWhite )

fn DoIt

HandleEvents

GML

Create two new objects and rename them to "Game" and "Point" respectively.


"Game" Object Create Event:

offset = 32; //Distance from triangle vertices to edges of window

//triangle vertex coordinates
x1 = room_width / 2;
y1 = offset;
x2 = room_width - offset;
y2 = room_height - offset;
x3 = offset;
y3 = room_height - offset;

//Coords of randomly chosen vertex (set to 0 to start, will automatically be set in step event)
vx = 0;
vy = 0;

//Coords of current point
px = random(room_width);
py = random(room_height);

//Make sure the point is within the triangle
while(!point_in_triangle(px, py, x1, y1, x2, y2, x3, y3))
{
	px = random(room_width);
	py = random(room_height);
}

vertex = 0; //This determines which vertex coords are chosen
max_iterations = 8000;
step = true; //Used with the interval alarm to change the step speed
step_count = 0;
interval = 1; //Number of frames between each step. 1 = no delay
alarm[0] = interval;


"Game" Object Step Event:

if(step and step_count < max_iterations) //Wait for alarm to finish, or stop completely
{										// if the desired number of iterations is hit
	vertex = choose(1, 2, 3);
	step = false;
	alarm[0] = interval;
	switch(vertex)
	{
		case 1:
			vx = x1;
			vy = y1;
		break;
	
		case 2:
			vx = x2;
			vy = y2;
		break;
	
		case 3:
			vx = x3;
			vy = y3;
		break;
	}

	var dir = point_direction(px, py, vx, vy);
	var mid_dist = point_distance(px, py, vx, vy);
	var midx = px + lengthdir_x(mid_dist / 2, dir);
	var midy = py + lengthdir_y(mid_dist / 2, dir);
	instance_create_layer(midx, midy, "Instances", Point);

	px = midx;
	py = midy;
	
	step_count++;
}


"Game" Object Draw Event:

if(step_count < max_iterations)
{
	draw_triangle(x1, y1, x2, y2, x3, y3, true);
	draw_circle(px, py, 1, false);
	draw_line(px, py, vx, vy);
}


"Game" Object Alarm 0:

step = true;
alarm[0] = interval;


"Point" Object Draw Event:

draw_circle(x, y, 5, false);

Gnuplot

Translation of: PARI/GP
Works with: gnuplot version 5.0 (patchlevel 3) and above
File:ChGS3Gnu1.png
Output ChGS3Gnu1.png
## Chaos Game  (Sierpinski triangle) 2/16/17 aev
reset
fn="ChGS3Gnu1"; clr='"red"';
ttl="Chaos Game  (Sierpinski triangle)"
sz=600; sz1=sz/2; sz2=sz1*sqrt(3);
x=y=xf=yf=v=0;
dfn=fn.".dat"; ofn=fn.".png";
set terminal png font arial 12 size 640,640
set print dfn append
set output ofn
unset border; unset xtics; unset ytics; unset key;
set size square 
set title ttl font "Arial:Bold,12"
lim=30000; max=100; x=y=xw=yw=p=0;
randgp(top) = floor(rand(0)*top)
x=randgp(sz); y=randgp(sz2);
do for [i=1:lim] {
  v=randgp(3);
  if (v==0) {x=x/2; y=y/2}
  if (v==1) {x=sz1+(sz1-x)/2; y=sz2-(sz2-y)/2}
  if (v==2) {x=sz-(sz-x)/2; y=y/2}
  xf=floor(x); yf=floor(y); 
  if(!(xf<1||xf>sz||yf<1||yf>sz)) {print xf," ",yf};
}
plot dfn using 1:2 with points  pt 7 ps 0.5 lc @clr
set output
unset print
Output:
File: ChGS3Gnu1.png 

Go

This writes a simple GIF animation of the method.

package main

import (
	"fmt"
	"image"
	"image/color"
	"image/draw"
	"image/gif"
	"log"
	"math"
	"math/rand"
	"os"
	"time"
)

var bwPalette = color.Palette{
	color.Transparent,
	color.White,
	color.RGBA{R: 0xff, A: 0xff},
	color.RGBA{G: 0xff, A: 0xff},
	color.RGBA{B: 0xff, A: 0xff},
}

func main() {
	const (
		width          = 160
		frames         = 100
		pointsPerFrame = 50
		delay          = 100 * time.Millisecond
		filename       = "chaos_anim.gif"
	)

	var tan60 = math.Sin(math.Pi / 3)
	height := int(math.Round(float64(width) * tan60))
	b := image.Rect(0, 0, width, height)
	vertices := [...]image.Point{
		{0, height}, {width, height}, {width / 2, 0},
	}

	// Make a filled triangle.
	m := image.NewPaletted(b, bwPalette)
	for y := b.Min.Y; y < b.Max.Y; y++ {
		bg := int(math.Round(float64(b.Max.Y-y) / 2 / tan60))
		for x := b.Min.X + bg; x < b.Max.X-bg; x++ {
			m.SetColorIndex(x, y, 1)
		}
	}

	// Pick starting point
	var p image.Point
	rand.Seed(time.Now().UnixNano())
	p.Y = rand.Intn(height) + b.Min.Y
	p.X = rand.Intn(width) + b.Min.X // TODO: make within triangle

	anim := newAnim(frames, delay)
	addFrame(anim, m)
	for i := 1; i < frames; i++ {
		for j := 0; j < pointsPerFrame; j++ {
			// Pick a random vertex
			vi := rand.Intn(len(vertices))
			v := vertices[vi]
			// Move p halfway there
			p.X = (p.X + v.X) / 2
			p.Y = (p.Y + v.Y) / 2
			m.SetColorIndex(p.X, p.Y, uint8(2+vi))
		}
		addFrame(anim, m)
	}
	if err := writeAnim(anim, filename); err != nil {
		log.Fatal(err)
	}
	fmt.Printf("wrote to %q\n", filename)
}

// Stuff for making a simple GIF animation.

func newAnim(frames int, delay time.Duration) *gif.GIF {
	const gifDelayScale = 10 * time.Millisecond
	g := &gif.GIF{
		Image: make([]*image.Paletted, 0, frames),
		Delay: make([]int, 1, frames),
	}
	g.Delay[0] = int(delay / gifDelayScale)
	return g
}
func addFrame(anim *gif.GIF, m *image.Paletted) {
	b := m.Bounds()
	dst := image.NewPaletted(b, m.Palette)
	draw.Draw(dst, b, m, image.ZP, draw.Src)
	anim.Image = append(anim.Image, dst)
	if len(anim.Delay) < len(anim.Image) {
		anim.Delay = append(anim.Delay, anim.Delay[0])
	}
}
func writeAnim(anim *gif.GIF, filename string) error {
	f, err := os.Create(filename)
	if err != nil {
		return err
	}
	err = gif.EncodeAll(f, anim)
	if cerr := f.Close(); err == nil {
		err = cerr
	}
	return err
}

Groovy

Library: JavaFX
import javafx.animation.AnimationTimer
import javafx.application.Application
import javafx.scene.Scene
import javafx.scene.layout.Pane
import javafx.scene.paint.Color
import javafx.scene.shape.Circle
import javafx.stage.Stage

class ChaosGame extends Application {

    final randomNumberGenerator = new Random()

    @Override
    void start(Stage primaryStage) {
        primaryStage.title = 'Chaos Game'
        primaryStage.scene = getScene()
        primaryStage.show()
    }

    def getScene() {
        def colors = [Color.RED, Color.GREEN, Color.BLUE]

        final width = 640, height = 640, margin = 60
        final size = width - 2 * margin

        def points = [
                new Circle(width / 2, margin, 1, colors[0]),
                new Circle(margin, size, 1, colors[1]),
                new Circle(margin + size, size, 1, colors[2])
        ]

        def pane = new Pane()
        pane.style = '-fx-background-color: black;'
        points.each {
            pane.children.add it
        }

        def currentPoint = new Circle().with {
            centerX = randomNumberGenerator.nextInt(size - margin) + margin
            centerY =  randomNumberGenerator.nextInt(size - margin) + margin
            it
        }

        ({

            def newPoint = generatePoint(currentPoint, points, colors)
            pane.children.add newPoint
            currentPoint = newPoint

        } as AnimationTimer).start()

        new Scene(pane, width, height)
    }

    def generatePoint(currentPoint, points, colors) {
        def selection = randomNumberGenerator.nextInt 3
        new Circle().with {
            centerX = (currentPoint.centerX + points[selection].centerX) / 2
            centerY = (currentPoint.centerY + points[selection].centerY) / 2
            radius = 1
            fill = colors[selection]
            it
        }
    }

    static main(args) {
        launch(ChaosGame)
    }
}

Haskell

import Control.Monad (replicateM)
import Control.Monad.Random (fromList)

type Point = (Float,Float)
type Transformations = [(Point -> Point, Float)] -- weighted transformations

-- realization of the game for given transformations
gameOfChaos :: MonadRandom m => Int -> Transformations -> Point -> m [Point]
gameOfChaos n transformations x = iterateA (fromList transformations) x
  where iterateA f x = scanr ($) x <$> replicateM n f

Some transformations:

-- the Sierpinsky`s triangle
triangle = [ (mid (0, 0), 1)
           , (mid (1, 0), 1)
           , (mid (0.5, 0.86), 1) ]
  where mid (a,b) (x,y) = ((a+x)/2, (b+y)/2)

-- the Barnsley's fern
fern = [(f1, 1), (f2, 85), (f3, 7), (f4, 7)]
  where f1 (x,y) = (0, 0.16*y)
        f2 (x,y) = (0.85*x + 0.04*y, -0.04*x + 0.85*y + 1.6)
        f3 (x,y) = (0.2*x - 0.26*y, 0.23*x + 0.22*y + 1.6)
        f4 (x,y) = (-0.15*x + 0.28*y, 0.26*x + 0.24*y + 0.44)

-- A dragon curve
dragon = [(f1, 1), (f2, 1)]
  where f1 (x,y) = (0.5*x - 0.5*y, 0.5*x + 0.5*y)
        f2 (x,y) = (-0.5*x + 0.5*y+1, -0.5*x - 0.5*y)

Drawing the result:

import Control.Monad.Random (getRandomR)
import Graphics.Gloss

main = do x <- getRandomR (0,1)
          y <- getRandomR (0,1)
          pts <- gameOfChaos 500000 triangle (x,y)
          display window white $ foldMap point pts
            where window = InWindow "Game of Chaos" (400,400) (0,0)
                  point (x,y) = translate (100*x) (100*y) $ circle 0.02

J

Plan, working in complex plane:

  • Make an equilateral triangle.
  • Make a list of N targets
  • Starting with a random point near the triangle,
    • iteratively generate new points
    • plot the new points

J has a particularly rich notation for numbers.

  • 1ad_90 specifies a complex number with radius 1 at an angle of -90 degrees
  • 2p1 is 2 times (pi raised to the first power)


require'plot'
NB. equilateral triangle with vertices on unit circle. rotated for fun.
Triangle=: *1ad_90 1ad150 1ad30*j./2 1 o.(2p1%6)*?0   
Targets=: (?3000#3) { Triangle
Start=: j./2 1 o.2p1*?0       NB. start on unit circle
'marker' plot ((+/%#)@(,{.) , ])/Targets,Start

Java

Works with: Java version 8
import java.awt.*;
import java.awt.event.*;
import java.util.*;
import javax.swing.*;
import javax.swing.Timer;

public class ChaosGame extends JPanel {
    static class ColoredPoint extends Point {
        int colorIndex;

        ColoredPoint(int x, int y, int idx) {
            super(x, y);
            colorIndex = idx;
        }
    }

    Stack<ColoredPoint> stack = new Stack<>();
    Point[] points = new Point[3];
    Color[] colors = {Color.red, Color.green, Color.blue};
    Random r = new Random();

    public ChaosGame() {
        Dimension dim = new Dimension(640, 640);
        setPreferredSize(dim);
        setBackground(Color.white);

        int margin = 60;
        int size = dim.width - 2 * margin;

        points[0] = new Point(dim.width / 2, margin);
        points[1] = new Point(margin, size);
        points[2] = new Point(margin + size, size);

        stack.push(new ColoredPoint(-1, -1, 0));

        new Timer(10, (ActionEvent e) -> {
            if (stack.size() < 50_000) {
                for (int i = 0; i < 1000; i++)
                    addPoint();
                repaint();
            }
        }).start();
    }

    private void addPoint() {
        try {
            int colorIndex = r.nextInt(3);
            Point p1 = stack.peek();
            Point p2 = points[colorIndex];
            stack.add(halfwayPoint(p1, p2, colorIndex));
        } catch (EmptyStackException e) {
            e.printStackTrace();
        }
    }

    void drawPoints(Graphics2D g) {
        for (ColoredPoint p : stack) {
            g.setColor(colors[p.colorIndex]);
            g.fillOval(p.x, p.y, 1, 1);
        }
    }

    ColoredPoint halfwayPoint(Point a, Point b, int idx) {
        return new ColoredPoint((a.x + b.x) / 2, (a.y + b.y) / 2, idx);
    }

    @Override
    public void paintComponent(Graphics gg) {
        super.paintComponent(gg);
        Graphics2D g = (Graphics2D) gg;
        g.setRenderingHint(RenderingHints.KEY_ANTIALIASING,
                RenderingHints.VALUE_ANTIALIAS_ON);

        drawPoints(g);
    }

    public static void main(String[] args) {
        SwingUtilities.invokeLater(() -> {
            JFrame f = new JFrame();
            f.setDefaultCloseOperation(JFrame.EXIT_ON_CLOSE);
            f.setTitle("Chaos Game");
            f.setResizable(false);
            f.add(new ChaosGame(), BorderLayout.CENTER);
            f.pack();
            f.setLocationRelativeTo(null);
            f.setVisible(true);
        });
    }
}

JavaScript

Plots the fractal on an HTML canvas element.

<html>

<head>

<meta charset="UTF-8">

<title>Chaos Game</title>

</head>

<body>

<p>
<canvas id="sierpinski" width=400 height=346></canvas>
</p>

<p>
<button onclick="chaosGame()">Click here to see a Sierpiński triangle</button>
</p>

<script>

function chaosGame() {
    var canv = document.getElementById('sierpinski').getContext('2d');
    var x = Math.random() * 400;
    var y = Math.random() * 346;
    for (var i=0; i<30000; i++) {
        var vertex = Math.floor(Math.random() * 3);
        switch(vertex) {
            case 0:
                x = x / 2;
                y = y / 2;
                canv.fillStyle = 'green';
                break;
            case 1:
                x = 200 + (200 - x) / 2
                y = 346 - (346 - y) / 2
                canv.fillStyle = 'red';
                break;
            case 2:
                x = 400 - (400 - x) / 2
                y = y / 2;
                canv.fillStyle = 'blue';
        }
        canv.fillRect(x,y, 1,1);
    }
}

</script>

</body>

</html>

Julia

Run in REPL.

using Luxor

function chaos()
    width  = 1000
    height = 1000
    Drawing(width, height, "./chaos.png")
    t = Turtle(0, 0, true, 0, (0., 0., 0.))
    x = rand(1:width)
    y = rand(1:height)

    for l in 1:30_000
        v = rand(1:3)
        if v == 1
            x /= 2
            y /= 2
        elseif v == 2
            x = width/2 + (width/2 - x)/2
            y = height - (height - y)/2
        else
            x = width - (width - x)/2
            y = y / 2
        end
        Reposition(t, x, height-y)
        Circle(t, 3)
    end
end

chaos()
finish()
preview()

Kotlin

Translation of: Java
//Version 1.1.51

import java.awt.*
import java.util.Stack
import java.util.Random
import javax.swing.JPanel
import javax.swing.JFrame
import javax.swing.Timer
import javax.swing.SwingUtilities

class ChaosGame : JPanel() {

    class ColoredPoint(x: Int, y: Int, val colorIndex: Int) : Point(x, y)

    val stack = Stack<ColoredPoint>()
    val points: List<Point>
    val colors = listOf(Color.red, Color.green, Color.blue)
    val r = Random()

    init {
        val dim = Dimension(640, 640)
        preferredSize = dim
        background = Color.white
        val margin = 60
        val size = dim.width - 2 * margin
        points = listOf(
            Point(dim.width / 2, margin),
            Point(margin, size),
            Point(margin + size, size)
        )
        stack.push(ColoredPoint(-1, -1, 0))

        Timer(10) {
            if (stack.size < 50_000) {
                for (i in 0 until 1000) addPoint()
                repaint()
            }
        }.start()
    }

    private fun addPoint() {
        val colorIndex = r.nextInt(3)
        val p1 = stack.peek()
        val p2 = points[colorIndex]
        stack.add(halfwayPoint(p1, p2, colorIndex))
    }

    fun drawPoints(g: Graphics2D) {
        for (cp in stack) {
            g.color = colors[cp.colorIndex]
            g.fillOval(cp.x, cp.y, 1, 1)
        }
    }

    fun halfwayPoint(a: Point, b: Point, idx: Int) =
        ColoredPoint((a.x + b.x) / 2, (a.y + b.y) / 2, idx)

    override fun paintComponent(gg: Graphics) {
        super.paintComponent(gg)
        val g = gg as Graphics2D
        g.setRenderingHint(RenderingHints.KEY_ANTIALIASING,
                            RenderingHints.VALUE_ANTIALIAS_ON)
        drawPoints(g)
    }
}

fun main(args: Array<String>) {
    SwingUtilities.invokeLater {
        val f = JFrame()
        with (f) {
            defaultCloseOperation = JFrame.EXIT_ON_CLOSE
            title = "Chaos Game"
            isResizable = false
            add(ChaosGame(), BorderLayout.CENTER)
            pack()
            setLocationRelativeTo(null)
            isVisible = true
        }
    }
}
Output:
Same as Java entry

to chaosgame :sidelength :iterations
    make "width :sidelength
    make "height (:sidelength/2 * sqrt 3)
    make "x (random :width)
    make "y (random :height)
    repeat :iterations [
        make "vertex (random 3)
        if :vertex = 0 [
            make "x (:x / 2)
            make "y (:y / 2)
            setpencolor "green
        ]
        if :vertex = 1 [
            make "x (:width / 2 + ((:width / 2 - :x) / 2))
            make "y (:height - ((:height - :y) / 2))
            setpencolor "red
        ]
        if :vertex = 2 [
            make "x (:width - ((:width - :x) / 2))
            make "y (:y / 2)
            setpencolor "blue
        ]
        penup
        setxy (:x - :width / 2) (:y - :height / 2)
        pendown
        forward 1
    ]
    hideturtle
end

Lua

Needs LÖVE 2d Engine

math.randomseed( os.time() )
colors, orig = { { 255, 0, 0 }, { 0, 255, 0 }, { 0, 0, 255 } }, {}

function love.load()
    wid, hei = love.graphics.getWidth(), love.graphics.getHeight()
    
    orig[1] = { wid / 2, 3 }
    orig[2] = { 3, hei - 3 }
    orig[3] = { wid - 3, hei - 3 }
    local w, h = math.random( 10, 40 ), math.random( 10, 40 )
    if math.random() < .5 then w = -w end
    if math.random() < .5 then h = -h end
    orig[4] = { wid / 2 + w, hei / 2 + h }
    
    canvas = love.graphics.newCanvas( wid, hei )
    love.graphics.setCanvas( canvas ); love.graphics.clear()
    love.graphics.setColor( 255, 255, 255 )
    love.graphics.points( orig )
    love.graphics.setCanvas()
end
function love.draw()
    local iter = 100 --> make this number bigger to speed up rendering
    for rp = 1, iter do
        local r, pts = math.random( 6 ), {}
        if r == 1 or r == 4 then
            pt = 1
        elseif r == 2 or r == 5 then
            pt = 2
        else 
            pt = 3
        end
        local x, y = ( orig[4][1] + orig[pt][1] ) / 2, ( orig[4][2] + orig[pt][2] ) / 2
        orig[4][1] = x; orig[4][2] = y
        pts[1] = { x, y, colors[pt][1], colors[pt][2], colors[pt][3], 255 }
        love.graphics.setCanvas( canvas )
        love.graphics.points( pts )
    end
    love.graphics.setCanvas()
    love.graphics.draw( canvas )
end

M2000 Interpreter

Translation of: Locomotive Basic

Old style programming (GOTO, ON GOTO) inside Module. Export bitmap to Clipboard.


Module Chaos {
	01 Read Ox as integer, Oy as Integer
	02 def Screen$
	05 cls 0,0  // black background, row for split screen
	10 def integer x,y,i,v
	20 x = 640 * rnd
	30 y = 400 * rnd
	40 for i=1 to 20000
	50 v = rnd * 2 + 1
	60 on v goto 70,100,130
	70 x = x/2
	80 y = y/2
	90 goto 150
	100 x = 320 + (320-x)/2
	110 y = 400 - (400-y)/2
	120 goto 150
	130 x = 640 - (640-x)/2
	140 y = y/2
	150 pset v*2,  x*twipsX+Ox,y*twipsY+Oy
	160 next i
	170 Move Ox, Oy
	180 Copy 640*twipsX, 400*twipsY to Screen$
	190 Clipboard Screen$
}
Call Chaos 3000, 3000
Output:


Maple

chaosGame := proc(numPoints)
	local points, i;
	randomize();
	use geometry in
	RegularPolygon(triSideways, 3, point(cent, [0, 0]), 1);
	rotation(tri, triSideways, Pi/2, counterclockwise);
	randpoint(currentP, -1/2*sqrt(3)..1/2*sqrt(3), -1/2..1/2);
	points := [coordinates(currentP)];
	for i to numPoints do
		midpoint(mid, currentP, parse(cat("rotate_triSideways_", rand(1..3)(), "_tri")));
		points := [op(points), coordinates(mid)];
		point(currentP, coordinates(mid));
	end do:
	end use;
	use plottools in
		plots:-display( seq([plots:-display([seq(point(points[i]), i = 1..j)])], j = 1..numelems(points) ), insequence=true);
	end use;
end proc:

Mathematica /Wolfram Language

points = 5000;
a = {0, 0};
b = {1, 0};
c = {0.5, 1};
d = {.7, .3};
S = {};
For[i = 1, i < points, i++, t = RandomInteger[2]; 
 If[t == 0, d = Mean[{a, d}], 
  If[t == 1, d = Mean[{b, d}], d = Mean[{c, d}]]]; AppendTo[S, d]]
Graphics[Point[S]]

Nim

Using a game library

Library: rapid

The "rapid" library is no longer maintained and this program fails to compile with last available version.

import random

import rapid/gfx

var
  window = initRWindow()
    .title("Rosetta Code - Chaos Game")
    .open()
  surface = window.openGfx()
  sierpinski = window.newRCanvas()
  points: array[3, Vec2[float]]

for i in 0..<3:
  points[i] = vec2(cos(PI * 2 / 3 * i.float), sin(PI * 2 / 3 * i.float)) * 300

var point = vec2(rand(0.0..surface.width), rand(0.0..surface.height))

surface.vsync = false
surface.loop:
  draw ctx, step:
    let vertex = sample(points)
    point = (point + vertex) / 2
    ctx.renderTo(sierpinski):
      ctx.transform():
        ctx.translate(surface.width / 2, surface.height / 2)
        ctx.rotate(-PI / 2)
        ctx.begin()
        ctx.point((point.x, point.y))
        ctx.draw(prPoints)
    ctx.clear(gray(0))
    ctx.begin()
    ctx.texture = sierpinski
    ctx.rect(0, 0, surface.width, surface.height)
    ctx.draw()
    ctx.noTexture()
  update step:
    discard

Using SDL

Library: SDL2
## needs sdl2 ("nimble install sdl2")

import sdl2, random

let
  max_it = 50000
  size = [800, 600]
  v = [
    [0, 0],
    [size[0] - 1, 0],
    [size[0] div 2, size[1] - 1]
    ]

discard sdl2.init(INIT_EVERYTHING)

var
  window: WindowPtr
  render: RendererPtr

window = createWindow("chaos", 100, 100, cint(size[0]), cint(size[1]), SDL_WINDOW_SHOWN)
render = createRenderer(window, -1, Renderer_Accelerated or
    Renderer_PresentVsync or Renderer_TargetTexture)

var
  evt = sdl2.defaultEvent
  runGame = true
  it = 0
  r: Point

r.x = cint(rand(size[0] - 1))
r.y = cint(rand(size[1] - 1))
render.setDrawColor(0, 0, 0)
render.clear

while it < max_it:
  let vn = rand(2)
  r.x = cint((r.x + v[vn][0]) div 2)
  r.y = cint((r.y + v[vn][1]) div 2)
  if vn == 0:
    render.setDrawColor(255, 0, 0)
  elif vn == 1:
    render.setDrawColor(0, 255, 0)
  else:
    render.setDrawColor(0, 0, 255)
  render.drawPoint(r.x, r.y)
  inc it

while runGame:
  render.present
  delay(100)
  while pollEvent(evt):
    if evt.kind == QuitEvent:
      runGame = false
      break

destroy render
destroy window

Writing result into an image

Library: imageman
import math
import random

import imageman

const
  Width = 400
  Height = 400
  Margin = 20

type Coords = tuple[x, y: float]

# The triangle.
const T = [Coords (0.0, 0.0), (1.0, 0.0), (0.5, 0.5 * tan(PI / 3))]

#---------------------------------------------------------------------------------------------------

func toPoint(v: Coords): Point =
  ## Convert [0..1] coordinates to image coordinates.
  ## We have to change scale, then to change position of y-axis.
  result = ((Margin + v.x * (Width - 2 * Margin)).toInt,
            ((Height - Margin) - v.y * (Height - 2 * Margin)).toInt)

#---------------------------------------------------------------------------------------------------

func side(p, p1, p2: Coords): float =
  ## Auxiliary function to check if a point is in a triangle.
  (p2.y - p1.y) * (p.x - p1.x) + (p1.x - p2.x) * (p.y - p1.y)

#---------------------------------------------------------------------------------------------------

proc firstPoint(): Coords =
  ## Choose the first point.

  while true:
    result = (x: rand(1.0), y: rand(1.0))
    let b1 = side(result, T[0], T[1]) >= 0
    let b2 = side(result, T[1], T[2]) >= 0
    let b3 = side(result, T[2], T[0]) >= 0
    if b1 == b2 and b2 == b3:
      # The point is in the triangle. Keep it.
      return

#———————————————————————————————————————————————————————————————————————————————————————————————————

const
  Iterations = 50_000
  Black = ColorRGBU [byte 0, 0, 0]
  White = ColorRGBU [byte 255, 255, 255]
  PointColor = ColorRGBU [byte 255, 255, 0]   # Color for points.

# Points in image coordinates.
const
  A = T[0].toPoint
  B = T[1].toPoint
  C = T[2].toPoint


randomize()
var image = initImage[ColorRGBU](Width, Height)
image.fill(Black)

# Draw the triangle.
image.drawLine(A, B, White)
image.drawLine(B, C, White)
image.drawLine(C, A, White)

var p = firstPoint()

for _ in 1..Iterations:
  let pt = p.toPoint
  image[pt.x, pt.y] = PointColor
  # Find position of next point.
  let idx = rand(2)
  p = ((p.x + T[idx].x) / 2, (p.y + T[idx].y) / 2)

image.savePNG("chaos_game.png", compression = 9)

PARI/GP

Note: Find plotmat() here on RosettaCode Wiki.

Works with: PARI/GP version 2.9.1 and above
File:SierpTri1.png
Output SierpTri1.png
\\ Chaos Game  (Sierpinski triangle) 2/15/17 aev
pChaosGameS3(size,lim)={
my(sz1=size\2,sz2=sz1*sqrt(3),M=matrix(size,size),x,y,xf,yf,v);
x=random(size); y=random(sz2);
for(i=1,lim, v=random(3);
  if(v==0, x/=2; y/=2;);
  if(v==1, x=sz1+(sz1-x)/2; y=sz2-(sz2-y)/2;);
  if(v==2, x=size-(size-x)/2; y/=2;);
  xf=floor(x); yf=floor(y); if(xf<1||xf>size||yf<1||yf>size, next);
  M[xf,yf]=1;
);\\fend
plotmat(M);
}
\\ Test:
pChaosGameS3(600,30000); \\ SierpTri1.png
Output:
> pChaosGameS3(600,30000); \\ SierpTri1.png
 *** matrix(600x600) 18696 DOTS
time = 751 ms.

Pascal

program ChaosGame;

// FPC 3.0.2
uses
  Graph, windows, math;

// Return a point on a circle defined by angle and the circles radius
// Angle 0 = Radius points to the left
// Angle 90 = Radius points upwards
Function PointOfCircle(Angle: SmallInt; Radius: integer): TPoint;
var Ia: Double;
begin
  Ia:=DegToRad(-Angle);
  result.x:=round(cos(Ia)*Radius);
  result.y:=round(sin(Ia)*Radius);
end;

{ Main }

var
  GraphDev,GraphMode: smallint;
  Triangle: array[0..2] of Tpoint; // Corners of the triangle
  TriPnt: Byte;                    // Point in ^^^^
  Origin: TPoint;                  // Defines center of triangle
  Itterations: integer;            // Number of Itterations
  Radius: Integer;
  View: viewPorttype;
  CurPnt: TPoint;
  Rect: TRect;
  Counter: integer;
begin

  Repeat {forever}

    // Get the Itteration count 0=exit
    Write('Itterations: ');
    ReadLn(Itterations);

    if Itterations=0 then halt;

    // Set Up Graphics screen (everythings Auto detect)
    GraphDev:=Detect;
    GraphMode:=0;
    InitGraph(GraphDev,GraphMode,'');
    if GraphResult<>grok then
    begin
      Writeln('Graphics doesn''t work');
      Halt;
    end;

    // set Origin to center of the _Triangle_ (Not the creen)
    GetViewSettings(View);
    Rect.Create(View.x1,View.y1+10,View.x2,View.y2-10);
    Origin:=Rect.CenterPoint;
    Origin.Offset(0,Rect.Height div 6);  //  Center Triangle on screen

    // Define Equilateral triangle,
    Radius:=Origin.y;         // Radius of Circumscribed circle
    for Counter:=0 to 2 do
      Triangle[Counter]:=PointOfCircle((Counter*120)+90,Radius)+Origin;

    // Choose random starting point, in the incsribed circle of the triangle
    Radius:=Radius div 2;     // Radius of inscribed circle
    CurPnt:=PointOfCircle(random(360),random(Radius div 2))+Origin;

    // Play the Chaos Game
    for Counter:=0 to Itterations do
    begin
      TriPnt:=Random(3);                      // Select Triangle Point
      Rect.Create(Triangle[TriPnt],CurPnt);;  // Def. rect. between TriPnt and CurPnt
      CurPnt:=Rect.CenterPoint;               // New CurPnt is center of rectangle
      putPixel(CurPnt.x,CurPnt.y,cyan);       // Plot the new CurPnt
    end;

  until False;
end.

Perl

use Imager;

my $width  = 1000;
my $height = 1000;

my @points = (
    [ $width/2,         0],
    [        0, $height-1],
    [$height-1, $height-1],
);

my $img = Imager->new(
                      xsize    => $width,
                      ysize    => $height,
                      channels => 3,
                     );

my $color = Imager::Color->new('#ff0000');
my $r = [int(rand($width)), int(rand($height))];

foreach my $i (1 .. 100000) {
    my $p = $points[rand @points];

    my $h = [
        int(($p->[0] + $r->[0]) / 2),
        int(($p->[1] + $r->[1]) / 2),
    ];

    $img->setpixel(
        x     => $h->[0],
        y     => $h->[1],
        color => $color,
    );

    $r = $h;
}

$img->write(file => 'chaos_game_triangle.png');

Phix

Implements five of the fractals on the wikipedia page.

Library: Phix/pGUI
Library: Phix/online

You can run this online here. Press space to cycle through the five fractals.

--
-- demo\rosetta\Chaos_game.exw
-- ===========================
--
with javascript_semantics
include pGUI.e

Ihandle dlg, canvas
cdCanvas cddbuffer, cdcanvas

enum TRI,SQ1,SQ2,SQ3,PENT

sequence descs = {"Sierpinsky Triangle",
                  "Square 1",
                  "Square 2",
                  "Square 3",
                  "Pentagon"}

integer mode = TRI

function redraw_cb(Ihandle /*ih*/, integer /*posx*/, /*posy*/)
    atom {w,h} = IupGetIntInt(canvas, "DRAWSIZE")
    atom {x,y} = {w*0.05,h*0.05}
    {w,h} = {w*0.9,h*0.9}
    sequence points = iff(mode<SQ1?{{x,y},{x+w/2,y+h},{x+w,y}}:
                      iff(mode<PENT?{{x,y},{x,y+h},{x+w,y+h},{x+w,y}}
                                   :{{x+w/6,y},{x,y+h*2/3},{x+w/2,y+h},{x+w,y+h*2/3},{x+w*5/6,y}}))
    cdCanvasActivate(cddbuffer)
    integer last = 0
    for i=1 to 1000 do
        integer r = rand(length(points))
        if mode=TRI or r!=last then
            atom {nx,ny} = points[r]
            {x,y} = {(x+nx)/2,(y+ny)/2}
            cdCanvasPixel(cddbuffer, x, y, CD_GREY)
            if mode=SQ2
            or mode=SQ3 then
                r = mod(r,length(points))+1
                if mode=SQ3 then
                    r = mod(r,length(points))+1
                end if
            end if
            last = r
        end if
    end for
    cdCanvasFlush(cddbuffer)
    IupSetStrAttribute(dlg, "TITLE", "Chaos Game (%s)", {descs[mode]})
    return IUP_DEFAULT
end function

function timer_cb(Ihandle /*ih*/)
    IupUpdate(canvas)
    return IUP_IGNORE
end function

function map_cb(Ihandle ih)
    cdcanvas = cdCreateCanvas(CD_IUP, ih)
    cddbuffer = cdCreateCanvas(CD_DBUFFER, cdcanvas)
    cdCanvasSetBackground(cddbuffer, CD_WHITE)
    cdCanvasSetForeground(cddbuffer, CD_GRAY)
    return IUP_DEFAULT
end function

function key_cb(Ihandle /*ih*/, atom c)
    if c=K_ESC then return IUP_CLOSE end if
    if c=' ' then
        mode += 1
        if mode>PENT then
            mode = TRI
        end if
        cdCanvasClear(cddbuffer)
        IupRedraw(canvas)
    end if
    return IUP_CONTINUE
end function

procedure main()
    IupOpen()

    canvas = IupCanvas("RASTERSIZE=640x640")
    IupSetCallbacks(canvas, {"MAP_CB", Icallback("map_cb"),
                             "ACTION", Icallback("redraw_cb")})
    dlg = IupDialog(canvas, `TITLE="Chaos Game"`)
    IupSetCallback(dlg, "KEY_CB", Icallback("key_cb"))

    IupShow(dlg)
    IupSetAttribute(canvas, "RASTERSIZE", NULL)
    Ihandle timer = IupTimer(Icallback("timer_cb"), 40)
    if platform()!=JS then
        IupMainLoop()
        IupClose()
    end if
end procedure

main()

Plain English

To run:
Start up.
Initialize our reference points.
Clear the screen to the lightest gray color.
Play the chaos game.
Refresh the screen.
Wait for the escape key.
Shut down.

To play the chaos game:
Pick a spot within 2 inches of the screen's center.
Loop.
Draw the spot.
If a counter is past 20000, exit.
Pick a reference spot.
Find a middle spot of the spot and the reference spot.
Put the middle spot into the spot.
Repeat.

To find a middle spot of a spot and another spot:
Put the spot's x coord plus the other spot's x coord divided by 2 into the middle spot's x coord.
Put the spot's y coord plus the other spot's y coord divided by 2 into the middle spot's y coord.

The top spot is a spot.
The left spot is a spot.
The right spot is a spot.

To initialize our reference points:
Move up 2-1/2 inches.
Put the context's spot into the top spot.
Turn right. Turn 1/6 of the way around.
Move 5 inches.
Put the context's spot into the right spot.
Turn 1/3 of the way around.
Move 5 inches.
Put the context's spot into the left spot.

To pick a reference spot:
Pick a number between 1 and 3.
If the number is 1, put the top spot into the reference spot.
If the number is 2, put the right spot into the reference spot.
If the number is 3, put the left spot into the reference spot.
Output:

[2]

Processing

size(300, 260);

background(#ffffff); // white

int x = floor(random(width));
int y = floor(random(height));

int colour = #ffffff;

for (int i=0; i<30000; i++) {
  int v = floor(random(3));
  switch (v) {
  case 0:
    x = x / 2;
    y = y / 2;
    colour = #00ff00; // green
    break;
  case 1:
    x = width/2 + (width/2 - x)/2;
    y = height - (height - y)/2;
    colour = #ff0000; // red
    break;
  case 2:
    x = width - (width - x)/2;
    y = y / 2;
    colour = #0000ff; // blue
  }
  set(x, height-y, colour);
}

Processing Python mode

from __future__ import division

size(300, 260)

background(255)  # white

x = floor(random(width))
y = floor(random(height))

for _ in range(30000):
    v = floor(random(3))
    if v == 0:
        x = x / 2
        y = y / 2
        colour = color(0, 255, 0)  # green
    elif v == 1:
        x = width / 2 + (width / 2 - x) / 2
        y = height - (height - y) / 2
        colour = color(255, 0, 0)  # red
    elif v == 2:
        x = width - (width - x) / 2
        y = y / 2
        colour = color(0, 0, 255)  # blue

    set(x, height - y, colour)

Python

import argparse
import random
import shapely.geometry as geometry
import numpy as np
import matplotlib.pyplot as plt
import matplotlib.animation as animation


def main(args):
    # Styles
    plt.style.use("ggplot")

    # Creating figure
    fig = plt.figure()
    line, = plt.plot([], [], ".")

    # Limit axes
    plt.xlim(0, 1)
    plt.ylim(0, 1)

    # Titles
    title = "Chaos Game"
    plt.title(title)
    fig.canvas.set_window_title(title)

    # Getting data
    data = get_data(args.frames)

    # Creating animation
    line_ani = animation.FuncAnimation(
        fig=fig,
        func=update_line,
        frames=args.frames,
        fargs=(data, line),
        interval=args.interval,
        repeat=False
    )

    # To save the animation install ffmpeg and uncomment
    # line_ani.save("chaos_game.gif")

    plt.show()


def get_data(n):
    """
    Get data to plot
    """
    leg = 1
    triangle = get_triangle(leg)
    cur_point = gen_point_within_poly(triangle)
    data = []
    for _ in range(n):
        data.append((cur_point.x, cur_point.y))
        cur_point = next_point(triangle, cur_point)
    return data


def get_triangle(n):
    """
    Create right triangle
    """
    ax = ay = 0.0
    a = ax, ay

    bx = 0.5  *  n
    by = 0.75 * (n ** 2)
    b = bx, by

    cx = n
    cy = 0.0
    c = cx, cy

    triangle = geometry.Polygon([a, b, c])
    return triangle


def gen_point_within_poly(poly):
    """
    Generate random point inside given polygon
    """
    minx, miny, maxx, maxy = poly.bounds
    while True:
        x = random.uniform(minx, maxx)
        y = random.uniform(miny, maxy)
        point = geometry.Point(x, y)
        if point.within(poly):
            return point


def next_point(poly, point):
    """
    Generate next point according to chaos game rules
    """
    vertices = poly.boundary.coords[:-1]  # Last point is the same as the first one
    random_vertex = geometry.Point(random.choice(vertices))
    line = geometry.linestring.LineString([point, random_vertex])
    return line.centroid


def update_line(num, data, line):
    """
    Update line with new points
    """
    new_data = zip(*data[:num]) or [(), ()]
    line.set_data(new_data)
    return line,


if __name__ == "__main__":
    arg_parser = argparse.ArgumentParser(description="Chaos Game by Suenweek (c) 2017")
    arg_parser.add_argument("-f", dest="frames", type=int, default=1000)
    arg_parser.add_argument("-i", dest="interval", type=int, default=10)

    main(arg_parser.parse_args())

Quackery

  [ $ "turtleduck.qky" loadfile ] now!

  [ 2 3 circle ]              is dot        (     -->     )

  [ 1 fly
    -1 4 turn
    1 fly
    1 4 turn ]                is toxy       ( n n -->     )

  [ swap 2dup toxy
    dot
    1 2 turn
    toxy
    1 2 turn ]                is plot       ( n n -->     )

  [ 200 random
    346 random
    over 346 *
    over 200 * < if
      [ dip [ 400 + ]
        692 swap - ] ]        is intriangle (     --> n n )

  [ 3 random
    [ table
      [ 2 /
        dip [ 2 / ] ]
      [ 2 /
        dip [ 800 + 2 / ] ]
      [ 692 + 2 /
        dip [ 400 + 2 / ] ] ]
    do ]                      is tovertex   ( n n -->     )

   turtle
  0 frames
  -400 1 fly
  1 4 turn
  340 1 fly
  -1 4 turn
  intriangle
  10000 times
    [ i^ 100 mod 0= if frame
      2dup plot
      tovertex ]
  2drop
  1 frames
Output:

R

Note: Find plotmat() here on RosettaCode Wiki.

Translation of: PARI/GP
Works with: R version 3.3.1 and above
File:SierpTriR1.png
Output SierpTriR1.png
# Chaos Game  (Sierpinski triangle) 2/15/17 aev
# pChaosGameS3(size, lim, clr, fn, ttl)
# Where: size - defines matrix and picture size; lim - limit of the dots; 
#   fn - file name (.ext will be added); ttl - plot title;
pChaosGameS3 <- function(size, lim, clr, fn, ttl)
{
  cat(" *** START:", date(), "size=",size, "lim=",lim, "clr=",clr, "\n");
  sz1=floor(size/2); sz2=floor(sz1*sqrt(3)); xf=yf=v=0;
  M <- matrix(c(0), ncol=size, nrow=size, byrow=TRUE);
  x <- sample(1:size, 1, replace=FALSE);
  y <- sample(1:sz2, 1, replace=FALSE);
  pf=paste0(fn, ".png");
  for (i in 1:lim) { v <- sample(0:3, 1, replace=FALSE);
    if(v==0) {x=x/2; y=y/2;}
    if(v==1) {x=sz1+(sz1-x)/2; y=sz2-(sz2-y)/2;}
    if(v==2) {x=size-(size-x)/2; y=y/2;}
    xf=floor(x); yf=floor(y); if(xf<1||xf>size||yf<1||yf>size) {next};
    M[xf,yf]=1;
  }
  plotmat(M, fn, clr, ttl, 0, size);
  cat(" *** END:",date(),"\n");
}  
pChaosGameS3(600, 30000, "red", "SierpTriR1", "Sierpinski triangle")
Output:
> pChaosGameS3(600, 30000, "red", "SierpTriR1", "Sierpinski triangle")
 *** START: Wed Feb 15 21:40:48 2017 size= 600 lim= 30000 clr= red 
 *** Matrix( 600 x 600 ) 15442 DOTS
 *** END: Wed Feb 15 21:40:51 2017 
 

Alternative code:

pta = c(1,2) 
ptb = c(4,2) 
ptc = c(2.5,4) 
spt = c(1,2)

plot(t(data.frame(pta,ptb,ptc)), 
     xlab= "", ylab = "", pch = 19, asp =1,
     xaxt='n',yaxt='n', ann=FALSE,frame.plot=FALSE)
points(x = spt[1], y = spt[2], col = "blue", pch = 19)

ittt = 100000
ptcex = .2
for (i in 1:ittt) {
  d = sample(1:6,1,TRUE)
  if (d == 1 | d == 2) {
    pta1 = spt + ((pta-spt)/2)
    points(pta1[1],pta1[2], col = "red", pch = 19, cex = ptcex)
    spt=pta1
  }
  if (d == 3 | d == 4) {
    ptb1 = spt + (ptb-spt)/2
    points(ptb1[1],ptb1[2], col = "red", pch = 19, cex = ptcex)
    spt=ptb1
  }
  if (d == 5 | d == 6) {
    ptc1 = spt + (ptc-spt)/2
    points(ptc1[1],ptc1[2], col = "red", pch = 19, cex = ptcex)
    spt=ptc1
  } 
}

Racket

Translation of: Haskell
#lang racket

(require 2htdp/image)

(define SIZE 300)

(define (game-of-chaos fns WIDTH HEIGHT SIZE
                       #:offset-x [offset-x 0] #:offset-y [offset-y 0]
                       #:iters [iters 10000]
                       #:bg [bg 'white] #:fg [fg 'black])
  (define dot (square 1 'solid fg))
  (define all-choices (apply + (map first fns)))
  (for/fold ([image (empty-scene WIDTH HEIGHT bg)]
             [x (random)] [y (random)]
             #:result image)
            ([i (in-range iters)])
    (define picked (random all-choices))
    (define fn (for/fold ([acc 0] [result #f] #:result result) ([fn (in-list fns)])
                 #:break (> acc picked)
                 (values (+ (first fn) acc) (second fn))))
    (match-define (list x* y*) (fn x y))
    (values (place-image dot (+ offset-x (* SIZE x*)) (+ offset-y (* SIZE y*)) image)
            x* y*)))

(define (draw-triangle)
  (define ((mid a b) x y) (list (/ (+ a x) 2) (/ (+ b y) 2)))
  (define (triangle-height x) (* (sqrt 3) 0.5 x))
  (game-of-chaos (list (list 1 (mid 0 0))
                       (list 1 (mid 1 0))
                       (list 1 (mid 0.5 (triangle-height 1))))
                 SIZE (triangle-height SIZE) SIZE))

(define (draw-fern)
  (define (f1 x y) (list 0 (* 0.16 y)))
  (define (f2 x y) (list (+ (* 0.85 x) (* 0.04 y)) (+ (* -0.04 x) (* 0.85 y) 1.6)))
  (define (f3 x y) (list (+ (* 0.2 x) (* -0.26 y)) (+ (* 0.23 x) (* 0.22 y) 1.6)))
  (define (f4 x y) (list (+ (* -0.15 x) (* 0.28 y)) (+ (* 0.26 x) (* 0.24 y) 0.44)))
  (game-of-chaos (list (list 1 f1) (list 85 f2) (list 7 f3) (list 7 f4))
                 (/ SIZE 2) SIZE (/ SIZE 11) #:offset-x 70 #:offset-y 10
                 #:bg 'black #:fg 'white))

(define (draw-dragon)
  (game-of-chaos
   (list (list 1 (λ (x y) (list (+ (* 0.5 x) (* -0.5 y)) (+ (* 0.5 x) (* 0.5 y)))))
         (list 1 (λ (x y) (list (+ (* -0.5 x) (* 0.5 y) 1) (+ (* -0.5 x) (* -0.5 y))))))
   SIZE (* 0.8 SIZE) (/ SIZE 1.8) #:offset-x 64 #:offset-y 120))

(draw-triangle)
(draw-fern)
(draw-dragon)

Raku

(formerly Perl 6)

Works with: Rakudo version 2018.10
use Image::PNG::Portable;

my ($w, $h) = (640, 640);

my $png = Image::PNG::Portable.new: :width($w), :height($h);

my @vertex = [0, 0], [$w, 0], [$w/2, $h];

my @xy = [0,0], [0,0], [0,0], [0,0];

# :degree must be equal to or less than @xy elements.
(^1e5).race(:4degree).map: {
    my $p = ++$ % +@xy;
    @xy[$p] = do given @vertex.pick -> @v { ((@xy[$p] »+« @v) »/» 2)».Int };
    $png.set: |@xy[$p], 0, 255, 0;
}

$png.write: 'Chaos-game-perl6.png';

REXX

/*REXX pgm draws a Sierpinski triangle by running the  chaos game  with a million points*/
parse value  scrsize()   with  sd  sw  .         /*obtain the depth and width of screen.*/
sw= sw - 2                                       /*adjust the screen width down by two. */
sd= sd - 4                                       /*   "    "     "   depth   "   " four.*/
parse arg pts chr seed .                         /*obtain optional arguments from the CL*/
if pts=='' | pts==","  then pts= 1000000         /*Not specified?  Then use the default.*/
if chr=='' | chr==","  then chr= '∙'             /* "      "         "   "   "      "   */
if datatype(seed,'W')  then call random ,,seed   /*Is  specified?    "   "  RANDOM seed.*/
x= sw;       hx= x % 2;     y= sd                /*define the initial starting position.*/
@.= ' '                                          /*   "   all screen points as a blank. */
        do pts;  ?= random(1, 3)                 /* [↓]  draw a # of (million?)  points.*/
                       select                    /*?:  will be a random number: 1 ──► 3.*/
                       when ?==1  then parse value          x%2          y%2   with   x  y
                       when ?==2  then parse value  hx+(hx-x)%2  sd-(sd-y)%2   with   x  y
                       otherwise       parse value  sw-(sw-x)%2          y%2   with   x  y
                       end   /*select*/
        @.x.y= chr                               /*set the    X, Y    point to a bullet.*/
        end   /*pts*/                            /* [↑]  one million points ≡ overkill? */
                                                 /* [↓]  display the points to the term.*/
        do      row=sd   to 0  by -1;   _=       /*display the points, one row at a time*/
             do col=0   for sw+2                 /*   "     a  row (one line) of image. */
             _= _ || @.col.row                   /*construct a  "    "    "    "   "    */
             end   /*col*/                       /*Note: display image from top──►bottom*/
                                                 /* [↑]  strip trailing blanks (output).*/
        say strip(_, 'T')                        /*display one row (line) of the image. */
        end        /*row*/                       /*stick a fork in it,  we're all done. */

This REXX program makes use of   SCRSIZE   REXX program (or BIF)   which is used to determine the screen
width and depth of the terminal (console).   Some REXXes don't have this BIF.

The   SCRSIZE.REX   REXX program is included here   ───►   SCRSIZE.REX.

(Shown at   1/10   size on a   426×201   screen.)

output   when using the following input:       ,   █
                                                                                                                                                                                                                   █
                                                                                                                                                                                                                  ███
                                                                                                                                                                                                                 █████
                                                                                                                                                                                                                ███████
                                                                                                                                                                                                               █████████
                                                                                                                                                                                                              █████ █████
                                                                                                                                                                                                             █████████████
                                                                                                                                                                                                            ███████████████
                                                                                                                                                                                                           █████       █████
                                                                                                                                                                                                          ███████     ███████
                                                                                                                                                                                                         █████████   █████████
                                                                                                                                                                                                        ████  █████ █████  ████
                                                                                                                                                                                                       █████████████████████████
                                                                                                                                                                                                      ███████████████████████████
                                                                                                                                                                                                    █████                     ████
                                                                                                                                                                                                    ██████                   ███████
                                                                                                                                                                                                  █████████                 █████████
                                                                                                                                                                                                 ████   ████               ████   ████
                                                                                                                                                                                                ██████ ██████             ██████ ██████
                                                                                                                                                                                               ███████████████           ███████████████
                                                                                                                                                                                              ████         ████         ████         ████
                                                                                                                                                                                             ██████       ██████       ██████       ██████
                                                                                                                                                                                            ████████     ████████     ████████     ████████
                                                                                                                                                                                           ███    ███   ████   ███   ███   ████   ███    ███
                                                                                                                                                                                          █████ ██████ ██████ ███████████ ██████ █████ ██████
                                                                                                                                                                                         █████████████████████████████████████████████████████
                                                                                                                                                                                        ███                                                 ███
                                                                                                                                                                                       █████                                               █████
                                                                                                                                                                                      ███████                                             ████████
                                                                                                                                                                                     ███   ███                                           ███    ███
                                                                                                                                                                                   ██████ █████                                         █████ ██████
                                                                                                                                                                                  ██████████████                                       ██████████████
                                                                                                                                                                                 ████████████████                                     ████████████████
                                                                                                                                                                                █████        █████                                   █████        █████
                                                                                                                                                                               ███████      ███████                                 ███████      ███████
                                                                                                                                                                              █████████    ██████████                              █████████    █████████
                                                                                                                                                                             █████  ████  █████  █████                           █████  █████  ████  █████
                                                                                                                                                                            ███████████████████████████                         ███████████████████████████
                                                                                                                                                                           █████████████████████████████                       █████████████████████████████
                                                                                                                                                                          ████                      █████                     █████                      ████
                                                                                                                                                                         ██████                    ███████                   ███████                    ██████
                                                                                                                                                                        ████████                  █████████                 █████████                  ████████
                                                                                                                                                                       ████  ████                ████   ████               ████   ████                ████  █████
                                                                                                                                                                     ██████████████             █████████████             ██████ ██████              █████████ ███
                                                                                                                                                                    ████████████████           ███████████████           ███████████████            ███████████████
                                                                                                                                                                   ████          ████         ████         ████         ████         ████          ████         ████
                                                                                                                                                                  ██████        ██████       ██████       ██████       ██████       ██████       ███████       ██████
                                                                                                                                                                 █████████     ████████     ████████     █████████    ████████     ████████     █████████     ████████
                                                                                                                                                                ████   ████  ████   ████   ████  ████   ████   ████  ████  ████   ████   ███   ████   ████   ███   ████
                                                                                                                                                               ██████ ████████████ ██████ ████████████ ██████ ██████████████████ ██████ ████████████ ████████████ ██████
                                                                                                                                                              ███████████████████████████████████████████████████████████████████████████████████████████████████████████
                                                                                                                                                             ███                                                                                                       ███
                                                                                                                                                            █████                                                                                                     █████
                                                                                                                                                           ███████                                                                                                   ███████
                                                                                                                                                          ███   ███                                                                                                 ███   ███
                                                                                                                                                         █████ █████                                                                                              ██████ █████
                                                                                                                                                       ██████████████                                                                                            ██████████████
                                                                                                                                                      ███          ███                                                                                          ███          ███
                                                                                                                                                     █████        █████                                                                                        █████        █████
                                                                                                                                                    ████████     ████████                                                                                     ███████      ████████
                                                                                                                                                   ██████████   ██████████                                                                                   ██████████   ██████████
                                                                                                                                                  █████  █████ █████  █████                                                                                 █████  █████ █████  █████
                                                                                                                                                 ███████████████████████████                                                                               ███████████████████████████
                                                                                                                                                █████████████████████████████                                                                             █████████████████████████████
                                                                                                                                               ████                      █████                                                                           █████                     █████
                                                                                                                                              ███████                   ███████                                                                         ███████                   ███████
                                                                                                                                             █████████                 █████████                                                                       █████████                 █████████
                                                                                                                                            ████  █████               █████  ████                                                                     ████  █████               █████  ████
                                                                                                                                          ██████████████             █████████████                                                                   █████████████             █████████████
                                                                                                                                         ████████████████           ███████████████                                                                ████████████████           ███████████████
                                                                                                                                        █████         ████         ████         ████                                                              █████         ████         ████         ████
                                                                                                                                       ███ ███       ██████       ██████       ███████                                                           ███ ███       ██████       ██████       ███████
                                                                                                                                      █████████     ████████     ████████     █████████                                                         █████████     ████████     ████████     █████████
                                                                                                                                     ████   ████  █████  ████   ████  ████   ████   ████                                                       ████   ████  ████   ████   ████  ████   ████   ████
                                                                                                                                    ██████ ███████████████████ ████████████ ██████ ██████                                                     ██████ ███████████████████ ███████████████████ ██████
                                                                                                                                   ███████████████████████████████████████████████████████                                                   ███████████████████████████████████████████████████████
                                                                                                                                  ████                                                 ████                                                 ███                                                  ████
                                                                                                                                 ██████                                               ██████                                               ██████                                               ██████
                                                                                                                                ████████                                             ████████                                             ████████                                             ████████
                                                                                                                               ███   ████                                           ███   ████                                           ███   ████                                           ███   ████
                                                                                                                              █████ ██████                                         ████████████                                        ██████ ██████                                         █████ ██████
                                                                                                                            ███████████████                                       ██████████████                                      ███████████████                                       ██████████████
                                                                                                                           ████          ███                                     ███          ███                                    ████          ███                                     ███          ███
                                                                                                                          ██████        █████                                   █████        █████                                  ██████        █████                                   █████        █████
                                                                                                                         ████████      ███████                                 ███████      ███████                                ████████      ███████                                 ███████      ███████
                                                                                                                        ███    ███   ████   ███                              ████   ███    ███   ████                             ███    ███   ████   ███                              ████   ███    ███   ████
                                                                                                                       █████  █████ ██████ █████                            ██████ █████  █████ ██████                           █████  █████ ██████ █████                            ██████ █████  █████ ██████
                                                                                                                      ███████████████████████████                          ████████████████████████████                         ███████████████████████████                          ████████████████████████████
                                                                                                                     █████████████████████████████                        ██████████████████████████████                       █████████████████████████████                        ██████████████████████████████
                                                                                                                    █████                      ████                      █████                      █████                     █████                     █████                      █████                      █████
                                                                                                                   ███████                   ████████                   ███████                    ███████                   ███████                   ████████                   ███████                    ███████
                                                                                                                  █████████                 ██████████                 █████████                  █████████                 █████████                 ██████████                 █████████                  █████████
                                                                                                                 ████  █████               █████  █████               █████  ████                ████  █████               ████  █████               █████  █████               █████ █████                ████  █████
                                                                                                                █████████████             ██████████████             █████████████             ██████████████             █████████████             ██████████████             █████████████             ██████████████
                                                                                                              ████████████████           ████████████████           ███████████████           ████████████████          ████████████████           ████████████████           ███████████████           ████████████████
                                                                                                             █████         ████         █████        █████         ████         █████        █████         ████        █████         ████         █████        █████         ████         ████         █████         ████
                                                                                                            ███████       ██████       ███████      ███████       ██████       ███████      ███████      ███████      ███████       ██████       ███████      ███████       ██████       ███████      ███████       ██████
                                                                                                           █████████     ████████     █████████    █████████    █████████     █████████    █████████    █████████    █████████     ████████     █████████    █████████    █████████     █████████    █████████    █████████
                                                                                                          ████   ████  █████  █████  ████  █████  ████   ████  █████  ████   ████  █████  ████   ████  █████  ████  ████   ████  █████  ████   ████   ████  ████   ████  █████  ████   ████  █████  ████   ████  █████  ████
                                                                                                         ██████████████████████████████████████████████████████████████████ █████████ █████████ █████████ █████████████████████████ █████████ ███████████████████ █████████ █████████ █████████ █████████ █████████ █████████
                                                                                                        ███████████████████████████████████████████████████████████████████████████████████████████████████████████████████████████████████████████████████████████████████████████████████████████████████████████████████████
                                                                                                       ████                                                                                                                                                                                                                 ████
                                                                                                      ██████                                                                                                                                                                                                               ██████
                                                                                                     ████████                                                                                                                                                                                                             ████████
                                                                                                    ████  ████                                                                                                                                                                                                           ████  ████
                                                                                                   ████████████                                                                                                                                                                                                         ████████████
                                                                                                  ██████████████                                                                                                                                                                                                       ██████████████
                                                                                                 ████         ███                                                                                                                                                                                                     ████         ████
                                                                                                ██████       ██████                                                                                                                                                                                                  ██████       ██████
                                                                                               ████████     ████████                                                                                                                                                                                                ████████     ████████
                                                                                              ███   ████   ███   ████                                                                                                                                                                                              ███   ████   ███   ████
                                                                                             █████ ██████ █████ ██████                                                                                                                                                                                            █████ ██████ █████ ██████
                                                                                            ███████████████████████████                                                                                                                                                                                          ███████████████████████████
                                                                                           ███                       ███                                                                                                                                                                                        ███                       ███
                                                                                          █████                     █████                                                                                                                                                                                      █████                     █████
                                                                                        ████████                   ███████                                                                                                                                                                                   ████████                   ███████
                                                                                       ██████████                 █████████                                                                                                                                                                                 ██████████                 █████████
                                                                                      █████  █████               █████ █████                                                                                                                                                                               █████  █████               █████ █████
                                                                                     ██████████████            ██████████████                                                                                                                                                                             ██████████████            ██████████████
                                                                                    ████████████████          ████████████████                                                                                                                                                                           ████████████████          ████████████████
                                                                                   █████        █████        █████         ████                                                                                                                                                                         █████        █████        █████         ████
                                                                                  ███████      ███████      ███████       ███████                                                                                                                                                                      ███████      ███████      ███████       ███████
                                                                                 █████████    █████████    █████████     █████████                                                                                                                                                                    █████████    █████████    █████████     █████████
                                                                                ████   ████  █████  █████ █████  ████  █████  █████                                                                                                                                                                  █████  ████  █████  ████  █████  ████   ████  █████
                                                                               █████████████████████████████████████████████████████                                                                                                                                                                █████████████████████████████████████████████████████
                                                                              ███████████████████████████████████████████████████████                                                                                                                                                              ███████████████████████████████████████████████████████
                                                                             ████                                                 ████                                                                                                                                                            ████                                                 ████
                                                                            ██████                                              ███████                                                                                                                                                          ██████                                              ███████
                                                                          █████████                                            █████████                                                                                                                                                       █████████                                            █████████
                                                                         ████   ████                                          ████   ████                                                                                                                                                     █████  ████                                          ████   ████
                                                                        █████████████                                        █████████████                                                                                                                                                   ██████ ██████                                        █████████████
                                                                       ███████████████                                      ███████████████                                                                                                                                                 ███████████████                                      ███████████████
                                                                      ████         ████                                    ████         ████                                                                                                                                               ████         ████                                    ████         ████
                                                                     ██████       ██████                                  ██████       ██████                                                                                                                                             ██████       ██████                                  ██████       ██████
                                                                    ████████     ████████                                ████████     ████████                                                                                                                                           ████████     ████████                                ████████     ████████
                                                                   ████   ███   ████   ████                             ████   ███   ████   ███                                                                                                                                         ████   ███   ████   ███                              ████   ███   ████   ████
                                                                  ████████████ ██████ ██████                           ██████ █████ ██████ ██████                                                                                                                                      ██████ █████ ██████ ██████                           ████████████ ██████ ██████
                                                                 ████████████████████████████                         ████████████████████████████                                                                                                                                    ████████████████████████████                         ████████████████████████████
                                                                ███                       ████                       ███                       ████                                                                                                                                  ███                       ████                       ███                       ████
                                                               █████                     ██████                     █████                     ██████                                                                                                                                █████                     ██████                     █████                     ██████
                                                             ████████                   ████████                  ████████                   ████████                                                                                                                              ███████                   ████████                   ███████                   ████████
                                                            ████   ███                 ███    ███                ████   ███                 ███    ███                                                                                                                           ████   ███                 ███    ███                ████   ███                 ███    ███
                                                           ██████ █████               █████  █████              ██████ █████               █████  █████                                                                                                                         ██████ █████               █████  █████              ██████ █████               █████  █████
                                                          ██████████████             ██████████████            ██████████████             ██████████████                                                                                                                       ██████████████             ██████████████            ██████████████             ██████████████
                                                         ████████████████           ████████████████          ████████████████           ████████████████                                                                                                                     ████████████████           ████████████████          ████████████████           ████████████████
                                                        █████        ██████        █████        █████        █████        ██████        █████        █████                                                                                                                   █████        ██████        █████        █████        █████        █████         █████        █████
                                                       ███████      ████████      ███████      ███████      ███████      ████████      ███████      ███████                                                                                                                 ███████      ████████      ███████      ███████      ███████      ████████      ███████      ███████
                                                      █████████    ██████████    █████████    █████████    █████████    ██████████    █████████    █████████                                                                                                               █████████    ██████████    █████████    █████████    █████████    ██████████    █████████    █████████
                                                     █████  ████  █████  █████ █████  █████  █████  ████  █████  ████  █████  █████  ████  █████  █████ █████                                                                                                             █████  ████  █████  █████  ████  █████  █████  ████  █████  ████  █████  █████  ████  █████  █████ █████
                                                    ██████████████████████████████████████████████████████████████████████████████████████████████████████████                                                                                                           ██████████████████████████████████████████████████████████████████████████████████████████████████████████
                                                   █████████████████████████████████████████████████████████████████████████████████████████████████████████████                                                                                                        █████████████████████████████████████████████████████████████████████████████████████████████████████████████
                                                  ████                                                                                                      █████                                                                                                      ████                                                                                                      █████
                                                 ██████                                                                                                    ███████                                                                                                    ██████                                                                                                    ███████
                                                ████████                                                                                                  █████████                                                                                                  ████████                                                                                                  █████████
                                               ████  █████                                                                                               █████  ████                                                                                                ████  █████                                                                                               █████  ████
                                              █████████████                                                                                             █████████████                                                                                              █████████████                                                                                             ███ █████████
                                             ███████████████                                                                                           ███████████████                                                                                            ███████████████                                                                                           ███████████████
                                           █████         ████                                                                                         ████         ████                                                                                         █████         ████                                                                                         ████         ████
                                           ██████       ██████                                                                                       ██████       ██████                                                                                       ███████       ██████                                                                                       ██████       ██████
                                         █████████    █████████                                                                                     ████████     ████████                                                                                     █████████    █████████                                                                                     ████████     ████████
                                        ████   ████  ████   ████                                                                                   ████  ████   ████   ████                                                                                  ████   ████  ████   ████                                                                                   ████  ████   ████   ███
                                       ██████ ████████████ ██████                                                                                 ████████████ ██████ ██████                                                                                ██████ ████████████ ██████                                                                                 ████████████ ██████ ██████
                                      ████████████████████████████                                                                               ████████████████████████████                                                                              ████████████████████████████                                                                               ████████████████████████████
                                     ████                       ███                                                                             ███                       ████                                                                            ████                      ████                                                                             ███                       ████
                                    ██████                    ██████                                                                           █████                     ██████                                                                          ██████                    ██████                                                                          ██████                     ██████
                                   ████████                  ████████                                                                        ████████                   ████████                                                                        ████████                  ████████                                                                        ████████                   ████████
                                  ███   ████                ████   ███                                                                      ████   ███                 ███   ████                                                                      ███   ████                ████   ███                                                                      ████   ███                 ███   ████
                                 █████ ██████              ██████ █████                                                                    ██████ █████               █████ ██████                                                                    █████ ██████              ██████ █████                                                                    ██████ █████               █████ ██████
                                ██████████████            ███████████████                                                                 ███████████████            ██████████████                                                                  ██████████████            ███████████████                                                                 ███████████████            ██████████████
                               ███          ███          ███          ████                                                               ███          ████          ███          ███                                                                ███          ███          ███          ████                                                               ███          ████          ███          ███
                             ██████        █████        █████        ██████                                                             █████        ██████       ██████        █████                                                             ██████        █████        █████        ██████                                                             █████        ██████        █████        █████
                            ████████      ███████      ███████      ████████                                                           ███████      ████████     ████████      ███████                                                           ████████      ███████      ███████      ████████                                                           ███████      ████████     ████████      ███████
                           ██████████    █████████    ██████████   ██████████                                                         █████████    ██████████   ██████████    █████████                                                         ██████████    █████████    ██████████   ██████████                                                         ██████████   ██████████   ██████████    █████████
                          █████  █████  █████ █████  █████ ██████ █████  █████                                                       █████ ██████ █████  █████ █████  █████  █████ █████                                                       █████  █████  █████ █████  █████ █████  █████  █████                                                       █████ █████  █████  █████ █████  █████  █████ █████
                         ██████████████████████████████████████████████████████                                                     █████████████████████████████████████████████████████                                                     ██████████████████████████████████████████████████████                                                     █████████████████████████████████████████████████████
                        ████████████████████████████████████████████████████████                                                   ████████████████████████████████████████████████████████                                                  ████████████████████████████████████████████████████████                                                   ████████████████████████████████████████████████████████
                       █████                                                █████                                                 ████                                                 █████                                                █████                                                █████                                                 ████                                                 █████
                      ███████                                              ███████                                               ███████                                              ███████                                              ███████                                              ███████                                               ██████                                               ███████
                     █████████                                            █████████                                             █████████                                            █████████                                            █████████                                            █████████                                            ██████████                                            █████████
                    █████ █████                                          █████  ████                                          █████  █████                                          ████  █████                                          █████  ████                                          █████  ████                                          █████  █████                                          ████  █████
                   █████████████                                        ██████████████                                       ██████████████                                        █████████████                                        █████████████                                        █████████████                                        ██████████████                                        █████████████
                  ███████████████                                      ████████████████                                     ████████████████                                      ███████████████                                      ███████████████                                      ████████████████                                     ████████████████                                      ███████████████
                 ████         ████                                    ████         █████                                   █████        █████                                   █████         ████                                    ████         ████                                    ████         █████                                   █████        █████                                   █████         ████
                ██████       ██████                                  ██████       ███████                                 ███████      ███████                                 ███████       ██████                                  ██████       ██████                                  ██████       ███ ███                                 ███ ███      ███████                                 ███████       ██████
               ████████     ████████                                █████████    █████████                               █████████    █████████                               █████████     ████████                                ████████     ████████                                █████████    █████████                               █████████    █████████                               █████████     ████████
             █████  ████   ████  █████                             ████  █████  ████   ████                             ████   ████  ████   ████                             ████   ████  █████  ████                             █████  ████   ████  █████                             ████  █████  ████   ████                             ████   ████  ████   ████                             ████   ████  █████  ████
            █████████████ █████████████                           ███████████████████ ██████                           ██████ ████████████ ██████                           ██████ ███████████████████                           █████████████ █████████████                           ███████████████████ ██████                           ██████ ████████████ ██████                           ██████ ███████████████████
           █████████████████████████████                         ████████████████████████████                         ████████████████████████████                         █████████████████████████████                        █████████████████████████████                         ████████████████████████████                         ████████████████████████████                         █████████████████████████████
          ████                       ████                       ████                      ████                       ████                      ████                       ████                       ████                      ████                       ████                       ████                      ████                       ████                      ████                       ████                       ████
         ██████                     ██████                    ███████                    ██████                     ██████                    ██████                     ██████                     ██████                    ██████                     ██████                    ███████                    ██████                     ██████                     █████                     ██████                     ██████
        ████████                   ████████                  █████████                  ████████                   ████████                  ████████                   ████████                   ████████                  ████████                   ████████                  █████████                  ████████                   ████████                  █████████                  ████████                   ████████
       ████   ███                 ███   ████                ████   ████                ████   ███                 ███   ████                ████   ████                ████  ████                ████   ████                ████   ███                 ███   ████                ████   ████                ████   ███                 ███   ████                ████   ████                ████  ████                ████   ████
      ██████ █████               █████ ██████              ██████ ██████              ████████████              ██████ ██████              ██████ ██████              ████████████              ██████ ██████              ██████ ██████              ████████████              ██████ ██████              ████████████               █████ ██████              ██████ ██████              ████████████              ██████ ██████
     ███████████████            ██████████████            ███████████████            ███████████████            ██████████████            ███████████████            ██████████████            ███████████████            ███████████████            ██████████████            ███████████████            ███████████████           ███████████████            ███████████████            ██████████████            ███████████████
    ███          ████          ███          ███          ████         ████          ███          ████         ████          ███          ████         ████          ███          ███          ████          ███          ███          ████         ████          ███          ████         ████          ███          ████         ████          ███          ████         ████          ███          ███          ████          ███
   █████        ██████       ██████        █████        ██████       ██████        █████        ██████       ██████        █████        ██████       ██████        █████        ██████       ██████       ██████        █████        ██████       ██████        █████        ██████       ██████        █████        ██████       ██████        █████        ██████       ██████        █████        ██████       ██████        █████
  ████████     ████████     ████████      ████████     ████████     ████████      ███████      ████████     ████████      ███████      ████████     ████████      ███████      ████████     ████████     ████████      ████████     ████████     ████████      ████████     ████████     ████████      ███████      ████████     ████████      ███████      ████████     ████████     ████████      ████████     ████████     ████████
 ███   ███    ███    ███   ████   ███    ███   ████   ███    ███   ████   ███    ███   ████   ███    ███   ███    ███   ████   ███    ███   ████   ███    ███   ████   ███    ███   ████   ███    ███   ████   ███    ███   ████   ███    ███   ████   ███    ███   ████   ███    ███   ████   ███    ███   ███    ███   ████   ███    ███   ████   ███    ███    ███   ███    ███   ████   ███    ███   ████   ███    ███   ████   ███
█████ ██████ █████  █████ ██████ █████  █████ ██████ █████ ██████ ██████ █████  █████ ██████ █████ ██████ █████  █████ ██████ █████  █████ ██████ █████  █████ ██████ █████  █████ ██████ █████  █████ ██████ █████  █████ ██████ █████  █████ ██████ █████  █████ ██████ █████  █████ ██████ █████  █████ ██████ █████ ██████ ██████ █████ ██████ ██████ █████ ██████ █████  █████ ██████ █████  █████ ██████ █████  █████ ██████ █████

Ring

# Project : Chaos game

load "guilib.ring"

paint = null

new qapp 
       {
       win1 = new qwidget() {
                  setwindowtitle("Archimedean spiral")
                  setgeometry(100,100,500,600)
                  label1 = new qlabel(win1) {
                               setgeometry(10,10,400,400)
                               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)
                  setpen(pen)

       x = floor(random(10)/10 * 200)
       y = floor(random(10/10) * 173)
       for i = 1 to 20000
           v = floor(random(10)/10 * 3) + 1
	   if v = 1 
	      x = x/2
	      y = y/2
	   ok
	   if v = 2 
	      x = 100 + (100-x)/2
	      y = 173 - (173-y)/2
	   ok
	   if v = 3 
	      x = 200 - (200-x)/2
	      y = y/2
	   ok
	   drawpoint(x,y)
       next
       endpaint()
       }
       label1 {setpicture(p1) show()}

Run BASIC

x	= int(rnd(0) * 200)
y	= int(rnd(0) * 173)
graphic #g, 200,200
#g color("green")
for i =1 TO 20000
	v = int(rnd(0) * 3) + 1
	if v = 1 then
		x = x/2
		y = y/2
	end if
	if v = 2 then
		x = 100 + (100-x)/2
		y = 173 - (173-y)/2
	end if
	if v = 3 then
		x = 200 - (200-x)/2
		y = y/2
	end if
	#g set(x,y)
next
render #g

Rust

Dependencies: image, rand

extern crate image;
extern crate rand;

use rand::prelude::*;
use std::f32;

fn main() {
    let max_iterations = 50_000;
    let img_side = 800;
    let tri_size = 400.0;

    // Create a new ImgBuf
    let mut imgbuf = image::ImageBuffer::new(img_side, img_side);

    // Create triangle vertices
    let mut vertices: [[f32; 2]; 3] = [[0.0, 0.0]; 3];
    for i in 0..vertices.len() {
        vertices[i][0] = (img_side as f32 / 2.0)
            + (tri_size / 2.0) * (f32::consts::PI * i as f32 * 2.0 / 3.0).cos();
        vertices[i][1] = (img_side as f32 / 2.0)
            + (tri_size / 2.0) * (f32::consts::PI * i as f32 * 2.0 / 3.0).sin();
    }
    for v in &vertices {
        imgbuf.put_pixel(v[0] as u32, v[1] as u32, image::Luma([255u8]));
    }
    println!("Verticies: {:?}", vertices);

    // Iterate chaos game
    let mut rng = rand::thread_rng();
    let mut x = img_side as f32 / 2.0;
    let mut y = img_side as f32 / 2.0;
    for _ in 0..max_iterations {
        let choice = rng.gen_range(0..vertices.len());
        x = (x + vertices[choice][0]) / 2.0;
        y = (y + vertices[choice][1]) / 2.0;

        imgbuf.put_pixel(x as u32, y as u32, image::Luma([255u8]));
    }

    // Save image
    imgbuf.save("fractal.png").unwrap();
}

Scala

Java Swing Interoperability

import javax.swing._
import java.awt._
import java.awt.event.ActionEvent

import scala.collection.mutable
import scala.util.Random

object ChaosGame extends App {
  SwingUtilities.invokeLater(() =>
    new JFrame("Chaos Game") {

      class ChaosGame extends JPanel {
        private val (dim, margin)= (new Dimension(640, 640), 60)
        private val sizez: Int = dim.width - 2 * margin
        private val (stack, r) = (new mutable.Stack[ColoredPoint], new Random)
        private val points = Seq(new Point(dim.width / 2, margin),
          new Point(margin, sizez),
          new Point(margin + sizez, sizez)
        )
        private val colors = Seq(Color.red, Color.green, Color.blue)

        override def paintComponent(gg: Graphics): Unit = {
          val g = gg.asInstanceOf[Graphics2D]

          def drawPoints(g: Graphics2D): Unit = {
            for (p <- stack) {
              g.setColor(colors(p.colorIndex))
              g.fillOval(p.x, p.y, 1, 1)
            }
          }

          super.paintComponent(gg)
          g.setRenderingHint(RenderingHints.KEY_ANTIALIASING, RenderingHints.VALUE_ANTIALIAS_ON)
          drawPoints(g)
        }


        private def addPoint(): Unit = {
          val colorIndex = r.nextInt(3)

          def halfwayPoint(a: Point, b: Point, idx: Int) =
            new ColoredPoint((a.x + b.x) / 2, (a.y + b.y) / 2, idx)

          stack.push(halfwayPoint(stack.top, points(colorIndex), colorIndex))
        }

        class ColoredPoint(x: Int, y: Int, val colorIndex: Int) extends Point(x, y)

        stack.push(new ColoredPoint(-1, -1, 0))
        new Timer(100, (_: ActionEvent) => {
          if (stack.size < 50000) {
            for (i <- 0 until 1000) addPoint()
            repaint()
          }
        }).start()
        setBackground(Color.white)
        setPreferredSize(dim)
      }

      add(new ChaosGame, BorderLayout.CENTER)
      pack()
      setDefaultCloseOperation(WindowConstants.EXIT_ON_CLOSE)
      setLocationRelativeTo(null)
      setResizable(false)
      setVisible(true)
    }
  )

}

Scilab

This script uses complex numbers to represent (x,y) coordinates: real part as x position, and imaginary part as y position.

//Input
n_sides = 3;
side_length = 1;
ratio = 0.5;
n_steps = 1.0d5;
first_step = 0;

if n_sides<3 then
    error("n_sides should be at least 3.");
end

//Calculating vertices' positions
theta = (2 * %pi) / n_sides;
alpha = (180 - (360/n_sides)) / 2 * (%pi/180);
radius = (sin(theta) / side_length) / sin(alpha);
vertices = zeros(1,n_sides);
for i=1:n_sides
    vertices(i) = radius * exp( %i * theta * (i-1) ); //equally spaced vertices over a circumference
                                                      //centered on 0 + 0i, or (0,0)
end
clear theta alpha radius i


//Iterations
tic();
points = zeros(1,n_steps);
points(1) = first_step;
i = 2;
while i <= n_steps
    random=grand(1,'prm',[1:n_sides]'); //sort vertices randomly
    random=random(1);                   //choose the first random vertices
        
    points(i) = ( vertices(random) - points(i-1) ) * (1-ratio) + points(i-1);
    
    i = i + 1;  
end
time=toc();
disp('Time: '+string(time)+'s.');

//Ploting
scf(0); clf();
xname('Chaos game: '+string(n_sides)+'-sides polygon');
plot2d(real(points),imag(points),0)
plot2d(real(vertices),imag(vertices),-3);
set(gca(),'isoview','on');
Output:

It outputs a graphic window and prints on the console the time elapsed during iterations.

Time: 1.0424433s.

Sidef

require('Imager')

var width  = 600
var height = 600

var points = [
    [width//2,        0],
    [       0, height-1],
    [height-1, height-1],
]

var img = %O|Imager|.new(
                      xsize => width,
                      ysize => height,
                     )

var color = %O|Imager::Color|.new('#ff0000')
var r = [(width-1).irand, (height-1).irand]

30000.times {
    var p = points.rand

    r[] = (
        (p[0] + r[0]) // 2,
        (p[1] + r[1]) // 2,
    )

    img.setpixel(
        x     => r[0],
        y     => r[1],
        color => color,
    )
}

img.write(file => 'chaos_game.png')

Output image: Chaos game

Simula

BEGIN
    INTEGER U, COLUMNS, LINES;
    COLUMNS := 40;
    LINES := 80;
    U := ININT;
    BEGIN
        CHARACTER ARRAY SCREEN(0:LINES, 0:COLUMNS);
        INTEGER X, Y, I, VERTEX;

        FOR X := 0 STEP 1 UNTIL LINES-1 DO
            FOR Y := 0 STEP 1 UNTIL COLUMNS-1 DO
                SCREEN(X, Y) := ' ';

        X := RANDINT(0, LINES - 1, U);
        Y := RANDINT(0, COLUMNS - 1, U);

        FOR I := 1 STEP 1 UNTIL 5000 DO
        BEGIN
            VERTEX := RANDINT(1, 3, U);
            IF VERTEX = 1 THEN BEGIN X := X // 2;
                                     Y := Y // 2;
                               END ELSE
            IF VERTEX = 2 THEN BEGIN X := LINES // 2 + (LINES // 2 - X) // 2;
                                     Y := COLUMNS - (COLUMNS - Y) // 2;
                               END ELSE
            IF VERTEX = 3 THEN BEGIN X := LINES - (LINES - X) // 2;
                                     Y := Y // 2;
                               END ELSE ERROR("VERTEX OUT OF BOUNDS");
            SCREEN(X, Y) := 'X';
        END;

        FOR Y := 0 STEP 1 UNTIL COLUMNS-1 DO
        BEGIN
            FOR X := 0 STEP 1 UNTIL LINES-1 DO
                OUTCHAR(SCREEN(X, Y));
            OUTIMAGE;
        END;
    END;
END
Input:
678
Output:
XXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXX XXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXX
 XXXX XXX  XXXX XXXX XXX  XXXX XXX  XXXX  XXX XXXX XXXX  XXX  XXX  XXX XXXX XXXX
  XXXXXXX   XXXXXX    XXXXXXX    XXXXXX   XXXXXXX   XXXXXXX   XXXXXXX   XXXXXXX
   XXXX      XXXXX     XXXXX     XXXXX     XXXXX     XXXXX     XXXXX      XXXX
    XX        XXX       XX        XXX       XXX       XXX       XXX        XX
     XXXXXXXXXXX         XXXXXXXXXXX         XXXXXXXXXXX          XXXXXXXXXX
      XXXX XXX            XXXX XXXX           XXXX XXXX            XXX XXXX
       XXXXXX              XXXXXXX             XXXXXXX             XXXXXXX
        XXXXX               XX XX               XXXXX               XXXXX
         XXX                 XXX                 XXX                  XX
          XXXXXXXXXXXXXXXXXXXXX                   XXXXXXXXXXXXXXXXXXXXX
           XXXX XXXX XXXX XXXX                     XXXX XXXX XXXX XXXX
            XXXXXXX   XXXXXXX                       XXXX XX   XX XXXX
             XXXXX     XXXXX                         XXXXX     XXXXX
              XXX      XXXX                           XXX       XXX
               XXXXXXXXXXX                             XXXXXXXXXXX
                XXXX XXXX                               XXXXXXXXX
                XXXXX XX                                 XXXXXXX
                  XXXXX                                    XXXX
                   XXX                                     XXX
                    XXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXX
                     XXXX XXXX XXXX XXXX XXXX XXXX XXXX XXXX
                      XX   XX   XXX  XXX  XX  XXX  XXX   XX
                       XXXXX     XXXXX     XXXXX    XXXXXX
                        XXXX      XXX       XXX       XXX
                         XXXXXXXXXXXX        XXXXXXXXXXX
                          XXXXXXXXX           XXXX XXXX
                           XXX  XX            XXX   XX
                            XXXXX              XXXXXX
                             XXX                XXXX
                              XXXXXXXXXXXXXXXXXXXXX
                               XXXXXXXXXXXXXXXXXXX
                                XXX  XXX XXX  XXX
                                 XXXXXX   XXXXXX
                                  XXXX     XXXX
                                 X XXXXXXXX XX
                                    XXXXXXXXX
                                     XXX XXX
                                      XXXXX
                                       XXX

Uiua

Dim ← 500
Points ← [[50 ⌊÷2Dim] [-50Dim 50] [-50Dim -50Dim]]
# Uncomment to try different square or pentagonal references.
# Points ← [[50 50] [-50Dim 50] [50 -50Dim][-50Dim -50Dim]]
# Points ← [[50 ⌊÷2Dim] [⌊×0.4Dim 50] [⌊×0.4Dim -50Dim] [-50Dim 120] [-50Dim -120Dim]]
Colours ← [[1 0 0] [0 1 0] [0 0 1] [1 1 0] [1 0 1] [0 1 1]]
Rand ← ⌊×⚂

↯Dim_Dim_3 0
∧(⍜(⊡|[1 1 1]◌))Points
⊟Rand Dim Rand Dim
⍥(
  Rand⧻Points
  # Set next point and colour based on target.
  ⊃(⌊÷2+⊡:Points|⊙◌⊡:Colours)
  ⟜⍜⊡◌⊙:
)10000
◌
# Uncomment to save image.
# &fwa "UiuaChaosGameSerpinski.png" &ime "png"
Output:
Render using colours associated with each target point.

Wren

Translation of: Kotlin
Library: DOME
Library: Wren-dynamic
Library: Wren-seq
import "dome" for Window
import "graphics" for Canvas, Color
import "math" for Point
import "random" for Random
import "./dynamic" for Tuple
import "./seq" for Stack

var ColoredPoint = Tuple.create("ColoredPoint", ["x", "y", "colorIndex"])

class ChaosGame {
    construct new(width, height) {
        Window.resize(width, height)
        Canvas.resize(width, height)
        Window.title = "Chaos game"
        _width = width
        _height = height
        _stack = Stack.new()
        _points = null
        _colors = [Color.red, Color.green, Color.blue]
        _r = Random.new()
    }

    init() {
        Canvas.cls(Color.white)
        var margin = 60
        var size = _width - 2 * margin
        _points = [
            Point.new((_width/2).floor, margin),
            Point.new(margin, size),
            Point.new(margin + size, size)
        ]
        _stack.push(ColoredPoint.new(-1, -1, 0))
    }

    addPoint() {
        var colorIndex = _r.int(3)
        var p1 = _stack.peek()
        var p2 = _points[colorIndex]
        _stack.push(halfwayPoint(p1, p2, colorIndex))
    }

    drawPoints() {
        for (cp in _stack) {
            var c = _colors[cp.colorIndex]
            Canvas.circlefill(cp.x, cp.y, 1, c)
        }
    }

    halfwayPoint(a, b, idx) { ColoredPoint.new(((a.x + b.x)/2).floor, ((a.y + b.y)/2).floor, idx) }

    update() {
        if (_stack.count < 50000) {
            for (i in 0...25) addPoint()
        }
    }

    draw(alpha) {
        drawPoints()
    }
}

var Game = ChaosGame.new(640, 640)

X86 Assembly

Sixty bytes handles it.

      1                                  ;Assemble with: tasm, tlink /t
      2     0000                                 .model  tiny
      3     0000                                 .code
      4                                          .386
      5                                          org     100h
      6                                  ;assume: ax=0, bx=0, cx=00FFh, dx=cs, si=0100h
      7
      8     0100  B0 12                  start:  mov     al, 12h         ;set 640x480x4 graphic screen
      9     0102  CD 10                          int     10h
     10
     11     0104  69 04 4E35             cha10:  imul    ax, [si], 4E35h ;generate random number
     12     0108  40                             inc     ax
     13     0109  89 04                          mov     [si], ax        ;save seed
     14     010B  8A C4                          mov     al, ah          ;use high byte
     15     010D  D4 03                          aam     3               ;al:= rem(al/3)
     16     010F  8A D8                          mov     bl, al
     17     0111  02 DB                          add     bl, bl          ;double to index words
     18
     19     0113  03 8F 0130r                    add     cx, [bx+Tx]     ;X:= (X+Tx(R)) /2
     20     0117  D1 E9                          shr     cx, 1
     21
     22     0119  03 97 0136r                    add     dx, [bx+Ty]     ;Y:= (Y+Ty(R)) /2
     23     011D  D1 EA                          shr     dx, 1
     24
     25     011F  B8 0C02                        mov     ax, 0C02h       ;write green (2) graphics pixel
     26     0122  CD 10                          int     10h             ;(bh=0)
     27
     28     0124  B4 01                          mov     ah, 01h         ;loop until keystroke
     29     0126  CD 16                          int     16h
     30     0128  74 DA                          jz      cha10
     31
     32     012A  B8 0003                        mov     ax, 0003h       ;restore normal text-mode screen
     33     012D  CD 10                          int     10h
     34     012F  C3                             ret                     ;return to DOS
     35
     36     0130  0140 002B 0255         Tx      dw      320, 320-277, 320+277 ;equilateral triangle
     37     0136  0000 01DF 01DF         Ty      dw        0, 479,     479
     38                                          end     start

XPL0

int Tx, Ty, X, Y, R;
[SetVid($12);                   \640x480x4 graphics
Tx:= [320, 320-277, 320+277];   \equilateral triangle
Ty:= [0, 479, 479];             \277 = 480 / (2*Sin(60))
X:= Ran(640);                   \random starting point
Y:= Ran(480);
repeat  R:= Ran(3);             \select random triangle point
        X:= (X+Tx(R))/2;        \new point is halfway to it
        Y:= (Y+Ty(R))/2;
        Point(X, Y, 2\green\);  \plot new point
until   KeyHit;
SetVid($03);                    \restore normal text mode
]

Yabasic

width = 640 : height = 480
open window width, height
window origin "lb"

x = ran(width)
y = ran(height)

for i = 1 to 200000
    vertex = int(ran(3))
    if vertex = 1 then
        x = width / 2 + (width / 2 - x) / 2
        y = height - (height - y) / 2
    elseif vertex = 2 then
        x = width - (width - x) / 2
        y = y / 2
    else
        x = x / 2
        y = y / 2
    end if
    color 255 * (vertex = 0), 255 * (vertex = 1), 255 * (vertex = 2)
    dot x, y
next

Z80 Assembly

Translation of: BASIC

This program runs on an MSX-2, in "SCREEN 5" (256x192 graphics mode). It assembles to a .COM file that runs under MSX-DOS, and it will run until you press the space key.

VREG:	equ	99h	; VDP register port
VR0:	equ	0F3DFh	; Copy of VDP R0 in memory
VR1:	equ	0F3E0h	; Copy of VDP R1 in memory
NEWKEY:	equ	0FBE5h	; MSX BIOS puts key data here
VDP:	equ	98h	; VDP data port
ROM:	equ	0FCC0h	; Main ROM slot
JIFFY:	equ	0FCE9h	; BIOS timer
calslt:	equ	1Ch	; Interslot call routine
initxt:	equ	6Ch	; Switch to default text mode
	org	100h
	ld	bc,(JIFFY)	; Initialize RNG with time
	ld	d,b 
	ld	e,c
	exx		; RNG state stored in alternate registers
	di		; Set up the VDP for 256x192 graphics mode
	ld	a,(VR0)	; Get old value of R0
	and	112	; Blank out mode bits
	or	6	; Set high 3 bits = 011(0)
	out	(VREG),a
	ld	a,128	; Store in register 0
	out	(VREG),a
	ld	a,(VR1)	; Get old value of R1
	and	99	; Blank out mode bits
	out	(VREG),a
	ld	a,129	; Low mode bits are 0 so we can just send it
	out	(VREG),a
	ld	a,31	; Bitmap starts at beginning of VRAM
	out	(VREG),a
	ld	a,130
	out	(VREG),a
	xor	a	; Zero out the VRAM - set address to 0
	out	(VREG),a
	ld	a,142
	out	(VREG),a
	xor	a
	out	(VREG),a
	ld	a,64	; Tell VDP to allow writing to VRAM
	out	(VREG),a
	xor	a 	; Write zeroes to the VDP
	ld	c,192	; 2 pixels per byte, meaning 128*192 bytes
zero1:	ld	b,128
zero2:	out	(VDP),a
	djnz	zero2
	dec	c
	jr	nz,zero1
	ei
genX:	call	random	; Generate starting X coordinate
	cp	200
	jr	nc,genX
	ld	b,a	; B = X
genY:	call	random	; Generate starting Y coordinate
	cp	173
	jr	nc,genY
	ld	c,a	; C = Y
step:	call	random	; Get direction
	and	a,3	; Directions {0,1,2}
	cp 	a,3
	jr	z,step
	ld	ixh,a	; Store direction in IXH for color
	dec	a	; Select direction
	jr 	z,d1
	dec	a
	jr	z,d2
	xor	a	; X /= 2
	rr	b
	xor	a	; Y /= 2
	rr	c
	jr	plot	
d1:	xor	a	; There's a 16-bit SBC but not a 16-bit SUB
	ld 	hl,100	; (16-bit math or intermediate values won't fit)
	ld	d,a	; DE = X
	ld	e,b
	sbc	hl,de	; 100 - X 
	xor	a	
	rr	h	; (100 - X) / 2
	rr	l
	ld	e,100	; (100 - X) / 2 + 100
	add	hl,de
	ld	b,l	; -> X	
	xor	a
	ld	hl,173	; 173
	ld	e,c
	sbc	hl,de	; (173 - Y)
	rr	h	; (173 - Y) / 2
	rr	l
	ex	de,hl
	ld	l,173
	xor	a
	sbc	hl,de	; 173 - (173-Y)/2
	ld	c,l 	; -> Y
	jr	plot	
d2:	xor	a
	rr 	c	; Y /= 2 
	xor	a
	ld	hl,200
	ld	d,a	; DE = X
	ld	e,b
	sbc	hl,de	; 200-X
	xor	a
	rr	h	; (200-X)/2
	rr	l
	ex	de,hl
	ld 	l,200
	sbc	hl,de	; 200 - (200-X)/2
	ld	b,l	; -> X
plot:	ld	d,c	; Write address = CB/2
	ld	e,b
	xor	a
	rr	d
	rr	e
	ld	a,d	; First control byte =
	rlca		; high 2 bytes of address
	rlca
	and	3
	ld	h,a	; Keep this value, we'll need it again
	di
	out	(VREG),a
	ld	a,142	; To port 14
	out	(VREG),a
	ld	a,e	; 2nd control byte = low 8 bits
	out	(VREG),a
	ld	a,d	; 3rd control byte = middle 6 bits
	and	63	; Bit 6 off = read
	out	(VREG),a
	nop		; Give it some processing time
	nop
	in	a,(VDP)	; Read the two pixels there
	ld	l,a	; Keep this byte
	ld	a,h	; Now set the VDP to write to that address
	out	(VREG),a
	ld	a,142
	out	(VREG),a
	ld	a,e
	out	(VREG),a
	ld	a,d
	and	63	; Bit 6 on = write
	or	64
	out	(VREG),a
	ld	a,ixh	; Get color
	add	a,12
	ld	d,b	; Left or right pixel?
	rr	d
	jr 	c,wpix
	rlca		; Shift left if X is even 
	rlca
	rlca 
	rlca 
wpix:	or	l	; OR with other pixel in the byte
	out	(VDP),a	; Write byte
	ei
wkey:	ld	a,(NEWKEY+8)
	inc	a	; Check if space key pushed
	jp	z,step	; If not, do another step
	ld	iy,ROM	; Switch back to text mode and quit
	ld	ix,initxt
	jp	calslt
random:	exx		; RNG state stored in alternate registers
	inc	b	; X++
	ld	a,b	; X,
	xor	e	; ^ C,
	xor	c	; ^ A,
	ld	c,a	; -> A
	add	a,d	; + B
	ld	d,a	; -> B
	rra		; >> 1
	xor	c	; ^ A,
	add	a,e	; + C,
	ld	e,a	; -> C
	exx
	ret

zkl

This is a half assed animated process - a bunch of pixels are drawn every couple of seconds and the pixmap written [to the file system]. So, if you open the output file ("chaosGame.jpg") it will [auto] update and show the progression of the image.

Uses the PPM class from http://rosettacode.org/wiki/Bitmap/Bresenham%27s_line_algorithm#zkl

Translation of: Java
w,h:=640,640;
bitmap:=PPM(w,h,0xFF|FF|FF);  // White background
colors:=T(0xFF|00|00,0x00|FF|00,0x00|00|FF);   // red,green,blue
 
margin,size:=60, w - 2*margin;
points:=T(T(w/2, margin), T(margin,size), T(margin + size,size) );
N,done:=Atomic.Int(0),Atomic.Bool(False);
 
Thread.HeartBeat('wrap(hb){  // a thread
   var a=List(-1,-1);

   if(N.inc()<50){
      do(500){ 
	 colorIndex:=(0).random(3);  // (0..2)
	 b,p:=points[colorIndex], halfwayPoint(a,b);
	 x,y:=p;
	 bitmap[x,y]=colors[colorIndex];
	 a=p;
      }
      bitmap.writeJPGFile("chaosGame.jpg",True);
   }
   else{ hb.cancel(); done.set(); }  // stop thread and signal done
},2).go();     // run every 2 seconds, starting now
 
fcn halfwayPoint([(ax,ay)], [(bx,by)]){ T((ax + bx)/2, (ay + by)/2) }

done.wait();  // don't exit until thread is done
println("Done");
Cookies help us deliver our services. By using our services, you agree to our use of cookies.