Open Side Menu Go to the Top
Register
StackAndTile StackAndTile

12-19-2009 , 08:50 PM
Quote:
Originally Posted by Max1mums
This test will take 10 pixels per table, run it please.
i get around 500 ms for 24 stars tables

Last edited by greg nice; 12-19-2009 at 09:03 PM.
StackAndTile Quote
12-19-2009 , 08:54 PM
btw, i appreciate everyones input and discussion here. it all helps make the program better and more efficient
StackAndTile Quote
12-19-2009 , 09:15 PM
xK1nGeNx, replace this line
WinGet, listft, List, ahk_class Logged in QWidget,,Full Tilt
with this:
WinGet, listft, List, Logged ahk_class QWidget,,Full Tilt

I get about 350 greg but that's not the point, i mean there is no big difference between taking 1 pixel and 10.
StackAndTile Quote
12-19-2009 , 10:48 PM
thanks for your hard work greg, but I dont think flop detection is going to work with the pixel things. At least not on my computer. I thought I had a very good computer (quad core 3.0, 4g ram, nice video card) but after 10+ tables things start to slow down way too much. Thanks for your work regardless.
StackAndTile Quote
12-19-2009 , 11:12 PM
thank you, i am looking into fixes to speed things up
StackAndTile Quote
12-19-2009 , 11:14 PM
Quote:
Originally Posted by Max1mums
but i don't really think you need it, you can take just one or two pixels from buffer and if all are white - there is card on that position.
problem is scaling with various table sizes, and also different card mods. i think thats why betpot uses such a large area to scan for a card

Last edited by greg nice; 12-19-2009 at 11:38 PM.
StackAndTile Quote
12-20-2009 , 12:13 AM
v 1.11

http://www.overcards.com/wiki/moin.cgi/StackAndTile

i've slightly optimized the flop detection, it searches a smaller area now. from my tests, it is just as fast as if it were searching for one pixel. hopefully people can test and report back whether this is improvement or not
StackAndTile Quote
12-20-2009 , 06:04 AM
Quote:
Originally Posted by greg nice
problem is scaling with various table sizes, and also different card mods. i think thats why betpot uses such a large area to scan for a card
But why can't you compare with background color again? Look how PokerShortCuts handle it.
You still look through 165 pixels while you could get same result with 1.

Last edited by Max1mums; 12-20-2009 at 06:16 AM.
StackAndTile Quote
12-20-2009 , 06:48 AM
Anyway it looks like buffer overflow problem, check your code again for possible reasons.
StackAndTile Quote
12-20-2009 , 09:01 AM
Code:
PixelColorA(col_x,col_y,id)
{
  ;critical
  d := "", c := "", p := "", pix := ""
  Display_CreateWindowCapture(d, c, p, id)
  pix := Display_GetPixel(c, col_x, col_y)
  Display_DeleteWindowCapture(d, c, p)
  return pix
}
This seems to be the case, you don't clear buffer here.

I dared to change your code a bit greg, just for people to test it:
Code:
; StackAndTile
version := 1.11
;
; Author: greg nice @ 2p2 (PM me if you would like to make a donation)
; Written in AHK Version: 1.0.48.05
; Source Code License: GNU General Public License v3      
;                      http://www.gnu.org/licenses/gpl.html
; Credit where its due: Chris228 (StarsAssistant), Max1mums, _dave_, juk, Roland, Xander, etc
;
;
; Description:
;
; Allows you to have a stack of tables. When a table requires action, it gets
; tiled into a grid of slots on your screen. When you fold, the table returns
; to the stack. 
;
;
; Latest version and documentation found here:
;
; http://www.overcards.com/wiki/moin.cgi/StackAndTile
;
;
;
; Notes, Limitations, etc:
;
; 1. Move when action required
;
;      Preflop - default method from version 1.00. Tables get tiled into grid when its your turn to act starting preflop. This method is stable and preferred.
;      Flop - Waits until your turn to act on the flop before moving. This method is slow. Please report bugs in 2p2 thread. Still to do: handle conflicting sites auto popup activation
;
; 2. Fold and Re-stack Hotkey
;
;      The table stays in grid until you press the Fold and Re-stack Hotkey. This means a few things:
;      If you go to showdown, the table stays (allowing you to see mucked cards from pt3 hud, etc). This seems ok to me, because you will soon have another preflop decision, in which you can 'Fold, re-stack'
;      If you wish to Fold but keep the table in grid to view the rest of hand, you can manually click Fold with your mouse, or setup a hotkey to Fold in another script.
;
; 3. Other Notes
;
;      1. You must clear your Fold hotkey from other programs like Table Ninja or BetPot. StackAndTile will handle the Folding with its own hotkey.
;      2. If you change any settings in the GUI, you MUST click the Save button before they are used.
;      3. This script does not resize tables. Make sure all your tables are consistent size! Not included because redrawing the Stars tables is intensive.
;      4. To manually change settings, you could edit the ini file yourself and then reload the script.
;          For example, custom slots locations (overlapping, etc):
;          - edit ini file for slot#x and slot#y for each slot and total_slots for how many slots you want 
;
;
;
;
; USERS DONT NEED TO EDIT THIS SCRIPT. 
;
;
;
;
; =====================================================================



#NoEnv 
SendMode Input  
SetWorkingDir %A_ScriptDir% 
SetWinDelay, 10
SetTitleMatchMode, 2       ;// match string anywhere in title, needed for functions that use the ahk_groups
CoordMode, Pixel, Relative

OnExit, ExitSub

starsfoldx := 442                  ;// these are client area coordinates for each site's fold button. 
starsfoldy := 538
ftfoldx := 516                     ;// windowspy_x - xborder = x,
ftfoldy := 501                     ;// windowspy_y - yborder - caption = y

ini := "StackAndTile.ini"
readSettingsIntoVars()
if !FileExist(ini)
  MsgBox, Run Setup before using

GroupAdd, StarsTables, ahk_class PokerStarsTableFrameClass
GroupAdd, FullTiltTables, Logged In As ahk_class QWidget,,,Full Tilt Poker

GroupAdd, AllTables, ahk_group StarsTables
GroupAdd, AllTables, ahk_group FullTiltTables

Menu, Tray, NoStandard
Menu, Tray, Add, StackAndTile, menuGUI
Menu, Tray, Default, StackAndTile
Menu, Tray, Add
Menu, Tray, Add, Exit, ExitSub
Menu, Tray, Tip, StackAndTile v%version%

Gui, +ToolWindow
Gui, Font, cBlack, Tahoma
Gui, Add, Tab2, x6 y11 w360 h360 vMyTab, Control|Settings|Sites
Gui, Add, GroupBox, x26 y41 w320 h200 , 
Gui, Font, s16 bold underline, Tahoma
Gui, Add, Button, x101 y101 w170 h80 vStartButton, Start
Gui, Font, s12 norm bold, Tahoma
Gui, Add, Text, x101 y191 w160 vRunningText,  
Gui, Font, s12 norm, Tahoma
Gui, Add, Button, x101 y271 w170 h50 vSetupButton, Setup Grid
Gui, Font, s8 norm, Tahoma
Gui, Add, Text, x26 y326 w320 vSetupText,  

Gui, Tab, 2
Gui, Font, s10 underline, Tahoma
Gui, Add, GroupBox, x26 y41 w320 h120 , Stack

Gui, Font, s8 norm, Tahoma
Gui, Add, Text, x56 y71, Stack location:
Gui, Add, Radio, x156 y73 checked%StackUsesSlot% gRadioSlot vStackUsesSlot, Slot:
Gui, Add, Radio, x156 y101 checked%StackUsesCustom% gRadioCustom vStackUsesCustom, Custom:
Gui, Font, s8 norm, Tahoma
Gui, Font, s8 norm, Tahoma
Gui, Add, DropDownList, x236 y71 w60 disabled%StackUsesCustom% vDDLslot, 
Loop, %totalslots%
  GuiControl, ,DDLslot, %A_Index%
GuiControl, ChooseString, DDLslot, %stackslot%
Gui, Add, Text, x236 y101 w20 h20, x:
Gui, Add, Text, x236 y121 w20 h20, y:
Gui, Add, Edit, x251 y101 w45 h20 disabled%StackUsesSlot% vCustomStackX, %stackx%
Gui, Add, Edit, x251 y121 w45 h20 disabled%StackUsesSlot% vCustomStackY, %stacky%
Gui, Add, Button, x300 y111 h20 disabled%StackUsesSlot% vGetButton, Get

Gui, Font, s10 underline, Tahoma
Gui, Add, GroupBox, x26 y161 w320 h150 , Tile

Gui, Font, s8 cNavy underline, Tahoma
Gui, Add, Text, x56 y191 gTextHotkey vHotkeyText, Hotkey
Gui, Font, s8 cBlack norm, Tahoma
Gui, Add, Text, x99 y191 vRestackText, to 'Fold and Re-stack' :
Gui, Add, Edit, x246 y191 w60 h20 vFoldHotkey, %FoldHotkey%
Gui, Add, Radio, x86 y216 checked%SendActiveTable% vSendActiveTable, Send to active table
Gui, Add, Radio, x86 y236 checked%SendTableUnderMouse% vSendTableUnderMouse, Send to table under mouse
Gui, Add, Text, x56 y271, Move when action required: 
Gui, Add, DropDownList, x236 y268 w80 vMoveStreet, preflop|flop ***
GuiControl, ChooseString, MoveStreet, %moveonstreet%

Gui, Font, s8 cNavy underline, Tahoma
Gui, Add, Text, x41 y321 h20 gText**, ** 
Gui, Font, s8 cBlack norm, Tahoma
Gui, Add, Button, x256 y321 w90 h30 vSaveButton, Save

Gui, Tab, 3
Gui, Font, s10 underline, Tahoma
Gui, Add, GroupBox, x26 y41 w320 h220 ,  
Gui, Font, s8 norm, Tahoma
Gui, Add, Text, x46 y61 , Which sites would you like to StackAndTile ?
Gui, Add, CheckBox, x46 y101 checked%IncludeStars% gCheckboxPokerStars vIncludeStars, PokerStars
Gui, Add, CheckBox, % "x66 y122 checked" . DetectStarsAIs . " disabled" . !IncludeStars . " vDetectStarsAIs", Detect Stars All-ins  **
Gui, Add, CheckBox, x46 y151 checked%IncludeFulltilt% vIncludeFulltilt, Full Tilt **
Gui, Font, s8 cNavy underline, Tahoma
Gui, Add, Text, x41 y321 h20 gText**, ** 
Gui, Font, s8 cBlack norm, Tahoma
Gui, Add, Button, x256 y321 w90 h30 vSaveButton2, Save

IniRead, guix, %ini%, settings, gui_x, center
IniRead, guiy, %ini%, settings, gui_y, center
Gui, Show, x%guix% y%guiy% w370 h375, StackAndTile v%version%

running := 0
setuprunning := 0

debug := 0


return                    ;// end of autoexec





; ====================
; subs
; ====================


Text**:
  MsgBox,64,, These features marked ** will quite possibly slow things down.`nYou sacrifice potential lag to use them.`n`nIf things aren't working or table colors have changed, try running Setup Grid again.
return


TextHotkey:
  MsgBox,64,, Text of hotkey button must match the AHK naming system.`n`nFor the A key, enter "A"`nFor right mouse click, enter "RButton"`n`nSee this website for the full list:`nhttp://www.autohotkey.com/docs/KeyList.htm
return


menuGUI:
  Gui, Show
return


GuiClose:
  Gui, Cancel
return


RadioSlot:
  GuiControl, enable, DDLslot
  GuiControl, disable, GetButton
  GuiControl, disable, CustomStackX
  GuiControl, disable, CustomStackY
return


RadioCustom:
  GuiControl, disable, DDLslot
  GuiControl, enable, GetButton
  GuiControl, enable, CustomStackX
  GuiControl, enable, CustomStackY
return


CheckboxPokerStars:
  Gui, Submit, NoHide
  if (IncludeStars)   ;// if checked
    GuiControl, enable, DetectStarsAIs
  else 
    GuiControl, disable, DetectStarsAIs
return


ButtonSave:
  Gui, Submit, NoHide
  if StackUsesCustom 
  {
    stackslot := 0
    IniWrite, %CustomStackX%, %ini%, settings, stack_x
    IniWrite, %CustomStackY%, %ini%, settings, stack_y
  }
  else {
    if (DDLslot) {
      stackslot := DDLslot
      IniWrite, % coordxforslot%stackslot%, %ini%, settings, stack_x
      IniWrite, % coordyforslot%stackslot%, %ini%, settings, stack_y
    }
    else {
      MsgBox, 48,, Choose a stack slot
      return
    }
  }
  IniWrite, %stackslot%, %ini%, settings, stack_slot
  IniWrite, %SendTableUnderMouse%, %ini%, settings, send_table_under_mouse
  IniWrite, %FoldHotkey%, %ini%, settings, fold_hotkey
  moveonstreet := MoveStreet
  if (moveonstreet = "flop ***")
    moveonstreet := "flop"
  IniWrite, %moveonstreet%, %ini%, settings, move_on_street
  IniWrite, %IncludeStars%, %ini%, settings, include_stars
  IniWrite, %DetectStarsAIs%, %ini%, settings, detect_stars_allins
  IniWrite, %IncludeFulltilt%, %ini%, settings, include_fulltilt
  Reload             ;// script will readSettingsIntoVars() at the start
return


ButtonStart:
  if (!running) {
    tablequeue := ""            ;// queue of tables that need action (in the stack only)
    slottedlist := ""
    stackedlist := ""
    most_urgent_table := ""
    oldurgent := ""
    Loop, %totalslots% 
      tableinslot%A_Index% := ""     ;// set all slots empty
    Hotkey, %FoldHotkey%, on
    SetTimer, StackAndTile, 500
    GuiControl, disable, SetupButton
    GuiControl, , StartButton, Stop
    GuiControl, , RunningText, Running...
    GuiControl, , MyTab, |Control
    running := 1
  } 
  else {
    Hotkey, %FoldHotkey%, off
    SetTimer, StackAndTile, Off
    GuiControl, enable, SetupButton
    GuiControl, ,StartButton, Start
    GuiControl, ,RunningText,  
    GuiControl, , MyTab, |Control|Settings|Sites
    running := 0
  }
return


ButtonGet:
  Gui +OwnDialogs
  MsgBox, Drag a poker table to the position on screen that you would like the stack to be.`nThen press F12.
  Hotkey, F12, getTableCoords
  Hotkey, F12, on
return


ButtonSetupGrid:
  if (!setuprunning) {
    Gui +OwnDialogs
    Hotkey, F10, setupTableGrid
    Hotkey, F10, on
    GuiControl, , SetupButton, Cancel
    GuiControl, disable, StartButton
    GuiControl, , MyTab, |Control
    MsgBox, Observe a Pokerstars table. Click on it. Press F10.
    GuiControl, , SetupText, Observe a Pokerstars table. Click on it. Press F10.
    setuprunning := 1
  }
  else
    Reload
return


ExitSub:
  Gui +lastfound
  WinGetPos, x, y
  IniWrite, %x%, %ini%, settings, gui_x
  IniWrite, %y%, %ini%, settings, gui_y
ExitApp



;// getTableCoords: grab x,y of table, store in gui fields for custom stack

getTableCoords:
  Gui +OwnDialogs
  win := WinActive("ahk_group AllTables")
  if (win) {
    WinGetTitle, tablename, ahk_id %win%
    MsgBox, 4, ,Will use location of `n`n   %tablename% `n`n OK? Yes or No?
    IfMsgBox Yes
    {
      WinGetPos, x, y, , , ahk_id %win%
      GuiControl, ,CustomStackX, %x%
      GuiControl, ,CustomStackY, %y%
      MsgBox, X,Y coords have been grabbed: %x% by %y%`nIf you want to use this location for the stack, make sure to click the cirle radio button next to 'Custom', and then click Save.
    }
  }
  else
    MsgBox, 48,,Not a poker table
  Hotkey, F12, off
return



;// setupTableGrid: grab table dimensions, build slot grid, get fold hotkey, store in ini

setupTableGrid:
  Gui +OwnDialogs
  win := WinActive("ahk_group StarsTables")
  if (win) {
    WinGetTitle, tablename, ahk_id %win%
    MsgBox, 4, ,We will first get the table size and setup the grid. We will use this table for this: `n`n   %tablename% `n`n OK? Yes or No?
    IfMsgBox Yes
    {
      FileDelete, %ini%
      WinGetPos, , , w, h, ahk_id %win%
      columns := Floor(A_ScreenWidth/w)
      rows := Floor(A_ScreenHeight/h)
      totalslots := columns * rows
      MsgBox, Table dimensions are w%w% by h%h%. `nSlots will be start at upper left of screen and continue right, then down, as if you were reading a page.`nTotal slots for your resolution is: %totalslots%
      IniWrite, %totalslots%, %ini%, settings, total_slots
      stackslot := 0
      while ((stackslot < 1) OR (stackslot > totalslots)) {
        if a_index > 1                  ;// if while loop has been repeated
          MsgBox, Invalid slot number
        InputBox, stackslot, Stack Slot, Which slot number to use for the stack?,,280,180,,,,,1
        if ErrorLevel
          stackslot := 1
      }
      slot := 0
      Loop, %rows% {
        r := a_index
        Loop, %columns% {
          c := a_index
          slot++
          xx := (c-1) * w
          yy := (r-1) * h
          IniWrite, %xx%, %ini%, settings, slot%slot%x
          IniWrite, %yy%, %ini%, settings, slot%slot%y
          if (slot = stackslot) {
            stackx := xx
            stacky := yy
          }
        }
      }
      IniWrite, %stackslot%, %ini%, settings, stack_slot
      IniWrite, %stackx%, %ini%, settings, stack_x
      IniWrite, %stacky%, %ini%, settings, stack_y
      InputBox, FoldHotkey, Fold and re-stack Hotkey, Please enter the key you would like to use as a hotkey to click Fold and then re-stack the table.`n`nThis should be used as a replacement of your Fold hotkey in other programs. ,,280,180,,,,,F3
      IniWrite, %FoldHotkey%, %ini%, settings, fold_hotkey
      sfx := starsfoldx, sfy := starsfoldy
      relStarsWindowPoint(win, sfx, sfy)
      WinActivate, ahk_id %win%
      PixelGetColor, stars_nofold_col, sfx, sfy
      IniWrite, %stars_nofold_col%, %ini%, settings, stars_nofold_pixelcol
      IniWrite, %IncludeStars%, %ini%, settings, include_stars       
    }
    else                               ;// else, MsgBox = no
      return
  }
  else {                                    ;// else, win not pokerstars
    MsgBox, 48,,Not a Pokerstars table
    return
  }
  Hotkey, F10, off
  MsgBox 4,, Include Full Tilt detection?
  IfMsgBox Yes
  {
    IncludeFulltilt := 1
    GuiControl, , IncludeFulltilt, 1
    IniWrite, %IncludeFulltilt%, %ini%, settings, include_fulltilt
    MsgBox, IMPORTANT!`n`nSit at a Full Tilt table and make sure its the correct size. Play a hand. When the 'Fold' button is visible, press F11.
    GuiControl, , SetupText, Press F11 on a Fulltilt table when 'Fold' button is visible.
    Hotkey, F11, setupFulltilt
    Hotkey, F11, on
  }
  else
  {
    IncludeFulltilt := 0
    IniWrite, %IncludeFulltilt%, %ini%, settings, include_fulltilt
    GuiControl, , SetupText,  
    GuiControl, enable, StartButton
    GuiControl, , MyTab, |Control|Settings|Sites
    MsgBox, Setup finished
    Reload
  }
return




;// setupFulltilt: grabs the fold pixel color

setupFulltilt:
  Gui +OwnDialogs
  win := WinActive("ahk_group FulltiltTables")
  if (win) {
    WinGetTitle, tablename, ahk_id %win%
    MsgBox, 4, ,We will use the color of the Fold button from table: `n`n   %tablename% `n`n OK? Yes or No?
    IfMsgBox Yes
    {
      ffx := ftfoldx, ffy := ftfoldy
      relFullTiltWindowPoint(win, ffx, ffy)
      WinActivate, ahk_id %win%
      PixelGetColor, ft_fold_col, ffx, ffy
      IniWrite, %ft_fold_col%, %ini%, settings, ft_fold_pixelcol
      Hotkey, F11, off
      GuiControl, , SetupText,  
      GuiControl, enable, StartButton
      GuiControl, , MyTab, |Control|Settings|Sites
      MsgBox, Setup finished
      Reload
    }
    else
      return
  }
  else
    MsgBox, 48,, Not a Full Tilt table
return






;// StackAndTile: main loop that does all the dirty work

StackAndTile:
  tables := ""
  if (IncludeStars)
    tables := tables . "," . starslist()
  if (IncludeFulltilt)
    tables := tables . "," . fulltiltlist()
  ;tables := alltableslist()        ;// dont add all tables if dont need to


  ;// first, clean up lists
  ;// remove tables that no longer exist

  Loop, %totalslots% {      ;// check if any slot table was manually closed, therefore set its slot to empty
    i := a_index
    if ((tableinslot%i% != "") and (!(InStr(tables, tableinslot%i%, true, 0))))   ;// if slot is not empty, and not in tables list
      tableinslot%i% := ""
  }
  Loop, Parse, tablequeue, `,
  {
    StringTrimLeft, this_id, A_LoopField, InStr(A_LoopField, "_")  ;// trims the timestamp
    if (!InStr(tables, this_id))                          ;// if table from queue is no longer in table list (ex: got closed)
      listDelItem(tablequeue, A_Loopfield)                  ;// remove it from queue
  }
  Loop, Parse, stackedlist, `,
  {
    if (!InStr(tables, A_Loopfield))
      listDelItem(stackedlist, A_Loopfield)
  }
  Loop, Parse, slottedlist, `,
  {
    if (!InStr(tables, A_Loopfield))
      listDelItem(slottedlist, A_Loopfield)
  }
  Loop, Parse, nonurgents, `,
  {
    if (!InStr(tables, A_Loopfield))
      listDelItem(nonurgents, A_Loopfield)
  }  


  ;// next,
  ;// find urgents:

  Loop, Parse, tables, `, 
  {
    if (!InStr(stackedlist, A_LoopField)) {     
      if (!InStr(slottedlist, A_LoopField)) { 
        WinMove, ahk_id %A_LoopField%,, %stackx%, %stacky%         ;//  auto stack new tables
        listAdd(stackedlist, A_Loopfield)         
      }
    }

    ;// check if urgent:

    if (IncludeFulltilt) {
      variation := 8                                              ;// color variation tolerance, experiment with values
      IfWinExist, ahk_id%A_Loopfield% ahk_group FullTiltTables
      {                                                            ;// if a Fulltilt table
        ffx := ftfoldx, ffy := ftfoldy
        relFullTiltWindowPoint(A_LoopField, ffx, ffy)
        pixel := PixelColorA(ffx, ffy, A_LoopField)
        if (Display_CompareColors(ft_fold_col, pixel, variation) = 1) {         ; fulltilt cant use fold background color because preselect buttons cover it. so instead we compare if the current pixel is a close match to when the fold was visible during setup
          if (!InStr(tablequeue, A_LoopField)) {
            if (!InStr(slottedlist, A_LoopField)) {
              DllCall("QueryPerformanceCounter", "Int64 *", CurrentQPC)
              listAdd(tablequeue, CurrentQPC . "-" . A_TickCount . "_" . A_LoopField)
              listDelItem(nonurgents, A_LoopField) 
            }   
          }
        }
        else {
          if (!InStr(nonurgents, A_LoopField))
            if (!InStr(slottedlist, A_LoopField))
              listAdd(nonurgents, A_LoopField)
          if (InStr(tablequeue, A_LoopField))
            listDelItem(tablequeue, A_LoopField)
        }
      }
    }
    if (IncludeStars) {
      IfWinExist, ahk_id%A_Loopfield% ahk_group StarsTables                     ;// if a stars table 
      {                                                       
        ControlGet, v, Visible, , PokerStarsSliderEditorClass1, ahk_id%A_LoopField%         ;// search for slider
        if ( v = 1 ) {  
          if (!InStr(tablequeue, A_LoopField)) {                                      ;//if not already in queue
            if (!InStr(slottedlist, A_LoopField)) {                                   ;// and not already slotted
              DllCall("QueryPerformanceCounter", "Int64 *", CurrentQPC)
              listAdd(tablequeue, CurrentQPC . "-" . A_TickCount . "_" . A_LoopField)     ;//timestamp it, add it to queue
              listDelItem(nonurgents, A_LoopField) 
            }   
          }
        } 
        else {                                ;// slider not visible
          if (DetectStarsAIs) {
            sfx := starsfoldx, sfy := starsfoldy
            relStarsWindowPoint(A_LoopField, sfx, sfy)
            pixel := PixelColorA(sfx, sfy, A_LoopField)
            if (pixel != stars_nofold_col) {
              if (!InStr(tablequeue, A_LoopField)) {  
                if (!InStr(slottedlist, A_LoopField)) { 
                  DllCall("QueryPerformanceCounter", "Int64 *", CurrentQPC)
                  listAdd(tablequeue, CurrentQPC . "-" . A_TickCount . "_" . A_LoopField)
                  listDelItem(nonurgents, A_LoopField) 
                }   
              }
            } 
            else {                                      ;// not urgent
              if (!InStr(nonurgents, A_LoopField))
                if (!InStr(slottedlist, A_LoopField))     ;// dont move slotted tables to bottom
                  listAdd(nonurgents, A_LoopField)        ;// add to nonurgents list, for move to bottom of stack later
              if (InStr(tablequeue, A_LoopField))         ;// if tables were still waiting in queue for an open slot, but are no longer urgent
                listDelItem(tablequeue, A_LoopField)       ;// remove them from queue
            }
          } 
          else {
            if (!InStr(nonurgents, A_LoopField))
              if (!InStr(slottedlist, A_LoopField))
                listAdd(nonurgents, A_LoopField)
            if (InStr(tablequeue, A_LoopField))    
              listDelItem(tablequeue, A_LoopField) 
          }
        }
      }
    }
  }

  ;// sort by timestamp 
  ;// and grab most urgent:

  tmpvar := ""
  Loop, Parse, tablequeue, `,
  {
    if (InStr(A_LoopField, "0x"))
      listAdd(tmpvar, A_LoopField )
  }

  Sort, tmpvar, N D`,      ;// since tables are timestamped, we can sort them numerically in order

  tablequeue := CleanList(tmpvar)
  most_urgent_table := ""

 
  ;// finally,
  ;// move into empty slot:

  Loop, Parse, tablequeue, `,
  {
    StringTrimLeft, most_urgent_table, A_LoopField, InStr(A_LoopField, "_")      ;// remove the timestamp, store in most_urgent

    if (most_urgent_table != "") {

      ;ToolTip, most = %most_urgent_table%`nold  = %old_urgent%

      Loop, parse, nonurgents, `,
      {
        WinGetTitle, tit, ahk_id%a_loopfield%
        ;msgbox sending to bottom:`n%tit%
        WinSet, Bottom,, ahk_id%A_LoopField%           ;// move non urgents to bottom, take care of auto popup not happening when action requred in grid (thx e306)
      }

      if (moveonstreet = "preflop") {
        if (moveIntoEmptySlot(most_urgent_table) = 0) {        ;// if move into slot was successful 
          listAdd(slottedlist, most_urgent_table)               ;// add table to list of slotted tables
          listDelItem(stackedlist, most_urgent_table)           ;// remove from list of stacked
          listDelItem(tablequeue, A_Loopfield)       ;// remove table from queue. if all slots were full, then the action continues in the stack via stars auto popup on activation
                                                     ;// but tablequeue stores the table in case a slot frees up
        }
      }

      else if (moveonstreet = "flop") {

        IfWinExist, ahk_id %most_urgent_table% ahk_group StarsTables
        {
          str_stars := GetStreetStars(most_urgent_table)
          s := "stars"
        }
        IfWinExist, ahk_id%most_urgent_table% ahk_group FullTiltTables
        {
          str_ft := GetStreetFT(most_urgent_table)
          s := "ft"
        }

        if (str_%s% = "flop") {         ;// if on flop 
          if (moveIntoEmptySlot(most_urgent_table) = 0) {
            listAdd(slottedlist, most_urgent_table)
            listDelItem(stackedlist, most_urgent_table)
            listDelItem(tablequeue, A_Loopfield)
          }
        }

      }
    }
    break         ;// only do the first in queuelist (most urgent)
  }
return





;// foldReStack: HOTKEY to click Fold on table, remove it from slot, re-stack it

foldReStack:
  if SendTableUnderMouse
    MouseGetPos,,, win
  else
    WinGet, win, ID, A
  IfWinExist, ahk_id%win% ahk_group StarsTables 
  {
    FoldStars(win)
    WinMove, ahk_id %win%,, %stackx%, %stacky%      ;// re-stack it
    listAdd(stackedlist, win) 
  }
  Else IfWinExist, ahk_id%win% ahk_group FullTiltTables
  {
    FoldFT(win)
    WinMove, ahk_id %win%,, %stackx%, %stacky%      ;// re-stack it
    listAdd(stackedlist, win) 
  }
  Sleep 100
  Loop, %totalslots% {
    i := a_index
    if (win = tableinslot%i%) {   
      tableinslot%i% := ""                     ;// remove table from slot array
      listDelItem(slottedlist, win)            ;// and from slottedlist
      break
    }   
  }
return




; =========================
; functions
; =========================


;// readSettingsIntoVars: reads ini and updates the script's variables for use

readSettingsIntoVars() {
  global                                  ;// make all vars in this func global
  IniRead, totalslots, %ini%, settings, total_slots, 0
  Loop, %totalslots% {
    i := a_index
    IniRead, coordxforslot%i%, %ini%, settings, slot%i%x, 0
    IniRead, coordyforslot%i%, %ini%, settings, slot%i%y, 0
  }
  IniRead, stackslot, %ini%, settings, stack_slot, 1
  if (stackslot = 0) { 
    StackUsesSlot := 0
    StackUsesCustom := 1
  } else {
    StackUsesSlot := 1
    StackUsesCustom := 0
  }
  IniRead, stackx, %ini%, settings, stack_x, 0
  IniRead, stacky, %ini%, settings, stack_y, 0
  IniRead, moveonstreet, %ini%, settings, move_on_street, preflop
  IniRead, SendTableUnderMouse, %ini%, settings, send_table_under_mouse, 1
  if (SendTableUnderMouse = 1)
    SendActiveTable := 0
  else
    SendActiveTable := 1
  IniRead, DetectStarsAIs, %ini%, settings, detect_stars_allins, 1
  IniRead, IncludeStars, %ini%, settings, include_stars, 1
  IniRead, IncludeFulltilt, %ini%, settings, include_fulltilt, 0
  IniRead, stars_nofold_col, %ini%, settings, stars_nofold_pixelcol, 0
  IniRead, ft_fold_col, %ini%, settings, ft_fold_pixelcol, 0 
  IniRead, FoldHotkey, %ini%, settings, fold_hotkey, F3
  Hotkey, %FoldHotkey%, foldReStack
}




moveIntoEmptySlot(id) {
  global totalslots
  global stackslot
  Loop, %totalslots% {
    i := a_index
    if (tableinslot%i% = "") {                 ;// if slot is empty
      if (i != stackslot) {                    ;// and not the slot used for the stack
        WinMove, ahk_id %id%,, coordxforslot%i%, coordyforslot%i% 
        tableinslot%i% := id
        return 0                             ;// slots were avail, move was successful
      } 
    }
  }
  return 1                         ;// return 1 if all slots full
}





starslist() {
  WinGet, list, list, ahk_group StarsTables
  Loop, %list%
    listAdd(tableids, list%a_index%)
  return tableids
}


fulltiltlist() {
  WinGet, list, list, ahk_group FullTiltTables
  Loop, %list%
    listAdd(tableids, list%a_index%)
  return tableids
}


alltableslist() {
  WinGet, list, list, ahk_group AllTables
  Loop, %list%
    listAdd(tableids, list%a_index%)
  return tableids
}



;removes empty items (and trailing delimiters)
CleanList(list, del="") {
  del := del="" ? "," : del
  Loop {
    StringReplace, list, list, %del%%del%, %del%, UseErrorLevel
    If ! ErrorLevel
     break
   }
  If InStr(list, del) = 1
   StringTrimLeft, list, list, 1
  If InStr(list, del,0,0) = StrLen(list)
   StringTrimRight, list, list, 1
  return list
}






; Some BetPot functions


cp_hex2rgb(hex, del=",") {
StringMid, r, hex, 1, 2
StringMid, g, hex, 3, 2
StringMid, b, hex, 5, 2
r:="0x" r, g:="0x" g, b:="0x" b
r+=0
g+=0
b+=0
return R . del . G . del . B
}


; finds number of specified pixels in a region
GetPixelCount(x1, y1, x2, y2, color, id)
{

  local device, context, pixs

  pixels := (x2 - x1 + 1)*(y2 - y1 + 1)
  If ( pixels <= 0 )
  {
    ErrorLevel = 1
    return
  }

  Display_CreateWindowCapture(device, context, pixs, id)

  count = 0
  x = %x1%
  Loop
  {
    If ( x > x2 )
    {
      break
    }
    y = %y1%
    Loop
    {
      If ( y > y2 )
      {
        break
      }
      c := Display_GetPixel(context, x, y)
      If ( c = color )
      {
        count++
      }
      y++
    }
    x++
  }
  Display_DeleteWindowCapture(device, context, pixs)
  return count
}





GetStreetStars(id) {
  global debug

  device := "", context := "", pix := ""

  street := "pre"

  x1 := 382+4
  y1 := 185+29
  x2 := 395+4
  y2 := 200+29
  relStarsClientPoint(id, x1, y1)
  relStarsClientPoint(id, x2, y2)

  pixels := (x2 - x1 + 1)*(y2 - y1 + 1)
  if ( pixels <= 0 )
    return street

  if (debug)
    debug_gui(id, x1, y1, x2, y2)

  Display_CreateWindowCapture(device, context, pixs, id)
  count = 0
  x = %x1%
  Loop
  {
    if ( x > x2 )
      break
    y = %y1%
    Loop
    {
      if ( y > y2 )
        break
      c := Display_GetPixel(context, x, y)
      if ( c = 0xffffff )
      {
        count++
        if (count > 5)
          break
      }
      y++
    }
    if (count > 5)
      break
    x++
  }

  if ( count > 5 )
    street := "flop"

  Display_DeleteWindowCapture(device, context, pixs)

  return street
}



GetStreetFT(id)
{
  global debug

  device := "", context := "", pix := ""

  street := "pre"

  x1 := 378+4
  y1 := 240+29
  x2 := 394+4
  y2 := 260+29
  relFulltiltClientPoint(id, x1, y1)
  relFulltiltClientPoint(id, x2, y2)

  pixels := (x2 - x1 + 1)*(y2 - y1 + 1)
  if ( pixels <= 0 )
    return street

  if (debug)
    debug_gui(id, x1, y1, x2, y2)

  Display_CreateWindowCapture(device, context, pixs, id)
  count = 0
  x = %x1%
  Loop
  {
    if ( x > x2 )
      break
    y = %y1%
    Loop
    {
      if ( y > y2 )
        break
      c := Display_GetPixel(context, x, y)
      if ( c = 0xffffff )
      {
        count++
        if (count > 5)
          break
      }
      y++
    }
    if (count > 5)
      break
    x++
  }

  if ( count > 5 )
    street := "flop"

  Display_DeleteWindowCapture(device, context, pixs)

  return street
}





debug_gui(id, x1, y1, x2, y2, delay=500)
{
  WinGetPos, x, y, , , ahk_id%id%
  x1 += x
  y1 += y
  x2 += x
  y2 += y
  ;msgbox %x1% %y1%`n%x2% %y2%
  Gui, 2: +Alwaysontop +Lastfound +Owner
  Gui, 2: Color, cBlack
  WinSet, Transparent, 200
  Gui, 2: -Caption
  w1 := x2 - x1
  h1 := y2 - y1
  Gui, 2: Show, w%w1% h%h1% x%x1% y%y1% NoActivate
  Sleep, %delay%
  Gui,2: Destroy


}





relStarsClientPoint(id, ByRef x, ByRef y) {

;// modifies x,y coords depending on your table size

  SysGet, xborder, 32                 ;// 4
  SysGet, yborder, 33                 ;// 4
  SysGet, caption, 4                  ;// 25
  ;//caption := caption + border         ;// 29 ??
  rw := 792                           ;// stars standard table is 800x579, subtract two borders
  rh := 546                           ;// subtract 1 caption and 2 borders
  WinGetPos, , , w, h, ahk_id%id%
  w := w - (2*xborder)
  h := h - (2*yborder) - caption
  x := Floor( (x / rw ) * w )
  y := Floor( (y / rh) * h  )
}


relStarsWindowPoint(id, ByRef x, ByRef y)
{
  SysGet, xborder, 32                 ;// 4
  SysGet, yborder, 33                 ;// 4
  SysGet, caption, 4                  ;// 25
  relStarsClientPoint(id, x, y)
  x := x + xborder
  y := y + yborder + caption
}



relStarsScreenPoint(id, ByRef x, ByRef y)
{
  relStarsWindowPoint(id, x, y)
  WinGetPos, x1, y1, , , ahk_id%id%
  x += x1
  y += y1
}



relFullTiltClientPoint(id, ByRef x, ByRef y) {

;// modifies x,y coords depending on your table size

  SysGet, xborder, 32                 ;// 4
  SysGet, yborder, 33                 ;// 4
  SysGet, caption, 4                  ;// 25
  rw := 794                           ;// ftp standard table is 802x580, subtract two borders
  rh := 547                           ;// subtract 1 caption and 2 borders
  WinGetPos, , , w, h, ahk_id%id%
  w := w - (2*xborder)
  h := h - (2*yborder) - caption    
  x := Floor( (x / rw ) * w )     
  y := Floor( (y / rh) * h  )      
}



relFullTiltWindowPoint(id, ByRef x, ByRef y) 
{
  SysGet, xborder, 32                 ;// 4
  SysGet, yborder, 33                 ;// 4
  SysGet, caption, 4                  ;// 25
  relFullTiltClientPoint(id, x, y)
  x := x + xborder
  y := y + yborder + caption   
}





PostLeftClick(x, y, table_id, activate=1) {

; ### JUK: Send the down left click, then the mouse-up messages.
; NOTE: This is relative to the top left of the client area and NOT the top left of the
;       window (ie: It *doesn't* include the title-bar like AHK's MouseClick does!!!).

  If activate
    WinActivate, ahk_id%table_id%
DllCall("SetCapture","Uint",table_id)
  PostMessage, 0x201, 0x0001, ((y<<16)^x), , ahk_id%table_id%
  PostMessage, 0x202 , 0, ((y<<16)^x), , ahk_id%table_id%
DllCall("ReleaseCapture")
}




PostStarsClick(x, y, id)
{
  relStarsClientPoint(id, x, y)
  PostLeftClick(x, y, id)
}
    
CallStars(id)
{
  PostStarsClick(600,533,id)
}

RaiseStars(id)
{
  PostStarsClick(730,520,id)
}

FoldStars(id)
{
  PostStarsClick(416,501,id)
  Sleep, 20
  PostStarsClick(412,498,id)
  Sleep, 20
  PostStarsClick(416,478,id)
}



;// PostFullTiltClick: input x,y including borders and captions (grabbed from windowspy?)

PostFullTiltClick(x,y,id)
{
  relFullTiltClientPoint(id, x, y)
  ;msgbox x %x% y %y%
  PostLeftClick(x, y, id)
}


FoldFT(id) {
  PostFullTiltClick(516, 501, id)
  Sleep, 20
  PostFullTiltClick(546, 506, id)
  Sleep, 20
  PostFullTiltClick(521, 535, id)
}





;// input coordinates relative to full window id (coords including border and caption) same as built in PixelGetColor

PixelColorA(col_x,col_y,id)
{
 ; critical ; speed up
 ; d := "", c := "", p := "", pix := ""
  pix := ""
  Display_CreateWindowCapture(disp, cont, px, id)
  pix := Display_GetPixel(cont, col_x, col_y)
  Display_DeleteWindowCapture(disp, cont, px)
  oldfrmt := A_FormatInteger
  SetFormat, IntegerFast, hex
  pix += 0  ; Sets Var (which previously contained 11) to be 0xb.
  pix .= ""  ; Necessary due to the "fast" mode.
  SetFormat, IntegerFast, %oldfrmt%
  return pix
}




; based off Xander and Max1mums



Display_CreateWindowCapture(ByRef device, ByRef context, ByRef pixels, id, redraw="1") {	
	WinGetPos, , , w, h, ahk_id %id%
	device := DllCall("GetDC", "UInt", id)
	context := DllCall("gdi32.dll\CreateCompatibleDC", "UInt", device)
	;pixels := DllCall("gdi32.dll\CreateCompatibleBitmap", "UInt", device, "Int", w, "Int", h)
	;//DIB seems to have slightly better performance than Bitmap when grabbing multiple pixels at a time
	pixels := CreateDIBSection(device, w, h)
	DllCall("gdi32.dll\SelectObject", "UInt", context, "UInt", pixels)
	DllCall("PrintWindow", "UInt", id, "UInt", context, "UInt", 0)
	WinGet,ctrls,ControlList,ahk_id %id%
        Loop,Parse,ctrls,`n
        {
         class:=A_LoopField
         ControlGet,ctrlid,Hwnd,,%class%,ahk_id %id%
         ControlGet,visible,Visible,,,ahk_id %ctrlid%
         If visible=1
         DllCall("RedrawWindow","UInt",ctrlid,"UInt",0,"UInt",0,"UInt", 1|16|64|2048)
        }
        DllCall("RedrawWindow","UInt",id,"UInt",0,"UInt",0,"UInt", 1|16|64|1024) 
}



Display_DeleteWindowCapture(ByRef device, ByRef context, ByRef pixels) {
	DllCall("gdi32.dll\ReleaseDC", "UInt", device)
	DllCall("gdi32.dll\DeleteDC", "UInt", device)
	DllCall("gdi32.dll\DeleteDC", "UInt", context)
	DllCall("gdi32.dll\DeleteObject", "UInt", pixels)
}


Display_GetPixel(ByRef context, x, y) {
	pix := DllCall("GetPixel", "UInt", context, "Int", x, "Int", y)
	return pix
}


Display_CompareColors(ByRef bgr1, ByRef bgr2, ByRef variation) {
	c1 := bgr1 & 0xff
	c2 := bgr2 & 0xff
	if (abs(c1 - c2) > variation)
		return false
	c1 := (bgr1 >> 8) & 0xff
	c2 := (bgr2 >> 8) & 0xff
	if (abs(c1 - c2) > variation)
		return false
	c1 := (bgr1 >> 16) & 0xff
	c2 := (bgr2 >> 16) & 0xff
	if (abs(c1 - c2) > variation)
		return false
	return true
}




CreateDIBSection(hDC, nW, nH, bpp = 32, ByRef pBits = "") {
   NumPut(VarSetCapacity(bi, 40, 0), bi)
   NumPut(nW, bi, 4)
   NumPut(nH, bi, 8)
   NumPut(bpp, NumPut(1, bi, 12, "UShort"), 0, "Ushort")
   NumPut(0,  bi,16)
   Return DllCall("gdi32\CreateDIBSection", "Uint", hDC, "Uint", &bi, "Uint", 0, "UintP", pBits, "Uint", 0, "Uint", 0)
}





; From Rolands functions


; add item to the end of list

listAdd( byRef list, item, del="," ) {
  list:=( list!="" ? ( list . del . item ) : item )
  return list
}


;removes said item from said list

listDelItem( byRef list, item, del=",") {
  ifEqual, item,, return list
  list:=del . list . del
  StringReplace, list, list, %item%%del%
  StringTrimLeft, list, list, 1
  StringTrimRight, list, list, 1
  return list
}

Last edited by Max1mums; 12-20-2009 at 09:06 AM.
StackAndTile Quote
12-20-2009 , 09:19 AM
One thing I wanted to mention is your resolution detection is not advanced enough.My screen resolution is 1280 x 800 and if I minimize the poker table to the smallest it can go I can fit 4 tables.However if I mover my task bar to the side instead of the bottom I can increase the table size and still fit 4 tables with zero overlap but your software does not seem to recognize the new space and still says I can only fit 2 tables.With TOI I can run 4 of these sized tables.Just figured I would mention it.Thanks
StackAndTile Quote
12-20-2009 , 10:50 AM
thx Max, what was i not clearing? was i missing that extra DeleteDC? ppl please try his code and see if you get the lag
StackAndTile Quote
12-20-2009 , 02:43 PM
Well can anyone report on last version? It doesn't get "super laggy" for me with 30 tables opened.
StackAndTile Quote
12-20-2009 , 03:37 PM
Version 1.10 really focked up my computer.

I am runnig windows XP via boot camp on a mac pro with a good processor and 5gb ram and good video card.

I was using the function to move tables whenever action is required with 6 sng's open. It worked really well for the first 10-15 minutes. After that things really went bad.
At first it began lagging and the script stopped or something with the result of tables remaining in grid and i wasn't able to send them back to stack. I tried to stop the script and run it again but nothing worked.
I was just running pokerstars and firefox and i was using pokerstars black theme.
StackAndTile Quote
12-20-2009 , 03:41 PM
Not 1.10, fixed version i posted on previous page.
StackAndTile Quote
12-20-2009 , 04:31 PM
Quote:
Originally Posted by risky.ray.johnson
Version 1.10 really focked up my computer.

I am runnig windows XP via boot camp on a mac pro with a good processor and 5gb ram and good video card.

I was using the function to move tables whenever action is required with 6 sng's open. It worked really well for the first 10-15 minutes. After that things really went bad.
At first it began lagging and the script stopped or something with the result of tables remaining in grid and i wasn't able to send them back to stack. I tried to stop the script and run it again but nothing worked.
I was just running pokerstars and firefox and i was using pokerstars black theme.
Exact same thing happened to me. On Win7 though, quad core 2.6, 4GB RAM.
StackAndTile Quote
12-20-2009 , 04:36 PM
Also, is there a way to close the script, or stop it? The "Start" "Stop" button has no effect on turning off the hotkey, RButton will still move the tables regardless which is fine, but I cant use right click for anything else on my computer and the only way I can stop the script is to Alt+Ctrl+Del and stop it.
EDIT: Well if I open, Start/Then Stop it will work so its fine.
StackAndTile Quote
12-20-2009 , 04:40 PM
i am running the new script and there is absolutely no lag, but it dosent detect when alot of the hands goto flop

after thinking about it, i think it is because my stack 0 and stack 1 is the same stack. so if stack 1 is available then it wont move the postflop TOI.

But seems the Max1mums has solved the lag problem
StackAndTile Quote
12-20-2009 , 05:25 PM
Yeah I agree, LAG problem seems to be gone. I just 16 tabled for about 25 minutes and the program worked flawlessly. Now if I could just learn to 16 table a bit better...
StackAndTile Quote
12-20-2009 , 05:55 PM
Well I just wanted to help greg solve problems with pixelsearch function because he found it in some of my posts (and prove that it isn't hopeless ), I won't interrupt greg's work on his script any more if lag problem is gone.
StackAndTile Quote
12-20-2009 , 05:59 PM
its no interruption at all, i appreciate the help. this is what open source is all about.

"Stop" button should turn off hotkey..

i will try to implement Max's solutions
StackAndTile Quote
12-20-2009 , 06:25 PM
Boo to open source!! I need to work like 24/7 to keep up with you guys!!!
Nice project! I have promised myself to never look in your code, because that would be not right (stealing free open-source code then selling), so no worries...

BTW Sorry to bump your thread, but do you guys have any idea what TableNinja uses instead of pixeldetection? I mean... it has no lag and stuff. Is it because its written in a more advanced language, or does he read the pokerstars log file or what? I absolutely hate pixel detection, it's so primitive.
StackAndTile Quote
12-20-2009 , 06:50 PM
And which tableninja functions may require pixelsearch at all? Timebank and I am back clicker? Or are you talking about FT version? It is always possible to track which files tableninja reads
p.s. you are always free to look at code cause it's free source and supposed to be opened for everyone.
StackAndTile Quote
12-20-2009 , 06:57 PM
im not into stars (and ft flickers on my machine) but i noticed the table that got put back into the stack got stacked on top...which seems a bummer to me...
StackAndTile Quote
12-20-2009 , 07:02 PM
Quote:
Originally Posted by Max1mums
And which tableninja functions may require pixelsearch at all? Timebank and I am back clicker?
+wait for bb clicker
StackAndTile Quote

      
m