patternMinor
Auto-click the sequence
Viewed 0 times
autoclickthesequence
Problem
The following Pascal script needs a bit of context for its purpose to be understood. For those who don't give about purpose, feel free to skip ahead.
Background
A game I'm terribly fond of has a couple of levels which have nothing to do with the rest of the game. One of those is a puzzle:
When you open the game, it looks like this:
Turns out you need to connect all the 8 red dots to the emitter like this:
All dots must be clicked in a specific sequence. If a dot is clicked and allowed to switch, it will light up if not already lit up. If it was already lit up it will darken again. The sequence to light up the 8th dot looks like this:
The mathematically inclined can probably tell us what such a sequence is called, but it should be obvious to the rest of us that the first 7 characters are always the same and only the 8th varies.
Now, there's an achievement for lighting up all 8 dots within 60 seconds. Since it's already 128 clicks for lighting up the 8th one alone, I decided to automate the process using SCAR Divi (manual), an environment running Pascal scripts which allows you to automate keyboard presses and mouse movements.
Code
The resulting code is ugly, but I was mainly looking for fast code. This means it may not be up to par with Pascal-style and I took a short-cut wherever I thought it would influence the execution speed.
I'm looking for improvements on readability wherever this does not hurt the performance in any way. I've written a fair bit of Pascal but I've always been a little fuzzy on what did and didn't impact performance. General tips about this are welcome.
The most used procedure is
Background
A game I'm terribly fond of has a couple of levels which have nothing to do with the rest of the game. One of those is a puzzle:
Alpha Sector::virgilw::BrainWhen you open the game, it looks like this:
Turns out you need to connect all the 8 red dots to the emitter like this:
All dots must be clicked in a specific sequence. If a dot is clicked and allowed to switch, it will light up if not already lit up. If it was already lit up it will darken again. The sequence to light up the 8th dot looks like this:
1 2 1 3 1 2 1 4
1 2 1 3 1 2 1 5
1 2 1 3 1 2 1 4
1 2 1 3 1 2 1 6
1 2 1 3 1 2 1 4
1 2 1 3 1 2 1 5
1 2 1 3 1 2 1 4
1 2 1 3 1 2 1 7
1 2 1 3 1 2 1 4
1 2 1 3 1 2 1 5
1 2 1 3 1 2 1 4
1 2 1 3 1 2 1 6
1 2 1 3 1 2 1 4
1 2 1 3 1 2 1 5
1 2 1 3 1 2 1 4
1 2 1 3 1 2 1 8
The mathematically inclined can probably tell us what such a sequence is called, but it should be obvious to the rest of us that the first 7 characters are always the same and only the 8th varies.
Now, there's an achievement for lighting up all 8 dots within 60 seconds. Since it's already 128 clicks for lighting up the 8th one alone, I decided to automate the process using SCAR Divi (manual), an environment running Pascal scripts which allows you to automate keyboard presses and mouse movements.
Code
The resulting code is ugly, but I was mainly looking for fast code. This means it may not be up to par with Pascal-style and I took a short-cut wherever I thought it would influence the execution speed.
I'm looking for improvements on readability wherever this does not hurt the performance in any way. I've written a fair bit of Pascal but I've always been a little fuzzy on what did and didn't impact performance. General tips about this are welcome.
The most used procedure is
MnC(x, y), short for Move'n'Click. It moves the mouse to whatever coordSolution
I've done similar things in the past, although never with a scripting language and I haven't used Pascal in a really long time, so this is more of an approach review than a code review.
The action happens in
Moving the Mouse
The first thing you do is
If it is only concerned by the clicks, then great, you only need to worry about clicking the mouse. If the program does care about the movement then you might want to think about using the
Clicking the mouse
After you click the mouse, you wait before doing the next thing. You may be able to make it so that you don't need to wait as long by using playing with
The action happens in
MnC:Procedure MnC(x,y : integer);
begin
MoveMouse(x,y);
Wait(30);
ClickMouse(x,y,false);
Wait(29);
end;Moving the Mouse
The first thing you do is
MouseMove. The question that immediately springs to mind is do you need to move the mouse? Unless the program your are interacting with actually tracks mouse movements in an attempt to detect bots, you probably don't need to move it. Most of the times in the programs I have written I have been able to just send mouse click events at the relevant coordinates. The library you're using supports a SetMousePos method that will simply set the coordinates of the mouse. However, as ClickMouse calls this under the hood, this might not work for you. I'd try running the script with just two clicks and a longer wait between them to detect if the program really requires the movements or if it's only concerned by the clicks.ClickMouse(421,298,false);
Wait(100);
ClickMouse(470,311,false);
Wait(100);If it is only concerned by the clicks, then great, you only need to worry about clicking the mouse. If the program does care about the movement then you might want to think about using the
MoveMouseEx function, which supports an additional parameter MouseSpeed. The default speed is 20, with larger numbers being faster so increasing the number should either make the function return faster, or allow you to wait for less time before clicking. Depending on whether the movement is async, you may also find that you need to wait less time for shorter movements (i.e. the mouse will get from 8 to 7 faster than it will get from 8 to 1).Clicking the mouse
After you click the mouse, you wait before doing the next thing. You may be able to make it so that you don't need to wait as long by using playing with
MouseClickEx and passing in different values for Interval which is how long the mouse button is held down for. Alternately, depending on how your application works you may be able to detect that the mouse click has been recognised (because some pixels have changed from red to green for example). The library appears to have a few functions that might support this: FindColors or FindBitmap would appear to be good starting points. You could then loop until the click has been recognised, rather than waiting.Code Snippets
Procedure MnC(x,y : integer);
begin
MoveMouse(x,y);
Wait(30);
ClickMouse(x,y,false);
Wait(29);
end;ClickMouse(421,298,false);
Wait(100);
ClickMouse(470,311,false);
Wait(100);Context
StackExchange Code Review Q#119318, answer score: 2
Revisions (0)
No revisions yet.