#include "squaredance.h"
#include <assert.h>

/* 16-Apr-2021: changed ResetNormal so that it didn't force dancers to the */
/*  position specified by moveto. Some dances have slightly different behavior*/
/*  the second time through, which implies a slightly different start location*/
/*  and an <if>. See PatricksWaltz.dance */
int danceNeedsCoupleCount(Dance *dance) {
    if ( dance->is_figure )
return( false );

    switch ( dance->formation ) {
      case sp_squaredSet:
      case sp_rect6Set:
      case sp_2Couple:
      case sp_3Couple:
      case sp_4Couple:
      case sp_5Couple:
      case sp_6Couple:
      case sp_7Couple:
      case sp_8Couple:
      case sp_3CplCircle:
      case sp_5CplCircle:
      case sp_6CplCircle:
      case sp_7CplCircle:
      case sp_square3:
      case sp_custom:
      case sp_custom3:
      case sp_facingCouples:
      case sp_facingCouplesBecket:
      /* case sp_facingCouplesProper: */
return( false );

      case sp_dupleMinor:
      case sp_becket:
      case sp_becketCCW:
      case sp_shortWaves:
      case sp_dupleMinorProgressed:
      case sp_fourFaceFour:
      case sp_tempest:
      case sp_quadrupleMinor:
      case sp_quadrupleMinorBecket:
      case sp_threeFaceThree:
      case sp_tripleMinor:
      case sp_rotatedTripleMinor:
      case sp_circularMonople:
      case sp_trioCircularMonople:
return( true );

      case sp_scottishDupleMinor:
      case sp_scottishTripleMinor:
return( false );

      default:
	assert( false );
return( false );
    }
}

int danceMinorSetSize(Dance *dance) {
    switch ( dance->formation ) {
      case sp_squaredSet:
      case sp_rect6Set:
      case sp_2Couple:
      case sp_3Couple:
      case sp_4Couple:
      case sp_5Couple:
      case sp_6Couple:
      case sp_7Couple:
      case sp_8Couple:
      case sp_3CplCircle:
      case sp_5CplCircle:
      case sp_6CplCircle:
      case sp_7CplCircle:
      case sp_square3:
      case sp_custom:
      case sp_custom3:
      case sp_facingCouples:
      case sp_facingCouplesBecket:
      /*case sp_facingCouplesProper:*/
return( 0 );

      case sp_circularMonople:
return( 2 );

      case sp_trioCircularMonople:
return( 3 );

      case sp_dupleMinor:
      case sp_dupleMinorProgressed:
      case sp_becket:
      case sp_becketCCW:
      case sp_shortWaves:
      case sp_scottishDupleMinor:
return( 4 );
      case sp_tripleMinor:
      case sp_scottishTripleMinor:
      case sp_threeFaceThree:
      case sp_rotatedTripleMinor:
return( 6 );
      case sp_fourFaceFour:
      case sp_tempest:
      case sp_quadrupleMinor:
      case sp_quadrupleMinorBecket:
return( 8 );

      default:
	assert( false );
return( 0 );
    }
}

int danceCoupleSize(Dance *dance) {
return( dance->formation!=sp_threeFaceThree ? 2 : 3 );
}

void danceXScale(Dance *dance, double xscale) {
    int i;
    struct transformation trans;

    dance->minorset_spacing *= xscale;

    if ( dance->comp_cnt!=0 ) {
	for ( i=0; i<dance->comp_cnt; ++i )
	    danceXScale(dance->components[i],xscale);
return;
    }

    memset(&trans,0,sizeof(trans));
    trans.xscale = xscale; trans.yscale = 1;
    for ( i=0; i<dance->role_cnt; ++i ) {
	danceBlockTransform(&dance->roles[i].figures,&trans);
    }
    for ( i=0; i<dance->people; ++i ) {
	danceBlockTransform(&dance->dancers[i].figures,&trans);
    }
}

static int blockClaspsOutsideMinorSet( Block *b, int ignoreFinalClasp ) {
    int j, lastj;
    FigureSegment *cs;

    /* Don't check the final clasp of the minor set. */
    /* We use this routine to see if we should have a <minorset1 tag, and */
    /*  normally if there is a clasp outside the set we need one... except */
    /*  if it's the last thing we do (see SapphireSea) where it's really */
    /*  the first move of the next set */
    lastj = b->move_cnt-1;
    if (  lastj<0 )
return( false );
    while ( b->moves[lastj].cmd == c_end || b->moves[lastj].cmd==c_resetDance )
	--lastj;

    for ( j=0, cs = b->moves; j<=lastj; ++j, ++cs ) {
	if ( ((cs->join_right_hand&HAND_MINORSET_MASK)!=0 && (!ignoreFinalClasp || j!=lastj || cs->millibars<cs->join_right_millibars)) ||
		((cs->join_left_hand&HAND_MINORSET_MASK)!=0 && (!ignoreFinalClasp || j!=lastj || cs->millibars<cs->join_left_millibars)) )
return( true );
	if ( cs->ifblock!=NULL ) {
	    Block *b2;
	    for ( b2 = cs->ifblock ; b2!=NULL; b2 = b2->next ) {
		if ( blockClaspsOutsideMinorSet(b2, j<lastj? false : ignoreFinalClasp ))
return( true );
	    }
	}
    }
return( false );
}
    
int danceClaspsOutsideMinorSet( Dance *dance ) {
    int i;

    if ( dance->choreo_cnt!=0 ) {
	for ( i=0; i<dance->choreo_cnt; ++i ) {
	    if ( danceClaspsOutsideMinorSet(dance->sequence[i].figure ) )
return( true );
	}
return( false );
    }

    for ( i=0; i<dance->role_cnt; ++i ) {
	if ( blockClaspsOutsideMinorSet( &dance->roles[i].figures, true ))
return( true );
    }
return( false );
}

int danceMinorSetMillibarCount(Dance *dance) {
    int i,cnt;
    Person *p;

    if ( dance->choreo_cnt!=0 ) {
	cnt = 0;
	for ( i=0; i<dance->choreo_cnt; ++i )
	    cnt += danceMinorSetMillibarCount(dance->sequence[i].figure ) *
		    dance->sequence[i].time_scale;
return( cnt );
    }

    if ( dance->role_cnt!=0 )
	p = &dance->roles[0];
    else
	p = &dance->dancers[0];

    if ( p==NULL ) {
	fprintf( stderr, "Couldn't find a role with a bar I could count.\n" );
return( 32*1000 );	/* Almost all contras and many English have 32 bar music */
    }
return( blockCountMillibars( &p->figures ));
}

static int danceComponentMinorSetMillibarCount(Dance *dance) {

    if ( dance->choreo_cnt==0 )
return( danceMinorSetMillibarCount(dance ));
    else if ( dance->choreo_pos==0 )
return( danceMinorSetMillibarCount(dance->sequence[0].figure ));
    else if ( dance->choreo_pos>dance->choreo_cnt )	/* This happens at the very end of the dance when we try to reset dancers for their new state in what would be the next figure */
return( danceMinorSetMillibarCount(dance->sequence[dance->choreo_cnt-1].figure ));
    else
return( danceMinorSetMillibarCount(dance->sequence[dance->choreo_pos-1].figure ));
}

int danceMinorSetActualMillibarCount(Dance *dance) {
    int i,cnt;

    if ( dance->choreo_cnt!=0 ) {
	cnt = 0;
	for ( i=0; i<dance->choreo_cnt; ++i )
	    cnt += danceMinorSetActualMillibarCount(dance->sequence[i].figure ) *
		    dance->sequence[i].time_scale;
return( cnt );
    }

    cnt = 0;
    for ( i=0; i<dance->call_cnt; ++i ) {
	CallList *cl = &dance->calls[i];
	if ( (cl->part_mask&1) || (cl->part_mask&NOTLAST_MASK) )
	    cnt += cl->actual_millibars;
    }
return( cnt );
}

int danceHasReset(Dance *dance) {
    Person *p;
    int i;
    FigureSegment *cs;

    if ( dance->sequence!=NULL )
return( danceHasReset(dance->sequence[0].figure) );

    if ( dance->dancers!=NULL )
	p = dance->dancers;
    else
	p = dance->roles;
    if ( p==NULL )
return( false );
    for ( i=0, cs = p->figures.moves; i<p->figures.move_cnt; ++i, ++cs ) {
	if ( cs->cmd==c_resetDance )
return( true );
	else if ( cs->cmd==c_end )
return( false );
    }
return( false );
}

int danceCoupleSpacing(Dance *dance) {
    int minx, maxx, miny, maxy;
    int i, jump;

    switch ( dance->formation ) {
      case sp_dupleMinor:
      case sp_dupleMinorProgressed:
      case sp_becket:
      case sp_becketCCW:
      case sp_shortWaves:
      case sp_scottishDupleMinor:
      case sp_tripleMinor:
      case sp_quadrupleMinor:
      case sp_scottishTripleMinor:

	minx = 999999; maxx=0;
	miny = 999999; maxy=0;
/* The American Husband has 1s+3s normally, and 2s in becket. I used to have
 *  a 4 where there is now a 3 (in the for statement below) but that gave the
 *  wrong answer for it
 */
	for ( i=0; i<3 && i<dance->people; ++i ) {
	    if ( dance->dancers[i].figures.moves[0].endPoint.x<minx )
		minx = dance->dancers[i].figures.moves[0].endPoint.x;
	    else if ( dance->dancers[i].figures.moves[0].endPoint.x>maxx )
		maxx = dance->dancers[i].figures.moves[0].endPoint.x;
	    if ( dance->dancers[i].figures.moves[0].endPoint.y<miny )
		miny = dance->dancers[i].figures.moves[0].endPoint.y;
	    else if ( dance->dancers[i].figures.moves[0].endPoint.y>maxy )
		maxy = dance->dancers[i].figures.moves[0].endPoint.y;
	}
	jump = maxx-minx;
	if ( /*dance->formation==sp_shortWaves &&*/ jump<dance->units/8 ) {
	    jump = maxy-miny;
	    if ( jump < dance->units/8 )
		jump = dance->units/4;
	}
      break;
      case sp_circularMonople: case sp_trioCircularMonople:
	jump = dance->dancers[1].figures.moves[0].endPoint.x -
		dance->dancers[0].figures.moves[0].endPoint.x;
	if ( jump==0 ) {
	    jump = dance->dancers[1].figures.moves[0].endPoint.y -
		    dance->dancers[0].figures.moves[0].endPoint.y;
/*	    if ( dance->sicilian ) */
/*		jump *= 1.5; */
	}
	if ( jump<0 )
	    jump = -jump;
	if ( jump < dance->units/8 )
	    jump = dance->units/4;
      break;
      case sp_fourFaceFour:
	jump = dance->dancers[4].figures.moves[0].endPoint.x -
		dance->dancers[0].figures.moves[0].endPoint.x;
      break;
      case sp_tempest:
	  jump = dance->units/2;
      break;
      case sp_quadrupleMinorBecket:
	jump = dance->dancers[0].figures.moves[0].endPoint.x -
		dance->dancers[1].figures.moves[0].endPoint.x;
      break;
      case sp_rotatedTripleMinor:
	jump = dance->dancers[0].figures.moves[0].endPoint.x -
		dance->dancers[1].figures.moves[0].endPoint.x;
	if ( jump<0 ) jump = -jump;
      break;
      case sp_threeFaceThree:
	jump = dance->dancers[3].figures.moves[0].endPoint.x -
		dance->dancers[0].figures.moves[0].endPoint.x;
      break;

      default:
        jump = 0;
    }
return( jump );
}

int danceMinorSetSpacing(Dance *dance) {

    if ( dance->minorset_spacing!= 0 )
return( dance->minorset_spacing );

    switch ( dance->formation ) {
      case sp_circularMonople: case sp_trioCircularMonople:
	if ( dance->role_cnt>=2 &&
		  dance->roles[0].figures.moves[0].endPoint.x == dance->roles[1].figures.moves[0].endPoint.x )
return( danceCoupleSpacing(dance));
	else
return( 2*danceCoupleSpacing(dance));

      case sp_dupleMinor:
      case sp_dupleMinorProgressed:
      case sp_becket:
      case sp_becketCCW:
      case sp_shortWaves:
      case sp_scottishDupleMinor:
      case sp_threeFaceThree:
      case sp_rotatedTripleMinor:
      case sp_fourFaceFour:
return( 2*danceCoupleSpacing(dance));

      case sp_quadrupleMinor:
      case sp_quadrupleMinorBecket:
return( 4*danceCoupleSpacing(dance));

      case sp_tripleMinor:
      case sp_scottishTripleMinor:
return( 3*danceCoupleSpacing(dance));

      case sp_tempest:
return( dance->units );

      default:
return( 0 );
    }
}

static int conditionHasLast(Condition *expr) {

    switch ( expr->operator ) {
      case op_and:
      case op_or:
	if ( conditionHasLast(expr->op1))
return( true );
	else
return( conditionHasLast(expr->op2));

      case op_not:
return( conditionHasLast(expr->op1));

      case op_bottomset:
      case op_topset:
      case op_majorpos:
      case op_proper:
      case op_improper:
      case op_first:
      case op_part:
return( false );

      case op_last:
return( true );
    }
}

int danceHasLastCondition(Dance *dance) {
    Person *p;
    int i;
    FigureSegment *cs;
    Block *b;

    if ( dance->roles==NULL )
	p = dance->dancers;
    else
	p = dance->roles;
    for ( i=0, cs = p->figures.moves; i<p->figures.move_cnt; ++i, ++cs ) {
	if ( cs->cmd==c_if ) {
	    for ( b=cs->ifblock; b!=NULL; b=b->next )
		if ( b->condition!=NULL && conditionHasLast(b->condition) )
return( true );
	} else if ( cs->cmd==c_end )
return( false );
    }
return( false );
}

int danceRoleIndex(Dance *dance, enum role r) {
    int i;

    for ( i=0; i<dance->role_cnt; ++i )
	if ( dance->roles[i].effective_role == r )
return( i );

return( -1 );
}

static int danceRoleIndexSex(Dance *dance, enum role r, int sex) {
    int i;

    for ( i=0; i<dance->role_cnt; ++i )
	if ( dance->roles[i].effective_role == r && dance->roles[i].sex==sex )
return( i );

    assert(false /* No role found */);
return( -1 );
}

static Person *danceRoleSex(Dance *dance, enum role r, int sex) {
    int i;

    for ( i=0; i<dance->role_cnt; ++i )
	if ( dance->roles[i].effective_role == r && dance->roles[i].sex==sex )
return( &dance->roles[i] );

    fprintf( stderr, "Looking for role='%s' sex=%s\n", roleNames[r], sexNames[sex] );
    assert(false /* No role found */);
return( NULL );
}

/* In my representation: A normal contra set will be aligned with the band to */
/*  the left. So couples with lower x coordinates will be closer to the band */
static int xCompare(const void *v1,const void *v2) {
    const Person *p1 = *(const Person **) v1;
    const Person *p2 = *(const Person **) v2;

    if ( p1->now.x<p2->now.x )
return( -1 );
    else if ( p1->now.x>p2->now.x )
return( 1 );

    /* Now within a couple I shall be sexist and ask for the men to appear in the list first */
    if ( p1->sex<p2->sex )
return( -1 );
    else if ( p1->sex>p2->sex )
return( 1 );
    else {
	fprintf( stderr, "Two couples appear to be at the same place %s%c %s%c\n",
		roleNames[p1->effective_role], sexChars[p1->sex],
		roleNames[p2->effective_role], sexChars[p2->sex] );
	assert(false);		/* Two couples at the same place? */
    }
}

/* In my representation: A normal contra set will be aligned with the band to */
/*  the left. So couples with lower x coordinates will be closer to the band */
static int xMonoCompare(const void *v1,const void *v2) {
    const Person *p1 = *(const Person **) v1;
    const Person *p2 = *(const Person **) v2;

    if ( p1->now.x<p2->now.x )
return( -1 );
    else if ( p1->now.x>p2->now.x )
return( 1 );

    if ( p1->now.y<p2->now.y )
return( -1 );
    else if ( p1->now.y>p2->now.y )
return( 1 );

    {
	fprintf( stderr, "Two people appear to be at the same place %s%c %s%c\n",
		roleNames[p1->effective_role], sexChars[p1->effective_sex],
		roleNames[p2->effective_role], sexChars[p2->effective_sex] );
	assert(false);		/* Two couples at the same place? */
    }
}

/* If the dance starts in wavy lines then we have two couples at the same x */
/*  coord. One should be facing down the hall (orient=270), the other up (orient=90) */
/*  order the ones with a 270 orientation first, because that's how they'd be */
/*  in a normal line */
static int xShortWavesCompare(const void *v1,const void *v2) {
    const Person *p1 = *(const Person **) v1;
    const Person *p2 = *(const Person **) v2;

    if ( p1->now.x<p2->now.x )
return( -1 );
    else if ( p1->now.x>p2->now.x )
return( 1 );

    if ( p1->effective_role==r_1s && p2->effective_role==r_2s )
return( -1 );
    if ( p1->effective_role==r_2s && p2->effective_role==r_1s )
return( 1 );

#if 0
    /* Now it is possible that the man and woman in the 1s might have slightly*/
    /*  different orientations if their splines aren't perfect, but we want */
    /*  them to be the same. So do some fudging */
    o1 = p1->now_orientation;
    if ( o1>250 ) o1 = 270;
    else if ( o1>70 ) o1 = 90;
    o2 = p2->now_orientation;
    if ( o2>250 ) o2 = 270;
    else if ( o2>70 ) o2 = 90;
    if ( o1>o2 )
return( -1 );
    else if ( o1<o2 )
return( 1 );
#endif

    /* Now within a couple I shall be sexist and ask for the men to appear in the list first */
    if ( p1->sex<p2->sex )
return( -1 );
    else if ( p1->sex>p2->sex )
return( 1 );
    else
	assert(false);		/* Two couples at the same place? */
}

/* In a four face four dance we have two couples at the same place. Order the */
/*  one on the left first (note: facing down, left has bigger y, facing up left smaller y) */
/*  (and since men are on the left this gets the sexes in order too) */
static int x4Face4Compare(const void *v1,const void *v2) {
    const Person *p1 = *(const Person **) v1;
    const Person *p2 = *(const Person **) v2;

    /* now_couple_x is the average of the two people in the couple's position */
    /*  in a normal 4x4 it's the same as now.x for each */
    /* In a becket quadruple minor, or tempest then the following should still */
    /*  work */
    if ( p1->now_couple_x<p2->now_couple_x )
return( -1 );
    else if ( p1->now_couple_x>p2->now_couple_x )
return( 1 );

    if ( p1->couple_number==p2->couple_number ) {
	if ( p1->sex<p2->sex )
return( -1 );
	else if ( p1->sex>p2->sex )
return( 1 );
    else
return( 0 );
    }
    if ( p1->now_orientation==p2->now_orientation && (p1->now_orientation==-90 || p1->now_orientation==270) ) {
	/* Facing down */
	if ( p1->now.y>p2->now.y )
return( -1 );
	else if ( p1->now.y<p2->now.y )
return( 1 );
	else
return( 0 );
/* GWW: 4/May/2024 changed this line so it would work for tempest formation */
/*  where the inactive couples face in (0,180) rather than up */
/* Not sure what effect it has (if any) on quadruple minor becket */
/*    } else if ( p1->now_orientation==p2->now_orientation && p1->now_orientation==90 ) { */
    } else if ( p1->now_orientation>=0 && p1->now_orientation<=180 &&
		p2->now_orientation>=0 && p2->now_orientation<=180 ) {
	/* Facing up */
	if ( p1->now.y<p2->now.y )
return( -1 );
	else if ( p1->now.y>p2->now.y )
return( 1 );
	else
return( 0 );
    }
printf( "We shouldn't get here any more p1->orient=%.0f, p2->orient=%.0f, p1->now=(%.0f,%.0f) p2->now=(%.0f,%.0f)\n",
	p1->now_orientation, p2->now_orientation, p1->now.x, p1->now.y, p2->now.x, p2->now.y );
    if ( p1->effective_role==r_1sleft || p1->effective_role==r_1sright ||
	     p1->effective_role==r_outAtTopLeft || p1->effective_role==r_outAtTopRight ) {
	if ( p1->now.y>p2->now.y )
return( -1 );
	else if ( p1->now.y<p2->now.y )
return( 1 );
	else {
	    fprintf( stderr, "Two couples appear to be at the same place %s%c %s%c\n",
		    roleNames[p1->effective_role], sexChars[p1->sex],
		    roleNames[p2->effective_role], sexChars[p2->sex] );
	    assert(false);		/* Two couples at the same place? */
	}
    } else {
	if ( p1->now.y<p2->now.y )
return( -1 );
	else if ( p1->now.y>p2->now.y )
return( 1 );
	else {
	    fprintf( stderr, "Two couples appear to be at the same place %s%c %s%c\n",
		    roleNames[p1->effective_role], sexChars[p1->sex],
		    roleNames[p2->effective_role], sexChars[p2->sex] );
	    assert(false);		/* Two couples at the same place? */
	}
    }
}

static int x3Face3Compare(const void *v1,const void *v2) {
    const Person *p1 = *(const Person **) v1;
    const Person *p2 = *(const Person **) v2;

    if ( p1->now_couple_x<p2->now_couple_x )
return( -1 );
    else if ( p1->now_couple_x>p2->now_couple_x )
return( 1 );

    if ( p1->couple_number==p2->couple_number ) {
return( p1->effective_sex-p2->effective_sex );
    }
    fprintf( stderr, "Two trios appear to be at the same place %s%c %s%c\n",
	    roleNames[p1->effective_role], sexChars[p1->sex],
	    roleNames[p2->effective_role], sexChars[p2->sex] );
    assert(false);		/* Two couples at the same place? */
}

/* Becket formation is hardest because couples aren't at the same x position */
/* And if progression happens at the beginning of the minorset (rather than */
/*  the end) then we can't use Out At Top as a marker */
static int xBecketCompare(const void *v1,const void *v2) {
    const Person *p1 = *(const Person **) v1;
    const Person *p2 = *(const Person **) v2;
    int in_my_minor_set=0;

    if ( p1->couple_number==p2->couple_number ) {
	if ( p1->sex<p2->sex )
return( -1 );
	else
return( 1 );
    }
    if ( p1->now.y==p2->now.y ) {
	if ( p1->now.x<p2->now.x )
return( -1 );
	else if ( p1->now.x>p2->now.x )
return( 1 );
	else
	    assert( p1->now.x!=p2->now.x );
    } else if ( p1->now.x>=p2->now.x+512 )
return( 1 );
    else if ( p1->now.x+512<=p2->now.x )
return( -1 );

    if ( p1->now.y>192 ) {
	if ( p1->sex==s_female )
	    in_my_minor_set = p2->now.x>=p1->now.x && p2->now.x<=p1->now.x+300;
	else
	    in_my_minor_set = p2->now.x>=p1->now.x-300 && p2->now.x<=p1->now.x;
    } else {
	if ( p1->sex==s_male )
	    in_my_minor_set = p2->now.x>=p1->now.x && p2->now.x<=p1->now.x+300;
	else
	    in_my_minor_set = p2->now.x>=p1->now.x-300 && p2->now.x<=p1->now.x;
    }
    if ( !in_my_minor_set ) {
	if ( p1->now.x<p2->now.x )
return( -1 );
	else if ( p1->now.x>p2->now.x )
return( 1 );
    } else {
	if ( p1->now.y>=192 )
return( -1 );
	else
return( 1 );
    }
return( 0 );
}

static int xBecketCCWCompare(const void *v1,const void *v2) {
    const Person *p1 = *(const Person **) v1;
    const Person *p2 = *(const Person **) v2;

    if ( p1->couple_number==p2->couple_number ) {
	if ( p1->sex<p2->sex )
return( -1 );
	else
return( 1 );
    }
    if ( p1->now_couple_x > p2->now_couple_x )
return( 1 );
    else if ( p1->now_couple_x < p2->now_couple_x )
return( -1 );

    if ( p1->now.y>p2->now.y )
return( 1 );
    else if ( p1->now.y<p2->now.y )
return( -1 );

return( 0 );
}

static int angleCompare(float t1, float t2) {
    float diff = t1-t2;

    if ( diff>2*3.14 )
	diff -= 2*PI;
    if ( diff<-2*3.14 )
	diff += 2*PI;
    if ( diff<.0001 && diff>-.0001 )
return( 0 );
    if ( diff>0 )
return( 1 );
    else
return( -1 );
}

static int xSicilianCompare(const void *v1,const void *v2) {
    const Person *p1 = *(const Person **) v1;
    const Person *p2 = *(const Person **) v2;
    int cmp = angleCompare(p1->now_sicilian_theta,p2->now_sicilian_theta );

    if ( cmp!=0 )
return( cmp );

    /* Now within a couple I shall be sexist and ask for the men to appear in the list first */
    if ( p1->effective_sex<p2->effective_sex )
return( -1 );
    else if ( p1->effective_sex>p2->effective_sex )
return( 1 );
    else {
	angleCompare(p1->now_sicilian_theta,p2->now_sicilian_theta ); /* Debug */
	fprintf( stderr, "Two couples appear to be at the same place %s%c %s%c\n",
		roleNames[p1->effective_role], sexChars[p1->sex],
		roleNames[p2->effective_role], sexChars[p2->sex] );
	assert(false);		/* Two couples at the same place? */
    }
}
/* If the dance starts in wavy lines then we have two couples at the same x */
/*  coord. One should be facing down the hall (orient=270), the other up (orient=90) */
/*  order the ones with a 270 orientation first, because that's how they'd be */
/*  in a normal line */
static int xSicilianShortWavesCompare(const void *v1,const void *v2) {
    const Person *p1 = *(const Person **) v1;
    const Person *p2 = *(const Person **) v2;
    int cmp = angleCompare(p1->now_sicilian_theta,p2->now_sicilian_theta );

    if ( cmp!=0 )
return( cmp );

    if ( p1->effective_role==r_1s && p2->effective_role==r_2s )
return( -1 );
    if ( p1->effective_role==r_2s && p2->effective_role==r_1s )
return( 1 );

#if 0
    /* Now it is possible that the man and woman in the 1s might have slightly*/
    /*  different orientations if their splines aren't perfect, but we want */
    /*  them to be the same. So do some fudging */
    o1 = p1->now_orientation-p1->now_sicilian_theta;
    if ( o1>250 ) o1 = 270;
    else if ( o1>70 ) o1 = 90;
    o2 = p2->now_orientation-p1->now_sicilian_theta;
    if ( o2>250 ) o2 = 270;
    else if ( o2>70 ) o2 = 90;
    if ( o1>o2 )
return( -1 );
    else if ( o1<o2 )
return( 1 );
#endif

    /* Now within a couple I shall be sexist and ask for the men to appear in the list first */
    if ( p1->sex<p2->sex )
return( -1 );
    else if ( p1->sex>p2->sex )
return( 1 );
    else
	assert(false);		/* Two couples at the same place? */
}

/* In a four face four dance we have two couples at the same place. Order the */
/*  one on the left first (note: facing down, left has bigger y, facing up left smaller y) */
/*  (and since men are on the left this gets the sexes in order too) */
static int xSicilian4Face4Compare(const void *v1,const void *v2) {
    const Person *p1 = *(const Person **) v1;
    const Person *p2 = *(const Person **) v2;
    int cmp = angleCompare(p1->now_sicilian_couple_theta,p2->now_sicilian_couple_theta );

    if ( cmp!=0 )
return( cmp );

    if ( p1->couple_number==p2->couple_number ) {
	if ( p1->sex<p2->sex )
return( -1 );
	else if ( p1->sex>p2->sex )
return( 1 );
    else
return( 0 );
    }
    /* Note that this is backwards from y (in the non-sicilian case) */
    /*  as y goes up, dancer aproaches center, and radius goes down */
    /* No need to worry about out at top/bottom here */
    if ( p1->effective_role == r_2sleft || p1->effective_role == r_2sright ) {
	if ( p1->now_sicilian_radius>p2->now_sicilian_radius )
return( -1 );
	else if ( p1->now_sicilian_radius<p2->now_sicilian_radius )
return( 1 );
    } else {
	if ( p1->now_sicilian_radius>p2->now_sicilian_radius )
return( 1 );
	else if ( p1->now_sicilian_radius<p2->now_sicilian_radius )
return( -1 );
    }

    fprintf( stderr, "Two couples appear to be at the same place %s%c %s%c\n",
	    roleNames[p1->effective_role], sexChars[p1->sex],
	    roleNames[p2->effective_role], sexChars[p2->sex] );
    assert(false);		/* Two couples at the same place? */
}

static int xSicilian3Face3Compare(const void *v1,const void *v2) {
    const Person *p1 = *(const Person **) v1;
    const Person *p2 = *(const Person **) v2;
    int cmp = angleCompare(p1->now_sicilian_couple_theta,p2->now_sicilian_couple_theta );

    if ( cmp!=0 )
return( cmp );

    if ( p1->couple_number==p2->couple_number ) {
return( p1->effective_sex-p2->effective_sex );
    }
#if 0
    /* Note that this is backwards from y (in the non-sicilian case) */
    /*  as y goes up, dancer aproaches center, and radius goes down */
    /* No need to worry about out at top/bottom here */
    if ( p1->effective_role == r_1s ) {
	if ( p1->now_sicilian_radius>p2->now_sicilian_radius )
return( 1 );
	else if ( p1->now_sicilian_radius<p2->now_sicilian_radius )
return( -1 );
	else
return( 0 );
    } else {
	if ( p1->now_sicilian_radius<p2->now_sicilian_radius )
return( 1 );
	else if ( p1->now_sicilian_radius>p2->now_sicilian_radius )
return( -1 );
	else
return( 0 );
    }
#endif

    fprintf( stderr, "Two trios appear to be at the same place %s%c %s%c\n",
	    roleNames[p1->effective_role], sexChars[p1->sex],
	    roleNames[p2->effective_role], sexChars[p2->sex] );
    assert(false);		/* Two couples at the same place? */
}

static int xSicilianRTM_1s_m_Compare(const void *v1,const void *v2) {
    const Person *p1 = *(const Person **) v1;
    const Person *p2 = *(const Person **) v2;
    int cmp = angleCompare(p1->now_sicilian_theta,p2->now_sicilian_theta );

    if ( cmp!=0 )
return( cmp );

    fprintf( stderr, "Two males in role 1 appear to be at the same place %s%c %s%c\n",
	    roleNames[p1->effective_role], sexChars[p1->sex],
	    roleNames[p2->effective_role], sexChars[p2->sex] );
    assert(false);		/* Two couples at the same place? */
}

/* Becket formation is hardest because couples aren't at the same theta position */
static int xSicilianBecketCompare(const void *v1,const void *v2) {
    const Person *p1 = *(const Person **) v1;
    const Person *p2 = *(const Person **) v2;
    int cmp = angleCompare(p1->now_sicilian_couple_theta,p2->now_sicilian_couple_theta );

    if ( cmp!=0 )
return( cmp );

    if ( p1->couple_number==p2->couple_number ) {
	if ( p1->sex<p2->sex )
return( -1 );
	else
return( 1 );
    }
    if ( p1->now_sicilian_radius<p2->now_sicilian_radius )
return( -1 );
    else if ( p1->now_sicilian_radius>p2->now_sicilian_radius )
return( 1 );
    else {
	fprintf( stderr, "!!!! This shouldn't happen, two couples at same theta, radius.\n" );
return( 0 );
    }
}

/* Becket formation is hardest because couples aren't at the same theta position */
static int xSicilianBecketCCWCompare(const void *v1,const void *v2) {
    const Person *p1 = *(const Person **) v1;
    const Person *p2 = *(const Person **) v2;
    int cmp = angleCompare(p1->now_sicilian_couple_theta,p2->now_sicilian_couple_theta );

    if ( cmp!=0 )
return( cmp );

    if ( p1->couple_number==p2->couple_number ) {
	if ( p1->sex<p2->sex )
return( -1 );
	else
return( 1 );
    }
/* In woodlands waltz 1s are on the outside */
    if ( p1->now_sicilian_radius>p2->now_sicilian_radius )
return( -1 );
    else
return( 1 );
}


static void order(Dance *dance, int (*compar)(const void *,const void *)) {
    int i;

    if ( dance->orderedList==NULL )
	dance->orderedList = malloc(dance->people*sizeof(Person *));
    for ( i=0; i<dance->people; ++i )
	dance->orderedList[i] = &dance->dancers[i];
    qsort(dance->orderedList,dance->people,sizeof(Person *),compar);
    if ( dance->formation==sp_circularMonople || dance->formation==sp_trioCircularMonople ) {
	/* No checks, expect a mixer */
    } else if ( dance->formation==sp_rotatedTripleMinor ) {
	/* No checks, expect a mixer */
    } else if ( dance->tags!=NULL && strstr(dance->tags,"mixer")!=NULL ) {
	/* No checks, expect a mixer */
    } else if ( dance->formation!=sp_threeFaceThree ) {
	for ( i=0; i<dance->people; i+=2 ) {
	    if ( dance->orderedList[i]->sex!=s_male ) {
		printf( "i=%d (possibly partners do not end at the same x location, or perhaps one takes a little longer to get there)\n", i );
		assert( dance->orderedList[i]->sex==s_male );
	    }
	    if ( dance->orderedList[i]->couple_number!=dance->orderedList[i+1]->couple_number ) {
		int j;
		for ( j=0; j< dance->people; ++j ) {
		    printf( "%d: couple=%d, role=%s sex=%c(%c) pos=(%.1f,%.1f theta=%.3f ctheta=%.3f radius=%.0f)", j, dance->orderedList[j]->couple_number,
			    roleNames[dance->orderedList[j]->effective_role],
			    sexChars[dance->orderedList[j]->effective_sex],
			    sexChars[dance->orderedList[j]->sex],
			    dance->orderedList[j]->now.x,
			    dance->orderedList[j]->now.y,
			    dance->orderedList[j]->now_sicilian_theta,
			    dance->orderedList[j]->now_sicilian_couple_theta,
			    dance->orderedList[j]->now_sicilian_radius);
		    if ( i==j )
			printf( " *\n" );
		    else
			printf( "\n" );
		}
		printf( "i=%d couples=%d,%d\n", i,  dance->orderedList[i]->couple_number, dance->orderedList[i+1]->couple_number);
		compar(&dance->orderedList[i],&dance->orderedList[i+1]);
		assert( dance->orderedList[i]->couple_number==dance->orderedList[i+1]->couple_number );
	    }
	}
    } else {
	for ( i=0; i<dance->people; i+=3 ) {
	    assert( dance->orderedList[i]->couple_number==dance->orderedList[i+1]->couple_number &&
		    dance->orderedList[i]->couple_number==dance->orderedList[i+2]->couple_number );
	}
    }
}

Person *danceFindRole(Dance *dance, enum role role,enum sex sex) {
    int i;

    for ( i=0; i<dance->role_cnt; ++i )
	if ( dance->roles[i].effective_role == role && dance->roles[i].sex==sex )
return( &dance->roles[i] );

return( NULL );
}

static int minorSetFindIndexOfRole(Dance *dance,int minor_set_start,int minor_set_size,
			enum role role, enum sex sex) {
    int i;
    enum role mss_role = dance->orderedList[minor_set_start]->effective_role;

    if ( mss_role >= r_outAtTop && mss_role <= r_outAtBottomRight ) {
	if ( mss_role >= r_outAtTop && mss_role <= r_outAtBottom ) {
	    role = mss_role;
	} else if ( mss_role == r_outAtTop1of2 || mss_role == r_outAtTop1of3 || mss_role == r_outAtBottom1of2 || mss_role == r_outAtBottom1of3 ) {
	    if ( role == r_1s )
		role = mss_role;
	    else if ( role == r_2s )
		role = mss_role+1;
	    else if ( role == r_3s )
		role = mss_role+2;
	} else if ( mss_role == r_outAtTop2of3 || mss_role == r_outAtBottom2of3 ) {
	    if ( role == r_1s )
		role = mss_role-1;
	    else if ( role == r_2s )
		role = mss_role;
	    else if ( role == r_3s )
		role = mss_role+1;
	} else if ( mss_role == r_outAtTopLeft ) {
	    if ( role==r_1sleft )
		role = mss_role;
	    else if ( role==r_1sright )
		role = mss_role+1;
	} else if ( mss_role==r_outAtBottomLeft ) {
	    if ( role==r_2sleft )
		role = mss_role;
	    else if ( role==r_2sright )
		role = mss_role+1;
	}
    }

    for ( i=minor_set_start; i<minor_set_start+minor_set_size && i<dance->people; ++i ) {
	if ( i<0 )
    continue;
	if ( dance->orderedList[i]->effective_role==role &&
		dance->orderedList[i]->effective_sex==sex )
return( dance->orderedList[i]-dance->dancers );
    }
return( -1 );
}

static int dancerIsProper(Person *p,Dance *dance) {
    int highy, lowy, y1, y2, diffhigh, difflow;
    if ( dance->sicilian )		/* Too hard to figure out */
return( -1 );

    y1 = dance->roles[0].figures.moves[0].endPoint.y;
    if ( dance->role_cnt<2 )
return( -1 );	/* meaningless */
    y2 = dance->roles[1].figures.moves[0].endPoint.y;
    if ( y1==y2 ) {	/* becket dance? */
	if ( dance->role_cnt<3 )
return( -1 );
	y2 = dance->roles[2].figures.moves[0].endPoint.y;
    }
    if ( y1==y2 )
return( -1 );
    if ( y1>y2 ) {
	highy = y1;
	lowy = y2;
    } else {
	highy = y2;
	lowy = y1;
    }
    
    diffhigh = p->now.y-highy;
    diffhigh *= diffhigh;
    difflow  = p->now.y-lowy;
    difflow  *= diffhigh;
    if ( diffhigh > difflow ) {
	/* closer to the low line */
	if ( p->sex == s_female )
return( false );
	else if ( p->sex == s_male )
return( true );
	else
return( -1 );		/* meaningless for trios */
    } else {
	if ( p->sex == s_female )
return( true );
	else if ( p->sex == s_male )
return( false );
	else
return( -1 );		/* meaningless for trios */
    }
}

static int evalCondition(Condition *expr,Person *p,Dance *dance) {
    int out_at_bottom, mss;

    switch ( expr->operator ) {
      case op_or:
	if ( evalCondition(expr->op1,p,dance))
return( true );
	else
return( evalCondition(expr->op2,p,dance));
      case op_and:
	if ( !evalCondition(expr->op1,p,dance))
return( false );
	else
return( evalCondition(expr->op2,p,dance));
      case op_not:
return( !evalCondition(expr->op1,p,dance));

      case op_part:
return( dance->current_part+1==expr->argument1 );

      case op_first:
return( dance->first_minor_set );
      case op_last:
return( dance->last_minor_set );

      case op_topset:
	if ( dance->sicilian )		/* No one is ever out, no topset or bottomset in a sicilian configuration */
return( false );
	if ( p->effective_role==r_outAtTop && expr->argument1==0 && expr->argument2==1 )
return( true );
    /* This is the number of couples out. in a four face four/tempest/quad minor it will be 2 not 1 */
	if ( dance->start_first_minor_set!=expr->argument2 )
return( false );

	/* This is a hack. I don't want to be a topset in the one tempest */
	/*  old style progression dance if there are waiting couples above me */
	if ( dance->formation==sp_tempest && dance->old_style_progression &&
		dance->orderedList!=NULL &&
		dance->orderedList[0]->effective_role==r_waiting_left )
return( false );

return( (p->current_pos-dance->start_first_minor_set)/ ( danceMinorSetSize(dance)/2 ) == expr->argument1-1 );

      case op_bottomset:
	if ( dance->sicilian )		/* No one is ever out, no topset or bottomset in a sicilian configuration */
return( false );
	if ( p->effective_role==r_outAtBottom && expr->argument1==0 && expr->argument2==1 )
return( true );
	mss = danceMinorSetSize(dance)/2;
	if ( mss==0 ) mss = dance->people/2;	/* whole set dance */
	out_at_bottom = (dance->people/2 - dance->start_first_minor_set) % mss;
    /* This is the number of couples out. in a four face four/tempest/quad minor it will be 2 not 1 */
	if ( out_at_bottom!=expr->argument2 )
return( false );

return( ((dance->people/2-1 - p->current_pos)-out_at_bottom)/ mss == expr->argument1-1 );

      case op_majorpos:
	if ( dance->sicilian )		/* No one is ever out, no topset or bottomset in a sicilian configuration */
return( false );
	if ( expr->argument1>=0 )
return( expr->argument1 == p->current_pos );
	else
return( dance->people/2+expr->argument1 == p->current_pos );

      case op_proper:
return( dancerIsProper(p,dance));

      case op_improper:
return( !dancerIsProper(p,dance));
    }
}

static int matchesConditions(FigureSegment *moves,Person *p,Dance *dance) {
    int size, sets, off;

    if ( dance->sicilian ) {
	/* No one is ever out. There is no topset nor bottomset nor any other */
	/*  complication */
	switch ( moves->condition ) {
	  case if_always:
	  case if_nottopset:
	  case if_notbottomset:
	  case if_notsemitopset:
	  case if_notsemibottomset:
	  case if_nottopsetorsemi:
	  case if_notbottomsetorsemi:
return( true );
	  default:
return( false );
	}
    }

    switch ( moves->condition ) {
      case if_always:
return( true );

      case if_topset:
      case if_nottopset:
	if ( dance->start_first_minor_set==0 && p->current_pos<danceMinorSetSize(dance)/2)
return( moves->condition==if_topset );
	else if ( p->current_pos<dance->start_first_minor_set )
return( moves->condition==if_topset );
	else
return( moves->condition!=if_topset );

      case if_bottomset:
      case if_notbottomset:
        size = danceMinorSetSize(dance);
	sets = (dance->people-2*dance->start_first_minor_set)/size;
	off = dance->people - (sets*size + 2*dance->start_first_minor_set);
	if ( off==0 )
	    off = size;
	if ( 2*p->current_pos >= dance->people-off )
return( moves->condition==if_bottomset );
	else
return( moves->condition!=if_bottomset );

      case if_semitopset:
      case if_notsemitopset:
	if ( dance->start_first_minor_set!=0 &&
		p->current_pos >= dance->start_first_minor_set &&
		p->current_pos <  dance->start_first_minor_set+
			danceMinorSetSize(dance)/2)
return( moves->condition==if_semitopset );
	else
return( moves->condition!=if_semitopset );

      case if_semibottomset:
      case if_notsemibottomset:
        size = danceMinorSetSize(dance);
	sets = (dance->people-2*dance->start_first_minor_set)/size;
	off = dance->people - (sets*size + 2*dance->start_first_minor_set);
	if ( off==0 )		/* => No couple out at bottom, but semibottomset requires there to be a couple out */
return( moves->condition!=if_semibottomset );

	if ( 2*p->current_pos >= dance->people-off ) /* couple out at bottom is bottomset */
return( moves->condition!=if_semibottomset );
	if ( 2*p->current_pos >= dance->people-off-size )
return( moves->condition==if_semibottomset );
	else
return( moves->condition!=if_semibottomset );

      case if_nottopsetorsemi:
return( p->current_pos >= dance->start_first_minor_set+ danceMinorSetSize(dance)/2);

      case if_notbottomsetorsemi:
        size = danceMinorSetSize(dance);
	sets = (dance->people-2*dance->start_first_minor_set)/size;
	off = dance->people - (sets*size + 2*dance->start_first_minor_set);

return( 2*p->current_pos < dance->people-off-size );

      case if_nottopbottomset:
	if ( dance->start_first_minor_set==0 && p->current_pos<danceMinorSetSize(dance)/2)
return( false );	/* top set */
	else if ( p->current_pos<dance->start_first_minor_set )
return( false );	/* out at top set */

        size = danceMinorSetSize(dance);
	sets = (dance->people-2*dance->start_first_minor_set)/size;
	off = dance->people - (sets*size + 2*dance->start_first_minor_set);
	if ( off==0 )
	    off = size;
	if ( 2*p->current_pos >= dance->people-off )
return( false );	/* bottom set or out at bottom */
	else
return( true );

    }

return( false );	/* Shouldn't happen */
}

static void blockSplineMake(Block *to) {
    Position *here = &to->moves[0].endPoint;
    FigureSegment *cs, *cs_end;

    cs_end = to->moves + to->move_cnt;
    for ( cs=to->moves ; cs<cs_end; ++cs ) {
	if ( cs->cmd==c_curveto || cs->cmd==c_lineto ) {
	    splineMake(cs,here);
	    here = &cs->endPoint;
	}
    }
}

static void blockCopyAndFlatten(Block *to,Block *from,Person *p,Dance *dance) {
    FigureSegment *cs, *cs_end;
    FigureSegment *tocs, *tocs_end;
    
    cs = from->moves; cs_end = cs+from->move_cnt;
    tocs = to->moves+to->move_cnt; tocs_end = to->moves+to->move_max;
    
    for ( ; cs<cs_end; ++cs ) {
	if ( cs->cmd==c_if ) {
	    Block *b;
	    for ( b=cs->ifblock ; b!=NULL; b=b->next ) {
		if ( b->condition==NULL || evalCondition(b->condition,p,dance))
	    break;
	    }
	    if ( b==NULL ) {
		fprintf( stderr, "If without an else. (linenumber=%ld).\n", b->lineno );
exit(1);
	    }
	    blockCopyAndFlatten(to,b,p,dance);
	    tocs = to->moves+to->move_cnt; tocs_end = to->moves+to->move_max;
	} else if ( (cs->part_mask&(1<<dance->current_part))!=0 &&
		matchesConditions(cs,p,dance) ) {
	    if ( tocs>=tocs_end ) {
	    	to->move_cnt = (tocs-to->moves);
	    	to->moves = realloc(to->moves, (to->move_max += 20)*sizeof(FigureSegment));
		tocs = to->moves+to->move_cnt; tocs_end = to->moves+to->move_max;
	    }
	    *tocs = *cs;
	    tocs->levitation = valueChangeCopy(tocs->levitation);
	    tocs->outness    = valueChangeCopy(tocs->outness);
	    /* No need to copy ifblocks, we flattened any of them above */
	    tocs->condition  = if_always;
	    tocs->part_mask  = (unsigned int) -1;
	    ++tocs;
	    to->move_cnt = tocs-to->moves;
	}
    }
    to->move_cnt = tocs - to->moves;
    if ( to->move_cnt>0 && to->moves[0].cmd==c_moveto )
	blockSplineMake(to);
}

static int dancerCanDoScottish4CoupleProgression(Person *p) {

    if ( p==NULL )
return( false );

    if ( p->figures.move_cnt<1 )
return( false );
    if ( p->figures.moves[1].cmd!=c_pause )
return( false );
    if ( p->figures.moves[1].part_mask != (unsigned int) -1 )
return( false );
    if ( p->figures.moves[1].condition != if_always )
return( false );

return( true );
}

static int danceCanDoAutomaticScottish4CoupleProgression(Dance *dance) {
    /* the 3s and the outAtBottom roles both need to begin with at least */
    /* 1 second (bar) of pause. There can't be a part_mask, nor a condition */

return( dancerCanDoScottish4CoupleProgression(danceFindRole(dance,r_3s,s_male  )) &&
	dancerCanDoScottish4CoupleProgression(danceFindRole(dance,r_3s,s_female)) &&
	dancerCanDoScottish4CoupleProgression(danceFindRole(dance,r_outAtBottom,s_male)) &&
	dancerCanDoScottish4CoupleProgression(danceFindRole(dance,r_outAtBottom,s_female)) );
}

static int danceHasBuiltInScottish4CoupleProgressionPre(Dance *dance) {
    /* special role for the 1s and 3s to swap places */

return( danceFindRole(dance,r_3s_progression,s_male  )!= NULL &&
	danceFindRole(dance,r_3s_progression,s_female)!= NULL &&
	danceFindRole(dance,r_1s_progression,s_male)!= NULL &&
	danceFindRole(dance,r_1s_progression,s_female)!= NULL );
}

static int danceHasBuiltInScottish4CoupleProgressionPost(Dance *dance) {
    /* special role for the 3s and 4s to swap places after the figure starts */

return( danceFindRole(dance,r_3s_progression,s_male  )!= NULL &&
	danceFindRole(dance,r_3s_progression,s_female)!= NULL &&
	danceFindRole(dance,r_4s_progression,s_male)!= NULL &&
	danceFindRole(dance,r_4s_progression,s_female)!= NULL );
}

static int refigureHand(Dance *dance,int minorSetStart, int minorSetSize,int fullMinorSetSize,int oldMask ) {
    int hand;
    int newMinorSet = minorSetStart, setoff=0;
    int normalMinorSetSize;
    int role, sex;
    /* What hand to clasp. */
    /* First problem, clasping the hand in the same minor set? just add the */
    /*  person number to the minorset start and that's right */
    /* Might also want to clasp the hand of someone in the preceding or following */
    /*  sets, then we have to check if we actually have that many sets in the */
    /*  dance (with complications for the half sets when someone is out at the ends) */
    /* In some calls we want people to wrap around the end of the set */
    /* In others we don't (long lines) */
    /* Other aspects of this program won't support wrapping around the ends */
    /*  so we ignore that. If the indicated dancer doesn't exist, no hand clasp */

    if ( oldMask==0 )
return( 0 );
    hand = (oldMask&HAND_INDIVIDUAL_MASK);
    if ( hand==HAND_STAR )
return( HAND_STAR|(oldMask&HAND_ABOVE_MASK) );		/* Clasp at the center of a star, not a person, so don't update */
    if ( hand>=fullMinorSetSize )
return( 0 );

    if ( (oldMask&HAND_MINORSET_MASK)!=0 ) {
	setoff = (oldMask&HAND_MINORSET_OFFSET)>>HAND_MINORSET_SHIFT;
	normalMinorSetSize = danceMinorSetSize(dance);
	/* If we are out at the ends, then the size of our current minor set */
	/*  may not be the same as the general size in the rest of the dance */
	if ( oldMask&HAND_MINORSET_UP ) {
	    newMinorSet -= setoff * normalMinorSetSize;
	    if ( newMinorSet+hand < 0 ) {
		if ( newMinorSet>-normalMinorSetSize ) {
		    /* If they try a hand clasp with someone out at the top */
		    /*  then find someone to clasp. The guys out at top can */
		    /*  act as either ones or twos (or, I guess threes in a triple) */
		    /*  so don't be picky */
		    /* Except some becket dances want to be picky */
		    if ( oldMask&HAND_NOTOUT_MASK )
return( 0 );
		    if ( hand&1 )
return( (dance->orderedList[1]-dance->dancers) | (oldMask&HAND_COPY_MASK));
		    else
return( (dance->orderedList[0]-dance->dancers) | (oldMask&HAND_COPY_MASK));
		}
return( 0 );
	    }
	} else {
	    newMinorSet += minorSetSize + (setoff-1) * normalMinorSetSize;
	    if ( newMinorSet+hand >= dance->people ) {
		if ( newMinorSet<dance->people ) {
		    /* if out at bottom, don't be picky about roles */
		    if ( oldMask&HAND_NOTOUT_MASK )
return( 0 );
		    if ( hand&1 )
return( (dance->orderedList[newMinorSet+1]-dance->dancers) | (oldMask&HAND_COPY_MASK));
		    else
return( (dance->orderedList[newMinorSet+0]-dance->dancers) | (oldMask&HAND_COPY_MASK));
		}
return( 0 );
	    }
	}
    }
    if ( (oldMask&HAND_NOTOUT_MASK)!=0 &&
	    dance->orderedList[newMinorSet+hand]->effective_role >= r_outAtTop &&
	    dance->orderedList[newMinorSet+hand]->effective_role <= r_outAtBottomRight )
return( 0 );

    role = dance->roles[hand].effective_role;
    sex  = dance->roles[hand].effective_sex;

    if ( newMinorSet==minorSetStart ) {
	hand = minorSetFindIndexOfRole(dance,minorSetStart,minorSetSize,
		role, sex);
	if ( hand==-1 ) {
	    if ( minorSetSize==2 )	/* out at top or bottom */
		hand = dance->orderedList[minorSetStart+(oldMask&1)] - dance->dancers;
	    else if ( minorSetSize==3 && danceMinorSetSize(dance)>3 )  /* three face three */
		hand = dance->orderedList[minorSetStart+(oldMask&HAND_INDIVIDUAL_MASK)%3] - dance->dancers;
	    else if ( minorSetSize==4 && danceMinorSetSize(dance)>4 ) /* four out at top or bottom, triple, four-face-four */
		hand = dance->orderedList[minorSetStart+(oldMask&3)] - dance->dancers;
	}
    } else if ( newMinorSet<0 ) {
	/* out at top give them the closest person of the right sex */
	hand = dance->orderedList[newMinorSet+minorSetSize-2+sex] - dance->dancers;
#if 0
    /* OK This didn't work for three coney walk */
    /*  I think the test should be newMinorSet+hand (rather than minorSetSize) */
    /*  but that test has already been done above, so this should never happen */
    } else if ( newMinorSet+minorSetSize>dance->people ) {
	hand = dance->orderedList[newMinorSet+sex] - dance->dancers;
#endif
    } else {
	hand = minorSetFindIndexOfRole(dance,newMinorSet,normalMinorSetSize,
		role, sex);
	if ( hand==-1 ) {
	    /* Will this break three coney? Needed for Triple Play */
	    if ( newMinorSet+normalMinorSetSize>dance->people && normalMinorSetSize==4 )
		hand = dance->orderedList[newMinorSet+(oldMask&1)] - dance->dancers;
	}
    }
    if ( hand==-1 )
return( 0 );

return( hand | (oldMask&HAND_COPY_MASK) );
}

static void fillDancer(Dance *dance, int di, Person *role) {
    memcpy(&dance->dancers[di],role,sizeof(Person));
    dance->dancers[di].current_pos = di/2;
    dance->dancers[di].started = true;
    dance->dancers[di].figures.moves = malloc(dance->dancers[di].figures.move_max*sizeof(FigureSegment));
    dance->dancers[di].figures.move_cnt = 0;
    dance->dancers[di].effective_sex = role->sex;	/* Usually these will always be the same, but not in HalfeHannikin, where people switch lines */
    dance->dancers[di].now = role->figures.moves[0].endPoint;	/* Need this to calculate proper conditions on the first iteration */
    blockCopyAndFlatten(&dance->dancers[di].figures,&role->figures,&dance->dancers[di],dance);
    dance->dancers[di].actualFigureStartPos = role->actualFigureStartPos;
}

static void makeDancerWait(Dance *dance, int di, enum role role) {
    dance->dancers[di].effective_role = role;
    dance->dancers[di].display_role = r_last_unused;
    if ( dance->formation==sp_threeFaceThree )
	dance->dancers[di].sex = s_left + (di%3);
    else
	dance->dancers[di].sex = di&1;
    dance->dancers[di].effective_sex = dance->dancers[di].sex;
    dance->dancers[di].current_pos = di/2;
    dance->dancers[di].figures.move_cnt = dance->dancers[di].figures.move_max = 4;
    dance->dancers[di].figures.moves = calloc(4,sizeof(FigureSegment));
    dance->dancers[di].figures.moves[0].cmd = c_moveto;
    /* I used just to take outAtBottom for both, but that doesn't work for improper dances */
    if ( dance->formation==sp_threeFaceThree ) {
	dance->dancers[di].figures.moves[0].endPoint.x = danceFindRole(dance,r_outAtBottom,s_left+di%3)->figures.moves[0].endPoint.x;
	dance->dancers[di].figures.moves[0].endPoint.y = danceFindRole(dance,r_outAtTop   ,s_left+di%3)->figures.moves[0].endPoint.y;
    } else if ( role == r_waiting_left ) {
	dance->dancers[di].figures.moves[0].endPoint.x = danceFindRole(dance,r_2sleft,di&1)->figures.moves[0].endPoint.x;
	dance->dancers[di].figures.moves[0].endPoint.y = danceFindRole(dance,r_2sleft,di&1)->figures.moves[0].endPoint.y;
    } else if ( role == r_waiting_right ) {
	dance->dancers[di].figures.moves[0].endPoint.x = danceFindRole(dance,r_2sright,di&1)->figures.moves[0].endPoint.x;
	dance->dancers[di].figures.moves[0].endPoint.y = danceFindRole(dance,r_2sright,di&1)->figures.moves[0].endPoint.y;
    } else {
	dance->dancers[di].figures.moves[0].endPoint.x = danceFindRole(dance,r_outAtBottom,di&1)->figures.moves[0].endPoint.x;
	dance->dancers[di].figures.moves[0].endPoint.y = danceFindRole(dance,r_outAtTop   ,di&1)->figures.moves[0].endPoint.y;
    }
    dance->dancers[di].figures.moves[0].part_mask = -1;
    if ( dance->formation==sp_threeFaceThree || dance->formation==sp_fourFaceFour )
	dance->dancers[di].figures.moves[0].degrees=90;
    else if ( dance->sicilian ) {
	/* The old style progression in a sisilian circle starts with just the */
	/* 1s+2s active, with every one on the 2s half of the circle facing the 1s */
	/* and every one on the 1s half facing the 2s */
	if ( di>dance->people/2+1 )
	    dance->dancers[di].figures.moves[0].degrees=-90;
	else
	    dance->dancers[di].figures.moves[0].degrees=90;
    } else if ( role==r_waiting_left )
	dance->dancers[di].figures.moves[0].degrees=0;
    else if ( role==r_waiting_right )
	dance->dancers[di].figures.moves[0].degrees=180;
    else if ( di&1 )
	dance->dancers[di].figures.moves[0].degrees=180;
    if ( danceFindRole(dance,role,dance->dancers[di].sex)!=NULL ) {
	/* In case we have an up a double sequence or something */
	/*  where everyone needs to be active */
	fillDancer(dance,di  ,danceRoleSex(dance,r_waiting,dance->dancers[di].sex));
    } else {
	dance->dancers[di].figures.moves[1].cmd = c_pause;
	dance->dancers[di].figures.moves[1].millibars = danceComponentMinorSetMillibarCount(dance);
	dance->dancers[di].figures.moves[1].part_mask = (unsigned int) -1;
	dance->dancers[di].figures.moves[1].part_mask = -1;
	dance->dancers[di].figures.moves[2].cmd = c_resetDance;
	dance->dancers[di].figures.moves[2].part_mask = (unsigned int) -1;
	dance->dancers[di].figures.moves[2].part_mask = -1;
	dance->dancers[di].figures.moves[3].cmd = c_end;
	dance->dancers[di].figures.moves[3].part_mask = -1;
    }
    dance->dancers[di].actualFigureStartPos = dance->dancers[di].figures.moves[0].endPoint;
}

static void setMoves(Dance *dance, int i ) {
    Person *p = dance->orderedList[i];
    Person *r = danceFindRole(dance,p->effective_role,p->effective_sex);
    int j;

    /* To allow for a little erratic behavior, use a different role sometimes */
    if ( p->effective_role==r_outAtBottom ) {
	Person *tempr = danceFindRole(dance,r_outAtBottom_alt,p->sex);
	if ( tempr!=NULL && tempr->couple_number==p->couple_number )
	    r = tempr;
    }

    for ( j=0; j<p->figures.move_cnt; ++j ) {
	free(p->figures.moves[j].levitation);
	free(p->figures.moves[j].outness);
    }
    p->figures.move_cnt = 0;
    if ( (p->effective_role==r_waiting || p->effective_role==r_waiting_left || p->effective_role==r_waiting_right) && r==NULL )
	makeDancerWait(dance,i,p->effective_role);
    else if ( r==NULL ) {
	fprintf( stderr, "Failed to find a role for this dancer.\n" );
	assert(r!=NULL);
    } else {
	blockCopyAndFlatten(&p->figures,&r->figures,p,dance);
	p->display_role = r->display_role;
    }
    p->current = p->figures.moves;
    if ( r!=NULL )
	p->actualFigureStartPos = r->actualFigureStartPos;

    if ( p->effective_role == r_1s_progression )
	p->effective_role = r_1s;
    else if ( p->effective_role == r_3s_progression && danceHasBuiltInScottish4CoupleProgressionPre(dance))
	p->effective_role = r_3s;
    else if ( p->effective_role == r_3s_progression && danceHasBuiltInScottish4CoupleProgressionPost(dance))
	p->effective_role = r_outAtBottom;
    else if ( p->effective_role == r_4s_progression )
	p->effective_role = r_3s;	/* Yup, the 4s become 3s */

    assert( p->figures.moves[0].cmd==c_moveto );
}

static void translateMoves(Dance *dance, int i, int minorSetSize ) {
    Person *p = dance->orderedList[i];
    Position translate;
    int j;
    int mss;

    assert( p->figures.moves[0].cmd==c_moveto );
    translate.x = p->now.x - p->figures.moves[0].endPoint.x;
    if ( dance->becket_style!=bs_none )
	translate.x = p->now.x - p->actualFigureStartPos.x;
    /*translate.y = p->now.y - p->figures.moves[0].endPoint.y;*/	/* This breaks Impropriety, and I don't think it is ever correct */
    translate.y = 0;
    for ( j=0; j<p->figures.move_cnt; ++j ) {
	FigureSegment *cs = &p->figures.moves[j];
	if (( cs->cmd==c_moveto || cs->cmd==c_lineto || cs->cmd==c_curveto ) && !cs->position_absolute ) {
	    cs->endPoint.x += translate.x;
	    cs->endPoint.y += translate.y;
	    if ( cs->cmd==c_curveto ) {
		cs->cp1.x += translate.x;
		cs->cp1.y += translate.y;
		cs->cp2.x += translate.x;
		cs->cp2.y += translate.y;
	    }
	    if ( cs->cmd==c_lineto || cs->cmd==c_curveto ) {
		cs->splines[0].d += translate.x;
		cs->splines[1].d += translate.y;
	    }
	}
	/* Figuring out whether star_center is useful involves too many checks */
	/*  easier just to always update it. If it isn't used, it won't be looked at */
	if ( !cs->position_absolute ) {
	    cs->star_center.x += translate.x;
	    cs->star_center.y += translate.y;
	}
	if ( cs->join_right_hand!=0 || cs->join_left_hand!=0 || cs->orient==mo_faceDancer ) {
	    int minor_set_start = -999;
	    mss = minorSetSize;
	    if ( p->effective_role==r_outAtTop || p->effective_role==r_outAtBottom ) {
		if ( dance->formation!=sp_threeFaceThree ) {
		    if ( p->sex==s_male )
			minor_set_start = i;
		    else
			minor_set_start = i-1;
		    mss = 2;
		} else {
		    minor_set_start= 3* (i/3);
		    mss = 3;
		}
	    } else if ( p->effective_role==r_outAtTop1of2 || p->effective_role==r_outAtBottom1of2 ) {
		if ( p->sex==s_male )
		    minor_set_start = i;
		else
		    minor_set_start = i-1;
		mss = 4;
	    } else if ( p->effective_role==r_outAtTop2of2 || p->effective_role==r_outAtBottom2of2 ) {
		if ( p->sex==s_male )
		    minor_set_start = i-2;
		else
		    minor_set_start = i-3;
		mss = 4;
	    } else if ( p->effective_role==r_outAtTop1of3 || p->effective_role==r_outAtBottom1of3 ) {
		if ( p->sex==s_male )
		    minor_set_start = i;
		else
		    minor_set_start = i-1;
		mss = 6;
	    } else if ( p->effective_role==r_outAtTop2of3 || p->effective_role==r_outAtBottom2of3 ) {
		if ( p->sex==s_male )
		    minor_set_start = i-2;
		else
		    minor_set_start = i-3;
		mss = 6;
	    } else if ( p->effective_role==r_outAtTop3of3 || p->effective_role==r_outAtBottom3of3 ) {
		if ( p->sex==s_male )
		    minor_set_start = i-4;
		else
		    minor_set_start = i-5;
		mss = 6;
	    } else if ( p->effective_role==r_1s ) {
		if ( dance->formation==sp_threeFaceThree )
		    minor_set_start = 3*(i/3);
		else if ( dance->formation==sp_dupleMinorProgressed ) {
		    if ( p->effective_sex==s_male )
			minor_set_start = i-2;
		    else if ( p->effective_sex==s_female )
			minor_set_start = i-3;
		} else if ( p->effective_sex==s_male )
		    minor_set_start = i;
		else if ( p->effective_sex==s_female )
		    minor_set_start = i-1;
#if 0
		else if ( p->effective_sex==s_left )
		    minor_set_start = i;
		else if ( p->effective_sex==s_center )
		    minor_set_start = i-1;
		else if ( p->effective_sex==s_right )
		    minor_set_start = i-2;
#endif
	    } else if ( p->effective_role==r_2s ) {
		if ( dance->formation==sp_threeFaceThree )
		    minor_set_start = 3*(i/3)-3;
		else if ( dance->formation==sp_dupleMinorProgressed ) {
		    if ( p->effective_sex==s_male )
			minor_set_start = i;
		    else if ( p->effective_sex==s_female )
			minor_set_start = i-1;
		} else if ( p->effective_sex==s_male )
		    minor_set_start = i-2;
		else if ( p->effective_sex==s_female )
		    minor_set_start = i-3;
#if 0
		else if ( p->effective_sex==s_left )
		    minor_set_start = i-3;
		else if ( p->effective_sex==s_center )
		    minor_set_start = i-4;
		else if ( p->effective_sex==s_right )
		    minor_set_start = i-5;
#endif
	    } else if ( p->effective_role==r_3s ) {
		if ( p->sex==s_male )
		    minor_set_start = i-4;
		else
		    minor_set_start = i-5;
	    } else if ( p->effective_role==r_4s ) {
		if ( p->sex==s_male )
		    minor_set_start = i-6;
		else
		    minor_set_start = i-7;
	    } else if ( p->effective_role==r_outAtTopLeft || p->effective_role==r_outAtBottomLeft ) {
		if ( p->sex==s_male )
		    minor_set_start = i-0;
		else
		    minor_set_start = i-1;
		mss = 4;
	    } else if ( p->effective_role==r_outAtTopRight || p->effective_role==r_outAtBottomRight ) {
		if ( p->sex==s_male )
		    minor_set_start = i-2;
		else
		    minor_set_start = i-3;
		mss = 4;
	    } else if ( p->effective_role==r_1sleft ) {
		if ( p->sex==s_male )
		    minor_set_start = i-0;
		else
		    minor_set_start = i-1;
	    } else if ( p->effective_role==r_1sright ) {
		if ( p->sex==s_male )
		    minor_set_start = i-2;
		else
		    minor_set_start = i-3;
	    } else if ( p->effective_role==r_2sleft ) {
		if ( p->sex==s_male )
		    minor_set_start = i-4;
		else
		    minor_set_start = i-5;
	    } else if ( p->effective_role==r_2sright ) {
		if ( p->sex==s_male )
		    minor_set_start = i-6;
		else
		    minor_set_start = i-7;
	    } else if ( p->effective_role==r_waiting ) {
		if ( p->sex==s_male )
		    minor_set_start = i-0;
		else
		    minor_set_start = i-1;
		mss = 2;
	    } else
		assert(false);
#if 0
	    if ( !(cs->join_right_hand&HAND_MINORSET_UP) && (cs->join_right_hand&HAND_MINORSET_MASK)!=0 &&
		    refigureHand(dance,minor_set_start,mss,cs->join_right_hand)==0 )
 printf( "Debug!!! Right\n" );
#endif
	    cs->join_right_hand = refigureHand(dance,minor_set_start,mss,minorSetSize,cs->join_right_hand);
#if 0
	    if ( !(cs->join_left_hand&HAND_MINORSET_UP) && (cs->join_left_hand&HAND_MINORSET_MASK)!=0 &&
		    refigureHand(dance,minor_set_start,mss,minorSetSize,cs->join_left_hand)==0 )
 printf( "Debug!!! Left\n" );
#endif
	    cs->join_left_hand  = refigureHand(dance,minor_set_start,mss,minorSetSize,cs->join_left_hand);
	    if ( cs->orient==mo_faceDancer ) {
		/* cs->faceDancer += minor_set_start; */ /* Original code was simple, and I think wrong, new code untested */
		int role = dance->roles[cs->faceDancer].effective_role;
		int sex  = dance->roles[cs->faceDancer].sex;
		int dancer = minorSetFindIndexOfRole(dance,minor_set_start,mss,
			role, sex);
		cs->faceDancer = dancer;
	    }
	}
    }
}

CallList *danceFindFirstCallInCurrentPart(CallList *cl, int cnt, int mask) {
    int i;

    for ( i=0; i<cnt; ++i, ++cl )
	if ( cl->part_mask&mask )
return( cl );

return( NULL );
}

/* ScottishFixup, ScottishProgression */
static void switch3s4s(Dance *dance) {
    /* In a scottish 4 couple triple set, the 1s dance their role twice */
    /* then there are 2 couples out above and 2 couples out below */
    /* In Scottish, the couple at the top becomes new 1s */
    /*  And the couples in positions 3&4 switch */
    /* What that means is that the couple in 3rd position, currently set up as 3s */
    /*  must get a few extra commands to move it to the bottom of the set, and */
    /*  then take the remaining moves from couple 4 to become out at bottom */
    /* Conversely couple in 4th position get some extra moves to go to the 3rd*/
    /*  position and then takes the remaining moves from couple 3 */
    /* And in a 7 (10, 13, ...) couple set, it is the 6s & 7s (9s&10s, ...) */
    /*  which do this */
    int cnts[8], maxs[8];
    FigureSegment *newCs, *news[8];
    int i,j,k, base;
    int m3, f3;
    int m4, f4;

    base = dance->people - 4;
/* When we start, the old 1s have role r_3s, and the bottom couple has role r_outAtBottom */
    dance->orderedList[base+0]->effective_role = r_outAtBottom;
    dance->orderedList[base+1]->effective_role = r_outAtBottom;
    dance->orderedList[base+2]->effective_role = r_3s;
    dance->orderedList[base+3]->effective_role = r_3s;

    for ( i=base; i<base+4; ++i ) {
	Person *p = dance->orderedList[i];
	Person *otherp;
	/*Person *partner;*/
	if ( i<base+2 )
	    otherp = dance->orderedList[i+2];
	else
	    otherp = dance->orderedList[i-2];
	/* partner = dance->orderedList[i^1]; */
	newCs = calloc((2+otherp->figures.move_cnt+4),sizeof( FigureSegment ));
	newCs[0] = p->figures.moves[0];		/* The first entry is the moveto and we want that */
	newCs[1] = p->figures.moves[0];		/* Initialize fields to something reasonable */
	newCs[2] = p->figures.moves[0];
	newCs[3] = p->figures.moves[0];

	newCs[1].cmd = c_lineto;
	newCs[1].millibars = 500;
	newCs[1].orient = mo_fixed;
	newCs[1].part_mask = (unsigned int) -1;
	newCs[1].endPoint.x = (p->figures.moves[0].endPoint.x + otherp->figures.moves[0].endPoint.x)/2;
	/* 1s step behind, 3s in front */
	if ( ((i==base+1 || i==base+2) && dance->improper_mask==0 ) ||
		((i==base || i==base+2) && dance->improper_mask==1 ) )
	    newCs[1].endPoint.y = otherp->figures.moves[0].endPoint.y+64;
	else
	    newCs[1].endPoint.y = otherp->figures.moves[0].endPoint.y-64;
	newCs[2].cmd = c_lineto;
	newCs[2].millibars = 500;
	newCs[2].orient = mo_fixed;
	newCs[2].part_mask = (unsigned int) -1;
	newCs[2].endPoint = otherp->figures.moves[0].endPoint;
	splineMake(newCs+1,&p->figures.moves[0].endPoint);
	splineMake(newCs+2,&newCs[1].endPoint);
	if ( otherp->figures.moves[1].cmd == c_pause &&
		otherp->figures.moves[1].millibars >= 1000 )
	    /* Good */;
	else {
	    fprintf( stderr, "There's not enough time to do a scottish progression at the end of the 2nd time through.\n" );
	    assert( otherp->figures.moves[1].cmd == c_pause &&
		    otherp->figures.moves[1].millibars >= 1000 );
	}
	j=3;
	if ( otherp->figures.moves[1].join_right_hand!=0 ) {
	    otherp->figures.moves[1].join_right_millibars-=1000;
	    
	    if ( otherp->figures.moves[1].join_right_millibars<0 ) {
		fprintf( stderr, "Right hand clasp lost in scottish progression.\n" );
		otherp->figures.moves[1].join_right_hand = 0;
	    } else if ( otherp->figures.moves[1].join_right_millibars==0 ) {
		newCs[2].join_right_hand = otherp->figures.moves[1].join_right_hand;
		newCs[2].join_right_millibars = 500;
		otherp->figures.moves[1].join_right_hand = 0;
	    }
	}
	if ( otherp->figures.moves[1].join_left_hand!=0 ) {
	    otherp->figures.moves[1].join_left_millibars-=1000;
	    
	    if ( otherp->figures.moves[1].join_left_millibars<0 ) {
		fprintf( stderr, "Left hand clasp lost in scottish progression.\n" );
		otherp->figures.moves[1].join_left_hand = 0;
	    } else if ( otherp->figures.moves[1].join_left_millibars==0 ) {
		newCs[2].join_left_hand = otherp->figures.moves[1].join_left_hand;
		newCs[2].join_left_millibars = 500;
		otherp->figures.moves[1].join_left_hand = 0;
	    }
	}
	if ( otherp->figures.moves[1].millibars>1000 ) {
	    newCs[3] = otherp->figures.moves[1];
	    newCs[3].millibars -= 1000;
	    j=4;
	}
	memcpy(newCs+j,otherp->figures.moves+2,(otherp->figures.move_cnt-2)*sizeof(FigureSegment));
	news[i-base] = newCs;
	cnts[i-base] = j+otherp->figures.move_cnt-2;
	maxs[i-base] = 2+otherp->figures.move_cnt+4;
    }
    /* I don't need to reallocate/free levitation/outness because the simple copies just work */
    for ( i=base; i<base+4; ++i ) {
	Person *p = dance->orderedList[i];
	free(p->figures.moves);
	p->figures.moves = news[i-base];
	p->figures.move_cnt = cnts[i-base];
	p->figures.move_max = maxs[i-base];
	p->current = p->figures.moves+1;
    }

    /* One last problem: hand clasps, we need to switch any clasps intended for */
    /*  the couple in 3rd place to the couple in 4th place */
    /* (and if the 4th place couple take hands (even though they are out they might need to move down when lines move down) */
    /*  then they'll need their clasps adjusted too) */
    m3 = dance->orderedList[base+0] - dance->dancers;
    f3 = dance->orderedList[base+1] - dance->dancers;
    m4 = dance->orderedList[base+2] - dance->dancers;
    f4 = dance->orderedList[base+3] - dance->dancers;
    for ( i=0; i<dance->people; ++i ) {
	Person *p = dance->orderedList[i];
	for ( k=0; k<p->figures.move_cnt; ++k ) {
	    FigureSegment *cs = &p->figures.moves[k];
	    if ( cs->join_right_hand&(HAND_RIGHT_MASK|HAND_LEFT_MASK) ) {
		if ( (cs->join_right_hand&HAND_INDIVIDUAL_MASK)== m3 )
		    cs->join_right_hand =
			    (cs->join_right_hand&~HAND_INDIVIDUAL_MASK)|m4;
		else if ( (cs->join_right_hand&HAND_INDIVIDUAL_MASK)== f3 )
		    cs->join_right_hand =
			    (cs->join_right_hand&~HAND_INDIVIDUAL_MASK)|f4;
		else if ( (cs->join_right_hand&HAND_INDIVIDUAL_MASK)== m4 )
		    cs->join_right_hand =
			    (cs->join_right_hand&~HAND_INDIVIDUAL_MASK)|m3;
		else if ( (cs->join_right_hand&HAND_INDIVIDUAL_MASK)== f4 )
		    cs->join_right_hand =
			    (cs->join_right_hand&~HAND_INDIVIDUAL_MASK)|f3;
	    }
	    if ( cs->join_left_hand&(HAND_RIGHT_MASK|HAND_LEFT_MASK) ) {
		if ( (cs->join_left_hand&HAND_INDIVIDUAL_MASK)== m3 )
		    cs->join_left_hand =
			    (cs->join_left_hand&~HAND_INDIVIDUAL_MASK)|m4;
		else if ( (cs->join_left_hand&HAND_INDIVIDUAL_MASK)== f3 )
		    cs->join_left_hand =
			    (cs->join_left_hand&~HAND_INDIVIDUAL_MASK)|f4;
		else if ( (cs->join_left_hand&HAND_INDIVIDUAL_MASK)== m4 )
		    cs->join_left_hand =
			    (cs->join_left_hand&~HAND_INDIVIDUAL_MASK)|m3;
		else if ( (cs->join_left_hand&HAND_INDIVIDUAL_MASK)== f4 )
		    cs->join_left_hand =
			    (cs->join_left_hand&~HAND_INDIVIDUAL_MASK)|f3;
	    }
	}
    }
}

static Position *csPreviousEndPoint(FigureSegment *moves, FigureSegment *cs) {
    Position *last = NULL;
    int part_mask, p;

    part_mask = 0;
    for ( p=0 ; p<32; ++p )
	if ( (1<<p)&cs->part_mask ) {
	    part_mask = 1<<p;
    break;
	}
    if ( part_mask == 0 )
	part_mask = 1;

    last = &moves[0].endPoint;
    while ( moves!=cs ) {
	if ( (part_mask & moves->part_mask)) {
	    if ( cs->condition==moves->condition ||
		    moves->condition==if_always ||
		    moves->condition==if_nottopset ||
		    moves->condition==if_notbottomset ||
		    moves->condition==if_notsemitopset ||
		    moves->condition==if_notsemibottomset ||
		    moves->condition==if_nottopsetorsemi ||
		    moves->condition==if_notbottomsetorsemi ||
		    moves->condition==if_nottopbottomset ) {
		if ( moves->cmd==c_moveto || moves->cmd==c_lineto || moves->cmd==c_curveto )
		    last = &moves->endPoint;
	    }
	}
	++moves;
    }
return( last );
}

static void csChangeLineToDegenerateCurveto(FigureSegment *cs,Position *prev) {
    float diff_x, diff_y;

    if ( prev==NULL )
return;
    if ( cs->cmd!=c_lineto )
return;
    diff_x = cs->endPoint.x - prev->x;
    diff_y = cs->endPoint.y - prev->y;

    cs->cmd = c_curveto;
    cs->cp1.x = prev->x + diff_x/3;
    cs->cp1.y = prev->y + diff_y/3;
    cs->cp2.x = cs->endPoint.x - diff_x/3;
    cs->cp2.y = cs->endPoint.y - diff_y/3;
}

static void offsetCoordinates(Dance *dance,Position *pos, Person *p) {
    double r, theta;
    /* for each position we need to find a new r,theta value */
    /* theta is just our theta at the start of this minorset */
    /*  offset by the distance along the major set from pos.x back to where */
    /*  we were at start divided by the length (len) multiplied by 2*PI */
    /* r is y-middle + radius */
    /* with these we calculate new positions */

if ( p->couple_number==15 )
 r=1;		/* Debug breakpoint */
    r = dance->sicilian_midline-pos->y + dance->sicilian_radius;
    theta = p->now_sicilian_theta +
	    2*PI * (pos->x-p->figures.moves[0].endPoint.x)/dance->sicilian_circumference - PI/2;
assert( !isnan(theta));
    pos->x = r*cos(theta) + dance->sicilian_center.x;
    pos->y = r*sin(theta) + dance->sicilian_center.y;
}

static void offsetControlCoordinates(Dance *dance,Position *pos, Position *base, Person *p) {
    double r, theta;
    /* for each position we need to find a new r,theta value */
    /* theta is just our theta at the start of this minorset */
    /*  offset by the distance along the major set from pos.x back to where */
    /*  we were at start divided by the length (len) multiplied by 2*PI */
    /* r is y-middle + radius */
    /* with these we calculate new positions */

if ( p->couple_number==15 )
 r=1;		/* Debug breakpoint */
    r = dance->sicilian_midline-pos->y + dance->sicilian_radius;
    theta = p->now_sicilian_theta +
	    2*PI * (pos->x-p->figures.moves[0].endPoint.x)/dance->sicilian_circumference - PI/2;
assert( !isnan(theta));
    pos->x = r*cos(theta) + dance->sicilian_center.x;
    pos->y = r*sin(theta) + dance->sicilian_center.y;
}

static void offsetOrientation(Dance *dance,FigureSegment *cs, Person *p) {
    double theta;

    if ( cs->degrees==DEGREES_END )
return;
    theta = 360*p->now_sicilian_theta/(2*PI) +
	    360 * (cs->endPoint.x-p->figures.moves[0].endPoint.x)/dance->sicilian_circumference;
    cs->degrees += theta;
    if ( cs->degrees>360 )
	cs->degrees -= 360;
}

static int danceSicilianFigureClasp(Dance *dance,Person *p, int clasp, int minor_set_size ) {
    int minor_set_start;
    int setoff;
    int person;

    if ( clasp==0 )
return( 0 );
    if ( (clasp&HAND_INDIVIDUAL_MASK)==HAND_STAR )
return( clasp );

    if ( dance->formation==sp_threeFaceThree || dance->formation==sp_trioCircularMonople ) {
	minor_set_start = 3*p->current_pos;
	if ( p->effective_role==r_2s )
	    minor_set_start -= 3;
    } else switch ( p->effective_role ) {
      case r_1s: case r_1sleft:
	minor_set_start = 2*p->current_pos;
      break;
      case r_2s: case r_1sright:
	minor_set_start = 2*p->current_pos-2;
      break;
      case r_3s: case r_2sleft:
	minor_set_start = 2*p->current_pos-4;
      break;
      case r_2sright:
	minor_set_start = 2*p->current_pos-6;
      break;
      default:
	assert(false);
    }
    person = (clasp&HAND_INDIVIDUAL_MASK);
/*    role = dance->roles[person].effective_role; */
/*    sex  = dance->roles[person].sex; */

    setoff = (clasp&HAND_MINORSET_OFFSET)>>HAND_MINORSET_SHIFT;
    if ( clasp&HAND_MINORSET_UP )
	setoff = -setoff;
    person += minor_set_start + setoff*minor_set_size;
    while ( person<0 )
	person += dance->people;
    while ( person>= dance->people )
	person -= dance->people;
    person = dance->orderedList[person] - dance->dancers;
return( person | (clasp&HAND_COPY_MASK));
}

static void danceSicilianFigure4Face4Roles(Dance *dance) {
    int i;
    int first;

    if ( dance->orderedList[0]->effective_role == r_2sleft || dance->orderedList[0]->effective_role == r_2sright ) {
	Person *space[4];
	memcpy(space,dance->orderedList,4*sizeof(Person *));
	for ( i=4; i<dance->people; ++i )
	    dance->orderedList[i-4] = dance->orderedList[i];
	memcpy(dance->orderedList+dance->people-4,space,4*sizeof(Person *));
    }
    first = 1;
    for ( i=0; i<dance->people; i+=2 ) {
	if ( dance->orderedList[i]->effective_role==r_1sleft ||
		dance->orderedList[i]->effective_role==r_1sright ) {
	    if ( first ) {
		dance->orderedList[i]->effective_role= r_1sleft;
		dance->orderedList[i+1]->effective_role= r_1sleft;
	    } else {
		dance->orderedList[i]->effective_role= r_1sright;
		dance->orderedList[i+1]->effective_role= r_1sright;
	    }
	} else {
	    if ( first ) {
		dance->orderedList[i]->effective_role= r_2sleft;
		dance->orderedList[i+1]->effective_role= r_2sleft;
	    } else {
		dance->orderedList[i]->effective_role= r_2sright;
		dance->orderedList[i+1]->effective_role= r_2sright;
	    }
	}
	first = !first;
    }
}

static void danceSicilianFigureTripleRoles(Dance *dance) {
    /* 1s are fixed, 2s, 3s probaby not. So find first 1 */
    int i,j;
    enum role role;

    for ( i=0; i<dance->people; ++i )
	if ( dance->orderedList[i]->effective_role == r_1s )
    break;
    role = r_2s;
    for ( j=i+3; j<dance->people; j+=2 ) {
	if ( role==r_1s ) {
	    assert( dance->orderedList[j-1]->effective_role == r_1s );
	    assert( dance->orderedList[j]->effective_role == r_1s );
	} else {
	    dance->orderedList[j-1]->effective_role = role;
	    dance->orderedList[j]->effective_role = role;
	}
	++role;
	if ( role==r_4s )
	    role = r_1s;
    }
    role = r_3s;
    for ( j=i-2; j>=0; j-= 2 ) {
	dance->orderedList[j+1]->effective_role = role;
	dance->orderedList[j]->effective_role = role;
	--role;
    }
}

static void danceSicilianFigure3Face3Sexes(Dance *dance) {
    int i;

    for ( i=0; i<dance->people; i+=3 ) {
	dance->orderedList[i+0]->effective_sex = s_left;
	dance->orderedList[i+1]->effective_sex = s_center;
	dance->orderedList[i+2]->effective_sex = s_right;
    }
}
	    
static double initialRadius(Person *p, Dance *dance) {
    Position *initPos = &p->figures.moves[0].endPoint;

return( (initPos->x-dance->sicilian_center.x) *
	 (initPos->x-dance->sicilian_center.x) +
	 (initPos->y-dance->sicilian_center.y) *
	 (initPos->y-dance->sicilian_center.y));
}

static Person *findBest(Dance *dance, enum role role, enum sex sex, double baseTheta) {
    int k, best_k;
    double best_off;

    best_off = 1e38;
    best_k   = -1;
    for ( k=0; k<dance->people; ++k ) {
	Person *p = &dance->dancers[k];
	if ( !p->ticked && p->effective_role==role && p->sex==sex ) {
	    double off = p->now_sicilian_theta - baseTheta;
	    if ( off <0 ) off = -off;
	    if ( off>PI ) off = 2*PI-off;
	    if ( off<best_off ) {
		best_off = off;
		best_k = k;
	    }
	}
    }
    if ( best_k==-1 ) {
	fprintf( stderr, "Failed to find %s %c.\n", roleNames[role], sexChars[sex] );
	assert( best_k!=-1 );
    }
    dance->dancers[best_k].ticked = true;
return( &dance->dancers[best_k]);
}

static double femaleOffset(Dance *dance,Position *male,Position *female) {
    double angle_fudge = 2*PI/(2*dance->people);
    double mtheta, ftheta, off;

    mtheta = atan2(male->y-dance->sicilian_center.y,
		   male->x-dance->sicilian_center.x) + PI/2;
    mtheta = angle_fudge * round(mtheta/angle_fudge);
    ftheta = atan2(female->y-dance->sicilian_center.y,
		   female->x-dance->sicilian_center.x) + PI/2;
    ftheta = angle_fudge * round(ftheta/angle_fudge);
    off = ftheta-mtheta;
    if ( off>PI ) off = off-2*PI;
    if ( off<PI ) off = 2*PI+off;
return( off );
}

static void danceAssignRotatedTripleMinorRoles(Dance *dance) {
    double radius1=-1, radius2=-1, radius3=-1;
    double femaleOff;
    int i,j;
    Person **r1s_m;
  enum role debugr;		/* !!! Debug !!! */

    for ( i=0; i<dance->people; ++i )
	dance->dancers[i].ticked = 0;

    if ( dance->orderedList==NULL ) {
	dance->orderedList = malloc(dance->people*sizeof(Person *));
	femaleOff = femaleOffset(dance,&dance->dancers[0].figures.moves[0].endPoint,&dance->dancers[1].figures.moves[0].endPoint );
    } else
	femaleOff = femaleOffset(dance,&dance->orderedList[0]->figures.moves[0].endPoint,&dance->orderedList[1]->figures.moves[0].endPoint );

    for ( i=0; i<dance->people; ++i ) {
	if ( dance->dancers[i].effective_role == r_1s ) {
	    radius1 = initialRadius(&dance->dancers[i],dance);
    break;
	}
    }
    for ( i=0; i<dance->people; ++i ) {
	if ( dance->dancers[i].effective_role == r_2s ) {
	    radius2 = initialRadius(&dance->dancers[i],dance);
    break;
	}
    }
    for ( i=0; i<dance->people; ++i ) {
	if ( dance->dancers[i].effective_role == r_3s ) {
	    radius3 = initialRadius(&dance->dancers[i],dance);
    break;
	}
    }
    assert( radius1!=-1 && radius2!=-1 && radius3!=-1 );

    for ( i=0; i<dance->people; ++i ) {
	Person *p = &dance->dancers[i];
	double off1 = p->now_sicilian_radius - radius1;
	double off2 = p->now_sicilian_radius - radius2;
	double off3 = p->now_sicilian_radius - radius3;
	if ( off1<0 ) off1=-off1;
	if ( off2<0 ) off2=-off2;
	if ( off3<0 ) off3=-off3;
  debugr = p->effective_role;
	if ( off1<off2 && off1<off3 )
	    p->effective_role = r_1s;
	else if ( off2<off3 )
	    p->effective_role = r_2s;
	else
	    p->effective_role = r_3s;
  assert(debugr==p->effective_role ); 	/* !!! Debug this is always true of Dudley's Reel */
    }

    r1s_m = malloc(dance->people/6*sizeof(Person *));
    for ( i=j=0; i<dance->people; ++i ) {
	Person *p = &dance->dancers[i];
	if ( p->effective_role == r_1s && p->sex==s_male ) {
	    r1s_m[j++] = p;
	    p->ticked = true;
	}
    }
    assert(j==dance->people/6);
    qsort(r1s_m,j,sizeof(Person *),xSicilianRTM_1s_m_Compare);

    for ( i=0; i<j; ++i ) {
	Person *base = r1s_m[i];
	dance->orderedList[6*i+0] = base;
	dance->orderedList[6*i+1] = findBest(dance,r_1s,s_female,base->now_sicilian_theta+femaleOff);
	dance->orderedList[6*i+2] = findBest(dance,r_2s,s_male,base->now_sicilian_theta);
	dance->orderedList[6*i+3] = findBest(dance,r_2s,s_female,base->now_sicilian_theta+femaleOff);
	dance->orderedList[6*i+4] = findBest(dance,r_3s,s_male,base->now_sicilian_theta);
	dance->orderedList[6*i+5] = findBest(dance,r_3s,s_female,base->now_sicilian_theta+femaleOff);
    }
    free(r1s_m);
}

static void danceResetSicilianOctoberFlurry(Dance *dance,int frame, int frames_per_bar ) {
    int i;
    /* This dance has a very weird progression */
    /* It's a mixer where the women progress normally and the men stay */
    /* about the same place but switch between being 1s and 2s */

    /* the men will always stay in the same order */
    /* But when dancers[0] is a 2 he is paired with the last man, and when he's */
    /*  a 1 his is paired with the 2nd man. (This affects the "cut") */
    /* women always retain the same role and are paired with the closest man */

    if ( dance->orderedList==NULL )
	dance->orderedList = malloc(dance->people*sizeof(Person *));
    for ( i=0; i<dance->people; i+=2 ) {
	Person *p = &dance->dancers[i];
	p->effective_role = ( p->effective_role==r_1s ) ? r_2s : r_1s;
    }
    if ( dance->dancers[0].effective_role==r_2s ) {
	dance->orderedList[0] = &dance->dancers[dance->people-2];
	dance->dancers[dance->people-2].current_pos=0;
	for ( i=0; i<dance->people-2; i+=2 ) {
	    dance->orderedList[i+2] = &dance->dancers[i];
	    dance->dancers[i].current_pos = i/2+1;
	}
    } else {
	for ( i=0; i<dance->people; i+=2 ) {
	    dance->orderedList[i] = &dance->dancers[i];
	    dance->dancers[i].current_pos = i/2;
	}
    }
    for ( i=1; i<dance->people; i+=2 )
	dance->orderedList[i] = NULL;

    for ( i=0; i<dance->people; ++i ) {
	Person *p = &dance->dancers[i];
	p->now_sicilian_theta = atan2(p->now.y-dance->sicilian_center.y,
				      p->now.x-dance->sicilian_center.x);
    }
    for ( i=1; i<dance->people; i+=2 ) {
	Person *f = &dance->dancers[i];
	Person *bestm;
	int j, bestj;
	double d, bestd;
	bestj = -1;
	bestd = 1e+10;
	for ( j=0; j<dance->people; j+=2 ) { 
	    Person *m = &dance->dancers[j];
	    d = f->now_sicilian_theta - m->now_sicilian_theta;
	    if ( d<0 ) d = -d;
	    if ( d>PI )
		d = 2*PI-d;
	    if ( d<bestd ) {
		bestd = d;
		bestj = j;
	    }
	}
	bestm = &dance->dancers[bestj];
	if ( dance->orderedList[2*bestm->current_pos+1]!=NULL ) {
	    int k;
	    fprintf( stderr, "Attempt to give a man two partners in ResetSicilianOctober.\n" );
	    fprintf( stderr, "people=%d\n", dance->people );
	    fprintf( stderr, "Man=%d woman1=%d woman2=%d\n", bestj, (int) (dance->orderedList[bestm->current_pos+1]-dance->dancers), i );
	    fprintf( stderr, "Man theta=%.3f woman1 theta=%.3f woman2 theta=%.3f\n",
		bestm->now_sicilian_theta, dance->orderedList[bestm->current_pos+1]->now_sicilian_theta, f->now_sicilian_theta );
	    fprintf( stderr, "man[n-2]=%.3f man[n-4]=%.3f\n",
		dance->dancers[dance->people-2].now_sicilian_theta,
		dance->dancers[dance->people-4].now_sicilian_theta );
	    for ( k=0; k<dance->people; ++k )
		fprintf( stderr, "%d: %.3f\n", k, dance->dancers[k].now_sicilian_theta );
	    abort();
	}
	f->current_pos = bestm->current_pos;
	dance->orderedList[2*bestm->current_pos+1] = f;
    }
    /* Probably unnecessary, but let's be consistent */
    for ( i=0; i<dance->people; ++i ) {
	Person *p = &dance->dancers[i];
	p->now_sicilian_theta += PI/2;
    }
}

static void danceResetSicilianWitchesCauldron(Dance *dance,int frame, int frames_per_bar ) {
    int i;
    /* This dance has a very weird progression */
    /* It's a mixer where the men progress normally and the women stay */
    /* about the same place but switch between being 1s and 2s */
    /* (It's the opposite of October Flurry) */

    /* the women will always stay in the same order */
    /* But when dancers[1] is a 2 she is paired with the last woman, and when she's */
    /*  a 1 she is is paired with the 2nd woman. (This affects the "cut") */
    /* men always retain the same role and are paired with the closest woman */

    if ( dance->orderedList==NULL )
	dance->orderedList = malloc(dance->people*sizeof(Person *));
    for ( i=1; i<dance->people; i+=2 ) {
	Person *p = &dance->dancers[i];
	p->effective_role = ( p->effective_role==r_1s ) ? r_2s : r_1s;
    }
    if ( dance->dancers[1].effective_role==r_2s ) {
	dance->orderedList[1] = &dance->dancers[dance->people-1];
	dance->dancers[dance->people-1].current_pos=0;
	for ( i=1; i<dance->people-2; i+=2 ) {
	    dance->orderedList[i+2] = &dance->dancers[i];
	    dance->dancers[i].current_pos = i/2+1;
	}
    } else {
	for ( i=1; i<dance->people; i+=2 ) {
	    dance->orderedList[i] = &dance->dancers[i];
	    dance->dancers[i].current_pos = i/2;
	}
    }
    for ( i=0; i<dance->people; i+=2 )
	dance->orderedList[i] = NULL;

    for ( i=0; i<dance->people; ++i ) {
	Person *p = &dance->dancers[i];
	p->now_sicilian_theta = atan2(p->now.y-dance->sicilian_center.y,
				      p->now.x-dance->sicilian_center.x);
    }
    for ( i=0; i<dance->people; i+=2 ) {
	Person *m = &dance->dancers[i];
	Person *bestf;
	int j, bestj;
	double d, bestd;
	bestj = -1;
	bestd = 1e+10;
	for ( j=1; j<dance->people; j+=2 ) { 
	    Person *f = &dance->dancers[j];
	    d = f->now_sicilian_theta - m->now_sicilian_theta;
	    if ( d<0 ) d = -d;
	    if ( d>PI )
		d = 2*PI-d;
	    if ( d<bestd ) {
		bestd = d;
		bestj = j;
	    }
	}
	bestf = &dance->dancers[bestj];
	if ( dance->orderedList[2*bestf->current_pos]!=NULL ) {
	    int k;
	    fprintf( stderr, "Attempt to give a woman two partners in ResetSicilianWitches.\n" );
	    fprintf( stderr, "people=%d\n", dance->people );
	    fprintf( stderr, "Woman=%d man1=%d man2=%d\n", bestj, (int) (dance->orderedList[2*bestf->current_pos]-dance->dancers), i );
	    fprintf( stderr, "Woman theta=%.3f man1 theta=%.3f man2 theta=%.3f\n",
		bestf->now_sicilian_theta, dance->orderedList[2*bestf->current_pos]->now_sicilian_theta, m->now_sicilian_theta );
	    fprintf( stderr, "woman[n-2]=%.3f woman[n-4]=%.3f\n",
		dance->dancers[dance->people-1].now_sicilian_theta,
		dance->dancers[dance->people-3].now_sicilian_theta );
	    for ( k=0; k<dance->people; ++k )
		fprintf( stderr, "%d: %.3f\n", k, dance->dancers[k].now_sicilian_theta );
	    abort();
	}
	m->current_pos = bestf->current_pos;
	dance->orderedList[2*bestf->current_pos] = m;
    }
    /* Probably unnecessary, but let's be consistent */
    for ( i=0; i<dance->people; ++i ) {
	Person *p = &dance->dancers[i];
	p->now_sicilian_theta += PI/2;
    }
}

static void danceResetSicilian(Dance *dance,int frame, int frames_per_bar ) {
    /* for duple minor (and 4 face 4, becket) everyone stays in the same */
    /*  role, but the moves need to be rotated to reflect their new position */
    /* for triple minor, 1s stay 1s through out but 2s and 3s probably switch */
    /* So for triple minor we should probably order the dancers, order them */
    /*  based on theta which is calculated in the obvious way from the dancer's */
    /*  current position with respect to dance->sicilian_center */
    /* (We'll need this value anyway to readapt the moves) */
    /* Oops 4 face 4 will probably swap lefts and rights so they change roles too */
    /*  We need the r value here to figure which is closer to the center, which right which left */
    /* We don't handle hand-clasps out of set. Need to be ready to wrap !!!!! */
    int i,j;
    int mss;
    Position here;
    double angle_fudge = 2*PI/(2*dance->people);
    double cut = 0;

    if ( dance->name!=NULL && strcmp(dance->name,"October Flurry")==0 ) {
	danceResetSicilianOctoberFlurry(dance,frame,frames_per_bar);
    } else if ( dance->name!=NULL && strcmp(dance->name,"Witches' Cauldron")==0 ) {
	danceResetSicilianWitchesCauldron(dance,frame,frames_per_bar);
    } else {
    if ( dance->tags!=NULL && strstr(dance->tags,"mixer")!=NULL ) {
	double biggest_gap;
	int biggest_i;
	for ( i=0; i<dance->people ; ++i ) {
	    Person *p = &dance->dancers[i];
	    p->now_sicilian_theta = atan2(p->now.y-dance->sicilian_center.y,
					  p->now.x-dance->sicilian_center.x) + PI/2;
	}
	if ( dance->formation==sp_threeFaceThree )
	    order(dance,xSicilian3Face3Compare);
	else
	    order(dance,xSicilianCompare);
	biggest_i = -1;
	biggest_gap = -1;
	for ( i=1; i<dance->people; ++i ) {
	    double gap = dance->orderedList[i]->now_sicilian_theta - dance->orderedList[i-1]->now_sicilian_theta;
	    if ( gap<0 )
		gap = -gap;
	    while ( gap>2*PI ) gap -= 2*PI;
	    if ( gap>PI )
		gap = 2*PI-gap;
	    if ( gap>biggest_gap ) {
		biggest_gap = gap;
		biggest_i = i;
	    }
	}
	if ( biggest_i==-1 )	/* all at the same place */
	    biggest_i = 1;
	cut = (dance->orderedList[biggest_i]->now_sicilian_theta + dance->orderedList[biggest_i-1]->now_sicilian_theta ) / 2;
	for ( i=0; i<dance->people ; ++i ) {
	    Person *p = &dance->dancers[i];
	    p->now_sicilian_theta -= cut;
	    while ( p->now_sicilian_theta < 0 )
		p->now_sicilian_theta += 2*PI;
	    while ( p->now_sicilian_theta >= 2*PI )
		p->now_sicilian_theta -= 2*PI;
	}
	order(dance,xSicilianCompare);
    } else {
	for ( i=0; i<dance->people ; ++i ) {
	    Person *p = &dance->dancers[i];
	    p->now_sicilian_theta = atan2(p->now.y-dance->sicilian_center.y,
					  p->now.x-dance->sicilian_center.x) + PI/2;
	    p->now_sicilian_theta = angle_fudge * round(p->now_sicilian_theta/angle_fudge);
	    if ( p->now_sicilian_theta > 3*PI/2 )
		p->now_sicilian_theta -= 2*PI;
	    if ( p->now_sicilian_theta < -PI/2 )
		p->now_sicilian_theta += 2*PI;

	    if ( dance->formation==sp_fourFaceFour || dance->formation==sp_tempest ||
		    dance->formation==sp_quadrupleMinorBecket ||
		    dance->formation==sp_threeFaceThree ||
		    dance->formation==sp_rotatedTripleMinor ||
		    dance->formation==sp_becket || dance->formation==sp_becketCCW )
		p->now_sicilian_radius = (p->now.x-dance->sicilian_center.x) *
					 (p->now.x-dance->sicilian_center.x) +
					 (p->now.y-dance->sicilian_center.y) *
					 (p->now.y-dance->sicilian_center.y);
	    }

#if 0
for ( i=0; i<dance->people; ++i ) {	/* !!!!! Debug */
	Person *p = &dance->dancers[i];
 printf( "%2d: %s %c (%.2f,%.2f) %.4f %.1f\n",
   i, roleNames[p->effective_role], sexChars[p->sex],
   p->now.x, p->now.y, p->now_sicilian_theta, sqrt(p->now_sicilian_radius));
}
#endif

	if ( dance->tags!=NULL && strstr(dance->tags,"mixer")!=NULL ) {
	    /* it's a mixer. Do nothing about couples */
	} else if ( dance->formation==sp_rotatedTripleMinor ) {
	    /* it's a mixer. Do nothing about couples */
	} else if ( dance->formation!=sp_threeFaceThree ) {
	    for ( i=0; i<dance->people ; i+=2 ) {
		Person *p1 = &dance->dancers[i];
		Person *p2 = &dance->dancers[i+1];
		assert( p1->couple_number == p2->couple_number );
		/* If the cut happens within a couple bad things happen */ 
		if ( p1->now_sicilian_theta>4 && p2->now_sicilian_theta<-1 )
		    p1->now_sicilian_theta -= 2*PI;
		else if ( p1->now_sicilian_theta<-1 && p2->now_sicilian_theta>4 )
		    p2->now_sicilian_theta -= 2*PI;
		
		p1->now_sicilian_couple_theta =
		    p2->now_sicilian_couple_theta =
			(p1->now_sicilian_theta+p2->now_sicilian_theta)/2;
	    }
	    if ( dance->formation==sp_fourFaceFour || dance->formation==sp_tempest || dance->formation==sp_quadrupleMinorBecket ) {
		for ( i=0; i<dance->people ; i+=4 ) {
		    Person *p1 = &dance->dancers[i];
		    Person *p2 = &dance->dancers[i+1];
		    Person *p3 = &dance->dancers[i+2];
		    Person *p4 = &dance->dancers[i+3];
		    /* If the cut happens between travelling budies bad things happen */ 
		    if ( p1->now_sicilian_couple_theta>4.7 && p3->now_sicilian_couple_theta<-1.5 )
			p1->now_sicilian_couple_theta -= 2*PI;
		    else if ( p1->now_sicilian_couple_theta<-1.5 && p3->now_sicilian_couple_theta>4.7 )
			p3->now_sicilian_couple_theta -= 2*PI;
		    
		    p1->now_sicilian_couple_theta =
			p2->now_sicilian_couple_theta =
			p3->now_sicilian_couple_theta =
			p4->now_sicilian_couple_theta =
			    (p1->now_sicilian_couple_theta+p3->now_sicilian_couple_theta)/2;
		}
	    }
	} else {
	    for ( i=0; i<dance->people ; i+=3 ) {
		Person *p1 = &dance->dancers[i];
		Person *p2 = &dance->dancers[i+1];
		Person *p3 = &dance->dancers[i+2];
		assert( p1->couple_number == p2->couple_number && p1->couple_number==p3->couple_number );
		/* If the cut happens within a trio bad things happen */ 
		if ( p1->now_sicilian_theta>4.7 && p2->now_sicilian_theta>4.7 && p3->now_sicilian_theta<-1.5 )
		    p3->now_sicilian_theta += 2*PI;
		else if ( p1->now_sicilian_theta>4.7 && p3->now_sicilian_theta>4.7 && p2->now_sicilian_theta<-1.5 )
		    p2->now_sicilian_theta += 2*PI;
		else if ( p2->now_sicilian_theta>4.7 && p3->now_sicilian_theta>4.7 && p1->now_sicilian_theta<-1.5 )
		    p1->now_sicilian_theta += 2*PI;
		else if ( p1->now_sicilian_theta<-1.5 && p2->now_sicilian_theta<-1.5 && p3->now_sicilian_theta>4.7 )
		    p3->now_sicilian_theta -= 2*PI;
		else if ( p1->now_sicilian_theta<-1.5 && p3->now_sicilian_theta<-1.5 && p2->now_sicilian_theta>4.7 )
		    p2->now_sicilian_theta -= 2*PI;
		else if ( p2->now_sicilian_theta<-1.5 && p3->now_sicilian_theta<-1.5 && p1->now_sicilian_theta>4.7 )
		    p1->now_sicilian_theta -= 2*PI;
		
		p1->now_sicilian_couple_theta =
		    p2->now_sicilian_couple_theta =
			p3->now_sicilian_couple_theta =
			    (p1->now_sicilian_theta+p2->now_sicilian_theta+p3->now_sicilian_theta)/3;
		printf( "" );
	    }
	}
	for ( i=0; i<dance->people ; ++i ) {
	    Person *p = &dance->dancers[i];
	    if ( p->now_sicilian_couple_theta < 0 )
		p->now_sicilian_couple_theta += 2*PI;
	}
    }
    switch ( dance->formation ) {
      case sp_becket:
	order(dance,xSicilianBecketCompare);
      break;
      case sp_becketCCW:
	order(dance,xSicilianBecketCCWCompare);
      break;
      case sp_shortWaves:
	order(dance,xSicilianShortWavesCompare);
      break;
      case sp_dupleMinor:
      case sp_dupleMinorProgressed:
      case sp_tripleMinor:
      case sp_scottishDupleMinor:
      case sp_scottishTripleMinor:
      case sp_quadrupleMinor:
      case sp_circularMonople:
      case sp_trioCircularMonople:
	order(dance,xSicilianCompare);
	if ( dance->orderedList[0]->effective_sex==s_female ) {
	    if ( dance->formation==sp_circularMonople ) {
		Person *last = dance->orderedList[0];
		for ( i=1 ; i<dance->people ; ++i )
		    dance->orderedList[i-1] = dance->orderedList[i];
		dance->orderedList[dance->people-1] = last;
	    } else
		fprintf( stderr, "Whoops! Ordered list starts with a woman.\n" );
	}
      break;
      case sp_fourFaceFour:
      case sp_tempest:
      case sp_quadrupleMinorBecket:
	order(dance,xSicilian4Face4Compare);
      break;
      case sp_threeFaceThree:
	order(dance,xSicilian3Face3Compare);
      break;
      case sp_rotatedTripleMinor:
	danceAssignRotatedTripleMinorRoles(dance);
      break;
      default:
	assert(false);
      break;
    }
    if ( dance->old_style_progression ) {
	if ( dance->couples==0 )
	    dance->couples = dance->people/2;
	if ( dance->current_minorset < dance->couples/2 ) {
	    /* Are there any couples in "waiting" state? If so change the two which*/
	    /*  are adjacent to active couples into whatever that couple isn't */
	    int p1=-1, p2=-1;
	    for ( i=0; i<dance->people ; i+=2 ) {
		if ( dance->dancers[i].effective_role==r_waiting &&
			dance->dancers[i-2<0?dance->people-2:i-2].effective_role == r_2s )
		    p2 = i;
		else if ( dance->dancers[i].effective_role==r_waiting &&
			dance->dancers[i+2<dance->people?i+2:0].effective_role == r_1s )
		    p1 = i;
	    }
	    if ( p1!=-1 ) {
		dance->dancers[p1].effective_role = r_1s;
		dance->dancers[p1+1].effective_role = r_1s;
	    }
	    if ( p2!=-1 ) {
		dance->dancers[p2].effective_role = r_2s;
		dance->dancers[p2+1].effective_role = r_2s;
	    }
	} else if ( dance->current_minorset>= dance->couples ) {
	    if ( dance->current_minorset == dance->couples ) {
		dance->dancers[0].effective_role = r_waiting;
		dance->dancers[1].effective_role = r_waiting;
		dance->dancers[2].effective_role = r_waiting;
		dance->dancers[3].effective_role = r_waiting;
	    } else {
		dance->dancers[2+2*(dance->current_minorset-dance->couples)+0].effective_role = r_waiting;
		dance->dancers[2+2*(dance->current_minorset-dance->couples)+1].effective_role = r_waiting;
		dance->dancers[dance->people-2*(dance->current_minorset-dance->couples)+0].effective_role = r_waiting;
		dance->dancers[dance->people-2*(dance->current_minorset-dance->couples)+1].effective_role = r_waiting;
	    }
	}
    }
    if ( cut!=0 ) {
	for ( i=0; i<dance->people ; ++i ) {
	    Person *p = &dance->dancers[i];
	    p->now_sicilian_theta += cut;
	}
    }
    if ( dance->formation==sp_tripleMinor || dance->formation==sp_scottishTripleMinor )
	danceSicilianFigureTripleRoles(dance);
    else if ( dance->formation==sp_fourFaceFour || dance->formation==sp_tempest )
	danceSicilianFigure4Face4Roles(dance);
    else if ( dance->formation==sp_threeFaceThree )
	danceSicilianFigure3Face3Sexes(dance);
    if ( dance->formation!=sp_threeFaceThree && dance->formation!=sp_trioCircularMonople ) {
	for ( i=0; i<dance->people; ++i )
	    dance->orderedList[i]->current_pos = i/2;
    } else {
	for ( i=0; i<dance->people; ++i )
	    dance->orderedList[i]->current_pos = i/3;
    }
    }	/* End of special check for October Flury */

    /* In most dance styles people are stuck in one role. */
    /*  In Triples 1s are always 1s but 2s & 3s alternate */
    /*  In Quadruples 1s are always 1s but 2s become 4s, 3s->2s, 4s->2s */
    /*  In 4Face4 left and right switch each time through (usually) */
    mss = danceMinorSetSize(dance);
    for ( i=0; i<dance->people ; ++i ) {
	Person *p = &dance->dancers[i];
	Person *r = danceFindRole(dance,p->effective_role,p->effective_sex);
	for ( j=0; j<p->figures.move_cnt; ++j ) {
	    free( p->figures.moves[j].levitation);
	    free( p->figures.moves[j].outness);
	}
	p->figures.move_cnt = 0;
	if ( p->effective_role == r_waiting )
	    makeDancerWait(dance,i  ,r_waiting);
	else
	    blockCopyAndFlatten(&p->figures,&r->figures,p,dance);

	/* <pause's need to know where they are, otherwise orientation goes wonky */
	here.x = here.y = -dance->sicilian_circumference;
	for ( j=0; j<p->figures.move_cnt; ++j ) {
	    FigureSegment *cs = &p->figures.moves[j];
	    if ( cs->cmd==c_lineto )
		csChangeLineToDegenerateCurveto(cs,&here);
	    if ( cs->cmd==c_moveto || cs->cmd==c_curveto )
		here = cs->endPoint;
	    else if ( cs->cmd==c_pause )
		cs->endPoint = here;
	}

	/* Start at end because I use moves[0] as an origin so it must be the last thing to change */
	for ( j=p->figures.move_cnt-1; j>=0; --j ) {
	    FigureSegment *cs = &p->figures.moves[j];
	    if ( cs->cmd==c_moveto || cs->orient==mo_rotateto ||
		    cs->orient==mo_cw_rotateto || cs->orient==mo_ccw_rotateto )
		offsetOrientation(dance,cs,p);
	    if ( cs->cmd==c_moveto || cs->cmd==c_lineto || cs->cmd==c_curveto ) {
		if ( cs->cmd==c_curveto ) {
		    offsetControlCoordinates(dance,&cs->cp1,csPreviousEndPoint(p->figures.moves,cs),p);
		    offsetControlCoordinates(dance,&cs->cp2,&cs->endPoint,p);
		}
		offsetCoordinates(dance,&cs->endPoint,p);
	    }
	    if ( (cs->join_right_hand&HAND_INDIVIDUAL_MASK)==HAND_STAR ||
		 (cs->join_left_hand&HAND_INDIVIDUAL_MASK)==HAND_STAR )
		offsetCoordinates(dance,&cs->star_center,p);
	    if ( cs->join_right_hand!=0 )
		cs->join_right_hand = danceSicilianFigureClasp(dance,p,cs->join_right_hand,mss);
	    if ( cs->join_left_hand!=0 )
		cs->join_left_hand = danceSicilianFigureClasp(dance,p,cs->join_left_hand,mss);
		
	}
    }
    danceOutputDebugFigure("refuf.dance",dance);
}

static void danceResetNormal(Dance *dance,int frame, int frames_per_bar ) {
    int i, j, outTop, outBottom, firstWait, first1m, lastWait;
    int moreJiggeryPokeryNeeded;
    int start;
    int progression;
    int bestr;

    progression= dance->progression;
    if ( dance->choreo_cnt!=0 ) {
	if ( dance->choreo_pos==1 )
	    progression = dance->sequence[dance->choreo_cnt-1].figure->progression;
	else if ( dance->choreo_pos==0 )
	    fprintf( stderr, "%s:%d This should never happen????\n", __FILE__, __LINE__ );
	else if ( dance->choreo_pos-2 < dance->choreo_cnt )
	    progression = dance->sequence[dance->choreo_pos-2].figure->progression;
	else
	    fprintf( stderr, "%s:%d This should never happen????\n", __FILE__, __LINE__ );
    }

    switch ( dance->formation ) {
      case sp_squaredSet:
      case sp_rect6Set:
      case sp_2Couple:
      case sp_3Couple:
      case sp_4Couple:
      case sp_5Couple:
      case sp_6Couple:
      case sp_7Couple:
      case sp_8Couple:
      case sp_3CplCircle:
      case sp_5CplCircle:
      case sp_6CplCircle:
      case sp_7CplCircle:
      case sp_square3:
      case sp_custom:
      case sp_facingCouples:
      case sp_facingCouplesBecket:
      /*case sp_facingCouplesProper:*/
	/* for each role, find the couple closest to that role */
	/*  hope than no couple gets chosen twice */
	/* Oops. In mixers men and women are on different cycles, so check person closest */
	/* force the couple to have the role's exact position */
	/*   No... some dances want minor sets after the first to start in a continuous flow from the end of the last minor set requiring an <if> and different start positions */
	/* replace the couple's command list with the role's */
	/* Update the hand joins for new people */
	for ( j=0; j<dance->people; ++j )
	    dance->dancers[j].ticked = 0;
	for ( i=0; i<dance->role_cnt; ++i ) {
	    dance->roles[i].now = dance->roles[i].figures.moves[0].endPoint;
	    if ( dance->style==ds_scottish && (dance->improper_mask&(1<<(i/2)))) {
		/* in scottish longways improper dances the improper couples are */
		/*  not where they should be as there are 2 bars at the start of */
		/*  dance when they cross over. So force them to be where they */
		/*  should be */
		if ( dance->roles[i].sex==s_male )
		    dance->roles[i].now.y=dance->roles[i+1].figures.moves[0].endPoint.y;
		else if ( dance->roles[i].sex==s_female )
		    dance->roles[i].now.y=dance->roles[i-1].figures.moves[0].endPoint.y;
	    }
	}
	/* In custom circles it is possible that the couples will not end up */
	/*  where another couple started, but they might be out of phase. So */
	/*  check for that and be prepared to rotate the roles */
	/* Then there is the case of Social Symmetry where the longways set */
	/*  rotates by 90 degrees each time through the dance */
	/* And then there's Winter Garden, where the dancers end where they */
	/*  started, but the roles have to rotate. That is after a minorset */
	/*  the 1s,2s,3s are where they began, but now it is the 2s's turn  */
	/*  to be active so the 1s role must rotate to them */
	bestr=0;
	if ( dance->progression_mod!=1 || dance->progression_offset!=0 ) {
	    double theta = 2*PI/(dance->progression_mod*dance->role_cnt/2);
	    bestr=-1;
	    double bestd=999999999;
	    int rot;
	    Person *p = &dance->dancers[0];
	    if ( dance->progression_offset!=0 )
		theta = 2*PI/dance->progression_offset;
	    else if ( dance->formation!=sp_custom )
		theta = PI/dance->progression_mod;
	    else
		theta = 2*PI/(dance->progression_mod*dance->role_cnt/2);
	    if ( dance->progression_mod!=1 ) {
		if ( dance->formation==sp_4Couple ) {
		    for ( i=0; i<8; ++i ) {
			p = &dance->dancers[i];
			if (( p->now.x!=320 && p->now.x!=576) || (p->now.y!=64 && p->now.y!=320))
		    break;
		    }
		    if ( i==8 ) {
			p = &dance->dancers[0];
			fprintf( stderr, "Progression is going to fail.\n" );
		    }
		}
		for ( rot=0; rot<dance->progression_mod; ++rot ) {
		    double c = cos(rot*theta), s=sin(rot*theta);
		    for ( i=0; i<dance->role_cnt; ++i ) if ( dance->ignore_sex || p->sex==dance->roles[i].sex ) {
			Position *here = &dance->roles[i].now;
			double x = dance->progression_center.x + c*(here->x-dance->progression_center.x) - s*(here->y-dance->progression_center.y) - p->now.x;
			double y = dance->progression_center.y + s*(here->x-dance->progression_center.x) + c*(here->y-dance->progression_center.y) - p->now.y;
			double d = x*x + y*y;
			if ( d<bestd ) {
			    bestd = d;
			    bestr = rot;
			}
		    }
		}
	    } else {
		bestr = dance->current_minorset;
	    }
	    if ( bestr==-1 )
		bestr = 0;
	    if ( bestr!=0 ) {
		double c = cos(bestr*theta), s=sin(bestr*theta);
		for ( i=0; i<dance->role_cnt; ++i ) {
		    Position *here = &dance->roles[i].now;
		    double x = dance->progression_center.x + c*(here->x-dance->progression_center.x) - s*(here->y-dance->progression_center.y);
		    double y = dance->progression_center.y + s*(here->x-dance->progression_center.x) + c*(here->y-dance->progression_center.y);
		    here->x = x;
		    here->y = y;
		}
	    }
	}
	for ( i=0; i<dance->role_cnt; ++i ) {
	    int bestj=-1;
	    double bestd=999999999;
	    for ( j=0; j<dance->people; ++j ) {
		if ( !dance->dancers[j].ticked && (dance->ignore_sex || dance->dancers[j].sex==dance->roles[i].sex )) {
		    double x,y,d;
		    x = (dance->dancers[j].now.x-dance->roles[i].now.x);
		    y = (dance->dancers[j].now.y-dance->roles[i].now.y);
		    d = x*x + y*y;
		    if ( d<bestd ) {
			bestd = d;
			bestj = j;
		    }
		}
	    }
	    Person *r = &dance->roles[i], *p = &dance->dancers[bestj];
	    r->mapped_to = bestj;
	    p->mapped_to = i;
	    p->ticked = true;
	    p->effective_role = r->effective_role;
	    p->display_role = r->display_role;
	    /* We don't want any drift, so if positions don't line up perfectly*/
	    /*  force them to do so. This will look like a jump when displayed */
	    /* p->now = r->now; */
	    /* p->now_orientation = r->figures.moves[0].degrees; */  /* This introduces some nasty jumps. See RuftyTufty */
	    for ( j=0; j<p->figures.move_cnt; ++j ) {
		free( p->figures.moves[j].levitation );
		free( p->figures.moves[j].outness );
	    }
	    p->figures.move_cnt = 0;
	    blockCopyAndFlatten(&p->figures,&r->figures,p,dance);
	    if ( bestr!=0 ) {
		double theta;
		struct transformation trans;
		/* Theta in degrees here, not radians */
		if ( dance->progression_offset!=0 )
		    theta = dance->current_minorset*360/dance->progression_offset;
		else if ( dance->formation!=sp_custom )
		    theta = bestr * 180/dance->progression_mod;
		else
		    theta = bestr * 360/(dance->progression_mod*dance->role_cnt/2);
		memset(&trans,0,sizeof(trans));
		trans.xscale = trans.yscale = 1.0;
		trans.rotateby = theta;
		trans.center_x = dance->progression_center.x;
		trans.center_y = dance->progression_center.y;
		danceBlockTransform(&p->figures,&trans);
	    }
	}
	/* Must wait until all roles are mapped before we figure hand clasps */
	for ( i=0; i<dance->role_cnt; ++i ) {
	    Person *p = &dance->dancers[i];
	    for ( j=0; j<p->figures.move_cnt; ++j ) {
		FigureSegment *cs = &p->figures.moves[j];
		if ( (cs->join_right_hand&HAND_INDIVIDUAL_MASK)==HAND_STAR )
		    /* unchanged */;
		else if ( cs->join_right_hand!=0 && (cs->join_right_hand&HAND_INDIVIDUAL_MASK)<dance->role_cnt )
		    cs->join_right_hand =
			    (cs->join_right_hand&(HAND_COPY_MASK)) |
			    dance->roles[cs->join_right_hand&HAND_INDIVIDUAL_MASK].mapped_to;
		if ( (cs->join_left_hand&HAND_INDIVIDUAL_MASK)==HAND_STAR )
		    /* unchanged */;
		else if ( cs->join_left_hand!=0  && (cs->join_left_hand&HAND_INDIVIDUAL_MASK)<dance->role_cnt)
		    cs->join_left_hand =
			    (cs->join_left_hand&(HAND_COPY_MASK)) |
			    dance->roles[cs->join_left_hand&HAND_INDIVIDUAL_MASK].mapped_to;
		if ( cs->orient == mo_faceDancer )
		    cs->faceDancer = dance->roles[cs->faceDancer].mapped_to;
	    }
	}
      break;

      case sp_custom3:
	/* for each role, find the person closest to that role */
	/*  note that effective sex may change in mixers */
	/* force the person to have the role's exact position (and sex) */
	/* replace the couple's command list with the role's */
	/* Update the hand joins for new people */
	for ( j=0; j<dance->people; ++j )
	    dance->dancers[j].ticked = 0;
	for ( i=0; i<dance->role_cnt; ++i ) {
	    dance->roles[i].now = dance->roles[i].figures.moves[0].endPoint;
	}
	for ( i=0; i<dance->role_cnt; ++i ) {
	    int bestj=-1;
	    double bestd=999999999;
	    for ( j=0; j<dance->people; ++j ) {
		if ( !dance->dancers[j].ticked ) {
		    double x,y,d;
		    x = (dance->dancers[j].now.x-dance->roles[i].now.x);
		    y = (dance->dancers[j].now.y-dance->roles[i].now.y);
		    d = x*x + y*y;
		    if ( d<bestd ) {
			bestd = d;
			bestj = j;
		    }
		}
	    }
	    Person *r = &dance->roles[i], *p = &dance->dancers[bestj];
	    r->mapped_to = bestj;
	    p->mapped_to = i;
	    p->ticked = true;
	    p->effective_role = r->effective_role;
	    p->effective_sex  = r->sex;
	    /* We don't want any drift, so if positions don't line up perfectly*/
	    /*  force them to do so. This will look like a jump when displayed */
	    p->now = r->now;
	    /* p->now_orientation = r->figures.moves[0].degrees; */  /* This introduces some nasty jumps. See RuftyTufty */
	    for ( j=0; j<p->figures.move_cnt; ++j ) {
		free( p->figures.moves[j].levitation );
		free( p->figures.moves[j].outness );
	    }
	    p->figures.move_cnt = 0;
	    blockCopyAndFlatten(&p->figures,&r->figures,p,dance);
	}
	/* Must wait until all roles are mapped before we figure hand clasps */
	for ( i=0; i<dance->role_cnt; ++i ) {
	    Person *p = &dance->dancers[i];
	    for ( j=0; j<p->figures.move_cnt; ++j ) {
		FigureSegment *cs = &p->figures.moves[j];
		if ( (cs->join_right_hand&HAND_INDIVIDUAL_MASK)==HAND_STAR )
		    /* unchanged */;
		else if ( cs->join_right_hand!=0 && (cs->join_right_hand&HAND_INDIVIDUAL_MASK)<dance->role_cnt )
		    cs->join_right_hand =
			    (cs->join_right_hand&(HAND_COPY_MASK)) |
			    dance->roles[cs->join_right_hand&HAND_INDIVIDUAL_MASK].mapped_to;
		if ( (cs->join_left_hand&HAND_INDIVIDUAL_MASK)==HAND_STAR )
		    /* unchanged */;
		else if ( cs->join_left_hand!=0  && (cs->join_left_hand&HAND_INDIVIDUAL_MASK)<dance->role_cnt)
		    cs->join_left_hand =
			    (cs->join_left_hand&(HAND_COPY_MASK)) |
			    dance->roles[cs->join_left_hand&HAND_INDIVIDUAL_MASK].mapped_to;
		if ( cs->orient == mo_faceDancer )
		    cs->faceDancer = dance->roles[cs->faceDancer].mapped_to;
	    }
	}
      break;

      case sp_circularMonople:
	/* for each person's current point, find the person who started the dance closest to that. */
	/* NOTE: In Halfe Hannikin people can dance a role of the opposite sex!!! */
	/* In a monopole there are only two possibilities, male or female everyone is a 1s */
	/*  only difference is offset */
	/* I assume that everyone moves to where someone was before */
	order(dance,xMonoCompare);
	for ( i=0; i<dance->people; ++i ) {
	    dance->orderedList[i]->effective_sex = i&1 ? s_female : s_male;
	    dance->orderedList[i]->current_pos = i/2;
	}

	for ( i=0; i<dance->people; ++i ) {
	    setMoves(dance,i);
	    translateMoves(dance,i,2);
	}
      break;

      case sp_trioCircularMonople:
	/* for each person's current point, find the person who started the dance closest to that. */
	/* In a monopole there are only three possibilities, left,center,right everyone is a 1s */
	/*  only difference is offset */
	/* I assume that everyone moves to where someone was before */
	order(dance,xMonoCompare);
	for ( i=0; i<dance->people; ++i ) {
	    dance->orderedList[i]->effective_sex = i%3==0 ? s_left : i%3==1? s_center : s_right;
	    dance->orderedList[i]->current_pos = i/3;
	}

	for ( i=0; i<dance->people; ++i ) {
	    setMoves(dance,i);
	    translateMoves(dance,i,3);
	}
      break;

      case sp_dupleMinor:
      case sp_dupleMinorProgressed:
      case sp_becket:
      case sp_becketCCW:
      case sp_shortWaves:
      case sp_scottishDupleMinor:
	/* Check for double progression (top couple facing down) */
	/* We could probably use a check similar to that used in triple progression */
	/* Did we have a couple out at the top? */
	    /* That couple becomes a 1, all other couples retain their roles */
	/* Else */
	    /* Top couple becomes out, all others retain roles */
	/* Did we have a couple out at the bottom? */
	    /* They become 2s, all others retain roles */
	/* Else */
	    /* bottom couple becomes out */
	/* translate all commands by new x-locations */
	/* Update the hand joins for new people */
	for ( i=0; i<dance->people ; ++i ) {	/* LathropHouse needs this. I don't know why */
	    Person *p = &dance->dancers[i];
	    p->now.x = round( p->now.x );
	    p->now.y = round( p->now.y );
#if 0
 printf("%d: %d%c %s (%d,%d) %d\n",		/* DEBUG */
  i, p->couple_number, sexChars[p->sex], roleNames[p->effective_role],
  (int) p->now.x, (int) p->now.y, ((int) p->now.x)%64 );
#endif
	}
	if ( dance->formation== sp_becket || dance->formation== sp_becketCCW ||
		dance->becket_style==bs_ccw || dance->becket_style==bs_cw ) {
	    for ( i=0; i<dance->people ; i+=2 ) {
		Person *p1 = &dance->dancers[i];
		Person *p2 = &dance->dancers[i+1];
		assert( p1->couple_number == p2->couple_number );
		p1->now_couple_x =
		    p2->now_couple_x =
			(p1->now.x+p2->now.x)/2;
	    }
	}
	if ( dance->formation== sp_shortWaves )
	    order(dance,xShortWavesCompare);
	else if ( dance->formation== sp_becket || dance->becket_style==bs_cw )
	    order( dance,xBecketCompare );
	else if ( dance->formation== sp_becketCCW || dance->becket_style==bs_ccw )
	    order( dance,xBecketCCWCompare );
	else
	    order(dance,xCompare);
	outTop = outBottom = firstWait = -1;
	for ( i=0; i<dance->people; ++i ) {
	    if ( dance->orderedList[i]->effective_role == r_outAtTop )
		outTop = i;
	    else if ( dance->orderedList[i]->effective_role == r_outAtBottom )
		outBottom = i;
	    else if ( firstWait==-1 &&
		    dance->orderedList[i]->effective_role == r_waiting )
		firstWait = i;
	    dance->orderedList[i]->current_pos = i/2;
	}
	if ( dance->old_style_progression && dance->current_minorset==0 &&
		dance->orderedList[0]->effective_role==r_1s ) {
	    for ( i=4; i<dance->people ; ++i )
		dance->orderedList[i]->effective_role= r_waiting;
	    firstWait = 4;
	}
	if ( firstWait==-1 )
	    firstWait = dance->people;
	else
	    firstWait += 2;
	if ( dance->current_minorset>=dance->people-1 && dance->old_style_progression ) {
	    lastWait=-1;
	    for ( i=0; i<dance->people; ++i ) {
		if ( dance->orderedList[i]->effective_role == r_waiting )
		    lastWait = i;
	    }
	    if ( lastWait==dance->people-1 )
		/* Done */;
	    else {
		dance->orderedList[lastWait+1]->effective_role = r_waiting;
		dance->orderedList[lastWait+2]->effective_role = r_waiting;
		for ( i=lastWait+3; i+3<dance->people ; i+=4 ) {
		    dance->orderedList[i+0]->effective_role = r_1s;
		    dance->orderedList[i+1]->effective_role = r_1s;
		    dance->orderedList[i+2]->effective_role = r_2s;
		    dance->orderedList[i+3]->effective_role = r_2s;
		}
		if ( lastWait+5==dance->people ) {
		    dance->orderedList[lastWait+3]->effective_role = r_waiting;
		    dance->orderedList[lastWait+4]->effective_role = r_waiting;
		} else if ( i<dance->people ) {
		    dance->orderedList[i+0]->effective_role = r_outAtBottom;
		    dance->orderedList[i+1]->effective_role = r_outAtBottom;
		}
	    }
	} else {
	    if ( progression%2==0 || outTop!=-1 ) {
		dance->start_first_minor_set = 0;
		for ( i=0; i+3<dance->people && i+3<firstWait; i+=4 ) {
		    dance->orderedList[i+0]->effective_role = r_1s;
		    dance->orderedList[i+1]->effective_role = r_1s;
		    dance->orderedList[i+2]->effective_role = r_2s;
		    dance->orderedList[i+3]->effective_role = r_2s;
		}
	    } else {
		dance->start_first_minor_set = 1;
		dance->orderedList[0]->effective_role = r_outAtTop;
		dance->orderedList[1]->effective_role = r_outAtTop;
		for ( i=2; i+3<dance->people && i+3<firstWait; i+=4 ) {
		    dance->orderedList[i+0]->effective_role = r_1s;
		    dance->orderedList[i+1]->effective_role = r_1s;
		    dance->orderedList[i+2]->effective_role = r_2s;
		    dance->orderedList[i+3]->effective_role = r_2s;
		}
	    }
	    if ( dance->current_minorset<dance->people/2-1 && dance->old_style_progression ) {
		if ( i<firstWait ) {
		    dance->orderedList[i+0]->effective_role = r_waiting;
		    dance->orderedList[i+1]->effective_role = r_waiting;
		}
		if ( firstWait!=dance->people ) {
		    dance->orderedList[firstWait  ]->effective_role = r_waiting;
		    dance->orderedList[firstWait+1]->effective_role = r_waiting;
		}
	    } else {
		if ( i<dance->people ) {
		    dance->orderedList[i+0]->effective_role = r_outAtBottom;
		    dance->orderedList[i+1]->effective_role = r_outAtBottom;
		}
	    }
	}
	if ( dance->formation == sp_dupleMinorProgressed ) {
	    for ( i=0; i<dance->people; ++i ) {
		if ( dance->orderedList[i]->effective_role == r_1s )
		    dance->orderedList[i]->effective_role = r_2s;
		else if ( dance->orderedList[i]->effective_role == r_2s )
		    dance->orderedList[i]->effective_role = r_1s;
	    }
	}

	for ( i=0; i<dance->people; ++i ) {
	    setMoves(dance,i);
	    translateMoves(dance,i,4);
	}
      break;

      case sp_fourFaceFour:
      case sp_tempest:
      case sp_quadrupleMinorBecket:
	{
	    for ( i=0; i<dance->people ; i+=2 ) {
		Person *p1 = &dance->dancers[i];
		Person *p2 = &dance->dancers[i+1];
		assert( p1->couple_number == p2->couple_number );
		p1->now_couple_x =
		    p2->now_couple_x =
			(p1->now.x+p2->now.x)/2;
	    }
	}
	order(dance,x4Face4Compare);
	/* Similar to above, except there are two couples out top and bottom */
	/* Did we have two couples out at the top? */
	    /* That couple becomes a 1, all other couples retain their roles */
	    /* except left/right may switch */
	/* Else */
	    /* Top couple becomes out, all others retain roles */
	/* Did we have a couple out at the bottom? */
	    /* They become 2s, all others retain roles */
	/* Else */
	    /* bottom couple becomes out */
	/* translate all commands by new x-locations */
	/* roles may switch from left to right, or may not */
	/* Update the hand joins for new people */
	outTop = outBottom = firstWait = -1;
	for ( i=0; i<dance->people; ++i ) {
	    if ( dance->orderedList[i]->effective_role == r_outAtTopLeft || dance->orderedList[i]->effective_role == r_outAtTopRight )
		outTop = i;
	    else if ( dance->orderedList[i]->effective_role == r_outAtBottomLeft || dance->orderedList[i]->effective_role == r_outAtBottomRight )
		outBottom = i;
	    else if ( firstWait==-1 &&
		    (dance->orderedList[i]->effective_role == r_waiting_left || dance->orderedList[i]->effective_role == r_waiting_right ))
		firstWait = i;
	    dance->orderedList[i]->current_pos = i/2;
	}
	if ( dance->current_minorset>=dance->people/2-1 && dance->old_style_progression ) {
	  /* Tested for tempest, not for normal 4x4 */
	    lastWait=-1;
	    for ( i=0; i<dance->people; ++i ) {
		if ( dance->orderedList[i]->effective_role == r_waiting_left ||
			dance->orderedList[i]->effective_role == r_waiting_right )
		    lastWait = i;
	    }
	    if ( lastWait==dance->people-1 )
		/* Done */;
	    else {
		dance->orderedList[lastWait+1]->effective_role = r_waiting_left;
		dance->orderedList[lastWait+2]->effective_role = r_waiting_left;
		dance->orderedList[lastWait+3]->effective_role = r_waiting_right;
		dance->orderedList[lastWait+4]->effective_role = r_waiting_right;
		for ( i=lastWait+5; i+7<dance->people ; i+=8 ) {
		    dance->orderedList[i+0]->effective_role = r_1sleft;
		    dance->orderedList[i+1]->effective_role = r_1sleft;
		    dance->orderedList[i+2]->effective_role = r_1sright;
		    dance->orderedList[i+3]->effective_role = r_1sright;
		    dance->orderedList[i+4]->effective_role = r_2sleft;
		    dance->orderedList[i+5]->effective_role = r_2sleft;
		    dance->orderedList[i+6]->effective_role = r_2sright;
		    dance->orderedList[i+7]->effective_role = r_2sright;
		}
		if ( i+3<dance->people ) {
		    dance->orderedList[i  ]->effective_role = r_outAtBottomLeft;
		    dance->orderedList[i+1]->effective_role = r_outAtBottomLeft;
		    dance->orderedList[i+2]->effective_role = r_outAtBottomRight;
		    dance->orderedList[i+3]->effective_role = r_outAtBottomRight;
		}
	    }
	    outTop = -1;
	} else {
	    if ( dance->progression%2==0 ) {
		/* Top couple is always in */
		for ( i=0; i<(dance->people/8)*8; i+=8 ) {
		    dance->orderedList[i+0]->effective_role = r_1sleft;
		    dance->orderedList[i+1]->effective_role = r_1sleft;
		    dance->orderedList[i+2]->effective_role = r_1sright;
		    dance->orderedList[i+3]->effective_role = r_1sright;
		    dance->orderedList[i+4]->effective_role = r_2sleft;
		    dance->orderedList[i+5]->effective_role = r_2sleft;
		    dance->orderedList[i+6]->effective_role = r_2sright;
		    dance->orderedList[i+7]->effective_role = r_2sright;
		}
		if ( i<dance->people ) {
		    dance->orderedList[i+0]->effective_role = r_outAtBottomLeft;
		    dance->orderedList[i+1]->effective_role = r_outAtBottomLeft;
		    dance->orderedList[i+2]->effective_role = r_outAtBottomRight;
		    dance->orderedList[i+3]->effective_role = r_outAtBottomRight;
		}
	    } else {
		if ( outTop!=-1 ) {
		    assert(outTop==3);
		    assert(dance->orderedList[outTop-3]->effective_role == r_outAtTopLeft || dance->orderedList[outTop-3]->effective_role == r_outAtTopRight );
		    if ( dance->formation == sp_tempest && dance->old_style_progression ) {
			Person *temp;
			/* order4face4 determines ordering by the direction people are facing*/
			/*  but in a tempest old style dance, the 1s starting at the top are */
			/*  still facing as if they were 2s, so the ordering algorithm mixes */
			/*  them up. Just unmix them here */
			temp = dance->orderedList[outTop-3];
			dance->orderedList[outTop-3] = dance->orderedList[outTop-1];
			dance->orderedList[outTop-1] = temp;
			temp = dance->orderedList[outTop-2];
			dance->orderedList[outTop-2] = dance->orderedList[outTop  ];
			dance->orderedList[outTop  ] = temp;
		    }
		    dance->orderedList[outTop-3]->effective_role = r_1sleft;
		    dance->orderedList[outTop-2]->effective_role = r_1sleft;
		    dance->orderedList[outTop-1]->effective_role = r_1sright;
		    dance->orderedList[outTop]->effective_role = r_1sright;
		    if ( dance->formation == sp_tempest ) {
			dance->orderedList[outTop-1]->now.x =
			    dance->orderedList[outTop-2]->now.x =
				dance->orderedList[outTop-3]->now.x;
		    }
		    dance->start_first_minor_set = 0;
		} else if ( dance->orderedList[0]->effective_role == r_2sleft || dance->orderedList[0]->effective_role == r_2sright ) {
		    dance->orderedList[0]->effective_role = r_outAtTopLeft;
		    dance->orderedList[1]->effective_role = r_outAtTopLeft;
		    dance->orderedList[2]->effective_role = r_outAtTopRight;
		    dance->orderedList[3]->effective_role = r_outAtTopRight;
		    dance->start_first_minor_set = 2;
		}
		if ( firstWait!=-1 ) {
		    dance->orderedList[firstWait+0]->effective_role = r_2sleft;
		    dance->orderedList[firstWait+1]->effective_role = r_2sleft;
		    dance->orderedList[firstWait+2]->effective_role = r_2sright;
		    dance->orderedList[firstWait+3]->effective_role = r_2sright;
		} else if ( outBottom!=-1 ) {
		    assert(dance->orderedList[outBottom-3]->effective_role == r_outAtBottomLeft || dance->orderedList[outBottom-3]->effective_role == r_outAtBottomRight );
		    dance->orderedList[outBottom-3]->effective_role = r_2sleft;
		    dance->orderedList[outBottom-2]->effective_role = r_2sleft;
		    dance->orderedList[outBottom-1]->effective_role = r_2sright;
		    dance->orderedList[outBottom  ]->effective_role = r_2sright;
		} else if ( dance->orderedList[dance->people-1]->effective_role == r_1sleft || dance->orderedList[dance->people-1]->effective_role == r_1sright ) {
		    dance->orderedList[dance->people-4]->effective_role = r_outAtBottomLeft;
		    dance->orderedList[dance->people-3]->effective_role = r_outAtBottomLeft;
		    dance->orderedList[dance->people-2]->effective_role = r_outAtBottomRight;
		    dance->orderedList[dance->people-1]->effective_role = r_outAtBottomRight;
		}
	    }
	}
	for ( i=0; i<dance->people; ++i ) {
	    if ( dance->orderedList[i]->effective_role==r_1sleft || dance->orderedList[i]->effective_role==r_1sright ) {
		/* Dancers usually swap from left to right with each dance */
		/* (but they stay 1s or 2s */
		if ( i%4<2 )
		    dance->orderedList[i]->effective_role=r_1sleft;
		else
		    dance->orderedList[i]->effective_role=r_1sright;
	    } else if ( dance->orderedList[i]->effective_role==r_2sleft || dance->orderedList[i]->effective_role==r_2sright ) {
		if ( i%4>=2 )
		    dance->orderedList[i]->effective_role=r_2sright;
		else
		    dance->orderedList[i]->effective_role=r_2sleft;
	    }
	}
	for ( i=0; i<dance->people; ++i ) {
	    setMoves(dance,i);
	    translateMoves(dance,i,8);
	}
	if ( outTop!=-1 && dance->formation == sp_tempest && dance->old_style_progression ) {
	    dance->orderedList[outTop-1]->now.x =
		dance->orderedList[outTop-2]->now.x =
		    dance->orderedList[outTop-3]->now.x-256;
	}
      break;

      case sp_threeFaceThree:
	{
	    for ( i=0; i<dance->people ; i+=3 ) {
		Person *p1 = &dance->dancers[i];
		Person *p2 = &dance->dancers[i+1];
		Person *p3 = &dance->dancers[i+2];
		assert( p1->couple_number == p2->couple_number );
		assert( p1->couple_number == p3->couple_number );
		p1->now_couple_x =
		    p2->now_couple_x =
			p3->now_couple_x =
			    (p1->now.x+p2->now.x+p3->now.x)/2;
	    }
	}
	order(dance,x3Face3Compare);



	/* Did we have a triple out at the top? */
	    /* That triple becomes a 1, all other couples retain their roles */
	/* Else */
	    /* Top triple becomes out, all others retain roles */
	/* Did we have a triple out at the bottom? */
	    /* They become 2s, all others retain roles */
	/* Else */
	    /* bottom triple becomes out */
	/* EmmaTurns three, everyone retains sex */
	/* JustPassingThrough, left and right switch sex */
	/* translate all commands by new x-locations */
	/* Update the hand joins for new people */
	outTop = outBottom = firstWait = lastWait = -1;
	for ( i=0; i<dance->people; ++i ) {
	    if ( dance->orderedList[i]->effective_role == r_outAtTop )
		outTop = i;
	    else if ( dance->orderedList[i]->effective_role == r_outAtBottom )
		outBottom = i;
	    else if ( firstWait==-1 &&
		    dance->orderedList[i]->effective_role == r_waiting )
		firstWait = i;
	    if ( dance->orderedList[i]->effective_role == r_waiting )
		lastWait = i;
	    dance->orderedList[i]->current_pos = i/3;
	}
	if ( outTop!=-1 ) {
	    assert(dance->orderedList[outTop-2]->effective_role == r_outAtTop );
	    dance->orderedList[outTop-2]->effective_role = r_1s;
	    dance->orderedList[outTop-1]->effective_role = r_1s;
	    dance->orderedList[outTop]->effective_role = r_1s;
	    dance->start_first_minor_set = 0;
	} else if ( dance->orderedList[0]->effective_role == r_2s ) {
	    dance->orderedList[0]->effective_role = r_outAtTop;
	    dance->orderedList[1]->effective_role = r_outAtTop;
	    dance->orderedList[2]->effective_role = r_outAtTop;
	    dance->start_first_minor_set = 1;
	}
	if ( firstWait>0 ) {
	    dance->orderedList[firstWait  ]->effective_role = r_2s;
	    dance->orderedList[firstWait+1]->effective_role = r_2s;
	    dance->orderedList[firstWait+2]->effective_role = r_2s;
	} else if ( outBottom!=-1 ) {
	    assert(dance->orderedList[outBottom-2]->effective_role == r_outAtBottom );
	    dance->orderedList[outBottom-2]->effective_role = r_2s;
	    dance->orderedList[outBottom-1]->effective_role = r_2s;
	    dance->orderedList[outBottom  ]->effective_role = r_2s;
	} else if ( dance->orderedList[dance->people-1]->effective_role == r_1s ) {
	    dance->orderedList[dance->people-3]->effective_role = r_outAtBottom;
	    dance->orderedList[dance->people-2]->effective_role = r_outAtBottom;
	    dance->orderedList[dance->people-1]->effective_role = r_outAtBottom;
	}
	if ( dance->current_minorset>=2*(dance->people/3)-1 && dance->old_style_progression ) {
	    if ( lastWait==dance->people-1 )
		/* Done */;
	    else {
		dance->orderedList[lastWait+1]->effective_role = r_waiting;
		dance->orderedList[lastWait+2]->effective_role = r_waiting;
		dance->orderedList[lastWait+3]->effective_role = r_waiting;
		if ( lastWait==dance->people-7 ) {
		    dance->orderedList[lastWait+4]->effective_role = r_waiting;
		    dance->orderedList[lastWait+5]->effective_role = r_waiting;
		    dance->orderedList[lastWait+6]->effective_role = r_waiting;
		}
	    }
	}
	/* Has the "sex" changed? */
	for ( i=0; i<dance->people; i+=3 ) {
	    Person *p1=dance->orderedList[i+0];
	    Person *p2=dance->orderedList[i+1];
	    Person *p3=dance->orderedList[i+2];
#if 0
	    /* There are two ways of defining left and right: */
	    /*  1) person on the left of the trio is left (Emma turns three) */
	    /*  2) person closest to left wall is left (Lavender) */
	    p1->effective_sex = s_left;
	    p2->effective_sex = s_center;
	    p3->effective_sex = s_right;
#else
	    enum sex best1=s_male, best2=s_male, best3=s_male;
	    float diff1=99999, diff2=99999, diff3=99999;
	    for ( j=0; j<dance->role_cnt; ++j ) if ( dance->roles[j].effective_role==p1->effective_role ) {
		Person *r = &dance->roles[j];
		int diff;
		diff =p1->now.y-r->figures.moves[0].endPoint.y;
		if ( diff<0 ) diff=-diff;
		if ( diff<diff1 ) {
		    diff1 = diff;
		    best1 = r->sex;
		}
		diff =p2->now.y-r->figures.moves[0].endPoint.y;
		if ( diff<0 ) diff=-diff;
		if ( diff<diff2 ) {
		    diff2 = diff;
		    best2 = r->sex;
		}
		diff =p3->now.y-r->figures.moves[0].endPoint.y;
		if ( diff<0 ) diff=-diff;
		if ( diff<diff3 ) {
		    diff3 = diff;
		    best3 = r->sex;
		}
	    }
	    p1->effective_sex = best1;
	    p2->effective_sex = best2;
	    p3->effective_sex = best3;
#endif
	}
	for ( i=0; i<dance->people; ++i ) {
	    setMoves(dance,i);
	    translateMoves(dance,i,6);
	}
      break;

      case sp_tripleMinor:
      case sp_scottishTripleMinor:

	/* Ignore double progression. That would be really weird in a triple minor */
	/*  No... I figured it out. Should work fine without any hacks */
	/* Ah, triple progression does happen though (Three Coney Walk). */
	/* Find the first couple dancing role 1 in the last minor set */
	/* Look at the index of their position in the ordered list */
	/* if index%6==2 */
	/*    There will be two people (one couple) out at the top */
	/*    and normal minor sets start at index 2 */
	/* if index%6==4 */
	/*    There will be four people (two couple) out at the top */
	/*    and normal minor sets start at index 4 */
	/* if index%6==0 */
	/*    Normal minor sets start at the top of the set, index 0 */
	/* translate all commands by new x-locations */
	/* Update the hand joins for new people */

	order(dance,xCompare);
	first1m = firstWait = lastWait = -1;
	for ( i=0; i<dance->people; ++i ) {
	    if ( dance->orderedList[i]->effective_role == r_1s && first1m == -1 )
		first1m = i;
	    else if ( dance->orderedList[i]->effective_role == r_waiting && firstWait == -1 )
		firstWait = i;
	    if ( dance->orderedList[i]->effective_role == r_waiting )
		lastWait = i;
	    dance->orderedList[i]->current_pos = i/2;
	}
	if ( dance->old_style_progression && dance->current_minorset==0 &&
		dance->orderedList[0]->effective_role==r_1s ) {
	    for ( i=6; i<dance->people ; ++i )
		dance->orderedList[i]->effective_role= r_waiting;
	    firstWait = 6;
	}
	if ( dance->progression==2 && dance->people==10 && first1m==8 )
	    first1m = 6;
	if ( firstWait==0 )	/* That means top couple has reached the top and is waiting there, not that some couples near the bottom are waiting */
	    firstWait = -1;
	if ( first1m<0 && dance->formation == sp_scottishTripleMinor )
	    fprintf( stderr, "%s: Unable to apply default scottish progression moving the swapping the old 1s+3s. You must supply an explicit progression for the second time through the dance. Probably.\n", dance->name );
	if ( !dance->old_style_progression && dance->progression!=0 && dance->comp_cnt==0 ) {
	    assert(first1m>0);
	    assert((first1m&1)==0);
	}
	/* In a duple minor it takes 2*couples-1 to get back to the top */
	/* but in a triple minor the 3s do not progress, so it takes twice as */
	/* long to make the return journey */
	if ( dance->current_minorset>=3*(dance->people/2)-2 && dance->old_style_progression ) {
	    dance->orderedList[lastWait+1]->effective_role = r_waiting;
	    dance->orderedList[lastWait+2]->effective_role = r_waiting;
	    start = lastWait+3;
	    if ( first1m==-1 ) {
		for ( i=0; i<dance->people; ++i )
		    dance->orderedList[i]->effective_role = r_waiting;
		start = dance->people;
	    }
	} else if ( first1m%6==2 ) {
	    dance->orderedList[0]->effective_role = r_outAtTop;
	    dance->orderedList[1]->effective_role = r_outAtTop;
	    start = 2;
	} else if ( first1m%6==4 ) {
	    dance->orderedList[0]->effective_role = r_outAtTop1of2;
	    dance->orderedList[1]->effective_role = r_outAtTop1of2;
	    dance->orderedList[2]->effective_role = r_outAtTop2of2;
	    dance->orderedList[3]->effective_role = r_outAtTop2of2;
	    start = 4;
	} else {
	    start = 0;
	}
	dance->start_first_minor_set = start/2;
	
	/* the ones remain 1s and generally the 2s & 3s alternate */
	for ( i=start; i+5<dance->people; i+=6 ) {
	    if ( dance->orderedList[i+2]->effective_role==r_waiting )
	break;
	    dance->orderedList[i  ]->effective_role = r_1s;
	    dance->orderedList[i+1]->effective_role = r_1s;
	    dance->orderedList[i+2]->effective_role = r_2s;
	    dance->orderedList[i+3]->effective_role = r_2s;
	    dance->orderedList[i+4]->effective_role = r_3s;
	    dance->orderedList[i+5]->effective_role = r_3s;
	}
	/* Even if there are two couples waiting, do not mark them as both */
	/*  out a bottom 1/2 of 2, as that would invoke progression routines */
	if ( firstWait!=-1 && dance->orderedList[firstWait  ]->effective_role==r_waiting ) {
	    dance->orderedList[firstWait  ]->effective_role = r_outAtBottom;
	    dance->orderedList[firstWait+1]->effective_role = r_outAtBottom;
	} else if ( i==dance->people ) {
	    /* Nobody out at bottom */;
	} else if ( i==dance->people-2 ) {
	    dance->orderedList[dance->people-1]->effective_role = r_outAtBottom;
	    dance->orderedList[dance->people-2]->effective_role = r_outAtBottom;
	} else {
	    dance->orderedList[dance->people-4]->effective_role = r_outAtBottom1of2;
	    dance->orderedList[dance->people-3]->effective_role = r_outAtBottom1of2;
	    dance->orderedList[dance->people-2]->effective_role = r_outAtBottom2of2;
	    dance->orderedList[dance->people-1]->effective_role = r_outAtBottom2of2;
	}

	if ( dance->people%6==2 && first1m==2 &&
		danceHasBuiltInScottish4CoupleProgressionPre(dance)) {
	    dance->orderedList[dance->people-6]->effective_role = r_1s_progression;
	    dance->orderedList[dance->people-5]->effective_role = r_1s_progression;
	    dance->orderedList[dance->people-2]->effective_role = r_3s_progression;
	    dance->orderedList[dance->people-1]->effective_role = r_3s_progression;
	}

	moreJiggeryPokeryNeeded = false;
	if (( dance->people==8 && first1m==4 && danceCanDoAutomaticScottish4CoupleProgression(dance)) ||
	    ( dance->people%6==2 && first1m==4 && dance->style == ds_scottish && danceCanDoAutomaticScottish4CoupleProgression(dance)) ||
	    ( dance->people%6==2 && first1m==4 && danceHasBuiltInScottish4CoupleProgressionPost(dance)) ||
	    ( dance->people%6==2 && first1m==4 && danceHasBuiltInScottish4CoupleProgressionPre(dance))) {
	    /* In a scottish 4 couple triple set, the ones dance their role twice */
	    /* then there are 2 couples out above and 2 couples out below */
	    /* In Scottish, the couple at the top becomes new 1s */
	    /*  And the couples in positions 3&4 switch */
	    /* Something similar happens for 7, 10, 13, ... couple sets */
	    /* ScottishFixup */
	    int j;
	    for ( j=0; j<dance->people-2; j+= 6 ) {
		dance->orderedList[j+0]->effective_role = r_1s;
		dance->orderedList[j+1]->effective_role = r_1s;
		dance->orderedList[j+2]->effective_role = r_2s;
		dance->orderedList[j+3]->effective_role = r_2s;
		dance->orderedList[j+4]->effective_role = r_3s;
		dance->orderedList[j+5]->effective_role = r_3s;
	    }
	    dance->orderedList[j+0]->effective_role = r_outAtBottom;
	    dance->orderedList[j+1]->effective_role = r_outAtBottom;
	    moreJiggeryPokeryNeeded=!danceHasBuiltInScottish4CoupleProgressionPre(dance) &&
			!danceHasBuiltInScottish4CoupleProgressionPost(dance);
	}

	if ( dance->people%6==2 && first1m==4 &&
		danceHasBuiltInScottish4CoupleProgressionPost(dance)) {
	    Person *p;

	    dance->orderedList[dance->people-4]->effective_role = r_3s_progression;
	    dance->orderedList[dance->people-3]->effective_role = r_3s_progression;
	    dance->orderedList[dance->people-2]->effective_role = r_4s_progression;
	    dance->orderedList[dance->people-1]->effective_role = r_4s_progression;

	    p = dance->orderedList[dance->people-4];
	    dance->orderedList[dance->people-4] = dance->orderedList[dance->people-2];
	    dance->orderedList[dance->people-2] = p;
	    p = dance->orderedList[dance->people-3];
	    dance->orderedList[dance->people-3] = dance->orderedList[dance->people-1];
	    dance->orderedList[dance->people-1] = p;

	    moreJiggeryPokeryNeeded = false;
	}
	    
	for ( i=0; i<dance->people; ++i )
	    setMoves(dance,i);
	for ( i=0; i<dance->people; ++i )
	    translateMoves(dance,i,6);
	if ( moreJiggeryPokeryNeeded )
	    switch3s4s(dance);
      break;


      case sp_quadrupleMinor:

	/* Ignore multiple progression. */
	/* Find the first couple dancing role 1 in the last minor set */
	/* Look at the index of their position in the ordered list */
	/* if index%8==2 */
	/*    There will be two people (one couple) out at the top */
	/*    and normal minor sets start at index 2 */
	/* if index%8==4 */
	/*    There will be four people (two couple) out at the top */
	/*    and normal minor sets start at index 4 */
	/* if index%8==6 */
	/*    There will be six people (three couple) out at the top */
	/*    and normal minor sets start at index 6 */
	/* if index%8==0 */
	/*    Normal minor sets start at the top of the set, index 0 */
	/* translate all commands by new x-locations */
	/* Update the hand joins for new people */

	order(dance,xCompare);
	first1m = firstWait = lastWait = -1;
	for ( i=0; i<dance->people; ++i ) {
	    if ( dance->orderedList[i]->effective_role == r_1s && first1m == -1 )
		first1m = i;
	    else if ( dance->orderedList[i]->effective_role == r_waiting && firstWait == -1 )
		firstWait = i;
	    if ( dance->orderedList[i]->effective_role == r_waiting )
		lastWait = i;
	    dance->orderedList[i]->current_pos = i/2;
	}
	if ( firstWait==0 )	/* That means top couple has reached the top and is waiting there, not that some couples near the bottom are waiting */
	    firstWait = -1;
	if ( !dance->old_style_progression && dance->progression!=0 && dance->comp_cnt==0 ) {
	    assert(first1m>0);
	    assert((first1m&1)==0);
	}
	/* In a duple minor it takes 2*couples-1 to get back to the top */
	/* but in a triple minor the 3s do not progress, so it takes twice as */
	/* and in a quad minor the 3s+4s do not progress, so it takes thrice as */
	/* long to make the return journey */
	if ( dance->current_minorset>=4*(dance->people/2)-3 && dance->old_style_progression ) {
	    dance->orderedList[lastWait+1]->effective_role = r_waiting;
	    dance->orderedList[lastWait+2]->effective_role = r_waiting;
	    start = lastWait+3;
	    if ( first1m==-1 ) {
		for ( i=0; i<dance->people; ++i )
		    dance->orderedList[i]->effective_role = r_waiting;
		start = dance->people;
	    }
	} else if ( first1m%8==2 ) {
	    dance->orderedList[0]->effective_role = r_outAtTop;
	    dance->orderedList[1]->effective_role = r_outAtTop;
	    start = 2;
	} else if ( first1m%8==4 ) {
	    dance->orderedList[0]->effective_role = r_outAtTop1of2;
	    dance->orderedList[1]->effective_role = r_outAtTop1of2;
	    dance->orderedList[2]->effective_role = r_outAtTop2of2;
	    dance->orderedList[3]->effective_role = r_outAtTop2of2;
	    start = 4;
	} else if ( first1m%8==6 ) {
	    dance->orderedList[0]->effective_role = r_outAtTop1of3;
	    dance->orderedList[1]->effective_role = r_outAtTop1of3;
	    dance->orderedList[2]->effective_role = r_outAtTop2of3;
	    dance->orderedList[3]->effective_role = r_outAtTop2of3;
	    dance->orderedList[4]->effective_role = r_outAtTop3of3;
	    dance->orderedList[5]->effective_role = r_outAtTop3of3;
	    start = 6;
	} else {
	    start = 0;
	}
	dance->start_first_minor_set = start/2;
	
	/* the ones remain 1s and generally the 2s become 4s */
	for ( i=start; i+7<dance->people; i+=8 ) {
	    if ( dance->orderedList[i+2]->effective_role==r_waiting )
	break;
	    dance->orderedList[i  ]->effective_role = r_1s;
	    dance->orderedList[i+1]->effective_role = r_1s;
	    dance->orderedList[i+2]->effective_role = r_2s;
	    dance->orderedList[i+3]->effective_role = r_2s;
	    dance->orderedList[i+4]->effective_role = r_3s;
	    dance->orderedList[i+5]->effective_role = r_3s;
	    dance->orderedList[i+6]->effective_role = r_4s;
	    dance->orderedList[i+7]->effective_role = r_4s;
	}
	/* Even if there are two couples waiting, do not mark them as both */
	/*  out a bottom 1/2 of 2, as that would invoke progression routines */
	if ( firstWait!=-1 && dance->orderedList[firstWait  ]->effective_role==r_waiting ) {
	    dance->orderedList[firstWait  ]->effective_role = r_outAtBottom;
	    dance->orderedList[firstWait+1]->effective_role = r_outAtBottom;
	} else if ( i==dance->people ) {
	    /* Nobody out at bottom */;
	} else if ( i==dance->people-2 ) {
	    dance->orderedList[dance->people-1]->effective_role = r_outAtBottom;
	    dance->orderedList[dance->people-2]->effective_role = r_outAtBottom;
	} else if ( i==dance->people-4 ) {
	    dance->orderedList[dance->people-4]->effective_role = r_outAtBottom1of2;
	    dance->orderedList[dance->people-3]->effective_role = r_outAtBottom1of2;
	    dance->orderedList[dance->people-2]->effective_role = r_outAtBottom2of2;
	    dance->orderedList[dance->people-1]->effective_role = r_outAtBottom2of2;
	} else {
	    dance->orderedList[dance->people-6]->effective_role = r_outAtBottom1of3;
	    dance->orderedList[dance->people-5]->effective_role = r_outAtBottom1of3;
	    dance->orderedList[dance->people-4]->effective_role = r_outAtBottom2of3;
	    dance->orderedList[dance->people-3]->effective_role = r_outAtBottom2of3;
	    dance->orderedList[dance->people-2]->effective_role = r_outAtBottom3of3;
	    dance->orderedList[dance->people-1]->effective_role = r_outAtBottom3of3;
	}
	    
	for ( i=0; i<dance->people; ++i )
	    setMoves(dance,i);
	for ( i=0; i<dance->people; ++i )
	    translateMoves(dance,i,8);
      break;

	default:
	  assert(false);
    }
}

void danceFixupFormation(Dance *dance,enum startingPosition formation,Dance *figure) {
    int i;

    if ( dance->people==0 )
return;
    if (( formation==sp_dupleMinor || formation==sp_tripleMinor || (formation>=sp_2Couple && formation<=sp_8Couple)) &&
	    (dance->formation==sp_dupleMinor || dance->formation==sp_tripleMinor || (dance->formation>=sp_2Couple && dance->formation<=sp_8Couple))) {
	order(dance,xCompare);
	if ( formation==sp_dupleMinor ) {
	    for ( i=0; i+3<dance->people; i+=4 ) {
		dance->orderedList[i]->effective_role = r_1s;
		dance->orderedList[i+1]->effective_role = r_1s;
		dance->orderedList[i+2]->effective_role = r_2s;
		dance->orderedList[i+3]->effective_role = r_2s;
	    }
	    if ( i<dance->people ) {
		dance->orderedList[i]->effective_role = r_outAtBottom;
		dance->orderedList[i+1]->effective_role = r_outAtBottom;
	    }
	} else if ( formation==sp_tripleMinor ) {
	    for ( i=0; i+5<dance->people; i+=6 ) {
		dance->orderedList[i]->effective_role = r_1s;
		dance->orderedList[i+1]->effective_role = r_1s;
		dance->orderedList[i+2]->effective_role = r_2s;
		dance->orderedList[i+3]->effective_role = r_2s;
		dance->orderedList[i+4]->effective_role = r_3s;
		dance->orderedList[i+5]->effective_role = r_3s;
	    }
	    if ( i+3<dance->people ) {
		dance->orderedList[i]->effective_role = r_outAtBottom1of2;
		dance->orderedList[i+1]->effective_role = r_outAtBottom1of2;
		dance->orderedList[i+2]->effective_role = r_outAtBottom2of2;
		dance->orderedList[i+3]->effective_role = r_outAtBottom2of2;
	    } else if ( i<dance->people ) {
		dance->orderedList[i]->effective_role = r_outAtBottom;
		dance->orderedList[i+1]->effective_role = r_outAtBottom;
	    }
	} else {
	    for ( i=0; i<dance->people; i+=2 ) {
		dance->orderedList[i]->effective_role = r_1s+(i/2);
		dance->orderedList[i+1]->effective_role = r_1s+(i/2);
	    }
	}
    } else if ( dance->formation==sp_custom && figure!=NULL && dance->people%4==0 &&
	    formation==sp_fourFaceFour ) {
	for ( i=0; i+1<dance->people; i+=2 ) {
	    dance->dancers[i].now_couple_x = dance->dancers[i+1].now_couple_x =
		    (dance->dancers[i].now.x+dance->dancers[i+1].now.x )/2;
	}
	order(dance,x4Face4Compare);
	i = 0;
	/* The oddity is we have to assign the people to the roles they would */
	/*  have had in the last bit of choreography, rather than what they'll*/
	/*  get in this bit (because we progress the roles a little later) */
	if ( dance->orderedList[0]->now_orientation!=90 ) {
	    /* top dancer is now facing down the hall, assume that entire line is out at top */
	    dance->orderedList[i  ]->effective_role = r_outAtTopLeft;
	    dance->orderedList[i+1]->effective_role = r_outAtTopLeft;
	    dance->orderedList[i+2]->effective_role = r_outAtTopRight;
	    dance->orderedList[i+3]->effective_role = r_outAtTopRight;
	    i = 4;
	}
	for ( ; i+7<dance->people; i+=8 ) {
	    dance->orderedList[i]->effective_role = r_2sleft;
	    dance->orderedList[i+1]->effective_role = r_2sleft;
	    dance->orderedList[i+2]->effective_role = r_2sright;
	    dance->orderedList[i+3]->effective_role = r_2sright;
	    dance->orderedList[i+4]->effective_role = r_1sleft;
	    dance->orderedList[i+5]->effective_role = r_1sleft;
	    dance->orderedList[i+6]->effective_role = r_1sright;
	    dance->orderedList[i+7]->effective_role = r_1sright;
	}
	if ( i+3<dance->people ) {
	    dance->orderedList[i  ]->effective_role = r_outAtBottomLeft;
	    dance->orderedList[i+1]->effective_role = r_outAtBottomLeft;
	    dance->orderedList[i+2]->effective_role = r_outAtBottomRight;
	    dance->orderedList[i+3]->effective_role = r_outAtBottomRight;
	}
    } else if ( formation==sp_custom && figure!=NULL && dance->people==figure->role_cnt ) {
	/* For each dancer find the role with the location nearest. Don't support */
	/* translations or rotations or anything fancy */
	int j;
	for ( i=0; i<figure->role_cnt; ++i )
	    figure->roles[i].ticked = false;
	for ( i=0; i<figure->role_cnt; ++i ) {
	    double best=1e99; int best_pos=-1;
	    for ( j=0; j<figure->role_cnt; ++j ) if ( !figure->roles[j].ticked ) {
		double xdiff, ydiff, len;
		xdiff = dance->dancers[i].now.x - figure->roles[i].figures.moves[0].endPoint.x;
		ydiff = dance->dancers[i].now.y - figure->roles[i].figures.moves[0].endPoint.y;
		len = xdiff*xdiff + ydiff*ydiff;
		if ( len< best ) {
		    best_pos=j;
		    best = len;
		}
	    }
	    if ( best_pos==-1 ) {
		fprintf( stderr, "Internal error: Failed to find a good role for dancer %d when changing from %s to %s\n",
			i,
			startFormationNames[dance->formation],
			startFormationNames[formation] );
		assert( best_pos!=-1 );
	    }
	    dance->dancers[i].effective_role = figure->roles[best_pos].effective_role;
	    if ( dance->dancers[i].effective_sex != figure->roles[best_pos].effective_sex )
		fprintf( stderr, "Warning: Dancer %d changes sex when changing from %s to %s\n",
		    i,
		    startFormationNames[dance->formation],
		    startFormationNames[formation] );
	    dance->dancers[i].effective_sex = figure->roles[best_pos].effective_sex;
	    figure->roles[best_pos].ticked = true;
	}
    } else {
	fprintf( stderr, "I don't know how to change from %s to %s\n",
	    startFormationNames[dance->formation],
	    startFormationNames[formation] );
exit(1);
    }
    dance->formation = formation;
}

void danceForceNoOneOutAtTop(Dance *dance) {
    int i;

    if ( dance->people==0 )
return;
    order(dance,xCompare);
    if ( dance->formation==sp_dupleMinor ) {
	dance->orderedList[0]->effective_role = r_outAtTop;
	dance->orderedList[1]->effective_role = r_outAtTop;
	for ( i=2; i<dance->people; i+=2 ) {
	    dance->orderedList[i]->effective_role = (i/2)&1 ? r_2s : r_1s;
	    dance->orderedList[i+1]->effective_role = (i/2)&1 ? r_2s : r_1s;
	}
    } else {
	/* untested */
	for ( i=0; i<dance->people; i+=2 ) {
	    dance->orderedList[i]->effective_role = (i/2)%3==0 ? r_1s : (i/2)%3==1 ? r_2s : r_3s;
	    dance->orderedList[i+1]->effective_role = (i/2)%3==0 ? r_1s : (i/2)%3==1 ? r_2s : r_3s;
	}
    }
}

static void danceListRoles(Dance *dance) {
    int i;

    printf( "\n" );
    for ( i=0; i<dance->people ; ++i ) {
	Person *p = &dance->dancers[i];

	printf( "%2d: %2d (%4d,%4d) %3d %c(%c) %s\n",
		i, p->current_pos,
		(int) p->now.x, (int) p->now.y,
		(int) p->now_orientation,
		sexChars[p->effective_sex],
		sexChars[p->sex],
		roleNames[p->effective_role] );
    }
}

void danceReset(Dance *dance,int frame, int frames_per_bar ) {
    int i;

    ++ dance->current_part;
    if ( dance->current_part>=dance->part_cnt )
	dance->current_part = 0;
    dance->first_minor_set = 0;

    if ( dance->sequence!=NULL )
	danceAdvanceChoreography(dance);

    if ( dance->formation==sp_custom || dance->formation==sp_custom3 ||
	    (dance->formation>= sp_3CplCircle && dance->formation <= sp_7CplCircle ) ||
	    dance->formation==sp_squaredSet ||dance->formation==sp_square3 ) {
	/* Well it's already in a circle. We can't sicilianize it */
	danceResetNormal(dance,frame,frames_per_bar);
    } else if ( dance->sicilian ) {
	danceResetSicilian(dance,frame,frames_per_bar);
    } else {
	danceResetNormal(dance,frame,frames_per_bar);
    }

    for ( i=0; i<dance->people; ++i ) {
	Person *p = &dance->dancers[i];
	p->current = p->figures.moves+1;
	splineMake(p->current,&p->now);
	p->millibars_start_of_current = (frame*MILLIBARS_MUL)/frames_per_bar;
	p->orientation_start_of_current = p->now_orientation;
	p->dropped_left_in_current = 0;
	p->dropped_right_in_current = 0;
	p->joined_left_in_current = 0;
	p->joined_right_in_current = 0;
    }
    if ( dance->calls!=NULL ) {
	dance->current = danceFindFirstCallInCurrentPart(dance->calls,dance->call_cnt,
		(1<<dance->current_part) |
		  (dance->last_minor_set?LAST_MASK:0) |
		  (!dance->last_minor_set?NOTLAST_MASK:0) |
		  (dance->first_minor_set?FIRST_MASK:0) |
		  (!dance->first_minor_set?NOTFIRST_MASK:0));
	dance->millibars_start_of_current = (frame*MILLIBARS_MUL)/frames_per_bar;
    }
    if ( dance->bbs!=NULL && dance->components==NULL ) {
	dance->currentBB = dance->bbs;
	dance->millibars_start_of_bbcurrent = (frame*MILLIBARS_MUL)/frames_per_bar;
	if ( dance->currentBB->automatic )
	    danceFindCurrentBB(dance,&dance->currentBB->bb);
	dance->bbStartOfCurrent = dance->currentBB->bb;
    }
    if ( dance->verbose )
	danceListRoles(dance);
#if 0
/* Debug !!!!! */
 dance->is_figure = true;
 danceOutputCall("debug.call",dance);
 dance->is_figure = false;
/* gubed */
#endif
}

static int translateHand(Dance *dance,int minorSetStart,int minorSetSize,int oldMask) {
    int hand;
    int setoff;
    int normalMinorSize = danceMinorSetSize(dance);
    /* What hand to clasp. */
    /* First problem, clasping the hand in the same minor set? just add the */
    /*  person number to the minorset start and that's right */
    /* Might also want to clasp the hand of someone in the preceding or following */
    /*  sets, then we have to check if we actually have that many sets in the */
    /*  dance (with complications for the half sets when someone is out at the ends) */
    /* In some calls we want people to wrap around the end of the set */
    /* In others we don't (long lines) */
    /* Other aspects of this program won't support wrapping around the ends */
    /*  so we ignore that. If the indicated dancer doesn't exist, no hand clasp */
    /* Mmm. Except in sicilian circles */

    if ( oldMask==0 )
return( 0 );
    if ( (oldMask&HAND_INDIVIDUAL_MASK)==HAND_STAR )
return( HAND_STAR|(oldMask&HAND_ABOVE_MASK) );

    hand = (oldMask&HAND_INDIVIDUAL_MASK);
    if ( hand>=danceMinorSetSize(dance) )
return( 0 );

    hand += minorSetStart;
    if ( (oldMask&HAND_MINORSET_MASK)!=0 ) {
	setoff = (oldMask&HAND_MINORSET_OFFSET)>>HAND_MINORSET_SHIFT;
	if ( oldMask&HAND_MINORSET_UP ) {
	    hand -= setoff*normalMinorSize;
#if 0 /* Removed this section 17 Jul 2019 ( see below) */
	    if ( hand < 0 && minorSetSize<normalMinorSize && hand>-normalMinorSize ) {
		/* Out at top, probably can't happen at start */
		if ( oldMask&HAND_NOTOUT_MASK )
return( 0 );
		hand &= 1;
	    } else
#endif
	    if ( hand<0 && dance->sicilian )
		hand += dance->people;
	    if ( hand<0 )
return( 0 );
	} else {
	    hand += setoff*normalMinorSize;
	    if ( hand>= dance->people && dance->sicilian )
		hand -= dance->people;
	    if ( hand >= dance->people && hand-normalMinorSize <dance->people && normalMinorSize==4 && dance->people%normalMinorSize!=0 ) {
		/* out at bottom, probably won't work for triple minor or four face four */
		/* Seems to fail me in a normal becket dance (Lizzie's Delight)  with -couples 4 */
		/* No one should be out at this point but this code got triggered */
		/* Well seems I do need it for MidwestFolklore.dance, so make the test more specific */
		if ( oldMask&HAND_NOTOUT_MASK )
return( 0 );
		hand = dance->people-2 + (hand&1);
	    } else if ( hand >= dance->people )
return( 0 );
	}
	if ( ( oldMask&HAND_NOTOUT_MASK ) &&
		dance->dancers[hand].effective_role>=r_outAtTop &&
		dance->dancers[hand].effective_role<=r_outAtBottomRight )
return( 0 );
    } else {
	/* for clasps of people in same set */
	int off = (oldMask&HAND_INDIVIDUAL_MASK);
	if ( off>=minorSetSize ) {
	    if ( minorSetSize==2 ) {
		while ( off>=minorSetSize )
		    off -= 2;
	    } else
return( 0 );
	}
	hand = minorSetStart + off;
    }
return( hand | (oldMask&HAND_COPY_MASK));
}

static void translateMovesByX(Dance *dance, Person *person,int xoff, int minorSetStart, int minorSetSize ) {
    int i;

    for ( i=0; i<person->figures.move_cnt; ++i ) {
	FigureSegment *cs = &person->figures.moves[i];
	if (( cs->cmd==c_moveto || cs->cmd==c_lineto || cs->cmd==c_curveto ) && !cs->position_absolute ) {
	    cs->endPoint.x += xoff;
	    if ( cs->cmd==c_curveto ) {
		cs->cp1.x += xoff;
		cs->cp2.x += xoff;
	    }
	    if ( cs->cmd==c_lineto || cs->cmd==c_curveto ) {
		cs->splines[0].d += xoff;
	    }
	}
	if ( !cs->position_absolute )
	    cs->star_center.x += xoff;
	cs->join_right_hand = translateHand(dance,minorSetStart,minorSetSize,cs->join_right_hand);
	cs->join_left_hand  = translateHand(dance,minorSetStart,minorSetSize,cs->join_left_hand );
	if ( cs->orient==mo_faceDancer )
	    cs->faceDancer += minorSetStart;
    }
}

static void changeCoordinates(Dance *dance,Position *pos) {
    double r, theta;
    /* for each position we need to find a new r,theta value */
    /* theta is just the distance along the major set back to the first couple */
    /*  (x-dance->center.x) divided by the length (dance->sicilian_circumference) multiplied by 2*PI */
    /* r is y-middle + radius */
    /* with these we calculate new positions */

    r = dance->sicilian_radius + dance->sicilian_midline-pos->y;
    theta = 2*PI * (pos->x-dance->sicilian_center.x)/dance->sicilian_circumference - PI/2;
assert(!isnan(r));
assert(!isnan(theta));
    pos->x = r*cos(theta) + dance->sicilian_center.x;
    pos->y = r*sin(theta) + dance->sicilian_center.y;
}

/* Change control points by insuring they are still at the same relative distance and angle from the new base point */
static void changeControlCoordinates(Dance *dance,Position *pos,Position *base) {
    double r, theta;
    double offr, offtheta;
    /* for each position we need to find a new r,theta value */
    /* theta is just the distance along the major set back to the first couple */
    /*  (x-dance->center.x) divided by the length (dance->sicilian_circumference) multiplied by 2*PI */
    /* r is y-middle + radius */
    /* with these we calculate new positions */

    r = dance->sicilian_midline-base->y + dance->sicilian_radius;
    theta = 2*PI * (base->x-dance->sicilian_center.x)/dance->sicilian_circumference - PI/2;
assert(!isnan(r));
assert(!isnan(theta));
    offr = sqrt((pos->x-base->x)*(pos->x-base->x) + (pos->y-base->y)*(pos->y-base->y));
    offtheta = atan2((pos->y-base->y),(pos->x-base->x));

    pos->x = r*cos(theta) + dance->sicilian_center.x;
    pos->y = r*sin(theta) + dance->sicilian_center.y;

    pos->x += offr*cos(theta+PI/2+offtheta);
    pos->y += offr*sin(theta+PI/2+offtheta);
}

static void changeOrientation(Dance *dance,FigureSegment *cs) {
    double theta;

    if ( cs->degrees==DEGREES_END )
return;
    theta = 360 * (cs->endPoint.x-dance->sicilian_center.x)/dance->sicilian_circumference;
    cs->degrees += theta;
    if ( cs->degrees>360 )
	cs->degrees -= 360;
}

static void danceMakeSicilian(Dance *dance, int couples) {
    /* Any minor set type dance should be translateable into a sicilian circle */
    /*  but since 1s remain 1s for the entire dance it's probably best to do */
    /*  this for dances which are relatively symmetric, otherwise the 2s (+ 3s?) */
    /*  will get bored and rebel */

    /* first check that we can, in fact, make a circle. The dance needs to have */
    /*  a minor set */
    /*int minorset_size;*/
    /*int line_size=1;*/	/* one couple facing each direction in minorset except in 4 face 4 */
    double len;
    double ymin;
    int i, j;
    Position here;

    switch ( dance->formation ) {
      case sp_circularMonople: case sp_trioCircularMonople:
	/*minorset_size = 1;*/
      break;

      case sp_dupleMinor:
      case sp_dupleMinorProgressed:
      case sp_becket:
      case sp_becketCCW:
      case sp_shortWaves:
      case sp_scottishDupleMinor:		/* These guys are perhaps unexpected since they bound the major set to 4, but they should work */
	if ( couples&1 ) {
	    fprintf( stderr, "You cannot have a Sicilian circle with an odd number of couples.\n" );
	    dance->sicilian = false;
return;
	}
	/*minorset_size = 2;*/
      break;
      case sp_tripleMinor:
      case sp_scottishTripleMinor:		/* I'm going to treat this just as an ecd triple minor and not worry about the complexities of Scottish progression */
      case sp_rotatedTripleMinor:
	if ( couples%3!=0 ) {
	    fprintf( stderr, "In a Sicilian circle the number of couples must be divisible by the minor set size.\n" );
	    dance->sicilian = false;
return;
	}
	/*minorset_size = 3;*/
      break;
      case sp_threeFaceThree:
	if ( couples%3!=0 ) {
	    fprintf( stderr, "In a Sicilian circle the number of couples must be divisible by the minor set size.\n" );
	    dance->sicilian = false;
return;
	}
	/*minorset_size = 3;*/
      case sp_fourFaceFour:
      case sp_tempest:
      case sp_quadrupleMinor:
      case sp_quadrupleMinorBecket:
	if ( couples%4!=0 ) {
	    fprintf( stderr, "In a Sicilian circle the number of couples must be divisible by the minor set size.\n" );
	    dance->sicilian = false;
return;
	}
	/*minorset_size = 4;*/
	/*line_size = 2;*/
      break;
      default:
	fprintf( stderr, "This dance has no minor set and cannot be danced in a Sicilian circle.\n" );
	dance->sicilian = false;
return;
    }
	
    /* first job is to find the length of the set */
    /* this is slightly complicated by the fact that we need to add on */
    /*  one intercouple space at the end of the set */
    /*  (can't have the last and first couples in the same place) */
    /* That doesn't work for tempest dances */
    /* Better is to find the location of the last 1s and add on the minorset spacing */
    /*  But that doesn't work for becket. Sigh */
    len = dance->dancers[dance->people-1].figures.moves[0].endPoint.x - dance->dancers[0].figures.moves[0].endPoint.x +
	    danceCoupleSpacing(dance);
    switch ( dance->formation ) {
      case sp_circularMonople: case sp_trioCircularMonople:
	    len = dance->dancers[dance->people-2].figures.moves[0].endPoint.x - dance->dancers[0].figures.moves[0].endPoint.x +
		    danceMinorSetSpacing(dance);
      break;

      case sp_fourFaceFour:
      case sp_tempest:
	len = dance->dancers[dance->people-5].figures.moves[0].endPoint.x - dance->dancers[0].figures.moves[0].endPoint.x +
		danceMinorSetSpacing(dance);
      break;
      case sp_quadrupleMinorBecket:
	len = dance->dancers[dance->people-7].figures.moves[0].endPoint.x - dance->dancers[1].figures.moves[0].endPoint.x +
		danceMinorSetSpacing(dance);
      break;

      case sp_becket:
	len = dance->dancers[dance->people-1].figures.moves[0].endPoint.x - dance->dancers[1].figures.moves[0].endPoint.x;
	len += danceCoupleSpacing(dance);
      break;
      case sp_becketCCW:
	len = dance->dancers[dance->people-2].figures.moves[0].endPoint.x - dance->dancers[0].figures.moves[0].endPoint.x;
	len += danceCoupleSpacing(dance);
      break;

      case sp_shortWaves:
	len = dance->dancers[dance->people-4].figures.moves[0].endPoint.x - dance->dancers[0].figures.moves[0].endPoint.x;
	len += danceMinorSetSpacing(dance);
      break;

      case sp_rotatedTripleMinor:
	len = dance->dancers[dance->people-6].figures.moves[0].endPoint.x - dance->dancers[0].figures.moves[0].endPoint.x;
	len += danceMinorSetSpacing(dance);
      break;

      case sp_dupleMinor:
	if ( dance->dancers[0].figures.moves[0].endPoint.x==320 &&
		dance->dancers[1].figures.moves[0].endPoint.x==576 &&
		dance->dancers[2].figures.moves[0].endPoint.x==832 &&
		dance->dancers[3].figures.moves[0].endPoint.x==1088 &&
		dance->dancers[0].figures.moves[0].endPoint.y==64 &&
		dance->dancers[1].figures.moves[0].endPoint.y==64 &&
		dance->dancers[2].figures.moves[0].endPoint.y==64 &&
		dance->dancers[3].figures.moves[0].endPoint.y==64 ) {
	    /* Special hack for appalacian circle dances where everyone starts */
	    /*  in a single circle and we start sort of becketty */
	    len = dance->dancers[dance->people-1].figures.moves[0].endPoint.x - dance->dancers[0].figures.moves[0].endPoint.x;
	    len += 256;
	}
      break;
	    
      default:
      break;
    }

    /* OK that's the circumference of the circle */
    dance->sicilian_radius = len/(2*PI);
    dance->sicilian_center.x = dance->dancers[0].figures.moves[0].endPoint.x;
    dance->sicilian_circumference = len;
    ymin = dance->dancers[0].figures.moves[0].endPoint.y<dance->dancers[1].figures.moves[0].endPoint.y ?
	    dance->dancers[0].figures.moves[0].endPoint.y :
	    dance->dancers[1].figures.moves[0].endPoint.y ;
    switch ( dance->formation ) {
      default:
	dance->sicilian_midline = (dance->dancers[0].figures.moves[0].endPoint.y + dance->dancers[1].figures.moves[0].endPoint.y)/2;
      break;
      case sp_threeFaceThree: case sp_trioCircularMonople:
	dance->sicilian_midline = (dance->dancers[0].figures.moves[0].endPoint.y + dance->dancers[2].figures.moves[0].endPoint.y)/2;
	ymin = ymin<dance->dancers[2].figures.moves[0].endPoint.y ?
		ymin :
		dance->dancers[2].figures.moves[0].endPoint.y ;
      break;
      case sp_fourFaceFour:
      case sp_tempest:
	dance->sicilian_midline = (dance->dancers[0].figures.moves[0].endPoint.y + dance->dancers[3].figures.moves[0].endPoint.y)/2;
      break;
      case sp_becket:
      case sp_becketCCW:
      case sp_quadrupleMinorBecket:
	dance->sicilian_midline = (dance->dancers[0].figures.moves[0].endPoint.y + dance->dancers[2].figures.moves[0].endPoint.y)/2;
	ymin = ymin<dance->dancers[2].figures.moves[0].endPoint.y ?
		ymin :
		dance->dancers[2].figures.moves[0].endPoint.y ;
      break;
    }
    /* Swings don't look nice if x/y scaled differently */
    /* Swings just don't look nice in my circular projection */

    if ( dance->sicilian_radius < 2*(dance->sicilian_midline-ymin) &&
	    dance->sicilianScale ) {
	double scale = 2*(dance->sicilian_midline-ymin)/dance->sicilian_radius;
	danceXScale(dance, scale);
	len *= scale;
	dance->sicilian_radius = len/(2*PI);
	dance->sicilian_center.x = dance->dancers[0].figures.moves[0].endPoint.x;
	dance->sicilian_circumference = len;
    }

    dance->sicilian_center.y = dance->sicilian_midline + dance->sicilian_radius;

    /* Now run through all moves of all dancers */
    /* for each position we need to find a new r,theta value */
    /* theta is just the distance along the major set back to the first couple */
    /*  (x-dance->center.x) divided by the length (len) multiplied by 2*PI */
    /* r is y-midline + radius */
    /* with these we calculate new positions */
    for ( i=0; i<dance->people; ++i ) {
	Person *p = &dance->dancers[i];

	/* <pause's need to know where they are, otherwise orientation goes wonky */
	here.x = here.y = -dance->sicilian_circumference;
	for ( j=0; j<p->figures.move_cnt; ++j ) {
	    FigureSegment *cs = &p->figures.moves[j];
	    if ( cs->cmd==c_lineto )
		csChangeLineToDegenerateCurveto(cs,&here);
	    if ( cs->cmd==c_moveto || cs->cmd==c_curveto )
		here = cs->endPoint;
	    else if ( cs->cmd==c_pause )
		cs->endPoint = here;
	}

	/* we need to know the endpoint of the unmodified previous spline */
	/*  so we run through the list backwards in order not to modify it too soon (don't care about next spline) */
	for ( j=p->figures.move_cnt-1; j>=0 ; --j ) {
	    FigureSegment *cs = &p->figures.moves[j];
	    if ( cs->cmd==c_moveto || cs->orient==mo_rotateto ||
		    cs->orient==mo_cw_rotateto || cs->orient==mo_ccw_rotateto )
		changeOrientation(dance,cs);
	    if ( cs->cmd==c_moveto || cs->cmd==c_lineto || cs->cmd==c_curveto ) {
		if ( cs->cmd==c_curveto ) {
		    changeControlCoordinates(dance,&cs->cp1,csPreviousEndPoint(p->figures.moves,cs));
		    changeControlCoordinates(dance,&cs->cp2,&cs->endPoint);
		}
		changeCoordinates(dance,&cs->endPoint);
	    }
	    if ( (cs->join_right_hand&HAND_INDIVIDUAL_MASK)==HAND_STAR ||
		 (cs->join_left_hand&HAND_INDIVIDUAL_MASK)==HAND_STAR )
		changeCoordinates(dance,&cs->star_center);
	    /* Bug!!!! hand clasps outside of minor set which wrap around */
	    /*  dancer 0 will not be clasped. (Because they weren't in the */
	    /*  linear form that figured out the clasps */
	    /* Ah. should be fixed. They are in the linear form now. */
	    /*  special check in translateHands for sicilian dances */
	}
    }
    danceOutputDebugFigure("fuf2.dance",dance);
}

static void danceSetDefaultActualStart(Dance *dance) {
    int i,j;

    for ( i=0; i<dance->role_cnt; ++i ) {
	Person *p = &dance->roles[i];
	if ( p->figures.move_cnt>0 && p->figures.moves[0].cmd == c_moveto )
	    p->actualFigureStartPos = p->figures.moves[0].endPoint;
    }
    if ( dance->comp_cnt!=0 ) {
	for ( j=0; j<dance->comp_cnt; ++j ) {
	    Dance *d = dance->components[j];
	    for ( i=0; i<d->role_cnt; ++i ) {
		Person *p = &d->roles[i];
		if ( p->figures.move_cnt>0 && p->figures.moves[0].cmd == c_moveto )
		    p->actualFigureStartPos = p->figures.moves[0].endPoint;
	    }
	}
    }
    if ( dance->becket_style==bs_ccw && dance->formation==sp_scottishDupleMinor ) {
	float x1s, x2s, ymen, ywomen;
	x1s    = dance->roles[0].figures.moves[0].endPoint.x;
	ymen   = dance->roles[0].figures.moves[0].endPoint.y;
	x2s    = dance->roles[2].figures.moves[0].endPoint.x;
	ywomen = dance->roles[1].figures.moves[0].endPoint.y;

	dance->roles[1].actualFigureStartPos.x = x2s;
	dance->roles[1].actualFigureStartPos.y = ymen;
	dance->roles[2].actualFigureStartPos.x = x2s;
	dance->roles[2].actualFigureStartPos.y = ywomen;
	dance->roles[3].actualFigureStartPos.x = x1s;
	dance->roles[3].actualFigureStartPos.y = ywomen;
    }
}

void danceStart(Dance *dance, int couples,int out_at_top) {
    int i;
    int sets;
    int off, basex, base1x, jump;

    if ( dance->sequence!=NULL && dance->choreo_pos==0 ) {
	if ( couples==0 ) {
	    if ( dance->formation>=sp_2Couple && dance->formation<=sp_8Couple )
		couples = 2 + (dance->formation-sp_2Couple);
	}
	danceAdvanceChoreography(dance);
    }

    danceSetDefaultActualStart(dance);
	
    if ( dance->is_figure )
return;
    dance->first_minor_set = true;
    switch ( dance->formation ) {
      case sp_squaredSet:
      case sp_rect6Set:
      case sp_2Couple:
      case sp_3Couple:
      case sp_4Couple:
      case sp_5Couple:
      case sp_6Couple:
      case sp_7Couple:
      case sp_8Couple:
      case sp_3CplCircle:
      case sp_5CplCircle:
      case sp_6CplCircle:
      case sp_7CplCircle:
      case sp_square3:
      case sp_custom:
      case sp_custom3:
      case sp_facingCouples:
      case sp_facingCouplesBecket:
      /*case sp_facingCouplesProper:*/
	/* These dances have no minor sets, so the number of people in the dance is fixed */
	/*  So we ignore the couples argument. */
	dance->people = dance->role_cnt;
	dance->dancers = calloc(dance->people,sizeof(Person));
	memcpy(dance->dancers,dance->roles,dance->people*sizeof(Person));
	for ( i=0; i<dance->people; ++i ) {
	    dance->dancers[i].figures.moves = malloc(dance->dancers[i].figures.move_max*sizeof(FigureSegment));
	    dance->dancers[i].figures.move_cnt = 0;
	    blockCopyAndFlatten(&dance->dancers[i].figures,&dance->roles[i].figures,&dance->dancers[i],dance);
	    dance->dancers[i].actualFigureStartPos = dance->roles[i].actualFigureStartPos;
	    dance->dancers[i].now_left_hand_point = -1;
	}
      break;

      case sp_circularMonople:
	dance->people = 2*couples;
	dance->dancers = calloc(dance->people,sizeof(Person));
	for ( i=0; i<couples; ++i ) {
	    fillDancer(dance,2*i  ,danceRoleSex(dance,r_1s,s_male));
	    fillDancer(dance,2*i+1,danceRoleSex(dance,r_1s,s_female));
	}
	/* only handle 1s/2s improper no idea how to behave if they talk about 3s */
	if ( dance->improper_mask&1 ) {
	    for ( i=0; i<couples; i+=2 ) {
		dance->dancers[2*i  ].sex = s_female;
		dance->dancers[2*i  ].effective_sex = s_male;
		dance->dancers[2*i+1].sex = s_male;
		dance->dancers[2*i+1].effective_sex = s_female;
	    }
	} else if ( dance->improper_mask&2 ) {
	    for ( i=1; i<couples; i+=2 ) {
		dance->dancers[2*i  ].sex = s_female;
		dance->dancers[2*i  ].effective_sex = s_male;
		dance->dancers[2*i+1].sex = s_male;
		dance->dancers[2*i+1].effective_sex = s_female;
	    }
	}

	off = 0;
	jump = danceMinorSetSpacing(dance);
	for ( i=0; i<dance->people; i+=2, off+=jump ) {
	    translateMovesByX(dance,&dance->dancers[i],off,i,2);
	    translateMovesByX(dance,&dance->dancers[i+1],off,i,2);
	}
      break;

      case sp_trioCircularMonople:
	dance->people = 3*couples;
	dance->dancers = calloc(dance->people,sizeof(Person));
	for ( i=0; i<couples; ++i ) {
	    fillDancer(dance,3*i  ,danceRoleSex(dance,r_1s,s_left));
	    fillDancer(dance,3*i+1,danceRoleSex(dance,r_1s,s_center));
	    fillDancer(dance,3*i+2,danceRoleSex(dance,r_1s,s_right));
	}
	/* ignore improper */

	off = 0;
	jump = danceMinorSetSpacing(dance);
	for ( i=0; i<dance->people; i+=3, off+=jump ) {
	    translateMovesByX(dance,&dance->dancers[i],off,i,3);
	    translateMovesByX(dance,&dance->dancers[i+1],off,i,3);
	    translateMovesByX(dance,&dance->dancers[i+2],off,i,3);
	}
      break;

      case sp_dupleMinor:
      case sp_dupleMinorProgressed:
      case sp_becket:
      case sp_becketCCW:
      case sp_shortWaves:
      case sp_scottishDupleMinor:
	if ( out_at_top ) {
	    fprintf( stderr, "Out at top not supported for duple minors yet.\n" );
	}
	dance->people = 2*couples;
	dance->dancers = calloc(dance->people,sizeof(Person));
	if ( dance->formation!=sp_scottishDupleMinor && !dance->old_style_progression ) {
	    for ( i=0; i<(couples&(~1)); i+=2 ) {
		/* 1s */
		fillDancer(dance,2*i  ,danceRoleSex(dance,r_1s,s_male));
		fillDancer(dance,2*i+1,danceRoleSex(dance,r_1s,s_female));
		/* 2s */
		fillDancer(dance,2*i+2,danceRoleSex(dance,r_2s,s_male));
		fillDancer(dance,2*i+3,danceRoleSex(dance,r_2s,s_female));
	    }
	    if ( couples&1 ) {
		/* Out at bottom */
		fillDancer(dance,2*i  ,danceRoleSex(dance,r_outAtBottom,s_male));
		fillDancer(dance,2*i+1,danceRoleSex(dance,r_outAtBottom,s_female));
	    }
	} else {
	    fillDancer(dance,0,danceRoleSex(dance,r_1s,s_male));
	    fillDancer(dance,1,danceRoleSex(dance,r_1s,s_female));
	    fillDancer(dance,2,danceRoleSex(dance,r_2s,s_male));
	    fillDancer(dance,3,danceRoleSex(dance,r_2s,s_female));
	    if ( couples>2 ) {
		if ( strcmp(dance->name,"The Glasgow Highlanders")==0 ) {/* The Glasgow Highlanders need the 3rd couple to be "out at bottom" while the 4th is "waiting" */
		    fillDancer(dance,4,danceRoleSex(dance,r_outAtBottom,s_male));
		    fillDancer(dance,5,danceRoleSex(dance,r_outAtBottom,s_female));
		    i = 3;
		} else
		    i = 2;
		for (  ; i<couples; ++i ) {
		    makeDancerWait(dance,2*i  ,r_waiting);
		    makeDancerWait(dance,2*i+1,r_waiting);
		}
	    }
	}
	jump = danceMinorSetSpacing(dance);
#if 0
	minx = 999999; maxx=0;
	for ( i=0; i<4 && i<dance->people; ++i ) {
	    if ( dance->dancers[i].figures.moves[0].endPoint.x<minx )
		minx = dance->dancers[i].figures.moves[0].endPoint.x;
	    else if ( dance->dancers[i].figures.moves[0].endPoint.x>maxx )
		maxx = dance->dancers[i].figures.moves[0].endPoint.x;
	}
	basex = dance->dancers[0].figures.moves[0].endPoint.x;
	base1x = dance->dancers[1].figures.moves[0].endPoint.x;
	jump = maxx-minx;
	jump_magic = 0;
	if ( /*dance->formation==sp_shortWaves &&*/ jump<dance->units/8 ) {
	    jump = dance->units/4;
	    jump_magic=1;
	}
	off = 0;
	while ( off+minx>jump )
	    off -= jump;
#else
	off = 0;
	basex = dance->dancers[0].figures.moves[0].endPoint.x;
	base1x = dance->dancers[1].figures.moves[0].endPoint.x;
#endif

	/* Initially I didn't need to adjust the first minor set, but now */
	/*  that I support hand clasps outside the minor set, I need to */
	/*  translate it too */
	if ( dance->formation!=sp_scottishDupleMinor && !dance->old_style_progression ) {
	    for ( i=0; i+2<dance->people; i+= 4, off+=jump ) {
		translateMovesByX(dance,&dance->dancers[i],off,i,4);
		translateMovesByX(dance,&dance->dancers[i+1],off,i,4);
		translateMovesByX(dance,&dance->dancers[i+2],off,i,4);
		translateMovesByX(dance,&dance->dancers[i+3],off,i,4);
	    }
	    if ( i<dance->people ) {
		int diff;
		if ( base1x==basex ) { /* Dance where partners are across the set from each other (normal improper, wavy lines, etc. */
		    diff = dance->dancers[i].figures.moves[0].endPoint.x - basex;
		} else if ( base1x<basex ) {
		    /* Normal becket */
		    if ( dance->dancers[i].figures.moves[0].endPoint.x<dance->dancers[i+1].figures.moves[0].endPoint.x )
			diff = dance->dancers[i].figures.moves[0].endPoint.x - base1x;
		    else if ( dance->dancers[i].figures.moves[0].endPoint.x==dance->dancers[i+1].figures.moves[0].endPoint.x )
			diff = 0;		/* Winter in Summerland */
		    else
			diff = dance->dancers[i].figures.moves[0].endPoint.x - basex;
		} else {
		    /* Counter clockwise becket */
		    if ( dance->dancers[i].figures.moves[0].endPoint.x>dance->dancers[i+1].figures.moves[0].endPoint.x )
			diff = dance->dancers[i].figures.moves[0].endPoint.x - base1x;
		    else if ( dance->dancers[i].figures.moves[0].endPoint.x==dance->dancers[i+1].figures.moves[0].endPoint.x )
			diff = 0;
		    else
			diff = dance->dancers[i].figures.moves[0].endPoint.x - basex;
		}

#if 0
		/* In a becket dance with a couple out on the wrong side (40 years of pumpkin pam) I need the following */
/*		if ( dance->dancers[i].figures.moves[0].endPoint.x<dance->dancers[i+1].figures.moves[0].endPoint.x ) {
/*		    if ( base1x<basex )
/*			diff = dance->dancers[i].figures.moves[0].endPoint.x - base1x;
/*		    else
/*			diff = dance->dancers[i].figures.moves[0].endPoint.x - basex;
/*		} else if ( base1x==basex ||
/*			dance->dancers[i].figures.moves[0].endPoint.x != dance->dancers[i+1].figures.moves[0].endPoint.x ||
/*			basex<base1x /* reverse becket */ )
/*		    diff = dance->dancers[i].figures.moves[0].endPoint.x - basex;
/*		else
/*		    diff = dance->dancers[i].figures.moves[0].endPoint.x - base1x;*/
#endif
		off -= diff;
		if ( dance->formation==sp_dupleMinorProgressed )
		    off -= dance->dancers[0].figures.moves[0].endPoint.x - dance->dancers[2].figures.moves[0].endPoint.x;
		translateMovesByX(dance,&dance->dancers[i],off,i,2);	/* Changed this from 2 to 4 17Aug20 !!!!!, changed back 28Aug20 */
		translateMovesByX(dance,&dance->dancers[i+1],off,i,2);
	    }
	} else {
	    int diff;
	    i=0;
	    translateMovesByX(dance,&dance->dancers[i],off,i,4);
	    translateMovesByX(dance,&dance->dancers[i+1],off,i,4);
	    translateMovesByX(dance,&dance->dancers[i+2],off,i,4);
	    translateMovesByX(dance,&dance->dancers[i+3],off,i,4);
	    off += jump;
	    diff = dance->dancers[4].figures.moves[0].endPoint.x - basex;
	    off -= diff;
	    for ( i=4; i<dance->people; i+= 2, off+=jump/2 ) {
		translateMovesByX(dance,&dance->dancers[i],off,i,4);
		translateMovesByX(dance,&dance->dancers[i+1],off,i,4);
	    }
	}
      break;

      case sp_threeFaceThree:
	if ( out_at_top ) {
	    fprintf( stderr, "Out at top not supported for three face three yet.\n" );
	}
	dance->people = 3*couples;
	dance->dancers = calloc(dance->people,sizeof(Person));
	if ( dance->old_style_progression ) {
	    fillDancer(dance,0,danceRoleSex(dance,r_1s,s_left));
	    fillDancer(dance,1,danceRoleSex(dance,r_1s,s_center));
	    fillDancer(dance,2,danceRoleSex(dance,r_1s,s_right));
	    fillDancer(dance,3,danceRoleSex(dance,r_2s,s_left));
	    fillDancer(dance,4,danceRoleSex(dance,r_2s,s_center));
	    fillDancer(dance,5,danceRoleSex(dance,r_2s,s_right));
	    for ( i=2; i<couples; ++i ) {
		makeDancerWait(dance,3*i  ,r_waiting);
		makeDancerWait(dance,3*i+1,r_waiting);
		makeDancerWait(dance,3*i+2,r_waiting);
	    }
	    off=0;
	    jump = danceMinorSetSpacing(dance);
	    translateMovesByX(dance,&dance->dancers[0],off,0,6);
	    translateMovesByX(dance,&dance->dancers[1],off,0,6);
	    translateMovesByX(dance,&dance->dancers[2],off,0,6);
	    translateMovesByX(dance,&dance->dancers[3],off,0,6);
	    translateMovesByX(dance,&dance->dancers[4],off,0,6);
	    translateMovesByX(dance,&dance->dancers[5],off,0,6);
	    off = jump;
	    jump/=2;
	    for ( i=2; i<couples; ++i, off += jump ) {
		translateMovesByX(dance,&dance->dancers[3*i],off,i,6);
		translateMovesByX(dance,&dance->dancers[3*i+1],off,i,6);
		translateMovesByX(dance,&dance->dancers[3*i+2],off,i,6);
	    }
	} else {
	    for ( i=0; i<(couples&(~1)); i+=2 ) {
		fillDancer(dance,3*i  ,danceRoleSex(dance,r_1s,s_left));
		fillDancer(dance,3*i+1,danceRoleSex(dance,r_1s,s_center));
		fillDancer(dance,3*i+2,danceRoleSex(dance,r_1s,s_right));
		fillDancer(dance,3*i+3,danceRoleSex(dance,r_2s,s_left));
		fillDancer(dance,3*i+4,danceRoleSex(dance,r_2s,s_center));
		fillDancer(dance,3*i+5,danceRoleSex(dance,r_2s,s_right));
	    }
	    if ( couples&1 ) {
		/* Out at bottom */
		fillDancer(dance,3*i  ,danceRoleSex(dance,r_outAtBottom,s_left));
		fillDancer(dance,3*i+1,danceRoleSex(dance,r_outAtBottom,s_center));
		fillDancer(dance,3*i+2,danceRoleSex(dance,r_outAtBottom,s_right));
	    }
	    off=0;
	    jump = danceMinorSetSpacing(dance);
	    for ( i=0; i<dance->people; i+= 6, off+=jump ) {
		translateMovesByX(dance,&dance->dancers[i],off,i,6);
		translateMovesByX(dance,&dance->dancers[i+1],off,i,6);
		translateMovesByX(dance,&dance->dancers[i+2],off,i,6);
		if ( i+3<dance->people ) {
		    translateMovesByX(dance,&dance->dancers[i+3],off,i,6);
		    translateMovesByX(dance,&dance->dancers[i+4],off,i,6);
		    translateMovesByX(dance,&dance->dancers[i+5],off,i,6);
		}
	    }
	}
      break;
      case sp_fourFaceFour:
      case sp_tempest:
      case sp_quadrupleMinorBecket:
	if ( out_at_top ) {
	    fprintf( stderr, "Out at top not supported for four face four yet.\n" );
	}
	dance->people = 2*couples;
	dance->dancers = calloc(dance->people,sizeof(Person));
	if ( !dance->old_style_progression ) {
	    for ( i=0; i<(couples&(~3)); i+=4 ) {
		/* 1s left */
		fillDancer(dance,2*i  ,danceRoleSex(dance,r_1sleft,s_male));
		fillDancer(dance,2*i+1,danceRoleSex(dance,r_1sleft,s_female));
		/* 1s right */
		fillDancer(dance,2*i+2,danceRoleSex(dance,r_1sright,s_male));
		fillDancer(dance,2*i+3,danceRoleSex(dance,r_1sright,s_female));
		/* 2s left */
		fillDancer(dance,2*i+4,danceRoleSex(dance,r_2sleft,s_male));
		fillDancer(dance,2*i+5,danceRoleSex(dance,r_2sleft,s_female));
		/* 2s right */
		fillDancer(dance,2*i+6,danceRoleSex(dance,r_2sright,s_male));
		fillDancer(dance,2*i+7,danceRoleSex(dance,r_2sright,s_female));
	    }
	    if ( couples&2 ) {
		/* Out at bottom */
		fillDancer(dance,2*i  ,danceRoleSex(dance,r_outAtBottomLeft,s_male));
		fillDancer(dance,2*i+1,danceRoleSex(dance,r_outAtBottomLeft,s_female));
		fillDancer(dance,2*i+2,danceRoleSex(dance,r_outAtBottomRight,s_male));
		fillDancer(dance,2*i+3,danceRoleSex(dance,r_outAtBottomRight,s_female));
	    }
	    off=0;
	    jump = danceMinorSetSpacing(dance);
	    for ( i=0; i<dance->people; i+= 8, off+=jump ) {
		translateMovesByX(dance,&dance->dancers[i],off,i,8);
		translateMovesByX(dance,&dance->dancers[i+1],off,i,8);
		translateMovesByX(dance,&dance->dancers[i+2],off,i,8);
		translateMovesByX(dance,&dance->dancers[i+3],off,i,8);
		if ( i+4<dance->people ) {
		    translateMovesByX(dance,&dance->dancers[i+4],off,i,8);
		    translateMovesByX(dance,&dance->dancers[i+5],off,i,8);
		    translateMovesByX(dance,&dance->dancers[i+6],off,i,8);
		    translateMovesByX(dance,&dance->dancers[i+7],off,i,8);
		}
	    }
	} else if ( dance->formation==sp_quadrupleMinorBecket ) {
	    fprintf( stderr, "Old style progression not supported for Gary Roodman's quadruple minor becket.\n" );
exit( 1 );
	} else {
	  /* Tested for tempest, not for normal 4x4 */
	    /* 1s left */
	    i = 0;
	    fillDancer(dance,2*i  ,danceRoleSex(dance,r_1sleft,s_male));
	    fillDancer(dance,2*i+1,danceRoleSex(dance,r_1sleft,s_female));
	    /* 1s right */
	    fillDancer(dance,2*i+2,danceRoleSex(dance,r_1sright,s_male));
	    fillDancer(dance,2*i+3,danceRoleSex(dance,r_1sright,s_female));
	    /* 2s left */
	    fillDancer(dance,2*i+4,danceRoleSex(dance,r_2sleft,s_male));
	    fillDancer(dance,2*i+5,danceRoleSex(dance,r_2sleft,s_female));
	    /* 2s right */
	    fillDancer(dance,2*i+6,danceRoleSex(dance,r_2sright,s_male));
	    fillDancer(dance,2*i+7,danceRoleSex(dance,r_2sright,s_female));
	    for ( i=4; i<(couples&(~1)); i+=2 ) {
		makeDancerWait(dance,2*i  ,r_waiting_left);
		makeDancerWait(dance,2*i+1,r_waiting_left);
		makeDancerWait(dance,2*i+2,r_waiting_right);
		makeDancerWait(dance,2*i+3,r_waiting_right);
	    }
	    jump = danceMinorSetSpacing(dance);
	    off = 0;
	    i=0;
	    translateMovesByX(dance,&dance->dancers[i  ],off,i,8);
	    translateMovesByX(dance,&dance->dancers[i+1],off,i,8);
	    translateMovesByX(dance,&dance->dancers[i+2],off,i,8);
	    translateMovesByX(dance,&dance->dancers[i+3],off,i,8);
	    translateMovesByX(dance,&dance->dancers[i+4],off,i,8);
	    translateMovesByX(dance,&dance->dancers[i+5],off,i,8);
	    translateMovesByX(dance,&dance->dancers[i+6],off,i,8);
	    translateMovesByX(dance,&dance->dancers[i+7],off,i,8);
	    if ( dance->formation==sp_tempest ) {
		for ( i=0; i<4; ++i ) {
		    int fudge = i<2 ? 6 : 2;
		    dance->dancers[i].figures.moves[0].endPoint.x = dance->dancers[i+fudge].figures.moves[0].endPoint.x - jump/2;
		    dance->dancers[i].figures.moves[0].endPoint.y = dance->dancers[i+fudge].figures.moves[0].endPoint.y;
		    dance->dancers[i].figures.moves[0].degrees = dance->dancers[i+fudge].figures.moves[0].degrees;
		    dance->dancers[i].actualFigureStartPos = dance->dancers[i].figures.moves[0].endPoint;
		}
	    }
	    off += jump/2;
	    for ( i=8; i<dance->people; i+= 4, off+=jump/2 ) {
		translateMovesByX(dance,&dance->dancers[i  ],off,i,8);
		translateMovesByX(dance,&dance->dancers[i+1],off,i,8);
		translateMovesByX(dance,&dance->dancers[i+2],off,i,8);
		translateMovesByX(dance,&dance->dancers[i+3],off,i,8);
	    }
	}
      break;

      case sp_quadrupleMinor:
	sets = couples/4;
	dance->people = 2*couples;
	dance->dancers = calloc(dance->people,sizeof(Person));
	if ( out_at_top ) {
	    fprintf( stderr, "Out at top not supported for quadruple minors yet.\n" );
	}
	for ( i=0; i<sets; ++i ) {
	    /* 1s */
	    fillDancer(dance,8*i  ,danceRoleSex(dance,r_1s,0));
	    fillDancer(dance,8*i+1,danceRoleSex(dance,r_1s,1));
	    /* 2s */
	    fillDancer(dance,8*i+2,danceRoleSex(dance,r_2s,0));
	    fillDancer(dance,8*i+3,danceRoleSex(dance,r_2s,1));
	    /* 3s */
	    fillDancer(dance,8*i+4,danceRoleSex(dance,r_3s,0));
	    fillDancer(dance,8*i+5,danceRoleSex(dance,r_3s,1));
	    /* 4s */
	    fillDancer(dance,8*i+6,danceRoleSex(dance,r_4s,0));
	    fillDancer(dance,8*i+7,danceRoleSex(dance,r_4s,1));
	}
	if ( !dance->old_style_progression ) {
	    if ( couples-4*sets==1 ) {
		/* out at bottom */
		fillDancer(dance,8*i,danceRoleSex(dance,r_outAtBottom,0));
		fillDancer(dance,8*i+1,danceRoleSex(dance,r_outAtBottom,1));
	    } else if ( couples-4*sets==2 ) {
		fillDancer(dance,8*i  ,danceRoleSex(dance,r_outAtBottom1of2,0));
		fillDancer(dance,8*i+1,danceRoleSex(dance,r_outAtBottom1of2,1));
		fillDancer(dance,8*i+2,danceRoleSex(dance,r_outAtBottom2of2,0));
		fillDancer(dance,8*i+3,danceRoleSex(dance,r_outAtBottom2of2,1));
	    } else if ( couples-4*sets==3 ) {
		fillDancer(dance,8*i  ,danceRoleSex(dance,r_outAtBottom1of3,0));
		fillDancer(dance,8*i+1,danceRoleSex(dance,r_outAtBottom1of3,1));
		fillDancer(dance,8*i+2,danceRoleSex(dance,r_outAtBottom2of3,0));
		fillDancer(dance,8*i+3,danceRoleSex(dance,r_outAtBottom2of3,1));
		fillDancer(dance,8*i+4,danceRoleSex(dance,r_outAtBottom3of3,0));
		fillDancer(dance,8*i+5,danceRoleSex(dance,r_outAtBottom3of3,1));
	    }
	} else {
	    if ( couples>4 ) {
		for ( i=4*sets ; i<couples; ++i ) {
		    makeDancerWait(dance,2*i  ,r_waiting);
		    makeDancerWait(dance,2*i+1,r_waiting);
		}
	    }
	}

	off=0;
	/* Need to fiddle even with first set, in case it involves out of set */
	/* hand clasps */
	jump = danceMinorSetSpacing(dance);
	for ( i=0; i<dance->people; i+= 8, off+=jump ) {
	    translateMovesByX(dance,&dance->dancers[i],off,i,8);
	    translateMovesByX(dance,&dance->dancers[i+1],off,i,8);
	    if ( i+2<dance->people ) {
		translateMovesByX(dance,&dance->dancers[i+2],off,i,8);
		translateMovesByX(dance,&dance->dancers[i+3],off,i,8);
		if ( i+4<dance->people ) {
		    translateMovesByX(dance,&dance->dancers[i+4],off,i,8);
		    translateMovesByX(dance,&dance->dancers[i+5],off,i,8);
		    if ( i+6<dance->people ) {
			translateMovesByX(dance,&dance->dancers[i+6],off,i,8);
			translateMovesByX(dance,&dance->dancers[i+7],off,i,8);
		    }
		}
	    }
	}
      break;

      case sp_tripleMinor:
      case sp_scottishTripleMinor:
      case sp_rotatedTripleMinor:
	if ( dance->formation==sp_scottishTripleMinor || dance->old_style_progression )
	    out_at_top = 0;
	sets = (couples-out_at_top)/3;
	dance->people = 2*couples;
	dance->dancers = calloc(dance->people,sizeof(Person));
	for ( i=0; i<sets; ++i ) {
	    /* 1s */
	    fillDancer(dance,6*i  +2*out_at_top,danceRoleSex(dance,r_1s,0));
	    fillDancer(dance,6*i+1+2*out_at_top,danceRoleSex(dance,r_1s,1));
	    /* 2s */
	    fillDancer(dance,6*i+2+2*out_at_top,danceRoleSex(dance,r_2s,0));
	    fillDancer(dance,6*i+3+2*out_at_top,danceRoleSex(dance,r_2s,1));
	    /* 3s */
	    fillDancer(dance,6*i+4+2*out_at_top,danceRoleSex(dance,r_3s,0));
	    fillDancer(dance,6*i+5+2*out_at_top,danceRoleSex(dance,r_3s,1));
	}
	if ( dance->formation!=sp_scottishTripleMinor && !dance->old_style_progression /*|| dance->people%6==2 : What's this for? */ ) {
	    if ( out_at_top==1 ) {
		fillDancer(dance,0,danceRoleSex(dance,r_outAtTop,0));
		fillDancer(dance,1,danceRoleSex(dance,r_outAtTop,1));
	    } else if ( out_at_top==2 ) {
		fillDancer(dance,0,danceRoleSex(dance,r_outAtTop1of2,0));
		fillDancer(dance,1,danceRoleSex(dance,r_outAtTop1of2,1));
		fillDancer(dance,0,danceRoleSex(dance,r_outAtTop2of2,0));
		fillDancer(dance,1,danceRoleSex(dance,r_outAtTop2of2,1));
	    }
	    if ( couples-3*sets-out_at_top==1 ) {
		/* out at bottom */
		fillDancer(dance,6*i  +2*out_at_top,danceRoleSex(dance,r_outAtBottom,0));
		fillDancer(dance,6*i+1+2*out_at_top,danceRoleSex(dance,r_outAtBottom,1));
	    } else if ( couples-3*sets-out_at_top==2 ) {
		fillDancer(dance,6*i  +2*out_at_top,danceRoleSex(dance,r_outAtBottom1of2,0));
		fillDancer(dance,6*i+1+2*out_at_top,danceRoleSex(dance,r_outAtBottom1of2,1));
		fillDancer(dance,6*i+2+2*out_at_top,danceRoleSex(dance,r_outAtBottom2of2,0));
		fillDancer(dance,6*i+3+2*out_at_top,danceRoleSex(dance,r_outAtBottom2of2,1));
	    }
	} else {
	    if ( couples>3 ) {
		for ( i=3*sets ; i<couples; ++i ) {
		    makeDancerWait(dance,2*i  ,r_waiting);
		    makeDancerWait(dance,2*i+1,r_waiting);
		}
	    }
	}

	off=0;
	/* Need to fiddle even with first set, in case it involves out of set */
	/* hand clasps */
	i = 0;
	if ( out_at_top!=0 ) {
	    jump = danceCoupleSpacing(dance);
	    for ( ; i<2*out_at_top ; i+=2, off+=jump ) {
		translateMovesByX(dance,&dance->dancers[i  ],off,i,6);
		translateMovesByX(dance,&dance->dancers[i+1],off,i,6);
	    }
	}
	jump = danceMinorSetSpacing(dance);
	for ( ; i<dance->people; i+= 6, off+=jump ) {
	    translateMovesByX(dance,&dance->dancers[i],off,i,6);
	    translateMovesByX(dance,&dance->dancers[i+1],off,i,6);
	    if ( i+2<dance->people ) {
		translateMovesByX(dance,&dance->dancers[i+2],off,i,6);
		translateMovesByX(dance,&dance->dancers[i+3],off,i,6);
		if ( i+4<dance->people ) {
		    translateMovesByX(dance,&dance->dancers[i+4],off,i,6);
		    translateMovesByX(dance,&dance->dancers[i+5],off,i,6);
		}
	    }
	}
	/* Why is this needed? It is wrong for the american husband, but that's a weird dance */
	/*
	jump = danceCoupleSpacing(dance);
	off = dance->dancers[0].figures.moves[0].endPoint.x + 4*jump;
	for ( i=8; i<dance->people; i+= 2, off+=jump ) {
	    dance->dancers[i+0].figures.moves[0].endPoint.x = off;
	    dance->dancers[i+1].figures.moves[0].endPoint.x = off;
	}
	*/
      break;

	default:
	    /* call positions, not for dances */
	    assert(false);
    }
    if ( dance->formation== sp_threeFaceThree || dance->formation==sp_custom3 || dance->formation==sp_square3 || dance->formation==sp_trioCircularMonople) {
	for ( i=0; i<dance->people; ++i ) {
	    dance->dancers[i].couple_number = i/3+1;
	    dance->dancers[i].current_pos = i/3;
	}
    } else if ( dance->style!=ds_longsword ) {
	for ( i=0; i<dance->people; ++i ) {
	    dance->dancers[i].couple_number = i/2+1;
	    dance->dancers[i].current_pos = i/2;
	}
    } else {
	for ( i=0; i<dance->people; ++i ) {
	    dance->dancers[i].couple_number = i+1;
	    dance->dancers[i].current_pos = i;
	}
    }
    /*dance->current_part = 0;*/
    dance->start_first_minor_set = 0;

    if ( dance->sicilian )
	danceMakeSicilian(dance,couples);
    danceOutputDebugFigure("refuf.dance",dance);

    if ( dance->choreo_cnt!=0 ) {
	for ( i=0; i<dance->choreo_cnt; ++i )
	    dance->sequence[i].figure->dancers = dance->dancers;
    }
}

/* Both outness and levitation use the same data structures */
static void personFigureValueChanges(FigureSegment *cs,int off, struct valPoints *pos, ValChange *changes) {

    if ( off>cs->millibars )
	off = cs->millibars;
    if ( changes!=NULL ) {
	short start = pos->end_of_last_move;
	short when = 0;
	int i;
	for ( i=0; changes[i].millibars!=-1 && off>changes[i].millibars; ++i ) {
	    start = changes[i].value;
	    when = changes[i].millibars;
	}
	if ( changes[i].millibars==-1 )
	    pos->now = start;
	else if ( changes[i].millibars==when )
	    pos->now = (start+changes[i].value)/2;
	else {
	    pos->now = start + (changes[i].value-start) * (off-when)/(changes[i].millibars-when);
	}
    }

    if ( off>=cs->millibars )
	pos->end_of_last_move = pos->now;
}

static void personFigureRThetaChanges(FigureSegment *cs,int off, struct rThetaPoints *pos, RThetaChange *changes) {

    if ( off>cs->millibars )
	off = cs->millibars;
    if ( changes!=NULL ) {
	RTheta *start = &pos->end_of_last_move;
	short when = 0;
	int i;
	for ( i=0; changes[i].millibars!=-1 && off>changes[i].millibars; ++i ) {
	    start = &changes[i].pos;
	    when =   changes[i].millibars;
	}
	if ( changes[i].millibars==-1 )
	    pos->now = *start;
/* I don't think this can happen except as two consecutive fields with the same time value */
/*  which would be an error */
	else if ( changes[i].millibars==when ) {
	    pos->now.r     = (start->r+changes[i].pos.r)/2;
	    pos->now.theta = (start->theta+changes[i].pos.theta)/2;
	} else {
	    /* r changes as you'd expect */
	    pos->now.r = start->r + (changes[i].pos.r-start->r) * (off-when)/(changes[i].millibars-when);
	    /* theta we need to worry about wrap around... */
	    float start_theta = start->theta, end_theta = changes[i].pos.theta;
	    while ( end_theta-start_theta >= 180 )
		end_theta -= 360;
	    while ( end_theta-start_theta < -180 )
		end_theta += 360;
	    pos->now.theta = start_theta + (end_theta-start_theta) * (off-when)/(changes[i].millibars-when);
	    if ( pos->now.theta<-180 )
		pos->now.theta += 360;
	    if ( pos->now.theta>180 )
		pos->now.theta -= 360;
	}
    }

    if ( off>=cs->millibars )
	pos->end_of_last_move = pos->now;
}

static double dancerFigureRotation(Dance *dance, Person *dancer,FigureSegment *cs,double frac) {
    double now_orientation;
    double deg_off;

    switch ( cs->orient ) {
      case mo_fixed:
	/* Does not change, ever */;
	now_orientation = dancer->now_orientation;
      break;
      case mo_rotating:
	  /* This is rotation relative to the current orientation */
	now_orientation = dancer->orientation_start_of_current +
		frac*cs->degrees;
      break;
      case mo_rotateto:
      case mo_cw_rotateto:
      case mo_ccw_rotateto:
	  /* This is rotation to an absolute orientation */
	{ float diff1, begin, final_orientation;
	    if ( cs->degrees!=DEGREES_END )
		final_orientation = cs->degrees;
	    else if ( cs->cmd==c_lineto )
		final_orientation = 180/PI * atan2(cs->splines[1].c,cs->splines[0].c)-90;
	    else if ( cs->cmd==c_curveto )
		final_orientation = 180/PI * atan2(cs->endPoint.y-cs->cp2.y,cs->endPoint.x-cs->cp2.x)-90;

	    final_orientation = fmod(final_orientation,360);
	    if ( cs->orient==mo_cw_rotateto ) {
		begin = fmod(dancer->orientation_start_of_current,360);
		if ( begin<final_orientation )
		    begin+=360;
		now_orientation = (1-frac) * begin +
			frac*final_orientation;
	    } else if ( cs->orient==mo_ccw_rotateto ) {
		begin = fmod(dancer->orientation_start_of_current,360);
		if ( begin>final_orientation )
		    final_orientation += 360;
		now_orientation = (1-frac) * begin +
			frac*final_orientation;
	    } else {
		diff1 = final_orientation-dancer->orientation_start_of_current;
#ifdef DEBUG
		if ( dance!=NULL ) {
		    if ( !cs->complained_about_rotation && cs->orient==mo_rotateto ) { float d=diff1;
			while ( d<0 ) d+= 360;
			while ( d>360 ) d-= 360;
			if ( d>178 && d<182 ) {
			    cs->complained_about_rotation = true;
			    if ( cs->copy_lineno!=0 )
				fprintf( stderr, "%s:%d (copied from %d): Rotation at or near 180 degrees in rotateto command. Likely to turn the wrong way. %s\n",
					dance->name, cs->copy_lineno, cs->lineno, dance->current==NULL ? "" : dance->current->callName );
			    else
				fprintf( stderr, "%s:%d: Rotation at or near 180 degrees in rotateto command. Likely to turn the wrong way. %s\n",
					dance->name, cs->lineno, dance->current==NULL ? "" : dance->current->callName );
			}
		    }
		}
#endif
/* !!!!! more work needed for cw_rotateto */
		if ( diff1>180 )
		    now_orientation = (1-frac) * (360+dancer->orientation_start_of_current) +
			    frac*final_orientation;
		else if ( diff1<-180 )
		    now_orientation = (1-frac) * dancer->orientation_start_of_current +
			    frac*(360+final_orientation);
		else
		    now_orientation = (1-frac) * dancer->orientation_start_of_current +
			    frac*final_orientation;
	    }
	    now_orientation= fmod(now_orientation,360);
	}
      break;
      case mo_forward:
      case mo_backward:
      case mo_forward90:
      case mo_forward_90:
        if ( cs->orient==mo_forward )
	    deg_off = -90;
	else if ( cs->orient==mo_forward90 )
	    deg_off = 0;
	else if ( cs->orient==mo_backward )
	    deg_off = 90;
	else
	    deg_off = 180;
        if ( cs->cmd==c_lineto ) {
	    now_orientation = deg_off +180.0/PI * atan2(cs->splines[1].c,cs->splines[0].c);
	} else if ( cs->cmd==c_curveto ) {
		now_orientation = deg_off +180.0/PI *
			atan2((3*cs->splines[1].a*frac+2*cs->splines[1].b)*frac+cs->splines[1].c,
			      (3*cs->splines[0].a*frac+2*cs->splines[0].b)*frac+cs->splines[0].c);
	} else {
	    /* this direction makes no sense unless the dancer is moving */
	    now_orientation = dancer->now_orientation;
	}
	while ( now_orientation < 0 )
	    now_orientation += 360;
	while ( now_orientation > 360 )
	    now_orientation -= 360;
      break;
      case mo_faceDancer:
        if ( cs->faceDancer >=0 && cs->faceDancer<=dance->people ) {
	    /* Small bug here we might be looking at where the other dancer is now, or where the dancer was last frame!!!! */
	    /* We now do a fixup pass later, but we still need this here, because */
	    /*  if this call finishes this cs and the next cs has a rotateto */
	    /*  we need the best approximation we can get to where we are facing */
	    Person *other = &dance->dancers[cs->faceDancer];
	    if ( other!=dancer )
		now_orientation = -90 + 180.0/PI*atan2(other->now.y-dancer->now.y,other->now.x-dancer->now.x);
	}
    }
    if ( now_orientation>=360 )
	now_orientation -= 360;
    else if ( now_orientation<0 )
	now_orientation += 360;
return( now_orientation );
}

static void personNextFrame(Dance *dance,Person *dancer,int f, int frames_per_bar) {
    FigureSegment *cs = dancer->current;
    int off = (f*MILLIBARS_MUL)/frames_per_bar - dancer->millibars_start_of_current;
    double efrac = off / (double) cs->millibars;
    double frac = efrac;

    if ( frac>1 )
	frac = 1;

    if ( cs->drop_right_millibars<=off && !dancer->dropped_right_in_current ) {
	dancer->now_hand_right = 0;
	dancer->dropped_right_in_current = true;
    }
    if ( cs->drop_left_millibars<=off && !dancer->dropped_left_in_current ) {
	dancer->now_hand_left  = 0;
	dancer->now_left_hand_point = -1;
	dancer->dropped_left_in_current = true;
    }
    if ( cs->join_right_millibars<=off && !dancer->joined_right_in_current ) {
	if ( cs->join_right_hand!=0 ) {
	    dancer->join_right_without_drop = dancer->now_hand_right;	/* Only used for verify, provides the previous state */
	    dancer->now_hand_right = cs->join_right_hand;
	    if ( (dancer->now_hand_right&HAND_INDIVIDUAL_MASK)==HAND_STAR ) {
		dancer->now_star_center.x = cs->star_center.x;
		dancer->now_star_center.y = cs->star_center.y;
	    } else if ( (dancer->now_hand_right&HAND_INDIVIDUAL_MASK)>=dance->people )
		dancer->now_hand_right = 0;
	    dancer->joined_right_in_current = true;
	}
    }
    if ( cs->join_left_millibars<=off && !dancer->joined_left_in_current ) {
	if ( cs->join_left_hand!=0 ) {
	    dancer->join_left_without_drop = dancer->now_hand_left;	/* Only used for verify, provides the previous state */
	    dancer->now_hand_left = cs->join_left_hand;
	    if ( (dancer->now_hand_left&HAND_INDIVIDUAL_MASK)==HAND_STAR ) {
		dancer->now_star_center.x = cs->star_center.x;
		dancer->now_star_center.y = cs->star_center.y;
	    } else if ( (dancer->now_hand_left&HAND_INDIVIDUAL_MASK)>=dance->people )
		dancer->now_hand_left = 0;
	    dancer->joined_left_in_current = true;
	} else if ( dance->style==ds_longsword && cs->join_left_to_point!=-1 )
	    dancer->now_left_hand_point = cs->join_left_to_point;
    }

    if ( cs->start_honour>=cs->end_honour || off<=cs->start_honour || off>=cs->end_honour )
	dancer->now_honour = 0;
    else if ( off<(cs->start_honour+cs->end_honour)/2 )
	dancer->now_honour = 2*(off-cs->start_honour)/(double)(cs->end_honour-cs->start_honour);
    else
	dancer->now_honour = 2*(cs->end_honour-off)/(double)(cs->end_honour-cs->start_honour);

#ifdef DEBUG
    if ( !cs->checked_rotation_continuous ) {
	double newo = dancerFigureRotation(dance,dancer,cs,0), oldo;
	cs->checked_rotation_continuous = 1;
	if ( cs->orient!=mo_faceDancer )
	    assert( dancer->orientation_start_of_current == dancer->now_orientation );
	newo = fmod( newo,360 );
	oldo = fmod( dancer->now_orientation,360 );
	if ( newo<0 ) newo += 360;
	if ( oldo<0 ) oldo += 360;
	if (( newo>=oldo-2 && newo<=oldo+2 ) ||
	    ( newo+360 <= oldo+2 ) ||
	    ( newo >= oldo+360-2 ) )
	    /* Looks good */;
	else if ( dance->sicilian &&
	    (( newo>=oldo-5 && newo<=oldo+5 ) ||
		( newo+360 <= oldo+5 ) ||
		( newo >= oldo+360-5 ) ))
	    /* We get more rounding errors in sicilian dances */;
	else {
	    if ( cs->orient != mo_faceDancer ) {
		if ( cs->copy_lineno!=0 )
		    fprintf( stderr, "@%s:%d (copied from %d): Discontinuous orientation: %.1f|%.1f  %s %s\n",
			dance->name, cs->copy_lineno, cs->lineno, oldo, newo,
			dance->current==NULL ? "" : dance->current->callName,
			cs->orient==mo_faceDancer ? "~but this involves a faceDancer where we might not know accurately where the other dancer is." : "." );
		else
		    fprintf( stderr, "@%s:%d: Discontinuous orientation: %.1f|%.1f  %s %s\n",
			dance->name, cs->lineno, oldo, newo,
			dance->current==NULL ? "" : dance->current->callName,
			cs->orient==mo_faceDancer ? "~but this involves a faceDancer where we might not know accurately where the other dancer is." : "." );
	    }
	}
    }
#endif
    dancer->now_orientation = dancerFigureRotation(dance,dancer,cs,frac);

    switch ( cs->cmd ) {
      case c_lineto:
	dancer->now.x = cs->splines[0].c*frac + cs->splines[0].d;
	dancer->now.y = cs->splines[1].c*frac + cs->splines[1].d;
      break;
      case c_curveto:
	dancer->now.x = ((cs->splines[0].a*frac+cs->splines[0].b)*frac+cs->splines[0].c)*frac + cs->splines[0].d;
	dancer->now.y = ((cs->splines[1].a*frac+cs->splines[1].b)*frac+cs->splines[1].c)*frac + cs->splines[1].d;
      break;
      case c_pause:
	/* Don't move */
      break;
      case c_resetDance:
      case c_end:
	if ( dance->choreo_cnt!=0 && dance->choreo_pos>0 )
	    fprintf( stderr, "Dancers probably have call sequences with a different number of bars, one (%d) has ended, another has not (or 'end/resetDance' in unexpected spot) in %s.\n", (int) (dancer-dance->dancers), dance->sequence[dance->choreo_pos-1].figure->name );
	else
	    fprintf( stderr, "Dancers probably have call sequences with a different number of bars, one (%d) has ended, another has not (or 'end/resetDance' in unexpected spot).\n", (int) (dancer-dance->dancers) );
exit(1);
      case c_moveto:
      default:
        fprintf( stderr, "frame=%d\n", f );
	fprintf( stderr, ":%d Bad cmd=%d %s\n", cs->lineno, cs->cmd, (cs->cmd>=0 && cs->cmd<=c_copy)?commandNames[cs->cmd]:"???" );
	fprintf( stderr, "Couple=%d, sex=%d\n", dancer->couple_number, dancer->sex );
	if ( cs->lineno==0 ) {
	    fprintf( stderr, "Next line no=%d\n", cs[1].lineno );
	    fprintf( stderr, "prev line no=%d\n", cs[-1].lineno );
	}
	assert(false);
    }
    personFigureValueChanges(cs,off,&dancer->levitation,cs->levitation);
    personFigureValueChanges(cs,off,&dancer->outness,cs->outness);

    personFigureRThetaChanges(cs,off,&dancer->rightHand,cs->rightHand);
    personFigureRThetaChanges(cs,off,&dancer->swordPoint,cs->swordPoint);
    personFigureRThetaChanges(cs,off,&dancer->leftHand,cs->leftHand);

    if ( efrac>=1 ) {
	dancer->orientation_start_of_current = dancer->now_orientation;
	dancer->millibars_start_of_current += cs->millibars;
	dancer->dropped_left_in_current = 0;
	dancer->dropped_right_in_current = 0;
	dancer->joined_left_in_current = 0;
	dancer->joined_right_in_current = 0;
	++dancer->current;
#ifdef DEBUG
	dancer->current->checked_rotation_continuous = 0;
#endif
	if ( dancer->current->cmd==c_lineto || dancer->current->cmd==c_curveto )
	    splineMake(dancer->current,&dancer->now);
	if ( efrac>1 )
	    personNextFrame(dance,dancer,f,frames_per_bar);
    }
}

static void personFixupFacing(Dance *dance,Person *dancer) {
    FigureSegment *cs = dancer->current;
    if ( cs->orient == mo_faceDancer ) {
	Person *other = &dance->dancers[cs->faceDancer];
	if ( other!=dancer )
	    dancer->now_orientation = -90 + 180.0/PI*atan2(other->now.y-dancer->now.y,other->now.x-dancer->now.x);
    }
}

CallList *danceCallNext(Dance *dance) {
    int mask = (1<<dance->current_part);
    if ( dance->last_minor_set )
	mask |= LAST_MASK;
    else
	mask |= NOTLAST_MASK;
    if ( dance->first_minor_set )
	mask |= FIRST_MASK;
    else
	mask |= NOTFIRST_MASK;
    do {
	++dance->current;
    } while ( dance->current<dance->calls+dance->call_cnt &&
	    (dance->current->part_mask & mask )==0 );
    if ( dance->current>=dance->calls+dance->call_cnt )
	dance->current = NULL;
return( dance->current );
}

static void callNextFrame(Dance *dance,int f, int frames_per_bar) {
    if ( dance->current!=NULL ) {
	int off = f*MILLIBARS_MUL/frames_per_bar - dance->millibars_start_of_current;
	if ( off>=dance->current->millibars ) {
	    CallList *old = dance->current;
	    danceCallNext(dance);
	    dance->millibars_start_of_current += old->millibars;
	}
	if ( dance->current==NULL || off<=dance->current->honour_start ||
		off >= dance->current->honour_end )
	    dance->honour = 0;
	else if ( off<(dance->current->honour_start+dance->current->honour_end)/2 )
	    dance->honour = 2*(off-dance->current->honour_start)/(double) (dance->current->honour_end-dance->current->honour_start);
	else
	    dance->honour = 2*(dance->current->honour_end-off)/(double) (dance->current->honour_end-dance->current->honour_start);
    }
}

static void bbNextFrame(Dance *dance,int f, int frames_per_bar) {
    if ( dance->currentBB!=NULL ) {
	int off = f*MILLIBARS_MUL/frames_per_bar - dance->millibars_start_of_bbcurrent;
	while ( dance->currentBB!=NULL && off>=dance->currentBB->millibars ) {
	    BBList *old = dance->currentBB;
	    dance->currentBB = dance->currentBB->next;
	    dance->millibars_start_of_bbcurrent += old->millibars;
	    dance->bbStartOfCurrent = old->bb;
	    if ( dance->currentBB!=NULL ) {
		if ( dance->currentBB->fixed )
		    dance->currentBB->bb = old->bb;
		else if ( dance->currentBB->automatic )
		    danceFindCurrentBB(dance,&dance->currentBB->bb);
	    }
	    off -= old->millibars;
	}
    }
}

/* Returns true each time we finish a minor set */
enum dancecondition danceNextFrame(Dance *dance,int f, int frames_per_bar) {
    int i;

    if ( f==0 ) {
	for ( i=0; i<dance->people; ++i ) {
	    Person *p = &dance->dancers[i];
	    FigureSegment *cs = &p->figures.moves[0];
	    if ( cs!=NULL && cs->cmd!=c_moveto )
		printf( "Lineno: %d\n", cs->lineno );
	    assert( cs!=NULL && cs->cmd == c_moveto );
	    p->current = &cs[1];
	    splineMake(p->current,&cs->endPoint);
	    p->millibars_start_of_current = 0;
	    p->orientation_start_of_current = p->now_orientation = cs->degrees;
	    p->now = cs->endPoint;
	    p->now_hand_right = cs->join_right_hand; 
	    p->now_hand_left  = cs->join_left_hand; 
	    p->dropped_left_in_current = 0;
	    p->dropped_right_in_current = 0;
	    p->joined_left_in_current = 0;
	    p->joined_right_in_current = 0;
	    if ( dance->style==ds_longsword ) {
		if ( cs->join_left_to_point != -1 )
		    p->now_left_hand_point = cs->join_left_to_point;
		if ( cs->rightHand!=NULL && cs->rightHand->millibars!=-1 )
		    p->rightHand.now = cs->rightHand->pos;
		if ( cs->swordPoint!=NULL && cs->swordPoint->millibars!=-1 )
		    p->swordPoint.now = cs->swordPoint->pos;
		if ( cs->leftHand!=NULL && cs->leftHand->millibars!=-1 )
		    p->leftHand.now = cs->leftHand->pos;
	    }
	}
	if ( dance->calls!=NULL ) {
	    dance->current = danceFindFirstCallInCurrentPart(dance->calls,dance->call_cnt,(1<<dance->current_part) | FIRST_MASK );
	    dance->millibars_start_of_current = 0;
	}
	if ( dance->bbs!=NULL ) {
	    dance->currentBB = dance->bbs;
	    dance->millibars_start_of_bbcurrent = 0;
	    if ( dance->currentBB->automatic )
		danceFindCurrentBB(dance,&dance->currentBB->bb);
	    dance->bbStartOfCurrent = dance->currentBB->bb;
	}
return( dc_continue );
    } else if ( dance->dancers[0].current->cmd == c_resetDance )
	/* All other dancers had better be at a reset */
	danceReset(dance,f,frames_per_bar);

    callNextFrame(dance,f,frames_per_bar);
    bbNextFrame(dance,f,frames_per_bar);
    for ( i=0; i<dance->people; ++i )
	personNextFrame(dance,&dance->dancers[i],f, frames_per_bar);
    for ( i=0; i<dance->people; ++i )
	personFixupFacing(dance,&dance->dancers[i]);

#if 0
  printf( "\nFrame: %d %.2f\n", f, f/(double) frames_per_bar );
  if ( dance->current!=NULL && dance->current->start_cnt==f )
   printf( "%s\n", dance->current->callName );
  for ( i=0; i<dance->people; ++i )
   printf( " %d: %.0f,%.0f\n", i, dance->dancers[i].now.x, dance->dancers[i].now.y );
#endif

    if ( dance->dancers[0].current->cmd == c_end )
return( dc_finished );

return( dance->dancers[0].current->cmd == c_resetDance ? dc_minorSetEnded : dc_continue );
}

void danceCleanup(Dance *dance) {
    int i;

    for ( i=0; i<dance->people; ++i )
	peopleFreeContents(&dance->dancers[i]);
    free(dance->dancers);
    dance->people = 0;
    dance->dancers = NULL;
}

static void _danceFindBB(Dance *dance, BB *bb, int max) {
    int i, first= true;
    Person *p, *top;
    enum role outAtTops[] = { r_outAtTop, r_outAtTop1of2, r_outAtTop2of2, r_outAtTopLeft, r_outAtTopRight, 0 };
    int j;
    int topx, basex;
    int maxActiveX=0, maxActiveXStart=0, maxAnyXStart=0;

    if ( dance->choreo_cnt!=0 ) {
	_danceFindBB(dance->sequence[0].figure,bb,max);
	for ( j=1; j<dance->choreo_cnt; ++j ) {
	    BB tempbb;
	    _danceFindBB(dance->sequence[j].figure,&tempbb,max);
	    if ( tempbb.minx < bb->minx )
		bb->minx = tempbb.minx;
	    if ( tempbb.miny < bb->miny )
		bb->miny = tempbb.miny;
	    if ( tempbb.maxx > bb->maxx )
		bb->maxx = tempbb.maxx;
	    if ( tempbb.maxy > bb->maxy )
		bb->maxy = tempbb.maxy;
	}
return;
    }

    if ( dance->dancers!=NULL ) {
	p = dance->dancers;
	top = p + max;
    } else {
	p = dance->roles;
	top = p + dance->role_cnt;
    }

    if ( strcmp(dance->name,"40 Years of Penguin Pam")==0 && max==dance->people ) {
	/* This quintuple progression dance needs a special case */
	for ( ; p<top ; ++p ) {
	    for ( i=0; i<1; ++i ) {
		FigureSegment *cs = &p->figures.moves[i];
		if ( cs->cmd==c_moveto || cs->cmd==c_lineto || cs->cmd==c_curveto ) {
		    if ( first ) {
			bb->minx = bb->maxx = cs->endPoint.x;
			bb->miny = bb->maxy = cs->endPoint.y;
			first = false;
		    } else {
			if ( bb->minx>cs->endPoint.x )
			    bb->minx = cs->endPoint.x;
			if ( bb->maxx<cs->endPoint.x )
			    bb->maxx = cs->endPoint.x;
			if ( bb->miny>cs->endPoint.y )
			    bb->miny = cs->endPoint.y;
			if ( bb->maxy<cs->endPoint.y )
			    bb->maxy = cs->endPoint.y;
		    }
		}
	    }
	}
	bb->minx -= 256;
	if ( dance->people%4==0 )
	    bb->maxx += 256;
return;
    }

/* Bug! this only finds the bb for the first time through the dance */
/*  So we never have a couple out at the top. When we do have a couple out */
/*  (especially in a 4 face 4 dance) we may lose some of their behavior */
/* So I've now added something that checks the out at tops */
/* Still might have problems with complicated out at bottoms */
    for ( ; p<top ; ++p ) {
	for ( i=0; i<p->figures.move_cnt; ++i ) {
	    FigureSegment *cs = &p->figures.moves[i];
	    if ( cs->cmd==c_moveto && cs->endPoint.x>maxAnyXStart )
		maxAnyXStart = cs->endPoint.x;
	    if ( cs->cmd==c_moveto || cs->cmd==c_lineto || cs->cmd==c_curveto ) {
		if ( first ) {
		    bb->minx = bb->maxx = cs->endPoint.x;
		    bb->miny = bb->maxy = cs->endPoint.y;
		    first = false;
		} else {
		    if ( bb->minx>cs->endPoint.x )
			bb->minx = cs->endPoint.x;
		    if ( bb->maxx<cs->endPoint.x )
			bb->maxx = cs->endPoint.x;
		    if ( bb->miny>cs->endPoint.y )
			bb->miny = cs->endPoint.y;
		    if ( bb->maxy<cs->endPoint.y )
			bb->maxy = cs->endPoint.y;
		    if ( p->effective_role<r_outAtTop && cs->endPoint.x> maxActiveX ) {
			maxActiveX = cs->endPoint.x;
			maxActiveXStart = p->figures.moves[0].endPoint.x;
		    }
		}
		if ( cs->cmd==c_curveto ) {
		    if ( bb->minx>cs->cp1.x )
			bb->minx = cs->cp1.x;
		    if ( bb->minx>cs->cp2.x )
			bb->minx = cs->cp2.x;
		    if ( bb->maxx<cs->cp1.x )
			bb->maxx = cs->cp1.x;
		    if ( bb->maxx<cs->cp2.x )
			bb->maxx = cs->cp2.x;

		    if ( bb->miny>cs->cp1.y )
			bb->miny = cs->cp1.y;
		    if ( bb->miny>cs->cp2.y )
			bb->miny = cs->cp2.y;
		    if ( bb->maxy<cs->cp1.y )
			bb->maxy = cs->cp1.y;
		    if ( bb->maxy<cs->cp2.y )
			bb->maxy = cs->cp2.y;
		}
	    }
	}
    }
    /* now we've found where the centers of people go, but they have width */
    /* so add a bit of fudge to the min/max */
    bb->minx -= 40; bb->miny -= 60; bb->maxx += 40; bb->maxy += 60;

    if ( max==dance->people ) {
	/* This adds the distances any couple goes out the end of the set to */
	/*  the starting location of the last dancer in the thought that at */
	/*  some point someone in the last dancer's position might go that far */
	int checkX = maxActiveX-maxActiveXStart + maxAnyXStart;
	if ( checkX > bb->maxx ) {
	    /* bb->maxx = checkX; */
	    /* Mmm that didn't work well for scottish triples */
	    if ( dance->formation==sp_tripleMinor )
		bb->maxx += 2*danceCoupleSpacing(dance);
	    else if ( dance->formation>=sp_dupleMinor ||
		    dance->formation==sp_scottishDupleMinor ||
		    dance->formation==sp_scottishTripleMinor )
		bb->maxx += danceCoupleSpacing(dance);
	}
	/* Makes room for the big 4 couple circle at the end of some scottish dances */
	if ( dance->style == ds_scottish && danceHasLastCondition(dance)) {
	    if ( bb->maxy<600 ) bb->maxy = 600;
	    if ( bb->miny>-180 ) bb->miny = -180;
	}
    }
    if ( dance->dancers!=NULL && max==dance->people && dance->dancers[1].figures.moves!=NULL && dance->dancers[1].figures.moves[0].cmd==c_moveto ) {
	/* I want the x location where the first couple starts */
	/*  if we are becket then I want the location of the first woman or the second man */
	/* first woman should always be right */
	basex = dance->dancers[1].figures.moves[0].endPoint.x;
	for ( j=0; outAtTops[j]!=0; ++j ) {
	    int s;
	    for ( s=0; s<2; ++s ) {
		p = danceFindRole(dance,outAtTops[j],s);
		if ( p!=NULL && p->figures.moves!=NULL ) {
		    topx = p->figures.moves[0].endPoint.x;
		    for ( i=0; i<p->figures.move_cnt; ++i ) {
			FigureSegment *cs = &p->figures.moves[i];
			if ( cs->cmd==c_moveto || cs->cmd==c_lineto || cs->cmd==c_curveto ) {
			    if ( first ) {
				bb->minx = bb->maxx = cs->endPoint.x - topx + basex;
				bb->miny = bb->maxy = cs->endPoint.y;
				first = false;
			    } else {
				if ( bb->minx>cs->endPoint.x - topx + basex )
				    bb->minx = cs->endPoint.x - topx + basex;
				if ( bb->maxx<cs->endPoint.x - topx + basex )
				    bb->maxx = cs->endPoint.x - topx + basex;
				if ( bb->miny>cs->endPoint.y )
				    bb->miny = cs->endPoint.y;
				if ( bb->maxy<cs->endPoint.y )
				    bb->maxy = cs->endPoint.y;
			    }
			}
		    }
		}
	    }
	}
    }

    if ( strcmp(dance->name,"String of Swings")==0 ) {
	if ( max==dance->people ) {
	    bb->minx -= 256;
	} else {
	    bb->maxx += 512;
	}
    }

    if ( first ) {
	bb->minx = bb->miny = 0;
	bb->maxx = bb->maxy = dance->units;
    } else {
#if 0
	chunk = dance->units/8;
	if ( bb->minx>0 )
	    bb->minx = chunk*(bb->minx/chunk);
	/*else */
	/*    bb->minx = chunk*((bb->minx-chunk+1)/chunk); */
	if ( bb->miny>0 )
	    bb->miny = chunk*(bb->miny/chunk);
	/*else*/
	/*    bb->miny = chunk*((bb->miny-chunk+1)/chunk);*/
	chunk = dance->units/8;
	bb->maxx = chunk * ((bb->maxx+chunk-1)/chunk);
	bb->maxy = chunk * ((bb->maxy+chunk-1)/chunk);
#endif
    }
}

void danceFindBB(Dance *dance, BB *bb) {
    if ( dance->dancers!=NULL ) {
	_danceFindBB(dance,bb,dance->people);
    } else {
	_danceFindBB(dance,bb,dance->role_cnt);
    }
}

void danceFindMinorSetBB(Dance *dance, BB *bb) {
    _danceFindBB(dance,bb,danceMinorSetSize(dance));
}

void danceFindCurrentBB(Dance *dance, BB *bb) {
    int first= true;
    Person *p, *top, *holdp;
    int chunk;

    if ( dance->dancers!=NULL ) {
	p = dance->dancers;
	top = p + dance->people;
    } else {
	p = dance->roles;
	top = p + dance->role_cnt;
    }
    holdp = p;

    for ( ; p<top ; ++p ) {
	if ( first ) {
	    bb->minx = bb->maxx = p->now.x;
	    bb->miny = bb->maxy = p->now.y;
	    first = false;
	} else {
	    if ( bb->minx>p->now.x )
		bb->minx = p->now.x;
	    if ( bb->maxx<p->now.x )
		bb->maxx = p->now.x;
	    if ( bb->miny>p->now.y )
		bb->miny = p->now.y;
	    if ( bb->maxy<p->now.y )
		bb->maxy = p->now.y;
	}
    }

    if ( !first && bb->minx==0 && bb->maxx==0 && bb->miny==0 && bb->maxy==0 ) {
	/* p->now has not been initialized, call happens too early */
	/*  so use the moveto location */
	first = true;
	for ( p=holdp ; p<top ; ++p ) {
	    FigureSegment *cs = &p->figures.moves[0];
	    if ( first ) {
		bb->minx = bb->maxx = cs->endPoint.x;
		bb->miny = bb->maxy = cs->endPoint.y;
		first = false;
	    } else {
		if ( bb->minx>cs->endPoint.x )
		    bb->minx = cs->endPoint.x;
		if ( bb->maxx<cs->endPoint.x )
		    bb->maxx = cs->endPoint.x;
		if ( bb->miny>cs->endPoint.y )
		    bb->miny = cs->endPoint.y;
		if ( bb->maxy<cs->endPoint.y )
		    bb->maxy = cs->endPoint.y;
	    }
	}
    }

    if ( first ) {
	bb->minx = bb->miny = 0;
	bb->maxx = bb->maxy = dance->units;
    } else {
	chunk = dance->units/4;
	if ( bb->minx>0 )
	    bb->minx = chunk*(bb->minx/chunk);
	/*else */
	/*    bb->minx = chunk*((bb->minx-chunk+1)/chunk); */
	if ( bb->miny>0 )
	    bb->miny = chunk*(bb->miny/chunk);
	/*else*/
	/*    bb->miny = chunk*((bb->miny-chunk+1)/chunk);*/
	chunk = dance->units/4;
	bb->maxx = chunk * ((bb->maxx+chunk-1)/chunk);
	bb->maxy = chunk * ((bb->maxy+chunk-1)/chunk);
    }
}
