home *** CD-ROM | disk | FTP | other *** search
/ PC World Komputer 1995 November / PCWK1195.iso / inne / dos / fraktale / frasr192.exe / LSYS.C < prev    next >
Encoding:
C/C++ Source or Header  |  1995-03-18  |  25.5 KB  |  965 lines

  1. #include <stdio.h>
  2. #include <stdlib.h>
  3. #include <string.h>
  4. #include <math.h>
  5. #ifdef __TURBOC__
  6. #include <alloc.h>
  7. #else
  8. #include <malloc.h>
  9. #endif
  10. #include "fractint.h"
  11. #include "prototyp.h"
  12. #include "lsys.h"
  13.  
  14. struct lsys_cmd {
  15.     void (*f)(struct lsys_turtlestatei *);
  16.     long n;
  17.     char ch;
  18. };
  19.  
  20. static int _fastcall readLSystemFile(char *);
  21. static void _fastcall free_rules_mem(void);
  22. static int _fastcall save_rule(char *,char far **);
  23. static void free_lcmds(void);
  24. static struct lsys_cmd far * _fastcall findsize(struct lsys_cmd far *,struct lsys_turtlestatei *, struct lsys_cmd far **,int);
  25. static struct lsys_cmd far * drawLSysI(struct lsys_cmd far *command,struct lsys_turtlestatei *ts, struct lsys_cmd far **rules,int depth);
  26. static int lsysi_findscale(struct lsys_cmd far *command, struct lsys_turtlestatei *ts, struct lsys_cmd far **rules, int depth);
  27. static struct lsys_cmd far *LSysISizeTransform(char far *s, struct lsys_turtlestatei *ts);
  28. static struct lsys_cmd far *LSysIDrawTransform(char far *s, struct lsys_turtlestatei *ts);
  29. static void _fastcall lsysi_dosincos(void);
  30.  
  31. static void lsysi_doslash(struct lsys_turtlestatei *cmd);
  32. static void lsysi_dobslash(struct lsys_turtlestatei *cmd);
  33. static void lsysi_doat(struct lsys_turtlestatei *cmd);
  34. static void lsysi_dopipe(struct lsys_turtlestatei *cmd);
  35. static void lsysi_dosizedm(struct lsys_turtlestatei *cmd);
  36. static void lsysi_dosizegf(struct lsys_turtlestatei *cmd);
  37. static void lsysi_dodrawd(struct lsys_turtlestatei *cmd);
  38. static void lsysi_dodrawm(struct lsys_turtlestatei *cmd);
  39. static void lsysi_dodrawg(struct lsys_turtlestatei *cmd);
  40. static void lsysi_dodrawf(struct lsys_turtlestatei *cmd);
  41. static void lsysi_dodrawc(struct lsys_turtlestatei *cmd);
  42. static void lsysi_dodrawgt(struct lsys_turtlestatei *cmd);
  43. static void lsysi_dodrawlt(struct lsys_turtlestatei *cmd);
  44.  
  45. /* Some notes to Adrian from PB, made when I integrated with v15:
  46.      printfs changed to work with new user interface
  47.      bug at end of readLSystemFile, the line which said rulind=0 fixed
  48.        to say *rulind=0
  49.      the calloc was not worthwhile, it was just for a 54 byte area, cheaper
  50.        to keep it as a static;    but there was a static 201 char buffer I
  51.        changed to not be static
  52.      use of strdup was a nono, caused problems running out of space cause
  53.        the memory allocated each time was never freed; I've changed to
  54.        use far memory and to free when done
  55.    */
  56.  
  57. #define sins ((long *)(boxy))
  58. #define coss (((long *)(boxy)+50)) /* 50 after the start of sins */
  59. static char far *ruleptrs[MAXRULES];
  60. static struct lsys_cmd far *rules2[MAXRULES];
  61. char maxangle;
  62. static char loaded=0;
  63.  
  64.  
  65. int _fastcall ispow2(int n)
  66. {
  67.   return (n == (n & -n));
  68. }
  69.  
  70. LDBL _fastcall getnumber(char far **str)
  71. {
  72.    char numstr[30];
  73.    LDBL ret;
  74.    int i,root,inverse;
  75.  
  76.    root=0;
  77.    inverse=0;
  78.    strcpy(numstr,"");
  79.    (*str)++;
  80.    switch (**str)
  81.    {
  82.    case 'q':
  83.       root=1;
  84.       (*str)++;
  85.       break;
  86.    case 'i':
  87.       inverse=1;
  88.       (*str)++;
  89.       break;
  90.    }
  91.    switch (**str)
  92.    {
  93.    case 'q':
  94.       root=1;
  95.       (*str)++;
  96.       break;
  97.    case 'i':
  98.       inverse=1;
  99.       (*str)++;
  100.       break;
  101.    }
  102.    i=0;
  103.    while ((**str<='9' && **str>='0') || **str=='.')
  104.    {
  105.       numstr[i++]= **str;
  106.       (*str)++;
  107.    }
  108.    (*str)--;
  109.    numstr[i]=0;
  110.    ret=atof(numstr);
  111.    if (ret <= 0.0) /* this is a sanity check, JCO 8/31/94 */
  112.       return 0;
  113.    if (root)
  114.      ret=sqrtl(ret);
  115.    if (inverse)
  116.      ret = 1.0/ret;
  117.    return ret;
  118. }
  119.  
  120. static int _fastcall readLSystemFile(char *str)
  121. {
  122.    int c;
  123.    char far **rulind;
  124.    int err=0;
  125.    int linenum,check=0;
  126.    char inline[161],fixed[161],*word;
  127.    FILE *infile;
  128.    char msgbuf[481]; /* enough for 6 full lines */
  129.  
  130.    if (find_file_item(LFileName,str,&infile) < 0)
  131.       return -1;
  132.    while ((c = fgetc(infile)) != '{')
  133.       if (c == EOF) return -1;
  134.    maxangle=0;
  135.    for(linenum=0;linenum<MAXRULES;++linenum) ruleptrs[linenum]=NULL;
  136.    rulind= &ruleptrs[1];
  137.    msgbuf[0]=(char)(linenum=0);
  138.  
  139.    while(file_gets(inline,160,infile) > -1)  /* Max line length 160 chars */
  140.    {
  141.       linenum++;
  142.       if ((word = strchr(inline,';')) != NULL) /* strip comment */
  143.      *word = 0;
  144.       strlwr(inline);
  145.  
  146.       if (strspn(inline," \t\n") < strlen(inline)) /* not a blank line */
  147.       {
  148.      word=strtok(inline," =\t\n");
  149.      if (!strcmp(word,"axiom"))
  150.      {
  151.         if (save_rule(strtok(NULL," \t\n"),&ruleptrs[0])) {
  152.             strcat(msgbuf,"Error:  out of memory\n");
  153.             ++err;
  154.         break;
  155.             }
  156.         check=1;
  157.      }
  158.      else if (!strcmp(word,"angle"))
  159.      {
  160.         maxangle=(char)atoi(strtok(NULL," \t\n"));
  161.         check=1;
  162.      }
  163.      else if (!strcmp(word,"}"))
  164.         break;
  165.      else if (strcspn(word,"+-/\\@|!c<>][") == 0 && strlen(word) == 1)
  166.         {
  167.            sprintf(&msgbuf[strlen(msgbuf)],
  168.            "Syntax error line %d: Redefined reserved symbol %s\n",linenum,word);
  169.            ++err;
  170.            break;
  171.         }
  172.      else if (strlen(word)==1)
  173.      {
  174.         strcat(strcpy(fixed,word),strtok(NULL," \t\n"));
  175.         if (save_rule(fixed,rulind++)) {
  176.         strcat(msgbuf, "Error:  out of memory\n");
  177.         ++err;
  178.                 break;
  179.             }
  180.         check=1;
  181.      }
  182.      else
  183.         if (err<6)
  184.         {
  185.            sprintf(&msgbuf[strlen(msgbuf)],
  186.                "Syntax error line %d: %s\n",linenum,word);
  187.            ++err;
  188.         }
  189.      if (check)
  190.      {
  191.         check=0;
  192.         if((word=strtok(NULL," \t\n"))!=NULL)
  193.            if (err<6)
  194.            {
  195.           sprintf(&msgbuf[strlen(msgbuf)],
  196.              "Extra text after command line %d: %s\n",linenum,word);
  197.           ++err;
  198.            }
  199.      }
  200.       }
  201.    }
  202.    fclose(infile);
  203.    if (!ruleptrs[0] && err<6)
  204.    {
  205.       strcat(msgbuf,"Error:  no axiom\n");
  206.       ++err;
  207.    }
  208.    if ((maxangle<3||maxangle>50) && err<6)
  209.    {
  210.       strcat(msgbuf,"Error:  illegal or missing angle\n");
  211.       ++err;
  212.    }
  213.    if (err)
  214.    {
  215.       msgbuf[strlen(msgbuf)-1]=0; /* strip trailing \n */
  216.       stopmsg(0,msgbuf);
  217.       return -1;
  218.    }
  219.    *rulind=NULL;
  220.    return 0;
  221. }
  222.  
  223. int Lsystem(void)
  224. {
  225.    int order;
  226.    char far **rulesc;
  227.    struct lsys_cmd far **sc;
  228.    int stackoflow = 0;
  229.  
  230.    if ( (!loaded) && LLoad())
  231.      return -1;
  232.  
  233.    overflow = 0;        /* reset integer math overflow flag */
  234.  
  235.    order=(int)param[0];
  236.    if (order<=0)
  237.      order=0;
  238.    if (usr_floatflag)
  239.     overflow = 1;
  240.    else {
  241.     struct lsys_turtlestatei ts;
  242.  
  243.     ts.stackoflow = 0;
  244.     ts.maxangle = maxangle;
  245.         ts.dmaxangle = (char)(maxangle - 1);
  246.  
  247.     sc = rules2;
  248.     for (rulesc = ruleptrs; *rulesc; rulesc++)
  249.         *sc++ = LSysISizeTransform(*rulesc, &ts);
  250.     *sc = NULL;
  251.  
  252.     lsysi_dosincos();
  253.     if (lsysi_findscale(rules2[0], &ts, &rules2[1], order)) {
  254.         ts.realangle = ts.angle = ts.reverse = 0;
  255.  
  256.         free_lcmds();
  257.         sc = rules2;
  258.         for (rulesc = ruleptrs; *rulesc; rulesc++)
  259.         *sc++ = LSysIDrawTransform(*rulesc, &ts);
  260.         *sc = NULL;
  261.  
  262.         /* !! HOW ABOUT A BETTER WAY OF PICKING THE DEFAULT DRAWING COLOR */
  263.         if ((ts.curcolor=15) > colors)
  264.             ts.curcolor=(char)(colors-1);
  265.         drawLSysI(rules2[0], &ts, &rules2[1], order);
  266.     }
  267.     stackoflow = ts.stackoflow;
  268.    }
  269.  
  270.    if (stackoflow) {
  271.       static char far msg[]={"insufficient memory, try a lower order"};
  272.       stopmsg(0,msg);
  273.    }
  274.    else if (overflow) {
  275.     struct lsys_turtlestatef ts;
  276.  
  277.     overflow = 0;
  278.  
  279.     ts.stackoflow = 0;
  280.     ts.maxangle = maxangle;
  281.         ts.dmaxangle = (char)(maxangle - 1);
  282.  
  283.     sc = rules2;
  284.     for (rulesc = ruleptrs; *rulesc; rulesc++)
  285.         *sc++ = LSysFSizeTransform(*rulesc, &ts);
  286.     *sc = NULL;
  287.  
  288.     lsysf_dosincos();
  289.     if (lsysf_findscale(rules2[0], &ts, &rules2[1], order)) {
  290.         ts.realangle = ts.angle = ts.reverse = 0;
  291.  
  292.         free_lcmds();
  293.         sc = rules2;
  294.         for (rulesc = ruleptrs; *rulesc; rulesc++)
  295.         *sc++ = LSysFDrawTransform(*rulesc, &ts);
  296.         *sc = NULL;
  297.  
  298.         /* !! HOW ABOUT A BETTER WAY OF PICKING THE DEFAULT DRAWING COLOR */
  299.         if ((ts.curcolor=15) > colors)
  300.             ts.curcolor=(char)(colors-1);
  301.         lsys_prepfpu(&ts);
  302.         drawLSysF(rules2[0], &ts, &rules2[1], order);
  303.         lsys_donefpu(&ts);
  304.     }
  305.         overflow = 0;
  306.    }
  307.    free_rules_mem();
  308.    free_lcmds();
  309.    loaded=0;
  310.    return 0;
  311. }
  312.  
  313. int LLoad(void)
  314. {
  315.    if (readLSystemFile(LName)) { /* error occurred */
  316.       free_rules_mem();
  317.       loaded=0;
  318.       return -1;
  319.    }
  320.    loaded=1;
  321.    return 0;
  322. }
  323.  
  324. static void _fastcall free_rules_mem(void)
  325. {
  326.    int i;
  327.    for(i=0;i<MAXRULES;++i)
  328.       if(ruleptrs[i]) farmemfree(ruleptrs[i]);
  329. }
  330.  
  331. static int _fastcall save_rule(char *rule,char far **saveptr)
  332. {
  333.    int i;
  334.    char far *tmpfar;
  335.    i=strlen(rule)+1;
  336.    if((tmpfar=farmemalloc((long)i))==NULL) {
  337.        return -1;
  338.    }
  339.    *saveptr=tmpfar;
  340.    while(--i>=0) *(tmpfar++)= *(rule++);
  341.    return 0;
  342. }
  343.  
  344. static void free_lcmds(void)
  345. {
  346.   struct lsys_cmd far **sc = rules2;
  347.  
  348.   while (*sc)
  349.     farmemfree(*sc++);
  350. }
  351.  
  352.  
  353.  
  354. #ifdef XFRACT
  355. #define lsysi_doslash_386 lsysi_doslash
  356. #define lsysi_dobslash_386 lsysi_dobslash
  357. #define lsys_doat lsysi_doat
  358. #define lsys_dosizegf lsysi_dosizegf
  359. #define lsys_dodrawg lsysi_dodrawg
  360. void lsys_prepfpu(struct lsys_turtlestatef *x) { }
  361. void lsys_donefpu(struct lsys_turtlestatef *x) { }
  362. #endif
  363.  
  364. /* integer specific routines */
  365.  
  366. #ifdef XFRACT
  367. static void lsysi_doplus(struct lsys_turtlestatei *cmd)
  368. {
  369.     if (cmd->reverse) {
  370.     if (++cmd->angle == cmd->maxangle)
  371.         cmd->angle = 0;
  372.     }
  373.     else {
  374.     if (cmd->angle)
  375.         cmd->angle--;
  376.     else
  377.         cmd->angle = cmd->dmaxangle;
  378.     }
  379. }
  380. #else
  381. extern void lsysi_doplus(struct lsys_turtlestatei *cmd);
  382. #endif
  383.  
  384. #ifdef XFRACT
  385. /* This is the same as lsys_doplus, except maxangle is a power of 2. */
  386. static void lsysi_doplus_pow2(struct lsys_turtlestatei *cmd)
  387. {
  388.     if (cmd->reverse) {
  389.     cmd->angle++;
  390.     cmd->angle &= cmd->dmaxangle;
  391.     }
  392.     else {
  393.     cmd->angle--;
  394.     cmd->angle &= cmd->dmaxangle;
  395.     }
  396. }
  397. #else
  398. extern void lsysi_doplus_pow2(struct lsys_turtlestatei *cmd);
  399. #endif
  400.  
  401. #ifdef XFRACT
  402. static void lsysi_dominus(struct lsys_turtlestatei *cmd)
  403. {
  404.     if (cmd->reverse) {
  405.     if (cmd->angle)
  406.         cmd->angle--;
  407.     else
  408.         cmd->angle = cmd->dmaxangle;
  409.     }
  410.     else {
  411.     if (++cmd->angle == cmd->maxangle)
  412.         cmd->angle = 0;
  413.     }
  414. }
  415. #else
  416. extern void lsysi_dominus(struct lsys_turtlestatei *cmd);
  417. #endif
  418.  
  419. #ifdef XFRACT
  420. static void lsysi_dominus_pow2(struct lsys_turtlestatei *cmd)
  421. {
  422.     if (cmd->reverse) {
  423.     cmd->angle--;
  424.     cmd->angle &= cmd->dmaxangle;
  425.     }
  426.     else {
  427.     cmd->angle++;
  428.     cmd->angle &= cmd->dmaxangle;
  429.     }
  430. }
  431. #else
  432. extern void lsysi_dominus_pow2(struct lsys_turtlestatei *cmd);
  433. #endif
  434.  
  435. static void lsysi_doslash(struct lsys_turtlestatei *cmd)
  436. {
  437.     if (cmd->reverse)
  438.     cmd->realangle -= cmd->num;
  439.     else
  440.     cmd->realangle += cmd->num;
  441. }
  442.  
  443. #ifndef XFRACT
  444. extern void lsysi_doslash_386(struct lsys_turtlestatei *cmd);
  445. #endif
  446.  
  447. static void lsysi_dobslash(struct lsys_turtlestatei *cmd)
  448. {
  449.     if (cmd->reverse)
  450.     cmd->realangle += cmd->num;
  451.     else
  452.     cmd->realangle -= cmd->num;
  453. }
  454.  
  455. #ifndef XFRACT
  456. extern void lsysi_dobslash_386(struct lsys_turtlestatei *cmd);
  457. #endif
  458.  
  459. static void lsysi_doat(struct lsys_turtlestatei *cmd)
  460. {
  461.     cmd->size = multiply(cmd->size, cmd->num, 19);
  462. }
  463.  
  464. static void lsysi_dopipe(struct lsys_turtlestatei *cmd)
  465. {
  466.     cmd->angle = (char)(cmd->angle + (char)(cmd->maxangle / 2));
  467.     cmd->angle %= cmd->maxangle;
  468. }
  469.  
  470. #ifdef XFRACT
  471. static void lsysi_dopipe_pow2(struct lsys_turtlestatei *cmd)
  472. {
  473.     cmd->angle += cmd->maxangle >> 1;
  474.     cmd->angle &= cmd->dmaxangle;
  475. }
  476. #else
  477. extern void lsysi_dopipe_pow2(struct lsys_turtlestatei *cmd);
  478. #endif
  479.  
  480. #ifdef XFRACT
  481. static void lsysi_dobang(struct lsys_turtlestatei *cmd)
  482. {
  483.     cmd->reverse = ! cmd->reverse;
  484. }
  485. #else
  486. extern void lsysi_dobang(struct lsys_turtlestatei *cmd);
  487. #endif
  488.  
  489. static void lsysi_dosizedm(struct lsys_turtlestatei *cmd)
  490. {
  491.     double angle = (double) cmd->realangle * ANGLE2DOUBLE;
  492.     double s, c;
  493.     long fixedsin, fixedcos;
  494.  
  495.     FPUsincos(&angle, &s, &c);
  496.     fixedsin = (long) (s * FIXEDLT1);
  497.     fixedcos = (long) (c * FIXEDLT1);
  498.  
  499.     cmd->xpos = cmd->xpos + (multiply(multiply(cmd->size, cmd->aspect, 19), fixedcos, 29));
  500.     cmd->ypos = cmd->ypos + (multiply(cmd->size, fixedsin, 29));
  501.  
  502. /* xpos+=size*aspect*cos(realangle*PI/180); */
  503. /* ypos+=size*sin(realangle*PI/180); */
  504.     if (cmd->xpos>cmd->xmax) cmd->xmax=cmd->xpos;
  505.     if (cmd->ypos>cmd->ymax) cmd->ymax=cmd->ypos;
  506.     if (cmd->xpos<cmd->xmin) cmd->xmin=cmd->xpos;
  507.     if (cmd->ypos<cmd->ymin) cmd->ymin=cmd->ypos;
  508. }
  509.  
  510. static void lsysi_dosizegf(struct lsys_turtlestatei *cmd)
  511. {
  512.   cmd->xpos = cmd->xpos + (multiply(cmd->size, coss[cmd->angle], 29));
  513.   cmd->ypos = cmd->ypos + (multiply(cmd->size, sins[cmd->angle], 29));
  514. /* xpos+=size*coss[angle]; */
  515. /* ypos+=size*sins[angle]; */
  516.   if (cmd->xpos>cmd->xmax) cmd->xmax=cmd->xpos;
  517.   if (cmd->ypos>cmd->ymax) cmd->ymax=cmd->ypos;
  518.   if (cmd->xpos<cmd->xmin) cmd->xmin=cmd->xpos;
  519.   if (cmd->ypos<cmd->ymin) cmd->ymin=cmd->ypos;
  520. }
  521.  
  522. static void lsysi_dodrawd(struct lsys_turtlestatei *cmd)
  523. {
  524.   double angle = (double) cmd->realangle * ANGLE2DOUBLE;
  525.   double s, c;
  526.   long fixedsin, fixedcos;
  527.   int lastx, lasty;
  528.  
  529.   FPUsincos(&angle, &s, &c);
  530.   fixedsin = (long) (s * FIXEDLT1);
  531.   fixedcos = (long) (c * FIXEDLT1);
  532.  
  533.   lastx=(int) (cmd->xpos >> 19);
  534.   lasty=(int) (cmd->ypos >> 19);
  535.   cmd->xpos = cmd->xpos + (multiply(multiply(cmd->size, cmd->aspect, 19), fixedcos, 29));
  536.   cmd->ypos = cmd->ypos + (multiply(cmd->size, fixedsin, 29));
  537. /* xpos+=size*aspect*cos(realangle*PI/180); */
  538. /* ypos+=size*sin(realangle*PI/180); */
  539.   draw_line(lastx,lasty,(int)(cmd->xpos >> 19),(int)(cmd->ypos >> 19),cmd->curcolor);
  540. }
  541.  
  542. static void lsysi_dodrawm(struct lsys_turtlestatei *cmd)
  543. {
  544.   double angle = (double) cmd->realangle * ANGLE2DOUBLE;
  545.   double s, c;
  546.   long fixedsin, fixedcos;
  547.  
  548.   FPUsincos(&angle, &s, &c);
  549.   fixedsin = (long) (s * FIXEDLT1);
  550.   fixedcos = (long) (c * FIXEDLT1);
  551.  
  552. /* xpos+=size*aspect*cos(realangle*PI/180); */
  553. /* ypos+=size*sin(realangle*PI/180); */
  554.   cmd->xpos = cmd->xpos + (multiply(multiply(cmd->size, cmd->aspect, 19), fixedcos, 29));
  555.   cmd->ypos = cmd->ypos + (multiply(cmd->size, fixedsin, 29));
  556. }
  557.  
  558. static void lsysi_dodrawg(struct lsys_turtlestatei *cmd)
  559. {
  560.   cmd->xpos = cmd->xpos + (multiply(cmd->size, coss[cmd->angle], 29));
  561.   cmd->ypos = cmd->ypos + (multiply(cmd->size, sins[cmd->angle], 29));
  562. /* xpos+=size*coss[angle]; */
  563. /* ypos+=size*sins[angle]; */
  564. }
  565.  
  566. static void lsysi_dodrawf(struct lsys_turtlestatei *cmd)
  567. {
  568.   int lastx = (int) (cmd->xpos >> 19);
  569.   int lasty = (int) (cmd->ypos >> 19);
  570.   cmd->xpos = cmd->xpos + (multiply(cmd->size, coss[cmd->angle], 29));
  571.   cmd->ypos = cmd->ypos + (multiply(cmd->size, sins[cmd->angle], 29));
  572. /* xpos+=size*coss[angle]; */
  573. /* ypos+=size*sins[angle]; */
  574.   draw_line(lastx,lasty,(int)(cmd->xpos >> 19),(int)(cmd->ypos >> 19),cmd->curcolor);
  575. }
  576.  
  577. static void lsysi_dodrawc(struct lsys_turtlestatei *cmd)
  578. {
  579.   cmd->curcolor = (char)(((int) cmd->num) % colors);
  580. }
  581.  
  582. static void lsysi_dodrawgt(struct lsys_turtlestatei *cmd)
  583. {
  584.   cmd->curcolor = (char)(cmd->curcolor - (char)cmd->num);
  585.   if ((cmd->curcolor %= colors) == 0)
  586.     cmd->curcolor = (char)(colors-1);
  587. }
  588.  
  589. static void lsysi_dodrawlt(struct lsys_turtlestatei *cmd)
  590. {
  591.   cmd->curcolor = (char)(cmd->curcolor + (char)cmd->num);
  592.   if ((cmd->curcolor %= colors) == 0)
  593.     cmd->curcolor = 1;
  594. }
  595.  
  596. static struct lsys_cmd far * _fastcall
  597. findsize(struct lsys_cmd far *command, struct lsys_turtlestatei *ts, struct lsys_cmd far **rules, int depth)
  598. {
  599.    struct lsys_cmd far **rulind;
  600.    int tran;
  601.  
  602. if (overflow)     /* integer math routines overflowed */
  603.     return NULL;
  604.  
  605. #ifndef __TURBOC__
  606.    if (stackavail() < 400) { /* leave some margin for calling subrtns */
  607.       ts->stackoflow = 1;
  608.       return NULL;
  609.       }
  610. #endif
  611.  
  612.    while (command->ch && command->ch !=']') {
  613.       if (! (ts->counter++)) {
  614.      /* let user know we're not dead */
  615.      if (thinking(1,"L-System thinking (higher orders take longer)")) {
  616.         ts->counter--;
  617.         return NULL;
  618.      }
  619.       }
  620.       tran=0;
  621.       if (depth) {
  622.      for(rulind=rules;*rulind;rulind++)
  623.         if ((*rulind)->ch==command->ch) {
  624.            tran=1;
  625.            if (findsize((*rulind)+1,ts,rules,depth-1) == NULL)
  626.           return(NULL);
  627.         }
  628.       }
  629.       if (!depth || !tran) {
  630.     if (command->f) {
  631.       ts->num = command->n;
  632.       (*command->f)(ts);
  633.       }
  634.     else if (command->ch == '[') {
  635.       char saveang,saverev;
  636.       long savesize,savex,savey;
  637.       unsigned long saverang;
  638.  
  639.       saveang=ts->angle;
  640.       saverev=ts->reverse;
  641.       savesize=ts->size;
  642.       saverang=ts->realangle;
  643.       savex=ts->xpos;
  644.       savey=ts->ypos;
  645.       if ((command=findsize(command+1,ts,rules,depth)) == NULL)
  646.          return(NULL);
  647.       ts->angle=saveang;
  648.       ts->reverse=saverev;
  649.       ts->size=savesize;
  650.       ts->realangle=saverang;
  651.       ts->xpos=savex;
  652.       ts->ypos=savey;
  653.     }
  654.       }
  655.       command++;
  656.    }
  657.    return command;
  658. }
  659.  
  660. static int
  661. lsysi_findscale(struct lsys_cmd far *command, struct lsys_turtlestatei *ts, struct lsys_cmd far **rules, int depth)
  662. {
  663.    float horiz,vert;
  664.    double xmin, xmax, ymin, ymax;
  665.    double locsize;
  666.    double locaspect;
  667.    struct lsys_cmd far *fsret;
  668.  
  669.    locaspect=screenaspect*xdots/ydots;
  670.    ts->aspect = FIXEDPT(locaspect);
  671.    ts->xpos =
  672.    ts->ypos =
  673.    ts->xmin =
  674.    ts->xmax =
  675.    ts->ymax =
  676.    ts->ymin =
  677.    ts->realangle =
  678.    ts->angle =
  679.    ts->reverse =
  680.    ts->counter = 0;
  681.    ts->size=FIXEDPT(1L);
  682.    fsret = findsize(command,ts,rules,depth);
  683.    thinking(0, NULL); /* erase thinking message if any */
  684.    xmin = (double) ts->xmin / FIXEDMUL;
  685.    xmax = (double) ts->xmax / FIXEDMUL;
  686.    ymin = (double) ts->ymin / FIXEDMUL;
  687.    ymax = (double) ts->ymax / FIXEDMUL;
  688.    if (fsret == NULL)
  689.       return 0;
  690.    if (xmax == xmin)
  691.       horiz = (float)1E37;
  692.    else
  693.       horiz = (float)((xdots-10)/(xmax-xmin));
  694.    if (ymax == ymin)
  695.       vert = (float)1E37;
  696.    else
  697.       vert = (float)((ydots-6) /(ymax-ymin));
  698.    locsize = (vert<horiz) ? vert : horiz;
  699.  
  700.    if (horiz == 1E37)
  701.       ts->xpos = FIXEDPT(xdots/2);
  702.    else
  703. /*    ts->xpos = FIXEDPT(-xmin*(locsize)+5+((xdots-10)-(locsize)*(xmax-xmin))/2); */
  704.       ts->xpos = FIXEDPT((xdots-locsize*(xmax+xmin))/2);
  705.    if (vert == 1E37)
  706.       ts->ypos = FIXEDPT(ydots/2);
  707.    else
  708. /*    ts->ypos = FIXEDPT(-ymin*(locsize)+3+((ydots-6)-(locsize)*(ymax-ymin))/2); */
  709.       ts->ypos = FIXEDPT((ydots-locsize*(ymax+ymin))/2);
  710.    ts->size = FIXEDPT(locsize);
  711.  
  712.    return 1;
  713. }
  714.  
  715. static struct lsys_cmd far * 
  716. drawLSysI(struct lsys_cmd far *command,struct lsys_turtlestatei *ts, struct lsys_cmd far **rules,int depth)
  717. {
  718.    struct lsys_cmd far **rulind;
  719.    int tran;
  720.  
  721. if (overflow)     /* integer math routines overflowed */
  722.     return NULL;
  723.  
  724. #ifndef __TURBOC__
  725.    if (stackavail() < 400) { /* leave some margin for calling subrtns */
  726.       ts->stackoflow = 1;
  727.       return NULL;
  728.       }
  729. #endif
  730.  
  731.    while (command->ch && command->ch !=']') {
  732.       if (!(ts->counter++)) {
  733.      if (keypressed()) {
  734.         ts->counter--;
  735.         return NULL;
  736.      }
  737.       }
  738.       tran=0;
  739.       if (depth) {
  740.      for(rulind=rules;*rulind;rulind++)
  741.         if ((*rulind)->ch == command->ch) {
  742.            tran=1;
  743.            if (drawLSysI((*rulind)+1,ts,rules,depth-1) == NULL)
  744.           return NULL;
  745.         }
  746.       }
  747.       if (!depth||!tran) {
  748.     if (command->f) {
  749.       ts->num = command->n;
  750.       (*command->f)(ts);
  751.       }
  752.     else if (command->ch == '[') {
  753.       char saveang,saverev,savecolor;
  754.       long savesize,savex,savey;
  755.       unsigned long saverang;
  756.  
  757.       saveang=ts->angle;
  758.       saverev=ts->reverse;
  759.       savesize=ts->size;
  760.       saverang=ts->realangle;
  761.       savex=ts->xpos;
  762.       savey=ts->ypos;
  763.       savecolor=ts->curcolor;
  764.       if ((command=drawLSysI(command+1,ts,rules,depth)) == NULL)
  765.          return(NULL);
  766.       ts->angle=saveang;
  767.       ts->reverse=saverev;
  768.       ts->size=savesize;
  769.       ts->realangle=saverang;
  770.       ts->xpos=savex;
  771.       ts->ypos=savey;
  772.       ts->curcolor=savecolor;
  773.     }
  774.       }
  775.       command++;
  776.    }
  777.    return command;
  778. }
  779.  
  780. static struct lsys_cmd far *
  781. LSysISizeTransform(char far *s, struct lsys_turtlestatei *ts)
  782. {
  783.   struct lsys_cmd far *ret;
  784.   struct lsys_cmd far *doub;
  785.   int maxval = 10;
  786.   int n = 0;
  787.   void (*f)();
  788.   long num;
  789.  
  790.   void (*plus)() = (ispow2(ts->maxangle)) ? lsysi_doplus_pow2 : lsysi_doplus;
  791.   void (*minus)() = (ispow2(ts->maxangle)) ? lsysi_dominus_pow2 : lsysi_dominus;
  792.   void (*pipe)() = (ispow2(ts->maxangle)) ? lsysi_dopipe_pow2 : lsysi_dopipe;
  793.  
  794.   void (*slash)() =  (cpu >= 386) ? lsysi_doslash_386 : lsysi_doslash;
  795.   void (*bslash)() = (cpu >= 386) ? lsysi_dobslash_386 : lsysi_dobslash;
  796.   void (*at)() =     (cpu >= 386) ? lsysi_doat_386 : lsysi_doat;
  797.   void (*dogf)() =   (cpu >= 386) ? lsysi_dosizegf_386 : lsysi_dosizegf;
  798.  
  799.   ret = (struct lsys_cmd far *) farmemalloc((long) maxval * sizeof(struct lsys_cmd));
  800.   if (ret == NULL) {
  801.        ts->stackoflow = 1;
  802.        return NULL;
  803.        }
  804.   while (*s) {
  805.     f = NULL;
  806.     num = 0;
  807.     ret[n].ch = *s;
  808.     switch (*s) {
  809.       case '+': f = plus;            break;
  810.       case '-': f = minus;           break;
  811.       case '/': f = slash;           num = (long) (getnumber(&s) * 11930465L);    break;
  812.       case '\\': f = bslash;         num = (long) (getnumber(&s) * 11930465L);    break;
  813.       case '@': f = at;              num = FIXEDPT(getnumber(&s));    break;
  814.       case '|': f = pipe;            break;
  815.       case '!': f = lsysi_dobang;     break;
  816.       case 'd':
  817.       case 'm': f = lsysi_dosizedm;   break;
  818.       case 'g':
  819.       case 'f': f = dogf;       break;
  820.       case '[': num = 1;        break;
  821.       case ']': num = 2;        break;
  822.       default:
  823.     num = 3;
  824.     break;
  825.     }
  826. #ifdef XFRACT
  827.     ret[n].f = (void (*)())f;
  828. #else
  829.     ret[n].f = (void (*)(struct lsys_turtlestatei *))f;
  830. #endif
  831.     ret[n].n = num;
  832.     if (++n == maxval) {
  833.       doub = (struct lsys_cmd far *) farmemalloc((long) maxval*2*sizeof(struct lsys_cmd));
  834.       if (doub == NULL) {
  835.          farmemfree(ret);
  836.          ts->stackoflow = 1;
  837.          return NULL;
  838.          }
  839.       far_memcpy(doub, ret, maxval*sizeof(struct lsys_cmd));
  840.       farmemfree(ret);
  841.       ret = doub;
  842.       maxval <<= 1;
  843.     }
  844.     s++;
  845.   }
  846.   ret[n].ch = 0;
  847.   ret[n].f = NULL;
  848.   ret[n].n = 0;
  849.   n++;
  850.  
  851.   doub = (struct lsys_cmd far *) farmemalloc((long) n*sizeof(struct lsys_cmd));
  852.   if (doub == NULL) {
  853.        farmemfree(ret);
  854.        ts->stackoflow = 1;
  855.        return NULL;
  856.        }
  857.   far_memcpy(doub, ret, n*sizeof(struct lsys_cmd));
  858.   farmemfree(ret);
  859.   return doub;
  860. }
  861.  
  862. static struct lsys_cmd far *
  863. LSysIDrawTransform(char far *s, struct lsys_turtlestatei *ts)
  864. {
  865.   struct lsys_cmd far *ret;
  866.   struct lsys_cmd far *doub;
  867.   int maxval = 10;
  868.   int n = 0;
  869.   void (*f)();
  870.   long num;
  871.  
  872.   void (*plus)() = (ispow2(ts->maxangle)) ? lsysi_doplus_pow2 : lsysi_doplus;
  873.   void (*minus)() = (ispow2(ts->maxangle)) ? lsysi_dominus_pow2 : lsysi_dominus;
  874.   void (*pipe)() = (ispow2(ts->maxangle)) ? lsysi_dopipe_pow2 : lsysi_dopipe;
  875.  
  876.   void (*slash)() =  (cpu >= 386) ? lsysi_doslash_386 : lsysi_doslash;
  877.   void (*bslash)() = (cpu >= 386) ? lsysi_dobslash_386 : lsysi_dobslash;
  878.   void (*at)() =     (cpu >= 386) ? lsysi_doat_386 : lsysi_doat;
  879.   void (*drawg)() =  (cpu >= 386) ? lsysi_dodrawg_386 : lsysi_dodrawg;
  880.  
  881.   ret = (struct lsys_cmd far *) farmemalloc((long) maxval * sizeof(struct lsys_cmd));
  882.   if (ret == NULL) {
  883.        ts->stackoflow = 1;
  884.        return NULL;
  885.        }
  886.   while (*s) {
  887.     f = NULL;
  888.     num = 0;
  889.     ret[n].ch = *s;
  890.     switch (*s) {
  891.       case '+': f = plus;            break;
  892.       case '-': f = minus;           break;
  893.       case '/': f = slash;           num = (long) (getnumber(&s) * 11930465L);    break;
  894.       case '\\': f = bslash;         num = (long) (getnumber(&s) * 11930465L);    break;
  895.       case '@': f = at;              num = FIXEDPT(getnumber(&s));    break;
  896.       case '|': f = pipe;            break;
  897.       case '!': f = lsysi_dobang;     break;
  898.       case 'd': f = lsysi_dodrawd;    break;
  899.       case 'm': f = lsysi_dodrawm;    break;
  900.       case 'g': f = drawg;           break;
  901.       case 'f': f = lsysi_dodrawf;    break;
  902.       case 'c': f = lsysi_dodrawc;    num = (long) getnumber(&s);    break;
  903.       case '<': f = lsysi_dodrawlt;   num = (long) getnumber(&s);    break;
  904.       case '>': f = lsysi_dodrawgt;   num = (long) getnumber(&s);    break;
  905.       case '[': num = 1;        break;
  906.       case ']': num = 2;        break;
  907.       default:
  908.     num = 3;
  909.     break;
  910.     }
  911. #ifdef XFRACT
  912.     ret[n].f = (void (*)())f;
  913. #else
  914.     ret[n].f = (void (*)(struct lsys_turtlestatei *))f;
  915. #endif
  916.     ret[n].n = num;
  917.     if (++n == maxval) {
  918.       doub = (struct lsys_cmd far *) farmemalloc((long) maxval*2*sizeof(struct lsys_cmd));
  919.       if (doub == NULL) {
  920.            farmemfree(ret);
  921.            ts->stackoflow = 1;
  922.            return NULL;
  923.            }
  924.       far_memcpy(doub, ret, maxval*sizeof(struct lsys_cmd));
  925.       farmemfree(ret);
  926.       ret = doub;
  927.       maxval <<= 1;
  928.     }
  929.     s++;
  930.   }
  931.   ret[n].ch = 0;
  932.   ret[n].f = NULL;
  933.   ret[n].n = 0;
  934.   n++;
  935.  
  936.   doub = (struct lsys_cmd far *) farmemalloc((long) n*sizeof(struct lsys_cmd));
  937.   if (doub == NULL) {
  938.        farmemfree(ret);
  939.        ts->stackoflow = 1;
  940.        return NULL;
  941.        }
  942.   far_memcpy(doub, ret, n*sizeof(struct lsys_cmd));
  943.   farmemfree(ret);
  944.   return doub;
  945. }
  946.  
  947. static void _fastcall lsysi_dosincos(void)
  948. {
  949.    double locaspect;
  950.    double TWOPI = 2.0 * PI;
  951.    double twopimax;
  952.    double twopimaxi;
  953.    double s, c;
  954.    int i;
  955.  
  956.    locaspect=screenaspect*xdots/ydots;
  957.    twopimax = TWOPI / maxangle;
  958.    for(i=0;i<maxangle;i++) {
  959.       twopimaxi = i * twopimax;
  960.       FPUsincos(&twopimaxi, &s, &c);
  961.       sins[i] = (long) (s * FIXEDLT1);
  962.       coss[i] = (long) ((locaspect * c) * FIXEDLT1);
  963.    }
  964. }
  965.