AI agent fails when aligned with its target
⚔️ A.I. vs. Physics

To solve this, you need to think a bit about the physics of your simulation, because it creates a problem for your A.I.

The funny thing is, you solved it by just altering the vectors a bit, but you seem to not understand why, so let us change that!







 May the force be with you

To put it simply: when you put two vectors on the same axis perfectly aligned, all that will happen is that the stronger force (i.e. greater vector) wins. Applying that to your simulation: when you align the agents on the same axis, the force of attraction towards the green agent wins over the repulsion from the red agent, forcing it ever closer towards it. I assume we all know what happens when the distances become zero, and you inevitably divide by zero? If you don't know: you can't. Other languages would panic, and Javascript just gives back NaN. Doing arithmetic with NaN will always yield NaN so the program still crashes somewhere down the line.

So that is the problem. But why did your "hack" fix it, and how do you embrace the fix as a proper solution?







 Solution

This is where the A.I. comes in. Think about it as if you were the blue agent: if you were walking straight towards an obstacle you are not allowed to touch, what would you do? I presume you would pick a direction, and turn into that direction to avoid the obstacle. Your agent is not as smart as you, so it does nothing and keeps its direction. When you added a tiny offset to its target vector, you decided it should change direction, albeit in a clunky way.

I propose you add a "preference" to the blue agent, deciding which direction to turn when it is perfectly aligned on some axis. You can use your fix, but I would personally prefer a solution to be more deliberate:

const degreesToRadians = degrees =&gt; degrees * (Math.PI / 180);
const rotate = (x, y, radians) =&gt; [
  x * Math.cos(radians) - y * Math.sin(radians),
  x * Math.sin(radians) + y * Math.cos(radians)
];

const preference = degreesToRadians(15);
const inProximity = lengthObstacle &lt; 60;
const aligned = vectorTargetX === 0 || vectorTargetY === 0;

if (inProximity &amp;&amp; aligned) {
  [agentX, agentY] = rotate(agentX, agentY, preference);
}
```