Exemple #1
0
 public override Path performOne(Dancer d, CallContext ctx)
 {
     if (d.data.leader)
     {
         //  Find another active dancer in the same line and move to that spot
         Dancer d2 = ctx.dancerClosest(d, dx => dx.data.active &&
                                       (CallContext.isRight(d)(dx) || CallContext.isLeft(d)(dx)));
         if (d2 != null)
         {
             double dist = CallContext.distance(d, d2);
             return(TamUtils.getMove(CallContext.isRight(d)(d2) ? "Run Right" : "Run Left")
                    .scale(dist / 3, dist / 2).changebeats(4.0));
         }
     }
     else if (d.data.trailer)
     {
         //  Looking at active leader?  Then take its place
         //  TODO maybe allow diagonal circulate?
         Dancer d2 = ctx.dancerInFront(d);
         if (d2 != null && d2.data.active)
         {
             double dist = CallContext.distance(d, d2);
             return(TamUtils.getMove("Forward").scale(dist, 1.0).changebeats(4.0));
         }
     }
     throw new CallError("Cannot figure out how to Circulate.");
 }
Exemple #2
0
 public override Path performOne(Dancer d, CallContext ctx)
 {
     if (d.data.leader)
     {
         var d2 = ctx.dancerInBack(d);
         if (d2 == null || !d2.data.active)
         {
             throw new CallError($"Trailer of {d} must also Zoom");
         }
         var a    = CallContext.angle(d);
         var c    = a < 0 ? "Run Left" : "Run Right";
         var dist = CallContext.distance(d, d2);
         return(TamUtils.getMove(c).changebeats(2).skew(-dist / 2, 0)
                .add(TamUtils.getMove(c).changebeats(2).skew(dist / 2, 0)));
     }
     else if (d.data.trailer)
     {
         var d2 = ctx.dancerInFront(d);
         if (d2 == null || !d2.data.active)
         {
             throw new CallError($"Leader of {d} must also Zoom");
         }
         var dist = CallContext.distance(d, d2);
         return(TamUtils.getMove("Forward").changebeats(4).scale(dist, 1));
     }
     else
     {
         throw new CallError($"Dancer {d} cannot Zoom");
     }
 }
Exemple #3
0
        public override Path performOne(Dancer d, CallContext ctx)
        {
            //  Find the dancer to hinge with
            Dancer d2 = null;
            var    d3 = ctx.dancerToRight(d);
            var    d4 = ctx.dancerToLeft(d);
            var    d0 = d.data.partner;

            if (d0 != null && d0.data.active)
            {
                d2 = d0;
            }
            else if (d3 != null & d3.data.active)
            {
                d2 = d3;
            }
            else if (d4 != null && d4.data.active)
            {
                d2 = d4;
            }
            if (d2 == null)
            {
                throw new CallError($"Dancer {d.number} cannot Hinge");
            }
            var m = CallContext.isRight(d)(d2) ? "Hinge Right" : "Hinge Left";

            return(TamUtils.getMove(m));
        }
        public override Path performOne(Dancer d, CallContext ctx)
        {
            var offsetX = 0.0;
            var move    = select(ctx, d);

            //  If leader or trailer, make sure to adjust quarter turn
            //  so handhold is possible
            if (move != "Stand")
            {
                if (d.data.leader)
                {
                    var d2   = ctx.dancerInBack(d);
                    var dist = CallContext.distance(d, d2);
                    if (dist > 2)
                    {
                        offsetX = -(dist - 2) / 2;
                    }
                }
                if (d.data.trailer)
                {
                    var d2   = ctx.dancerInFront(d);
                    var dist = CallContext.distance(d, d2);
                    if (dist > 2)
                    {
                        offsetX = (dist - 2) / 2;
                    }
                }
            }
            return(TamUtils.getMove(move).skew(offsetX, 0.0));
        }
 public override void perform(CallContext ctx, int i)
 {
     ctx.levelBeats();
     ctx.dancers.ForEach(d => {
         if (d.data.active)
         {
             //  Active dancers spread apart
             String m;
             if (ctx.dancersToRight(d).Count() == 0)
             {
                 m = "Dodge Right";
             }
             else if (ctx.dancersToLeft(d).Count() == 0)
             {
                 m = "Dodge Left";
             }
             else
             {
                 throw new CallError("Can not figure out how to Spread");
             }
             d.path.add(TamUtils.getMove(m).changebeats(2.0));
         }
         else
         {
             //  Inactive dancers move forward
             Dancer d2 = ctx.dancerInFront(d);
             if (d2 != null)
             {
                 double dist = CallContext.distance(d, d2);
                 d.path.add(TamUtils.getMove("Forward").scale(dist, 1.0).changebeats(2.0));
             }
         }
     });
 }
 public override Path performOne(Dancer d, CallContext ctx)
 {
     if (ctx.isInCouple(d))
     {
         return(TamUtils.getMove(d.data.beau ? "BackSashay Right" : "Sashay Left"));
     }
     throw new CallError("Only Couples can Half Sashay");
 }
Exemple #7
0
 public override void perform(CallContext ctx, int i = 0)
 {
     //  We need to look at all the dancers, not just actives
     //  because partners of the runners need to dodge
     ctx.dancers.ForEach(d => {
         if (d.data.active)
         {
             //  Find dancer to run around
             //  Usually it's the partner
             var d2 = d.data.partner;
             if (d2 == null)
             {
                 throw new CallError($"Dancer {d.number} has nobody to Run around.");
             }
             //  But special case of t-bones, could be the dancer on the other side,
             //  check if another dancer is running around this dancer's "partner"
             var d3 = d2.data.partner;
             if (d != d3 && d3 != null && d3.data.active)
             {
                 d2 = ctx.dancerToRight(d);
                 if (d2 == d.data.partner)
                 {
                     d2 = ctx.dancerToLeft(d);
                 }
             }
             //  Partner must be inactive
             if (d2 == null || d2.data.active)
             {
                 throw new CallError($"Dancer {d.number} has nobody to Run around.");
             }
             var m    = CallContext.isRight(d)(d2) ? "Run Right" : "Run Left";
             var dist = CallContext.distance(d, d2);
             d.path   = TamUtils.getMove(m).scale(1, dist / 2);
             //  Also set path for partner
             if (CallContext.isRight(d2)(d))
             {
                 m = "Dodge Right";
             }
             else if (CallContext.isLeft(d2)(d))
             {
                 m = "Dodge Left";
             }
             else if (CallContext.isInFront(d2)(d))
             {
                 m = "Forward 2";
             }
             else if (CallContext.isInBack(d2)(d))
             {
                 m = "Back 2"; //  really ???
             }
             else
             {
                 m = "Stand"; // should never happen
             }
             d2.path = TamUtils.getMove(m).scale(1, dist / 2);
         }
     });
 }
        override public void performCall(CallContext ctx, int notused)
        {
            var allp = TamUtils.getPaths(xelem);

            //  If moving just some of the dancers,
            //  see if we can keep them in the same shape
            if (ctx.actives.Count < ctx.dancers.Count)
            {
                //  No animations have been done on ctx2,
                //  so dancers are still at the start points
                var ctx3 = new CallContext(ctx2);
                //  So ctx3 is a copy of the start point
                var bounds1 = ctx3.bounds();
                //  Now add the paths
                ctx3.dancers.ForEach((d, i) => d.path.add(allp[i >> 1]));
                //  And move it to the end point
                ctx3.levelBeats();
                ctx3.analyze();
            }
            var vdif = ctx.computeFormationOffsets(ctx2, xmlmap);

            xmlmap.ForEach((m, i3) => {
                var p = new Path(allp[m >> 1]);
                //  Scale active dancers to fit the space they need
                //  Compute difference between current formation and XML formation
                var vd = vdif[i3].Rotate(-ctx.actives[i3].tx.Angle());
                //  Apply formation difference to first movement of XML path
                if (vd.Length() > 0.1)
                {
                    if (p.movelist.Count == 0)
                    {
                        p.add(TamUtils.getMove("Stand"));
                    }
                    p.skewFirst(-vd.X, -vd.Y);
                }
                //  Add XML path to dancer
                ctx.actives[i3].path.add(p);
                //  Move dancer to end so any subsequent modifications (e.g. roll)
                //  use the new position
                ctx.actives[i3].animateToEnd();
            });

            //  Mark dancers that had no XML move as inactive
            //  Needed for post-call modifications e.g. spread
            var inactives = new List <Dancer>();

            xmlmap.ForEach((m, i4) => {
                if (allp[m >> 1].movelist.Count == 0)
                {
                    inactives.Add(ctx.actives[i4]);
                }
            });
            inactives.ForEach(d => d.data.active = false);


            ctx.levelBeats();
            ctx.analyze();
        }
        public override Path performOne(Dancer d, CallContext ctx)
        {
            var d2 = ctx.dancerFacing(d);

            if (d2 != null)
            {
                return(TamUtils.getMove("Extend Right").scale(CallContext.distance(d, d2) / 2, 1)
                       .add(TamUtils.getMove("Hinge Left")));
            }
            else
            {
                throw new CallError($"Dancer {d.number} cannot Touch a Quarter");
            }
        }
 public override void perform(CallContext ctx, int i = 0)
 {
     //  Centers and ends cannot both cross run
     if (ctx.dancers.Any(d => d.data.active && d.data.center) &&
         ctx.dancers.Any(d => d.data.active && d.data.end))
     {
         throw new CallError("Centers and ends cannot both Cross Run");
     }
     //  We need to look at all the dancers, not just actives
     //  because partners of the runners need to dodge
     ctx.dancers.ForEach(d => {
         if (d.data.active)
         {
             //  Must be in a 4-dancer wave or line
             if (!d.data.center && !d.data.end)
             {
                 throw new CallError("General line required for Cross Run");
             }
             //  Partner must be inactive
             var d2 = d.data.partner;
             if (d2 != null)
             {
                 if (d2.data.active)
                 {
                     throw new CallError("Dancer and partner cannot both Cross Run");
                 }
                 //  Center beaus and end belles ruin left
                 var isright = d.data.beau ^ d.data.center;
                 //  TODO check for runners crossing paths
                 var m  = isright ? "Run Right" : "Run Left";
                 d.path = TamUtils.getMove(m).scale(1, 2);
             }
             else // Runner has no partner
             {
                 throw new CallError("Nobody to Cross Run around");
             }
         }
         else
         {
             //  Not an active dancer
             //  If partner is active then this dancer needs to dodge
             var d2 = d.data.partner;
             if (d2 != null && d2.data.active)
             {
                 d.path = TamUtils.getMove(d.data.beau ? "Dodge Right" : "Dodge Left");
             }
         }
     });
 }
        public override Path performOne(Dancer d, CallContext ctx)
        {
            //  Can only turn thru with another dancer
            //  in front of this dancer
            //  who is also facing this dancer
            var d2 = ctx.dancerFacing(d);

            if (d2 != null)
            {
                var dist = CallContext.distance(d, d2);
                return(TamUtils.getMove("Extend Right").scale(dist / 2, 0.5)
                       .add(TamUtils.getMove("Swing Left").scale(0.5, 0.5))
                       .add(TamUtils.getMove("Extend Left").scale(dist / 2, 0.5)));
            }
            throw new CallError($"Cannot find dancer to turn with {d.number}");
        }
        public override Path performOne(Dancer d, CallContext ctx)
        {
            var d2 = ctx.dancerFacing(d);

            if (d2 != null && ctx.dancerInFront(d2) == d)
            {
                var dist = CallContext.distance(d, d2);
                return(TamUtils.getMove("Extend Left").scale(dist / 2, 1)
                       .add(TamUtils.getMove("Hinge Right"))
                       .IfDo(name.StartsWith("Left"), p => p.reflect()));
            }
            else
            {
                throw new CallError($"Dancer {d.number} cannot Touch a Quarter");
            }
        }
Exemple #13
0
        public override Path performOne(Dancer d, CallContext ctx)
        {
            //  Can only pass thru with another dancer
            //  in front of this dancer
            //  who is also facing this dancer
            var d2 = ctx.dancerFacing(d);

            if (d2 != null)
            {
                var dist = CallContext.distance(d, d2);
                return(TamUtils.getMove("Extend Left").scale(dist / 2, 0.5)
                       .add(TamUtils.getMove("Extend Right").scale(dist / 2, 0.5)));
            }
            else
            {
                throw new CallError($"Dancer {d.number} has nobody to Pass Thru with");
            }
        }
        public override Path performOne(Dancer d, CallContext ctx)
        {
            //  Can only turn thru with another dancer
            //  in front of this dancer
            //  who is also facing this dancer
            var d2 = ctx.dancerInFront(d);

            if (d2 != null && d2.data.active && ctx.dancerInFront(d2) == d)
            {
                var dist = CallContext.distance(d, d2);
                return(TamUtils.getMove("Extend Left").scale(dist / 2, 0.5)
                       .add(TamUtils.getMove("Swing Right").scale(0.5, 0.5))
                       .add(TamUtils.getMove("Extend Right").scale(dist / 2, 0.5)));
            }
            else
            {
                throw new CallError($"Cannot find dancer to Turn Thru with {d}");
            }
        }
Exemple #15
0
        public override Path performOne(Dancer d, CallContext ctx)
        {
            var d2 = ctx.dancerFacing(d);

            if (d2 != null)
            {
                var dist = CallContext.distance(d, d2);
                var m    = TamUtils.getMove("Extend Left").scale(dist / 2, 0.5);
                if (d.gender == Gender.BOY)
                {
                    m.add(TamUtils.getMove("Lead Right").scale(dist / 2, 0.5));
                }
                else
                {
                    m.add(TamUtils.getMove("Quarter Left").skew(dist / 2, -0.5));
                }
                return(m);
            }
            else
            {
                throw new CallError($"Dancer {d.number} has nobody to Slide Thru with");
            }
        }
Exemple #16
0
        public override Path performOne(Dancer d, CallContext ctx)
        {
            var d2 = d.data.partner;

            if (d2 != null)
            {
                if (!d2.data.active)
                {
                    throw new CallError($"Dancer {d} must Wheel Around with partner");
                }
                if ((d.data.beau ^ d2.data.beau) && (d.data.belle ^ d2.data.belle))
                {
                    return(TamUtils.getMove(d.data.beau ? "Beau Wheel" : "Belle Wheel"));
                }
                else
                {
                    throw new CallError($"Dancer {d} is not part of a Facing Couple");
                }
            }
            else
            {
                throw new CallError($"Dancer {d} is not part of a Facing Couple");
            }
        }
Exemple #17
0
 public override Path performOne(Dancer d, CallContext ctx)
 {
     return(TamUtils.getMove(d.data.beau ? "U-Turn Right" : "U-Turn Left"));
 }
Exemple #18
0
        public override Path performOne(Dancer d, CallContext ctx)
        {
            //  Figure out what dancer we're trading with
            var    leftcount  = 0;
            Dancer bestleft   = null;
            var    rightcount = 0;
            Dancer bestright  = null;

            ctx.actives.ForEach(d2 => {
                if (d2 != d)
                {
                    if (CallContext.isLeft(d)(d2))
                    {
                        if (leftcount == 0 || CallContext.distance(d, d2) < CallContext.distance(d, bestleft))
                        {
                            bestleft = d2;
                        }
                        leftcount++;
                    }
                    else if (CallContext.isRight(d)(d2))
                    {
                        if (rightcount == 0 || CallContext.distance(d, d2) < CallContext.distance(d, bestright))
                        {
                            bestright = d2;
                        }
                        rightcount++;
                    }
                }
            });
            //  Check that the trading dancer is facing same or opposite direction
            if (bestright != null && !CallContext.isRight(bestright)(d) && !CallContext.isLeft(bestright)(d))
            {
                bestright = null;
            }
            if (bestleft != null && !CallContext.isRight(bestleft)(d) && !CallContext.isLeft(bestleft)(d))
            {
                bestleft = null;
            }

            var dtrade  = d;
            var samedir = false;
            var call    = "";

            //  We trade with the nearest dancer in the direction with
            //  an odd number of dancers
            if (bestright != null && ((rightcount % 2 == 1 && leftcount % 2 == 0) || bestleft == null))
            {
                dtrade  = bestright;
                call    = "Run Right";
                samedir = CallContext.isLeft(dtrade)(d);
            }
            else if (bestleft != null && ((rightcount % 2 == 0 && leftcount % 2 == 1) || bestright == null))
            {
                dtrade  = bestleft;
                call    = "Run Left";
                samedir = CallContext.isRight(dtrade)(d);
            }
            else
            {
                throw new CallError("Unable to calculate Trade");
            }

            //  Found the dancer to trade with.
            //  Now make room for any dancers in between
            var hands  = Hands.NOHANDS;
            var dist   = CallContext.distance(d, dtrade);
            var scaleX = 1.0;

            if (ctx.inBetween(d, dtrade).Count() > 0)
            {
                //  Intervening dancers
                //  Allow enough room to get around them and pass right shoulders
                if (call == "Run Right" && samedir)
                {
                    scaleX = 2.0;
                }
            }
            else
            {
                //  No intervening dancers
                if (call == "Run Left" && samedir)
                {
                    //  Partner trade, flip the belle
                    call = "Flip Left";
                }
                else
                {
                    scaleX = dist / 2;
                }
                //  Hold hands for miniwave trades
                if (!samedir && dist < 2.1)
                {
                    hands = call == "Run Left" ? Hands.LEFTHAND :Hands.RIGHTHAND;
                }
            }
            return(TamUtils.getMove(call).changehands(hands).scale(scaleX, dist / 2));
        }