/*
 * Copyright (C) Andrew Wuensche
 *
 *  This file is part of DDLab (Discrete Dynamics Lab) <www.ddlab.org>
 *
 *  DDLab is free software: you can redistribute it and/or modify
 *  it under the terms of the GNU General Public License as published by
 *  the Free Software Foundation, either version 3 of the License, or
 *  (at your option) any later version.
 *
 *  This program is distributed in the hope that it will be useful,
 *  but WITHOUT ANY WARRANTY; without even the implied warranty of
 *  MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
 *  GNU General Public License for more details.
 *
 *  You should have received a copy of the GNU General Public License
 *  along with DDLab.  If not, see <http://www.gnu.org/licenses/>.
 */

/************** include/define 13 May 93 ********************/
#include "edecfunc.h"
/***************  list of functions in this file ************/
/*unsigned long fact(char num)*/
/* # if __UNIX__ unsigned long long longlong_fact(char num, char startnum)
   # endif  */
/*unsigned long long_fact(char num, char startnum)*/
unsigned long atolu(char *string);
void set_i2dxj2d(void);
/*void end_page(char cur_scale, char keyindex)*/
# if __UNIX__ 
void putimage_scroll(int x, int y, Pixmap *image, 
                  int drawing_mode);
# endif
/*void next_line(float chwidth,float lineht)*/
/*void setpback_x_lines(char xlines)*/
/*void print_current_state(char *temp,char color)*/
/*void print_current_state_h(char *temp,char color)*/
/*void print_current_state_twod(char *temp,char color,char zero_color)*/
/*signed int print_current_bitstring_hexbytes
	     (signed int maxlines, char isrule, char *array,char nhoodz,
		   signed int xright,signed int color,char printer)*/
/*void set_small_font(void)*/
/*void set_medium_font(void)*/
/*void restore_def_font(void)*/
/*unsigned long print_bit_line(char *temp,unsigned int size,
	    unsigned int color,signed int cellscale,
					signed int cellsep)*/
/*void dec_to_value_line(char* value_line,
                unsigned long decvalue, signed int size)*/
/*void dec_to_value_line_flex(char* value_line,
	   unsigned long decvalue, signed int size, 
	   unsigned char vr,signed int vb)*/
/*void dec_to_bit_line(char* bitline,
	      unsigned long decvalue, signed int size)*/

/*char define_hex(char nhoodz,char isrule,char *array,
            signed int hexbyteposl,
	     signed int hexbyteposr,float thisxtext)*/
void input_hex(char nhoodz, char isrule, char *array, 
    unsigned int hexbyteposl,unsigned int hexbyteposr,unsigned char hexfold);
void define_bits_prompts(char isrule);
/*void define_bits(char nhoodz,char isrule,char *array,
       unsigned int leftpos,unsigned int rightpos)*/
void showbitcount(char isrule,unsigned int leftpos,signed int zcount, 
	          signed int cellx,signed int cellscale,unsigned char left_value);
signed int input_string_cell(char nhoodz,char isrule,char* array,
       unsigned int leftpos,unsigned int  rightpos,char stringtype,
	 float cellscale,float cellsep,
             float endx,float endy);
signed int save_patch_2d(unsigned int patch_size, signed int bytesP,char *patch_buf,
		signed int st_i,signed int st_j, signed int en_i, signed int en_j);
void draw_and_set_value_line(char from_patch,char* array, char isrule,
  char this_value,unsigned int leftpos,
   unsigned int zcount, float this_cellscale,
    char this_show_2d_divs, char this_dots, unsigned char cellcolor,
      float x1, float y1, char z1);

/*void draw_hexagonal_2d_cell(double this_hex_rad,
       float this_cellscale,
           char this_show_2d_divs,char this_dots, unsigned char thiscolor,
                    unsigned char this_divcolor,
                   signed int x1,signed int y1);*/
/*void random_bits(char nhoodz, char isrule, char seed_all,
                char hex, char *array, unsigned int leftpos)*/
/*void set_fraction_values(char isrule,signed int thistotal);*/
/*void implement_fraction_values(char isrule,char seed_all,
                         char *thisarray,signed int thistotal)*/
unsigned int randpos_block(void);
/*unsigned int set_central_block(char keep,char *array)*/
/*void show_multistate_color_key(char show_delete)*/ 
/*signed int print_layered_bitstring(char *array, unsigned int leftpos,
	      char thisscale,char thissep, char makerandom, char isrule)*/
/*unsigned long dec_equiv(char *temparray, char leftpos)*/
/*unsigned long dec_equiv_flex(char *temparray, char leftpos, 
                        signed int vr,signed int vb)*/
/*unsigned int dec_equiv_sound(char *temparray,
		signed int leftpos, signed int rightpos)*/
/*unsigned char random_seed(unsigned char color1,
                      signed int rand_seed_percent,char show_density)*/
/*unsigned char random_bitflip_state(unsigned char color1)*/

void change_Z(char *array, char nhoodz, char what, char show);
/*unsigned char bit_flip(char what,unsigned char color1)*/
/*unsigned char bit_flipback(unsigned char color1)*/
/*#if __WATCOM__
  signed int vgax(signed int xcoord)
  signed int vgay(signed int ycoord)
#endif*/
/*char final_quit(void)*/
/*void outof_memory(char *what)*/
/*char canalyzing(char nhoodz,char showz,char* thisrule)*/
/*void z_parameter_all(char nhoodz, char showz, char *thisrule)*/
/*void z_parameter_all_mvalue(char nhoodz, char showz, char *thisrule)*/
/*void reflect_m_ruletable(char nhoodz, char *thisrule, char *revrule);*/
/*void set_bitlong(register char *array,
       register unsigned long pos,register char bit)*/
/*char get_bitlong(register char *array,register unsigned long pos)*/
/*signed int get_value(char *array, unsigned int ct_count)*/
/*signed int get_value_flex(char *array, unsigned int ct_count,
                                     signed int  vb)*/
/*void set_value(char *array, 
    unsigned int ct_count, signed int tempvalue)*/
/*void set_value_flex(char *array, 
    unsigned int ct_count,signed int tempvalue,signed int vb)*/
/*char* rotate_array(char nhoodz,char *array, char direction,
			 char isrule, signed int rotinterval)*/
/*char* rotate_array_2d(char *array,
                       char direction,signed int rotinterval)*/
double aspectratio; /*calculate aspect ratio for mobile patches in hex layout*/
char* move_patch_2d(char *array,char direction,signed int rotinterval);
char* jump_patch_2d(char *array,unsigned int leftpos,signed int zcount);
char* redraw_patch_2d(char *array);
char* flip_array_1d(char *array,
            unsigned int string_max,unsigned int string_bytes);
char* v_spin_array_2d(char *array);
char* v_spin_patch_2d(char *array,signed int startx,signed int endx,
		                  signed int starty,signed int endy);
char* flip_array_2d(char *array,char hv);
char* flip_patch_2d(char *array,char hv);
char* compliment_patch_2d(char *array);
char* fill_patch_2d(char *array, unsigned char left_value);
char* fill_rnd_patch_2d(char *array);
char* fill_fraction_values_patch_2d(char *array);
char* flip_array_3d(char *array,char hv);
char* v_spin_array_3d(char *array);
char* rotate_array_3d(char *array,
			 char direction,signed int rotinterval);

/*signed int rot_cycle_equiv(register char *array)*/
/*char rot_cycle_equiv_2d(register char *array)*/
/*signed int repeating_seg(register char *array)*/
/*void repeating_seg_2d(register char *array)*/
/*char trans_sym_2d(register char *array)*/

signed int rot_size,start_h3d,start_j2d;
char fscale,strict_density, misc_hex2d;

/*#if __UNIX__
   int poly[12];
#elif __WATCOM__
   signed int poly[12];
   #endif*/
double hex_rad;
char draw_3d_grid,pi_outline,show_2d_divs=1,gaps_in_string;
unsigned char divcolor=0;
char show_dots=0;
char exact_density_bias_set=0,/*=1 was very slow, changed Dec 2016*/
     thick_line,patch_only=0; /*to move just the defined patch*/
signed int topleftx,toplefty;/*file variable to locate movable patch*/
/*to 3d graphic as a vector postscript*/
char  *filename_3d_PS,file_ret;
float Rdensity; /*to set new independent density for fill_rnd_patch_2d(..*/
signed int Pi2d,Pj2d; /*i,j width,height for jump patch*/
/*************** return factorial of number *****************/
unsigned long fact(char num){
  unsigned int z;
  unsigned long factnum=1;
  
    for (z=1;z<=num;z++) factnum*=z;
    return factnum;
}

/*** return factorial of number, long long doesnt work for DOS ***/
#  if __UNIX__
unsigned long long longlong_fact(char num, char startnum){
  unsigned int z;
  unsigned long long factnum=1;
    /* if startnum=1 this is a normal factorial */
    for (z=startnum;z<=num;z++) factnum*=z;
    return factnum;
}
#  endif

/*************** return factorial of number (for DOS *************/
unsigned long long_fact(char num, char startnum){
  unsigned int z;
  unsigned long factnum=1;
    /* if startnum=1 this is a normal factorial */
    for (z=startnum;z<=num;z++) factnum*=z;

    return factnum;
}

/*** to convert string to unsigned long decimal number *******/
unsigned long atolu(char *string){
  double d_decno;
  unsigned long decno;

   d_decno=atof(string);
   /*fprintf(stderr,"\n float=%f",d_decno);*/
   decno=(unsigned long)d_decno;
   /*ruledec=(unsigned long)_atold(is);*/  
   /*_atold(is) this works for signed long only*/
   /*fprintf(stderr,"\n dec=%lu",decno);*/
   return(decno);

}
/********** set default i2dxj2d Oct 1999 *************/
void set_i2dxj2d(void){
  signed int tempi2d,z;
  char factor_found=0;

   for (z=(signed int)ceil(pow((double)lineL,.5));z>=1;z--){
      if (lineL%z==0){
         factor_found=1;
         break;
      }
   }
   if (factor_found==1){
      j2d=z;
      i2d=(signed int)ceil((double)lineL/j2d);
      if (j2d>i2d){ /*make sure i is bigger*/
         tempi2d=i2d;
         i2d=j2d;
         j2d=tempi2d;
      }
   }
   else{
     i2d=lineL;
     j2d=1;
   }
}
/************* print the next line (and scroll if set), 13 May 93 *************/
void end_page(char cur_scale, char keyindex){  /* scale = ca scrolling interval*/
#if __WATCOM__
 unsigned long imsize=0,pixno;
 unsigned long imsizelimit;
 signed int maxwidth;
#endif
  signed int tempx,tempy;

      /*note: unsigned int scrolly must be a global variable
          - it is refered to again*/

      /*dont do this if not showing space-time patterns*/
      if (stp==0) return;

      if (scrolling==0){ /*for backwards stp only*/
         moveto(0,gety+cur_scale);		
         if (Maxy-gety<cur_scale){
            setviewport(0, 0,lineL*cur_scale+2, Maxy, 1);
            clearviewport();
            setviewport(0, 0, Maxx, Maxy, 0);
            moveto(0,0);
         }
         return;
      }

      if (nowscrolling==0){
	 if (d_mode==1 /*|| d_mode==3*/ ) moveto(0,gety+cur_scale);
         else if (d_mode==2){
             pixmap_width=getx+cur_scale;
             moveto(getx,gety+cur_scale);
         }
         /*fprintf(stderr,"\n %d<%d erased=%d",
		 Maxx-pixmap_width,vgax(130)+3+cur_scale*3, 
		 onthefly_box_erased);*/
         
         if (d_mode==2 
             && Maxx-pixmap_width<vgax(130)+3+cur_scale*3
             && onthefly_box_erased==0){ //if about to overwrite
                 	tempx=getx;
			tempy=gety;
			//taller box for DOS
#                       if __UNIX__
			    erase_box(Maxx-vgax(130)-3,Maxy-vgay(424),
							  Maxx-2,Maxy-2);
#                       elif __WATCOM__
			    erase_box(Maxx-vgax(130)-3,2,Maxx-2,Maxy-2);
#                       endif
			//it->keyindex=0;
			moveto(tempx,tempy);
                        onthefly_box_erased=1;
	 }

         /*pixmap_width wset in for?.c*/
	 /*else if (d_mode==3){
             pixmap_width=cur_scale*i2d +
	       (signed int)(sin(PI/4)*cur_scale*j2d)+cur_scale;
             if (eg.showlookupfreq || eg.showeeg==1) 
                    pixmap_width+=(signed int)eg.eegwidth;           
	 }*/
         if ( (d_mode==1 && Maxy-gety<cur_scale) ||		 
      	      (d_mode==2 && Maxy-gety<cur_scale*3) || 
              (d_mode==2 && Maxx- pixmap_width<cur_scale*3) ||
              (d_mode==3 &&  Maxy-gety<cur_scale)  ) {
                          
	    nowscrolling=1;   /*scroll display*/
            scrolly=gety-cur_scale;
	    if (d_mode==1 || d_mode==2){ 
               scrolly=gety-cur_scale;
               moveto(0,gety+cur_scale); 
            }
            else if (d_mode==3){
	        //scrolly=gety-cur_scale+vgax(1);
	        scrolly=gety-cur_scale+1;
		//pixmap_width+=vgax(110);
            }

            /****** not xwindows ************/
#           if __WATCOM__
	       /*malloc for  maxwidth instead of pixmap_width
		 because *pixmap_width can change if grath_layout is set*/
	       maxwidth=Maxx;

	       imsizelimit=640000;
	       /*imsize=(unsigned long)
		   imagesize(0,cur_scale,
		   pixmap_width,scrolly+cur_scale);*/

               imsize=(unsigned long)
		   imagesize(0,cur_scale,
		   maxwidth,scrolly+cur_scale);

	       if (imsize>imsizelimit){
		  tempx=draw_prompt_box(2);		    
		  outtext("Not enough memory to scroll");
		  moveto(tempx,gety+CHeight);
		  outtext("return to continue by sweeps:");
		  input_string(1,0);
		  erase_prompt_box(2);
		  scrolling=nowscrolling=0;
		  moveto(0,0);
		  setviewport(0, 0, pixmap_width, Maxy, 1);
		  clearviewport();
		  setviewport(0, 0, Maxx, Maxy, 0);
		  return;
	       }
	       /*size of space-time pattern image in bytes*/
	       /*pixno=(unsigned long)
		     (pixmap_width*(scrolly+1));*/
                pixno=(unsigned long)
		     (maxwidth*(scrolly+1));
 
	       if ((stpimage = malloc(imsize)) == NULL){
	       	  tempx=draw_prompt_box(1);		    
		  sprintf(textb[0],"stpimage was %dx%d, pixno=%lu",
			 pixmap_width,scrolly+1,pixno);
		  outtext(
                     "Not enough memory to scroll, expect CRASH");
		  moveto(tempx,gety+CHeight);
		  outtext(textb[0]);
		  moveto(tempx,gety+CHeight);
		  outtext("return to continue by sweeps:");
		  scrolling=nowscrolling=0;
		  moveto(0,0);
		  input_string(1,0);
		  setviewport(0,0,pixmap_width,Maxy,1);
		  clearviewport();
		  setviewport(0, 0, Maxx, Maxy, 0); 
	       }
#           endif

	    /***** not xwindows (above) ********/   
	 }     
#        if __UNIX__
	    else {  /*if not scrolling yet*/	
                copy_part_image(current_draw,
		    &W,0,gety-cur_scale,0,
                         gety-cur_scale,pixmap_width,cur_scale);
	    }
#        endif

      }
      else{  /*if (nowscrolling==1)*/     
          setfillstyle(SOLID_FILL,black);
#         if __UNIX__              
             bar(0,scrolly,pixmap_width,Maxy);
             if (d_mode==1 || d_mode==3){ 
                copy_part_image(current_draw,current_draw,
                    0,cur_scale,0,0,pixmap_width,scrolly);
                putimage_scroll(0,0,current_draw,COPY_PUT);
	     }
             /*diagonal 2d scrolling 
               -- allow for keyindex if set, March 2016 for Genaro*/
             else if (d_mode==2){ 
               
               unsigned int rightx;
	        if (scrolly>Maxy-cur_scale) scrolly=Maxy-cur_scale;
                //if (keyindex==1) rightx=Maxx-vgax(130)-4-cur_scale;
                //to allow for draw_rule_box, forvarX.c 3401
                if (keyindex==1) rightx=Maxx-vgax(170+4);
                else rightx=Maxx;
                copy_part_image(current_draw,current_draw,
                      cur_scale,cur_scale,0,0,rightx,scrolly);
                putimage_scroll(0,0,current_draw,COPY_PUT);
	     }
                                        
#         elif __WATCOM__
             if (d_mode==1 || d_mode==3){

	        getimage(0,cur_scale,
                    pixmap_width,scrolly+cur_scale,stpimage);
	        bar(0,scrolly,pixmap_width,scrolly+cur_scale);
                sprintf(textb[9],"%s","stpimage");
                putimage(0,0,stpimage,COPY_PUT,textb[9]);
	        bar(0,scrolly-cur_scale,
                    pixmap_width,scrolly+cur_scale);
             }
             /*diagonal 2d scrolling 
                 -- allow for keyindex if set, March 2016 for Genaro*/
             else if (d_mode==2){               
               unsigned int rightx;
                if (keyindex==1) rightx=Maxx-vgax(130)-4-cur_scale;
                else rightx=Maxx;
                getimage(cur_scale,cur_scale,
                    rightx,scrolly+cur_scale,stpimage);
                sprintf(textb[9],"%s","stpimage");
                putimage(0,0,stpimage,COPY_PUT,textb[9]);
             }
#         endif
	  moveto(0,scrolly-cur_scale);
      }  
}

/*******************  put an image ************/   
# if __UNIX__ 
void putimage_scroll(int x, int y, Pixmap *image, 
                  int drawing_mode){
 Window	root_window;
 int	top, left;
 unsigned int	border, depth;
 unsigned int	width, height;
	
    if (*image == 0) {
       fprintf(stderr,
              "%s\n", "Zero image passed to putimage - putimage_scroll");
       /*input_string(1,0);*/
       return;
    }				
    if (XGetGeometry(D,*image, &root_window, 
      &top, &left, &width, &height, &border, &depth) == 0)
		fprintf(stderr, "%s\n", 
            "Failed to get Pixmap geometry in putimage");
    XCopyArea(D,*image,W,Gc,0,0,width,height,x,y);
}
# endif
/**** print the next line acc to width/height of text, 13 May 93 ********/
void next_line(float chwidth,float lineht){  /*to locate start of new line*/
 signed int hpix,vpix;

            hpix=(signed int)( chwidth * CWidth);
	    vpix=(signed int)( lineht * CHeight);
	    moveto(hpix,gety+vpix);
	    /*if (Maxy-gety<CHeight ){
		draw_prompt_box(1);
		outtext("attempting to write text below Maxy");
		input_string(1,0);
	    }*/
}

/************* step back x lines, Aug 93 **************************/
void setpback_x_lines(char xlines){
 signed int tempx,tempy;

	next_line(xtext,-xlines);
	tempx=getx;
	tempy=gety;
	//setfillstyle(SOLID_FILL,black);
        //bar(getx-2,gety+2,Maxx-3,gety+CHeight*(xlines+1)+2);
	setfillstyle(SOLID_FILL,black);
        bar(getx-vgax(2),gety+2,Maxx-vgax(3),gety+CHeight*(xlines+1)+vgay(2));
	moveto(tempx,tempy);
	next_line(xtext,-1);
}

/************* print CA state as line of cells May 93 *****************/
void print_current_state(char *temp, char color){
 signed int tempx,tempy;
 unsigned int zu;

   tempx=getx;
   tempy=gety;
   setcolor(white);
   setfillstyle(SOLID_FILL,black);
   bar(tempx,tempy,tempx+L*scale+scale-sep,tempy+scale-sep);
   for(zu=L;zu!=Maxu;zu--){
      if (value_range==2){
         if (get_bit(temp,zu)==1) 
             setfillstyle(SOLID_FILL,color);
         else setfillstyle(SOLID_FILL,darkgray);
      }
      else setfillstyle(SOLID_FILL,color_v[get_value(temp,zu)]);
      if (scale>3) bar(getx,gety,getx+scale-sep,gety+scale-sep);
      else bar(getx,gety,getx+scale,gety+scale);
      /*put a dot on zero cell*/
      if (scale>3 && get_value(temp,zu)==0) putpixel(getx-1+scale/2,gety-1+scale/2,green);
      moverel(scale,0);
   }
   moveto(tempx,tempy);
}

/********** print CA state as line of cells highlighted in box  **********/
void print_current_state_h(char *temp, char color){
 signed int tempx,tempy;
 unsigned int zu;
 char temp_color_v0;

   temp_color_v0=color_v[0];
   color_v[0]=darkgray;
   tempx=getx;
   tempy=gety;
   setcolor(white);
   setfillstyle(SOLID_FILL,black);
   if (hilight_learn && color!=white){
      bar(tempx-1,tempy-1,tempx+L*scale+scale-sep+1,tempy+scale-sep+1);
      //rectangle(tempx-2,tempy-2,tempx+L*scale+scale-sep+2,tempy+scale-sep+2);
      rectangle(tempx-2,tempy-2,tempx+L*scale+scale-sep+3,tempy+scale-sep+3);
   }
   else bar(tempx,tempy,tempx+L*scale+scale-sep,tempy+scale-sep);
   for(zu=L;zu!=Maxu;zu--){
      if (value_range>2 || get_value(temp,zu)==0) 
                  setfillstyle(SOLID_FILL,color_v[get_value(temp,zu)]);
      else setfillstyle(SOLID_FILL,color); /*for v=2 graphic nodes in basins to change color*/ 
      if (scale>3 && node_tight==0) bar(getx,gety,getx+scale-sep,gety+scale-sep);
      else bar(getx,gety,getx+scale,gety+scale);
      /*put a dot on zero cell*/
      if (scale>3 && node_dots==1 && get_value(temp,zu)==0) 
                 putpixel(getx-1+scale/2,gety+scale/2,green);
      moverel(scale,0);
   }
   color_v[0]=temp_color_v0;
   moveto(tempx,tempy);
}

/************* print CA state in 2d in May 93 *****************/
void print_current_state_twod(char *temp, char color, char zero_color){
 signed int zz=0,tempx,tempy,leftoff;
 unsigned int zu;
 char temp_color_v0;

   tempx=getx;
   tempy=gety;
   
   if (zero_color==1){
      temp_color_v0=color_v[0];
      color_v[0]=darkgray;
   }   

   if (scale>3 && node_tight==0) leftoff=2;
   else leftoff=1;

   setcolor(white);
   setfillstyle(SOLID_FILL,black);
   if (hilight_learn && color!=white){
      bar(tempx-leftoff-2,tempy-leftoff-2,tempx+i2d*scale+2,tempy+j2d*scale+2);
      rectangle
	(tempx-leftoff-2,tempy-leftoff-2,tempx+i2d*scale+2,tempy+j2d*scale+2);
   }
   else bar(tempx-leftoff,tempy-leftoff,tempx+i2d*(scale),tempy+j2d*scale);

   for (zu=L;zu!=Maxu;zu--){
      zz+=1;
      if (value_range>2 || get_value(temp,zu)==0) 
                  setfillstyle(SOLID_FILL,color_v[get_value(temp,zu)]);
      else setfillstyle(SOLID_FILL,color); 
      /*for v=2 graphic nodes in basins to change color*/ 
    
      bar(getx,gety,getx+scale-leftoff,gety+scale-leftoff);

      if (scale>3  && node_dots==1 && get_value(temp,zu)==0)
                 putpixel(getx-1+scale/2,gety+scale/2,green);
      moverel(scale,0);
      if (zz%i2d==0) moveto(tempx,gety+scale);
   }
   rectangle(tempx-leftoff,tempy-leftoff,tempx+i2d*(scale),tempy+j2d*scale);
   if (zero_color==1) color_v[0]=temp_color_v0;
   moveto(tempx,tempy);
}

/******************** print current rule in hex **********************/
signed int print_current_bitstring_hexbytes(signed int maxlines, 
            char isrule, char *array, char nhoodz,
		   signed int xright, signed int color, char printer){
 char reduce_anyway=0;
 float xmove;
 signed int startx,tempx,
    tempx0,tempy0,
    lineno=0,/*no of lines needed*/       /*printer - (xterm)*/
    temp,                          /*   =0..screen only*/
    z,size,countz=0,countzz=0;     /*   =1..screen + printer/file*/
 unsigned char bytez=0,tempcolor,  /*   =2..screen, getx at end*/
    stop_printing=0;		   /*   =3..printer(xterm)/file only*/
 				   /*   =4..screen only in interrupt_stp_box*/
                                   /*   =5..screen only in wiring matrix*/
                                   /*   =6..screen wiring matrix + xterm*/
			           /*   =7..(global) bigbuf only*/
                                   /*   =8..screen + bigbuf (for wiring-matrix)*/
                                   
                                   /*isrule: 3=v-tot
                                             2=t-tot
                                             1=rule
                                             0=state
                                             4=iso-rule*/
#  if __WATCOM__                             
      xmove=2.5;
#  elif __UNIX__
      xmove=2; 
#  elif __LINUX__
      xmove=2.3;
#  endif

   tempx0=getx;
   tempy0=gety;

   startx=getx;
   tempcolor=getcolor();
   setcolor(color);
   if (isrule==3) isrule=2; /*isrule==3 is superseded*/
   if (isrule==4){/*isotropic ruletable*/
     size=(signed int)ceil(value_bits * (double)(iso_tablemax+1)/8);
   }
   else if (isrule==0 || nhoodz==0 || nhoodz==-2){  /*bytes in CA line*/
      size=(signed int)ceil( (double)(lineL*value_bits)/8);
      temp=32; /*was 64 */      
      if (xright<Maxx) temp=16;
   }
   else if (isrule==1 || isrule==11)  /*bytes in full rule table, min=1 (why 11 ??*/
       size=(signed int)ceil(value_bits * pow(value_range,(double)nhoodz)/8);
   else if (isrule==2){ 
      if (totalistic==1) /*totalistic tcode*/
          size=(signed int)ceil(value_bits * (double)(nhoodz*(value_range-1)+1)/8);
      else if (totalistic==2) 
         size=(signed int) /*bytes for k-code*/
            ceil(value_bits * (double)(v_tablecodemax[nhoodz]+1)/8);
   }
   //fprintf(stderr,"\n isrule=%d size=%d\n",isrule,size);

   if (isrule){
      temp=32;
      if (printer==4 || xright<Maxx) temp=16;
   }
   /*reduce size of font if in top-right win, or if hexchars>64*/
   if (getx>=Maxx*.75 && printer!=5  && printer!=6) reduce_anyway=1;
   if (printer!=8 && printer!=7){
      if (reduce_anyway==1 || (isrule && size>32  && printer!=5  && printer!=6) 
                                || (!isrule && size>32)){
          if (size>512) set_small_font(); 
          else set_medium_font();
          temp=64;
          xmove=2.3;
      }
   }
   if (printer==8) sprintf(bigbuf,"");

   for (z=size-1;z>=0;z--){
      bytez=array[z];
      countz+=1;
      countzz+=1;
      
      if (printer==3){ /*don't leave gaps*/
         if (bytez<16) sprintf(textb[1],"0%x",bytez);
         else sprintf(textb[1],"%x",bytez);
      }
      else{ /*leave gaps - xx xx xx*/
         if (bytez<16) sprintf(textb[1],"0%x ",bytez);
         else sprintf(textb[1],"%x ",bytez);
      }

      if (printer==7){  /*add to global bigbuf*/
            if (z==size-1) sprintf(bigbuf,"%s",textb[1]);
            memmove(bigbuf+2*(size-1-z),textb[1],2);
      }
      else if (printer==8 && countzz<=32){
	    /*for postScript file*/
            if (z==size-1) sprintf(bigbuf,"%s",textb[1]);
	    memmove(bigbuf+3*(size-1-z),textb[1],3);
            if (z==0)  memmove(bigbuf+3*(size-1-z)+3,"\n",2); /*to end the string*/
      } 
      
      else{
         if (printer==6) fprintf(stderr,"%s",textb[1]);
         /*print and/or save data*/
         if ((pdata || filedata) && (printer==1 || printer==3)){
            if (pdata) fprintf(stderr,"%s",textb[1]);
            if (filedata) save_data(textb[1]);
         }
      }
     
      tempx=getx;
      if (printer!=3 && printer!=7 /*&& printer!=8*/ && stop_printing==0) outtext(textb[1]);
      if (nhoodz!=-2){
	 moveto(tempx+CWidth*xmove,gety);

	 if ((countz==temp && printer<5) || getx>xright-vgax(8)){
            moveto(startx,gety+CHeight);	    
	    lineno++;
	    countz=0;
 
            /*if (printer==5 || printer==6 || printer==8) stop_printing=1;
	    else{
                moveto(startx,gety+CHeight);	    
	        lineno++;
	        countz=0;
	    }*/	    
	 }
      }

      /*to limit no of lines of hex output*/
      if (maxlines>0 && lineno>=maxlines) break;
   }
   if (nhoodz!=-2 && printer!=2) next_line(xtext,-lineno);
   if (printer!=8 && printer!=7){
      if (reduce_anyway==1 || (isrule && size>32  && printer!=5  && printer!=6) 
                                || (!isrule && size>32)){
        /*restore character size*/    
         restore_def_font();
      }
   }  
   setcolor(tempcolor);
   moveto(tempx0,tempy0);
   return(lineno-1);
}

/****** set a small size font .6 or.8 of default size  *************/
void set_small_font(void){
     
#      if __WATCOM__ /*problem here causing seg fault*/
         signed int thisfont;
             restore_def_font(); /*moved just for DOS */
	     if (hires==0){
                thisfont=sfont+2;/*small 640x480*/
                if (thisfont>3) thisfont=3;
             } 
	     else if (hires==1 || hires==2){
                thisfont=sfont+2;/*small 640x480*/
                if (thisfont>6) thisfont=6;
             }
             sprintf(textb[4],"n%d",thisfont);
             _setfont(textb[4]);
	     _getfontinfo(&info);
	     CHeight=info.pixheight;
             CWidth=info.avgwidth;
             font_d_m_s='s'; /*keep track of font: d=default, m=medium, s=small*/
 

/*this gave seg fault with suse linux 
 because correct fonts were missing
 the folowing should be in /etc/X11/XF86Config 
 FontPath      "/usr/X11R6/lib/X11/fonts/misc"
 FontPath      "/usr/X11R6/lib/X11/fonts/75dpi"
 FontPath     "/usr/X11R6/lib/X11/fonts/100dpi"
 see also void setup_fonts(signed int p_size) in g_set*.c*/

#     elif __UNIX__	   
            XSetFont(D,Gc,smallpropfont->fid);
            //CWidth*=.6;
            //CHeight*=.6;
            CWidth=CWidth_def*.6;
            CHeight=CHeight_def*.6;
            font_d_m_s='s'; /*keep track of font: d=default, m=medium, s=small*/	 
#     endif
   
}
    
/****** set a small size font .8 or.9 of default size  *************/    
void set_medium_font(void){
     
#      if __WATCOM__ /*problem here causing seg fault*/
         signed int thisfont;
	     restore_def_font(); /*moved just for DOS */
	     if (hires==0){
                thisfont=sfont+1;/*small 640x480*/
                if (thisfont>3) thisfont=3;
             } 
	     else if (hires==1 || hires==2){
                thisfont=sfont+1;/*small 640x480*/
                if (thisfont>6) thisfont=6;
             }
             sprintf(textb[4],"n%d",thisfont);
             _setfont(textb[4]);
	     _getfontinfo(&info);
	     CHeight=info.pixheight;
             CWidth=info.avgwidth;
             font_d_m_s='m'; /*keep track of font: d=default, m=medium, s=small*/

#     elif __UNIX__
            XSetFont(D,Gc,mediumpropfont->fid);
            //CWidth*=.8;
            //CHeight*=.8;
            CWidth=CWidth_def*.8;
            CHeight=CHeight_def*.8;

            font_d_m_s='m'; /*keep track of font: d=default, m=medium, s=small*/
#     endif
    
}
/******************** restore default font  *******************/
void restore_def_font(void){

#     if __WATCOM__  /*problem here causing seg fault*/ 
           sprintf(textb[4],"n%d",sfont);
           _setfont(textb[4]);   
	   _getfontinfo(&info);
	   CHeight=info.pixheight;
	   CWidth=info.avgwidth;

  
	 /*	 _setcharsize(ty1,tx1);            
		 _gettextsettings(&ts);*/
#     elif __UNIX__         
         XSetFont(D,Gc,propfont->fid);
         CHeight=CHeight_def;
         CWidth=CWidth_def;
#     endif
      
      font_d_m_s='d'; /*keep track of font: d=default, m=medium, s=small*/
}

/******************** print bit line, May 93 *******************/
unsigned long print_bit_line(char *temp,unsigned int size,
	    unsigned int color,signed int cellscale,
					signed int cellsep){
 unsigned int zu;
 unsigned long decnumber=0;
 char state_dec_ok=0;

   if (  (value_range==2 && lineL<=32) ||
         (value_range==3 && lineL<=20) ||
         (value_range==4 && lineL<=16) ||
         (value_range==5 && lineL<=13) ||
         (value_range==6 && lineL<=12) ||
         (value_range==7 && lineL<=11) ||
         (value_range==8 && lineL<=10)) state_dec_ok=1;
   if (state_dec_ok==0) return(0);

   for (zu=size-1;zu!=Maxu;zu--){
      if (value_range==2){
              decnumber+=(unsigned long)(get_bit(temp,zu)*pow(2,(double)zu));
         if (get_bit(temp,zu)) setfillstyle(SOLID_FILL,color);
         else setfillstyle(SOLID_FILL,darkgray);
      }
      else{ 
         decnumber+=(unsigned long)(get_value(temp,zu)*pow(value_range,(double)zu));
         setfillstyle(SOLID_FILL, 
                 color_v[get_value(temp,(unsigned int)zu)]);
      }
      bar(getx,gety,getx+cellscale-cellsep,gety+cellscale-cellsep);
      moverel(cellscale,0);
   }
   return(decnumber);
}

/********** convert dec to bitstring, max 32 bits, May 93 **************/
void dec_to_value_line(char* value_line,
	      unsigned long decvalue, signed int size){
 signed int z; /*max z=31*/
 unsigned long tempvalue,this_value;

 /*fprintf(stderr,"\n dec_to_value_line, decv=%lu size=%d",decvalue,size);*/
   tempvalue=decvalue;
   for (z=size-1; z>=0; z--){
     /*fprintf(stderr,"\n z=%d",z);*/
      set_value(value_line,z,0);
      for (this_value=value_range-1;this_value>0;this_value--){
	/*fprintf(stderr," %lu:",this_value);*/
         if (tempvalue>=this_value*(unsigned long)pow(value_range,z)){
	   /*fprintf(stderr," if %lu>=%lu",
	     tempvalue,this_value*(unsigned long)pow(value_range,z));*/
	    set_value(value_line,z,(signed int)this_value);
	    tempvalue-=this_value*(unsigned long)pow(value_range,z);
            break;         
         }
      }
      /*fprintf(stderr,"%d",get_value(value_line,z));*/
   }
}

/******* convert dec to valuestring, any value range, Sept 2002  *********/
void dec_to_value_line_flex(char* value_line,
	   unsigned long decvalue, signed int size, 
                   signed int vr, signed int vb){
 signed int z; /*max z=31*/
 unsigned long tempvalue,this_value;

 /*fprintf(stderr,"\n dec_to_value_line, decv=%lu size=%d",decvalue,size);*/
   tempvalue=decvalue;
   for (z=size-1; z>=0; z--){
     /*fprintf(stderr,"\n z=%d",z);*/
      set_value_flex(value_line,z,0,vb);
      for (this_value=vr-1;this_value>0;this_value--){
	/*fprintf(stderr," %lu:",this_value);*/
         if (tempvalue>=this_value*(unsigned long)pow(vr,z)){
	   /*fprintf(stderr," if %lu>=%lu",
	     tempvalue,this_value*(unsigned long)pow(vr,z));*/
	    set_value_flex(value_line,z,(signed int)this_value,vb);
	    tempvalue-=this_value*(unsigned long)pow(vr,z);
            break;         
         }
      }
      /*fprintf(stderr,"%d",get_value(value_line,z));*/
   }
}

/********** convert dec to x-ary value string , max 32 bits, May 93 *********/
void dec_to_bit_line(char* bitline,
	      unsigned long decvalue, signed int size){
 signed int z; /*max z=31*/
 unsigned long tempvalue;

   tempvalue=decvalue;
   for (z=size-1; z>=0; z--){
      set_bit0(bitline,z);
      /*fprintf(stderr,"\n%d:%lu-%lu: ",z,
	tempvalue,(unsigned long)pow(2,z));*/
      if (tempvalue>=(unsigned long)pow(2,z)){
	 set_bit1(bitline,z);
	 tempvalue-=(unsigned long)pow(2,z);         
      }
      /*fprintf(stderr,"%d",get_bit(bitline,z));*/
   }
}

/*********** define range of hex bytes in char array, 8 Aug 93 *********/
char define_hex(char nhoodz,char isrule,
        char *array,
             signed int hexbyteposl,
	     signed int hexbyteposr,float thisxtext){

 signed int xbox,endx,endy,z,zz=0,hexfold,pair,tempx,tempy,thisx;
 char vcount=0, 
      bad_value_found=0; /* for value_range>2 */
 unsigned char hexval;
 unsigned int string_size,string_bytes;
 
   tempx=getx;
   tempy=gety;
   if (isrule==4){
      get_prompt_box(8,4);
      xbox=draw_prompt_box(4);
   }
   else{
      get_prompt_box(9,2);
      xbox=draw_prompt_box(2);
   }
   
   outtext("enter hex, arrows-move");
   if (twod && !isrule) sprintf(textb[0],"rotate-l/r/u/d, accept-ret");
   else sprintf(textb[0],"rotate-l/r, accept-ret");
   moveto(xbox,gety+CHeight);
   outtext(textb[0]);

   if (isrule==4) moveto(xbox,gety+CHeight);/*for iso-rule*/
   else moveto(tempx,tempy);
   hexfold=16;
   string_bytes=hexbyteposl-hexbyteposr+1;

   if (isrule!=4) next_line(thisxtext,2);/*for iso-rule*/
   tempx=getx;
   tempy=gety;  
   
   if (isrule==1) 
         string_size=(unsigned int)pow(value_range,(double)nhoodz)-1;
   else if (isrule==2) 
     string_size=nhoodz*(value_range-1); //max index of tcode table
   else if (isrule==3) 
     string_size=v_tablecodemax[nhoodz]; //max index of kcode table
   else if (isrule==0) string_size=lineL-1;
   else if (isrule==4) string_size=iso_tablemax;
       
   if (string_bytes>32 && string_bytes<64){
      set_medium_font();          
      hexfold=16;
   }
   else if (string_bytes>64){
      set_small_font();          
      hexfold=32;
   }

 redraw:
   endx=0;
   
   for (z=hexbyteposl;z>=hexbyteposr;z--){
      zz+=1;
      for (pair=2;pair>=1;pair--){
	 thisx=getx;
	 if (pair==2)hexval=(array[z]&0xf0)>>4;
	 else if (pair==1) hexval=array[z]&0x0f;
	 sprintf(textb[0],"%x",hexval);
	 outtext(textb[0]);
	 moveto(thisx+CWidth,gety);
      }
      moveto(thisx+CWidth*2,gety);
      if (zz%hexfold == 0){
	 endx=getx;
         if (gety>=Maxy-CHeight*3-vgay(33)){
            moveto(tempx,gety+CHeight+3);
            outtext(" more");
            break; /*to stay in frame*/
         }
	 moveto(tempx,gety+CHeight+3);
      }
   }
   
   if (endx==0) endx=getx+CWidth;
   endy=gety+CHeight+3;

   moveto(tempx,tempy);
   input_hex(nhoodz,isrule,array,hexbyteposl,hexbyteposr,hexfold);
   if (value_range>2){
     signed int excess_bits;
     unsigned int zu;
     char *pstate1; 
      /*to correct entries outside value_range*/
      for (zu=0; zu<=string_size; zu++){
         if (get_value(array,zu)>value_range-1){
	    bad_value_found=1; 
            set_value(array,zu,value_range-1);
         }
      }    
      if (((string_size+1)*value_bits)%sizeof(char)!=0){
         excess_bits=(string_bytes*sizeof(char)) - 
                           ((string_size+1)*value_bits);
         pstate1=&array[string_bytes-1];
         for (z=7;z>=7-excess_bits;z--) set_bit0(pstate1,z);
      }
   }
      
   if (is[0]=='q') goto endFunc;
      
   if (is[0]=='r'){
      moveto(tempx,tempy);
      setfillstyle(SOLID_FILL,black);
      bar(getx,gety,endx,endy);
      is[0]=zz=endx=endy=0;
      goto redraw;
   }
   vcount=ceil( (double)string_size/hexfold );
   if (isrule!=2) moveto(tempx,tempy+vcount*(CHeight+3));

  endFunc:
   if (isrule==4) uncover_free_prompt_box(8);/*for iso-rule*/
   else uncover_free_prompt_box(9);
   restore_def_font();
   moveto(tempx,endy+CHeight+3);
   return(bad_value_found);
}

/*************** input hex in boxes, April 93 **************/
void input_hex(char nhoodz, char isrule, char *array, 
         unsigned int hexbyteposl,
         unsigned int hexbyteposr,
         unsigned char hexfold){
 signed int 
     test=0,tempx,tempy,startx;
 unsigned int string_bytes,hex_req,
     r_bytes,hexfold_bytes,zcount=0,z,count;
    
#  define showcount {\
      tempx=getx;\
      tempy=gety;\
      sprintf(textb[0],"hex count=%d",zcount);\
      inset_prompt_box(0,23,textb[0],'m');\
      moveto(tempx,tempy);}\

   string_bytes=hexbyteposl-hexbyteposr+1;
   showcount;

   r_bytes=2*(hexbyteposl-hexbyteposr+1); /*twice string length in bytes*/
   hexfold_bytes=hexfold*2;

#  if __WATCOM__
      fflush(stdin);
#  endif
   startx=getx;
   /* *is, char input buffer, must be big enough for largest hex array
    for rule = 2^13 = 32768 bits /8=4096  x2=8192 hex characters
    for 2d state = 250x250=62500 bits /8=7812.5 x2=15625characters */

   /*increase size of *is as required, was  1024*/
   hex_req=2*string_bytes;
   if ((is=(char *)realloc(is,hex_req*sizeof(char)))
				   ==NULL) outof_memory("is");
   
   /*keep existing hex rule table*/
   count=0;
   for (z=r_bytes/2-1;z!=Maxu;z--){
      is[count]=(array[z]&0xf0)>>4;
      is[count+1]=array[z]&0x0f;
      count+=2;
   }
   setfillstyle(SOLID_FILL,black);
   while (1){
      if (nhoodz>5) showcount;
#     if __WATCOM__
	 flashing_cursor(-1,+vgay(4),CWidth-1,CHeight+2,green);
#     elif __UNIX__
         flashing_cursor(0,0,0,0,-1,+vgay(3)-8,CWidth,CHeight+1-8,green);
#     endif
      test=keycheck(0);
      if (test=='q'){
	 is[0]='q';
	 goto exitFunc;        /*to stepback in setup*/
      }
      if (twod && !isrule){
	 /*rotate left,right,up,down*/
	 if (test=='l'|| test=='r'|| test=='u'|| test=='d'){
	    /* 0..................size*2 -1, update array*/
	    count=0;
	    for (z=hexbyteposl+1;z>=hexbyteposr+1;z--){               
	       array[z-1]= (is[count]<<4) + is[count+1];
	       count+=2;
	    }
	    rotate_array_2d(array,test,1);
	    is[0]='r';
	    goto exitFunc;
	 }
      }
      else {
	 /*rotate left or right*/
	 if (test=='l' || test=='r'){
	    /* 0..................size*2 -1, update array*/
	    count=0;
            /*+1 because hexbyteposr is unsigned int, usually=0*/
	    for (z=hexbyteposl+1;z>=hexbyteposr+1;z--){
	       array[z-1]= (is[count]<<4) + is[count+1];
	       count+=2;
	    }
	    rotate_array(nhoodz,array,test,isrule,1);
	    is[0]='r';          
	    goto exitFunc;
	 }
      }
      /*arrows:128+  75=left,77=right,72=up,80=down*/
      /*left arrow or back space*/
      if (test==LeftArrow || test==8){
	 if (zcount>0){
	    moveto(getx-CWidth,gety);
	    if (zcount%2==0) moveto(getx-CWidth,gety);
	    if (zcount%hexfold_bytes==0)
		   moveto (startx+CWidth*((3*hexfold_bytes/2)-2),
					    gety-(CHeight+3));
	    zcount--;
	 }
	 else if (zcount==0){
	    moveto(startx+CWidth*(3*((r_bytes-1)%hexfold_bytes)/2),
			      gety+(CHeight+3)*((r_bytes-1)/hexfold_bytes));
	    zcount=r_bytes-1;
	 }
	 showcount;
	 continue;
      }
      /*right arrow*/
      else if (test==RightArrow){
	 moveto(getx+CWidth,gety);
	 zcount++;
	 if (zcount%2==0) moveto(getx+CWidth,gety);
	 if (zcount%hexfold_bytes==0) moveto(startx,gety+CHeight+3);
	 if (zcount==r_bytes){
	    moveto(startx,gety-(CHeight+3)*(r_bytes/hexfold_bytes) );
	    zcount=0;
	 }
	 showcount;
	 continue;
      }
      /*down arrow*/
      else if (test==DownArrow){
	 if (r_bytes-1>=zcount+hexfold_bytes){
	    moveto(getx,gety+CHeight+3);
	    zcount+=hexfold_bytes;
	 }
	 showcount;
	 continue;
      }
      /*up arrow*/
      else if (test==UpArrow){
	 if (zcount>=hexfold_bytes){
	    moveto(getx,gety-(CHeight+3));
	    zcount-=hexfold_bytes;
	 }
	 showcount;
	 continue;
      }
      else if (test==13){  /*carrage return*/
	/*fflush(stdin);*/
	 break;
      }
      else if (zcount<r_bytes){
	 if (isxdigit(test)) { /*test for hex digit*/
	    sprintf(textb[0],"%c",test);
            setfillstyle(SOLID_FILL,black);
#        if __WATCOM__
	       bar(getx+1,gety,getx+CWidth,gety+CHeight);
#        elif __UNIX__
               bar(getx,gety-1,getx+CWidth,gety+CHeight);
#        endif
	    /*to avoid uneven textwidth*/
	    tempx=getx;
	    tempy=gety;
	    outtext(textb[0]);
	    moveto(tempx,tempy);
	    moveto(getx+CWidth,gety);
	    if (isdigit(test)) test-=48;
	    if (islower(test)) test-=87;
	    if (isupper(test)) test-=55;
	    is[zcount]=test;
	    zcount++;
	    if (zcount%2==0) moveto(getx+CWidth,gety);
	    if (zcount%hexfold_bytes==0) moveto(startx,gety+CHeight+3);

            if (zcount==r_bytes){
	       moveto(startx,gety-(CHeight+3)*(r_bytes/hexfold_bytes) );
	       zcount=0;
	    }
	    showcount;
	    continue;
	 }
      }
  }
  /*0..................size*2 -1, update array*/
  count=0;
  /*for (z=hexbyteposl;z>=hexbyteposr;z--){*/
  for (z=hexbyteposl;z!=Maxu;z--){
     array[z]= (is[count]<<4) + is[count+1];
     count+=2;
  }
  exitFunc:;
  if ((is=(char *)realloc(is,1024*sizeof(char)))
			    ==NULL) outof_memory("is");
}

/**prompt reminders  for define_bits (define range of bits in char array, 13 May 93)**/
void define_bits_prompts(char isrule){
  signed int xbox,tempx,tempy;
  unsigned char tempcolor;

  /*isrule: 0=seed, 1=rcode, 2=tcode, 3=kcode, 4=iso-rule*/

   tempx=getx;
   tempy=gety;
   tempcolor=getcolor();
   setcolor(white);
  
   xbox=draw_prompt_box(4);
   if (isotropic_set==1 && isrule==4){
        setcolor(lightred);
	outtext("(iso) ");
	setcolor(white);
   }
   sprintf(textb[0],"keys: val/draw-(%d-0) vert-v move-arrows",value_range-1);
   outtext(textb[0]);
   moveto(xbox,gety+CHeight);
   if (mouse_found) outtext("mouse: move-click draw-drag width-w ");
   else outtext("mouse not found, width-w ");
   if (patch_only==0){
     if (isrule==0){ //for seed
         if (oned) outtext(" PSript-P file-F"); 
	 else if (threed || twod) outtext("pan-U/D PSript-P file-F");
     }	 
     else{ //>seed-F not needed --- save space in prompt 
        // if (isotropic_set==1) outtext(" iso-file/rnd/group-f/R/G PSript-P >seed-F");
        if (isotropic_set==1){
	  if (oned || (twod && nhood>=3 && nhood<=9 && !(nhood==9 && hex2d==1)) 
              /*2 and 10, and 9hex not complete for iso-graphics*/
	         || (threed && (nhood==6 || nhood==7))) 
                         outtext(" iso-file/rnd/group-f/R/G PSript-P");
	   else outtext(" iso-file/rnd/group-f/R PSript-P");
	}
        else outtext(" file-f PSript-P >seed-F");	
     }		
   }
   moveto(xbox,gety+CHeight);
   if (patch_only==0) outtext("tog: gaps/0colr/dots/divs/divcolr-g/^/./i/!");
   else{
       setcolor(lightred);
       outtext("tog: 0colr/dots/divs/divcolr-^/./i/! fill-f rnd-S/V PSript-P -F");
       setcolor(white);
   }   
   if (oned || isrule) outtext(" exp/contr-e/c xaxis-[/]"); 
   else if ((threed || twod) && !isrule){                  
         /*to reset the density for a random patch*/
         if (twod && patch_only==0) outtext(" redef-S/V");
         outtext(" exp/contr-e/c");
   }   
   if (threed && !isrule){
     outtext("/E/C"); /*expand/contract 2d-e/c 3d-E/C*/
     moveto(xbox,gety+CHeight);    
     outtext("rot-l/r/b/f/u/d/+/- spin-s flip-X/Y comp-m grid3d-t back/cont-q/ret");
   }
   else if (oned && !isrule){
      moveto(xbox,gety+CHeight);
      outtext("rot-l/r/+/- flip-X comp-m toghex-x back/cont-q/ret");    
   } 
   else if (twod && !isrule){
      moveto(xbox,gety+CHeight);
      if (patch_only==0)
            outtext("patch-p rot-l/r/u/d/+/- spin-s flip-X/Y comp-m toghex-x back/cont-q/ret");
      else{
         setcolor(lightred);
         outtext("stop-patch-q move-j/l/r/u/d/+/- spin-s flip-X/Y comp-m ");
         setcolor(white);
	 outtext("toghex-x cont-ret");
      }
   }
   
   if (isrule){
         moveto(xbox,gety+CHeight); /*transform current rule to isotropic rule, added 12/10/2017*/
	 if (isotropic_set==0 && isrule==1){
	   if (twod && nhood==9 && value_range==2) //for 3x3 life-like rules, show H=Hensel notation
	      outtext("rot-l/r/+/- flip-X comp-m >iso-I/R/H/* back/cont-q/ret");
           else if (oned || (twod && nhood>=2 && nhood<=10) || /*2 and 10 not complete for iso-graphics*/
		 (threed && (nhood==6 || nhood==7)))
			   outtext("rot-l/r/+/- flip-X comp-m >iso-I/R/* back/cont-q/ret");
           else outtext("rot-l/r/+/- flip-X comp-m back/cont-q/ret");
	 }  
	 else outtext("rot-l/r/+/- flip-X comp-m back/cont-q/ret");	      
   }       

   /* -F allows postscript and save/load state, and save rule as seed*/
   setcolor(tempcolor);
   moveto(tempx,tempy);
}

/*********** define range of bits in char array, 13 May 93 *********/
void define_bits(char nhoodz,char isrule,char *array,
       unsigned int leftpos,unsigned int rightpos){

  signed int  startx,starty,
              tempx,tempy,tempx1,tempy1,
	      endx=0,endy; 
 unsigned int zz=0,zu,size,count_rows;
 char vcount=0,fscale_before,cellscale_before; 
 /*char fscale; global file variable, for 3d frame*/
 signed int fheight_max,h3,j3,i3,
                  sboxx,sboxy,ccel_x,ccel_y;
 unsigned int poss;
 unsigned char tempcolor,temp_color_v0;
   
   tempcolor=getcolor();

   if (threed && !isrule){
      if (i3d<=40 || j3d<=40 || h3d<=40) draw_3d_grid=1;
      else draw_3d_grid=0;
   }
   draw_3d_grid=1;
   patch_only=0;
   pi_outline=1;
   thick_line=0; /*/*width of drawn line set to one cell*/
   misc_hex2d=0;
   temp_color_v0=color_v[0];
   show_dots=1;
   color_v[0]=darkgray;
   if (isrule==0 && twod && regular2d_tgrid==1) misc_hex2d=1; /*2d hex layout*/
   tempx=getx;
   tempy=gety;
   cellscale_before=cellscale;
   if (isotropic_set==1) get_prompt_box(7,4); /*prompts for isotropic string*/
   else get_prompt_box(9,4); /*prompts for normal string*/  
   divcolor=black;
             
   define_bits_prompts(isrule);
   
   if (threed && !isrule){
     signed int w_count=0;
      fscale=vgax(8); /*initial cell scale of 3d frame*/
      fheight_max=vgay(390)-CHeight*5;      
      while (h3d*fscale + j3d*sin(PI/4)*fscale > fheight_max){
	 w_count++;
         if (w_count>20 || fscale==1) break;
         fscale-=1;
      }
   }
  /*--------------------------------------------------------------*/
  fscale_before=fscale;
 
  redraw3d:  /*if fscale changed*/
   moveto(tempx,tempy);
   if (fscale_before==fscale) 
             set_cellscale(nhoodz,isrule);
   size=leftpos-rightpos;
   next_line(xtext,2);
   startx=getx;
   starty=gety;
   topleftx=startx; /*file variable to locate movable patch*/
   toplefty=starty;
   if (threed && !isrule){
      sboxx=endx;
      sboxy=tview_y1-vgay(5);
      endx=startx+CWidth*2+1+CWidth*5;

      setcolor(lightred);
      rectangle(tview_x0,tview_y0,startx-3+Maxx*.52,tview_y1);
      erase_box(tview_x0+1,tview_y0+CHeight*2,Maxx,tview_y1-1);
   }

   if (size+1<foldposs) foldposs=size+1; /*Dec2 to fix single row bug again*/

   rot_size=1; /*size of rotations, can be reset in input_string_cell-+/-*/
   if (!isrule){
      if (threed) start_h3d=h3d-1; /*default start at top level*/
      else if (twod) start_j2d=j2d-1;
   }
   if (isrule==1 && value_range==2) /*initially binary rules have gaps between chars */
     gaps_in_string=1; /*i.e. 8 bit blocks, but can apply to v>2 (8 value blocks) or seeds*/
   else gaps_in_string=0; /*otherwize no gaps - but can be toggled*/
  /*--------------------------------------------------------------*/

  redraw: /*after rotation or compliment*/

   if (size+1<foldposs) foldposs=size+1; /*Dec2 to fix single row bug again*/
   if (!isrule){
      if (threed) size=(i3d*j3d*start_h3d) + (i3d*(j3d-1)) + (i3d-1);      
      else if (twod) size=i2d*start_j2d + i2d-1;      
   }
    
   if (twod && diff_plot){ /*line top to indicate (duplicate) sub-networks*/
      char linecolor;
         linecolor=getcolor();
         setcolor(black);
         line(getx+(cellscale_before*foldposs)/2,gety-CHeight*1.5,
                      getx+(cellscale_before*foldposs)/2,gety); 
         setcolor(linecolor);
         line(getx+(cellscale*foldposs)/2,gety-CHeight*1.5,
                      getx+(cellscale*foldposs)/2,gety);            
   }
   count_rows=0;
   hex_rad=(double)cellscale * cos(PI/6)*2/3;

   cellsep=0;

   if (threed && !isrule)
	 setviewport(0,tview_y0+CHeight*3,Maxx-1,tview_y1,0);
 
   /*calculate aspect ratio for mobile patches in hex layout, lattice must be square*/
   if (misc_hex2d==1 && cellscale>=3){
     double asp_sx,asp_sy,asp_ex,asp_ey;
     unsigned int azz=0,zu,acount_rows=0;
     signed int atempx,atempy,square_size;

      atempx=getx;
      atempy=gety;
      asp_sx=getx;
      asp_sy=gety;
      square_size=100;
      //for (zu=lineL-1;zu!=Maxu;zu--){
      for (zu=square_size*square_size-1;zu!=Maxu;zu--){      
         azz+=1;
         moverel(cellscale,0);
         //if (azz%foldposs==0){
         if (azz%square_size==0){
            asp_ex=getx;
            acount_rows++;
            if (acount_rows%2==1 && cellscale>=3)
	      moveto(xtext*CWidth+cellscale/2,gety+hex_rad*3/2);
	    else moveto(xtext*CWidth,gety+hex_rad*3/2);
         }
      }
      asp_ey=gety+hex_rad*2/3;
      aspectratio=(asp_ey-asp_sy)/(asp_ex-asp_sx);
      //fprintf(stderr,"\n c=%f, aspectratio=%f",cellscale,aspectratio);
      moveto(atempx,atempy);
   }

   for (zu=size;zu!=Maxu;zu--){  /*draw bitstring*/
      zz+=1;
          
      setfillstyle(SOLID_FILL,
             color_v[get_value(array,(unsigned int)zu)]);
      if (misc_hex2d==1 && cellscale>=3) /*hex cell*/
	  draw_hexagonal_2d_cell(hex_rad,cellscale,
                show_2d_divs,show_dots,
                  color_v[get_value(array,(unsigned int)zu)],
                      divcolor,getx,gety);
      else{ /*square cell*/
	 if (cellscale==1)
	    putpixel(getx,gety,color_v[get_value(array,(unsigned int)zu)]);
	 else{
            bar(getx,gety,getx+cellscale-cellsep,gety+cellscale-cellsep);
            /*put a dot on zero cell*/
	    if (show_dots==1 && get_value(array,(unsigned int)zu)==0 
	          && cellscale>3)
            putpixel(getx+cellscale/2,gety+cellscale/2,green);
            if ((cellscale>3 && show_2d_divs==1) ||
	        show_2d_divs==2 || show_2d_divs==3){ /*2 forces div between cells*/        
	       setcolor(divcolor);
	       rectangle(getx,gety,getx+cellscale,gety+cellscale);
            }
	 }   
      }
      setcolor(white);
      moverel(cellscale,0);
      if (gaps_in_string==1 && zz%8==0){ /*jump gaps if set*/
	 if (Maxx>=799) moverel(3,0);
	 else moverel(2,0);
      }
      
      if (zz%foldposs==0){
         count_rows++;
         if (threed && !isrule && zz%(i3d*j3d)==0){
            tempx1=getx;
            tempy1=gety; 	   
            line(getx+CWidth/2,gety+cellscale/2,
                      getx+CWidth*2,gety+cellscale/2);
            moveto(getx+CWidth*2+1,gety+cellscale/2-CHeight*.75);
            setfillstyle(SOLID_FILL,black);
            bar(getx,gety,getx+CWidth*2.5,gety+CHeight);
            sprintf(textb[0],"%d",zu/(i3d*j3d));
            outtext(textb[0]);
            moveto(tempx1,tempy1);                             
	 }
	 endx=getx;
         if (misc_hex2d==1 && cellscale>=3){
            if (count_rows%2==1 && cellscale>=3)
                  moveto(xtext*CWidth+cellscale/2,gety+hex_rad*3/2);
	    else  moveto(xtext*CWidth,gety+hex_rad*3/2);
         }
         else moveto(xtext*CWidth,gety+cellscale);
	 vcount+=1;
      }
      if (setting_seed && gety>=tview_y1-1) break; /*clip in seed box*/
   }
   endy=gety;

   /*draw 3d graphic*/
   if (threed && !isrule){
     unsigned char tempcolor3d;
      tempcolor3d=getcolor();
      /*restore viewport*/
      //setviewport(0,tview_y0+CHeight*3,Maxx,Maxy,0);

      setviewport(tview_x0,tview_y0+CHeight*3,Maxx,Maxy,0);

      sboxx=endx+CWidth*5;
      /*draw frame*/
      moveto(sboxx,sboxy-h3d*fscale);
      d_mode=4;	 
      draw_axon_plane(fscale,gety,draw_3d_grid); /*if wiring_postscript will save postscript*/ 

      /*setfillstyle(SOLID_FILL,yellow);*/
      if (bground=='w'){
	 setcolor(white); 
	 if (value_range==2) setfillstyle(SOLID_FILL,blue);
         /*yellow balls, black outline*/
      }
      else if (bground=='b'){
	 setcolor(yellow); 
	 if (value_range==2) setfillstyle(SOLID_FILL,lightblue);
         /*lightblue balls, yellow outline*/
      }  
      
      for (poss=lineL-1;poss!=Maxu;poss--){
         if (value_range>2)
                 setfillstyle(SOLID_FILL,color_v[get_value(array,poss)]);
         i3=poss%i3d;
	 j3=poss%(i3d*j3d)/i3d;
         h3=poss/(i3d*j3d);
         ccel_x=sboxx+i3d*fscale+j3d*sin(PI/4)*fscale
                    -i3*fscale-j3*sin(PI/4)*fscale-fscale;
         ccel_y= sboxy-j3d*sin(PI/4)*fscale
                     -h3*fscale+j3*sin(PI/4)*fscale;
         if (value_range==2){ 
	    if (get_bit(array,poss)==1){           
               if (fscale==1){
                   if (wiring_postscript){
                      color_ps(wiring_postscript-1,fillcolor);
                      smallspot_ps(ccel_x,ccel_y,1);
                   } 
                   putpixel(ccel_x,ccel_y,fillcolor);
               }  
	       else{
                   if (wiring_postscript){ /*empty circles in postscript*/
                       color_ps(wiring_postscript-1,fillcolor);
                       circle_fill_ps(ccel_x,ccel_y,fscale/2);/*filled circle*/
                       color_ps(wiring_postscript-1,getcolor());
                       if (fscale>=4) circle_ps(ccel_x,ccel_y,fscale/2);/*outline*/
                   }
                   pieslice(pi_outline,ccel_x,ccel_y,0,360,fscale/2);
                  
               }
	     }
	  }
	  else{
            if (get_value(array,poss)>=1){
               if (fscale==1){
                   if (wiring_postscript){
                      color_ps(wiring_postscript-1,fillcolor);
                      smallspot_ps(ccel_x,ccel_y,1);
                   } 
                   putpixel(ccel_x,ccel_y,fillcolor);
               }  
	       else{
                   if (wiring_postscript){ /*empty circles in postscript*/
                       color_ps(wiring_postscript-1,fillcolor);
                       circle_fill_ps(ccel_x,ccel_y,fscale/2);/*filled circle*/
                       color_ps(wiring_postscript-1,getcolor());
                       if (fscale>=4) circle_ps(ccel_x,ccel_y,fscale/2);/*outline*/
                   }
                   pieslice(pi_outline,ccel_x,ccel_y,0,360,fscale/2);
               }
	    }
	  }
      }
      setcolor(tempcolor3d);
      wiring_postscript=0;      
   }  
   moveto(startx,starty);
   if (threed && !isrule) fscale_before=fscale;
   cellscale_before=cellscale;
   cellscale=input_string_cell(nhoodz,isrule,array,leftpos,rightpos,1,
                             cellscale,cellsep,endx,endy);
   if (is[0]=='q') goto endFunc;
   
   if (is[0]=='r'){
      setviewport(tview_x0,tview_y0,tview_x1-1,tview_y1-1,1);     
      setfillstyle(SOLID_FILL,black);
      if  (threed && !isrule) bar(startx,starty,endx+CWidth*5,endy);
      //else if (oned && !isrule) bar(startx,starty,endx,endy+cellscale);       
      else bar(startx,starty,endx+cellscale/2,endy+cellscale*2);
      
      is[0]=zz=vcount=endx=endy=0;
      if (threed && !isrule && fscale_before!=fscale) goto redraw3d;
      else goto redraw;
   }
   if (nhoodz<=4 || isrule==2) moveto(endx+CWidth,starty-cellscale);   
   else {
      moveto(startx,starty+(cellscale*vcount));
      next_line(xtext,.5);
   }
  endFunc:
   setviewport(0,0,Maxx,Maxy,0);
   if (isotropic_set==1) uncover_free_prompt_box(7); /*prompts for isotropic string*/
   else uncover_free_prompt_box(9); /*prompts for normal string*/
   color_v[0]=temp_color_v0;
   setcolor(tempcolor);
}

/********* show info on active cell index for setting bits *******/
void showbitcount(char isrule,unsigned int leftpos,signed int zcount, 
                  signed int cellx,signed int cellscale,unsigned char left_value){
 signed int ii,jj,hh;
 unsigned int n;
 unsigned char tempcolor;
          
      tempcolor=getcolor();
      setcolor(white);      
      if (zcount<0 || zcount>(signed int)leftpos || (signed int)leftpos-zcount<0 || 
              foldposs-1-cellx<0 || foldposs-1-cellx>foldposs)
                          sprintf(textb[1],"outside grid");     
      else{ 
         n=leftpos-zcount;
         
         if (isrule==1) sprintf(textb[0],"rcode i=%d",n);
         else if (isrule==2 || isrule==3){ /*isrule==3 is TFO-mode*/
              if (totalistic==1) sprintf(textb[0],"tcode i=%d",n);
	      else if (totalistic==2) sprintf(textb[0],"kcode i=%d",n);
	 }
	 else if (isrule==4) sprintf(textb[0],"iso-rcode i=%d",n);
         else if (oned) sprintf(textb[0],"1d I=%d",n);
	 else if (twod){
              ii=n%i2d;
	      jj=n/i2d;
              sprintf(textb[0],"2d IJ=%dx%d",ii,jj);
         }
	 else if (threed){
              ii=n%i3d;
	      jj=n%(i3d*j3d)/i3d;
              hh=n/(i3d*j3d);
              sprintf(textb[0],"3d IJH=%dx%dx%d",ii,jj,hh);
         }
         sprintf(textb[1],"%s val=%d scale=%d rot=%d",
		 textb[0],left_value,cellscale,rot_size);
      }
      inset_prompt_box(0,25,textb[1],'m');
      setcolor(tempcolor);
}
      
      
/***** input bit string - set/erase cells, draw with mouse, June 93 *******/
signed int input_string_cell(char nhoodz,char isrule,char* array,
     unsigned int leftpos,unsigned int rightpos,
      char stringtype,float cellscale,float cellsep,
                 float endx,float endy){

  float startx,starty,x1,y1,x2,y2,hex_vmove; 
  signed int thistablemax,thistablebytes,z,z1,
             gap=0,gapno=0,cellx,celly,
             tempx,tempy;
 signed int zu,zcount,oldzcount,
                temp_zcount,rr,sizex,sizey;
 unsigned char cellcolor;
 char test=0,event,outside; /*thick_line is file variable*/ 
 unsigned char left_value,right_value,this_value;
 signed int patch123d[6]; /*co-ords to define 1d, 2d, or 3d  patch*/

#  define makespace3d				\
      setcolor(lightred);\
      rectangle(tview_x0,tview_y0,startx-3+Maxx*.52,tview_y1);\
      erase_box(tview_x0+1,tview_y0+CHeight*2,Maxx,tview_y1-1);

   if (isrule==0 && patch_only==0){
      if (oned){
         patch123d[0]=0;
         patch123d[1]=lineL-1;
      }
      else if (twod){
         patch123d[0]=patch123d[1]=0;
         patch123d[2]=i2d-1;
         patch123d[3]=j2d-1;
      }
      else if (threed){
         patch123d[0]=patch123d[1]=patch123d[2]=0;
         patch123d[3]=i3d-1;
         patch123d[4]=j3d-1;
         patch123d[5]=h3d-1;
      }
   }
   else{
      if (isrule==1) thistablemax= (signed int)pow(value_range,(double)nhoodz)-1;/*rcode*/ 
      else if (isrule==2) thistablemax=nhoodz*(value_range-1);/*tcode, totalistic=1*/
      else if (isrule==3) thistablemax=v_tablecodemax[nhoodz];/*kcode, totalistic=2*/
      else if (isrule==4) thistablemax=iso_tablemax;
      thistablebytes=(signed int)ceil(value_bits * (double)(thistablemax+1)/8);

      patch123d[0]=0;
      patch123d[1]=thistablemax;
   }
 
   tempx=getx;
   tempy=gety;

   /*to stop divs for small cells*/
   if (cellscale<=3  || show_2d_divs==0 ) cellsep=1;
   else if (show_2d_divs==1) cellsep=2; /*to restore divs if expanded*/   

   cellx=celly=0;
   if (thick_line<=0) thick_line=0; /*width of drawn line stays as revised*/
   if (!isrule){
      if (threed) leftpos=(i3d*j3d*start_h3d) + (i3d*(j3d-1)) + (i3d-1);
      else if (twod) leftpos=i2d*start_j2d + i2d-1;
   }
   rr=leftpos-rightpos+1;
   zcount=oldzcount=0;
   if (foldposs==0) set_cellscale(nhoodz,isrule);
   
   sizex=foldposs; /* sizex * sizey = size of 2d graphic */
   

   if (isrule) sizey=(unsigned int)ceil(((double)(thistablemax+1))/foldposs);
   else if (oned) sizey=(unsigned int)ceil(((double)(lineL))/foldposs);
   else sizey=j2d;

   /*for single row*/
   if (isrule==0 && oned && lineL<foldposs && showbits_1d_as_2d==0){
           sizex=lineL;
           sizey=1;
   }
   else if (isrule && thistablemax<=foldposs){
           sizex=thistablemax+1;
           sizey=1;
   }

   startx=getx;
   starty=gety;

   if (gaps_in_string==1){
	if (Maxx>=799) gap=3;
	else gap=2;
   }
   endx-=cellscale;
   hex_vmove=cellscale*cos(PI/6);
   if (misc_hex2d==1 && cellscale>=3){
      endy-=hex_vmove;
      if (rr%foldposs!=0) endy+=hex_vmove;
   }
   else{ 
      endy-=cellscale;
      if (rr%foldposs!=0) endy+=cellscale;
   }
#  if __WATCOM__    
      if (mouse_found){
         /*confine mouse in rectangle*/
         if (cellscale>=3){     
	    mouse_call(7,0,startx,endx+1);
	    mouse_call(8,0,starty,endy+2);
         }
	 else {
	    mouse_call(7,0,startx,endx);
	    mouse_call(8,0,starty,endy);
         }
      }
#  endif
      
   button_not_rel=0;
   left_value=value_range-1;
   right_value=0; /*the compliment*/

   while (1){
      //if (nhoodz>2) 
      showbitcount(isrule,leftpos,zcount,cellx,cellscale,left_value);
      if (oldzcount!=zcount && patch_only==0){
            /*remember last co-ords clicked to define 1d, 2d, 3d patch*/
            if (oned || isrule){ 
               patch123d[0]=leftpos-oldzcount;
               patch123d[1]=leftpos-zcount;
            } 
	    else if (twod){ /*last pair of ij co-ords to define 2d patch*/
               patch123d[0]=(leftpos-oldzcount)%i2d;
               patch123d[1]=(leftpos-oldzcount)/i2d;
               patch123d[2]=(leftpos-zcount)%i2d;
               patch123d[3]=(leftpos-zcount)/i2d;
            } 
            else if (threed){ /*last pair of ij co-ords to define 2d patch*/
               patch123d[0]=(leftpos-oldzcount)%i3d;
               patch123d[1]=(leftpos-oldzcount)%(i3d*j3d)/i3d;
               patch123d[2]=(leftpos-oldzcount)/(i3d*j3d);  
               patch123d[3]=(leftpos-zcount)%i3d;
               patch123d[4]=(leftpos-zcount)%(i3d*j3d)/i3d;
               patch123d[5]=(leftpos-zcount)/(i3d*j3d);
            } 
            oldzcount=zcount;       
      }  
   
      if (!isrule && misc_hex2d==1 &&  (j2d - (leftpos-zcount)/i2d)%2==0)
         moverel(cellscale/2,0);
     
#     if __WATCOM__
	 flashing_cursor(-1-3,-1+2,cellscale-cellsep+1-3,
			     cellscale-cellsep+1+2,green);
#     elif __UNIX__ /*change mouse shape in rectangle*/        
            if (cellscale>=3){   
               flashing_cursor(startx,endx+1,starty,endy+2,-1,-1-6,
		    cellscale-cellsep+1,cellscale-cellsep+1-6,green);
	    }
            else{
               flashing_cursor(startx,endx,starty,endy,-1,-1-6,
		    cellscale-cellsep+1,cellscale-cellsep+1-6,green);
	    }         
            mouse_found=1;
                  
#     endif
 
      if (!isrule && misc_hex2d==1 &&  (j2d - (leftpos-zcount)/i2d)%2==0)
                                        moverel(-cellscale/2,0);

      sprintf(textb[1],"width=%d",thick_line+1);
      if (button=='l' || button=='r'){         
         if (button=='l') 
                   sprintf(textb[0],"left button: set %ds %s",left_value,textb[1]); 
         else if (button=='r') 
                   sprintf(textb[0],"right button: set %ds %s",right_value,textb[1]);
         if (zcount<0 || zcount>(signed int)leftpos || 
	     (signed int)leftpos-zcount<0 || foldposs-1-cellx<0 || foldposs-1-cellx>foldposs)	   
	       inset_prompt_box(0,25,"outside grid",'m');
         else inset_prompt_box(0,25,textb[0],'m');   
      } 
      
      if (getx<startx) moveto(startx,gety); /*to stop input outside left*/
      if (getx>endx) moveto(endx,gety);     /*to stop input outside right*/
      gapno=(getx-startx)/(cellscale*8+gap);
      cellx=(getx-startx-(gapno*gap))/(cellscale);      
      gapno=cellx/8;

      if (gety<starty) moveto(getx,starty); /*to stop input above*/
      if (gety>endy) moveto(getx,endy);     /*to stop input below*/
      if (misc_hex2d==1 && cellscale>=3){
          celly=(gety-starty)/hex_vmove;
      }
      else celly=(gety-starty)/(cellscale);

      if (foldposs-1-cellx<0 || foldposs-1-cellx>foldposs)     
                                 zcount=cellx+foldposs*celly;
           
      if (mouse_found){
	 if (button=='l'|| button=='r'){
	  startmouse:
	    button_not_rel=outside=0;

	    if (gaps_in_string==1) gapno=(mouse_x-startx)/(cellscale*8+gap);
	    cellx=(mouse_x-startx-(gapno*gap))/(cellscale);
	    gapno=cellx/8;
            if (misc_hex2d==1 && cellscale>=3){
                celly=(mouse_y-starty)/hex_vmove;
            }
	    else celly=(mouse_y-starty)/(cellscale);

	    zcount=cellx+foldposs*celly;

	    /*prevent input beyond end of last partial row*/
#           if __WATCOM__
	       if (rr>foldposs && rr%foldposs!=0 && zcount>rr-1) outside=1;
#           elif __UNIX__
               if ((rr>foldposs && rr%foldposs!=0 && zcount>rr-1)
                    || inside_rect==0) outside=1;
#           endif
	    if (misc_hex2d==1 && cellscale>=3)
	             y1=starty+celly*hex_vmove;
            else y1=starty+celly*cellscale;
            x1=startx+gapno*gap+cellx*cellscale;
	    x2=x1+cellscale-cellsep;
	    y2=y1+cellscale-cellsep;
            
	    if (button=='l'){ 
              cellcolor=color_v[left_value];
              this_value=left_value;             
	      
	       /*check left mouse button released*/
#              if __WATCOM__   
	          mouse_call(6,0,0,0);
                  if (globbx==0) button_not_rel='l';
#              elif __UNIX__
                  event=XCheckWindowEvent(D,W,ButtonReleaseMask,&Event);
                  /*left button not released*/
                  if (event==0 || Event.xbutton.button!=1) 
                                              button_not_rel='l'; 
#              endif	      
	    }
	    if (button=='r'){ 
              cellcolor=color_v[right_value];
              this_value=right_value;                                
	      
	       /*check right mouse button released*/
#              if __WATCOM__   
	          mouse_call(6,1,0,0);
                  if (globbx==0) button_not_rel='r';
#              elif __UNIX__
                   event=XCheckWindowEvent(D,W,ButtonReleaseMask,&Event);
                   if (event==0 || Event.xbutton.button!=3) 
                                             button_not_rel='r';
#              endif	      
	    }
	    if (button_not_rel && !outside){
	       setfillstyle(SOLID_FILL,cellcolor);
             
	       for (z=0; z<=thick_line; z++){
	             /*check right mouse button released*/
		     button_not_rel=0;
#                 if __WATCOM__ 
                     mouse_call(6,0,0,0);  
	             mouse_call(6,1,0,0);
                     if (globbx==0) button_not_rel=1;
#                 elif __UNIX__
                     event=XCheckWindowEvent(D,W,ButtonReleaseMask,&Event);
                     if (event==0) button_not_rel=1;
#                 endif
		     if (button_not_rel==0) break;	    
                     if (z<=1) z1=z;
                     else {  
		        if (z%2==0) z1=-z/2;
                        else z1=z/2+1;
                     }
                 
		     if (cellx+z1<0 || cellx+z1>sizex-1 
		        || celly+z1<0 || celly+z1>sizey-1) continue;
                     temp_zcount=cellx+z1+foldposs*(celly+z1);
                     if (temp_zcount>leftpos) continue;
                     draw_and_set_value_line(0,array,isrule,
                             this_value,leftpos,temp_zcount,cellscale,
                             show_2d_divs,show_dots,cellcolor,x1,y1,z1);                    
                }    
	    }
	    if (button_not_rel){
#              if __WATCOM__   		  
                  mouse_call(3,0,0,0); /*mouse position*/
                  mouse_x=globcx;
		  mouse_y=globdx;
#              elif __UNIX__
                  if (XCheckWindowEvent(D,W,PointerMotionMask,&Event)){
                      if (Event.type == MotionNotify){
                         mouse_x=Event.xmotion.x;
                         mouse_y=Event.xmotion.y;
                         if (mouse_x>=startx && mouse_y>=starty
                               && mouse_x<=endx && mouse_y<=endy){
                             if (inside_rect==0){
                                XDefineCursor(D,W,leftCursor);
	                        inside_rect=1;
	                     }
                         }
                         else if (inside_rect==1){
                            XDefineCursor(D,W,rightCursor);
                            inside_rect=0;
                         }

                         /* show co-ordinates*/
	                 /*sprintf(textb[0],"x=%d y=%d",mouse_x,mouse_y);
	                 draw_hint_box(0,0,textb[0],vgax(500)); */         
                     }  
                  }
#              endif		 
	       goto startmouse;
	    }
	    moveto(x1,y1);
	    continue;
	 }
      }

      test=keycheck(0);
      if (test=='q'){
         if (patch_only==1){
            patch_only=0;
            define_bits_prompts(isrule);
            is[0]='r';
            goto endFunc;
	 }
         else{
            if (threed && !isrule && fscale>=2){
               makespace3d; /*erase existing 3d isonometric*/
	    }            
	    is[0]='q';
	    goto endFunc;        /*to stepback in setup*/
	 }
      }
      if (test=='>'){ 
         save_screen();/*save .nat screen image with >key*/
         is[0]='r';
	 goto endFunc;        /*to stepback in setup*/
      } 
      if (test=='<'){
         load_screen();/*load .nat screen image with < key*/
         is[0]='r';
	 goto endFunc;        /*to stepback in setup*/
      }  
      if (test=='g' && patch_only==0){
            gaps_in_string=abs(gaps_in_string-1); /*toggle gaps*/
            is[0]='r';
            goto endFunc;
      }
      if (test=='w'){
        signed int max_w, tempx,tempy;
        unsigned char tempcolor;
         tempx=getx;
         tempy=gety;
         if (isrule || (oned && showbits_1d_as_2d==0)){
	    if (sizey/4<8) max_w=sizey;
            else max_w=sizey/4;
         }
         else{ /*for 2d or 3d as 2d, max_w = smallest axis*/
            max_w=j2d;
            if (j2d>i2d) max_w=i2d;             
         } 
         get_prompt_box(2,1);
         tempcolor=getcolor();
         setcolor(white);
         draw_prompt_box(1);
         sprintf(textb[3],"reset line width (now %d) max %d:",
		 thick_line+1, max_w);
         outtext(textb[3]);
         input_string(2,0);
         if (atoi(is)>=1 && atoi(is)<=max_w) thick_line=atoi(is)-1;
         uncover_free_prompt_box(2);
         setcolor(tempcolor);
         moveto(tempx,tempy);
         continue;
      }
      if (test=='x'){  /*toggle hex layout*/
	 if (!isrule){
            misc_hex2d=abs(misc_hex2d-1);
            is[0]='r';
            goto endFunc;
         }
         else continue;
      }    
      if (test=='-'){
         rot_size-=1;
         if (rot_size<1) rot_size=1;
         continue;
      }
      if (test=='+'){
         if (threed && !isrule){
            if (rot_size<i3d-2 && rot_size<j3d-2 && rot_size<h3d-2)
                                  rot_size+=1;
         }
         else if (twod && !isrule){
	    if (rot_size<i2d-2 && rot_size<j2d-2) rot_size+=1;
         }
         else {
	    if ((isrule && rot_size<thistablebytes*8-2) 
                      || (!isrule && rot_size<lineL-2)) rot_size+=1;
         }
         continue;
      }
      if (test=='U' && patch_only==0){
         if ((threed || twod) && !isrule){
	    if (threed && start_h3d>=2){
               start_h3d-=1;
               is[0]='r';
               goto endFunc;
	    } 
            else if (twod && start_j2d>j2d/10){
	        start_j2d-=j2d/10;
               is[0]='r';
               goto endFunc;
	    } 
         }
         continue;
      }
      if (test=='D' && patch_only==0){
         if (threed && start_h3d<=h3d-2){
            start_h3d+=1;
            is[0]='r';
            goto endFunc;
         }
         else if (twod && start_j2d<j2d-1){
            start_j2d+=j2d/10;
            if (start_j2d>j2d-1) start_j2d=j2d-1;
            is[0]='r';
            goto endFunc;
         }
         continue;
      }
      if (test=='t'){ /*just update 3d, and toggle grid*/
         if (threed && !isrule){
	    makespace3d;               	    
	    draw_3d_grid=abs(draw_3d_grid-1);
            is[0]='r';
            goto endFunc;            
         }
         continue;
      }

      if (test=='p' && isrule==0 && twod && showbits_1d_as_2d==0 && gaps_in_string==0){
         /*toggle patch_only for moving a patch*/
         if (patch_only==0){
           unsigned int temp_ei,temp_ej; 
           /*EXT signed int Si,Sj,Ei,Ej; in eglob_ab.h, for moving a patch*/
            Si=patch123d[0];
            Sj=patch123d[1];
            Ei=patch123d[2];
            Ej=patch123d[3];
            
            /*rearange coords from small > large*/
            if (Ei<Si){
               temp_ei=Ei;
               Ei=Si;
               Si=temp_ei;
            }
	    if (Ej<Sj){
               temp_ej=Ej;
               Ej=Sj;
               Sj=temp_ej;
            }
            Pi2d=Ei-Si+1; /*i width for jump patch*/   
            Pj2d=Ej-Sj+1; /*j height for jump patch*/
            //fprintf(stderr,"\nS %dx%d (%d %d)(%d %d)",Pi2d,Pj2d,Si,Sj,Ei,Ej); 
	    patch_only=1; 
            define_bits_prompts(isrule);
            sprintf(textb[1],"patch active: %d,%d-%d,%d", Si,Sj,Ei,Ej);
            setcolor(lightred);
            inset_prompt_box(11,25,textb[1],'m');
            setcolor(white);
            restore_def_font();  
            continue;
	 }
         /*else if (patch_only==1){ //return or 'q' does this
            patch_only=0;
            define_bits_prompts(isrule);
            is[0]='r';
            goto endFunc;
	 }*/                  
      }

      if (test=='l'|| test=='r'|| ((test=='b'|| test=='f') && threed)
                               || test=='u'|| test=='d'){

	 if (threed && !isrule){ /*threed*/
            /*rotate left,right,back,front,up,down*/   	       
	    rotate_array_3d(array,test,rot_size);
            is[0]='r'; 
	    goto endFunc;
         }
         else if (twod && !isrule && /*twod*/
	       (test=='l'|| test=='r' || test=='u'|| test=='d')){
	    if (patch_only==1 && gaps_in_string==0){
               set_medium_font();
	       move_patch_2d(array,test,rot_size);
               sprintf(textb[7],"patch active: %d,%d-%d,%d", Si,Sj,Ei,Ej);
               setcolor(lightred);
               inset_prompt_box(12,25,textb[7],'m');
               setcolor(white);
               restore_def_font();
               if (patch_only==0){ /*in case edge is hit*/
                  define_bits_prompts(isrule);
               }                         
            }
	    else rotate_array_2d(array,test,rot_size);
            if (patch_only==1) continue;
	    else{
               is[0]='r';
	       goto endFunc;
	    }
         }
           
         else if (test=='l' || test=='r'){ /*oned rotate left or right*/
	   is[0]='r';
	   if (isotropic_set==1){
	       rotate_array(nhoodz,iso_rule,test,isrule,rot_size);
	   }
	   else if (isotropic_set==0){
	       rotate_array(nhoodz,array,test,isrule,rot_size);
	   }
	   
           patch_only=0;
	    goto endFunc;
         }
         continue;
      }
                
      if (test=='s'  && !isrule){
	 if (threed){	    
            v_spin_array_3d(array);
            is[0]='r';
	    goto endFunc;
 	 }
         else if (twod){
            if (patch_only==1 && gaps_in_string==0){
	        v_spin_patch_2d(array,startx,endx,starty,endy);
                continue;
            }
	    else{
                v_spin_array_2d(array);
                is[0]='r';
	        goto endFunc;
            }
	 }
	 continue;
      }
      if (test=='X' || test=='Y'){
	 if (threed){ 
            flip_array_3d(array,test);
            is[0]='r';
	    goto endFunc;
         }
         else if (twod){
            if (patch_only==1 && gaps_in_string==0){
	        flip_patch_2d(array,test);
                continue;
            }
            else{
               flip_array_2d(array,test);
               is[0]='r';
	       goto endFunc;
            }
         }            
         else if ((oned || isrule) && test=='X'){
            if (isrule) flip_array_1d(array,thistablemax,thistablebytes);
            else if (oned) flip_array_1d(array,lineL-1,bytesL);
            is[0]='r';
	    goto endFunc;
	 } 
         continue;
      }

      /*iso-rule:transform current rcode into isotropic rule, added 12/10/2017*/
      if ( (test=='I' || test=='H' || test=='R' || test=='*') &&
	          isotropic_set==0 && isrule==1 ){
	   char temp_gaps_in_string;
	   signed int temp_foldposs;
	    temp_gaps_in_string=gaps_in_string;
	    temp_foldposs=foldposs;//foldposs is global
	    if (test=='I') isotropic_rule(0,array,nhoodz,0,thistablemax,thistablemax,-2);
	     if (test=='R') isotropic_rule(3,array,nhoodz,0,thistablemax,thistablemax,-2);
	    else if (test=='*') isotropic_rule(1,array,nhoodz,0,thistablemax,thistablemax,-2);
	    else if (test=='H' && twod && nhoodz==9){
	              isotropic_rule(2,array,nhoodz,0,thistablemax,thistablemax,-2);
		      define_bits_prompts(1); //restore hints window after loading Hensel notation
            }
	    //so original bit/value presentation will be the same
	    gaps_in_string=temp_gaps_in_string;
	    foldposs=temp_foldposs;
	    is[0]='r';
	    goto endFunc;
            continue;
      }

      if (test=='E'){ /*expand 3d */
	if (threed &&  fscale<127 && !isrule){
	    makespace3d;     
            fscale+=1;        
            is[0]='r';
            goto endFunc;
        }
        continue;
      }   
      if (test=='C'){ /*contract 3d*/
	 if (threed && !isrule && fscale>=2){
           makespace3d; /*erase existing*/
           fscale-=1;        
           is[0]='r';
           goto endFunc;
         }
         continue;  
      }
            
      if (test=='e'){ /*expand rule, 1d, 2d*/ 
         if (cellscale<127){
	    if (threed && !isrule){ /*to redraw 3d shifted right*/
              makespace3d;
            }
            cellscale+=1;        
            is[0]='r';
            goto endFunc;
         }
         continue;
      }   
      if (test=='c'){ /*contract rule or seed, 1d, 2d*/
	 if (cellscale>=2){
	    if (threed && !isrule){/*to redraw 3d shifted left*/ 
	       makespace3d;
	    }
            cellscale-=1;        
            is[0]='r';
            goto endFunc;
         }
         continue;
      }
      if (test==']'){ /*double x-axis*/
	if ((isrule || oned==1) && foldposs < Maxint/2){
	    foldposs*=2;    
            is[0]='r';
            goto endFunc;
         }
         continue;       
      }
      if (test=='[' ){ /*halve x-axis*/
         if ((isrule || oned==1) && foldposs >= 2){
            foldposs/=2;       
            is[0]='r';
            goto endFunc;
         }
         continue;         
      }
      if (test=='i'){
         show_2d_divs=abs(show_2d_divs-1); 
         if (patch_only==1 && twod){
	       redraw_patch_2d(array);
               continue;
	 }
         else{               
               is[0]='r';
               goto endFunc;
         }
      } 
      
      if (test=='!'){
         /*show black/white/lightgrey lines between cells, 2d hex or square,
           also 1d, 2d as 3d, and rule*/
	 if (divcolor==black) divcolor=white;
         else if (divcolor==white) divcolor=lightgray;
         else if (divcolor==lightgray) divcolor=black;
         if (patch_only==1 && twod){
	       redraw_patch_2d(array);
               continue;
	 }
         else{               
               is[0]='r';
               goto endFunc;
         }
      } 
      
      if (test=='^'){
         if (color_v[0]==black) color_v[0]=darkgray;
         else color_v[0]=black;
         if (patch_only==1 && twod){
	       redraw_patch_2d(array);
               continue;
	 }
         else{               
               is[0]='r';
               goto endFunc;
         }
      } 
      if (test=='.'){
	 show_dots=abs(show_dots-1);
         if (patch_only==1 && twod){
	       redraw_patch_2d(array);
               continue;
	 }
         else{               
               is[0]='r';
               goto endFunc;
         }
      } 
    
      if (test=='f' && twod && isrule==0){ /*fill with default drawing color*/
         if (patch_only==1 && gaps_in_string==0){
	    fill_patch_2d(array,left_value); /*left_value=current active drawing value*/
            continue;
         }
      }
      if (test=='j' && twod && isrule==0){ /*copyfill with default drawing color*/
	signed int Six,Sjx;
        unsigned int n;
         if (patch_only==1 && gaps_in_string==0){
           n=leftpos-zcount;    
           Six=n%i2d;      
           Sjx=n/i2d;
           if (Six<0 || Sjx<0 || Six>i2d-1 || Sjx>j2d-1); // do nout -- cursor outside grid
	   else{
	       jump_patch_2d(array,leftpos,zcount); /*jump/copy to cursor pos*/
               sprintf(textb[1],"patch active: %d,%d-%d,%d", Si,Sj,Ei,Ej);
               setcolor(lightred);
               inset_prompt_box(11,25,textb[1],'m');
	   }
           continue;
         }
      }

      if (test=='S' && twod && isrule==0){
         if (Rdensity==0) Rdensity=bias_density_seed;     
         if (patch_only==1 && gaps_in_string==0){
	    fill_rnd_patch_2d(array); /*fill with random content acc to density*/
            continue;
         }
         else if (patch_only==0 && twod){ /*revise random content density*/
           signed int tempxV,tempyV;
            tempxV=getx;
            tempyV=gety;
            draw_prompt_box(1);              
            sprintf(textb[0],
            "revise rnd-density: enter %% (def %.3f%%):",Rdensity);       
            outtext(textb[0]);
            input_string(5,0);
            if (is[0]!=13){
	       if (atof(is)>=0 && atof(is)<=100)  Rdensity=atof(is);
            }
            define_bits_prompts(isrule);
            moveto(tempxV,tempyV);            
            continue;
         }
      }
      
      if (test=='V' && twod && isrule==0){
 	 if (patch_only==1 && gaps_in_string==0){
	    /*fill 2d patch with current value frequency*/
	    fill_fraction_values_patch_2d(array);
            continue;
         }
         else if (patch_only==0){
            /*reset value= bias for random seed with %/values*/
	   signed int xbox,tempxV,tempyV;
           char keep_bias_percent_rule=0;
           tempxV=getx;
           tempyV=gety;
          startB:
           xbox=draw_prompt_box(2);
           outtext("bias rnd seed, ");

           if (lineL<=255) outtext("%/values-p/v keep-k: "); /*choose of 'p' or 'v'*/      
           else outtext("%values-p keep-k: ");
           input_string(1,0); /*8 is outside range of values 0-7*/
           if (is[0]=='q'){
               define_bits_prompts(isrule);
               moveto(tempxV,tempyV);
               continue;
	   }       
	   if (is[0]=='k' &&  (bias_percent_seed[8]=='v' || bias_percent_seed[8]=='p')){ 
                 keep_bias_percent_rule=1;
	   }
           else if (is[0]=='p') bias_percent_seed[8]='p';
           else if (is[0]=='v' && lineL<=255) bias_percent_seed[8]='v';          
           
           moveto(xbox,gety+CHeight);
           set_fraction_values(isrule,lineL);
           if (is[0]=='q') goto startB;            	   

           define_bits_prompts(isrule);
           moveto(tempxV,tempyV);          
           continue;
         }
      }

      if (test=='m'){
         if (patch_only==1 && gaps_in_string==0){
	    compliment_patch_2d(array);
            continue;
         }
	 else{ 
            if (value_range==2){
	       if (isrule){
                  for (z=0;z<=thistablebytes-1;z++) array[z]=~array[z];
               }
               else{
                  for (zu=0;zu<=bytesL-1;zu++) array[zu]=~array[zu];
                  /*set excess bits to 0*/
                  for (zu=lineL;zu<=bytesL*8-1;zu++) set_bit0(array,zu);
               }
               if (isrule==0) bias_density_seed=100.0-bias_density_seed;
               else bias_density_rule=100.0-bias_density_rule;
            }
            else{
              char tempvalue;
              unsigned int ct_count;
	       /*compliment multivalue by subtraction*/
               for (ct_count=0;ct_count<=rr-1;ct_count++){
	          tempvalue=get_value(array,(unsigned int)ct_count);
                  tempvalue=(value_range-1)-tempvalue;
                  set_value(array,ct_count,tempvalue);
               }
            }
            is[0]='r';
            goto endFunc;
         }
      }
      if (patch_only==1 && twod && (test=='F' || test=='P')){ /*if moving patch is active*/
	 char *patch_buf;
         unsigned int zi,zj,counti,countj,indexA,indexP,patch_size;
         signed int bytesP;
         unsigned int tempx,tempy;
          tempx=getx;
          tempy=gety;
          get_prompt_box(2,4);
          patch_size=(Ei-Si+1)*(Ej-Sj+1);
          bytesP=(signed int)ceil(((double)(value_bits*patch_size))/8);
          if ((patch_buf=(char *)calloc(bytesP,sizeof(char)))
					==NULL) outof_memory("patch_buf");
          counti=countj=-1;
          for (zj=Sj;zj<=Ej;zj++){
	          countj+=1;
                  counti=-1;
                  for (zi=Si;zi<=Ei;zi++){
		     counti+=1;
		     indexA=i2d*zj + zi;
                     indexP=(Ei-Si+1)*countj + counti;
		     set_value(patch_buf,indexP,get_value(array,indexA));
                  }
	  }

          if (test=='P'){
               save_to_PostScript(patch_buf,Ei-Si+1,Ej-Sj+1,0,
                             patch_size,cellscale,show_2d_divs,
                             divcolor,show_dots,misc_hex2d,gaps_in_string);
               free(patch_buf);
          }

          else if (test=='F'){ /*free(patch_buf); inside*/
	    save_patch_2d(patch_size,bytesP,patch_buf,Si,Sj,Ei,Ej);
          }
	  	  
          uncover_free_prompt_box(2);
          moveto(tempx,tempy);
          continue;          
      }
      /*save/load rule in binary or ASCII*/
      if (isotropic_set==0 && test=='f' && isrule){	
	signed int tablemax,tablebytes,xbox,tempx,tempy;
	  get_prompt_box(2,1);
	  draw_prompt_box(1);
          if (totalistic==0){ 
               sprintf(textb[1],"rcode");
               tablemax=(signed int)pow(value_range,(double)nhood)-1;               
          }
          else if (totalistic==1){ 
               sprintf(textb[1],"tcode");
               tablemax=nhood*(value_range-1); /*max index of codetable*/
          }
          else if (totalistic==2){ 
               sprintf(textb[1],"kcode");
               tablemax=v_tablecodemax[nhood];
          }
          
          sprintf(textb[0],
            "%s (v=%d k=%d S=%d) load/save-l/s ASCII-L/S:",
		  textb[1],value_range,nhood,tablemax+1);
          outtext(textb[0]);
          input_string(1,0);
          if (is[0]=='L'){
           if (totalistic==0) load_save_ascii_rule_seed('l','r',carule[0], tablemax+1);
           else if (totalistic==1) load_save_ascii_rule_seed('l','r',cacode[0], tablemax+1);
           else if (totalistic==2) load_save_ascii_rule_seed('l','r',v_code[0], tablemax+1);
          }
          if (is[0]=='S'){
           if (totalistic==0) load_save_ascii_rule_seed('s','r',carule[0], tablemax+1);
           else if (totalistic==1) load_save_ascii_rule_seed('s','r',cacode[0], tablemax+1);
           else if (totalistic==2) load_save_ascii_rule_seed('s','r',v_code[0], tablemax+1);
          }
          else if (is[0]=='s'){ 
             if (totalistic==0) load_save_wrs('s',carule[0],0);
             else if (totalistic==1) load_save_wrs('s',cacode[0],0);
             else if (totalistic==2) load_save_wrs('s',v_code[0],0);
          }        
          else if (is[0]=='l'){
             if (totalistic==0) load_save_wrs('l',carule[0],0);
             else if (totalistic==1) load_save_wrs('l',cacode[0],0);
             else if (totalistic==2) load_save_wrs('l',v_code[0],0);
          }             	  
	  uncover_free_prompt_box(2);//restore define_bits_prompts
	  is[0]='r';
          goto endFunc;
      }

      /*save/load isocode in binary or ASCII, or edit/save/load in hex*/
      if (isotropic_set==1 && test=='f' && isrule){	
	signed int xbox,tempx,tempy;
	  get_prompt_box(2,1);
	  draw_prompt_box(1);
          sprintf(textb[0],
            "iso-rule (v=%d k=%d S=%d) load/save-l/s ASCII-L/S, hex-h:",
		  value_range,nhood,iso_tablemax+1/*,iso_tablemax-zcount*/);
          outtext(textb[0]);
          input_string(1,0);
          if (is[0]=='L' || is[0]=='S'){ //save iso-rule as ASCII string
            char temp;
            if (is[0]=='L') temp='l';
            else if (is[0]=='S') temp='s';
	    load_save_ascii_rule_seed(temp,'r',iso_rule, iso_tablemax+1);
          }
          else if (is[0]=='s') load_save_wrs('s',iso_rule,0);
          else if (is[0]=='l') load_save_wrs('l',iso_rule,0);
	  else if (is[0]=='h'){
	    signed int iso_tablebytes;
	    iso_tablebytes=(signed int)ceil(value_bits * (double)(iso_tablemax+1)/8);
	     define_hex(nhood,4,iso_rule,iso_tablebytes-1,0,0);

	  }	  
	  uncover_free_prompt_box(2);//restore define_bits_prompts
	  is[0]='r';
          goto endFunc;
      }
      /*generate random iso-rule and set density*/
      if (isotropic_set==1 && test=='R' && isrule){
	signed int Rtempx,Rtempy;
	  
	  //fprintf(stderr,"\nrand iso-rule, iso_tablemax=%d",iso_tablemax);
                    
	  next_line(xtext,-2.5); //to keep in same place
          Rtempx=getx;
          Rtempy=gety;
          erase_box(getx,gety,Maxx-2,Maxy-2);
          erase_prompt_box(4);//top right erase prompt reminder
          moveto(Rtempx,Rtempy);          
          random_bits(nhood,1,0,1,iso_rule,iso_tablemax);

          moveto(Rtempx,Rtempy);
          //next_line(xtext,-2.5); //to keep in same place
          erase_box(getx,gety,Maxx-2,Maxy-2);
          define_bits_prompts(4);//reshow top right prompt reminder which was partly covered
          moveto(Rtempx,Rtempy);
          is[0]='r';
          goto endFunc;
      }     

      /*************iso-group-graphic in top-rightside window*********************/
      if (isotropic_set==1 && test=='G' && isrule
              && (oned || (twod && nhood>=3 && nhood<=9 && !(nhood==9 && hex2d==1))
                /*2 and 10, and 9hex not complete for iso-graphics*/
		 || (threed && (nhood==6 || nhood==7)))){	
	signed int z,zx,zz,xbox,tempx,tempy,tempxx,tempyy,
	  iso_index,m_iso_index,temp_color_v0,tempcolor,stringlength,box_lines,
          t_count=0,tempnum,startA;
	float tempscale;
	char *temp_image,show3das2d,try3da,temp_is,skip_prompts=0;
	
        //rlayout shows all 2d square Moore nhoods in detail
	signed int tablemax,zcount=0, //for rlayout:
	  rlayoutx,rlayouty; /*blank out area*/
	char rlayout=0;
             
              tablemax=(signed int)pow(value_range,(double)nhoodz)-1; //for rlayout: 
	
	      //count number of digits in iso_tablemax+1
	      tempnum=iso_tablemax+1;
	      do{
		t_count++;  
	        tempnum/=10;
              } 
              while(tempnum!=0);
              //fprintf(stderr,"\nt_count=%d",t_count);
                            
	      if (oned==1); //allow any nhood
              else if (nhood<=2 || (hex2d==0 && nhood<4)) goto iso_skip;        
	      show3das2d=0;
              try3da=0;
	      
	      tempscale=cellscale;
	      if (tempscale<vgax(5)) tempscale=vgax(5); 
              tempx=getx;
              tempy=gety;
	      box_lines=(Maxy - vgay(6))/CHeight;
              //fprintf(stderr,"\nbox_lines=%d/%d=%d",Maxy,CHeight, box_lines);
              //get_prompt_box(8,20);
              get_prompt_box(8,box_lines);//complete right side of screen
              setviewport(Maxx/2, 0, Maxx, Maxy - vgay(6) -2, 1);
              temp_color_v0=color_v[0];
              
              color_v[0]=darkgray;
	      tempcolor=getcolor();
	      if (oned){
		 if ((temp_image=(char *)calloc(nhood,sizeof(char)))
		     				==NULL) outof_memory("temp_image");
	      }
	      else{	 
	         if ((temp_image=(char *)calloc(9,sizeof(char)))
					==NULL) outof_memory("temp_image");
	      }	 
	      is[0]=0;
              wiring_postscript=0;
	      
	   iso_start:
              //xbox=draw_prompt_box(20);
              xbox=draw_prompt_box(box_lines);//complete right side of screen
	      moveto(xbox,vgax(2));
	     

	      iso_index=iso_tablemax-zcount;
	      //in case mouse outside grid 
	      if (iso_index<0 || iso_index>iso_tablemax){
		   iso_index=iso_tablemax;
		   sprintf(textb[0],"(outside-grid) ");
		   outtext(textb[0]);
	      }
	      if (oned) sprintf(textb[2],"1d");
	      else if (twod && hex2d==0) sprintf(textb[2],"2d");
	      else if (twod && hex2d==1) sprintf(textb[2],"hex2d");
	      else if (threed) sprintf(textb[2],"3d");
	      /*fprintf(stderr,"\niso-groups(%d) v%dk%d(%s) iso-index=%d>%d group(size %d)=",
		      iso_tablemax+1,value_range,nhood,textb[2],iso_index,
		      get_value(iso_rule,iso_index),glbl_iso_list[iso_index][0]);*/
	      sprintf(textb[1],"iso-groups(%d) v%dk%d(%s)  iso-index=%d>%d group(size %d)",
		      iso_tablemax+1,value_range,nhood,textb[2],iso_index,
		      get_value(iso_rule,iso_index),glbl_iso_list[iso_index][0]);
	      outtext(textb[1]);
	      if (wiring_postscript){
		 color_ps(wiring_postscript-1,white);
                 //resetfont_ps("Times-Roman",CWidth*1.5);
                 resetfont_ps("Times-Bold",CWidth*1.5);
	         nodetext_ps(3,bground,textb[1],xbox,gety+CHeight);
	      }
	      
	      //dec list of group members
	      set_medium_font();
	      moveto(xbox,gety+CHeight*2);
	      
	      if (wiring_postscript){
		 moveto_ps(xbox,gety+CHeight*1.5);
                 //resetfont_ps("Times-Roman",CWidth);
                 resetfont_ps("Helvetica",CWidth*1.5);
	      }
              for (z=1;z<=glbl_iso_list[iso_index][0];z++){
		 if (getx>=Maxx-CWidth*5){
		     moveto(xbox,gety+CHeight);
		     if (wiring_postscript) moveto_ps(xbox,gety+CHeight);
		 }
		 //fprintf(stderr,"%d ",glbl_iso_list[iso_index][z]);
		 sprintf(textb[1],"%d  ",glbl_iso_list[iso_index][z]);
                 outtext(textb[1]);

		 if (wiring_postscript){
		   sprintf(textb[2],"%d",glbl_iso_list[iso_index][z]);
		   nodetext_ps(3,bground,textb[2],getx,gety+CWidth);
		 }		 		 
	      }
	      restore_def_font();
	      
	      moveto(xbox,gety+CHeight/2);
	      if (threed) moveto(getx,gety+tempscale);
              skip_prompts=0;

           iso_all_start: //this is the virtual loop
              if (skip_prompts){//1 or 2 
		  iso_index--;
                  //fprintf(stderr,"\niso_index=%d",iso_index);		     
		  //input_string(1,0);
              } 

              /*************************************************************************/ 	      	      
              if (oned){ 
               signed int newleft,thisy;
                 if (tempscale<vgax(1)) tempscale=vgax(1);
                 setcolor(white);
	         if (skip_prompts==0) moveto(xbox+tempscale,gety+CHeight);
		 else if (skip_prompts==1){ 
                    moveto(xbox+tempscale,gety);
                    thisy=gety;
                    //sprintf(textb[1],"%4d",iso_index);
                    sprintf(textb[1],"%*d",t_count,iso_index);
                    if (wiring_postscript){
		       moveto(getx,gety+tempscale*1);
                       color_ps(wiring_postscript-1,white);
                       //sprintf(textb[2],"%4d",iso_index);
                       sprintf(textb[2],"%*d",t_count,iso_index);
	               nodetext_ps(3,bground,textb[2],getx,gety);
	            }
                    moveto(getx,thisy);
                    outtext(textb[1]);
                    moveto(xbox+tempscale+CWidth*t_count,gety);//fix to line up
                    newleft=getx;                                        
                 }
		 tempy=gety;
	         for (z=1;z<=glbl_iso_list[iso_index][0];z++){
                    if (skip_prompts==2 && z==2) break;
		    if (getx>=Maxx-tempscale*3){//next line if near right edge
                        if (skip_prompts==0)  moveto(xbox+tempscale,gety+tempscale*4);
		        else if (skip_prompts==1) moveto(newleft,gety+tempscale*4);
                        else if (skip_prompts==2) moveto(startA,gety+tempscale*4);
		    }
		    dec_to_value_line(iso_group_image,glbl_iso_list[iso_index][z],nhood);
		    for (zz=0;zz<=nhood-1;zz++){
		      temp_image[zz]=get_value(iso_group_image,zz);
		    }  
		   
                    tempxx=getx;
                    tempyy=gety;
		    setcolor(divcolor);
		    zx=0;
                    for (zz=nhood-1;zz>=0;zz--){
			if (value_range>2 || temp_image[zz]==0) 
			  setfillstyle(SOLID_FILL,color_v[temp_image[zz]]);
                        else setfillstyle(SOLID_FILL,white);
			if (wiring_postscript){
			   color_ps(wiring_postscript-1,fillcolor);
                           rect_fill_ps(getx,gety,tempscale,tempscale);
			   color_ps(wiring_postscript-1,getcolor());/*color or gray*/
			   rect_outline_ps(getx,gety,tempscale,tempscale);
			}
			bar(getx,gety,getx+tempscale,gety+tempscale);
			rectangle(getx,gety,getx+tempscale,gety+tempscale);			
			//fprintf(stderr," %d:%d",zz,fillcolor);			
                        moverel(tempscale,0);
                     }
		     moveto(tempxx,tempyy);		    
		     moveto(getx+tempscale*(nhood+1),gety);
	         }
	      }


              /*************************************************************************/
	      if (rlayout==1 && twod && hex2d==0){//activated by tog-X -- works for value_range>2
                signed int newleft,thisy;
		
                 set_medium_font();
                 if (tempscale<vgax(1)) tempscale=vgax(1);//fix to line up
                 setcolor(white);
	         if (skip_prompts==0) moveto(xbox+tempscale,gety+CHeight);
		 else if (skip_prompts==1){ 
                    moveto(xbox+tempscale,gety);
                    thisy=gety;
		    
                    //sprintf(textb[1],"%*d",t_count,iso_index);                    
                    sprintf(textb[1],"%*d:%*d",t_count,iso_index,t_count,glbl_iso_list[iso_index][1]);

                    if (wiring_postscript){
		          moveto(getx,gety+tempscale*2);                         
                          color_ps(wiring_postscript-1,white);
                          //sprintf(textb[2],"%*d",t_count,iso_index);
                          sprintf(textb[2],"%*d:%*d",t_count,iso_index,t_count,glbl_iso_list[iso_index][1]); 
	                  nodetext_ps(3,bground,textb[2],getx,gety);
	            }
                    moveto(getx,thisy);
                    outtext(textb[1]);
                    //moveto(xbox+tempscale+CWidth*t_count,gety);//fix to line up
                    moveto(tempscale,gety);//fix to line up
                    newleft=getx;                                       
                 }

		 tempy=gety;
                 zcount=0;//for rlayout:
                 moveto(tempscale,gety);//for rlayout: for left side

		 /*blank out area for rcode all neighborhoods image*/
		 rlayoutx=getx;
		 rlayouty=gety;
		 setfillstyle(SOLID_FILL,0);
		 bar(rlayoutx,rlayouty,Maxx,Maxy);
		 
                 for (z=tablemax;z>=0;z--){  //for rlayout:
                   zcount+=1; //for rlayout:
		   if (nhood==9 || value_range>2){
		      if (zcount%64==1) moveto(tempscale,gety+tempscale*4); //fold at 64 for k=9
		   }
		   else if (nhood==8){
		      if (zcount%32==1) moveto(tempscale,gety+tempscale*4); //fold at 32 for k=8
		   }
                   else if (nhood==5){
		      if (zcount%16==1) moveto(tempscale,gety+tempscale*4); //fold at 16 for k=5
		   }
                   else{ //(nhood==4
		      if (zcount%8==1) moveto(tempscale,gety+tempscale*4); //fold at 8 for k=4
		   }
                   dec_to_value_line(iso_group_image,z,9);
 
		    for (zz=0;zz<=8;zz++){
		      if (nhood==9) temp_image[zz]=get_value(iso_group_image,zz);
		      else if (nhood==8){
			 if (zz<=3) temp_image[zz]=get_value(iso_group_image,zz);
                         if (zz==4) temp_image[zz]=-1;
			 if (zz>4)  temp_image[zz]=get_value(iso_group_image,zz-1);
		      }
		      else if (nhood==5){
			 if (zz==1) temp_image[zz]=get_value(iso_group_image,zz-1);
			 else if (zz==3) temp_image[zz]=get_value(iso_group_image,zz-2);
			 else if (zz==4) temp_image[zz]=get_value(iso_group_image,zz-2);
			 else if (zz==5) temp_image[zz]=get_value(iso_group_image,zz-2);
			 else if (zz==7) temp_image[zz]=get_value(iso_group_image,zz-3);
			 else temp_image[zz]=-1;
		      }
		      else if (nhood==4){
			 if (zz==1) temp_image[zz]=get_value(iso_group_image,0);
			 else if (zz==3) temp_image[zz]=get_value(iso_group_image,1);
			 else if (zz==5) temp_image[zz]=get_value(iso_group_image,2);
			 else if (zz==7) temp_image[zz]=get_value(iso_group_image,3);
			 else temp_image[zz]=-1;
		      }
		    }			
		    
                    tempxx=getx;
                    tempyy=gety;
		    setcolor(divcolor);
		    zx=0;
                    for (zz=8;zz>=0;zz--){
                        zx+=1;
			if (temp_image[zz]==-1) setfillstyle(SOLID_FILL,black);
                        else if (value_range>2 || temp_image[zz]==0) 
			  setfillstyle(SOLID_FILL,color_v[temp_image[zz]]);

                        /*show nhoods with ontput 1 in red*/
                        else if (value_range==2 && get_bit(carule[0],z)==1) setfillstyle(SOLID_FILL,red);//for rlayout:
                        else setfillstyle(SOLID_FILL,white);

			if (wiring_postscript){
			   color_ps(wiring_postscript-1,fillcolor);
                           rect_fill_ps(getx,gety,tempscale,tempscale);
			   color_ps(wiring_postscript-1,getcolor());/*color or gray*/
			   rect_outline_ps(getx,gety,tempscale,tempscale);
			}
			bar(getx,gety,getx+tempscale,gety+tempscale);
			rectangle(getx,gety,getx+tempscale,gety+tempscale);
			
                        moverel(tempscale,0);
			if (zx%3==0) moveto(tempxx,gety+tempscale);
                     }
		     moveto(tempxx,tempyy);		    
		     moveto(getx+tempscale*4,gety);
                     if (z<tablemax+1 && zcount%8==0) moverel(tempscale,0);//for rlayout, gaps between 8s
	         }
                 restore_def_font();
	      }
	      
	      /*************************************************************************/
	      if (rlayout==0 && twod && hex2d==0){
                signed int newleft,thisy;
                 set_medium_font();
                 if (tempscale<vgax(1)) tempscale=vgax(1);
                 setcolor(white);
	         if (skip_prompts==0) moveto(xbox+tempscale,gety+CHeight);
		 else if (skip_prompts==1){ 
                    moveto(xbox+tempscale,gety);
                    thisy=gety;
		    
                    //sprintf(textb[1],"%*d",t_count,iso_index); //below set width of number
                    sprintf(textb[1],"%*d:%*d",t_count,iso_index,t_count,glbl_iso_list[iso_index][1]);
		    //fprintf(stderr,"\n%s",textb[1]);

                    if (wiring_postscript){
		          moveto(getx,gety+tempscale*2);                         
                          color_ps(wiring_postscript-1,white);
                          //sprintf(textb[2],"%*d",t_count,iso_index); //below set width of number
                          sprintf(textb[2],"%*d:%*d",t_count,iso_index,t_count,glbl_iso_list[iso_index][1]); 
	                  nodetext_ps(3,bground,textb[2],getx,gety);
	            }
                    moveto(getx,thisy);
                    outtext(textb[1]);
                    //moveto(xbox+tempscale+CWidth*t_count*2,gety);//fix to line up
		    moveto(xbox+tempscale+CWidth*(strlen(textb[1]) +1),gety);//fix to line up
                    newleft=getx;                                       
                 }                

		 tempy=gety;
	         for (z=1;z<=glbl_iso_list[iso_index][0];z++){		   
                   if (skip_prompts==2 && z==2) break; 
		   if (getx>=Maxx-tempscale*3){ //next line if near right edge
		        if (skip_prompts==0) moveto(xbox+tempscale,gety+tempscale*3.5); //y gap in fold
		        else if (skip_prompts==1) moveto(newleft,gety+tempscale*3.5);
                        else if (skip_prompts==2) moveto(startA,gety+tempscale*3.5);
		    }
		    dec_to_value_line(iso_group_image,glbl_iso_list[iso_index][z],9);
		    for (zz=0;zz<=8;zz++){ 
		      if (nhood==9) temp_image[zz]=get_value(iso_group_image,zz);
		      else if (nhood==8){
			 if (zz<=3) temp_image[zz]=get_value(iso_group_image,zz);
                         if (zz==4) temp_image[zz]=-1;
			 if (zz>4)  temp_image[zz]=get_value(iso_group_image,zz-1);
		      }
		      else if (nhood==5){
			 if (zz==1) temp_image[zz]=get_value(iso_group_image,zz-1);
			 else if (zz==3) temp_image[zz]=get_value(iso_group_image,zz-2);
			 else if (zz==4) temp_image[zz]=get_value(iso_group_image,zz-2);
			 else if (zz==5) temp_image[zz]=get_value(iso_group_image,zz-2);
			 else if (zz==7) temp_image[zz]=get_value(iso_group_image,zz-3);
			 else temp_image[zz]=-1;
		      }
		      else if (nhood==4){
			 if (zz==1) temp_image[zz]=get_value(iso_group_image,0);
			 else if (zz==3) temp_image[zz]=get_value(iso_group_image,1);
			 else if (zz==5) temp_image[zz]=get_value(iso_group_image,2);
			 else if (zz==7) temp_image[zz]=get_value(iso_group_image,3);
			 else temp_image[zz]=-1;
		      }
		    }			
		    
                    tempxx=getx;
                    tempyy=gety;
		    setcolor(divcolor);
		    zx=0;
                    for (zz=8;zz>=0;zz--){
                        zx+=1;
			if (temp_image[zz]==-1) setfillstyle(SOLID_FILL,black);
                        else if (value_range>2 || temp_image[zz]==0) 
			  setfillstyle(SOLID_FILL,color_v[temp_image[zz]]);

                        /*show nhoods with ontput 1 in red*/
                        else if (value_range==2 && get_bit(iso_rule,iso_index)==1) setfillstyle(SOLID_FILL,red);

                        else setfillstyle(SOLID_FILL,white);

			if (wiring_postscript){
			   color_ps(wiring_postscript-1,fillcolor);
                           rect_fill_ps(getx,gety,tempscale,tempscale);
			   color_ps(wiring_postscript-1,getcolor());/*color or gray*/
			   rect_outline_ps(getx,gety,tempscale,tempscale);
			}
			bar(getx,gety,getx+tempscale,gety+tempscale);
			rectangle(getx,gety,getx+tempscale,gety+tempscale);
			
                        moverel(tempscale,0);
			if (zx%3==0) moveto(tempxx,gety+tempscale);
                     }
		     moveto(tempxx,tempyy);		    
		     moveto(getx+tempscale*4,gety); 		     
	         }
                 restore_def_font();
	      }

              /*************************************************************************/
	      if (twod && hex2d==1){
                //signed short temp_color;
		signed int psx,psy,newleft,thisy;
		float hex_rad;
		 if (tempscale<vgax(1)) tempscale=vgax(1);
                 setcolor(white);
		 if (skip_prompts==0) moveto(xbox+tempscale,gety+CHeight);
		 else if (skip_prompts==1){ 
                    moveto(xbox+tempscale,gety);
                    thisy=gety;
                    sprintf(textb[1],"%*d",t_count,iso_index);
                    if (wiring_postscript){
		       moveto(getx,gety+tempscale*2);
                       color_ps(wiring_postscript-1,white);
                       sprintf(textb[2],"%*d",t_count,iso_index);
	               nodetext_ps(3,bground,textb[2],getx,gety);
	            }
                    moveto(getx,thisy);
                    outtext(textb[1]);
                    moveto(xbox+tempscale+CWidth*(t_count+1),gety);//fix to line up
                    newleft=getx;
                                        
                 }
                 
		 tempy=gety;
	         for (z=1;z<=glbl_iso_list[iso_index][0];z++){
                    if (skip_prompts==2 && z==2) break;		    
		    if (getx>=Maxx-tempscale*3){ //next line if near right edge
		    //if ((iso_tablemax-iso_index)%23==0){ //for k=7 12 rows of 23
		       if (skip_prompts==0) moveto(xbox+tempscale,gety+tempscale*3); //y gap in fold
                       else if (skip_prompts==1) moveto(newleft,gety+tempscale*3);
                       else if (skip_prompts==2) moveto(startA,gety+tempscale*3);
		    }
		    dec_to_value_line(iso_group_image,glbl_iso_list[iso_index][z],7);
		    for (zz=0;zz<=6;zz++){
		      if (nhood==7) temp_image[zz]=get_value(iso_group_image,zz);
		      else if (nhood==6){
			 if (zz<=2) temp_image[zz]=get_value(iso_group_image,zz);
                         else if (zz==3) temp_image[zz]=-1;
			 else if (zz>3)  temp_image[zz]=get_value(iso_group_image,zz-1);
		      }
		      else if (nhood==4){
			 if (zz==0) temp_image[zz]=-1;
			 else if (zz<=3 ) temp_image[zz]=get_value(iso_group_image,zz-1);
                         else if (zz==6) temp_image[zz]=get_value(iso_group_image,zz-3);
			 else temp_image[zz]=-1;
		      }
		      else if (nhood==3){
			 if (zz==0) temp_image[zz]=-1;
			 else if (zz<=2 ) temp_image[zz]=get_value(iso_group_image,zz-1);
                         else if (zz==6) temp_image[zz]=get_value(iso_group_image,zz-4);
			 else temp_image[zz]=-1;
		      }
		    }			
		    
                    tempxx=getx;
                    tempyy=gety;		    
                    startx=getx;
		    zx=0;
		    hex_rad=tempscale * cos(PI/6)*2/3;
                    for (zz=6;zz>=0;zz--){
		        zx+=1;
			if (temp_image[zz]==-1) setfillstyle(SOLID_FILL,black);
                        else if (value_range>2 || temp_image[zz]==0) 
			  setfillstyle(SOLID_FILL,color_v[temp_image[zz]]);
                        else setfillstyle(SOLID_FILL,white);
			    
			draw_hexagonal_2d_cell(hex_rad,tempscale,1,0,0,divcolor,getx,gety);
			/*reversed the order (postscript after draw) for postscript to work*/
			if (wiring_postscript){
                            color_ps(wiring_postscript-1,fillcolor);
			    hex_fill_ps();
			    color_ps(wiring_postscript-1,getcolor());/*color or gray*/
			    hex_outline_ps();
			}
			moverel(tempscale,0);
			
			if (zx==2) moveto(startx-tempscale+tempscale/2,gety+hex_rad*1.5);
			else if (zx==5) moveto(startx,gety+hex_rad*1.5);
                     }
		     moveto(tempxx,tempyy);		    
		     moveto(getx+tempscale*3.5,gety);//x gap
	         }
	      }
	      /*************************************************************************/
	      if (threed && show3das2d==1){//not used
		signed short ii;	
		if (tempscale<vgax(1)) tempscale=vgax(1);
		moveto(xbox+tempscale,gety+CHeight);
		 
		 tempy=gety;
		 tempx=getx;
	         for (z=1;z<=glbl_iso_list[iso_index][0];z++){
		    if (getx>=Maxx-tempscale*3) moveto(xbox+tempscale,gety+tempscale*10);
		    dec_to_value_line(iso_group_image,glbl_iso_list[iso_index][z],7);
		    for (zz=0;zz<=6;zz++){
		      if (nhood==7) temp_image[zz]=get_value(iso_group_image,zz);
		      else if (nhood==6){
			 if (zz<=2) temp_image[zz]=get_value(iso_group_image,zz);
                         if (zz==3) temp_image[zz]=-1;
			 if (zz>3)  temp_image[zz]=get_value(iso_group_image,zz-1);
		      }
		    }			
		    
                    tempxx=getx;
                    tempyy=gety;		    
                    startx=getx;
		    setcolor(divcolor);
		    zx=0;
		    //hex_rad=tempscale * cos(PI/6)*2/3;
                    for (zz=26;zz>=0;zz--){
		        zx+=1;
		        if (zz==22) ii=6;
		        else if (zz==16) ii=5;
			else  if (zz==14 || zz==13 || zz==12) ii=zz-10;
		        else if (zz==10) ii=1;
		        else if (zz==4) ii=0;
			else ii=-1;
			if (ii==-1) setfillstyle(SOLID_FILL,0);
			if (temp_image[ii]==-1) setfillstyle(SOLID_FILL,0);
                        else if (value_range>2 || temp_image[ii]==0) 
			  setfillstyle(SOLID_FILL,color_v[temp_image[ii]]);
                        else setfillstyle(SOLID_FILL,white);
			
			if (ii!=-1 && temp_image[ii]!=-1) //show nothing
			     bar(getx,gety,getx+tempscale,gety+tempscale);
			rectangle(getx,gety,getx+tempscale,gety+tempscale);
			
			moverel(tempscale,0);
			if (zx%3==0) moveto(tempxx,gety+tempscale);
                     }
		     moveto(tempxx,tempyy);
		    
		     moveto(getx+tempscale*4,gety);
	         }
	      }

              /*************************************************************************/
	      else if (threed){
		signed int ii,temp_i3d,temp_j3d,temp_h3d,xi,xj,xh,newleft;
		char temp_d_mode,temp_draw_3d_grid;
		if (tempscale<vgax(1)) tempscale=vgax(1);
		if (skip_prompts==0) moveto(xbox+tempscale,gety+CHeight*2+1.5*tempscale);
                else if (skip_prompts==1){ 
                   moveto(xbox+tempscale,gety+6*tempscale);
                   sprintf(textb[1],"%*d",t_count,iso_index);
                   if (wiring_postscript){
                      sprintf(textb[2],"%*d",t_count,iso_index);
	              nodetext_ps(3,bground,textb[2],getx,gety);
	           }
                   outtext(textb[1]);
                   moveto(xbox+tempscale+CWidth*t_count,gety);//fix to line up
                   newleft=getx;
                }   
		temp_i3d=i3d;
		temp_j3d=j3d;
		temp_h3d=h3d;
		temp_d_mode=d_mode;
		temp_draw_3d_grid=draw_3d_grid; 
		i3d=j3d=h3d=3;
		draw_3d_grid=1;
		d_mode=4;
		
		 tempy=gety;
		 tempx=getx;		 
	         for (z=1;z<=glbl_iso_list[iso_index][0];z++){
                    if (skip_prompts==2 && z==2) break;
		    if (getx>=Maxx-tempscale*5){ 
                        if (skip_prompts==0) moveto(xbox+tempscale,gety+tempscale*6);
                        else if (skip_prompts==1) moveto(newleft,gety+tempscale*6);
                        else if (skip_prompts==2) moveto(startA,gety+tempscale*6);
                    }
		    dec_to_value_line(iso_group_image,glbl_iso_list[iso_index][z],7);
		    for (zz=0;zz<=6;zz++){
		      if (nhood==7) temp_image[zz]=get_value(iso_group_image,zz);
		      else if (nhood==6){
			 if (zz<=2) temp_image[zz]=get_value(iso_group_image,zz);
                         if (zz==3) temp_image[zz]=-1;
			 if (zz>3)  temp_image[zz]=get_value(iso_group_image,zz-1);
		      }
		    }			
		    
                    tempxx=getx;
                    tempyy=gety;		    
                    startx=getx;
		    
		    
		    setcolor(white);
		    moverel(tempscale/4,gety);
		    //wiring_postscript is within function
		    if (tempscale>=4) draw_axon_plane(tempscale,tempyy-tempscale,1);
                    else draw_axon_plane(tempscale,tempyy-tempscale,0);
		    moveto(tempxx,tempyy);
		    
                    zz=i3d*j3d*h3d;//=27
	           /*----------------------------------------------------------------------*/	      
		    
		   for (xh=0;xh<=2;xh++){
		      moveto(tempxx,tempyy+xh*tempscale);
		      for (xj=0;xj<=2;xj++){
		         moveto(tempxx+xj*sin(PI/4)*tempscale,gety-sin(PI/4)*tempscale);
		         for (xi=0;xi<=2;xi++){
			   moveto(getx+tempscale,gety); 
			 
			   zz-=1;//countdown from 26
			
		           if (zz==22) ii=6;
		           else if (zz==16) ii=5;
			   else  if (zz==14 || zz==13 || zz==12) ii=zz-10;
		           else if (zz==10) ii=1;
		           else if (zz==4) ii=0;
			   else ii=-1;
			   if (ii==-1) setfillstyle(SOLID_FILL,0);
			   if (temp_image[ii]==-1) setfillstyle(SOLID_FILL,0);
                           else if (value_range>2 || temp_image[ii]==0) 
			               setfillstyle(SOLID_FILL,color_v[temp_image[ii]]);
                           else setfillstyle(SOLID_FILL,white);


			   if (ii!=-1 && temp_image[ii]!=-1){
			      if (wiring_postscript){
                                 color_ps(wiring_postscript-1,fillcolor);
				 circle_fill_ps(getx,gety,tempscale/2);/*filled circle*/
                                 color_ps(wiring_postscript-1,white);
				 circle_ps(getx,gety,tempscale/2);/*outline*/		
			      }	
                              setcolor(white);
                              pieslice(2,getx,gety,0,360,tempscale/2);
	 		   }	
			   //else circle(getx,gety,tempscale/2); //to fill empty space
				
		       }//xi
	   	   }//xj
	         }//xh
	         /*----------------------------------------------------------------------*/
		     moveto(tempxx,tempyy);		    
		     moveto(getx+tempscale*6,gety);
	         }//z
		 i3d=temp_i3d;
		 j3d=temp_j3d;
		 h3d=temp_h3d;
		 d_mode=temp_d_mode;
		 draw_3d_grid=temp_draw_3d_grid; 
	      }
              /*************************************************************************/

	      if (skip_prompts==1){
                 if (iso_index==0 || gety>Maxy-CHeight*3) skip_prompts=0;//stop and show prompts;
                 else{
                   if (threed) moveto(xbox,gety+tempscale*1); //y gaps between groups
                   else if (twod && hex2d==1) moveto(xbox,gety+tempscale*3.5);
                   else if (twod && hex2d==0) moveto(xbox,gety+tempscale*4);
                   else if (oned) moveto(xbox,gety+tempscale*3);
                   goto iso_all_start;//show next group on new lime;
                 }
              }
              else if (skip_prompts==2){
                 if (iso_index==0 || gety>Maxy-CHeight*3) skip_prompts=0;//stop and show prompts;
                 else goto iso_all_start;//show next group on new lime;
              }
              
              
	      /*************************************************************************/
              wiring_postscript=0;
	      temp_is=is[0];
              
              if (gety>Maxy-CHeight*3){
                  erase_box(xbox,Maxy-CHeight*3,Maxx-4,Maxy-3);//make space for prompt at bottom  
                  moveto(xbox,Maxy-CHeight*3);
              }
	      else moveto(xbox,gety+tempscale*3+CHeight);
              
	      setcolor(white);
	      sprintf(textb[1],"%d",iso_tablemax);
	      stringlength=strlen(textb[1]);
	      if (rlayout==1) sprintf(textb[0],"full rule-table neighborhoods: %d-0",tablemax);
              else sprintf(textb[0],"newgroup: down-ret/] up-[ index(%d-0)",iso_tablemax);
	      outtext(textb[0]);
              moveto(xbox,gety+CHeight);
		 
	      if (twod && hex2d==0){//tog-X works for value_range>2
		if (rlayout==1) sprintf(textb[0],"tog-X scale(%.1f)-e/E/c/C PScript-p exit-q:",tempscale);
		else sprintf(textb[0],"tog-X scale(%.1f)-e/E/c/C more-m all-a PScript-p exit-q:",tempscale);
	      }	
              else sprintf(textb[0],"scale(%.1f)-e/E/c/C more-m all-a PScript-p exit-q:",tempscale);
	      outtext(textb[0]);
	      
              is[0]=0;
	      input_string(stringlength,-1);

	      //fprintf(stderr,"\natoi(is)=%d",atoi(is));
	      //fprintf(stderr,"\n before-rlayout=%d",rlayout);
	     
              if (is[0]==113){
		 if (rlayout==1){
                      /*blank out area for rcode all neighborhoods image*/		 
		      setfillstyle(SOLID_FILL,0);
		      bar(rlayoutx,rlayouty,Maxx,Maxy);
	         }
		 goto skipPS; //entered "q"
              }
              else if (is[0]=='m' || is[0]=='a' /*|| is[0]=='A'*/){
		     if (is[0]=='m' /*|| is[0]=='a'*/) skip_prompts=1;
                     //else if  (is[0]=='A') skip_prompts=2;
                     else if  (is[0]=='a') skip_prompts=2;
                     xbox=draw_prompt_box(box_lines);

                     if (skip_prompts==1) moveto(xbox,vgay(2)+tempscale);
                     else if (skip_prompts==2){
		        if (threed) startA=xbox-vgax(1);
		        else startA=xbox+vgax(6.5);
                        moveto(startA,vgay(2)+tempscale*6);
                     }
                     if (is[0]=='m' && iso_index>=0){                          
		          if (iso_index==0 || iso_index>iso_tablemax) iso_index=iso_tablemax+1;
                          else{
                             iso_index+=3; //else continue from last but include overlap
                              if (iso_index>iso_tablemax) iso_index=iso_tablemax+1;
                          } 
                          m_iso_index=iso_index;
                     }
                     else iso_index=iso_tablemax-zcount+1;
		     
		     if (iso_index<0 || iso_index>iso_tablemax) iso_index=iso_tablemax+1;//this fixed bug
		     
		     //fprintf(stderr,"\n iso_index=%d",iso_index);
                     goto iso_all_start;//start showing all group;
              }
              
	      else if (is[0]==13 || is[0]==']'){//or return for next iso-index countdown
		   zcount+=1;
		   if (zcount>iso_tablemax) zcount=0;    
		   goto iso_start;
	      }
	      else if (is[0]=='['){//for previous iso-index countup
		   zcount-=1;
		   if (zcount<0) zcount=iso_tablemax;   

		   goto iso_start;
	      }
              else if (is[0]=='e' || is[0]=='E') {//enter 'e'
		   if (is[0]=='e') tempscale++;
                   else if (is[0]=='E') tempscale+=0.1;
		   goto iso_start;
	      }
	      else if (is[0]=='c' || is[0]=='C'){//enter 'c'
		   if (is[0]=='c') tempscale--;
                   else if (is[0]=='C') tempscale-=0.1;
		   goto iso_start;
	      }
	      
	      else if (is[0]=='X' && twod && hex2d==0){
		   //toggle usual, and rlayout showing all 2d square nhoods in detail, k=4,5,8,9	
		   if (rlayout==1){
                      /*blank out area for rcode all neighborhoods image*/		 
		      setfillstyle(SOLID_FILL,0);
		      bar(rlayoutx,rlayouty,Maxx,Maxy);
	           }
		   rlayout=abs(rlayout-1);
		   goto iso_start;
	      }
	      
	      else if (is[0]=='P' || is[0]=='p'){
		 char filename_iso_PS[13];
		 
                   /*to redraw the whole thing exactly as is 
                             and save vector PostScript*/
		 		 
		            if (is[0]=='p') wiring_postscript=1;//color
		            else if (is[0]=='P') wiring_postscript=2;//greyscale
			    
                            file_ret=select_filename("SAVE","PostScript file","*.ps","my_isoPS");
                            if (file_ret=='q'){
			       wiring_postscript=0;
                               goto skipPS;
                            }
	                    memmove(filename_iso_PS,filename,13);
                            /*delete previous*/
                            fid_PS=myopen(filename_iso_PS,1,0);
                            vret=write(fid_PS,"",0);
                            close(fid_PS);

                            /*start new*/
                            fid_PS=myopen(filename_iso_PS,1,1);
                            if (fid_PS==-1){ 
                                  file_error(filename_iso_PS);
                                  close(fid_PS); 
                                  wiring_postscript=0;
                                  break;  
                            }
                            psize_ps=pointsize;
			    wiring_postscript=1;
                            prepare_basinPS(2,2); /*write/define postScipt for wiring*/
       
                            if (temp_is=='a' || temp_is=='m' /*|| temp_is=='A'*/){ //ps for all groups
			       //fprintf(stderr,"\nprinting all groups");
			       
                               if (/*temp_is=='a' ||*/ temp_is=='m') skip_prompts=1;
                               //else if (temp_is=='A') skip_prompts=2;
                               else if (temp_is=='a') skip_prompts=2;
                               xbox=draw_prompt_box(box_lines);
                               if (skip_prompts==1) moveto(xbox,vgay(2)+tempscale);
                               else if (skip_prompts==2){
                                  if (threed) startA=xbox-vgax(1);
		                  else startA=xbox+vgax(6.5);
                                  moveto(startA,vgay(2)+tempscale*6);
                               }
                               

                               if (temp_is=='a') iso_index=iso_tablemax-zcount+1;
			       //if (temp_is=='a') iso_index=iso_tablemax+1;
			       else if (temp_is=='m') iso_index=m_iso_index;
                               resetfont_ps("Helvetica",CWidth*1.3);
                               //resetfont_ps("Courier",CWidth*1.3);//require non-prop
                               is[0]=temp_is; //to Pprint same more than once, diff names
                               goto iso_all_start;
                            }                               			 
		            else{ //ps for one group
			       //fprintf(stderr,"\nprinting one group");
                               skip_prompts=0;
                               goto iso_start;
                            }	         
              }

	      else if (atoi(is)>=0 && atoi(is)<=iso_tablemax){
		 zcount=iso_tablemax-atoi(is);
		 goto iso_start;
	      }

	    skipPS:
              free(temp_image);
	      setcolor(tempcolor);
	      color_v[0]=temp_color_v0;
	      moveto(getx,gety);
              setviewport(0, 0, Maxx, Maxy, 0);
	      uncover_free_prompt_box(8);//restore define_bits_prompts
              
           iso_skip:
             
	     is[0]='r';
             goto endFunc;
      }
      
      /*seed 1d, 1d as 2d, 2d, 3d, or rule as 1d pattern (or patch)*/
      if (patch_only==0 && (test=='F' || test=='P')){ /*if moving patch is not active*/
	unsigned int xbox,tempx,tempy;
        signed int temp_lineL,temp_showbits_1d_as_2d,
                                temp_oned,temp_twod,temp_threed;

#       define clean_up_rule {\
	       lineL=temp_lineL;\
               showbits_1d_as_2d=temp_showbits_1d_as_2d;\
               oned=temp_oned;\
               twod=temp_twod;\
               threed=temp_threed;\
         }
       
         tempx=getx;
         tempy=gety;

         if (isrule>0){
	    temp_lineL=lineL;
            lineL=rr;
            temp_showbits_1d_as_2d=showbits_1d_as_2d;
            showbits_1d_as_2d=0;
            temp_oned=oned;
            temp_twod=twod;
            temp_threed=threed;
            oned=1;
            twod=threed=0;            
         }

         wiring_postscript=0; /*for 3d state graphic - sharing this name with 3d wiring graphic*/

         /*grab the whole hint box, to restore later*/
         get_prompt_box(2,4);

         xbox=draw_prompt_box(1);
         if (test=='F'){
            if (isrule==0){
	       if (showbits_1d_as_2d==1) 
                       outtext("SEED: load-l, save all-a, save1d>2d-x, save patch-p:");
               else outtext("SEED: load-l, save all-a, save patch-p:");
            }
            else if (isrule==1) outtext("RCODE as 1d SEED: save all-a, save patch-p:");
            else if (isrule==2) outtext("TCODE as 1d SEED: save all-a, save patch-p:");
            else if (isrule==3) outtext("KCODE as 1d SEED: save all-a, save patch-p:");
	    else if (isrule==4) outtext("ISO-CODE as 1d SEED: save all-a, save patch-p:");
	    
         }
         //moveto(xbox,gety+CHeight);
         else if (test=='P'){
	    if (isrule){
               if (isrule==1) outtext("PostScript RCODE: save all-a, save patch-p:");
               else if (isrule==2) outtext("PostScript TCODE: save all-a, save patch-p:");
               else if (isrule==3) outtext("PostScript KCODE: save all-a, save patch-p:");
	       else if (isrule==4) outtext("PostScript ISO-CODE: save all-a, save patch-p:");
            }
	    else if (oned) outtext("PostScript 1d: save all-a, save patch-p:");            
            else if (twod) outtext("PostScript 2d: save all-a, save patch-p:");
            else if (threed) outtext("PostScript 3d: save all 2d-a, save patch 2d-p, only 3d-3:");
         }
         input_string(1,0);
         if ( (test=='F' && isrule==0 && (is[0]=='l' || is[0]=='a' || 
                             (is[0]=='x' && showbits_1d_as_2d==1)  || is[0]=='p') ) ||
              (test=='F' && isrule>0  && (is[0]=='a' || is[0]=='p') ) ||
              (test=='P' && (twod || oned) && (is[0]=='a' || is[0]=='p')) ||
              (test=='P' && threed && (is[0]=='a' || is[0]=='p' || is[0]=='3')) ); /*do nothing*/ 
         else{  /*otherwize exit*/                  
            uncover_free_prompt_box(2);
            moveto(tempx,tempy);
            if (isrule>0) {clean_up_rule};
            continue;
         }
         if (test=='P' && threed && is[0]=='3' && isrule==0){                               
            draw_prompt_box(1);
            outtext("3d to PostScript: greyscale-P color-def:"); 
            input_string(1,0);
            if (is[0]!='q'){         
               if (is[0]=='P') wiring_postscript=2;
               else wiring_postscript=1;
               file_ret=select_filename("SAVE","PostScript file","*.ps","my_3dPS");
               if (file_ret=='q'){
	          wiring_postscript=0;                  
                  uncover_free_prompt_box(2);
                  moveto(tempx,tempy);
                  continue;
               }
               if ((filename_3d_PS=(char *)calloc(13,sizeof(char)))
				   ==NULL) outof_memory("filename_3d_PS");
	       memmove(filename_3d_PS,filename,13);
               /*delete previous*/
               fid_PS=myopen(filename_3d_PS,1,0);
               vret=write(fid_PS, "",0);
               close(fid_PS);
               /*start new*/
               fid_PS=myopen(filename_3d_PS,1,1);
               if (fid_PS==-1){ 
                  file_error(filename_3d_PS);
                  close(fid_PS); 
                  wiring_postscript=0;
                  free(filename_3d_PS);
                  uncover_free_prompt_box(2);
                  moveto(tempx,tempy);
                  continue;
               }
               /*need this to restrict BoundingBox*/
               sprintf(textb[0],"%%!PS-Adobe-3.0 EPSF-3.0\n");
               vret=write(fid_PS,textb[0],strlen(textb[0]));
               sprintf(textb[0],"%%%%BoundingBox: %d %d %d %d\n",
		  (signed int)(tview_x0+cellscale*i3d+CWidth*3),
		  vgay(33),
		  (signed int)(tview_x0+cellscale*i3d+CWidth*6+(i3d+2)*fscale
				    +sin(PI/4) * fscale*j3d),
		  (signed int)(vgay(33)+(h3d+2)*fscale+sin(PI/4)*fscale*j3d+CWidth*3));
	       vret=write(fid_PS,textb[0],strlen(textb[0]));
               prepare_basinPS(4,2); /*write/define postScipt for 3d*/
	    }            
            uncover_free_prompt_box(2);
            moveto(tempx,tempy);
            is[0]='r';  /*just update 3d*/      
            goto endFunc;
         }
         else if (test=='P' && is[0]=='a'){ /*save whole image postScript file*/
            if (showbits_1d_as_2d || 
                       (isrule==0 && (twod || threed))) /*in 3d this does 2d version only*/
	         save_to_PostScript(array,i2d,j2d,h3d,lineL, 
			 cellscale,show_2d_divs,divcolor,show_dots,misc_hex2d,gaps_in_string);
            else /*1d selected with 'b' in select seed, or for rule*/
                save_to_PostScript(array,sizex,sizey,0,lineL, 
			 cellscale,show_2d_divs,divcolor,show_dots,misc_hex2d,gaps_in_string);
            uncover_free_prompt_box(2);
            moveto(tempx,tempy);

            if (isrule>0) {clean_up_rule};
            continue;
         }
         else if (is[0]=='p'){ /* part of the image or file only*/
           unsigned int si,sj,sh,ei,ej,eh,
	                  temp_ei,temp_ej,temp_eh,
                          zi,zj,zh,counti,countj,counth,
                          indexA,indexP,patch_size;
           signed int xbox,bytesP;
           char *patch_buf,create_ps=0;

	    if (test=='P') create_ps=1; /*save patch postScript file*/

            si=sj=sh=0;
            ei=ej=eh=1;
            if (oned || isrule) ei=lineL-1; 
            if (twod){
               ei=i2d-1;
               ej=j2d-1;
	    }    
            if (threed){
               ei=i3d-1;
               ej=j3d-1;
               eh=h3d-1;
	    }
 
            get_prompt_box(6,2);
            xbox=draw_prompt_box(2);
            if (oned || isrule) sprintf(textb[0],
		     "1d: max i=%d, revise coords-ret, accept patch %d-%d -p:",
                                   lineL-1,patch123d[0],patch123d[1]);
            else if (twod) sprintf(textb[0],
                 "2d: max i,j=%d,%d, revise coords-ret, accept patch %d,%d-%d,%d -p:",
                   i2d-1,j2d-1,patch123d[0],patch123d[1],patch123d[2],patch123d[3]);
            else if (threed) sprintf(textb[0],
	       "3d: max i,j,h=%d,%d,%d revise coords-ret, %d,%d,%d-%d,%d,%d -p:",
                   i3d-1,j3d-1,h3d-1,
                     patch123d[0],patch123d[1],patch123d[2],
                           patch123d[3],patch123d[4],patch123d[5]);
            outtext(textb[0]);
            input_string(1,0);
 
            /*sets coords according to last 2 clicks, also as default*/
            if (oned || isrule){ 
		     si=patch123d[0];
                     ei=patch123d[1];
            }
	    else if (twod){ 
		     si=patch123d[0];
                     sj=patch123d[1];
                     ei=patch123d[2];
                     ej=patch123d[3];
            }
            else if (threed){ 
		     si=patch123d[0];
                     sj=patch123d[1];
                     sh=patch123d[2];
                     ei=patch123d[3];
                     ej=patch123d[4];
                     eh=patch123d[5];
            }
            if (is[0]=='p') goto skip_patch; /*skip defining patch manually*/

            moveto(xbox,gety+CHeight);
            sprintf(textb[0],"start i:");
            outtext(textb[0]);
            input_string(3,0); 
            if (is[0]!=13 && atoi(is)<=ei && atoi(is)>-1){
                si=atoi(is);
            }
            if (twod || threed){
               sprintf(textb[1]," j:");
               outtext(textb[1]);
               input_string(3,0);
               if (is[0]!=13 && atoi(is)<=ej && atoi(is)>-1) sj=atoi(is);
            }
            if (threed){
               sprintf(textb[1]," h:");
               outtext(textb[1]);
               input_string(3,0);
               if (is[0]!=13 && atoi(is)<=eh && atoi(is)>-1) sh=atoi(is);
            }
            sprintf(textb[0]," end i:");
            outtext(textb[0]);
            input_string(3,0);
            if (is[0]!=13 && atoi(is)<=ei && atoi(is)>-1){
               ei=atoi(is);
            }
            if (twod || threed){
               sprintf(textb[1]," j:");
               outtext(textb[1]);
               input_string(3,0);
               if (is[0]!=13 && atoi(is)<=ej && atoi(is)>-1) ej=atoi(is);
            }
            if (threed){
               sprintf(textb[1]," h:");
               outtext(textb[1]);
               input_string(3,0);
               if (is[0]!=13 && atoi(is)<=eh && atoi(is)>-1) eh=atoi(is);
	    }

	   skip_patch:
            if (ei<si){
               temp_ei=ei;
               ei=si;
               si=temp_ei;
            }
	    if (twod || threed){
	       if (ej<sj){
                  temp_ej=ej;
                  ej=sj;
                  sj=temp_ej;
               }
               if (eh<sh && threed){
                  temp_eh=eh;
                  eh=sh;
                  sh=temp_eh;
               }
            }
            if (oned || isrule) patch_size=ei-si+1;
            else if (twod) patch_size=(ei-si+1)*(ej-sj+1);
            else if (threed) patch_size=(ei-si+1)*(ej-sj+1)*(eh-sh+1);
	    bytesP=(signed int)ceil(((double)(value_bits*patch_size))/8);
            if ((patch_buf=(char *)calloc(bytesP,sizeof(char)))
					==NULL) outof_memory("patch_buf");
            counti=countj=counth=-1;
            if (oned || isrule){
                for (zi=si;zi<=ei;zi++){
                   counti+=1;
                   indexA=zi;
                   indexP=counti;
                   set_value(patch_buf,indexP,get_value(array,indexA));
                }
            }
            else if (twod){ 
               for (zj=sj;zj<=ej;zj++){
	          countj+=1;
                  counti=-1;
                  for (zi=si;zi<=ei;zi++){
		     counti+=1;
		     indexA=i2d*zj + zi;
                     indexP=(ei-si+1)*countj + counti;
		     set_value(patch_buf,indexP,get_value(array,indexA));
                  }
               }
	    }
            else if (threed){
               for (zh=sh;zh<=eh;zh++){
                  counth+=1;
                  countj=-1;
                  for (zj=sj;zj<=ej;zj++){
	             countj+=1;
                     counti=-1;
                     for (zi=si;zi<=ei;zi++){
		        counti+=1; 
		        indexA=(i3d*j3d*zh) + (i3d*zj) + zi; 
                        indexP=(ei-si+1)*(ej-sj+1)*counth + 
                                 ((ei-si+1)*countj) + counti;
		        set_value(patch_buf,indexP,get_value(array,indexA));
                     }
                  }
               }
	    }
           
            if (create_ps==1){
               if (oned || isrule){
		 unsigned int temp_x,temp_y;
		    if (patch_size<64){
                         temp_x=patch_size;
                         temp_y=1;
                    }
                    else{
                        temp_x=sizex;
                        temp_y=(unsigned int)ceil(((double)(patch_size))/sizex);
                    }
                    save_to_PostScript(patch_buf,temp_x,temp_y,0,
			      patch_size,cellscale,show_2d_divs,divcolor,
                              show_dots,misc_hex2d,gaps_in_string);
               }               
	       else if (twod) save_to_PostScript(patch_buf,ei-si+1,ej-sj+1,eh-sh+1,
			      patch_size,cellscale,show_2d_divs,divcolor,
                              show_dots,misc_hex2d,gaps_in_string);
               else if (threed) 
                  save_to_PostScript(patch_buf,ei-si+1,(ej-sj+1)*(eh-sh+1),eh-sh+1,
			      patch_size,cellscale,show_2d_divs,divcolor,
                              show_dots,misc_hex2d,gaps_in_string);
               
               free(patch_buf);               
               uncover_free_prompt_box(2);
               moveto(tempx,tempy);
               if (isrule>0) {clean_up_rule};
               continue;
            }
            else{ /*not .ps image, but save seed patch*/
               save_patch_2d(patch_size,bytesP,patch_buf,si,sj,ei,ej);
            }
            uncover_free_prompt_box(6); 
     
         }/* part of the image or file only*/
         
         if (is[0]=='l' && isrule==0){ /*load for seed only - not rule*/  
            load_save_wrs('l',array,'s');            
            uncover_free_prompt_box(2);
            moveto(tempx,tempy);
            is[0]='r';
            if (isrule>0) {clean_up_rule};
            goto endFunc;
         }
         /*test=='F' save for seed or rule as seed*/
         else if (is[0]=='a') load_save_wrs('s',array,'s');
         /*'x' save 1d as 2d if showbits_1d_as_2d==1*/
         else if (is[0]=='x') load_save_wrs('s',array,'x');
         uncover_free_prompt_box(2);
         moveto(tempx,tempy);
         if (isrule>0) {clean_up_rule};
         continue;
      }/*seed 1d, 1d as 2d, 2d, 3d, or rule as 1d pattern (or patch)*/


      /*arrows:128+  75=left,77=right,72=up,80=down*/
      /*left arrow or back space*/
      if (test==LeftArrow || test==8){
	 if (zcount>0){
	    moveto(getx-cellscale,gety);
            if (gaps_in_string==1 && zcount%8==0){ /*jump gaps if set*/
	       if (Maxx>=799) moverel(-3,0);
	       else moverel(-2,0);
	    }
	    if (zcount%foldposs==0){
               if (misc_hex2d==1 && cellscale>=3)
		   moveto(startx+cellscale*(foldposs-1),
                     gety-hex_vmove);
	       else moveto(startx+cellscale*(foldposs-1),gety-cellscale);
               if (gaps_in_string==1){
		  if (Maxx>=799) moverel(((foldposs/8)-1)*3,0);
		  else moverel(((foldposs/8)-1)*2,0);
	       }
	    }
	    zcount--;
	 }
	 else if (zcount==0){
            if (misc_hex2d==1 && cellscale>=3)
	      moveto(startx+cellscale*((rr-1)%foldposs),
	        starty+hex_vmove*((rr-1)/foldposs) ); 
            else moveto(startx+cellscale*((rr-1)%foldposs),
	        starty+cellscale*((rr-1)/foldposs) );
	    if (isrule==1 && nhoodz>3){
	       if (Maxx>799) moverel(((foldposs/8)-1)*3,0);
	       else moverel(((foldposs/8)-1)*2,0);
	    }
	    zcount=rr-1;
	 }
	 showbitcount(isrule,leftpos,zcount,cellx,cellscale,left_value);
	 continue;
      }
      /*right arrow*/
      if (test==RightArrow){
	 moveto(getx+cellscale,gety);
	 zcount++;
         if (gaps_in_string==1 && zcount%8==0){ /*jump gaps if set*/
	    if (Maxx>=799) moverel(3,0);
	    else moverel(2,0);
	 }
	 if (zcount%foldposs==0){
            if (misc_hex2d==1 && cellscale>=3)
               moveto(startx,gety+cellscale*(PI/6));
            else moveto(startx,gety+cellscale);
         }
	 if (zcount==rr){
	    moveto(startx,starty);
	    zcount=0;
	 }
	 showbitcount(isrule,leftpos,zcount,cellx,cellscale,left_value);
	 continue;
      }
      /*down arrow*/
      if (test==DownArrow){
	 if (rr-1>=zcount+foldposs){
            if (misc_hex2d==1 && cellscale>=3)
	       moveto(getx,gety+hex_vmove);
            else moveto(getx,gety+cellscale);
	    zcount+=foldposs;
	 }
	 showbitcount(isrule,leftpos,zcount,cellx,cellscale,left_value);
	 continue;
      }
      /*up arrow*/
      if (test==UpArrow){
	 if (zcount>=foldposs){
            if (misc_hex2d==1 && cellscale>=3)
                moveto(getx,gety-hex_vmove);
	    else moveto(getx,gety-cellscale);
	    zcount-=foldposs;
	 }
	 showbitcount(isrule,leftpos,zcount,cellx,cellscale,left_value);
	 continue;
      }
      
      /*3d: up h-axis*/
      /*else if (test=='['){  
         if (threed){
             n=leftpos-zcount;
             hh=n/(i3d*j3d);

	     if (zcount>=foldposs){
	    moveto(getx,gety-cellscale);

	    zcount-=foldposs;
	    }
	    showbitcount(isrule,leftpos,zcount,cellx,cellscale,left_value);
         }
	 continue;
      }*/

      /*carrage return*/
      if (test==13){         
	 is[zcount]=13;
	 /*fflush(stdin);*/
	 break;
      }
      /*test for digit*/
      if (stringtype==1 && zcount<rr){
          sprintf(textb[1],"%c",test);
          if (isdigit(test) && atoi(textb[1])<=value_range-1){
	       left_value=(unsigned char)atoi(textb[1]);
               right_value=(value_range-1)-left_value;               
               cellcolor=color_v[left_value];
               setfillstyle(SOLID_FILL,cellcolor);
               for (z=0; z<=thick_line; z++){
                 if (z<=1) z1=z;
                 else {  
		    if (z%2==0) z1=-z/2;
                    else z1=z/2+1;
                 }
                 
                 if (celly+z1<0 || celly+z1>sizey-1) continue;
                 temp_zcount=zcount+foldposs*z1;
                 if (temp_zcount>leftpos) continue;
                 draw_and_set_value_line(0,array,isrule,
                             left_value,leftpos,temp_zcount,cellscale,
                             show_2d_divs,show_dots,cellcolor,getx,gety,z1); 
               } 
	       zcount++;
	       moverel(cellscale,0);
               if (gaps_in_string==1 && zcount%8==0){ /*jump gaps if set*/
	          if (Maxx>=799) moverel(3,0);
	          else moverel(2,0);
	       }
	       if (zcount%foldposs==0){
                  if (misc_hex2d==1 && cellscale>=3)
                     moveto(startx,gety+hex_vmove); 
                  else moveto(startx,gety+cellscale);
               }
	       if (zcount==rr){
	          moveto(startx,starty);
	          zcount=0;
	       }
	   }
           /*draw vertical lines down*/
	   if (test=='v'){
              cellcolor=color_v[left_value];   
              setfillstyle(SOLID_FILL,cellcolor);

              for (z=0; z<=thick_line; z++){
                 if (z<=1) z1=z;
                 else {  
		    if (z%2==0) z1=-z/2;
                    else z1=z/2+1;
                 }
                 if (cellx+z1<0 || cellx+z1>sizex-1) continue; 
                 temp_zcount=zcount+z1;
                 if (temp_zcount>leftpos) continue;
                 draw_and_set_value_line(0,array,isrule,
                             this_value,leftpos,temp_zcount,cellscale,
                             show_2d_divs,show_dots,cellcolor,getx,gety,z1); 
                 if (rr-1>=zcount+foldposs){
                    if (misc_hex2d==1 && cellscale>=3) moveto(getx,gety+hex_vmove);
	            else moveto(getx,gety+cellscale);
	            zcount+=foldposs;
	         } 
	     }
          }      
      }/*test for digit*/
   }/*while (1)*/

  endFunc:
   if (mouse_found){
#     if __WATCOM__     /*release mouse for rectangle*/
         mouse_call(7,0,0,getmaxx());
         mouse_call(8,0,0,getmaxy());
#     elif __UNIX__
         XDefineCursor(D,W,rightCursor); /*restore cursor shape*/
#     endif
   }
   moveto(tempx,tempy);
   return(cellscale);
}

/********************** seperate function to save a 2d patch, March 2015 ************/
signed int save_patch_2d(unsigned int patch_size, signed int bytesP,char *patch_buf,
          signed int st_i,signed int st_j, signed int en_i, signed int en_j){
   signed int buffreq=-1;
   unsigned char *buf;
   signed int fid;
   char lead_bytes;

            /*see load_save_wrs in l_save88.c for details*/ 
            /*need more lead bytes big lattice > unsigned short*/
            if  (patch_size<Max_ushort) lead_bytes=5; /*Max_ushort= 65535*/
            else lead_bytes=9; /*up to (Maxu-1)=4294967294 in theory*/
 
            sprintf(textb[3],"mysee_v%d",value_range);
            file_ret=select_filename("SAVE","PATCH","*.eed",textb[3]);
            if (file_ret=='q'){
	        free(patch_buf);
                return(buffreq);
            }
            buffreq=lead_bytes+bytesP;
            sprintf(textb[0],"buf, buffreq=%d, calloc failed",buffreq);
            if ((buf=(unsigned char *)calloc(buffreq,sizeof(unsigned char)))
				 ==NULL) outof_memory(textb[0]);
            fid=myopen(filename,1,0);
            if (fid==-1){
               file_error(filename);     
               close(fid);
               free(buf);
               free(patch_buf);
               return(buffreq); 
            }
            if (patch_size<Max_ushort){
              buf[0]=value_range;
	      buf[1]=(unsigned char)(patch_size & 0x00ff); /*low byte */
	      buf[2]=(unsigned char)(patch_size >> 8);     /*high byte*/
	      if (twod || threed){
	         buf[3]=(unsigned char)(en_i-st_i+1);
	         buf[4]=(unsigned char)(en_j-st_j+1);
	      }
           }
           else{ /*(patch_size>=Max_ushort, 65535*/
	      buf[0]=value_range+128; /*set high bit to 1 to indicate lineL>65535*/
	      /*patch_size, unsigned int, in 4 bytes*/
	      buf[1] = (unsigned char) ((patch_size >> 24) & 0xff);
              buf[2] = (unsigned char) ((patch_size >> 16) & 0xff);
	      buf[3] = (unsigned char) ((patch_size >> 8) & 0xff);
              buf[4] = (unsigned char) (patch_size & 0xff);
	      if (twod || threed){
                 /*save width <Max_ushort in 2 bytes*/
	         buf[5]=(unsigned char)((en_i-st_i+1) & 0x00ff); /*low byte */
                 buf[6]=(unsigned char)((en_i-st_i+1) >> 8);     /*high byte*/
                 //?? fprintf(stderr,"\n saving i2d=%d",
		 //          (signed int)(buf[5]+(((signed int)buf[6])<<8)));
                 /*save height, unsigned short, in 2 bytes*/
	         buf[7]=(unsigned char)((en_j-st_j+1) & 0x00ff); /*low byte */
                 buf[8]=(unsigned char)((en_j-st_j+1) >> 8);     /*high byte*/
                 //?? fprintf(stderr,"\n saving j2d=%d",
                 //        (signed int)(buf[7]+(((signed int)buf[6])<<8)));
	      }
           }

	    /*buf[0]=value_range;
	    buf[1]=(unsigned char)(patch_size & 0x00ff); //low byte
	    buf[2]=(unsigned char)(patch_size >> 8);     //high byte
            if (twod || threed){
	      buf[3]=(unsigned char)(en_i-st_i+1);
	      buf[4]=(unsigned char)(en_j-st_j+1);
	    }*/

	    memmove(buf+lead_bytes,patch_buf,bytesP);
	    vret=write(fid, buf, lead_bytes+bytesP);
            close(fid);
            free(buf);
            free(patch_buf);
            return(buffreq); 
}


/***** set and draw the value line, works for diff line width Aug 2003  ****/
void draw_and_set_value_line(char from_patch,char* array,char isrule, 
  char this_value,unsigned int leftpos,
   unsigned int zcount,float this_cellscale,
    char this_show_2d_divs, char this_dots, unsigned char cellcolor,
     float x1, float y1, char z1){

 double hex_vmove;

   hex_vmove=this_cellscale*cos(PI/6);
   
   set_value(array,leftpos-zcount,this_value); /*set the value*/

   setfillstyle(SOLID_FILL,color_v[this_value]);

   
   if (twod && patch_only==1 && from_patch==1){ 
      /*convert y-coord to adjusted for panning U/D*/
       if (misc_hex2d==1 && cellscale>=3) y1-=(this_cellscale*aspectratio*(j2d-1-start_j2d));
       else y1-=(this_cellscale*(j2d-1-start_j2d));
   }
   
   if (misc_hex2d==1 && cellscale>=3){ /*hex grid*/
      x1+=cellscale*z1; /*for drawing line of z1 cells, for patch z1=0*/
      y1+=hex_vmove*z1; /*   as above */
      if ((j2d - (leftpos-zcount)/i2d)%2==0){
	  draw_hexagonal_2d_cell(hex_rad,this_cellscale,
			 this_show_2d_divs,this_dots,cellcolor,
                                  divcolor,x1+this_cellscale/2,y1);
      }
      else  draw_hexagonal_2d_cell(hex_rad,this_cellscale,
                    this_show_2d_divs,this_dots,cellcolor, 
                        divcolor,x1,y1);
   }
   else{ /*square grid*/
      x1+=cellscale*z1; /*for drawing line of z1 cells*/
      y1+=cellscale*z1; /* as above */
      /*fprintf(stderr,"\n%dx%d this_cellscale=%f color=%d",
	                     x1,y1,cellscale,cellcolor);*/
      bar(x1,y1,x1+this_cellscale,y1+this_cellscale);
      /*put a dot on zero cell*/
      if (this_value==0 && this_cellscale>=4 && this_dots==1)
         putpixel(x1-1+this_cellscale/2,y1-1+this_cellscale/2,green);
      
      if ((this_cellscale>3 && this_show_2d_divs==1) ||
	        this_show_2d_divs==2){ /*2 forces the edge line*/        
         setcolor(divcolor);
         rectangle(x1,y1,x1+this_cellscale,y1+this_cellscale);
      } 
   }
   
}

/*************** draw hexagonal 2d cell Jan 2004  **************/
void draw_hexagonal_2d_cell(double this_hex_rad,
       float this_cellscale,
          char this_show_2d_divs,char this_dots, unsigned char thiscolor,
                          unsigned char this_divcolor,
                           signed int x1,signed int y1){

         if (this_cellscale<=1){ 
            putpixel(x1,y1,thiscolor);
	    return;
	 } 
         poly[0]=x1+this_cellscale/2;
         poly[1]=y1;

         poly[2]=x1+this_cellscale;
         poly[3]=y1+(signed int)ceil(this_hex_rad/2);

         poly[4]=x1+this_cellscale;
         poly[5]=y1+(this_hex_rad*3)/2;

         poly[6]=x1+this_cellscale/2;
         poly[7]=y1+(signed int)ceil(this_hex_rad*2);

         poly[8]=x1;
         poly[9]=y1+(this_hex_rad*3)/2;

         poly[10]=x1;
         poly[11]=y1+(signed int)ceil(this_hex_rad/2);

         /*draw the filled poly*/
         fillpoly(6, poly);
         
         if ((this_cellscale>3 && this_show_2d_divs==1) ||
	        this_show_2d_divs==2){ /*2 forces the edge line*/
	   /*setcolor(black);*/
           setcolor(this_divcolor);
	    line(poly[0],poly[1],poly[2],poly[3]);
	    line(poly[2],poly[3],poly[4],poly[5]);
            line(poly[4],poly[5],poly[6],poly[7]);
            line(poly[6],poly[7],poly[8],poly[9]);
	    line(poly[8],poly[9],poly[10],poly[11]);
            line(poly[10],poly[11],poly[0],poly[1]);
	 }
         /*put a dot on zero cell*/
         if (this_dots==1 &&  this_cellscale>=4 &&
	      (thiscolor==black || thiscolor==darkgray))
	     putpixel(x1+this_cellscale/2,y1+this_hex_rad,green);
}

/****** select bitstring from a random sequence, 12 July 93 ********/
void random_bits(char nhoodz, char isrule, char seed_all,
		char hex, char *array, unsigned int leftpos){
 signed int z,tablemax,tablebytes,
              tempx,tempy,tempx0,tempy0,tempx1,tempy1,
	      rbox,this_density=0;
 signed long density_count=0;
 char ch,was_rotated=0,*carule_temp,temp_color_v0;
 unsigned long dec_max=0;
 unsigned int zu,temprand,ct_count,ct_total;
 float bias_density;
 char bias_rnd_rule_was_set=0,bias_rnd_seed_was_set=0; 

   if (isrule || oned){ /*check if rule or 1d state can be expressed as decimal*/
      dec_max=max_dec_rule(leftpos,value_range);
   }

   /*initially binary rules have gaps between chars (8 bits)/values
   the blocks start bottom right (index 0) - 
   as opposed to setting bits/values where the blocks start top left (index=max)
   the blocks are 8 bit/value long, so can apply to v>2 including seeds*/

   if (isrule==1 && value_range==2) gaps_in_string=1; 
   else gaps_in_string=0;  /*otherwize no gaps - but can be toggled*/

   /*set the scale of the graphic, cellscale, cellsep*/
   set_cellscale(nhood,isrule);

   temp_color_v0=color_v[0];
   color_v[0]=darkgray;
   if (xtext==(float)vgax(50)/CWidth) rbox=vgax(330);
   else if (xtext==(float)(trboxw+3)/CWidth) rbox=Maxx-5;
   
   else rbox=(signed int)(xtext*CWidth+vgax(280));

   if (value_range>2 || (isrule==1 && isrule!=3 && nhoodz>9)             
             || (!isrule && lineL>32*32 )) rbox=Maxx-5;
   if (tot_only==0){
      if (set_iso_input_histogram==1) tablemax= iso_tablemax;
      else tablemax= (signed int)pow(value_range,(double)nhoodz)-1; 

      tablebytes=(signed int)ceil(value_bits * (double)(tablemax+1)/8);
   
      if (isrule==2){ /*totalistic code*/      
         if ((carule_temp=(char *)calloc(tablebytes,sizeof(char)))
			       ==NULL) outof_memory("carule_temp");
      }
   }
     
   setcolor(white);
   next_line(xtext,1);
   if (isrule==0){ /* for seeds */
      if (threed) sprintf(textb[0],
       "tog-gaps-g exp/contr-e/c rotate-l/r/f/b/u/d another-n bias-s/v comp-m back-q accept-ret");
      else if (twod) sprintf(textb[0],
       "tog-gaps-g  exp/contr-e/c rotate-l/r/u/d another-n bias-s/v comp-m back-q accept-ret");
      else if (oned) sprintf(textb[0],
       "tog-gaps-g  exp/contr-e/c rotate-l/r another-n bias-s/v comp-m back-q accept-ret");
   }
   else if (isrule && totalistic) sprintf(textb[0],
      "tog gaps-g exp/contr-e/c rotate-l/r another-n bias-s/v comp-m back-q accept-ret");
   else if (isrule){
       if (isotropic_set==1){
           sprintf(textb[0],/*excludes forcing Z parameter*/
         "tog-gaps-g exp/contr-e/c rotate-l/r another-n bias-s/v comp-m back-q accept-ret");
       }
       else if (oned || (twod && nhood>=2 && nhood <=10) || (threed &&  (nhood==6 || nhood==7))){
           sprintf(textb[0],/*includes forcing Z parameter*/
      "tog-gaps-g exp/contr-e/c rotate-l/r another-n bias-s/v Z-u/d comp-m >iso-i back-q accept-ret");
       }
       else{ 
         sprintf(textb[0],/*includes forcing Z parameter*/
      "tog-gaps-g exp/contr-e/c rotate-l/r another-n bias-s/v Z-u/d comp-m back-q accept-ret");
       }
   }      
   set_medium_font();   
   outtext(textb[0]);
   restore_def_font();

   tempx0=getx;
   tempy0=gety;
   next_line(xtext,1.5);
   tempx1=getx;
   tempy1=gety;
   set_cellscale(nhoodz,isrule); 

  /*rule, tot code or state*/
   if (isrule==1) ct_total=tablemax+1;
   else if (isrule==2){
      if (totalistic==1) ct_total=
           (signed int) leftpos+1;/*size of tcode table*/
      else if (totalistic==2) ct_total=
           (signed int) leftpos+1;/*size of kcode table*/
   }      
   else ct_total=lineL;
   if (isrule) bias_density=bias_density_rule;
   else bias_density=bias_density_seed;
   ch='n';
   while(ch=='n'){
     
     if (cellscale<=3) cellsep=0; //to prevent wide gaps at start, Dec 2016
      else if (cellscale>=4) cellsep=2;
     
      if (isrule==0) setviewport(tview_x0,tview_y0,tview_x1-2,tview_y1,0);
      moveto(tempx1,tempy1);
      
      /*bias whole rule or seed*/
      if ( (bias_rnd_rule_was_set==1 && (bias_percent_rule[8]=='p' || bias_percent_rule[8]=='v'))
	|| (bias_rnd_seed_was_set==1 && (bias_percent_seed[8]=='p' || bias_percent_seed[8]=='v')) ){

            implement_fraction_values(isrule,seed_all,array,ct_total);        
            print_layered_bitstring(array,leftpos,cellscale,cellsep,0,isrule);
      }
      /*rules/codes randomised here - if was rotated dont randomise*/
      else if (isrule || seed_all){  
        if (was_rotated==0){
           density_count=0;
           for (ct_count=0;ct_count<=ct_total-1;ct_count++){
              temprand=myrand()%1000;
              if (temprand==0) temprand=1;
              if (value_range==2){
                  if ( (signed int) (10*bias_density)/temprand>=1){
                       /*set bits with bias_density probability*/
                       set_bit1(array,ct_count);
                       density_count++;
                  }
                  else set_bit0(array,ct_count);
              }          
              else{
                  if ( (signed int) (10*bias_density)/temprand >= 1){
                     /*set values with equal prob*/
		     set_value(array,ct_count,myrand()%(value_range-1)+1);
                     density_count++;
                  }
                  else set_value(array,ct_count,0);
              }              
           }
           /*not if array is too big*/
           /*check exact req density*/
           
           if (exact_density_bias_set==1 && ct_total<=65535){ 
	      unsigned int randpos, density_while=0;
              signed long  bits_req,excess_bits;

               bits_req=ct_total*(bias_density/100);
               excess_bits=density_count-bits_req;
              
               if (excess_bits>0){ /*turn bits off*/
                  while(excess_bits>0){
		     density_while+=1;
                     if (density_while>ct_total/2) break;
                     randpos=myrand()%ct_total;
                     if (value_range==2){
                        if (get_bit(array,randpos)==1){
                           set_bit0(array,randpos);
                           excess_bits-=1;
                        }
                     }
                     else{
                        if (get_value(array,randpos)>=1){
                           set_value(array,randpos,0);
                           excess_bits-=1;
                        }
                     }
                  }
               }
               else if (excess_bits<0){ /*turn bits on*/
                  while(excess_bits<0){
                     density_while+=1;
                     if (density_while>ct_total/2) break;
                     randpos=myrand()%ct_total;
                     if (value_range==2){
                        if (get_bit(array,randpos)==0){
                           set_bit1(array,randpos);
                           excess_bits+=1;
                        }
                     }
                     else{
                        if (get_value(array,randpos)==0){
                           set_value(array,randpos,myrand()%(value_range-1)+1);
                           excess_bits+=1;
                        }
                     }
                  }
               }
               /*count bits, or values > 0*/             
               density_count=0;
               for (ct_count=0;ct_count<=ct_total-1;ct_count++){
	          if (value_range==2){
                     if (get_bit(array,ct_count)==1) density_count++;
                  }
                  else{
                     if (get_value(array,ct_count)>=1) density_count++;
                  }
               } 
               excess_bits=density_count-bits_req;
	   }
        }
        print_layered_bitstring(array,leftpos,cellscale,cellsep,0,isrule);
      } /*from: if (isrule || seed_all){*/

      /*random block, square, cube, rectangle, or cuboild -- states only*/
      else if (isrule==0 && seed_all==0 && bias_rnd_seed_was_set==0){
         /*cell array randomised here*/
	 if (was_rotated==0){
	   unsigned int block_size;
            density_count=0;
            if (oned) block_size=blockx;              
            else if (twod) block_size=blockx*blocky;
            else if (threed) block_size=blockx*blocky*blockz;

            density_count=set_central_block(0,array);

            /*not if block_size is too big*/ 
            if (exact_density_bias_set==1 && block_size<=65535){
                /*check exact req bitcount*/
	      unsigned int randpos,density_while=0;
               signed long  bits_req,excess_bits;
                bits_req=block_size*(bias_density/100);
                excess_bits=density_count-bits_req;
                if (excess_bits>0){ /*turn bits off*/
                  while(excess_bits>0){
                     density_while+=1;
                     if (density_while>block_size/2) break;
                     randpos=randpos_block();
                     if (value_range==2){
                        if (get_bit(array,randpos)==1){
                           set_bit0(array,randpos);
                           excess_bits-=1;
                        }
                     }
                     else{
                        if (get_value(array,randpos)>=1){
                           set_value(array,randpos,0);
                           excess_bits-=1;
                        }
                     }
                  }
               }
               else if (excess_bits<0){ /*turn bits on*/
                  while(excess_bits<0){
                     density_while+=1;
                     if (density_while>block_size/2) break;
                     randpos=randpos_block();
                     if (value_range==2){
                        if (get_bit(array,randpos)==0){
                           set_bit1(array,randpos);
                           excess_bits+=1;
                        }
                     }
                     else{
                        if (get_value(array,randpos)==0){
                           set_value(array,randpos,myrand()%(value_range-1)+1);
                           excess_bits+=1;
                        }
                     }
                  }
               }
               this_density=excess_bits+bits_req;
            }
         }
	 print_layered_bitstring(array,lineL-1,cellscale,cellsep,0,isrule);
         //input_string(1,0);
         //set_central_block(0,array);
         //input_string(1,0);
      }
      was_rotated=0;
       
      /*show (dec) and hex rule below bits, erase space, rcode/kcode/tcode -- text size varies
        restrict but for small tablebytes*/  
      if (isrule){  /*for ruletable v2k17 S=131072*/      
	signed int rightedge;
	/*if (isrule==0){ 
            setviewport(tview_x0,tview_y0,tview_x1-2,tview_y1,1);
            rightedge=tview_x1-2;
	 }
	 else*/
         rightedge=rbox-1;
         next_line(xtext,1);
         moverel(0,cellscale);      	 
	 setfillstyle(SOLID_FILL,black);
	 bar(getx,gety,rightedge,Maxy-1);
         if (dec_max>0){
               sprintf(textb[0]," (dec)%lu",dec_equiv(array,leftpos));
               outtext(textb[0]);
         }
         if (tablebytes<32768){
            next_line(xtext,1);
            outtext(" (hex)");         
	    print_current_bitstring_hexbytes(0,isrule,array,nhoodz,rightedge,white,0);
         }         
      }

      if (isrule==0) setviewport(0, 0, Maxx, Maxy, 0);

      if (isrule){
	 if (isrule==1 && isotropic_set==0){
            if (value_range==2) z_parameter_all(nhoodz,1,array);
            else z_parameter_all_mvalue(nhoodz,1,array); 
         }
	 else if (tot_only==0 && isrule==2){
	    /*convert code to rule*/
            if (totalistic==1) code2rule(carule_temp,array,nhoodz);
            else if (totalistic==2) v_code2rule(carule_temp,array,nhoodz,1);
	    if (value_range==2) z_parameter_all(nhoodz,1,carule_temp);
            else z_parameter_all_mvalue(nhoodz,1,carule_temp);
	 }
      }
      if (1){ /*show density etc*/         
         unsigned int tot_density=0,tablebits,bitcount;

         if (isrule) tablebits=leftpos+1;
         else tablebits=lineL;
	 
         for (bitcount=0;bitcount<tablebits;bitcount++){
            if (value_range==2){
               if (get_bit(array,bitcount)==1) tot_density++;
	    }
            else{ 
               if (get_value(array,bitcount)>=1) tot_density++;
            }
	 }
         if (isrule){
             draw_box(-1,trboxw,Maxy/6,Maxx-2,Maxy/6+CHeight+vgay(4),1,0);
             moveto(trboxw+3,Maxy/6+1);
         }
         else draw_prompt_box(1);
 
         if (exact_density_bias_set==0) sprintf(textb[2],"prob");
         else sprintf(textb[2],"exact");
         if (value_range==2) sprintf(textb[1],"density 1s(%s)=",textb[2]);
         else sprintf(textb[1],"density %d-1s(%s)=",value_range-1,textb[2]);
 
         if (seed_all || isrule) sprintf(textb[0],"%s%d/%d=%.3f%%, bias=%.3f%%", 
                   textb[1],tot_density,tablebits,
                      100*(float)tot_density/tablebits,bias_density);
         else{
             unsigned int block_size;
	       if (blockx==0) block_size=lineL;
	       else{
                  if (oned) block_size=blockx;              
                  else if (twod) block_size=blockx*blocky;
                  else if (threed) block_size=blockx*blocky*blockz;
               }
               if (value_range==2) sprintf(textb[1],"density 1s(%s)=",textb[2]);
               else sprintf(textb[1],"density %d-1s(%s)=",value_range-1,textb[2]); 
               sprintf(textb[0],
                 "%s%d/%d=%.3f%%, block=%d/%d=%.3f%%, bias=%.3f%%", 
                   textb[1],tot_density,tablebits,                       
                      100*(float)tot_density/tablebits,
                        tot_density,block_size,                       
                           100*(float)tot_density/block_size,
                                        bias_density);            
         }

         if (isrule){  /*for rule*/
            if (bias_rnd_rule_was_set==1 && (bias_percent_rule[8]=='p' || bias_percent_rule[8]=='v')){
	       if (bias_percent_rule[8]=='p') sprintf(textb[0],"rule-bias: percent(100) 0--%d:",value_range-1);
               else sprintf(textb[0],"rule-bias: numbers of values(%d)  0--%d:",ct_total,value_range-1);
               for (z=0;z<=value_range-1;z++){
                  sprintf(textb[z+1]," %d ", bias_percent_rule[z]);
                  strcat(textb[0],textb[z+1]);
               }
            }
         }
         else{ /*for seed*/
            if (bias_rnd_seed_was_set==1 && (bias_percent_seed[8]=='p' || bias_percent_seed[8]=='v')){
	       if (bias_percent_seed[8]=='p') sprintf(textb[0],"seed-bias: percent(100)  0--%d:",value_range-1);
               else sprintf(textb[0],"seed-bias: numbers of values(%d)  0--%d:",ct_total,value_range-1);
               for (z=0;z<=value_range-1;z++){
                  sprintf(textb[z+1]," %d ", bias_percent_seed[z]);
                  strcat(textb[0],textb[z+1]);
               }
            }
         }        

         set_medium_font();
         outtext(textb[0]);
         restore_def_font();
      }

      /*for mouse*/
     moveto(tempx0,tempy0);
#     if __WATCOM__
	 flashing_cursor(0,CHeight-vgay(3),
			      CWidth,CHeight,green);
#     elif __UNIX__
	 flashing_cursor(0,0,0,0,0,CHeight-vgay(3)-6,
			      CWidth,CHeight-6,green);
#     endif

      if (button=='l') ch=13;
      else if (button=='r') ch='q';
      
      else {
#        if __WATCOM__
            ch=getch();
#        elif __UNIX__
            //if (XQLength(D)!=0) ch=keycheck(0);
            if (button=='k') ch=keycheck(0);
#        endif
      }


      if (threed && !isrule){
         /*rotate left,right,back,front,up,down*/
	 if (ch=='l'|| ch=='r'|| ch=='b'|| ch=='f' || ch=='u'|| ch=='d'){
	    rotate_array_3d(array,ch,1);
	    was_rotated=1;
	    ch='n'; 
	 }
      }
      if (twod && !isrule){
	 /*rotate left,right,up,down*/
	 if (ch=='l'|| ch=='r'|| ch=='u'|| ch=='d'){
	    rotate_array_2d(array,ch,1);
	    was_rotated=1;
	    ch='n';
	 }
      }
      else{
	 /*rotate left or right*/
	 if (ch=='l' || ch=='r'){
	    rotate_array(nhoodz,array,ch,isrule,1);
	    was_rotated=1;
	    ch='n';
	 }
      }
      if (ch=='c' || ch=='e'){        
         if ((cellscale>=2 && ch=='c') || (cellscale<127 && ch=='e')){
            /*contract or expand rule or seed, 1d, 2d, or 2d as 3d*/
            signed int cellsx,cellsy,sizex,sizey;

            cellsx=foldposs;
            if (ct_total<foldposs) cellsx=ct_total;
            cellsy=ct_total/foldposs;
            if (cellsy<4) cellsy=4;
            sizex=Maxx; //cellsx*cellscale)*1.5;was 1.2
            sizey=(cellsy*cellscale)*2; //was 1.2
            setfillstyle(SOLID_FILL,black);
            bar(xtext*CWidth,gety+CHeight*1.2, /*erase the pattern*/
                xtext*CWidth+sizex,gety+CHeight*1.2+sizey);
            if (cellscale>=2 && ch=='c') cellscale-=1;
            else if (cellscale<127 && ch=='e') cellscale+=1;
         }
         if (cellscale<=3) cellsep=0;
         else if (cellscale>=4) cellsep=2;
         was_rotated=1;
         ch='n';                         
      }
      /*
      if ((ch==']' || ch=='[') && (isrule || oned==1)){ 
        signed int cellsx,cellsy,sizex,sizey;
	  cellsx=foldposs;
          if (ct_total<foldposs) cellsx=ct_total;
          cellsy=ct_total/foldposs;
          if (cellsy<4) cellsy=4;
	  if (ch==']' && foldposs < Maxint/2) foldposs*=2;//double x-axis
          else if ( ch=='[' && foldposs > 2) foldposs/=2; //half x-axis
          was_rotated=1;
          sizex=(cellsx*cellscale)*1.2;
          sizey=(cellsy*cellscale)*1.2;
          setfillstyle(SOLID_FILL,black);
          bar(xtext*CWidth,gety+CHeight*1.2 - cellscale, //erase the pattern
                xtext*CWidth+sizex,gety+CHeight*1.2+sizey);
	  ch='n';      
      }*/
      
      if (ch=='g'){
        signed int cellsx,cellsy,sizex,sizey;
	    cellsx=foldposs;
            if (ct_total<foldposs) cellsx=ct_total;
            cellsy=ct_total/foldposs;
            if (cellsy<4) cellsy=4;
            if (ch=='g') gaps_in_string=abs(gaps_in_string-1); /*toggle gaps*/
            sizex=(cellsx*cellscale)*1.2;
            sizey=(cellsy*cellscale)*1.2;
            was_rotated=1;
            setfillstyle(SOLID_FILL,black);
            bar(xtext*CWidth,gety+CHeight*1.2, /*erase the pattern*/
                xtext*CWidth+sizex,gety+CHeight*1.2+sizey);
	    ch='n';
      }
      else if (ch=='s'){
         draw_prompt_box(1);
         if (exact_density_bias_set==0) sprintf(textb[1]," prob");
         else sprintf(textb[1]," exact");
         if (isrule) sprintf(textb[0],"density-bias rnd rule: enter %% (def %.3f%% %s):", 
                                                           bias_density,textb[1]);
         else sprintf(textb[0],"density-bias rnd seed: enter %% (def %.3f%% %s):",
                                                           bias_density,textb[1]);         
         outtext(textb[0]);

         input_string(5,0);
         if (is[0]!=13 && is[0]!='q'){
	   if (atof(is)>=0 && atof(is)<=100) bias_density=atof(is);
         }
         if (isrule) bias_density_rule=bias_density;
         else bias_density_seed=bias_density;
         if (exact_density_bias_set==0) sprintf(textb[0], " exact-e:");
         else sprintf(textb[0]," prob-p:");
         outtext(textb[0]);
         input_string(1,0);
         if (is[0]=='e') exact_density_bias_set=1;
         else if (is[0]=='p') exact_density_bias_set=0;
         bias_rnd_rule_was_set=0;
         ch='n'; 
         is[0]=0;
         erase_prompt_box(1);          
      }
      else if (ch=='v'){
         /*set new keep_bias_percent_seed¡Çbiased random rule with %/values*/
	signed int xbox;
        char keep_bias_percent_rule=0;

         bias_rnd_rule_was_set=0;
         bias_rnd_seed_was_set=0; 
        startB:
         xbox=draw_prompt_box(2);
         if (isrule) outtext("value-bias rnd rule, ");
         else outtext("value-bias rnd seed, ");

         if (ct_total<=255) outtext("%/values-p/v keep-k: "); /*choose of 'p' or 'v'*/
         else outtext("%values-p keep-k: ");
         input_string(1,0); /*8 is outside range of values 0-7*/

         if (isrule){  /*for rule*/
	      if (is[0]=='k' &&  (bias_percent_rule[8]=='v' || bias_percent_rule[8]=='p')){
		  keep_bias_percent_rule=1; /*keep the same bias but change rand rule*/
	      }
              else if (is[0]=='p') bias_percent_rule[8]='p';
              else if (is[0]=='v' && ct_total<=255) bias_percent_rule[8]='v';          
              else if (is[0]=='q') goto endFunc;
         }
         else{  /*for seed*/
	      if (is[0]=='k' &&  (bias_percent_seed[8]=='v' || bias_percent_seed[8]=='p')){ 
                 keep_bias_percent_rule=1;
	      }
              else if (is[0]=='p') bias_percent_seed[8]='p';
              else if (is[0]=='v' && ct_total<=255) bias_percent_seed[8]='v';          
              else if (is[0]=='q') goto endFunc;
         }
                
         if (keep_bias_percent_rule==0){ 
            moveto(xbox,gety+CHeight);
            set_fraction_values(isrule,ct_total);
            if (is[0]=='q') goto startB;
            if (isrule){  /*for rule*/   
               if (bias_percent_rule[8]=='p' || bias_percent_rule[8]=='v')             
	          implement_fraction_values(isrule,seed_all,array,ct_total);
	    }
            else{  /*for seed*/
               if (bias_percent_seed[8]=='p' || bias_percent_seed[8]=='v')
	          implement_fraction_values(isrule,seed_all,array,ct_total);
	    }
         }
         was_rotated=1; /*i.e. was changed, dont change again immediately*/
         if (isrule) bias_rnd_rule_was_set=1;
         else bias_rnd_seed_was_set=1;
         ch='n'; 
         is[0]=0;
         erase_prompt_box(2);     
      }
 
      else if (ch=='m'){
         if (value_range==2){
	    if (isrule){
               for (z=0;z<=tablebytes-1;z++) array[z]=~array[z];
            }
            else{
               for (zu=0;zu<=bytesL-1;zu++) array[zu]=~array[zu];
               /*set excess bits to 0*/
               for (zu=lineL;zu<=bytesL*8-1;zu++) set_bit0(array,zu);
            }
            bias_density=100.0-bias_density;
         }
         else{
           char tempvalue;
	   /*compliment multivalue by subtraction*/
            for (ct_count=0;ct_count<=ct_total-1;ct_count++){
	      tempvalue=get_value(array,(unsigned int)ct_count);
              tempvalue=(value_range-1)-tempvalue;
              set_value(array,ct_count,tempvalue);
            }
         }
         was_rotated=1; /*i.e. was changed, dont change again immediately*/
         ch='n'; 
      }
      else if (ch=='i' && isrule==1 && isotropic_set==0){ 
         /*transform current rcode into isotropic rule, added 12/10/2017*/
	 isotropic_rule(0,array,nhoodz,0,tablemax,tablemax,-2);
         was_rotated=1; /*i.e. was changed, dont change again immediately*/
         ch='n'; 
      }
      else if (ch=='u' && isrule && tot_only==0 && isotropic_set==0){ /*force Z up*/
          change_Z(array,nhoodz,'Z',1);
          was_rotated=1; /*i.e. was changed, dont change again immediately*/
          ch='n'; 
      } 
      else if (ch=='d' && isrule && tot_only==0 && isotropic_set==0){ /*force Z down*/
          change_Z(array,nhoodz,'z',1);
          was_rotated=1; /*i.e. was changed, dont change again immediately*/
          ch='n'; 
      }
      else if (ch=='q'){
	 is[0]='q'; 
         goto endFunc;
      }
   }
  endFunc:
   if (tot_only==0 && isrule==2) free(carule_temp);
   if (isrule){
        /*delete top right z parameter box*/
       draw_box(-1,trboxw,vgay(27),Maxx-2,vgay(49),0,0);
        /*delete mid right density box*/
       draw_box(-1,trboxw,Maxy/6,Maxx-2,Maxy/6+CHeight+vgay(4),0,0);
   }
   color_v[0]=temp_color_v0;
   /*
   if (isrule==0){ //to restore rule bias if applying this to the seed
      for (z=0;z<=value_range;z++){
         bias_percent[z]=temp_bias_percent[z];
      }
   }*/

   /*
   for (z=0;z<=value_range;z++){
      if (z<=value_range-1) fprintf(stderr,"%d ",bias_percent[z]);
      else fprintf(stderr,"%c ",bias_percent[z]);
   }*/
   moveto(tempx,tempy);
}

/********************** set_fraction_values Oct 2010 ***********************/
void set_fraction_values(char isrule, signed int thistotal){
  /*set the percentage or numbers of values in a rule or state*/

   signed int z,total_sofar=0;
   unsigned char temp_bias_percent[9];

         if (isrule) temp_bias_percent[8]=bias_percent_rule[8]; /*for rule*/
         else temp_bias_percent[8]=bias_percent_seed[8]; /*for seed*/

         for (z=0;z<=value_range-1;z++) temp_bias_percent[z]=0;
         if (temp_bias_percent[8]=='p' || temp_bias_percent[8]=='v'){
	    for (z=0;z<=value_range-2;z++){
	       if (temp_bias_percent[8]=='p'){
		   if (100-total_sofar<=0) break;
                   sprintf(textb[0]," %d(%d:",z,100-total_sofar);
	       }
               else if (temp_bias_percent[8]=='v'){
		   if (thistotal-total_sofar<=0) break; 
                   sprintf(textb[0]," %d(%d:",z,thistotal-total_sofar);
               }
               outtext(textb[0]);
               input_string(3,1);
               if (is[0]=='q') return;
               if (temp_bias_percent[8]=='p'){
                  if (is[0]!=13 && is[0]!='q' &&
                           atoi(is)>=0 && atoi(is)<=100-total_sofar) 
                                             temp_bias_percent[z]=atoi(is);
                  else temp_bias_percent[z]=(100-total_sofar)/(value_range-z);
               }
               else if (temp_bias_percent[8]=='v'){
                  if (is[0]!=13 && is[0]!='q' &&
		      atoi(is)>=0 && atoi(is)<=thistotal-total_sofar) 
                                              temp_bias_percent[z]=atoi(is);
                  else temp_bias_percent[z]=(thistotal-total_sofar)/(value_range-z);
               }
               total_sofar+=temp_bias_percent[z];
               /*fprintf(stderr," %d/%d",temp_bias_percent[z],total_sofar);*/ 
            }
            if (temp_bias_percent[8]=='p')
                                 temp_bias_percent[value_range-1]=100-total_sofar;
            else if (temp_bias_percent[8]=='v')
                                   temp_bias_percent[value_range-1]=thistotal-total_sofar;

            /*fprintf(stderr,"\n%c:",bias_percent[8]);   
	      for (z=value_range-1;z>=0;z--) fprintf(stderr,"%d ", temp_bias_percent[z]);*/
         }

   if (isrule){ /*for rule*/
      for (z=0;z<=value_range-1;z++){
         bias_percent_rule[z]=temp_bias_percent[z];
      }
   }
   else{ /*for seed*/
      for (z=0;z<=value_range-1;z++){
         bias_percent_seed[z]=temp_bias_percent[z];
      }
   }
}

/***** fill rule or state with values according to set percentages/numbers Oct 2010****/
void implement_fraction_values(char isrule,char seed_all,
                         char *thisarray,signed int thistotal){
          signed int z;
          unsigned int *temporder,countz,next_limit=0,zz,zu,ttot,vfreq[8],pos;
          char *temparray;
          unsigned char temp_bias_percent[9];
          signed int ii,jj,hh;

   if (isrule){ /*for rule*/
      for (z=0;z<=value_range-1;z++){
           temp_bias_percent[z]=bias_percent_rule[z];          
      }
      temp_bias_percent[8]=bias_percent_rule[8];
   }
   else{ /*for seed*/
      for (z=0;z<=value_range-1;z++){
           temp_bias_percent[z]=bias_percent_seed[z];          
      }
      temp_bias_percent[8]=bias_percent_seed[8];
   }               
               for (z=value_range-1;z>=0;z--) vfreq[z]=0;
               if ((temporder=(unsigned int *)calloc
                 (thistotal,sizeof(unsigned int)))==NULL) outof_memory("temporder");
               if ((temparray=(char *)calloc
                 (thistotal,sizeof(char)))==NULL) outof_memory("temparray");
               /*fill temparray with consecutive values according to set percentages)*/
               countz=-1;               
               for (z=0;z<=value_range-1;z++){	   
	          if (temp_bias_percent[8]=='p'){  /*percentages -- round up or down*/
                     next_limit= (unsigned int)floor((float)thistotal * 
                                        (float)temp_bias_percent[z]/100);
                     if ((double)thistotal * (double)temp_bias_percent[z]/100 
	                  - next_limit > .5) next_limit+=1;
                  }
                  else if (temp_bias_percent[8]=='v') /*actual values*/
	                        next_limit=temp_bias_percent[z];

	          for (zz=1;zz<=next_limit;zz++){
                     countz+=1;
                     if (countz>thistotal) goto skiprule;
                     set_value(temparray,countz,z);
                  }
               }
              skiprule:

               for (zz=0;zz<=thistotal-1;zz++) temporder[zz]=zz;
               /*revise this -- gets stuck for large array*/
               /* similar to shuffle_order(); learn*->c */
	       if (temp_bias_percent[8]=='v'){ /*actual values for <=255 */
                  for (zu=0;zu<=thistotal-1;zu++){
                     redowire:
                     temporder[zu]= myrand()%(thistotal);
                     if (zu>0){
	                for (zz=0;zz<=zu-1;zz++){
	                   if (temporder[zu]==temporder[zz]) goto redowire;
	                }
                     } 
	          }
               }

               if (isrule || seed_all){ /*for the full rule or seed*/
                  for (zz=0;zz<=thistotal-1;zz++){
                     if (temp_bias_percent[8]=='v')
                                  set_value(thisarray,zz,get_value(temparray,temporder[zz]));
                     else if (temp_bias_percent[8]=='p')
                        set_value(thisarray,zz,get_value(temparray,temporder[myrand()%(thistotal)]));
                     vfreq[get_value(temparray,temporder[zz])] +=1;
                  }
	       }
               else{ /*show block for seed*/
		  if (oned){
                      for (ii=lineL/2-blockx/2-1;ii<lineL/2-blockx/2+blockx;ii++){
			 pos=ii;
                         if (temp_bias_percent[8]=='v')
                            set_value(thisarray,pos,get_value(temparray,temporder[pos]));
                         else if (temp_bias_percent[8]=='p')
                            set_value(thisarray,pos,get_value(temparray,temporder[myrand()%(thistotal)]));
                         vfreq[get_value(temparray,temporder[pos])] +=1;
                      }
		  }
		  else if (twod){
                      for (jj=j2d/2-blocky/2-1;jj<j2d/2-blocky/2+blocky;jj++){
                         for (ii=i2d/2-blockx/2-1;ii<i2d/2-blockx/2+blockx;ii++){
                           pos=i2d*jj+ii;
                           if (temp_bias_percent[8]=='v')
                              set_value(thisarray,pos,get_value(temparray,temporder[pos]));
                           else if (temp_bias_percent[8]=='p')
                              set_value(thisarray,pos,get_value(temparray,temporder[myrand()%(thistotal)]));
                           vfreq[get_value(temparray,temporder[pos])] +=1;
                        }
                     }
                  }
                  else if (threed){
                     for (hh=h3d/2-blockz/2-1;hh<h3d/2-blockz/2+blockz;hh++){
                        for (jj=j3d/2-blocky/2-1;jj<j3d/2-blocky/2+blocky;jj++){
                           for (ii=i3d/2-blockx/2-1;ii<i3d/2-blockx/2+blockx;ii++){
                              pos=(i3d*j3d*hh) + (i3d*jj) + ii;
                              if (temp_bias_percent[8]=='v')
                                 set_value(thisarray,pos,get_value(temparray,temporder[pos]));
                              else if (temp_bias_percent[8]=='p')
                                 set_value(thisarray,pos,get_value(temparray,temporder[myrand()%(thistotal)]));
                              vfreq[get_value(temparray,temporder[pos])] +=1;
                           }
                        }
                     }
                  }
	       } 
	                      
               free(temporder);
               free(temparray);
               /*ttot=0;
               fprintf(stderr,"\nvfreq= ");
               for (z=value_range-1;z>=0;z--){ 
	          fprintf(stderr,"%d ", vfreq[z]);
                  ttot+=vfreq[z];
               }
               fprintf(stderr,"=%d %=", ttot);

               for (z=value_range-1;z>=0;z--){ 
	          fprintf(stderr,"%.1f ", ((float)vfreq[z]*100)/thistotal);
                  ttot+=vfreq[z];
	       }*/
}

/******set random position in 1d, 2d or 3d block, July 99  ********/
unsigned int randpos_block(void){
   unsigned int randpos,randii,randjj,randhh;

       if (oned) randpos=lineL/2-blockx/2+myrand()%blockx;
       else if (twod){ 
          randii=i2d/2-blockx/2+myrand()%blockx;
          randjj=j2d/2-blocky/2+myrand()%blocky;
          randpos=i2d*randjj + randii;
       }
       else if (threed){ 
          randii=i3d/2-blockx/2+myrand()%blockx;
          randjj=j3d/2-blocky/2+myrand()%blocky;
          randhh=h3d/2-blockz/2+myrand()%blockz;
          randpos=(i3d*j3d*randhh) + (i3d*randjj) + randii;
	}
        return(randpos);
}

/****** print bit string with random central block, Jan 94 ********/
unsigned int set_central_block(char keep,char *array){
 signed int ii,jj,hh,temprand;
 unsigned int mostx,mosty,mostz,
              zu,poss,density_count=0;
 float bias_density;

   /*this function applies to states only, not rules*/
   bias_density=bias_density_seed;

   /*set all bits to 0, else new block in state*/
   if (keep==0) memmove(array,all_0s,bytesL);

   if (oned){
      mostx=(unsigned int)(ceil((double)lineL/2)-ceil((double)blockx/2));
      /*if lineL = blockx,  mostx=0*/
      for (zu=0;zu<=blockx-1;zu++){
	  poss=zu+mostx;       
          if (bias_density<0 || bias_density>100 /*|| blockdiam<=3*/){
	      if (value_range==2){ 
                  set_bit(array,poss,(myrand()%100)/50);
              }
              else set_value(array,poss,myrand()%value_range);
	  }
	  else {
             temprand=myrand()%1000;
             if (temprand==0) temprand=1;
             if ((signed int)temprand<(10*bias_density)){   
                if (value_range==2){                
		   set_bit1(array,poss);
                }
                else set_value(array,poss,myrand()%(value_range-1)+1);
             }
             else set_value(array,poss,0);
	  }
          if (value_range==2){ 
	      if (get_bit(array,poss)==1) density_count++;
          }
          else if (get_value(array,poss)>=1) density_count++;	  
      }
   }
   else if (twod){
     mostx=(unsigned int)(ceil((double)i2d/2)-ceil((double)blockx/2));
     mosty=(unsigned int)(ceil((double)j2d/2)-ceil((double)blocky/2));
     
     for (jj=0; jj<=blocky-1;jj++){
          for (ii=0;ii<=blockx-1;ii++){
	    poss=i2d*(jj+mosty)+(ii+mostx);
            if (bias_density<0 || bias_density>100  /*|| blockdiam<=3*/){
	       if (value_range==2){ 
                  set_bit(array,poss,(myrand()%100)/50);
               }
               else set_value(array,poss,myrand()%value_range);
	    }
            else {
               temprand=myrand()%1000;
               if (temprand==0) temprand=1;
               if ((signed int)temprand<(10*bias_density)){ 
                  if (value_range==2){                
		     set_bit1(array,poss);
                  }
                  else set_value(array,poss,myrand()%(value_range-1)+1);
               }
               else set_value(array,poss,0);
	    }
            if (value_range==2){ 
	       if (get_bit(array,poss)==1) density_count++;
            }
            else if (get_value(array,poss)>=1) density_count++;	           
	 }
      }
   }
   else if (threed){
      mostx=(unsigned int)(ceil((double)i3d/2)-ceil((double)blockx/2));
      mosty=(unsigned int)(ceil((double)j3d/2)-ceil((double)blocky/2));
      mostz=(unsigned int)(ceil((double)h3d/2)-ceil((double)blockz/2));

      for (hh=0;hh<=blockz-1;hh++){
         for (jj=0;jj<=blocky-1;jj++){
            for (ii=0;ii<=blockx-1;ii++){
	      poss=(i3d*j3d*(hh+mostz)) + (i3d*(jj+mosty)) + (ii+mostx);
	      if (bias_density<0 || bias_density>100  /*|| blockdiam<=3*/){
                  if (value_range==2){ 
	             set_bit(array,poss,(myrand()%100)/50);
                  }
                  else set_value(array,poss,myrand()%value_range);
	       }
               else{
                  temprand=myrand()%1000;
                  if (temprand==0) temprand=1;
                  if ((signed int)temprand<(10*bias_density)){ 
                     if (value_range==2){                
		        set_bit1(array,poss);
                     }
                     else set_value(array,poss,myrand()%(value_range-1)+1);
                  }
                  else set_value(array,poss,0);
	       }
               if (value_range==2){ 
	          if (get_bit(array,poss)==1) density_count++;
               }
               else if (get_value(array,poss)>=1) density_count++;	
	    }
         }
      }
   }
   return(density_count);
}

/****** show multi-state color key  ********/
void show_multistate_color_key(char show_delete){
  signed int z,xbox,sx,bsize,bint,tempx,tempy,vrboxw;
  signed char tempcolor;

             tempcolor=getcolor();
             setcolor(white);     
             tempx=getx;
             tempy=gety;

             /*establish wdith of value-range color box*/
             if      (value_range==8) sprintf(textb[3],"X5XX4XX3XX2XX1");
	     else if (value_range==7) sprintf(textb[3],"X4XXX3XX2XX1");
	     else if (value_range==6) sprintf(textb[3],"X3XX2XX1X");
             else if (value_range==5) sprintf(textb[3],"X2XX1X");
             else if (value_range==4) sprintf(textb[3],"X1XX");
             else if (value_range==3) sprintf(textb[3],"X");
             else if (value_range==2) sprintf(textb[3],"");

             sprintf(textb[10],
	       "cell value-range = %d q%s", value_range,textb[3]);
             moveto(vgax(0),-50); /* y off the screen*/
             outtext(textb[10]);/*to get length of text*/
             vrboxw=getx;

             /*delete top left box at start*/
             if (show_delete==-1){ 
                erase_box(0,0,vrboxw,2+CHeight*3+vgay(6));
                setcolor(tempcolor);
                moveto(tempx,tempy);  
                return;
             }
    
	     /*fprintf(stderr,"\n show_delete=%d",show_delete);*/
             if (show_delete==0 || show_delete==1) xbox=Maxx-vrboxw;
             else if (show_delete==2 || show_delete==3) xbox=5;
	     bsize=CHeight;
	     bint=bsize*1.5;
              
             /*0 top right, 2 top left*/
             if (show_delete==0 || show_delete==2){
                   sprintf(textb[9],"%s","boximage[19]");
                   putimage(xbox-3,2,boximage[20],COPY_PUT,textb[9]);
	           freeimage(boximage[20]);
                   setcolor(tempcolor);
                   moveto(tempx,tempy);  
                   return;
             }             
             else if (show_delete==1 || show_delete==3){   
		   if (show_delete==1) /*top right*/
                      draw_box(20,xbox-3,2,Maxx-2,2+CHeight*3+vgay(6),1,0);
                   if (show_delete==3) /*top left*/
                     draw_box(20,xbox-3,2,vrboxw,2+CHeight*3+vgay(6),1,0);
		   moveto(xbox,gety+2);
		   sprintf(textb[0],"cell value-range = %d",value_range);
		   outtext(textb[0]);
		   moveto(xbox,gety+CHeight);
		   outtext("color key:  ");
		   sx=getx;
		   moveto(xbox,gety+CHeight+2);
                   sprintf(textb[0],"cell state:");
		   outtext(textb[0]);
		   moveto(sx,gety-CHeight-2);
		   for (z=value_range-1;z>=0;z--){		      
                      setfillstyle(SOLID_FILL,color_v[z]);
		      bar3d(getx,gety,getx+bsize,gety+bsize,0,0);
		      moveto(sx,gety+CHeight+2);
                      sprintf(textb[0],"%d",z);
		      outtext(textb[0]);
		      moveto(sx+bint,gety-CHeight-2);
		      sx+=bint;
		      moveto(sx,gety);
		   }                   
	      }
              setcolor(tempcolor);
              moveto(tempx,tempy);                
}

/****** print bit string, if >foldposs start new row, 13 May 93 ********/
signed int print_layered_bitstring(char *array, unsigned int leftpos,
       char thisscale,char thissep, char makerandom, char isrule){

 signed int extreme_right,extrabits,phantombits=0,zz=0,startx,temprand,
              tempx,tempy, this_value;
 unsigned int zu,count1s=0,bitstep=0;
 char stop_printing=0,was_folded=0,skip_print=0;
 float bias_density;

   //fprintf(stderr,"\nfoldposs=%d 3641",foldposs);
   if (isrule==0) bias_density=bias_density_seed;
   else bias_density=bias_density_rule;
   startx=getx;
   extrabits=(leftpos+1)%8;
   if (extrabits>0) phantombits=8-extrabits;
   if (value_range>2) phantombits=0;
      
   /*fprintf(stderr,"\n leftpos=%d phantombits=%d\n",leftpos,phantombits);*/ 
   for (zu=phantombits+leftpos;zu!=Maxu;zu--){
      if (getx>=Maxx || gety>=Maxy) skip_print=1;
      else skip_print=0;
      zz+=1;
      if (zu>leftpos){ /*indicate excess bits in array*/
	if (skip_print==0) putpixel(getx-1+thisscale/2,gety-1+thisscale/2,white);
         if ((isrule==1 && value_range>2) || (isrule==0 && oned)) 
                                                 moverel(thisscale,0);
      }   
      else{
	 bitstep+=1;
	 /*set cell value*/
         /*for value range=2 only -revise*/
	 if (value_range==2 && makerandom==1){                 
	   if (bias_density<0 || bias_density>100){
	      set_bit(array,zu,(myrand()%100)/50);
	   }
	   else {
              temprand=myrand()%1000;
              if (temprand==0) temprand=1; 
              set_bit(array,zu,(signed int)(10*bias_density)/temprand);
	   }
         }
         
	 if (get_value(array,zu)>0) count1s+=1; 

         /*print cell value*/ 
         if (stop_printing==0){
	    if (skip_print==0){
               this_value=get_value(array,zu);
               if (value_range==2){
	          if (get_bit(array,zu)==1){ 
                     setfillstyle(SOLID_FILL,yellow);/*was lightred*/
                     //count1s+=1;
                  }
	          else setfillstyle(SOLID_FILL,darkgray);
                  bar(getx,gety,getx+thisscale-thissep,
				      gety+thisscale-thissep);
                  /*put a dot on zero cell*/
	          /*if (get_bit(array,zu)==0 && thisscale>=4)
		    putpixel(getx-1+thisscale/2,gety-1+thisscale/2,green);*/
               }
               else{
		  //if (get_value(array,zu)>0) count1s+=1;
                  setfillstyle(SOLID_FILL,color_v[this_value]);
                  bar(getx,gety,getx+thisscale-thissep,
				      gety+thisscale-thissep);
                  /*put a dot on zero cell*/
	          /*if (this_value==0 && thisscale>=4)
		    putpixel(getx-1+thisscale/2,gety-1+thisscale/2,green);*/
               }
	    }

	    /*move to next position*/
            moverel(thisscale,0);
            if (gaps_in_string==1){
	       /*break bitstring into 8 bit/value chunks, starting bottom-right*/
	       if (zz%8==0){
	          if (Maxx>=799) moverel(3,0);
	          else moverel(2,0);
	       }
            }
 
            if ((twod || threed) && !isrule){
	        if (twod){ 
                   if (zu%i2d==0) moveto(xtext*CWidth,gety+thisscale);
                }
                else if (threed){
                   if (zu%i3d==0){                        
		      if (zu%(i3d*j3d)==0){ 
                           tempx=getx;
                           tempy=gety;
                           line(getx+CWidth/2,gety+thisscale/2,
                                    getx+CWidth*2,gety+thisscale/2);
                           moveto(getx+CWidth*2+1,
                                 gety+thisscale/2-CHeight/2);
                           sprintf(textb[0],"%d",zu/(i3d*j3d));
                           outtext(textb[0]);
                           moveto(tempx,tempy);                     
		       }
                       moveto(xtext*CWidth,gety+thisscale);
                   }
                }
	    } 
            /*to crop rcode in rule window*/
            else if (foldposs==-1 && isrule){
               if (getx>=Maxx)  break;
	    } 
            else if (zz%foldposs==0 && zu>0 && zz>8){
	       was_folded=1;
	       extreme_right=getx;
	       moveto(startx,gety+thisscale);
            }
            /*clip in seed box*/
            else if (setting_seed && gety>=tview_y1) stop_printing=1;            
         }
      }
   }
   
   if (!isrule && !makerandom==-1){
       if (value_range==2) sprintf(textb[1],"density 1s=");
       else sprintf(textb[1],"density %d-1s=",value_range-1); 
       sprintf(textb[1],"%s=%.1f",
                textb[1],100*(float)(count1s)/leftpos);
       moveto(startx,gety);
       setfillstyle(SOLID_FILL,black);
	    bar(startx,gety+thisscale,   
                  getx+strlen(textb[1])*CWidth,gety+CHeight);
       outtext(textb[1]);
   }
   stop_printing=0;
   if (was_folded==1) return(extreme_right);
   else return(getx);
}

/******** convert bit string to dec number, 13 May 93 **********/
unsigned long dec_equiv(char *temparray, char leftpos){
 signed int z;
 unsigned long number=0;

   for (z=0;z<=leftpos;z++){ 
      if (value_range==2){
         number+=get_bit(temparray,z)*(unsigned long)pow(2,z);
      }
      else{
         number+=get_value(temparray,z)*(unsigned long)pow(value_range,z);
      }
   }
   return(number);
}

/******** allow any value_range convert, Sept 2002  **********/
unsigned long dec_equiv_flex(char *temparray, char leftpos, 
                  signed int vr, signed int  vb){
 signed int z;
 unsigned long number=0;
 
   for (z=0;z<=leftpos;z++){ 
      number+=get_value_flex(temparray,z,vb)*(unsigned long)pow(vr,z);
   }
   return(number);
}

/******* convert bit sequence to dec number, 13 May 93 ***********/
unsigned int dec_equiv_sound(char *temparray,
		signed int leftpos, signed int rightpos){
 signed int z;
 unsigned int number=0;

   for (z=leftpos;z>=rightpos;z--)
		   number+=get_bit(temparray,z)*pow(2,z-rightpos);
   return(number);
}
/******************* random seed, April 93 ********************/
unsigned char random_seed(unsigned char color1,
                 signed int rand_seed_percent, char show_density){
  unsigned int zu1,bitno,Hamm,temprand;
  char *firstA, *compA, *firstcompA, bit;
  unsigned char tempcolor;
  signed int ii,jj;
  signed long density_count;
  float bias_density;

   bias_density= bias_density_seed;
   if (rand_seed_percent==0) return(ncolor);
   tempcolor=getcolor();
   setcolor(white);
   if (ncolor==0){
      if (color1==white) color1=yellow;
      else if (color1==yellow) color1=white;
   }

   if (rand_seed_percent==100){
      if (diff_plot){
         if (oned){
            for (zu1=lineL/2-1;zu1!=Maxu;zu1--){ 
	       if (value_range==2){ 
                  bit=(myrand()%100)/50;
                  set_bit(state1,zu1,bit);
                  set_bit(state1,zu1+lineL/2,bit);
               }
               else{
                  bit=myrand()%(value_range);
                  set_value(state1,zu1,bit);
                  set_value(state1,zu1+lineL/2,bit);
               }
            }
         }
         else{
            for (jj=j2d-1;jj>=0;jj--){
	       for (ii=i2d/2-1;ii>=0;ii--){
                  if (value_range==2){
                     bit=(myrand()%100)/50;
                     set_bit(state1,jj*i2d+i2d/2+ii,bit);
                     set_bit(state1,jj*i2d+ii,bit);
                  }
                  else{ 
                     bit=myrand()%(value_range);
                     set_value(state1,jj*i2d+i2d/2+ii,bit);
                     set_value(state1,jj*i2d+ii,bit);
                  } 
	       }		        
            }
	 }
      }
      else{ 
         density_count=0;         
	 for (zu1=L;zu1!=Maxu;zu1--){
            if (bias_density<0 || bias_density>100){
              if (value_range==2){ 
                  bit=(myrand()%100)/50;
                  set_bit(state1,zu1,bit);
              }
              else{ 
                  bit=myrand()%(value_range);
	          set_value(state1,zu1,bit);
              }
	    }
	    else {
              temprand=myrand()%1000;
              if (temprand==0) temprand=1; 
              if (value_range==2){
                  if ( (signed int) (20*bias_density)/temprand==1){
                       /*set bits with bias_density probability*/
                       set_bit1(state1,zu1);
                       density_count++;
                  }
                  else set_bit0(state1,zu1);
              }
              else{
                  if ( (signed int) (20*bias_density)/temprand==1){
                     /*set bits=values with equal prob*/
		     set_value(state1,zu1,myrand()%(value_range-1)+1);
                     density_count++;
                  }
                  else set_value(state1,zu1,0);
              }                 
	    }
         }
         /*not if array is too big*/ 
          if (exact_density_bias_set==1 && lineL<=65535){ /*check exact req density*/
	      unsigned int randpos;
              signed long  bits_req,excess_bits;

               bits_req=lineL*(bias_density/100);
               excess_bits=density_count-bits_req;

               if (excess_bits>0){ /*turn bits off*/
                  while(excess_bits>0){
                     randpos=myrand()%lineL;
                     if (labs(excess_bits)>lineL) break;
                     
                     if (value_range==2){
                        if (get_bit(state1,randpos)==1){
                           set_bit0(state1,randpos);
                           excess_bits-=1;
                        }
                     }
                     else{
                        if (get_value(state1,randpos)>=1){
                           set_value(state1,randpos,0);
                           excess_bits-=1;
                        }                     
                     }
                  }
               }
               else if (excess_bits<0){ /*turn bits on*/
                  while(excess_bits<0){
                     randpos=myrand()%lineL;
                     if (labs(excess_bits)>lineL) break;
                     if (value_range==2){
                        if (get_bit(state1,randpos)==0){
                           set_bit1(state1,randpos);
                           excess_bits+=1;
                        }
                     }
                     else{
                        if (get_value(state1,randpos)==0){
                           set_value(state1,randpos,myrand()%(value_range-1)+1);
                           excess_bits+=1;
                        }
                     }
                  }
               }
         }
      }
   }
   else{
     char value_was,rnd_value;
      Hamm=lineL* ((float)rand_seed_percent/100);
      if ((firstA=(char*)calloc(bytesL,sizeof(char)))
				    ==NULL) outof_memory(textb[0]);      
      if ((compA=(char*)calloc(bytesL,sizeof(char)))
				    ==NULL) outof_memory(textb[0]);     
      if ((firstcompA=(char*)calloc(bytesL,sizeof(char)))
				    ==NULL) outof_memory(textb[0]);
      /*flip bits if Hamm <= lineL/2, similar to  Derrida plot*/               
      if (Hamm<=lineL/2){                               
          bitno=0;
          memmove(firstA,state1,bytesL);   
          while(1){
             bitno+=1;
             zu1=myrand()%lineL; 
             /*flip a bit at random position*/
             if (value_range==2){
                set_bit(state1,zu1,abs(get_bit(state1,zu1)-1));
                /*restore flip if not different*/
                if (get_bit(state1,zu1)==get_bit(firstA,zu1)){ 
                             set_bit(state1,zu1,abs(get_bit(state1,zu1)-1));
                             bitno-=1;
                }                                                
                if (bitno==Hamm) break;
             }
             else{
                rnd_value=myrand()%value_range;
                value_was=get_value(state1,zu1);
                set_value(state1,zu1,rnd_value);
                /*restore flip if not different*/
                if (get_value(state1,zu1)==get_value(firstA,zu1)){ 
                             set_value(state1,zu1,value_was);
                             bitno-=1;
                }                                                
                if (bitno==Hamm) break;
             }
          } 	           
       }
       else if (Hamm>=lineL/2+1){
          /*restore bits in compliment (or different for value_range>2)
                                   if Hamm >= lineL/2 + 1*/           
	  for (zu1=L;zu1!=Maxu;zu1--){ 
             if (value_range==2){
                set_bit(compA,zu1,abs(get_bit(state1,zu1)-1));
             }
             else{
                bitno=0;                
                value_was=get_value(compA,zu1);
                while(1){
                   rnd_value=myrand()%value_range;
		   if (rnd_value!=value_was){ 
                      set_value(compA,zu1,rnd_value);
                      break;
		   }
                   bitno+=1;
                   if (bitno>10) break;
                } 
	     } 
          }
          memmove(firstcompA,compA,bytesL);
          bitno=0;
          while(1){
             if (Hamm==lineL) break;
             bitno+=1;
             zu1=myrand()%lineL;
             if (value_range==2){  
                /*flip a bit at random position in compliment*/
                set_bit(compA,zu1,abs(get_bit(compA,zu1)-1))
                /*restore flip*/
	        if (get_bit(compA,zu1)==get_bit(firstcompA,zu1)){
                   set_bit(compA,zu1,abs(get_bit(compA,zu1)-1));
                   bitno-=1;
                }
                if (bitno==lineL-Hamm) break;
             }
             else{
                rnd_value=myrand()%value_range;
                value_was=get_value(state1,zu1);  
                /*flip a value at random position in 100% different state*/
                set_value(compA,zu1,rnd_value);
                /*restore flip if not different*/
                if (get_value(compA,zu1)==get_value(firstcompA,zu1)){ 
                             set_value(compA,zu1,value_was);
                             bitno-=1;
                }  
                if (bitno==lineL-Hamm) break;
             }
          } 	           
          memmove(state1,compA,bytesL);                    
       }
       free(firstA);
       free(compA);
       free(firstcompA);
       setcolor(tempcolor);                      
   }
   

   if (show_density==1){ /*show density etc*/
        unsigned int ct_count;
        signed int tempx,tempy;
        /*signed int excess_bits;*/

        density_count=0;
        
	tempx=getx;;
        tempy=gety;
         /*count bits, or values > 0*/
         for (ct_count=0;ct_count<=lineL-1;ct_count++){
	          if (value_range==2){
                     if (get_bit(state1,ct_count)==1) density_count++;
                  }
                  else{
                     if (get_value(state1,ct_count)>=1) density_count++;
                  }
         }
         /*excess_bits=density_count-bits_req;*/
       
         draw_prompt_box(1);
         if (value_range==2) sprintf(textb[1],"density 1s=");
         else sprintf(textb[1],"density %d-1s=",value_range-1);  
         sprintf(textb[0],
           "%s%ld/%u=%.1f%%, bias=%.1f%%", 
                textb[1],density_count,lineL,
                   100*(float)density_count/lineL,bias_density);
         outtext(textb[0]);
         moveto(tempx,tempy);

   }     
   seed_was_set=1;
   return(color1);
}

/********** random bitflip in current state, March 94 ***********/
unsigned char random_bitflip_state(unsigned char color1){
 unsigned int z;

   if (ncolor==0){
     if (color1==white) color1=yellow;
     else if (color1==yellow) color1=white;
   }
   z=myrand()%lineL;
   if (value_range==2){ 
      set_bit(state1,z,abs(get_bit(state1,z)-1));
   }
   else set_value(state1,z,myrand()%value_range);
   seed_was_set=1;
   return(color1);
}

/*******************************************************/
void change_Z(char *array, char nhoodz, char what, char show){

  signed int temp,old_value,fliptable,counter;
  float ztemp;

         if (tot_only==1) return;

         if (value_range==2) fliptable= (signed int)pow(2,(double)nhoodz);
         else fliptable= (signed int)pow(value_range,(double)nhoodz);
         counter=0;
	 ztemp=zparam[0];
	 changebit1:
	 counter+=1;
	 temp= myrand() % fliptable; /*random bit flip position*/
	 if (value_range==2){
            set_bit(array,temp,abs(get_bit(array,temp)-1));
	    z_parameter_all(nhoodz,show,array);
         }
         else{
	     old_value=get_value(array,temp);
             set_value(array,temp,myrand()%value_range);
             z_parameter_all_mvalue(nhoodz,show,array);
         }
	 if ((what=='Z' && zparam[0]<ztemp) || 
              (what=='z' && zparam[0]>ztemp)){
	    /*flip back*/
	    if (value_range==2){ 
               set_bit(array,temp,abs(get_bit(array,temp)-1));
            }
            else set_value(array,temp,old_value);/*restore old value*/
	    /*flip another*/
	    if (counter<200) goto changebit1;
	 }
}

/******* flip rule table bit, random, all 0s, all 1s, April 93 *******/
unsigned char bit_flip(char what,unsigned char color1){
  signed int temp,oldvalue,z,zz,poss,tempx,tempy,
                      tablemax,fliptable;
 char backzero=0;

    /*
#  define remember_flippos {\
	if (direction=='f' && limitcheck==0){\
	   bitflipcount+=1;\
	   if( (flippos =(signed int*)\
	      realloc(flippos,sizeof(signed int)*(bitflipcount+1)))==NULL)\
		   outof_memory("flipppos");\
           if (value_range>2){\
              if( (flipvalue =(char*)\
              realloc(flipvalue,sizeof(char)*(bitflipcount+1)))==NULL)\
		   outof_memory("flipvalue");\
	   }\
	   flippos[bitflipcount]=temp;\
           if (value_range>2) flipvalue[bitflipcount]=oldvalue;\
	}\
   }
   */

 
   //realloc(flipvalue: now also applies for value_range=1 to allow zero flip June2021
#  define remember_flippos {					\
	if (direction=='f' && limitcheck==0 /*&& !rulemix*/){\
	   bitflipcount+=1;\
	   if( (flippos =(signed int*)\
	      realloc(flippos,sizeof(signed int)*(bitflipcount+1)))==NULL)\
		   outof_memory("flipppos");\
           if( (flipvalue =(char*)\
              realloc(flipvalue,sizeof(char)*(bitflipcount+1)))==NULL)\
		   outof_memory("flipvalue");\
	   flippos[bitflipcount]=temp;\
           flipvalue[bitflipcount]=oldvalue;\
	}\
   }
  
   //fprintf(stderr,"\n1:in bit_flip: what=%c:",what);

   tempx=getx;
   tempy=gety;
   if (tot_only==0){
      if (set_iso_input_histogram==1) tablemax=iso_tablemax;
      else tablemax= (signed int)pow(value_range,(double)nhood)-1;
   }
  
   if (rulemix) poss=L;
   else if (outer_tot==1){
       rulemix=1;
       poss=value_range-1;
   }
   else poss=0;
   if (tot_only==0){
       if (set_iso_input_histogram==1) fliptable=iso_tablemax+1;
       else fliptable= (signed int)pow(value_range,(double)nhood);
   }
   if (what=='r') backzero=1; /*for stable zero background*/
   if (what=='R') what='r';  
   if (tot_only==1){
     if (totalistic==1){
        fliptable=nhood * (value_range-1) +1;
        if (what=='k') what='K';
     }
     else if (totalistic==2){
        fliptable=v_tablecodemax[nhood]+1;
        if (what=='K') what='k';
     }
     
     if (what=='r'){
        if (totalistic==1) what='K';
        else if (totalistic==2) what='k';
     }
   }   
   if (what=='K') fliptable=nhood * (value_range-1) +1;
   else if (what=='k') fliptable=v_tablecodemax[nhood]+1;
   if (ncolor==0){
      if (color1==white) color1=yellow;
      else if (color1==yellow) color1=white;
   }
   if (nhood_mixed && (
      what=='[' || what=='r' || what=='K' || what=='k'
                || what=='A' || what=='M' || what=='C' || what=='B') ){
      draw_box(5,(signed int)((float)Maxx)/3,2,
	           ((signed int)((float)Maxx)/2)-3,2+CHeight+vgay(6),0,-1);
      memory_box(2,"setting rules, wait...");/*can take time*/
   }
   if (what!='1' && set_iso_bitflip==1) set_iso_bitflip=0;
   if (what!='`' && set_iso_bitflip==1) set_iso_bitflip=0;
   
   //fprintf(stderr,"\n2:what=%c:",what);
 
   switch(what){
      case '[': /*isotropic+legal rules*/
	 if (tot_only==1) goto end_bit_flip;//because tot_only rules are already isotropic
         for (z=0;z<=poss;z++){
            if (nhood_mixed) tablemax= 
               (signed int)pow(value_range,(double)nhoodm[z])-1;
            isotropic_rule(0,carule[z],nhoodm[z],0,tablemax,tablemax,-1);
         }
         set_iso_bitflip=1;
         break;
      case 'r': case 'K': case 'k':{  /* new random rule/s, tcode/s, kcode/s*/
        char temp_value,temp_zero;
	 if (tot_only==1 && what=='r') goto end_bit_flip; /*just in case*/
	 for (z=0;z<=poss;z++){
	       if (nhood_mixed){
                  if (what=='r') fliptable=
                          (signed int)pow(value_range,(double)nhoodm[z]);
                  else if (what=='K') fliptable=nhoodm[z] * (value_range-1) +1;
                  else if (what=='k') fliptable=v_tablecodemax[nhoodm[z]]+1;
               }
               /*set values respecting the bias_density_rule prob*/
               //fprintf(stderr,"\n3:what=%c:",what);  
	       for (zz=0;zz<=fliptable-1;zz++){
                                       
                     temp_value=myrand()%(value_range-1)+1; /*equal prob each value>0*/
                     temp_zero= myrand()%(100); /*set chance of 0 at .5*/
                     if (temp_zero>bias_density_rule) temp_value=0;
		     if (what=='r'){
		        if (set_iso_input_histogram==1){
			  signed int s;
			    //fprintf(stderr,"%d",temp_value);
                            set_value(iso_rule,zz,temp_value);
                            //modify carule[0] accordingly
                            for (s=1;s<=glbl_iso_list[zz][0];s++)
		              set_value(carule[0],glbl_iso_list[zz][s],get_value(iso_rule,zz));
		        }
                        else set_value(carule[z],zz,temp_value);
                     }
                     else if (what=='K') 
                          set_value(cacode[z],zz,temp_value);
                     else if (what=='k')
                          set_value(v_code[z],zz,temp_value);
               }
               if (backzero==1){ /*zero nhood ->0 for stable zero background*/
		 if (tot_only==0){
		     if (set_iso_input_histogram==1){
                        signed int s; 
                         set_value(iso_rule,0,0);
                         //modify carule[0] accordingly
                         for (s=1;s<=glbl_iso_list[0][0];s++)
		              set_value(carule[0],glbl_iso_list[0][s],get_value(iso_rule,0));
                     }
                     else set_value(carule[z],0,0);
                 }
                 else{
                   if (totalistic==1) set_value(cacode[z],0,0);
                   else if (totalistic==2) set_value(v_code[z],0,0);
                 }
               }

               if (tot_only==0){
                  if (what=='K'){
                     totalistic=1;
                     code2rule(carule[z],cacode[z],nhoodm[z]); 
                     totalistic=0;
                  } 
                  else if (what=='k'){ 
                     totalistic=2;
                     v_code2rule(carule[z],v_code[z],nhoodm[z],1); 
                     totalistic=0;
                  }
               }
	 }         
	 break;
      }
      case 'A':{ /*Altenberg random set, totalistic==2 ok, kcode*/
         signed int tablemax;
         unsigned int zu;
             
	     if (tot_only==1 && totalistic==1) goto end_bit_flip;
             if (tot_only==0)
                tablemax=(signed int)pow(value_range,(double)nhood)-1;
	     else tablemax=v_tablecodemax[nhood];
            
             for (zu=0;zu<=poss;zu++){
                if (tot_only==0){
                   if (nhood_mixed) tablemax= 
                          (signed int)pow(value_range,(double)nhoodm[zu])-1;
                   
                    altenberg_rule(carule[zu],nhoodm[zu],tablemax);
                    
                }
                else{
                   if (nhood_mixed) tablemax=v_tablecodemax[nhoodm[zu]];
                   altenberg_kcode(v_code[zu],nhoodm[zu],tablemax);
                }
             }
	     break;
      }
      case 'M':{ /*Majority random set, rules, tcode, kcode*/
         signed int tablemax;
         unsigned int zu;
             	     
             if (tot_only==0)
                tablemax=(signed int)pow(value_range,(double)nhood)-1;
             else if (totalistic==1) tablemax=nhood*(value_range-1);

             for (zu=0;zu<=poss;zu++){
                if (tot_only==0){
                   if (nhood_mixed) tablemax= 
                          (signed int)pow(value_range,(double)nhoodm[zu])-1;
                    majority_rule(carule[zu],nhoodm[zu],tablemax);
                    
                }
                else if (totalistic==1){
                   if (nhood_mixed) tablemax=nhoodm[zu]*(value_range-1);
                   majority_tcode(cacode[zu],nhoodm[zu],tablemax);
                }
                else if (totalistic==2) /*tablemax not required*/
                   majority_or_fprintf_vcode(1,v_code[zu],nhoodm[zu]);
                
             }      
	     break;
      }
      case 'C':{  /*random chain rule, or rules for rule-mix*/
	  signed int tablemax;
          unsigned int zu;
             if (tot_only==1) goto end_bit_flip;
             tablemax=(signed int)pow(value_range,(double)nhood)-1;
             //if (rulemix) endindex=lineL-1;
             //else endindex=0;
 
             for (zu=0;zu<=poss;zu++){
                if (nhood_mixed)
                     tablemax=(signed int)
                       pow(value_range,(double)nhoodm[zu])-1;
                /*fprintf(stderr,"%d ",zu);*/
                chain_rule(carule[zu],nhoodm[zu],tablemax,zu);
             }             
	     break;
      }
      case '1': case '`':{
          if (nhood_mixed && outer_tot==0) return(color1);
          fliptable= (signed int)pow(value_range,(double)nhood);
          if (set_iso_input_histogram==1) fliptable=iso_tablemax+1;
          if (tot_only==1){
             if (totalistic==1) fliptable=nhood * (value_range-1)+1;
             if (totalistic==2) fliptable=v_tablecodemax[nhood]+1;
          }
          /*************** select flip position for and rule type or value ramge *********/                 
	  if (index_of_flip==-1){ //mutate at random index
            signed int temp_count=0;

	     
	     //fprintf(stderr,"\n%d:",fliptable);
	     re_rand:
               temp=myrand() % fliptable; /*random index flip*/
               
	       if (get_bit(color_filter,temp)==0 && get_bit(mutation_filter,temp)==0); //accept
               else{
                    temp_count+=1;
                    //fprintf(stderr,"%d,",temp);)
	            if (temp_count<1000) goto re_rand;//choose another to seek unfiltered
                    //goto end_bit_flip; -- give up after 500 tries, and accept
                }

	        //fprintf(stderr,"\ntemp=(%d)%d",temp_count,temp);
                set_bit(mutation_filter,temp,1);//mark mutated index to not repeat
                //fprintf(stderr,"after->%d:%d",fliptable,temp);

                /*else temp is unfiltered -- accept*/
	     		  
          }

	  else{ 
               temp=index_of_flip; /*set index with '?' on-the-fly*/
               //fprintf(stderr,"\nindex_of_flip=%d,",temp);
               set_bit(mutation_filter,temp,1);//mark mutated index to not repeat
          }
	  index_of_flip=-1; /*to restore random flip*/
          /********** finish selecting flip position for and rule type or value ramge *********/
          /*
	  if (value_range==2){
             //applies to rcode. not iso-rule
	     if (set_iso_input_histogram==0 && set_iso_bitflip==1 && tot_only==0){ 
	        isotropic_rule(0,carule[0],nhoodm[0],temp,temp,tablemax,
                                             abs(get_bit(carule[0],temp)-1));
	     }
	     else if (tot_only==0){
	       if (set_iso_input_histogram==1){ //modify iso_rule
		    signed int s;
                      set_bit(iso_rule,temp,abs(get_bit(iso_rule,temp)-1));
                      //modify carule[0] accordingly
                      for (s=1;s<=glbl_iso_list[temp][0];s++)
			  set_bit(carule[0],glbl_iso_list[temp][s],get_bit(iso_rule,temp));
	        }
                else set_bit(carule[0],temp,abs(get_bit(carule[0],temp)-1));
             }
             else{
                if (totalistic==1){
                   set_bit(cacode[0],temp,abs(get_bit(cacode[0],temp)-1));
                }
            
                else if (totalistic==2){
                   set_bit(v_code[0],temp,abs(get_bit(v_code[0],temp)-1));
                }
             }
	  }*/
	  
          //else if (value_range>2){
	  if (1){
               char temp_value;	       

                /*first note current output value*/
                if (tot_only==0){
		     if (set_iso_input_histogram==1) temp_value=get_value(iso_rule,temp);
                     else temp_value=get_value(carule[0],temp);
                }
                else{
                   if (totalistic==1) temp_value=get_value(cacode[0],temp);
                   else if (totalistic==2) temp_value=get_value(v_code[0],temp);
                }
                oldvalue=temp_value;//note the previous value

		//fprintf(stderr,"\nwhat=%c",what);

		if (what=='`') temp_value=0; //set to zero
                else{
                   while(1){ /*flip to a different random value*/
                       temp_value=myrand()%value_range;
                       if (temp_value!=oldvalue) break;
                   }
		}
                //fprintf(stderr," ld=%d newv=%d",oldvalue,temp_value);
		
                if (set_iso_input_histogram==0 && set_iso_bitflip==1 && tot_only==0) 
		   isotropic_rule(0,carule[0],nhoodm[0],temp,temp,tablemax,temp_value);

                else if (tot_only==0){                   
		    if (set_iso_input_histogram==1){//modify iso_rule
                      signed int s,z; 
                        set_value(iso_rule,temp,temp_value);
			//fprintf(stderr,"\niso_rule=");
                        //for (z=iso_tablemax;z>=0;z--) fprintf(stderr,"%d",get_value(iso_rule,z));
                        //modify carule[0] accordingly
                        for (s=1;s<=glbl_iso_list[temp][0];s++)
		           set_value(carule[0],glbl_iso_list[temp][s],get_value(iso_rule,temp));
                        //fprintf(stderr,"\niso_rule=");
                        //for (z=iso_tablemax;z>=0;z--) fprintf(stderr,"%d",get_value(iso_rule,z));
		    }
                    else set_value(carule[0],temp,temp_value);
                }               
                else if (tot_only==0) set_value(carule[0],temp,temp_value);
                else{
                   if (totalistic==1) set_value(cacode[0],temp,temp_value);
                   else if (totalistic==2)
                                      set_value(v_code[0],temp,temp_value);
                } 
          }          
          remember_flippos;
          //fprintf(stderr,"\n->count=%d: p=%d ",bitflipcount, flippos[bitflipcount]); 
	  //if (value_range>2)
	  //fprintf(stderr,"v=%d",flipvalue[bitflipcount]);
          //input_string(1,0);
	 break;
       }
       case 'b':   /*flip all0->0 */
             if (rulemix) poss=L;
             else if (outer_tot==1){
                rulemix=1;
                poss=value_range-1;
             }
             else poss=0;
             for (z=0;z<=poss;z++){
	        if (tot_only==0){
		   if (set_iso_input_histogram==1){
                     signed int s; 
                      set_value(iso_rule,0,0);
                      //modify carule[0] accordingly
                            for (s=1;s<=glbl_iso_list[0][0];s++)
		              set_value(carule[0],glbl_iso_list[0][s],get_value(iso_rule,0));
                   }
                   else set_value(carule[z],0,0);
	        }
                else{
                   if (totalistic==1) set_value(cacode[z],0,0);
                   else if (totalistic==2) set_value(v_code[z],0,0);
                }
             }
             if (outer_tot==1) rulemix=0;	     
             break;

       case 'B':   /*flip allV->V */  
         if (tot_only==1){ 
            if (totalistic==1) tablemax=nhood * (value_range-1);
            else if (totalistic==2) tablemax=v_tablecodemax[nhood];
         }
         
	 for (z=0;z<=poss;z++){            
	    if (tot_only==0){                  
                 unsigned int u;
                 signed int i,vz;
                 signed int s;
                 signed int rcode_tablemax; 
 
                 rcode_tablemax=(signed int)pow(value_range,(double)nhood)-1;

                  /*flip allv->v in lookup table*/
                  for (vz=value_range-1;vz>=0;vz--){
		     u=0;
                     for (i=nhoodm[z]-1;i>=0;i--)
                          u+=vz*(signed int)pow(value_range,(double)i);

                     /* //convert iso-rule to rcode, but this is the wrong way round
                     if (set_iso_input_histogram==1){
                           set_value(iso_rule,group_list_iso[u],vz);
                           //modify carule[0] accordingly
                            for (s=1;s<=glbl_iso_list[zz][0];s++)
		              set_value(carule[0],glbl_iso_list[group_list_iso[u]][s],
                                             get_value(iso_rule,group_list_iso[u]));
		     }*/

                     set_value(carule[poss],u,vz);
                     /*fprintf(stderr,"\n%d: %d-%d",
		                      vz,u,get_value(carule[poss],u));*/
                     //convert to iso-rule for each uniform index u
                     if (set_iso_input_histogram==1){ 
		       isotropic_rule(0, carule[poss],nhood,u,u,
				 rcode_tablemax, -2);
                     }
                  }
                   //convert to whole iso-rule, otherwise bad side effecrs
                  if (set_iso_input_histogram==1){ 
		       isotropic_rule(0, carule[poss],nhood,0,rcode_tablemax,
				 rcode_tablemax, -2);
                  }
               }
               else if (tot_only==1){
                 signed int v_bits,index;
                 char freq,uni_k; 
                  
                  if (totalistic==1){
                      /*flip ends of lookup table ->max and 0*/
                     if (nhood_mixed) tablemax=nhoodm[z] * (value_range-1);
                     set_value(cacode[z],tablemax,value_range-1);
                     set_value(cacode[z],0,0);
                  }
                  else if (totalistic==2){
                      /*flip allv->v in lookup table*/
		      /*fprintf(stderr,"\n\n tot_only=%d what=%c",tot_only,what);*/
                     if (nhood_mixed) tablemax=v_tablecodemax[nhoodm[z]];
                     v_bits=check_value_bits(nhoodm[z]+1);
                     /*fprintf(stderr,"\n tablemax=%d vcode = ... ",tablemax);*/
                     for (index=0;index<=tablemax;index++){
			/*fprintf(stderr,"\n [%d] ",index);*/
                        uni_k=0;
                        for (zz=value_range-1; zz>=0; zz--){
                           freq=get_value_flex(v_index[nhoodm[z]][index],zz,v_bits);
                           /*fprintf(stderr,"%d ",freq);*/
                           if (freq==nhoodm[z]){
                              uni_k=1;

                              /*set all to max value (out of date)*/
			      /*set_value(v_code[poss],index,value_range-1);*/

                              /*set each to uni-value max*/ 
                              set_value(v_code[z],index,zz);
                           }
	                }
                        /*fprintf(stderr,"= %d ",
			  get_value_flex(v_code[z],index,value_bits));
			if (uni_k==1) fprintf(stderr," *");*/

	             }
                  }
               }
	 }
	 break;
 
      case 'Z': case 'z':   /*higher 'Z' or lower 'z', not done if rulemix*/
	 //fprintf(stderr,"\n changing Z"); 
   
         if (tot_only==1) goto end_bit_flip;
         change_Z(carule[0],nhood,what,0);
	 break;
   }

   if (nhood_mixed && (
      what=='[' || what=='r' || what=='K' || what=='k'
                || what=='A' || what=='M' || what=='C' || what=='B') ){
      /*restore pixels below memory box*/
      erase_memory_box(0);
      sprintf(textb[9],"%s","boximage[5]");
      putimage((signed int)((float)Maxx)/3,2,boximage[5],COPY_PUT,textb[9]);
      freeimage(boximage[5]);
   }   

  
   if (direction=='f' && limitcheck==0 /*&& !rulemix*/){
      if (tot_only==0 && !rulemix){ 
         if (value_range==2) z_parameter_all(nhood,0,carule[0]);
         else z_parameter_all_mvalue(nhood,0,carule[0]);
      }      
       
      if (what=='C') sprintf(textb[1],"chain ");
      else if (what=='O') sprintf(textb[1],"Orig ");
      else if (what=='A') sprintf(textb[1],"Alt ");
      else if (what=='M') sprintf(textb[1],"Maj ");
      else if (what=='[') sprintf(textb[1],"iso ");
      else sprintf(textb[1],"");
      if (tot_only==0){ 
          if (what=='k') sprintf(textb[1],"k-");
          else if (what=='K') sprintf(textb[1],"t-");
      }

      if (tot_only==0){
        if (set_iso_input_histogram==1)
	   sprintf(textb[2],"iso-rule (%d) v%dk%d: ",iso_tablemax+1,value_range,nhood);
	else sprintf(textb[2],"rcode v%dk%d: ",value_range,nhood);
      }	
      else{
         if (totalistic==1) sprintf(textb[2],"tcode v%dk%d: ",value_range,nhood);
         else if (totalistic==2) sprintf(textb[2],"kcode v%dk%d: ",value_range,nhood);
      }

      if (what=='1') sprintf(textb[3],"flip %d, pos %d ",bitflipcount,temp);
      else sprintf(textb[3],"");	

      if (tot_only==0 /*&& !rulemix*/){
         if (what=='C' || what=='z' || what=='Z')
                     sprintf(textb[4],"zl=%.2g zr=%.2g",zparam[1],zparam[2]);
         else sprintf(textb[4],"Z=%.2g",zparam[0]);        
      } 
      else sprintf(textb[4],"");

      sprintf(textb[0],"%s%s%s%s",textb[1],textb[2],textb[3],textb[4]);

      //this also resets iso-rule
      if (nhood_mixed) draw_rule_box(170,textb[0],nhoodm[0]);
      else draw_rule_box(170,textb[0],nhood);

      /*if (set_iso_input_histogram==1){ //in the terminal
         fprintf(stderr,"\nbit_flip:(%d)>iso-hex=",iso_tablemax+1);
         print_current_bitstring_hexbytes(16,4,iso_rule,nhood,Maxx,black,6);
      }*/
          
      setcolor(color1);
   }
  end_bit_flip:
   //fprintf(stderr,"\nabout to end_bit_flip");
   //input_string(1,0); 
   moveto(tempx,tempy);
   if (outer_tot==1) rulemix=0;
   return(color1);
}

/*******************************************************/
unsigned char bit_flipback(unsigned char color1){
 signed int tempx,tempy,tablemax;   

   if (bitflipcount>=1 && direction=='f' && limitcheck==0 /*&& !rulemix*/){
      if (ncolor==0){
	 if (color1==white) color1=yellow;
	 else if (color1==yellow) color1=white;
      }
      /*
      if (value_range==2){
         if (set_iso_input_histogram==0 && set_iso_bitflip==1 && tot_only==0){
                tablemax= (signed int)pow(value_range,(double)nhood)-1; 
		isotropic_rule(0,carule[0],nhoodm[0],
                       flippos[bitflipcount],flippos[bitflipcount],tablemax,
                             abs(get_bit(carule[0],flippos[bitflipcount])-1));
         }
	 else if (tot_only==0){
	   if (set_iso_input_histogram==1){
              signed int s;
                set_bit(iso_rule,flippos[bitflipcount],
                     abs(get_bit(iso_rule,flippos[bitflipcount])-1 ));
                //modify carule[0] accordingly
                for (s=1;s<=glbl_iso_list[flippos[bitflipcount]][0];s++)
		     set_value(carule[0],glbl_iso_list[flippos[bitflipcount]][s],
		          get_value(iso_rule,flippos[bitflipcount]));
	     }
	     else set_bit(carule[0],flippos[bitflipcount],
                  abs(get_bit(carule[0],flippos[bitflipcount])-1 ));
         }
         else{
            if (totalistic==1) set_bit(cacode[0],flippos[bitflipcount],
                  abs(get_bit(cacode[0],flippos[bitflipcount])-1 ));
            if (totalistic==2) set_bit(v_code[0],flippos[bitflipcount],
                  abs(get_bit(v_code[0],flippos[bitflipcount])-1 ));
         }
      }*/
      
      //else if (value_range>2){
      if (1){
	  //fprintf(stderr,"\n<-count=%d: p=%d ",bitflipcount, flippos[bitflipcount]); 
	  //if (value_range>2)
	  //fprintf(stderr,"v=%d",flipvalue[bitflipcount]);

         if (set_iso_input_histogram==0 && set_iso_bitflip==1 && tot_only==0){
            tablemax= (signed int)pow(value_range,(double)nhood)-1; 
            isotropic_rule(0,carule[0],nhoodm[0],
                    flippos[bitflipcount],flippos[bitflipcount],tablemax,
                                                flipvalue[bitflipcount]);
         } 
         else if (tot_only==0){
            if (/*isotropic_set &&*/ set_iso_input_histogram==1){
              signed int s;
                set_value(iso_rule,flippos[bitflipcount],flipvalue[bitflipcount]);
                //modify carule[0] accordingly
                for (s=1;s<=glbl_iso_list[flippos[bitflipcount]][0];s++)
		     set_value(carule[0],glbl_iso_list[flippos[bitflipcount]][s],
		               flipvalue[bitflipcount]);
	     }
	     else set_value(carule[0],flippos[bitflipcount],flipvalue[bitflipcount]);
         }
         else{
            if (totalistic==1) set_value(cacode[0],
                 flippos[bitflipcount],flipvalue[bitflipcount]);
            else if (totalistic==2) set_value(v_code[0],
                 flippos[bitflipcount],flipvalue[bitflipcount]);
         }
      }
      set_bit(mutation_filter,flippos[bitflipcount],0); //unmark mutated index to allow repeat
      bitflipcount-=1;
      tempx=getx;
      tempy=gety;

      if (tot_only==0){
         if (value_range==2) z_parameter_all(nhood,0,carule[0]);
         else z_parameter_all_mvalue(nhood,0,carule[0]);
	 if (set_iso_input_histogram==1)
	   sprintf(textb[0],"iso-rule (%d) v%dk%d: flipback %d, pos %d, Z=%.2g",
		   iso_tablemax+1,value_range,nhood,bitflipcount,
		   flippos[bitflipcount+1],zparam[0]);	         
         else sprintf(textb[0],
            "rcode v%dk%d: flipback %d, pos %d, Z=%.2g",
		 value_range,nhood,bitflipcount,
		     flippos[bitflipcount+1],zparam[0]); 
      }
      else{
	 if (totalistic==1) sprintf(textb[0],
              "tcode v%dk%d: flipback %d, pos %d",
		 value_range,nhood,bitflipcount,flippos[bitflipcount+1]);    
         else if (totalistic==2) sprintf(textb[0],
              "kcode v%dk%d: flipback %d, pos %d",
		 value_range,nhood,bitflipcount,flippos[bitflipcount+1]); 
      }
      
      draw_rule_box(170,textb[0],nhood);
      /*if (set_iso_input_histogram==1){ //in the terminal
         fprintf(stderr,"\n(%d)<iso-hex=",iso_tablemax+1);
         print_current_bitstring_hexbytes(16,4,iso_rule,nhood,Maxx,black,6);
      }*/
      moveto(tempx,tempy);
      setcolor(color1);
      /*re-allocate mem*/
      if (bitflipcount>0){
	 if( (flippos =(signed int*) realloc
		(flippos,sizeof(signed int)*(bitflipcount+1)))
					==NULL) outof_memory("flippos");
         //if (value_range>2){
	    //now also applies for value_range=1 to allow zero flip June2021
            if( (flipvalue =(char*) realloc
		(flipvalue,sizeof(char)*(bitflipcount+1)))
					==NULL) outof_memory("flipvalue");
	 //}
      }
   }
   return(color1);
}
/****************** turn vga x coord to general coord******************/
#if __WATCOM__
signed int vgax(signed int xcoord){
 signed int genx;

   genx=(signed int) (xcoord *((float)(getmaxx()+1)/640));
   if (genx<1) genx=1;
   return(genx);
}
#endif
/********* turn vga x coord to general coord*************/
#if __WATCOM__
signed int vgay(signed int ycoord){
 signed int geny;

   geny=(signed int) (ycoord *((float)(getmaxy()+1)/480));
   if (geny<1) geny=1;
   return(geny);
}
#endif

/********************************************************/
char final_quit(void){

   if (is[0]=='q'){
      if (nowscrolling==1){
	 memory_box(1,NULL);
	 freeimage(stpimage);
	 nowscrolling=0;
      }
      memory_box(1,NULL);
      outof_memory("?");
   }
   return(1);
}

/******************************************************/
void outof_memory(char *what){
   signed int tempx,tempy,temp;
   unsigned char tempcolor;

   setcolor(white);

   tempx=getx;
   tempy=gety;
  start:
   temp=CWidth*52;
   draw_box(-1,2,2,temp,CHeight*3+vgay(6),1,0);
   sprintf(textb[1]," insufficient memory for %s", what);
   sprintf(textb[2]," image:print/save-p/s, options-o");
   sprintf(textb[3]," return to Exit:");

   moveto(3,3);
   outtext(textb[1]);
   moveto(3,gety+CHeight);
   outtext(textb[2]);
   moveto(3,gety+CHeight);
   outtext(textb[3]);
   memory_box(1,NULL);
#  if __WATCOM__
      is[0]=getch();
#  elif __UNIX__
      /*if (XQLength(D)!=0) is[0]=keycheck(0);*/
      input_string(1,0);
 #  endif
   switch (is[0]){
      case 'p':
	 if (!stp){
	    tempcolor=getcolor();
	    setcolor(red);
	    rectangle(0,0,getmaxx(),getmaxy());
	    setcolor(tempcolor);
	 }
#        if __WATCOM__
	    printimage('L',0,0,0,0,getmaxx(),getmaxy());
#        elif __UNIX__
            printimage();
#        endif
	 goto start;
      case 's':
	 save_screen();
	 goto start;
      case 'o':
	 if (nhood && !rulemix){
	    interrupt_stp_box(2,carule[0],0,0,0,NULL,NULL,NULL,NULL);
	    if (rulemix==0) show_rule_bottom(nhood,0,carule[0],0);
	 }
	 break;
   }
   moveto(tempx,tempy);
   exit(1);  /* terminate program if out of memory */
}

/********** calculate canalizing inputs, Feb 95 *********************/
char canalyzing(char nhoodz,char showz,char* thisrule){

 char binv,
      thiscanal,
      output;
 signed int z,zz,
	      firstcount,
	      tablemax,
	      tempx,tempy;

   /*
   nm[nhood index][rule table index]|allocated and freed in main
   canal[nhood index]               |free_mem_nhood_matrix(char thisnhood)
   */
   canaltotal=0;
   tablemax=(signed int)pow(value_range,(double)nhoodz)-1;
   for (z=0;z<=1;z++) canal[z]=0;/*sell all bits in 2 bytes to 0*/

   for (z=0;z<=nhoodz-1;z++){
      for (binv=0;binv<=value_range-1;binv++){
	 firstcount=tablemax;
	 thiscanal=1;
	 for (zz=0;zz<=tablemax;zz++){
	    if (get_value(nm[z],zz)==binv){   /*first binv found*/
	       if (zz<firstcount){
		  output=get_value(thisrule,zz); /*note output*/
		  firstcount=zz;               /*note rule table index*/
	       }
	       else if (get_value(thisrule,zz)!=output){
		  thiscanal=0;
		  break;
	       }
	    }
	 }
	 if (thiscanal){
	    set_bit1(canal,z);/*set bit to 1*/
	    canaltotal+=1;
	    break;
	 }
      }
   }
   if (showz){
      tempx=getx;
      tempy=gety;
      draw_prompt_box(1);
      sprintf(textb[0],"C=%d/%d",canaltotal,nhoodz);
      outtext(textb[0]);
      if (canaltotal && nhoodz>1){
	 outtext("=");
	 for (z=nhoodz-1;z>=0;z--){
	    if (get_bit(canal,z)==1){
	       sprintf(textb[0],"%d",z);
	       outtext(textb[0]);
	    }
	    else outtext("*");
	 }
      }
      moveto(tempx,tempy);
   }
   return(output);
}

/********* Z param for nhoods 1-Maxnhood, June 93, binary ***************/
void z_parameter_all(char nhoodz, char showz, char *thisrule){
 float *ln,*notln,
       temp,onecount;
 signed int *ncount,
     tuple,tup,not,tablemax,tablebytes,i,x,y,z,
     revtable,q,sod,tempx,tempy;
 char *temprule,
      *revrule;  /*for re-aranging bits from right to left <--*/

  if (value_range>2) return;
  tempx=getx;
  tempy=gety;
  tablemax=(signed int)pow(value_range,(double)nhoodz)-1;
  tablebytes=(signed int)ceil(value_bits * ((double)tablemax+1)/8);

  if ((ln=(float*)calloc(nhoodz+1,sizeof(float)))==NULL)
					    outof_memory("ln");
  if ((notln=(float*)calloc(nhoodz+2,sizeof(float)))==NULL)
					    outof_memory("notln");
  if ((ncount=(signed int*)calloc(nhoodz+1,sizeof(signed int)))==NULL)
                                            outof_memory("ncount");
  /*to hold rule for standard left-> right algorithm*/
  if ((temprule=(char *)calloc
       (tablebytes,sizeof(char)))==NULL) outof_memory("temprule");
  if ((revrule=(char *)calloc
       (tablebytes,sizeof(char)))==NULL) outof_memory("revrule");
  
  /*re-arange rule table for zparam right to left <--
  by positioning acc to reflected nhoods, this allows calc of
  Z-right by same method as Z-left, ie take the nhood=3 rule table...

  left->right

  7  6  5  4  3  2  1  0   rule table index= dec nhoods
  :  :  :  :  :  :  :  :

  1  1  1  1  0  0  0  0 ..2  nhood index
  1  1  0  0  1  1  0  0 ..1
  1  0  1  0  1  0  1  0 ..0

  *  *  *  *  *  *  *  * ..outputs
  _  _  _  _  _  _  _  _
  \__/  \__/  \__/  \__/ ..deterministic permutation templates
  ____  ____  ____  ____
    \____/      \____/   ..ignore 0
  __________  __________
       \__________/      ..ignore 0,1


  left<-right

  7  6  5  4  3  2  1  0   same rule table index
  7  3  5  1  6  2  4  0   reflected nhoods
  :  :  :  :  :  :  :  :

  1  0  1  0  1  0  1  0 ..2  nhood index
  1  1  0  1  1  1  0  0 ..1
  1  1  1  1  0  0  0  0 ..0

  *  *  *  *  *  *  *  * ..outputs
  _  _  _  _  _  _  _  _
  \__/  \__/  \__/  \__/ ..deterministic permutation templates
  ____  ____  ____  ____
    \____/      \____/   ..ignore 2
  __________  __________
       \__________/      ..ignore 2,1

  */
  
  for (i=tablemax;i>=0;i--){
     revtable=0;
     sod=i;
     for (q=nhoodz-1;q>=0;q--){
	if (sod/(signed int)pow(2,(double)q)==1){
	   revtable+=(signed int)pow(2,(double)(nhoodz-1-q));
	   sod-=(signed int)pow(2,(double)q);
	}
     }
     set_bit(revrule,i,get_bit(thisrule,revtable));
  }
  notln[nhoodz+1]=1;

  if (nhoodz==1){
     if (get_bit(thisrule,0)!=get_bit(thisrule,1)) zparam[1]=zparam[2]=1;
     else zparam[1]=zparam[2]=0;
     goto skip2;
  }
  
  /*z=1..left->right, z=2 equivelent to left<-right*/
  for (z=1;z<=2;z++){
     /*print details*/
     /*if (z==2) moveto(vgax(50),gety+CHeight);
     sprintf(textb[0],"z%d: ",z);
     outtext(textb[0]);*/
     if (z==1) memmove(temprule,thisrule,tablebytes);
     if (z==2) memmove(temprule,revrule,tablebytes);
     tuple=2;/*size of template 2,4,8,16,....*/
     /*count template matches*/
     for (tup=1;tuple<=(tablemax+1)/2;tup++){
	if (tup>(tablemax+1)/2) break;
	tuple=(signed int)pow(2,(double)tup);
	/*fprintf(stderr,"tuple=%d\n",tuple);*/
	 /*for template size 4,8,16,...*/
	 for (x=0;x<=tablemax+1-tuple;x+=tuple) {
	   /*if (tup>1 && nhoodz>2){*/
	   if (tup>1){
	      for (y=1;y<=(tuple/2)-1;y++){
		 if (get_bit(temprule,x)!=get_bit(temprule,x+y)) goto skip1;
		 if (get_bit(temprule,x+tuple/2)!=
				get_bit(temprule,x+(tuple/2)+y)) goto skip1;
	      }
	   }
	   /*for template size 2*/
	   if (get_bit(temprule,x)==get_bit(temprule,x+tuple/2)) goto skip1;
	   /*count of template matches*/
	   ncount[nhoodz-(tup-1)]+=1;
	   skip1:;
	}
	/*print details*/
	 /*sprintf(textb[0],"n%d=",nhoodz-(tup-1));
	outtext(textb[0]);
	if (getx>Maxx-30) moveto(vgax(50),gety+CHeight);*/

	/*prob det = (count/max count) * not prob before*/
	ln[nhoodz-(tup-1)]=((float)ncount[nhoodz-(tup-1)]
		       /((tablemax+1)/tuple))*notln[nhoodz-(tup-2)];
	/*print details*/
	/*sprintf(textb[0],"%d/%d=%.3g,",ncount[nhoodz-(tup-1)],
			   (tablemax+1)/tuple,ln[nhoodz-(tup-1)]);
	outtext(textb[0]);
	if (getx>Maxx-30) moveto(vgax(50),gety+CHeight);*/

	/*calc not prob*/
	temp=0;
	for (not=1;not<=tup;not++){
	   temp+=ln[nhoodz-(not-1)];
	}
	notln[nhoodz-(tup-1)]=1-temp;

	/*print details*/
	/*sprintf(textb[0],"not%d=%.3g;",tup,notln[nhoodz-(tup-1)]);
	outtext(textb[0]);
	if (getx>Maxx-30) moveto(vgax(50),gety+CHeight);*/

     }
     zparam[z]=0;
     for (i=nhoodz;i>=1;i--) zparam[z]+=ln[i];
     for (i=nhoodz;i>=1;i--){
	ncount[i]=0;
	ln[i]=0;
	notln[i]=0;
     }
  }
 skip2:;
  /*print details*/
  if (zparam[1]>zparam[2]) zparam[0]=zparam[1];
  else zparam[0]=zparam[2];
  onecount=0;
  for (x=0; x<=tablemax; x++) {
	if (get_bit(thisrule,x)==1) onecount=onecount+1;
  }
  if (onecount<=(tablemax+1)/2) lratio = onecount/((tablemax+1)/2);
  else lratio=(tablemax+1-onecount)/((tablemax+1)/2);
  lambda=onecount/(tablemax+1);
  /*calculate canalyzing inputs*/
  canalyzing(nhoodz,0,thisrule);
  
  if (showz){ /*show in box near top-right*/
        set_medium_font();
        draw_box(-1,trboxw,vgay(27),Maxx-2,vgay(49),1,0);
	moveto(trboxw+3,vgay(29));
	/*show canalyzing inputs */
	sprintf(textb[0],"C=%d/%d",canaltotal,nhoodz);
	outtext(textb[0]);
	if (canaltotal && nhoodz>1){
	   outtext("=");
	   for (z=nhoodz-1;z>=0;z--){
	      if (get_bit(canal,z)==1){
		 sprintf(textb[0],"%d",z);
		 outtext(textb[0]);
	      }
	      else outtext("*");
	   }
	}
	outtext("  ");

	/*show Z and lambda*/
	sprintf(textb[0],"zl=%g zr=%g",zparam[1],zparam[2]);
	sprintf(textb[1],"ld=%g",lambda);
	sprintf(textb[2],"  ld-r=%g P=%g Z=%g",
			    lratio,.5+(1.0-lratio)/2,zparam[0]);

	outtext(textb[0]);
	moveto(trboxw+3,gety+CHeight);
	outtext(textb[1]);
	outtext(textb[2]);
        restore_def_font();
  } 
  free(ln);
  free(notln);
  free(ncount);
  free(temprule);
  free(revrule);  
  moveto(tempx,tempy);
}

/***** Z param for nhoods 1-Maxnhood, 2003, mult-value *********/
void z_parameter_all_mvalue(char nhoodz, char showz, char *thisrule){
 float *ln,*notln,temp;
 signed int *ncount,*v_count,biggest,
      tempfreq,same,muple,lev_muple,this_level,
      level_same_count,muple_count,mupno_level,this_step,
      not,tablemax,tablebytes,i,x,y,z,this_value,
      tempx,tempy,count;
 char *temprule,*kv_string,*kv_null,
      *revrule,  /*for re-aranging bits from right to left <--*/
      **level_same; /*to calculate other levels*/

  tempx=getx;
  tempy=gety;
  tablemax=(signed int)pow(value_range,(double)nhoodz)-1;
  tablebytes=(signed int)ceil(value_bits * ((double)tablemax+1)/8);


  if ((v_count=(signed int*)calloc(value_range,sizeof(signed int)))==NULL)
                         outof_memory("v_count"); /*for lambda para*/

  if ((ln=(float*)calloc(nhoodz+1,sizeof(float)))==NULL)
					    outof_memory("ln");
  if ((notln=(float*)calloc(nhoodz+2,sizeof(float)))==NULL)
					    outof_memory("notln");
  notln[0]=1;

  if ((ncount=(signed int*)calloc(nhoodz+1,sizeof(signed int)))==NULL)
                                            outof_memory("ncount"); 
  /*to hold rule for standard left-> right algorithm*/
  if ((temprule=(char *)calloc
       (tablebytes,sizeof(char)))==NULL) outof_memory("temprule");
  if ((revrule=(char *)calloc
       (tablebytes,sizeof(char)))==NULL) outof_memory("revrule");
  
  /*re-arange rule table for zparam right to left <--
  by positioning acc to reflected nhoods, this allows calc of
  Z-right by same method as Z-left, ie take the nhood=3 rule table...

  left->right (example for v=3)

  26  23  20   17  14  11   8   5   210   rule table index= dec nhoods
  :   :   :    :   :   :    :   :   :::
  222 222 222  111 111 111  000 000 000  ..2  nhood index
  222 111 000  222 111 000  222 111 000  ..1
  210 210 210  210 210 210  210 210 210  ..0
  *** *** ***  *** *** ***  *** *** ***  ..outputs
  ||| ||| |||  ||| ||| |||  ||| ||| |||  ..level 1
  ___ ___ ___  ___ ___ ___  ___ ___ ___  
   \___|___/    \___|___/    \___|__/    ..level 2, ignore 0, effective k-1
  ___________  ___________  ___________
        \___________|___________/        ..level 3, ignore 0,1,effective k-2
                                         ..level 4 etc for larger k.  

  left<-right

  26  23  20   25  22  19   24  20  18     rule table index= dec nhoods, rearanged
  :   :   :    :   :   :    :   :   :
  210 210 210  210 210 210  210 210 210  ..0
  222 111 000  222 111 000  222 111 000  ..1
  222 222 222  111 111 111  000 000 000  ..2  nhood index
  *** *** ***  *** *** ***  *** *** ***  ..outputs
  ||| ||| |||  ||| ||| |||  ||| ||| |||  ..level 1 mupno_level=27/3
  ___ ___ ___  ___ ___ ___  ___ ___ ___  
   \___|___/    \___|___/    \___|__/    ..level 2, ignore 0, effective k-1
  ___________  ___________  ___________
        \___________|___________/        ..level 3, ignore 0,1,effective k-2
                                         ..level 4 etc for larger k.
  
 Size of muple=v^level (in this example 3^1, 3^2, 3^3). number of levels=k.  
 At each level, within a muple, any unique value in muple is deterministic.
 Values that occur more than once are ambiguous, values missing are forbidden.*/ 

  reflect_m_ruletable(nhoodz,thisrule,revrule);
  notln[nhoodz+1]=1;

  if ((kv_string=(char *)calloc /*for value frequency in muple*/
                     (value_range,sizeof(char)))==NULL) outof_memory("(kv_string");
  if ((kv_null=(char *)calloc 
                     (value_range,sizeof(char)))==NULL) outof_memory("(kv_null");
  
  /* to keep track of equal muple to calculate next level */
  /* need 2 to alternate */
  mupno_level=(tablemax+1)/value_range; /*max = value_bits for each entry*/
  if ((level_same=(char **)calloc /*to store one value for each same muple set*/
             (2,sizeof(char*)))==NULL) outof_memory("level_same");
  for (i=0;i<=1;i++){
      if ((level_same[i]=(char *)calloc /*to store one value for each same muple set*/
             (mupno_level,sizeof(char)))==NULL) outof_memory("level_same");
  }
  /*fprintf(stderr,"\n level_same=");*/
  for (x=0;x<=mupno_level-1;x++){ /* fill buff with 9s*/
      level_same[0][x]=9;
      level_same[1][x]=9;
      /*fprintf(stderr,"%d",level_same[0][x]);*/
           
  }
  /*z=1..left->right, z=2 equivelent to left<-right*/
  for (z=1;z<=2;z++){
     count=0;
     /*fprintf(stderr,"\nz%d: ",z);*/
     if (z==1) memmove(temprule,thisrule,tablebytes);
     if (z==2) memmove(temprule,revrule,tablebytes);
     muple=value_range;/*size of template 3,9,27 for v=3 etc */
     
     for (this_level=1;this_level<=nhoodz;this_level++){ 
          count=0; /* of deterministic entries in rule table */        
          lev_muple=(signed int)pow(value_range,(double)this_level); /* v^level */
          mupno_level=(tablemax+1)/lev_muple; /*no of muples reduces for level 2+*/
          /* 1, 3, 9 for v=3 etc*/
          this_step=(signed int)pow(value_range,(double)(this_level-1));     
          /*fprintf(stderr,"\n thisstep=%d",this_step);*/
          if (this_level==1) this_step=1;
	  /*fprintf(stderr,"\n this_level=%d this_step=%d muple=%d lev_muple=%d",
	    this_level,this_step,muple,lev_muple);*/
	  /*for template size 3,9,27,...*/
          muple_count=0;
          level_same_count=0;
          for (x=0;x<=mupno_level-1;x++){ /* fill other buff with 9s*/
             level_same[this_level%2][x]=9;
	  }
	  for (x=0;x<=tablemax+1-lev_muple;x+=lev_muple){
	   if (x>0){ 
              muple_count+=1;
              level_same_count+=muple;
           }
           same=0;
           /*fprintf(stderr,"\n lev_muple=%d x=%d: ",lev_muple,x);*/

	   /*check frequency of values, unique values are deterministic*/
           /*is level odd or even*/
           if (this_level>1){ /*check prev level, (level odd or even)*/
	      /*fprintf(stderr,"\n lavel_same[%d]=",(this_level-1)%2);
              for (i=level_same_count;i<=level_same_count+muple-1;i++){
	         fprintf(stderr,"%d",level_same[(this_level-1)%2][i]);
              }
              fprintf(stderr," "); */
              for (i=level_same_count;i<=level_same_count+muple-1;i++){
	         if (level_same[(this_level-1)%2][i]==9){
	            same=0;
                    break;
                 }
                 else same=1;
              }
           }
           if (this_level==1 || same==1){
	      memmove(kv_string,kv_null,value_range); /*empty (kv_string*/
              for (y=x;y<=x+lev_muple-1;y+=this_step){
                  this_value=get_value(temprule,y);
                  /*fprintf(stderr,"%d",this_value);*/
                  /*kv_string records freq of diff values, this_value=position*/
                  tempfreq=kv_string[this_value]+1;
		  kv_string[this_value]+=1;
	      }
              /*fprintf(stderr," ");
              for (i=value_range-1;i>=0;i--) 
                  fprintf(stderr,"%d",kv_string[i]);*/

              for (i=value_range-1;i>=0;i--){
	          if (kv_string[i]==1) count+=this_step;
                  else if (kv_string[i]==value_range){
		      level_same[this_level%2][muple_count]=this_value; 
                      break;
                  }
              }
	      /*count of template matches*/
              /*fprintf(stderr," ..%d",count);*/
	      ncount[this_level]=count;            
           } 
           /*fprintf(stderr,"\n level_same[%d]=",abs(this_level%2-1));
           for (i=0;i<=((tablemax+1)/lev_muple)-1;i++){
	      fprintf(stderr,"%d",level_same[this_level%2][i]);
	   }*/  
	}
        /*prob det = (count/max count) * not prob before*/
	ln[this_level]=( (float)ncount[this_level]/(tablemax+1))
                                   *notln[this_level-1];
        /*fprintf(stderr,"\nln[%d]=%d/%d * %f =%f",this_level,ncount[this_level],
	        tablemax+1,notln[this_level-1],ln[this_level]);*/
	   /*calc not prob*/
	   temp=0;
	   for (not=1;not<=this_level;not++){
	      temp+=ln[not];
	   }
	   notln[this_level]=1-temp;	
     }
     zparam[z]=0;
     for (i=nhoodz;i>=1;i--) zparam[z]+=ln[i];
     for (i=nhoodz;i>=1;i--){
	ncount[i]=0;
	ln[i]=0;
	notln[i]=0;
     }
  }

  /*print details*/
  if (zparam[1]>zparam[2]) zparam[0]=zparam[1];
  else zparam[0]=zparam[2];
  
  for (x=0; x<=tablemax; x++) 
         v_count[get_value(thisrule,x)]+=1;
  
  biggest=0;
  for (z=0;z<=value_range-2;z++){
     if (v_count[z+1]>v_count[biggest]) biggest=z+1; 
  }

  /*fprintf(stderr,"\n ");
  for (z=0;z<=value_range-1;z++) fprintf(stderr,"%d=%d ",z,v_count[z]);
  fprintf(stderr," biggest=%d", biggest);*/

  /*Langton's lambda: fraction of non-quiescent values, 
    where quiescent is chosen as 0*/
  lambda=(float)((tablemax+1)-v_count[0])/(tablemax+1);
  /* lambda ratio: quiescent is the most frequent (biggest)...
     fraction of non-quiescent values (f),
     divided by max of most feq value in rule table */ 
  lratio=(float)((tablemax+1)-v_count[biggest])/ 
             (  (float)(  (tablemax+1)*(value_range-1) ) / value_range); 
  /*fprintf(stderr,"\n %d/%f",(tablemax+1)-v_count[biggest],
	  (float)((tablemax+1)*(value_range-1)) / value_range); 
  fprintf(stderr,"\n lambda=%f lratio=%f",lambda,lratio);*/

  /*calculate canalyzing inputs*/
  canalyzing(nhoodz,0,thisrule);
  
  if (showz){
        set_medium_font();
        draw_box(-1,trboxw,vgay(27),Maxx-2,vgay(49),1,0);
	moveto(trboxw+3,vgay(29));
	/*show canalyzing inputs */
	sprintf(textb[0],"C=%d/%d",canaltotal,nhoodz);
	outtext(textb[0]);
	if (canaltotal && nhoodz>1){
	  outtext("=");
	   for (z=nhoodz-1;z>=0;z--){
	      if (get_bit(canal,z)==1){
		 sprintf(textb[0],"%d",z);
		 outtext(textb[0]);
	      }
	      else outtext("*");
	   }
	}
	outtext("  ");

	/*show Z, lambda, lambda-ratio, and P for value_range=2 only*/
	sprintf(textb[0],"zl=%g zr=%g",zparam[1],zparam[2]);
	sprintf(textb[1],"ld=%g",lambda);
	if (value_range==2) sprintf(textb[2]," ld-r=%g P=%g Z=%g",
			    lratio,.5+(1.0-lratio)/2,zparam[0]);
        else sprintf(textb[2],"  ld-r=%g Z=%g",
			    lratio,zparam[0]);
	outtext(textb[0]);
	moveto(trboxw+vgax(3),gety+CHeight);
	outtext(textb[1]);
	outtext(textb[2]);
        restore_def_font();
  }
  free(v_count);
  for (i=0;i<=1;i++) free(level_same[i]);  
  free(level_same);  
  free(kv_string);  
  free(kv_null);  
  free(ln);  
  free(notln);  
  free(ncount);
  free(temprule);  
  free(revrule);  
  moveto(tempx,tempy);
}

/****** make a reflected mult-value rule table, March 2002 ********/
void reflect_m_ruletable(char nhoodz, char *thisrule, char *revrule){
  signed int tablemax,i,q,ref_ruleindex;
  char *ref_nhood;
 
  tablemax=(signed int)pow(value_range,(double)nhoodz)-1;
  if ((ref_nhood=(char *)calloc
          (nhoodz,sizeof(char)))==NULL) outof_memory("ref_nhood");

  for (i=tablemax;i>=0;i--){
    /*fprintf(stderr,"\n%d-",i);*/
     for (q=nhoodz-1;q>=0;q--){
        ref_nhood[(nhoodz-1)-q]=(char)get_value(nm[q],i);
        /*fprintf(stderr,"%d",get_value(nm[q],i));*/
     }
     /*fprintf(stderr,"-");*/
     ref_ruleindex=0;
     for (q=nhoodz-1;q>=0;q--){
        ref_ruleindex+=ref_nhood[q]*(signed int)pow(value_range,q);
        /*fprintf(stderr,"%d",ref_nhood[q]);*/
     }
     /*fprintf(stderr,"-%d",ref_ruleindex);*/
     set_value(revrule,i,get_value(thisrule,ref_ruleindex));
  }
  /*show the original and reflected rule table*/
  /*fprintf(stderr,"\n");
  count=0;
  for (i=tablemax;i>=0;i--){
     temp_count+=1;
     fprintf(stderr,"%d", get_value(thisrule,i));
     if (temp_count%value_range==0) fprintf(stderr," ");
  }
  fprintf(stderr,"\n");
  count=0;
  for (i=tablemax;i>=0;i--){
     count+=1;
     fprintf(stderr,"%d", get_value(revrule,i));
     if (count%value_range==0) fprintf(stderr," ");
  }
  fprintf(stderr,"\n");*/

  free(ref_nhood);
}

/***** set one bit in long char array at position pos, 5 Aug 93 *******/
void set_bitlong(register char *array,
       register unsigned long pos,register char bit){

   if (bit) array[pos/8] |= 1<<pos%8;
   else array[pos/8] &= ~(1<<pos%8);
   /*
   if (bit) array[pos>>3] |= 1<<(pos&7);
   else array[pos>>3] &= ~(1<<(pos&7));
   */
}

/**** get one bit from long char array at position pos, 5 Aug 93 ******/
char get_bitlong(register char *array,register unsigned long pos){

   return((array[pos/8]>>pos%8) & 1);
   /*
   return((array[pos>>3]>>(pos&7)) & 1);
   */
}

/***** for multi-state, get the value of a cell or rule table entry *****/
signed int get_value(char *array, unsigned int ct_count){
  signed int this_value=0;
  unsigned long ct_bitcount;
  char bit0,bit1,bit2,bit3,bit4;

     if (value_range==2){ 
            this_value=get_bit(array,ct_count);
     }    
     else{
            ct_bitcount=value_bits*ct_count;
            bit0=get_bit(array,ct_bitcount);
            if (value_bits==1) this_value=bit0; 
            else if (value_bits>1){ 
                   bit1=get_bit(array,ct_bitcount+1);
                   if (value_bits==2) this_value=bit0 + bit1*2; 
                   else if (value_bits==3){
		      bit2=get_bit(array,ct_bitcount+2);
                      this_value=bit0 + bit1*2 + bit2*4; 
                   } 
                   else if (value_bits==4){ /*values up to 15*/
		      bit2=get_bit(array,ct_bitcount+2);
                      bit3=get_bit(array,ct_bitcount+3);
                      this_value=bit0 + bit1*2 + bit2*4 + bit3*8; 
                   }
                   else if (value_bits==5){ /*values up to 31*/
		      bit2=get_bit(array,ct_bitcount+2);
                      bit3=get_bit(array,ct_bitcount+3);
                      bit4=get_bit(array,ct_bitcount+4);
                      this_value=bit0 + bit1*2 + bit2*4 + bit3*8 + bit4*16; 
                   }
            }
      }           
      return(this_value);
}

/***** get the value for any value range, number of bits specified *****/
signed int get_value_flex(char *array, unsigned int ct_count,
                  signed int  vb){

  signed int this_value=0;
  unsigned long ct_bitcount;
  char bit0,bit1,bit2,bit3,bit4;

            ct_bitcount=vb*ct_count;
            bit0=get_bit(array,ct_bitcount);
            if (vb==1) this_value=bit0; 
            else if (vb>1){ 
                   bit1=get_bit(array,ct_bitcount+1);
                   if (vb==2) this_value=bit0 + bit1*2; 
                   else if (vb==3){
		      bit2=get_bit(array,ct_bitcount+2);
                      this_value=bit0 + bit1*2 + bit2*4; 
                   } 
                   else if (vb==4){ /*values up to 15*/
		      bit2=get_bit(array,ct_bitcount+2);
                      bit3=get_bit(array,ct_bitcount+3);
                      this_value=bit0 + bit1*2 + bit2*4 + bit3*8; 
                   }
                   else if (vb==5){ /*values up to 31*/
		      bit2=get_bit(array,ct_bitcount+2);
                      bit3=get_bit(array,ct_bitcount+3);
                      bit4=get_bit(array,ct_bitcount+4);
                      this_value=bit0 + bit1*2 + bit2*4 + bit3*8 + bit4*16; 
                   }
            
     }     
     return(this_value);
}

/***** for multi-state, set the value of a cell or rule table entry *****/
void set_value(char *array, 
              unsigned int ct_count, signed int tempvalue){
   unsigned long ct_bitcount;
   
   if (value_range==2){ 
      set_bit(array,ct_count,tempvalue);
   }
   else{  /* & keeps the relevant bit, sets others to 0 */
      ct_bitcount=value_bits*ct_count;
      if (value_bits>=1) set_bit(array,ct_bitcount,tempvalue & 01);
      if (value_bits>=2) set_bit(array,ct_bitcount+1,(tempvalue & 02) >> 1);
      if (value_bits>=3) set_bit(array,ct_bitcount+2,(tempvalue & 04) >> 2);
      if (value_bits>=4) set_bit(array,ct_bitcount+3,(tempvalue & 010) >> 3);
      if (value_bits>=5) set_bit(array,ct_bitcount+4,(tempvalue & 020) >> 4);
   }  
}

/***** set the value for any values range, number of bits specified *****/
void set_value_flex(char *array, 
     unsigned int ct_count,signed int tempvalue,signed int vb){
   unsigned long ct_bitcount;
   
    /* & keeps the relevant bit, sets others tp 0 */
      ct_bitcount=vb*ct_count;
      if (vb>=1) set_bit(array,ct_bitcount,tempvalue & 01);
      if (vb>=2) set_bit(array,ct_bitcount+1,(tempvalue & 02) >> 1);
      if (vb>=3) set_bit(array,ct_bitcount+2,(tempvalue & 04) >> 2);
      if (vb>=4) set_bit(array,ct_bitcount+3,(tempvalue & 010) >> 3);
      if (vb>=5) set_bit(array,ct_bitcount+4,(tempvalue & 020) >> 4); 
}

/***** rotate bytesL bits in char array by rotinterval, 13 May 93 *****/
char* rotate_array(char nhoodz,char *array, char direction,
			 char isrule, signed int rotinterval){

 char endvalue;
 signed int z1,ii;
 unsigned int sizeA;

     if (!isrule) sizeA=lineL;
     else {
        if (isotropic_set==1){
	   sizeA=iso_tablemax+1;
	}
        if (isrule==1){
	   sizeA=(unsigned int)pow(value_range,(double)nhoodz);
	}
	else{
           if (totalistic==1)  /*for totalistic code, isrule=2*/
	      sizeA=(unsigned int)(nhood*(value_range-1)+1);
           else if (totalistic==2) sizeA=(unsigned int)
				     v_tablecodemax[nhood]+1;
	}
     }
     for (z1=1;z1<=rotinterval;z1++){
      switch(direction){
	case 'l':
	   /*rotate left, endbit=left*/
	   endvalue=get_value(array,sizeA-1);
	   for (ii=sizeA-1;ii>=1;ii--)
                  set_value(array,ii,get_value(array,ii-1));
	   set_value(array,0,endvalue);
	   break;
	case 'r':
	   /*rotate right, endbit=right*/
	   endvalue=get_value(array,0);
	   for (ii=0;ii<=sizeA-2;ii++)
		  set_value(array,ii,get_value(array,ii+1));
	   set_value(array,sizeA-1,endvalue);
	   break;	
      }
   }
   return(array);
}


/***** rotate 2d left/right/up/downarray by rotinterval, 13 May 93 *****/
char* rotate_array_2d(char *array,
			 char direction,signed int rotinterval){

 signed int z1,ii,jj;
 unsigned int ipos,jpos;
 char endvalue;

   for (z1=1;z1<=rotinterval;z1++){
      switch(direction){
	case 'l':
	   /*rotate left, endbit=left*/
	   for (jj=j2d-1;jj>=0;jj--){
	      endvalue=get_value(array,i2d-1+i2d*jj);
	      for (ii=i2d-1;ii>=1;ii--){
		  ipos=ii+i2d*jj;
                  set_value(array,ipos,get_value(array,ipos-1));
	      }
	      set_value(array,i2d*jj,endvalue);
	   }
	   break;
	case 'r':
	   /*rotate right, endbit=right*/
	   for (jj=j2d-1;jj>=0;jj--){
	      endvalue=get_value(array,i2d*jj);
	      for (ii=0;ii<=i2d-2;ii++){
		  ipos=ii+i2d*jj;
		  set_value(array,ipos,get_value(array,ipos+1));
	      }
	      set_value(array,i2d-1+i2d*jj,endvalue);
	   }
	   break;
	case 'u':
	   /*rotate up, endbit=top*/
	   for (ii=i2d-1;ii>=0;ii--){
	      endvalue=get_value(array,ii+i2d*(j2d-1));
	      for (jj=j2d-1;jj>=1;jj--){
		 jpos=ii+i2d*jj;
		 set_value(array,jpos,get_value(array,jpos-i2d));
	      }
	      set_value(array,ii,endvalue);
	   }
	   break;
	case 'd':
	   /*rotate down, endbit=bottom*/
	   for (ii=i2d-1;ii>=0;ii--){
	      endvalue=get_value(array,ii);
              for (jj=0;jj<=j2d-2;jj++){
		 jpos=ii+i2d*jj;
		 set_value(array,jpos,get_value(array,jpos+i2d));
	      }
	      set_value(array,ii+i2d*(j2d-1),endvalue);
	   }
	   break;
      }
   }
   return(array);
}

/***** rotate 2d patch only left/right/up/downarray by rotinterval, 29 July 2014 *****/
char* move_patch_2d(char *array,char direction,signed int rotinterval){

 signed int z1,ii,jj;
 unsigned int ipos,jpos;
 double hex_vmove;

   if (misc_hex2d==1 && cellscale>=3) hex_vmove=aspectratio; //hex_vmove=cos(PI/6);
   else hex_vmove=1;

   setviewport(tview_x0,tview_y0,tview_x1-2,tview_y1,0); /*keep moves in window*/    
   for (z1=1;z1<=rotinterval;z1++){
      switch(direction){

        case 'l': /*move patch left*/	   
           if (Ei<i2d-1){ /*stop at left boundary*/
		    Si++;
                    Ei++;
	   }
           else goto skip;
           
           /*rotate left, endbit=left*/
	   for (jj=j2d-1;jj>=0;jj--){
	      if (jj<Sj || jj>Ej) continue;
	      for (ii=i2d-1;ii>=1;ii--){
                  if (ii>Ei || ii<Si) continue;
                  ipos=ii+i2d*jj;
                  draw_and_set_value_line(1,array,0,get_value(array,ipos-1),L,L-ipos,
		    cellscale,show_2d_divs,show_dots,color_v[get_value(array,ipos-1)],
		      topleftx + (i2d-1-ii)*cellscale, toplefty + (j2d-1-jj)*cellscale*hex_vmove,0);
                  draw_and_set_value_line(1,array,0,0,L,L-(ipos-1),/*follow up with zeros*/
		    cellscale,show_2d_divs,show_dots,color_v[0],
		      topleftx + (i2d-1-(ii-1))*cellscale, toplefty + (j2d-1-jj)*cellscale*hex_vmove,0);
	      }
	   }
           break;

	case 'r': /*move patch right*/
          if (Si>0){ /*stop at right boundary*/
	       Si--;
               Ei--;
	   }
	   else goto skip;
           
	   for (jj=j2d-1;jj>=0;jj--){
              if (jj<Sj || jj>Ej) continue;
	      for (ii=0;ii<=i2d-1;ii++){
                  if (ii<Si || ii>Ei) continue;
		  ipos=ii+i2d*jj;
                  draw_and_set_value_line(1,array,0,get_value(array,ipos+1),L,L-ipos,
		   cellscale,show_2d_divs,show_dots,color_v[get_value(array,ipos+1)],
		     topleftx + (i2d-1-ii)*cellscale, toplefty + (j2d-1-jj)*cellscale*hex_vmove,0);
                  draw_and_set_value_line(1,array,0,0,L,L-(ipos+1),
		   cellscale,show_2d_divs,show_dots,color_v[0],
		     topleftx + (i2d-1-(ii+1))*cellscale, toplefty + (j2d-1-jj)*cellscale*hex_vmove,0);
	      }              
	   }
           break;

	case 'u': /*move patch up*/	   
           if (Ej<j2d-1){ /*stop at top boundary*/
	      Sj++;
              Ej++;
	   }
           else goto skip;
           
	   for (ii=i2d-1;ii>=0;ii--){
              if (ii<Si || ii>Ei) continue;	      
	      for (jj=j2d-1;jj>=1;jj--){
                 if (jj<Sj || jj>Ej) continue;
		 jpos=ii+i2d*jj;
                 draw_and_set_value_line(1,array,0,get_value(array,jpos-i2d),L,L-jpos,
		  cellscale,show_2d_divs,show_dots,color_v[get_value(array,jpos-i2d)],
		   topleftx + (i2d-1-ii)*cellscale, toplefty + (j2d-1-jj)*cellscale*hex_vmove,0);
	         draw_and_set_value_line(1,array,0,0,L,L-(jpos-i2d),
		   cellscale,show_2d_divs,show_dots,color_v[0],
		   topleftx + (i2d-1-ii)*cellscale, toplefty + (j2d-1-(jj-1))*cellscale*hex_vmove,0);
	      }
	   }
           break;

	case 'd': /*move patch down*/
           if (Sj>0){ /*stop at bottom boundary*/
	       Sj--;
               Ej--;
	   }
           else goto skip;
           
	   for (ii=i2d-1;ii>=0;ii--){
              if (ii<Si || ii>Ei) continue;	      
              for (jj=0;jj<=j2d-2;jj++){
                 if (jj<Sj || jj>Ej) continue;
		 jpos=ii+i2d*jj;
                 draw_and_set_value_line(1,array,0,get_value(array,jpos+i2d),L,L-jpos,
		  cellscale,show_2d_divs,show_dots,color_v[get_value(array,jpos+i2d)],
		   topleftx + (i2d-1-ii)*cellscale, toplefty + (j2d-1-jj)*cellscale*hex_vmove,0);
		 draw_and_set_value_line(1,array,0,0,L,L-(jpos+i2d),
		  cellscale,show_2d_divs,show_dots,color_v[0],
		   topleftx + (i2d-1-ii)*cellscale, toplefty + (j2d-1-(jj+1))*cellscale*hex_vmove,0);
	      }
	   }
           break;
      }
   }
   skip:
   return(array);
}

/***** rotate 2d patch only left/right/up/downarray by rotinterval, 29 July 2014 *****/
char* jump_patch_2d(char *array,unsigned int leftpos,signed int zcount){
  signed int tempi,tempj,
    ii,jj,Six,Sjx,Eix,Ejx,tempx,tempy,MaxSi,MaxSj,
             pos,posA,pos_array;
  char *tempS,tempvalue;
  double hex_vmove;
  unsigned int n; 

   if (misc_hex2d==1 && cellscale>=3) hex_vmove=aspectratio; //hex_vmove=cos(PI/6);
   else hex_vmove=1;
   setviewport(tview_x0,tview_y0,tview_x1-2,tview_y1,0); /*keep moves in window*/
   if ((tempS=(char*)calloc(bytesL,sizeof(char)))
				 ==NULL) outof_memory("tempS");   

   n=leftpos-zcount;
   Six=n%i2d;      
   Sjx=n/i2d; 
   Eix=Six+Pi2d-1;  
   Ejx=Sjx+Pj2d-1;
   //fprintf(stderr,"\nA %dx%d (%d %d)(%d %d)",Pi2d,Pj2d, Six,Sjx, Eix,Ejx); 

        /*copy patch to temp array*/
        for (jj=0;jj<=Pj2d-1;jj++){      
	     for (ii=0;ii<=Pi2d-1;ii++){
                  pos=ii+Pi2d*jj;
                  pos_array=(ii+Si)+i2d*(jj+Sj);
                  tempvalue=get_value(array,pos_array);
                  set_value(tempS,pos,tempvalue);       
              }
        }
       
        /* set and redraw at cursor position*/  
        for (jj=0;jj<=Pj2d-1;jj++){
	   tempj=j2d-1-(jj+Sjx);       
	   for (ii=0;ii<=Pi2d-1;ii++){
	      tempi=i2d-1-(ii+Six);
              tempx=topleftx+tempi*cellscale;
              tempy=toplefty+tempj*cellscale*hex_vmove;
              pos=ii+Pi2d*jj;         
	      posA=(ii+Six)+i2d*(jj+Sjx);
              MaxSi=posA%i2d;    
              MaxSj=posA/i2d;
              if (MaxSi==0 || MaxSi>i2d-1 || MaxSj>j2d-1) continue; //dont write outside
              draw_and_set_value_line(1,array,0,get_value(tempS,pos),L,L-posA,
		cellscale,show_2d_divs,show_dots,color_v[get_value(tempS,pos)],tempx,tempy,0);
            }
	}
        free(tempS);
        /*change active patch to new position*/
        //fprintf(stderr,"\nB1 %dx%d (%d %d)(%d %d)",Pi2d,Pj2d,Six,Sjx,Eix,Ejx);        
        Si=Six;      
        Sj=Sjx; 
        Ei=Eix;
        if (Ei>i2d-1) Ei=i2d-1; /*correct if over left edge*/
        Ej=Ejx;
        if (Ej>j2d-1)  Ej=j2d-1; /*correct if over top edge*/
        Pi2d=Ei-Si+1;/*i width for jump patch*/
        Pj2d=Ej-Sj+1;/*j height for jump patch*/
        //fprintf(stderr,"\nB2 %dx%d (%d %d)(%d %d)",Pi2d,Pj2d,Si,Sj,Ei,Ej);
        return(array);

}

/***** spin 2d clockwize, Sept 04 *****/
char* v_spin_array_2d(char *array){

 signed int ii,jj,ni,nj,ni2d, nj2d;
 unsigned int newpos,oldpos,pos;
 char *tempS;

           if ((tempS=(char*)calloc(bytesL,sizeof(char)))
				 ==NULL) outof_memory("tempS");  
    
           /*spin 90 degrees, 
             if not square, right or lower square only is spun*/
	   /*does not work too well on aqq hex lattice*/
           ni2d=i2d;      
           nj2d=j2d;
           if (i2d>j2d) ni2d=j2d;      
           else if (j2d>i2d) nj2d=i2d;
	   
	   for (jj=nj2d-1;jj>=0;jj--){      
	      for (ii=ni2d-1;ii>=0;ii--){
                  ni=nj2d-1-jj;
                  nj=ii;
                  /*in case i2d != j2d*/
                  if (ni<=i2d-1 && ni>=0 && nj<=j2d-1 && nj>=0){
                     newpos=ni+i2d*nj;
		     oldpos=ii+i2d*jj;
                     if (newpos<=L && oldpos<=L)
                         set_value(tempS,newpos,get_value(array,oldpos));
                  }
	      }
	   }
           for (jj=nj2d-1;jj>=0;jj--){      
	      for (ii=ni2d-1;ii>=0;ii--){
                  pos=ii+i2d*jj;
                  set_value(array,pos,get_value(tempS,pos));
              }
           }
           /*memmove(array,tempS,bytesL);*/
           free(tempS);
           return(array);
}

/***** spin 2d clockwize, Aug 2014 *****/
char* v_spin_patch_2d(char *array,signed int startx,signed int endx,
                                  signed int starty,signed int endy){

  signed int ii,jj,ni,nj,ni2d,nj2d,
             newpos,oldpos,pos,posA,tempx,tempy;
  char *tempS;
  double hex_vmove;

   if (misc_hex2d==1 && cellscale>=3) hex_vmove=aspectratio; //hex_vmove=cos(PI/6);
   else hex_vmove=1;
 
           setviewport(tview_x0,tview_y0,tview_x1-2,tview_y1,0); /*keep moves in window*/ 
           if ((tempS=(char*)calloc(bytesL,sizeof(char))) 
				 ==NULL) outof_memory("tempS");      
           /*spin 90 degrees, 
             if not square, right or lower square only is spun*/
	   /*does not work too well on a hex lattice*/
           ni2d=Ei-Si+1;     
           nj2d=Ej-Sj+1;
           if (ni2d>nj2d) ni2d=nj2d;
           else if (nj2d>ni2d) nj2d=ni2d;
	   
	   for (jj=0;jj<=nj2d-1;jj++){      
	     for (ii=0;ii<=ni2d-1;ii++){
                  ni=nj2d-1-jj;
                  if (ni<0 || ni>i2d-1) continue; /*to stop spin outside limits*/
                  nj=ii;
                  if (nj<0 || nj>j2d-1) continue; /*to stop spin outside limits*/
                  newpos=ni+ni2d*nj;
                  oldpos=(ii+Si)+i2d*(jj+Sj);
		  set_value(tempS,newpos,get_value(array,oldpos));
	      }
	   }
           
           for (jj=0;jj<=nj2d-1;jj++){      
	     for (ii=0;ii<=ni2d-1;ii++){
	        tempx=topleftx+(i2d-1-(ii+Si))*cellscale;
                tempy=toplefty+(j2d-1-(jj+Sj))*cellscale*hex_vmove;
                if (tempx<startx || tempx>endx) continue;
                if (tempy<starty || tempy>endy) continue;
                pos=ii+ni2d*jj;                  
		posA=(ii+Si)+i2d*(jj+Sj);
                draw_and_set_value_line(1,array,0,get_value(tempS,pos),L,L-posA,
		  cellscale,show_2d_divs,show_dots,color_v[get_value(tempS,pos)],tempx,tempy,0);
              }
	   }
           free(tempS);
           return(array);
}


/***** flip (reflect) 1d seed or rule, Nov 09 *****/
char* flip_array_1d(char *array,
         unsigned int string_max,unsigned int string_bytes){

 unsigned int ii,pos,pos_flip;
 char *tempS;
           
        if ((tempS=(char*)calloc(string_bytes,sizeof(char)))
				 ==NULL) outof_memory("tempS");
        
	for (ii=string_max;ii!=Maxu;ii--){
             pos=ii;	      
	     pos_flip=string_max-ii;
             set_value(tempS,pos,get_value(array,pos_flip));                                
        }        
        memmove(array,tempS,string_bytes);
        free(tempS);
        return(array);
}

/***** flip horizontally (i) or vertically (j) 2d, Nov 05 *****/
char* flip_array_2d(char *array,char xy){

 signed int ii,jj,ii_hflip,jj_hflip,pos,pos_flip;
 char *tempS;
           
        if ((tempS=(char*)calloc(bytesL,sizeof(char)))
				 ==NULL) outof_memory("tempS");  
        if (xy=='X'){
           for (jj=j2d-1;jj>=0;jj--){   
	      for (ii=i2d-1;ii>=0;ii--){
                  pos=ii+i2d*jj;	      
		  ii_hflip=i2d-1-ii;
                  pos_flip=ii_hflip+i2d*jj;
                  set_value(tempS,pos,get_value(array,pos_flip));                  
              }
           }
        }
        else if (xy=='Y'){
           for (jj=j2d-1;jj>=0;jj--){   
	      for (ii=i2d-1;ii>=0;ii--){
                  pos=ii+i2d*jj;		      
		  jj_hflip=j2d-1-jj;
                  pos_flip=ii+i2d*jj_hflip;
                  set_value(tempS,pos,get_value(array,pos_flip));
              }
           }
        }
        memmove(array,tempS,bytesL);
        free(tempS);
        return(array);
}

/***** redraw the patch including 0color/dots/dive/divcolor-^/./i/! 2d, Aug 2014 *****/
char* redraw_patch_2d(char *array){ /*if any of these are changed*/
  signed int ii,jj,ni2d,nj2d,tempx,tempy,
             pos,posA,pos_array;
  char *tempS,tempvalue;
  double hex_vmove;

   if (misc_hex2d==1 && cellscale>=3) hex_vmove=aspectratio; //hex_vmove=cos(PI/6);
   else hex_vmove=1;
         
       setviewport(tview_x0,tview_y0,tview_x1-2,tview_y1,0); /*keep moves in window*/
       if ((tempS=(char*)calloc(bytesL,sizeof(char)))
				 ==NULL) outof_memory("tempS");
        ni2d=Ei-Si+1;     
        nj2d=Ej-Sj+1;
              
        for (jj=0;jj<=nj2d-1;jj++){      
	     for (ii=0;ii<=ni2d-1;ii++){
                  pos=ii+ni2d*jj;
	          pos_array=(ii+Si)+i2d*(jj+Sj);
                  tempvalue=get_value(array,pos_array);
                  set_value(tempS,pos,tempvalue);       
              }
        }     
        for (jj=0;jj<=nj2d-1;jj++){      
	   for (ii=0;ii<=ni2d-1;ii++){
	      tempx=topleftx+(i2d-1-(ii+Si))*cellscale;
              tempy=toplefty+(j2d-1-(jj+Sj))*cellscale*hex_vmove;
              pos=ii+ni2d*jj;                  
	      posA=(ii+Si)+i2d*(jj+Sj);
              draw_and_set_value_line(1,array,0,get_value(tempS,pos),L,L-posA,
		cellscale,show_2d_divs,show_dots,color_v[get_value(tempS,pos)],tempx,tempy,0);
            }
	}
        free(tempS);
        return(array);
}

/***** flip horizontally (i) or vertically (j) 2d, Aug 2014 *****/
char* flip_patch_2d(char *array,char xy){

 signed int ii,jj,ni2d,nj2d,tempx,tempy;
 unsigned int pos,posA,pos_flip;
 char *tempS;
 double hex_vmove;

   if (misc_hex2d==1 && cellscale>=3) hex_vmove=aspectratio; //hex_vmove=cos(PI/6);
   else hex_vmove=1;

        setviewport(tview_x0,tview_y0,tview_x1-2,tview_y1,0); /*keep moves in window*/      
        if ((tempS=(char*)calloc(bytesL,sizeof(char)))
				 ==NULL) outof_memory("tempS");
        ni2d=Ei-Si+1;     
        nj2d=Ej-Sj+1;
       
        if (xy=='X'){
           for (jj=0;jj<=nj2d-1;jj++){      
	     for (ii=0;ii<=ni2d-1;ii++){
                  pos=ni2d-1-ii+ni2d*jj;
	          pos_flip=(ii+Si)+i2d*(jj+Sj);
                  set_value(tempS,pos,get_value(array,pos_flip));                  
              }
           }
        }
        else if (xy=='Y'){
	  for (jj=0;jj<=nj2d-1;jj++){   
	      for (ii=0;ii<=ni2d-1;ii++){
		  pos=ii+ni2d*(nj2d-1-jj);
		  pos_flip=(ii+Si)+i2d*(jj+Sj);    
                  set_value(tempS,pos,get_value(array,pos_flip));
              }
           }
        }
        for (jj=0;jj<=nj2d-1;jj++){      
	   for (ii=0;ii<=ni2d-1;ii++){
	      tempx=topleftx+(i2d-1-(ii+Si))*cellscale;
              tempy=toplefty+(j2d-1-(jj+Sj))*cellscale*hex_vmove;
              pos=ii+ni2d*jj;                  
	      posA=(ii+Si)+i2d*(jj+Sj);
              draw_and_set_value_line(1,array,0,get_value(tempS,pos),L,L-posA,
		cellscale,show_2d_divs,show_dots,color_v[get_value(tempS,pos)],tempx,tempy,0);
                //set_value(array,posA,get_value(tempS,pos));
            }
	}
        /*memmove(array,tempS,bytesL);*/
        free(tempS);
        return(array);
}

/***** compliment 2d patch, Aug 2014 *****/
char* compliment_patch_2d(char *array){
  signed int ii,jj,ni2d,nj2d,tempx,tempy,
             pos,posA,pos_array;
  char *tempS,tempvalue;
  double hex_vmove;

   if (misc_hex2d==1 && cellscale>=3) hex_vmove=aspectratio; //hex_vmove=cos(PI/6);
   else hex_vmove=1;
         
       setviewport(tview_x0,tview_y0,tview_x1-2,tview_y1,0); /*keep moves in window*/
       if ((tempS=(char*)calloc(bytesL,sizeof(char)))
				 ==NULL) outof_memory("tempS");
        ni2d=Ei-Si+1;     
        nj2d=Ej-Sj+1;
              
        for (jj=0;jj<=nj2d-1;jj++){      
	     for (ii=0;ii<=ni2d-1;ii++){
                  pos=ii+ni2d*jj;
	          pos_array=(ii+Si)+i2d*(jj+Sj);
                  tempvalue=get_value(array,pos_array);
                  tempvalue=(value_range-1)-tempvalue;
                  set_value(tempS,pos,tempvalue);       
              }
        }     
        for (jj=0;jj<=nj2d-1;jj++){      
	   for (ii=0;ii<=ni2d-1;ii++){
	      tempx=topleftx+(i2d-1-(ii+Si))*cellscale;
              tempy=toplefty+(j2d-1-(jj+Sj))*cellscale*hex_vmove;
              pos=ii+ni2d*jj;                  
	      posA=(ii+Si)+i2d*(jj+Sj);
              draw_and_set_value_line(1,array,0,get_value(tempS,pos),L,L-posA,
		cellscale,show_2d_divs,show_dots,color_v[get_value(tempS,pos)],tempx,tempy,0);
            }
	}
        free(tempS);
        return(array);
}

/***** fill 2d patch with currently selected color, Aug 2014 *****/
char* fill_patch_2d(char *array, unsigned char left_value){ 
  /*left_value=current active drawing value*/
  signed int ii,jj,ni2d,nj2d,tempx,tempy,
             pos,posA;
  char *tempS,tempvalue;
  double hex_vmove;

   if (misc_hex2d==1 && cellscale>=3) hex_vmove=aspectratio; //hex_vmove=cos(PI/6);
   else hex_vmove=1;
         
       setviewport(tview_x0,tview_y0,tview_x1-2,tview_y1,0); /*keep moves in window*/
       if ((tempS=(char*)calloc(bytesL,sizeof(char)))
				 ==NULL) outof_memory("tempS");
        ni2d=Ei-Si+1;     
        nj2d=Ej-Sj+1;
              
        for (jj=0;jj<=nj2d-1;jj++){      
	     for (ii=0;ii<=ni2d-1;ii++){
                  pos=ii+ni2d*jj;
                  tempvalue=left_value;
                  set_value(tempS,pos,tempvalue);       
              }
        }
        for (jj=0;jj<=nj2d-1;jj++){      
	   for (ii=0;ii<=ni2d-1;ii++){
	      tempx=topleftx+(i2d-1-(ii+Si))*cellscale;
              tempy=toplefty+(j2d-1-(jj+Sj))*cellscale*hex_vmove;
              pos=ii+ni2d*jj;                  
	      posA=(ii+Si)+i2d*(jj+Sj);
              draw_and_set_value_line(1,array,0,get_value(tempS,pos),L,L-posA,
		cellscale,show_2d_divs,show_dots,color_v[get_value(tempS,pos)],tempx,tempy,0);
            }
	}    
        free(tempS);
        return(array);
}

/***** fill 2d patch with current random density, Oct 2014 *****/
char* fill_rnd_patch_2d(char *array){
  signed int ii,jj,ni2d,nj2d,tempx,tempy,
             pos,posA,temprand;
  char *tempS;  
  double hex_vmove;

   if (misc_hex2d==1 && cellscale>=3) hex_vmove=aspectratio; //hex_vmove=cos(PI/6);
   else hex_vmove=1;

       setviewport(tview_x0,tview_y0,tview_x1-2,tview_y1,0); /*keep moves in window*/
       if ((tempS=(char*)calloc(bytesL,sizeof(char)))
				 ==NULL) outof_memory("tempS");
        ni2d=Ei-Si+1;     
        nj2d=Ej-Sj+1;
              
        for (jj=0;jj<=nj2d-1;jj++){      
	   for (ii=0;ii<=ni2d-1;ii++){
              pos=ii+ni2d*jj;
              if ( Rdensity<0 || Rdensity>100 /*|| blockdiam<=3*/){
	         if (value_range==2){ 
                    set_bit(tempS,pos,(myrand()%100)/50);
                 }
                 else set_value(tempS,pos,myrand()%value_range);
	      }
	      else {
                 temprand=myrand()%1000;
                 if (temprand==0) temprand=1;
                 if ((signed int)temprand<(10*Rdensity)){   
                    if (value_range==2){                
		       set_bit1(tempS,pos);
                    }
                    else set_value(tempS,pos,myrand()%(value_range-1)+1);
                 }
                 else set_value(tempS,pos,0);
	      }
	   }
        }         
        for (jj=0;jj<=nj2d-1;jj++){      
	   for (ii=0;ii<=ni2d-1;ii++){
	      tempx=topleftx+(i2d-1-(ii+Si))*cellscale;
              tempy=toplefty+(j2d-1-(jj+Sj))*cellscale*hex_vmove;
              pos=ii+ni2d*jj;                  
	      posA=(ii+Si)+i2d*(jj+Sj);
              draw_and_set_value_line(1,array,0,get_value(tempS,pos),L,L-posA,
		cellscale,show_2d_divs,show_dots,color_v[get_value(tempS,pos)],tempx,tempy,0);
            }
	}    
        free(tempS);
        return(array);
}

/***** fill 2d patch with current value frequency, Dec 2014 *****/
char* fill_fraction_values_patch_2d(char *array){
          signed int z;
          unsigned int *temporder,countz,next_limit=0,zz,zu,ttot,vfreq[8];
          char *temparray;
          unsigned char temp_bias_percent[9];
          signed int ii,jj,thistotal;

  signed int ni2d,nj2d,tempx,tempy,
             pos,posA;
  char *tempS;
  
  double hex_vmove;

      thistotal=lineL;
      /*for seed*/
      for (z=0;z<=value_range-1;z++){
           temp_bias_percent[z]=bias_percent_seed[z];          
      }
      temp_bias_percent[8]=bias_percent_seed[8];
              
               for (z=value_range-1;z>=0;z--) vfreq[z]=0;
               if ((temporder=(unsigned int *)calloc
                 (thistotal,sizeof(unsigned int)))==NULL) outof_memory("temporder");
               if ((temparray=(char *)calloc
                 (thistotal,sizeof(char)))==NULL) outof_memory("temparray");
               /*fill temparray with consecutive values according to set percentages)*/
               countz=-1;               
               for (z=0;z<=value_range-1;z++){	   
	          if (temp_bias_percent[8]=='p'){  /*percentages -- round up or down*/
                     next_limit= (unsigned int)floor((float)thistotal * 
                                        (float)temp_bias_percent[z]/100);
                     if ((double)thistotal * (double)temp_bias_percent[z]/100 
	                  - next_limit > .5) next_limit+=1;
                  }
                  else if (temp_bias_percent[8]=='v') /*actual values*/
	                        next_limit=temp_bias_percent[z];

	          for (zz=1;zz<=next_limit;zz++){
                     countz+=1;
                     if (countz>thistotal) goto skiprule;
                     set_value(temparray,countz,z);
                  }
               }
              skiprule:

               for (zz=0;zz<=thistotal-1;zz++) temporder[zz]=zz;
               /*revise this -- gets stuck for large array*/
               /* similar to shuffle_order(); learn*->c */
	       if (temp_bias_percent[8]=='v'){ /*actual values for <=255 */
                  for (zu=0;zu<=thistotal-1;zu++){
                     redowire:
                     temporder[zu]= myrand()%(thistotal);
                     if (zu>0){
	                for (zz=0;zz<=zu-1;zz++){
	                   if (temporder[zu]==temporder[zz]) goto redowire;
	                }
                     } 
	          }
               }

   if (misc_hex2d==1 && cellscale>=3) hex_vmove=aspectratio; //hex_vmove=cos(PI/6);
   else hex_vmove=1;

       setviewport(tview_x0,tview_y0,tview_x1-2,tview_y1,0); /*keep moves in window*/
       if ((tempS=(char*)calloc(bytesL,sizeof(char)))
				 ==NULL) outof_memory("tempS");
        ni2d=Ei-Si+1;     
        nj2d=Ej-Sj+1;
               
               
               for (jj=0;jj<=nj2d-1;jj++){      
	          for (ii=0;ii<=ni2d-1;ii++){
                           pos=ii+ni2d*jj;
                           if (temp_bias_percent[8]=='v')
                              set_value(tempS,pos,get_value(temparray,temporder[pos]));
                           else if (temp_bias_percent[8]=='p')
                              set_value(tempS,pos,get_value(temparray,temporder[myrand()%(thistotal)]));
                           vfreq[get_value(temparray,temporder[pos])] +=1;
                   }
               }

               for (jj=0;jj<=nj2d-1;jj++){      
	          for (ii=0;ii<=ni2d-1;ii++){
	             tempx=topleftx+(i2d-1-(ii+Si))*cellscale;
                     tempy=toplefty+(j2d-1-(jj+Sj))*cellscale*hex_vmove;
                     pos=ii+ni2d*jj;                  
	             posA=(ii+Si)+i2d*(jj+Sj);
                     draw_and_set_value_line(1,array,0,get_value(tempS,pos),L,L-posA,
		       cellscale,show_2d_divs,show_dots,color_v[get_value(tempS,pos)],tempx,tempy,0);
                  }
	       }    
               free(tempS);
               return(array);  
	                      
               free(temporder);
               free(temparray);

               /*ttot=0;
               fprintf(stderr,"\nvfreq= ");
               for (z=value_range-1;z>=0;z--){ 
	          fprintf(stderr,"%d ", vfreq[z]);
                  ttot+=vfreq[z];
               }
               fprintf(stderr,"=%d %=", ttot);

               for (z=value_range-1;z>=0;z--){ 
	          fprintf(stderr,"%.1f ", ((float)vfreq[z]*100)/thistotal);
                  ttot+=vfreq[z];
	       }*/
}

/***** flip horizontally (i) or vertically (j) 3d, Nov 09 *****/
char* flip_array_3d(char *array,char xy){

 signed int ii,jj,hh,ii_hflip,jj_hflip;
 unsigned int pos,pos_flip;
 char *tempS;

     if ((tempS=(char*)calloc(bytesL,sizeof(char)))
				 ==NULL) outof_memory("tempS"); 
     for (hh=h3d-1;hh>=0;hh--){            
        if (xy=='X'){
           for (jj=j3d-1;jj>=0;jj--){   
	      for (ii=i3d-1;ii>=0;ii--){
                  pos=(i3d*j3d*hh) + (i3d*jj) + ii;
		  ii_hflip=i2d-1-ii;
                  pos_flip=(i3d*j3d*hh) + (i3d*jj) + ii_hflip;
                  set_value(tempS,pos,get_value(array,pos_flip));                  
              }
           }
        }
        else if (xy=='Y'){
           for (jj=j3d-1;jj>=0;jj--){   
	      for (ii=i3d-1;ii>=0;ii--){
                  pos=(i3d*j3d*hh) + (i3d*jj) + ii;
		  jj_hflip=j3d-1-jj;
                  pos_flip=(i3d*j3d*hh) + (i3d*jj_hflip) + ii;
                  set_value(tempS,pos,get_value(array,pos_flip));
              }
           }
        }
     }
     memmove(array,tempS,bytesL);
     free(tempS);
     return(array);
}

/*************** spin 3d, Sept 04 ***************/
char* v_spin_array_3d(char *array){

 signed int ii,jj,hh,ni,nj,ni3d,nj3d;
 unsigned int newpos,oldpos,pos;
 char *tempS;

        if ((tempS=(char*)calloc(bytesL,sizeof(char)))
				 ==NULL) outof_memory("tempS");  
    
	/*spin 90 degrees about vertical axis
          if horiz plane is not square, right or near square only is spun*/

        ni3d=i3d;      
        nj3d=j3d;
        if (i3d>j3d) ni3d=j3d;      
        else if (j3d>i3d) nj3d=i3d;

        for (hh=h3d-1;hh>=0;hh--){
	   for (jj=nj3d-1;jj>=0;jj--){      
	      for (ii=ni3d-1;ii>=0;ii--){
                  ni=nj3d-1-jj;
                  nj=ii;
                  /*in case i3d != j3d*/
                  if (ni<=i3d-1 && ni>=0 && nj<=j3d-1 && nj>=0){
                     newpos=(i3d*j3d*hh) + (i3d*nj) + ni;
                     oldpos=(i3d*j3d*hh) + (i3d*jj) + ii;
                     if (newpos<=L && oldpos<=L)       
                        set_value(tempS,newpos,get_value(array,oldpos));
                  }
	      }
	   }
        }
        
        for (hh=h3d-1;hh>=0;hh--){
	   for (jj=nj3d-1;jj>=0;jj--){      
	      for (ii=ni3d-1;ii>=0;ii--){
                 pos=(i3d*j3d*hh) + (i3d*jj) + ii;
                 set_value(array,pos,get_value(tempS,pos));
              }
           }
        }
        /*memmove(array,tempS,bytesL);*/
        free(tempS);
        return(array);
}


/***** rotate 3d left/right/up/downarray by rotinterval, 13 May 93 *****/
char* rotate_array_3d(char *array,
			 char direction,signed int rotinterval){

 signed int z1,ii,jj,hh,newii,newjj,newhh;
 unsigned int oldpos,newpos;
 char *tempS;

   for (z1=1;z1<=rotinterval;z1++){ 
           if ((tempS=(char*)calloc(bytesL,sizeof(char)))
				 ==NULL) outof_memory("tempS");      
	   /*rotate up*/
           for (hh=h3d-1;hh>=0;hh--){
              for (jj=j3d-1;jj>=0;jj--){
	         for (ii=i3d-1;ii>=0;ii--){
                    oldpos=(i3d*j3d*hh) + (i3d*jj) + ii;
                    if (direction=='l'){ /*left*/
                       newii=ii+1;
                       if (newii==i3d) newii=0;
                       newpos=(i3d*j3d*hh) + (i3d*jj) + newii;
                    }
                    else if (direction=='r'){ /*right*/
                       newii=ii-1;
                       if (newii<0) newii=i3d-1;
                       newpos=(i3d*j3d*hh) + (i3d*jj) + newii;
                    }
                    else if (direction=='b'){ /*back*/
                       newjj=jj+1;
                       if (newjj==j3d) newjj=0;
                       newpos=(i3d*j3d*hh) + (i3d*newjj) + ii;
                    }
                    else if (direction=='f'){ /*front*/
                       newjj=jj-1;
                       if (newjj<0) newjj=j3d-1;
                       newpos=(i3d*j3d*hh) + (i3d*newjj) + ii;
                    }
                    else if (direction=='u'){ /*up*/
                       newhh=hh+1;
                       if (newhh==h3d) newhh=0;
                       newpos=(i3d*j3d*newhh) + (i3d*jj) + ii;
                    }
                    else if (direction=='d'){ /*down*/
                       newhh=hh-1;
                       if (newhh<0) newhh=h3d-1;
                       newpos=(i3d*j3d*newhh) + (i3d*jj) + ii;
                    }                    
                    if (value_range==2){
                         set_bit(tempS,newpos,get_bit(array,oldpos));
                    }
                    else set_value(tempS,newpos,get_value(array,oldpos));
                 }
              }
           }
           memmove(array,tempS,bytesL);
           free(tempS);
   }
   return(array);
}

/********* rotation equivelents in attractor cycle, 13 May 93 ************/
signed int rot_cycle_equiv(register char *array){

 signed int z,z0,repseg;

 /* 	given 1 cycle state and period.
	computes 1. segment repeats.
		 2. equivalent cycle states.
		 3. no of equivalent basins=repseg/cyclematch */

   /*length of repeating segments in circular bit string*/
   repseg=repeating_seg(array);

   /*check no of occurances of rotation equivalents in cycle*/
   cyclematch=1;
   memmove(rot,array,bytesL);
   for (z=2;z<=attperiod;z++){
      for (z0=1;z0<=repseg;z0++){
	 if (z0!=1){ /*miss out first=same*/
	    /*if repeat found*/
	    if (memcmp(att[z],rot,bytesL)==0) cyclematch+=1;
	 }
	 rotate_array(nhood,rot,'l',0,1);
      }
   }
   return(cyclematch);
}

/********* rotation equivelents in 2-d attractor cycle, Oct 94 ************/
char rot_cycle_equiv_2d(register char *array){

 signed int z,z0,diag;
 char hv_rot_equal=0;

   repeating_seg_2d(array);
   if (/*i2d==j2d &&*/ repseg_2d[0]>1 && repseg_2d[1]>1)
				    hv_rot_equal=trans_sym_2d(array);
   /*
   if (repseg_2d[0]>1 && repseg_2d[1]>1
		   && (repseg_2d[0]==i2d || repseg_2d[1]==j2d))
				    hv_rot_equal=trans_sym_2d(array);
   */
   cyclematch_2d[0]=1;/*horizontal rotations*/
   cyclematch_2d[1]=1;/*vertical rotations*/


   memmove(rot,array,bytesL);
   for (z=2;z<=attperiod;z++){
      for (z0=1;z0<=repseg_2d[0];z0++){
	 if (z0!=1){ /*miss out first=same*/
	    /*if repeat found */
	    if (memcmp(att[z],rot,bytesL)==0) cyclematch_2d[0]+=1;
	 }
	 rotate_array_2d(rot,'l',1);
     }
   }

   memmove(rot,array,bytesL);
   for (z=2;z<=attperiod;z++){
      for (z0=1;z0<=repseg_2d[1];z0++){
	 if (z0!=1){ /*miss out first=same*/
	    /*if repeat found*/
	    if (memcmp(att[z],rot,bytesL)==0) cyclematch_2d[1]+=1;
	 }
	 rotate_array_2d(rot,'u',1);
      }
   }

   /*if square grid, check diagonal pos and neg, ie / and \ */
   cyclematch_2d_diag[0]=0;
   cyclematch_2d_diag[1]=0;

   if (hv_rot_equal==0 && i2d==j2d
    && repseg_2d[0]>1 && repseg_2d[0]==repseg_2d[1]
     && !(cyclematch_2d[0]==(unsigned int)repseg_2d[0] 
        || cyclematch_2d[1]==(unsigned int)repseg_2d[1])){

      for (diag=0;diag<=1;diag++){
	 memmove(rot,array,bytesL);
	 cyclematch_2d_diag[diag]=1;
	 for (z=2;z<=attperiod;z++){
	    for (z0=1;z0<=repseg_2d[0];z0++){
	       /*
	       memory_box(0,NULL);
	       moveto((signed int)((float)Maxx)/3+2,4);
	       print_current_state_twod(att[z],white,1);
	       moveto(getx+15,4);
	       print_current_state_twod(rot,white,1);
	       */
	       if (z0!=1){ /*miss out first=same*/
		  /*if repeat found*/
		  if (memcmp(att[z],rot,bytesL)==0)

		  cyclematch_2d_diag[diag]+=1;
		  /*
		  sprintf(textb[0],"dg[%d]=%d",
				  diag,cyclematch_2d_diag[diag]);

		  moveto(getx+15, 2);
		  outtext(textb[0]);
		  */
	       }
	       /*getch();*/

	       if (diag==0) rotate_array_2d(rot,'r',1);
	       else rotate_array_2d(rot,'l',1);
	       rotate_array_2d(rot,'u',1);
	    }
	 }
       }
       if (cyclematch_2d_diag[0]!=(unsigned int)repseg_2d[0]) 
                                           cyclematch_2d_diag[0]=0;
       if (cyclematch_2d_diag[1]!=(unsigned int)repseg_2d[0]) 
                                           cyclematch_2d_diag[1]=0;
   }
   return(hv_rot_equal);
}

/************ computes segment repeats in state, 13 May 93 *************/
signed int repeating_seg(register char *array){

 unsigned int z,

   rotmatch=0,/*degree of rot sym in bit hoop, max=lineL, min=1*/
   repseg=0;/*length of repeating segments in bit hoop (lineL/rotmatch)*/

   memmove(rot,array,bytesL);
   rotmatch=1;
   for (z=0;z<=L;z++){
      if (z!=0){  /*miss out first=same*/
	 /*if repeat found*/
	 if (memcmp(rot,array,bytesL)==0) rotmatch+=1;
      }
      rotate_array(nhood,rot,'l',0,1);
   }
   repseg=lineL/rotmatch; /*min length of repeating segments         */
			  /*all 0s,1s, ..repseg=1,  01,01..repseg=2  */
			  /*nomatch,..repseg=L, rotmatch=1           */
   return(repseg);
}

/********* rotation equivelents in 2-d attractor cycle, Oct 94 ************/
void repeating_seg_2d(register char *array){

 signed int z,
	      rotmatch_2d;/*degree of rot sym max=i2d or j2d min=1*/

   memmove(rot,array,bytesL);

   rotmatch_2d=1;
   for (z=0;z<=i2d-1;z++){
      if (z!=0){  /*miss out first=same*/
	 /*if repeat found*/
	 if (memcmp(rot,array,bytesL)==0) rotmatch_2d+=1;
      }
      rotate_array_2d(rot,'l',1);
   }                             /*min width of trans req to retun to start*/
   repseg_2d[0]=i2d/rotmatch_2d; /*usualy=min number of repeating columns*/
				 /*nomatch,..repseg_2d[0]=i2d, all =1*/
   rotmatch_2d=1;
   for (z=0;z<=j2d-1;z++){
      if (z!=0){  /*miss out first=same*/
	 /*if repeat found*/
	 if (memcmp(rot,array,bytesL)==0) rotmatch_2d+=1;
      }
      rotate_array_2d(rot,'u',1);
   }                             /*min height of trans req to retun to start*/
   repseg_2d[1]=j2d/rotmatch_2d; /*usualy=min number of repeating rows*/
				 /*nomatch,..repseg_2d[1]=j2d, all same=1*/
}

/********* 2d, check if horiz=vert translation, Oct 94 ************/
char trans_sym_2d(register char *array){

 char *rot1,*rot2,hv_rot_equal=0;

   /*if i2d=j2d, check if horiz=vert translation, ie up=right or left*/
   sprintf(textb[0],"rot1,2");
   if ((rot1=(char *)calloc(bytesL,sizeof(char)))
					    ==NULL) outof_memory(textb[0]);
   if ((rot2=(char *)calloc(bytesL,sizeof(char)))
					    ==NULL) outof_memory(textb[0]);
   memmove(rot,array,bytesL);
   memmove(rot1,array,bytesL);
   memmove(rot2,array,bytesL);
				 /*     o     */
   rotate_array_2d(rot,'u',1);   /*     o     */
   rotate_array_2d(rot1,'l',1);  /*     *     */
   rotate_array_2d(rot2,'r',1);  /* ooo*o*ooo */

   if ((memcmp(rot,rot1,bytesL)==0 || memcmp(rot,rot2,bytesL)==0)){
      repseg_2d[0]=1;
      hv_rot_equal=1;
   }

   else if (i2d>3 && i2d%2==0){
      /*translate one more, ie 2 cells*/  /*     o     */
      rotate_array_2d(rot,'u',1);         /*     *     */
      rotate_array_2d(rot1,'l',1);        /*     o     */
      rotate_array_2d(rot2,'r',1);        /*  o*ooo*o  */
      if ((memcmp(rot,rot1,bytesL)==0 ||
		       memcmp(rot,rot2,bytesL)==0)){
	 repseg_2d[0]=2;
	 hv_rot_equal=1;
      }
   }
   /*even arrays only from now on*/
   if (hv_rot_equal==1 || (i2d%2!=0 || i2d%2!=0)) goto end;

   if (j2d>3 && repseg_2d[1]==j2d){
	 memmove(rot1,array,bytesL); /*restor arrays*/
	 memmove(rot2,array,bytesL);
	 rotate_array_2d(rot1,'r',1);
	 rotate_array_2d(rot2,'u',2);
						 /*  o    */
	 if (memcmp(rot1,rot2,bytesL)==0){       /*  *    */
	    repseg_2d[0]=1;                      /*  o    */
	    hv_rot_equal=1;                      /*  o*oo */
	    goto end;
	 }
   }
   if (i2d>3 && repseg_2d[0]==i2d){
	    memmove(rot1,array,bytesL); /*restor arrays*/
	    memmove(rot2,array,bytesL);
	    rotate_array_2d(rot1,'l',2);
	    rotate_array_2d(rot2,'u',1);		/*    o	 */
	    if (memcmp(rot1,rot2,bytesL)==0){           /*    o  */
	       repseg_2d[1]=1;                          /*    *  */
	       hv_rot_equal=1;                          /* o*oo  */
	    }
   }
  end:
   free(rot1);
   free(rot2);
   return(hv_rot_equal);
}

/*************************************************************************/








