Daniel P. Barron

The drunken explorer.

Saturday, December 17, 2016 

The charge was made that a new mining style should be introduced to foxybot. Just so happens I had already resolved to come up with one for my own purposes. The default ‘line’ method causes characters to drift up hills,i and requires somewhat frequent supervision to keep it in the right spot. Not only this, but the “right spot” is often a small point, or at least a round sort of area; that is, not a thin line. To make the line explore method cover a more reasonable area, I used it in combination with an xmacro script that turned my character periodically, and then sent a pilot command to aim him back at the optimal gathering spot. This was the functionality I intended to add to foxybot, but Mircea’s request for a drunken walkii method inspired me to finally do it.

Here’s how to add the ‘drunk’ explore method to foxybot.

In botactivity.h, add a new constantiii for this style:

//explore strategies for the explore activity

In botactivity.cpp:

In ExploreActivity::DoInit(), add this if statement where it checks "words:"iv

			else if (s.CompareNoCase(csString("drunk")))
				strat = EXPLORE_DRUNK;

In MovementStrategy::Move(), add this case to the switch:v

		if (movesDone == 0)vi
			startPos = worldHandler::GetCurrentPos();vii
		else if (((double)rand() / (double)RAND_MAX) < ((double)size / ((double)size + (double)pow(size, 0.5))))viii
worldHandler::Turn(((double)rand() / (double)RAND_MAX) * M_PI * 2);ix
else worldHandler::TurnToPoint(startPos.x, startPos.z);x


That's all there is to it!

  1. This is because characters move faster up-hill than they move down-hill, and the difference causes high points to act as bot attractors.

  2. It’s very simple. In each iteration of the bot activity, the character turns to a random angle and walks forward one step.

  3. Each constant just replaces a number so that instead of saying “mining style #4” we can say “the drunken mining style.”

  4. This corresponds to when the user types /bot explore 999 drunk ...

  5. This switch is where we can define how drunken mining is to work.

  6. First we check if this is the first explore attempt

  7. store the character’s starting position. This is used to keep the bot focused on one spot; we don’t want our characters to fall down any cliffs!

  8. decide if the bot will move randomly in this itteration or if it will move towards the starting point. It takes the "size" from the user command-- that is, the 24 in /bot explore 999 drunk 24 1 7 ... --and uses it to make a fraction which is compared to a random number. We want the bot to move towards the center square-root-of-size many times per size-plus-square-root-of-size explore attempts, which is the same thing (assuming infinite tries) as moving randomly for 'size' many tries, and then towards the center for square-root-of-size many tries.
    Example of a literal-to-Mircea's-spec version of the drunken logic:
    		if (((double)rand() / (double)RAND_MAX) < (pow(size, 0.5) - floor(pow(size, 0.5))))
    			if ((movesDone % (int)(size + ceil(pow(size, 0.5)))) < size)
    				worldHandler::Turn(((double)rand() / (double)RAND_MAX) * M_PI * 2);
    			else worldHandler::TurnToPoint(startPos.x, startPos.z);
    			if ((movesDone % (int)(size + floor(pow(size, 0.5)))) < size)
    				worldHandler::Turn(((double)rand() / (double)RAND_MAX) * M_PI * 2);
    			else worldHandler::TurnToPoint(startPos.x, startPos.z);

    This version is more precise if the supplied 'size' is a perfect square; otherwise the non-integer remainder of the square root is compared against rand() to preserve the substance of non-perfect-square values of 'size' in determining how far to go before re-centering. I leave it up to you to decide which method is the correct. I prefer the simpler, more random way; it more accurately models the movement we desire, which is that the character will move around a particular point in a random manner. The 'size' input lets you define how far the character will stray from the start point.

  9. tells the character to turn to a random angle. It simply multiplies 2*pi and a random fraction and feeds it to a function that turns the character.

  10. this is where we aim back at the start position.

  11. make the character move foward.

One Response

  1. [...] I had previously described how to make your Eulora character explore like a drunk. This is a very useful method when the area you are trying to target is closer to a point. The drunk explorer has a strong preference for gathering closer to the starting location; even at large size settings, the distribution will still put most of the attempts near the center. I have created a graph of 10`000 explore attempts using the drunk method in order to demonstrate this property. It looks like a fuzzy paintbrush tool from an image manipulation program. [...]

Leave a Reply

Your criticism is welcome. Your name and website are optional. Some HTML tags are allowed.