Unfortunately there's no way to tell the Factorio path finder to avoid enemy bases, so repathing wouldn't do any good as we'd just get the same cached path back.
[…]
I suppose we could make the enemy sensor behave as a panic-and-run-away sensor when a car is unarmed...
That is exactly what I meant with "repathing"! :-)
Unarmed means the car has no gun(s). The enemy sensor doesn't check ammo, it only detects enemies and fires the gun if available. It won't send a car after enemies, nor attract enemies any more than a car without sensors does.
According to the info page, you shouldn't need the ammo sensor either to detect whether the vehicle weapon has ammo:
Ammo sensor: Car will reload ammunition from its inventory.
I'd interpret this in the way that the ammo sensor (as well as the enemy sensor) would somehow know the ammo inventory, but the ammo sensor would check the trunk inventory for ammo if the weapon has run out of ammo, and reload it. If the vehicle has a weapon, if there is ammo in the trunk, and if an ammo sensor is installed in the vehicle, the weapon will always be loaded -- otherwise, the vehicle should go into panic mode if enemies were near.
How about this (using code from your control.lua in the following)?
908 local enemy = nil
909 local gun = nil
910 local driver = car.get_driver()
911 local passenger = car.get_passenger()
912 local trunk = car.get_inventory(defines.inventory.car_trunk)
913 local ftank = car.get_fuel_inventory()
914 local clip = car.get_inventory(defines.inventory.car_ammo)
915
916 if car.prototype.guns then
917 for _, g in pairs(car.prototype.guns) do
918 gun = g
919 break
920 end
921 end
922
923 if state.enemy_sensor and gun then
924 enemy = car.surface.find_nearest_enemy({
925 force = car.force,
926 position = car.position,
927 max_distance = gun.attack_parameters.range + 3,
928 })
929 end
930
I would change the enemy sensor code to
923 if state.enemy_sensor and gun and clip and not clip.is_empty() then
924 enemy = car.surface.find_nearest_enemy({
925 force = car.force,
926 position = car.position,
927 max_distance = gun.attack_parameters.range + 3,
928 })
929 else (Panic mode) end
930
(If present, the ammo sensor would have loaded the weapon, so trunk is empty and can be neglected.) I'm not sure if that's necessary, but just to be on the safe side, I'd move lines 931-941 before line 923. This way it should be certain that no ammo is left in the trunk before the enemy sensor decides that the vehicle should go hunting:
931 -- reload
932 if state.ammo_sensor and gun and trunk and clip and clip.is_empty() then
933 for item, count in pairs(trunk.get_contents()) do
934 local stack = { name = item, count = count }
935 if clip.can_insert(stack) then
936 notify(state, "reload")
937 trunk.remove({ name = item, count = clip.insert(stack) or 1 })
938 break
939 end
940 end
941 end
What do you think about this?