Ive been trying to get a genetic algorithm working , that will learn how to play any snes game , ive been trying to get it to beat the first level of super mario world.
so far i am able to generate a random string and that is translated into keystrokes , and they are successfully sent to the SNES emulator , but i have no previous experience with GA's , plus im not fluent in c++ . So im asking for some info on how i should set up this GA, also it needs a way of deciding when to press each key , right now i have it press a key after x amount of milseconds.
im looking to get something like this http://www.youtube.com/watch?v=c7xJNAJys2s
and here is my code(its all in one file as id like to work it out first then ill clean it up), main is at the bottom :\
thanks for looking through all that.Code:#include <windows.h> #include <iostream> #include <vector> #include <Winbase.h> // rand num generator im using #include "MersenneTwister.h" // size of string to generate #define SIZE 500 #define POP 100 // DXI key codes, only way of sending keystrokes to the snes emulator #define DIKEYBOARD_UP 0x04C8 #define DIKEYBOARD_LEFT 0x04CB #define DIKEYBOARD_RIGHT 0x04CD #define DIKEYBOARD_DOWN 0x04D0 #define DIKEYBOARD_A 0x041E #define DIKEYBOARD_C 0x042E #define DIKEYBOARD_D 0x0420 #define DIKEYBOARD_S 0x041F #define DIKEYBOARD_X 0x042D #define DIKEYBOARD_Z 0x042C using namespace std; //needs alot of work int place(vector<int> vect, int place) { int x = 1; int num1 = 0; int num2 = 0; int num3 = 0; if(place == 1 || 2 || 3) { do { if(num1 < vect[x]) { num1 = vect[x]; } x++; }while(x != SIZE); do { if(num2 < vect[x]) { num2 = vect[x]; } x++; }while(x != SIZE); do { if(num3 < vect[x] < num2) { num3 = vect[x]; } x++; }while(x != SIZE); } if(place == 1) { return num1; } if(place == 2) { return num2; } if(place == 3) { return num3; } } // reads from the addresses and returns their value int ReadMyAddress(unsigned long lol) { // read from pointer , not working //(DWORD*)ptr = 0xbasepointer; //ptr = (DWORD*)(*ptr + 0x0ffset); // BYTE value so i dont have to convert from 4BYTE BYTE MyBuffer = 0; // holds the address of the value being read unsigned long Address = lol; // holds the process id DWORD pid = 0; // handle to process HANDLE hProcess = 0; // handle to window HWND hProc; // finds window , used to get process ID hProc = FindWindow(NULL, L"ZSNES"); // error check to see if window is found if(hProc) {GetWindowThreadProcessId(hProc, &pid); } VirtualProtectEx(hProc, (LPVOID)Address, 256, PAGE_EXECUTE_READWRITE, NULL); hProcess = OpenProcess(PROCESS_ALL_ACCESS, 0, pid); ReadProcessMemory(hProcess, ULongToPtr(Address), &MyBuffer, sizeof(MyBuffer), NULL); return MyBuffer; } // generates the numbers in the array and returns the array vector<int> genGen () { // sets array size to what was defined vector<int> ary; int i = 0; // populates the array do { MTRand lool; ary.push_back(lool.randInt(9)); i++; } while ( i != SIZE); // returns the array(size is what was defined up top) return ary; } // Key input func , presses specified key void Key ( int key) { INPUT input; memset(&input,0,sizeof(INPUT)); input.type=INPUT_KEYBOARD; input.ki.wScan = key; // direct-input scancode input.ki.dwFlags=0; SendInput(1,&input,sizeof(INPUT)); Sleep(50); input.ki.dwFlags=KEYEVENTF_KEYUP; SendInput(1,&input,sizeof(INPUT)); } // fitness funtion, i have a vague idea what to do int testFit() { int Addy_Timer = ReadMyAddress(0x57C00D6); int Addy_MyHealth = ReadMyAddress(0x57C0F2C); int Addy_EnemyHealth = ReadMyAddress(0x57C100C); //int Addy_MyBonus = ReadMyAddress(0x57C1B0C); //int Addy_EnemyBonus = ReadMyAddress(0x57C1B5C); signed short int score = ((Addy_MyHealth - Addy_EnemyHealth) + Addy_Timer); return score; } // pushes gene keys void pressKey (vector<int> aray) { int i = 0; do { switch (aray[i]) { case 0: Key(DIKEYBOARD_X);//c cout << 'x'; break; case 1: Key(DIKEYBOARD_Z);//v cout << 'z'; break; case 2: Key(DIKEYBOARD_C);//x cout << 'c'; break; case 3: Key(DIKEYBOARD_D);//d cout << 'd'; break; case 4: Key(DIKEYBOARD_A);//a cout<< 'a'; break; case 5: Key(DIKEYBOARD_S);//s cout << 's'; break; case 6: Key(DIKEYBOARD_UP);//up cout<< " UP "; break; case 7: Key(DIKEYBOARD_DOWN);//down cout << " DWN "; break; case 8: Key(DIKEYBOARD_LEFT);//left cout << " LFT "; break; case 9: Key(DIKEYBOARD_RIGHT);//right cout << " RHT "; break; } i++; Sleep(300); } while(i != SIZE); } // MAIN int main(int argc,char * argv[]) { // finds window , used to get process ID HWND hProc = FindWindow(NULL, L"ZSNES"); int run = 0; int strand_c = 0; int fitness [POP]; vector< vector<int> > strand(POP, vector<int>(SIZE)); vector<int> testfit; SetForegroundWindow(hProc); do { // generate gene and put in vect vector<int> vect = genGen(); //output gene string int x =0; int generation = 0; do{ cout << vect[x]; x++; } while(x != SIZE); //Key(0x042E, TRUE); //sends vector to be processed pressKey(vect); //assigns gene a score int gene = testFit(); //stores the score in vect testfit testfit[generation] = gene; // assign current gene to pool do{ strand [strand_c][run] = vect[run]; run++; }while(run != SIZE); strand_c++; generation++; // send f1 to reload save //Key(0x042E, TRUE);//f1 } while (run != POP); //place the gene's return 0; }



LinkBack URL
About LinkBacks


