Sign in to follow this  
Followers 0
Affe

Solitaire Bot - Card Recognition

6 posts in this topic

Well, I was going to post this in the example scripts section, but for some reason it says that I do not have the rights to post there.

So I'll go ahead and post this here, and also see if anyone has any ideas for finishing the program.

First, I would like to note that I am writing this bot out of boredom and to see what I can come up with as far as pattern recognition goes.

I have the program currently set up to open Solitaire (sol.exe), and then identify the first seven cards dealt. Below is the code for the program, and the .ini file that is used to identify the cards.

I use the following method to identify the cards:

The program reads several lines of pixels off of the cards, and then turns those pixel numbers into a string. This string is then searched for in an array of cards where the definitions of these strings is kept. When a match is found, the card is identified.

I figured someone may be interested in the method I used to identify the cards, as I feel it may have many uses. The code is below, and the .ini file and code file are linked below:

#Include<Array.au3>

Run("sol.exe")
WinWaitActive("Solitaire")
$size = WinGetPos("Solitaire")

;~ MsgBox(0, "Active window stats (x,y,width,height):", $size[0] & " " & $size[1] & " " & $size[2] & " " & $size[3])

$x_coord_window = $size[0]
$y_coord_window = $size[1]
$window_width = $size[2]
$window_height = $size[3]

$Tooltip = True

;~ Card size on 1028 x 768 is 70 wide by 96 tall
;~ Window opens as 593 wide by 438 tall
;~ 7 cards put together are 490 wide
;~ Green space between cards is 12 pixels
;~ Width Example:
;~ [Left Window Edge to card 15 px]<-->[Card 70 px]<-->12 px<-->[Card 70 px]<-- etc...
;~ Height from top of solitaire screen to top of most left hand card = 157 px
;~ Height from top of solitaire screen to top of first Ace slot = 55 px
;~ Height of stacked cards (cards behind viewable cards) = 3 px
;~ Height of stacked cards (multi-visible) = 15 px
;~ Location from top of card to top of Unit Image = 4 px and 4 px from left side of card
;~ Example of where cards are "grabbed":
;~ * = grab point
;~       ________
;~  *  _| 
;~   _|
;~  |
;~  |
;~ Note that it just barely grabs at the corner -- the far left edge
;Identify Cards Section:  Used to first identify the cards dealt
;First Create an array that can contain 56 cards with the following attributes: X coordinates, Y coordinates, Number/Character/Type
Global $Card[52][3]
;Now Create an array to load from the .ini and compare to the $Card array to identify cards
Global $Load[52][2]
Global $Load2[52]

;Now load from the .ini
$Load = IniReadSection("cards.ini", "section1")
If @error Then 
    MsgBox(4096, "", "Error occurred, probably no INI file.")
;~;Test to see if .ini loaded properly
;~ Else
;~  For $i = 1 To $Load[0][0]
;~      MsgBox(4096, "", "Key: " & $Load[$i][0] & @CRLF & "Value: " & $Load[$i][1])
;~  Next
EndIf

;Below finds the location of the first card on the left
$x_card = $x_coord_window + 15
$y_card = $y_coord_window + 157

;Then the program assigns locations to each of the first seven cards
$x = 0
While $x < 7
    $Card[$x][0] = $x_card
    $Card[$x][1] = $y_card
    $x_card = $x_card + 70 + 12;adds 70 to consider width of card, 12 to consider space between cards
    $y_card = $y_card + 3;adds 3 to consider the distance due to each unknown bottom card
    $x = $x + 1
Wend
;~;****************************************************************************************
;~;TEST FOR THE ARRAY ADDITIONS - MOVES EACH CARD UP 4 PIXELS GOING FROM LEFT TO RIGHT
;~ $x = 0
;~ While $x < 7
;~  MouseMove($Card[$x][0], $Card[$x][1])
;~  MouseDown("left")
;~  MouseMove($Card[$x][0], $Card[$x][1] - 4)
;~  MouseMove($Card[$x][0], $Card[$x][1])
;~  MouseUp("left")
;~  $x = $x + 1
;~ WEnd
;~;****************************************************************************************


;~;****************************************************************************************
;~;Below was used to populate the .ini for the "Pattern Identifier"
;(creates a code used to identify cards and stores it in a file to be used as a reference)
;~ $file = FileOpen("test.txt", 1)
;~; Check if file opened for writing OK
;~ If $file = -1 Then
;~  MsgBox(0, "Error", "Unable to open file.")
;~  Exit
;~ EndIf

;~ $x = 0
;~ $check = ""
;~ While $x < 7
;~  For $j = 5 to 27 Step 2
;~      For $i = 4 to 11 Step 1
;~          $check = $check & PixelGetColor($Card[$x][0] + $i, $Card[$x][1] + $j)
;~      Next
;~  Next
;~  $Card[$x][2] = $check
;~  $str = StringFormat("Position %s", $x)
;~  $card_name = InputBox("What am I looking at?", $str)
;~  $str = StringFormat("%s=%s", $card_name, $Card[$x][2])
;~  FileWriteLine($file, $str)
;~  $x = $x + 1
;~  $check = ""
;~ WEnd

;~;****************************************************************************************


;First, we need to load the two-dimensional $Load array into a one dimensional array so that we can search it
$x = 0
While $x < 52
    $Load2[$x] = $Load[$x][1]
    $x = $x + 1
WEnd

;Now we need to identify the number and character on the cards
$x = 0
$check = ""
While $x < 7
    For $j = 5 to 27 Step 2
        For $i = 4 to 11 Step 1
            $check = $check & PixelGetColor($Card[$x][0] + $i, $Card[$x][1] + $j)
            $Pos = _ArraySearch ($Load2, $check, 0, 0, 0, True)
            Select
                Case $Pos = -1
                    MsgBox(0, "Not Found", '"' & $check & '" was not found in the array.')
                Case Else
                    $Card[$x][2] = $Load[$Pos][0]
                    ToolTip($Card[$x][2], $Card[$x][0], $Card[$x][1])
            EndSelect
        Next
    Next
    $x = $x + 1
    $check = ""
    Sleep(2000)
WEnd

If anyone has any suggestions on how to finish the bot (pattern matching to make it move the cards in the correct places, etc) I happily welcome input.

Cards.ini

Solitaire_Bot.au3


[center][/center]

Share this post


Link to post
Share on other sites



I noticed that on different machines the window opens at different sizes. I've fixed the file where you can download the .au3, and here is the change below:

;Below finds the location of the first card on the left
$x_adj = 15
$y_adj = 157
If $size[3] < 438 Then
    $change = 438 - $size[3]
    $y_adj = 157 - $change
ElseIf $size[3] > 438 Then
    $change = $size[3] - 438
    $y_adj = 157 + $change
EndIf
If $size[2] < 593 Then
    $change = 593 - $size[2]
    $x_adj = 15 - $change
ElseIf $size[3] > 593 Then
    $change = $size[2] - 593
    $x_adj = 15 + $change
EndIf
$x_card = $x_coord_window + $x_adj
$y_card = $y_coord_window + $y_adj

[center][/center]

Share this post


Link to post
Share on other sites

Well done Affe, I think your way about recognizing the cards is brilliant. I to have been working on a card

recognition bot and your way about doing everything has really helped me.

Regards,

Ozi

Share this post


Link to post
Share on other sites

Hi, may I ask you for cards.ini file for Solitaire bot? Link is dead. Thank you :)

Share this post


Link to post
Share on other sites

lol, thread is almost 7 years old...

Share this post


Link to post
Share on other sites

Myshaak,

Welcome to the AutoIt forum. :)

Firstly, please note that the post above yours is over 6 years old - we do not encourage necro-posting after such time, particularly in view of the thread subject as you will see in a moment. ;)

Next, you appear to have missed the Forum rules on your way in. Please read them now (there is also a link at bottom right of each page) - particularly the bit about not discussing game automation - and then you will understand why you will get no help and this thread will now be locked. :naughty:

See you soon with a legitimate question I hope. :)

M23


Any of my own code posted anywhere on the forum is available for use by others without any restriction of any kind._______My UDFs:

Spoiler

ArrayMultiColSort ---- Sort arrays on multiple columns
ChooseFileFolder ---- Single and multiple selections from specified path treeview listing
Date_Time_Convert -- Easily convert date/time formats, including the language used
ExtMsgBox --------- A highly customisable replacement for MsgBox
GUIExtender -------- Extend and retract multiple sections within a GUI
GUIFrame ---------- Subdivide GUIs into many adjustable frames
GUIListViewEx ------- Insert, delete, move, drag, sort, edit and colour ListView items
GUITreeViewEx ------ Check/clear parent and child checkboxes in a TreeView
Marquee ----------- Scrolling tickertape GUIs
NoFocusLines ------- Remove the dotted focus lines from buttons, sliders, radios and checkboxes
Notify ------------- Small notifications on the edge of the display
Scrollbars ----------Automatically sized scrollbars with a single command
StringSize ---------- Automatically size controls to fit text
Toast -------------- Small GUIs which pop out of the notification area

 

Share this post


Link to post
Share on other sites
Guest
This topic is now closed to further replies.
Sign in to follow this  
Followers 0