File: common\lsysf.c
1 #include <string.h>
2 #ifdef __TURBOC__
4 #else
5 #include <malloc.h>
6 #endif
7
8 /* see Fractint.c for a description of the "include" hierarchy */
9 #include "port.h"
10 #include "prototyp.h"
11 #include "lsys.h"
12
13 #ifdef max
15 #endif
16
17 struct lsys_cmd {
18 void (*f)(struct lsys_turtlestatef *);
19 int ptype;
20 union {
21 long n;
22 LDBL nf;
23 } parm;
24 char ch;
25 };
26
27 #define sins_f ((LDBL *)(boxy))
28 #define coss_f (((LDBL *)(boxy)+50))
29
30 static struct lsys_cmd far * _fastcall findsize(struct lsys_cmd far *,struct lsys_turtlestatef *, struct lsys_cmd far **,int);
31
32 /* Define blanks for portability */
33 #ifdef XFRACT
36 #endif
37
38
39 #ifdef XFRACT
53 #else
54 extern void lsysf_doplus(struct lsys_turtlestatef *cmd);
55 #endif
56
57 #ifdef XFRACT
58 /* This is the same as lsys_doplus, except maxangle is a power of 2. */
59 static void lsysf_doplus_pow2(struct lsys_turtlestatef *cmd)
60 {
61 if (cmd->reverse) {
62 cmd->angle++;
63 cmd->angle &= cmd->dmaxangle;
64 }
65 else {
66 cmd->angle--;
67 cmd->angle &= cmd->dmaxangle;
68 }
69 } 70 #else
71 extern void lsysf_doplus_pow2(struct lsys_turtlestatef *cmd);
72 #endif
73
74 #ifdef XFRACT
88 #else
89 extern void lsysf_dominus(struct lsys_turtlestatef *cmd);
90 #endif
91
92 #ifdef XFRACT
93 static void lsysf_dominus_pow2(struct lsys_turtlestatef *cmd)
94 {
95 if (cmd->reverse) {
96 cmd->angle--;
97 cmd->angle &= cmd->dmaxangle;
98 }
99 else {
100 cmd->angle++;
101 cmd->angle &= cmd->dmaxangle;
102 }
103 } 104 #else
105 extern void lsysf_dominus_pow2(struct lsys_turtlestatef *cmd);
106 #endif
107
108 #ifdef XFRACT
116 #else
117 extern void lsysf_doslash(struct lsys_turtlestatef *cmd);
118 #endif
119
120 #ifdef XFRACT
128 #else
129 extern void lsysf_dobslash(struct lsys_turtlestatef *cmd);
130 #endif
131
132 #ifdef XFRACT
137 #else
138 extern void lsysf_doat(struct lsys_turtlestatef *cmd, long n);
139 #endif
140
141 static void
142 lsysf_dopipe(struct lsys_turtlestatef *cmd)
143 {
144 cmd->angle = (char)(cmd->angle + cmd->maxangle / 2);
145 cmd->angle %= cmd->maxangle;
146 }
147
148 #ifdef XFRACT
154 #else
155 extern void lsysf_dopipe_pow2(struct lsys_turtlestatef *cmd);
156 #endif
157
158 #ifdef XFRACT
163 #else
164 extern void lsysf_dobang(struct lsys_turtlestatef *cmd);
165 #endif
166
167 #ifdef XFRACT
184 #else
185 extern void lsysf_dosizedm(struct lsys_turtlestatef *cmd, long n);
186 #endif
187
188 #ifdef XFRACT
199 #else
200 extern void lsysf_dosizegf(struct lsys_turtlestatef *cmd);
201 #endif
202
203 #ifdef XFRACT
220 #else
221 extern void lsysf_dodrawd(struct lsys_turtlestatef *cmd);
222 #endif
223
224 #ifdef XFRACT
236 #else
237 extern void lsysf_dodrawm(struct lsys_turtlestatef *cmd);
238 #endif
239
240 #ifdef XFRACT
246 #else
247 extern void lsysf_dodrawg(struct lsys_turtlestatef *cmd);
248 #endif
249
250 #ifdef XFRACT
259 #else
260 extern void lsysf_dodrawf(struct lsys_turtlestatef *cmd);
261 #endif
262
263 static void lsysf_dodrawc(struct lsys_turtlestatef *cmd)
264 {
265 cmd->curcolor = (char)(((int) cmd->parm.n) % colors);
266 }
267
268 static void lsysf_dodrawgt(struct lsys_turtlestatef *cmd)
269 {
270 cmd->curcolor = (char)(cmd->curcolor - cmd->parm.n);
271 if ((cmd->curcolor %= colors) == 0)
272 cmd->curcolor = (char)(colors-1);
273 }
274
275 static void lsysf_dodrawlt(struct lsys_turtlestatef *cmd)
276 {
277 cmd->curcolor = (char)(cmd->curcolor + cmd->parm.n);
278 if ((cmd->curcolor %= colors) == 0)
279 cmd->curcolor = 1;
280 }
281
282 static struct lsys_cmd far * _fastcall
283 findsize(struct lsys_cmd far *command, struct lsys_turtlestatef *ts, struct lsys_cmd far **rules, int depth)
284 {
285 struct lsys_cmd far **rulind;
286 int tran;
287
288 if (overflow) /* integer math routines overflowed */
289 return NULL;
290
291 if (stackavail() < 400) { /* leave some margin for calling subrtns */
292 ts->stackoflow = 1;
293 return NULL;
294 }
295
296
297 while (command->ch && command->ch !=']') {
298 if (! (ts->counter++)) {
299 static FCODE msg[]={"L-System thinking (higher orders take longer)"};
300 /* let user know we're not dead */
301 if (thinking(1,msg)) {
302 ts->counter--;
303 return NULL;
304 }
305 }
306 tran=0;
307 if (depth) {
308 for(rulind=rules;*rulind;rulind++)
309 if ((*rulind)->ch==command->ch) {
310 tran=1;
311 if (findsize((*rulind)+1,ts,rules,depth-1) == NULL)
312 return(NULL);
313 }
314 }
315 if (!depth || !tran) {
316 if (command->f) {
317 switch (command->ptype) {
318 case 4:
319 ts->parm.n = command->parm.n;
320 break;
321 case 10:
322 ts->parm.nf = command->parm.nf;
323 break;
324 default:
325 break;
326 }
327 (*command->f)(ts);
328 }
329 else if (command->ch == '[') {
330 char saveang,saverev;
331 LDBL savesize,savex,savey,saverang;
332
333 lsys_donefpu(ts);
334 saveang=ts->angle;
335 saverev=ts->reverse;
336 savesize=ts->size;
337 saverang=ts->realangle;
338 savex=ts->xpos;
339 savey=ts->ypos;
340 lsys_prepfpu(ts);
341 if ((command=findsize(command+1,ts,rules,depth)) == NULL)
342 return(NULL);
343 lsys_donefpu(ts);
344 ts->angle=saveang;
345 ts->reverse=saverev;
346 ts->size=savesize;
347 ts->realangle=saverang;
348 ts->xpos=savex;
349 ts->ypos=savey;
350 lsys_prepfpu(ts);
351 }
352 }
353 command++;
354 }
355 return command;
356 }
357
358 int _fastcall
359 lsysf_findscale(struct lsys_cmd far *command, struct lsys_turtlestatef *ts, struct lsys_cmd far **rules, int depth)
360 {
361 float horiz,vert;
362 LDBL xmin, xmax, ymin, ymax;
363 LDBL locsize;
364 LDBL locaspect;
365 struct lsys_cmd far *fsret;
366
367 locaspect=screenaspect*xdots/ydots;
368 ts->aspect = locaspect;
369 ts->xpos =
370 ts->ypos =
371 ts->xmin =
372 ts->xmax =
373 ts->ymax =
374 ts->ymin = 0;
375 ts->angle =
376 ts->reverse =
377 ts->counter = 0;
378 ts->realangle = 0;
379 ts->size = 1;
380 lsys_prepfpu(ts);
381 fsret = findsize(command,ts,rules,depth);
382 lsys_donefpu(ts);
383 thinking(0, NULL); /* erase thinking message if any */
384 xmin = ts->xmin;
385 xmax = ts->xmax;
386 ymin = ts->ymin;
387 ymax = ts->ymax;
388 /* locsize = ts->size; */
389 if (fsret == NULL)
390 return 0;
391 if (xmax == xmin)
392 horiz = (float)1E37;
393 else
394 horiz = (float)((xdots-10)/(xmax-xmin));
395 if (ymax == ymin)
396 vert = (float)1E37;
397 else
398 vert = (float)((ydots-6) /(ymax-ymin));
399 locsize = (vert<horiz) ? vert : horiz;
400
401 if (horiz == 1E37)
402 ts->xpos = xdots/2;
403 else
404 /* ts->xpos = -xmin*(locsize)+5+((xdots-10)-(locsize)*(xmax-xmin))/2; */
405 ts->xpos = (xdots-locsize*(xmax+xmin))/2;
406 if (vert == 1E37)
407 ts->ypos = ydots/2;
408 else
409 /* ts->ypos = -ymin*(locsize)+3+((ydots-6)-(locsize)*(ymax-ymin))/2; */
410 ts->ypos = (ydots-locsize*(ymax+ymin))/2;
411 ts->size = locsize;
412
413 return 1;
414 }
415
416 struct lsys_cmd far * _fastcall
417 drawLSysF(struct lsys_cmd far *command,struct lsys_turtlestatef *ts, struct lsys_cmd far **rules,int depth)
418 {
419 struct lsys_cmd far **rulind;
420 int tran;
421
422 if (overflow) /* integer math routines overflowed */
423 return NULL;
424
425
426 if (stackavail() < 400) { /* leave some margin for calling subrtns */
427 ts->stackoflow = 1;
428 return NULL;
429 }
430
431
432 while (command->ch && command->ch !=']') {
433 if (!(ts->counter++)) {
434 if (keypressed()) {
435 ts->counter--;
436 return NULL;
437 }
438 }
439 tran=0;
440 if (depth) {
441 for(rulind=rules;*rulind;rulind++)
442 if ((*rulind)->ch == command->ch) {
443 tran=1;
444 if (drawLSysF((*rulind)+1,ts,rules,depth-1) == NULL)
445 return NULL;
446 }
447 }
448 if (!depth||!tran) {
449 if (command->f) {
450 switch (command->ptype) {
451 case 4:
452 ts->parm.n = command->parm.n;
453 break;
454 case 10:
455 ts->parm.nf = command->parm.nf;
456 break;
457 default:
458 break;
459 }
460 (*command->f)(ts);
461 }
462 else if (command->ch == '[') {
463 char saveang,saverev,savecolor;
464 LDBL savesize,savex,savey,saverang;
465
466 lsys_donefpu(ts);
467 saveang=ts->angle;
468 saverev=ts->reverse;
469 savesize=ts->size;
470 saverang=ts->realangle;
471 savex=ts->xpos;
472 savey=ts->ypos;
473 savecolor=ts->curcolor;
474 lsys_prepfpu(ts);
475 if ((command=drawLSysF(command+1,ts,rules,depth)) == NULL)
476 return(NULL);
477 lsys_donefpu(ts);
478 ts->angle=saveang;
479 ts->reverse=saverev;
480 ts->size=savesize;
481 ts->realangle=saverang;
482 ts->xpos=savex;
483 ts->ypos=savey;
484 ts->curcolor=savecolor;
485 lsys_prepfpu(ts);
486 }
487 }
488 command++;
489 }
490 return command;
491 }
492
493 struct lsys_cmd far *
494 LSysFSizeTransform(char far *s, struct lsys_turtlestatef *ts)
495 {
496 struct lsys_cmd far *ret;
497 struct lsys_cmd far *doub;
498 int max = 10;
499 int n = 0;
500 void (*f)();
501 long num;
502 int ptype;
503 double PI180 = PI / 180.0;
504
505 void (*plus)() = (ispow2(ts->maxangle)) ? lsysf_doplus_pow2 : lsysf_doplus;
506 void (*minus)() = (ispow2(ts->maxangle)) ? lsysf_dominus_pow2 : lsysf_dominus;
507 void (*pipe)() = (ispow2(ts->maxangle)) ? lsysf_dopipe_pow2 : lsysf_dopipe;
508
509 void (*slash)() = lsysf_doslash;
510 void (*bslash)() = lsysf_dobslash;
511 void (*at)() = lsysf_doat;
512 void (*dogf)() = lsysf_dosizegf;
513
514 ret = (struct lsys_cmd far *) farmemalloc((long) max * sizeof(struct lsys_cmd));
515 if (ret == NULL) {
516 ts->stackoflow = 1;
517 return NULL;
518 }
519 while (*s) {
520 f = NULL;
521 num = 0;
522 ptype = 4;
523 ret[n].ch = *s;
524 switch (*s) {
525 case '+': f = plus; break;
526 case '-': f = minus; break;
527 case '/': f = slash; ptype = 10; ret[n].parm.nf = getnumber(&s) * PI180; break;
528 case '\\': f = bslash; ptype = 10; ret[n].parm.nf = getnumber(&s) * PI180; break;
529 case '@': f = at; ptype = 10; ret[n].parm.nf = getnumber(&s); break;
530 case '|': f = pipe; break;
531 case '!': f = lsysf_dobang; break;
532 case 'd':
533 case 'm': f = lsysf_dosizedm; break;
534 case 'g':
535 case 'f': f = dogf; break;
536 case '[': num = 1; break;
537 case ']': num = 2; break;
538 default:
539 num = 3;
540 break;
541 }
542 #ifdef XFRACT
544 #else
545 ret[n].f = (void (*)(struct lsys_turtlestatef *))f;
546 #endif
547 if (ptype == 4)
548 ret[n].parm.n = num;
549 ret[n].ptype = ptype;
550 if (++n == max) {
551 doub = (struct lsys_cmd far *) farmemalloc((long) max*2*sizeof(struct lsys_cmd));
552 if (doub == NULL) {
553 farmemfree(ret);
554 ts->stackoflow = 1;
555 return NULL;
556 }
557 far_memcpy(doub, ret, max*sizeof(struct lsys_cmd));
558 farmemfree(ret);
559 ret = doub;
560 max <<= 1;
561 }
562 s++;
563 }
564 ret[n].ch = 0;
565 ret[n].f = NULL;
566 ret[n].parm.n = 0;
567 n++;
568
569 doub = (struct lsys_cmd far *) farmemalloc((long) n*sizeof(struct lsys_cmd));
570 if (doub == NULL) {
571 farmemfree(ret);
572 ts->stackoflow = 1;
573 return NULL;
574 }
575 far_memcpy(doub, ret, n*sizeof(struct lsys_cmd));
576 farmemfree(ret);
577 return doub;
578 }
579
580 struct lsys_cmd far *
581 LSysFDrawTransform(char far *s, struct lsys_turtlestatef *ts)
582 {
583 struct lsys_cmd far *ret;
584 struct lsys_cmd far *doub;
585 int max = 10;
586 int n = 0;
587 void (*f)();
588 LDBL num;
589 int ptype;
590 LDBL PI180 = PI / 180.0;
591
592 void (*plus)() = (ispow2(ts->maxangle)) ? lsysf_doplus_pow2 : lsysf_doplus;
593 void (*minus)() = (ispow2(ts->maxangle)) ? lsysf_dominus_pow2 : lsysf_dominus;
594 void (*pipe)() = (ispow2(ts->maxangle)) ? lsysf_dopipe_pow2 : lsysf_dopipe;
595
596 void (*slash)() = lsysf_doslash;
597 void (*bslash)() = lsysf_dobslash;
598 void (*at)() = lsysf_doat;
599 void (*drawg)() = lsysf_dodrawg;
600
601 ret = (struct lsys_cmd far *) farmemalloc((long) max * sizeof(struct lsys_cmd));
602 if (ret == NULL) {
603 ts->stackoflow = 1;
604 return NULL;
605 }
606 while (*s) {
607 f = NULL;
608 num = 0;
609 ptype = 4;
610 ret[n].ch = *s;
611 switch (*s) {
612 case '+': f = plus; break;
613 case '-': f = minus; break;
614 case '/': f = slash; ptype = 10; ret[n].parm.nf = getnumber(&s) * PI180; break;
615 case '\\': f = bslash; ptype = 10; ret[n].parm.nf = getnumber(&s) * PI180; break;
616 case '@': f = at; ptype = 10; ret[n].parm.nf = getnumber(&s); break;
617 case '|': f = pipe; break;
618 case '!': f = lsysf_dobang; break;
619 case 'd': f = lsysf_dodrawd; break;
620 case 'm': f = lsysf_dodrawm; break;
621 case 'g': f = drawg; break;
622 case 'f': f = lsysf_dodrawf; break;
623 case 'c': f = lsysf_dodrawc; num = getnumber(&s); break;
624 case '<': f = lsysf_dodrawlt; num = getnumber(&s); break;
625 case '>': f = lsysf_dodrawgt; num = getnumber(&s); break;
626 case '[': num = 1; break;
627 case ']': num = 2; break;
628 default:
629 num = 3;
630 break;
631 }
632 #ifdef XFRACT
634 #else
635 ret[n].f = (void (*)(struct lsys_turtlestatef *))f;
636 #endif
637 if (ptype == 4)
638 ret[n].parm.n = (long)num;
639 ret[n].ptype = ptype;
640 if (++n == max) {
641 doub = (struct lsys_cmd far *) farmemalloc((long) max*2*sizeof(struct lsys_cmd));
642 if (doub == NULL) {
643 farmemfree(ret);
644 ts->stackoflow = 1;
645 return NULL;
646 }
647 far_memcpy(doub, ret, max*sizeof(struct lsys_cmd));
648 farmemfree(ret);
649 ret = doub;
650 max <<= 1;
651 }
652 s++;
653 }
654 ret[n].ch = 0;
655 ret[n].f = NULL;
656 ret[n].parm.n = 0;
657 n++;
658
659 doub = (struct lsys_cmd far *) farmemalloc((long) n*sizeof(struct lsys_cmd));
660 if (doub == NULL) {
661 farmemfree(ret);
662 ts->stackoflow = 1;
663 return NULL;
664 }
665 far_memcpy(doub, ret, n*sizeof(struct lsys_cmd));
666 farmemfree(ret);
667 return doub;
668 }
669
670 void _fastcall lsysf_dosincos(void)
671 {
672 LDBL locaspect;
673 LDBL TWOPI = 2.0 * PI;
674 LDBL twopimax;
675 LDBL twopimaxi;
676 int i;
677
678 locaspect=screenaspect*xdots/ydots;
679 twopimax = TWOPI / maxangle;
680 for(i=0;i<maxangle;i++) {
681 twopimaxi = i * twopimax;
682 sins_f[i]= sinl(twopimaxi);
683 coss_f[i]= locaspect * cosl(twopimaxi);
684 }
685
686 }
687