Notice that I didn't use the more common term Chess AI because I didn't create it. AI is just about making a decision where bots include scraping data, processing data and outputing data. Chess AI needs a well formatted board state, but if you are writing a chess bot for example for PlayChess.com you don't have the well defined structure in your hands. You need to somehow scrape the data out of it, either by memory reading which can get really tedious if developers added a security measure for it, or by image processing which is easier for most of the cases.
If it wasn't a native application, and it was but a javascript web application there is a third and easier way, scraping and manipulating DOM. So writing bots for web applications are very easy compared to native applications with some security measures.
I usually use C#.NET to write bots and most of my projects since I don't care about portability of my pet-projects.
Part 1) Scraping the data via image processing
Part 2) Passing the board state to a Chess AI
Picking a Chess Engine is important, if you have your own engine that is good , you can probably connect that easily to your bot, but if that is not the case, you must use 2 functions, first one should convert the board state to a format that engine can understand, and the second one should convert the engine moves to a format that yours output layer can understand.
If the engine you found is open-source your job is easier since you will obviously have access to code. I found crafty chess engine which is both open source, robust and powerful, you can find it here http://www.craftychess.com/ . But I don't use crafty's open source property, since crafty already gave me enough options. For example the command "output long" makes crafty to output moves like Nb1c3 which is easier to parse, normally chess moves are like Nc3, so you have to calculate the starting position which is a hard work for example when two pieces can move to the same location it gets even harder.
Another command "xboard" mutes crafty's unwanted data, it only outputs it's moves which is also better for us because we don't care about how many positions it analyzed and those kinds of information.
I got crafty's exe and in my loop everytime a new game starts I start a process too, and redirect it's standart input and output to my C# program.
If the engine you found is open-source your job is easier since you will obviously have access to code. I found crafty chess engine which is both open source, robust and powerful, you can find it here http://www.craftychess.com/ . But I don't use crafty's open source property, since crafty already gave me enough options. For example the command "output long" makes crafty to output moves like Nb1c3 which is easier to parse, normally chess moves are like Nc3, so you have to calculate the starting position which is a hard work for example when two pieces can move to the same location it gets even harder.
Another command "xboard" mutes crafty's unwanted data, it only outputs it's moves which is also better for us because we don't care about how many positions it analyzed and those kinds of information.
I got crafty's exe and in my loop everytime a new game starts I start a process too, and redirect it's standart input and output to my C# program.
Part 3) Passing the result of Chess AI to PlayChess client
Now the last part is to make the move on the native application. You can try many things, you may intercept TCP packets and send your own tcp packets, or an easier way is to use Windows' SendMessage and SendInput API to make the move. I used this library http://inputsimulator.codeplex.com/ for it's simplicity for this project. You should turn the Chess AI's move output to source and destination coordinates, after that you can write a function like this and make your moves !!
public void makeMove(int r1, int c1, int r2, int c2)
{
InputSimulator inputsimul = new InputSimulator();
inputsimul .Mouse.MoveMouseTo((c1*64+32+76) * (65535.0 / 1366.0), (r1*64+32+161) * (65535 / 768.0));
System.Threading.Thread.Sleep(200);
inputsimul .Mouse.LeftButtonDown();
System.Threading.Thread.Sleep(200);
inputsimul .Mouse.MoveMouseTo((c2 * 64 + 32 + 76) * (65535.0 / 1366.0), (r2 * 64 + 32 + 161) * (65535 / 768.0));
System.Threading.Thread.Sleep(200);
inputsimul .Mouse.LeftButtonUp();
}
This makes a drap-drop move from r1,c1 to r2,c2 where these variables represent tile coordinates, not pixel coordinates. +32 is used for clicking in the middle, 76 is offset of my board and the inputsimulator library takes input from 0 to 65535 where 65535 represents the maximum width or height of your screen.
This makes a drap-drop move from r1,c1 to r2,c2 where these variables represent tile coordinates, not pixel coordinates. +32 is used for clicking in the middle, 76 is offset of my board and the inputsimulator library takes input from 0 to 65535 where 65535 represents the maximum width or height of your screen.
No comments:
Post a Comment