forked from perelman/contra-renderer
145 lines
4.9 KiB
TypeScript
145 lines
4.9 KiB
TypeScript
import { HandConnection, HandTo, BalanceWeight, PositionKind, ShortLinesPosition, SemanticPosition } from "../interpreterCommon.js";
|
|
import { SemanticAnimationKind } from "../lowLevelMove.js";
|
|
import { Hand } from "../rendererConstants.js";
|
|
import { ISingleVariantMoveInterpreter, LowLevelMovesForAllDancers, MoveInterpreter, MoveInterpreterCtorArgs, PartialLowLevelMove, SemanticPositionsForAllDancers, SingleVariantMoveInterpreter, Variant, VariantCollection, moveInterpreters } from "./_moveInterpreter.js";
|
|
|
|
const moveName = "pull by dancers";
|
|
|
|
class PullByDancersSingleVariant extends SingleVariantMoveInterpreter<PullByDancers, typeof moveName> {
|
|
moveAsVariants(previousMoveVariant: string): VariantCollection {
|
|
const res = new Map<string, Variant>();
|
|
|
|
for (const toShortLines of [true, false]) {
|
|
try {
|
|
res.set(toShortLines ? "ToShortLines" : "FullPullBy", {
|
|
lowLevelMoves: this.moveAsLowLevelMovesTo(toShortLines),
|
|
previousMoveVariant
|
|
});
|
|
}
|
|
catch { }
|
|
}
|
|
|
|
return res;
|
|
}
|
|
|
|
|
|
moveAsLowLevelMovesTo(toShortLines: boolean): LowLevelMovesForAllDancers {
|
|
// TODO Might make sense to think of pull by as not a full swap?
|
|
// e.g., in Blue and Green Candles, it's treated as only getting to
|
|
// ShortLinesPosition.Middle* before doing an allemande.
|
|
return this.handlePairedMove(this.move.parameters.who, ({ startPos, around, withPos }) => {
|
|
if (toShortLines) {
|
|
if (startPos.kind !== PositionKind.Circle) {
|
|
throw new Error("ToShortLines variant of " + this.move.move + " only makes sense starting from a circle.");
|
|
}
|
|
}
|
|
|
|
// TODO Adjust facing?
|
|
const startPosition = {
|
|
...startPos,
|
|
hands: new Map<Hand, HandConnection>([
|
|
[
|
|
this.moveInterpreter.hand,
|
|
{ hand: this.moveInterpreter.hand, to: around === "Center" ? HandTo.DiagonalAcrossCircle : HandTo.DancerForward }
|
|
]]),
|
|
facing: startPos.which.facingAcross(),
|
|
};
|
|
|
|
const endPos: SemanticPosition = toShortLines
|
|
? {
|
|
...withPos,
|
|
hands: undefined,
|
|
facing: startPosition.facing,
|
|
kind: PositionKind.ShortLines,
|
|
which: ShortLinesPosition.fromSide(withPos.which.leftRightSide(), "Middle"),
|
|
longLines: undefined, // Needed to satisfy type-checker.
|
|
}
|
|
: {
|
|
...withPos,
|
|
hands: undefined,
|
|
facing: startPosition.facing,
|
|
};
|
|
const passBy: PartialLowLevelMove = {
|
|
beats: this.moveInterpreter.pullBeats,
|
|
endPosition: endPos,
|
|
movementPattern: {
|
|
kind: SemanticAnimationKind.PassBy,
|
|
around,
|
|
side: this.moveInterpreter.hand,
|
|
withHands: true,
|
|
facing: "Start",
|
|
otherPath: "Swap",
|
|
}
|
|
};
|
|
|
|
if (this.move.parameters.bal) {
|
|
return this.combine([
|
|
{
|
|
beats: this.moveInterpreter.balancePartBeats,
|
|
endPosition: {
|
|
...startPosition,
|
|
balance: BalanceWeight.Forward,
|
|
},
|
|
movementPattern: {
|
|
kind: SemanticAnimationKind.Linear,
|
|
}
|
|
},
|
|
{
|
|
beats: this.moveInterpreter.balancePartBeats,
|
|
endPosition: {
|
|
...startPosition,
|
|
balance: BalanceWeight.Backward,
|
|
},
|
|
movementPattern: {
|
|
kind: SemanticAnimationKind.Linear,
|
|
}
|
|
},
|
|
passBy], startPosition);
|
|
} else {
|
|
return this.combine([passBy], startPosition);
|
|
}
|
|
}, !toShortLines ? undefined : ({startPos}) => {
|
|
return this.combine([{
|
|
beats: this.move.beats,
|
|
movementPattern: {
|
|
kind: SemanticAnimationKind.Linear,
|
|
},
|
|
endPosition: {
|
|
...startPos,
|
|
kind: PositionKind.ShortLines,
|
|
which: ShortLinesPosition.fromSide(startPos.which.leftRightSide(), "Far"),
|
|
facing: startPos.which.facingAcross(),
|
|
hands: undefined,
|
|
longLines: undefined,
|
|
}
|
|
}], startPos);
|
|
});
|
|
}
|
|
}
|
|
|
|
class PullByDancers extends MoveInterpreter<typeof moveName> {
|
|
public readonly hand: Hand;
|
|
public readonly balancePartBeats: number;
|
|
public readonly pullBeats: number;
|
|
|
|
constructor(args: MoveInterpreterCtorArgs<typeof moveName>) {
|
|
super(args);
|
|
|
|
this.hand = this.move.parameters.hand ? Hand.Right : Hand.Left;
|
|
const balanceBeats = this.move.parameters.bal
|
|
? this.move.beats > 4
|
|
? this.move.beats - 4
|
|
: this.move.beats > 2
|
|
? 2
|
|
: this.move.beats / 2
|
|
: 0;
|
|
this.balancePartBeats = balanceBeats / 2;
|
|
this.pullBeats = this.move.beats - balanceBeats;
|
|
}
|
|
|
|
buildSingleVariantMoveInterpreter(startingPos: SemanticPositionsForAllDancers): ISingleVariantMoveInterpreter {
|
|
return new PullByDancersSingleVariant(this, startingPos);
|
|
}
|
|
}
|
|
|
|
moveInterpreters.set(moveName, PullByDancers); |