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."); }
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"); } }
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"); }
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"); } }
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}"); } }
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"); } }
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"); } }
public override Path performOne(Dancer d, CallContext ctx) { return(TamUtils.getMove(d.data.beau ? "U-Turn Right" : "U-Turn Left")); }
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)); }