home *** CD-ROM | disk | FTP | other *** search
/ Shareware Overload / ShartewareOverload.cdr / windows / winsrc.zip / LSYS.C < prev    next >
Text File  |  1990-12-13  |  13KB  |  582 lines

  1. #include <stdio.h>
  2. #include <stdlib.h>
  3. #include <string.h>
  4. #include <math.h>
  5. #include "fractint.h"
  6.  
  7. extern int xdots,ydots;
  8. extern int colors;
  9. extern char LFileName[];
  10. extern char LName[];
  11. extern double param[];
  12.  
  13. int Lsystem();
  14. extern void draw_line (int X1, int Y1, int X2, int Y2, int color);
  15. extern int thinking(int,char *);
  16.  
  17. static float getnumber(char far **str);
  18. static char far *findsize(char far *command,char far **rules,char depth);
  19. static void findscale(char far *command, char far **rules, char depth);
  20. static char far *drawLSys(char far *command, char far **rules, char depth);
  21. static int  readLSystemFile(char *str);
  22. static void free_rules_mem();
  23. static int  save_rule(char *rule,char far **saveptr);
  24.  
  25. static float aspect; /* aspect ratio of each pixel, ysize/xsize */
  26.  
  27. /* Some notes to Adrian from PB, made when I integrated with v15:
  28.      printfs changed to work with new user interface
  29.      bug at end of readLSystemFile, the line which said rulind=0 fixed
  30.        to say *rulind=0
  31.      the calloc was not worthwhile, it was just for a 54 byte area, cheaper
  32.        to keep it as a static;    but there was a static 201 char buffer I
  33.        changed to not be static
  34.      use of strdup was a nono, caused problems running out of space cause
  35.        the memory allocated each time was never freed; I've changed to
  36.        use far memory and to free when done
  37.    */
  38.  
  39. /* My local globals !! If global space is scarce, something can be done
  40.    with these */
  41.  
  42. static float far sins[50];
  43. static float far coss[50];
  44. static char maxangle,curcolor;
  45. static float xpos,ypos,size,realangle;
  46. static char counter,angle,reverse;
  47. static float Xmin,Xmax,Ymin,Ymax;
  48.  
  49.  
  50. static float getnumber(char far **str)
  51. {
  52.    char numstr[30];
  53.    float ret;
  54.    int i,root,inverse;
  55.  
  56.    root=0;
  57.    inverse=0;
  58.    strcpy(numstr,"");
  59.    (*str)++;
  60.    switch (**str)
  61.    {
  62.    case 'q':
  63.       root=1;
  64.       (*str)++;
  65.       break;
  66.    case 'i':
  67.       inverse=1;
  68.       (*str)++;
  69.       break;
  70.    }
  71.    switch (**str)
  72.    {
  73.    case 'q':
  74.       root=1;
  75.       (*str)++;
  76.       break;
  77.    case 'i':
  78.       inverse=1;
  79.       (*str)++;
  80.       break;
  81.    }
  82.    i=0;
  83.    while (**str<='9' && **str>='0' || **str=='.')
  84.    {
  85.       numstr[i++]=**str;
  86.       (*str)++;
  87.    }
  88.    (*str)--;
  89.    numstr[i]=0;
  90.    ret=atof(numstr);
  91.    if (root) ret=sqrt(ret);
  92.    if (inverse) ret=1/ret;
  93.    return ret;
  94. }
  95.  
  96.  
  97. static char far *findsize(char far *command,char far **rules,char depth)
  98. {
  99.    char far **rulind,tran;
  100.  
  101.    while ((*command)&&(*command!=']'))
  102.    {
  103.       if (!(counter++))
  104.       {
  105.      /* let user know we're not dead */
  106.      if (thinking(1,"L-System thinking (higher orders take longer)"))
  107.      {
  108.         counter--;
  109.         return NULL;
  110.      }
  111.       }
  112.       tran=0;
  113.       if (depth)
  114.       {
  115.      for(rulind=rules;*rulind;rulind++)
  116.         if (**rulind==*command)
  117.         {
  118.            tran=1;
  119.            findsize((*rulind)+1,rules,depth-1);
  120.         }
  121.       }
  122.       if (!depth || !tran)
  123.      switch (*command)
  124.      {
  125.      case '+':
  126.         if (reverse)
  127.         {
  128.            if (++angle==maxangle)
  129.           angle=0;
  130.         }
  131.         else
  132.         {
  133.            if (angle)
  134.           angle--;
  135.            else
  136.           angle=maxangle-1;
  137.         }
  138.         break;
  139.      case '-':
  140.         if (reverse)
  141.         {
  142.            if (angle)
  143.           angle--;
  144.            else angle=maxangle-1;
  145.         }
  146.         else
  147.         {
  148.            if (++angle==maxangle)
  149.           angle=0;
  150.         }
  151.         break;
  152.      case '/':
  153.         if (reverse)
  154.         {
  155.          realangle-=getnumber(&command);
  156.          while (realangle<0) realangle+=360;
  157.         }
  158.         else
  159.         {
  160.          realangle+=getnumber(&command);
  161.          while (realangle>=360) realangle-=360;
  162.         }
  163.         break;
  164.      case '\\':
  165.         if (reverse)
  166.         {
  167.          realangle+=getnumber(&command);
  168.          while (realangle>=360) realangle-=360;
  169.         }
  170.         else
  171.         {
  172.         realangle-=getnumber(&command);
  173.         while (realangle<0) realangle+=360;
  174.         }
  175.         break;
  176.      case '@':
  177.         size*=getnumber(&command);
  178.         break;
  179.      case '|':
  180.         angle+=maxangle/2;
  181.         angle%=maxangle;
  182.         break;
  183.      case '!':
  184.         reverse=!reverse;
  185.         break;
  186.      case 'd':
  187.      case 'm':
  188.         xpos+=size*aspect*cos(realangle*PI/180);
  189.         ypos+=size*sin(realangle*PI/180);
  190.         if (xpos>Xmax) Xmax=xpos;
  191.         if (ypos>Ymax) Ymax=ypos;
  192.         if (xpos<Xmin) Xmin=xpos;
  193.         if (ypos<Ymin) Ymin=ypos;
  194.         break;
  195.      case 'g':
  196.      case 'f':
  197.         xpos+=size*coss[angle];
  198.         ypos+=size*sins[angle];
  199.         if (xpos>Xmax) Xmax=xpos;
  200.         if (ypos>Ymax) Ymax=ypos;
  201.         if (xpos<Xmin) Xmin=xpos;
  202.         if (ypos<Ymin) Ymin=ypos;
  203.         break;
  204.      case '[':
  205.         {
  206.            char saveang,saverev;
  207.            float savesize,saverang,savex,savey;
  208.  
  209.            saveang=angle;
  210.            saverev=reverse;
  211.            savesize=size;
  212.            saverang=realangle;
  213.            savex=xpos;
  214.            savey=ypos;
  215.            command=findsize(command+1,rules,depth);
  216.            angle=saveang;
  217.            reverse=saverev;
  218.            size=savesize;
  219.            realangle=saverang;
  220.            xpos=savex;
  221.            ypos=savey;
  222.         }
  223.         break;
  224.      }
  225.       command++;
  226.    }
  227.    return command;
  228. }
  229.  
  230.  
  231. static void findscale(char far *command, char far **rules, char depth)
  232. {
  233.    float horiz,vert;
  234.    int i;
  235.    aspect=SCREENASPECT*xdots/ydots;
  236.    for(i=0;i<maxangle;i++)
  237.    {
  238.       sins[i]=sin(2*i*PI/maxangle);
  239.       coss[i]=aspect*cos(2*i*PI/maxangle);
  240.    }
  241.    xpos=ypos=Xmin=Xmax=Ymax=Ymin=angle=reverse=realangle=counter=0;
  242.    size=1;
  243.    findsize(command,rules,depth);
  244.    if (Xmax==Xmin)
  245.       horiz=1E37;
  246.    else
  247.       horiz=(xdots-10)/(Xmax-Xmin);
  248.    if (Ymax==Ymin)
  249.       vert=1E37;
  250.    else
  251.       vert=(ydots-6)/(Ymax-Ymin);
  252.    size=vert<horiz?vert:horiz;
  253.    if (horiz==1E37)
  254.       xpos=xdots/2;
  255.    else
  256.       xpos=-Xmin*(size)+5+((xdots-10)-(size)*(Xmax-Xmin))/2;
  257.    if (vert==1E37)
  258.       ypos=ydots/2;
  259.    else
  260.       ypos=-Ymin*(size)+3+((ydots-6)-(size)*(Ymax-Ymin))/2;
  261.    thinking(0,NULL); /* erase thinking message if any */
  262. }
  263.  
  264. static char far *drawLSys(char far *command,char far **rules,char depth)
  265. {
  266.    char far **rulind,tran;
  267.    int lastx,lasty;
  268.  
  269.    while (*command&&*command!=']')
  270.    {
  271.       if (!(counter++))
  272.       {
  273.      if (check_key())
  274.      {
  275.         counter--;
  276.         return NULL;
  277.      }
  278.       }
  279.       tran=0;
  280.       if (depth)
  281.       {
  282.      for(rulind=rules;*rulind;rulind++)
  283.         if (**rulind==*command)
  284.         {
  285.            tran=1;
  286.            drawLSys((*rulind)+1,rules,depth-1);
  287.         }
  288.       }
  289.       if (!depth||!tran)
  290.      switch (*command)
  291.      {
  292.      case '+':
  293.         if (reverse)
  294.         {
  295.            if (++angle==maxangle) angle=0;
  296.         }
  297.         else
  298.         {
  299.            if (angle) angle--;
  300.            else angle=maxangle-1;
  301.         }
  302.         break;
  303.      case '-':
  304.         if (reverse)
  305.         {
  306.            if (angle) angle--;
  307.            else angle=maxangle-1;
  308.         }
  309.         else
  310.         {
  311.            if (++angle==maxangle) angle=0;
  312.         }
  313.         break;
  314.      case '/':
  315.         if (reverse)
  316.         {
  317.          realangle-=getnumber(&command);
  318.          while (realangle<0) realangle+=360;
  319.         }
  320.         else
  321.         {
  322.          realangle+=getnumber(&command);
  323.          while (realangle>=360) realangle-=360;
  324.         }
  325.         break;
  326.      case '\\':
  327.         if (reverse)
  328.         {
  329.          realangle+=getnumber(&command);
  330.          while (realangle>=360) realangle-=360;
  331.         }
  332.         else
  333.         {
  334.         realangle-=getnumber(&command);
  335.         while (realangle<0) realangle+=360;
  336.         }
  337.         break;
  338.      case '@':
  339.         size *= getnumber(&command);
  340.         break;
  341.      case '|':
  342.         angle+=maxangle/2;
  343.         angle%=maxangle;
  344.         break;
  345.      case '!':
  346.         reverse=!reverse;
  347.         break;
  348.      case 'd':
  349.         lastx=xpos;
  350.         lasty=ypos;
  351.         xpos+=size*aspect*cos(realangle*PI/180);
  352.         ypos+=size*sin(realangle*PI/180);
  353.         draw_line(lastx,lasty,xpos,ypos,curcolor);
  354.         break;
  355.      case 'm':
  356.         xpos+=size*aspect*cos(realangle*PI/180);
  357.         ypos+=size*sin(realangle*PI/180);
  358.         break;
  359.      case 'g':
  360.         xpos+=size*coss[angle];
  361.         ypos+=size*sins[angle];
  362.         break;
  363.      case 'f':
  364.         lastx=xpos;
  365.         lasty=ypos;
  366.         xpos+=size*coss[angle];
  367.         ypos+=size*sins[angle];
  368.         draw_line(lastx,lasty,xpos,ypos,curcolor);
  369.         break;
  370.      case '[':
  371.         {
  372.            char saveang,saverev,savecolor;
  373.            float savesize,saverang,savex,savey;
  374.  
  375.            saveang=angle;
  376.            saverev=reverse;
  377.            savesize=size;
  378.            saverang=realangle;
  379.            savex=xpos;
  380.            savey=ypos;
  381.            savecolor=curcolor;
  382.            command=drawLSys(command+1,rules,depth);
  383.            angle=saveang;
  384.            reverse=saverev;
  385.            size=savesize;
  386.            realangle=saverang;
  387.            xpos=savex;
  388.            ypos=savey;
  389.            curcolor=savecolor;
  390.         }
  391.         break;
  392.      case 'c':
  393.         curcolor=((int)getnumber(&command))%colors;
  394.         break;
  395.      case '>':
  396.         curcolor-=getnumber(&command);
  397.         if ((curcolor &= colors-1) == 0) curcolor = colors-1;
  398.         break;
  399.      case '<':
  400.         curcolor+=getnumber(&command);
  401.         if ((curcolor &= colors-1) == 0) curcolor = 1;
  402.         break;
  403.      }
  404.       command++;
  405.    }
  406.    return command;
  407. }
  408.  
  409.  
  410. #define MAXRULES 27 /* this limits rules to 25 */
  411. static char far *ruleptrs[MAXRULES];
  412.  
  413. static int readLSystemFile(char *str)
  414. {
  415.    int c;
  416.    int scanrtn;
  417.    char far **rulind;
  418.    int err=0;
  419.    int linenum=0,check=0;
  420.    char inline[161],fixed[161],*word;
  421.    FILE *infile;
  422.    char msgbuf[481]; /* enough for 6 full lines */
  423.    char StrBuff[201];
  424.  
  425.    maxangle=0;
  426.    for(linenum=0;linenum<MAXRULES;++linenum) ruleptrs[linenum]=NULL;
  427.    if(infile = fopen(LFileName, "rt"))
  428.    {  /* BDT use variable files */
  429.       fscanf(infile,"%200[ \n\t]",StrBuff);
  430.       while(fscanf(infile, "%200[^ \n\t{]", StrBuff) != EOF)
  431.       {
  432.      if (!stricmp(StrBuff,str))
  433.      {
  434.         maxangle=-1;
  435.         break;
  436.      }
  437.      /* skip to next lsys */
  438.      while((c = fgetc(infile)) != EOF)
  439.         if(c == '}')
  440.            break;
  441.      /* skip white space */
  442.      while((scanrtn=fscanf(infile,"%200[ \n\t]", StrBuff)) != EOF)
  443.         if(scanrtn == 0)
  444.            break;
  445.       }
  446.    }
  447.    if (!maxangle){
  448.      sprintf(inline,"L-System \"%s\" not found.\n",str);
  449.      stopmsg(0,inline);
  450.      return -1;
  451.    }
  452.  
  453.    rulind=&ruleptrs[1];
  454.    msgbuf[0]=0;
  455.  
  456.    while(fgets(inline,160,infile))          /* Max line length 160 chars */
  457.    {
  458.       linenum++;
  459.       strlwr(inline);
  460.  
  461.       word=strtok(inline," =\011\n");
  462.  
  463.       if (!word || !strcmp(word,";;"));
  464.       else if (!strcmp(word,"axiom"))
  465.       {
  466.      save_rule(strtok(NULL," \011\n"),&ruleptrs[0]);
  467.      check=1;
  468.       }
  469.       else if (!strcmp(word,"angle"))
  470.       {
  471.      maxangle=atoi(strtok(NULL," \011\n"));
  472.      check=1;
  473.       }
  474.       else if (!strcmp(word,"}"))
  475.      break;
  476.       else if (strlen(word)==1)
  477.       {
  478.      strcat(strcpy(fixed,word),strtok(NULL," \011\n"));
  479.      save_rule(fixed,rulind++);
  480.      check=1;
  481.       }
  482.       else
  483.      if (err<6)
  484.      {
  485.         sprintf(&msgbuf[strlen(msgbuf)],
  486.             "Syntax error line %d: %s\n",linenum,word);
  487.         ++err;
  488.      }
  489.       if (check)
  490.       {
  491.      check=0;
  492.      if(word=strtok(NULL," \011\n"))
  493.         if (err<6)
  494.         {
  495.            sprintf(&msgbuf[strlen(msgbuf)],
  496.                "Extra text after command line %d: %s\n",linenum,word);
  497.            ++err;
  498.         }
  499.       }
  500.  
  501.    }
  502.    fclose(infile);
  503.    if (!ruleptrs[0] && err<6)
  504.    {
  505.       strcat(msgbuf,"Error:  no axiom\n");
  506.       ++err;
  507.    }
  508.    if ((maxangle<3||maxangle>50) && err<6)
  509.    {
  510.       strcat(msgbuf,"Error:  illegal or missing angle\n");
  511.       ++err;
  512.    }
  513.    if (err)
  514.    {
  515.       msgbuf[strlen(msgbuf)-1]=0; /* strip trailing \n */
  516.       stopmsg(0,msgbuf);
  517.       return -1;
  518.    }
  519.    *rulind=NULL;
  520.    return 0;
  521. }
  522.  
  523.  
  524. static char loaded=0;
  525.  
  526. int Lsystem()
  527. {
  528.    int order;
  529.    if ((!loaded)&&LLoad()) return (-1);
  530.    order=param[0];
  531.    if (order<=0) order=0;
  532.    findscale(ruleptrs[0],&ruleptrs[1],order);
  533.    realangle=angle=reverse=0;
  534.  
  535. /* !! HOW ABOUT A BETTER WAY OF PICKING THE DEFAULT DRAWING COLOR */
  536.  
  537.    if ((curcolor=15) > colors) curcolor=colors-1;
  538.  
  539.    drawLSys(ruleptrs[0],&ruleptrs[1],order);
  540.    free_rules_mem();
  541.    loaded=0;
  542.    return 0;
  543. }
  544.  
  545.  
  546. int LLoad()
  547. {
  548.    char i;
  549.    if (readLSystemFile(LName)) { /* error occurred */
  550.       free_rules_mem();
  551.       loaded=0;
  552.       return -1;
  553.    }
  554.  
  555.    for(i=0;i<maxangle;i++)
  556.    {
  557.       sins[i]=sin(2*i*PI/maxangle);
  558.       coss[i]=aspect*cos(2*i*PI/maxangle);
  559.    }
  560.    loaded=1;
  561.    return 0;
  562. }
  563.  
  564. static void free_rules_mem()
  565. {
  566.    int i;
  567.    for(i=0;i<MAXRULES;++i)
  568.       if(ruleptrs[i]) farmemfree(ruleptrs[i]);
  569. }
  570.  
  571. static int save_rule(char *rule,char far **saveptr)
  572. {
  573.    int i;
  574.    char far *tmpfar;
  575.    i=strlen(rule)+1;
  576.    if((tmpfar=farmemalloc((long)i))==NULL) return -1;
  577.    *saveptr=tmpfar;
  578.    while(--i>=0) *(tmpfar++)=*(rule++);
  579.    return 0;
  580. }
  581.  
  582.