Compare commits

...

2 Commits

Author SHA1 Message Date
Daniel Perelman 1caab5d112 Initial support for ricochet in hey. 2023-10-14 15:08:41 -07:00
Daniel Perelman 0bb4e2c051 Fix CirclePosition.fromSides() 2023-10-14 15:08:15 -07:00
2 changed files with 80 additions and 22 deletions

View File

@ -1972,16 +1972,14 @@ function moveAsLowLevelMoves({ move, nextMove, startingPos, numProgessions }: {
case "hey": case "hey":
type HeyStep = { type HeyStep = {
kind: "StandStill" | "Loop" | "CenterPass" | "EndsPassIn" | "EndsPassOut", kind: "StandStill" | "Loop" | "CenterPass" | "EndsPassIn" | "EndsPassOut" | "Ricochet",
endPosition: SemanticPosition, endPosition: SemanticPosition,
} }
if (move.parameters.dir !== "across") { if (move.parameters.dir !== "across") {
throw new Error("Unsupported hey direction: " + move.parameters.dir); throw new Error("Unsupported hey direction: " + move.parameters.dir);
} }
if (move.parameters.rico1 || move.parameters.rico2 || move.parameters.rico3 || move.parameters.rico4) {
throw new Error("Ricochet hey is unsupported.");
}
let heyParts: number; let heyParts: number;
switch (move.parameters.until) { switch (move.parameters.until) {
case "half": case "half":
@ -2080,6 +2078,14 @@ function moveAsLowLevelMoves({ move, nextMove, startingPos, numProgessions }: {
// TODO Loop should probably be its own kind? Or RotateAround? // TODO Loop should probably be its own kind? Or RotateAround?
kind: SemanticAnimationKind.Linear, kind: SemanticAnimationKind.Linear,
minRotation: endsShoulder === Hand.Right ? +180 : -180, minRotation: endsShoulder === Hand.Right ? +180 : -180,
} : heyStep.kind === "Ricochet" ? {
// TODO This is a hack.
kind: SemanticAnimationKind.PassBy,
around: heyStep.endPosition.which.leftRightSide(),
withHands: false,
otherPath: "Swap",
facing: "Start",
side: endsShoulder,
} : { } : {
kind: SemanticAnimationKind.PassBy, kind: SemanticAnimationKind.PassBy,
around: heyStep.kind === "CenterPass" ? "Center" : heyStep.endPosition.which.leftRightSide(), around: heyStep.kind === "CenterPass" ? "Center" : heyStep.endPosition.which.leftRightSide(),
@ -2091,7 +2097,10 @@ function moveAsLowLevelMoves({ move, nextMove, startingPos, numProgessions }: {
heyStep, heyStep,
}; };
} }
function continueHey(prevStep: HeyStep, stepsLeft: number): HeyStep { function continueHey(prevStep: HeyStep, stepsLeft: number, beenInCenter: boolean): HeyStep {
// TODO Not sure why type checker requires rechecking this here.
if (move.move !== "hey") throw new Error("Unreachable.");
// Continuing hey so everyone is either passing (in center or on ends) or looping on ends. // Continuing hey so everyone is either passing (in center or on ends) or looping on ends.
if (prevStep.endPosition.kind === PositionKind.Circle) { if (prevStep.endPosition.kind === PositionKind.Circle) {
if (prevStep.endPosition.facing === prevStep.endPosition.which.facingAcross()) { if (prevStep.endPosition.facing === prevStep.endPosition.which.facingAcross()) {
@ -2155,12 +2164,44 @@ function moveAsLowLevelMoves({ move, nextMove, startingPos, numProgessions }: {
}, },
} }
} }
else if (!isFacingSide) {
const rico = inCenterFirst
? beenInCenter
? move.parameters.rico3
: move.parameters.rico1
: beenInCenter
? move.parameters.rico4
: move.parameters.rico2;
if (rico) {
const onLeftSide = prevStep.endPosition.which.isLeft();
return {
kind: "Ricochet",
endPosition: {
...prevStep.endPosition,
kind: PositionKind.Circle,
which: CirclePosition.fromSides(prevStep.endPosition.which.leftRightSide(),
// TODO might be swapped
(endsShoulder === Hand.Left) === onLeftSide ? CircleSide.Top : CircleSide.Bottom),
facing: onLeftSide ? Facing.Left : Facing.Right,
}
}
} else {
return {
kind: "CenterPass",
endPosition: {
...prevStep.endPosition,
which: prevStep.endPosition.which.swapSides()
},
}
}
}
else { else {
return { return {
kind: isFacingSide ? (inMiddle ? "EndsPassOut" : "EndsPassIn") : "CenterPass", kind: inMiddle ? "EndsPassOut" : "EndsPassIn",
endPosition: { endPosition: {
...prevStep.endPosition, ...prevStep.endPosition,
which: isFacingSide ? prevStep.endPosition.which.swapOnSide() : prevStep.endPosition.which.swapSides() which: prevStep.endPosition.which.swapOnSide()
}, },
} }
} }
@ -2169,13 +2210,15 @@ function moveAsLowLevelMoves({ move, nextMove, startingPos, numProgessions }: {
} }
} }
const inCenterFirst = firstPassInCenter && findPairOpposite(move.parameters.who, id) !== null
|| move.parameters.who2 && findPairOpposite(move.parameters.who2, id) !== null;
let firstHeyStep: HeyStep; let firstHeyStep: HeyStep;
let startingPos: SemanticPosition; let startingPos: SemanticPosition;
if (firstPassInCenter) { if (firstPassInCenter) {
if (startPos.kind !== PositionKind.Circle) { if (startPos.kind !== PositionKind.Circle) {
throw new Error("Hey starting in center not from circle is unsupported."); throw new Error("Hey starting in center not from circle is unsupported.");
} }
const inCenterFirst = findPairOpposite(move.parameters.who, id) !== null;
startingPos = { startingPos = {
kind: startPos.kind, kind: startPos.kind,
which: startPos.which, which: startPos.which,
@ -2184,16 +2227,29 @@ function moveAsLowLevelMoves({ move, nextMove, startingPos, numProgessions }: {
lineOffset: startPos.lineOffset, lineOffset: startPos.lineOffset,
}; };
if (inCenterFirst) { if (inCenterFirst) {
firstHeyStep = { if (move.parameters.rico1) {
kind: "CenterPass", firstHeyStep = {
endPosition: { kind: "Ricochet",
kind: PositionKind.ShortLines, endPosition: {
which: startPos.which.isLeft() ? ShortLinesPosition.MiddleRight : ShortLinesPosition.MiddleLeft, kind: PositionKind.Circle,
facing: startingPos.facing, which: startPos.which.swapUpAndDown(),
setOffset: startPos.setOffset, facing: startPos.which.facingOut(),
lineOffset: startPos.lineOffset, setOffset: startPos.setOffset,
} lineOffset: startPos.lineOffset,
}; }
};
} else {
firstHeyStep = {
kind: "CenterPass",
endPosition: {
kind: PositionKind.ShortLines,
which: startPos.which.isLeft() ? ShortLinesPosition.MiddleRight : ShortLinesPosition.MiddleLeft,
facing: startingPos.facing,
setOffset: startPos.setOffset,
lineOffset: startPos.lineOffset,
}
};
}
} else { } else {
firstHeyStep = { firstHeyStep = {
kind: "StandStill", kind: "StandStill",
@ -2220,9 +2276,11 @@ function moveAsLowLevelMoves({ move, nextMove, startingPos, numProgessions }: {
} }
const heySteps: HeyStep[] = [firstHeyStep]; const heySteps: HeyStep[] = [firstHeyStep];
let beenInCenter = firstHeyStep.kind === "CenterPass" || firstHeyStep.kind === "Ricochet";
for(let i = 1; i < heyParts; i++) { for(let i = 1; i < heyParts; i++) {
const isLast = i === heyParts - 1; const isLast = i === heyParts - 1;
const nextHeyStep = continueHey(heySteps[i - 1], heyParts - i - 1); const nextHeyStep = continueHey(heySteps[i - 1], heyParts - i - 1, beenInCenter);
beenInCenter ||= nextHeyStep.kind === "CenterPass" || nextHeyStep.kind === "Ricochet";
heySteps.push(nextHeyStep); heySteps.push(nextHeyStep);
} }
return combine(heySteps.map(heyStepToPartialLowLevelMove), { ...startingPos, hands: undefined }); return combine(heySteps.map(heyStepToPartialLowLevelMove), { ...startingPos, hands: undefined });

View File

@ -38,9 +38,9 @@ export class CirclePosition {
? topBottomSide === CircleSide.Top ? topBottomSide === CircleSide.Top
? CirclePosition.TopLeft ? CirclePosition.TopLeft
: CirclePosition.BottomLeft : CirclePosition.BottomLeft
: topBottomSide === CircleSide.Bottom : topBottomSide === CircleSide.Top
? CirclePosition.BottomLeft ? CirclePosition.TopRight
: CirclePosition.BottomLeft; : CirclePosition.BottomRight;
} }
private static enumValueToNumber(enumValue: CirclePositionEnum) : number { private static enumValueToNumber(enumValue: CirclePositionEnum) : number {