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 walk ii method inspired me to finally do it.
Here’s how to add the ‘drunk’ explore method to foxybot.
In botactivity.h
, add a new constant iii for this style:
//explore strategies for the explore activity enum EXPLORE_STRATEGIES { EXPLORE_RADIAL = 1, EXPLORE_GRID = 2, EXPLORE_LINE = 3, EXPLORE_DRUNK = 4 };
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
case EXPLORE_DRUNK: { 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); xworldHandler::StepForward(); xi
}
That's all there is to it!
- This is because characters move faster up-hill than they move down-hill, and the difference causes high points to act as bot attractors. ^
- It’s very simple. In each iteration of the bot activity, the character turns to a random angle and walks forward one step. ^
- Each constant just replaces a number so that instead of saying “mining style #4” we can say “the drunken mining style.” ^
- This corresponds to when the user types
/bot explore 999 drunk ...
^ - This switch is where we can define how drunken mining is to work. ^
- First we check if this is the first explore attempt ^
- 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! ^
- 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); } else { 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. ^ - 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. ^
- this is where we aim back at the start position. ^
- make the character move foward. ^
[...] 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. [...]