From 5558cca57f14d56ee2cc94485433333d118faae5 Mon Sep 17 00:00:00 2001 From: qfox Date: Sun, 10 Sep 2006 14:11:26 +0000 Subject: [PATCH] BasicBot 0.3.1: Removed code-length limit (rather drastic change). Improved the GUI and added stuff for future features. --- src/drivers/win/basicbot.cpp | 762 +++++++++++++++++++++-------------- src/drivers/win/basicbot.h | 5 +- src/drivers/win/res.rc | Bin 119484 -> 126056 bytes src/drivers/win/resource.h | 49 ++- 4 files changed, 505 insertions(+), 311 deletions(-) diff --git a/src/drivers/win/basicbot.cpp b/src/drivers/win/basicbot.cpp index 0dbd7967..25ec356c 100644 --- a/src/drivers/win/basicbot.cpp +++ b/src/drivers/win/basicbot.cpp @@ -1,4 +1,3 @@ -int res; /** * qfox: * todo: boundrycheck every case in the switch! the string checks might override the boundries and read data its not supposed to. i'm not quite sure if this is an issue in C though. @@ -34,26 +33,26 @@ int res; #include "basicbot.h" #include "../../input.h" // qfox: fceu_botmode() fceu_setbotmode() -// qfox: v0.1.0 will be the last release by Luke, mine will start at v0.2.0 and +// v0.1.0 will be the last release by Luke, mine will start at v0.2.0 and // go up each time something is released to the public, so you'll // know your version is the latest or whatever. Version will be -// put in the project as well. -static char BBversion[] = "0.3.0"; +// put in the project as well. A changelog will be kept. +static char BBversion[] = "0.3.1"; // title -static char BBcaption[] = "Basic Bot v0.3.0 by qFox"; +static char BBcaption[] = "Basic Bot v0.3.1 by qFox"; +// save/load version +static int BBsaveload = 1; -static HWND hwndBasicBot = 0; // GUI handle -static bool BotRunning = false; // Is the bot computing or not? +static HWND hwndBasicBot = 0; // GUI handle +static bool BotRunning = false; // Is the bot computing or not? static uint32 rand1=1, rand2=0x1337EA75, rand3=0x0BADF00D; -#define BOT_MAXCODE 1024 // Max length of code-fields in bytes -#define BOT_FORMULAS 28 // Number of code fields in the array -static char Formula[BOT_FORMULAS][BOT_MAXCODE]; // These hold BOT_FORMULAS formula's entered in the GUI: -static int Bytecode[BOT_FORMULAS][BOT_MAXCODE]; // Byte code converted formulas -static int ByteCodePointer; // Points to position of next value +#define BOT_FORMULAS 35 // Number of code fields in the array +char * Formula[BOT_FORMULAS]; // These hold BOT_FORMULAS formula's entered in the GUI: +int * Bytecode[BOT_FORMULAS]; // Byte code converted formulas static int ByteCodeField; // Working field -static int CODE_1_A = 0, // code fields +static int CODE_1_A = 0, // Code fields CODE_1_B = 1, CODE_1_SELECT = 2, CODE_1_START = 3, @@ -69,20 +68,69 @@ static int CODE_1_A = 0, // code fields CODE_2_DOWN = 13, CODE_2_LEFT = 14, CODE_2_RIGHT = 15, - CODE_STOP = 16, - CODE_MAX = 17, - CODE_TIE1 = 18, - CODE_TIE2 = 19, - CODE_TIE3 = 20, - CODE_X = 21, - CODE_Y = 22, - CODE_Z = 23, - CODE_P = 24, - CODE_Q = 25, - CODE_EXTRA = 26, - CODE_COMMENTS = 27; + CODE_OK = 16, + CODE_INVALID = 17, + CODE_ROLLBACK = 18, + CODE_MAXFRAMES = 19, + CODE_MAXATTEMPTS= 20, + CODE_MAXPARTS = 21, + CODE_SCORE = 22, + CODE_TIE1 = 23, + CODE_TIE2 = 24, + CODE_TIE3 = 25, + CODE_TIE4 = 26, + CODE_TIE5 = 27, + CODE_X = 28, + CODE_Y = 29, + CODE_Z = 30, + CODE_P = 31, + CODE_Q = 32, + CODE_EXTRA = 33, + CODE_COMMENTS = 34; +// array contains GUI id's for certain pieces of code +// these are in sync with the CODE_ ints above +int Labels[] = { + GUI_BOT_A_1, + GUI_BOT_B_1, + GUI_BOT_SELECT_1, + GUI_BOT_START_1, + GUI_BOT_UP_1, + GUI_BOT_DOWN_1, + GUI_BOT_LEFT_1, + GUI_BOT_RIGHT_1, + GUI_BOT_A_2, + GUI_BOT_B_2, + GUI_BOT_SELECT_2, + GUI_BOT_START_2, + GUI_BOT_UP_2, + GUI_BOT_DOWN_2, + GUI_BOT_LEFT_2, + GUI_BOT_RIGHT_2, + GUI_BOT_OK, + GUI_BOT_INVALID, + GUI_BOT_ROLLBACK, + GUI_BOT_MAXFRAMES, + GUI_BOT_MAXATTEMPTS, + GUI_BOT_MAXPARTS, + GUI_BOT_SCORE, + GUI_BOT_TIE1, + GUI_BOT_TIE2, + GUI_BOT_TIE3, + GUI_BOT_TIE4, + GUI_BOT_TIE5, + GUI_BOT_X, + GUI_BOT_Y, + GUI_BOT_Z, + GUI_BOT_P, + GUI_BOT_Q, + GUI_BOT_EXTRA, + GUI_BOT_COMMENTS + }; -const int BOT_BYTE_LB = 48, // commands +// these are the commands +// they are actually the "bytecode" commands, +// used by the encoder and interpreter +const int BOT_BYTE_LB = 48, BOT_BYTE_RB = 1, BOT_BYTE_LIT = 2, BOT_BYTE_COLON = 3, @@ -149,7 +197,9 @@ static int BotFrame, // Which frame is currently or last computed? static int BotAttempts, // Number of attempts tried so far BotFrames, // Number of frames computed so far - BotBestScore[4]; // Maximize, tie1, tie2, tie3 + Oks, // Number of successfull attempts + Invalids, // Number of invalidated attempts + BotBestScore[6]; // Maximize, tie1, tie2, tie3 static bool NewAttempt; // Tells code to reset certain run-specific info static int LastButtonPressed; // Used for lastbutton command (note that this @@ -191,11 +241,6 @@ bool UpdateFromGUI = false; // When this flag is set, the next new attempt wi // the settings from gui to mem. note that this cannot set // the settings for both players at once... maybe later. -float AverageScore[4]; // Keep the average scores in here. to prevent overflow - // this is not a total, but the average is computed after - // every attempt and put back in here. this shouldn't - // affect accuracy. - int X,Y,Z,P,Prand,Q,Qrand; // Static variables (is this a contradiction?) and // probabilities. XYZ remain the same, PQ return randomly a // number in the range of 0-P or 0-Q. They can be used in @@ -221,6 +266,56 @@ static void SeedRandom(uint32 seed) if(rand1 == 0) rand1 = 1; // luke: I forget if this is necessary. } +/** + * Get the length of a textfield ("edit control") or textarea + * It's more of a macro really. + * Returns 0 when an error occurs, the length of current + * contents in any other case (check LastError in case of 0) + */ +unsigned int FieldLength(HWND winhandle,int controlid) +{ + HWND hwndItem = GetDlgItem(winhandle,controlid); + return SendMessage(hwndItem,WM_GETTEXTLENGTH,0,0); +} +/** + * Get the text from a freaking textfield/textarea + * Will reserve new memory space. These strings need + * to be "free"d when done with them!! + **/ +char * GetText(HWND winhandle, int controlid) +{ + unsigned int count = FieldLength(hwndBasicBot,controlid); + char *t = new char[count+1]; + GetDlgItemTextA(hwndBasicBot,controlid,t,count+1); + return t; +} + +/** + * copies "len" chars or until a '\0' from the + * old string to a new buffer and terminates + * this buffer with a '\0' + **/ +char * ToString(char * old, int len) +{ + char * temp = new char[len+1]; + for (int i=0; i': if(*(GlobalCurrentChar + 1) == '=') { GlobalCurrentChar += 2; - Bytecode[ByteCodeField][ByteCodePointer++] = BOT_BYTE_GTEQ; + bytes[pointer++] = BOT_BYTE_GTEQ; } else if(*(GlobalCurrentChar + 1) == '>') { GlobalCurrentChar += 2; - Bytecode[ByteCodeField][ByteCodePointer++] = BOT_BYTE_RSHIFT; + bytes[pointer++] = BOT_BYTE_RSHIFT; } else { ++GlobalCurrentChar; - Bytecode[ByteCodeField][ByteCodePointer++] = BOT_BYTE_GT; + bytes[pointer++] = BOT_BYTE_GT; } break; case '<': if(*(GlobalCurrentChar + 1) == '=') { GlobalCurrentChar += 2; - Bytecode[ByteCodeField][ByteCodePointer++] = BOT_BYTE_LTEQ; + bytes[pointer++] = BOT_BYTE_LTEQ; } else if(*(GlobalCurrentChar + 1) == '<') { GlobalCurrentChar += 2; - Bytecode[ByteCodeField][ByteCodePointer++] = BOT_BYTE_LSHIFT; + bytes[pointer++] = BOT_BYTE_LSHIFT; } else { ++GlobalCurrentChar; - Bytecode[ByteCodeField][ByteCodePointer++] = BOT_BYTE_LT; + bytes[pointer++] = BOT_BYTE_LT; } break; case '!': if(*(GlobalCurrentChar + 1) == '=') { GlobalCurrentChar += 2; - Bytecode[ByteCodeField][ByteCodePointer++] = BOT_BYTE_UEQ; + bytes[pointer++] = BOT_BYTE_UEQ; } else { @@ -456,7 +562,8 @@ static void ToByteCode(char * formula, int codefield) // use it as a prefix, checking if the next is 1000 // (or 0) or not and inverting it. For now error it. debugS("Unknown command (!...)"); - return; + free(bytes); + return NULL; } break; case '?': @@ -467,30 +574,30 @@ static void ToByteCode(char * formula, int codefield) // if true, it skips over 1, jumping to 3 when reaching : // else it just jumps to 2 // this is basic branching using a stack :) - Bytecode[ByteCodeField][ByteCodePointer++] = BOT_BYTE_IIF; - qmarkstack[++qpoint] = ByteCodePointer++; + bytes[pointer++] = BOT_BYTE_IIF; + qmarkstack[++qpoint] = pointer++; break; case ':': { ++GlobalCurrentChar; // colon encountered - Bytecode[ByteCodeField][ByteCodePointer++] = BOT_BYTE_COLON; + bytes[pointer++] = BOT_BYTE_COLON; // next position will contain jump to end of second statement - colonstack[++cpoint] = ByteCodePointer++; + colonstack[++cpoint] = pointer++; // put the number of positions after this target as jump target after the ? int qmarkpos = qmarkstack[qpoint--]; - Bytecode[ByteCodeField][qmarkpos] = ByteCodePointer - qmarkpos; + bytes[qmarkpos] = pointer - qmarkpos; break; } case ';': { ++GlobalCurrentChar; - Bytecode[ByteCodeField][ByteCodePointer++] = BOT_BYTE_SCOLON; + bytes[pointer++] = BOT_BYTE_SCOLON; // semicolon encountered // had to use the semicolon to simplify determining end of second arg... // next position is the target of the colon int colonpos = colonstack[cpoint--]; - Bytecode[ByteCodeField][colonpos] = ByteCodePointer - colonpos; + bytes[colonpos] = pointer - colonpos; break; } case 10: @@ -509,7 +616,7 @@ static void ToByteCode(char * formula, int codefield) { // attempt GlobalCurrentChar += 7; - Bytecode[ByteCodeField][ByteCodePointer++] = BOT_BYTE_ATTEMPT; + bytes[pointer++] = BOT_BYTE_ATTEMPT; } else if((*(GlobalCurrentChar+1) == 'd' &&*(GlobalCurrentChar+2) == 'd' @@ -526,7 +633,7 @@ static void ToByteCode(char * formula, int codefield) { // addcounter() ac() GlobalCurrentChar += (*(GlobalCurrentChar+1) == 'd') ? 11 : 3; - Bytecode[ByteCodeField][ByteCodePointer++] = BOT_BYTE_AC; + bytes[pointer++] = BOT_BYTE_AC; } else if(*(GlobalCurrentChar+1) == 'b' &&*(GlobalCurrentChar+2) == 's' @@ -534,14 +641,14 @@ static void ToByteCode(char * formula, int codefield) { // abs() GlobalCurrentChar += 4; - Bytecode[ByteCodeField][ByteCodePointer++] = BOT_BYTE_ABS; + bytes[pointer++] = BOT_BYTE_ABS; } else { // a() ++GlobalCurrentChar; - Bytecode[ByteCodeField][ByteCodePointer++] = BOT_BYTE_LIT; - Bytecode[ByteCodeField][ByteCodePointer++] = 1; + bytes[pointer++] = BOT_BYTE_LIT; + bytes[pointer++] = 1; } break; case 'b': @@ -553,14 +660,14 @@ static void ToByteCode(char * formula, int codefield) { // button GlobalCurrentChar += 6; - Bytecode[ByteCodeField][ByteCodePointer++] = BOT_BYTE_BUTTON; + bytes[pointer++] = BOT_BYTE_BUTTON; } else { // button B ++GlobalCurrentChar; - Bytecode[ByteCodeField][ByteCodePointer++] = BOT_BYTE_LIT; - Bytecode[ByteCodeField][ByteCodePointer++] = 2; + bytes[pointer++] = BOT_BYTE_LIT; + bytes[pointer++] = 2; } break; case 'c': @@ -575,13 +682,14 @@ static void ToByteCode(char * formula, int codefield) { // counter() GlobalCurrentChar += (*(GlobalCurrentChar+1) == 'o') ? 8 : 2; - Bytecode[ByteCodeField][ByteCodePointer++] = BOT_BYTE_C; + bytes[pointer++] = BOT_BYTE_C; } else { BotSyntaxError(2001); debugS("Unknown Command (c...)"); - return; + free(bytes); + return NULL; } break; case 'd': @@ -591,13 +699,14 @@ static void ToByteCode(char * formula, int codefield) { // down GlobalCurrentChar += 4; - Bytecode[ByteCodeField][ByteCodePointer++] = BOT_BYTE_DOWN; + bytes[pointer++] = BOT_BYTE_DOWN; } else { BotSyntaxError(3001); debugS("Unknown Command (d...)"); - return; + free(bytes); + return NULL; } break; case 'e': @@ -606,14 +715,15 @@ static void ToByteCode(char * formula, int codefield) &&*(GlobalCurrentChar+3) == 'o') { GlobalCurrentChar += 4; - Bytecode[ByteCodeField][ByteCodePointer++] = BOT_BYTE_ECHO; + bytes[pointer++] = BOT_BYTE_ECHO; break; } else { BotSyntaxError(4001); debugS("Unknown Command (e...)"); - return; + free(bytes); + return NULL; } case 'f': if(*(GlobalCurrentChar+1) == 'r' @@ -623,26 +733,27 @@ static void ToByteCode(char * formula, int codefield) { // frame GlobalCurrentChar += 5; - Bytecode[ByteCodeField][ByteCodePointer++] = BOT_BYTE_FRAME; + bytes[pointer++] = BOT_BYTE_FRAME; } else { BotSyntaxError(5001); debugS("Unknown Command (f...)"); - return; + free(bytes); + return NULL; } break; case 'i': ++GlobalCurrentChar; - Bytecode[ByteCodeField][ByteCodePointer++] = BOT_BYTE_I; + bytes[pointer++] = BOT_BYTE_I; break; case 'j': ++GlobalCurrentChar; - Bytecode[ByteCodeField][ByteCodePointer++] = BOT_BYTE_J; + bytes[pointer++] = BOT_BYTE_J; break; case 'k': ++GlobalCurrentChar; - Bytecode[ByteCodeField][ByteCodePointer++] = BOT_BYTE_K; + bytes[pointer++] = BOT_BYTE_K; break; case 'l': if((*(GlobalCurrentChar+1) == 'b') || @@ -658,7 +769,7 @@ static void ToByteCode(char * formula, int codefield) { // lastbutton lb GlobalCurrentChar += (*(GlobalCurrentChar+1) == 'b') ? 2 : 10; - Bytecode[ByteCodeField][ByteCodePointer++] = BOT_BYTE_LAST; + bytes[pointer++] = BOT_BYTE_LAST; } else if(*(GlobalCurrentChar+1) == 'e' &&*(GlobalCurrentChar+2) == 'f' @@ -666,7 +777,7 @@ static void ToByteCode(char * formula, int codefield) { // left GlobalCurrentChar += 4; - Bytecode[ByteCodeField][ByteCodePointer++] = BOT_BYTE_LEFT; + bytes[pointer++] = BOT_BYTE_LEFT; } else if(*(GlobalCurrentChar+1) == 'o' &&*(GlobalCurrentChar+2) == 'o' @@ -680,14 +791,15 @@ static void ToByteCode(char * formula, int codefield) // statement, it needs to be closed before leaving this // block anyways. (make sure the code checks for this!) GlobalCurrentChar += 4; - Bytecode[ByteCodeField][ByteCodePointer++] = BOT_BYTE_LOOP; - colonstack[++cpoint] = ByteCodePointer++; + bytes[pointer++] = BOT_BYTE_LOOP; + colonstack[++cpoint] = pointer++; } else { BotSyntaxError(7001); debugS("Unknown Command (l...)"); - return; + free(bytes); + return NULL; } break; case 'm': @@ -697,7 +809,7 @@ static void ToByteCode(char * formula, int codefield) { // mem() GlobalCurrentChar += 4; - Bytecode[ByteCodeField][ByteCodePointer++] = BOT_BYTE_MEM; + bytes[pointer++] = BOT_BYTE_MEM; } else if(*(GlobalCurrentChar+1) == 'e' &&*(GlobalCurrentChar+2) == 'm' @@ -706,7 +818,7 @@ static void ToByteCode(char * formula, int codefield) { // memh() GlobalCurrentChar += 5; - Bytecode[ByteCodeField][ByteCodePointer++] = BOT_BYTE_MEMH; + bytes[pointer++] = BOT_BYTE_MEMH; } else if(*(GlobalCurrentChar+1) == 'e' &&*(GlobalCurrentChar+2) == 'm' @@ -715,7 +827,7 @@ static void ToByteCode(char * formula, int codefield) { // meml() GlobalCurrentChar += 5; - Bytecode[ByteCodeField][ByteCodePointer++] = BOT_BYTE_MEML; + bytes[pointer++] = BOT_BYTE_MEML; } else if(*(GlobalCurrentChar+1) == 'e' &&*(GlobalCurrentChar+2) == 'm' @@ -724,13 +836,14 @@ static void ToByteCode(char * formula, int codefield) { // memw() GlobalCurrentChar += 5; - Bytecode[ByteCodeField][ByteCodePointer++] = BOT_BYTE_MEMW; + bytes[pointer++] = BOT_BYTE_MEMW; } else { BotSyntaxError(8001); debugS("Unknown Command (m...)"); - return; + free(bytes); + return NULL; } break; case 'n': @@ -746,7 +859,7 @@ static void ToByteCode(char * formula, int codefield) { // right GlobalCurrentChar += 5; - Bytecode[ByteCodeField][ByteCodePointer++] = BOT_BYTE_RIGHT; + bytes[pointer++] = BOT_BYTE_RIGHT; } else if((*(GlobalCurrentChar+1) == 'e' &&*(GlobalCurrentChar+2) == 's' @@ -766,13 +879,14 @@ static void ToByteCode(char * formula, int codefield) { // resetcounter() rc() GlobalCurrentChar += (*(GlobalCurrentChar+1) == 'e') ? 13 : 3; - Bytecode[ByteCodeField][ByteCodePointer++] = BOT_BYTE_RC; + bytes[pointer++] = BOT_BYTE_RC; } else { BotSyntaxError(9001); debugS("Unknown Command (r...)"); - return; + free(bytes); + return NULL; } break; case 's': @@ -783,7 +897,7 @@ static void ToByteCode(char * formula, int codefield) { // start GlobalCurrentChar += 5; - Bytecode[ByteCodeField][ByteCodePointer++] = BOT_BYTE_START; + bytes[pointer++] = BOT_BYTE_START; } else if(*(GlobalCurrentChar+1) == 'e' &&*(GlobalCurrentChar+2) == 'l' @@ -793,7 +907,7 @@ static void ToByteCode(char * formula, int codefield) { // select GlobalCurrentChar += 6; - Bytecode[ByteCodeField][ByteCodePointer++] = BOT_BYTE_SELECT; + bytes[pointer++] = BOT_BYTE_SELECT; } // why was there no short version for setcounter()? There is now... :) else if ((*(GlobalCurrentChar+1) == 'c') || @@ -810,7 +924,7 @@ static void ToByteCode(char * formula, int codefield) { // setcounter() sc() GlobalCurrentChar += (*(GlobalCurrentChar+1) == 'c') ? 3 : 11; - Bytecode[ByteCodeField][ByteCodePointer++] = BOT_BYTE_SC; + bytes[pointer++] = BOT_BYTE_SC; } // qfox: Added stop command. Should do exactly the same as pressing the "stop" button.\ // But probably won't yet :) @@ -820,13 +934,14 @@ static void ToByteCode(char * formula, int codefield) { // stop GlobalCurrentChar += 4; - Bytecode[ByteCodeField][ByteCodePointer++] = BOT_BYTE_STOP; + bytes[pointer++] = BOT_BYTE_STOP; } else { BotSyntaxError(10001); debugS("Unknown Command (s...)"); - return; + free(bytes); + return NULL; } break; case 'u': @@ -834,13 +949,14 @@ static void ToByteCode(char * formula, int codefield) { // up GlobalCurrentChar += 2; - Bytecode[ByteCodeField][ByteCodePointer++] = BOT_BYTE_UP; + bytes[pointer++] = BOT_BYTE_UP; } else { BotSyntaxError(11001); debugS("Unknown Command (p...)"); - return; + free(bytes); + return NULL; } break; case 'v': @@ -859,7 +975,8 @@ static void ToByteCode(char * formula, int codefield) { BotSyntaxError(12001); debugS("Unknown Command (v...)"); - return; + free(bytes); + return NULL; } break; case '0': @@ -892,8 +1009,8 @@ static void ToByteCode(char * formula, int codefield) // I don't think ahead needs to be incremented before adding it to // currentchar, because the while increments it for _every_ character. GlobalCurrentChar += ahead; - Bytecode[ByteCodeField][ByteCodePointer++] = BOT_BYTE_LIT; - Bytecode[ByteCodeField][ByteCodePointer++] = value; + bytes[pointer++] = BOT_BYTE_LIT; + bytes[pointer++] = value; negmode = false; break; } @@ -924,8 +1041,8 @@ static void ToByteCode(char * formula, int codefield) ++ahead; } GlobalCurrentChar += ahead; - Bytecode[ByteCodeField][ByteCodePointer++] = BOT_BYTE_LIT; - Bytecode[ByteCodeField][ByteCodePointer++] = value; + bytes[pointer++] = BOT_BYTE_LIT; + bytes[pointer++] = value; negmode = false; hexmode = false; } @@ -934,37 +1051,39 @@ static void ToByteCode(char * formula, int codefield) // If not in hexmode, we cant use these characters. BotSyntaxError(1003); debugS("Not in hexmode!"); - return; + free(bytes); + return NULL; } break; case 'P': ++GlobalCurrentChar; - Bytecode[ByteCodeField][ByteCodePointer++] = BOT_BYTE_P; + bytes[pointer++] = BOT_BYTE_P; break; case 'Q': ++GlobalCurrentChar; - Bytecode[ByteCodeField][ByteCodePointer++] = BOT_BYTE_Q; + bytes[pointer++] = BOT_BYTE_Q; break; case 'X': ++GlobalCurrentChar; - Bytecode[ByteCodeField][ByteCodePointer++] = BOT_BYTE_X; + bytes[pointer++] = BOT_BYTE_X; break; case 'Y': ++GlobalCurrentChar; - Bytecode[ByteCodeField][ByteCodePointer++] = BOT_BYTE_Y; + bytes[pointer++] = BOT_BYTE_Y; break; case 'Z': ++GlobalCurrentChar; - Bytecode[ByteCodeField][ByteCodePointer++] = BOT_BYTE_Z; + bytes[pointer++] = BOT_BYTE_Z; break; default: // Unknown characters should error out. You can use spaces. BotSyntaxError(12001); debugS("Unknown character..."); - return; + free(bytes); + return NULL; } } - return; + return bytes; } @@ -1328,11 +1447,17 @@ void UpdateBasicBot() //if(BotFrame > (BOT_MAXFRAMES-4) || (int) (NextRandom() % BOT_MAXPROB) < EvaluateFormula(Formula[20])) int i; // loopcounter - if(BotFrame > (BOT_MAXFRAMES-5) || Interpret(CODE_STOP) == BOT_MAXPROB) + bool improvement = true; + if(BotFrame > (BOT_MAXFRAMES-5) || (improvement = (Interpret(CODE_INVALID) == BOT_MAXPROB)) || Interpret(CODE_OK) == BOT_MAXPROB) { + // a little misleading, but if the improvement + // bool is set here, the attempt is invalid + if (improvement) + ++Invalids; + else + ++Oks; - int currentscore[4]; - bool better = false; + int currentscore[6]; // This was the last frame of this attempt NewAttempt = true; @@ -1340,42 +1465,44 @@ void UpdateBasicBot() // This evaluates each of the four strings (over and over again) // which can become rather sluggish. // maximize, tie1, tie2, tie3 - for(i=0; i < 4; i++) + for(i=0; i < 6; i++) { - currentscore[i] = Interpret(CODE_MAX+i); + currentscore[i] = Interpret(CODE_SCORE+i); } // Update last score UpdateLastGUI(currentscore); - // Update avg score - for (i=0; i<4; ++i) - AverageScore[i] = ((AverageScore[i]*BotAttempts)+currentscore[i])/(BotAttempts+1); - // show them - UpdateAvgGUI(); - - - // compare all scores. if scores are not equal, a break _will_ - // occur. else the next will be checked. if all is equal, the - // old best is kept. - for(i=0; i < 4; i++) + // dont improve if this attempt was invalid + if (!improvement) { - if(currentscore[i] > BotBestScore[i]) + improvement = false; + // compare all scores. if scores are not equal, a break _will_ + // occur. else the next will be checked. if all is equal, the + // old best is kept. + for(i=0; i < 6; i++) { - better = true; - break; - } - else if(currentscore[i] < BotBestScore[i]) - { - break; + if(currentscore[i] > BotBestScore[i]) + { + improvement = true; + break; + } + else if(currentscore[i] < BotBestScore[i]) + { + break; + } } } + else + { + improvement = false; + } // Update best - if(better) + if(improvement) { // Update the scores - for(i = 0; i < 4; i++) + for(i = 0; i < 6; i++) { BotBestScore[i] = currentscore[i]; } @@ -1403,7 +1530,7 @@ void UpdateBasicBot() // random number, the button is pressed :) for(i=0;i<16;i++) { - res = Interpret(i); + int res = Interpret(i); if(GetRandom(BOT_MAXPROB) < res) { // Button flags: @@ -1465,7 +1592,7 @@ void UpdateBasicBot() /** * Check the current settings for syntax validity **/ -static void CheckCode() +/*static void CheckCode() { EvaluateError = false; for(int i=0;i<8;i++) @@ -1511,7 +1638,7 @@ static void CheckCode() error(0); } } - +*/ /** * save code seems to be good. **/ @@ -1577,9 +1704,22 @@ static bool SaveBasicBotFile(char fn[]) fputc('o',fp); fputc('t',fp); fputc(0,fp); + fputc(BBsaveload&0xFF,fp); + // for every line... for(i=0;i>24,fp); + fputc((len&0x00FF0000)>>16,fp); + fputc((len&0x0000FF00)>>8,fp); + fputc( len&0x000000FF,fp); + // now put in the data + for (j=0; j128, or something. + if(code[j] & 128) + code[j] = 0; } + // we want no memleaks, no sir! + if (Formula[i] != NULL) + free(Formula[i]); + // hook them up! + Formula[i] = code; } // release lock and resources fclose(fp); debugS("Loaded file!"); return true; } - debugS("Error loading file!"); + debugS("Error loading file! Unable to open it!"); + error(1005); return false; } @@ -1684,13 +1854,12 @@ static bool LoadBasicBotFile(char fn[]) * Moved code to start function to be called from other places. * The code puts all the code from gui to variables and starts bot. **/ -static void StartBasicBot() { +static void StartBasicBot() +{ // todo: make sure you are or get into botmode here FCEU_SetBotMode(1); BotRunning = true; FromGUI(); - for (int i=0; i<4; ++i) - AverageScore[4] = 0.0; SetDlgItemText(hwndBasicBot,GUI_BOT_RUN,(LPTSTR)"Stop!"); } @@ -1717,37 +1886,17 @@ static void FromGUI() { if (hwndBasicBot) { - int i; // buttons - for(i = 0; i < 8; i++) + for (int i = 0; i < BOT_FORMULAS; i++) { - // id 1000-1008 are for the buttons - memset(Formula[i + (EditPlayerOne?0:8)],0,BOT_MAXCODE); - GetDlgItemText(hwndBasicBot,1000+i,Formula[i + (EditPlayerOne?0:8)], BOT_MAXCODE); - ToByteCode(Formula[i+(EditPlayerOne?0:8)],i+(EditPlayerOne?0:8)); + // since we malloc the strings, we need to free them before replacing them... + if (Formula[i] != NULL) + free(Formula[i]); + Formula[i] = GetText(hwndBasicBot,Labels[i]); + // um yeah, eval-ing the comments is a bad idea :p + if (i != CODE_COMMENTS) + Bytecode[i] = ToByteCode(Formula[i]); } - memset(Formula[CODE_STOP],0,BOT_MAXCODE); - GetDlgItemText(hwndBasicBot, GUI_BOT_END, Formula[CODE_STOP], BOT_MAXCODE); - ToByteCode(Formula[CODE_STOP],CODE_STOP); - memset(Formula[CODE_MAX],0,BOT_MAXCODE); - GetDlgItemText(hwndBasicBot, GUI_BOT_MAX, Formula[CODE_MAX], BOT_MAXCODE); - ToByteCode(Formula[CODE_MAX],CODE_MAX); - memset(Formula[CODE_TIE1],0,BOT_MAXCODE); - GetDlgItemText(hwndBasicBot, GUI_BOT_TIE1, Formula[CODE_TIE1], BOT_MAXCODE); - ToByteCode(Formula[CODE_TIE1],CODE_TIE1); - memset(Formula[CODE_TIE2],0,BOT_MAXCODE); - GetDlgItemText(hwndBasicBot, GUI_BOT_TIE2, Formula[CODE_TIE2], BOT_MAXCODE); - ToByteCode(Formula[CODE_TIE2],CODE_TIE2); - memset(Formula[CODE_TIE3],0,BOT_MAXCODE); - GetDlgItemText(hwndBasicBot, GUI_BOT_TIE3, Formula[CODE_TIE3], BOT_MAXCODE); - ToByteCode(Formula[CODE_TIE3],CODE_TIE3); - memset(Formula[CODE_EXTRA],0,BOT_MAXCODE); - GetDlgItemText(hwndBasicBot, GUI_BOT_EXTRA, Formula[CODE_EXTRA], BOT_MAXCODE); - ToByteCode(Formula[CODE_EXTRA],CODE_EXTRA); - memset(Formula[CODE_COMMENTS],0,BOT_MAXCODE); - GetDlgItemText(hwndBasicBot, GUI_BOT_COMMENTS, Formula[CODE_COMMENTS], BOT_MAXCODE); - // DONT EVAL THE COMMENTS! gah - // function, because we call this from a different button as well UpdateStatics(); } @@ -1759,26 +1908,12 @@ static void FromGUI() **/ static void ToGUI() { - if (hwndBasicBot && Formula && Formula[CODE_EXTRA]) + if (hwndBasicBot && Formula) { - int i; - // buttons - for(i = 0; i < 8; i++) + for (int i=0; i 4k, but ok. + memset(tempstring, 0, BOT_RESULTBUFSIZE); // clear the array char symbols[] = "ABET^v<>ABET^v<>"; bool seenplayer2 = false; // Bool keeps track of player two inputs - // Update best score - sprintf(tempstring, "%d %d %d %d (%dth)", BotBestScore[0], BotBestScore[1], BotBestScore[2], BotBestScore[3], BotAttempts); - SetDlgItemText(hwndBasicBot,GUI_BOT_BESTRESULT,tempstring); - memset(tempstring, 0, BOT_RESULTBUFSIZE); // clear the array + // Update best scores + SetDlgItemInt(hwndBasicBot,GUI_BOT_ATTEMPT_BEST,BotAttempts,TRUE); + SetDlgItemInt(hwndBasicBot,GUI_BOT_FRAMES_BEST,BotFrame,TRUE); + SetDlgItemInt(hwndBasicBot,GUI_BOT_SCORE_BEST,BotBestScore[0],TRUE); + SetDlgItemInt(hwndBasicBot,GUI_BOT_TIE1_BEST,BotBestScore[1],TRUE); + SetDlgItemInt(hwndBasicBot,GUI_BOT_TIE2_BEST,BotBestScore[2],TRUE); + SetDlgItemInt(hwndBasicBot,GUI_BOT_TIE3_BEST,BotBestScore[3],TRUE); + SetDlgItemInt(hwndBasicBot,GUI_BOT_TIE4_BEST,BotBestScore[4],TRUE); + SetDlgItemInt(hwndBasicBot,GUI_BOT_TIE5_BEST,BotBestScore[5],TRUE); // Create the run in ascii - int i,j,k; - k = 0; // keep track of len, needs to be below bufsize + int k = 0; // keep track of len, needs to be below bufsize // Make output as text // While you're not exceeding the max of frames, a // frame had input, and you're not exceeding the bufsize... // Warning: the second condition prevents a bufferoverrun, // -21 is because between checks a max of 21 chars // could be added. - for(i = 0; i < BOT_MAXFRAMES && BestAttempt[i] != -1 && k < BOT_RESULTBUFSIZE-21; i++) + for(int i = 0; i < BOT_MAXFRAMES && BestAttempt[i] != -1 && k < BOT_RESULTBUFSIZE-21; i++) { tempstring[k] = '0' + ((i/10) % 10); k++; @@ -2102,7 +2250,7 @@ void UpdateBestGUI() tempstring[k] = '.'; k++; seenplayer2=0; - for(j = 0; j < 16; j++) + for(int j = 0; j < 16; j++) { if(BestAttempt[i] & (1 << j)) { @@ -2123,25 +2271,20 @@ void UpdateBestGUI() // Update best score keys SetDlgItemText(hwndBasicBot,GUI_BOT_KEYS,tempstring); } -/** - * Update the averages - */ -void UpdateAvgGUI() -{ - SetDlgItemInt(hwndBasicBot,GUI_BOT_AVGMAX,AverageScore[0], TRUE); - SetDlgItemInt(hwndBasicBot,GUI_BOT_AVGTIE1,AverageScore[1], TRUE); - SetDlgItemInt(hwndBasicBot,GUI_BOT_AVGTIE2,AverageScore[2], TRUE); - SetDlgItemInt(hwndBasicBot,GUI_BOT_AVGTIE3,AverageScore[3], TRUE); -} /** * Update the Last Scores */ void UpdateLastGUI(int last[]) { - // 300 should be enough..? - char lastscore[300]; - sprintf(lastscore, "%d %d %d %d (%dth)", last[0], last[1], last[2], last[3], BotAttempts); - SetDlgItemText(hwndBasicBot,GUI_BOT_LAST,lastscore); + // Update best scores + SetDlgItemInt(hwndBasicBot,GUI_BOT_ATTEMPT_LAST,BotAttempts,TRUE); + SetDlgItemInt(hwndBasicBot,GUI_BOT_FRAMES_LAST,BotFrame,TRUE); + SetDlgItemInt(hwndBasicBot,GUI_BOT_SCORE_LAST,last[0],TRUE); + SetDlgItemInt(hwndBasicBot,GUI_BOT_TIE1_LAST,last[1],TRUE); + SetDlgItemInt(hwndBasicBot,GUI_BOT_TIE2_LAST,last[2],TRUE); + SetDlgItemInt(hwndBasicBot,GUI_BOT_TIE3_LAST,last[3],TRUE); + SetDlgItemInt(hwndBasicBot,GUI_BOT_TIE4_LAST,last[4],TRUE); + SetDlgItemInt(hwndBasicBot,GUI_BOT_TIE5_LAST,last[5],TRUE); } /** @@ -2151,6 +2294,8 @@ void UpdateCountersGUI() { SetDlgItemInt(hwndBasicBot,GUI_BOT_ATTEMPTS,BotAttempts,TRUE); SetDlgItemInt(hwndBasicBot,GUI_BOT_FRAMES,BotFrames,TRUE); + SetDlgItemInt(hwndBasicBot,GUI_BOT_OKS,Oks,TRUE); + SetDlgItemInt(hwndBasicBot,GUI_BOT_INVALIDS,Invalids,TRUE); } /** * Set up the vars to start a new attempt @@ -2171,3 +2316,4 @@ void SetNewAttempt() Prand = GetRandom(P); Qrand = GetRandom(Q); } + diff --git a/src/drivers/win/basicbot.h b/src/drivers/win/basicbot.h index a5e9080f..ea16059b 100644 --- a/src/drivers/win/basicbot.h +++ b/src/drivers/win/basicbot.h @@ -7,8 +7,9 @@ static void BotSyntaxError(int errorcode); static void StopBasicBot(); static void StartBasicBot(); - static void debug(int n); - static void error(int n); + static int debug(int n); + static char * debugS(char * s); + static int error(int n); static void FromGUI(); static void UpdateStatics(); void UpdateExternalButton(); diff --git a/src/drivers/win/res.rc b/src/drivers/win/res.rc index b1df2d08bcd9374dabd65a0221933185a3bfc897..b6b07684732eabf87c188cabd00a1a7f81cde161 100644 GIT binary patch delta 4829 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 delta 2478 zcma)8TWnNS6g?}zOdr!1W$2V=JG5me2y^ee?v%F7w4kYJGldqy!w|<{fCQ03A>sp@ z5I+ow(%#7ar3MqfD8wos5<*Sn!!Iz#_|=pTi5jD*KmI80ea_tJRM3#g+&gpb+K;pL z+WXuezVqMw$UioXE9)!31LCwLg15+TyGVZIZ^)2hIDNfQzaN%*QDTQw||E^t`4bFRJ8@Gxn7cIoUqFSZqdpoeN^{9G99aXQZmsN)fvtd#RTT%=8Eshdg*sT^0)8#09i&D(ucsKGi zwg*0{wa`?Em!!0XQ%r{ml=SFQj(cxvs0a^Gi;ZOk8;7!XiH)O+C?u8GG{uS`($p6# zfv2?&417E{L>GftN_+P6<=Hr@{U#I9af%+wqdQsD(sUfP99^qLOMEVlOryo*YtA@*+&)~Ngz_`X-`_?{-LzH=Djk?1X)G1355MAqe=02sRz*wSvAa`9cn-g@_mSj zv{g)VZ^UTuqVQ}8jbwj`W%PFv0s6Wfoz$O11&#J2w8)W`Na8-t=3%d$FHn@diBHoL z#%GMIQ6wmH2!UWJQo2PWDM#2Q-Bd=7=+ovs3XuEB-8tDu9cOrBZ#o$D8+Ge)Omx*!cN&o;x{swm8-~@Z z>M(zfu@Ia1`q(Y%p4XaKqQ}(v%j_q+#Fw*U3e+^@3Q!@QN@;lHfhrBj>fM2_41+y%b;GK8|m z(jj4U{$@z9cx2k7>Gm*heQu1q;!Fot1Rbpf(ZnX+sYr(h3t>HS?(yk1I+w?)22WZB zmDbn-YJ`?=MGK41^qv_k3+-zukVkdUj5RNiQECBr&mb=*aGsVlu4yn0pzF(hRb9xjXa}MjqJQdConJk#zWc zB%XFpG&?|y~uLz%w#a)H{Me8R~HVjio*0FpW+)&@`T8%m-PHNwSWqK ztyvJzk~1gm&UUuY7g?;R;c)u7oFmM4VS@M6>DLkcr10KBBWF?X&P{Enk9!cVGacuR z%^2^FskPi$OJ`I;PA^)jWG;EqHz(2MUfAVgrQcTE@i!W8JUEOi{d8*@t9T$fDn{9x PXrS9OsQBzt97+8HEV}(o diff --git a/src/drivers/win/resource.h b/src/drivers/win/resource.h index cb27a41f..13b5d794 100644 --- a/src/drivers/win/resource.h +++ b/src/drivers/win/resource.h @@ -6,7 +6,17 @@ #define GUI_BOT_VALUES 2 #define IDI_ICON1 101 #define IDI_ICON2 102 +#define GUI_BOT_A_1 1000 +#define GUI_BOT_B_1 1001 +#define GUI_BOT_SELECT_1 1002 +#define GUI_BOT_START_1 1003 +#define GUI_BOT_UP_1 1004 +#define GUI_BOT_DOWN_1 1005 +#define GUI_BOT_LEFT_1 1006 +#define GUI_BOT_RIGHT_1 1007 +#define GUI_BOT_A_2 1008 #define GUI_BOT_END 1009 +#define GUI_BOT_INVALID 1009 #define GUI_BOT_X 1010 #define GUI_BOT_TIE1 1011 #define GUI_BOT_TIE2 1012 @@ -15,6 +25,7 @@ #define GUI_BOT_LOAD 1015 #define GUI_BOT_RUN 1016 #define GUI_BOT_MAX 1017 +#define GUI_BOT_SCORE 1017 #define GUI_BOT_Y 1018 #define GUI_BOT_KEYS 1019 #define GUI_BOT_EXTRA 1020 @@ -28,10 +39,25 @@ #define GUI_BOT_Q 1027 #define GUI_BOT_TEST 1028 #define GUI_BOT_RESET 1029 +#define GUI_BOT_ROLLBACK 1030 +#define GUI_BOT_MAXFRAMES 1031 +#define GUI_BOT_MAXATTEMPTS 1032 +#define GUI_BOT_MAXPARTS 1033 +#define GUI_BOT_B_2 1034 #define GUI_BOT_P1 1035 +#define GUI_BOT_INTERNAL 1035 #define GUI_BOT_CLEAR 1036 #define GUI_BOT_ATTEMPTS 1037 +#define GUI_BOT_SELECT_2 1038 +#define GUI_BOT_START_2 1039 #define GUI_BOT_P2 1040 +#define GUI_BOT_EXTERNAL 1040 +#define GUI_BOT_UP_2 1041 +#define GUI_BOT_DOWN_2 1042 +#define GUI_BOT_LEFT_2 1043 +#define GUI_BOT_RIGHT_2 1044 +#define GUI_BOT_TIE4 1045 +#define GUI_BOT_TIE5 1046 #define GUI_BOT_FRAMES 1049 #define GUI_BOT_BESTRESULT 1050 #define GUI_BOT_LAST 1051 @@ -40,6 +66,27 @@ #define GUI_BOT_AVGTIE1 1054 #define GUI_BOT_AVGTIE2 1056 #define GUI_BOT_AVGTIE3 1057 +#define GUI_BOT_OK 1061 +#define GUI_BOT_ATTEMPT_LAST 1062 +#define GUI_BOT_ATTEMPT_BEST 1063 +#define GUI_BOT_SCORE_LAST 1064 +#define GUI_BOT_SCORE_BEST 1065 +#define GUI_BOT_TIE1_LAST 1066 +#define GUI_BOT_TIE1_BEST 1067 +#define GUI_BOT_TIE2_BEST 1068 +#define GUI_BOT_TIE3_BEST 1069 +#define GUI_BOT_TIE4_BEST 1070 +#define GUI_BOT_TIE5_BEST 1071 +#define GUI_BOT_TIE2_LAST 1072 +#define GUI_BOT_TIE3_LAST 1073 +#define GUI_BOT_TIE4_LAST 1074 +#define GUI_BOT_TIE5_LAST 1075 +#define GUI_BOT_ATTEMPT_LAST2 1076 +#define GUI_BOT_ATTEMPT_LAST3 1077 +#define GUI_BOT_FRAMES_LAST 1078 +#define GUI_BOT_FRAMES_BEST 1079 +#define GUI_BOT_OKS 1080 +#define GUI_BOT_INVALIDS 1082 #define ID_DEBUG_DEBUGGER 40053 #define ID_DEBUG_PPUVIEWER 40054 #define ID_DEBUG_NAMETABLEVIEWER 40055 @@ -56,7 +103,7 @@ #ifndef APSTUDIO_READONLY_SYMBOLS #define _APS_NEXT_RESOURCE_VALUE 103 #define _APS_NEXT_COMMAND_VALUE 40013 -#define _APS_NEXT_CONTROL_VALUE 1059 +#define _APS_NEXT_CONTROL_VALUE 1077 #define _APS_NEXT_SYMED_VALUE 101 #endif #endif