*(This tutorial is very much in progress so nonsense is likely.)*

Two-dimensional **vectors** are used a lot in Grobots, mostly to represent positions and velocities. This tutorial is intended to help you understand how to use vector arithmetic to write sides.

## Vector basicsEdit

Grobots uses vectors for positions and velocities. A vector in Grobots is represented by its two components. For example the grobots code `3 4`

pushes 3 and then 4 onto the stack, which can be interpreted as the vector with an x-component of 3 and a y-component of 4.

Vectors can be added with `v+`

and subtracted with `v-`

.

For example, if *vect-a* is a variable holding the vector (2, 5) and vect-b is a variable holding the vector (-1, 3), the code

vect-a vect-b v+

would leave the vector (1, 8) on the stack.

`norm`

returns the length of a vector using the Pythagorean theorem.
Length.

vs* and vs/. These can be understood either as multiplying the components by the scalar or by multiplying or dividing the length of the vector by the scalar leaving the direction unchanged.

## Summary of Grobots syntaxEdit

(Table here describing v+, v-, vs*, vs/, norm, angle, rect-to-polar, polar-to-rect, unitize, vnegate, dot, cross, and project. Note that all but the first five will be discussed later. Or link to the vector section of the language reference?)

`dist`

and `in-range`

Edit

The Grobots built-in `dist`

computes the distance between two vectors: `p1 p2 dist`

, where p1 and p2 are vectors, is equivalent to `p1 p2 v- norm`

or in math notation |* p1*-

*|. The vector*

**p2**`p1 p2 v-`

is the vector from *to*

**p2***; to see this draw a picture. Therefore*

**p1**`p1 p2 v- norm`

is the distance from *to*

**p1***.*

**p2**The Grobots built-in `p1 p2 d in-range`

, where p1 and p2 are vectors and d is a scalar, determines whether or not p1 and p2 are within a distance of d. It's equivalent to `p1 p2 dist d <`

.

`seek-location`

Edit

Many basic gatherers (e.g. the Animal side in the main tutorial) includes the code `food-position seek-location`

to move the robot towards the food. So what does that do? That code is equivalent to the following:

position velocity 11 vs* v+ food-position radius in-range if engine-max-power engine-power! food-position position v- 0.09 vs* engine-velocity! else 0 engine-power! then

`position velocity 11 vs* v+`

is where we'll be in 11 frames if we continue moving at our current velocity. The condition of the `if`

therefore gives us an idea if we're on track to being within our radius of the food soon (and hence close enough to eat it). If we are on track then we turn off the engine to save energy. If not, we turn on the engine with `engine-max-power engine-power!`

. To set `engine-velocity`

we first compute the vector displacement that we desire: `food-position position v-`

. We don't want to do all of this in just one frame, so we multiply by 0.09 to get the velocity. Equivalently we could have written `food-position position v- 11.1111 vs/ engine-velocity!`

, which shows the interpretation: we want to (ideally) move at whatever velocity would get us there in about 11 frames, so as we approach the destination, we'll slow down.

## Chasing shots and unitize operatorEdit

To chase a shot it's helpful to get a vector in the opposite direction as `shot-velocity`

with length say 0.2. Getting the opposite direction can be accomplished by multiplying by -1, for which a short-hand `vnegate`

exists. This can be accomplished using operations described so far using `shot-velocity vnegate 0.2 shot-velocity norm / vs*`

, but that's inconveniently long, especially if shot-velocity is replaced with a more complicated expression. An alternative is to use the `unitize`

operator, which changes the length of a vector to 1 by doing `2dup norm vs/`

. We can also multiply the length by -0.2 instead of multiplying by -1 (the vnegate) and then 0.2. In summary The faster way to do the task at the beginning of this paragraph is `shot-velocity unitize -0.2 vs*`

.

## Angles and polar formEdit

So far we've determined the lengths of vectors but we haven't changed the length nor considered direction at all. To quantify direction one can use `angle`

, which returns the angle between a vector and the x-axis. If the vector points upwards (y-component positive) the angle is positive and if the vector points downwards it is negative. Angles in grobots use radians, where a full revolution/turn is 2pi instead of the customary 360 degrees.

A vector can be represented as *x* and *y* coordinates ("rectangular form"), or as a magnitude computed with `norm`

and a direction computed with `angle`

("polar form"). Rectangular form is more convenient for most purposes, but polar form is more convenient for direction-related purposes like firing weapons. The Grobots primitives `rect-to-polar`

and `polar-to-rect`

convert between them.

Let's suppose we want to limit the speed we travel to say 0.05 for efficiency. This can be done without polar form: engine-velocity unitize engine-velocity norm 0.05 min vs* engine-velocity!. A better way is via polar coordinates: `engine-velocity rect-to-polar swap 0.05 min swap polar-to-rect engine-velocity!`

. In this case both versions are 8 instructions, but if engine-velocity is replaced with another vector the polar form version pulls ahead.

One thing that can't be done without polar form is changing the direction of a vector. For example when running away from a shot it's helpful to run at an angle from the shot rather than straight away so that shots in the air don't hit. To flee from a shot at speed 0.2 and direction 0.4 radians from the shot's direction of travel use `0.2 shot-velocity angle 0.4 + polar-to-rect engine-velocity!`

.

Rotating a vector pi/2 counter-clockwise (90 degrees) is a simple operation using what we've described so far: `rect-to-polar pi/2 + polar-to-rect`

. Some code uses the shorter but difficult to read `negate swap`

for the same purpose. `swap negate`

rotates pi/2 clockwise. So don't be surprised if you see those idioms in sides you read.

## Movement in combatEdit

Movement in combat usually has two goals: stay within range of the enemy but only barely, and passively dodge to reduce the chance of being hit. Here's some code based on RK:

## Circling a foodEdit

Active 9's gatherers do a form of passive dodging when hurt: circling a food. The relevant code is:

## Rotating the coordinate axes and Active dodgingEdit

These topics are described in the Active Dodging Tutorial.