#include #include #include #include #include #include "fractint.h" extern int xdots,ydots; extern int colors; extern char LFileName[]; extern char LName[]; extern double param[]; int Lsystem(); extern int thinking(int,char *); static float _fastcall getnumber(char far **); static char far * _fastcall findsize(char far *,char far **,int); static int _fastcall findscale(char far *, char far **, int); static char far * _fastcall drawLSys(char far *, char far **, int); static int _fastcall readLSystemFile(char *); static void _fastcall free_rules_mem(void); static int _fastcall save_rule(char *,char far **); static float aspect; /* aspect ratio of each pixel, ysize/xsize */ /* Some notes to Adrian from PB, made when I integrated with v15: printfs changed to work with new user interface bug at end of readLSystemFile, the line which said rulind=0 fixed to say *rulind=0 the calloc was not worthwhile, it was just for a 54 byte area, cheaper to keep it as a static; but there was a static 201 char buffer I changed to not be static use of strdup was a nono, caused problems running out of space cause the memory allocated each time was never freed; I've changed to use far memory and to free when done */ static float far sins[50]; static float far coss[50]; static char maxangle,curcolor; static float xpos,ypos,size,realangle; static char counter,angle,reverse,stackoflow; static float Xmin,Xmax,Ymin,Ymax; static float _fastcall getnumber(char far **str) { char numstr[30]; float ret; int i,root,inverse; root=0; inverse=0; strcpy(numstr,""); (*str)++; switch (**str) { case 'q': root=1; (*str)++; break; case 'i': inverse=1; (*str)++; break; } switch (**str) { case 'q': root=1; (*str)++; break; case 'i': inverse=1; (*str)++; break; } i=0; while (**str<='9' && **str>='0' || **str=='.') { numstr[i++]=**str; (*str)++; } (*str)--; numstr[i]=0; ret=atof(numstr); if (root) ret=sqrt(ret); if (inverse) ret=1/ret; return ret; } static char far * _fastcall findsize(char far *command,char far **rules,int depth) { char far **rulind,tran; #ifndef __TURBOC__ if (stackavail() < 400) { /* leave some margin for calling subrtns */ stackoflow = 1; return NULL; } #endif while ((*command)&&(*command!=']')) { if (!(counter++)) { /* let user know we're not dead */ if (thinking(1,"L-System thinking (higher orders take longer)")) { counter--; return NULL; } } tran=0; if (depth) { for(rulind=rules;*rulind;rulind++) if (**rulind==*command) { tran=1; if (findsize((*rulind)+1,rules,depth-1) == NULL) return(NULL); } } if (!depth || !tran) switch (*command) { case '+': if (reverse) { if (++angle==maxangle) angle=0; } else { if (angle) angle--; else angle=maxangle-1; } break; case '-': if (reverse) { if (angle) angle--; else angle=maxangle-1; } else { if (++angle==maxangle) angle=0; } break; case '/': if (reverse) { realangle-=getnumber(&command); while (realangle<0) realangle+=360; } else { realangle+=getnumber(&command); while (realangle>=360) realangle-=360; } break; case '\\': if (reverse) { realangle+=getnumber(&command); while (realangle>=360) realangle-=360; } else { realangle-=getnumber(&command); while (realangle<0) realangle+=360; } break; case '@': size*=getnumber(&command); break; case '|': angle+=maxangle/2; angle%=maxangle; break; case '!': reverse=!reverse; break; case 'd': case 'm': xpos+=size*aspect*cos(realangle*PI/180); ypos+=size*sin(realangle*PI/180); if (xpos>Xmax) Xmax=xpos; if (ypos>Ymax) Ymax=ypos; if (xposXmax) Xmax=xpos; if (ypos>Ymax) Ymax=ypos; if (xpos=360) realangle-=360; } break; case '\\': if (reverse) { realangle+=getnumber(&command); while (realangle>=360) realangle-=360; } else { realangle-=getnumber(&command); while (realangle<0) realangle+=360; } break; case '@': size *= getnumber(&command); break; case '|': angle+=maxangle/2; angle%=maxangle; break; case '!': reverse=!reverse; break; case 'd': lastx=xpos; lasty=ypos; xpos+=size*aspect*cos(realangle*PI/180); ypos+=size*sin(realangle*PI/180); draw_line(lastx,lasty,(int)xpos,(int)ypos,curcolor); break; case 'm': xpos+=size*aspect*cos(realangle*PI/180); ypos+=size*sin(realangle*PI/180); break; case 'g': xpos+=size*coss[angle]; ypos+=size*sins[angle]; break; case 'f': lastx=xpos; lasty=ypos; xpos+=size*coss[angle]; ypos+=size*sins[angle]; draw_line(lastx,lasty,(int)xpos,(int)ypos,curcolor); break; case '[': { char saveang,saverev,savecolor; float savesize,saverang,savex,savey; saveang=angle; saverev=reverse; savesize=size; saverang=realangle; savex=xpos; savey=ypos; savecolor=curcolor; if ((command=drawLSys(command+1,rules,depth)) == NULL) return(NULL); angle=saveang; reverse=saverev; size=savesize; realangle=saverang; xpos=savex; ypos=savey; curcolor=savecolor; } break; case 'c': curcolor=((int)getnumber(&command))%colors; break; case '>': curcolor-=getnumber(&command); if ((curcolor &= colors-1) == 0) curcolor = colors-1; break; case '<': curcolor+=getnumber(&command); if ((curcolor &= colors-1) == 0) curcolor = 1; break; } command++; } return command; } #define MAXRULES 27 /* this limits rules to 25 */ static char far *ruleptrs[MAXRULES]; static int _fastcall readLSystemFile(char *str) { int c; char far **rulind; int err=0; int linenum,check=0; char inline[161],fixed[161],*word; FILE *infile; char msgbuf[481]; /* enough for 6 full lines */ if (find_file_item(LFileName,str,&infile) < 0) return -1; while ((c = fgetc(infile)) != '{') if (c == EOF) return -1; maxangle=0; for(linenum=0;linenum50) && err<6) { strcat(msgbuf,"Error: illegal or missing angle\n"); ++err; } if (err) { msgbuf[strlen(msgbuf)-1]=0; /* strip trailing \n */ stopmsg(0,msgbuf); return -1; } *rulind=NULL; return 0; } static char loaded=0; int Lsystem() { int order; if ((!loaded)&&LLoad()) return (-1); order=param[0]; if (order<=0) order=0; stackoflow = 0; if (findscale(ruleptrs[0],&ruleptrs[1],order)) { realangle=angle=reverse=0; /* !! HOW ABOUT A BETTER WAY OF PICKING THE DEFAULT DRAWING COLOR */ if ((curcolor=15) > colors) curcolor=colors-1; drawLSys(ruleptrs[0],&ruleptrs[1],order); } if (stackoflow) { static char far msg[]={"insufficient memory, try a lower order"}; stopmsg(0,msg); } free_rules_mem(); loaded=0; return 0; } int LLoad() { char i; if (readLSystemFile(LName)) { /* error occurred */ free_rules_mem(); loaded=0; return -1; } for(i=0;i=0) *(tmpfar++)=*(rule++); return 0; }