//---------------------------------------------------------------------------
#include <vcl.h>
#pragma hdrstop

#include "froslina6.h"
#include <math.h>
//---------------------------------------------------------------------------
#pragma package(smart_init)
#pragma resource "*.dfm"
TForm1 *Form1;
//---------------------------------------------------------------------------
//  Obiekt pomocniczy - parametr rośliny (np. długość)
//  z procesem samomodyfikacji przypadkowej na szerokość Amutacja.
//  Gdy określono obydwie granice, nastąpi 'przycięcie' genu.
TGen :: TGen( double Ag, double Amutacja,
            double Amin/*=NIEOKRESLONY*/, double Amax/*=NIEOKRESLONY*/)
{
 g = Ag;
 mutacja = Amutacja;
 min = Amin;
 max = Amax;
}
//---------------------------------------------------------------------------
//  Pomocnicza funkcja, rozpraszająca pseudolosowo podaną wartość
//  i przycinająca ją do podanego zakresu.
double TGen :: mutuj( double Ag, double Amut, double Amin, double Amax) const
{
 int a = 1000.0 * Amut;     //"poszerzony" zakres losowania
 double b = Ag + (random( 2*a)-a) / 1000.0;

 if( Amin != NIEOKRESLONY && Amax != NIEOKRESLONY)
 {
    if( b > Amax)
        b = Amax;
    if( b < Amin)
        b = Amin;
 }
 return b;
}
//---------------------------------------------------------------------------
//  Zwróć wartość rozproszoną przypadkowo na głębokość mutacja.
double TGen :: daj_zmutowany_parametr( void) const
{
 return mutuj( g, mutacja, min, max);
}
//---------------------------------------------------------------------------
//  Wersja "kolorowa" ...
TColor TGen :: daj_zmutowany_kolor( void) const
{
 TColor kolor = (TColor)g,
        kolor_mut = (TColor)mutacja,
        kolor_min = (TColor)min,
        kolor_max = (TColor)max;
 int r = GetRValue( kolor), r_mut, r_min, r_max;  //rozkład koloru na r, g, b
 int g = GetGValue( kolor), g_mut, g_min, g_max;
 int b = GetBValue( kolor), b_mut, b_min, b_max;

 r_mut = GetRValue( kolor_mut);
 g_mut = GetGValue( kolor_mut);
 b_mut = GetBValue( kolor_mut);
 if( min != NIEOKRESLONY && max != NIEOKRESLONY)
 {
    r_min = GetRValue( kolor_min),
    r_max = GetRValue( kolor_max);
    g_min = GetGValue( kolor_min),
    g_max = GetGValue( kolor_max);
    b_min = GetBValue( kolor_min),
    b_max = GetBValue( kolor_max);
 }
 else
 {
    r_min=g_min=b_min=0;
    r_max=g_max=b_max=255;
 }
 r = mutuj( r, r_mut, r_min, r_max);
 g = mutuj( g, g_mut, g_min, g_max);
 b = mutuj( b, b_mut, b_min, b_max);

 return RGB( r, g, b);          //synteza zmutowanych składników
}
//---------------------------------------------------------------------------
//  Pokaż bieżące parametry mutacji
void TGen :: daj_min_max( double &Amin, double &Amax) const
{
 Amin = min;
 Amax = max;
}
//---------------------------------------------------------------------------
//  Pokaż bieżące parametry mutacji
void TGen :: daj_mut( double &Amut) const
{
 Amut = mutacja;
}
//---------------------------------------------------------------------------
__fastcall TForm1::TForm1(TComponent* Owner) : TForm(Owner)
{
}
//---------------------------------------------------------------------------
void __fastcall TForm1::FormPaint(TObject *Sender)
{
 TGen Adlg( 2.6, 0);         //opis długości witki A
 TGen Agrubosc( 1, 0);
 TGen Akolor( clGreen, 0x002000);
 TGen Bdlg( 3, 0);          //analogicznie opis witki B
 TGen Bgrubosc( 2, 0) ;     //jej grubość,
 TGen Bkolor( clSilver, 0x202020); //kolor,
 TGen Zmianadlg( 0.9, 1, 0.8, 1);   //zmiana długości
 TGen Kierunek( 90, 20);    //kąt prowadzenia gałązki
 TGen Lzakret( 40, 10);     //kąt odchylenia w lewo
 TGen Rzakret( 40, 10);     //w prawo
 TGen Odrost( 1, 0);  //współczynnik zmutowania odrostu

 formula = "B";             //inicjowanie formuły

 rozwin();
 rozwin();
 rozwin();
 rozwin();
 rozwin();
 rozwin();
// rozwin();
 POZYCJA = 0;               //inicjowanie algorytmu rysuj()
 rysuj( 160, 10, Adlg, Agrubosc, Akolor,
                 Bdlg, Bgrubosc, Bkolor,
                 Zmianadlg, Kierunek, Lzakret, Rzakret,
                 Odrost);
}
//---------------------------------------------------------------------------
//  Wzrost rośliny
void TForm1 :: rozwin( void)
{
 String tmp;
 int i, dlg = formula.Length();
 char c;

 for( i = 1; i <= dlg; i ++)
 {
    c = formula[ i];
    switch( c)
    {
     case 'A':              //gałązka typu A
                tmp += "AA";
                break;
     case 'B':              //gałązka typu B
                tmp += "A(RDB)(LDB)(RDB)(LDB)AB";
                break;
     case 'D':              //zmiana długości
                tmp += "D";
                break;
     case 'R':              //zwrot w prawo
                tmp += "R";
                break;
     case 'L':              //zwrot w lewo
                tmp += "L";
                break;
     case '(':              //boczny odrost
                tmp += "(";
                break;
     case ')':              //koniec odrostu
                tmp += ")";
                break;
    }
 }
 formula = tmp;
}
//---------------------------------------------------------------------------
//  Interpretuj formułę, począwszy od pozycji POZYCJA.
//  Uwaga: bywa, że ta funkcja wywołuje samą siebie.
//  Wtedy kluczowe znaczenie ma zewnętrzna zmienna POZYCJA ...
void TForm1 ::  rysuj( double Ax0, double Ay0,
                TGen Adlg, TGen Agrub, TGen Akolor,
                TGen Bdlg, TGen Bgrub, TGen Bkolor,
                TGen Zmianadlg,
                TGen Kierunek, TGen Lzakret, TGen Rzakret,
                TGen Odrost)
{
 double x0 = Ax0, y0 = Ay0;
 double adlg, agrub, bdlg, bgrub;   //bieżące parametry rośliny
 double zmianadlg;
 TColor akolor, bkolor;
 double kierunek, lzakret, rzakret, odrost;

 double mutacja, min, max;  //pomocnicze


 int len = formula.Length();
 char c;
 double k = M_PI / 180.;    //stopnie na radiany

 while( POZYCJA < len)
 {
    adlg = Adlg.daj_zmutowany_parametr();
    agrub = Agrub.daj_zmutowany_parametr();
    akolor = Akolor.daj_zmutowany_kolor();

    bdlg = Bdlg.daj_zmutowany_parametr();
    bgrub = Bgrub.daj_zmutowany_parametr();
    bkolor = Bkolor.daj_zmutowany_kolor();

    zmianadlg = Zmianadlg.daj_zmutowany_parametr();

    kierunek = Kierunek.daj_zmutowany_parametr();
    lzakret = Lzakret.daj_zmutowany_parametr();
    rzakret = Rzakret.daj_zmutowany_parametr();

    odrost = Odrost.daj_zmutowany_parametr();

    c = formula[ ++POZYCJA];
    switch( c)
    {
     case 'A':              //wykreśl odcinek 'A'
                Canvas -> Pen -> Width = agrub;
                Canvas -> Pen -> Color = akolor;
                Canvas -> MoveTo( x0, ClientHeight-y0);
                x0 += adlg * cos( k * kierunek);
                y0 += adlg * sin( k * kierunek);
                Canvas -> LineTo( x0, ClientHeight-y0);
                break;
     case 'B':              //wykreśl odcinek 'B'
                Canvas -> Pen -> Width = bgrub;
                Canvas -> Pen -> Color = bkolor;
                Canvas -> MoveTo( x0, ClientHeight-y0);
                x0 += bdlg * cos( k * kierunek);
                y0 += bdlg * sin( k * kierunek);
                Canvas -> LineTo( x0, ClientHeight-y0);
                break;
     case 'D':              //zmiana długości
                Adlg.daj_mut( mutacja);
                Adlg.daj_min_max( min, max);
                Adlg = TGen( adlg * zmianadlg, mutacja, min, max);
                Bdlg.daj_mut( mutacja);
                Bdlg.daj_min_max( min, max);
                Bdlg = TGen( bdlg * zmianadlg, mutacja, min, max);
                break;
     case 'L':              //zwrot w lewo
                Kierunek.daj_min_max( min, max);
                Lzakret.daj_mut( mutacja);
                Kierunek = TGen( kierunek + lzakret, mutacja, min, max);
                break;
     case 'R':              //zwrot w prawo
                Kierunek.daj_min_max( min, max);
                Rzakret.daj_mut( mutacja);
                Kierunek = TGen( kierunek - rzakret, mutacja, min, max);
                break;
     case '(':              //odrost - wywołanie rekurencyjne.
                            //Zbuduj nowe geny z bieżących parametrów
                {   Adlg.daj_min_max( min, max);
                    Adlg.daj_mut( mutacja);
                    TGen nowyAdlg( adlg, mutacja*odrost, min, max);

                    Agrub.daj_min_max( min, max);
                    Agrub.daj_mut( mutacja);
                    TGen nowyAgrub( agrub, mutacja*odrost, min, max);

                    Akolor.daj_min_max( min, max);
                    Akolor.daj_mut( mutacja);
                    TGen nowyAkolor( akolor, mutacja*odrost, min, max);

                    Bdlg.daj_min_max( min, max);
                    Bdlg.daj_mut( mutacja);
                    TGen nowyBdlg( bdlg, mutacja*odrost, min, max);

                    Bgrub.daj_min_max( min, max);
                    Bgrub.daj_mut( mutacja);
                    TGen nowyBgrub( bgrub, mutacja*odrost, min, max);

                    Bkolor.daj_min_max( min, max);
                    Bkolor.daj_mut( mutacja);
                    TGen nowyBkolor( bkolor, mutacja*odrost, min, max);

                    Zmianadlg.daj_min_max( min, max);
                    Zmianadlg.daj_mut( mutacja);
                    TGen nowyZmianadlg( zmianadlg, mutacja*odrost, min, max);

                    Kierunek.daj_min_max( min, max);
                    Kierunek.daj_mut( mutacja);
                    TGen nowyKierunek( kierunek, mutacja*odrost, min, max);

                    Lzakret.daj_min_max( min, max);
                    Lzakret.daj_mut( mutacja);
                    TGen nowyLzakret( lzakret, mutacja*odrost, min, max);

                    Rzakret.daj_min_max( min, max);
                    Rzakret.daj_mut( mutacja);
                    TGen nowyRzakret( rzakret, mutacja*odrost, min, max);

                    Odrost.daj_min_max( min, max);
                    Odrost.daj_mut( mutacja);
                    TGen nowyOdrost( odrost, mutacja*odrost, min, max);

                    rysuj( x0, y0, nowyAdlg, nowyAgrub, nowyAkolor,
                        nowyBdlg, nowyBgrub, nowyBkolor, nowyZmianadlg,
                        nowyKierunek, nowyLzakret, nowyRzakret,
                        nowyOdrost);
                }
                break;
     case ')':              //koniec odrostu
                return;
    }
 }
 return;
}
//---------------------------------------------------------------------------


