Jugglers' Drift Specification

Footwork

Establishing initial positions; Cartesian coordinates

#jugglers Alice Bob Carol
#r P1 (10,0)
#r P2 (0,-5)
#r P3 (0,5)
t=1: Alice.pos = P1; Alice.face = (0,0)
t=1: Bob.pos = P2; Bob.face = Alice.pos
t=1: Carol.pos = P3; Carol.face = Alice.pos

The #jugglers directive tells the names of the jugglers, and at the same time indicates how many jugglers there are in the pattern. Internally, the jugglers are numbered starting at 1; Juggler[1] is a synonym for Alice in this example.

Timesteps are also numbered starting at 1.

Polar coordinates

#jugglers Alice Bob Carol
#r C (0,0)
t=1: Alice.pos = 5*(0 deg); Alice.face = (0,0)
t=1: Bob.pos = 5*(120 deg); Bob.face = (0,0)
t=1: Carol.pos = 5*(240 deg); Carol.face = (0,0)

The syntax (expr deg) means "the Cartesian vector obtained by going out 1 unit along the ray at expr degrees from (0,0)". The angle is measured from standard position, i.e., (0 deg) is equivalent to (1,0) and (90 deg) is equivalent to (0,1).

Defining movement

t=3: Bob.pos = (-3,0); Carol.pos = (0,0)
t=5: Bob.pos = P3; Carol.pos = P2

Movement is interpolated between the specified positions and times (basically in a straight line for now, but in v2 it should follow a nice spline curve).

If Juggler[i].face is defined, then the juggler will turn to face that absolute position. Facing is also smoothly interpolated between the specified facings and times.

Passing

Passing uses standard multihand notation. The suffix x on a throw means that it's a jim (thrown to the opposite hand from what you'd expect).

t=1: Alice (-,3:Bob)
t=1: Bob (-,3:Alice)
t=3: Alice (-,3:Carol)
t=3: Carol (-,3:Alice)

Looping the pattern

To loop a pattern repeatedly, use the #splice directive:

t=1: Alice (-,3:Bob)
t=1: Bob (-,3:Alice)
t=3: Alice (-,3:Carol)
t=3: Carol (-,3:Alice)
t=5: #splice t=1
This causes everybody to repeat their pattern starting from the given timestep.

Extensible patterns

Certain patterns (e.g. line feed, Feast, Jim's Feast, Seattle Shuffle) take an arbitrary number of jugglers. Those patterns can be represented by "extensible" pattern files where the number of jugglers is not fixed.

Run one of these files using a command line like ./jdrift -n 5 feed.pass. The number after the -n indicates the total number of jugglers. If -n is not given, then the file itself may provide a default using the syntax (default 5).

Within the file, the current number of jugglers can always be obtained using the meta-variable #Jugglers.

#jugglers Alice Bob ... (default 5)
#r P1 (10,0)
#r P2 (0,-5)
#r P3 (0,5)
t=1: Alice.pos = (0,0); Alice.face = Alice.pos+(1,0)  ! juggler 1
t=1: Bob.pos = (3,5); Bob.face = Bob.pos-(1,0)        ! juggler 2
t=1: Juggler[2*i+1].pos = (6*i,0)                     ! juggler 3,5,etc.
t=1: Juggler[2*i].pos = (6*i-3,5)                     ! juggler 4,6,etc.
The syntax Juggler[arith-expr] implicitly refers to all unnamed jugglers with an index that matches arith-expr. This is determined internally by the following algorithm:
  1. Identify all unbound identifiers within arith-exprs in the current statement. If there are no unbound identifiers (e.g., Juggler[3+7]), then give an error. If there are more than one, then give a different error. Otherwise, there is exactly one unbound identifier in there (e.g., Juggler[2*i]). Let's call it i.
  2. Evaluate arith-expr for i in [0,#JugglerCount].
  3. Evaluating arith-expr may result in an index which is out of bounds (remember, the only valid indices are those less than #JugglerCount and greater than the number of named jugglers in the pattern). If an index is out of bounds, then just ignore it; don't evaluate the statement's side-effects for that index.
  4. But if arith-expr is in-bounds, then go on to evaluate the whole statement. Notice that the unbound variable is allowed to appear anywhere in the statement.

Juggling

To do.