/*
 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/>.
 */

/***************** run backwards, compute pre-images ************/
#include "edecfunc.h"
/***************  list of functions in this file *************/
/*void show_statespace_matrix(char *thisstate)*/
/*void run_backward(void)*/
/*void back_onthefly_prompts(void);*/
/*void prestate_successor_pairs(void)*/
void pre_exhaustive(void);
void pre_neutral(void);
/*void prepair_pre_rand(void*/
void rearrange_cell_order(void);
/*void free_pre_rand(void)*/
/*void pre_images_rand(void)*/
void pre_images_binary(void);
void pre_images_multi_state(void);
char check_pre_image(char *pre_state);
void accept_pre_image(char *pre);
void interrupt_pre_fan(void);
/*void setup_ppstack_hist(void)*/

/*computing pre-images for random wiring*/
char
      ***PS,    /*[tog][Pscount][char array]....partial pre-image 0,1*/
      ***PSflag, /*parrallel array, flags if bit was set=1, empty=0*/
      *PStemp,
      *flagtemp,
      **nhoodE,   /*reduced effective nhood*/
      **skiptable, /*skip rule table entry because nhood reduced*/
      *stateB,    /*previous state in rev alg, was in eglob_ab.h*/
      stateB_extra; /*extra bytes at each end of stateB, 1 if k<=16, else 2.
		       (so total 2 or 4) stateB_extra.L...0.stateB_extra */

unsigned long  
      *PScount; /*count of partial pre-images in toggled stacks*/
 
char attrepeat, /*1 if pre_image on attractor cycle*/
     **preim0, /*pointer to pointers to preimages*/
     **preim1, /*toggle 2 arrays this<-->next*/
     *arule,     /*array for any size nhood rule in backwards proc.*/
     *arule1,     /*another...*/
     *arule2,     /*another......*/
     *pre_start;     /*start string assumed for goback*/

signed int *cell_order;
char abort_subtree=0; /*if nextindex>Maxu, 4294967295 (unsigned long)*/
char allbitssame; /*1 for all values, else 0*/

/*** mark each state on grid, 1/2 bits (or more)=y, 1/2 bits (or less)=x ***/
void show_statespace_matrix(char *thisstate){
 signed int z,zz,yL,xL,
	      tempx,tempy,
	      mright,mbot,mleft,mtop,   /*  0_______   plot the string */
	      mwidth,mheight;           /* 0|       |  (8)7654-3210    */
					/*  |       |  on 2-d grid     */
 double	sx,/*x pos of state on grid*/   /*  |       |                  */
	sy,/*y poss "     "        */   /*  |       |3210              */
	sq;/*size of square block  */   /*  |       |                  */
 unsigned long thisx=0,/*x value   */	/*  |_______|                  */
	       thisy=0,/*y value   */   /*   (8)7654                   */
               max_Length;

   /*matrixx,matrixy must be global variables*/

   tempx=getx;
   tempy=gety;

   if (show_ss_matrixF){
      mright=Maxx-vgax(136);
      mbot=Maxy-2;
   }
   else{
      mright=Maxx-2;
      mbot=Maxy-vgay(31);
   }   
   mwidth=mheight=msize;

   if (lineL%2==0) mtop=mbot-mheight;
   //else mtop=mbot-mheight/2;
   else mtop=mbot-mheight/value_range;
   mleft=mright-mwidth;
   
   max_Length=maxL_lu;
   
   if (lineL>=max_Length*2) yL=xL=max_Length/2;
   else{
      if (lineL%2==0) yL=xL=lineL/2-1;
      else{
	 yL=lineL/2-1;
	 xL=lineL/2;
      }
   }
 
   /*set up the window for grid*/
   if (thisstate==NULL){     

      if (show_ss_matrixF) matrixcolor=yellow;
      draw_box(-1,mleft-1,mtop-1,mright,mbot,1,0);
      matrixx=matrixy=0; /*max x,y axis*/

      zz=0;
      for (z=lineL/2-1;z>=0;z--){
         
	 matrixy+=(value_range-1)*
                 (unsigned long)pow(value_range,(double)(yL-zz));
	 zz++;
	 if (zz>max_Length/2) break;
      }
      zz=0;
      for (z=lineL-1;z>=lineL/2;z--){
	 matrixx+=(value_range-1)*
                  (unsigned long)pow(value_range,(double)(xL-zz));
	 zz++;
	 if (zz>max_Length/2) break;
      }
   }
   else{
      zz=0;
      for (z=lineL/2-1;z>=0;z--){
         if (value_range==2){
	    thisy+=(unsigned long)get_bit(thisstate,z)*
			      pow(2,(double)(yL-zz));
         }
         else thisy+=(unsigned long)get_value(thisstate,z)*
			      pow(value_range,(double)(yL-zz));
	 zz++;
	 if (zz>max_Length/2) break;
      }
      zz=0;
      for (z=lineL-1;z>=lineL/2;z--){
         if (value_range==2){
	    thisx+=(unsigned long)get_bit(thisstate,z)*
				    pow(2,(double)(xL-zz));
         }
         else thisx+=(unsigned long)get_value(thisstate,z)*
				    pow(value_range,(double)(xL-zz));
	 zz++;
	 if (zz>max_Length/2) break;
      }

      sy=mtop+(double)(thisy*(mbot-mtop))/(matrixy+1);
      sx=mleft+(double)(thisx*(mright-mleft))/(matrixx+1);
      /*space for single pixels only*/
      if (matrixx>=mwidth) putpixel(sx,sy,matrixcolor);
      /*space for square bars*/
      else{
	 sq=(double)mwidth/(matrixx+1)-1;
	 setfillstyle(SOLID_FILL,matrixcolor);
	 bar(sx,sy,sx+sq,sy+sq);                     
         if (sq>textwidth(all_1s)+CWidth*1.5){
               sprintf(textb[0],"%lu",dec_equiv(thisstate,L)); 
	       moveto(sx+2,sy+2);	    
	       outtext(textb[0]);
         }	 
      }
   }
   moveto(tempx,tempy);
}

/******************* run backwards from seed, May 93 ***********/
void run_backward(void){
 unsigned int zu,zu1,count1s;
 unsigned long maxsubtreefan=0;
 signed int  z,zz,
      xbox,stpwidth,
      tempx,tempy,temphx,tempCWidth,tempCHeight,
      tablesize,tablebytes,
      barlen,  /*progress bar*/
      pre_equiv_no=0, /*no of rotation equivalent states*/
      thisbasinno,
      segsize;
 unsigned int z0,z1,cm_d;
 unsigned long actual_fansize=0;
 float gofEdensity;
 unsigned char tempcolor,tempcolor1;
 
# if __WATCOM__
     char temp_sfont;
# endif

# define free_rest {  free(preim1);\
		      free(preim0);\
		      free(xx0);   \
		      free(yy0);   \
		      free(xx1);   \
		      free(yy1);   \
		      if (exhaustive_testing==0 && nonlocal==0){\
			    free(arule);\
			    free(arule1);\
			    free(arule2);\
			    free(pre_start);\
			    free(stateB);  \
                            free(kv_out);\
                            free(kv_freq);\
                            free(next_right_stack);\
		      }\
  }

# define show_ss_state(ss_state) {\
	       if (show_ss_matrix){\
		  if (ss_m_att_only){\
		     if (precount==0) show_statespace_matrix(ss_state);\
		  }\
		  else if (!basinfield || successive_basins){\
		      if (precount==0) matrixcolor=lightred;\
		      else matrixcolor=green;\
		      show_statespace_matrix(ss_state);\
		  }\
		  else show_statespace_matrix(ss_state);\
	       }\
  }


  
  /*draw box to show partial pre-image stack size*/
  if (nonlocal==0 && !nhood_mixed){
     if (see_ppstack){  /*decrease bar showing pp stack*/    
       setcolor(white);       
#      if __UNIX__
	 rectangle(vgax(125),Maxy-vgay(41),vgax(125)+vgax(150),Maxy-vgay(33));
#      elif __WATCOM__
	 rectangle(vgax(140),Maxy-vgay(41),vgax(140)+vgax(150),Maxy-vgay(33));
#      endif
     }
  }
  
  pretested=precount=totalprecount=gofEno=totalgofE=0;
  level=0;     /*current level*/
  /*adjust level for segfan*/
  if (startsegfan==1){
	level=1;
	if (justonepreimage==1) level=2;
  }
  abort_subtree=0;
  is[0]=0; /*to avoid early exit*/
  thisindex=0; /*index in current level*/
  nextindex=0; /*index in next level*/
  thismax=0;   /*no of states in current level, level 0 has 1 seed state*/
  nextmax=0;   /*         next    */
  /*thisstart=0;*/ /*total count of first state in current level*/
  pretog=0;    /*toggle for 2 arrays this<-->next*/
  segfan=0;
  if (scale>vgax(3)) sep=2;
  else sep=1;
  if (scale==1) sep=0;
  early_exit_draw_fan=0; //for istr_graph early exit 

  /*size of rule table in bits/values*/
  tablesize=(signed int)pow(value_range,(double)nhood);
  tablebytes=(signed int)ceil(((double)(value_bits * tablesize))/8);
  if (tablebytes==0) tablebytes=1;
  if (nhood<=16) stateB_extra=1; // extra bytes at each end of stateB
  else stateB_extra=2;

  sprintf(textb[0],"run backwards arrays");
  if (exhaustive_testing==0 && nonlocal==0 ){
     /*3 arrays to hold rule/s*/
     if ((arule=(char *)calloc(tablebytes,sizeof(char)))
				 ==NULL) outof_memory(textb[0]);
     if ((arule1=(char *)calloc(tablebytes,sizeof(char)))
				 ==NULL) outof_memory(textb[0]);
     if ((arule2=(char *)calloc(tablebytes,sizeof(char)))
				 ==NULL) outof_memory(textb[0]);
     
     if ((pre_start=(char*)calloc(nhood,sizeof(char)))
                        ==NULL) outof_memory(textb[0]);

     if ((stateB=(char*)calloc((bytesL+2*stateB_extra)*value_bits,sizeof(char)))
       ==NULL) outof_memory(textb[0]);
     if ((kv_out=(char*)calloc(value_range,sizeof(char)))
				 ==NULL) outof_memory(textb[0]);
     if ((kv_freq=(char*)calloc(value_range,sizeof(char)))
				 ==NULL) outof_memory(textb[0]);
     if ((next_right_stack=(char*)calloc(value_range,sizeof(char)))
				 ==NULL) outof_memory(textb[0]);
  }
  
  if ((preim0=(char**)calloc(1,sizeof(char*)))
				     ==NULL) outof_memory(textb[0]);
  if ((preim1=(char**)calloc(1,sizeof(char*)))
				     ==NULL) outof_memory(textb[0]);
  if ((xx0=(signed int*)calloc(1,sizeof(signed int)))
				     ==NULL) outof_memory(textb[0]);
  if ((yy0=(signed int*)calloc(1,sizeof(signed int)))
				     ==NULL) outof_memory(textb[0]);
  if ((xx1=(signed int*)calloc(1,sizeof(signed int)))
				     ==NULL) outof_memory(textb[0]);
  if ((yy1=(signed int*)calloc(1,sizeof(signed int)))
				     ==NULL) outof_memory(textb[0]);
  isrepeat=0;
  precount=0;

 startback:
  nextbefore=nextindex;
  if (precount>0){
     if (pretog){
	memmove(state1,preim1[thisindex],bytesL);
	free(preim1[thisindex-1]);/*deallocate previous*/
     }
     else{
	memmove(state1,preim0[thisindex],bytesL);
	free(preim0[thisindex-1]);/*deallocate previous*/
     }
  }
  else memmove(state1,firstseed,bytesL);
  
  if (stp){
    end_page(scale,0);
     print_current_state(state1,white);
  }
  /*count states with majority of given a value (Raja's rule)*/
  if (show_maj>=0){
       count1s=0;
       for (zu=0;zu<=L;zu++){
	  if (get_value(state1,zu)==show_maj) count1s+=1;
       }
  }

  /*if drawing basin field, tick off used states*/
  /* tickspace=lineL^value_range */
  if (basinfield || show_ss_matrix){
     if ((nonlocal==0 || compress_1d_local==1 || regular2d)
	&& !dontcompress && !rulemix && exhaustive_testing!=2 
	            && NULLboundaries==0){ //compress basins
	memmove(tempState,state1,bytesL);
	//?? fprintf(stderr,"\n state1= %lu",dec_equiv(tempState,L));
	/*count segmented states*/
	/*issegstate=0;*/
	if (regular2d){
	   
	   /*if (repseg_2d[0]<lineL || repseg_2d[1]<lineL) issegstate=1;*/
	   if (insegloop){
	     //?? fprintf(stderr,"\ntest01?? insegloop=%d seg_2d_h[%d]=%d seg_2d_v[%d]=%d",
	     //?? insegloop,segindex,seg_2d_h[segindex],segindex,seg_2d_v[segindex]);
	      for (z=1;z<=seg_2d_h[segindex];z++){
		 for (zz=1;zz<=seg_2d_v[segindex];zz++){
		     if (basinfield && dec_equiv(tempState,L)<=tickspace)
		          set_bitlong(tickoff,dec_equiv(tempState,L),1);
		     show_ss_state(tempState);
		     //?? fprintf(stderr," %lu",dec_equiv(tempState,L));
		     progbar+=1;
		     rotate_array_2d(tempState,'u',1);
		 }
		 rotate_array_2d(tempState,'l',1);
	      }
	   }
	   else if (attperiod==0){
	      if (basinfield && dec_equiv(tempState,L)<=tickspace)
		          set_bitlong(tickoff,dec_equiv(tempState,L),1);
	      //?? fprintf(stderr,"\ntest02?? attperiod=%lu", attperiod);
	      show_ss_state(tempState);
	   }
	   else {
	      if (cyclematch_2d_diag[0]>1 || cyclematch_2d_diag[1]>1){
		 //?? fprintf(stderr,"\ntest03?? cyclematch_2d_diag %d,%d",
			      //?? cyclematch_2d_diag[0],cyclematch_2d_diag[1]);
		 if (cyclematch_2d_diag[0]>1)
			      cm_d=cyclematch_2d_diag[0];
		 else if (cyclematch_2d_diag[1]>1)
			      cm_d=cyclematch_2d_diag[1];
		 for (z=1;z<=basinno;z++){
		    for (z0=1;z0<=cm_d;z0++){
		       if (basinfield && dec_equiv(tempState,L)<=tickspace)
			  set_bitlong(tickoff,dec_equiv(tempState,L),1);
		       show_ss_state(tempState);
		       progbar+=1;
		       if (cyclematch_2d_diag[0]>1)
			   rotate_array_2d(tempState,'r',1);
		       else rotate_array_2d(tempState,'l',1);
		       rotate_array_2d(tempState,'u',1);
		    }
		    rotate_array_2d(tempState,'l',1);
		 }
	      }
	      else{
		 //?? fprintf(stderr,"\ntest04?? cyclematch_2d %d,%d",
			 //?? cyclematch_2d[0],cyclematch_2d[1]);
		 for (zu=1;zu<=cyclematch_2d[0];zu++){
		    /*if (issegstate) segstates+=1;*/
		    for (zu1=1;zu1<=cyclematch_2d[1];zu1++){
		       if (basinfield && dec_equiv(tempState,L)<=tickspace)
			   set_bitlong(tickoff,dec_equiv(tempState,L),1);
		       show_ss_state(tempState);
		       memmove(tempState2,tempState,bytesL);

		       for (z0=1;z0<=basinno_2d_h;z0++){
			  /*if (issegstate) segstates+=1;*/
			  for (z1=1;z1<=basinno_2d_v;z1++){
			     if (z0==1 && z1==1) continue;
			     /*if (issegstate) segstates+=1;*/
			     rotate_array_2d(tempState2,'u',1);
			     if (basinfield &&
				dec_equiv(tempState2,L)<=tickspace)
			       set_bitlong(tickoff,dec_equiv(tempState2,L),1);
			     show_ss_state(tempState2);
			     progbar+=1;
			  }
			  rotate_array_2d(tempState2,'l',1);
		       }

		       progbar+=1;
		       rotate_array_2d(tempState,'u',basinno_2d_v);
		    }
		    rotate_array_2d(tempState,'l',basinno_2d_h);
		 }
	      }
	   }
	}//end if (regular2d)
	
	/*---------------------compress_1d_local--------------------------*/
	else{
	   /*if (repeating_seg(tempState)<lineL) issegstate=1;*/
	   if (insegloop){
	      for (z=1;z<=seg[segindex];z++){
		 /*if (issegstate) segstates+=1;*/
		 rotate_array(nhood,tempState,'l',0,1);
		 if (basinfield && dec_equiv(tempState,L)<=tickspace)
			   set_bitlong(tickoff,dec_equiv(tempState,L),1);
		 show_ss_state(tempState);
		 progbar+=1;
	      }
	   }
	   else if (attperiod==0){
	      show_ss_state(tempState);
	   }
	   else {
	      for (zu=1;zu<=cyclematch;zu++){
		 /*if (issegstate) segstates+=1;*/
		 rotate_array(nhood,tempState,'l',0,basinno);
		 if (basinfield && dec_equiv(tempState,L)<=tickspace)
			   set_bitlong(tickoff,dec_equiv(tempState,L),1);
		 show_ss_state(tempState);
		 memmove(tempState2,tempState,bytesL);

		 for (zz=1;zz<=basinno-1;zz++){
		    /*if (issegstate) segstates+=1;*/
		    rotate_array(nhood,tempState2,'l',0,1);
		    if (basinfield && dec_equiv(tempState2,L)<=tickspace)
			    set_bitlong(tickoff,dec_equiv(tempState2,L),1);
		    show_ss_state(tempState2);
		    progbar+=1;
		 }
		 progbar+=1;
	      }
	   }
	}//end compress_1d_local	
     }//end compress basins
     /*-----------------------not compressed---------------------*/
     else {
	if (basinfield && dec_equiv(state1,L)<=tickspace)
			  set_bitlong(tickoff,dec_equiv(state1,L),1);
        
	show_ss_state(state1);
	progbar+=1;
	//fprintf(stderr,"(%lu:%lu)",progbar,dec_equiv(state1,L)); //fprintf??
     }
     if (basinfield){
		setfillstyle(SOLID_FILL,green);
		barlen=(signed int)((float)(barxr-barxl-2)*
					  ((float)progbar/(statespace+1)));
		bar(barxl+1,baryt+vgay(2),barxl+barlen,baryb-vgay(2));
     }
  }//end (basinfield || show_ss_matrix)
  
  else show_ss_state(state1);


  /*if showing pre-image frequency histogram,
    count no of equivalent states, 
    or states with maj of given value -- highlighted in basinsor if */
  if (pre_fansize_freq_hist || show_maj>=0){
     if ((nonlocal==0 || compress_1d_local==1 || regular2d)
           && !dontcompress && !rulemix && exhaustive_testing!=2){
	if (!basinfield) thisbasinno=1;
	else thisbasinno=basinno;
	if (regular2d){
	   if (insegloop) pre_equiv_no=
			     seg_2d_h[segindex]*seg_2d_v[segindex];
	   else if (direction=='f') pre_equiv_no=cyclematch*thisbasinno;
	   else pre_equiv_no=1;
	}
	else{
	   if (insegloop) pre_equiv_no=seg[segindex];
	   else if (direction=='f') pre_equiv_no=cyclematch*thisbasinno;
	   else pre_equiv_no=1;
	}
     }
     else pre_equiv_no=1;
  }


  if (stp) end_page(scale,0);
  /*check if backwards seed is all 0s or 1s*/
  if ((nonlocal==0 || compress_1d_local==1 || regular2d)
	  && !dontcompress && !rulemix && exhaustive_testing!=2 
            && NULLboundaries==0){
     if (value_range==2){
        if (memcmp(all_0s,state1,bytesL)==0 ||
                 memcmp(all_1s,state1,bytesL)==0)
					 allbitssame=1;
        else allbitssame=0;
     }
     else{
       allbitssame=1;
       for (z=L;z>=1;z--){
	 if (get_value(state1,z)!=get_value(state1,z-1)){
            allbitssame=0;
            break;
         }
       }
     }
  }
  else allbitssame=0;

  /*interupt - only at new firstseed*/
  //the prompts are shown in the bottom title bar, code in "void back_onthefly_prompts(void)"
  //dont apply for jump_graph or ibaf_graph (inappropriate, and basins too small so no time to apply)
 early_exit:
  if (jump_graph==0 && ibaf_graph==0){
    if (event_ready() || (istr_graph==1 && early_exit_draw_fan==1)){
      float r; /*to change basin scale*/
      if (istr_graph==1 && early_exit_draw_fan==1){	
	//fprintf(stderr,"\n4:%d>%d early_exit_draw_fan:",istr_node_count,max_istr_node_no);
          is[0]='q'; //to interupt
      }	  
    tempcolor=getcolor();
    switch(is[0]){     
     case '<': /*alter pre-image speed slower*/
        if (pre_speed==0) pre_speed+=500;
        else pre_speed*=2;
        break;
     case '>': /*alter pre-image speed  max*/
        pre_speed=0;
        break;
     case 'P': /*see partial pre-image histogram on-the-fly*/
	if (nonlocal){
	   if (see_ppstack==0){
              see_ppstack=1;      
              /*rescale y axis smaller*/
              if (ppL==lineL && pp_hist_max < pp_ymax/6){
	         pp_ymax=pp_ymax*.75;
	         if (pp_ymax<10) pp_ymax=10;
	         ppL=0;
              }
              pp_hist_max=0;
              setup_ppstack_hist();
              sprintf(textb[0],"partial pre-image histogram: start pause-p");
	      draw_prompt_box(1);
	      outtext(textb[0]);
           }
           else if (see_ppstack==1){ 
              see_ppstack=0;
              erase_box(pp_startx0,pp_starty0-pp_depthy,
			     pp_startx0+pp_widthx,pp_starty0);
              erase_prompt_box(1);
           }              
	}
	break;
     /*partial pre-image histogram: start pause*/
     case 'p':
	if (see_ppstack==1 && nonlocal){
	   erase_prompt_box(1);
	   see_ppstack=2;
	}
	break;
     /*toggle state space matrix*/
     case 'm':
	if (show_ss_matrix==1){
	   draw_box(-1,Maxx-2-vgax(msize)-1,
	   Maxy-vgay(31)-vgay(msize)-1,Maxx-2,Maxy-vgay(31),0,0);	  
	   show_ss_matrix=0;
	}
	else{
	   show_ss_matrix=1;
	   show_statespace_matrix(NULL);
	}
	break;
     /*expand basin scale*/
     case 'E':
        startrad*=1.1;
	demorad*=1.1;
        free(rad);
         if ((rad=(float*)calloc(lastlevel+1,sizeof(float)))
				  ==NULL) outof_memory("rad");
         for (z=1;z<=lastlevel;z++){    /*lastindex=lastlevel-1*/
            if (z==1) r=startrad;
            else r += (startrad/trans_shrink_fact)/log(pow(z,2));
            rad[z-1]=r;
         }
         break;
     /*contract basin scale*/
     case 'C':
        startrad*=.9;
	//fprintf(stderr,"\nstartrad=%f",startrad);
	if (startrad<220.0/Maxx){
	   startrad=220.0/Maxx;
	   break; /*limit contraction*/
	}  
	demorad*=.9;
        free(rad);
         if ((rad=(float*)calloc(lastlevel+1,sizeof(float)))
				  ==NULL) outof_memory("rad");
         for (z=1;z<=lastlevel;z++){    /*lastindex=lastlevel-1*/
            if (z==1) r=startrad;
            else r += (startrad/trans_shrink_fact)/log(pow(z,2));
            rad[z-1]=r;
         }
	 break;
	    
     /*expand space-time pattern scale*/
     case 'e':
	if (stp || shownumbers==3){
           /*first turn off scrolling __WATCOM__ */
           if (scrolling==1){
	      if (nowscrolling==1){
#         	  if __WATCOM__
		      freeimage(stpimage);
#                 endif
                  nowscrolling=0;
	       }
	   }     
	   scale+=1;
#          if __UNIX__
	      pixmap_width=lineL*scale;
#          endif
	   /*sep=2->1 pix div, sep=1-> no div*/
	   if (scale>vgax(3)) sep=2;
	   else sep=1;
	}
	break;
     /*contract space-time pattern scale*/
     case 'c':
	if (stp || shownumbers==3){
	   /*first turn off scrolling __WATCOM__ */
           if (scrolling==1){
	      if (nowscrolling==1){
#         	  if __WATCOM__
		      freeimage(stpimage);
#                 endif
                  nowscrolling=0;
	       }
	   }           
	   stpwidth=lineL*scale;
	   scale-=1;
	   if (scale<=0){
	      scale=1;
	      break;
	   }
	   if (stp){
	      setfillstyle(SOLID_FILL,black);
	      bar(lineL*scale,0,stpwidth,Maxy);
	   }
#          if __UNIX__
	      pixmap_width=lineL*scale;
#          endif
	   /*sep=2->1 pix div, sep=1-> no div*/
	   if (scale>vgax(3)) sep=2;
	   else sep=1;
	}
	break;
	
     case'#':/*toggle scrolling*/
	if (stp){
	   if (scrolling==1){
	      scrolling=0;
              if (nowscrolling==1){
#                if __WATCOM__
		    freeimage(stpimage);
#                endif
              }
	      stpwidth=lineL*scale;
#             if __UNIX__
		 pixmap_width=lineL*scale;
#             endif
	      /*clear area of screen*/
	      setviewport(0,0,stpwidth,Maxy,1);
	      clearviewport();
	      setviewport(0, 0, Maxx, Maxy, 1);
	   }
	   else scrolling=1;
           nowscrolling=0;
           /*fprintf(stderr,"\n scrolling=%d",scrolling);*/
	}
	break;
     case 's': /*toggle showing space-time patterns*/
	if (stp==1){
	   stp=0;
           /*clear area of screen*/
           stpwidth=lineL*scale;
#          if __UNIX__
		 pixmap_width=lineL*scale;
#          endif
	   setviewport(0,0,stpwidth,Maxy,1);
	   clearviewport();
	   setviewport(0, 0, Maxx, Maxy, 1);
	}
	else if (stp==0) stp=1;
	break;

     case'q':
	tempx=getx;
	tempy=gety;
	tempcolor1=getcolor();
	setcolor(white);
       startinterrupt:
        sprintf(textb[1],"level=%u, incomplete tree=%lu",level,precount+1);
	if (istr_graph && early_exit_draw_fan==1) sprintf(textb[0],
	     "draw incomplete istr-graph with %d nodes-ret:",istr_node_count);//or any key
	else{
	   if (basinfield) sprintf(textb[0],
	      "next-tree/basin-n options-o stopfield-q speed-V cont-ret:");
  	   else if (direction!='b') sprintf(textb[0],
	      "next-tree-n options-o stopbasin-q speed-V cont-ret:");
	   else if (direction=='b')sprintf(textb[0],
	      "options-o stopsubtree-q speed-V cont-ret:");
        }
	xbox=draw_prompt_box(2);
        outtext(textb[1]);
        moveto(xbox,gety+CHeight);
	if (pre_fansize_freq_hist) outtext("inhist-h ");
	outtext(textb[0]);
	input_string(1,0);
	erase_prompt_box(2);
	if (istr_graph && early_exit_draw_fan==1) is[0]='q'; //any input: draw istr_graph
	
        if (is[0]=='V'){
	   if (slowfactor==0) slowfactor=33000;
           draw_prompt_box(1);
	   sprintf(textb[0],
               "speed: max-m, or slowmotion (now %d):",slowfactor);
	   outtext(textb[0]);
	   input_string(6,0);
           if (is[0]=='m') pre_speed=0;
           else{ 
              if (is[0]==13) pre_speed=slowfactor*500;
              else if (atol(is)>1){ 
                 slowfactor=atol(is);
                 pre_speed=slowfactor*500;
              }
           }
           setcolor(tempcolor1);
	   goto startinterrupt;
        }
	else if (is[0]=='o'){
         char CA_1d=0;
         unsigned int thisposs;
	   basin_not_complete=1;/*to prevent changes to network*/
           if (nonlocal==0) CA_1d=1;
	   finish_options(1);
           if (CA_1d==1){ /*restor local 1d wiring, otherwise seg fault*/
              nonlocal=0;
              for (thisposs=lineL-1;thisposs!=Maxu;thisposs--)
		    oneD_local_wire_cell(thisposs,lineL-1);
           }
	   setcolor(tempcolor1);
           basin_not_complete=0;
	   goto startinterrupt;
	}
	else if (is[0]=='h' && pre_fansize_freq_hist){
	   show_pre_fansize_freq_hist();
	   setcolor(tempcolor1);
	   goto startinterrupt;
	}
	if (is[0]=='q' || is[0]=='n'){	  
	   if (pretog){
	      for (zu=thisindex;zu<=thismax;zu++) free(preim1[zu]);
	      for (zu=1;zu<=nextmax;zu++) free(preim0[zu]);
	   }
	   else{
	      for (zu=thisindex;zu<=thismax;zu++) free(preim0[zu]);
	      for (zu=1;zu<=nextmax;zu++) free(preim1[zu]);
	   }
	   free_rest;
	   treesize=precount+1;
	   thisindex=nextindex=precount=0;
           pretested=0;
	   /*next tree space-time pattern from the top*/
	   if (stp){
	      setviewport(0, 0, (L+1)*scale+2, Maxy, 1);
	      clearviewport();
	      setviewport(0, 0, Maxx, Maxy, 1);
	      moveto(0,0);
	   }

           /*show various onthefly prompts (also in main)*/
	   if (is[0]=='n') back_onthefly_prompts();
	   earlyexit=1;
	   /*memory_box(1,NULL);*/
	   setcolor(tempcolor1);
	   return;
	}
        if (exhaustive_testing==0) back_onthefly_prompts(); /*done in pre_exhaustive(*/
	if (stp) end_page(scale,0);
	if (basinfield) progress_bar(); /*redraw progbar box*/
	moveto(tempx,tempy);
	setcolor(tempcolor1);
    }//end switch 
    setcolor(tempcolor);
   }//end event_ready
  }//end if (jump_graph==0 && ibaf_graph==0)
  
  is[0]=0;
  /*no of segments in pre-image fan from all 0s and 1s*/
  if (insegloop==0) segno=0;

  /*added to keep track of states -- 
      this is the root of the subtree about to be computed*/
  //fprintf(stderr,"\n(%lu)",dec_equiv(state1,L));

  /*-----------------------start finding pre-image fan--------------------*/
  if (neutral_order==1) pre_neutral(); //neutral order components
  else if (exhaustive_testing) pre_exhaustive();//exhaustive pairs, works for NULLb 
  else if (nonlocal==1) pre_images_rand();//random (non-local) wiring algorithm
  else{//for 1d  CA (inc rulemix) reverse algorithm, but not k-mix
       //assumed start strings for each pre-image fan

    char countN=0, nhood_too_big=0;//for NULLb and nhood>lineL

     if (nonlocal==0 && !nhood_mixed){
       signed int outside_state, //inputs outside the left boundary
                  count_zz; 
        
       //fprintf(stderr,"\n************************************");
       if (NULLboundaries==1 && nhood>1 && oned /*&& nhood>2*/){
	   if (nhood%2==1) outside_state=nhood/2; //odd nhood
	   else outside_state=nhood/2-1; //even nhood
           
           count_zz=(signed int)pow(value_range,
                       (double)nhood-1-outside_state)-1;            
        }
        else count_zz=(signed int)pow(value_range,(double)nhood-1)-1;
        //fprintf(stderr,"\ncount_zz=%d:",count_zz);
        //input_string(1,0);

	for (zz=0;zz<=count_zz;zz++){
	   countN=nhood_too_big=0;

	   //fprintf(stderr,"\nzz=%d:",zz);
	   for (z=nhood-2;z>=0;z--){

	      if (NULLboundaries==1){
                countN+=1;
               
	        if (nhood>lineL && countN > outside_state+lineL && get_value(nm[z],zz)>0){ 
		   nhood_too_big=1;
                   break;
                }                 
              }

              if (value_range==2) pre_start[z] = get_bit(nm[z],zz);
              else pre_start[z] = get_value(nm[z],zz);
              //fprintf(stderr,"%d",pre_start[z]);                   
           }
           if (nhood_too_big==1) continue;

	   if (value_range==2) pre_images_binary();
           else pre_images_multi_state();
           //input_string(1,0);
	}
     }
  }
  /*-----------------------conclude finding pre-image fan--------------------*/
  
  /*abort subtree if nextindex>Maxu, 4294967295 (unsigned long)*/
  if (abort_subtree==1){
     /*if (show_one_att_state){
        draw_att_state(1); 
     }*/
     draw_prompt_box(1);
     sprintf(textb[0],
        "\n nextindex=%lu, too many pre-images subtree level %d, abort-ret",
                                         nextindex,level);
     outtext(textb[0]);
     input_string(1,0);
     is[0]='q';
     return;
  }

  if (is[0]=='q' || is[0]=='n'){
     if (pretog){
	for (zu=thisindex;zu<=thismax;zu++) free(preim1[zu]);
	for (zu=1;zu<=nextindex;zu++) free(preim0[zu]);
     }
     else{
	for (zu=thisindex;zu<=thismax;zu++) free(preim0[zu]);
	for (zu=1;zu<=nextindex;zu++) free(preim1[zu]);
     }
     free_rest;
     treesize=precount+1;
     thisindex=nextindex=pretested=precount=0;
     if (direction=='b') segfan=0;
     memory_box(0,NULL);
     return;
  }

  /*if just one pre-image from point attractior*/
  /*this is only allowed once, otherwise level problems in multi_value*/
  //if (justonepreimage_found==0 && value_range>2){ //caused equv to fail
  if (justonepreimage_found==0){
   if (segfan &&
       (!nonlocal || compress_1d_local==1 || regular2d)
	     && !dontcompress && !rulemix && exhaustive_testing!=2
                                 && NULLboundaries==0){
     if (regular2d && segno==1 && seg_2d_h[1]==1 && seg_2d_v[1]==1){
	seg_2d_h[1]=seg_2d_v[1]=0;
        sprintf(textb[0],"realloc-seg_2d,segseed");
	if( (seg_2d_h=(signed int*)realloc
	   (seg_2d_h, sizeof(signed int)))
	       ==NULL) outof_memory(textb[0]);
	if( (seg_2d_v=(signed int*)realloc
	   (seg_2d_v, sizeof(signed int)))
	       ==NULL) outof_memory(textb[0]);
	free(segseed[1]);
	if( (segseed = (char**) realloc(segseed,sizeof(char*)*2))
				    ==NULL) outof_memory(textb[0]);
	segfan=0;
	justonepreimage=1;
        justonepreimage_found=1;
     }
     else if (segno==1 && seg[1]==1){
	seg[1]=0;
	sprintf(textb[0],"realloc-seg,segseed");
	if( (seg = (signed int*)realloc(seg, sizeof(signed int)))
				       ==NULL) outof_memory(textb[0]);
	free(segseed[1]);
	if( (segseed = (char**) realloc(segseed,sizeof(char*)*2))
				       ==NULL) outof_memory(textb[0]);
	segfan=0;
	justonepreimage=1;
        justonepreimage_found=1;
     }
   }
  }
  fansize=nextindex-nextbefore;
  
  /*nextbefore=precount before state tested*/
  if (segfan &&
       (!nonlocal || compress_1d_local==1 || regular2d)
	     && !dontcompress && !rulemix && exhaustive_testing!=2){
     totalsegfan=0;
     if (regular2d){
	for (zu=1;zu<=segno;zu++) totalsegfan+=(seg_2d_h[zu]*seg_2d_v[zu]);
     }
     else{
	for (zu=1;zu<=segno;zu++) totalsegfan+=seg[zu];
     }
     if (maxtreefan<totalsegfan) maxtreefan=totalsegfan;
     if (level==0)  maxtreefan+=1; /*add attractor link: Aug 05*/
     /*if (!justonepreimage) maxtreefan+=1;*/
  }
  /*if showing pre-image frequency histogram,
    count no of equivalent states*/
  if (pre_fansize_freq_hist){
     actual_fansize=0;
     if (segfan &&
	  (!nonlocal || compress_1d_local==1 || regular2d)
		&& !dontcompress && !rulemix && exhaustive_testing!=2){
	actual_fansize=totalsegfan;
	if (!justonepreimage) actual_fansize+=1;
	if (actual_fansize<maxinhist) pre_fan_freq[actual_fansize]+=1;
	else pre_fan_freq[maxinhist]+=1;
     }
     else{
	actual_fansize=fansize;
	if (level==0 && direction=='f') actual_fansize+=1;
	if (fansize<maxinhist) pre_fan_freq[actual_fansize]+=pre_equiv_no;
	else pre_fan_freq[maxinhist]+=pre_equiv_no;
     }     
  }

  if (show_maj>=0){
      if (count1s>lineL/2) isexception+=pre_equiv_no;      
  }
  if (maxtreefan<fansize){
     maxtreefan=fansize;/*max pre-imaging in tree*/
     if (direction=='f' && level==0) maxtreefan+=1; 
                              /* +pre-image on attractor*/      
  }  

  if (direction=='f' && level==0 && fansize==0 &&  maxtreefan==0) 
         maxtreefan=1; /*add attractor link: Nov 04*/ 
  if (maxsubtreefan<fansize){
     maxsubtreefan=fansize;/*max pre-imaging in tree*/
     if (direction=='f' && level==0) 
               maxsubtreefan+=1; /* +pre-image on attractor*/
  }
  
  tempx=getx;
  tempy=gety;

  if (labelsizefactor>0 && (shownumbers==1 || shownumbers==2)){
       tempCWidth=CWidth;
       tempCHeight=CHeight;     

#      if __WATCOM__
          _setcharsize((signed int)ty1*labelsizefactor,
                       (signed int)tx1*labelsizefactor);
          _gettextsettings(&ts);          
          CWidth=ts.width;
	  CHeight=ts.height;
          temp_sfont=sfont;
          sfont=0;
#       elif __UNIX__
          CHeight*=labelsizefactor;
          CWidth*=labelsizefactor;
          XSetFont(D,Gc,tempfont->fid);
#       endif
    }
    
    /*oy was signed short = 0 to 32767 then -32767 to 0, so avoid minus values*/
    /*now oy is max signed int*/
    /*if way below screen dont'draw -- will be returned by draw_fan()*/
    if (oy>Max_oy) oy=Max_oy; /*Max_oy=Maxy*2 set in main*/
    
    if (!gd_z_graph){
       draw_fan();
       if (istr_graph==1){
	  //fprintf(stderr,"\n1:back, %d>=%d",istr_node_count,max_istr_node_no);
          if (basinfield){
	     if (istr_node_count>max_istr_node_no){
	         early_exit_draw_fan=1;
	         //fprintf(stderr,"\n3:basinfield:%d>%d early_exit_draw_fan:",istr_node_count,max_istr_node_no);
	         //is[0]='q'; //to interupt
	         goto early_exit;
             }
	  }
	  
          else{
	      if (istr_node_count>=max_istr_node_no-(max_istr_node_no/9)){
	         early_exit_draw_fan=1;
	         //fprintf(stderr,"\n3:singe/subtree: %d>%d early_exit_draw_fan:",istr_node_count,max_istr_node_no);
	         //is[0]='q'; //to interupt
	         goto early_exit;
	      }	 
	  }    
       }
    } 
    else{
	  /*rectangle to contain basins*/        
	  if (stp) setviewport(lineL*scale+vgax(12),vgay(46),
                                       Maxx-3,vgay(157),1);
	  else  setviewport(3,vgay(46),Maxx-3,vgay(157),1);
	  draw_fan();
	  setviewport(0, 0, Maxx, Maxy, 0);
    }

    if (labelsizefactor>0 && (shownumbers==1 || shownumbers==2)){
       CWidth=tempCWidth;
       CHeight=tempCHeight;
#      if __WATCOM__
          _setcharsize(ty1,tx1);
          _gettextsettings(&ts);
          sfont=temp_sfont;
#      elif __UNIX__   
          restore_def_font();        
#      endif
    }

  moveto(tempx,tempy);
  /*if segmented fan from all 0s or 1s*/
  if (segfan &&
       (!nonlocal || compress_1d_local==1 || regular2d)
	    && !dontcompress && !rulemix  && exhaustive_testing!=2){
     sprintf(textb[0],"xseg");
     if ((segx=(signed int*)calloc(segno+1,sizeof(signed int)))
					 ==NULL) outof_memory(textb[0]);
     sprintf(textb[0],"yseg");
     if ((segy=(signed int*)calloc(segno+1,sizeof(signed int)))
					 ==NULL) outof_memory(textb[0]);
     /*copy co-ords of segseed nodes*/
     if (pretog){
	memmove(segx,xx0,sizeof(signed int)*(segno+1));
	memmove(segy,yy0,sizeof(signed int)*(segno+1));
     }
     else {
	memmove(segx,xx1,sizeof(signed int)*(segno+1));
	memmove(segy,yy1,sizeof(signed int)*(segno+1));
     }
     if (pretog){
	for (zu=thisindex;zu<=thismax;zu++) free(preim1[zu]);
	for (zu=1;zu<=nextindex;zu++) free(preim0[zu]);
     }
     else{
	for (zu=thisindex;zu<=thismax;zu++) free(preim0[zu]);
	for (zu=1;zu<=nextindex;zu++) free(preim1[zu]);
     }
     free_rest;
     thisindex=nextindex=precount=0;
     pretested=0;
     return;
  }
    /*
	 subtree structurel

	 level.. 0    1    this              next               last level
								  :
		      |	   |<-this           |<-next
		      |       max               max
  initial	 |         |                 |                    |
     seed -->o   |    |    |<-this           |               . .  |
		 |    |    |  index
		      |                      |                    |
			   |                 |<-next              |
			   |                 |  index             |
					     |

    pretog. . .  0    1    0                 1     */

  /*if (fansize>0) fprintf(stderr,"\n >>draw_fan complete, fansize=%lu nextindex=%lu", 
                            fansize,nextindex);*/

  
  

  if (datapause==3){ /*pause for sub-tree if not g-of-E $$$*/
      if (fansize>0){
         tempx=getx;
	 tempy=gety;
         xbox=draw_prompt_box(1);
         sprintf(textb[0],"fansize=%lu nextindex=%lu level=%d fan-root=%lu(hex)=",
		 fansize, nextindex, level,dec_equiv(state1,L));
         outtext(textb[0]);
         print_current_bitstring_hexbytes(0,0,state1,0,Maxx,white,0);
	 
         xbox=memory_box(-3.4,NULL);
	 moveto(xbox+vgax(3),vgay(3));
	 outtext("next fan-ret tree-q:");
	 input_string(1,0);
         if (is[0]=='q') datapause=2;
         is[0]='0'; /*reset is[0]*/
         erase_memory_box(-3.4);
	 erase_prompt_box(1);
         moveto(tempx,tempy);
      }
  }
  nextmax=nextindex;
  if (fansize==0) gofEno+=1; /*count of garden of Eden states*/
  fansize=0;
  
  if (thisindex==thismax){ /*this level test complete*/
     /*fprintf(stderr,"\n thismax=%lu, level %d -> %d",
                    thismax, level, level+1);
		    input_string(1,0);*/
     level++;     
     if (pretog) free(preim1[thisindex]);
     else free(preim0[thisindex]);     
     /*toggle 2 arrays this<-->next*/
     pretog=abs(pretog-1);
     thismax=nextmax;
     thisindex=nextindex=nextmax=0;
  }
  /*end of subtree, all garden of Eden states have been reached*/
  /*backward run stops at level_limit if =Maxu*/ 
  if (pretested == precount || 
      (/*level_limit!=Maxu &&*/ basinfield==0 && level==level_limit)){
     
     level-=1;
     if (maxtreelevel<level) maxtreelevel=level;
     tempx=getx;
     tempy=gety;

     if (direction=='b'){   /*if backward*/
	gofEdensity=(float)gofEno/(precount+1);
	treesize=precount+1;
	if (datapause>=2 && insegloop){  /*pause to show tree data*/
           tempx=getx;
	   tempy=gety;
	   xbox=draw_prompt_box(2);

	   if (regular2d) segsize=seg_2d_h[segindex]*seg_2d_v[segindex];
	   else segsize=seg[segindex];
	   sprintf(textb[0],
		"seg-fan=%lu (%d segs) seg-tree=%d no=%d size=%lu ",
			     totalsegfan,segno,segindex,segsize,treesize);
	   outtext(textb[0]);
	   moveto(xbox,gety+CHeight);
	   sprintf(textb[0],"seg-root(hex)=");
	   outtext(textb[0]);
	   temphx=getx;
	   print_current_bitstring_hexbytes(0,0,firstseed,0,Maxx,white,0);
	   
	   moveto(temphx+(vgax(4)*bytesL/2)+(CWidth*2*bytesL),gety);
	   sprintf(textb[0]," g=%lu=%.3g ml=%d mp=%lu\n",
		    gofEno,gofEdensity,level,maxsubtreefan);
	   outtext(textb[0]);

	   /*xbox=memory_box(0,NULL);
	   moveto(xbox+vgax(3),vgay(3));
	   outtext("options-o cont-ret:");
	   input_string(1,0);
	   if (is[0]=='o') finish_options(1);
           erase_memory_box(-4);
	   erase_prompt_box(2);*/

           xbox=memory_box(-3.4,NULL);
	   moveto(xbox+vgax(3),vgay(3));
	   outtext("next tree-ret nopause-q:");
	   input_string(1,0);
           if (is[0]=='q') datapause=2;
           is[0]='0'; /*reset is[0]*/
           erase_memory_box(-3.4);
	   erase_prompt_box(1);
           moveto(tempx,tempy);
	}
	/*print and/or save tree data*/
	if ((pdata==2 || filedata==2) && insegloop){
	   if (regular2d) segsize=seg_2d_h[segindex]*seg_2d_v[segindex];
	   else segsize=seg[segindex];
	   if (segindex==1){
		 sprintf(textb[0],
		  "   seg-fan=%lu (%d segs) \n",totalsegfan,segno);
		 if (pdata==2) print_out(textb[0]);
		 if (filedata==2) save_data(textb[0]);
	   }
	   sprintf(textb[0],"      %d. ",segindex);
	   if (pdata==2) print_out(textb[0]);
	   if (filedata==2) save_data(textb[0]);
	   print_current_bitstring_hexbytes (0,0,firstseed,0,Maxx,white,3);
           	   
	   sprintf(textb[0]," %d %lu ",segsize,treesize);
	   if (pdata==2) print_out(textb[0]);
	   if (filedata==2) save_data(textb[0]);
	   sprintf(textb[0]," %lu %.3g %d %lu\n",
		    gofEno,gofEdensity,level,maxsubtreefan);
	   if (pdata==2) print_out(textb[0]);
	   if (filedata==2) save_data(textb[0]);
	}
     }
     else{  /*if forward, tree from cycle state*/
	if (precount==0){
	   if (insegloop) gofEno=1;
	   else gofEno=0;  /*att state without tree*/
	}
	gofEdensity=(float)(gofEno)/(precount+1);
	treesize=precount+1;

	if (datapause>=2){  /*pause to show tree data*/
           tempx=getx;
	   tempy=gety;
	   xbox=draw_prompt_box(2);
	   if (insegloop){
	      if (regular2d) segsize=seg_2d_h[segindex]*seg_2d_v[segindex];
	      else segsize=seg[segindex];
	      sprintf(textb[0],
		"seg-fan=%lu (%d segs) thisseg=%d segindex=%d treesize=%lu ",
			     totalsegfan,segno,segindex,segsize,treesize);
	      outtext(textb[0]);
	   }
	   else{
	      sprintf(textb[0],"tree %lu. no=%d treesize=%lu ",
		  (signed int)attperiod-(attindex-1),cyclematch,treesize);
	      outtext(textb[0]);
	      if (treesize!=precount+1){
		 sprintf(textb[0],"ERROR count=%lu",precount+1);
		 outtext(textb[0]);
	      }
	      sprintf(textb[0],"(tree types=%d att=%lu)",
		       (signed int)attperiod/cyclematch,attperiod);
	      outtext(textb[0]);
	   }
	   moveto(xbox,gety+CHeight);

           if (screensavedemo==0){
	      if (insegloop) sprintf(textb[0],"seg-root(hex)=");
	      else sprintf(textb[0],"root(hex)=");
	      outtext(textb[0]);
	      temphx=getx;
	      print_current_bitstring_hexbytes(0,0,firstseed,0,Maxx,white,0);
	      moveto(temphx+(vgax(4)*bytesL/2)+(CWidth*2*bytesL),gety);
	      sprintf(textb[0]," g=%lu=%.3g ml=%d mp=%lu",
		    gofEno,gofEdensity,level,maxsubtreefan);
	      outtext(textb[0]);
           }

	   xbox=memory_box(-3.4,NULL); 
	   moveto(xbox+vgax(3),vgay(3));
           if (rangeL==1 || basinfield)
	         outtext("next tree-ret basin-q:");
           else outtext("next tree-ret nopause-q:");
	   input_string(1,0);
           if (is[0]=='q'){
              if (rangeL || basinfield) datapause=1;
              else datapause=0;
           }
           is[0]='0'; /*reset is[0]*/
           erase_memory_box(-3.4);
	   erase_prompt_box(2);
           moveto(tempx,tempy);
	}
	if (pdata==2 || filedata==2){  /*pause to show tree data*/
	   if (insegloop){
	      if (regular2d) segsize=seg_2d_h[segindex]*seg_2d_v[segindex];
	      else segsize=seg[segindex];
	      if (segindex==1){
		 sprintf(textb[0],
		  "      seg-fan=%lu (%d segs) \n",totalsegfan,segno);
		 if (pdata==2) print_out(textb[0]);
		 if (filedata==2) save_data(textb[0]);
	      }
	      sprintf(textb[0],"      %d. ",segindex);
	      if (pdata==2) print_out(textb[0]);
	      if (filedata==2) save_data(textb[0]);
	      print_current_bitstring_hexbytes (0,0,firstseed,0,Maxx,white,3);
	      	      
	      sprintf(textb[0]," %d %lu ",segsize,treesize);
	      if (pdata==2) print_out(textb[0]);
	      if (filedata==2) save_data(textb[0]);

	   }
	   else{
	      sprintf(textb[0],
		   "   %lu. ",(signed int)attperiod-(attindex-1));
	      if (pdata==2) print_out(textb[0]);
	      if (filedata==2) save_data(textb[0]);
	      print_current_bitstring_hexbytes (0,0,firstseed,0,Maxx,white,3);
	      
	      sprintf(textb[0]," %d %lu ",cyclematch,treesize);
	      if (pdata==2) print_out(textb[0]);
	      if (filedata==2) save_data(textb[0]);
	      if (treesize!=precount+1){
		 sprintf(textb[0],"ERROR count=%lu ",precount+1);
		 if (pdata==2) print_out(textb[0]);
		 if (filedata==2) save_data(textb[0]);
	      }
	   }
	   sprintf(textb[0]," %lu %.3g %d %lu\n",
		    gofEno,gofEdensity,level,maxsubtreefan);
	   if (pdata==2) print_out(textb[0]);
	   if (filedata==2) save_data(textb[0]);
	}
     }
     moveto(tempx,tempy);
     if (pretested != precount && 
	 (/*level_limit!=Maxu &&*/ basinfield==0 && level==level_limit)){
        if (pretog){
	   for (zu=thisindex;zu<=thismax;zu++) free(preim1[zu]);
	   for (zu=1;zu<=nextmax;zu++) free(preim0[zu]);
	}
	else{
	    for (zu=thisindex;zu<=thismax;zu++) free(preim0[zu]);
	    for (zu=1;zu<=nextmax;zu++) free(preim1[zu]);
	}
     }
     else{
        if (pretog) free(preim1[thisindex]);
        else free(preim0[thisindex]);
     }
     free_rest;
     return;
  }
  pretested++;
  thisindex++;
  
  goto startback;
}

/*****show various onthefly prompts (also in main) moved here March 07*******/
void back_onthefly_prompts(void){
       float temp_CWidth,temp_CHeight;
       
       //basinsize:E/C designed for screen-saver demo, but applies while any type of attractor basin is run.
       //except during jump_graph or ibaf_graph (inappropriate, and basins too small so no time to apply)
       if (jump_graph==0 && ibaf_graph==0){
           temp_CWidth=CWidth;
           temp_CHeight=CHeight;
           set_medium_font();

           if (nonlocal && exhaustive_testing==0 && neutral_order==0)
              sprintf(textb[1]," ppstack:tog-P");
           else sprintf(textb[1],"%s","");
           if (neutral_order==1) sprintf(textb[0],
              "STP:tog/scroll/exp/contr-s/#/e/c%s slow/max:</> basinsize:E/C",
                    textb[1]);
	   else sprintf(textb[0],
              "matrix-m STP:tog/scroll/exp/contr-s/#/e/c%s slow/max:</> basinsize:E/C",
                    textb[1]);

           draw_hint_box(0,0,textb[0],bottom_title_middx);

           restore_def_font();
           CWidth=temp_CWidth;
           CHeight=temp_CHeight;
       }   
}


/*** setup state-successor pair array by exhaustive testing, Sept 94 ****/
void prestate_successor_pairs(void){

 signed int  i,ii,jj,hh;
 char exLeftMax,exRightMax,ex2d3d;
 
 char save_exh=0,load_exh=0,print_exh=0;
 signed int u, /*index into rule table*/
	      tempx,tempy,xbox,barlen;
 unsigned int poss,n,*pnhood; /*memory for pseudo-nhood*/
 unsigned long state_space,prestate,tickoffbytes;

 unsigned int bitno,zu1; /*Ham_bias is a glbal variable*/
 char *temp_pn; //for NULLboundaries

#if __WATCOM__
 unsigned long memreq;
#  endif

# define exhau_box draw_box(-1,trboxw,vgay(46),Maxx-vgax(2),vgay(60),1,0);\
		     moveto(trboxw+vgax(2),vgay(46));

   /*memory for pseudo-nhood*/
   sprintf(textb[0],"pnhood");
   if ((pnhood=(unsigned int *)calloc(nhood,sizeof(unsigned int)))
			      ==NULL) outof_memory(textb[0]);

   state_space=(unsigned long)(pow(value_range,(double)lineL));
   
   if (!screensavedemo)
      draw_box(15,trboxw,vgay(46),Maxx-vgax(2),vgay(60),0,0);/*save box area*/

#  if __WATCOM__
      memory_box(1,NULL);
      memreq=state_space*bytesL*sizeof(char);
      /*watcom: no 2^16=65535 limit*/
      if ((long)_memavl()+get_memory()<memreq){
	 exhau_box;
	 if (memreq>0xffff-1)
	   sprintf(textb[0],
	     "mem req %lu*%d=%lu larger than avail=%lu, cont-ret:",
			   state_space,bytesL*sizeof(char),memreq,
				       (long)_memavl()+get_memory());
	 outtext(textb[0]);
	 exhaustive_testing=0;
	 input_string(1,0);
         sprintf(textb[9],"%s","boximage[15]");
	 putimage(trboxw,vgay(46),boximage[15],COPY_PUT,textb[9]);
	 freeimage(boximage[15]);
	 free(pnhood);
	 return;
      }

#  endif

   /*memory for exhaustive pairs, index=prestate,
                             char array=successor state*/
   sprintf(textb[0],"exh_pairs");
   if ((exh_pairs=(char*)calloc(state_space*bytesL,sizeof(char)))
				      ==NULL) outof_memory(textb[0]);
   if (jump_graph && exh_pairs_in_jump_nodes==0){//to redraw basins within jump-graph nodes if exhaustive_testing){ 
      //fprintf(stderr,"\ncalloc exh_pairs_backup ... ");
      sprintf(textb[0],"exh_pairs_backup");//for jump-graph if exhaustive_testing, including random-map, freed in graphxx.c
      if ((exh_pairs_backup=(char*)calloc(state_space*bytesL,sizeof(char)))
				      ==NULL) outof_memory(textb[0]);
      //fprintf(stderr,"calloced!");
   }

   
   /*fprintf(stderr,"\n->skip_compute_exh_pairs,jump_graph=%d ep_in_jump_nodes=%d",
     jump_graph,exh_pairs_in_jump_nodes);*/
   if (jump_graph && exh_pairs_in_jump_nodes==1) goto skip_compute_exh_pairs;
   
   /*memory for state-space tickoff (already done for field)*/
   if (!basinfield && !(direction=='f' && limitcheck==0)){

      tickspace=(unsigned long)(pow(value_range,(double)lineL)-1);

      tickoffbytes=(unsigned long)ceil( (double) (tickspace+1)/8 );
      sprintf(textb[0],"tickoff"); /*state-space index set to 0*/
      if ((tickoff=(char *)calloc(tickoffbytes,sizeof(char)))
					==NULL) outof_memory(textb[0]);
   }

   save_exh=load_exh=print_exh=0;

   if (!rangeL && !screensavedemo && !mutantdontpause){         
      exhau_box;
      is[0]=is[1]=is[2]=0;

#       if __UNIX__
	   sprintf(textb[1],", prt-p/+p:");
#       elif __WATCOM__
           sprintf(textb[1],":");
#       endif

      if (exhaustive_testing==2){
         if (Ham_bias>0) sprintf(textb[0],
             "random map: load-l, Ham%d-(def), reset Ham-h, and save-s/+s%s",
                                      Ham_bias,textb[1]);
         else sprintf(textb[0],
             "random map: load-l, rnd-(def), set Ham-h, and save-s/+s%s",textb[1]);
         
         outtext(textb[0]);
         input_string(3,0);
	 show_rule_bottom(nhood,1,carule[0],0);
      }      
      else{
	  sprintf(textb[0],
              "exhaustive pairs: load-l compute-ret, and save-s%s",textb[1]);
          outtext(textb[0]);
          input_string(2,0);
      }

      if (is[0]=='q'){
	 /*erase boxes*/
         sprintf(textb[9],"%s","boximage[15]");
	 putimage(trboxw,vgay(46),boximage[15],COPY_PUT,textb[9]);
	 free(exh_pairs);
	 
	 /*if (jump_graph){
            fprintf(stderr,"\nfree exh_pairs_backup  (q1)... ");
	    free(exh_pairs_backup);
	    fprintf(stderr,"freed!");
	    }*/
 	 
	 freeimage(boximage[15]);
	 free(pnhood);
	 return;
      }
      if (is[0]=='s' || is[1]=='s' || is[2]=='s'){
	 save_exh=1;
	 /*dontcompress=1;  no, commpression still works with exhaustive  pairs*/
      }
      if (is[0]=='p' || is[1]=='p' || is[2]=='p') print_exh=1;

      if (is[0]=='l'){ //load only into either exh or random map
	 load_exh=1;
	 if (exhaustive_testing==2) dontcompress=1;
	 
	 load_save_exhaustive('l');
	 if (is[0]=='q'){
	    /*erase boxes*/
            sprintf(textb[9],"%s","boximage[15]");
	    putimage(trboxw,vgay(46),boximage[15],COPY_PUT,textb[9]);
	    free(exh_pairs);
	    
	    /*if (jump_graph){
	       fprintf(stderr,"\nfree exh_pairs_backup  (q2)... ");
	       free(exh_pairs_backup);
	       fprintf(stderr,"freed!");
	       }*/
	    
	    freeimage(boximage[15]);
	    free(pnhood);
	    return;
	 }
      } 
          
      if (exhaustive_testing==2 && is[0]=='h'){
         if (load_exh==0){
	    exhau_box;
	    sprintf(textb[0],
	      "set Hamming distance (0-%d):",lineL);
	    outtext(textb[0]);
	    input_string(2,0);
	    if (is[0]!=13 && atof(is)>=0 && atof(is)<=lineL){
	       Ham_bias=atof(is);
            }
	 }
      }
   }

   if (load_exh==0){
      if (!screensavedemo){
	 exhau_box;
	 if (seq_update==1) outtext("seq update->, ");
	 else if (seq_update==2) outtext("<-seq update, ");
	 else if (seq_update==3) outtext("rand seq update, ");
	 outtext("setting up exhaustive pairs, interrupt-q");
      }
      /*set all bits to 0*/
      memmove(state1,all_0s,bytesL);
      memmove(state2,all_0s,bytesL);

      if (!screensavedemo) progress_bar(); /*draw progbar box*/
      moveto(0,0);

      for (prestate=0;prestate<=state_space-1;prestate++){
	 if (print_exh==1) fprintf(stderr,"\n %lu ",prestate);
         /*translate state in decimal to char array*/
	 if (value_range==2) dec_to_bit_line(state1,prestate,lineL);
         else dec_to_value_line(state1,prestate,lineL);
         if (print_exh==1){ 
             for (poss=L;poss!=Maxu;poss--) fprintf(stderr,"%d",get_value(state1, poss));
         }

	 /*show progress with bar in 64 steps*/
	 if (!screensavedemo){
	    if ((prestate+1)%(unsigned long)ceil((double)state_space/64)==0){
	       setfillstyle(SOLID_FILL,red);
	       barlen=(signed int)((double)(barxr-barxl-2)*
				  ((double)(prestate+1)/(state_space)));
	       bar(barxl+1,baryt+vgay(2),barxl+barlen,baryb-vgay(2));
	    }
	 }
	 if (event_ready()){   /*to interrupt, early exit*/
	    if (is[0]=='q'){
	       tempx=getx;
	       tempy=gety;

	      startinterrupt:
	       sprintf(textb[0],
	         "exhaustive pairs %d%% complete; stop-q, options-o, cont-ret:",
		   (signed int)(100*((double)prestate/state_space)));
	       exhau_box;
	       outtext(textb[0]);
	       input_string(1,0);

	       if (is[0]=='o'){
	          finish_options(1);
	          goto startinterrupt;
	       }

               if (is[0]=='q'){
	          /*erase boxes*/
                   sprintf(textb[9],"%s","boximage[15]");
	           putimage(trboxw,vgay(46),boximage[15],COPY_PUT,textb[9]);
                   if (!basinfield && !(direction=='f' && limitcheck==0)){
		      /*space-time patterns only*/
		      free(exh_pairs);
		      
		      /* if (jump_graph){
	                 fprintf(stderr,"\nfree exh_pairs_backup  (q3)... ");
	                 free(exh_pairs_backup);
	                 fprintf(stderr,"freed!");
			 }*/
		      
                      free(tickoff);
		      //fprintf(stderr," \n back 1:free(tickoff)"); //fprintf??
                      exhaustive_testing=0;
                   }
	           freeimage(boximage[15]);
	           free(pnhood);
                   moveto(tempx,tempy);                
	           return;
	       }
	       is[0]=0;
	       exhau_box;
	       outtext("setting up exhaustive pairs, interrupt-q");            
	       moveto(tempx,tempy);
	    }
         }
	 

         /*show intermediate states in sequential updating*/ 
         /*fprintf(stderr,"----------");
         for (poss=L; poss!=Maxu; poss--) 
                     fprintf(stderr,"%d",get_bit(state1,poss));
		     fprintf(stderr,"-");
         for (poss=0;poss<=L; poss++) 
	    fprintf(stderr,"%d",seq_order[poss]);*/

         if (exhaustive_testing==1) {
	    /*run forward one step*/
	    for (poss=L; poss!=Maxu; poss--){
	       if (seq_update>0){
		  n=seq_order[poss]; /*set seq updating order*/
                  /*fprintf(stderr,"\n %d-",n);*/
	       }   
               else n=poss;
	       /*local nhood with periodic boundary conditions*/
	       if (nonlocal==0){
		  for (i=0;i<=nhoodm[n]-1;i++)
			    pnhood[i]=(lineL+n-(nhoodm[n]/2)+i)%lineL;
	       }
	       /*nonlocal=1, get psuedo-nhood from wiring scheme*/
	       else {
		  for (i=0;i<=nhoodm[n]-1;i++) pnhood[i]=wiring[n][i];
	       }
	       u=0; /*find dec value of actual or pseudo-nhood*/
	       
               /*will cope with k bigger that netsize*/
               if ((temp_pn=(char*)calloc(nhoodm[n],sizeof(char)))
		      ==NULL) outof_memory("temp_pn");

       /*--------------------------------------*/	       
       if (NULLboundaries==1){
	
	if (oned && nhoodm[n]>1){
               char countl=0, countr=0;
	       
                /* left end
                   1   3    5      7
                   |  \|/ \\|// \\\|/// .... odd nhoods
                   0  1    2      3                   */
                if (nhoodm[n]%2==1) exLeftMax=nhoodm[n]/2;
 
                /* 2    4     6       8
                   |/  \|// \\|/// \\\|//// .... even nhoods
                  0    1     2       3        extra on right */
                else exLeftMax=nhoodm[n]/2 - 1;

                /*right end
                      3    5      7
                     \|/ \\|// \\\|/// .... odd nhoods
                       1    2      3                   */
                               
                /* 2    4     6       8
                   |/  \|// \\|/// \\\|//// .... even nhoods
                    1    2     3       4        extra on right */
                exRightMax=nhoodm[n]/2;

             /*will cope with k bigger that netsize*/
	     if (1){ //lineL<nhoodm[n]){
	       signed int  exL,exR,thisn;

	           thisn=(signed int)n;	
                   exL=exLeftMax-(L-thisn);//check if i is outside left edge
                   for (i=nhoodm[thisn]-1;i>=0;i--){
                       countl+=1;
                       if (countl <= exL) temp_pn[i]=1;
                       else break;                                              
		   }
                   if (diff_plot && thisn<=L/2){
		      countl=0; //check if i is outside centre left edge
                      exL=exLeftMax-(L/2-thisn);
                      for (i=nhoodm[thisn]-1;i>=0;i--){
                         countl+=1;
                         if (countl <= exL) temp_pn[i]=1;
                         else break;                                              
		      }
                   }
                   exR=exRightMax-thisn; //check if i is outside right edge
                   for (i=0;i<=nhoodm[thisn]-1;i++){
                       countr+=1;
                       if (countr <= exR) temp_pn[i]=1;
                       else break;
		   }
                   if (diff_plot && thisn>=lineL/2){
		      countr=0; //check if i is outside centre right edge
                      exR=exRightMax-(thisn-lineL/2); 
                      for (i=0;i<=nhoodm[thisn]-1;i++){
                         countr+=1;
                         if (countr <= exR) temp_pn[i]=1;
                         else break;
		      }
		   }
                   
                   /*fprintf(stderr,"\n n=%d:******************************",thisn);
                   for (i=nhoodm[n]-1;i>=0;i--){
                      fprintf(stderr,"%d",temp_pn[i]); //fprintf??
		    }*/
                   //input_string(1,0);
             }
   
	     else{ //alternative methods superseded
                if (n > L-exLeftMax){ //left boundary                                      
                   for (i=nhoodm[n]-1;i>=1;i--){ //left <- right                        
		        //if (pnhood[i]<pnhood[0]) temp_pn[i]=1; //this also works
                        if (wiring[n][i] < exLeftMax) temp_pn[i]=1;
                   } 
                   /*for (ii=exLeftMax-1;ii>=0;ii--){ //this also works
                      if (n == L-ii){                  		                             
			 for (i=nhoodm[n]-1;i>=nhoodm[n]-1-(exLeftMax-1-ii); i--){
                            temp_pn[i]=1;
		         }
                      }
		   }*/
                }
                if (n < exRightMax){ //right boundary
                   for (i=nhoodm[n]-2;i>=0;i--){ //right -> left
		        //if (pnhood[i]>nhoodm[n]-1) temp_pn[i]=1; //this also works
                        if (wiring[n][i] > L-exRightMax) temp_pn[i]=1;
                   }                    
                   /*for (ii=exRightMax-1;ii>=0;ii--){ //this also works
                      if (n == ii){                         
		         for (i=exRightMax-1-ii;i>=0;i--){
			    temp_pn[i]=1;
                         }
		      }
		   }*/
                }
             }
        }
	else if (twod){
	       if (nhoodm[n]<=8) ex2d3d=1;
	       else if (nhoodm[n]<=13) ex2d3d=2;
               else ex2d3d=3;
               ii=n%i2d;
	       jj=n/i2d;


	       if (diff_plot){
                  if (ii >= i2d-1-ex2d3d){ //left boundary
                     for (i=nhoodm[n]-1;i>=1;i--){ //left <- right
                        if (wiring[n][i]%i2d < i2d/2+ex2d3d
                              && wiring[n][i]%i2d >= i2d/2) temp_pn[i]=1;
                     }
                  }
		  if (ii<=i2d/2-1 && ii >= i2d/2-1-ex2d3d){ //left boundary centre){
                     for (i=nhoodm[n]-1;i>=1;i--){ //left <- right
		        if (wiring[n][i]%i2d < ex2d3d) temp_pn[i]=1;
                     }
                  }
                  if (ii <= ex2d3d){ //right boundary
                     for (i=nhoodm[n]-1;i>=0;i--){ //left -> right
                        if (wiring[n][i]%i2d > i2d/2-1-ex2d3d
			  &&  wiring[n][i]%i2d <=i2d/2-1) temp_pn[i]=1;
                     } 
                  }
                  if (ii>=i2d/2 && ii<=i2d/2-1 + ex2d3d){ 
                     for (i=nhoodm[n]-1;i>=0;i--){ //left -> right
                        if (wiring[n][i]%i2d > i2d-1-ex2d3d) temp_pn[i]=1;
                     } 
                  }
	       }

               else{
                  if (ii >= i2d-1-ex2d3d){ //left boundary
                     for (i=nhoodm[n]-1;i>=1;i--){ //left <- right
                        if (wiring[n][i]%i2d < ex2d3d) temp_pn[i]=1;
                     }
                  }
	        
	          if (ii <= ex2d3d){ //right boundary
                     for (i=nhoodm[n]-1;i>=0;i--){ //left -> right
                        if (wiring[n][i]%i2d > i2d-1-ex2d3d) temp_pn[i]=1;
                     } 
                  }
               } 
               
               if (jj >= j2d-1-ex2d3d){ //top boundary
                   for (i=nhoodm[n]-1;i>=1;i--){ //bottom ^ top
		      if (wiring[n][i]/i2d < ex2d3d) temp_pn[i]=1; 
                   }
               }   
	       if (jj <= ex2d3d){ //bottom boundary
                   for (i=nhoodm[n]-1;i>=0;i--){ //top v bottom
                      if (wiring[n][i]/i2d > j2d-1-ex2d3d) temp_pn[i]=1; 
                   }
               }
          }
          else if (threed){
	       if (nhoodm[n]<=7) ex2d3d=2;
	       else ex2d3d=3;

               ii=n%i3d;
	       jj=n%(i3d*j3d)/i3d;
               hh=n/(i3d*j3d);
               //n=(i3d*j3d*hh) + (i3d*jj) + ii;

               if (ii >= i3d-1-ex2d3d){ //left boundary
                   for (i=nhoodm[n]-1;i>=0;i--){ //left <- right
                      if (wiring[n][i]%i3d < ex2d3d) temp_pn[i]=1;
                   }
                }
	        if (ii <= ex2d3d){ //right boundary
                   for (i=nhoodm[n]-1;i>=0;i--){ //left -> right
                       if (wiring[n][i]%i3d > i3d-1-ex2d3d) temp_pn[i]=1;
                   } 
                }
                
                if (jj >= j3d-1-ex2d3d){ //top boundary, highest jj
                   for (i=nhoodm[n]-1;i>=0;i--){
		      if (wiring[n][i]%(i3d*j3d)/i3d < ex2d3d) temp_pn[i]=1; 
                   }
                }   
	        if (jj <= ex2d3d){ //bottom boundary
                   for (i=nhoodm[n]-1;i>=0;i--){
                      if (wiring[n][i]%(i3d*j3d)/i3d > j3d-1-ex2d3d) temp_pn[i]=1; 
                   }
                }

                if (hh >= h3d-1-ex2d3d){ //front boundary, highest hh
                   for (i=nhoodm[n]-1;i>=0;i--){
		      if (wiring[n][i]/(i3d*j3d) < ex2d3d) temp_pn[i]=1; 
                   }
                }   
	        if (hh <= ex2d3d){ //back boundary
                   for (i=nhoodm[n]-1;i>=0;i--){ //bottom
                      if (wiring[n][i]/(i3d*j3d) > h3d-1-ex2d3d) temp_pn[i]=1; 
                   }
                }
	  }

             /*if (n > L-exLeftMax || n < exRightMax){
		  fprintf(stderr,"\nexL=%d exR=%d nhoodm[%d]=%d n=%d: ",
			  exLeftMax,exRightMax,n,nhoodm[n],n);
                   for (i=nhoodm[n]-1;i>=0;i--){
                      fprintf(stderr,"%d",temp_pn[i]); 
                   }
	      }*/                       
       }//if (NULLboundaries==1){
       /*--------------------------------------*/	       

                for (i=nhoodm[n]-1;i>=0;i--){
		    if (NULLboundaries==1 && temp_pn[i]==1) continue;
	            if (value_range==2) u+=get_bit(state1,pnhood[i])*
                            (signed int)pow(2,(double)i);
                    else u+=get_value(state1,pnhood[i])*
                            (signed int)pow(value_range,(double)i);
	        }
                free(temp_pn);

	       /*set cell next line according to rule look-up table*/
               if (value_range==2){
	           if (!rulemix){
		      set_bit(state2,n,get_bit(carule[0],u));
	           }
	           else set_bit(state2,n,get_bit(carule[n],u));
               }
               else{
                   if (!rulemix){
		      set_value(state2,n,get_value(carule[0],u));
	           }
	           else set_value(state2,n,get_value(carule[n],u));
               }
	       /*for sequential updating only*/   
               if (seq_update){
		 /*unsigned int this_poss;*/ 
                  if (value_range==2){
                        set_bit(state1,n,get_bit(state2,n));  
		    /*for (this_poss=L; this_poss!=Maxu; this_poss--) 
		      fprintf(stderr,"%d",get_bit(state1,this_poss));*/
                  }
                  else set_value(state1,n,get_value(state2,n));
               }	
	    }
            /*fprintf(stderr," - %lu",dec_equiv(state2,L));*/
	 }//if (exhaustive_testing==1) {
	 
	 /*set exhaustive  pairs acc to Hamming distance or at random*/         
	 else if (exhaustive_testing==2){
	    //fprintf(stderr,"\nHam_bias=%d",Ham_bias);
	    if (Ham_bias>0){

	       if (value_range==2) dec_to_bit_line(tempState,prestate,lineL);
               else dec_to_value_line(tempState,prestate,lineL);
	       memmove(state2,tempState,bytesL);

	       /*flip bits if Ham_bias <= lineL/2*/
	       if (Ham_bias<=lineL/2 || value_range>2){
		  bitno=0;
		  while(1){
		     bitno+=1;
		     zu1=myrand()%lineL;
                     if (value_range==2){
		        /*flip a bit at random position*/
		        set_bit(state2,zu1,abs(get_bit(state2,zu1)-1));
		        /*restore flip if not different*/
		        if (get_bit(state2,zu1)==get_bit(tempState,zu1)){
			     set_bit(state2,zu1,abs(get_bit(state2,zu1)-1));
			     bitno-=1;
		        }
                     }
                     else{
		       char temp_value;
		        temp_value=get_value(state2,zu1);
                        /*flip a value at random position*/
		        set_value(state2,zu1,myrand()%value_range);
		        /*restore flip if not different*/
		        if (get_value(state2,zu1)==get_value(tempState,zu1)){
			     set_value(state2,zu1,temp_value);
			     bitno-=1;
		        }
                     }
		     if (bitno==Ham_bias) break;
		  }
	       }
	       else if (Ham_bias>=lineL/2+1 && value_range==2){
		 /*restore bits in compliment if Ham_bias >= lineL/2 + 1*/
                 /* not for  value_range>2 because ? compliment*/
		 for (zu1=L;zu1!=Maxu;zu1--)
		        set_bit(tempState2,zu1,abs(get_bit(tempState,zu1)-1));
		  bitno=0;
		  while(1){
		     if (Ham_bias==lineL) break;
		     bitno+=1;
		     zu1=myrand()%lineL;
		     /*flip a bit at random position in compliment*/
		     set_bit(tempState2,zu1,abs(get_bit(tempState2,zu1)-1))
		     /*restore flip*/
		     if (get_bit(tempState2,zu1)!=get_bit(tempState,zu1)){
			set_bit(tempState2,zu1,abs(get_bit(tempState2,zu1)-1));
				bitno-=1;
		     }
		     if (bitno==lineL-Ham_bias) break;
		  }
		  memmove(state2,tempState2,bytesL);
	       }
	    }
	    else{
	       for (n=L;n!=Maxu;n--){
                  if (value_range==2){ 
                      set_bit(state2,n,( (rand() % 100)/50) );
                  }
                  else set_value(state2,n,myrand()%value_range);
               }
	    }
	 }
	 
	 if (seq_update==0) memmove(exh_pairs+prestate*bytesL,state2,bytesL);
         /*for sequential updating only*/
	 else memmove(exh_pairs+prestate*bytesL,state1,bytesL);

         if (print_exh==1 /*&& seq_update>0*/){
            fprintf(stderr," ");
            for (poss=L;poss!=Maxu;poss--) fprintf(stderr,"%d",get_value(state2, poss));
            fprintf(stderr," %lu",dec_equiv(state2,L));
         }
      }
      
   } /*if (load_exh==0)*/

   if (print_exh==1 && load_exh==1){
      for (prestate=0;prestate<=state_space-1;prestate++){
         memmove(state2,exh_pairs+prestate*bytesL,bytesL);

         fprintf(stderr,"\n %lu ",prestate);
         if (value_range==2) dec_to_bit_line(state1,prestate,lineL);
         else dec_to_value_line(state1,prestate,lineL);
         for (poss=L;poss!=Maxu;poss--) fprintf(stderr,"%d",get_value(state1, poss));
         fprintf(stderr," ");
         memmove(state2,exh_pairs+prestate*bytesL,bytesL);
         for (poss=L;poss!=Maxu;poss--) fprintf(stderr,"%d",get_value(state1, poss));
         fprintf(stderr," %lu",dec_equiv(state2,L));
      }
   }
   if (save_exh==1){
      exhau_box;
      outtext("SAVE exhaustive pairs-s:");
      input_string(1,0);
      if (is[0]=='s') load_save_exhaustive('s');
   }

   skip_compute_exh_pairs:

   
   //fprintf(stderr,"\nabout to copy,  exh_pairs_in_jump_nodes=%d", exh_pairs_in_jump_nodes);
   //initially exh_pairs are calculated, so copy exh_pairs to exh_pairs_backup
   if (jump_graph && exh_pairs_in_jump_nodes==0){
         //fprintf(stderr,"\nmemmove exh_pairs <- exh_pairs_backup ... ");
         memmove(exh_pairs_backup,exh_pairs,state_space*bytesL);
         //fprintf(stderr,"moved!");
   }
    //otherwise, dont calculate calculate but copy  exh_pairs_backup to exh_pairs
    if (jump_graph && exh_pairs_in_jump_nodes==1){
         //fprintf(stderr,"\nmemmove exh_pairs_backup <- exh_pairs ... ");
         memmove(exh_pairs,exh_pairs_backup,state_space*bytesL);
         //fprintf(stderr,"moved!");
   }
   //jump_graph_table(0,NULL,'s'); 
   //input_string(1,0);

   /*erase boxes*/
   if (!screensavedemo){
      sprintf(textb[9],"%s","boximage[15]");
      putimage(trboxw,vgay(46),boximage[15],COPY_PUT,textb[9]);
      freeimage(boximage[15]);
      xbox=(signed int)((float)Maxx)/2;
      erase_box(xbox,vgay(30),Maxx-2,vgay(30)+vgay(9)+vgay(3));
   }
   free(pnhood);
   //fprintf(stderr,"\nend prestate_successor_pairs");
}

/***** compute pre-images by exhaustive testing, Sept 94 **********/
void pre_exhaustive(void){

 unsigned long state_space,prestate;
 
   attrepeat=0;
   state_space=(unsigned long)(pow(value_range,(double)lineL));
   back_onthefly_prompts();

   for (prestate=0;prestate<=state_space-1;prestate++){
      if (get_bitlong(tickoff,prestate)) continue;
      if (memcmp(state1,exh_pairs+prestate*bytesL,bytesL)==0){
	 /*pre-image found*/
	 if (value_range==2) dec_to_bit_line(state2,prestate,(signed int)lineL);
         else dec_to_value_line(state2,prestate,(signed int)lineL);
	 /*check for cycle repeat, rotation (from all 0s or 1s),
						if ok add, print*/
	 if (check_pre_image(state2)==0){
            accept_pre_image(state2);
	    /*if interrupt*/
	    interrupt_pre_fan();
	    if (is[0]=='q' || is[0]=='n') return;
	 }
      }
   }
}

/***** neutral_order==1 compute "pre-images" for neutral orders ******/
void pre_neutral(void){
 signed int preno=0;
 unsigned int *order,temp,z;
 unsigned long index,checkindex;
 char connected;
 signed int wire;  
   /*allocate memory for order[index]*/ 
   if ((order=(unsigned int *)calloc(templineL,sizeof(unsigned int)))
    			       ==NULL) outof_memory("order");   
   index=dec_equiv(state1,L);
   
   for (z=1;z<=templineL-1;z++){
      connected=0; 
      /*restore order*/
      index_to_order(index,order,templineL);
      
      for (wire=nhood-1;wire>=0;wire--){ /*max nhood*/
	 /*check if the 2 order-neighbour-elements
	 whose order is to be swapped have any links to each other
         abcdefg...z
	 swap bc
	 has c at least one input from b*/
	 if (wire<=nhoodm[order[z]]-1){
            if (wiring[order[z]][wire]==order[z-1]){
	       connected=1;
	       break;
	    }
	 }
	 /*swap cb back to bc?, c is already updated
	 has b at least one input from c*/
	 if (wire<=nhoodm[order[z-1]]-1){
	    if (wiring[order[z-1]][wire]==order[z]){
	       connected=1;	       
	       break;
	    }
	 }
      }
      if (connected==1) continue;
      /*swap orders*/
      temp=order[z];
      order[z]=order[z-1];
      order[z-1]=temp;
      checkindex=order_to_index(order,templineL);
            
      if (get_bitlong(tickoff,checkindex)) continue;
      /*if legal, tickoff as part of component*/
      set_bitlong(tickoff,checkindex,1);    
      memmove(state2,all_0s,bytesL); /*set array to null*/      
      if (value_range==2) dec_to_bit_line(state2,checkindex,lineL);
      else dec_to_value_line(state2,checkindex,lineL);
      /*assign as "pre-image"*/
      if (check_pre_image(state2)==0){
	   accept_pre_image(state2);	   
           preno+=1;            
           /*if interrupt*/
           interrupt_pre_fan();
           if (is[0]=='q' || is[0]=='n'){
	      free(order);
	      return;
           }
       }
   }   
   free(order);
}

/**** prepair for pre-images, - random Boolean networks, Oct 94 *****/
void prepair_pre_rand(void){
 signed int
     Tcell,    /*target cell index*/
     Rtable,   /*rule table index*/
     tablemax, /*highest index in rule table*/
     tablebytes,/*no of bytes               */
     z;

 char tempbit,
      *samebits; /*for cheking same n-tupules*/

      /*global variables:
      **nhoodE, reduced effective nhood
      **skiptable; skip rule table entry because nhood reduced*/

  tablemax=(signed int)pow(value_range,(double)nhood)-1;
  tablebytes=(signed int)ceil(((double)(value_bits *(tablemax+1)))/8);
  sprintf(textb[0],"prepair pre-rand");
  if ((arule=(char *)calloc(tablebytes,sizeof(char)))
				 ==NULL) outof_memory(textb[0]);

  if ((PS=(char ***)calloc(2,sizeof(char**)))
                                        ==NULL) outof_memory(textb[0]);
  if ((PSflag=(char ***)calloc(2,sizeof(char**)))
					==NULL) outof_memory(textb[0]);
  /*allocate initial mem PS[1],PSflag[1]*/
  if ((PS[1]=(char **)calloc(1,sizeof(char*)))
                                        ==NULL)outof_memory(textb[0]);
  if ((PSflag[1]=(char **)calloc(1,sizeof(char*)))
					==NULL) outof_memory(textb[0]);
  /*allocate initial mem PS[0],PSflag[0]*/
  if ((PS[0]=(char **)calloc(2,sizeof(char*)))
					==NULL) outof_memory(textb[0]);
  if ((PSflag[0]=(char **)calloc(2,sizeof(char*)))
                                        ==NULL) outof_memory(textb[0]);
  if ((PStemp=(char *)calloc(bytesL,sizeof(char)))
					==NULL) outof_memory(textb[0]);
  if ((flagtemp=(char *)calloc(bytesL,sizeof(char)))
					==NULL) outof_memory(textb[0]);
  if ((PScount=(unsigned long*)calloc(2,sizeof(unsigned long)))
					==NULL) outof_memory(textb[0]);
  if ((nhoodE=(char**)calloc(lineL,sizeof(char*)))
					==NULL) outof_memory(textb[0]);
  if ((skiptable=(char**)calloc(lineL,sizeof(char*)))
					==NULL) outof_memory(textb[0]);
  for (z=lineL-1;z>=0;z--){
     if (nhood_mixed){
	tablemax=(signed int)pow(value_range,(double)nhoodm[z])-1;
        tablebytes=(signed int)ceil(((double)(value_bits *(tablemax+1)))/8);
     }
     if ((nhoodE[z]=(char*)calloc(tablemax+1,sizeof(char)))
					==NULL) outof_memory(textb[0]);
     if ((skiptable[z]=(char*)calloc(tablebytes,sizeof(char)))
					==NULL) outof_memory(textb[0]);
  }
  memory_box(1,NULL);
  if (!rulemix) memmove(arule,carule[0],tablebytes);

  if (value_range==2 && NULLboundaries==0){

  for (Tcell=lineL-1;Tcell>=0;Tcell--){   /*for each target cell*/
     if (nhood_mixed){
	tablemax=(signed int)pow(value_range,(double)nhoodm[Tcell])-1;
        tablebytes=(signed int)ceil(((double)(value_bits *(tablemax+1)))/8);
     }
     if (rulemix) memmove(arule,carule[Tcell],tablebytes);

     /*each rule table entry*/
     for (Rtable=tablemax;Rtable>=0;Rtable--){
	/*skip redundant rule table entries*/
	if (get_bit(skiptable[Tcell],Rtable)==1) continue;
	/*check if effective nhood smaller than actual                    */
	/*	    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                        */
	/*	  ____                   ..equal tupule, reduce nhood by 1*/
	/*	  __________             ..equal 4-tupule, ..2            */
	/*	  ______________________ ..equal 8-tupule, ..3  etc..     */


	if ((Rtable+1)%2==0){
	   tempbit=get_bit(arule,Rtable); /*compare 2 bits */
	   if (tempbit==get_bit(arule,Rtable-1)){
	      /*reduce effective nhood by 1 wiring ..87654321* */
	      nhoodE[Tcell][Rtable]=1;
	      set_bit1(skiptable[Tcell],Rtable-1);
	      if ((Rtable+1)%4==0 &&
		  tempbit==get_bit(arule,Rtable-2) &&
			 tempbit==get_bit(arule,Rtable-3)){/*compare 4 bits*/
		 /*reduce effective nhood by 2 wiring ..8765432**  */
		 nhoodE[Tcell][Rtable]=2;
		 for (z=Rtable-1;z>=Rtable-3;z--)
		       set_bit1(skiptable[Tcell],z);
		 if ((Rtable+1)%8==0){  /*compare 8 bits, 1 byte  */
		  if (tempbit) samebits=rule_all_1s;
		  else samebits=rule_all_0s;
		  if (memcmp(arule+Rtable/8,samebits,1)==0){
		    /*reduce effective nhood by 3 wiring ..876543*** */
		    nhoodE[Tcell][Rtable]=3;
		    for (z=Rtable-1;z>=Rtable-7;z--)
		       set_bit1(skiptable[Tcell],z);
		    if ((Rtable+1)%16==0 && /*2 bytes*/
		      memcmp(arule+(Rtable/8)-1,samebits,2)==0){
		      /*reduce effective nhood by 4 wiring ..87654**** */
		      nhoodE[Tcell][Rtable]=4;
		      for (z=Rtable-1;z>=Rtable-15;z--)
		       set_bit1(skiptable[Tcell],z);
		      if ((Rtable+1)%32==0 && /*4 bytes*/
			memcmp(arule+(Rtable/8)-3,samebits,4)==0){
			/*reduce effective nhood by 5 wiring..8765***** */
			nhoodE[Tcell][Rtable]=5;
			for (z=Rtable-1;z>=Rtable-31;z--)
			  set_bit1(skiptable[Tcell],z);
			if ((Rtable+1)%64==0 && /*8 bytes*/
			  memcmp(arule+(Rtable/8)-7,samebits,8)==0){
			  /*reduce effective nhood by 6 wiring..876****** */
			  nhoodE[Tcell][Rtable]=6;
			  for (z=Rtable-1;z>=Rtable-63;z--)
			   set_bit1(skiptable[Tcell],z);
			  if ((Rtable+1)%128==0 && /*16 bytes*/
			    memcmp(arule+(Rtable/8)-15,samebits,16)==0){
			    /*reduce effective nhood by 7 wiring..87******* */
			    nhoodE[Tcell][Rtable]=7;
			    for (z=Rtable-1;z>=Rtable-127;z--)
			     set_bit1(skiptable[Tcell],z);
			    if ((Rtable+1)%256==0 && /*32 bytes*/
			      memcmp(arule+(Rtable/8)-31,samebits,32)==0){
			      /*reduce effective nhood by 8 wiring..8******** */
			      nhoodE[Tcell][Rtable]=8;
			      for (z=Rtable-1;z>=Rtable-255;z--)
			       set_bit1(skiptable[Tcell],z);
			    }
			  }
			}
		      }
		    }
		  }
		}
	      }
	   }
	}     
     }
  }
  }
  /*rearrange cell order to maximise wiring overlap*/   
  if (see_ppstack==1){
     draw_prompt_box(1); 
     outtext("partial pre-image histogram: start pause-p:");
  }
  if (reorderRBN==1) rearrange_cell_order();
}
/******** rearrange cell order to maxdimize wiring overlap **************/
void rearrange_cell_order(void){

  signed int tempx;
  signed int *cell_filled,count,
               Tcell,r_cell,z;
  char match_found;
  signed int s_wire,r_wire;

  if ((cell_order=(signed int *)calloc(lineL,sizeof(signed int)))
			   ==NULL) outof_memory("cell_order");
  if ((cell_filled=(signed int *)calloc(lineL,sizeof(signed int)))
			   ==NULL) outof_memory("cell_filled");

  for (Tcell=lineL-1;Tcell>=0;Tcell--){ 
     cell_order[Tcell]=-1;
     cell_filled[Tcell]=-1;
  }
  count=lineL-1;
  match_found=0;
  Tcell=cell_filled[lineL-1]=cell_order[lineL-1]=lineL-1;
 
  while(count>0){
     count--;
     for (r_cell=lineL-1;r_cell>=0;r_cell--){                                   
        if (cell_order[r_cell]==-1 && r_cell!=Tcell
	                    && cell_filled[r_cell]==-1){
            for (s_wire=0;s_wire<=nhoodm[Tcell]-1;s_wire++){
	      for (r_wire=nhoodm[r_cell]-1;r_wire>=0;r_wire--){
                 if (wiring[Tcell][s_wire]==wiring[r_cell][r_wire]){
                     match_found=1;
                     cell_order[count]=r_cell;
                     Tcell=r_cell;
                     cell_filled[Tcell]=Tcell;
                     cell_filled[r_cell]=r_cell;
                     
                     goto skip;
	         }
              }
           }
        }       
     }
     
     skip:
     if (match_found==1){
        match_found=0;
     }           
     else{  /*find max available cell order*/
        for (z=lineL-1;z>=0;z--){
          if (cell_filled[z]==-1){ 
             Tcell=cell_order[count]=cell_filled[z]=z;
             break;
	  }
        }                        
     }
  }  
  if (mutant_layout==0 && screensavedemo==0){
    char order_lines=0;
     draw_box(-1,trboxw,CHeight*4.7,Maxx-2,CHeight*5.7,0,0);
     outtext("reorder=");
     tempx=getx;
     for (z=lineL-1;z>=0;z--){ /*show the new order*/
        if (getx>Maxx-CWidth*3){
	   order_lines++;
           moveto(tempx,gety+CHeight);
        }
        if (order_lines>=2) break;
        sprintf(textb[0],"%d ",cell_order[z]);
        outtext(textb[0]);
     }
  } 
  free(cell_filled);   
}

/** free initial mem for pre-images, - random Boolean networks, Oct 94 ***/
void free_pre_rand(void){
  signed int z;

   if (reorderRBN==1) free(cell_order);
   for (z=0;z<=1;z++){
      free(PS[z]);
      free(PSflag[z]);
   }

   free(PS);
   free(PSflag);
   free(PStemp);
   free(flagtemp);
   free(PScount);

   free(arule);

   for (z=lineL-1;z>=0;z--){
      free(nhoodE[z]);
      free(skiptable[z]);
   }
   free(nhoodE);
   free(skiptable);
}

/*** compute pre-images, - random Boolean networks, Nov 93 - now multi-value ***/
void pre_images_rand(void){

 signed int tog;    /*toggle id of two latest partial pre-image stacks*/

 char newbit, /*new bit from pseudo-nhood*/
      PSbit,  /*bit at wire coupling in partial pre-image*/
      existbit, /*bit flags if above has been set=1, or is empty=0*/
      conflict=0;
      /*global variables:*/
      /*
      **nhoodE,    reduced effective nhood
      **skiptable; skip rule table entry because nhood reduced
      */

#     if __WATCOM__ 
        unsigned int 
          zu,
	  ppstack,   /*partial pre-image index*/
	  wildpre; /*to deal pre-image with wildcards*/
	  /*file variable:
	  *PScount,  count of partial pre-images in toggled stacks*/
#      elif __UNIX__
          unsigned long
          zu,
	  ppstack,   /*partial pre-image index*/
	  wildpre; /*to deal pre-image with wildcards*/
	  /*file variable:
	  *PScount,  count of partial pre-images in toggled stacks*/
#      endif

 signed int
     Tcell,    /*target cell index*/
     z,zz,i,endz,
     Rtable,   /*rule table index*/
     tablemax, /*highest index in rule table*/
     tablebytes,/*no of bytes               */
     byteno,
     tempx,tempy,
     possofw,  /*to deal pre-image with wildcards*/
     pp_temp;
 char exLeftMax,exRightMax,*temp_pn;

 //fprintf(stderr,"\n NULLboundaries=%d twod=%d",NULLboundaries,twod); //fprintf??

  attrepeat=0; /*1 if pre_image on attractor cycle*/
  if ((PS[1][0]=(char *)calloc(1,sizeof(char)))
					==NULL) outof_memory("PS[1][0]");
  if ((PSflag[1][0]=(char *)calloc(1,sizeof(char)))
					==NULL) outof_memory("PSflag[1][0]");
  for (z=0;z<=1;z++){
     if (z==1) byteno=bytesL;
     else byteno=1;
     if ((PS[0][z]=(char *)calloc(byteno,sizeof(char)))
					==NULL) outof_memory("PS[0][z]");
     if ((PSflag[0][z]=(char *)calloc(byteno,sizeof(char)))
					==NULL) outof_memory("PSflag[0][z]");
  }

  tog=0;
  tablemax=(signed int)pow(value_range,(double)nhood)-1;
  tablebytes=(signed int)ceil(((double)(value_bits * (tablemax+1)))/8);
  
  PScount[0]=1;   /*notional initial pp stack=1*/
  /*memset(PS[0][1],0,bytesL);
    memset(PSflag[0][1],0,bytesL);*/
  PScount[1]=0;
  if (!rulemix) memmove(arule,carule[0],tablebytes);
  if (see_ppstack){
     pp_histcount+=1;/*to find average histogram*/
     /*rescale y axis smaller*/
     if (ppL==lineL && pp_hist_max < pp_ymax/6){
	pp_ymax=pp_ymax*.75;
	if (pp_ymax<10) pp_ymax=10;
	ppL=0;
     }
     pp_hist_max=0;
     setup_ppstack_hist();
  }
  
  for (zz=lineL-1;zz>=0;zz--){   /*for each target cell*/
    if (reorderRBN==1) Tcell=cell_order[zz];
    else Tcell=zz;   
    
    if (nhood_mixed){
       tablemax=(signed int)pow(value_range,(double)nhoodm[Tcell])-1;
       tablebytes=(signed int)ceil(((double)(value_bits * (tablemax+1)))/8);
    }
    if (NULLboundaries==1 && oned && nhoodm[Tcell]>1){
      char countl=0,countr=0;
      signed int  exL,exR;
      //fprintf(stderr,"\nzz=%d Tcell=%d", zz,Tcell);
      //fprintf(stderr,"**********************************");
          if ((temp_pn=(char*)calloc(nhoodm[Tcell],sizeof(char)))
		      ==NULL) outof_memory("temp_pn");
                   
          if (nhoodm[Tcell]%2==1) exLeftMax=nhoodm[Tcell]/2;
          else exLeftMax=nhoodm[Tcell]/2 - 1;
          exRightMax=nhoodm[Tcell]/2;
          //check if i is outside left edge
          exL=exLeftMax-(L-Tcell);
          for (i=nhoodm[Tcell]-1;i>=0;i--){
                       countl+=1;
                       if (countl <= exL) temp_pn[i]=1;
                       else break;                       
                       
	 }
         //check if i is outside right edge
         exR=exRightMax-Tcell;
         for (i=0;i<=nhoodm[Tcell]-1;i++){
                       countr+=1;
                       if (countr <= exR) temp_pn[i]=1;
                       else break;
	 }
         /*fprintf(stderr,"temp_pn[i]=");
         if (newbit>0)for (i=nhoodm[Tcell]-1;i>=0;i--){ 
	   fprintf(stderr,"%d",temp_pn[i]);
         } 
         input_string(1,0);*/
    }               
    
    if (rulemix) memmove(arule,carule[Tcell],tablebytes);
    tog=abs(tog-1); /*toggle 0-1 for even-odd, first tog=1*/
    /*de-allocate mem in current stack*/
    
    if (PScount[tog]>0){
	for (zu=1;zu<=PScount[tog];zu++){
	      free(PS[tog][zu]);
	      free(PSflag[tog][zu]);
	}
	/*realloc mem for new pp stack stack PS[tog][set count to 0]*/
	if ((PS[tog]=(char**)realloc(PS[tog],sizeof(char*)))
				  ==NULL) outof_memory("PS[tog]");
	if ((PSflag[tog]=(char**)realloc(PSflag[tog],sizeof(char*)))
				  ==NULL) outof_memory("PSflag[tog]");
    }
    PScount[tog]=0;  /*set new pre-image count to 0*/
    /*for each item in previous partial pre-image stack*/
    for (ppstack=1;ppstack<= PScount[abs(tog-1)];ppstack++){
       //fprintf(stderr,"\nRtable=%lu:",ppstack);

       for (Rtable=tablemax;Rtable>=0;Rtable--){
	  //fprintf(stderr,"\nRtable=%d:",Rtable);
         
	  if (value_range==2){
             /*reject rule table entries that dont match target cell*/
             if (get_bit(state1,Tcell)!=get_bit(arule,Rtable)) continue;         
	     /*skip redundant rule table entries*/
	     if (NULLboundaries==0 && get_bit(skiptable[Tcell],Rtable)==1) continue;
          }
          else{
             /*reject rule table entries that dont match target cell*/
             if (get_value(state1,Tcell)!=get_value(arule,Rtable)) continue;
          } 
	  /*copy partial pre-image from stack to temp bitstring*/
	  memmove(PStemp,PS[abs(tog-1)][ppstack],bytesL);
	  /*copy parrallel flag array from flag stack to temp bitstring*/
	  memmove(flagtemp,PSflag[abs(tog-1)][ppstack],bytesL);

          if (value_range==2 && NULLboundaries==0) endz=nhoodE[Tcell][Rtable];
	  else endz=0;

          //fprintf(stderr,"\nppstack=%lu:",ppstack);
          for (z=nhoodm[Tcell]-1;z>=endz;z--){
	     /*get new bit from pseudo-nhood*/
                          
             if (value_range==2) newbit = get_bit(nm[z],Rtable); 
             else newbit = get_value(nm[z],Rtable);

             if (NULLboundaries==1 && oned && nhoodm[Tcell]>1){
	       if (temp_pn[z]==1){
		     if (newbit>0){//only zeros are allowed beyond edges 
		        conflict=1;
                        break;
                     }
                     else if (newbit==0){
		        //fprintf(stderr,"*");
                        conflict=0;
                        continue;//leave as wildcard
		     }
               }
               if (conflict==1){
		   conflict=0;
                   //fprintf(stderr," conflict!");
		   break;
	       }
             }
	               
	     /*get value at wire coupling, 0,1 or value*/
	     if (value_range==2) PSbit =  get_bit(PStemp,wiring[Tcell][z]);
             else PSbit =  get_value(PStemp,wiring[Tcell][z]);

	     existbit=get_bit(flagtemp,wiring[Tcell][z]);
	     /*fprintf(stderr," %d:%d=%d", 
	             z,PSbit,existbit);*/ 
	     /*ERROR - if bits conflict and  bit set reject psuedo-nhood*/
             if (PSbit>=1 && existbit==0){
		tempx=getx;
		tempy=gety;
		draw_prompt_box(1);
		sprintf(textb[0],
		  "ERROR - PSbit=%d so existbit should=1 (=%d)",
						       PSbit,existbit);
		outtext(textb[0]);
                input_string(1,0);
		/*finish_options(1);*/
		moveto(tempx,tempy);
	     }
	     /*if bits conflict and  bit set reject psuedo-nhood*/
	     if (newbit!=PSbit && existbit==1){
		conflict=1;
                //fprintf(stderr," conflict!");
		break;
	     }
             /*if bit empty insert a new bit, set flag*/
	     if (value_range==2){
                 if (newbit!=PSbit) set_bit(PStemp,wiring[Tcell][z],newbit);
             }
             else{ 
                 if (newbit!=PSbit) set_value(PStemp,wiring[Tcell][z],newbit);
             }
             //fprintf(stderr,"%d",newbit);
	    
	     /*flag the new bit as existing*/
	     if (existbit!=1) set_bit1(flagtemp,wiring[Tcell][z]);
	  } // for (z=nhoodm[Tcell]-1;z>=endz;z--){...

          if (conflict==1){
		conflict=0;
		continue; //to next Rtable
	  }
	  PScount[tog]+=1;
	  /*realloc mem for new pp stack stack PS[tog][PScount[tog]]*/
	  sprintf(textb[0],"bigger pp stack=%lu",PScount[tog]);
	  if ((PS[tog]=(char**)realloc(PS[tog],(PScount[tog]+1)*
			sizeof(char*)))==NULL) outof_memory(textb[0]);
	  if ((PSflag[tog]=(char**)realloc(PSflag[tog],(PScount[tog]+1)*
			sizeof(char*)))==NULL) outof_memory(textb[0]);
	  if ((PS[tog][PScount[tog]]=(char*)calloc(bytesL,sizeof(char)))
					  ==NULL) outof_memory(textb[0]);
	  if ((PSflag[tog][PScount[tog]]=(char*)calloc(bytesL,sizeof(char)))
					  ==NULL) outof_memory(textb[0]);
	  /*copy partial pre-image to next pp stack*/
	  memmove(PS[tog][PScount[tog]],PStemp,bytesL);
	  /*copy parrallel flag array to next flag stack*/
	  memmove(PSflag[tog][PScount[tog]],flagtemp,bytesL);
       }/*next Rtable*/
    }/*next ppstack*/

    if (PScount[tog]==0){
       if (NULLboundaries==1 && oned && nhoodm[Tcell]>1){ 
          free(temp_pn);
          //fprintf(stderr,"\ntest_nhood freed!");
       }
       break; //for (zz=lineL-1;zz>=0;zz--){  for each target cell
    }
    /*show partial pre-image histogram*/
    if (see_ppstack){ /*to find average histogram*/
  
       pp_hist_total[zz]+=PScount[tog];
       pp_hist[Tcell]=PScount[tog];
       /*rescale y axis bigger*/
       if (PScount[tog]>pp_ymax){
	  pp_ymax=PScount[tog]*1.2;
	  ppL=0;
	  setup_ppstack_hist();

          setviewport(pp_startx0,pp_starty0-pp_depthy,
			     pp_startx0+pp_widthx,pp_starty0,0);
	  for (z=lineL-1;z>=zz;z--){ /* ..was z>=Tcell*/
	     pp_heighty=(signed int)(vgax(120)*(float)pp_hist[zz]/pp_ymax);
             if (pp_heighty>pp_ymax) pp_heighty=pp_ymax;/*bar max=window height*/             
	     bar(pp_startx,pp_starty-pp_heighty,
				   pp_startx+pp_barwidth,pp_starty);                         
	     pp_startx+=pp_bartotw;
	  }
          setviewport(0, 0, Maxx, Maxy, 0);
       }
       else{
	  pp_heighty=(signed int)(vgax(120)*(float)PScount[tog]/pp_ymax);
          setviewport(pp_startx0,pp_starty0-pp_depthy,
			     pp_startx0+pp_widthx,pp_starty0,0);
	  bar(pp_startx,pp_starty-pp_heighty,
				   pp_startx+pp_barwidth,pp_starty);
          setviewport(0, 0, Maxx, Maxy, 0);
	  pp_startx+=pp_bartotw;
       }
    }
    if (pp_hist_max < pp_hist[Tcell]) pp_hist_max=pp_hist[Tcell];

    if (NULLboundaries==1 && oned && nhoodm[Tcell]>1) free(temp_pn);
    
  }//for (zz=lineL-1;zz>=0;zz--){  for each target cell*/

  if (PScount[tog]>0){
     signed int Tcell1;
      wildpre=0;
      while (wildpre<PScount[tog]){
	 wildpre+=1;
	 while(1){
	    possofw=-1;
	    for (z=lineL-1;z>=0;z--){
               if (reorderRBN==1) Tcell1=cell_order[z];
               else Tcell1=z;
	       if (get_bit(PSflag[tog][wildpre],Tcell1)==0){
		  possofw=Tcell1;
                  /*fprintf(stderr,"%d",possofw);*/
		  break;
	       }
	    }
	    /*wildcard not found*/
	    if (possofw==-1) break;
            
            for (i=value_range-1;i>0;i--){
	       /*wildcard found - undo wildcard in PSflag*/
	       set_bit1(PSflag[tog][wildpre],possofw);
	       /*copy pre-image to PStemp*/
	       memmove(PStemp,PS[tog][wildpre],bytesL);
	       /*copy parrallel flag array to flagtemp*/
	       memmove(flagtemp,PSflag[tog][wildpre],bytesL);
	       /*set 1 at wildcard poss in temp array*/

	       if (value_range==2) set_bit1(PStemp,possofw);
               /*set all possible values*/
               else set_value(PStemp,possofw,i);

	       PScount[tog]+=1;
	       /*realloc mem for new pp stack stack PS[tog][PScount[tog]]*/
	       sprintf(textb[0],"wildpre, pp stack=PScount[tog]");
	       if ((PS[tog]=(char**)realloc(PS[tog],(PScount[tog]+1)*
			sizeof(char*)))==NULL) outof_memory(textb[0]);
	       if ((PSflag[tog]=(char**)realloc(PSflag[tog],(PScount[tog]+1)*
			 sizeof(char*)))==NULL) outof_memory(textb[0]);
	       if ((PS[tog][PScount[tog]]=(char*)calloc(bytesL,sizeof(char)))
				      ==NULL) outof_memory(textb[0]);
	       if ((PSflag[tog][PScount[tog]]=(char*)calloc(bytesL,
			       sizeof(char)))==NULL) outof_memory(textb[0]);
	       /*copy temp arrays to top of pre-image stack*/
	       memmove(PS[tog][PScount[tog]],PStemp,bytesL);
	       memmove(PSflag[tog][PScount[tog]],flagtemp,bytesL);
            }
	 }
      }
      /*count pre-images due to wildcards*/
      if (see_ppstack 
               &&  PScount[tog] > pp_hist[0] /*<-- hack: why would this not be true?*/
               &&  PScount[tog] - pp_hist[0]>0){
	 pp_wild=(signed int)(PScount[tog]-pp_hist[0]);
	 pp_wild_tot+=pp_wild;

	 pp_startx-=pp_bartotw;
#        if __WATCOM__	 
	    setfillstyle(INTERLEAVE_FILL,red);
#        elif __UNIX__	 
	    setfillstyle(SOLID_FILL,yellow);
#        endif
       
	 pp_temp=pp_starty-pp_heighty-1
	    -(signed int)vgax(120)*(float)pp_wild/pp_ymax;
	 if (pp_temp < pp_starty0-pp_depthy+1)
			       pp_temp=pp_starty0-pp_depthy+1;

         setviewport(pp_startx0,pp_starty0-pp_depthy,
			     pp_startx0+pp_widthx,pp_starty0,0);
	 bar(pp_startx,pp_temp,
	             pp_startx+pp_barwidth,pp_starty-pp_heighty-1);
         setviewport(0, 0, Maxx, Maxy, 0);

         if (see_ppstack==2)
             sprintf(textb[0],
              "pre=%lu (wild=%d) abandon pause-p, early exit-q, see next-def:",
	                PScount[tog],pp_wild);
      }
      else if (see_ppstack==2)
        sprintf(textb[0],
          "pre=%lu abandon pause-p, early exit-q, see next-def:",PScount[tog]);

      if (see_ppstack==2){
	 tempx=getx;
	 tempy=gety;
	 draw_prompt_box(1);
	 outtext(textb[0]);
	 input_string(1,0);
	 if (is[0]=='p'){
	    erase_prompt_box(1);
            back_onthefly_prompts();
	    see_ppstack=1;
            sprintf(textb[0],"partial pre-image histogram: start pause-p");
	    draw_prompt_box(1);
	    outtext(textb[0]);
	 }
	 moveto(tempx,tempy);
      }

      for (zu=1;zu<=PScount[tog];zu++){
	 /*check for cycle repeat, rotation (from all 0s or 1s),
						if ok add, print*/
	 if (check_pre_image(PS[tog][zu])==1) continue;
	 accept_pre_image(PS[tog][zu]);
      }
  }
  for (zz=0;zz<=1;zz++){
     for (zu=0;zu<=PScount[zz];zu++){
	free(PS[zz][zu]);
	free(PSflag[zz][zu]);
     }
  }

  return;
}

/** compute pre-images 1D local, 1 rule or mixed May 93 - rev Dec 93 ****/
void pre_images_binary(void){
  unsigned int 
      ppindex,     /*continue pp from ppindex....*/
      *ppend,            /*holds index reached by pp*/
      bytereached,  /*pos of index in countdown of bytes in B*/
      n,m;
  signed int
      u,u1,ur,i,		/*n'hood value*/
      z,tablebytes;  /*no of bytes               */
  char **pp,       /*array of pointers to partial pre-images pointers*/
       trypp=0,failpcheck=0,
       nrad,oddrad=0,ppcomplete,tu1;
  unsigned long ppcount=0,  /*count of partial pre-images in queue*/
		maxppcount=0;

  char exRightMax;

    attrepeat=0; /*1 if pre_image on attractor cycle*/

    if ((pp=(char**)calloc(1,sizeof(char*)))==NULL) outof_memory("pp");
    if ((ppend=(unsigned int*)calloc(1,sizeof(unsigned int)))
				 ==NULL) outof_memory("ppend");
	/*	nhood=3     nhood=4     asymmetric nhood is
		o o *       o o o *     wider on the right
		\ | /       \ | / /
		  T           T         */
    nrad=nhood/2;
    if (nhood%2==0){ //even nhood
	nrad-=1;
	oddrad=1;
    }
    /* bitstrings state1, stateB and pp:

	       L        n             0
	       |        |             |
	     --------|--------|--------      .........state1
		   2        1        0

	      L+8       m m-nrad      8        0
	      |	 |      | |           |        |
    --------|--------|--------|--------|--------  ....stateB
	  4        3        2        1        0

		   set to 1  0
			  |  |
    --------|--------|--------     ...................pp
	  2        1        0
    */
    memset(stateB,0,bytesL+2*stateB_extra); /*set all bits in stateB to 0*/
    for (z=nhood-2+oddrad;z>=0;z--) 
           set_bit(stateB,8*stateB_extra +L +z-(nrad+oddrad-1),pre_start[z]);

    /*fprintf(stderr,"\nstateB=");
    for (z=8*stateB_extra +L +(nhood-2+oddrad)-(nrad+oddrad-1);z>=0;z--)
                 fprintf(stderr,"%d",get_value(stateB,z));
    fprintf(stderr,"\nstate1=");
    for (z=L;z>=0;z--)
                 fprintf(stderr,"%d",get_value(state1,z));

    input_string(1,0);*/

    /*	     +8 L(+8)          NOTE: to accommodate for k>16, 
		 |             stateB needs 2 extra bytes (16 bits) at each end                                     
	 =1      --------      instead of 1 byte (8 bits) at each end
	 =2 	 x-------
	 =3	xx-------
	 =4     xxx------       assumed start strings for
	 =5    xxxx------       different size nhoods
	 =6    xxxxx-----
	 =7   xxxxxx-----
	 =8   xxxxxxx----
	 =9  xxxxxxxx----    */
    ppindex=L;
    tablebytes=(signed int)ceil(pow(2,(double)nhood)/8);
    /*homogenious rule*/
    if (!rulemix){
	memmove(arule,carule[0],tablebytes);
	memmove(arule1,carule[0],tablebytes);
	memmove(arule2,carule[0],tablebytes);
    }

    if (NULLboundaries==1) exRightMax=nhood/2;


 pre1:
    //fprintf(stderr,"\n");
    for (n=ppindex;n!=Maxu;n--){      /* from pp string left to right ----->*/
        //fprintf(stderr,"\n");
#if     __DARWIN__
        fprintf(stderr,""); //for NULLb, without this there's a Mac segfault!??
#endif
	if (rulemix){
	   memmove(arule,carule[n],tablebytes);                 /*rule at n*/
	   memmove(arule1,carule[(lineL+n-1)%lineL],tablebytes);/*rule at n-1*/
	   memmove(arule2,carule[(lineL+n+1)%lineL],tablebytes);/*rule at n+1*/
	}
	/*backwards logic*/
	m=n+8*stateB_extra;
     
     if (NULLboundaries==1 && nhood>1 && n < exRightMax){ //set next bit right end to 0
            /*excluded permutation left->right, 21*->T,321*->T
	      nhood ending with 0*/
	    u=0; i=nhood;
	    for (z=nrad;z>=1-nrad-oddrad;z--){                
		i--;                              
		u += get_bit(stateB, m+z) * (signed int)pow(2,(double)i);
	     }
	     if (get_bit(arule,u)==get_bit(arule,u+1)
				     && get_bit(state1,n)!=get_bit(arule,u)){
		trypp=1;
		break;
	     }

             /*deterministic permutation  left->right*/
	     if (get_bit(arule,u)!=get_bit(arule,u+1)){
	        if (get_bit(state1,n)==get_bit(arule,u)){
		   set_bit0(stateB,m-nrad-oddrad);/*right end of nhood=0*/
                   continue;
                }
		else{ 
                    trypp=1;
		    break;
                }
             }            
      }

      else { //normal (periodic), (inc NULL if central)  logic
	/*excluded permutation left->right, 21*->T,321*->T
	  nhood ending with 0*/
	u=0; i=nhood;
	for (z=nrad;z>=1-nrad-oddrad;z--){                
		i--;                              
		u += get_bit(stateB, m+z) * (signed int)pow(2,(double)i);
	}
	if (get_bit(arule,u)==get_bit(arule,u+1)
				     && get_bit(state1,n)!=get_bit(arule,u)){
		trypp=1;
		break;
	}

	/*excluded permutation right->left,T<-*10, T<-*3210
	  nhood starting with 0*/
        if (NULLboundaries==0){
	   ur=0;i=nhood-1;
	   for (z=nrad;z>=1-nrad-oddrad;z--){
		i--;
		ur = ur + get_bit(stateB, m+z) * (signed int)pow(2,(double)i);
	   }
	   if (get_bit(arule2,ur)
	        ==get_bit(arule2,ur+(signed int)pow(2,(double)nhood)/2)
			&& get_bit(state1,(lineL+n+1)%lineL)!=get_bit(arule2,ur)){
		trypp=1;
		break;
	   }
	}

	/*deterministic permutation  left->right*/
	if (get_bit(arule,u)!=get_bit(arule,u+1)){
		if (get_bit(state1,n)==get_bit(arule,u))
			set_bit0(stateB,m-nrad-oddrad);/*right end of nhood=0*/
		else set_bit1(stateB,m-nrad-oddrad);/*right end of nhood=1*/
		/*check boundary conditions*/
                if (nhood>1 && NULLboundaries==0){
		      if (n<=nhood-2 && pre_start[n]!=get_bit(stateB,m-nrad-oddrad)){
			   trypp=1;
			   break;
		      }
                }
		continue;
	}
	/* else if ambiguous permutation*/
	set_bit0(stateB,m-nrad-oddrad);/*next cell could be both 1 and 0, assume 0*/
        /*end basic backwards logic*/

        /*extra checks, not applicable NULLboundaries, or for nhood=1*/
        if (nhood>1 && NULLboundaries==0){ 
	   /*shift right nhood ending with 0*/
	   u1=0;i=nhood;
	   for (z=nrad-1;z>=-nrad-oddrad;z--){
		i--;
		u1 += get_bit(stateB, m+z) * pow(2,(double)i);
	   }

	   if (get_bit(arule1,u1)==get_bit(arule1,u1+1)){
	      /*check for deterministic permutation 2-tuples pairs unequal
			   A *  B *
			     |    |
			    -2    2    */
	      if (u1%4==0) tu1=2;
	      else tu1=-2;
	      if (get_bit(arule1,u1)!=get_bit(arule1,u1+tu1) &&
			    get_bit(arule1,u1+tu1)==get_bit(arule1,u1+tu1+1)){
	         if (get_bit(state1,(lineL+n-1)%lineL)==get_bit(arule1,u1)){
			    if (tu1==2) set_bit0(stateB,m-nrad-oddrad);
			    else set_bit1(stateB,m-nrad-oddrad);
		 }
		 else{
			    if (tu1==2) set_bit1(stateB,m-nrad-oddrad);
			    else set_bit0(stateB,m-nrad-oddrad);
		 }
		 /*check boundary conditions*/
		 if (n<=nhood-2 && pre_start[n]!=get_bit(stateB,m-nrad-oddrad)){
			trypp=1;
			break;
		 }
		 continue;
               }
	       /*
	       shift ppindex->right,
	       check for excluded permutation 21*->T, 4321*->T
	       if excluded change assumed next cell from 0 to 1
	       */
	      if (get_bit(state1,(lineL+n-1)%lineL) !=get_bit(arule1,u1)){ 
	          set_bit1(stateB,m-nrad-oddrad);
	          /*check  if 1 is compatible with boundary conditions*/
	          if (n<=nhood-2 && pre_start[n]!=1){
			trypp=1;
			break;
	          }
	          continue;
	      }
	   }

	   /* end extra backwards logic*/
	   if (n<=nhood-2 && pre_start[n]!=1){/*check boundary for*/
		continue;         /*alternative ending in 1*/
	   }                    /*to be added to pp stack*/                  
	}

	ppcount ++;    /*ppcount=partial preimage no*/
	if (maxppcount<ppcount){
	   maxppcount=ppcount;
	   if( (pp=(char**) realloc(pp,sizeof(char*)*(ppcount+1)))
					==NULL) outof_memory("pp");
	   if((ppend=(unsigned int*)realloc
		(ppend,sizeof(unsigned int)*(ppcount+1)))
					==NULL) outof_memory("ppend");
	}
	if (see_ppstack  && ppcount<vgax(150)){  /*increace bar showing pp stack*/
	   /*fprintf(stderr,"%lu ",ppcount);*/
	   setcolor(yellow);

	   setfillstyle(SOLID_FILL,yellow);
#          if __UNIX__
	      bar(vgax(125),Maxy-vgay(40),vgax(125)+vgax(ppcount),Maxy-vgay(34));
#          elif __WATCOM__
	      line(vgax(140)+vgax(ppcount),Maxy-vgay(40),
				   vgax(140)+vgax(ppcount),Maxy-vgay(34));
#          endif

           setcolor(white);
	}

	/*in stateB*/        
	bytereached=(m-nrad-oddrad)/8;    /* countdown*/
	/*alloc required bytes*/
	sprintf(textb[0],"pp[%lu]",ppcount);
	if ((pp[ppcount]=(char *)malloc(bytesL+2*stateB_extra-bytereached))
				      ==NULL) outof_memory(textb[0]);
	memset(pp[ppcount], 0, bytesL+2*stateB_extra-bytereached);
	/*signed int array holding ppend index - to be continued from this*/
	ppend[ppcount]=n;
	memmove(pp[ppcount],stateB+bytereached,bytesL+2*stateB_extra-bytereached);
	set_bit1(pp[ppcount],(m-nrad-oddrad)%8);   /*set last bit to 1*/

    } //normal (periodic) logic

    }  /*** next n ***/

    if (trypp==1){
	trypp=0;
	goto pre3;
    }
 pre2:
    if (NULLboundaries==0){
       failpcheck=0;         /*periodic boundary check*/
       if (nhood>1){
          for (z=nhood-2;z>=0;z--){
             if (pre_start[z]!=get_bit(stateB,8*stateB_extra+z-nrad-oddrad)){
	        failpcheck=1;
	        break;
             }
          }
       }
       if (failpcheck==1) goto pre3;
    }

    /*pp line is now complete and valid*/
    /*set_bits in stateB beyond L to 0, allows bytes to be compared*/
    for (z=(bytesL+1*stateB_extra)*8-1;z>=L+1;z--) set_bit0(stateB,z+8*stateB_extra);

    /*check for cycle repeat, rotation (from all 0s or 1s, if ok add, print*/
    if (check_pre_image(stateB+1*stateB_extra)==1) goto pre3;
    accept_pre_image(stateB+1*stateB_extra);
    /*if interrupt*/
    interrupt_pre_fan();
    if (is[0]=='q' || is[0]=='n'){
       for (z=1;z<=ppcount;z++) free(pp[z]);
       free(pp);
       free(ppend);
       ppcount=0;
       return;
    }
 pre3:
    if (ppcount==0){
       free(pp);
       free(ppend);
       return;  /*preim stack empty*/
    }
    ppcomplete=0;
    if (ppend[ppcount] == 0) ppcomplete=1;
    memset(stateB,0,bytesL+2*stateB_extra); /*set all bits in stateB to 0*/
    bytereached=(8*stateB_extra+ppend[ppcount]-nrad-oddrad)/8; /* countdown*/
    memmove(stateB+bytereached,pp[ppcount],bytesL+2*stateB_extra-bytereached);

    ppindex=ppend[ppcount]-1;
    free(pp[ppcount]);
    ppcount--;    
    if (see_ppstack && ppcount+1<vgax(150)){  /*decrease bar showing pp stack*/
       setcolor(black);
#      if __UNIX__
	  line(vgax(125)+vgax(ppcount+1),Maxy-vgay(40),
		     vgax(125)+vgax(ppcount+1),Maxy-vgay(34));
#      elif __WATCOM__
	  line(vgax(140)+vgax(ppcount+1),Maxy-vgay(40),
		     vgax(140)+vgax(ppcount+1),Maxy-vgay(34));
#      endif


       setcolor(white);
    }
    if (ppcomplete==1) goto pre2;
    goto pre1;
}

/** compute multi-value pre-images 1D local, 1 rule or mixed 2003 ***/
void pre_images_multi_state(void){
  unsigned int 
      ppindex,     /*continue pp from ppindex....*/
      *ppend,            /*holds index reached by pp*/
      n,m;	         
  signed int
      z,u,i, 	    
    tablemax,tablebytes,  /*no of bytes*/   
      target,next_right,count;

  char **pp,       /*array of pointers to partial pre-images pointers*/
       trypp=0,failpcheck=0,
       nrad,oddrad=0,ppcomplete,problem;
  unsigned long ppcount=0,  /*count of partial pre-images in queue*/
		maxppcount=0;

  char exRightMax;

    attrepeat=0; /*1 if pre_image on attractor cycle*/

    if ((pp=(char**)calloc(1,sizeof(char*)))==NULL) outof_memory("pp");
    if ((ppend=(unsigned int*)calloc(1,sizeof(unsigned int)))
				 ==NULL) outof_memory("ppend");
	/*	nhood=3     nhood=4     asymmetric nhood is
		o o *       o o o *     wider on the right
		\ | /       \ | / /
		  T           T         */
    nrad=nhood/2;
    if (nhood%2==0){
        nrad-=1;     /*left of center*/
	oddrad=1;  /*left of center*/
    }
    /* bitstrings state1, stateB and pp:

	       L        n             0
	       |        |             |
	     --------|--------|--------      .........state1
		   2        1        0

	      L+8       m m-nrad      8        0
	      |	 |      | |           |        |
    --------|--------|--------|--------|--------  ....stateB
	  4        3        2        1        0

		   set to 1  0
			  |  |
    --------|--------|--------     ...................pp
	  2        1        0
    */
    memset(stateB,0,bytesL+2*stateB_extra*value_bits); /*set all bits in stateB to 0*/
    /*load start string*/
    /*fprintf(stderr,"\n new start string\n");
    for (z=nhood-2;z>=0;z--)
                 fprintf(stderr,"%d",pre_start[z]);*/

    for (z=nhood-2+oddrad;z>=0;z--) 
            set_value(stateB,8*stateB_extra +L +z-(nrad+oddrad-1),pre_start[z]);

    /*fprintf(stderr,"\n");
    for (z=8*stateB_extra +L +(nhood-2+oddrad)-(nrad+oddrad-1);z>=0;z--)
                 fprintf(stderr,"%d",get_value(stateB,z));
    fprintf(stderr,"\n ");
    for (z=L;z>=0;z--)
                 fprintf(stderr,"%d",get_value(state1,z));*/
    
    
    /*		 L(+8)
		 |
	 =1      --------
	 =2 	 x-------
	 =3	xx-------
	 =4     xxx------       assumed start strings for
	 =5    xxxxx-----       different size nhoods
	 =6    xxxxxx----
	 =7   xxxxxxx----
	 =8   xxxxxxxx---
	 =9  xxxxxxxxx---    */
    ppindex=L;
    tablemax= (signed int)pow(value_range,(double)nhood)-1;
    tablebytes=(signed int)ceil(value_bits * (double)(tablemax+1)/8);
    /*homogenious rule*/
    if (!rulemix)
	memmove(arule,carule[0],tablebytes);

    if (NULLboundaries==1) exRightMax=nhood/2;
   
 pre1:
    for (n=ppindex;n!=Maxu;n--){      /* from left to right  ----->*/
        /*fprintf(stderr,"\n n=%d",n);*/
#if     __DARWIN__
        fprintf(stderr,""); //for NULLb, without this there's a Mac segfault!??
#endif
	if (rulemix) memmove(arule,carule[n],tablebytes);  /*rule at n*/
	   
	/*backwards logic*/
	m=n+8*stateB_extra;
        target=get_value(state1,n); 

    
    if (NULLboundaries==1 && nhood>1 && n < exRightMax){ //set next bit right end to 0 
	/*excluded permutation left->right, 21*->T,321*->T
	  nhood ending with 0*/
        /* u = dec index of moving start string in preimage*/
	u=0; i=nhood;
        /*fprintf(stderr,"\n");*/
	for (z=nrad;z>=1-nrad-oddrad;z--){
	   i--;
           u += get_value(stateB, m+z) * (signed int)pow(value_range,(double)i);
	}
        /*fprintf(stderr,"=%d\n",u);*/ 
        /*check pattern of outputs from this muple of left->right nhoods*/
        memset(kv_out,0,value_range);
        memset(kv_freq,0,value_range);
        problem=0;
        for (i=u;i<=u+value_range-1;i++){
	    /*fprintf(stderr,"\ni=%d u=%d\n",i,u);*/

	    kv_out[i-u]=get_value(arule,i);
            kv_freq[get_value(arule,i)]+=1;

            if (kv_freq[get_value(arule,i)]>value_range){
	       fprintf(stderr,
                "\n u=%d i=%d kv_freq[%d]=%d",u,i,get_value(arule,i),
                                      kv_freq[get_value(arule,i)]);
	       problem=1;
               input_string(1,0);
	    }
        }
        if (problem==1){
           fprintf(stderr,"\nkv_out,kv_freq=");
           for (i=value_range-1;i>=0;i--) fprintf(stderr,"%d",kv_out[i]); 
           fprintf(stderr," ");
           for (i=value_range-1;i>=0;i--) fprintf(stderr,"%d",kv_freq[i]);
           fprintf(stderr," kv_freq[%d]=%d",target,kv_freq[target]);
           input_string(1,0);
        }

        /*forbidden left->right*/
        if (kv_freq[target]==0){ 
           trypp=1;
           /*fprintf(stderr,"\n ****ABORT at cell %d",n);*/
	   break;
	}
        /*deterministic or ambiguous left->right*/
        else if (kv_freq[target]>=1){
             if (kv_out[0]==target){
               set_value(stateB,m-nrad-oddrad,0);
               continue;
	   }
           else{ 
                trypp=1;
		break;
           } 
        }	
     }

     else { //normal (periodic) logic
	/*excluded permutation left->right, 21*->T,321*->T
	  nhood ending with 0*/
        /* u = dec index of moving start string in preimage*/
	u=0; i=nhood;
        /*fprintf(stderr,"\n");*/
	for (z=nrad;z>=1-nrad-oddrad;z--){
	   i--;
           u += get_value(stateB, m+z) * (signed int)pow(value_range,(double)i);
           /*fprintf(stderr,"%d+",
	     get_value(stateB, m+z) * (signed int)pow(value_range,(double)i));*/
	}
        /*fprintf(stderr,"=%d\n",u);*/ 
        /*check pattern of outputs from this muple of left->right nhoods*/
        memset(kv_out,0,value_range);
        memset(kv_freq,0,value_range);
        problem=0;
        for (i=u;i<=u+value_range-1;i++){
	    /*fprintf(stderr,"\ni=%d u=%d\n",i,u);*/

	    kv_out[i-u]=get_value(arule,i);
            kv_freq[get_value(arule,i)]+=1;

            if (kv_freq[get_value(arule,i)]>value_range){
	       fprintf(stderr,
                "\n u=%d i=%d kv_freq[%d]=%d",u,i,get_value(arule,i),
                                      kv_freq[get_value(arule,i)]);
	       problem=1;
               input_string(1,0);
	    }
        }
        if (problem==1){
           fprintf(stderr,"\nkv_out,kv_freq=");
           for (i=value_range-1;i>=0;i--) fprintf(stderr,"%d",kv_out[i]); 
           fprintf(stderr," ");
           for (i=value_range-1;i>=0;i--) fprintf(stderr,"%d",kv_freq[i]);
           fprintf(stderr," kv_freq[%d]=%d",target,kv_freq[target]);
           input_string(1,0);
        }

        /*forbidden left->right*/
        if (kv_freq[target]==0){ 
           trypp=1;
           /*fprintf(stderr,"\n ****ABORT at cell %d",n);*/
	   break;
	}
        /*deterministic left->right*/
        else if (kv_freq[target]==1){
	   /* which muple has the output "target" ? */
	   for (i=0;i<=value_range-1;i++){
	      if (kv_out[i]==target){
	         next_right=i;
                 break;
              }
	   } 
           set_value(stateB,m-nrad-oddrad,next_right);
           /*check boundary conditions*/
           if (NULLboundaries==0 && nhood>1){
	      if (n<=nhood-2 && pre_start[n]!=next_right){
	          trypp=1;
                  /*fprintf(stderr,"\n ****ABORT at cell %d",n);*/
	          break;
	      }
           }
           /*fprintf(stderr,"\n ");
           for (z=L+8;z>=m-nrad-oddrad;z--){
              fprintf(stderr,"%d",get_value(stateB,z));
           }
           fprintf(stderr,"= stateB up to cell %d",n);*/
	   continue;
        }
        /*ambiguous left->right*/
	else if (kv_freq[target]>1){ 
	   count=0;
           for (i=0;i<=value_range-1;i++){
             if (count>kv_freq[target]) break;
	     if (kv_out[i]==target){
                count+=1;
                if (count==1){
                   next_right=i;
                   set_value(stateB,m-nrad-oddrad,next_right);
                
                   /*fprintf(stderr,"\n ");
                   for (z=L+8;z>=m-nrad-oddrad;z--){
                      fprintf(stderr,"%d",get_value(stateB,z));
                   }
                   fprintf(stderr,"= stateB up to cell %d, other ends: ",n);*/
                }
                /* keep other next_rights*/ 
                else{ 
                   next_right_stack[count-2]=i;
                   /*fprintf(stderr,"[%d]=%d ",count-2,next_right_stack[count-2]);*/
                } 
	     }
	   }
        }
          
	ppcount += (kv_freq[target]-1);  /*inc partial preimage count*/

        /*fprintf(stderr,"\n *** freq=%d: add %d to stack: ppcount=%lu",
	  kv_freq[target], kv_freq[target]-1,ppcount);*/

	if (maxppcount<ppcount){
	   maxppcount=ppcount;
	   if( (pp=(char**) realloc(pp,sizeof(char*)*(ppcount+1)))
					==NULL) outof_memory("pp");
	   if((ppend=(unsigned int*)realloc
		(ppend,sizeof(unsigned int)*(ppcount+1)))
					==NULL) outof_memory("ppend");
	}
	if (see_ppstack  && ppcount<vgax(150)){  /*increace bar showing pp stack*/
	   setcolor(yellow);

#          if __UNIX__
	      bar(vgax(125),Maxy-vgay(40),vgax(125)+vgax(ppcount),Maxy-vgay(34));
#          elif __WATCOM__
	      line(vgax(140)+vgax(ppcount),Maxy-vgay(40),
				   vgax(140)+vgax(ppcount),Maxy-vgay(34));
#          endif

	   setcolor(white);
	}
	count=0;
        for (i=ppcount+1-(kv_freq[target]-1);i<=ppcount;i++){	   
           if ((pp[i]=(char*)calloc(bytesL+2*stateB_extra*value_bits,sizeof(char)))
				 ==NULL) outof_memory(textb[0]);
	   /*signed int array holding ppend index - to be continued from this*/
	   ppend[i]=n;
           memmove(pp[i],stateB,bytesL+2*stateB_extra*value_bits);
           /*set end value to alternative other values*/
           set_value(pp[i],m-nrad-oddrad,next_right_stack[count]);
           /*fprintf(stderr,"\npp[%d]=",i);
           for (z=L+8*stateB_extra;z>=m-nrad-oddrad;z--){
              fprintf(stderr,"%d",get_value(pp[i],z));
	   } */
           count++;          
        }
        /*fprintf(stderr,"\n *******added to stack*******");
	  input_string(1,0);*/

    }  //normal (periodic) logic

    }  /*** next n ***/


    if (trypp==1){
	trypp=0;
	goto pre3;
    }
 pre2:
    if (NULLboundaries==0){
       failpcheck=0;         /*periodic boundary check*/
       if (nhood>1){
          for (z=nhood-2;z>=0;z--){
             if(pre_start[z]!=get_value(stateB,8*stateB_extra+z-nrad-oddrad)){
	        failpcheck=1;
	        break;
             }
          }
       }
       if (failpcheck==1) goto pre3;
    }

    /*pp line is now complete and valid*/
    /*set_bits in stateB beyond L to 0, allows bytes to be compared*/
    for (z=16*stateB_extra+L;z>=L+8*stateB_extra+1;z--) set_value(stateB,z,0);

    /*check for cycle repeat, rotation (from all 0s or 1s, if ok add, print*/
    /*fprintf(stderr,"\nvalid pre-image=");
      for (z=L;z>=0;z--) fprintf(stderr,"%d",get_value(stateB+value_bits,z));*/

    if (check_pre_image(stateB+value_bits*stateB_extra)==1){
	 /*fprintf(stderr,"\n*****reject");*/
         goto pre3;
    }
    else{
       /*fprintf(stderr,"\n*****accept");*/
       accept_pre_image(stateB+value_bits*stateB_extra);
       /*input_string(1,0);*/
    }
    
    /*if interrupt*/
    interrupt_pre_fan();
    if (is[0]=='q' || is[0]=='n'){
       for (z=1;z<=ppcount;z++) free(pp[z]);
       free(pp);
       free(ppend);
       ppcount=0;
       return;
    }
 pre3:
    if (ppcount==0){
       free(pp);
       free(ppend);
       return;  /*preim stack empty*/
    }
    ppcomplete=0;
    if (ppend[ppcount] == 0) ppcomplete=1;
    memmove(stateB,pp[ppcount],bytesL+2*stateB_extra*value_bits);

    ppindex=ppend[ppcount]-1;
    free(pp[ppcount]);
    ppcount--;
    if (see_ppstack && ppcount+1<vgax(150)){  /*decrease bar showing pp stack*/
       setcolor(black);
#      if __UNIX__
	  line(vgax(125)+vgax(ppcount+1),Maxy-vgay(40),
		     vgax(125)+vgax(ppcount+1),Maxy-vgay(34));
#      elif __WATCOM__
	  line(vgax(140)+vgax(ppcount+1),Maxy-vgay(40),
		     vgax(140)+vgax(ppcount+1),Maxy-vgay(34));
#      endif

       setcolor(white);
    }
    if (ppcomplete==1) goto pre2;
    goto pre1;
}

/**** check pre-image for repeat, (if pre-im of all 0s or 1s) rotation,
		accept and print if ok **********************************/
char check_pre_image(char *pre_state){
  unsigned int
      repseg=0, /*lenth of segment repeating segment in circular ca-array*/
    tempx,tempy,z,zz,thislevel=0;
  signed int z0,z1;
  char rotrepeat, /*for rotation equivalent repeats*/
      reject=0;
  unsigned char tempcolor;

    /*check for pre-image on cycle*/
    if (level==0 && attperiod>0 && attrepeat==0){
       signed int i;
       isrepeat=1;
       //fprintf(stderr,"\ncompare pre-image with cycle");
       if (attindex>1){

	 /*fprintf(stderr,"\n");
          for (i=L;i>=0;i--) fprintf(stderr,"%d",get_value(pre_state,i));
          fprintf(stderr,"\n");
          for (i=L;i>=0;i--) fprintf(stderr,"%d",get_value(att[attindex-1],i));
	 */

	  if (memcmp(att[attindex-1],pre_state,bytesL)==0){ /*if same*/
	     attrepeat=1;
	     reject=1;
	     goto pre3;
	  }
       }
       else{
	  /*fprintf(stderr,"\n");
          for (i=L;i>=0;i--) fprintf(stderr,"%d",get_value(pre_state,i));
          fprintf(stderr,"\n");
          for (i=L;i>=0;i--) fprintf(stderr,"%d",get_value(att[attperiod],i));
	  */

	  if (memcmp(att[attperiod],pre_state,bytesL)==0){ /*if same*/             
	     attrepeat=1;
	     reject=1;
	     goto pre3;
	  }
       }
    }

    /*subtree only, check for repeat,
      if not, endless repeat if att cycle hit*/    
    if (isrepeat==0 && attperiod==0 && neutral_order==0){      
       /* can occur more than once if seed is all-0s or all-1s,
          otherwise just once
          note: don't use bitseed as this changes if "forward before backward"
        "this_firstseed" is either the actual seed, or the seed reached
         if a run was made forward before starting backward. 
         "firstseed" itself is either the same as "this_firstseed",
         or "firstseed" is the "segno" equivalent predecessors (in turn)
         of the all-0s or all-1s state. This is similar to successive states
         on an attractor cycle.*/
       if (memcmp(this_firstseed,pre_state,bytesL)==0 ||
                memcmp(firstseed,pre_state,bytesL)==0){/*if same*/
	  isrepeat=1;
          if (screensavedemo==0){
	      tempx=getx;
	      tempy=gety;
	      draw_prompt_box(1);
	      sprintf(textb[0],"repeat of seed");    
	      outtext(textb[0]);
              /*fprintf(stderr,"\n isrepeat=%d attperiod=%d neutral_order=%d",
                        isrepeat,attperiod, neutral_order);
	      input_string(1,0);*/	  
	      moveto(tempx,tempy);
	   }
           totatt_states=level+1;
	   reject=1;
	   goto pre3;
       }
    }
    /*if seed was all 0s or all 1s*/
    if (allbitssame==1 && insegloop==0  && !rulemix && !dontcompress
       && exhaustive_testing!=2 && NULLboundaries==0 &&
	     (!nonlocal || compress_1d_local==1 || regular2d)){
	  segfan=1; /*indicates condition above*/
	  memmove(tempState, pre_state, bytesL);
	  if (regular2d){
	     repeating_seg_2d(tempState);
	     if (repseg_2d[0]>1 && repseg_2d[1]>1)
					    trans_sym_2d(tempState);
	  }
	  else repseg=repeating_seg(tempState);
	  /*check for repeat with fan so far*/
	  rotrepeat=0;
	  if (segno>0){
	     /*check for repeats in previous segments*/
	     for (zz=1;zz<=segno;zz++){
		/*if rotation symmetry is different, dont bother*/
		if (regular2d){
		   if (seg_2d_h[zz]!=repseg_2d[0] ||
			     seg_2d_v[zz]!=repseg_2d[1]) continue;

		   for (z0=1;z0<=repseg_2d[0];z0++){
		      for (z1=1;z1<=repseg_2d[1];z1++){
			 if (memcmp(segseed[zz],tempState,bytesL)==0){
			    rotrepeat=1;
			    break;
			 }
			 rotate_array_2d(tempState,'u',1);
		      }
		      if (rotrepeat==1) break;
		      rotate_array_2d(tempState,'l',1);
		   }
		}
		else{
		   if (seg[zz]!=(signed int)repseg) continue;
		   for (z=1;z<=repseg;z++){
		      if (memcmp(segseed[zz],
			    rotate_array(nhood,
			             tempState,'l',0,1),bytesL)==0){
			 rotrepeat=1;
			 break;
		      }
		   }
		}
		if (rotrepeat==1) break;
	     }
	     /*reject*/
	     if (rotrepeat==1){
		reject=1;
		goto pre3;
	     }
	  }
	  segno+=1;    /*number rototation equivelent groups*/

	  sprintf(textb[0],"checking seg etc");
	  if (regular2d){
	     if( (seg_2d_h=(signed int*)realloc
		    (seg_2d_h, sizeof(signed int)*(segno+1)))
				    ==NULL) outof_memory(textb[0]);
	     if( (seg_2d_v=(signed int*)realloc
		    (seg_2d_v, sizeof(signed int)*(segno+1)))
				    ==NULL) outof_memory(textb[0]);

	     seg_2d_h[segno]=repseg_2d[0] ; /*repeating columns*/
	     seg_2d_v[segno]=repseg_2d[1] ; /*repeating rows*/
	  }
	  else {
	     if( (seg=(signed int*)realloc
		    (seg, sizeof(signed int)*(segno+1)))
				    ==NULL) outof_memory(textb[0]);
	     seg[segno]=repseg; /*repeating segment=size of groups*/
	  }
	  if( (segseed = (char**) realloc(segseed,sizeof(char*)*(segno+1)))
				    ==NULL) outof_memory(textb[0]);
	  if ((segseed[segno]=(char*)calloc(bytesL,sizeof(char)))
				    ==NULL) outof_memory(textb[0]);
	  memmove(segseed[segno],pre_state,bytesL);
    }
    precount++;
    nextindex++;
    
    
    if (screensavedemo==0 && nextindex-nextbefore>1 && (nextindex-nextbefore)%100==0){    
        tempcolor=getcolor();/*to monitor large pre-image fan*/
        setcolor(white);     /*otherwise it may seem nothing is happening*/
        tempx=getx;
        tempy=gety;  
        sprintf (textb[1],"level=%u fan=%lu+",level,nextindex-nextbefore); 
        inset_prompt_box(0,15,textb[1],'m'); 
        thislevel=level;
        setcolor(tempcolor);
        moveto(tempx,tempy);
    }
    //if (precount%100==0) fprintf(stderr,"\n%lu",precount); 

    /*abort subtree if nextindex>4294967295 (unsigned long)*/      
    if (nextindex==Maxlu){  
       abort_subtree=1;
       return(0);
    }

    if (stp){
       print_current_state(pre_state,lightred);
       end_page(scale,0);
    }

    if (exhaustive_testing){ /*tick off used state*/
       if (dontcompress==1 || (nonlocal && !regular2d) ||
	   exhaustive_testing==2 || NULLboundaries==1){
	          set_bitlong(tickoff,dec_equiv(pre_state,L),1);
       }
       else{
	  /*tickoff equivalents (all 0s or 1s)*/
	  if (allbitssame==1 && insegloop==0 && !rulemix){
	     memmove(tempState, pre_state, bytesL);
	     if (regular2d){
		for (z0=1;z0<=repseg_2d[0];z0++){
		   for (z1=1;z1<=repseg_2d[1];z1++){
		      if (!(z0==1 && z1==1))/*miss out first=same*/
			 rotate_array_2d(tempState,'u',1);
		   }
		   rotate_array_2d(tempState,'l',1);
		}
		set_bitlong(tickoff,dec_equiv(tempState,L),1);
		/*print_current_state(tempState,lightred);*/
		/*end_page(scale,0);*/
	     }
	     else{
		for (z=1;z<=repseg-1;z++){
		   rotate_array(nhood,tempState,'l',0,1);
		   set_bitlong(tickoff,dec_equiv(tempState,L),1);
		   /*print_current_state(tempState,lightred);*/
		   /*end_page(scale,0);*/
		}
	     }
	  }
       }
    }
    pre3:
    return(reject);
}

/*********** accept the pre-image and print, Nov 93, revised 2025***********/
void accept_pre_image(char *pre){

	/*store pre-image*/
	sprintf(textb[0],"accept pre-image");
        //fprintf(stderr,"<%lu>",dec_equiv(state1,L));/*root state*/
	
	if (pretog){
	   /*added to keep track of preimage statess*/
           //fprintf(stderr,"%lu ",dec_equiv(pre,L));
	   
	   if( (preim0 = (char**) realloc(preim0,
		  sizeof(char*)*(nextindex+1)))
				==NULL) outof_memory(textb[0]);
	   if( (xx0 = (signed int*)
		realloc(xx0,sizeof(signed int)*(nextindex+1)))
				==NULL) outof_memory(textb[0]);
	   if( (yy0 = (signed int*)
		realloc(yy0,sizeof(signed int)*(nextindex+1)))
				==NULL) outof_memory(textb[0]);
	   if ((preim0[nextindex]=(char*)calloc(bytesL,sizeof(char)))
				==NULL) outof_memory(textb[0]);
	   /*store valid preim*/
	   memmove(preim0[nextindex], pre, bytesL);
	   
	}
	else{
	   /*added to keep track of staes*/
           //fprintf(stderr,"%lu ",dec_equiv(pre,L));
	   
	   if( (preim1 = (char**) realloc(preim1,
			    sizeof(char*)*(nextindex+1)))
				==NULL) outof_memory(textb[0]);
	   if( (xx1 = (signed int*)
		realloc(xx1,sizeof(signed int)*(nextindex+1)))
				==NULL) outof_memory(textb[0]);
	   if( (yy1 = (signed int*)
	       realloc(yy1,sizeof(signed int)*(nextindex+1)))
				==NULL) outof_memory(textb[0]);
	   if ((preim1[nextindex]=(char*)calloc(bytesL,sizeof(char)))
				==NULL) outof_memory(textb[0]);
	   /*store valid preim*/
	   memmove(preim1[nextindex], pre, bytesL);	   
	}        
}

/********************* interrupt_fan, Nov 93 *************************/
void interrupt_pre_fan(void){
 signed int tempcolor,tempx,tempy,xbox;

   if (event_ready()){   /*to interrupt, early exit*/
    if (is[0]=='q'){
      tempcolor=getcolor();
      setcolor(black);
      tempx=getx;
      tempy=gety;
      earlyexit=1;

      /* bug in UNIX version ??
      if (pretog) memmove(state1,preim1[thisindex],bytesL);
      else memmove(state1,preim0[thisindex],bytesL);
      */

     startinterrupt:
      sprintf(textb[1],
         "early exit - in pre-image fan (%lu found)",precount);
      if (basinfield) sprintf(textb[0],
	   "next-tree/basin-n options-o stopfield-q cont-ret:");
      else if (direction!='b') sprintf(textb[0],
	   "next-tree-n options-o stop basin-q cont-ret:");
      else if (direction=='b')sprintf(textb[0],
	   "options-o stop subtree-q cont-ret:");

      xbox=draw_prompt_box(2);
      outtext(textb[1]);
      moveto(xbox,gety+CHeight);
      if (pre_fansize_freq_hist) outtext("inhist-h ");
      outtext(textb[0]);
      input_string(1,0);
      erase_prompt_box(2);
      moveto(tempx,tempy);
      if (is[0]=='o'){
        char CA_1d=0;
        unsigned int thisposs;
         basin_not_complete=1;
         if (nonlocal==0) CA_1d=1;
	 finish_options(1);
         if (CA_1d==1){ /*restor local 1d wiring, otherwise seg fault*/
            nonlocal=0;
            for (thisposs=lineL-1;thisposs!=Maxu;thisposs--)
		    oneD_local_wire_cell(thisposs,lineL-1);
         }
         basin_not_complete=0;
	 goto startinterrupt;
      }
      else if (is[0]=='h' && pre_fansize_freq_hist){
	 show_pre_fansize_freq_hist();
	 goto startinterrupt;
      }

      else if (is[0]=='n' || is[0]=='q'){
	 if (is[0]=='n') back_onthefly_prompts();
         moveto(tempx,tempy);
         setcolor(tempcolor);
	 return;
      }
      back_onthefly_prompts();
      earlyexit=0;
      setcolor(tempcolor);
    }
   }
}

/** display partial pre-image stack histogram for non-local wiring, Aug 94 ***/
void setup_ppstack_hist(void){
   signed int z,maxhistwidth,tempx,tempy;
   unsigned long zul;
   
     tempx=getx;
     tempy=gety;
     if (ppL!=lineL){
	ppL=lineL;

	pp_startx0=vgax(126);
	pp_starty0=Maxy-vgay(40);

	pp_bartotw=vgax(10);
	maxhistwidth=Maxx-(pp_startx0+vgax(50)+vgax(10));
	if ((lineL+1)*pp_bartotw > maxhistwidth)
	   pp_bartotw=(signed int)((float)maxhistwidth/(lineL+1));
	pp_barwidth=pp_bartotw-2;
	if (pp_barwidth<=0) pp_barwidth=1;
	pp_widthx=vgax(50)+(lineL+1)*pp_bartotw;
	pp_depthy=vgay(150);
	setfillstyle(SOLID_FILL,black);
	bar(pp_startx0+1,pp_starty0-pp_depthy+1,
			     pp_startx0+pp_widthx-1,pp_starty0-1);
	setcolor(red);
	rectangle(pp_startx0,pp_starty0-pp_depthy,
			     pp_startx0+pp_widthx,pp_starty0);
	pp_startx=pp_startx0+vgax(50);
	pp_starty=pp_starty0-vgay(25);

	setcolor(white);
	if (pp_ymax==0){
	   pp_ymax=(signed int)ceil(pow((double)(lineL*nhood),
				 1+(double)nhood/30+(double)nhood/150));
	   if (pp_ymax<10) pp_ymax=10;
	}
	pp_divy=(signed int)ceil((float)pp_ymax/4);

	if (pp_divy<5)      pp_divy-=pp_divy%2;
	else if (pp_divy<10) pp_divy-=pp_divy%5;
	else if (pp_divy<100) pp_divy-=pp_divy%10;
	else if (pp_divy<1000) pp_divy-=pp_divy%100;
	else if (pp_divy<10000) pp_divy-=pp_divy%1000;
        else if (pp_divy<100000) pp_divy-=pp_divy%10000;
        else if (pp_divy<1000000) pp_divy-=pp_divy%100000;
	if (pp_divy<1) pp_divy=1;

	for (z=0;z<=lineL-1;z++){
	   line(pp_startx+z*pp_bartotw,pp_starty+2,
		pp_startx+pp_barwidth+z*pp_bartotw,pp_starty+2);
	   if (z==0 || z==lineL-1){
	      moveto(pp_startx+z*pp_bartotw,pp_starty+vgay(4));
	      sprintf(textb[0],"%d",lineL-1-z);
	      outtext(textb[0]);
	   }
	}
	for (zul=0;zul<=pp_ymax;zul+=pp_divy){
	   pp_heighty=(signed int)ceil((vgay(120)*(float)zul/pp_ymax));
	   line(pp_startx-vgax(10),pp_starty-pp_heighty,
				   pp_startx-vgax(5),pp_starty-pp_heighty);
	   moveto(pp_startx-vgax(30),pp_starty-pp_heighty-CHeight/2);
	   sprintf(textb[0],"%lu",zul);
	   outtext(textb[0]);
	}
     }
     setfillstyle(SOLID_FILL,black);
     bar(pp_startx0+vgax(50),pp_starty0-pp_depthy+1,
				   pp_startx0+pp_widthx-1,pp_starty);
     setfillstyle(SOLID_FILL,green);
     pp_startx=pp_startx0+vgax(50);
     moveto(tempx,tempy);
}
/******************************************************************/
