Well friends,

It's Christmas Eve, my two-year-old is sleeping soundly in her bed and presents are wrapped, so what better to do than to hack away at RunZH?

As you may have seen from the beta page or the in-game MOTD (I update it! You should read it! It's relevant!), I've officially declared that we're now testing crafting. So naturally, I was poking around at the crafting system.

Couple of big bugs stood out immediately:

  1. I haven't actually implemented the "Zulu Hides" yet
  2. If you lumberjack wood from a tree, it keeps the properties of e.g. Golden Reflections, but it doesn't call itself that. It just calls itself "log".
  3. Several of the GatherNode flock escaped their enclosure (the map) and fled off into the Great Beyond.

Tracking code exposes the location of the escapee

You can see here that the x and y coordinates of the Golden Reflections GatherNode are (11371, -772) which is neat enough. But then you realise the map is only 7168 tiles wide, and negative Y coordinates should be impossible!

Well, it turns out that my algorithm was flawed. For a GatherNode with position (X, Y) and velocity (u, v):

Should GatherNode drift?
If Yes:
X' = X + u
Y' = Y + v
Would (X', Y') be out of bounds?
If Yes:
Reflect about the nearest axis:
u = -u or v = -v as appropriate

X = X + u
Y = Y + v

Clever readers may spot the bug I didn't: I only check if (X', Y') is out of bounds, but it's possible at the corners of the map to have the reflected vector still end up outside the map, and that dear friends is how the odyssey of the Golden Reflections GatherNode began. The poor little Node had been traveling for upwards of 2200 world saves only for its escape to be foiled!

Alas for poor Golden Reflections GatherNode, the code is much simpler now and the tyrannical modulo operator brooks no disagreement nor tolerates any escape. We cannot remove all freedom, however (we aren't barbarians), so we allow the little GatherNodes the opportunity to mutate their velocity vectors every so often.

public void Mutate() {
        if( m_mutatechance <= Utility.RandomDouble() ) {
        m_vX = Utility.RandomMinMax(-10, 10);
        m_vY = Utility.RandomMinMax(-10, 10);

    public void Drift() {

        if ( m_driftchance >= Utility.RandomDouble() ) {

        m_X = ( m_X + m_vX ) % m_xbound;
        m_Y = ( m_Y + m_vY ) % m_ybound;

        Mutate(); //keep it gangsta

Merry Christmas!