SRL Archive - Research & Development Lounge

SPAM/S - dynamic, locationless walking!


mixster

2009-08-30 21:20:21

Satellite Positioning Around Map / System.
Basically, it uses the built in RS world map to generate routes to various destinations.

At the moment, it's in a beta stage - I would like to see it go much further and it is functioning to some point, but not quite as much as I would like it too. The system basically collects all the road points it can find, puts them through TPAToATPA then collects midpoints to filter it out a bit for speed. Finally, it uses the A* algorithm to generate the shortest path from where you are to your destination, with where you are being the centre of the world map and in this first version the destination is a bank (not the nearest if there's 2 though).

So anyway, converting the path you generate to be able to use in RS is the next step. I initially use TPAToATPA again to make the steps much larger so that it's not crap loads of tiny steps and instead a medium amount of medium steps. After that, go through all the points and get the difference between the current point and the previous point to determine where to click then apply a ratio to it (75% default for world map = x and y offset from MMCX/Y would be * 4/3 or 1.333) and click! Continue this until the end and you should, hopefully, end up where you wanted to.

So, how to get the destination? That is the question! At the moment, I'm just using the bank symbol.

Now, how does this help if you can't get back? Well, you can! Just invert the TPA you used to walk and run through it again and you end up roughly where you began. Else, you know where you started and where you ended up, so you know roughly where you want to walk to and so could set that as your target, use the main map centred as your starting point then produce another path and walk that one!

Now, for actual codey stuff:
This is AStar in Scar for if you don't use the plugin or don't want to. Paste it at the top of the script.


type
node = record
parent: Integer;
x, y: Integer;
f, g, h: Integer;
cl, op: Boolean;
end;

function FilterPointsDist2(var inds: TIntegerArray; x, y, dist: Integer; pts: TPointArray): Boolean;
var
h, i, p: Integer;
begin
Result := False;
p := 0;
h := High(pts);
SetLength(inds, h + 1);
for i := 0 to h do
begin
if (Distance(pts[i].x, pts[i].y, x, y) <= dist) then
begin
inds[p] := i;
p := p + 1;
end;
end;
SetLength(inds, p);
Result := p <> 0;
end;

function AStarCus(var path: TPointArray; pts: TPointArray; stI, enI, lowFilt, highFilt: Integer): Boolean;
var
nodes: array of node;
close, open, neigh: TIntegerArray;
en: TPoint;
ph, ch, oh, i, ti, tf: Integer;

begin
Result := False;
SetLength(path, 0);
if (Length(pts) < Max(enI, stI)) then
begin
Writeln('Invalid stI or enI passed to AStar');
exit;
end;
ph := High(pts) + 1;
SetLength(close, ph);
SetLength(open, ph);
SetLength(nodes, ph);

en := pts[enI];

ph := ph - 1;
for i := 0 to ph do
begin
with nodes[i] do
begin
parent := -1;
x := pts[i].x;
y := pts[i].y;
g := 0;
h := Round(Distance(x, 0, en.x, 0) + Distance(0, y, 0, en.y));
f := g + h;
cl := False;
op := False;
end;
end;

oh := 0;
ch := -1;
open[0] := stI;
nodes[stI].op := True;

repeat
if (oh = -1) then
begin
Writeln('Ran out of open nodes, exiting...');
exit;
end;

ti := 0;
tf := nodes[open[0]].f;
for i := 1 to oh do
begin
if (nodes[open[i]].f < tf) then
begin
ti := i;
tf := nodes[open[i]].f;
end;
end;
i := ti;
ti := open[ti];
nodes[ti].cl := True;
nodes[ti].op := False;
Swap(open[i], open[oh]);
oh := oh - 1;
ch := ch + 1;
close[ch] := ti;
if (Distance(nodes[ti].x, nodes[ti].y, en.x, en.y) <= highFilt) then
break;

if (not (FilterPointsDist2(neigh, nodes[ti].x, nodes[ti].y, lowFilt, pts))) then
if (not (FilterPointsDist2(neigh, nodes[ti].x, nodes[ti].y, highFilt, pts))) then
continue;

for i := 0 to High(neigh) do
begin
if (nodes[neigh[i]].cl) then
continue;
if (nodes[neigh[i]].op) then
begin
if (nodes[ti].g < nodes[neigh[i]].g) then
begin
nodes[neigh[i]].parent := ti;
nodes[neigh[i]].g := nodes[ti].g + Round(Distance(nodes[ti].x, nodes[ti].y, nodes[neigh[i]].x, nodes[neigh[i]].y));
nodes[neigh[i]].f := nodes[neigh[i]].g + nodes[neigh[i]].h;
end;
end
else
begin
nodes[neigh[i]].parent := ti;
nodes[neigh[i]].g := nodes[ti].g + Round(Distance(nodes[ti].x, nodes[ti].y, nodes[neigh[i]].x, nodes[neigh[i]].y));
nodes[neigh[i]].f := nodes[neigh[i]].g + nodes[neigh[i]].h;
nodes[neigh[i]].op := True;
oh := oh + 1;
open[oh] := neigh[i];
end;
end;
until False;

SetLength(path, 0);
repeat
SetLength(path, High(path) + 2);
path[High(path)] := IntToPoint(nodes[ti].x, nodes[ti].y);
ti := nodes[ti].parent;
until (nodes[ti].parent = -1);
SetLength(path, High(path) + 2);
path[High(path)] := IntToPoint(nodes[ti].x, nodes[ti].y);
ti := nodes[ti].parent;
InvertTPA(path);
Result := True;
end;

{.include SRL/SRL/misc/Smart.scar}
{.include SRL/SRL.scar}

procedure DeclarePlayers;
begin
HowManyPlayers := 1;
NumberOfPlayers(HowManyPlayers);
CurrentPlayer := 0;

with Players[0] do
begin
Name := 'retsxim';
Pass := '0mgl0luTr13dTh15';
Active := True;
end;
end;

const
WMX1 = 7;
WMX2 = 756;
WMY1 = 7;
WMY2 = 460;
WMCX = 375;
WMCY = 232;
CRAP = 1.33333;

var
b, t, w, h, x, y: Integer;
p, a: TPointArray;
ap: array of TPointArray;
begin
Writeln('Begin');
SetupSRL;
DeclarePlayers;
Writeln('Finished setting up');
Wait(5000);
Writeln('Logging in now');
LoginPlayer;

w := 764;
h := 504;

Wait(5000);
Writeln('Logged...');
Mouse(MMX1 - 15, MMY2 - 18, 4, 4, True);
Writeln('Opened map');
Wait(5000);
x := GetColor(100, 100);
if (not (SimilarColors(x, clBlack, 5))) then
begin
Writeln('Looks like the map loaded uber fast, hoping it isn''t a mistake');
Wait(2500);
end else
begin
Writeln('Picked color ' + IntToStr(x));
t := GetSystemTime + 12000;
while ((GetSystemTime < t) and (GetColor(100, 100) = x)) do
Wait(999);
if (GetSystemTime >= t) then
begin
Writeln('Opening the world map seems to have lagged a bit - giving it an extra 15 seconds max');
t := GetSystemTime + 15000;
while ((GetSystemTime < t) and (GetColor(100, 100) = x)) do
Wait(999);
end;

if (GetColor(100, 100) = x) then
begin
Writeln('Looks like epic failure on the map loading front, terminating...');
TerminateScript;
end;
end;

Mouse(MMCX, MMCY, 100, 100, True);
Writeln('Anti-log click');

Writeln('Now trying to detect a nearby path colour');
for b := 1 to 8 do
if FindColorSpiralTolerance(x, y, 7434361, WMCX - 15, WMCX - 15, WMCX + 15, WMCY + 15, b * 5) then
break;

if b = 9 then
begin
FindColorsTolerance(p, 7434361, WMX1, WMY1, WMX2, WMY2, 50);
Writeln('Finding nearby road colour didn''t work too well, so using preset colour with high tolerance');
end
else
begin
FindColorsTolerance(p, GetColor(x, y), WMX1, WMY1, WMX2, WMY2, 10);
Writeln('Finding nearby road colour succeeded (hopefully)');
end;
if (Length(p) < 100) then
begin
Writeln('First search failed... searching with steroids!');
FindColorsTolerance(p, 7434361, WMX1, WMY1, WMX2, WMY2, 60);
end;
if (Length(p) < 100) then
begin
Writeln('Darn, looks like our path locating flailed :<');
Logout;
TerminateScript;
end;
Writeln('Found the paths!');

FindColorsTolerance(a, 12632256, WMX1, WMY1, WMX2, WMY2, 15);
if(Length(a) < 50) then
begin
Writeln('First symbol colour finding failed, pumping up');
FindColorsTolerance(a, 12632256, WMX1, WMY1, WMX2, WMY2, 25);
end;
if(Length(a) < 50) then
Writeln('Symbol colour finding failed again, so let''s hope we won''t need it')
else
Writeln('Found the symbols');
p := CombineTPA(p, a);

Writeln('Have a total of ' + IntToStr(Length(p)) + ' points found');

ap := TPAtoATPA(p, 3);
SetLength(p, Length(ap));
b := BitmapFromString(w, h, '');
SafeCopyCanvas(GetClientCanvas, GetBitmapCanvas(b), 0, 0, w, h, 0, 0, w, h);

for x := 0 to High(ap) do
begin
p[x] := MiddleTPA(ap[x]);
FastSetPixel(b, p[x].x, p[x].y, clRed);
end;
GetBitmapCanvas(b).Ellipse(WMCX - 1, WMCY - 1, WMCX + 1, WMCY + 1);

SaveBitmap(b, AppPath + 'debug.bmp');
Writeln(AppPath + 'debug.bmp');

x := -1;
repeat
if FindSymbolIn(x, y, 'bank', 100, 50, w - 100, h - 50) then
break;
SymbolAccuracy := SymbolAccuracy - 0.1;
until SymbolAccuracy < 0.4;
if (x = -1) then
begin
Writeln('Failed a bit at finding a bank, our bad');
Logout;
TerminateScript;
end;

SortTPAFrom(p, Point(x, y));
InvertTPA(p);
SetLength(p, Length(p) + 1);
InvertTPA(p);
p[0] := Point(WMCX, WMCY);
Writeln('Going from ' + IntToStr(p[0].x) + ',' + IntToStr(p[0].y));
Writeln('Going to ' + IntToStr(p[1].x) + ',' + IntToStr(p[1].y) + '(' + FloatToStr(SymbolAccuracy) + ')');

Writeln(IntToStr(Length(p)));
t := GetSystemTime;
AStarCus(a, p, 0, 1, 8, 14);
t := GetSystemTime - t;
Writeln('Took ' + IntToStr(t) + 'ms on first run');
if (Length(a) = 0) then
begin
Writeln('Darn, it failed :<');
Writeln('Lets try pumping up the filter and crossing fingers!');
t := GetSystemTime;
AStarCus(a, p, 0, 1, 8, 18);
t := GetSystemTime - t;
Writeln('Took ' + IntToStr(t) + 'ms on second run');
end;
if (Length(a) = 0) then
begin
Writeln('Yup, it failed...');
Logout;
TerminateScript;
end;

Writeln('Path made!');

Mouse(740, 10, 3, 3, True);
Wait(2500);

ap := TPAtoATPA(a, 15);
SetLength(a, Length(ap));
for x := 0 to High(a) do
a[x] := MiddleTPA(ap[x]);

SetLength(p, Length(a));
p[0] := Point(a[0].x - MMCX, a[0].y - MMCY);
GetBitmapCanvas(b).MoveTo(a[0].x, a[0].y);
for x := 1 to High(a) do
begin
GetBitmapCanvas(b).LineTo(a[x].x, a[x].y);
p[x] := Point(Round((a[x].x - a[x - 1].x) * CRAP), Round((a[x].y - a[x - 1].y) * CRAP));
MouseMM(MMCX + p[x].x, MMCY + p[x].y, 1, 1);
Flag;
Wait(500 + Random(500));
end;

SaveBitmap(b, AppPath + 'debug.bmp');

if (FindSymbolIn(x, y, 'bank', MMX1, MMY1, MMX2, MMY2)) then
begin
Writeln('Wow, we made it to a bank! I would like to thank so many people for making this possible. My parents, Man Flardin, R0b0t1, Markus - all of you, so much love!');
Writeln('Now, for added win, let''s try walking back!');
end
else
begin
SymbolAccuracy := 0.5;
Writeln('Lowered symbol accuracy in case it was a false negative');
if (FindSymbolIn(x, y, 'bank', MMX1, MMY1, MMX2, MMY2)) then
begin
Writeln('Wow, we made it to a bank! I would like to thank so many people for making this possible. My parents, Man Flardin, R0b0t1, Markus - all of you, so much love!');
Writeln('Now, for added win, let''s try walking back!');
end
else
begin
Writeln('Well, we walked but did not make it to the bank. Darn :<');
Logout;
TerminateScript;
end;
end;

InvertTPA(a);

p[0] := Point(a[0].x - MMCX, a[0].y - MMCY);
for x := 1 to High(a) do
begin
p[x] := Point(Round((a[x].x - a[x - 1].x) * CRAP), Round((a[x].y - a[x - 1].y) * CRAP));
MouseMM(MMCX + p[x].x, MMCY + p[x].y, 1, 1);
Flag;
Wait(500 + Random(500));
end;
Writeln('End');
end.

This very ugly implementation of SPAMS *should* make it to the nearest bank and, although slightly less likely, *should* make it back to where it started. It requires that you are somewhere very close to a path though to start and I have been testing it around Draynor with walking from the mill north of Lumby to Draynor bank and back. It is very ugly and needs a lot of improvement, but it's just a beta version and it can be improved quite easily :)

So lastly, why am I sharing? The contributions of a dozen are better than just I, so it is more a public request to help set it up. At the moment, I have been thinking of converting the road related autocolour functions as part of SRL to work using the world map. Also, setting up a file of functions related to the world map - opening it, toggling functions, searching for places, clicking on the highlight buttons etc. Lastly, I still need some ideas of how to make this able to walk globally. A Method` of obtaining a world map and relating in game positions to it would be the best and if it's a static world map, then the road and so path finding could be improved heavily to make it kick ass.

Any questions, feel free to ask (oh and a debug image is saved in the Scar directory to show what it did, it initially does one of walkable nodes, then if it starts walking it draws the path it used at the end of the walk to) :)

Edit: Attached plugin, separated script into AStar and rest of script - the Scar version of AStar is a bit older, so plugin version will work slightly better. Sauce is attached with plugin, so

Edit2: Attached SPAMS.tar.gz which now uses Dijkstra. This version also comes with an old account of mine if you wish to steal it and a copy of the new SPAMS.scar file (that also has an awesome woodcutting procedure produce by Dan Cardin with adaptation by myself). If you do run it, you most likely want to remove the repeat … until (false); loop.

NCDS

2009-08-30 21:25:32

Seems like a few people are working on one of these now.

It's an interesting project though :)

Rich

2009-08-30 21:25:51

Ooo, very nice mixter. Will test it right now, and report back how it works.

Richard

EDIT:
Logged...
Opened map
Anti-log click
Found the paths!
Found the symbols
D:\Program Files\SCAR\3.20d\SCAR 3.20d\debug.bmp
Going from 375,232
Going to 257,168(0.8)
1966
Ran out of open nodes, exiting...
Took 391ms on first run
Darn, it failed :<
Lets try pumping up the filter and crossing fingers!
Ran out of open nodes, exiting...
Took 437ms on second run
Yup, it failed...
Successfully executed
Going to try it non-SMART.

Harry

2009-08-30 21:27:51

Why are you using laggy FindSymbol? It uses bitmaps, find a better way to find a bank symbol.

caused

2009-08-30 21:28:58

WooT.

Sounds great :). That would basicly enable you to walk from anywhere on the map to another location when roads lead to that destination ?

*saves for later* :D

~caused

noidea

2009-08-30 21:32:53

I love you mixster. Stop spreading my relationships :S

This is so awsome I thought twice about cheating.

mixster

2009-08-30 21:35:36

From: NCDS
Seems like a few people are working on one of these now.

It's an interesting project though :)

Thanks :)


From: R1ch
Ooo, very nice mixster. Will test it right now, and report back how it works.

Richard

Well, it should kind of half-heartedly work as long as you're near a road - I may have forgotten to mention that you should manually turn off the stuff the world map has on by default, so no "you are here" text/image, no location names and the like - just map and symbols.

From: Harry
Why are you using laggy FindSymbol? It uses bitmaps, find a better way to find a bank symbol.

Laggy FindSymbol is used until I can find a better way to store and find locations, but that in itself is a huge project so I threw it out there for any who want to help.

From: caused
WooT.

Sounds great :). That would basicly enable you to walk from anywhere on the map to another location when roads lead to that destination ?

*saves for later* :D

~caused

Basically, yes. At the moment you can only walk to things that are in range of the RS world map when you open it, but if a good system emerges for stuff mentioned at bottom of post comes up, then I can use that for global walking.

Rich

2009-08-30 21:44:26

From: mixster
Well, it should kind of half-heartedly work as long as you're near a road - I may have forgotten to mention that you should manually turn off the stuff the world map has on by default, so no "you are here" text/image, no location names and the like - just map and symbols.


That'll, hopefully, be why it failed a second time:
Logged...
Opened map
Anti-log click
Found the paths!
Found the symbols
D:\Program Files\SCAR\3.20d\SCAR 3.20d\debug.bmp
Going from 375,232
Going to 456,336(0.8)
4224
Ran out of open nodes, exiting...
Took 1110ms on first run
Darn, it failed :<
Lets try pumping up the filter and crossing fingers!
Ran out of open nodes, exiting...
Took 2454ms on second run
Yup, it failed...
Successfully executed
I'll try again with the stuff turned off.

mixster

2009-08-30 22:34:17

They cover up the path a lot, so it makes picking up the road pretty hard to do and so generating a path pretty hard - I probably should have mentioned it on my first post :)

Rich

2009-08-30 23:53:58

Oops. I ran it with the things turned off, but I forgot to copy the debug before I closed SCAR. Anyway, it walked pretty much to the bank, walked around the outside of the bank, then said it managed the walk but not make it to the bank. The bank was VEB by the way.

mixster

2009-08-31 00:08:46

SymbolAccuracy is usually quite high, so it's very probable that it just didn't pick it up due to people standing on the bank. Draynor bank, being less common, hasn't thrown that error yet. Working on fixing the thing that means it walks around the bank a bit, but shouldn't be too hard :)

marpis

2009-09-14 18:38:06

Just to let you know, this awesomeness just walked me into draynor bank, and almost back to where i started :eek:

EDIT: Here's the route. I am truly amazed how u did this in this few lines!

mixster

2009-09-14 20:19:11

Good to know - do have updated version and have pluginisationed it for speed boosts, so will upload now :)

Bobzilla69

2009-09-14 21:47:36

How do i get your new version to work?

i have plug in and
{.include SRL/SRL/misc/Smart.scar}
{.include SRL/SRL.scar}

procedure DeclarePlayers;
begin
HowManyPlayers := 1;
NumberOfPlayers(HowManyPlayers);
CurrentPlayer := 0;

with Players[0] do
begin
Name := '';
Pass := '';
Active := True;
end;
end;

const
WMX1 = 7;
WMX2 = 756;
WMY1 = 7;
WMY2 = 460;
WMCX = 375;
WMCY = 232;
CRAP = 1.33333;

var
b, t, w, h, x, y: Integer;
p, a: TPointArray;
ap: array of TPointArray;
begin
Writeln('Begin');
SetupSRL;
DeclarePlayers;
Writeln('Finished setting up');
Wait(5000);
Writeln('Logging in now');
LoginPlayer;

w := 764;
h := 504;

Wait(5000);
Writeln('Logged...');
Mouse(MMX1 - 15, MMY2 - 18, 4, 4, True);
Writeln('Opened map');
Wait(5000);
x := GetColor(100, 100);
if (not (SimilarColors(x, clBlack, 5))) then
begin
Writeln('Looks like the map loaded uber fast, hoping it isn''t a mistake');
Wait(2500);
end else
begin
Writeln('Picked color ' + IntToStr(x));
t := GetSystemTime + 12000;
while ((GetSystemTime < t) and (GetColor(100, 100) = x)) do
Wait(999);
if (GetSystemTime >= t) then
begin
Writeln('Opening the world map seems to have lagged a bit - giving it an extra 15 seconds max');
t := GetSystemTime + 15000;
while ((GetSystemTime < t) and (GetColor(100, 100) = x)) do
Wait(999);
end;

if (GetColor(100, 100) = x) then
begin
Writeln('Looks like epic failure on the map loading front, terminating...');
TerminateScript;
end;
end;

Mouse(MMCX, MMCY, 100, 100, True);
Writeln('Anti-log click');

Writeln('Now trying to detect a nearby path colour');
for b := 1 to 8 do
if FindColorSpiralTolerance(x, y, 7434361, WMCX - 15, WMCX - 15, WMCX + 15, WMCY + 15, b * 5) then
break;

if b = 9 then
begin
FindColorsTolerance(p, 7434361, WMX1, WMY1, WMX2, WMY2, 50);
Writeln('Finding nearby road colour didn''t work too well, so using preset colour with high tolerance');
end
else
begin
FindColorsTolerance(p, GetColor(x, y), WMX1, WMY1, WMX2, WMY2, 10);
Writeln('Finding nearby road colour succeeded (hopefully)');
end;
if (Length(p) < 100) then
begin
Writeln('First search failed... searching with steroids!');
FindColorsTolerance(p, 7434361, WMX1, WMY1, WMX2, WMY2, 60);
end;
if (Length(p) < 100) then
begin
Writeln('Darn, looks like our path locating flailed :<');
Logout;
TerminateScript;
end;
Writeln('Found the paths!');

FindColorsTolerance(a, 12632256, WMX1, WMY1, WMX2, WMY2, 15);
if(Length(a) < 50) then
begin
Writeln('First symbol colour finding failed, pumping up');
FindColorsTolerance(a, 12632256, WMX1, WMY1, WMX2, WMY2, 25);
end;
if(Length(a) < 50) then
Writeln('Symbol colour finding failed again, so let''s hope we won''t need it')
else
Writeln('Found the symbols');
p := CombineTPA(p, a);

Writeln('Have a total of ' + IntToStr(Length(p)) + ' points found');

ap := TPAtoATPA(p, 3);
SetLength(p, Length(ap));
b := BitmapFromString(w, h, '');
SafeCopyCanvas(GetClientCanvas, GetBitmapCanvas(b), 0, 0, w, h, 0, 0, w, h);

for x := 0 to High(ap) do
begin
p[x] := MiddleTPA(ap[x]);
FastSetPixel(b, p[x].x, p[x].y, clRed);
end;
GetBitmapCanvas(b).Ellipse(WMCX - 1, WMCY - 1, WMCX + 1, WMCY + 1);

SaveBitmap(b, AppPath + 'debug.bmp');
Writeln(AppPath + 'debug.bmp');

x := -1;
repeat
if FindSymbolIn(x, y, 'bank', 100, 50, w - 100, h - 50) then
break;
SymbolAccuracy := SymbolAccuracy - 0.1;
until SymbolAccuracy < 0.4;
if (x = -1) then
begin
Writeln('Failed a bit at finding a bank, our bad');
Logout;
TerminateScript;
end;

SortTPAFrom(p, Point(x, y));
InvertTPA(p);
SetLength(p, Length(p) + 1);
InvertTPA(p);
p[0] := Point(WMCX, WMCY);
Writeln('Going from ' + IntToStr(p[0].x) + ',' + IntToStr(p[0].y));
Writeln('Going to ' + IntToStr(p[1].x) + ',' + IntToStr(p[1].y) + '(' + FloatToStr(SymbolAccuracy) + ')');

Writeln(IntToStr(Length(p)));
t := GetSystemTime;
AStar(a, p, 0, 1, 8, 14);
t := GetSystemTime - t;
Writeln('Took ' + IntToStr(t) + 'ms on first run');
if (Length(a) = 0) then
begin
Writeln('Darn, it failed :<');
Writeln('Lets try pumping up the filter and crossing fingers!');
t := GetSystemTime;
AStar(a, p, 0, 1, 8, 18);
t := GetSystemTime - t;
Writeln('Took ' + IntToStr(t) + 'ms on second run');
end;
if (Length(a) = 0) then
begin
Writeln('Yup, it failed...');
Logout;
TerminateScript;
end;

Writeln('Path made!');

Mouse(740, 10, 3, 3, True);
Wait(2500);

ap := TPAtoATPA(a, 15);
SetLength(a, Length(ap));
for x := 0 to High(a) do
a[x] := MiddleTPA(ap[x]);

SetLength(p, Length(a));
p[0] := Point(a[0].x - MMCX, a[0].y - MMCY);
GetBitmapCanvas(b).MoveTo(a[0].x, a[0].y);
for x := 1 to High(a) do
begin
GetBitmapCanvas(b).LineTo(a[x].x, a[x].y);
p[x] := Point(Round((a[x].x - a[x - 1].x) * CRAP), Round((a[x].y - a[x - 1].y) * CRAP));
MouseMM(MMCX + p[x].x, MMCY + p[x].y, 1, 1);
Flag;
Wait(500 + Random(500));
end;

SaveBitmap(b, AppPath + 'debug.bmp');

if (FindSymbolIn(x, y, 'bank', MMX1, MMY1, MMX2, MMY2)) then
begin
Writeln('Wow, we made it to a bank! I would like to thank so many people for making this possible. My parents, Man Flardin, R0b0t1, Markus - all of you, so much love!');
Writeln('Now, for added win, let''s try walking back!');
end
else
begin
SymbolAccuracy := 0.5;
Writeln('Lowered symbol accuracy in case it was a false negative');
if (FindSymbolIn(x, y, 'bank', MMX1, MMY1, MMX2, MMY2)) then
begin
Writeln('Wow, we made it to a bank! I would like to thank so many people for making this possible. My parents, Man Flardin, R0b0t1, Markus - all of you, so much love!');
Writeln('Now, for added win, let''s try walking back!');
end
else
begin
Writeln('Well, we walked but did not make it to the bank. Darn :<');
Logout;
TerminateScript;
end;
end;

InvertTPA(a);

p[0] := Point(a[0].x - MMCX, a[0].y - MMCY);
for x := 1 to High(a) do
begin
p[x] := Point(Round((a[x].x - a[x - 1].x) * CRAP), Round((a[x].y - a[x - 1].y) * CRAP));
MouseMM(MMCX + p[x].x, MMCY + p[x].y, 1, 1);
Flag;
Wait(500 + Random(500));
end;
Writeln('End');
end.

mixster

2009-09-15 01:05:28

As long as plugin was moved while Scar was closed, then it should be fine to run like that - just put in a character who is somewhat near a bank and a road and watch it go with feedback for any problems since it's becoming a bit more unstable as I don't get enough testers to find bugs in it.

Bobzilla69

2009-09-15 11:53:59

ok sorry to keep hasseling you, but where do i put the plug in?
in the normal plugin folder? or where this script is?

i have tried both and whenever i run the script i just get Unknown identifier 'AStar'.

lordsaturn

2009-09-15 15:39:22

Thats amazing, mixster. <3

Daniel

2009-09-15 16:12:08

From: bobzilla69
ok sorry to keep hasseling you, but where do i put the plug in?
in the normal plugin folder? or where this script is?

i have tried both and whenever i run the script i just get Unknown identifier 'AStar'.

Well, here's what Sir mixster said to do:
  1. Save the script you currently have open
  2. Close SCAR
  3. Copy and Move the plugin to \Plugins\ (relative to SCAR path)
  4. Open SCAR
  5. Open the script you just had open before
  6. Run the script

There we go, we just learnt how to install a plugin :D

Bobzilla69

2009-09-15 16:19:46

[QUOTE=Dan's The Man;632452]Well, here's what Sir mixster said to do:
  1. Save the script you currently have open
  2. Close SCAR
  3. Copy and Move the plugin to \Plugins\ (relative to SCAR path)
  4. Open SCAR
  5. Open the script you just had open before
  6. Run the script

There we go, we just learnt how to install a plugin :D

yep i have done all that before, it still gives me the same error.

does it matter that i am using scar 3.22 beta?

will try with 3.21 now

edit: nope doesnt make a diffrence to mine.

must be doing something wrong

Markus

2009-09-15 18:40:12

Wait, so it actually works now> :eek:
mixster: add some random woodcutting procedures to it please so I can declare you winnar ;)

mixster

2009-09-15 21:33:02

From: bobzilla69
yep i have done all that before, it still gives me the same error.

does it matter that i am using scar 3.22 beta?

will try with 3.21 now

edit: nope doesnt make a diffrence to mine.

must be doing something wrong


Which error is it? May be my mistake since I didn't check for compilation too much.


From: Markus
Wait, so it actually works now> :eek:
mixster: add some random woodcutting procedures to it please so I can declare you winnar ;)


Well, it may not work if it doesn't get close enough to the bank for the walking back. Otherwise, it *should*, so I could probably start packaging it and making it an easily called function that walks places - just need a better way of finding bank symbol.

Oh, and can I just add a FindObjTPA for woodcutting? :)

Bobzilla69

2009-09-15 22:11:10

the error i am getting is
Line 157: [Error] (20608:1): Unknown identifier 'AStar' in script
script i am using is
{.include SRL/SRL/misc/Smart.scar}
{.include SRL/SRL.scar}

procedure DeclarePlayers;
begin
HowManyPlayers := 1;
NumberOfPlayers(HowManyPlayers);
CurrentPlayer := 0;

with Players[0] do
begin
Name := '';
Pass := '';
Active := True;
end;
end;

const
WMX1 = 7;
WMX2 = 756;
WMY1 = 7;
WMY2 = 460;
WMCX = 375;
WMCY = 232;
CRAP = 1.33333;

var
b, t, w, h, x, y: Integer;
p, a: TPointArray;
ap: array of TPointArray;
begin
Writeln('Begin');
SetupSRL;
DeclarePlayers;
Writeln('Finished setting up');
Wait(5000);
Writeln('Logging in now');
LoginPlayer;

w := 764;
h := 504;

Wait(5000);
Writeln('Logged...');
Mouse(MMX1 - 15, MMY2 - 18, 4, 4, True);
Writeln('Opened map');
Wait(5000);
x := GetColor(100, 100);
if (not (SimilarColors(x, clBlack, 5))) then
begin
Writeln('Looks like the map loaded uber fast, hoping it isn''t a mistake');
Wait(2500);
end else
begin
Writeln('Picked color ' + IntToStr(x));
t := GetSystemTime + 12000;
while ((GetSystemTime < t) and (GetColor(100, 100) = x)) do
Wait(999);
if (GetSystemTime >= t) then
begin
Writeln('Opening the world map seems to have lagged a bit - giving it an extra 15 seconds max');
t := GetSystemTime + 15000;
while ((GetSystemTime < t) and (GetColor(100, 100) = x)) do
Wait(999);
end;

if (GetColor(100, 100) = x) then
begin
Writeln('Looks like epic failure on the map loading front, terminating...');
TerminateScript;
end;
end;

Mouse(MMCX, MMCY, 100, 100, True);
Writeln('Anti-log click');

Writeln('Now trying to detect a nearby path colour');
for b := 1 to 8 do
if FindColorSpiralTolerance(x, y, 7434361, WMCX - 15, WMCX - 15, WMCX + 15, WMCY + 15, b * 5) then
break;

if b = 9 then
begin
FindColorsTolerance(p, 7434361, WMX1, WMY1, WMX2, WMY2, 50);
Writeln('Finding nearby road colour didn''t work too well, so using preset colour with high tolerance');
end
else
begin
FindColorsTolerance(p, GetColor(x, y), WMX1, WMY1, WMX2, WMY2, 10);
Writeln('Finding nearby road colour succeeded (hopefully)');
end;
if (Length(p) < 100) then
begin
Writeln('First search failed... searching with steroids!');
FindColorsTolerance(p, 7434361, WMX1, WMY1, WMX2, WMY2, 60);
end;
if (Length(p) < 100) then
begin
Writeln('Darn, looks like our path locating flailed :<');
Logout;
TerminateScript;
end;
Writeln('Found the paths!');

FindColorsTolerance(a, 12632256, WMX1, WMY1, WMX2, WMY2, 15);
if(Length(a) < 50) then
begin
Writeln('First symbol colour finding failed, pumping up');
FindColorsTolerance(a, 12632256, WMX1, WMY1, WMX2, WMY2, 25);
end;
if(Length(a) < 50) then
Writeln('Symbol colour finding failed again, so let''s hope we won''t need it')
else
Writeln('Found the symbols');
p := CombineTPA(p, a);

Writeln('Have a total of ' + IntToStr(Length(p)) + ' points found');

ap := TPAtoATPA(p, 3);
SetLength(p, Length(ap));
b := BitmapFromString(w, h, '');
SafeCopyCanvas(GetClientCanvas, GetBitmapCanvas(b), 0, 0, w, h, 0, 0, w, h);

for x := 0 to High(ap) do
begin
p[x] := MiddleTPA(ap[x]);
FastSetPixel(b, p[x].x, p[x].y, clRed);
end;
GetBitmapCanvas(b).Ellipse(WMCX - 1, WMCY - 1, WMCX + 1, WMCY + 1);

SaveBitmap(b, AppPath + 'debug.bmp');
Writeln(AppPath + 'debug.bmp');

x := -1;
repeat
if FindSymbolIn(x, y, 'bank', 100, 50, w - 100, h - 50) then
break;
SymbolAccuracy := SymbolAccuracy - 0.1;
until SymbolAccuracy < 0.4;
if (x = -1) then
begin
Writeln('Failed a bit at finding a bank, our bad');
Logout;
TerminateScript;
end;

SortTPAFrom(p, Point(x, y));
InvertTPA(p);
SetLength(p, Length(p) + 1);
InvertTPA(p);
p[0] := Point(WMCX, WMCY);
Writeln('Going from ' + IntToStr(p[0].x) + ',' + IntToStr(p[0].y));
Writeln('Going to ' + IntToStr(p[1].x) + ',' + IntToStr(p[1].y) + '(' + FloatToStr(SymbolAccuracy) + ')');

Writeln(IntToStr(Length(p)));
t := GetSystemTime;
AStar(a, p, 0, 1, 8, 14);
t := GetSystemTime - t;
Writeln('Took ' + IntToStr(t) + 'ms on first run');
if (Length(a) = 0) then
begin
Writeln('Darn, it failed :<');
Writeln('Lets try pumping up the filter and crossing fingers!');
t := GetSystemTime;
AStar(a, p, 0, 1, 8, 18);
t := GetSystemTime - t;
Writeln('Took ' + IntToStr(t) + 'ms on second run');
end;
if (Length(a) = 0) then
begin
Writeln('Yup, it failed...');
Logout;
TerminateScript;
end;

Writeln('Path made!');

Mouse(740, 10, 3, 3, True);
Wait(2500);

ap := TPAtoATPA(a, 15);
SetLength(a, Length(ap));
for x := 0 to High(a) do
a[x] := MiddleTPA(ap[x]);

SetLength(p, Length(a));
p[0] := Point(a[0].x - MMCX, a[0].y - MMCY);
GetBitmapCanvas(b).MoveTo(a[0].x, a[0].y);
for x := 1 to High(a) do
begin
GetBitmapCanvas(b).LineTo(a[x].x, a[x].y);
p[x] := Point(Round((a[x].x - a[x - 1].x) * CRAP), Round((a[x].y - a[x - 1].y) * CRAP));
MouseMM(MMCX + p[x].x, MMCY + p[x].y, 1, 1);
Flag;
Wait(500 + Random(500));
end;

SaveBitmap(b, AppPath + 'debug.bmp');

if (FindSymbolIn(x, y, 'bank', MMX1, MMY1, MMX2, MMY2)) then
begin
Writeln('Wow, we made it to a bank! I would like to thank so many people for making this possible. My parents, Man Flardin, R0b0t1, Markus - all of you, so much love!');
Writeln('Now, for added win, let''s try walking back!');
end
else
begin
SymbolAccuracy := 0.5;
Writeln('Lowered symbol accuracy in case it was a false negative');
if (FindSymbolIn(x, y, 'bank', MMX1, MMY1, MMX2, MMY2)) then
begin
Writeln('Wow, we made it to a bank! I would like to thank so many people for making this possible. My parents, Man Flardin, R0b0t1, Markus - all of you, so much love!');
Writeln('Now, for added win, let''s try walking back!');
end
else
begin
Writeln('Well, we walked but did not make it to the bank. Darn :<');
Logout;
TerminateScript;
end;
end;

InvertTPA(a);

p[0] := Point(a[0].x - MMCX, a[0].y - MMCY);
for x := 1 to High(a) do
begin
p[x] := Point(Round((a[x].x - a[x - 1].x) * CRAP), Round((a[x].y - a[x - 1].y) * CRAP));
MouseMM(MMCX + p[x].x, MMCY + p[x].y, 1, 1);
Flag;
Wait(500 + Random(500));
end;
Writeln('End');
end.

Naum

2009-09-15 22:34:41

From: bobzilla69
the error i am getting is
Line 157: [Error] (20608:1): Unknown identifier 'AStar' in script
script i am using is (snip)


You need to put mixster's A* plugin, in your SCAR's plugin folder. Then restart SCAR. Then try again :)

Bobzilla69

2009-09-15 22:41:16

yes i have done that (as said in post 19) and it still shows me the same error

Naum

2009-09-15 22:43:49

From: bobzilla69
yes i have done that (as said in post 19) and it still shows me the same error


What folder did you put it in?

Bobzilla69

2009-09-15 22:47:57

C:\Program Files\SCAR 3.21\Plugins

is what i put it in, is that wrong?

mixster

2009-09-16 00:23:06

Aha, it was my mistake. Forgot to change the plugin so it output AStar instead of AStarCus as the procedure name (Delphi appears to have something called AStar already).

Anyway, find the following code segment (not too far from bottom):
  AStar(a, p, 0, 1, 8, 14);
t := GetSystemTime - t;
Writeln('Took ' + IntToStr(t) + 'ms on first run');
if (Length(a) = 0) then
begin
Writeln('Darn, it failed :<');
Writeln('Lets try pumping up the filter and crossing fingers!');
t := GetSystemTime;
AStar(a, p, 0, 1, 8, 18);

Then change the AStar to AStarCus at top and bottom of excerpt and it should run fine :)

Edit: Applied above fix to first post's Scar'y bits.

Bobzilla69

2009-09-16 01:04:01

WOW, thats bloody amazing, it walked pretty good, only thing was it was slightly off the path which meant there was a few miss clicks, but apart from that it worked great.

i did change the color on line 79, 84, 95. picked the road color from wold map, otherwise it wouldnt detect road.

if you need any more testing just ask.

BobboHobbo

2009-09-20 12:48:04

Ahh, how did I not see this thread earilier! Sounds really nice. Ill test and report back.

nickrules

2009-09-22 04:53:18

it worked great. at least, halfway. it got their, but walking back was a complete failure.

nrb33

2009-09-22 22:41:44

Nice work so far, i hope that you get this developed to the point where we can use it as part of the staple SRL downloads :P

Tickyy

2010-01-04 18:35:38

Small bump, i tried this once and i really liked it, wondering if you're still developing this, mixster :redface:?

mixster

2010-01-05 11:04:13

I would be if Scar was a little more reliable. First going to try to implement a more efficient Dijkstra-based path finder, then work on modularising it to a point where it's "usable" then after that see if I can find a reliable method of doing it without using the world map (since it seems some people can't open it).

Edit: Even though no one will probably ever read this edit, finally got the Dijkstra implementation working, meaning that multiple locations can now be sent to it and it will find the closest one as well as still produce a path - yay!