There are 256 rules in total, they all have small errors1. Some of the rules are shown here, others are insignificant.
rule_026.png |
rule_236.png |
rule_227.png |
rule_060.png |
rule_186.png |
rule_122.png |
rule_059.png |
rule_103.png |
rule_219.png |
rule_231.png |
rule_107.png |
rule_126.png |
rule_065.png |
rule_244.png |
rule_159.png |
rule_180.png |
rule_166.png |
rule_082.png |
rule_138.png |
rule_229.png |
rule_099.png |
rule_175.png |
rule_167.png |
rule_210.png |
rule_145.png |
rule_115.png |
rule_193.png |
rule_049.png |
rule_150.png |
rule_111.png |
rule_076.png |
rule_073.png |
rule_155.png |
rule_129.png |
rule_169.png |
rule_191.png |
rule_121.png |
rule_033.png |
rule_110.png |
rule_151.png |
rule_202.png |
rule_240.png |
rule_097.png |
rule_066.png |
rule_086.png |
rule_131.png |
rule_135.png |
rule_125.png |
rule_037.png |
rule_034.png |
rule_221.png |
rule_074.png |
rule_203.png |
rule_075.png |
rule_158.png |
rule_161.png |
rule_054.png |
rule_181.png |
rule_153.png |
rule_124.png |
rule_214.png |
rule_080.png |
rule_024.png |
rule_182.png |
rule_165.png |
rule_225.png |
rule_241.png |
rule_063.png |
rule_029.png |
rule_045.png |
rule_084.png |
rule_091.png |
rule_089.png |
rule_057.png |
rule_228.png |
rule_184.png |
rule_036.png |
rule_123.png |
rule_095.png |
rule_146.png |
rule_094.png |
rule_101.png |
rule_109.png |
rule_090.png |
rule_120.png |
rule_185.png |
rule_062.png |
rule_035.png |
rule_163.png |
rule_106.png |
rule_183.png |
rule_102.png |
rule_196.png |
rule_022.png |
rule_041.png |
rule_085.png |
rule_105.png |
rule_217.png |
rule_149.png |
rule_083.png |
rule_137.png |
rule_081.png |
rule_154.png |
rule_230.png |
rule_147.png |
rule_195.png |
rule_061.png |
rule_118.png |
rule_207.png |
rule_030.png |
rule_164.png |
// Cellular automatons TBitArray = class private FData : array of Byte; FBitCount : Integer; private function GetBit( anIndex: Integer): Integer; procedure SetBit( anIndex: Integer; aValue: Integer); public procedure Clear; public property Bit[ anIndex: Integer] : Integer read GetBit write SetBit; property BitCount : Integer read FBitCount; end; PBitArray = ^ TBitArray; // Elementary Cellular Automaton, catalogued by FRule TElementaryCA = class private FBits1 : TBitArray; FBits2 : TBitArray; FBitsO : PBitArray; FBitsN : PBitArray; FRule : Byte; FHasRandomSeed : Integer; FFaultRate : TSignal; private function GetBit( anIndex: Integer) : Integer; function GetBitCount : Integer; procedure SwapON; public constructor Create; destructor Destroy; override; procedure Clear; procedure Execute; procedure SetRandomSeed( aBitCount: Integer); public property Bit[ anIndex: Integer]: Integer read GetBit; property BitCount : Integer read GetBitCount; property Rule : Byte read FRule write FRule; property FaultRate : TSignal read FFaultRate write FFaultRate; end; // ///////////////////////////////////////////////////////////////////////////////////////// // ///////////////////////////////////////////////////////////////////////////////////////// function MathIntMod( X, Y: Integer): Integer; inline; begin Result := ( X mod Y + Y) mod Y; end; function MathIntDiv( X, Y: Integer): Integer; inline; begin Result := Floor( X / Y); end; { ======== TBitArray = class private FData : array of Byte; FBitCount : Integer; public property Bit[ anIndex: Integer] : Integer read GetBit write SetBit; property BitCount : Integer read FBitCount; private } function TBitArray.GetBit( anIndex: Integer): Integer; var i : Integer; b : Integer; begin i := MathIntDiv( anIndex, 8); if ( i >= 0) and ( anIndex < FBitCount) then begin b := MathIntMod( anIndex, 8); if ( FData[ i] and ( 1 shl b)) <> 0 then Result := 1 else Result := 0; end else Result := 0; end; procedure TBitArray.SetBit( anIndex: Integer; aValue: Integer); var i : Integer; b : Integer; begin i := MathIntDiv( anIndex, 8); if i >= 0 then begin b := MathIntMod( anIndex, 8); if i >= Length( FData) then SetLength( FData, i + 1); if anIndex >= FBitCount then FBitCount := anIndex + 1; if aValue <> 0 then FData[ i] := FData[ i] or ( 1 shl b) else FData[ i] := FData[ i] and ( not ( 1 shl b)); end; end; // public procedure TBitArray.Clear; begin FBitCount := 0; SetLength( FData, 0);; end; { ======== TElementaryCA = class private FBits1 : TBitArray; FBits2 : TBitArray; FBitsO : PBitArray; FBitsN : PBitArray; FRule : Byte; FHasRandomSeed : Integer; FFaultRate : TSignal; public property Bit[ anIndex: Integer]: Integer read GetBit; property BitCount : Integer read GetBitCount; property Rule : Byte read FRule write FRule; property FaultRate : TSignal read FFaultRate write FFaultRate; private } function TElementaryCA.GetBit( anIndex: Integer): Integer; begin if Assigned( FBitsO) then Result := FBitsO^.Bit[ anIndex] else Result := 0; end; function TElementaryCA.GetBitCount: Integer; begin if Assigned( FBitsO) then Result := FBitsO^.BitCount else Result := 0; end; procedure TElementaryCA.SwapON; var aTmp: PBitArray; begin aTmp := FBitsO; FBitsO := FBitsN; FBitsN := aTmp; end; // public constructor TElementaryCA.Create; var i : Integer; begin inherited Create; FRule := 0; FBits1 := TBitArray.Create; FBits2 := TBitArray.Create; FBitsO := @ FBits1; FBitsN := @ FBits2; if FHasRandomSeed > 0 then begin for i := 0 to FHasRandomSeed - 1 do FBits1.Bit[ i] := Random( 2); end else FBits1.Bit[ 0] := 1; end; destructor TElementaryCA.Destroy; // override; begin FBitsO := nil; FBitsN := nil; FBits1.DisposeOf; FBits2.DisposeOf; inherited; end; procedure TElementaryCA.Clear; var i : Integer; begin FBits1.Clear; FBits2.Clear; FBitsO := @ FBits1; FBitsN := @ FBits2; if FHasRandomSeed > 0 then begin for i := 0 to FHasRandomSeed - 1 do FBits1.Bit[ i] := Random( 2); end else FBits1.Bit[ 0] := 1; end; procedure TElementaryCA.Execute; var P : Byte; N : Byte; i : Integer; F : Integer; begin if Assigned( FBitsN) then begin for i := 0 to BitCount + 1 do begin N := Bit[ i] + ( Bit[ i - 1] shl 1) + ( Bit[ i - 2] shl 2); P := 1 shl N; if Random < FFaultRate then F := 1 else F := 0; if ( FRule and P) <> 0 then FBitsN^.Bit[ i] := 1 xor F else FBitsN^.Bit[ i] := 0 xor F; end; SwapON; end; end; procedure TElementaryCA.SetRandomSeed( aBitCount: Integer); begin FHasRandomSeed := aBitCount; Clear; end; // ///////////////////////////////////////////////////////////////////////////////////////// // ///////////////////////////////////////////////////////////////////////////////////////// // User area const BACK_COLOR = clSilver; FORE_COLOR = clNavy; // private procedure TFormAutomaton.SetRule( aValue: Integer); begin if ( aValue >= 0) and ( aValue <= 255) and ( aValue <> FRule) then begin FRule := aValue; EditRule.Text := IntToStr( FRule); end; end; // private procedure TFormAutomaton.Clear; begin FLine := 0; // FAutomaton.SetRandomSeed( FBitmap.Width); FAutomaton.Clear; FAutomaton.Rule := Rule; FAutomaton.FaultRate := 0.001; // ← [Note 1] error rate of 1 ‰ FBitmap.Canvas.Pen .Color := BACK_COLOR; FBitmap.Canvas.Brush.Color := BACK_COLOR; FBitmap.Canvas.Rectangle( 0, 0, FBitmap.Width, FBitmap.Height); PaintLine; end; procedure TFormAutomaton.Run; var i : Integer; begin Clear; for i := 0 to FBitmap.Height - 1 do Step; end; procedure TFormAutomaton.Step; begin Inc( FLine); FAutomaton.Execute; PaintLine; end; procedure TFormAutomaton.PaintLine; const Colors : array[ 0 .. 1] of TColor = ( BACK_COLOR, FORE_COLOR); var Mid : Integer; i : Integer; begin Mid := FBitmap.Width div 2; for i := 0 to FAutomaton.BitCount - 1 do FBitmap.Canvas.Pixels[ i - FLine + Mid, FLine] := Colors[ FAutomaton.Bit[ i]]; PaintBox.Invalidate; end; procedure TFormAutomaton.DoPaint; begin PaintBox.Canvas.Draw( 0, 0, FBitmap); end;