fix: stabilize route completion threshold to prevent stuck trains

Problem: Route completion threshold was recalculated every frame based on
current passengers. When passengers were auto-regenerated mid-route (after
all delivered), the maxCars value could change, shifting the threshold and
potentially causing the train to never cross it properly.

Solution:
- Store route exit threshold in a ref when route starts
- Only update threshold at route completion for next route
- Threshold remains stable throughout entire route even when passengers regenerate

This ensures trains always complete routes when reaching the exit threshold,
preventing situations where players get stuck answering problems after train
has disappeared.
This commit is contained in:
Thomas Hallock
2025-10-01 12:36:55 -05:00
parent db56ce89ee
commit b7233f9e4a

View File

@@ -43,6 +43,7 @@ export function useSteamJourney() {
const { playSound } = useSoundEffects()
const gameStartTimeRef = useRef<number>(0)
const lastUpdateRef = useRef<number>(0)
const routeExitThresholdRef = useRef<number>(107) // Default for 1 car: 100 + 7
// Initialize game start time and generate initial passengers
useEffect(() => {
@@ -54,6 +55,12 @@ export function useSteamJourney() {
if (state.passengers.length === 0) {
const newPassengers = generatePassengers(state.stations)
dispatch({ type: 'GENERATE_PASSENGERS', passengers: newPassengers })
// Calculate and store exit threshold for this route
const CAR_SPACING = 7
const maxPassengers = calculateMaxConcurrentPassengers(newPassengers, state.stations)
const maxCars = Math.max(1, maxPassengers)
routeExitThresholdRef.current = 100 + (maxCars * CAR_SPACING)
}
}
}, [state.isGameActive, state.style, state.stations, state.passengers.length, dispatch])
@@ -158,9 +165,8 @@ export function useSteamJourney() {
})
// Check for route completion (entire train exits tunnel)
// Last car is at trainPosition - (maxCars * CAR_SPACING)%
// So wait until trainPosition >= 100 + (maxCars * CAR_SPACING)% for entire train to exit
const ENTIRE_TRAIN_EXIT_THRESHOLD = 100 + (maxCars * CAR_SPACING)
// Use stored threshold (stable for entire route)
const ENTIRE_TRAIN_EXIT_THRESHOLD = routeExitThresholdRef.current
if (trainPosition >= ENTIRE_TRAIN_EXIT_THRESHOLD && state.trainPosition < ENTIRE_TRAIN_EXIT_THRESHOLD) {
// Play celebration whistle
@@ -180,6 +186,11 @@ export function useSteamJourney() {
// Generate new passengers
const newPassengers = generatePassengers(state.stations)
dispatch({ type: 'GENERATE_PASSENGERS', passengers: newPassengers })
// Calculate and store new exit threshold for next route
const newMaxPassengers = calculateMaxConcurrentPassengers(newPassengers, state.stations)
const newMaxCars = Math.max(1, newMaxPassengers)
routeExitThresholdRef.current = 100 + (newMaxCars * CAR_SPACING)
}
}, UPDATE_INTERVAL)