{****************************************************************************}
{* Grammar-based program for simulating flower-field. Made by Wilhelmiina   *}
{* Hämäläinen, long ago, for Turbo-Pascal. Works at least with Turbo-Pascal *}
{* 7.0, might work as such with Gnu-Pascal.                                 *}
{****************************************************************************}

program flowerpower(input, output);

uses Crt, Graph;

const oiklehti: array[1..7, 1..2] of integer=
      ((0,10), (5,3), (10,0), (20,0), (15,7), (10,10), (0,10));

      vaslehti: array[1..7, 1..2] of integer=
      ((20,10), (15,3), (10,0), (0,0), (5,7), (10,10), (20,10));

      v2lehti: array[1..5,1..2] of integer=
      ((0,10),(8,12),(10,20),(3,18),(0,10));

      o2lehti: array[1..5, 1..2] of integer=
      ((10,20),(12,12),(20,10),(17,18),(10,20));

      isov2lehti: array[1..7,1..2] of integer=
      ((0,0),(6,5),(9,13),(9,20),(4,18),(0,10),(0,0));

      isoo2lehti: array[1..7,1..2] of integer=
      ((20,0),(14,5),(11,13),(11,20),(16,18),(20,10),(20,0));

      {kielon kukat:}
      om1: array[1..5,1..2] of integer =
      ((19,10),(20,12),(19,11),(18,12),(19,10));

      om2: array[1..5,1..2] of integer =
      ((14,13),(16,15),(15,15),(15,16),(14,15));

      om3: array[1..5,1..2] of integer =
      ((10,18),(12,17),(11,18),(12,19),(10,18));

      vm1: array[1..5,1..2] of integer =
      ((1,10),(0,12),(1,11),(2,12),(1,10));

      vm2: array[1..5,1..2] of integer =
      ((6,13),(4,15),(5,15),(5,16),(6,15));

      vm3: array[1..5,1..2] of integer =
      ((10,18),(8,17),(9,18),(8,19),(10,18));

type kuvatietue=record
                      tyyppi:integer;
                      vari:word;
                end;

var GrDriver, GrMode, i, j, l: integer;
    kuvat: array[1..24, 1..24] of kuvatietue;


procedure TarkistaBGIVirhe(SuljeGrafiikka:boolean);
{****************************************************************************}
{* tarkistaa, tapahtuiko virhe grafiikkatilaa kaynnistaessa                 *}
{****************************************************************************}

var virhe:integer;
begin
     virhe:=GraphResult;
     if virhe < 0 then
     begin
          if SuljeGrafiikka then
             CloseGraph;
          writeln('Error: ', GraphErrorMsg(virhe));
          halt(1);
     end;
end;


procedure Alusta;
{****************************************************************************}
{* suorittaa alustustoimenpiteet                                            *}
{****************************************************************************}
var i,j:integer;

begin
    DetectGraph(GrDriver,GrMode);   {grafiikkatilan alustus}
    if (GrDriver <> VGA) then
       begin
            writeln('This program requires a VGA-display');
            halt(1);
       end;
    GrDriver:=VGA;
    GrMode:=VGAHi;
    InitGraph(GrDriver,GrMode,'');
    TarkistaBGIVirhe(false);
    for i:=1 to 24 do
        for j:=1 to 24 do
            kuvat[i,j].tyyppi:=0;
end;

procedure olehti(x, y:integer);
begin
     SetViewPort(x, y, x+20, y+20, ClipOn);
     SetColor(DarkGray);
     SetFillStyle(SolidFill, Green);
     FillPoly(7, oiklehti);
     SetViewPort(0, 0, GetMaxX, GetMaxY, ClipOn);
end;

procedure vlehti(x, y:integer);
begin
     SetViewPort(x, y, x+20, y+20, ClipOn);
     SetColor(DarkGray);
     SetFillStyle(SolidFill, Green);
     FillPoly(7, vaslehti);
     SetViewPort(0, 0, GetMaxX, GetMaxY, ClipOn);
end;

procedure kaksoislehti(x, y:integer);
begin
     SetViewPort(x, y, x+20, y+20, ClipOn);
     SetColor(DarkGray);
     SetFillStyle(SolidFill, Green);
     FillPoly(5, v2lehti);
     FillPoly(5, o2lehti);
     SetViewPort(0, 0, GetMaxX, GetMaxY, ClipOn);
end;

procedure isokaksoislehti(x, y:integer);
begin
     SetViewPort(x, y, x+20, y+20, ClipOn);
     SetColor(DarkGray);
     SetFillStyle(SolidFill, Green);
     FillPoly(5, isov2lehti);
     FillPoly(5, isoo2lehti);
     SetViewPort(0, 0, GetMaxX, GetMaxY, ClipOn);
end;

procedure okielo(x, y:integer);
begin
     SetViewPort(x, y, x+20, y+20, ClipOn);
     SetColor(White);
     SetFillStyle(SolidFill, White);
     FillPoly(5, om1);
     FillPoly(5, om2);
     FillPoly(5, om3);
     SetViewPort(0, 0, GetMaxX, GetMaxY, ClipOn);
end;

procedure omarjat(x, y:integer);
begin
     SetViewPort(x, y, x+20, y+20, ClipOn);
     SetColor(Red);
     SetFillStyle(SolidFill, Red);
     FillEllipse(19,11,1,1);
     FillEllipse(15,14,1,1);
     FillEllipse(12,18,1,1);
     SetViewPort(0, 0, GetMaxX, GetMaxY, ClipOn);
end;

procedure vkielo(x, y:integer);
begin
     SetViewPort(x, y, x+20, y+20, ClipOn);
     SetColor(White);
     SetFillStyle(SolidFill, White);
     FillPoly(5, vm1);
     FillPoly(5, vm2);
     FillPoly(5, vm3);
     SetViewPort(0, 0, GetMaxX, GetMaxY, ClipOn);
end;

procedure vmarjat(x, y:integer);
begin
     SetViewPort(x, y, x+20, y+20, ClipOn);
     SetColor(Red);
     SetFillStyle(SolidFill, Red);
     FillEllipse(1,11,1,1);
     FillEllipse(5,14,1,1);
     FillEllipse(8,18,1,1);
     SetViewPort(0, 0, GetMaxX, GetMaxY, ClipOn);
end;
procedure vvarsi(x, y: integer);
begin
     SetViewPort(x, y, x+20, y+20, ClipOn);
     SetColor(Green);
     Ellipse(0, 20, 0, 90, 10, 10);
     SetViewPort(0, 0, GetMaxX, GetMaxY, ClipOn);
end;

procedure svarsi(x, y: integer);
begin
     SetViewPort(x, y, x+20, y+20, ClipOn);
     SetColor(Green);
     Line(10, 0, 10, 20);
     SetViewPort(0, 0, GetMaxX, GetMaxY, ClipOn);
end;

procedure ovarsi(x, y: integer);
begin
     SetViewPort(x, y, x+20, y+20, ClipOn);
     SetColor(Green);
     Ellipse(20, 20, 90, 180, 10, 10);
     SetViewPort(0, 0, GetMaxX, GetMaxY, ClipOn);
end;

procedure havu(x, y: integer);
begin
     SetViewPort(x, y, x+20, y+20, ClipOn);
     SetColor(Green);
     Line(10, 0, 10, 20);
     Line(10,20,20,10);
     Line(10,20,0,10);
     Line(10,13,18,7);
     Line(10,13,2,7);
     Line(10,9,14,2);
     Line(10,9,6,2);
     SetViewPort(0, 0, GetMaxX, GetMaxY, ClipOn);
end;


procedure snuppu(x, y:integer; vari:word);
begin
     SetViewPort(x, y, x+20, y+20, ClipOn);
     SetColor(white);
     SetFillStyle(SolidFill, vari);
     FillEllipse(10,10,3,6);
     SetViewPort(0, 0, GetMaxX, GetMaxY, ClipOn);
end;

procedure onuppu(x, y:integer; vari:word);
begin
     SetViewPort(x, y, x+20, y+20, ClipOn);
     SetColor(white);
     SetFillStyle(SolidFill, vari);
     FillEllipse(10,10,6,3);
     SetViewPort(0, 0, GetMaxX, GetMaxY, ClipOn);
end;

procedure vnuppu(x, y:integer; vari:word);
begin
     SetViewPort(x, y, x+20, y+20, ClipOn);
     SetColor(white);
     SetFillStyle(SolidFill, vari);
     FillEllipse(10,10,6,3);
     SetViewPort(0, 0, GetMaxX, GetMaxY, ClipOn);
end;

procedure kukka(x, y:integer; vari:word);
begin
     SetViewPort(x, y, x+20, y+20, ClipOn);
     SetColor(white);
     SetFillStyle(SolidFill, vari);
     FillEllipse(10,5,3,5);
     FillEllipse(15,10,5,3);
     FillEllipse(10,15,3,5);
     FillEllipse(5,10,5,3);
     SetViewPort(0, 0, GetMaxX, GetMaxY, ClipOn);
end;

procedure asetavari(m,n:integer);
var nro:integer;
begin
     nro:=random(9);
     case nro of
          1: kuvat[m,n].vari:=blue;
          2: kuvat[m,n].vari:=cyan;
          3: kuvat[m,n].vari:=red;
          4: kuvat[m,n].vari:=magenta;
          5: kuvat[m,n].vari:=lightblue;
          6: kuvat[m,n].vari:=lightred;
          7: kuvat[m,n].vari:=lightcyan;
          8: kuvat[m,n].vari:=lightmagenta;
          0: kuvat[m,n].vari:=yellow;
     end;
end;

procedure arvosiemenet(lkm:integer);
 var m,n,p,i:integer;
 begin
      for i:=1 to lkm do
          begin
               m:=random(23)+1;
               n:=random(23)+1;
               if kuvat[m,n].tyyppi=0 then
               begin
                    p:=random(4);
                    case p of
                    0: begin
                        kaksoislehti(80+(m-1)*20,(n-1)*20);
                        kuvat[m,n].tyyppi:=10;
                   end;
                   1: begin
                       vvarsi(80+(m-1)*20,(n-1)*20);
                       kuvat[m,n].tyyppi:=1;
                  end;
                  2: begin
                        ovarsi(80+(m-1)*20,(n-1)*20);
                        kuvat[m,n].tyyppi:=2;
                   end;
                   3: begin
                       svarsi(80+(m-1)*20,(n-1)*20);
                       kuvat[m,n].tyyppi:=8;
                       end;
                   end;  {case}
               end;
          end;
 end;

procedure piirra(m,n:integer);
var nro,t:integer;
begin
     t:=kuvat[m,n].tyyppi;
     case t of
          0: begin
                  arvosiemenet(1);
          end;
          1: begin               {vvarsi}
             nro:=random(2);
             case nro of
                  0: begin      {varsi->vlehti}
                     if (m>1) then
                        begin
                        vlehti(80+(m-2)*20,(n-1)*20);
                        kuvat[m-1,n].tyyppi:=3;
                        end;
                     end;

                  1: begin
                     if (m>1) then   {vvarsi->vnuppu}
                        begin
                             asetavari(m-1,n);
                             vnuppu(80+(m-2)*20,(n-1)*20,kuvat[m-1,n].vari);
                             kuvat[m-1,n].tyyppi:=5;
                        end;
                     end;
             end; {sis. case}
          end;
          2: begin               {ovarsi}
             nro:=random(2);
             case nro of
                  0: begin      {ovarsi->olehti}
                     if (m<24) then
                        begin
                        olehti(80+m*20,(n-1)*20);
                        kuvat[m+1,n].tyyppi:=3;
                        end;
                     end;

                  1: begin
                     if (m<24) then   {ovarsi->onuppu}
                        begin
                             asetavari(m+1,n);
                             vnuppu(80+m*20,(n-1)*20,kuvat[m+1,n].vari);
                             kuvat[m+1,n].tyyppi:=5;
                        end;
                     end;
                  end; {sis. case}
          end;

          5,6,9: begin      {vnuppu, onuppu, snuppu -> kukka}
                    kukka(80+(m-1)*20,(n-1)*20, kuvat[m,n].vari);
                    kuvat[m,n].tyyppi:=7;
                end;

          7: begin            {kukka -> kaksoislehti}
                  SetFillStyle(SolidFill,Black);
                  Bar(80+(m-1)*20,(n-1)*20,80+m*20,n*20);
                  kaksoislehti(80+(m-1)*20,(n-1)*20);
                  kuvat[m,n].tyyppi:=10;
          end;

          8: begin  {svarsi}
                    nro:=random(7);
                    case nro of
                         0: begin          {svarsi->vvarsi}
                                 vvarsi(80+(m-1)*20,(n-1)*20);
                                 kuvat[m,n].tyyppi:=30;
                         end;
                         1: begin       {svarsi->ovarsi}
                                  ovarsi(80+(m-1)*20,(n-1)*20);
                                  kuvat[m,n].tyyppi:=31;
                         end;
                         2: begin       {svarsi->snuppu}
                                 if (n>1) then begin
                                    asetavari(m,n-1);
                                    snuppu(80+(m-1)*20,(n-2)*20,kuvat[m,n-1].vari);
                                    kuvat[m,n-1].tyyppi:=9;
                                 end;
                         end;
                         3: begin      {svarsi->2lehti}
                                 if (n>1) then begin
                                    kaksoislehti(80+(m-1)*20,(n-2)*20);
                                    kuvat[m,n-1].tyyppi:=10;
                                 end;
                         end;
                         4: begin    {svarsi->vkielovarsi}
                            if (n>1) then begin
                               vvarsi(80+(m-1)*20,(n-2)*20);
                               kuvat[m,n-1].tyyppi:=16;
                               isokaksoislehti(80+(m-1)*20,(n-1)*20);
                               kuvat[m,n].tyyppi:=11;
                            end;
                         end;
                         5: begin    {svarsi->okielovarsi}
                            if (n>1) then begin
                               ovarsi(80+(m-1)*20,(n-2)*20);
                               kuvat[m,n-1].tyyppi:=17;
                               isokaksoislehti(80+(m-1)*20,(n-1)*20);
                               kuvat[m,n].tyyppi:=11;
                            end;
                         end;
                         6: begin   {svarsi->havu}
                                 havu(80+(m-1)*20,(n-1)*20);
                                 kuvat[m,n].tyyppi:=18;
                         end;
                    end; {sisempi case}
          end;

          10,11: begin     {kaksoislehti}
              nro:=random(5);
              case nro of
                   0: begin   {2lehti->vvarsi}
                           vvarsi(80+(m-1)*20,(n-1)*20);
                           kuvat[m,n].tyyppi:=1;
                   end;
                   1: begin   {2lehti->ovarsi}
                           ovarsi(80+(m-1)*20,(n-1)*20);
                           kuvat[m,n].tyyppi:=2;
                   end;
                   2: begin   {2lehti->svarsi}
                           svarsi(80+(m-1)*20,(n-1)*20);
                           kuvat[m,n].tyyppi:=8;
                   end;
                   3: begin   {2lehti->iso2lehti}
                           if (t=10) then begin
                              isokaksoislehti(80+(m-1)*20,(n-1)*20);
                              kuvat[m,n].tyyppi:=11;
                           end;
                      end;
                   end; {sis. case}
              end;
              12: begin      {vkielo->vmarjat}
                       vmarjat(80+(m-1)*20,(n-1)*20);
                       kuvat[m,n].tyyppi:=14;
              end;
              13: begin      {okielo->omarjat}
                       omarjat(80+(m-1)*20,(n-1)*20);
                       kuvat[m,n].tyyppi:=15;
              end;
              16: begin       {vkielovarsi->vkielo}
                       vkielo(80+(m-1)*20,(n-1)*20);
                       kuvat[m,n].tyyppi:=12;
              end;
              17: begin       {okielovarsi->okielo}
                       okielo(80+(m-1)*20,(n-1)*20);
                       kuvat[m,n].tyyppi:=13;
              end;

              30: begin      {vvarsi ja svarsi}
                       nro:=random(2);
                       case nro of
                       0: begin      {varsi->vlehti}
                          if (m>1) then
                          begin
                               vlehti(80+(m-2)*20,(n-1)*20);
                               kuvat[m-1,n].tyyppi:=3;
                          end;
                        end;

                        1: begin
                           if (m>1) then   {vvarsi->vnuppu}
                           begin
                              asetavari(m-1,n);
                              vnuppu(80+(m-2)*20,(n-1)*20,kuvat[m-1,n].vari);
                              kuvat[m-1,n].tyyppi:=5;
                           end;
                           end;
                        end; {sis. case}
                       nro:=random(6);
                       case nro of
                         0: begin          {svarsi->vvarsi}
                                 vvarsi(80+(m-1)*20,(n-1)*20);
                                 kuvat[m,n].tyyppi:=30;
                         end;
                         1: begin       {svarsi->ovarsi}
                                  ovarsi(80+(m-1)*20,(n-1)*20);
                                  kuvat[m,n].tyyppi:=31;
                         end;
                         2: begin       {svarsi->snuppu}
                                 if (n>1) then begin
                                    asetavari(m,n-1);
                                    snuppu(80+(m-1)*20,(n-2)*20,kuvat[m,n-1].vari);
                                    kuvat[m,n-1].tyyppi:=9;
                                 end;
                         end;
                         3: begin      {svarsi->2lehti}
                                 if (n>1) then begin
                                    kaksoislehti(80+(m-1)*20,(n-2)*20);
                                    kuvat[m,n-1].tyyppi:=10;
                                 end;
                         end;
                         4: begin    {svarsi->vkielovarsi}
                            if (n>1) then begin
                               vvarsi(80+(m-1)*20,(n-2)*20);
                               kuvat[m,n-1].tyyppi:=16;
                               isokaksoislehti(80+(m-1)*20,(n-1)*20);
                               kuvat[m,n].tyyppi:=11;
                            end;
                         end;
                         5: begin    {svarsi->okielovarsi}
                            if (n>1) then begin
                               ovarsi(80+(m-1)*20,(n-2)*20);
                               kuvat[m,n-1].tyyppi:=17;
                               isokaksoislehti(80+(m-1)*20,(n-1)*20);
                               kuvat[m,n].tyyppi:=11;
                            end;
                         end;
                    end; {sisempi case}
          end;
          31: begin          {ovarsi ja svarsi}
                   nro:=random(2);
                   case nro of
                   0: begin      {ovarsi->olehti}
                     if (m<24) then
                        begin
                        olehti(80+m*20,(n-1)*20);
                        kuvat[m+1,n].tyyppi:=3;
                        end;
                     end;

                  1: begin
                     if (m<24) then   {ovarsi->onuppu}
                        begin
                             asetavari(m+1,n);
                             vnuppu(80+m*20,(n-1)*20,kuvat[m+1,n].vari);
                             kuvat[m+1,n].tyyppi:=5;
                        end;
                     end;
                  end; {sis. case}
                  nro:=random(6);
                    case nro of
                         0: begin          {svarsi->vvarsi}
                                 vvarsi(80+(m-1)*20,(n-1)*20);
                                 kuvat[m,n].tyyppi:=30;
                         end;
                         1: begin       {svarsi->ovarsi}
                                  ovarsi(80+(m-1)*20,(n-1)*20);
                                  kuvat[m,n].tyyppi:=31;
                         end;
                         2: begin       {svarsi->snuppu}
                                 if (n>1) then begin
                                    asetavari(m,n-1);
                                    snuppu(80+(m-1)*20,(n-2)*20,kuvat[m,n-1].vari);
                                    kuvat[m,n-1].tyyppi:=9;
                                 end;
                         end;
                         3: begin      {svarsi->2lehti}
                                 if (n>1) then begin
                                    kaksoislehti(80+(m-1)*20,(n-2)*20);
                                    kuvat[m,n-1].tyyppi:=10;
                                 end;
                         end;
                         4: begin    {svarsi->vkielovarsi}
                            if (n>1) then begin
                               vvarsi(80+(m-1)*20,(n-2)*20);
                               kuvat[m,n-1].tyyppi:=16;
                               isokaksoislehti(80+(m-1)*20,(n-1)*20);
                               kuvat[m,n].tyyppi:=11;
                            end;
                         end;
                         5: begin    {svarsi->okielovarsi}
                            if (n>1) then begin
                               ovarsi(80+(m-1)*20,(n-2)*20);
                               kuvat[m,n-1].tyyppi:=17;
                               isokaksoislehti(80+(m-1)*20,(n-1)*20);
                               kuvat[m,n].tyyppi:=11;
                            end;
                         end;
                    end; {sisempi case}
          end;

     end;     {ulompi case}
end;




{************************************************************************}
{* paaohjelma                                                           *}
{************************************************************************}
begin
     Alusta;
     randomize;
     arvosiemenet(10);
     repeat
         begin
              i:=random(23)+1;
              j:=random(23)+1;
              piirra(i,j);
              delay(100);
         end;
     until keypressed;
     readln;
     CloseGraph;
     readln;
end.
