Take this example for determining which lane of a road for a car to be in, ripped directly from my code, so somewhat messy.
if(NAV_GetState(car->pilot,NAV_ISPERP))
{
DoubleSwitchLanesWeight = 0.0f; // The higher this is the less likely a car is to try to change two lanes at once
laneWeightThreshold = 150.0f; // The lower this is the more likely a car is to slow behind other traffic
StickToLaneWeight = 20.0f; // The higher this is the more likely a car is to choose it's current lane
SpeedWeightDivider = 1.0f; // The higher this is the less likely a pilot is to change lane for speed
FlightMultiplier = 0.0f; // The higher this is the less likely a pilot is to damage other cars/themselves to get into a lane
OppositeDirectionWeight = -200.0f; // The higher this is the less likely a car will take a lane going in the opposite direction
SideWalkWeight = -200.0f; // The higher this is the less likely a car will use a sidewalk
}
else
{
DoubleSwitchLanesWeight = 30.0f; // The higher this is the less likely a car is to try to change two lanes at once
laneWeightThreshold = 50.0f; //50 // The lower this is the more likely a car is to slow behind other traffic
StickToLaneWeight = 100.0f; //75 // The higher this is the more likely a car is to choose it's current lane
SpeedWeightDivider = 2.0f - car->pilot->agro; // The higher this is the less likely a pilot is to change lane for speed
FlightMultiplier = 1.0f; // The higher this is the less likely a pilot is to damage other cars/themselves to get into a lane
OppositeDirectionWeight = -2000.0f; // The higher this is the less likely a car will take a lane going in the opposite direction
SideWalkWeight = -2000.0f; // The higher this is the less likely a car will use a sidewalk
}
The first instance is for a getaway driver, the second is for a normal car trying to drive legally.
These values are used in a series of computations to determine the following weights
totalWeightFromLane
which is the sum of
weightFromAlreadyBeingInLane
weightFromNextCorner
weightFromLaneDistance
weightFromLaneDisappearing
weightFromForwardObstacle
weightFromRearObstacle weightFromCurveObstacle
weightFromBeingStuck
weightFromLaneBeingIllegal
Each of which represent different factors in driving.
The weights are totalled up and the car switches to the lane with the new highest value.
As the values are all floats and there are so many heuristics involved, in the unlikely event of a tie (I don't think I've ever had one) it is pretty unimportant which lane the car ends up in.
No randomness but certainly not what you would consider an FSM.
The fuzziness comes from an inability for us to see the logic, not the lack of logic itself.
MikeD