File: common\lsysf.c

    1 #include <string.h>
    2 #ifdef __TURBOC__
3 #include <alloc.h>
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
14 #undef 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
34 void lsysf_prepfpu(struct lsys_turtlestatef *x) { } 35 void lsysf_donefpu(struct lsys_turtlestatef *x) { }
36 #endif 37 38 39 #ifdef XFRACT
40 static void lsysf_doplus(struct lsys_turtlestatef *cmd) 41 { 42 if (cmd->reverse) { 43 if (++cmd->angle == cmd->maxangle) 44 cmd->angle = 0; 45 } 46 else { 47 if (cmd->angle) 48 cmd->angle--; 49 else 50 cmd->angle = cmd->dmaxangle; 51 } 52 }
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
75 static void lsysf_dominus(struct lsys_turtlestatef *cmd) 76 { 77 if (cmd->reverse) { 78 if (cmd->angle) 79 cmd->angle--; 80 else 81 cmd->angle = cmd->dmaxangle; 82 } 83 else { 84 if (++cmd->angle == cmd->maxangle) 85 cmd->angle = 0; 86 } 87 }
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
109 static void lsysf_doslash(struct lsys_turtlestatef *cmd) 110 { 111 if (cmd->reverse) 112 cmd->realangle -= cmd->parm.nf; 113 else 114 cmd->realangle += cmd->parm.nf; 115 }
116 #else 117 extern void lsysf_doslash(struct lsys_turtlestatef *cmd); 118 #endif 119 120 #ifdef XFRACT
121 static void lsysf_dobslash(struct lsys_turtlestatef *cmd) 122 { 123 if (cmd->reverse) 124 cmd->realangle += cmd->parm.nf; 125 else 126 cmd->realangle -= cmd->parm.nf; 127 }
128 #else 129 extern void lsysf_dobslash(struct lsys_turtlestatef *cmd); 130 #endif 131 132 #ifdef XFRACT
133 static void lsysf_doat(struct lsys_turtlestatef *cmd) 134 { 135 cmd->size *= cmd->parm.nf; 136 }
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
149 static void lsysf_dopipe_pow2(struct lsys_turtlestatef *cmd) 150 { 151 cmd->angle += cmd->maxangle >> 1; 152 cmd->angle &= cmd->dmaxangle; 153 }
154 #else 155 extern void lsysf_dopipe_pow2(struct lsys_turtlestatef *cmd); 156 #endif 157 158 #ifdef XFRACT
159 static void lsysf_dobang(struct lsys_turtlestatef *cmd) 160 { 161 cmd->reverse = ! cmd->reverse; 162 }
163 #else 164 extern void lsysf_dobang(struct lsys_turtlestatef *cmd); 165 #endif 166 167 #ifdef XFRACT
168 static void lsysf_dosizedm(struct lsys_turtlestatef *cmd) 169 { 170 double angle = (double) cmd->realangle; 171 double s, c; 172 173 s = sin(angle); 174 c = cos(angle); 175 176 cmd->xpos += cmd->size * cmd->aspect * c; 177 cmd->ypos += cmd->size * s; 178 179 if (cmd->xpos>cmd->xmax) cmd->xmax=cmd->xpos; 180 if (cmd->ypos>cmd->ymax) cmd->ymax=cmd->ypos; 181 if (cmd->xpos<cmd->xmin) cmd->xmin=cmd->xpos; 182 if (cmd->ypos<cmd->ymin) cmd->ymin=cmd->ypos; 183 }
184 #else 185 extern void lsysf_dosizedm(struct lsys_turtlestatef *cmd, long n); 186 #endif 187 188 #ifdef XFRACT
189 static void lsysf_dosizegf(struct lsys_turtlestatef *cmd) 190 { 191 cmd->xpos += cmd->size * coss_f[(int)cmd->angle]; 192 cmd->ypos += cmd->size * sins_f[(int)cmd->angle]; 193 194 if (cmd->xpos>cmd->xmax) cmd->xmax=cmd->xpos; 195 if (cmd->ypos>cmd->ymax) cmd->ymax=cmd->ypos; 196 if (cmd->xpos<cmd->xmin) cmd->xmin=cmd->xpos; 197 if (cmd->ypos<cmd->ymin) cmd->ymin=cmd->ypos; 198 }
199 #else 200 extern void lsysf_dosizegf(struct lsys_turtlestatef *cmd); 201 #endif 202 203 #ifdef XFRACT
204 static void lsysf_dodrawd(struct lsys_turtlestatef *cmd) 205 { 206 double angle = (double) cmd->realangle; 207 double s, c; 208 int lastx, lasty; 209 s = sin(angle); 210 c = cos(angle); 211 212 lastx=(int) cmd->xpos; 213 lasty=(int) cmd->ypos; 214 215 cmd->xpos += cmd->size * cmd->aspect * c; 216 cmd->ypos += cmd->size * s; 217 218 draw_line(lastx, lasty, (int) cmd->xpos, (int) cmd->ypos, cmd->curcolor); 219 }
220 #else 221 extern void lsysf_dodrawd(struct lsys_turtlestatef *cmd); 222 #endif 223 224 #ifdef XFRACT
225 static void lsysf_dodrawm(struct lsys_turtlestatef *cmd) 226 { 227 double angle = (double) cmd->realangle; 228 double s, c; 229 230 s = sin(angle); 231 c = cos(angle); 232 233 cmd->xpos += cmd->size * cmd->aspect * c; 234 cmd->ypos += cmd->size * s; 235 }
236 #else 237 extern void lsysf_dodrawm(struct lsys_turtlestatef *cmd); 238 #endif 239 240 #ifdef XFRACT
241 static void lsysf_dodrawg(struct lsys_turtlestatef *cmd) 242 { 243 cmd->xpos += cmd->size * coss_f[(int)cmd->angle]; 244 cmd->ypos += cmd->size * sins_f[(int)cmd->angle]; 245 }
246 #else 247 extern void lsysf_dodrawg(struct lsys_turtlestatef *cmd); 248 #endif 249 250 #ifdef XFRACT
251 static void lsysf_dodrawf(struct lsys_turtlestatef *cmd) 252 { 253 int lastx = (int) cmd->xpos; 254 int lasty = (int) cmd->ypos; 255 cmd->xpos += cmd->size * coss_f[(int)cmd->angle]; 256 cmd->ypos += cmd->size * sins_f[(int)cmd->angle]; 257 draw_line(lastx,lasty,(int) cmd->xpos, (int) cmd->ypos, cmd->curcolor); 258 }
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
543 ret[n].f = (void (*)())f;
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
633 ret[n].f = (void (*)())f;
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