I keep forgetting that its not just lying around..
unction FindTileOnPath(var Index: integer; Path: TTileArray; P: TTile; MaxDist: Integer): Boolean;
var {Find the closest tile in a path within MaxDist}
I, H, DistC, DistS, T: integer;
begin
T := GetTimeRunning;
H := High(Path);
Index := -1;
if (H < 0) then Exit;
DistS := Distance(P.x, P.y, Path[0].x, Path[0].y); //Distance from Current Tile
for I := 0 to H do //Looks for the Closest Tile
begin
DistC := Distance(P.x, P.y, Path[I].x, Path[I].y);
if DistC <= DistS then
begin
DistS := DistC;
Index := I;
end;
end;
Result := DistS <= MaxDist;
if not Result then Index := -1;
WriteLn('FindTileOnPath: Index = ' + IntToStr(Index) + ' Time: ' + IntToStr(GetTimeRunning - T) + ' ms');
end;
function FurthestVisibleTile(tPath: TTileArray; P: TTile; sTile, eTile: Integer): Integer;
var {Returns the Index of the furthest tile in a path }
H: Integer; {between given indices that is still on the MM}
begin
SetLength(tPath, eTile + 1); //Removes tiles not in range
InvertPath(tPath);
SetLength(tPath, Length(tPath) - sTile);
InvertPath(tPath);
H := High(tPath);
for Result := H downto 0 do //Finds the furthest visible tile.
if (Sqrt(Sqr((tPath[Result].X - P.X) * 4.0) + Sqr((tPath[Result].Y - P.Y) * 4.0)) < 69.0) then
begin
IncEx(Result, sTile);
Exit;
end;
Result := -1;
end;
{
Creates a TPA between points, tDist intervals, Rand randonmness (Tiles)
}
function CreatePathBetween(fT, tT: TTile; tDist, Rand: Integer): TTileArray;
var
hyp, xR, yR: Extended;
l: Integer;
begin
if not LoggedIn then Exit;
{ Set Result Length and first point at initial tile. }
SetLength(Result, Ceil(Distance(fT.X, fT.y, tT.X, tT.Y) * 1.0 / tDist) + 1);
Result[0] := fT;
{ If no need for intermediate tiles then nvm. :) }
if (Distance(fT.X, fT.Y, tT.X, tT.Y) <= tDist) then
begin
Result[High(Result)] := tT;
Exit;
end;
{ Ratios for 'Similar Triangles' maths. }
hyp := Hypot(fT.X - tT.x, fT.Y - tT.Y);
xR := (tT.X - fT.X) / hyp;
yR := (tT.Y - fT.Y) / hyp;
{ Set points. }
for l := 1 to High(Result) - 1 do
begin
Result[l].X := Round(fT.X + l * tDist * xR) + RandomRange(-Rand, Rand);
Result[l].Y := Round(fT.Y + l * tDist * yR) + RandomRange(-Rand, Rand);
end;
{ Last point is tT. }
Result[High(Result)] := tT;
end;
{
Expands ctrlPoints into a path with tDist intervals and Randomness
}
function ExpandPath(ctrlTiles: TTileArray; tDist, Randomness: Integer): TTileArray;
var
i, h: Integer;
t: T2DPointArray;
begin
Result := [];
h := High(ctrlTiles);
SetLength(t, h);
for i := 1 to h do
t[i - 1] := CreatePathBetween(ctrlTiles[I - 1], ctrlTiles[I], tDist, Randomness);
Result := MergeATPA(t);
end;
{
Walks to a path.
}
function EnterPath(Path: TTileArray): Boolean;
var
I: Integer;
tmpPath: TTileArray;
begin
if (FindTileOnPath(I, Path, GetMyPos, 50)) then
begin
{ Create path between current tile and closest path tile }
tmpPath := CreatePathBetween(GetMyPos, Path[I], 3, 5);
Result := WalkPath(tmpPath);
if (Result) then Exit;
end;
WriteLn('Could not enter path!');
end;
{
Walk to a tile.
}
function WalkTile(T: TTile): Boolean;
begin
Result := EnterPath([T]);
end;
{
Walk to a path.
}
function Walk(Path: TTileArray; Destination: Integer): Boolean;
var
P, DTile: TTile;
H, D, tileInd, pInd, Attempts, time: Integer;
begin
time := GetTimeRunning;
H := High(Path);
if (H < 0) then Exit;
if (Destination = -1) then
D := H
else
D := Destination;
{ Expands path and finds new destination index }
DTile := Path[D];
Path := ExpandPath(Path, 1, 3);
H := High(Path);
FindTileOnPath(D, Path, DTile, 3);
{ Finds you on a path and attempts to walk to it if possible }
if (not(EnterPath(Path))) then
begin
p := GetMyPos;
WriteLn('E:: Lost en route. ' + IntToStr(p.x) + ', ' + IntToStr(p.y));;
LogOut;
Exit;
end;
FindTileOnPath(pInd, Path, GetMyPos, 5);
if (pInd > D) then
begin
{ Sorts out walking direction }
InvertPath(Path);
D := H - D;
pInd := H - pInd;
end;
P := GetMyPos;
{ Loops through the tiles and walks :) }
while (Distance(P.X, P.Y, Path[D].X, Path[D].Y) > 3) and (Attempts < 5) do
begin
tileInd := FurthestVisibleTile(Path, P, pInd, D);
{ If the furthest tile is found, Walk to it! }
if (tileInd > -1) then
begin
WriteFMT('Next Tile: %d (%d, %d)',
[tileInd, Path[tileInd].X, Path[tileInd].Y]);
if (WalkToTile(Path[tileInd],
0,
RandomRange(1, 4)*Integer(Random(20)<>0))) then
begin
Attempts := 0;
Wait(100 + Random(100));
P := GetMyPos;
FindTileOnPath(pInd, Path, P, 5);
end;
end;
Inc(Attempts);
end;
R_FFlag(0);
Result := (DistanceFrom(Path[D]) <= 5);
if (not(Result)) then
WriteLn('Walk failed');
end;
Some functions names have changed, but the algorithm still works as of a few months ago. I see no reason why it wouldn't. Basically, you just supply a series of control points to ExpandPath and it will fill in the rest of the points that are necessary and will make sure that they are within the flag distance before clicking (they are calculated to make sure). The expanding algorithm will also veer off and back repeatedly to make the path random.. I never did any drawings of how it worked. But it was legit flawless before we tried updating it and forgot about it.
Hell the points are probably all still valid in that script.. :P Fastest mining anyone *ever* did. But it took a lot of data-mining.
Anyway, the fill sauce is here:
http://code.google.com/p/nzmm/source/browse/trunk/?r=9