Here are three portal finders by @J J; and @euphemism; They are currently broken but used to present state-of-the-art techniques on finding it! They are currently broken, but you might be able to fix them
This first one is by J J, it uses a traditional approach to find the portal by using the colours. It used to be very reliable but it is not toooo original.
Simba Code:
function FindPortal3(var x, y : integer) : boolean; //By J J, thanks!
var
PortalColors: TPointArray;
Splitted: T2DPointArray;
P: TPoint;
i, smallestX, smallestY, biggestX, biggestY, xSize, ySize: Integer;
begin
// Attempts to find the portal colors
//ColorToleranceSpeed(2);
//SetColorSpeed2Modifiers(4.71, 2.55);
if FindColorsSpiralTolerance(MainScreen.CX, MainScreen.CY, PortalColors, 13489057, mainscreen.getbounds(), 20, colorSetting(2, 4.71, 2.55)) then
begin
(* Colors have been found, they will be drawn on SMART in the color red
After that it will get splitted into an ATPA with a distance of 3 *)
{$IFDEF SMARTDRAW} try
SMART_DrawDotsEx(True, PortalColors, clRed); except end;
{$ENDIF}
Splitted := SplitTPA(PortalColors, 3);
SortATPASize(Splitted, True);
(* ATPA has been sorted on size, large to small. The biggest one will get
drawn on SMART in the color cyan. A box around will also be drawn. *)
{$IFDEF SMARTDRAW} try
SMART_DrawDotsEx(False, Splitted[0], clAqua);
SMART_DrawBoxEx(False, False, GetTPABounds(Splitted[0]), clGreen); except end;
{$ENDIF}
// Calculating the X and Y size of our best TPA
smallestX := MainScreen.X2;
smallestY := MainScreen.Y2;
for i:=0 to high(Splitted[0]) do
begin
// Check if the X is bigger or smaller than our extreme values
if Splitted[0][i].x < smallestX then
smallestX := Splitted[0][i].x
else
if Splitted[0][i].x > biggestX then
biggestX := Splitted[0][i].x;
// Check if the Y is bigger or smaller than our extreme values
if Splitted[0][i].y < smallestY then
smallestY := Splitted[0][i].y
else
if Splitted[0][i].y > biggestY then
biggestY := Splitted[0][i].y;
end;
(* Calculating the actual size. We take 40% of the size because the outline
of a circle is two times the radius. To be sure we click on a clickable
part we take 40% instead of 50%. *)
//writeln('bigggestX : ' + IntToStr(biggestX) + ' en smallestX: ' + IntToStr(smallestX));
//writeln('bigggestY : ' + IntToStr(biggestY) + ' en smallestY: ' + IntToStr(smallestY));
xSize := ((biggestX - smallestX) * 4) div 10;
ySize := ((biggestY - smallestY) * 4) div 10;
(* The middle of the biggest TPA will get calculated and we will move the
mouse to a spot around the middle. We draw this oval on SMART. *)
P := MiddleTPA(Splitted[0]);
{$IFDEF SMARTDRAW} try
SMART_DrawEllipse(False, P, xSize, ySize, False, clYellow); except end;
{$ENDIF}
MouseOval(P.x, P.y, xSize, ySize, 2);
// Checking if the uptext is correct
if isMouseOverText(['nter', 'ortal', 'Enter', 'Portal', 'tal', 'ter'], 500) then //WaitUptextMulti -> isMouseOverText?
begin
(* The uptext is correct, the portal has been detected! We perform a
left mouse click and wait until we have stopped moving. Result = true *)
//ClickMouse2(1);
//FFlag(0);
//while IsMoving do
// Wait(RandomRange(100, 200));
Result := True;
x := P.x; //Small modification to account for the rest of the script
y := P.y;
m_Debug('Portal found with FindPortal3!');
end;
end;
end;
The second one is by our fello euphemism. It uses a different approach: look for everything that is not a portal, then the portal will be left! It's pretty effective, but slow, and it'll also see other players as a portal. That's why it was second choice.
Simba Code:
// Half-broken
function FindPortal2(var cx, cy: Integer; force : boolean): Boolean; //by euphemism, thanks!
var
Area, ColorSpeed, EdgeColor, EdgeTol, GroundColor, GroundTol, I, Match,
WallColor, WallTol: Integer;
TestPoint: TPoint;
EdgeHue, EdgeSat, GroundHue, GroundSat, WallHue, WallSat: Extended;
CharBox, AreaBox, SearchBox: TBox;
CharTPA, ColorsTPA, NewTPA, EdgeTPA, SearchTPA: TPointArray;
ResultsATPA, NewATPA: T2DPointArray;
begin
//ColorSpeed := GetColorToleranceSpeed;
//ColorToleranceSpeed(2);
//SetToleranceSpeed2Modifiers(0.37, 1.57);
Match := 0;
Result := False;
CharBox := IntToBox(MainSCreen.CX - 14, MainScreen.CY - 21, MainSCreen.CX + 12, MainSCreen.CY + 16);
CharTPA := TPAFromBox(CharBox);
//SearchBox := IntToBox(MSX1, MSY1, MSX2, MSY2);
//SearchBox := IntToBox(201, 123, 320, 231); //FASTER, BUT THIS ONLY WORKS IF YOU ARE ADJACENT TO THE PORTAL
SearchBox := IntToBox(MainSCreen.CX - 80, MainSCreen.CY - 80, MainSCreen.CX + 80, MainSCreen.CY + 80);
SearchTPA := TPAFromBox(SearchBox);
GroundColor := 7047023; GroundHue := 0.72; GroundSat := 0.22; GroundTol := 43;
WallColor := 16180721; WallHue := 3.42; WallSat := 7.34; WallTol := 4;
EdgeColor := 10391949; EdgeHue := 0.16; EdgeSat := 0.23; EdgeTol := 28;
//Find ground colours
//SetToleranceSpeed2Modifiers(GroundHue, GroundSat);
if not FindColorsTolerance(NewTPA, GroundColor, searchbox, GroundTol, colorSetting(2, GroundHue, GroundSat)) then
Exit;
//Find wall colours
SetToleranceSpeed2Modifiers(WallHue, WallSat);
FindColorsTolerance(ColorsTPA, WallColor, SearchBox.x1, SearchBox.y1,
SearchBox.x2, SearchBox.y2, WallTol);
//Finds wall colours
ColorsTPA := CombineTPA(ColorsTPA, NewTPA);
//Add edge colours, too
SetToleranceSpeed2Modifiers(EdgeHue, EdgeSat);
FindColorsTolerance(EdgeTPA, EdgeColor, SearchBox.x1, SearchBox.y1,
SearchBox.x2, SearchBox.y2, EdgeTol);
//SearchTPA is the entire box we are searching in,
//We remove our own character and all other points from it
AppendTPA(ColorsTPA, EdgeTPA);
NewTPA := ClearTPAFromTPA(SearchTPA, ColorsTPA);
ColorsTPA := ClearTPAFromTPA(NewTPA, CharTPA);
ResultsATPA := SplitTPA(ColorsTPA, 1);
SetLength(NewATPA, 0);
//This thing is still a miracle to me (Markus)
for I := 0 to High(ResultsATPA) do
begin
AreaBox := GetTPABounds(ResultsATPA[i]);
Area := ((AreaBox.X2 - AreaBox.X1) * (AreaBox.Y2 - AreaBox.Y1));
//Probably filters based on not being too small/large, portals arent big
if (InRange(Area, 500, 1500) and (InRange(Length(ResultsATPA[i]), 250,
1200))) then
begin
SetLength(NewATPA, Length(NewATPA) + 1);
NewATPA[Match] := ResultsATPA[i];
Inc(Match);
end;
end;
//When no points left, no point to contine
if Length(NewATPA) = 0 then
Exit;
SortATPAFromMidPoint(NewATPA, MainScreen.getcenterpoint);
//Regular (A)TPA iteration
for I := 0 to High(NewATPA) do
begin
TestPoint := MiddleTPA(NewATPA[i]);
{$IfDef SMARTDRAW} try
//Flashes the points, though noone watches it.
Smart_DrawDotsEx(True, NewATPA[i], clFuchsia);
m_DrawSmartLines;
except end;
{$EndIf}
MMouse(TestPoint.x, TestPoint.y, 5, 5);
writeln('P2: '+GetUpText);
if WaitUpTextMulti(['Enter', 'Portal', 'nter', 'ortal', 'er P'], 500) then
begin
Result := True;
m_debug('Portal found with FindPortal2!');
cx := TestPoint.x;
cy := TestPoint.y;
Break;
end else
if force then
begin
ClickMouse2(false);
if WaitOptionEx('eleport', 'all', clickLeft, 500) then
begin
cx := TestPoint.x;
cy := TestPoint.y;
result := true;
break;
end
end;
end;
end;
The third portal finder is also by euphemism. It uses some of Simba's bitmap manipulating tricks to isolate the portal from the background and then search that image. It worked around 2012 but not that effectively. That's why it was the 3rd portal finder in a row in the script. It could, however, function on a couple of edge cases where the others failed horribily.
Simba Code:
//No idea
//by euphemism, try #2
function FindPortal(var X, Y: Integer; force : boolean): Boolean;
var
x1, y1, x2, y2, W, H: Integer;
CTS, ClientBitmap, I, Len: Integer;
GrabBox: TBox;
TPA: TPointArray;
ATPA: T2DPointArray;
ITarget, KMTarget: Integer;
begin
Result := False;
// CTS := GetColorToleranceSpeed;
//SetColorToleranceSpeed(2);
//Grabs rectangle around player, something like 7x6 tiles
ClientBitmap := BitmapFromClient(125, 65, 380, 265);
SetBitmapName(ClientBitmap, 'ClientGrab');
//Changes Simba's target to the bitmap we just made
KMTarget := GetKeyMouseTarget;
ITarget := GetImageTarget;
SetTargetBitmap(ClientBitmap);
//Applies bitmap filters to make it easier to single out portal
{$IfDef LAPE} //defines could be removed, but this just works.
InvertBitmap(ClientBitmap);
PosterizeBitmap(ClientBitmap, 15);
ContrastBitmap(ClientBitmap, 1);
BrightnessBitmap(ClientBitmap, 15);
{$Else}
GetMufasaBitmap(ClientBitmap).Invert(GetMufasaBitmap(ClientBitmap));
GetMufasaBitmap(ClientBitmap).Posterize(GetMufasaBitmap(ClientBitmap), 15);
GetMufasaBitmap(ClientBitmap).Contrast(GetMufasaBitmap(ClientBitmap), 1);
GetMufasaBitmap(ClientBitmap).Brightness(GetMufasaBitmap(ClientBitmap), 15);
{$EndIf}
GetClientDimensions(W, H);
x1 := 0; y1 := 0; x2 := W - 1; y2 := H - 1;
//Filters out most of the ground, painting it white on bitmap
//SetColorSpeed2Modifiers(0.30, 0.58);
FindColorsTolerance(TPA, 5135981, IntToBox(x1, y1, x2, y2), 29, colorSetting(2, 0.30, 0.58));
Len := Length(TPA);
for I := 0 to (Len - 1) do
FastSetPixel(ClientBitmap, TPA[i].x, TPA[i].y, clWhite);
//Filters out most of rocks and trees, painting them white on bitmap
//SetColorSpeed2Modifiers(1.25, 0.21);
FindColorsTolerance(TPA, 9344658, x1, y1, x2, y2, 20, colorSetting(2, 1.25, 0.21));
Len := Length(TPA);
for I := 0 to (Len - 1) do
FastSetPixel(ClientBitmap, TPA[i].x, TPA[i].y, clWhite);
//Turns bitmap to greyscale and ups contrast, making portal more or less black, and most everything left a lighter grey
{$IfDef LAPE}
GreyScaleBitmap(ClientBitmap);
ContrastBitmap(ClientBitmap, 4);
{$Else}
GetMufasaBitmap(ClientBitmap).GreyScale(GetMufasaBitmap(ClientBitmap));
GetMufasaBitmap(ClientBitmap).Contrast(GetMufasaBitmap(ClientBitmap), 4);
{$EndIf}
//Finds the black of the portal
SetColorToleranceSpeed(0);
if not FindColorsTolerance(TPA, 2236962, x1, y1, x2, y2, 34) then
Exit;
SplitTPAWrap(TPA, 5, ATPA);
SortATPASize(ATPA, True);
Len := Length(ATPA);
//Loops through black groups to find one with correct dimensions
for I := 0 to (Len - 1) do
begin
GrabBox := GetTPABounds(ATPA[i]);
W := (GrabBox.x2 - GrabBox.x1);
H := (GrabBox.y2 - GrabBox.y1);
if (not (InRange(W, 25, 38) and InRange(H, 15, 38))) then
Continue;
TPA[0] := MiddleTPA(ATPA[i]);
OffSetTPA(TPA, IntToPoint(125, 65));
X := TPA[0].x;
Y := TPA[0].y;
//Debug image--------------------
// note by Markus: replace by Smart Graphics
if ((result)) then
begin
Len := Length(ATPA[i]);
for W := 0 to (Len - 1) do
FastSetPixel(ClientBitmap, ATPA[i][W].x, ATPA[i][W].y, clFuchsia);
{$IfDef SMARTDRAW}
SMART_DrawBitmap(true, ClientBitmap, IntToPoint(GrabBox.x1, GrabBox.Y1));
{$EndIf}
// DisplayDebugImgWindow(0,0);
// DisplayDebugImgWindow(255,200);
// DrawBitmapDebugImg(ClientBitmap);
end;
MMouse(x, y, 5, 5);
writeln('P1: '+GetUpText);
if (not(WaitUpTextMulti(['nter', 'ortal', 'Ent', 'Port', 'er P'], 500))) then
if force then
begin
ClickMouse2(false);
if not WaitOptionEx('eleport', 'all', clickLeft, 500) then
continue;
end;
Result := True;
m_debug('Portal found with FindPortal!');
Break;
end;
//-------------------------------
//Sets Simba's target back to SMART
FreeTarget(GetImageTarget);
SetKeyMouseTarget(KMTarget);
SetImageTarget(ITarget);
SetColorToleranceSpeed(CTS);
FreeBitmap(ClientBitmap);
end;