autohotkey use a return value imagesearch and click - autohotkey

I have a function:
NormalRand(x,y,int=1) {
Loop 12
{
Random, var,0.0,1
Num+=var
}
norm := (int) ? Round((y+x)/2+((Num-6)*(y-x))/6) : (y+x)/2+((Num-6)*(y-x))/6
Return norm < x ? x : norm > y ? y : norm
}
I have an imagesearch:
ImageSearch, FoundX, FoundY, 0, 0, A_ScreenWidth, A_ScreenWidth, *50 Okay.jpg
If ErrorLevel = 0
{
xCord = NormalRand(%FoundX%-10,%FoundX%+10)
yCord = NormalRand(%FoundY%-10,%FoundY%+10)
MsgBox, 4,, Found the image at %xCord% %yCord%
Click, %xCord%, %yCord% Left, 1
Sleep, 2000
}
I am trying to use the NormalRand function to distribute my clicks around the buttons so they are harder to detect within the program I will use this with. However, when i try to sent the cords to the click it doens't work. When i test it with msgbox i get this output Found the image at NormalRand(391-10,391+10) NormalRand(676-10,676+10)
I can't seem to figure out how to get it to send the numbers instead of the text.

What we have here, is misuse, and probably also unintentional use, of the legacy syntax.
Lets look at these two lines:
xCord = NormalRand(%FoundX%-10,%FoundX%+10)
yCord = NormalRand(%FoundY%-10,%FoundY%+10)
You're actually assigning text to those variables, not calling a function.
See this as an example:
xCord = NormalRand(%FoundX%-10,%FoundX%+10)
yCord = NormalRand(%FoundY%-10,%FoundY%+10)
MsgBox, % xCord "`n" yCord
For legacy syntax you're referencing the FoundX and FoundY variables correctly by wrapping them around %, but you're not doing that for the function name.
So in legacy syntax you'd do this:
xCord = %NormalRand%(%FoundX%-10,%FoundX%+10)
yCord = %NormalRand%(%FoundY%-10,%FoundY%+10)
However, please stop using legacy syntax. It's so ancient, bad and very different compared to other programming languages you maybe have experienced.
Expression syntax is what you want to use, so instead of legacy =, we're using := to assign an expression to our variables. (= is never ever used!)
In expression syntax your function calls look normal and nice:
xCord := NormalRand(FoundX-10, FoundX+10)
yCord := NormalRand(FoundY-10, FoundY+10)
And to preach even more about legacy syntax, you're also using it on the if-statement. To not use the legacy if-statement, use if ().

Related

Issue returning proper mouse cords

In this problem setXTowerLocation() is called, a message box than appears after exiting the message box the function getXCords() is called in which it continuously scans checking the keyState of Lbutton once it detects that its pushed down the getxCords() function returns the x value of the cords of the mouse, which in turned gets set to a global variable in the setXTowerLocation() function before returning and displaying the x cord in a message box. Every time i run it the message box comes up blank, i have tested aspects of the code and they all seem to work individually so i believe it must be an error in syntax?
The ending message box is only for testing purposes. Thanks in advance :)
SendMode Input
Global xTowerLocation =
setXTowerLocation()
MsgBox, 0, MessageBox, %xTowerLocation%
getxCords()
{
xCord =
Loop,
{
GetKeyState, state, Lbutton
if(state = "D")
{
MouseGetPos, xx, yy
xCord := %xx%
return
}
}
return xCord
}
setXTowerLocation() {
MsgBox, 0, MessageBox, Begin?
IfMsgBox OK
xTowerLocation := getxCords()
return
}
Yes, syntax error in that xCord is referenced to a variable named after the contents (the mouse coord). Fix these two lines in getxCords() so xCord holds the value of the variable xx as follows:
xCord := xx
return xCord
And then no xCord on that later return (at end of the function).
EDIT: For even more fun, make the above xCord line as follows:
xCord := "x= " . xx . " , y= " . yy

Julia + GTK - global variable change in callback

I am trying to learn Julia Language, and my current project is a "5 in a row" program. I started making an interface with Julia wrapper on Gtk for this game, but stumbled upon an interesting problem. Code is below.
The problem is: after callback function work cur_step variable is not changing, and labels of buttons are not changing too. However, if I delete the if-condition in the callback function, buttons will all get labels "x" after pressing as it is supposed to be right now.
I'm writing my code with Julia 1.0 in Jupyter Notebook.
I've tried to set up cur_step variable as global, since thought that it was a scope problem, but it didn't work out.
using Gtk
cur_step = "x"
function click_once_callback(widget)
set_gtk_property!(widget, :sensitive, false)
set_gtk_property!(widget, :label, cur_step)
if cur_step == "x"
cur_step = "o"
else
cur_step = "x"
end
end
letters = ['a','b','c','d','e','f','g','h','i','j','k','l','m','n','o']
win = GtkWindow("GoMoku")
g = GtkGrid()
buttons = []
for i=1:15
b = []
for j=1:15
letter = letters[i]
push!(b,GtkButton("$letter:$j"))
end
push!(buttons,b)
end
for i=1:15
for j=1:15
g[i,16-j] = buttons[i][j]
id = signal_connect(click_once_callback, buttons[i][j], "clicked")
end
end
set_gtk_property!(g, :column_homogeneous, true)
set_gtk_property!(g, :column_spacing, 15) # introduce a 15-pixel gap between columns
set_gtk_property!(g, :row_spacing, 15) # introduce a 15-pixel gap between rows
push!(win, g)
showall(win)
Why is it so that global variable not changing through the callback function? I expect to change cur_step iteratively after each button was clicked.
Thank you in advance!
You need to label cur_step as global inside your function (as well as outside, for good code signposting).
A function can use a variable from its parent scope without problems, as long as there's no assignment anywhere within the function's scope. If there is an assignment somewhere (even if it's in an if block), then the function is interpreted as local; this is true even prior to the point where its assignment occurs.
In order to treat a variable that gets assigned at some point inside the function properly as a global one, you need to explicitly point this out inside the function by using global cur_step.

Repeatedly calling a hotkey

I've tried to implement a t flip flop(I think this is what it's called) into my program but am having some issues with it. The idea is to have the program start and stop while using the same hotkey. This is what I have so far.
looping := false
pass = 0
max = 2
^r::
pass++
looping := true
while(looping = true AND pass < max)
{
Send, stack overflow, save me!
}
looping := false
pass = 0
return
When I run the program and hit the hotkey the while loop starts. However, when I attempt to break the loop by pressing ^r I get no response and the program keeps looping.
I think you are referring to a "toggle" script. I am not what sure you are trying to achieve exactly, but the key is using a logical not: looping := !true. More about it here.
looping := false
pass = 0
max = 2
^r::
pass++
looping := !true
while (looping & pass < max)
{
Send, stack overflow, save me!
}
pass = 0
return
There's a lot of resources for this, here are a few:
https://autohotkey.com/boards/viewtopic.php?t=11952
http://maul-esel.github.io/ahkbook/en/toggle-autofire.html
https://www.reddit.com/r/AutoHotkey/comments/6wqgbu/how_do_i_toggle_hold_down_a_key/dmad0xx

1-line try/catch equivalent in MATLAB

I have a situation in MATLAB where I want to try to assign a struct field into a new variable, like this:
swimming = fish.carp;
BUT the field carp may or may not be defined. Is there a way to specify a default value in case carp is not a valid field? For example, in Perl I would write
my $swimming = $fish{carp} or my $swimming = 0;
where 0 is the default value and or specifies the action to be performed if the assignment fails. Seems like something similar should exist in MATLAB, but I can't seem to find any documentation of it. For the sake of code readability I'd rather not use an if statement or a try/catch block, if I can help it.
You can make your own function to handle this and keep the code rather clear. Something like:
swimming = get_struct(fish, 'carp', 0);
with
function v = get_struct(s, f, d)
if isfield(s, f)
v = s.(f); % Struct value
else
v = d; % Default value
end
Best,
From what I know, you can't do it in one line in MATLAB. MATLAB logical constructs require explicit if/else statements and can't do it in one line... like in Perl or Python.
What you can do is check to see if the fish structure contains the carp field. If it isn't, then you can set the default value to be 0.
Use isfield to help you do that. Therefore:
if isfield(fish, 'carp')
swimming = fish.carp;
else
swimming = 0;
end
Also, as what Ratbert said, you can put it into one line with commas... but again, you still need that if/else construct:
if isfield(fish,'carp'), swimming = fish.carp; else, swimming = 0;
Another possible workaround is to declare a custom function yourself that takes in a structure and a field, and allow it to return the value at the field, or 0.
function [out] = get_field(S, field)
if isfield(S, field)
out = S.(field);
else
out = 0;
end
Then, you can do this:
swimming = get_field(fish, 'carp');
swimming will either by 0, or fish.carp. This way, it doesn't sacrifice code readability, but you'll need to create a custom function to do what you want.
If you don't like to define a custom function in a separate function file - which is certainly a good option - you can define two anonymous functions at the beginning of your script instead.
helper = {#(s,f) 0, #(s,f) s.(f)}
getfieldOrDefault = #(s,f) helper{ isfield(s,f) + 1 }(s,f)
With the definition
fish.carp = 42
and the function calls
a = getfieldOrDefault(fish,'carp')
b = getfieldOrDefault(fish,'codfish')
you get for the first one
a = 42
and the previous defined default value for the second case
b = 0

Create a CoffeeScript range with a length instead an endpoint?

I want to create a CoffeeScript range (like [4...496]) but using a length instead of an end range. This can be done with a loop like
myNum = getBigNumber()
newArray = ( n + myNum for n in [0...50] )
but I'm wondering if there is range-related shortcut that I'm missing. Is there something like
[getBigNumber()...].length(50) available in CoffeeScript?
You can just do
range = [myNum...myNum + 50]
Edit: As mu points out in the comments, CoffeeScript will add some complexity whether you use the snippet above or the original code. If performance is an issue, it might be better to drop down to plain JS for the loop (using backticks in the CoffeeScript code).
Assuming you want an ascending (i.e. low to high) range, you can do:
myNum = getBigNumber()
length = 50
range = new Array length
i = 0
`for(; i < length ; i++) { range[i] = i + myNum }` # raw, escaped JS
It's a lot faster than CoffeeScript's way of doing things, but note that CoffeeScript's range syntax also supports creating descending ranges by just flipping the boundary values. So CoffeeScript is (as always) easier on the eyes and simpler to work with, but raw JS is 3.5x faster in my test.