program: basic // prim is ; always dancer relative def: nothing prim: 0,0,none def: _nothing preserve roll prim: 0,0,none,preserve-roll def: face right in: 2 prim: 0,0,right def: face left in: 2 prim: 0,0,left def: face in in: 2 prim: 0,0,in def: face out in: 2 prim: 0,0,out // meta-commands def: bow to your partner spoken: bow to (your|the) partner (and (your|the) corner too)? call: nothing // work out grammar implications def: anyone while others(sel, c1, c2=nothing) /* default to 'nothing' if the 'while...' isn't present */ spoken: [-20] \ (while the (others|) )? // special case "everybody" as a filler word. from: ANY condition: AND(EQUAL CALL([sel], ALL), EQUAL CALL([c2], nothing)) call: [c1] // special case HEADS and SIDES from static square from: STATIC SQUARE call: _anyone while others static square([sel],[c1],[c2]) // recognize cases where this really means something like 'concentric' from: CENTER HALF // the selected must be centers, and no centers can be unselected. condition: ARE([sel], CENTER), "Not all selected are centers" condition: ARE(CENTER, [sel]), "Not all centers are selected" call: _quasi concentric([c1],[c2]) // like concentric, but no adjust after from: CENTER HALF // other way 'round condition: ARE([sel], not(CENTER)), "Some selected are centers" condition: ARE(not(CENTER), [sel]), "Some centers are selected" call: _quasi concentric([c2],[c1]) from: CENTER HALF // same as above, but special cased because END and OUTSIDE tags aren't // applied by the CENTER HALF matcher. condition: OR(EQUAL CALL([sel], END), EQUAL CALL([sel], OUTSIDE)) call: _quasi concentric([c2],[c1]) from: ANY // ugly hack to support "boys trade" == "boys trade down the line" condition: EQUAL CALL([c1], trade), "Not a trade" condition: EQUAL CALL([c2], nothing), "Not just a trade" call: trade down the line([sel]) from: ANY condition: GREATER(NUM DANCERS([sel]), 0) select: [sel] call: [c1] select: OTHERS call: [c2] from: ANY call: _anyone while others([sel],[c1],[c2]) // break static square cases out into a special call for efficiency def: _anyone while others static square(sel, c1, c2) // special case 'heads promenade half way while the sides...' from: STATIC SQUARE condition: AND(EQUAL CALL([sel], HEAD), EQUAL CALL([c1], promenade half way)) call: _sides start call: anyone while others([sel], _outsides promenade half way, [c2]) from: STATIC SQUARE condition: AND(EQUAL CALL([sel], HEAD), EQUAL CALL([c1], reverse(promenade half way))) call: _sides start call: anyone while others([sel], reverse(_outsides promenade half way), [c2]) from: STATIC SQUARE condition: AND(EQUAL CALL([sel], SIDE), EQUAL CALL([c1], promenade half way)) call: _heads start call: anyone while others([sel], _outsides promenade half way, [c2]) from: STATIC SQUARE condition: AND(EQUAL CALL([sel], SIDE), EQUAL CALL([c1], reverse(promenade half way))) call: _heads start call: anyone while others([sel], reverse(_outsides promenade half way), [c2]) // special case 'heads square thru...' from static square // XXX: "Dancers should return to Squared Set spots for Head Ladies Chain, // Heads Right and Left Thru, Heads Pass Thru, or Heads Square Thru 3." // ...or Heads Dosado from: STATIC SQUARE condition: EQUAL CALL([sel], HEAD) call: _heads start, anyone while others([sel],[c1],[c2]) from: STATIC SQUARE condition: EQUAL CALL([sel], SIDE) call: _sides start, anyone while others([sel],[c1],[c2]) // local helpers def: _anyone(sel, c1) call: anyone while others([sel], [c1], nothing) def: _centers(c) from: CENTER_HALF call: _anyone(CENTER, [c]) def: _ends(c) from: CENTER HALF call: _anyone(END, [c]) def: _heads start from: STATIC SQUARE in: 2 select: HEAD prim: 0, 2, none // "press ahead" select: OTHERS prim: 0, 0, none // stay where they are def: _sides start from: STATIC SQUARE in: 2 select: SIDE prim: 0, 2, none // "press ahead" select: OTHERS prim: 0, 0, none // stay where they are def: down the middle(sel, c=nothing) spoken: [-20] down the middle ((and)? )? from: STATIC SQUARE call: _anyone while others static square([sel], [c], nothing) from: 2x4 condition: are([sel], NUMBER 4) call: _with designated([sel], _designees in) call: _centers([c]) // callerlab #1: CIRCLE LEFT / CIRCLE RIGHT def: circle left(n) spoken: circle (to the)? left way? call: _fractional(_multiply num([n],4), _circle left 1/4) def: circle right(n) spoken: circle (to the)? right way? call: mirror(circle left([n])) def: circle four(n) spoken: circle four way? from: FACING COUPLES call: _fractional(_multiply num([n],4), _circle left 1/4) def: circle two(n) // "single circle" wording is "improper" spoken: single circle from: FACING DANCERS call: _fractional(_multiply num([n],4), _circle left 1/4) def: _circle left 1/4 from: STATIC SQUARE in: 4 part: select: BEAU prim: -2,2,right,sashay-start sashay-finish prim: -2,0,none,sashay-start sashay-finish force-roll-right select: BELLE prim: -2,0,none,sashay-start sashay-finish force-roll-right prim: -2,2,right,sashay-start sashay-finish from: FACING COUPLES in: 2 ipart: select: BEAU prim: 0,2,right,sashay-start sashay-finish select: BELLE prim: -2,0,right,sashay-start sashay-finish from: FACING DANCERS in: 2 // not well specified prim: -1,1,right,sashay-start sashay-finish // callerlab #2: FORWARD AND BACK def: forward and back spoken: (forward and back) | (up to the middle and back) in: 8 from: FACING COUPLES, STATIC SQUARE // XXX: SUPPRESS BREATHING call: _forward 1, _pause, _back 1, _pause def: _forward 1 in: 3 prim: 0, 1, none def: _back 1 in: 3 prim: 0,-1, none def: _pause in: 1 prim: 0, 0, none // callerlab #3: DOSADO / DOSADO TO A WAVE def: _finish dosado in: 6 from: RH MINIWAVE prim: 1, 1,none,sashay-finish prim: 1,-1,none,sashay-start prim: -1,-1,none,sashay-finish def: dosado optional: LEFT in: 6 from: RH MINIWAVE ipart: // how many parts does dosado have, if from miniwave? call: _finish dosado from: ANY ipart: call: _mixed touch part: 3 call: _finish dosado // XXX add to a wave production here, and enforce that // is dosado below the true level of 'to a wave' def: dosado to a wave in: 6 call: dosado, step to a wave // callerlab #4: SWING // ambiguity with A2 swing, we'll try to tell by program // level and starting formation which is meant. def: swing from: GENERAL LINE, FACING COUPLES condition: PROGRAM AT LEAST(A2), "Only partner swing allowed below A2" call: _wave swing from: ANY call: partner swing def: _wave swing // specifically not a partner swing in: 3 from: GENERAL LINE condition: AND(NOT(TBONED(ALL)), \ MATCH(_SELECTION PATTERN(BEAU), "____|__xx|xx__|xxxx")), \ "End and adjacent center must be in mini-wave" call: trade from: ANY condition: not(formation(RH MINIWAVE)) // control recursion call: _mixed touch, _wave swing // XXX: we end in couples facing in, is that right? def: partner swing spoken: (partner swing) | (swing your partner) | (swing (the|your) corner) in: 6 ipart: from: ANY // _cast to wall always goes at least 3/8 call: _swing to wall, _finish swing from: ANY // start with turn and touch if necessary call: _turn and touch, _swing to wall, _finish swing // turn 1/2 or 3/8, whichever will leave you aligned to a wall. // this also ensures that we always swing at least 3/8 around def: _swing to wall call: _with designated(MATCH(_FACING PATTERN(), "[<>^v]"), \ _designees swing to wall) def: _designees swing to wall in: 4 ends in: MATCH(_FACING PATTERN(), "[v^<>]+"), \ [0] "Should end facing a wall" from: RH MINIWAVE // same-sex swinging not allowed: how would we know who spins out at // the end? condition: not(or(are(ALL, BOY), are(ALL, GIRL))), "Same-sex swing" from: ANY condition: are(ALL, DESIGNATED) call: cast(1/2) from: ANY call: cast(3/8) def: _finish swing condition: equal num(NUM DANCERS(), 8) ipart: from: ANY // in RH MINIWAVE, but don't break into subformations condition: formation(RH MINIWAVE) from: ANY condition: MATCH(_INOUT PATTERN(BOY), "iiii") call: _break out from swing from: ANY call: _swing until boys in, _break out from swing // designated dancers do nothing; nondesignated dancers swing 1/8 if they // are not aligned to walls, else swing 1/4 def: _swing until boys in from: ANY ends in: MATCH(_INOUT PATTERN(BOY), "iiii") call: _outfacers swing from: ANY // tail recursion call: _outfacers swing, _swing until boys in def: _outfacers swing call: _with designated(MATCH(_INOUT PATTERN(), "iiiiiiii"), \ _nondesignee boys swing 1/4) // swing 1/4 unless the boy is designated (which means he's facing in) def: _nondesignee boys swing 1/4 from: RH MINIWAVE from: ANY condition: ARE(BOY, DESIGNATED) call: nothing from: ANY call: cast(1/4) def: _break out from swing from: ANY call: _swing more, _finish break out from swing from: ANY call: _finish break out from swing // make sure we swing to promenade direction in certain pinwheel formations, // where we can go an extra quarter while still having all the boys // facing "in" def: _swing more ends in: MATCH(_INOUT PATTERN(BOY), "iiii") call: cast(1/4) def: _finish break out from swing in: 1 from: RH MINIWAVE condition: not(or(are(ALL, BOY), are(ALL, GIRL))), "Same-sex swing" select: GIRL prim: 0, 0, right prim: 0, 0, right select: BOY prim: 0, 0, none // callerlab #5: PROMENADE FAMILY // this is the four-person call. def: _single promenade 1/8 in: 2 from: LH SINGLE PROMENADE prim: 0, 2, left 1/8 def: _single promenade 1/4 in: 4 from: LH SINGLE PROMENADE prim: -2, 2, left from: LH DIAMOND select: POINT prim: -2, 2, left select: CENTER prim: -1, 2, left // all other formations ought to end in LH SINGLE PROMENADE // all roll directions should be left // XXX: enforce with 'ends in'? from: LH STAR prim: -1, 2, left from: LH BOX select: LEADER prim: -1, 1, left select: TRAILER prim: 1, 1, none, sashay-start force-roll-left from: LH SINGLE QUARTER TAG select: CENTER prim: -1, 2, left select: END prim: 2, 2, none, sashay-start force-roll-left from: LH SINGLE THREE QUARTER TAG ipart: select: CENTER prim: 1, 0, none, sashay-start sashay-finish force-roll-left prim: -2, 2, left select: END prim: 0, 0, left prim: -2, 2, left from: LH SINGLE QUARTER ZEE select: LEADER prim: -1, 2, left select: TRAILER prim: 1, 2, none, force-roll-left from: LH SINGLE THREE QUARTER ZEE ipart: call: _zee adjust to promenade, _single promenade 1/4 from: LH IN PINWHEEL, LH OUT PINWHEEL ipart: call: _pinwheel adjust to promenade, _single promenade 1/4 // split out into a separate call to get the timing right (real quick) def: _zee adjust to promenade from: LH SINGLE THREE QUARTER ZEE in: 1 select: LEADER prim: -1, 0, left, sashay-start select: TRAILER prim: 1, 0, none, sashay-start sashay-finish force-roll-left // split out into a separate call to get the timing right (real quick) def: _pinwheel adjust to promenade from: LH IN PINWHEEL, LH OUT PINWHEEL in: 1 prim: out 1, 1, none, sashay-start sashay-finish force-roll-left // another 4-person promenade def: _single star promenade 1/8 in: 2 from: LH STAR prim: 0, 1, left 1/8 def: _single star promenade 1/4 in: 4 from: LH STAR prim: -1, 1, left // all other formations ought to end in LH STAR // all roll directions should be left // XXX: enforce with 'ends in'? from: LH SINGLE PROMENADE prim: -2, 1, left from: LH DIAMOND select: POINT prim: -2, 1, left select: CENTER prim: -1, 1, left // this is the eight-person call. def: _single file promenade 1/8 in: 2 from: SINGLE FILE PROMENADE select: LEADER /* a little bogus, but we'll live */ prim: -2, 2, left select: TRAILER prim: 0, 2, none, force-roll-left // all other formations ought to end in SINGLE FILE PROMENADE // all roll directions should be left // XXX: enforce with 'ends in'? from: LH COLUMN select: NUMBER 1 prim: -2, 0, left, sashay-start select: NUMBER 2 prim: 0, 2, left, sashay-finish select: NUMBER 3, NUMBER 4 prim: 2, 2, none, force-roll-left // promenade some number of 1/4s, plus an extra 1/8 at the end if needed. def: _single promenade(n) from: ANY condition: equal num(_fraction(_multiply num([n], 4)), 0) call: _fractional(_multiply num([n], 4), _single promenade 1/4) from: ANY condition: greater(1/4, [n]) call: _fractional(_multiply num(2, _fraction(_multiply num([n], 4))), \ _single promenade 1/8) from: ANY call: _fractional(_floor(_multiply num([n], 4)), _single promenade 1/4) call: _fractional(_multiply num(2, _fraction(_multiply num([n], 4))), \ _single promenade 1/8) // promenade some number of 1/4s, plus an extra 1/8 at the end if needed. def: _single star promenade(n) from: ANY condition: equal num(_fraction(_multiply num([n], 4)), 0) call: _fractional(_multiply num([n], 4), _single star promenade 1/4) from: ANY call: _fractional(_floor(_multiply num([n], 4)), _single star promenade 1/4) call: _fractional(_multiply num(2, _fraction(_multiply num([n], 4))), \ _single star promenade 1/8) def: _single file promenade(n) call: _fractional(_multiply num([n], 8), _single file promenade 1/8) def: _promenade(n) from: STATIC SQUARE call: 1/2(reverse(wheel around)), _promenade([n]) from: ANY call: _start promenade from facing, as couples(_single promenade([n])) // XXX same thing from 1/8 rotated version of this (darn circle choreo) from: ANY // PROMENADE, STAR PROMENADE, as couples diamonds, etc. call: as couples(_single promenade([n])) // this is used for 'dosado, promenade': the dosado leaves you facing def: _start promenade from facing in: 2 from: FACING DANCERS condition: and(not(ALL(BOY)), not(ALL(GIRL))), "Same sex promenade" select: BOY prim: -1, 1, none prim: 0, 0, none select: GIRL prim: -1, 1, right prim: 0, 0, right // do a call *only if it leaves us at home* // this is how we implement the base case of promenade home, etc. def: _finish at home(who, what) // we're going to the head beau's (belle's) home. ends in: MATCH(_SELECTION PATTERN \ (and(formation(STATIC SQUARE, [who]), or(DANCER 1,DANCER 2))),\ "______(_x|x_)") ends in: MATCH(_FACING PATTERN(), "vv......") call: [what] // Continue to 'promenade home' (or whatever) after checking to ensure // dancer 1 or 2 is a beau (or belle). This ensures that our recursion // will terminate! def: _promenade check(formation, who, what) // could use 'from: {NO SUB} [formation]' here. // if we were to do a sub-formation match, it would scramble the rotation // of the formation, and we need the rotation to know when we're home. condition: OR(ARE(DANCER 1, formation([formation], [who])), \ ARE(DANCER 2, formation([formation], [who]))), "Whose home?" call: [what] // as basic defs say, we always go at least 1/4 def: _promenade home(sel) ipart: from: ANY // use ANY to guarantee no rotation // only successful if we end at home call: _finish at home([sel], and(_promenade(1/4), as couples(roll))) from: ANY // use ANY to guarantee no rotation // only successful if we end at home call: _finish at home([sel], and(_promenade(3/8), as couples(roll))) from: ANY call: _promenade(1/4) call: _promenade check(PROMENADE, [sel], _promenade home([sel])) def: promenade home call: _promenade home(BEAU) // promenade until couple 1 is a beau def: wrong way promenade home spoken: (wrong way|reverse) promenade (home?) call: mirror(_promenade home(BELLE)) def: _outsides promenade half way // used for outer concentric promenade in: 8 ipart: from: FACING COUPLES call: 1/2(reverse(wheel around)), counter rotate(1/2), 1/2(wheel around) def: promenade half way optional: REVERSE in: 8 ipart: call: _promenade(1/2), 1/2(wheel around) def: star promenade(n) spoken: star promenade call: as couples(_single star promenade([n])) // we always go at least 1/4, like for promenade home def: _star promenade home(sel) ipart: from: ANY // use ANY to guarantee no rotation call: _finish at home([sel], and(star promenade(1/4), as couples(roll))) from: ANY // use ANY to guarantee no rotation call: _finish at home([sel], and(star promenade(3/8), as couples(roll))) from: ANY call: star promenade(1/4) call: _promenade check(STAR PROMENADE, [sel], _star promenade home([sel])) def: star promenade home call: _star promenade home(BEAU) def: wrong way star promenade spoken: (reverse|wrong way) star promenade (home?) call: mirror(_star promenade home(BELLE)) // we always go at least 1/4, like for promenade home def: _finish single file promenade home(pattern) // we're going to the head *boys'* home, since beau/belle is meaningless // for single file promenade ends in: MATCH(_SELECTION PATTERN(DANCER 1), [pattern]) call: and roll(_fractional(2, _single file promenade 1/8)) def: _single file promenade home(pattern) ipart: from: ANY // use ANY to guarantee no rotation in: 4 call: _finish single file promenade home([pattern]) from: ANY call: _single file promenade 1/8, _single file promenade home([pattern]) def: single file promenade home spoken: single file promenade (home)? call: _single file promenade home("______x_") def: reverse single file promenade home spoken: reverse single file promenade (home)? call: mirror(_single file promenade home("_______x")) def: promenade inside(sel) // what formation does this end in? spoken: four promenade inside ipart: // 8 beats total call: _in(1, _start promenade inside([sel])), \ _in(5, _centers(_single promenade(3/4))), \ _in(2, _centers(_finish promenade inside)) def: _start promenade inside(sel) in: 2 from: STATIC SQUARE select: [sel] prim: in 1, 1, right, sashay-finish select: OTHERS prim: in 1, -1, none, sashay-start sashay-finish def: _finish promenade inside in: 4 from: LH SINGLE PROMENADE prim: -2, 2, none, force-roll-left def: reverse promenade inside(sel) spoken: four reverse promenade inside call: mirror(promenade inside([sel])) // callerlab #6: ALLEMANDE FAMILY // XXX in circle choreo, boys prefer turning to the left, girls to the right // (callerlab case 2) def: allemande left spoken: (allemande left)|(left allemande) in: 4 // half ipart: from: LH MINIWAVE call: _miniwave trade, step thru from: ANY call: mirror(_turn and touch), _miniwave trade, step thru // callerlab #7: ARM TURNS def: arm turn(n) spoken: arm turn from: MINIWAVE call: _in(_multiply num([n],4), cast([n])) def: left arm turn(n) spoken: left arm turn from: LH MINIWAVE call: arm turn([n]) def: right arm turn(n) spoken: right arm turn from: RH MINIWAVE call: arm turn([n]) // callerlab #8: RIGHT AND LEFT GRAND FAMILY def: _start right and left grand in: 4 ends in: formation(RIGHT AND LEFT GRAND) from: RIGHT AND LEFT GRAND select: CENTER prim: 2, 4, left 1/8 // from 2,0 to 4,4 prim: -3, 1, left 1/8 // from 4,4 to 0,2 select: OTHERS prim: 2, 2, right 1/8 // from 4,0 to 2,-2 prim: 0, 2, right 1/8 // from 2,-2 to 0,-4 from: WRONG WAY THAR select: CENTER prim: 3, 4, left 1/8 // from 1,0 to 4,4 prim: -3, 1, left 1/8 // from 4,4 to 0,2 select: OTHERS prim: 1, 2, right 1/8 // from 3,0 to 2,-2 prim: 0, 2, right 1/8 // from 2,-2 to 0,-4 // diamond-like starting formation from: RIGHT AND LEFT GRAND DIAMOND select: and(CENTER, POINT) prim: 2, 4, left 1/8 // from 2,0 to 4,4 prim: -3, 1, left 1/8 // from 4,4 to 0,2 select: CENTER // not a point prim: 3, 4, left 1/8 // from 1,0 to 4,4 prim: -3, 1, left 1/8 // from 4,4 to 0,2 select: POINT prim: 2, 2, right 1/8 // from 4,0 to 2,-2 prim: 0, 2, right 1/8 // from 2,-2 to 0,-4 select: OTHERS // not a center, not a point prim: 1, 2, right 1/8 // from 3,0 to 2,-2 prim: 0, 2, right 1/8 // from 2,-2 to 0,-4 from: PARALLEL RH WAVES select: and(CENTER, TRAILER) prim: 3, 1, none // from 1,-1 to 4,0 prim: -2, 2, left 1/8 // from 4,0 to 2,2 select: and(CENTER, LEADER) prim: -1, 3, left 1/4 // from 1,1 to 0,4 prim: -2, 2, left 1/8 // from 0,4 to 2,-2 select: and(END, TRAILER) prim: 1, 1, none // from 3,1 to 2,0 prim: -2, 4, right 1/8 // from 2,0 to 4,-4 select: and(END, LEADER) prim: 3, 1, right 1/4 // from 3,-1 to 0,-2 prim: -2, 4, right 1/8 // from 0,-2 to -4,-4 def: _finish right and left grand(who) in: 4 from: RIGHT AND LEFT GRAND condition: ARE(CENTER, [who]), "Wrong way!" select: CENTER prim: 2, 4, left 1/8 // from 0,2 to -4,4 prim: -2, 1, left 1/8 // from -4,4 to -3,1 select: OTHERS prim: 2, 2, right 1/8 // from 0,-4 to -2,-2 prim: 0, 1, right 1/8 // from -2,-2 to -3, -1 def: _turn and touch in: 2 ends in: formation(RH MINIWAVE), "Didn't end right" from: TRADE BY // special case 'cuz mixed(FACING DANCERS, COUPLE) is ambiguous call: _quasi concentric(touch, _hinge) from: mixed(FACING DANCERS, RH MINIWAVE) from: FACING DANCERS call: touch from: RH MINIWAVE call: nothing from: mixed(FACING DANCERS, RH MINIWAVE, COUPLE) from: FACING DANCERS call: touch from: RH MINIWAVE call: nothing from: COUPLE call: 1/2(partner trade) def: _right and left grand(centers) in: 10 ipart: from: ANY // try no adjustment call: _start right and left grand call: _finish right and left grand([centers]) from: ANY // try 'touch' adjustment call: _turn and touch call: _start right and left grand call: _finish right and left grand([centers]) def: right and left grand call: _right and left grand(BOY) def: wrong way grand call: _right and left grand(GIRL) def: weave the ring call: right and left grand // modulo hand-holds def: left and right grand call: mirror(wrong way grand) // callerlab #9: LEFT-HAND STAR / RIGHT-HAND STAR // XXX DEFINE ME // callerlab #10: PASS THRU def: pass thru optional: LEFT in: 2 // define the common case first: we've got two parts there from: FACING DANCERS prim: 0, 1, none prim: 0, 1, none // from mixed formation, this is indivisible from: mixed(FACING DANCERS, RH MINIWAVE) xpart: 2 from: FACING DANCERS prim: 0, 1, none prim: 0, 1, none from: RH MINIWAVE call: step thru // "rear back and..." def: pull by call: pass thru // at least until i implement hand holds def: right pull by call: pull by def: left pull by call: left(pull by) // callerlab #11: HALF SASHAY FAMILY def: half sashay optional: REVERSE in: 4 from: COUPLE select: BEAU prim: 1, -1, none, sashay-start sashay-finish prim: 1, 1, none, sashay-start sashay-finish select: BELLE prim: -1, 1, none, sashay-start sashay-finish prim: -1,-1, none, sashay-start sashay-finish // semi-legal alternatives to "roll away" to make it clearer who's // doing what -- usually called when it's (unusually) the boys rolling // away. Note that we get a grammar conflict if this is just // roll away: consider for instance "boys roll away" with the // boys the centers of right-hand two-faced lines. Do you mean "centers // roll away (each other)" or "ends roll away the centers". So we don't // allow that form, preferring the " roll away the " where // the ambiguity is resolved. def: _roll away(sel1,sel2) // Not reversable: the call would be "boys reverse roll away", not // "reverse boys roll away" // (also "reversable" messes with the precedence level) spoken: roll (the|that) away from: COUPLE, TWO-FACED LINE /* allows "ends roll away the centers" */ condition: ARE([sel1],BEAU), [1] "Those doing the rolling must be beaus" condition: ARE([sel2],BELLE), [1] "Those rolling away must be belles" call: roll away // ignore the selectors def: _reverse roll away(sel1,sel2) spoken: reverse roll (the|that) away from: COUPLE, TWO-FACED LINE /* allows "centers reverse roll away the ends" */ condition: ARE([sel1],BELLE), [1] "Those doing the rolling must be belles" condition: ARE([sel2],BEAU), [1] "Those rolling away must be beaus" call: reverse(roll away) // ignore the selectors // XXX _circle choreo def: roll away optional: REVERSE in: 4 from: COUPLE select: BEAU ipart: prim: 1, 0, none, sashay-start sashay-finish prim: 0, 0, none ipart: prim: 1, 0, none, sashay-start sashay-finish prim: 0, 0, none select: BELLE ipart: prim: -1, 2, left prim: 0, 0, left ipart: prim: 1, 2, left, sashay-start sashay-finish prim: 0, 0, left // old definition, doesn't animate well =( from: COUPLE select: BEAU ipart: prim: 1/2, 0, none, sashay-start sashay-finish prim: 1/2, 0, none, sashay-start sashay-finish ipart: prim: 1/2, 0, none, sashay-start sashay-finish prim: 1/2, 0, none, sashay-start sashay-finish select: BELLE ipart: prim: -1/2, 1, left prim: 1, 1/2, left, sashay-finish ipart: prim: 1/2, 1, left, sashay-start sashay-finish prim: 1, -1/2, left, sashay-start // XXX DEFINE ME ladies in, men sashay // callerlab #12: TURN BACK FAMILY // XXX: from a single quarter tag, currently no one can roll // what should happen is that the miniwave rolls toward the // handhold, and only the ends have an undefined roll // XXX: same general idea holds for t-boned formations. def: u turn back in: 2 from: 2x2, 1x2 // XXX use 'allow unmatched dancers' select: BEAU prim: 0, 0, right prim: 0, 0, right select: BELLE prim: 0, 0, left prim: 0, 0, left // we can u-turn back from other formations, too: turn toward // the center in that case. from: ANY prim: 0, 0, in // fails for dancers on centerline. call: _in(1, roll) // ie, continue in the same direction from: SINGLE DANCER // if all else fails prim: 0, 0, right, force-roll-none prim: 0, 0, right, force-roll-none // XXX DEFINE ME: "gents or ladies backtrack" // callerlab #13: SEPARATE (see BMS addendum) // XXX DEFINE ME: around 1 or 2 to a line // XXX DEFINE ME: around 1 or 2 and come into the middle // callerlab #14: SPLIT TWO (see BMS addendum) // XXX DEFINE ME // callerlab #15: COURTESY TURN // XXX definition says that 'courtesy turn' without a fraction means // "turn to the center of the formation in which it is working" // use a pattern predicate for in/out? def: courtesy turn(n=3/4) spoken: courtesy turn ()? from: FACING DANCERS call: _in(_multiply num([n],8), \ and(_start courtesy turn, courtesy turn([n]))) from: COUPLE call: _fractional([n], _courtesy turn 4/4) def: _start courtesy turn in: 1 from: FACING DANCERS select: BOY prim: 0, 0, left select: GIRL prim: 0, 0, right def: _courtesy turn 4/4 in: 8 call: 2(wheel around) // modulo hand hold // callerlab #16: LADIES CHAIN FAMILY def: two ladies chain(sel) spoken: two chain // 'two ladies chain' in: 8 from: FACING COUPLES condition: ARE([sel], BELLE), "Named dancers must be belles" call: 1/2(wheel around), chain down the line def: four ladies chain(sel,n=1/2) spoken: four chain ()? // timing = 6 + 2 per 1/4 ipart: from: STATIC SQUARE // XXX or circle (adjust?) condition: ARE([sel], BELLE), "Named dancers must be belles" condition: NOT(GREATER(1/4, [n])), "Must chain at least 1/4" call: _start belles chain call: _in(_multiply num(8,[n]),\ _centers(reverse(_single star promenade([n])))) call: _finish belles chain, _in(4, courtesy turn(3/4)) def: _start belles chain in: 1 from: STATIC SQUARE select: BELLE prim: in 1, 2, left select: BEAU prim: in 1, 0, none, sashay-start sashay-finish def: _finish belles chain in: 1 from: CENTER HALF select: CENTER prim: -1, 0, none, sashay-start sashay-finish select: OTHERS prim: 0, -1, left, sashay-finish def: chain down the line in: 8 from: RH TWO-FACED LINE call: _centers(right arm turn(1/2)), courtesy turn(3/4) from: LH OCEAN WAVE call: _quasi concentric(right arm turn(1/2), u turn back) call: courtesy turn(3/4) // callerlab #17: DO PASO // XXX: how do we do the 'no courtesy turn' version in the text ui? // in the game UI, we'd have a special 'call waiting' predicate. // XXX: WRITE ME def: _do paso(last=courtesy turn) // SS from start to finish of courtesy turn 16 to next call 12 call: _do paso face and left touch call: left(turn thru) call: mirror(left allemande) call: [last] // callerlab #18: LEAD RIGHT def: lead right in: 4 call: as couples(_single lead right) def: lead left call: mirror(lead right) def: _single lead right from: FACING DANCERS prim: 1, 0, right 1/8 prim: -1/2,1/2, right 1/8 // callerlab #19: VEER LEFT / VEER RIGHT // XXX: callerlab definition permits this from facing dancers?! def: veer left in: 2 call: as couples(_single veer left) def: veer right call: mirror(veer left) def: _single veer left from: FACING DANCERS, LH MINIWAVE call: _extend // callerlab #20: BEND THE LINE def: bend the line in: 4 call: as couples(_single bend) def: _single bend from: COUPLE, MINIWAVE prim: 0, 0, in def: bend the big line in: 6 call: as couples(bend the line) /// XXX "lines of 6, bend the line" // callerlab #21: CIRCULATE FAMILY // XXX from t-boned columns, the #3 dancer split circs instead of column cir. // definition should be FROM: 2x4 def: circulate // all-8 spoken: (all eight)? circulate in: 4 from: ANY condition: equal num(NUM DANCERS(), 8) from: PARALLEL GENERAL LINES call: concentric(_box circulate) from: GENERAL COLUMNS call: column circulate from: ANY condition: equal num(NUM DANCERS(), 4) from: 2x2 call: _box circulate def: column circulate from: GENERAL COLUMNS select: NUMBER 1 call: _lead circ select: OTHERS call: _trail circ def: single file circulate call: column circulate def: _lead circ // leaders part of a box/column circulate prim: in 1, 1, in prim: in 1, 1, in def: _trail circ // trailers part of a box/column circulate prim: 0,1,none prim: 0,1,none def: split circulate from: PARALLEL GENERAL LINES, GENERAL COLUMNS, ANY call: _box circulate // on each side. def: box circulate condition: equal num(NUM DANCERS(), 4), \ "Perhaps you mean to say CENTERS box circulate?" call: _box circulate def: _box circulate // for internal use: this is the 2x2 version of circulate in: 4 // not official from: 2x2 select: LEADER call: _lead circ select: TRAILER call: _trail circ def: couples circulate call: as couples(circulate) // callerlab #22: RIGHT AND LEFT THRU def: right and left thru in: 6 call: right pull by, _finish right and left thru(1/2) def: _finish right and left thru(n=1/2) from: BACK TO BACK COUPLES call: courtesy turn([n]) def: right and left thru and a quarter more in: 8 call: right pull by, _finish right and left thru(3/4) def: right and left thru full turn spoken: right and left thru full turn (around)? in: 10 call: right pull by, _finish right and left thru(4/4) def: left and right thru call: left(right and left thru) def: left and right thru and a quarter more call: left(right and left thru and a quarter more) def: left and right thru full turn spoken: left and right thru full turn (around)? call: left(right and left thru full turn) // callerlab #23: GRAND SQUARE def: grand square(n=24) spoken: grand square ( steps )? from: STATIC SQUARE condition: FALSE(), "Who should face in?" call: nothing from: O DOUBLE PASS THRU call: _fractional(_multiply num([n],1/24), _grand square(nothing, nothing)) def: _grand square(first, last) ipart: call: _in(4, and([first], _grand square 1/4(face in))) ipart: call: _grand square 1/4(face in) ipart: call: _grand square 1/4(face in) ipart: call: _grand square 1/4(nothing) ipart: call: _grand square 1/4(face in) ipart: call: _grand square 1/4(face in) ipart: call: _grand square 1/4(face in) ipart: call: _grand square 1/4([last]) def: _grand square 1/4(face) in: 4 ipart: from: O DOUBLE PASS THRU, BUTTERFLY DOUBLE PASS THRU select: CENTER call: _in(3, _back 2), _in(1, [face]) select: END call: _in(3, _forward 2), _in(1, [face]) def: _forward 2 in: 3 prim: 0, 2, none def: _back 2 in: 3 prim: 0, -2, none def: _grand square face(sel) in: 1 select: [sel] prim: 0, 0, in select: OTHERS prim: 0, 0, none def: face grand square(sel, n=24) // XXX boys face grand square, etc? spoken: face grand square ( steps )? call: _fractional(_multiply num([n],1/24), \ _grand square(_grand square face([sel]), _grand square face([sel]))) // callerlab #24: STAR THRU def: star thru in: 4 from: FACING DANCERS condition: not(or(ALL(BOY), ALL(GIRL))), "Same sex star thru!" call: slide thru // modulo styling // callerlab #25: CIRCLE TO A LINE // XXX DEFINE ME // callerlab #26: WALK AROUND THE CORNER // XXX DEFINE ME // callerlab #27: SEE SAW def: see saw spoken: see saw (your own)? in: 8 call: mirror(all around the corner) // callerlab #28: SQUARE THRU FAMILY // timing of square thru is "2 beats per hand" def: square thru(n) optional: LEFT spoken: square thru (hands (around|round)?)? from: ANY condition: and(greater([n],0),not(greater([n],1))) call: _fractional([n], _in(2, pull by)) from: ANY condition: greater([n], 1) ipart: // does square thru N have N distinct parts? call: _in(2, _sq_thru_part), left(square thru(_subtract num([n],1))) def: _sq_thru_part // definition is: // call: pull by, quarter in // but looks better if we blend the quarter in ipart: from: FACING COUPLES prim: 0, 1, none prim: 0, 1, in from: RH OCEAN WAVE select: CENTER prim: 0, 1, in select: END prim: in 2, 1, in from: ANY // fall back to real definition, so "rear back and..." works call: pull by, quarter in def: _full_square_thru optional: LEFT spoken: square thru call: square thru(4) // callerlab #29: CALIFORNIA TWIRL def: california twirl in: 4 from: COUPLE condition: ARE(BEAU, BOY), "Boys must be beaus" condition: ARE(BELLE, GIRL), "Girls must be belles" call: partner trade // apart from styling, that is. // callerlab #30: DIVE THRU // XXX: callerlab says, "the couple whose back is to the center of the square // (unless a specific couple is directed) makes an arch..." // Are there other formations this can be done from? Should we support // dive thru? def: dive thru from: EIGHT CHAIN THRU // total 6 beats, but only 2 for the couple diving. // (how can we express the overlap?) call: _in(2, pass thru), _in(4, _ends(california twirl)) // callerlab #31: WHEEL AROUND def: wheel around optional: REVERSE in: 4 call: 2(_quarter wheel) def: _quarter wheel in: 2 from: COUPLE select: BEAU prim: 1, -1, left select: BELLE prim: -1, 1, left // callerlab #32: THAR FAMILY // XXX DEFINE ME // callerlab #33: SHOOT THE STAR // XXX DEFINE ME // callerlab #34: SLIP THE CLUTCH // XXX DEFINE ME // callerlab #35: BOX THE GNAT def: box the gnat in: 4 ipart: from: RH MINIWAVE condition: not(or(ALL(BOY), ALL(GIRL))), "Same sex boxing!" select: BOY prim: in 1,1,right prim: 0,0,right select: GIRL prim: in 1,1,left,sashay-finish prim: 0,0,left from: ANY call: _mixed touch, box the gnat // callerlab #36: TRADE FAMILY def: trade down the line(sel) spoken: trade down the line in: 4 from: 1x4 condition: AND(MATCH(_SELECTION PATTERN([sel]), "_x_x|x_x_"), \ NOT(TBONED([sel]))) select: [sel] prim: in 2, 2, in prim: in 2, 2, in select: OTHERS prim: 0, 0, none prim: 0, 0, none from: 1x4 condition: AND(MATCH(_SELECTION PATTERN([sel]), x__x), NOT(TBONED([sel]))) select: [sel] prim: in 3, 3, in prim: in 3, 3, in select: OTHERS prim: 0, 0, none prim: 0, 0, none // XXX: these cases are really "trade" not "trade down the line" // but this solves some problems while 'do your part' isn't implemented from: 1x4 condition: AND(MATCH(_SELECTION PATTERN([sel]), "xx__|__xx"), \ NOT(TBONED([sel]))) from: 1x2 select: [sel] call: trade select: OTHERS call: nothing from: 1x4 condition: AND(MATCH(_SELECTION PATTERN([sel]), "_xx_"), \ NOT(TBONED([sel]))) call: _centers(trade) def: trade from: mixed(COUPLE, RH_MINIWAVE, LH_MINIWAVE) from: COUPLE call: partner trade from: MINIWAVE call: _miniwave trade def: couples trade in: 6 call: as couples(trade) def: _miniwave trade from: MINIWAVE in: 4 prim: in 1,1,in prim: in 1,1,in def: partner trade from: COUPLE in: 4 prim: in 1,1,in prim: in 1,1,in // callerlab #37: OCEAN WAVE FAMILY (see BMS addendum) def: step to a wave in: 2 // not official from: FACING DANCERS call: _extend // the general case def: step thru in: 2 // not official from: MINIWAVE call: _extend // the general case def: balance in: 4 prim: 0, 1/2, none prim: 0,-1/2, none // modulo styling -- and breathing? // callerlab #38: ALAMO STYLE // XXX DEFINE ME // callerlab #39: SWING THRU FAMILY def: swing thru optional: LEFT in: 6 // XXX DEFINE ME: also from alamo ring from: RH OCEAN WAVE call: right arm turn(1/2) call: anyone while others(CENTER,left arm turn(1/2),_nothing preserve roll) from: LH OCEAN WAVE call: _centers(right arm turn(1/2)), left arm turn(1/2) from: ANY call: _mixed touch, swing thru // callerlab #40: RUN FAMILY // NOTE THAT 'leads run' = 'IN YOUR BOX, leads run' // NOTE THAT 'boys run' = 'IN YOUR COUPLES, boys run' // ie, we need to select a formation to get dancers tagged first. def: run(sel) spoken: run in: 4 from: 1x4, 2x4, BOX, mixed(COUPLE, RH MINIWAVE, LH MINIWAVE), 1x2 // do the select from the 1x4 and 2x4 so that 'centers' works right call: _with designated([sel], _designees run) // we can't use in/out in primitives here because (1) centers of waves // run out, while ends of waves run in, and (2) the "run-around" dancer // stands on the centerline of the formation at one point. // XXX: we really want a "designated and the dancer they are next to" // matcher here, to handle certain complex t-boned runs with // otherwise ambiguous 1x2 matches. def: _designees run from: mixed(COUPLE, RH MINIWAVE, LH MINIWAVE), 1x2 from: ANY // unlike kickoff, if no one is designated, no one does anything condition: ARE(DESIGNATED, NONE), "Run w/ no designated dancers" call: nothing from: 1x2 condition: not(ARE(DESIGNATED, NONE)), "Run w/ designated dancers" condition: not(or(ARE(DESIGNATED, TRAILER), ARE(DESIGNATED, LEADER))),\ "Designated dancers must be in lines" // designated must be "in lines" (ie EW) so must match BEAU or BELLE select: and(DESIGNATED, BEAU) prim: 1,1,right prim: 1,1,right select: and(DESIGNATED, BELLE) prim: -1,1,left prim: -1,1,left select: BEAU prim: 1,0,none,sashay-start sashay-finish prim: 1,0,none,sashay-start sashay-finish select: BELLE prim: -1,0,none,sashay-start sashay-finish prim: -1,0,none,sashay-start sashay-finish select: LEADER prim: 0,-1,none prim: 0,-1,none select: TRAILER prim: 0,1,none prim: 0,1,none def: cross run(sel) spoken: cross run in: 6 from: 1x4 call: _with designated([sel], _designees cross run) def: _designees cross run from: 1x4 condition: not(or(ARE(DESIGNATED, TRAILER), ARE(DESIGNATED, LEADER))),\ "Designated dancers must be in lines" // in order for "do half of everyone cross run" to end in a tidal wave // (as JYAW says it should), we do a big step/small step thing, with // centers taking the small step first and ends taking the big step 1st select: and(DESIGNATED, CENTER) prim: in 1, 1, in prim: in 1, 3, in select: and(DESIGNATED, END) prim: in 3, 1, in prim: in 1, 1, in select: OTHERS call: _designees run // callerlab #41: PASS THE OCEAN def: pass the ocean in: 4 condition: or(PROGRAM AT LEAST(PLUS), formation(FACING COUPLES)), \ "Ocean wave rule not allowed here below plus" call: pass thru, quarter in, step to a wave // callerlab #42: EXTEND def: extend optional: LEFT // at basic/mainstream, extend is from 1/4 tag only from: QUARTER TAG call: _extend from: ANY condition: PROGRAM AT LEAST(PLUS), "Not allowed below Plus" call: _extend def: _extend // the general case in: 2 from: SINGLE DOUBLE PASS THRU select: LEADER prim: -1,1, none select: TRAILER prim: 0,1, none from: LH BOX, LH MINIWAVE, LH SINGLE QUARTER TAG, LH SINGLE THREE QUARTER TAG call: mirror(_extend) from: RH BOX select: LEADER prim: 1,1, none select: TRAILER prim: 0,1, none from: RH MINIWAVE prim: 1,1, none from: FACING DANCERS prim: -1,1,none from: RH SINGLE QUARTER TAG select: CENTER prim: 0, 1, none select: END prim: -1, 1, none from: RH SINGLE THREE QUARTER TAG select: CENTER prim: 1, 1, none select: END prim: 0, 1, none // callerlab #43: WHEEL AND DEAL FAMILY def: wheel and deal in: 4 call: as couples(single wheel) // callerlab #44: DOUBLE PASS THRU def: double pass thru in: 4 call: tandem(pass thru) // callerlab #45: FIRST COUPLE GO LEFT/RIGHT (see BMS addendum) def: first couple go left next couple go left // ends in promenade in: 6 from: COMPLETED DOUBLE PASS THRU call: as couples(_single go left left) def: first couple go left next couple go right // ends in facing lines in: 6 from: COMPLETED DOUBLE PASS THRU call: as couples(_single go left right) def: first couple go right next couple go right call: mirror(first couple go left next couple go left) def: first couple go right next couple go left call: mirror(first couple go left next couple go right) def: _single go left left ipart: from: COMPLETED SINGLE DOUBLE PASS THRU // ends in: single promenade select: END // starts at 0, 3 ; ends at -2,0 prim: -1, 1, left // to -1, 4 prim: -2, 1, left // to -2, 2 prim: 0, 2, none, force-roll-left select: CENTER // starts at 0, 1 ; ends at 0,2 prim: 0, 1/2, none // to 0, 1 1/2 prim: 0, 1/2, none // to 0, 2 prim: 0, 0, left // to 0,2 def: _single go left right ipart: from: COMPLETED SINGLE DOUBLE PASS THRU // ends in: facing couple select: END // starts at 0, 3 ; ends at -1, 1 prim: -1, 1, left // to -1, 4 prim: -2, 1, left // to -2, 2 prim: -1, 1, none, force-roll-left select: CENTER // starts at 0, 1 ; ends at 1, 1 prim: 1, 1, right // to 1, 2 prim: 1, 1, right // to 2, 1 prim: 1, 0, none, force-roll-right sashay-start sashay-finish // callerlab #46: ZOOM def: zoom in: 4 from: BOX, TANDEM COUPLES select: BEAU call: mirror(_right single zoom) select: BELLE call: _right single zoom // XXX redefine using in/out? def: _right single zoom from: TANDEM select: LEADER ipart: prim: 1,1,right prim: 2,1,right ipart: prim: 1,2,right prim: 1,1,right select: TRAILER ipart: prim: 0,1,none ipart: prim: 0,1,none // callerlab #47: FLUTTERWHEEL / REVERSE FLUTTERWHEEL def: flutterwheel optional: REVERSE in: 8 from: FACING COUPLES ipart: call: _start a flutterwheel call: counter rotate(1/4) call: mirror(1/2(wheel around)) call: circle left(1/4) // make sure we end with sweep def: _start a flutterwheel in: 3 // arbitrary just sets fraction relative to rest of flutterwheel from: FACING COUPLES select: BEAU prim: 1, -1, none prim: 0, 0, left select: BELLE prim: -2, 1, none prim: 1, 1, right // callerlab #48: SWEEP A QUARTER def: sweep(n) spoken: [-10] sweep condition: AND(GREATER([n],0), GREATER(1, [n])), \ "Must sweep some number of quarters" // two beats per quarter call: _in(_multiply num([n], 8), \ as couples(_fractional(_multiply num([n], 4), _single sweep 1/4))) def: _single sweep 1/4 from: FACING DANCERS from: ANY condition: MATCH(_SWEEP PATTERN(), RR) // right sweep prim: 1, 1, left from: ANY condition: MATCH(_SWEEP PATTERN(), LL) // left sweep prim: -1, 1, right from: ANY condition: MATCH(_SWEEP PATTERN(), "_.|._") // missing sweep condition: FALSE(), [2] "No sweep direction" // override 'mismatched' msg call: nothing from: ANY condition: FALSE(), "Mismatched sweep direction" call: nothing def: and sweep(c, n) spoken: [-10] and sweep call: [c], sweep([n]) // callerlab #49: TRADE BY // XXX: callerlab says "any formation in which two couples are facing each // other and the other two are facing out" // obvious candidates: TRADE BY, RH 3/4 TAG def: trade by optional: LEFT in: 4 from: CENTER HALF call: _quasi concentric(pass thru, _finish trade by) def: _finish trade by condition: MATCH(_INOUT PATTERN(), "oooo"), \ "Outside couples must face out" call: partner trade // callerlab #50: TOUCH 1/4 def: touch optional: LEFT in: 2 call: step to a wave def: _touch(n) // touch 3/4 is mainstream, not basic // timing: 2 per quarter optional: LEFT spoken: touch condition: or(equal num([n],1/4), program at least(MAINSTREAM)), \ "Only touch 1/4 is allowed at Basic" call: _in(_multiply num([n], 8), \ and(touch, _fractional([n], _cast 4/4))) def: _mixed touch // used as part of ocean wave/facing couples adjustment in: 2 condition: not(formation(RH MINIWAVE)) // must be doing *something* from: ANY ends in: formation(RH MINIWAVE) // control recursion from: FACING DANCERS // simple case call: touch from: mixed(RH MINIWAVE, FACING DANCERS) from: FACING DANCERS call: touch from: RH MINIWAVE call: nothing // callerlab #51: FERRIS WHEEL // ferris wheel should be: call: ferris(wheel and deal) // but ferris is a hard concept to program, and c3b and/or c4 to boot. // XXX: we'll use the simpler stretch definition for now. def: ferris wheel in: 6 //call: stretch(wheel and deal) call: as couples(_single ferris wheel) example: ferris wheel before: ! ^ ^ ! A a c C ! ^ ^ v v ! B b d D ! v v after: ! a A ! v v ! b B ! v v ! ^ ^ ! C c ! ^ ^ ! D d def: _single ferris wheel ipart: call: and roll(_start single ferris wheel) def: _start single ferris wheel in: 5 from: BOX select: LEADER prim: 0, 1, none prim: in 1, 1, in select: TRAILER prim: 0, 1, none prim: in 1, 1, in /////////////////// end of basic list ///////////////////////