Let me know if this is off topic, but as a developer, my eyes were opened when I learned genetic algorithms. While the mathematics are tangential to actual biology, I think it illustrates the mechanism of an environmentally directed evolution of random mutations. An example I have is here:
https://github.com/Jarrod1937/genetic-algo-example/blob/master/ga/Form1.cs
The mutations are random, but the fitness function defines when the mutation is beneficial. In the case of a virus, the virus successfully propagating is the fitness function, and thus those of a higher fitness are more likely to propagate more, thus you see the increasing adaption against things that prevent propagation. However, this isn't the virus knowing where or how to adapt, rather, it is a case of sample bias. Your sample of viruses are the ones that survived and propagated, you don't see all of the failures that came before.