Skip to content

Contains programming spoilers and example solutions.

Programming tips

This section contains some tips and tricks for programming your robot.

Repeated mining

The default program includes the mine(); action. However, most of the time your robot won't be able to gather all ore from the mining spot with only one mining action. Since the mine() action returns the amount mined, you can use a while loop to continue mining until there is no ore left:

while (mine() > 0)
{
}

When the while loop is started, the while-expression is evaluated. When the expression evaluates to 'true', the code-block is executed and the process is repeated. When the expression evaluates to 'false', the code-block is skipped and the program continues after the while loop.

Since the actual action, the mining, is already done in the expression, the code-block can be empty. To make the code more simple, we can skip the body altogether by adding a semicolon after the expression:

while (mine() > 0);

There's another trick to make the code more efficient. A numeric value of 0 will be evaluated as 'false', all other numeric values will be evaluated to 'true'. The mine() action itself will return 0 when nothing is mined, which will be evaluated as 'false'. It will return a value larger then zero when something is mined, which will be evaluated as 'true'.

So by replacing 'mine() > 0' by 'mine()', we get exactly the same result:

while (mine());

This will efficiently mine all ore from the current robot position.

One-time actions

When the robot reaches the end of its program, the program is restarted. This is fine with the initial code, but sooner or later you'll want to add some code that's only executed once.

To achieve this, you can use a while-loop. A while loop contains a block of code that is repeatedly executed until the expression evaluates to 'false'.

The expression can be some calculation or comparison, but it can also be a constant value. When you use the constant value 'true', the block is executed repeatedly until the mining session ends or the robot's battery is depleted.

‹Insert the one-time code here>

while (true)
{
    ‹Insert the repeated code here>
}

Detecting a collision

You can move your robot forward by using the 'move(..)' command. Sooner or later, however, your robot will collide with a wall or another robot. Ignoring this collision and continuing to move forward will repeat the collision over and over again, assuming the robot you're colliding with doesn't solve this problem for you.

To continue looking for ore to mine after a collision, there are two steps needed:

  • Detect the collision.
  • Take action to avoid repeating the same collision over and over again.

The move(..) command returns the actual distance traveled. This can be used to detect the collision. For instance, replace the default 'move(1);' with the following:

if (move(1) < 0.9)
{
    ‹Insert some smooth collision-avoiding moves here>
}

Now why is the move result compared with 0.9 and not with 1?

The mine() command always returns a round number, the amount of ore mined. This can be 0, 1, 2, 3, etc. but never 0.5 or 1.3.

The move(..) command, however, returns a 'floating point' value. And the actual distance traveled can be 1.00000001 or 0.9999999.

When we compare to 1 and the actual distance traveled turns out to be 0.9999999, we would assume we've collided with something while we didn't. So by comparing to 0.9 we can avoid this mistake.

For the same reason, comparing to 0 would be unsafe while 0.1 would be a good value.

Avoiding repeated collisions

When we've detected a collision, we need to do something to avoid repeating that collision on the next move. There are a lot of ways to do this, so don't be afraid to try something completely different from this example.

The first action we could do is moving backwards a bit. Moving backwards is done with the 'move(..)' command too, but with a negative distance instead of a positive. 'move(-1);' for example would do the trick.

As a next step we could do a rotation. 'rotate(135);' will rotate the robot clockwise. If you prefer to rotate counter-clockwise you can use a negative number.

As a final step we can move forward again. Since the robot is moving in another direction now, chances are we won't collide anymore.

The final code, including the collision detection, will look something like this:

if (move(1) < 0.9)
{
    move(-1);
    rotate(135);
    move(1);
}

Selective mining

Most ore fields contain more then one type of ore. However, you're most probably only interested in one type. Since your ore container has a limited size and the mining session has a limited amount of cycles, you'll prefer your robot to pick the right type of ore instead of mining everything it can find.

The easiest way would be to tell your robot to mine only the best type of ore. However, since the robots mining unit can't tell the difference between the types of ore, the solution needs to be more complicated.

The mining unit can't tell the difference between two types of ore, but the ore container can. Read how much is stored with robot properties:

  • robot.oreStored — total ore in the container.
  • robot.oreStoredA — highest-quality ore in the container.
  • robot.oreStoredB — medium-quality ore in the container.
  • robot.oreStoredC — lowest-quality ore in the container.

We can use robot.oreStoredA to keep track of the amount of high quality ore. By comparing that value before the mine() action with the value after mine(), we can tell whether we've mined the ore we want or not.

Since robot.oreStoredA only tells the current amount of high quality ore in the container and not the previous amount, we'll need to store it before we start mining.

For this, we can use a variable:

int amountBeforeMining;

do {
    amountBeforeMining = robot.oreStoredA;
    mine();
} while (robot.oreStoredA > amountBeforeMining);

This will repeat the mining process until there is no more high quality ore to mine at the current robot location.

Ore Scanner

The ore scanner allows the robot to scan the area for ore and return the type and distance of the ore. A scan can be initiated with the scan() command, optionally with a direction parameter. After a scan, the oreType() and oreDistance() commands can be used to get the type and distance of the ore found, if any. If the ore is of the type you want, you can move to the ore with the move(oreDistance()) command.

scan();
if (oreType() == 1)
{
    move(oreDistance());
    while (mine());
}

Scanning in a direction returns the ore type and distance along that ray relative to the robot's position and orientation when scan() started (not when the scan finishes). If the ore is of the type you want, you can rotate into the direction of the ore and move to the ore with the move(oreDistance()) command.

scan(90);
if (oreType() == 1)
{
    rotate(90);
    move(oreDistance());
    while (mine());
}

Nested heaps and mixed cells

Later areas often place a small high-value heap inside a larger lower-value heap. To handle this correctly, keep the following in mind:

  • scan() reports the nearest ore of any type, not "nearest type 1 only".
  • mine() collects every type on the cell under the robot.
  • dumpB() drops only medium ore; dumpC() drops low; dump() dumps everything.
  • dump() / dumpA() / dumpB() / dumpC() place ore on the ground (or into the depot at spawn). If you run mine() again without moving after dumpB() or dumpC(), you'll mine the same ore again.

More detail on scan, mine, and dump is in the Mechanics and Robot programming guides.

Using the depot

Once achievements unlock depot capacity for an ore type, dumping that ore at your spawn corner banks it for the rest of the rally without taking container space. Overflow still goes onto the ground, so a full depot behaves like a normal dump at home.

A useful pattern is to mine until the container is full of the ore you want to keep, navigate back to spawn using robot.xPos and robot.yPos (both are 0 at the rally start corner), then dump:

while (robot.oreStored < robot.oreCap)
{
    // mine and seek as usual...
}
// Face and move until robot.xPos and robot.yPos are back near 0, then:
dump();

Depot dumps only apply when you are on that spawn corner. Mechanics explains capacity, scoring, and what the replay markers mean.