Andrew Bedno    Andrew@Bedno.com • 773-213-4578
 History   Kudos   Samples 

Pascal
1992 - Ongoing  (32 Years 3 Months)
Pascal

Handheld Fractal Generator

Descended from work I did in Pascal for PCs in 1992, this version compiles for Palm OS.
Also download my library of Pascal routines, utilities and game programs.

Program Fractal;

{$ApplName Fractal}
{$R *.bin}

Uses Window, Form, Menu, Rect, Crt, Event, SysEvent, SystemMgr, HSUtils;

Const
  Color = 1;
  NumIts = 30000;
  MaxColor = 65000;
  MaxLines = 4;
  MaxFractal = 5;
  DevXMax = 160;
  DevYMax = 160;
  MenuAbout = 1001;
  AlertAbout  = 1022;
  MenuMain  = 1000;

Type
  String2 = String[2];
  FractalSetRecord =
    Array [ 1 .. MaxLines ] of Record  A, B, C, D, E, F, P : Real;  End;
  WindowRecord =
    Record  X1, Y1, X2, Y2 : Real;  End;
  FractalDataRecord =
    Record
      Lines : Byte;
      Name : String[ 80 ];
      W : WindowRecord;
      FR : FractalSetRecord;
    End;

Var
  FractalData : FractalDataRecord;
  Result, PrevY : Integer;
  WorldX1, WorldY1, WorldX2, WorldY2, WorldXFactor, WorldYFactor : Real;
  FrcX, FrcY : Real;
  FractalNum, PrevFractalNum : Byte;
  CD : Array [ 1 .. MaxFractal ] of FractalDataRecord;
  WorkRect: RectangleType;
  Event: EventType;

{---------------------------------------------------------------------------}

Procedure SetupConstData;
  Begin
    CD[1].Lines := 4;  CD[1].Name := 'COMET';
    CD[1].W.X1 := 0.0; CD[1].W.Y1 := 0.0; CD[1].W.X2 := 18.0; CD[1].W.Y2 := 9.0;
    CD[1].FR[1].A := 0.0; CD[1].FR[1].B := 0.0; CD[1].FR[1].C := 0.0; CD[1].FR[1].D := 0.0; CD[1].FR[1].E := 1.0; CD[1].FR[1].F := 0.0; CD[1].FR[1].P := 0.01;
    CD[1].FR[2].A := 0.85; CD[1].FR[2].B := 0.4; CD[1].FR[2].C := -0.04; CD[1].FR[2].D := 0.85; CD[1].FR[2].E := 0.0; CD[1].FR[2].F := 1.6; CD[1].FR[2].P := 0.85;
    CD[1].FR[3].A := 0.2; CD[1].FR[3].B := -0.26; CD[1].FR[3].C := 0.23; CD[1].FR[3].D := 0.22; CD[1].FR[3].E := 0.0; CD[1].FR[3].F := 1.6; CD[1].FR[3].P := 0.07;
    CD[1].FR[4].A := -0.15; CD[1].FR[4].B := 0.28; CD[1].FR[4].C := 0.26; CD[1].FR[4].D := 0.24; CD[1].FR[4].E := 0.0; CD[1].FR[4].F := 0.44; CD[1].FR[4].P := 0.07;
    CD[2].Lines := 4;  CD[2].Name := 'FERN';
    CD[2].W.X1 := -5.0; CD[2].W.Y1 := 0.0; CD[2].W.X2 := 4.0; CD[2].W.Y2 := 12.0;
    CD[2].FR[1].A := 0.0; CD[2].FR[1].B := 0.0; CD[2].FR[1].C := 0.0; CD[2].FR[1].D := 0.0; CD[2].FR[1].E := 1.0; CD[2].FR[1].F := 0.0; CD[2].FR[1].P := 0.01;
    CD[2].FR[2].A := 0.85; CD[2].FR[2].B := -0.03; CD[2].FR[2].C := 0.03; CD[2].FR[2].D := 0.85; CD[2].FR[2].E := 0.0; CD[2].FR[2].F := 1.6; CD[2].FR[2].P := 0.85;
    CD[2].FR[3].A := 0.2; CD[2].FR[3].B := -0.26; CD[2].FR[3].C := 0.23; CD[2].FR[3].D := 0.22; CD[2].FR[3].E := 0.0; CD[2].FR[3].F := 1.6; CD[2].FR[3].P := 0.07;
    CD[2].FR[4].A := -0.15; CD[2].FR[4].B := 0.28; CD[2].FR[4].C := 0.26; CD[2].FR[4].D := 0.24; CD[2].FR[4].E := 0.0; CD[2].FR[4].F := 0.44; CD[2].FR[4].P := 0.07;
    CD[3].Lines := 4;  CD[3].Name := 'NEBULA';
    CD[3].W.X1 := -0.15; CD[3].W.Y1 := -0.2; CD[3].W.X2 := 0.57; CD[3].W.Y2 := 0.57;
    CD[3].FR[1].A := 0.1; CD[3].FR[1].B := 0.42; CD[3].FR[1].C := -0.42; CD[3].FR[1].D := 0.5; CD[3].FR[1].E := 0.1; CD[3].FR[1].F := 0.0; CD[3].FR[1].P := 0.1;
    CD[3].FR[2].A := 0.42; CD[3].FR[2].B := -0.42; CD[3].FR[2].C := 0.42; CD[3].FR[2].D := 0.42; CD[3].FR[2].E := 0.1; CD[3].FR[2].F := 0.2; CD[3].FR[2].P := 0.42;
    CD[3].FR[3].A := 0.42; CD[3].FR[3].B := 0.42; CD[3].FR[3].C := -0.42; CD[3].FR[3].D := 0.42; CD[3].FR[3].E := 0.2; CD[3].FR[3].F := 0.2; CD[3].FR[3].P := 0.42;
    CD[3].FR[4].A := 0.1; CD[3].FR[4].B := 0.0; CD[3].FR[4].C := 0.0; CD[3].FR[4].D := 0.1; CD[3].FR[4].E := 0.0; CD[3].FR[4].F := 0.2; CD[3].FR[4].P := 0.06;
    CD[4].Lines := 4;  CD[4].Name := 'SNAILS';
    CD[4].W.X1 := -4.5; CD[4].W.Y1 := 0.0; CD[4].W.X2 := 1.5; CD[4].W.Y2 := 4.0;
    CD[4].FR[1].A := 0.0; CD[4].FR[1].B := 0.0; CD[4].FR[1].C := 0.0; CD[4].FR[1].D := 0.0; CD[4].FR[1].E := 1.0; CD[4].FR[1].F := 0.0; CD[4].FR[1].P := 0.01;
    CD[4].FR[2].A := 0.74; CD[4].FR[2].B := -0.43; CD[4].FR[2].C := 0.43; CD[4].FR[2].D := 0.74; CD[4].FR[2].E := 0.0; CD[4].FR[2].F := 1.6; CD[4].FR[2].P := 0.85;
    CD[4].FR[3].A := 0.2; CD[4].FR[3].B := -0.26; CD[4].FR[3].C := 0.23; CD[4].FR[3].D := 0.22; CD[4].FR[3].E := 0.0; CD[4].FR[3].F := 1.6; CD[4].FR[3].P := 0.07;
    CD[4].FR[4].A := -0.15; CD[4].FR[4].B := 0.28; CD[4].FR[4].C := 0.26; CD[4].FR[4].D := 0.24; CD[4].FR[4].E := 0.0; CD[4].FR[4].F := 0.44; CD[4].FR[4].P := 0.07;
    CD[5].Lines := 4;  CD[5].Name := 'TREE';
    CD[5].W.X1 := -0.3; CD[5].W.Y1 := 0.0; CD[5].W.X2 := 0.3; CD[5].W.Y2 := 0.5;
    CD[5].FR[1].A := 0.0; CD[5].FR[1].B := 0.0; CD[5].FR[1].C := 0.0; CD[5].FR[1].D := 0.5; CD[5].FR[1].E := 0.0; CD[5].FR[1].F := 0.0; CD[5].FR[1].P := 0.05;
    CD[5].FR[2].A := 0.42; CD[5].FR[2].B := -0.42; CD[5].FR[2].C := 0.42; CD[5].FR[2].D := 0.42; CD[5].FR[2].E := 0.0; CD[5].FR[2].F := 0.2; CD[5].FR[2].P := 0.4;
    CD[5].FR[3].A := 0.42; CD[5].FR[3].B := 0.42; CD[5].FR[3].C := -0.42; CD[5].FR[3].D := 0.42; CD[5].FR[3].E := 0.0; CD[5].FR[3].F := 0.2; CD[5].FR[3].P := 0.4;
    CD[5].FR[4].A := 0.1; CD[5].FR[4].B := 0.0; CD[5].FR[4].C := 0.0; CD[5].FR[4].D := 0.1; CD[5].FR[4].E := 0.0; CD[5].FR[4].F := 0.2; CD[5].FR[4].P := 0.15;
  End;

{---------------------------------------------------------------------------}

Procedure SetWorld( InX1, InY1, InX2, InY2 : Real );
  Begin
    WorldX1 := InX1;  WorldY1 := InY1;  WorldX2 := InX2;  WorldY2 := InY2;
    WorldXFactor := DevXMax / ( WorldX2 - WorldX1 );
    WorldYFactor := DevYMax / ( WorldY2 - WorldY1 );
  End;

{---------------------------------------------------------------------------}

Procedure Plot( X, Y, C : LongInt );
  Begin
    Result := WinSetForeColor(C);
    WinDrawPixel(X,Y);
  End;

{----------------------------------------------------------------}

Function GetDot( X, Y : LongInt ) : LongInt;
  Begin
    GetDot := WinGetPixel(X,Y);
  End;

{----------------------------------------------------------------}

Procedure SetDot( X, Y : Real );
  Var
    Color : LongInt;
  Begin
    If ( X >= WorldX1 ) and ( X <= WorldX2 ) and
       ( Y >= WorldY1 ) and ( Y <= WorldY2 ) Then
      Begin
        X := ( X - WorldX1 ) * WorldXFactor;
        Y := ( DevYMax - 1 ) - ( Y - WorldY1 ) * WorldYFactor;
        Color := GetDot( Trunc( X ), Trunc( Y ) );
        If Color < MaxColor Then Color := Trunc( (Color + 1) * 1.5 );
        Plot( Trunc( X ), Trunc( Y ), Color )
      End;
  End;

{---------------------------------------------------------------------------}

Procedure Iterate;
  Var
    Delta : Byte;
    R, Prob, NewX, NewY : Real;
  Begin
    With FractalData do
      Begin
        R := Random;  Prob := FR[ 1 ].P;  Delta := 1;
        While ( R > Prob ) and ( Delta < Lines ) do
          Begin
            Inc( Delta );
            Prob := Prob + FR[ Delta ].P;
          End;
        With FR[ Delta ] do
          Begin
            NewX := A * FrcX + B * FrcY + E;
            NewY := C * FrcX + D * FrcY + F;
          End;
        FrcX := NewX;  FrcY := NewY;
        SetDot( FrcX, FrcY );
      End;
  End;

{---------------------------------------------------------------------------}

Procedure Generate;
  Var
    BurstIt : LongInt;
    ItLoop : LongInt;
    BResult : Boolean;
  Const
    BurstSize = 100;
  Begin
    FrcX := 0.0;  FrcY := 0.0;
    SetWorld( FractalData.W.X1, FractalData.W.Y1,
              FractalData.W.X2, FractalData.W.Y2 );
    ItLoop := 1;
    While ( ItLoop <= NumIts ) do
      Begin
        For BurstIt := 1 to BurstSize do Iterate;
        EvtGetEvent(Event, 5);
        if (Event.eType = 21) Then
          Result := FrmAlert(AlertAbout)
        Else
          BResult := SysHandleEvent(Event);
        If (Event.eType = appStopEvent) Then Exit;
        ItLoop := ItLoop + BurstSize;
      End;
  End;

{---------------------------------------------------------------------------}

Resource
(ResTAIN,1000,'Fractal');
(Restver,1000,'1.0');

Begin
  Randomize;
  RctSetRectangle(WorkRect, 0, 0, 160, 160);
  SetupConstData;
  FractalNum := 0;
  While True Do
    Begin
      PrevFractalNum := FractalNum;
      Repeat
        FractalNum := Trunc(1 + ( MaxFractal * Random));
      Until (FractalNum <> PrevFractalNum);
      WinEraseRectangle(WorkRect, 0);
      FractalData := CD[ FractalNum ];
      GotoXY(1,1);
      WriteLn('Fractals by Andrew@Bedno.com');
      GotoXY(16,16);
      Write(FractalData.Name);
      Generate;
      If (Event.eType=appStopEvent) Then Exit;
    End;
End.


 SAMPLE   DOWNLOAD         < NEWER