File: common\evolve.c

    1 #include "port.h"
    2 #include "prototyp.h"
    3 #include "fractype.h"
    4 #include "helpdefs.h"
    5 #define PARMBOX 128
    6 U16 gene_handle = 0;
    7 
    8 /* px and py are coordinates in the parameter grid (small images on screen) */
    9 /* evolving = flag, gridsz = dimensions of image grid (gridsz x gridsz) */
   10 int px,py,evolving,gridsz;
   11 #define MAXGRIDSZ 51  /* This is arbitrary, = 1024/20 */
   12 static int far ecountbox[MAXGRIDSZ][MAXGRIDSZ];
   13 
   14 unsigned int this_gen_rseed;
   15 /* used to replay random sequences to obtain correct values when selecting a
   16    seed image for next generation */
   17 
   18 double opx,opy,newopx,newopy,paramrangex,paramrangey,dpx,dpy,fiddlefactor;
   19 double fiddle_reduction;
   20 double parmzoom;
   21 char odpx,odpy,newodpx,newodpy;
   22 /* offset for discrete parameters x and y..*/
   23 /* used for things like inside or outside types, bailout tests, trig fn etc */
   24 /* variation factors, opx,opy, paramrangex/y dpx, dpy.. used in field mapping
   25    for smooth variation across screen. opx =offset param x, dpx = delta param
   26    per image, paramrangex = variation across grid of param ...likewise for py */ 
   27 /* fiddlefactor is amount of random mutation used in random modes ,
   28    fiddle_reduction is used to decrease fiddlefactor from one generation to the
   29    next to eventually produce a stable population */
   30 
   31 U16 prmboxhandle = 0;
   32 U16 imgboxhandle = 0;
   33 int prmboxcount,imgboxcount;
   34 U16 oldhistory_handle = 0;
   35 char s_random[] = "random";
   36 char s_spread[] = "spread";
   37 char s_xplusy[] = "x+y";
   38 char s_xminusy[] = "x-y";
   39 
   40 struct phistory_info      /* for saving evolution data of center image */
   41 {
   42    double param0;
   43    double param1;
   44    double param2;
   45    double param3;
   46    double param4;
   47    double param5;
   48    double param6;
   49    double param7;
   50    double param8;
   51    double param9;
   52    int inside;
   53    int outside;
   54    int decomp0;
   55    double invert0;
   56    double invert1;
   57    double invert2;
   58    BYTE trigndx0;
   59    BYTE trigndx1;
   60    BYTE trigndx2;
   61    BYTE trigndx3;
   62    int bailoutest;
   63 };
   64 
   65 typedef struct phistory_info    PARAMHIST;
   66 
   67 void param_history(int mode);
   68 void varydbl(GENEBASE gene[],int randval,int i);
   69 int varyint( int randvalue, int limit, int mode);
   70 int wrapped_positive_varyint( int randvalue, int limit, int mode );
   71 void varyinside(GENEBASE gene[], int randval, int i);
   72 void varyoutside(GENEBASE gene[], int randval, int i);
   73 void varypwr2(GENEBASE gene[], int randval, int i);
   74 void varytrig(GENEBASE gene[], int randval, int i);
   75 void varybotest(GENEBASE gene[], int randval, int i);
   76 void varyinv(GENEBASE gene[], int randval, int i);
   77 int explore_check(void);
   78 void spiralmap(int);
   79 static void set_random(int);
   80 void set_mutation_level(int);
   81 void SetupParamBox(void);
   82 void ReleaseParamBox(void);
   83 
   84 void initgene(void) /* set up pointers and mutation params for all usable image
   85                    control variables in fractint... revise as necessary when
   86                    new vars come along... dont forget to increment NUMGENES
   87                    (in fractint.h ) as well */
   88 {
   89  int i = 0;
   90  /* 0 = dont vary, 1= with x axis, 2 = with y */
   91  /* 3 = with x+y, 4 = with x-y, 5 = random, 6 = weighted random */
   92  /* Use only 15 letters below: 123456789012345 */
   93   static FCODE s_Param0[] =  {"Param 1 real"};
   94   static FCODE s_Param1[] =  {"Param 1 imag"};
   95   static FCODE s_Param2[] =  {"Param 2 real"};
   96   static FCODE s_Param3[] =  {"Param 2 imag"};
   97   static FCODE s_Param4[] =  {"Param 3 real"};
   98   static FCODE s_Param5[] =  {"Param 3 imag"};
   99   static FCODE s_Param6[] =  {"Param 4 real"};
  100   static FCODE s_Param7[] =  {"Param 4 imag"};
  101   static FCODE s_Param8[] =  {"Param 5 real"};
  102   static FCODE s_Param9[] =  {"Param 5 imag"};
  103   static FCODE s_inside[] =  {"inside colour"};
  104   static FCODE s_outside[] = {"outside colour"};
  105   static FCODE s_decomp[] =  {"decomposition"};
  106   static FCODE s_trigfn1[] = {"trig function 1"};
  107   static FCODE s_trigfn2[] = {"trig fn 2"};
  108   static FCODE s_trigfn3[] = {"trig fn 3"};
  109   static FCODE s_trigfn4[] = {"trig fn 4"};
  110   static FCODE s_botest[]  = {"bailout test"};
  111   static FCODE s_invertr[] = {"invert radius"};
  112   static FCODE s_invertx[] = {"invert center x"};
  113   static FCODE s_inverty[] = {"invert center y"};
  114 
  115   GENEBASE gene[NUMGENES] = {
  116     { &param[0],   varydbl,     5, "",1 },
  117     { &param[1],   varydbl,     5, "",1 },
  118     { &param[2],   varydbl,     0, "",1 },
  119     { &param[3],   varydbl,     0, "",1 },
  120     { &param[4],   varydbl,     0, "",1 },
  121     { &param[5],   varydbl,     0, "",1 },
  122     { &param[6],   varydbl,     0, "",1 },
  123     { &param[7],   varydbl,     0, "",1 },
  124     { &param[8],   varydbl,     0, "",1 },
  125     { &param[9],   varydbl,     0, "",1 },
  126     { &inside,     varyinside,  0, "",2 },
  127     { &outside,    varyoutside, 0, "",3 },
  128     { &decomp[0],  varypwr2,    0, "",4 },
  129     { &inversion[0],varyinv,    0, "",7 },
  130     { &inversion[1],varyinv,    0, "",7 },
  131     { &inversion[2],varyinv,    0, "",7 },
  132     { &trigndx[0], varytrig,    0, "",5 },
  133     { &trigndx[1], varytrig,    0, "",5 },
  134     { &trigndx[2], varytrig,    0, "",5 },
  135     { &trigndx[3], varytrig,    0, "",5 },
  136     { &bailoutest, varybotest,  0, "",6 }
  137   };
  138   i = -1;
  139   far_strcpy(gene[++i].name, s_Param0); /* name of var for menus */
  140   far_strcpy(gene[++i].name, s_Param1);
  141   far_strcpy(gene[++i].name, s_Param2);
  142   far_strcpy(gene[++i].name, s_Param3);
  143   far_strcpy(gene[++i].name, s_Param4);
  144   far_strcpy(gene[++i].name, s_Param5);
  145   far_strcpy(gene[++i].name, s_Param6);
  146   far_strcpy(gene[++i].name, s_Param7);
  147   far_strcpy(gene[++i].name, s_Param8);
  148   far_strcpy(gene[++i].name, s_Param9);
  149   far_strcpy(gene[++i].name, s_inside);
  150   far_strcpy(gene[++i].name, s_outside);
  151   far_strcpy(gene[++i].name, s_decomp);
  152   far_strcpy(gene[++i].name, s_invertr);
  153   far_strcpy(gene[++i].name, s_invertx);
  154   far_strcpy(gene[++i].name, s_inverty);
  155   far_strcpy(gene[++i].name, s_trigfn1);
  156   far_strcpy(gene[++i].name, s_trigfn2);
  157   far_strcpy(gene[++i].name, s_trigfn3);
  158   far_strcpy(gene[++i].name, s_trigfn4);
  159   far_strcpy(gene[++i].name, s_botest);
  160 
  161   if (gene_handle == 0)
  162      gene_handle = MemoryAlloc((U16)sizeof(gene),1L,FARMEM);
  163   MoveToMemory((BYTE *)&gene, (U16)sizeof(gene), 1L, 0L, gene_handle);
  164 }
  165 
  166 void param_history(int mode)
  167 { /* mode = 0 for save old history,
  168      mode = 1 for restore old history */
  169 
  170    PARAMHIST oldhistory;
  171 
  172    if (oldhistory_handle == 0)
  173       oldhistory_handle = MemoryAlloc((U16)sizeof(oldhistory),1L,FARMEM);
  174 
  175    if (mode == 0) { /* save the old parameter history */
  176       oldhistory.param0 = param[0];
  177       oldhistory.param1 = param[1];
  178       oldhistory.param2 = param[2];
  179       oldhistory.param3 = param[3];
  180       oldhistory.param4 = param[4];
  181       oldhistory.param5 = param[5];
  182       oldhistory.param6 = param[6];
  183       oldhistory.param7 = param[7];
  184       oldhistory.param8 = param[8];
  185       oldhistory.param9 = param[9];
  186       oldhistory.inside = inside;
  187       oldhistory.outside = outside;
  188       oldhistory.decomp0 = decomp[0];
  189       oldhistory.invert0 = inversion[0];
  190       oldhistory.invert1 = inversion[1];
  191       oldhistory.invert2 = inversion[2];
  192       oldhistory.trigndx0 = trigndx[0];
  193       oldhistory.trigndx1 = trigndx[1];
  194       oldhistory.trigndx2 = trigndx[2];
  195       oldhistory.trigndx3 = trigndx[3];
  196       oldhistory.bailoutest = bailoutest;
  197       MoveToMemory((BYTE *)&oldhistory, (U16)sizeof(oldhistory), 1L, 0L, oldhistory_handle);
  198    }
  199 
  200    if (mode == 1) { /* restore the old parameter history */
  201       MoveFromMemory((BYTE *)&oldhistory, (U16)sizeof(oldhistory), 1L, 0L, oldhistory_handle);
  202       param[0] = oldhistory.param0;
  203       param[1] = oldhistory.param1;
  204       param[2] = oldhistory.param2;
  205       param[3] = oldhistory.param3;
  206       param[4] = oldhistory.param4;
  207       param[5] = oldhistory.param5;
  208       param[6] = oldhistory.param6;
  209       param[7] = oldhistory.param7;
  210       param[8] = oldhistory.param8;
  211       param[9] = oldhistory.param9;
  212       inside = oldhistory.inside;
  213       outside = oldhistory.outside;
  214       decomp[0] = oldhistory.decomp0;
  215       inversion[0] = oldhistory.invert0;
  216       inversion[1] = oldhistory.invert1;
  217       inversion[2] = oldhistory.invert2;
  218       invert = (inversion[0] == 0.0) ? 0 : 3 ;
  219       trigndx[0] = oldhistory.trigndx0;
  220       trigndx[1] = oldhistory.trigndx1;
  221       trigndx[2] = oldhistory.trigndx2;
  222       trigndx[3] = oldhistory.trigndx3;
  223       bailoutest = oldhistory.bailoutest;
  224    }
  225 }
  226 
  227 void varydbl(GENEBASE gene[],int randval,int i) /* routine to vary doubles */
  228 {
  229 int lclpy = gridsz - py - 1;
  230    switch(gene[i].mutate) {
  231     default:
  232     case 0:
  233        break;
  234     case 1:
  235        *(double *)gene[i].addr = px * dpx + opx; /*paramspace x coord * per view delta px + offset */
  236        break;
  237     case 2: 
  238        *(double *)gene[i].addr = lclpy * dpy + opy; /*same for y */
  239        break;
  240     case   3:
  241        *(double *)gene[i].addr = px*dpx+opx +(lclpy*dpy)+opy; /*and x+y */
  242        break;
  243     case 4:
  244        *(double *)gene[i].addr = (px*dpx+opx)-(lclpy*dpy+opy); /*and x-y*/
  245        break;
  246     case 5:
  247        *(double *)gene[i].addr += (((double)randval / RAND_MAX) * 2 * fiddlefactor) - fiddlefactor;
  248        break;
  249     case 6:  /* weighted random mutation, further out = further change */
  250        {
  251        int mid = gridsz /2;
  252        double radius =  sqrt( sqr(px - mid) + sqr(lclpy - mid) );
  253        *(double *)gene[i].addr += ((((double)randval / RAND_MAX) * 2 * fiddlefactor) - fiddlefactor) * radius;
  254        }
  255        break;
  256    }
  257 return;
  258 }
  259 
  260 int varyint( int randvalue, int limit, int mode)
  261 {
  262 int ret = 0;
  263 int lclpy = gridsz - py - 1;
  264  switch(mode) {
  265    default:
  266    case 0:
  267      break;
  268    case 1: /* vary with x */
  269      ret = (odpx+px)%limit;
  270      break;
  271    case 2: /* vary with y */
  272      ret = (odpy+lclpy)%limit;
  273      break;
  274    case 3: /* vary with x+y */
  275      ret = (odpx+px+odpy+lclpy)%limit;
  276      break;
  277    case 4: /* vary with x-y */
  278      ret = (odpx+px)-(odpy+lclpy)%limit;
  279      break;
  280    case 5: /* random mutation */
  281      ret = randvalue % limit;
  282      break;
  283    case 6:  /* weighted random mutation, further out = further change */
  284      {
  285      int mid = gridsz /2;
  286      double radius =  sqrt( sqr(px - mid) + sqr(lclpy - mid) );
  287      ret = (int)((((randvalue / RAND_MAX) * 2 * fiddlefactor) - fiddlefactor) * radius);
  288      ret %= limit;
  289      }
  290        break;
  291  }
  292  return(ret);
  293 }
  294 
  295 int wrapped_positive_varyint( int randvalue, int limit, int mode )
  296 {
  297    int i;
  298    i = varyint(randvalue,limit,mode);
  299    if (i < 0)
  300       return(limit + i);
  301    else
  302       return(i);
  303 }
  304 
  305 void varyinside(GENEBASE gene[], int randval, int i)
  306  {
  307    int choices[9]={-59,-60,-61,-100,-101,-102,-103,-104,-1};
  308    if (gene[i].mutate)
  309      *(int*)gene[i].addr=choices[wrapped_positive_varyint(randval,9,gene[i].mutate)];
  310    return;
  311  }
  312 
  313 void varyoutside(GENEBASE gene[], int randval, int i)
  314  {
  315    int choices[8]={-1,-2,-3,-4,-5,-6,-7,-8};
  316    if (gene[i].mutate)
  317      *(int*)gene[i].addr=choices[wrapped_positive_varyint(randval,8,gene[i].mutate)];
  318    return;
  319  }
  320 
  321 void varybotest(GENEBASE gene[], int randval, int i)
  322  {
  323    int choices[7]={Mod, Real, Imag, Or, And, Manh, Manr};
  324    if (gene[i].mutate) {
  325      *(int*)gene[i].addr=choices[wrapped_positive_varyint(randval,7,gene[i].mutate)];
  326      /* move this next bit to varybot where it belongs */
  327      setbailoutformula(bailoutest);
  328    }
  329    return;
  330  }
  331 
  332 void varypwr2(GENEBASE gene[], int randval, int i)
  333  {
  334   int choices[9]={0,2,4,8,16,32,64,128,256}; 
  335   if (gene[i].mutate)
  336     *(int*)gene[i].addr=choices[wrapped_positive_varyint(randval,9,gene[i].mutate)];
  337   return;
  338 }
  339 
  340 void varytrig(GENEBASE gene[], int randval, int i)
  341  {
  342   if (gene[i].mutate)
  343   /* Changed following to BYTE since trigfn is an array of BYTEs and if one */
  344   /* of the functions isn't varied, it's value was being zeroed by the high */
  345   /* BYTE of the preceeding function.  JCO  2 MAY 2001 */
  346      *(BYTE*)gene[i].addr=(BYTE)wrapped_positive_varyint(randval,numtrigfn,gene[i].mutate);
  347      /* replaced '30' with numtrigfn, set in prompts1.c */
  348   set_trig_pointers(5); /*set all trig ptrs up*/
  349   return;
  350  } 
  351 
  352 void varyinv(GENEBASE gene[], int randval, int i)
  353   {
  354    if (gene[i].mutate)
  355       varydbl(gene,randval,i);
  356    invert = (inversion[0] == 0.0) ? 0 : 3 ;
  357   }
  358 
  359 #define LOADCHOICES(X)     {\
  360    static FCODE tmp[] = { X };\
  361    far_strcpy(ptr,(char far *)tmp);\
  362    choices[++k]= ptr;\
  363    ptr += sizeof(tmp);\
  364    }
  365 
  366 /* --------------------------------------------------------------------- */
  367 /*
  368     get_evolve_params() is called from FRACTINT.C whenever the 'ctrl_e' key
  369     is pressed.  Return codes are:
  370       -1  routine was ESCAPEd - no need to re-generate the images
  371      0  minor variable changed.  No need to re-generate the image.
  372        1  major parms changed.  Re-generate the images.
  373 */
  374 int get_the_rest(void)
  375 {
  376   char *evolvmodes[]={s_no,s_x,s_y,s_xplusy,s_xminusy,s_random,s_spread};
  377   static FCODE o_hdg[]={"Variable tweak central 2 of 2"};
  378   int i,k,num, numtrig;
  379   char hdg[sizeof(o_hdg)];
  380   char far *choices[20];
  381   char far *ptr;
  382   struct fullscreenvalues uvalues[20];
  383   GENEBASE gene[NUMGENES];
  384 
  385   far_strcpy(hdg,o_hdg);
  386   ptr = (char far *)MK_FP(extraseg,0);
  387 
  388    MoveFromMemory((BYTE *)&gene, (U16)sizeof(gene), 1L, 0L, gene_handle);
  389 
  390    numtrig = (curfractalspecific->flags >> 6) & 7;
  391    if(fractype==FORMULA || fractype==FFORMULA ) {
  392       numtrig = maxfn;
  393       }
  394 
  395 choose_vars_restart:
  396 
  397    k = -1;
  398    for (num = MAXPARAMS; num < (NUMGENES - 5); num++) {
  399       choices[++k]=gene[num].name;
  400       uvalues[k].type = 'l';
  401       uvalues[k].uval.ch.vlen = 7;
  402       uvalues[k].uval.ch.llen = 7;
  403       uvalues[k].uval.ch.list = evolvmodes;
  404       uvalues[k].uval.ch.val =  gene[num].mutate;
  405    }
  406 
  407    for (num = (NUMGENES - 5); num < (NUMGENES - 5 + numtrig); num++) {
  408       choices[++k]=gene[num].name;
  409       uvalues[k].type = 'l';
  410       uvalues[k].uval.ch.vlen = 7;
  411       uvalues[k].uval.ch.llen = 7;
  412       uvalues[k].uval.ch.list = evolvmodes;
  413       uvalues[k].uval.ch.val =  gene[num].mutate;
  414    }
  415 
  416    if (curfractalspecific->calctype == StandardFractal &&
  417        (curfractalspecific->flags & BAILTEST) ) {
  418       choices[++k]=gene[NUMGENES - 1].name;
  419       uvalues[k].type = 'l';
  420       uvalues[k].uval.ch.vlen = 7;
  421       uvalues[k].uval.ch.llen = 7;
  422       uvalues[k].uval.ch.list = evolvmodes;
  423       uvalues[k].uval.ch.val =  gene[NUMGENES - 1].mutate;
  424    }
  425 
  426    LOADCHOICES("");
  427    uvalues[k].type = '*';
  428    LOADCHOICES("Press F2 to set all to off");
  429    uvalues[k].type ='*';
  430    LOADCHOICES("Press F3 to set all on");
  431    uvalues[k].type = '*';
  432    LOADCHOICES("Press F4 to randomize all");
  433    uvalues[k].type = '*';
  434 
  435    i = fullscreen_prompt(hdg,k+1,choices,uvalues,28,NULL);
  436 
  437    switch(i) {
  438      case F2: /* set all off */
  439        for (num = MAXPARAMS; num < NUMGENES; num++)
  440           gene[num].mutate = 0;
  441        goto choose_vars_restart;
  442      case F3: /* set all on..alternate x and y for field map */
  443        for (num = MAXPARAMS; num < NUMGENES; num ++ )
  444           gene[num].mutate = (char)((num % 2) + 1);
  445        goto choose_vars_restart;
  446      case F4: /* Randomize all */
  447        for (num =MAXPARAMS; num < NUMGENES; num ++ )
  448           gene[num].mutate = (char)(rand() % 6);
  449        goto choose_vars_restart;
  450      case -1:
  451        return(-1);
  452      default:
  453        break;
  454    }
  455 
  456    /* read out values */
  457    k = -1;
  458    for ( num = MAXPARAMS; num < (NUMGENES - 5); num++)
  459       gene[num].mutate = (char)(uvalues[++k].uval.ch.val);
  460 
  461    for (num = (NUMGENES - 5); num < (NUMGENES - 5 + numtrig); num++) 
  462       gene[num].mutate = (char)(uvalues[++k].uval.ch.val);
  463 
  464    if (curfractalspecific->calctype == StandardFractal &&
  465        (curfractalspecific->flags & BAILTEST) )
  466       gene[NUMGENES - 1].mutate = (char)(uvalues[++k].uval.ch.val);
  467 
  468    MoveToMemory((BYTE *)&gene, (U16)sizeof(gene), 1L, 0L, gene_handle);
  469    return(1); /* if you were here, you want to regenerate */
  470 }
  471 
  472 int get_variations(void)
  473 {
  474   char *evolvmodes[]={s_no,s_x,s_y,s_xplusy,s_xminusy,s_random,s_spread};
  475   static FCODE o_hdg[]={"Variable tweak central 1 of 2"};
  476   int i,k,num, numparams;
  477   char hdg[sizeof(o_hdg)];
  478   char far *choices[20];
  479   char far *ptr;
  480   struct fullscreenvalues uvalues[20];
  481   GENEBASE gene[NUMGENES];
  482   int firstparm = 0;
  483   int lastparm  = MAXPARAMS;
  484   int chngd = -1;
  485 
  486   far_strcpy(hdg,o_hdg);
  487   ptr = (char far *)MK_FP(extraseg,0);
  488 
  489    MoveFromMemory((BYTE *)&gene, (U16)sizeof(gene), 1L, 0L, gene_handle);
  490 
  491    if(fractype == FORMULA || fractype == FFORMULA) {
  492       if(uses_p1)  /* set first parameter */
  493          firstparm = 0;
  494       else if(uses_p2)
  495          firstparm = 2;
  496       else if(uses_p3)
  497          firstparm = 4;
  498       else if(uses_p4)
  499          firstparm = 6;
  500       else
  501          firstparm = 8; /* uses_p5 or no parameter */
  502 
  503       if(uses_p5) /* set last parameter */
  504          lastparm = 10;
  505       else if(uses_p4)
  506          lastparm = 8;
  507       else if(uses_p3)
  508          lastparm = 6;
  509       else if(uses_p2)
  510          lastparm = 4;
  511       else
  512          lastparm = 2; /* uses_p1 or no parameter */
  513    }
  514 
  515    numparams = 0;
  516    for (i = firstparm; i < lastparm; i++)
  517    {
  518       if (typehasparm(julibrot?neworbittype:fractype,i,NULL)==0) {
  519          if(fractype == FORMULA || fractype == FFORMULA)
  520            if(paramnotused(i))
  521               continue;
  522          break;
  523       }
  524       numparams++;
  525    }
  526 
  527    if (fractype != FORMULA && fractype != FFORMULA)
  528       lastparm = numparams;
  529 
  530 choose_vars_restart:
  531 
  532    k = -1;
  533    for (num = firstparm; num < lastparm; num++) {
  534       if(fractype == FORMULA || fractype == FFORMULA)
  535         if(paramnotused(num))
  536            continue;
  537       choices[++k]=gene[num].name;
  538       uvalues[k].type = 'l';
  539       uvalues[k].uval.ch.vlen = 7;
  540       uvalues[k].uval.ch.llen = 7;
  541       uvalues[k].uval.ch.list = evolvmodes;
  542       uvalues[k].uval.ch.val =  gene[num].mutate;
  543    }
  544 
  545    LOADCHOICES("");
  546    uvalues[k].type = '*';
  547    LOADCHOICES("Press F2 to set all to off");
  548    uvalues[k].type ='*';
  549    LOADCHOICES("Press F3 to set all on");
  550    uvalues[k].type = '*';
  551    LOADCHOICES("Press F4 to randomize all");
  552    uvalues[k].type = '*';
  553    LOADCHOICES("Press F6 for second page"); /* F5 gets eaten */
  554    uvalues[k].type = '*';
  555 
  556    i = fullscreen_prompt(hdg,k+1,choices,uvalues,92,NULL);
  557 
  558    switch(i) {
  559      case F2: /* set all off */
  560        for (num = 0; num < MAXPARAMS; num++)
  561           gene[num].mutate = 0;
  562        goto choose_vars_restart;
  563      case F3: /* set all on..alternate x and y for field map */
  564        for (num = 0; num < MAXPARAMS; num ++ )
  565           gene[num].mutate = (char)((num % 2) + 1);
  566        goto choose_vars_restart;
  567      case F4: /* Randomize all */
  568        for (num =0; num < MAXPARAMS; num ++ )
  569           gene[num].mutate = (char)(rand() % 6);
  570        goto choose_vars_restart;
  571      case F6: /* go to second screen, put array away first */
  572        MoveToMemory((BYTE *)&gene, (U16)sizeof(gene), 1L, 0L, gene_handle);
  573        chngd = get_the_rest();
  574        MoveFromMemory((BYTE *)&gene, (U16)sizeof(gene), 1L, 0L, gene_handle);
  575        goto choose_vars_restart;
  576      case -1:
  577        return(chngd);
  578      default:
  579        break;
  580    }
  581 
  582    /* read out values */
  583    k = -1;
  584    for (num = firstparm; num < lastparm; num++) {
  585       if(fractype == FORMULA || fractype == FFORMULA)
  586         if(paramnotused(num))
  587            continue;
  588       gene[num].mutate = (char)(uvalues[++k].uval.ch.val);
  589    }
  590 
  591    MoveToMemory((BYTE *)&gene, (U16)sizeof(gene), 1L, 0L, gene_handle);
  592    return(1); /* if you were here, you want to regenerate */
  593 }
  594 
  595 void set_mutation_level(int strength)
  596 {
  597 /* scan through the gene array turning on random variation for all parms that */
  598 /* are suitable for this level of mutation */
  599  int i;
  600  GENEBASE gene[NUMGENES];
  601  /* get the gene array from far memory */
  602  MoveFromMemory((BYTE *)&gene, (U16)sizeof(gene), 1L, 0L, gene_handle);
  603 
  604  for (i=0;i<NUMGENES;i++) {
  605    if(gene[i].level <= strength)
  606       gene[i].mutate = 5; /* 5 = random mutation mode */
  607    else
  608       gene[i].mutate = 0;
  609  }
  610  /* now put the gene array back in far memory */
  611  MoveToMemory((BYTE *)&gene, (U16)sizeof(gene), 1L, 0L, gene_handle);
  612  return;
  613 }
  614 
  615 int get_evolve_Parms(void)
  616 {
  617    static FCODE o_hdg[]={"Evolution Mode Options"};
  618    char hdg[sizeof(o_hdg)];
  619    char far *choices[20];
  620    char far *ptr;
  621    int oldhelpmode;
  622    struct fullscreenvalues uvalues[20];
  623    int i,j, k, tmp;
  624    int old_evolving,old_gridsz;
  625    int old_variations = 0;
  626    double old_paramrangex,old_paramrangey,old_opx,old_opy,old_fiddlefactor;
  627 
  628    /* fill up the previous values arrays */
  629    old_evolving      = evolving;
  630    old_gridsz        = gridsz;
  631    old_paramrangex   = paramrangex;
  632    old_paramrangey   = paramrangey;
  633    old_opx           = opx;
  634    old_opy           = opy;
  635    old_fiddlefactor  = fiddlefactor;
  636 
  637 get_evol_restart:
  638 
  639    far_strcpy(hdg,o_hdg);
  640    ptr = (char far *)MK_FP(extraseg,0);
  641    if ((evolving & RANDWALK)||(evolving & RANDPARAM)) {
  642    /* adjust field param to make some sense when changing from random modes*/
  643    /* maybe should adjust for aspect ratio here? */
  644       paramrangex = paramrangey = fiddlefactor * 2;
  645       opx = param[0] - fiddlefactor;
  646       opy = param[1] - fiddlefactor;
  647       /* set middle image to last selected and edges to +- fiddlefactor */
  648    }
  649 
  650    k = -1;
  651 
  652    LOADCHOICES("Evolution mode? (no for full screen)");
  653    uvalues[k].type = 'y';
  654    uvalues[k].uval.ch.val = evolving&1;
  655 
  656    LOADCHOICES("Image grid size (odd numbers only)");
  657    uvalues[k].type = 'i';
  658    uvalues[k].uval.ival = gridsz;
  659 
  660    if (explore_check()) {  /* test to see if any parms are set to linear */
  661                            /* variation 'explore mode' */
  662      LOADCHOICES("Show parameter zoom box?")
  663      uvalues[k].type = 'y';
  664      uvalues[k].uval.ch.val = ((evolving & PARMBOX) / PARMBOX);
  665 
  666      LOADCHOICES("x parameter range (across screen)");
  667      uvalues[k].type = 'f';
  668      uvalues[k].uval.dval = paramrangex;
  669 
  670      LOADCHOICES("x parameter offset (left hand edge)");
  671      uvalues[k].type = 'f';
  672      uvalues[k].uval.dval = opx;
  673 
  674      LOADCHOICES("y parameter range (up screen)");
  675      uvalues[k].type = 'f';
  676      uvalues[k].uval.dval = paramrangey;
  677 
  678      LOADCHOICES("y parameter offset (lower edge)");
  679      uvalues[k].type = 'f';
  680      uvalues[k].uval.dval= opy;
  681    }
  682 
  683      LOADCHOICES("Max random mutation");
  684      uvalues[k].type = 'f';
  685      uvalues[k].uval.dval = fiddlefactor;
  686 
  687      LOADCHOICES("Mutation reduction factor (between generations)");
  688      uvalues[k].type = 'f';
  689      uvalues[k].uval.dval = fiddle_reduction;
  690 
  691    LOADCHOICES("Grouting? ");
  692    uvalues[k].type = 'y';
  693    uvalues[k].uval.ch.val = !((evolving & NOGROUT) / NOGROUT); 
  694 
  695    LOADCHOICES("");
  696    uvalues[k].type = '*';
  697 
  698    LOADCHOICES("Press F4 to reset view parameters to defaults.");
  699    uvalues[k].type = '*';
  700 
  701    LOADCHOICES("Press F2 to halve mutation levels");
  702    uvalues[k].type = '*';
  703 
  704    LOADCHOICES("Press F3 to double mutation levels" );
  705    uvalues[k].type ='*';
  706 
  707    LOADCHOICES("Press F6 to control which parameters are varied");
  708    uvalues[k].type = '*';
  709    oldhelpmode = helpmode;     /* this prevents HELP from activating */
  710    helpmode = HELPEVOL; 
  711    i = fullscreen_prompt(hdg,k+1,choices,uvalues,255,NULL);
  712    helpmode = oldhelpmode;     /* re-enable HELP */
  713    if (i < 0) {
  714    /* in case this point has been reached after calling sub menu with F6 */
  715    evolving      = old_evolving;
  716    gridsz        = old_gridsz;
  717    paramrangex   = old_paramrangex;
  718    paramrangey   = old_paramrangey;
  719    opx           = old_opx;
  720    opy           = old_opy;
  721    fiddlefactor  = old_fiddlefactor;
  722 
  723       return(-1);
  724    }
  725 
  726    if (i == F4) {
  727       set_current_params();
  728       fiddlefactor = 1;
  729       fiddle_reduction = 1.0;
  730       goto get_evol_restart;
  731    }
  732    if (i==F2 ) {
  733       paramrangex = paramrangex / 2;
  734       opx = newopx = opx + paramrangex / 2;
  735       paramrangey = paramrangey / 2;
  736       opy = newopy = opy + paramrangey / 2;
  737       fiddlefactor = fiddlefactor / 2;
  738       goto get_evol_restart;
  739    }
  740    if (i==F3 ) {
  741     double centerx, centery;
  742       centerx = opx + paramrangex / 2;
  743       paramrangex = paramrangex * 2;
  744       opx = newopx = centerx - paramrangex / 2;
  745       centery = opy + paramrangey / 2;
  746       paramrangey = paramrangey * 2;
  747       opy = newopy = centery - paramrangey / 2;
  748       fiddlefactor = fiddlefactor * 2;
  749       goto get_evol_restart;
  750    }
  751 
  752    j = i;   
  753 
  754    /* now check out the results (*hopefully* in the same order <grin>) */
  755 
  756    k = -1;
  757 
  758    viewwindow = evolving = uvalues[++k].uval.ch.val;
  759 
  760    if (!evolving && i != F6)  /* don't need any of the other parameters JCO 12JUL2002 */
  761       return(1);              /* the following code can set evolving even if it's off */
  762 
  763    gridsz = uvalues[++k].uval.ival;
  764    tmp = sxdots / (MINPIXELS<<1);
  765    /* (sxdots / 20), max # of subimages @ 20 pixels per subimage */
  766    /* MAXGRIDSZ == 1024 / 20 == 51 */
  767    if (gridsz > MAXGRIDSZ)
  768       gridsz = MAXGRIDSZ;
  769    if (gridsz > tmp)
  770       gridsz = tmp;
  771    if (gridsz < 3)
  772       gridsz = 3;
  773    gridsz |= 1; /* make sure gridsz is odd */
  774    if (explore_check()) {
  775      tmp = (PARMBOX * uvalues[++k].uval.ch.val);
  776      if (evolving)
  777         evolving += tmp;
  778      paramrangex = uvalues[++k].uval.dval;
  779      newopx = opx = uvalues[++k].uval.dval;
  780      paramrangey = uvalues[++k].uval.dval;
  781      newopy = opy = uvalues[++k].uval.dval;
  782    }
  783 
  784      fiddlefactor = uvalues[++k].uval.dval;
  785 
  786      fiddle_reduction = uvalues[++k].uval.dval;
  787 
  788    if (!(uvalues[++k].uval.ch.val)) evolving = evolving + NOGROUT;
  789 
  790    viewxdots = (sxdots / gridsz)-2;
  791    viewydots = (sydots / gridsz)-2;
  792    if (!viewwindow) viewxdots=viewydots=0;
  793 
  794    i = 0;
  795 
  796    if ( evolving != old_evolving
  797     || (gridsz != old_gridsz) ||(paramrangex!= old_paramrangex)
  798     || (opx != old_opx ) || (paramrangey != old_paramrangey)
  799     || (opy != old_opy)  || (fiddlefactor != old_fiddlefactor)
  800     || (old_variations > 0) )
  801       i = 1;
  802 
  803    if (evolving && !old_evolving)
  804       param_history(0); /* save old history */
  805 
  806    if (!evolving && (evolving == old_evolving)) i = 0;
  807 
  808 if (j==F6) {
  809       old_variations = get_variations();
  810       set_current_params();
  811       if (old_variations > 0)
  812         {
  813           viewwindow = 1;
  814           evolving |= 1;   /* leave other settings alone */
  815         }
  816       fiddlefactor = 1;
  817       fiddle_reduction = 1.0;
  818       goto get_evol_restart;
  819    }
  820    return(i);
  821 }
  822 
  823 void SetupParamBox(void)
  824 {
  825    int vidsize;
  826    prmboxcount = 0;
  827    parmzoom=((double)gridsz-1.0)/2.0;
  828 /* need to allocate 2 int arrays for boxx and boxy plus 1 byte array for values */  
  829    vidsize = (xdots+ydots) * 4 * sizeof(int) ;
  830    vidsize = vidsize + xdots + ydots + 2 ;
  831    if (prmboxhandle == 0)
  832       prmboxhandle = MemoryAlloc((U16)(vidsize),1L,FARMEM);
  833    if (prmboxhandle == 0 ) {
  834      static FCODE msg[] = {"Sorry...can't allocate mem for parmbox"};
  835      texttempmsg(msg);
  836      evolving=0;
  837    }
  838    prmboxcount=0;
  839 
  840 /* vidsize = (vidsize / gridsz)+3 ; */ /* allocate less mem for smaller box */
  841 /* taken out above as *all* pixels get plotted in small boxes */
  842    if (imgboxhandle == 0)
  843       imgboxhandle = MemoryAlloc((U16)(vidsize),1L,FARMEM);
  844    if (!imgboxhandle) {
  845      static FCODE msg[] = {"Sorry...can't allocate mem for imagebox"};
  846      texttempmsg(msg);
  847    }
  848 }
  849 
  850 void ReleaseParamBox(void)
  851 {
  852    MemoryRelease(prmboxhandle);
  853    MemoryRelease(imgboxhandle);
  854    prmboxhandle = 0;
  855    imgboxhandle = 0; 
  856 }
  857 
  858 void set_current_params(void)
  859 {
  860    paramrangex = curfractalspecific->xmax - curfractalspecific->xmin;
  861    opx = newopx = - (paramrangex / 2);
  862    paramrangey = curfractalspecific->ymax - curfractalspecific->ymin;
  863    opy = newopy = - (paramrangey / 2);
  864    return;
  865 }
  866 
  867 void fiddleparms(GENEBASE gene[], int ecount)
  868 {
  869 /* call with px,py ... parameter set co-ords*/
  870 /* set random seed then call rnd enough times to get to px,py */ 
  871 /* 5/2/96 adding in indirection */ 
  872 /* 26/2/96 adding in multiple methods and field map */
  873 /* 29/4/96 going for proper handling of the whole gene array */
  874 /*         bung in a pile of switches to allow for expansion to any
  875            future variable types */
  876 /* 11/6/96 scrapped most of switches above and used function pointers 
  877            instead */
  878 /* 4/1/97  picking it up again after the last step broke it all horribly! */
  879 
  880  int i;
  881 
  882 /* when writing routines to vary param types make sure that rand() gets called
  883 the same number of times whether gene[].mutate is set or not to allow
  884 user to change it between generations without screwing up the duplicability
  885 of the sequence and starting from the wrong point */
  886 
  887 /* this function has got simpler and simpler throughout the construction of the
  888  evolver feature and now consists of just these few lines to loop through all
  889  the variables referenced in the gene array and call the functions required
  890  to vary them, aren't pointers marvellous! */
  891 
  892  if ((px == gridsz / 2) && (py == gridsz / 2)) /* return if middle image */
  893     return;
  894 
  895  set_random(ecount);   /* generate the right number of pseudo randoms */
  896 
  897  for (i=0;i<NUMGENES;i++)
  898     (*(gene[i].varyfunc))(gene,rand(),i);
  899 
  900 }
  901 
  902 static void set_random(int ecount)
  903 { /* This must be called with ecount set correctly for the spiral map. */
  904   /* Call this routine to set the random # to the proper value */
  905   /* if it may have changed, before fiddleparms() is called. */
  906   /* Now called by fiddleparms(). */
  907  int index,i;
  908 
  909  srand(this_gen_rseed);
  910  for (index=0;index < ecount;index++)
  911    for (i=0;i<NUMGENES;i++)
  912      rand();
  913 }
  914 
  915 int explore_check(void)
  916 {
  917 /* checks through gene array to see if any of the parameters are set to */
  918 /* one of the non random variation modes. Used to see if parmzoom box is */
  919 /* needed */
  920    int nonrandom = FALSE;
  921    int i;
  922    GENEBASE gene[NUMGENES];
  923    MoveFromMemory((BYTE *)&gene, (U16)sizeof(gene), 1L, 0L, gene_handle);
  924    for (i=0;i<NUMGENES && !(nonrandom);i++)
  925       if ((gene[i].mutate > 0) && (gene[i].mutate < 5)) nonrandom = TRUE;
  926    return(nonrandom);
  927 }
  928 
  929 void drawparmbox(int mode)
  930 {
  931 /* draws parameter zoom box in evolver mode */
  932 /* clears boxes off screen if mode=1, otherwise, redraws boxes */
  933 struct coords tl,tr,bl,br;
  934 int grout;
  935  if (!(evolving & PARMBOX)) return; /* don't draw if not asked to! */
  936  grout = !((evolving & NOGROUT)/NOGROUT) ;
  937  imgboxcount = boxcount;
  938  if (boxcount) {
  939    /* stash normal zoombox pixels */
  940    MoveToMemory((BYTE *)boxx,(U16)(boxcount*2),1L,0L,imgboxhandle);
  941    MoveToMemory((BYTE *)boxy,(U16)(boxcount*2),1L,1L,imgboxhandle);
  942    MoveToMemory((BYTE *)boxvalues,(U16)boxcount,1L,4L,imgboxhandle);
  943    clearbox(); /* to avoid probs when one box overlaps the other */
  944  }
  945  if (prmboxcount!=0)  { /* clear last parmbox */
  946    boxcount=prmboxcount;
  947    MoveFromMemory((BYTE *)boxx,(U16)(boxcount*2),1L,0L,prmboxhandle);
  948    MoveFromMemory((BYTE *)boxy,(U16)(boxcount*2),1L,1L,prmboxhandle);
  949    MoveFromMemory((BYTE *)boxvalues,(U16)boxcount,1L,4L,prmboxhandle);
  950    clearbox();
  951  }
  952 
  953  if (mode == 1) {
  954     boxcount = imgboxcount;
  955     prmboxcount = 0;
  956     return;
  957  }
  958 
  959  boxcount =0;
  960  /*draw larger box to show parm zooming range */
  961  tl.x = bl.x = ((px -(int)parmzoom) * (int)(dxsize+1+grout))-sxoffs-1;
  962  tl.y = tr.y = ((py -(int)parmzoom) * (int)(dysize+1+grout))-syoffs-1; 
  963  br.x = tr.x = ((px +1+(int)parmzoom) * (int)(dxsize+1+grout))-sxoffs;
  964  br.y = bl.y = ((py +1+(int)parmzoom) * (int)(dysize+1+grout))-syoffs;
  965 #ifndef XFRACT
  966  addbox(br);addbox(tr);addbox(bl);addbox(tl);
  967  drawlines(tl,tr,bl.x-tl.x,bl.y-tl.y);
  968  drawlines(tl,bl,tr.x-tl.x,tr.y-tl.y);
969 #else 970 boxx[0] = tl.x + sxoffs; 971 boxy[0] = tl.y + syoffs; 972 boxx[1] = tr.x + sxoffs; 973 boxy[1] = tr.y + syoffs; 974 boxx[2] = br.x + sxoffs; 975 boxy[2] = br.y + syoffs; 976 boxx[3] = bl.x + sxoffs; 977 boxy[3] = bl.y + syoffs; 978 boxcount = 8;
979 #endif 980 if(boxcount) { 981 dispbox(); 982 /* stash pixel values for later */ 983 MoveToMemory((BYTE *)boxx,(U16)(boxcount*2),1L,0L,prmboxhandle); 984 MoveToMemory((BYTE *)boxy,(U16)(boxcount*2),1L,1L,prmboxhandle); 985 MoveToMemory((BYTE *)boxvalues,(U16)boxcount,1L,4L,prmboxhandle); 986 } 987 prmboxcount = boxcount; 988 boxcount = imgboxcount; 989 if(imgboxcount) { 990 /* and move back old values so that everything can proceed as normal */ 991 MoveFromMemory((BYTE *)boxx,(U16)(boxcount*2),1L,0L,imgboxhandle); 992 MoveFromMemory((BYTE *)boxy,(U16)(boxcount*2),1L,1L,imgboxhandle); 993 MoveFromMemory((BYTE *)boxvalues,(U16)boxcount,1L,4L,imgboxhandle); 994 dispbox(); 995 } 996 return; 997 } 998 999 void set_evolve_ranges(void) 1000 { 1001 int lclpy = gridsz - py - 1; 1002 /* set up ranges and offsets for parameter explorer/evolver */ 1003 paramrangex=dpx*(parmzoom*2.0); 1004 paramrangey=dpy*(parmzoom*2.0); 1005 newopx=opx+(((double)px-parmzoom)*dpx); 1006 newopy=opy+(((double)lclpy-parmzoom)*dpy); 1007 1008 newodpx=(char)(odpx+(px-gridsz/2)); 1009 newodpy=(char)(odpy+(lclpy-gridsz/2)); 1010 return; 1011 } 1012 1013 void spiralmap(int count) 1014 { 1015 /* maps out a clockwise spiral for a prettier and possibly */ 1016 /* more intuitively useful order of drawing the sub images. */ 1017 /* All the malarky with count is to allow resuming */ 1018 1019 int i,mid,offset; 1020 i = 0; 1021 mid = gridsz / 2; 1022 if (count == 0) { /* start in the middle */ 1023 px = py = mid; 1024 return; 1025 } 1026 for(offset = 1; offset <= mid; offset ++) { 1027 /* first do the top row */ 1028 py = (mid - offset); 1029 for(px = (mid - offset)+1; px <mid+offset; px++) { 1030 i++; 1031 if (i==count) return; 1032 } 1033 /* then do the right hand column */ 1034 for (; py < mid + offset; py++) { 1035 i++; 1036 if (i == count ) return; 1037 } 1038 /* then reverse along the bottom row */ 1039 for (;px > mid - offset;px--) { 1040 i++; 1041 if (i == count) return; 1042 } 1043 /* then up the left to finish */ 1044 for (; py >= mid - offset; py-- ) { 1045 i++; 1046 if (i== count ) return; 1047 } 1048 } 1049 } 1050 1051 int unspiralmap(void) 1052 { 1053 /* unmaps the clockwise spiral */ 1054 /* All this malarky is to allow selecting different subimages */ 1055 /* Returns the count from the center subimage to the current px & py */ 1056 int mid; 1057 static int oldgridsz = 0; 1058 1059 mid = gridsz / 2; 1060 if ((px == mid && py == mid) || (oldgridsz != gridsz)) { 1061 int i, gridsqr; 1062 /* set up array and return */ 1063 gridsqr = gridsz * gridsz; 1064 ecountbox[px][py] = 0; /* we know the first one, do the rest */ 1065 for (i = 1; i < gridsqr; i++) { 1066 spiralmap(i); 1067 ecountbox[px][py] = i; 1068 } 1069 oldgridsz = gridsz; 1070 px = py = mid; 1071 return(0); 1072 } 1073 return(ecountbox[px][py]); 1074 } 1075 1076 /* points to ponder..... 1077 watch out for near mem..... (TW) It's better now. 1078 try and keep gene array in overlay? (TW) No, but try dynamic alloc. 1079 how to preserve 'what to mutate ' choices through overlay swaps in 1080 prompts... (TW) Needs checking, seems OK. LOADCHOICES copies, so is 1081 safe. 1082 */ 1083 1084