jvanegmond Posted November 11, 2008 Posted November 11, 2008 (edited) I felt I needed a break from all the serious programming and went back to botting in AutoIt. This time botting a simple game, minesweeper. The UDF could probably be used in a programming/AI class. The bot shows how fast and how simple you can beat minesweeper. Pay attention: Only tested on XP SP3, doesn't work on Vista because the game looks very different (pixel wise).examplebot.au3expandcollapse popup#include "minesweeper.au3" Opt("WinTitleMatchMode", 4) Opt("MouseClickDelay", 0) Opt("MouseClickDownDelay", 0) HotKeySet("{ESC}","_Exit") ;; Emergency exit Local $mGW = 16 ; My grid width Local $mGH = 16 ; My grid heigth Local $mStuck = 0 _WinMine_Initialize() _WinMine_SetupGame("Intermediate") _WinMine_SetSpeed(0) While _WinMine_Loop() If ( _WinMine_HasDied() ) Then _WinMine_NewGame() EndIf If ( _WinMine_HasWon() ) Then MsgBox(0x40, "Minesweeper bot", "Hey, I won! :D") Exit EndIf _WinMine_ReadMines() If (_WinMine_CountMines($MINE_UNKNOWN) <= (($mGW*$mGH)-100)) Then $mStuck += 1 ; pretends to be stuck at the moment, until something is done For $x = 0 to $mGW-1 For $y = 0 to $mGH-1 _CheckMine($x,$y) Next Next If ( $mStuck == 5 ) Then ;If ( MsgBox(0x4,"Minesweeper bot", "I appear to be stuck! Should I make a gamble?") == 0x6 ) Then _RandomClickMine() $mStuck = 0 ;EndIf EndIf Else ;; Randomly open up mines _WinMine_ClickMine(Random(1,$mGW-1,1),Random(1,$mGH-1,1)) EndIf WEnd Func _RandomClickMine() Local $a = 1 While 1 For $x = 0 to $mGW-1 For $y = 0 to $mGH-1 If (_WinMine_GetMine($x,$y) == $MINE_UNKNOWN) Then $surrounding = _WinMine_CountSurroundingMines($x, $y, $MINE_UNKNOWN) If $surrounding < $a Then _WinMine_ClickMine($x,$y) _WinMine_ReadMines() Return EndIf EndIf Next Next $a += 1 If ( $a == 20 ) Then Return EndIf WEnd EndFunc Func _CheckMine($x,$y) $thisMine = _WinMine_GetMine($x,$y) Switch $thisMine Case $MINE_BOMB, $MINE_EMPTY, $MINE_UNKNOWN Return Case $MINE_ONE $mines_nearby = _WinMine_CountSurroundingMines($x,$y,$MINE_UNKNOWN) $flags_nearby = _WinMine_CountSurroundingMines($x,$y,$MINE_FLAG) If ( $mines_nearby == 0) Then Return ;; Some speed improvement If ( $mines_nearby == 1 AND $flags_nearby == 0 ) Then $mStuck = 0 _WinMine_FlagSurroundingMines($x,$y) ElseIf ($flags_nearby == 1) Then $mStuck = 0 _WinMine_OpenSurroundingMines($x,$y) EndIf Case $MINE_TWO $mines_nearby = _WinMine_CountSurroundingMines($x,$y,$MINE_UNKNOWN) $flags_nearby = _WinMine_CountSurroundingMines($x,$y,$MINE_FLAG) If ( $mines_nearby == 0) Then Return ;; Some speed improvement If ($mines_nearby == 1 AND $flags_nearby == 1) Then $mStuck = 0 _WinMine_FlagSurroundingMines($x,$y) ElseIf ($mines_nearby = 2 AND $flags_nearby == 0) Then $mStuck = 0 _WinMine_FlagSurroundingMines($x,$y) ElseIf ($flags_nearby == 2) Then $mStuck = 0 _WinMine_OpenSurroundingMines($x,$y) EndIf Case $MINE_THREE $mines_nearby = _WinMine_CountSurroundingMines($x,$y,$MINE_UNKNOWN) $flags_nearby = _WinMine_CountSurroundingMines($x,$y,$MINE_FLAG) If ( $mines_nearby == 0) Then Return ;; Some speed improvement If ($mines_nearby == 1 AND $flags_nearby == 2) Then $mStuck = 0 _WinMine_FlagSurroundingMines($x,$y) ElseIf ($mines_nearby == 2 AND $flags_nearby == 1) Then $mStuck = 0 _WinMine_FlagSurroundingMines($x,$y) ElseIf ($mines_nearby == 3 AND $flags_nearby == 0) Then $mStuck = 0 _WinMine_FlagSurroundingMines($x,$y) ElseIf ($flags_nearby == 3) Then $mStuck = 0 _WinMine_OpenSurroundingMines($x,$y) EndIf Case $MINE_FOUR $mines_nearby = _WinMine_CountSurroundingMines($x,$y,$MINE_UNKNOWN) $flags_nearby = _WinMine_CountSurroundingMines($x,$y,$MINE_FLAG) If ( $mines_nearby == 0) Then Return ;; Some speed improvement If ($mines_nearby == 1 AND $flags_nearby == 3) Then $mStuck = 0 _WinMine_FlagSurroundingMines($x,$y) ElseIf ($mines_nearby == 2 AND $flags_nearby == 2) Then $mStuck = 0 _WinMine_FlagSurroundingMines($x,$y) ElseIf ($mines_nearby == 3 AND $flags_nearby == 1) Then $mStuck = 0 _WinMine_FlagSurroundingMines($x,$y) ElseIf ($mines_nearby == 4 AND $flags_nearby == 0) Then $mStuck = 0 _WinMine_FlagSurroundingMines($x,$y) ElseIf ($flags_nearby == 4) Then $mStuck = 0 _WinMine_OpenSurroundingMines($x,$y) EndIf EndSwitch EndFunc ;; A function for emergency exit Func _Exit() Exit EndFunc Edited September 30, 2010 by Manadar github.com/jvanegmond
jvanegmond Posted November 11, 2008 Author Posted November 11, 2008 (edited) And a bot that automatically does expert level, I have a feeling people are going to ask for this. expandcollapse popup#include "minesweeper.au3" Opt("WinTitleMatchMode", 4) Opt("MouseClickDelay", 0) Opt("MouseClickDownDelay", 0) HotKeySet("{ESC}","_Exit") ;; Emergency exit Local $mGW = 30 ; My grid width Local $mGH = 16 ; My grid heigth Local $mStuck = 0 _WinMine_Initialize() _WinMine_SetupGame("Expert") _WinMine_SetSpeed(0) While _WinMine_Loop() If ( _WinMine_HasDied() ) Then _WinMine_NewGame() EndIf If ( _WinMine_HasWon() ) Then MsgBox(0x40, "Minesweeper bot", "Hey, I won! :D") Exit EndIf _WinMine_ReadMines() If (_WinMine_CountMines($MINE_UNKNOWN) <= (($mGW*$mGH)-100)) Then $mStuck += 1 ; pretends to be stuck at the moment, until something is done For $x = 0 to $mGW-1 For $y = 0 to $mGH-1 _CheckMine($x,$y) Next Next If ( $mStuck == 5 ) Then ;If ( MsgBox(0x4,"Minesweeper bot", "I appear to be stuck! Should I make a gamble?") == 0x6 ) Then _RandomClickMine() $mStuck = 0 ;EndIf EndIf Else ;; Randomly open up mines _WinMine_ClickMine(Random(1,$mGW-1,1),Random(1,$mGH-1,1)) EndIf WEnd Func _RandomClickMine() Local $a = 1 While 1 For $x = 0 to $mGW-1 For $y = 0 to $mGH-1 If (_WinMine_GetMine($x,$y) == $MINE_UNKNOWN) Then $surrounding = _WinMine_CountSurroundingMines($x, $y, $MINE_UNKNOWN) If $surrounding < $a Then _WinMine_ClickMine($x,$y) _WinMine_ReadMines() Return EndIf EndIf Next Next $a += 1 If ( $a == 20 ) Then Return EndIf WEnd EndFunc Func _CheckMine($x,$y) $thisMine = _WinMine_GetMine($x,$y) Switch $thisMine Case $MINE_BOMB, $MINE_EMPTY, $MINE_UNKNOWN Return Case $MINE_ONE $mines_nearby = _WinMine_CountSurroundingMines($x,$y,$MINE_UNKNOWN) $flags_nearby = _WinMine_CountSurroundingMines($x,$y,$MINE_FLAG) If ( $mines_nearby == 0) Then Return ;; Some speed improvement If ( $mines_nearby == 1 AND $flags_nearby == 0 ) Then $mStuck = 0 _WinMine_FlagSurroundingMines($x,$y) ElseIf ($flags_nearby == 1) Then $mStuck = 0 _WinMine_OpenSurroundingMines($x,$y) EndIf Case $MINE_TWO $mines_nearby = _WinMine_CountSurroundingMines($x,$y,$MINE_UNKNOWN) $flags_nearby = _WinMine_CountSurroundingMines($x,$y,$MINE_FLAG) If ( $mines_nearby == 0) Then Return ;; Some speed improvement If ($mines_nearby == 1 AND $flags_nearby == 1) Then $mStuck = 0 _WinMine_FlagSurroundingMines($x,$y) ElseIf ($mines_nearby = 2 AND $flags_nearby == 0) Then $mStuck = 0 _WinMine_FlagSurroundingMines($x,$y) ElseIf ($flags_nearby == 2) Then $mStuck = 0 _WinMine_OpenSurroundingMines($x,$y) EndIf Case $MINE_THREE $mines_nearby = _WinMine_CountSurroundingMines($x,$y,$MINE_UNKNOWN) $flags_nearby = _WinMine_CountSurroundingMines($x,$y,$MINE_FLAG) If ( $mines_nearby == 0) Then Return ;; Some speed improvement If ($mines_nearby == 1 AND $flags_nearby == 2) Then $mStuck = 0 _WinMine_FlagSurroundingMines($x,$y) ElseIf ($mines_nearby == 2 AND $flags_nearby == 1) Then $mStuck = 0 _WinMine_FlagSurroundingMines($x,$y) ElseIf ($mines_nearby == 3 AND $flags_nearby == 0) Then $mStuck = 0 _WinMine_FlagSurroundingMines($x,$y) ElseIf ($flags_nearby == 3) Then $mStuck = 0 _WinMine_OpenSurroundingMines($x,$y) EndIf Case $MINE_FOUR $mines_nearby = _WinMine_CountSurroundingMines($x,$y,$MINE_UNKNOWN) $flags_nearby = _WinMine_CountSurroundingMines($x,$y,$MINE_FLAG) If ( $mines_nearby == 0) Then Return ;; Some speed improvement If ($mines_nearby == 1 AND $flags_nearby == 3) Then $mStuck = 0 _WinMine_FlagSurroundingMines($x,$y) ElseIf ($mines_nearby == 2 AND $flags_nearby == 2) Then $mStuck = 0 _WinMine_FlagSurroundingMines($x,$y) ElseIf ($mines_nearby == 3 AND $flags_nearby == 1) Then $mStuck = 0 _WinMine_FlagSurroundingMines($x,$y) ElseIf ($mines_nearby == 4 AND $flags_nearby == 0) Then $mStuck = 0 _WinMine_FlagSurroundingMines($x,$y) ElseIf ($flags_nearby == 4) Then $mStuck = 0 _WinMine_OpenSurroundingMines($x,$y) EndIf EndSwitch EndFunc ;; A function for emergency exit Func _Exit() Exit EndFunc Edited November 13, 2008 by Manadar github.com/jvanegmond
Draygoes Posted November 11, 2008 Posted November 11, 2008 (edited) As soon as it sees the minesweeper window, it crashes with the following error message... --------------------------- AutoIt Error --------------------------- Line 257 (File "C:\Users\Draygoes\Desktop\minesweeper.au3"): $b += PixelGetColor($a[0],$a[1]+$i,$hWnd) $b += PixelGetColor($a^ ERROR Error: Subscript used with non-Array variable. --------------------------- OK --------------------------- EDIT This is in Vista btw. If you want a copy of the Vista version of mine sweeper, just let me know and I can send it to you via pm... Edited November 11, 2008 by Draygoes Spoiler "If a vegetarian eats vegetables,What the heck does a humanitarian eat?" "I hear voices in my head, but I ignore them and continue on killing." "You have forced me to raise the indifference warning to beige, it's a beige alert people. As with all beige alerts please prepare to think about the possibility of caring." An optimist says that giving someone power DOESN'T immediately turn them into a sadist. A pessimist says that giving someone power doesn't IMMEDIATELY turn them into a sadist.
dansxmods Posted November 11, 2008 Posted November 11, 2008 (edited) Works Great for me this is awesome. Edit: It hasn't beat expert yet most it got down to is 23 Mines. Edited November 11, 2008 by dansxmods
jvanegmond Posted November 11, 2008 Author Posted November 11, 2008 If you want a copy of the Vista version of mine sweeper, just let me know and I can send it to you via pm...I just got a Vista machine yesterday, so I'm happy to try it on that. It's probably a slight difference in the color or box sizes. That can be adjusted.Works Great for me this is awesome.Edit: It hasn't beat expert yet most it got down to is 23 Mines.Thank you. The detection rules for the example bot aren't really fit for Expert. I've written the bot for intermediate mostly, but you can try yours for expert using the UDF. It's quite simple to use as you can see. github.com/jvanegmond
dansxmods Posted November 12, 2008 Posted November 12, 2008 I just got a Vista machine yesterday, so I'm happy to try it on that. It's probably a slight difference in the color or box sizes. That can be adjusted.Thank you. The detection rules for the example bot aren't really fit for Expert. I've written the bot for intermediate mostly, but you can try yours for expert using the UDF. It's quite simple to use as you can see. I think i will i might edit it to be able to choose the level at run time and even choose a custom level.Using your version it got down to 3 mines and then clicked on a mine and lost the game.
jvanegmond Posted November 12, 2008 Author Posted November 12, 2008 I think i will i might edit it to be able to choose the level at run time and even choose a custom level.Using your version it got down to 3 mines and then clicked on a mine and lost the game.It has a random function that kicks in when it gets stuck. I should be using probability calculations, but once I had all this I thought it was time to let someone else play with the UDF.If you are going to work with this, please don't modify the UDF, if you need any other functions write them in your own script. I also rather wouldn't have you edit the examplebot with a simple GUI.The idea of this is to let programmers / students play with this as an introduction to AI: Not to finish minesweeper. github.com/jvanegmond
dansxmods Posted November 12, 2008 Posted November 12, 2008 It has a random function that kicks in when it gets stuck. I should be using probability calculations, but once I had all this I thought it was time to let someone else play with the UDF.If you are going to work with this, please don't modify the UDF, if you need any other functions write them in your own script. I also rather wouldn't have you edit the examplebot with a simple GUI.The idea of this is to let programmers / students play with this as an introduction to AI: Not to finish minesweeper.No wukkas buddy I would keep any changes to the udf to myself anyway. I am I guess you could say a "student" of AutoIT and at the same time my own teacher. So thank you for this great script it is helping me learn pixel related things I wanted to learn.Daniel.
jvanegmond Posted November 12, 2008 Author Posted November 12, 2008 No wukkas buddy I would keep any changes to the udf to myself anyway. I am I guess you could say a "student" of AutoIT and at the same time my own teacher. So thank you for this great script it is helping me learn pixel related things I wanted to learn.Daniel.Thank you. I am glad it's found its purpose already. github.com/jvanegmond
cageman Posted November 12, 2008 Posted November 12, 2008 i tested it worked great! only problem was that i needed to change the word minesweeper into my own language. i dont know if this is correct, but when your bot finished the game and all the mines were flagged it started clicking and found a mine.. possible?
jvanegmond Posted November 13, 2008 Author Posted November 13, 2008 (edited) Using your version it got down to 3 mines and then clicked on a mine and lost the game.Random function was bugged and therefore it lost on Expert quite a lot. Now I've fixed it it actually finishes Expert quite a lot.Update:× Added _WinMine_SetSpeed ( 0 value for fast, 1 for normal, 2 for snail)× Added more speed× Fixed _RandomClickMine which was causing it to lose on expert.i dont know if this is correct, but when your bot finished the game and all the mines were flagged it started clicking and found a mine.. possible?Probably also because of the _RandomClickMine described above. Please see if it works correctly for you now. Edited November 13, 2008 by Manadar github.com/jvanegmond
jvanegmond Posted November 13, 2008 Author Posted November 13, 2008 This could probably be a better random function. Just not sure yet.. expandcollapse popupFunc _RandomClickMine() Local $mChance[$mGW][$mGH] Local $lowestChance = 1000 Local $lowestX, $lowestY For $x = 0 to $mGW-1 For $y = 0 to $mGH-1 $mChance[$x][$y] = _CalculateChanceBomb($x,$y) If ($mChance[$x][$y] <> -1 AND $mChance[$x][$y] < $lowestChance) Then $lowestChance = $mChance[$x][$y] $lowestX = $x $lowestY = $y EndIf Next Next _WinMine_ClickMine($lowestX, $lowestY) Sleep(500) EndFunc Func _CalculateChanceBomb($x,$y) $thisMine = _WinMine_GetMine($x,$y) If $thisMine <> $MINE_UNKNOWN Then Return -1 EndIf $lOne = _WinMine_CountSurroundingMines($x,$y,$MINE_ONE) $lTwo = _WinMine_CountSurroundingMines($x,$y,$MINE_TWO) $lThree = _WinMine_CountSurroundingMines($x,$y,$MINE_THREE) $lFour = _WinMine_CountSurroundingMines($x,$y,$MINE_FOUR) $lFive = _WinMine_CountSurroundingMines($x,$y,$MINE_FIVE) $lSix = _WinMine_CountSurroundingMines($x,$y,$MINE_SIX) $lTotal = $lOne + ($lTwo * 2) + ($lThree * 3) + ($lFour * 4) + ($lFive * 5) + ($lSix * 6) If ($lTotal <= 1) Then Return -1 Else Return $lTotal EndIf EndFunc Also, I wanted to let you Vista users know that a Vista compatible version is on it's way. github.com/jvanegmond
Ximorro Posted November 2, 2009 Posted November 2, 2009 Hi Manadar, I know this is an old post but I'm interested in logical solutions (no cheating) to minesweeper and found your post. The problem is that I cannot see the link to "minesweeper.au3" file. Is it that I am sleepy today or it was removed? If the code is after examplebot.au3, I get strange characters at the end of the codebox... I'll be glad if someone can upload minesweeper.au3 (or tell me where it is), thanks. By the way, did you coninue developing of Vista version? Bye.
jvanegmond Posted November 2, 2009 Author Posted November 2, 2009 Forum conversion messed the code tags up. I will try to find minesweeper.au3 in my personal folders, I will update here tonight. github.com/jvanegmond
Ximorro Posted November 2, 2009 Posted November 2, 2009 Uau! That's a quick reply! I'll look for it tomorrow, thanks.
jvanegmond Posted November 3, 2009 Author Posted November 3, 2009 Uau! That's a quick reply!I'll look for it tomorrow, thanks.I found it. Uploaded in first post. github.com/jvanegmond
Ximorro Posted November 3, 2009 Posted November 3, 2009 I found it. Uploaded in first post.Thankyou very much!By the way, did you make progress with the Vista version?. Due to the changing background I think using PixelChecksum to search for numbers and mines is no longer useful, maybe that task has to be made using some calls to PixelGetColor...But PixelGetColor is so slow in Vista...
jvanegmond Posted November 3, 2009 Author Posted November 3, 2009 No, I never got around to it then and I probably will never do it. PixelGetColor can be a lot faster on Vista if you specify a window handle. github.com/jvanegmond
Recommended Posts
Create an account or sign in to comment
You need to be a member in order to leave a comment
Create an account
Sign up for a new account in our community. It's easy!
Register a new accountSign in
Already have an account? Sign in here.
Sign In Now