climberman Posted July 5, 2008 Share Posted July 5, 2008 I've been working on writing up some stuff for a trading bot for the Magic the gathering online game. Most of the core features i found here and there, but I wanted to share and get some feedback or help since there really was none when I was looking. The scripts I have so far will pretty much perform all the essential operations the bot is based on. I'd appreciate any comments or suggestions if you have any, and the code is extremely long since I'm almost done with it. It's based on OCR to determine what is being traded, enjoy! I haven't rn or compiled the whole thing since putting the parts together and adding stuff yet. It still needs a GUI to really be practical. expandcollapse popup; http://msdn2.microsoft.com/en-us/library/a...office.11).aspx #include <GUIConstants.au3> #include <Array.au3> #include <WindowsConstants.au3> #include <ScreenCapture.au3> Dim $CardName Dim $CardSet Dim $CardQty Dim $Update ;to update price lists, set update to 1, to only update several, change the statements in the program $Update = 1 ;StandingReserve's commonBot ;Version: 0.11 $tradeOn = 1 $maxtime = 600000 ;add leftovers info $greetMessage = "Hello, I'm an automated trader. As you select cards, I will show you prices and update the total cost. You have 10 minutes to complete your trade. If you encounter any problems please PM betterwork." $noTicket = "You have no tickets tradeable. Please make a ticket tradeable or exit the trade" $iniFileLines = 8 $os = "2000" $resolutionX = 1024 $resolutionY = 768 $colordepth = 32 ;Variables for screen locations ;Variables for checksum location for looking for beginning of trade $top = 415 $left = 500 $bottom = 420 $right = 505 ;Variables for checking for withdrawing from trade ;PixelGetColor(639,329) = 3356477 then $withdrawX = 639 $withdrawY = 329 $withdrawColor = 3356477 ;Variable to recognize 32 cards ;80,280,100,300 $CardTarget = 490423324 $cardTakenX1 = 80 $cardTakenY1 = 280 $cardTakenX2 = 100 $cardTakenY2 = 300 ;Location of ticket already taken ;MouseClick("left",185,155,1,10) $myTicketX = 185 $myTicketY = 155 ;Variables for narrowing our search down to just tickets ;MouseClick("left",80,62,1,10) ;MouseClick("left",240,144,1,0) ;MouseClick("left",160,200,1,10) $searchX = 80 $searchY = 62 $dropX = 240 $dropY = 144 $boosterX = 160 $boosterY = 200 ;Ticket to take location ;if PixelGetColor(420,155) <> 9185056 then $ticketX = 420 $ticketY = 155 $ticketColor = 9185056 ;Tradebutton Location ;MouseClick("left",195,60,1,10) $tradeButtonX = 195 $tradeButtonY = 60 ;Make sure they don't cheat the bot $cheatCheckX = 195 $cheatCheckY = 140 $myTicketsBackground = 2969133 ;Variables for confirming the trade $confirmDropX = 240 $confirmDropY = 330 $confirmClickX = 170 $confirmClickY = 345 ;Variables to determine if they have confirmed $theirConfirmX1 = 45 $theirConfirmY1 = 325 $theirConfirmX2 = 60 $theirConfirmY2 = 330 $theirConfirmChecksum = 518491551 ;Final trade confirmation $performThisTradeX = 715 $performThisTradeY = 600 $performThisTradeWaitX1 = 300 $performThisTradeWaitY1 = 460 $performThisTradeWaitX2 = 305 $performThisTradeWaitY2 = 465 ;Checking for completed Trade $tradeCompletedX = 500 $tradeCompletedY = 400 $tradeCompletedColor = 3290940 $tradeCompletedCheckX = 614 $tradeCompletedCheckY = 424 $completedDragStartX = 525 $completedDragStartY = 60 $completedDragFinishX = 800 $completedDragFinishY = 60 $completedDragClickX = 1000 $completedDragClickY = 55 ;Canceling Trade Variables $cancelTradeX = 775 $cancelTradeY = 600 ;reset from withdrawel variables $resetX = 606 $resetY = 418 ;Chat location $chatX = 285 $chatY = 710 ;CardsRequest location $RequestLeft = 19 $RequestRight = 412 $RequestTop = 209 $RequestBottom = 593 If $Update = 1 Then;update pricelists ListUpdate(SHM);shadowmoor ListUpdate(MOR);morningtide ListUpdate(LRW);lorwyn ListUpdate(FUT);futuresight ListUpdate(PLC);planar chaos ListUpdate(TSP);time spiral ListUpdate(CSP);coldsnap ListUpdate(10TH);tenth edition EndIf Func OCR($left, $top, $right, $bottom);pass bounds to capture Dim $miDoc, $Doc Dim $str Dim $oWord Dim $sArray[500] Dim $count Const $miLANG_ENGLISH = 9 #CS Const $miLANG_ITALIAN = 16 Const $miLANG_CZECH = 5 Const $miLANG_DANISH = 6 Const $miLANG_DUTCH = 19 Const $miLANG_FINNISH = 11 Const $miLANG_FRENCH = 12 Const $miLANG_GERMAN = 7 Const $miLANG_GREEK = 8 Const $miLANG_HUNGARIAN = 14 Const $miLANG_JAPANESE = 17 Const $miLANG_KOREAN = 18 Const $miLANG_NORWEGIAN = 20 Const $miLANG_POLISH = 21 Const $miLANG_PORTUGUESE = 22 Const $miLANG_RUSSIAN = 25 Const $miLANG_SPANISH = 10 Const $miLANG_SWEDISH = 29 Const $miLANG_TURKISH = 31 Const $miLANG_SYSDEFAULT = 2048 Const $miLANG_CHINESE_SIMPLIFIED = 2052 Const $miLANG_CHINESE_TRADITIONAL = 1028 #CE ; Initialize error handler $oMyError = ObjEvent("AutoIt.Error","MyErrFunc") ;take screenshot $sTargetImage = "C:\Users\Brian\Desktop\mtgobot\OCR_tgt.jpg" _ScreenCapture_Capture($sTargetImage, $left, $top, $right, $bottom, $fCursor = False) $miDoc = ObjCreate("MODI.Document") $miDocView = ObjCreate("MiDocViewer.MiDocView") $miDoc.Create("C:\Users\Brian\Desktop\mtgobot\OCR_tgt.jpg") $miDoc.Ocr($miLANG_ENGLISH, True, False) $i = 0 For $oWord in $miDoc.Images(0).Layout.Words $str = $str & $oWord.text & @CrLf ConsoleWrite($oWord.text & @CRLF) $sArray [$i] = $oWord.text $i += 1 Next _FileWriteFromArray("C:\Users\Brian\Desktop\mtgobot\OCR_tgt.txt", $sArray, 1) ;test display array ;_ArrayDisplay($sArray,"OCR Result") EndFunc Func Done();look for done statement Dim $miDoc, $Doc Dim $str Dim $oWord Dim $sArray[500] Dim $count Const $miLANG_ENGLISH = 9 ;take screenshot $sTargetImage = "C:\Users\Brian\Desktop\mtgobot\DONE_tgt.jpg" _ScreenCapture_Capture($sTargetImage, $left, $top, $right, $bottom, $fCursor = False); put in values to look for done $miDoc = ObjCreate("MODI.Document") $miDocView = ObjCreate("MiDocViewer.MiDocView") $miDoc.Create("C:\Users\Brian\Desktop\mtgobot\DONE_tgt.jpg") $miDoc.Ocr($miLANG_ENGLISH, True, False) $i = 0 For $oWord in $miDoc.Images(0).Layout.Words $str = $str & $oWord.text & @CrLf ConsoleWrite($oWord.text & @CRLF) $sArray [$i] = $oWord.text $i += 1 Next ; sort the array to be able to do a binary search $sArray = StringLower(_ArrayToString($sArray)) _ArraySort($sArray) return _ArrayBinarySearch($sArray, "done") EndFunc Func PlayerName() EndFunc ;------------------------------ This is a COM Error handler -------------------------------- Func MyErrFunc() $HexNumber=hex($oMyError.number,8) Msgbox(0,"COM Error Test","We intercepted a COM Error !" & @CRLF & @CRLF & _ "err.description is: " & @TAB & $oMyError.description & @CRLF & _ "err.windescription:" & @TAB & $oMyError.windescription & @CRLF & _ "err.number is: " & @TAB & $HexNumber & @CRLF & _ "err.lastdllerror is: " & @TAB & $oMyError.lastdllerror & @CRLF & _ "err.scriptline is: " & @TAB & $oMyError.scriptline & @CRLF & _ "err.source is: " & @TAB & $oMyError.source & @CRLF & _ "err.helpfile is: " & @TAB & $oMyError.helpfile & @CRLF & _ "err.helpcontext is: " & @TAB & $oMyError.helpcontext _ ) SetError(1) ; to check for after this function returns Endfunc Func GetName();will only do one card for now, returns the card name _FileReadToArray("C:\Users\Brian\Desktop\mtgobot\OCR_tgt.txt", $sArray, 1) $i = 1 While StringIsDigit($sArray[$i]) = 0 $CardName += " " & $sArray[$i] $i += 1 WEnd StringTrimLeft($CardName,1) return $CardName EndFunc Func GetQty($sArray);will only do one card for now, returns the quantity selected for trade _FileReadToArray("C:\Users\Brian\Desktop\mtgobot\OCR_tgt.txt", $sArray, 1) $i = 1 $CardQty = 0 While $CardQty = 0 If StringIsDigit($sArray[$i]) = 1 Then $CardQty = $sArray[$i] Else $i += 1 EndIf WEnd return number($CardQty) EndFunc Func GetPrice($CardSet, $CardName);Pass abbreviated card set and card name Dim $Arrayline[999] Dim $PriceList[999][10] Dim $col Dim $row Dim $i _FileReadToArray("C:\Users\Brian\Desktop\mtgobot\Price_"&$CardSet&".txt",$Arrayline) $row = _ArraySearch($Arrayline, $CardName)+1 return $Arrayline[$row] EndFunc Func GetSet() EndFunc Func ListUpdate($CardSet);Pass abbreviated card set Dim $Arrayline[999] Dim $PriceList[999][10] Dim $col Dim $row Dim $oHTTP Dim $HTMLSource Dim $i $oHTTP = ObjCreate("winhttp.winhttprequest.5.1") $oHTTP.Open("GET","http://www.magictraders.com/cgi-bin/set_query.cgi?set="&$CardSet&"&excel=true") $oHTTP.Send() $HTMLSource = $oHTTP.Responsetext $HTMLSource = StringTrimLeft($HTMLSource, StringInStr($HTMLSource, "Card")-1) $HTMLSource = StringReplace($HTMLSource,@LF,"|");couldn't get it without this intermediate step, unsure why $Arrayline = StringSplit($HTMLSource, "|") $col = 1 $row = 0 $i = 1 for $col = 1 to 8 $PriceList[$row][$col] = $Arrayline[$i] $i = $i + 1 Next $row = 1 While $i <= $Arrayline[0]-8 for $col = 1 to 8 $PriceList[$row][$col] = $Arrayline[$i] $i = $i + 1 Next $row = $row + 1 WEnd _FileWriteFromArray("C:\Users\Brian\Desktop\mtgobot\Price_"&$CardSet&".txt",$Arrayline, 1) Run("Notepad.exe " & "C:\Users\Brian\Desktop\mtgobot\Price_"&$CardSet&".txt") EndFunc ;This function waits until the trade window pops up at a specific point. Func waitForTrade($left,$top,$right,$bottom) $checksum = PixelChecksum($left,$top,$right,$bottom) while $checksum = PixelChecksum($left,$top,$right,$bottom) Sleep(100) WEnd enterTrade($left,$top) EndFunc Func enterTrade($x,$y) MouseClick("left",$x,$y, 1, 0) SellCards() EndFunc Func SellCards() sendMessage($greetMessage) $startTime = TimerInit() $ticketTaken = 0 $temp = 1 $confirmed = 0 mouseClick("left",$myTicketX, $myTicketY, 1, 0) while $temp = 1 ;First check if they have withdrawn from trade if PixelGetColor($withdrawX, $withdrawY) = $withdrawColor then ResetFromWithdraw() endif ;The checksum changes when a card has been added or subtracted $checksum = PixelChecksum($cardTakenX1, $cardTakenY1, $cardTakenX2 , $cardTakenY2) While $checksum = PixelChecksum($cardTakenX1, $cardTakenY1, $cardTakenX2 , $cardTakenY2) Sleep(100) WEnd OCR($RequestLeft, $RequestTop, $RequestRight, $RequestBottom);add ocr, write back, wait for done command $CardName = GetName() $CardSet = GetSet() $CardQty = GetQty() $CardPrice = GetPrice($CardSet, $CardName) sendMessage($CardName & " (" & $CardPrice & ")" & "total is " & Number($CardPrice*$CardQty) " type 'done' when finished") $TixQty = Ceiling($CardPrice*$CardQty) if Done() = <> -1 Then TakeTickets($TixQty) ;Make sure that they don't remove their ticket $safetyChecksum = PixelGetColor($cheatCheckX, $cheatCheckY) if $safetyChecksum = $myTicketsBackground then SendMessage("Please do not alter the trade") else if $confirmed = 0 then MouseClick("left",$confirmDropX, $confirmDropY,1,10) Sleep(50) MouseClick("left",$confirmClickX, $confirmClickY,1,10) $confirmed = 1 endif if PixelGetColor($withdrawX, $withdrawY) = $withdrawColor then ResetFromWithdraw() endif $confirmchecksum = PixelChecksum($theirConfirmX1, $theirConfirmY1, $theirConfirmX2, $theirConfirmY2) if $confirmchecksum = $TheirConfirmChecksum then sleep(2000) if PixelGetColor($withdrawX, $withdrawY) = $withdrawColor then ResetFromWithdraw() endif performThisTrade() endif endif if TimerDiff($startTime) > $maxtime then abortTrade() endif ;Slow down the bot some sleep(500) wend EndFunc Func performThisTrade() MouseClick("left",$performThisTradeX, $performThisTradeY) $waitchecksum = PixelChecksum($performThisTradeWaitX1,$performThisTradeWaitY1,$performThisTradeWaitX2,$performThisTradeWaitY2) while $waitchecksum = PixelChecksum($performThisTradeWaitX1,$performThisTradeWaitY1,$performThisTradeWaitX2,$performThisTradeWaitY2) sleep(20) wend ;see if they confirmed if pixelGetColor($tradeCompletedX, $tradeCompletedY) = $tradeCompletedColor then MouseClick("left",$tradeCompletedCheckX, $tradeCompletedCheckY) sleep(10) MouseClickDrag("left",$completedDragStartX, $completedDragStartY, $completedDragFinishX, $completedDragFinishY) MouseClick("left",$completedDragClickX,$completedDragClickY) waitForTrade($left,$top,$right,$bottom) else ;they canceled, we need to recover MouseClick("left",$tradeButtonX, $tradeButtonY) SellCards() endif EndFunc Func abortTrade() MouseClick("left",$cancelTradeX ,$cancelTradeY) sleep(500) waitForTrade($left,$top,$right,$bottom) EndFunc Func resetFromWithdraw() MouseClick("left",$resetX,$resetY) waitForTrade($left,$top,$right,$bottom) EndFunc Func sendMessage($messageString) MouseClick("left",$chatX, $chatY) Send($messageString) Send("{ENTER}") EndFunc Func TakeTickets($TixQty) For $i = 1 to $TixQty ;Find a ticket MouseClick("left",$searchX , $searchY,1,10) Sleep(100) MouseClick("left",$dropX,$dropY,1,0) Sleep(100) MouseClick("left",$boosterX,$boosterY,1,10) Sleep(6000) if PixelGetColor($ticketX, $ticketY) <> $ticketColor then ;They don't have a ticket up for trade sendMessage($noTicket) Sleep(20) MouseClick("left", $tradeButtonX, $tradeButtonY,1,10) else MouseClick("left",$ticketX, $ticketY,1,10) Sleep(20) MouseClick("left",$tradeButtonX, $tradeButtonY,1,10) $ticketTaken += 1 $confirmed = 0 endif Next EndFunc ;These are values for checking the numbers of cards being transfered ;1: 3679399253 ;2: 1426267079 ;3: 4173342256 ;4: 1439835295 ;5: 1724459089 ;6: 2880646084 ;7: 1121135944 ;8: 1938694045 ;9: 3701681956 ;10: 493890957 ;11: 1740194342 ;12: 2902536487 ;13: 476855108 ;14: 1477851429 ;15: 1764179205 ;16: 1983987807 ;17: 4997678 ;18: 1694577754 ;19: 387007444 ;20: 3295953430 ;21: 193285263 ;22: 1355627408 ;23: 3223930285 ;24: 4224926606 ;25: 217270126 ;26: 437078728 ;27: 2752072855 ;28: 147668675 ;29: 3134082621 ;30: 1749044351 ;31: 1753762558 ;32: 2916104703 OR 490423324 ;Unconfirmed: 406357036 ;Confirmed: 518491551 ;Binder Ring: 16382453 (x:639 y:329) ;MessageWindow Background: 3356477 Link to comment Share on other sites More sharing options...
Durovec Posted July 9, 2008 Share Posted July 9, 2008 (edited) Nice topic. I'm prepared to help. I'm also working on my own bot... Your code seems to work only with version 2. I don't have experience with OCR, but I think that PixelChecksum will return better results. Cannot see any login procedure, connection with database, don't use PixelGetColor(),... Edited July 9, 2008 by Durovec Link to comment Share on other sites More sharing options...
climberman Posted July 10, 2008 Author Share Posted July 10, 2008 Nice topic. I'm prepared to help. I'm also working on my own bot...Your code seems to work only with version 2. I don't have experience with OCR, but I think that PixelChecksum will return better results. Cannot see any login procedure, connection with database, don't use PixelGetColor(),...I'm not totally sure what I'm doing in the first place, but I haven't actually been able to test this at all in game yet. There is no login, I'm working on a GUI with controls to turn the bot on and off, so if the connection is lost for now thats a problem. I'd definitely apprecfiate any help.Here's what i know works:The ocr accurately identifies words and take screenshots of specified coordinates.The price lists can be automatically updated.The bot displays a message when the screen changes where it's looking for a trade window to openThe Checksum issue is this: how can you tell what the card name actually is you're looking at? The idea of this bot is you tell it to figure out the card name that shows up when a person selects to trade for it. Thanks for the reply Link to comment Share on other sites More sharing options...
Scen Posted July 10, 2008 Share Posted July 10, 2008 I like it! I haven't looked at any MTGO bots yet, but I've played MTGO before and I was thinking of making one. What had me stumped is how I was going to determine what cards I was looking at. Your use of OCR is exactly what I'm looking for.I'm not totally sure what I'm doing in the first place, but I haven't actually been able to test this at all in game yet. There is no login, I'm working on a GUI with controls to turn the bot on and off, so if the connection is lost for now thats a problem. I'd definitely apprecfiate any help.I think I'd worry about getting the whole process to work before working on a GUI to turn it off and on. That way you can handle disconnects. You can always go back in and add a way to turn it on and off later. Generally the way I go about it is program a working bot first then handle a GUI.The Checksum issue is this: how can you tell what the card name actually is you're looking at? The idea of this bot is you tell it to figure out the card name that shows up when a person selects to trade for it.That's what I was thinking.. OCR will give you the ability to price cards. He may be speaking from the perspective of writing a "3:1 or 2:1" bot, where you don't have to worry as much about what you're looking at. All you would have to do is filter out the cards you already have alot of and trade.Anyways good job so far :-o Link to comment Share on other sites More sharing options...
Scen Posted July 10, 2008 Share Posted July 10, 2008 The ocr accurately identifies words and take screenshots of specified coordinates.I got started on the OCR function and I'm having difficulties with it. When I use an image of a card and give it to the reader the array returned skips over the name and starts with the rules text. If I crop the card.bmp file to just the title- it does capture the title like I wanted. However, it is reading "Calciderm" as ((Caiciderm . I tried cropping the bubble part of the title to remove the ((s but then it won't read the name again. Even if I leave those ((s there, I still have the issue that its reading Calciderm as Caiciderm. Are you running into any similar problems? I suppose I could just ignore them.. and in my database I'd have to call "calciderm" caiciderm.. but I'd rather find a solution than a work-around. Link to comment Share on other sites More sharing options...
climberman Posted July 10, 2008 Author Share Posted July 10, 2008 I got started on the OCR function ...........into any similar problems? I suppose I could just ignore them.. and in my database I'd have to call "calciderm" caiciderm.. but I'd rather find a solution than a work-around.Good to know, I'll look into it some more and see what I get. I'm on a 1024 x 768 resolution how bout you? O hey I gotta mention something. Don't use the cards vew, use the list view. It will work much better.I wanted to post a screenshot to show how to put it in list mode but it only will insert images from the web. its attached instead see the arrow that button goes to list view, on top its on card view. I'll post the results of my ocr findings later, will try to read some cards from my deck editor's sideboard (might be same location as trade window). Link to comment Share on other sites More sharing options...
climberman Posted July 11, 2008 Author Share Posted July 11, 2008 Ok, I'm going back to setting up the bot piece by piece. Here are my results so far and a few special instructions. First I replaced the marbled background image with just a black one so the ocr works better. Then I set up the GUI so the only thing that runs is the OCR when i tell the bot to run. I'm attaching my code as a file., and also the black bg. My results on this were that it took the screenshot of my sideboard cards and got every single card name correct. Next I'll be testing the price referrencing i think. If you guys need any help with running the script as it is so far, let me know, r if you have suggestions.bot.au3 Link to comment Share on other sites More sharing options...
Ixidior Posted May 23, 2009 Share Posted May 23, 2009 Ok, I'm going back to setting up the bot piece by piece. Here are my results so far and a few special instructions. First I replaced the marbled background image with just a black one so the ocr works better. Then I set up the GUI so the only thing that runs is the OCR when i tell the bot to run. I'm attaching my code as a file., and also the black bg. My results on this were that it took the screenshot of my sideboard cards and got every single card name correct. Next I'll be testing the price referrencing i think. If you guys need any help with running the script as it is so far, let me know, r if you have suggestions.hi there.. i'm new here and i'm trying to make a trader bot for MTGO. I'm good at programming.. cause i'm creative.. but.. i have very big problems when i don't know anything like.. OCR.. what is ORC???. I understand a big part of your bot but i don't get how to know what card was selected by the customer}plz help me i'll be very grateful Link to comment Share on other sites More sharing options...
Recommended Posts