SRL Archive - RS3 Help

Stuck in ---- Waiting while the player is moving...


Twinki

2015-01-22 18:45:47


My script keeps getting stuck in the same area. It'll stay in —- Waiting while the player is moving… until it crashes or closes Simba.

I have no idea what's causing this. At first I thought it was because flags that SPS would finish at, and since WaitPlayerMoving goes by what looks like PixelShift, it was just detecting the flags. That doesn't seem to be the case.

This only happens sometimes. The script will run for 20 minutes, then all of a sudden get stuck, or it'll run for only 2 minutes and get stuck. So at this point, I have no idea.

Full Script:


program TwinkiTanner;
{$DEFINE SMART}
{$I SRL-6/SRL.simba}
{$I SPS/lib/SPS-RS3.Simba}
{$i srl-6/lib/misc/srlplayerform.simba}

{------------------------------------------------------------------------------)
I wanted to thank all those who've helped me accomplish this, and give credits
where due.

TheMayor, for the tutorials, would've never figured out TPA's if it wasn't for you
hoodz, for the examples and help with questions I had
Ross, for the Tanner example script, I based a lot of this after your script
BMWxi, for the private help and general feedback
Clarity, for the private help and feedback!
Enig, for the awesome GFX!

Thank you guys in the IRC for pointing out some mistakes and improvements that could be made
(------------------------------------------------------------------------------}

{--- Constants that can easily be updated * No touchy, unless you know what you're doing--}
Const
{--- Banker / Bank Booth---}
B_HUE := 0.65;
B_SAT := 0.89;
B_COLOR := 13624282;
B_TOL := 15;
B_FILTER := 15; //ATPA Filter
{--- Relative Object for Banker ---}
rB_HUE := 0.10;
rB_SAT := 0.36;
rB_COLOR := 5528700;
rB_TOL := 9;
rB_EXCLUDE := 150; //Exclude Distance

{--- Jack the Tanner ---}
J_HUE := 0.12;
J_SAT := 0.70;
J_COLOR := 2908960;
J_TOL := 10;
J_FILTER := 10; //ATPA Filter
{--- Relative Object for Jack ---}
rJ_HUE := 1.12;
rJ_SAT := 8.11;
rJ_COLOR := 15397620;
rJ_TOL := 2;
rJ_EXCLUDE := 150; //Exclude Distance

Var
HardLeatherDTM, GreenLeatherDTM, BlueLeatherDTM, RedLeatherDTM,
BlackLeatherDTM, RoyalLeatherDTM, DTMToLook, FoundDTMs, TotalTannedLeather: Integer;
BotStatus: String;
TannerTestMode, FindTheTwinkiSMARTDebug: boolean;

procedure initPlayerForm();
begin
with playerForm do
begin
name := 'TwinkiTanner - Setup';
scriptHelpThread := '';
editBoxLabels := ['Amount to Tan: ', 'Bank Preset'];
editBoxDefaults := ['100000', '1'];
editBoxHints := ['Amount of Hide to Tan', 'Bank Preset to use (1 or 2)'];

checkBoxLabels := ['Draw on SMART', 'TwinkiTanner SMART Debug', 'Test Mode'];
checkBoxDefaults := ['True', 'False', 'False'];
checkBoxHints := ['Do you want do draw some debug information on SMART?', 'Turns on TwinkiTanner SMART Debug', 'This is for testing Stability of the core of this script'];
end;
end;

procedure declarePlayers();
var
i: Integer;
begin
players.setup(playerForm.playerNames, playerForm.playerFile);
currentPlayer := 0;
for i := 0 to high(players) do
with players[i] do
begin
integers[0] := strToInt(playerForm.players[i].settings[0]);
integers[1] := strToInt(playerForm.players[i].settings[1]);

smartEnableDrawing := strToBool(playerForm.players[i].settings[2]);
FindTheTwinkiSMARTDebug := strToBool(playerForm.players[i].settings[3]);
TannerTestMode := strToBool(playerForm.players[i].settings[4]);
end;
end;



{------------------------------------------------------------------------------)
Function: FindTheTwinki
Description: Custom FindObject. Anyone is welcome to use this, I just ask you provide credits where it's due!
Credits: Twinki (Thank you TheMayor, hoodz, Ross, and BMWxi for the help!)
(------------------------------------------------------------------------------}
function FindTheTwinki(Hue, Sat: extended; Color, Tolerance, Filter, clickType: Integer; mouseOverText, chooseOptions: array of string;
MouseMove: boolean = true; FindRelativeObject: boolean = false; rHue, rSat: extended = 0; rColor, rTolerance: Integer = 0; excludePointsDist: Integer = 150): boolean;
Var
attempts, X, Y, i: integer;
rTPA, TPA: TPointArray;
ATPA: T2DPointArray;
rPoint : TPoint;

begin
repeat
if not isLoggedIn() then exit;
if FindTheTwinkiSMARTDebug then smartImage.clear();
minimap.waitPlayerMoving()

if FindRelativeObject = true then
begin
if not findColorsSpiralTolerance(X, Y, rTPA, rColor, mainScreen.getBounds(), rTolerance, colorSetting(2, rHue, rSat)) then
begin
WriteLn('Failed FindTheTwinki, re-trying');
randomCompass(10, 200, false);
Wait(randomRange(1000, 2000));
inc(attempts);
end;
if length(rTPA) < 1 then exit;
if FindTheTwinkiSMARTDebug then smartImage.debugTPA(rTPA, false);
rPoint := middleTPA(rTPA);
end;

if findColorsSpiralTolerance(X, Y, TPA, Color, mainScreen.getBounds(), Tolerance, colorSetting(2, Hue, Sat)) then
begin
if length(TPA) < 1 then exit;
if FindRelativeObject = true then TPA.excludePointsDist(0, excludePointsDist, rPoint.x, rPoint.y);
ATPA := TPA.toATPA(30, 30);
ATPA.filterBetween(1, Filter);
ATPA.sortFromMidPoint(mainscreen.playerPoint);
if FindTheTwinkiSMARTDebug then smartImage.debugATPA(ATPA);

for i := 0 to high(ATPA) do
begin
if (length(ATPA[i]) < 25) then continue;
if FindTheTwinkiSMARTDebug then smartImage.drawText('ATPA Length: '+IntToStr(length(ATPA[i])), point(ATPA[i][0].x+10, ATPA[i][0].y+10), clLime);

if MouseMove = true then Mouse(ATPA[i].getBounds().getRandomPoint(), MOUSE_MOVE);
if MouseMove = false then Mouse(ATPA[i].getBounds().getRandomPoint(), MOUSE_NONE);

if isMouseOverText(mouseOverText, 150) then
begin
if clickType = MOUSE_NONE then exit();
fastClick(clickType);
if clickType = MOUSE_LEFT then SmallRandomMouse();
Wait(randomRange(250, 750));

if chooseOption.optionsExist(chooseOptions) then
chooseOption.select(chooseOptions, 1000);
exit(true);
end;
end;
end
else
begin
WriteLn('Failed FindTheTwinki, re-trying');
randomCompass(10, 200, false);
Wait(randomRange(1000, 2000));
inc(attempts);
end;
if FindTheTwinkiSMARTDebug then smartImage.clear();
until attempts >= 5;
end;

{------------------------------------------------------------------------------)
Procedure: Proggy
Description: Draws a progress report on SMART
Credits: Clarity, for the right coordinates :D
(------------------------------------------------------------------------------}
procedure Proggy;
begin
if not smartEnableDrawing then
begin
WriteLn('***************TwinkiTanner***************');
WriteLn('* Time Running: '+ToStr(TimeRunning));
WriteLn('* STATUS: ',+BotStatus);
WriteLn('* Leathers Tanned: '+ToStr(TotalTannedLeather));
WriteLn('******************************************');
end
else
begin
smartImage.clear();
smartImage.drawText('TwinkiTanner', point(mainscreen.x1 + 5, mainscreen.y1 + 5), 'LoginChars', true, clWhite);
smartImage.drawText('Time Running:', point(mainscreen.x1 + 15, mainscreen.y1 + 25), 'SmallChars', true, clYellow);
smartImage.drawText(toStr(TimeRunning), point(mainscreen.x1 + 96, mainscreen.y1 + 25), 'SmallChars', true, clWhite);
smartImage.drawText('Tanned:', point(mainscreen.x1 + 15, mainscreen.y1 + 50), 'SmallChars', true, clYellow);
smartImage.drawText(toStr(TotalTannedLeather) + ' hides', point(mainscreen.x1 + 61, mainscreen.y1 + 50), 'SmallChars', true, clWhite);
smartImage.drawText('STATUS: ', point(actionbar.x1 + 5, actionbar.y1 - 20), 'Loginchars', true, clWhite);
smartImage.drawText(BotStatus, point(actionbar.x1 + 68, actionbar.y1 - 20), 'Loginchars', true, clYellow);
end;
end;

{------------------------------------------------------------------------------)
Procedure: RunToJack
Description: Runs to Jack the Tanner
(------------------------------------------------------------------------------}
procedure RunToJack;
Var
PathToJack: TPointArray;
begin
if not isLoggedIn() then exit;

BotStatus := 'Running to Jack the Tanner';
if not TannerTestMode then Proggy;
PathToJack := [Point(152, 130), Point(167, 162), Point(171, 195), Point(165, 227), Point(133, 270)]
if SPS.walkPath(PathToJack) then minimap.waitPlayerMoving()
else
begin
ClearDebug();
BotStatus := 'ERROR: Hmph, we failed running to Jack.. our legs must be broken';
if not TannerTestMode then Proggy;
WriteLn('ERROR: Hmph, we failed running to Jack.. our legs must be broken');
TerminateScript();
end;
end;

{------------------------------------------------------------------------------)
Procedure: RunToBank
Description: Runs to Burthope Bank
(------------------------------------------------------------------------------}
procedure RunToBank;
Var
PathToBank: TPointArray;
begin
if not isLoggedIn() then exit;

BotStatus := 'Running to the Burthorpe Banker';
if not TannerTestMode then Proggy;
PathToBank := [Point(144, 253), Point(150, 222), Point(153, 203), Point(156, 161), Point(148, 131)]
if SPS.walkPath(PathToBank) then
begin
minimap.waitPlayerMoving();
Wait(randomRange(1000, 2000));
end
else
begin
ClearDebug();
BotStatus := 'ERROR: Hmph, we failed running to the bank.. our legs must be broken';
if not TannerTestMode then Proggy;
WriteLn('ERROR: Hmph, we failed running to the bank.. our legs must be broken');
TerminateScript();
end;
end;

{------------------------------------------------------------------------------)
Function: FindBanker
Description: Finds the Gnome Banker in Burthope, returns True if found, uses FindTheTwinki
(------------------------------------------------------------------------------}
function FindBanker(): boolean;
begin
if not isLoggedIn() then Exit();
if bankScreen.isOpen() then Exit();
BotStatus := 'Trying to find the Burthorpe Gnome Banker';
Proggy;
case random(1, 2) of
1: if FindTheTwinki(B_HUE, B_SAT, B_COLOR, B_TOL, B_FILTER, MOUSE_LEFT, ['anker','ank','ooth'], [''], true, true, rB_HUE, rB_SAT, rB_COLOR, rB_TOL, rB_EXCLUDE) then
result := true
else
begin
ClearDebug();
BotStatus := 'ERROR: Could not find the Gnome Banker';
Proggy;
WriteLn('ERROR: Could not find the Gnome Banker');
exit();
end;
2: if FindTheTwinki(B_HUE, B_SAT, B_COLOR, B_TOL, B_FILTER, MOUSE_RIGHT, ['anker','ank','ooth'], ['ank', 'ooth'], true, true, rB_HUE, rB_SAT, rB_COLOR, rB_TOL, rB_EXCLUDE) then
result := true
else
begin
ClearDebug();
BotStatus := 'ERROR: Could not find the Gnome Banker';
Proggy;
WriteLn('ERROR: Could not find the Gnome Banker');
exit();
end;
end;
end;


{------------------------------------------------------------------------------)
Procedure: FindJack
Description: Finds Jack the Tanner using FindTheTwinki
(------------------------------------------------------------------------------}
function FindJack(): boolean;
begin
if not isLoggedIn() then exit();
if productionScreen.isOpen() then productionscreen.close();

BotStatus := 'Trying to find Jack the Tanner';
Proggy;
if FindTheTwinki(J_HUE, J_SAT, J_COLOR, J_TOL, J_FILTER, MOUSE_RIGHT, ['ack','val'], ['an', 'ide'], true, true, rJ_HUE, rJ_SAT, rJ_COLOR, rJ_TOL, rJ_EXCLUDE) then
result := true
else
begin
ClearDebug();
BotStatus := 'ERROR: Could not find Jack';
Proggy;
WriteLn('ERROR: Could not find Jack');
TerminateScript();
end;
end;


{------------------------------------------------------------------------------)
Procedure: BankHides
Description: Uses Bank Presets to quickly deposit and take out Hides
(------------------------------------------------------------------------------}
procedure BankHides;
Var
i: Integer;
bankScreenTimer: TTimeMarker;
begin
if not bankScreen.isOpen() then
if FindBanker then
begin
bankScreenTimer.start();
repeat
begin
Wait(randomRange(100, 250));
BotStatus := 'Waiting for Bank Screen to open';
Proggy;
if bankScreenTimer.getTime() > 20000 then
begin
ClearDebug();
BotStatus := 'ERROR: We ran out of time waiting for the Bank Screen to open';
Proggy;
WriteLn('ERROR: We ran out of time waiting for the Bank Screen to open');
TerminateScript();
end;
end;
until bankScreen.isOpen();

if bankScreen.isOpen() then
begin
bankScreenTimer.reset();
BotStatus := 'Bank Screen is open, taking out hides';
Proggy;
end;
end;

if bankScreen.isOpen() then
begin
BotStatus := 'Bank Screen is open, taking out hides';
Proggy;
if players[i].integers[1] = 1 then
begin
case random(1, 2) of
1: bankScreen.clickButton(BANK_BUTTON_PRESET_1, true);
2: bankScreen.clickButton(BANK_BUTTON_PRESET_1, false);
end;
end
else
if players[i].integers[1] = 2 then
begin
case random(1, 2) of
1: bankScreen.clickButton(BANK_BUTTON_PRESET_2, true);
2: bankScreen.clickButton(BANK_BUTTON_PRESET_2, false);
end;
end
else
begin
ClearDebug();
BotStatus := 'ERROR: Something went wrong in the Bank Button Presets';
Proggy;
WriteLn('ERROR: Something went wrong in the Bank Button Presets');
TerminateScript();
end;
Wait(randomRange(1500, 2500));
if not tabbackpack.isItemInSlot(1) then
begin
ClearDebug();
BotStatus := 'ERROR: We''re either out of Leather or you didn''t setup your Bank Preset correctly';
Proggy;
WriteLn('ERROR: We''re either out of Leather or you didn''t setup your Bank Preset correctly');
TerminateScript();
end;
end
else
begin
ClearDebug();
BotStatus := 'ERROR: Could not Bank Hides';
Proggy;
WriteLn('ERROR: Could not Bank Hides');
TerminateScript();
end;
end;

{------------------------------------------------------------------------------)
Procedure: DepositLast
Description: Depososits the last Tanned Leather then logs out
(------------------------------------------------------------------------------}
procedure DepositLast;
Var
i: Integer;
bankScreenTimer: TTimeMarker;
begin
if not bankScreen.isOpen() then
if FindBanker then
begin
bankScreenTimer.start();
repeat
begin
Wait(randomRange(100, 250));
BotStatus := 'Waiting for Bank Screen to open';
Proggy;
if bankScreenTimer.getTime() > 20000 then
begin
ClearDebug();
BotStatus := 'ERROR: We ran out of time waiting for the Bank Screen to open';
Proggy;
WriteLn('ERROR: We ran out of time waiting for the Bank Screen to open');
TerminateScript();
end;
end;
until bankScreen.isOpen();

if bankScreen.isOpen() then
begin
bankScreenTimer.reset();
BotStatus := 'Bank Screen is open, depositing and logging out';
Proggy;
Wait(randomRange(500, 750));
bankScreen.quickDeposit(QUICK_DEPOSIT_INVENTORY);
bankScreen.close();
players[currentPlayer].logout();
smartImage.clear();
smartEnableDrawing := false;
Proggy;
TerminateScript();
end;
end;
end;

{------------------------------------------------------------------------------)
Procedure: CountTannedLeather
Description: Counts Tanned Leather using DTM's
(------------------------------------------------------------------------------}
function CountTannedLeather(): boolean;
Var
i: Integer;
DTMArray: TIntegerArray;
begin
DTMArray := [HardLeatherDTM, GreenLeatherDTM, BlueLeatherDTM, RedLeatherDTM, BlackLeatherDTM, RoyalLeatherDTM];

for i := 0 to high(DTMArray) do
begin
if tabBackpack.countDTM(DTMArray[i]) > 1 then
begin
if tabBackpack.countDTM(DTMArray[i]) < 28 then
begin
BotStatus := 'Found less than 28 Tanned Leather, depositing and logging out';
Proggy;
TotalTannedLeather := TotalTannedLeather + tabBackpack.countDTM(DTMArray[i]);
DepositLast;
end;
TotalTannedLeather := TotalTannedLeather + tabBackpack.countDTM(DTMArray[i]);
result := true
end;
end;
end;

{------------------------------------------------------------------------------)
Procedure: TanHides
Description: Tans Hides at Jack
(------------------------------------------------------------------------------}
procedure TanHides;
Var
i: Integer;
productionScreenTimer: TTimeMarker;
CraftSymbol: TPoint;
begin
if not productionScreen.isOpen() then
if FindJack then
begin
productionScreenTimer.start();
repeat
begin
Wait(randomRange(100, 250));
BotStatus := 'Waiting for Production Screen to show up';
Proggy;
if productionScreenTimer.getTime() > 25000 then
begin
ClearDebug();
BotStatus := 'ERROR: We ran out of time waiting for the Production Screen to open';
Proggy;
WriteLn('ERROR: We ran out of time waiting for the Production Screen to open');
TerminateScript();
end;
end;
until productionScreen.isOpen();

if productionScreen.isOpen() then
begin
productionScreenTimer.reset();
BotStatus := 'Production Screen is Open, tanning hides';
Proggy;
end;
end;

if productionScreen.isOpen then
begin
BotStatus := 'Production Screen is Open, tanning hides';
Proggy;
case random(1, 2) of
1: productionScreen.clickStart(true);
2: productionScreen.clickStart(false);
end;
Wait(randomRange(500, 750));
end
else
begin
ClearDebug();
BotStatus := 'ERROR: Production Screen at Jack failure';
Proggy;
WriteLn('ERROR: Production Screen at Jack failure');
TerminateScript();
end;
end;

{------------------------------------------------------------------------------)
Procedure: checkForImages
Description: Downloads the SPS map and/or paint picture if you don't have them.
Credits: Kevin
(------------------------------------------------------------------------------}
procedure checkForImages(path, link, item: string);
var
progFile: longInt;
picName: string;

begin
picName := AppPath + path;

try
if not fileExists(picName) then
begin
writeLn('NOTIFICATION: ' + item + ' does not exist - Downloading it now!.');
progFile := createFile(picName);
end else
exit;

closeFile(progFile);

progFile := rewriteFile(picName, false);
writeFileString(progFile, getPage(link));
writeLn('NOTIFICATION: ' + item + ' has been download to Simba folder!');
writeLn('');
finally
if (progFile > 0) then
closeFile(progFile);
end;
end;

{------------------------------------------------------------------------------)
Procedure: TestMode
Description: Tests the barebones of the script, for stability purposes
(------------------------------------------------------------------------------}
procedure TestMode;
Var
FailedJack, FailedBank, FoundBank, FoundJack: Integer;
TestTime: TTimeMarker;

begin
ClearDebug();
WriteLn('WARNING: This is Test Mode, it''s meant for testing the barebones of the script, set TannerTestMode to false at the bottom to turn it off');
Wait(randomRange(6000, 10000));
ClearDebug();
FindTheTwinkiSMARTDebug := true;
if TannerTestMode then
begin
TestTime.start;
repeat
begin
if FindTheTwinki(B_HUE, B_SAT, B_COLOR, B_TOL, B_FILTER, MOUSE_MOVE, ['anker','ank','ooth'], [''], true, true, rB_HUE, rB_SAT, rB_COLOR, rB_TOL, rB_EXCLUDE) then
begin
WriteLn('TEST MODE: Found Bank Booth');
inc(FoundBank);
end
else
begin
WriteLn('TEST MODE: Didn''t find Bank Booth');
inc(FailedBank);
end;
RunToJack;
if FindTheTwinki(J_HUE, J_SAT, J_COLOR, J_TOL, J_FILTER, MOUSE_MOVE, ['ack','val'], ['an', 'ide'], true, true, rJ_HUE, rJ_SAT, rJ_COLOR, rJ_TOL, rJ_EXCLUDE) then
begin
WriteLn('TEST MODE: Found Jack');
inc(FoundJack);
end
else
begin
WriteLn('TEST MODE: Didn''t find Jack');
inc(FailedJack);
end;
RunToBank;
ClearDebug();
WriteLn('Found Bank: '+toStr(FoundBank)+' times');
WriteLn('Found Jack: '+toStr(FoundJack)+' times');
Writeln('Been Testing for: '+msToTime(TestTime.getTime(), TIME_FORMAL));
end;
until ((FoundBank >= 10) and (FoundJack >= 10)) or (TestTime.getTime() > 900000);
TestTime.pause;
ClearDebug();
WriteLn('** Test completed, results: **');
WriteLn('* Found Bank: '+toStr(FoundBank)+' times');
WriteLn('* Found Jack: '+toStr(FoundJack)+' times');
WriteLn('* Failed to find Bank: '+toStr(FailedBank)+' times');
WriteLn('* Failed to find Jack: '+toStr(FailedJack)+' times');
WriteLn('* Test took '+msToTime(TestTime.getTime(), TIME_FORMAL));
WriteLn('** Please report these findings to Twinki **');
TestTime.reset;
end;
end;

{------------------------------------------------------------------------------)
Procedure: MainLoop
Description: The main loop of this script, don't touch it!
(------------------------------------------------------------------------------}
procedure MainLoop;
Var
i: Integer;
begin
BotStatus := 'Booting up';
Proggy;

repeat
Proggy;
if not isLoggedIn() then
begin
players[currentPlayer].login();
Wait(randomRange(2000, 3000));
minimap.clickCompass();
mainscreen.setAngle(MS_ANGLE_HIGH);
exitTreasure();
closePollWindow();
end;

BankHides;
RunToJack;
TanHides;
RunToBank;
if not CountTannedLeather then
begin
WriteLn('ERROR: Couldn''t count Tanned Leather');
TerminateScript();
end;

until (TotalTannedLeather >= players[i].integers[0]);
DepositLast;
end;

procedure LoadDTMs;
begin
HardLeatherDTM := DTMFromString('mlwAAAHicY2dgYOABYk4gFgVicSBmZYAAGSDmg7IZgVgKKs8LxToaskCSCYoZkdhMDFwMuAEjHgwFAIsvAVE=');
GreenLeatherDTM := DTMFromString('mrAAAAHic42BgYBAAYhEgZgViWQYIYANiKSDmBWJuIJYBYhYgZoeKSQKxGFQthxUXkGTCghnBtCQDfsBIAMMAAKrkAWQ=');
BlueLeatherDTM := DTMFromString('mlwAAAHicY2dgYOAEYiEGCBAAYiYgZgdiCSAWBGJmIGYDYhkgloSq4wVibl4fqGpMDFOHDTDiwVAAAIALAUA=');
RedLeatherDTM := DTMFromString('mlwAAAHicY2dgYOABYjEglmKAAFYglgFiPiDmh4qDxHiBWAKIhaDqbHk5gSQTGmYE05IMuAEjHgwFAI95AVY=');
BlackLeatherDTM := DTMFromString('mrAAAAHic42BgYOAFYiYgFgdiUQYIkAFiYSDmAWIuIGYHYkYglgBiIagYCEgCsbysLNQEZMwIZ7Mz4AeMBDAMAACkAwFT');
RoyalLeatherDTM := DTMFromString('mlwAAAHicY2dgYOBngAAZIBYHYk4gZgViQSDmBWI+IOYBYgkglgRiZqh6R5koIMmEFUsy4AaMeDAUAACpPQGn');
end;

procedure FreeTheDTMs;
begin
FreeDTM(HardLeatherDTM);
FreeDTM(GreenLeatherDTM);
FreeDTM(BlueLeatherDTM);
FreeDTM(RedLeatherDTM);
FreeDTM(BlackLeatherDTM);
FreeDTM(RoyalLeatherDTM);
end;

begin
//Setup
ClearDebug();
initPlayerForm();
runPlayerForm();
if (not playerForm.isScriptReady) then exit;
declarePlayers();
smartShowConsole := false;
DisableSRLDebug := false;
SetupSRL();
AddOnTerminate('FreeTheDTMs');
LoadDTMs;
CheckForImages('Includes/SPS/img/runescape_other/BURTHORPE_TAN.png', 'http://i.imgur.com/ITtmmeI.png', 'SPS map'); //Thank you Ross for the SPS map :)
SPS.setup('BURTHORPE_TAN', RUNESCAPE_OTHER);
//Startup
if not isLoggedIn() then players[currentPlayer].login();
BotStatus := '';
Wait(randomRange(2000, 3000));
minimap.clickCompass();
mainscreen.setAngle(MS_ANGLE_HIGH);
exitTreasure();
closePollWindow();
//mainscreen.setZoom(true, 50);
//mainscreen.setZoom(false, 10);

if not TannerTestMode then
begin
while players.getActive > 0 do
mainLoop;
end
else
TestMode;

WriteLn('Finished Tanning, total time running: '+ timeRunning);
end.

KeepBotting

2015-01-22 18:54:10

minimap.waitPlayerMoving() is a loop that calls .isPlayerMoving() - a function which looks at the center point of the minimap to determine its result.

I just ran a quick test and it works fine - your screenshot doesn't include the minimap so please supply that - as well as tell us if there's anything on your minimap that would obviously throw off a pixel shift check.

Here's an image for clarification, you can see the console displays debug output that suggests the function is returning true or false many times in a row, the alteration of which corresponds to the rhythm of my player's movement (or lack thereof), shortly before the screenshot was taken. The red box on the minimap is where the function is looking.


Twinki

2015-01-22 19:00:45

From: KeepBotting
minimap.waitPlayerMoving() is a loop that calls .isPlayerMoving() - a function which looks at the center point of the minimap to determine its result.

I just ran a quick test and it works fine - your screenshot doesn't include the minimap so please supply that - as well as tell us if there's anything on your minimap that would obviously throw off a pixel shift check.


This is what the Minimap looks like, tried to capture it while the script was still running
There are a lot of NPC's that move around.

KeepBotting

2015-01-22 19:02:41

From: Twinki
This is what the Minimap looks like, tried to capture it while the script was still running
There are a lot of NPC's that move around.


Refer to my edit - then reposition your player to a clearer area and test again. It may be all the movement that is throwing it off.

Twinki

2015-01-22 19:27:43

From: KeepBotting
Refer to my edit - then reposition your player to a clearer area and test again. It may be all the movement that is throwing it off.


I'm sitting in the same spot with the same debug and just watching the console. It looks like the movement around me only causes isPlayerMoving to be true only once every 5-10 seconds. Weird..

I'm going to keep watching it to see what happens.

KeepBotting

2015-01-22 19:31:09

From: Twinki
I'm sitting in the same spot with the same debug and just watching the console. It looks like the movement around me only causes isPlayerMoving to be true only once every 5-10 seconds. Weird..

I'm going to keep watching it to see what happens.


.waitPlayerMoving() can take some parameters, shiftInterval and maxTime, the defaults of which are 500 and 20000 respectively. Playing around with those might alleviate the issue.

Twinki

2015-01-22 19:33:16

From: KeepBotting
.waitPlayerMoving() can take some parameters, shiftInterval and maxTime, the defaults of which are 500 and 20000 respectively. Playing around with those might alleviate the issue.


Actually…
I have no idea what it's doing lol..

KeepBotting

2015-01-22 19:38:04

From: Twinki
Actually… http://i.gyazo.com/5ac89773cdd0ba8300a88157682a230a.png

I have no idea what it's doing lol..

Looks like it's stuck in the same loop as before, with .isPlayerMoving() returning true once every 5 to 10 seconds, causing .waitPlayerMoving() to loop again for the full 20-second default.

Set new values for .waitPlayerMoving()'s parameters, 500 is probably fine for shiftInterval but maxTime should be lowered. It goes minimap.waitPlayerMoving(shiftInterval, maxTime); where both parameters are integers.

@Olly; I see you viewing the thread, any ideas on why we're getting false-positives from .isPlayerMoving() once in a while?

E: what's also weird is that the SRL debug says you're waiting while moving, but the debug below that says you're stationary. What's the conditional for the latter to print?

E again: I see that there's more output near the top of the console that suggests the script is walking paths and waiting for movement to stop just fine. Perhaps you've got an infinite loop in the walking routine?

Twinki

2015-01-22 19:42:21

From: KeepBotting
Looks like it's stuck in the same loop as before, with .isPlayerMoving() returning true once every 5 to 10 seconds, causing .waitPlayerMoving() to loop again for the full 20-second default.

Set new values for .waitPlayerMoving()'s parameters, 500 is probably fine for shiftInterval but maxTime should be lowered. It goes minimap.waitPlayerMoving(shiftInterval, maxTime); where both parameters are integers.

@Olly; I see you viewing the thread, any ideas on why we're getting false-positives from .isPlayerMoving() once in a while?

E: what's also weird is that the SRL debug says you're waiting while moving, but the debug below that says you're stationary. What's the conditional for the latter to print?


I was just going to try adding in my own loop at the top:


if minimap.isPlayerMoving() then
begin
isPlayerMovingTimer.start();
repeat
begin
Wait(randomRange(100, 250));
if isPlayerMovingTimer.getTime() > 20000 then
begin
WriteLn('ERROR: We ran out of time waiting for the player to stop moving');
TerminateScript();
end;
end;
until not minimap.isPlayerMoving();
end;

EDIT:
Here's my Walk procedures


{------------------------------------------------------------------------------)
Procedure: RunToJack
Description: Runs to Jack the Tanner
(------------------------------------------------------------------------------}
procedure RunToJack;
Var
PathToJack: TPointArray;
begin
if not isLoggedIn() then exit;

BotStatus := 'Running to Jack the Tanner';
if not TannerTestMode then Proggy;
PathToJack := [Point(152, 130), Point(167, 162), Point(171, 195), Point(165, 227), Point(133, 270)]
if SPS.walkPath(PathToJack) then minimap.waitPlayerMoving()
else
begin
ClearDebug();
BotStatus := 'ERROR: Hmph, we failed running to Jack.. our legs must be broken';
if not TannerTestMode then Proggy;
WriteLn('ERROR: Hmph, we failed running to Jack.. our legs must be broken');
TerminateScript();
end;
end;

{------------------------------------------------------------------------------)
Procedure: RunToBank
Description: Runs to Burthope Bank
(------------------------------------------------------------------------------}
procedure RunToBank;
Var
PathToBank: TPointArray;
begin
if not isLoggedIn() then exit;

BotStatus := 'Running to the Burthorpe Banker';
if not TannerTestMode then Proggy;
PathToBank := [Point(144, 253), Point(150, 222), Point(153, 203), Point(156, 161), Point(148, 131)]
if SPS.walkPath(PathToBank) then
begin
minimap.waitPlayerMoving();
Wait(randomRange(1000, 2000));
end
else
begin
ClearDebug();
BotStatus := 'ERROR: Hmph, we failed running to the bank.. our legs must be broken';
if not TannerTestMode then Proggy;
WriteLn('ERROR: Hmph, we failed running to the bank.. our legs must be broken');
TerminateScript();
end;
end;
This is where it's getting stuck:

{------------------------------------------------------------------------------)
Function: FindTheTwinki
Description: Custom FindObject. Anyone is welcome to use this, I just ask you provide credits where it's due!
Credits: Twinki (Thank you TheMayor, hoodz, Ross, and BMWxi for the help!)
(------------------------------------------------------------------------------}
function FindTheTwinki(Hue, Sat: extended; Color, Tolerance, Filter, clickType: Integer; mouseOverText, chooseOptions: array of string;
MouseMove: boolean = true; FindRelativeObject: boolean = false; rHue, rSat: extended = 0; rColor, rTolerance: Integer = 0; excludePointsDist: Integer = 150): boolean;
Var
attempts, X, Y, i: integer;
rTPA, TPA: TPointArray;
ATPA: T2DPointArray;
rPoint: TPoint;
isPlayerMovingTimer: TTimeMarker;

begin
repeat
if not isLoggedIn() then exit;
if FindTheTwinkiSMARTDebug then smartImage.clear();
minimap.waitPlayerMoving();

if FindRelativeObject = true then
begin
if not findColorsSpiralTolerance(X, Y, rTPA, rColor, mainScreen.getBounds(), rTolerance, colorSetting(2, rHue, rSat)) then
begin
WriteLn('Failed FindTheTwinki, re-trying');
randomCompass(10, 200, false);
Wait(randomRange(1000, 2000));
inc(attempts);
end;
if length(rTPA) < 1 then exit;
if FindTheTwinkiSMARTDebug then smartImage.debugTPA(rTPA, false);
rPoint := middleTPA(rTPA);
end;

if findColorsSpiralTolerance(X, Y, TPA, Color, mainScreen.getBounds(), Tolerance, colorSetting(2, Hue, Sat)) then
begin
if length(TPA) < 1 then exit;
if FindRelativeObject = true then TPA.excludePointsDist(0, excludePointsDist, rPoint.x, rPoint.y);
ATPA := TPA.toATPA(30, 30);
ATPA.filterBetween(1, Filter);
ATPA.sortFromMidPoint(mainscreen.playerPoint);
if FindTheTwinkiSMARTDebug then smartImage.debugATPA(ATPA);

for i := 0 to high(ATPA) do
begin
if (length(ATPA[i]) < 25) then continue;
if FindTheTwinkiSMARTDebug then smartImage.drawText('ATPA Length: '+IntToStr(length(ATPA[i])), point(ATPA[i][0].x+10, ATPA[i][0].y+10), clLime);

if MouseMove = true then Mouse(ATPA[i].getBounds().getRandomPoint(), MOUSE_MOVE);
if MouseMove = false then Mouse(ATPA[i].getBounds().getRandomPoint(), MOUSE_NONE);

if isMouseOverText(mouseOverText, 150) then
begin
if clickType = MOUSE_NONE then exit();
fastClick(clickType);
if clickType = MOUSE_LEFT then SmallRandomMouse();
Wait(randomRange(250, 750));

if chooseOption.optionsExist(chooseOptions) then
chooseOption.select(chooseOptions, 1000);
exit(true);
end;
end;
end
else
begin
WriteLn('Failed FindTheTwinki, re-trying');
randomCompass(10, 200, false);
Wait(randomRange(1000, 2000));
inc(attempts);
end;
if FindTheTwinkiSMARTDebug then smartImage.clear();
until attempts >= 5;
end;

KeepBotting

2015-01-22 20:21:56

From: Twinki
I was just going to try adding in my own loop at the top:


if minimap.isPlayerMoving() then
begin
isPlayerMovingTimer.start();
repeat
begin
Wait(randomRange(100, 250));
if isPlayerMovingTimer.getTime() > 20000 then
begin
WriteLn('ERROR: We ran out of time waiting for the player to stop moving');
TerminateScript();
end;
end;
until not minimap.isPlayerMoving();
end;

EDIT:
Here's my Walk procedures


{------------------------------------------------------------------------------)
Procedure: RunToJack
Description: Runs to Jack the Tanner
(------------------------------------------------------------------------------}
procedure RunToJack;
Var
PathToJack: TPointArray;
begin
if not isLoggedIn() then exit;

BotStatus := 'Running to Jack the Tanner';
if not TannerTestMode then Proggy;
PathToJack := [Point(152, 130), Point(167, 162), Point(171, 195), Point(165, 227), Point(133, 270)]
if SPS.walkPath(PathToJack) then minimap.waitPlayerMoving()
else
begin
ClearDebug();
BotStatus := 'ERROR: Hmph, we failed running to Jack.. our legs must be broken';
if not TannerTestMode then Proggy;
WriteLn('ERROR: Hmph, we failed running to Jack.. our legs must be broken');
TerminateScript();
end;
end;

{------------------------------------------------------------------------------)
Procedure: RunToBank
Description: Runs to Burthope Bank
(------------------------------------------------------------------------------}
procedure RunToBank;
Var
PathToBank: TPointArray;
begin
if not isLoggedIn() then exit;

BotStatus := 'Running to the Burthorpe Banker';
if not TannerTestMode then Proggy;
PathToBank := [Point(144, 253), Point(150, 222), Point(153, 203), Point(156, 161), Point(148, 131)]
if SPS.walkPath(PathToBank) then
begin
minimap.waitPlayerMoving();
Wait(randomRange(1000, 2000));
end
else
begin
ClearDebug();
BotStatus := 'ERROR: Hmph, we failed running to the bank.. our legs must be broken';
if not TannerTestMode then Proggy;
WriteLn('ERROR: Hmph, we failed running to the bank.. our legs must be broken');
TerminateScript();
end;
end;
This is where it's getting stuck:

{------------------------------------------------------------------------------)
Function: FindTheTwinki
Description: Custom FindObject. Anyone is welcome to use this, I just ask you provide credits where it's due!
Credits: Twinki (Thank you TheMayor, hoodz, Ross, and BMWxi for the help!)
(------------------------------------------------------------------------------}
function FindTheTwinki(Hue, Sat: extended; Color, Tolerance, Filter, clickType: Integer; mouseOverText, chooseOptions: array of string;
MouseMove: boolean = true; FindRelativeObject: boolean = false; rHue, rSat: extended = 0; rColor, rTolerance: Integer = 0; excludePointsDist: Integer = 150): boolean;
Var
attempts, X, Y, i: integer;
rTPA, TPA: TPointArray;
ATPA: T2DPointArray;
rPoint: TPoint;
isPlayerMovingTimer: TTimeMarker;

begin
repeat
if not isLoggedIn() then exit;
if FindTheTwinkiSMARTDebug then smartImage.clear();
minimap.waitPlayerMoving();

if FindRelativeObject = true then
begin
if not findColorsSpiralTolerance(X, Y, rTPA, rColor, mainScreen.getBounds(), rTolerance, colorSetting(2, rHue, rSat)) then
begin
WriteLn('Failed FindTheTwinki, re-trying');
randomCompass(10, 200, false);
Wait(randomRange(1000, 2000));
inc(attempts);
end;
if length(rTPA) < 1 then exit;
if FindTheTwinkiSMARTDebug then smartImage.debugTPA(rTPA, false);
rPoint := middleTPA(rTPA);
end;

if findColorsSpiralTolerance(X, Y, TPA, Color, mainScreen.getBounds(), Tolerance, colorSetting(2, Hue, Sat)) then
begin
if length(TPA) < 1 then exit;
if FindRelativeObject = true then TPA.excludePointsDist(0, excludePointsDist, rPoint.x, rPoint.y);
ATPA := TPA.toATPA(30, 30);
ATPA.filterBetween(1, Filter);
ATPA.sortFromMidPoint(mainscreen.playerPoint);
if FindTheTwinkiSMARTDebug then smartImage.debugATPA(ATPA);

for i := 0 to high(ATPA) do
begin
if (length(ATPA[i]) < 25) then continue;
if FindTheTwinkiSMARTDebug then smartImage.drawText('ATPA Length: '+IntToStr(length(ATPA[i])), point(ATPA[i][0].x+10, ATPA[i][0].y+10), clLime);

if MouseMove = true then Mouse(ATPA[i].getBounds().getRandomPoint(), MOUSE_MOVE);
if MouseMove = false then Mouse(ATPA[i].getBounds().getRandomPoint(), MOUSE_NONE);

if isMouseOverText(mouseOverText, 150) then
begin
if clickType = MOUSE_NONE then exit();
fastClick(clickType);
if clickType = MOUSE_LEFT then SmallRandomMouse();
Wait(randomRange(250, 750));

if chooseOption.optionsExist(chooseOptions) then
chooseOption.select(chooseOptions, 1000);
exit(true);
end;
end;
end
else
begin
WriteLn('Failed FindTheTwinki, re-trying');
randomCompass(10, 200, false);
Wait(randomRange(1000, 2000));
inc(attempts);
end;
if FindTheTwinkiSMARTDebug then smartImage.clear();
until attempts >= 5;
end;

Try removing it from the last routine there, see what happens. It's already called by each walking routine, so doesn't really need to be called by the object finder as well

Twinki

2015-01-22 20:28:41

From: KeepBotting
Try removing it from the last routine there, see what happens. It's already called by each walking routine, so doesn't really need to be called by the object finder as well


I've tried that, but the issue was each area SPS runs to is a "Loading Please Wait" area, meaning when it walks forward at a certain spot it goes to load in the map and such, causing the script to kinda lag out. I did try just adding in a Wait, but it didn't seem to be as stable and efficient. I'll try again, and see what happens.

EDIT: It actually looks like SPS calls waitPlayerMoving in WalkPath when it gets to it's last point. Going to try removing WaitPlayerMoving in the Walking procedures itself, and see what happens.

Twinki

2015-01-22 21:24:30

Okay, it's something with my FindTheTwinki Function, not SRL.



{------------------------------------------------------------------------------)
Function: FindTheTwinki
Description: Custom FindObject. Anyone is welcome to use this, I just ask you provide credits where it's due!
Credits: Twinki (Thank you TheMayor, hoodz, Ross, and BMWxi for the help!)
(------------------------------------------------------------------------------}
function FindTheTwinki(Hue, Sat: extended; Color, Tolerance, Filter, clickType: Integer; mouseOverText, chooseOptions: array of string;
MouseMove: boolean = true; FindRelativeObject: boolean = false; rHue, rSat: extended = 0; rColor, rTolerance: Integer = 0; excludePointsDist: Integer = 150): boolean;
Var
attempts, X, Y, i: integer;
rTPA, TPA: TPointArray;
ATPA: T2DPointArray;
rPoint: TPoint;
isPlayerMovingTimer: TTimeMarker;

begin
repeat
if not isLoggedIn() then exit;
if FindTheTwinkiSMARTDebug then smartImage.clear();

if minimap.isPlayerMoving() then
begin
isPlayerMovingTimer.start();
repeat
begin
WriteLn('Stuck in loop');
Wait(randomRange(100, 250));
if isPlayerMovingTimer.getTime() > 20000 then
begin
WriteLn('ERROR: We ran out of time waiting for the player to stop moving');
TerminateScript();
end;
end;
until not minimap.isPlayerMoving();
WriteLn('Out of loop');
end;

if FindRelativeObject = true then
begin
if not findColorsSpiralTolerance(X, Y, rTPA, rColor, mainScreen.getBounds(), rTolerance, colorSetting(2, rHue, rSat)) then
begin
WriteLn('Failed FindTheTwinki, re-trying');
randomCompass(10, 200, false);
Wait(randomRange(1000, 2000));
inc(attempts);
end;
if length(rTPA) < 1 then exit;
if FindTheTwinkiSMARTDebug then smartImage.debugTPA(rTPA, false);
rPoint := middleTPA(rTPA);
end;

if findColorsSpiralTolerance(X, Y, TPA, Color, mainScreen.getBounds(), Tolerance, colorSetting(2, Hue, Sat)) then
begin
if length(TPA) < 1 then exit;
if FindRelativeObject = true then TPA.excludePointsDist(0, excludePointsDist, rPoint.x, rPoint.y);
ATPA := TPA.toATPA(30, 30);
ATPA.filterBetween(1, Filter);
ATPA.sortFromMidPoint(mainscreen.playerPoint);
if FindTheTwinkiSMARTDebug then smartImage.debugATPA(ATPA);

for i := 0 to high(ATPA) do
begin
if (length(ATPA[i]) < 25) then continue;
if FindTheTwinkiSMARTDebug then smartImage.drawText('ATPA Length: '+IntToStr(length(ATPA[i])), point(ATPA[i][0].x+10, ATPA[i][0].y+10), clLime);

if MouseMove = true then Mouse(ATPA[i].getBounds().getRandomPoint(), MOUSE_MOVE);
if MouseMove = false then Mouse(ATPA[i].getBounds().getRandomPoint(), MOUSE_NONE);

if isMouseOverText(mouseOverText, 150) then
begin
if clickType = MOUSE_NONE then exit();
fastClick(clickType);
if clickType = MOUSE_LEFT then SmallRandomMouse();
Wait(randomRange(250, 750));

if chooseOption.optionsExist(chooseOptions) then
chooseOption.select(chooseOptions, 1000);
exit(true);
end;
end;
end
else
begin
WriteLn('Failed FindTheTwinki, re-trying');
randomCompass(10, 200, false);
Wait(randomRange(1000, 2000));
inc(attempts);
end;
if FindTheTwinkiSMARTDebug then smartImage.clear();
WriteLn('Stuck Twinki loop');
until attempts >= 5;
end;

It seems to be skipping all of my If statements, i'm not quite sure how to fix this or where I've went wrong. Any help is appreciated.

HKbotz

2015-01-23 10:07:16

It looks like the problem is your else statement never gets executed cause it always finds the color you want, and therefore attempts never increases causing an infinite loop.
Here is your funtion again, I cleaned up the indentation(makes it easier to follow the logic), and added comments of where I think the problem is, and inc(attempts) outside the else statement, that way worst case it loops 5 times without finding anything and exits.

Try the fixed one and see if it works.
{------------------------------------------------------------------------------)
Function: FindTheTwinki
Description: Custom FindObject. Anyone is welcome to use this, I just ask you provide credits where it's due!
Credits: Twinki (Thank you TheMayor, hoodz, Ross, and BMWxi for the help!)
(------------------------------------------------------------------------------}
function FindTheTwinki(Hue, Sat: extended; Color, Tolerance, Filter, clickType: Integer; mouseOverText, chooseOptions: array of string;
MouseMove: boolean = true; FindRelativeObject: boolean = false; rHue, rSat: extended = 0; rColor, rTolerance: Integer = 0; excludePointsDist: Integer = 150): boolean;
Var
attempts, X, Y, i: integer;
rTPA, TPA: TPointArray;
ATPA: T2DPointArray;
rPoint: TPoint;
isPlayerMovingTimer: TTimeMarker;

begin
repeat
if not isLoggedIn() then
exit;
if FindTheTwinkiSMARTDebug then
smartImage.clear();

if minimap.isPlayerMoving() then
begin
isPlayerMovingTimer.start();
repeat
//begin <-- not required, you don't need begin/end for repeat loops ~HKbots
WriteLn('Stuck in loop');
Wait(randomRange(100, 250));
if isPlayerMovingTimer.getTime() > 20000 then
begin
WriteLn('ERROR: We ran out of time waiting for the player to stop moving');
TerminateScript();
end;
//end;
until not minimap.isPlayerMoving();
WriteLn('Out of loop');
end;

if FindRelativeObject = true then //with default param, this never executes since it's set to false ~HKbotz
begin
if not findColorsSpiralTolerance(X, Y, rTPA, rColor, mainScreen.getBounds(), rTolerance, colorSetting(2, rHue, rSat)) then
begin
WriteLn('Failed FindTheTwinki, re-trying');
randomCompass(10, 200, false);
Wait(randomRange(1000, 2000));
inc(attempts);
end;
if length(rTPA) < 1 then
exit;
if FindTheTwinkiSMARTDebug then
smartImage.debugTPA(rTPA, false);
rPoint := middleTPA(rTPA);
end;

(*
Looks like error is here cause it always finds color, and never executes
the else statement, meaning attempts never increases, causing and infinite loop ~HKbots *)
if findColorsSpiralTolerance(X, Y, TPA, Color, mainScreen.getBounds(), Tolerance, colorSetting(2, Hue, Sat)) then
begin
if length(TPA) < 1 then
exit;
if FindRelativeObject = true then
TPA.excludePointsDist(0, excludePointsDist, rPoint.x, rPoint.y);
ATPA := TPA.toATPA(30, 30);
ATPA.filterBetween(1, Filter);
ATPA.sortFromMidPoint(mainscreen.playerPoint);
if FindTheTwinkiSMARTDebug then
smartImage.debugATPA(ATPA);

for i := 0 to high(ATPA) do
begin
if (length(ATPA[i]) < 25) then
continue;
if FindTheTwinkiSMARTDebug then
smartImage.drawText('ATPA Length: '+IntToStr(length(ATPA[i])), point(ATPA[i][0].x+10, ATPA[i][0].y+10), clLime);

if MouseMove = true then
Mouse(ATPA[i].getBounds().getRandomPoint(), MOUSE_MOVE);
if MouseMove = false then
Mouse(ATPA[i].getBounds().getRandomPoint(), MOUSE_NONE);

if isMouseOverText(mouseOverText, 150) then
begin
if clickType = MOUSE_NONE then
exit(true); (* added true(I assume that's what you wanted :p) to your
exit statement, was blank before. ~HKbotz *)
fastClick(clickType);
if clickType = MOUSE_LEFT then
SmallRandomMouse();
Wait(randomRange(250, 750));

if chooseOption.optionsExist(chooseOptions) then
chooseOption.select(chooseOptions, 1000);
exit(true);
end;
end;
end else //this never gets executed if it finds the color ~HKbots
begin
WriteLn('Failed FindTheTwinki, re-trying');
randomCompass(10, 200, false);
Wait(randomRange(1000, 2000));
inc(attempts);
end;
inc(attempts); //added here so it will always increase attemps no matter what ~HKbots
if FindTheTwinkiSMARTDebug then smartImage.clear();
WriteLn('Stuck Twinki loop');
until attempts >= 5;
end;