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

/************************ DRAW BASINS ************************/

#include "edecfunc.h"
//#include "stdlib.h" //seems to be required

/***************  list of functions in this file *************/
/*void draw_fan(void)*/
void compute_heading(void);
void compute_fan_angle(float gap);
void plot_motor(char savecoords,char* temp_state1);
void plot_motor_segfan(char savecoords,char* temp_state1);
void draw_node(char* temp_state1,signed int nodecolor,char savecoords);
void find_sucessor(char* temp_state1); //new function March2025
void copy_cycle_tree(char *temp_state1);
void copy_fan_tree(char *temp_state1);


float thisrad,   /*distance of given node from origin*/
      nextrad,   /*distance of fan nodes from origin*/
      segfanangle;      /*small angle between segfan pre-images*/ 
signed int xx,yy;
//char early_exit_draw_fan=0; make global

/******************* draw pre-image fan, May 93 **************/
void draw_fan(void){

 float interval2, /*distance between levels*/
       gap,       /* ?? gap between points on fan*/
       constantinterval;
 unsigned zul;
 
 /*fprintf(stderr," %d",istr_node_count); 
   //if istr_node_count>=max_istr_node_no max 
   if (istr_graph==1 && early_exit_draw_fan==1){
      fprintf(stderr,"\n1:%d>=%dearly_exit_draw_fan:", istr_node_count,max_istr_node_no);
      return; 
      }*/
   
   /*print or save states: revised Aug 07*/
   if (level>0 && (printstates==3 || printstates==4 ||
                    filestates==3 || filestates==4)){ 
                /* do nothing - only attractor states*/
   }
   else if (filestates || printstates){
     signed int i;
     /* revised Aug 30 2007 */
     if (value_range==2){        
        for (i=0; i<=lineL-1; i++){
           textb[0][i] = get_bit(state1,lineL-1-i) ? '1': '0';
        }
        textb[0][lineL] = '\0';
        if (printstates) fprintf(stderr,"%s",textb[0]);
     }  
     else{ 
        for (i=0; i<=lineL-1; i++){
           textb[0][i] = get_value(state1,lineL-1-i)+48;
        }
        textb[0][lineL] = '\0';
        if (printstates) fprintf(stderr,"%s",textb[0]);
     }

     if (filestates==1 || printstates==1 || filestates==3 || printstates==3) 
            sprintf(textb[1], " %d %d %lu\n", 
               basintypeno, level,
                   (level ==0) ? fansize+1 : fansize);
     else sprintf(textb[1],"\n");

     if (printstates) fprintf(stderr,"%s",textb[1]);
     if (filestates){
        save_data(textb[0]);
        save_data(textb[1]);
     }
   }

   else if (pre_speed>0){
       unsigned int z1;
        for (zul=0;zul<=pre_speed;zul++){ /*to slow down on-the-fly*/
	   for (z1=0;z1<=40;z1++) { }; /*do anything*/
        }	   
   }

   /*if way below screen dont'draw field or range, i.e.  with multiple rows,
     but a single basin (long transients) is ok*/
   if ((basinfield || rangeL) && (oy>=Max_oy && !istr_graph)){ //Max_oy=Maxy*2 set in main*/
     startsegfan=0; //but Max_oy is increased to Maxint for ibaf-graph in run*.c
      return;
   }
   
   //no nodes incompatible with istr_graph, revert to spots
   if (istr_graph==1 && shownumbers==-1) shownumbers=0;

   heading=0;

   if (startsegfan==0){
      if (level==0 && attperiod>0){
	 xx=cyclex[attindex];
	 yy=cycley[attindex];
      }
      else if (level==0 && attperiod==0){
	 xx=ox;  /*transient sub-tree only*/
	 yy=oy;  /*start position = origin*/
      }
      else {
	 if (pretog){  /*pretog==1*/
	    xx=xx1[thisindex];
	    yy=yy1[thisindex];
	 }
	 else {
	    xx=xx0[thisindex];
	    yy=yy0[thisindex];
	 }         
      }
   }
   else {  /*for segmented fan, all 0s or 1s*/
      xx=segx[segindex];
      yy=segy[segindex];
      startsegfan=0;
   }
   //fprintf(stderr,"\n%d-%d",xx,yy);
   
   /*save positions for ibaf-graph, 
     only works for whole field, not single basin or subtree*/
   if (jump_graph==0 && ibaf_graph==1 && exhaustive_testing){
      signed int this_state;
       //fprintf(stderr,"\n%d: %dx%d",(signed int)dec_equiv(state1,L),xx,yy);
       this_state=(signed int)dec_equiv(state1,L);
       basin_pos[this_state+1][0]=xx;
       basin_pos[this_state+1][1]=yy;       
   }
   /*save positions for state transition graph (istr_graph) saved in void draw_node(*/
   
   /*save positions from basins inside jump_graph nodes 
     for use in ibaf-graph. Must be whole field so no compressed*/
   else if (lineL<=max_exh_lu && jump_graph==1
	    && use_preset_basin_pos==1 && dontcompress==1){
      signed int this_state;
       //fprintf(stderr,"\n%d: %dx%d",(signed int)dec_equiv(state1,L),xx,yy);
       this_state=(signed int)dec_equiv(state1,L);
       basin_pos_injump[this_state+1][0]=xx;
       basin_pos_injump[this_state+1][1]=yy; 
  } 
   
  /*if (fansize>0) fprintf(stderr," %lu",fansize);*/

  if (level<lastlevel-1){      /* index is LASTLEVEL-1*/
      thisrad=rad[level];
      nextrad=rad[level+1];
      /*fprintf(stderr,"\nstate1:level=%d -> %d",level, level+1);*/
   }
   else{
      constantinterval=rad[lastlevel-1]-rad[lastlevel-2];
      thisrad=rad[lastlevel-1]+constantinterval*(level-(lastlevel-1));
      nextrad=thisrad+constantinterval;
      /*fprintf(stderr,"\nstate1:level=%d -> %d",level, level+1);*/
   }

   interval2=nextrad-thisrad; /*dist. between levels*/
   gap=interval2/2; /*controls spread of fan*/
   spot=(interval2/8)*(thisrad/nextrad); /*diameter of spot*/

   if ((attperiod<6 && (shownumbers!=3)) || pretested==0){

	 if (linec==black){          /*change color for each new transient*/
	    linec=start_edge_color;  /*if on att cycle, or each new fan if*/
	    spotc=green;             /*cycle is less than 6 long or*/
	 }                           /*starting from a given input*/
	 else if (linec==lightred){  /*defaut start_edge_color=red*/ 
	    linec=lightcyan;
	    spotc=lightred;
	 }
	 else if (linec==lightcyan){
	    linec=green;
	    spotc=lightred;
	 }
	 else if (linec==green){
	    linec=yellow;
	    spotc=green;
	 }
	 else if (linec==yellow){
            linec=lightred;
	    spotc=green;
	 }
   }
   /*highlight transient nodes if g-of-E states suppressed*/
   if (just_G==2) spotc=white;
 
   /*garden of Eden states*/
   if (fansize==0){
      moveto(xx,yy);
      if (just_G==2); /*dont draw g-of-E states*/
      //else if (shownumbers!=-1 || just_G==1 || show_maj>=0){
      else if (shownumbers!=-1 || show_maj>=0){ 
	 /*dont draw outside screen + 50, unless istr_graph is active*/
	 if (istr_graph==0 && (xx<-50 || xx>Maxx+50 || yy<-50 || yy>Maxy+50));
         else draw_node(state1,white,1);
      }
      if (dontcopytrees<3){
	 compute_heading();
	 if (insegloop==1) copy_fan_tree(state1);
	 if (cyclematch>1) copy_cycle_tree(state1);
      }
      goto exitFunc;
   }
   compute_heading();
   compute_fan_angle(gap);
     
   /*color code was here, moved up to fix segfan color bug*/

   if (segfan==0) plot_motor(1,state1);
   else plot_motor_segfan(1,state1);
   if (insegloop==1 && dontcopytrees==0) copy_fan_tree(state1);
   if (cyclematch>1 && dontcopytrees==0) copy_cycle_tree(state1);
 exitFunc:
   setcolor(white);

}

/****************** heading of centre line of fan, May 93 **************/
void compute_heading(void){
 double ratio;

   if (level==0 && (attperiod==1 || attperiod==0))
	      heading=-(deg * 45 + orient_angle); /*def 45 degrees*/
   if (attperiod>1 || level>0){
      if (xx!=ox){
	 ratio=fabs((double)(yy-oy)/(double)(xx-ox));     
	 heading= (float) atan (ratio);
         /*
          yy>oy  |   yy>oy
  PI-h    xx<ox  |   xx>ox ...ok
        ---------|--------
          yy<oy  |   yy<oy
  PI+h    xx<ox  |   xx>ox  2*PI-h  */

	 if (yy<oy && xx>ox) heading=2*PI-heading;
	 else if (yy<oy && xx<ox) heading=PI+heading;
	 else if (yy>=oy && xx<ox) heading=PI-heading;
      }
      else if (xx==ox && yy<oy) heading=3*PI/2;
      else if (xx==ox && yy>oy) heading=PI/2;
      
      /*tilt heading 15 degrees for level 1 of cycles*/
      if (level==0) heading-=(PI/12);
      /*fprintf(stderr,
	"\n xx:ox %d:%d, yy:oy %d:%d h=%f",xx,ox,yy,oy,heading*57.2958);*/
   }
}

/*********** make seperate function May 2000 **************/
void compute_fan_angle(float gap){

   if (level==0) {
      angle=1.65*PI/fansize; /* =297 degrees*/
      /*360 degrees=2*PI Radians, degrees=PI*57.2958*/
      if (attperiod==0) angle=2*PI/fansize; /*subtrees*/
      else if (attperiod==2) angle=.85*PI/fansize; /*period 2*/
      else if (attperiod>2) angle=2* atan((double)(gap/nextrad))/
					      pow((double)fansize,.5);
   }
   /*angle from single pre-image from point attractor ?*/
   else if (attperiod<=1 && level==1 && thismax==1)
				     angle=1.65*PI/fansize;
   /*angle between nodes centred from point attractor*/
   else angle=2* atan( (double) (gap/nextrad))
					/ pow( (double)fansize,.5);

   if ((direction=='b' && level==0)  /*subtree root*/
       || (attperiod<=2 && level==0) /*point attractor, or 2 state attractor*/ 
       || fansize==1
       || (attperiod<=1 && level==1 && thismax==1)); /*dont alter angle*/
   /*alter default fan angle*/
   else if (fan_angle_fact!=0 && fan_angle_fact!=1) angle*=fan_angle_fact;

   /*to limit angle of fan*/
   if (attperiod==1 || attperiod==0){
      if ((level==0 || (level==1 && thismax==1))==0){
	 if (angle*fansize > .85*PI*(rad[0]/thisrad))
				angle=(.85*PI/fansize)*(rad[0]/thisrad);
      }
   }   
   /*limit max angle to 297 degrees*/
   else if (attperiod==2 && level==0){
     if (startsegfan){ 
         if (angle*fansize*fansize/totalsegfan>1.65*PI){ 
           angle=(1.65*PI)/(fansize*fansize/totalsegfan);
        }
     }
     else{
        if (angle*fansize>1.65*PI){ 
           angle=(1.65*PI)/fansize;
           
	}    
     }
   }
   else if (attperiod>=2 || (attperiod==0 && level>0)){
      if (angle*fansize > .85*PI * ((rad[0])/nextrad))
			angle=(.85*PI/fansize)*((rad[0])/nextrad);
   }
   
   /*limit max angle to 360 degrees*/
   if (angle*fansize>2*PI) angle=2*PI/fansize; 

}
/**************** plot pre-image fan, May 93 **************************/
void plot_motor(char savecoords,char* temp_state1){

 float stangle,heading2;
 unsigned long z;


   stangle=heading+((fansize-1) * angle/2);
   for (z=1;z<=fansize;z++){
      moveto (xx,yy);
      if (basin_postScript) moveto_ps(xx,yy);
      heading2=stangle-angle*(z-1); /*pre-im angle*/
      cx=(signed int)(cos(heading2)*nextrad+ox);
      cy=(signed int)(sin(heading2)*nextrad+oy);
      
      if (savecoords){   /*first equivalent only*/
	 if (pretog==0){ /*co-ords of copies not recorded*/
	    xx1[nextbefore+z]=cx;/*predes. to be future inputs*/
	    yy1[nextbefore+z]=cy;/*first equivalents only*/
	 }
	 if (pretog==1){
	    xx0[nextbefore+z]=cx;/*predes. to be future inputs*/
	    yy0[nextbefore+z]=cy;/*first equivalents only*/
	 }
      }
      if (savecoords==1 || dontcopytrees==0){
	 setcolor(linec);
         if (basin_postScript){
              if (basin_postScript==1) color_ps(0,linec);
              else if (basin_postScript==2) color_ps(1,linec);
              lineto_stroke_ps(cx,cy);
         }
         /*these are the links -- comment out to suppress*/
	 /*dont draw outside screen + 50, unless istr_graph is active*/
	 if (istr_graph==0 && (xx<-50 || xx>Maxx+50 || yy<-50 || yy>Maxy+50));
	 else lineto(cx,cy);
      }
   }
   moveto(xx,yy);
   if (basin_postScript) moveto_ps(xx,yy);
   if (fansize==0 && just_G==2); /*dont draw g-of-E states*/
   else if ((shownumbers!=-1 && just_G!=1) || show_maj>=0){
      /*dont draw outside screen + 50, unless istr_graph is active*/
      if (istr_graph==0 && (xx<-50 || xx>Maxx+50 || yy<-50 || yy>Maxy+50));
      else draw_node(temp_state1,spotc,savecoords);
   }
}

/************** plot fan in equivalent segments, June 93 ************/
void plot_motor_segfan(char savecoords,char* temp_state1){

 float stangle,heading2=0,headingcopies;
 unsigned long z;
 signed int zz,copies;

   segfanangle=angle*((double)fansize)/totalsegfan;
   stangle=heading+((totalsegfan-1) * segfanangle/2);
   heading2=stangle;
   linec=black;
   for (z=1;z<=fansize;z++){
      if (linec==black){
	 linec=start_edge_color;
         linec=lightcyan;
	 spotc=green;
      }
      /*change color for each new transient if on att cycle,
      or each new fan if cycle is less than 6 long or
      starting from a given input*/
      else if (linec==lightred){
	 linec=lightcyan;
	 spotc=lightred;
      }
      else if (linec==lightcyan){
	 linec=green;
	 spotc=lightred;
      }
      else if (linec==green){
	 linec=yellow;
	 spotc=green;
      }
      else if (linec==yellow){
	 linec=lightred;
	 spotc=green;
      }

      moveto (xx,yy);
      if (basin_postScript) moveto_ps(xx,yy);
      if (z>1){
	 if (regular2d) heading2-=segfanangle*seg_2d_h[z-1]*seg_2d_v[z-1];
	 else heading2-=segfanangle*seg[z-1]; /*pre-im angle*/
      }
      cx=(signed int)(cos(heading2)*nextrad+ox);
      cy=(signed int)(sin(heading2)*nextrad+oy);
      if (savecoords){   /*first equivalent only*/
	 if (pretog==0){ /*co-ords of copies not recorded*/
	    xx1[nextbefore+z]=cx;/*predes. to be future inputs*/
	    yy1[nextbefore+z]=cy;/*first equivalents only*/
	 }
	 if (pretog==1){
	    xx0[nextbefore+z]=cx;/*predes. to be future inputs*/
	    yy0[nextbefore+z]=cy;/*first equivalents only*/
	 }
      }
      if (savecoords==1 || dontcopytrees==0){
	 setcolor(linec);
         if (basin_postScript){
            moveto_ps(xx,yy);            
            if (basin_postScript==1) color_ps(0,linec);
            else if (basin_postScript==2) color_ps(1,linec);
            lineto_stroke_ps(cx,cy);
         }
	 /*dont draw outside screen + 50, unless istr_graph is active*/
	 if (istr_graph==0 && (xx<-50 || xx>Maxx+50 || yy<-50 || yy>Maxy+50));
         else lineto(cx,cy);
      }
      headingcopies=heading2;
      if (regular2d){
	 copies=seg_2d_h[z]*seg_2d_v[z]-1;
      }
      else copies=seg[z]-1;
      for (zz=1;zz<=copies;zz++){
	 headingcopies-=segfanangle;
	 cx=(signed int)(cos(headingcopies)*nextrad+ox);
	 cy=(signed int)(sin(headingcopies)*nextrad+oy);
	 if (!dontcopytrees){
            moveto(xx,yy);
            if (basin_postScript) moveto_ps(xx,yy);            
         }
	 else{ 
            moveto(xx+(cx-xx)*3/4,yy+(cy-yy)*3/4);
            if (basin_postScript) moveto_ps(xx+(cx-xx)*3/4,yy+(cy-yy)*3/4);
         }
         if (basin_postScript)	 lineto_stroke_ps(cx,cy);
	 /*dont draw outside screen + 50, unless istr_graph is active*/
	 if (istr_graph==0 && (xx<-50 || xx>Maxx+50 || yy<-50 || yy>Maxy+50));
         else lineto(cx,cy);
      }
   }
   moveto(xx,yy);
   if (fansize==0 && just_G==2); /*dont draw g-of-E states*/
   else if ((shownumbers!=-1 && just_G!=1) || show_maj>=0){
      /*dont draw outside screen + 50, unless istr_graph is active*/
      if (istr_graph==0 && (xx<-50 || xx>Maxx+50 || yy<-50 || yy>Maxy+50));
      else draw_node(temp_state1,spotc,savecoords);
   }  
}

/********** draw node as spot, dec number or string, June 93 ***********/
void draw_node(char* temp_state1,signed int nodecolor,char savecoords){
          /*savecoords==0 copied -- from copy_cycle_tree( or copy_fan_tree(*/ 
 signed int z,repseg,tempx,tempy;
 unsigned int count1s,zu;
 unsigned char blockcolor,tarcolor,precolor;
# if __WATCOM__
   signed int getxtemp,getytemp;
# endif
   char temp_ps;

# define highline	{if (memcmp(temp_state1,tar,bytesL)==0){\
			    blockcolor=tarcolor;\
			 }\
			 else {\
			   for (zu=0;zu<=notolearn-1;zu++){\
			     if (memcmp(temp_state1,learn_pre[zu],bytesL)==0){\
				blockcolor=precolor;\
				break;\
			     }\
			   }\
			 }}

# if __WATCOM__
# define smallspot	 _setpixel(xx,yy-1);\
			 _setpixel(xx-1,yy);\
			 _setpixel(xx+1,yy);\
			 _setpixel(xx,yy+1);
# endif

   /*if (!(clip_ps==1 && getx>=clip_x0 && gety>=clip_y0 
		       && getx<=clip_x1 && gety<=clip_y1)){
       temp_ps=basin_postScript;
       basin_postScript=0;
   }*/
                    
    //check for states= Z=1 rules in basin states
    /*if (value_range==2){ 
      char this_nhood=0;

        for (z=2; z<=7; z++){
	  if ( (signed int)ceil(pow(2,(double)z)) == lineL){
               this_nhood=z;
               break;
	   }
        }
	if (this_nhood){
	      z_parameter_all(this_nhood, 0, temp_state1);
              //show all z=1 rules
	      if (zparam[1]==1 || zparam[2]==1);
              //show just chain rules
              //if ((zparam[1]==1 || zparam[2]==1) && (zparam[1]!=zparam[2]));
              else return;
        }

    }*/

    //list each state -- ibaf_graph for single absin or subtree    
    //fprintf(stderr,"\n%lu",dec_equiv(temp_state1,L));
    
    if (just_G==3){ /*repeating segments -- rotational symmetry*/
       /*size of repeating segments in rotational equivalent states*/
       /*repseg=lineL:no repeats, repseg=1:uniform state - lineL repeats
       repseg=x:lineL/x repeats*/  
       repseg=repeating_seg(temp_state1);
       if (repseg==lineL) return;
       /*else fprintf(stderr," %d",repseg);*/
    }

    /*to show majority of selected value (exceptions in Raja's rule)*/
    if (show_maj>=0){
       count1s=0;
       for (zu=0;zu<=L;zu++){
	 if (get_value(temp_state1,zu)==show_maj) count1s+=1;
       }
    }

    /*spot -- also shown if spots (small or normal) 
                 are selected for suppressed copies of equiv trees*/
    if ((shownumbers==0 && savecoords==1) || 
           (shownumbers==0 && dontcopytrees==0) ||
             (savecoords==0 && (dontcopytrees==1 || dontcopytrees==2)) || 
                                            show_maj>=0){
	
	setcolor(nodecolor);        
        if (basin_postScript==1) color_ps(0,nodecolor);
        else if (basin_postScript==2) color_ps(1,nodecolor);
	if (dontcopytrees==1 && savecoords==0){            
	  if (basin_postScript){
              sprintf(textb[0],"%d %d dot1\n",xx,Maxy-yy);
	      vret=write(fid_PS,textb[0],strlen(textb[0]));
              if (vret==0) fprintf(stderr,"\n read=%d",vret);              
	  }
	  lineto(xx,yy); /*another way of showing one pixel*/ 
	}
	else{
	   /*square instead of spot to highlight maj exceptions*/
	   if (show_maj>=0){ 
	      if (count1s>lineL/2) {
		char tempfillc;
		 setcolor(white);                 
		 /*darkgray better to print*/
                 if (bground=='w') tempfillc=blue;
	         else if (bground=='b') tempfillc=yellow;
                 setfillstyle(SOLID_FILL,tempfillc);
                 bar3d(xx-scale/2,yy-scale/2,xx+scale/2,yy+scale/2,0,0);
                 if (basin_postScript){
                    if (basin_postScript==1) color_ps(0,tempfillc);
                    else if (basin_postScript==2) color_ps(1,tempfillc);
		    block_fill_ps(xx-scale/2,yy-scale/2); /*fill block*/
                    if (basin_postScript==1) color_ps(0,white);
                    else if (basin_postScript==2) color_ps(1,white);
                    block_stroke_ps(xx-scale/2,yy-scale/2); /*outline block*/
                 }
	      }
              else if (shownumbers==0){             
#                if __UNIX__
                    if (spot<1) circle(xx,yy,1);
	            else circle(xx,yy,spot);                     
#                elif __WATCOM__
		    if (spot<1) {smallspot}
		    else circle(xx,yy,spot);
#                endif
                 if (basin_postScript){
                    if (spot<1.3) smallspot_ps(xx,yy,1.3); 
	            else circle_ps(xx,yy,(double)spot);
	         }
	      }
           }
	   else if (hilight_learn){
	      tarcolor=lightred;
	      precolor=yellow;
	      blockcolor=black;
	      highline;
	      if (blockcolor!=black){
		 setfillstyle(SOLID_FILL,blockcolor);
		 bar(xx-1,yy-1,xx+3,yy+3);
		 setcolor(white);
		 rectangle(xx-3,yy-3,xx+4,yy+4);
                 if (basin_postScript){
                    if (basin_postScript==1) color_ps(0,blockcolor);
                    else if (basin_postScript==2) color_ps(1,blockcolor);
		    block_fill_ps(xx-scale/2,yy-scale/2); /*fill block*/
                    if (basin_postScript==1) color_ps(0,white);
                    else if (basin_postScript==2) color_ps(1,white);
                    block_stroke_ps(xx-scale/2,yy-scale/2); /*outline block*/
                 }
	      }
	      else if (hilight_learn !=2){
#                if __UNIX__
                    if (spot<1) circle (xx,yy,1);
	            else circle (xx,yy,spot);                     
#                elif __WATCOM__
		    if (spot<1) {smallspot}
		    else circle(xx,yy,spot);
#                endif
                 if (basin_postScript){
                    if (spot<1.3) smallspot_ps(xx,yy,1.3); 
	            else circle_ps(xx,yy,(double)spot);
	         }
	      }
	   }
	   else{
#             if __UNIX__
                 if (spot<1) circle (xx,yy,1);
	         else circle (xx,yy,spot);                     
#             elif __WATCOM__
                 if (spot<1) {smallspot}
	         else circle(xx,yy,spot);
#             endif
              if (basin_postScript){
		//if (spot<1) smallspot_ps(xx,yy,1.5); 
                 if (spot<1.3) circle_ps(xx,yy,1.3); 
	         else circle_ps(xx,yy,(double)spot);
	      }
	   }
	}
    }
    

#   if __WATCOM__
    /*decimal or hex equivalent*/
    else if (shownumbers==1 && lineL<=32){
     signed int blockwidth;
     
       getxtemp=getx;
       getytemp=gety;
       sprintf(textb[1],"%lu",dec_equiv(temp_state1,L));
       setcolor(white);
       blockcolor=black;
       if (hilight_learn){
	  tarcolor=lightred;
	  precolor=yellow;
	  highline;
       }
       if (!(hilight_learn==2 && blockcolor==black)){
	  setfillstyle(SOLID_FILL,blockcolor);
	  if (blockcolor!=black) setcolor(black);
	  blockwidth=textwidth(textb[1]);
	  if (labelsizefactor>0){ /*scaled line seg font*/
             bar(getx+1,gety,getx+blockwidth,gety+CHeight);
             _grtext(getxtemp,getytemp,textb[1]);
          }
          else{ /*default font*/
             bar(getx+1,gety+2,getx+blockwidth+1,gety+CHeight-2);
             moveto(getxtemp,getytemp);
             outtext(textb[1]);
          }
       }
    }
    /*hex equivalent*/
    else if (shownumbers==2){
      unsigned char forecolor;
       getxtemp=getx;
       getytemp=gety;

       forecolor=white;
       blockcolor=black;
       if (hilight_learn){
	  tarcolor=lightred;
	  precolor=yellow;
	  highline
	    ;
       }
       if (!(hilight_learn==2 && blockcolor==black)){
	  setfillstyle(SOLID_FILL,blockcolor);
	  if (blockcolor!=black) forecolor=black;
	  bar(getx+1,gety+2,getx+(bytesL*2*textwidth("z"))+1,
					gety+textheight("z")+1);
	  moveto(getxtemp,getytemp);
	  print_current_bitstring_hexbytes(0,0,state1,-2,10000,forecolor,0);
	  moveto(getxtemp,getytemp);
       }
    }

#   elif __UNIX__
    /*decimal or hex equivalent*/
    else if ((shownumbers==1 && lineL<33) || shownumbers==2){
       if (shownumbers==1) sprintf(textb[1],"%lu",dec_equiv(temp_state1,L));
       setcolor(white);
       blockcolor=black;
       if (hilight_learn){
	  tarcolor=lightred;
	  precolor=yellow;
	  highline;
       }
       if (!(hilight_learn==2 && blockcolor==black)){
	     setfillstyle(SOLID_FILL,blockcolor);
             tempx=getx;
             tempy=gety;
             if (blockcolor!=black) setcolor(black);
             //XSetBackground(D,Gc,Color_Table[(blockcolor)]);
	     XSetBackground(D,Gc,(unsigned long)Color_Table[blockcolor]);
             if (shownumbers==2){
                unsigned char bytez;
                sprintf(textb[1],"");
                for (z=bytesL-1;z>=0;z--){
                   bytez=temp_state1[z];
                   if (bytez<16) sprintf(textb[2],"0%x",bytez);
                   else sprintf(textb[2],"%x",bytez);
                   sprintf(textb[1],"%s%s",textb[1],textb[2]);
                }
                /*this draws a rectange in current background first, then the string*/
                XDrawImageString(D,W,Gc,tempx,tempy,textb[1],strlen(textb[1]));
                /*moverel(XTextWidth(tempfont,textb[1],strlen(textb[1])),0);*/
                if (basin_postScript){
                     nodetext_ps(1,blockcolor,textb[1],tempx,tempy);
                     if (hilight_learn){
                        color_ps(basin_postScript-1,getcolor());/*color or gray*/
                        nodetext_ps(3,getcolor(),textb[1],tempx-1,tempy+1);
                     }
                }                 
	     }
             else{            
                /*this draws a rectange in current background first, then the string*/
                XDrawImageString(D,W,Gc,tempx,tempy,textb[1],strlen(textb[1]));
                if (basin_postScript){                     
                     nodetext_ps(1,blockcolor,textb[1],tempx,tempy);
                     if (hilight_learn){
                        color_ps(basin_postScript-1,getcolor());/*color or gray*/
                        nodetext_ps(3,getcolor(),textb[1],tempx-1,tempy+1);
                     }
                }      
             }
             if (bground=='w') XSetBackground(D, Gc, WhitePixel(D, S));
             else if (bground=='b') XSetBackground(D, Gc, BlackPixel(D, S));
       }
    }
#   endif
    
    /*graghic bit-string*/
    else if (shownumbers==3){
       if (hilight_learn){
	  tarcolor=lightred;
	  precolor=yellow;
	  blockcolor=white;
	  highline;
       }
       else{
	  if (linec==lightcyan) blockcolor=magenta;
	  else if (linec==green) blockcolor=cyan;
	  else if (linec==yellow) blockcolor=lightred;
	  else if (linec==lightred) blockcolor=yellow;
	  else blockcolor=white;
       }
       
       /*if (hilight_learn!=2){*/ /*change, this didnt work*/
       if (!(hilight_learn==2 && blockcolor==white)){
	  if (twod || showbits_1d_as_2d){
             print_current_state_twod(temp_state1,blockcolor,0);
             if (basin_postScript) sp_node_ps(1,temp_state1,getx,gety,blockcolor);
	  }
	  else{ 
             print_current_state_h(temp_state1,blockcolor);
             if (basin_postScript) sp_node_ps(0,temp_state1,getx,gety,blockcolor);
          }
       }
   }

   /*if (!(clip_ps==1 && getx>=clip_x0 && gety>=clip_y0 
                                      && getx<=clip_x1 && gety<=clip_y1))
				      basin_postScript=temp_ps;*/
    if (istr_graph==1){
      signed int this_sucessor;
      unsigned int z,zw;
      
       basin_pos[istr_node_count+1][0]=xx;
       basin_pos[istr_node_count+1][1]=yy;
       
       find_sucessor(temp_state1);
       
       istr_node_count+=1;
            
    }
}

/*** find single output for interactive state tyransition graph, subtree, single gasin, etc. Aprill 2025 **/
void find_sucessor(char* temp_state1){
  char *this_successor;
  signed int i,temp;
  unsigned int z,n,*wnhood;

  
  //fprintf(stderr,"\nin find_sucessor -- istr_node_count=%d:",istr_node_count);
   /*memory for pseudo-nhood*/
   if ((wnhood=(unsigned int *)calloc(nhood,sizeof(unsigned int)))
			      ==NULL) outof_memory("wnhood");

   if ((this_successor=(char *)calloc(bytesL,sizeof(char)))==NULL) outof_memory("this_successor");
       
                   if (exhaustive_testing) 
		     memmove(this_successor,exh_pairs+dec_equiv(temp_state1,L)*bytesL,bytesL);
                   else{
		     for (n=L; n!=Maxu; n--){
		        //fprintf(stderr," %d ",n);
			//local nhood with periodic boundary conditions
			if (nonlocal==0){
	                    //i.e. for nhood=9 lineL=3 to work
	                    if (L<nhoodm[n]/2){
		               for (i=0;i<=nhoodm[n]-1;i++){
		                  temp=lineL+n-(nhoodm[n]/2)+i;
		                  if (temp<0) temp+=lineL;
		                  wnhood[i]=abs(temp)%lineL;
		               }
	                    }
	                    else{
		               for (i=0;i<=nhoodm[n]-1;i++)
			          wnhood[i]=(lineL+n-(nhoodm[n]/2)+i)%lineL;
	                    }
	                 }    
	                 //set local 2d wiring
	                 else if (loc_twod_fonly){
                            if (twod==2) wire_2d_local(n,wnhood);
                            else if (threed==3) wire_3d_local(n,wnhood); 
                         }
			 //nonlocal=1, get psuedo-nhood from wiring scheme
	                 else{
	                    for (i=0;i<=nhoodm[n]-1;i++) 
                                      wnhood[i]=wiring[n][i];
			 }
                                                 
		         /*xxxxxxxxxxxx next time-step xxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxx*/
			 //note: next_time_step returns value of actual or pseudo-nhood
                         if (tot_only==0)
                             next_time_step(carule,temp_state1,this_successor,0,NULL,1,wnhood,n,0);
			 else{
			     if (totalistic==1) //run_forward(cacode);
                                next_time_step(cacode,temp_state1,this_successor,0,NULL,1,wnhood,n,0); 
                             else if (totalistic==2) //run_forward(v_code);	      
	                        next_time_step(v_code,temp_state1,this_successor,0,NULL,1,wnhood,n,0);        
			 }
                         /*xxxxxxxxxxxx end next time-step xxxxxxxxxxxxxxxxxxxxxxxxxxxxx*/
		      }/*for loop*/
                   }
		     
	//the sucessor is the root of the subtree!! (fan).
	//Link arrows go from state to root in state transition graph
		   memmove(pat_state0[istr_node_count],temp_state1,bytesL);//state
		   memmove(pat_state1[istr_node_count],this_successor,bytesL);//root
	
	free(wnhood);	
	free(this_successor);
}  


/************* copy equivalent trees on cycle, Aug 93 ****************/
void copy_cycle_tree(char *temp_state1){
 signed int subperiod,z=0;
 unsigned int z0,z1,cm_d;

#define locate_cycle_tree heading-=(2*PI/attperiod)*subperiod;\
			      if (heading<2*PI) heading+=2*PI;\
			      if (level==0 && attperiod>0){\
				 xx=cyclex[attindex-z*subperiod];\
				 yy=cycley[attindex-z*subperiod];\
			      }\
			      else{\
				 xx=(signed int)(cos(heading)*thisrad+ox);\
				 yy=(signed int)(sin(heading)*thisrad+oy);\
			      }

    if (regular2d){
       if (cyclematch_2d_diag[0]>1 || cyclematch_2d_diag[1]>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];
	  subperiod=attperiod/cm_d;
	  for (z0=1;z0<=cm_d;z0++){
	     /*miss out last=same*/
	     if (z0!=cm_d){
		z+=1;
		locate_cycle_tree;
		
		if (cyclematch_2d_diag[0]>1) //if (shownumbers>0) removed for istr_graph to work
			   rotate_array_2d(temp_state1,'r',1);
		else rotate_array_2d(temp_state1,'l',1);
		rotate_array_2d(temp_state1,'u',1);
		
		if (fansize==0){
		   moveto(xx,yy);
                   if (just_G==2); /*dont draw g-of-E states*/
		   else{
		      /*dont draw outside screen + 50, unless istr_graph is active*/
	              if (istr_graph==0 && (xx<-50 || xx>Maxx+50 || yy<-50 || yy>Maxy+50));
                      else draw_node(temp_state1,white,0);
                   }
		}
		else plot_motor(0,temp_state1);
	     }
	  }
       }
       else{
	  subperiod=attperiod/(cyclematch_2d[0]*cyclematch_2d[1]);
	  for (z0=1;z0<=cyclematch_2d[0];z0++){
	    //if (shownumbers>0) removed for istr_graph to work
	    if (cyclematch_2d[1]==1) rotate_array_2d(temp_state1,'l',1);
	     for (z1=1;z1<=cyclematch_2d[1];z1++){
		/*miss out last=same*/
		if (!(z0==cyclematch_2d[0] && z1==cyclematch_2d[1])){
		   z+=1;
		   locate_cycle_tree;
		   rotate_array_2d(temp_state1,'u',1);
		   if (fansize==0){
		      moveto(xx,yy);
                      if (just_G==2); /*dont draw g-of-E states*/
		      else{
			 /*dont draw outside screen + 50, unless istr_graph is active*/
	                 if (istr_graph==0 && (xx<-50 || xx>Maxx+50 || yy<-50 || yy>Maxy+50));
                         else draw_node(temp_state1,white,0);
                      }
		   }
		   else plot_motor(0,temp_state1);
		}
	     }
	     if (cyclematch_2d[1]>1) rotate_array_2d(temp_state1,'l',1);
	  }
       }
    }
    else{
       subperiod=attperiod/cyclematch;
       for (z=1;z<=cyclematch-1;z++){
	  locate_cycle_tree;
	  /*rotate heading*/
	  //if (shownumbers>0) removed for istr_graph to work
	  rotate_array(nhood,temp_state1,'l',0,attrepseg/cyclematch);
	  if (fansize==0){
	     moveto(xx,yy);
             if (just_G==2); /*dont draw g-of-E states*/
	     else{
	       /*dont draw outside screen + 50, unless istr_graph is active*/
	      if (istr_graph==0 && (xx<-50 || xx>Maxx+50 || yy<-50 || yy>Maxy+50));
               else draw_node(temp_state1,white,0);
             }
	  }
	  else plot_motor(0,temp_state1);
       }
    }
}

/****** copy equivelent sub-trees on segmented fan, Aug 93 ************/
void copy_fan_tree(char *temp_state1){
 signed int z,z0,z1;

#define locate_fan_tree heading=heading-segfanangle;\
			   if (heading<2*PI) heading+=(2*PI);\
			   cx=(signed int)(cos(heading)*nextrad+ox);\
			   cy=(signed int)(sin(heading)*nextrad+oy);\
			   xx=(signed int)(cos(heading)*thisrad+ox);\
			   yy=(signed int)(sin(heading)*thisrad+oy);

   if (regular2d){
      for (z0=1;z0<=seg_2d_h[segindex];z0++){	
	 //if (shownumbers>0) removed for istr_graph to work
	 if (seg_2d_v[segindex]==1) rotate_array_2d(temp_state1,'l',1); 
	 for (z1=1;z1<=seg_2d_v[segindex];z1++){
	    if (z0==seg_2d_h[segindex] && z1==seg_2d_v[segindex]) continue;
	    locate_fan_tree;
	    //if (shownumbers>0) removed for istr_graph to work
	    rotate_array_2d(temp_state1,'u',1);
	    if (fansize==0){
	       moveto(xx,yy);
               if (just_G==2); /*dont draw g-of-E states*/
	       else{
		  /*dont draw outside screen + 50, unless istr_graph is active*/
	          if (istr_graph==0 && (xx<-50 || xx>Maxx+50 || yy<-50 || yy>Maxy+50));
                  else draw_node(temp_state1,white,0);
               }
	       continue;
	    }
	    plot_motor(0,temp_state1);
	 }
	 //if (shownumbers>0) removed for istr_graph to work
	 if (seg_2d_v[segindex]>1) rotate_array_2d(temp_state1,'l',1);	 
      }
   }
   else{
      for (z=1;z<=seg[segindex]-1;z++){
	 locate_fan_tree;
	 //if (shownumbers>0) removed for istr_graph to work
	 rotate_array(nhood,temp_state1,'l',0,1);
	 if (fansize==0){
	    moveto(xx,yy);
            if (just_G==2); /*dont draw g-of-E states*/
	    else{
	       /*dont draw outside screen + 50, unless istr_graph is active*/
	       if (istr_graph==0 && (xx<-50 || xx>Maxx+50 || yy<-50 || yy>Maxy+50));
               else draw_node(temp_state1,white,0);
            }
	    continue;
	 }
	 plot_motor(0,temp_state1);
      }
   }
}

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

















