GCPP:Proposal-Arowana/Implementation Notes

The Runner
The runner is the player's piece that moves on the board. It is defined by its position on the board, and its current speed. For the sake of simplification, let us assume it is round, so it is further defined by its radius.

Because the speed might be very low at a given time, it is given in units of 1/100 pixels per tick. Because the position has to change even if the speed is very slow, the position is also given in units of 1/100 pixels.

int x; /** Runner horizontal position in 1/100 pixels */ int y; /** Runner vertical position in 1/100 pixels */ int dx; /** Runner horizontal speed in 1/100 pixels per tick */ int dy; /** Runner vertical speed in 1/100 pixels per tick */

For the sake of simplicity, rotation momentum is not taken into account.

Static parameters
These parameters define the puzzle mechanics.

int viscosity; /** kinematic viscosity factor for runner natural slow down, in percent */ int radius; /** runner radius for collision detection, in 1/100 pixels */ int lineInterval; /** interval between two vertical lines that slow down the runner, in 1/100 pixels */ int minSpeed; /** speed at which the run should be stopped */

Acceleration
If it is in the zone of influence of an obstacle, the runner's speed will be affected:

dx = dx + ax; dy = dy + ay;

Finally, the runner's speed will also slowly decrease. We apply a kinematic viscosity factor.

dx = (dx * v) / 100; dy = (dy * v) / 100;

This happens each time the runner has crossed a vertical line. These lines are placed at a regular interval k. The interval in which the runner lies is x / k. So the test for decreasing the speed is that the interval has just changed:

((x - dx) / k) != (x / k)

Movement
Each tick, the runner's speed affects its position:

x = x + dx; y = y + dy;

Check for runner stop
The speed is reduced every time the runner crosses a vertical line. Ultimately, the speed will be so slow that the course should be declared as ended. This is checked using a speed threshold:

(dx * dx) + (dy * dy) < minSpeed * minSpeed

If this condition is met, the run is considered as ended and the score is counted.

Check for course completion
The course is completed when the runner has exited the board on the opposite side as it has entered.

Check if the runner has exited the board
x < 0 x > boardWidth y < 0 y > boardHeight

Check for loops
The number of loops the runner goes around an obstacle has to be counted for the scoring. Seen from the obstacle, the runner position gives an "azimuth". Each tick, this azimuth changes of a small angle.

Each tick, we integrate this angle. If it goes over 2xPi, then the runner has gone one time around the obstacle. A score message can be shown, for example.

For an obstacle o:

Vector v1 = (x - o.x, y - o.y); Vector v0 = (x - dx - o.x, y - dy - o.y); int vProduct = v1.x * v0.y - v1.y * v0.x; int sProduct = v1.x * v0.x + v1.x * v0.x;  o.angle += asin(vProduct / sProduct);

Math/Physics notes
Just some quick notes of open source NetLogo models that I can easily steal some math formulas from if they are needed.
 * If an obstacle is actively repelling the moving needle
 * If an obstacle is actively attracting the moving needle, such as with gravitation
 * Erosion