InGame v2.0

Post gaming related scripts
_3D_
Posts: 189
Joined: 29 Jan 2014, 14:40

[POWER of FAT ARROW functions] Part I - Mostly harmless.

23 Aug 2018, 14:06

Preamble:
https://lexikos.github.io/v2/docs/Varia ... #fat-arrow () => expr it is simple sintax but let see what it can do.
Examples:
Lets begin with something simple.

Code: Select all

sup:= 7
function()
function() {
	global			;global scope to function()
	out:= 10
	;function name is visible inside whole containing body
	scop( 5)
	;scop()'s variables scope is the same as scope containing scop()		
	scop(arg) => (msgBox("arg= " arg " out= " out " sup= " sup))
}
To be demonstrated variables visibility all fat arrow functions will be pressent as sub functions. If function() "see" global variables scop() will "see" them too.
The most important things in one alghoritm is divergency and cyclicality.
Let see what about if/else/loop/for/do/while/until.

Code: Select all

glo:= 7
obj:= {one:"oneVal", two:"twoVal"}

function()
function() {
	global
	extr()
	extr() => (
		(if glo == 13		;no action
			MsgBox("true " (glo==13))
		),
		(loop 10			;no action
			MsgBox("loop A_Index= " A_Index)
		),
		(while glo > 0		;no action
			MsgBox("while A_Index= " A_Index)
		),
		(for k,v in obj		;no action
			MsgBox("key:val= [" k ":" v "]")
	)	)
}
As if/else/loop/for/do/while/until are not expressions so they not work.
About IF.

Code: Select all

function()	
function() { ;ternary instead if/else
	_if(5)
	_if(arg) => (arg == 5? MsgBox(arg "==5"): ;if a==5 then MsgBox(arg "==5")
						   MsgBox(arg "!=5")  ;		   else MsgBox(arg "!=5")
				)							  ;"" must be used as nothing
   ;_if(arg) => (arg == 5? MsgBox(arg): "")	  ;	  at both places (then/else)		
}
About LOOP/WHILE.

Code: Select all

function()
function() { ;recursion instead loop/while
	_loop(10)		
	_loop(arg) => (	
		arg > 0	? tooltip(arg) sleep(1000) _loop(arg-1) ;no comma 
				: tooltip()
	)
}
Don`t forget recursion is powerful but must be guaranteed end of recursion and think about stack (most arguments - most stack).
Different expressions not enclosed and not comma separated it is possible but not well.
Yet another recursion example.

Code: Select all

function()
function() {
	;global		
	local sta	;_for use local variable
				;to keep value in recursion
	_for()
	_for() => ( ;for(sta:=10; sta > 2; sta:=sta-1) {
				;	tooltip("sta= " sta)
				;	sleep(mis)
				;}
				;tooltip()
		(sta:= sta? sta-1: 10),
		(sta > 2 ? tooltip("sta= " sta) sleep(1000) _for()
				 : tooltip()
	)	)
}
And another one but here fat arrow function inside fat arrow function.

Code: Select all

function()
MsgBox("global= " glo) 
function() {
	global
	out:= 10
	recu()			
	recu() => (
		(glo:= glo? glo: 20), ;create global variable (if global)
							  ;comma is a must
		(out > 0? sub_%mod(out, 2)%()				;new line
				  sleep(1000) out-- recu()			;no comma
				: ""
		),
		;fat arrow function in fat arrow function
		sub_1() => (tooltip("1= " out " glo= " (glo-=1)))					  
	)
	sub_0() => (tooltip("0= " out " glo= " (glo-=1)))
}
Conclusions:

Code: Select all

;think for fat arrow function as expresion that must return result
FatArrowFunc([byRef]arg) => (	
	;variables
	;	byRef - work as usual
	;	scope - the same as scope of containing scope
	;	create variables -	as part of expression
	;		global 	;no affect even persist
	;		local	;"
	;		static 	;"
	;			 -	newly created variable can be
	;				local for fatArrowFunc()
	;				or
	;				global (if global persyst in containing scope)
	;			 -	there no mechanism subfunction to create
	;				variable into containing function
	
	(<var:= expr/func>), ;comma is a must if new variable created
						 ;() and , is not mandatory but using them
						 ;		   is best for syntax and readability
	(<expr/func>)	;space or new line separate expressions
					;using () and comma is the best and clear syntax
				
	;if/else/loop/for/do/while/until
	;	and so on not expressions not ussable  
	
	((arg)? (<expr/func>): (<expr/func>))
	
	;best syntax - brakets and commas
	;FatArrowFunc(arg) => (
	;	(<expression>),
	;	(<expression>),
	;	((<expression>) ? (<expression>)
	;				  	: (<expression>)
	;	),
	;	"" ;do nothing (NOP)
	;)
	
	;retun		;forbiden
	;			;think that return is at => place
	;					 =>
	;FatArrowFunc(arg) { return (
	;	(<expr>),
	;	(<expr>)
	;)
	;}
	
	;last expression is return value
)
All examples in one only code:

Code: Select all

#SingleInstance Force
;Copyright (c) D.Donchev

mis:= 200
sup:= 7
obj:= {one:"oneVal", two:"twoVal"}

function()
msgBox("glo= " glo)	;see recu()

function() {
	global			;function() scope to global
	out:= 10
;scop example ==========
	scop( 5)		;function name is visible
					;inside whole containing body
	scop(arg) => ( 	;scop() variable scope is the same as
					;scope containing scop()
		msgBox("arg= " arg " out= " out " sup= " sup)
	)
;}	
;cycl example ==========	
	cycl(10)		;recursion
	cycl(arg) => (	;recursion instead loop
		arg > 0	? tooltip(arg) sleep(mis) cycl(arg-1) ;no comma 
				: tooltip()
	)
;}	
;recu example ==========	
	recu()			;visibility
	recu() => (
		(glo:= glo? glo: 20), ;create global variable (if global)
							  ;comma is a must
		
		(out > 0? sub%mod(out, 2)%()				;new line
				  sleep(mis) out-- recu()			;no comma
				: ""
		),	;enclosure ternary expression
		;fat arrow function  in fat arrow function
		sub1() => (tooltip("1= " out " glo= " (glo-=1)))					  
	) 
	sub0() => (tooltip("0= " out " glo= " (glo-=1)))
;}
;_for example ==========
	local sta	;_for use local variable
				;to keep value in recursion
	_for()
	_for() => ( ;for(sta:=10; sta > 2; sta:=sta-1) {
				;	tooltip("sta= " sta)
				;	sleep(mis)
				;}
				;tooltip()
		(sta:= sta? sta-1: 10), 
		(sta > 2 ? tooltip("sta= " sta) sleep(mis) _for()
				 : tooltip()
	)	)
;}	
;extr example ==========	
	extr()
	extr() => (
		(if glo == 13		;no action
			MsgBox("true " (glo==13))
		),
		(loop 10			;no action
			MsgBox("loop A_Index= " A_Index)
		),
		(while sup > 0		;no action
			MsgBox("while A_Index= " A_Index)
		),
		(for k,v in obj		;no action
			MsgBox("key:val= [" k ":" v "]")
	)	)
}
ExitApp
#!Q::ExitApp
Working example - fat arrow function as function argument.

Code: Select all

myToolTip("111", 200, 200, 20, 3000)
myToolTip("222", 100, 100,   , 2000)

myToolTip(text, x:="", y:="", w:="", time:="") {
	tooltip(text, x, y, w)
	if(time is "number")
		SetTimer(()=>tooltip(,,,w), time<0?time:-time) ;fat as argument
}
Fat arrow functions and classes.

Code: Select all

class A {
	static var:= 1
	met() {
		return 2
	}
	fat()=>(3)
}

for k,v in A
	MsgBox(k " : " v " -> " type(v))
	
MsgBox("outside A => " fat()) ;fat() is global becouse class definition is global

Code: Select all

	_Class  : A -> String		(ok)
	var		: 1 -> Integer		(ok)
	met		:	-> Func			(ok)
	
	fat is invisible lol -->	(no)
		is not a member of A	(ok)
All fat arrow functions defined inside class definition becomes global.

Code: Select all

#SingleInstance Force
;Copyright (c) D.Donchev

class Def {
	static ClassVar
	one:= 1
	two:= 2

	;Example (1) run last set fat function
	ini(arg:="") {
		if(type(arg) == "Func")
			this.ClassVar:= arg				;set
		if(type(this.ClassVar) != "Func")
			this.ClassVar:= ()=>"default"	;default
			
		MsgBox(%this.ClassVar%())			;action
	}
	;Example (2) run argument fat func or internal
	tos(arg:="") {
		;arg:= type(arg) == "Func"? arg: ()=>"no format"
		if(type(arg) != "Func")
			arg:= ()=>"no format"
		return %arg%(this)
}	}
Ins:= new Def
;Example (1) ----------
Def.ini()	;default
Ins.ini()	;default
;expect: if ClassVar not set then init
;OK
Def.ini(()=>"class new")	;class new
Ins.ini()					;class new
;expect: if class ClassVar is changed then instance ClassVar changed
;OK
Ins.ini(()=>"instanse new") ;instanse new
Def.ini()					;class new
Ins.ini()					;instance new
;expect: ;if instance ClassVar is changed then class ClassVar NOT changeg
;OK
;Examle (2) ----------
MsgBox(Ins.tos())
;expected: run internal default fat func
;OK
MsgBox(Ins.tos((this) => ("myown= " this.one " then " this.two)))
;expected: run argument fat func
;OK
MsgBox(Ins.tos((this) => ( ;recursion demo
	;for(k, v in this)
	;	res.= k " : " v " | "
	;return res
	
	;3 lines - without pushing arguments
	;(_enum:= this._NewEnum()),
	;_act()=>(_enum.Next(k,v)? ((res .= k ":" v "|"), _act()): res),
	;_act()
	
	;2 lines - stack breaker (LOL)
	_act(_enum)=>(_enum.Next(k,v)? ((res .= k ":" v "|"), _act(_enum)): res),
	_act(this._NewEnum())
)))
;expected: recursion must end
;OK

ExitApp
#!Q::ExitApp ;if something wrong
Comments inside the code. Most important is that all functions related to classes must have at least one argument because all methods are called with first argument this.
Again:
Enclose all individual expression in () and separate expressions with comas. Enclose all expressions in () like {} for best reading. "" can be used as nothing (NOP). Ternary instead IF/ELSE and recursion instead LOOP/WHILE.

Code: Select all

[FatArrowFunctionName]([agruments])=>(
	(expression),
	(expression) ;last expression is return value
)
Enjoy!
AHKv2.0 use the future now.
_3D_
Posts: 189
Joined: 29 Jan 2014, 14:40

dd_pixelGetColor.ahk

31 Aug 2018, 03:53

An old project that I use all the time.
https://autohotkey.com/boards/viewtopic ... 400#p17615
Some in time I add snapShot() that get bmp from screen and save it to file. So this day I revised snapShot() and let see what happen:
The first code:

Code: Select all

snapShot() {
	Suspend("On")  ;disable hotkeys to be used in InputBox
	param:= InputBox("SnapShot",,"W150 H100")
	Suspend("Off") ;enable hotkeys
	
	loop (param:= StrSplit(param, [",",":","|"," "])).length() ;delimiters
		if param[A_Index] {
			goto("CASE_" (++cnt)) ;switch
			CASE_1: ;begin point x coordinate
				x:= param[A_Index]
				continue
			CASE_2: ;begin point y coordinate
				y:= param[A_Index]
				continue
			CASE_3: ;width or end point x coordinate   
				if RegExMatch(param[A_Index], "i)W([\d]+)", arg)
					 w:= arg[1]
				else w:= param[A_Index] - x + 1 ;calculate x2-x1+1
				continue
			CASE_4: ;height or end point y coordinate
				if RegExMatch(param[A_Index], "i)H([\d]+)", arg)
					 h:= arg[1]
				else h:= param[A_Index] - y + 1 ;calculate y2-y1+1
				break ;break loop
		}
	Gdip_SaveBitmapToFile(pBmp:= Gdip_BitmapFromScreen(x "|" y "|" w "|" h), ".\" x "-" y ".bmp")
		Gdip_DisposeImage(pBmp)
}
I see that too many madness in code.
First revise:

Code: Select all

snapShot() {
	Suspend("On")  ;disable hotkeys to be used in InputBox
	loop Parse, InputBox("SnapShot",,"W150 H100"), ",:| " ;delimiters
		if A_LoopField {
			goto("CASE_" (++cnt)) ;switch
			CASE_1: ;begin point x coordinate
				x:= A_LoopField
				continue
			CASE_2: ;begin point y coordinate
				y:= A_LoopField
				continue
			CASE_3: ;width or end point x coordinate   
				w:= RegExMatch(A_LoopField, "i)W([\d]+)", arg)? arg[1]: A_LoopField - x + 1 ;calculate x2-x1+1
				continue
			CASE_4: ;height or end point y coordinate
				h:= RegExMatch(A_LoopField, "i)H([\d]+)", arg)? arg[1]: A_LoopField - y + 1 ;calculate y2-y1+1
				break ;break loop
		}
	Suspend("Off") ;enable hotkeys	
	Gdip_SaveBitmapToFile(pBmp:= Gdip_BitmapFromScreen(x "|" y "|" w "|" h), ".\" x "-" y ".bmp")
		Gdip_DisposeImage(pBmp)
}
Loop Parse instead StrSplit - faster and less ram.
Now how to avoid Goto? A simple test function:

Code: Select all

#SingleInstance Force
;Copyright (c) D.Donchev
fun()
fun() {
	x:= y:= w:= h:= 0 ;define variables for fat functions
	;fat functions throws exceptions if not number result
	static xywh :=	[()=>(x:= A_LoopField + 0)
					,()=>(y:= A_LoopField + 0)
					,()=>(w:= RegExMatch(A_LoopField, "i)W([\d]+)", _)? _[1]: A_LoopField - x + 1)
					,()=>(h:= RegExMatch(A_LoopField, "i)H([\d]+)", _)? _[1]: A_LoopField - y + 1)]
	;possible syntaxes
	;100 200 109 209
	;100 200 W10 209
	;100 200 109 H10
	;100 200 W10 H10
	;Suspend("On" ) ;disable hotkeys 
	cntr:= 1
	loop Parse, i:= InputBox("SnapShot",,"W150 H100"), ",:| " 	;i - just for test
		if A_LoopField 			;skip "" (100: 200: W10: H10) 
			try xywh[cntr++]()	;keep 0 for incorrect syntax parameter
			catch
				MsgBox("Incorrect syntax: parameter " cntr-1 ":= " A_LoopField)
	until(cntr > 4)
	MsgBox(i "`nX`t:= " x "`nY`t:= " y "`nW`t:= " w "`nH`t:= " h)
	;Gdip_SaveBitmapToFile(pBmp:= Gdip_BitmapFromScreen(x "|" y "|" w "|" h), ".\" x "-" y ".bmp")
	;	Gdip_DisposeImage(pBmp)
	;Suspend("Off")
}
ExitApp
#!Q::ExitApp ;quit
Function needed 4 parameters x, y, w, h
- x and y - start point coordinate
- w and h - end point coordinate or width and height (see syntax in code)
And the result without comments:

Code: Select all

snapShot() {
	x:= y:= w:= h:= 0 ;define variables for fat functions
	static xywh :=	[()=>(x:= A_LoopField + 0)
					,()=>(y:= A_LoopField + 0)
					,()=>(w:= RegExMatch(A_LoopField, "i)W([\d]+)", _)? _[1]: A_LoopField - x + 1)
					,()=>(h:= RegExMatch(A_LoopField, "i)H([\d]+)", _)? _[1]: A_LoopField - y + 1)]
	Suspend("On" )
	cntr:= 1
	loop Parse, InputBox("SnapShot",,"W150 H100"), ",:| " 	
		if A_LoopField 			
			try xywh[cntr++]()	
	until(cntr > 4)
	Suspend("Off")
	
	Gdip_SaveBitmapToFile(pBmp:= Gdip_BitmapFromScreen(x "|" y "|" w "|" h), ".\" x "-" y ".bmp")
		Gdip_DisposeImage(pBmp)
}
And the whole project:

Code: Select all

#SingleInstance Force
;Copyright (c) D.Donchev

CoordMode("Mouse", "Screen")
CoordMode("Pixel", "Screen")
	pToken:= Gdip_Startup()
	Gui:= GuiCreate("-Caption +E0x80000 +LastFound +AlwaysOnTop +ToolWindow +OwnDialogs")
	Gui.Show("NA")
  
	hwnd:= WinExist()
	hbm := CreateDIBSection(mwW:=75, mwH:=35)
	hdc := CreateCompatibleDC()
	obm := SelectObject(hdc, hbm)
	G   := Gdip_GraphicsFromHDC(hdc)
  
	Gdip_SetSmoothingMode(G, 4)
	pBrush := Gdip_BrushCreateSolid(0x7FC0C0C0)
	Gdip_FillRectangle(G, pBrush,  0, 0, mwW, mwH), Gdip_DeleteBrush(pBrush)
	MouseGetPos mX, mY
	UpdateLayeredWindow(hwnd, hdc, mX, mY, mwW, mwH)
	OnMessage(0x200, ()=>PostMessage(0xA1, 2))
	ShowHide:= RunStop:= 1
	SetTimer("mainWindowContent", 100)
  
mainWindowContent() {
	global
	MouseGetPos mX, mY
	color  := Gdip_GetPixel(Gdip_BitmapFromScreen(mX "|" mY "|1|1", 0x40CC0020), 0, 0) & 0xFFFFFF
	tcolor := (color > 0x800000)? "FF000000": "FFFFFFFF"
	pBrush := Gdip_BrushCreateSolid(0xFF000000|color)
	Gdip_FillRectangle(G, pBrush,  5,  5, mwW-10, mwH-10), Gdip_DeleteBrush(pBrush)
	Gdip_TextToGraphics(G, format("{1:4d}:{2:4d}", mX, mY), "X0 Y6 Center C" tcolor " R4 S10 Bold", "Verdana", mwW, 47)
	Gdip_TextToGraphics(G, format("{1:06X}", color)       , "X0 Y17 Center C" tcolor " R4 S10 Bold", "Verdana", mwW, 47)
	UpdateLayeredWindow(hwnd, hdc)
}

!Space::RunStop :=!RunStop , GuiControl()
#Space::ShowHide:=!ShowHide, GuiControl()
#M:: ;move mouse pointer to possition
	m:= StrSplit(InputBox("Position(X Y)",,"W150 H100",mX " " mY), [",",":","|"," "])
	MouseMove(m[1], m[m.length()])            
return
#!S::snapShot()		
#!F4::ExitApp
#!F1::msgBOX(""
	. "ALT+Space`tRun/Stop`n"
	. "WIN+Space`tShow/Hide`n"
	. "WIN+M`t`tMouseMove`n"
	. "WIN+ALT+S`tSnapShot`n"
	. "WIN+ALT+F1`tHelp`n"
	. "WIN+ALT+F4`tExit")
GuiControl() {
	global
	SetTimer("mainWindowContent", "Off")
	Gui.Hide()
	if ShowHide {
		SetTimer("mainWindowContent", RunStop? "On": "Off")
		Gui.Show()
} 	}
snapShot() {
	x:= y:= w:= h:= 0 ;define variables for fat functions
	static xywh :=	[()=>(x:= A_LoopField + 0)
					,()=>(y:= A_LoopField + 0)
					,()=>(w:= RegExMatch(A_LoopField, "i)W([\d]+)", _)? _[1]: A_LoopField - x + 1)
					,()=>(h:= RegExMatch(A_LoopField, "i)H([\d]+)", _)? _[1]: A_LoopField - y + 1)]
	Suspend("On" )
	cntr:= 1
	loop Parse, InputBox("SnapShot",,"W150 H100"), ",:| " 	
		if A_LoopField 			
			try xywh[cntr++]()	
	until(cntr > 4)
	Suspend("Off")
	
	Gdip_SaveBitmapToFile(pBmp:= Gdip_BitmapFromScreen(x "|" y "|" w "|" h), ".\" x "-" y ".bmp")
		Gdip_DisposeImage(pBmp)
}
Enjoy!
AHKv2.0 use the future now.
_3D_
Posts: 189
Joined: 29 Jan 2014, 14:40

fast and furious

23 Sep 2018, 02:55

A simple speed test about sending and running functions as arguments.

Code: Select all

#SingleInstance Force
;Copyright (c) D.Donchev

loops:= 100000
;test function
funct() {
	return ""
}
fatfu()=>""
;complete argument check ------------------------------------------------------
ff_1(arg:="") {
	return %(type(arg) == "Func"? arg: ()=>)%()
}
;run if only ------------------------------------------------------------------
ff_2(arg:="") {
	if(type(arg) == "Func")
		return %arg%()
}
;try to run -------------------------------------------------------------------
ff_3(arg:="") {
	try return %arg%()
}
;ternary run ------------------------------------------------------------------
ff_4(arg:="") {
	return type(arg) == "Func"? %arg%(): ""
}
loop 4 {
	fn:= A_Index
	elaps:= A_TickCount
	loop loops
		ff_%fn%()				;ternary run faster - fast check
		;ff_%fn%(Func("funct"))	;try run faster - nothing to check
		;ff_%fn%(Func("fatfu"))	;try run faster - nothing to check
		;ff_%fn%(()=>"") 		;try run faster - nothing to check
	elaps:= A_TickCount - elaps
	MsgBox(fn ":=" elaps)
}
The conclusions:
1. If everything fine - try run is faster - due to no any additional check.
2. If is needed check - ternary run is faster - due to faster check.
It is script language and user must keep language rules. So complete propriety check not possible.

Enjoy!
AHKv2.0 use the future now.

Return to “Gaming”

Who is online

Users browsing this forum: No registered users and 7 guests