Chapter 35
What a cat does to the rider
A crossing cat plays on the clock alone, and the rider reacts to it on every step, in two ways: the rider holds the throttle, and looks. Both reactions are the rider's own, so they live on the rider's side, in the EncounterReaction module. Its two functions match on the encounter ahead, and the cat is the one case that changes the rider.
EncounterReactionHold the throttle §
A limit on the throttle is a ThrottleLimit, from the “The throttle” chapter: either NoLimit, or AtMost some acceleration.
While a cat crosses, the rider's speed can only hold or fall. That's AtMost(Acceleration.steady), which caps the acceleration at zero:
## What `encounter`, at `stage`, asks of the throttle of a rider on its
## segment: while a cat crosses, the rider eases off, holding the
## acceleration at none, which stops them speeding up and never brakes.
encounter_throttle : Encounter, Animation.Stage -> ThrottleLimit
encounter_throttle = |encounter, stage|
match encounter {
CatCrosses(_) =>
match stage {
Playing(_) => AtMost(Acceleration.steady)
Waiting | Past(_) => NoLimit
}
BirdHere(_) | QuietRoad => NoLimit
}
The outer match asks what's on the segment, and the inner one asks where the crossing has got to. A bird and a quiet road both get NoLimit.
The cat's limit is one of the four in the throttle's chain of limits, beside the bend, the gawking and the road's shoulder. The chain starts from the cruise acceleration and keeps the lowest. Holding at steady also holds the rider at or below the speed the plan was made for, so the cat is across before the rider arrives.
Look §
How hard something holds the rider's eye is an Attention. A full look to the side is 1, and a crossing cat holds the eye harder than that, so underneath it's an F64, which can go past 1:
Attention :: F64.{
# ...
encounter_attention returns the pull of the encounter on the rider's segment:
## How hard `encounter`, at `stage`, holds the eye of a rider on its
## segment.
encounter_attention : Encounter, Animation.Stage -> Attention
encounter_attention = |encounter, stage|
match encounter {
CatCrosses(_) => cat_attention(stage)
BirdHere(_) | QuietRoad => Attention.none
}
The cat's pull rises as it crosses, up to its peak of 1.8, then fades over 83 steps once it's across, about 80 metres past the cat at a metre a step:
## How hard a crossing cat holds the rider's eye at `stage`: rising to the
## cat's peak as it crosses, then fading once it is across.
cat_attention : Animation.Stage -> Attention
cat_attention = |stage|
match stage {
Waiting => Attention.none
Playing(steps_in) => {
progress = Fraction.of(steps_in.ratio_to(CatCrossing.crossing_span.length))
CatCrossing.peak_attention.scaled_by(Easing.smoothstep(progress))
}
Past(steps_past) => {
faded = Fraction.clamp(steps_past.ratio_to(attention_fade))
CatCrossing.peak_attention.scaled_by(Easing.smoothstep(faded).complement())
}
}
Playing and Past both carry a step count, and cat_attention uses both: one says how far into the crossing, the other how long since it ended.
Rider.attention takes the stronger of two pulls: the cat's, and the depth of the rider's last look, which lingers after the eyes come home. The camera widens its view for that attention, as a startled rider takes in more of the road.
Of the three encounters, the cat alone changes the rider, through both reactions. The rider's reactions to the bends and the pigs came in the rider's own chapters. The cat's are the last of the ride's moving parts. What's left is the machinery under them: the math, the proofs and the platform.