All pastes #265095 Raw Edit

Something

public cpp v1 · immutable
·published 2006-12-03 00:34 UTC
rendered paste body
/**Yeah well... this is TASbot.It's derived from BasicBot.When extending basicbot I ran into quite a few issues. In the end I decidedto rewrite the whole thing from scratch. This is the result.qFox, december 2006*/#include "common.h"      // windows stuff, amongst others#include "../../fceu.h"  // fceu internal dependancies#include "basicbot.h"    // duh#include "../../input.h" // fceu_botmode() fceu_setbotmode()#include <ctime>         // time is fed to the randomizer as seed// version stuffstatic char TB_version[] = "0.1.0a";                    // versionstatic char TB_caption[] = "TAS Bot v0.1.0a by qFox";   // for titlestatic int File_version = 1;                            // when saving / loading, if a older file// does not have the same lay-out as the// current version, it can not be loaded.// GUIHWND hwndTASbot = 0;                                    // GUI handle// parserchar * BotCurrentChar;                                  // points to the current position of the string// the parser is currently processingint BotCurrentCode;                                     // the same, for bytecodesint BotCurrentField;                                    // points to the field currently parsingint BotByteCodeField;                                   // same, but for the bytecode interpreterbool ProcessCode = true;			                    // This boolean tells the code whether or not to process// some code. This is mainly used in branching (iif's)// to skip over the part of the code that is not to be// executed. It still needs to be parsed because the// pointer needs to be moved ahead.// attempt input sequences (BOT_MAXFRAMES is defined in header)static uint32 BotCurrentAttempt[BOT_MAXFRAMES];		    // Contains all the frames of the current attempt.static uint32 BotBestAttempt[BOT_MAXFRAMES]; 			    // Contains all the frames of the best attempt so far.static uint32 BotAttemptPointer;			            // Points to the last frame of the current attempt.// Togglesbool BotRunning = false;                                // is the bot currently running?bool Bot_Update_gui_next = false;                           // will run fromGUI asapbool Bot_Reset_stats = false;                               // will end current attempt and reset all statsbool Bot_Eval_error = false;                            // if true, bot will stop at first opportunity// defines#define BOT_MAX_COUNTERS 256int BotCounter[BOT_MAX_COUNTERS];#define BOT_MAX_SCORES 6#define BOT_MAX_PROB 1000// statsint BotFrame,BotTotalFrames,BotAttempt,BotTotalAttempts,BotOks,BotInvalids,BotSegments,BotBestScore[BOT_MAX_SCORES];// static varsint Bot_X,Bot_Y,Bot_Z,Bot_P, Bot_Prand,Bot_Q, Bot_Qrand;int BotLastbutton;// symbols to refer to the gui control-idsenum CODEFIELDS {	//Buttons	CODE_BUTTON_START_MARKER,	CODE_1_A, CODE_1_B, CODE_1_SELECT, CODE_1_START, CODE_1_UP, CODE_1_DOWN, CODE_1_LEFT, CODE_1_RIGHT, 	CODE_2_A, CODE_2_B, CODE_2_SELECT, CODE_2_START, CODE_2_UP, CODE_2_DOWN, CODE_2_LEFT, CODE_2_RIGHT,	CODE_BUTTON_END_MARKER,	// Conditions	CODE_OK, CODE_INVALID, CODE_SEGMENT, CODE_STOP,	// scores	CODE_SCORE1, CODE_SCORE2, CODE_SCORE3, CODE_SCORE4, CODE_SCORE5, CODE_SCORE6,	// static variables	CODE_X, CODE_Y, CODE_Z, CODE_P, CODE_Q,	// pre/post code	CODE_PRE_FRAME, CODE_POST_FRAME, CODE_PRE_ATTEMPT, CODE_POST_ATTEMPT, CODE_PRE_SEGMENT, CODE_POST_SEGMENT,	// textual controls, not to be parsed	CODE_COMMENT_MARKER, 	CODE_COMMENTS, CODE_ROM,	CODE_TITLE1, CODE_TITLE2, CODE_TITLE3, CODE_TITLE4, CODE_TITLE5, CODE_TITLE6,	BOT_FORMULAS};// these are the label-symbols in the GUI. they are in sync with the CODEFIELDS enumerationint labels[] = {	// Buttons	CODE_BUTTON_START_MARKER,	BOT_GUI_A_1, BOT_GUI_B_1, BOT_GUI_SELECT_1, BOT_GUI_START_1, BOT_GUI_UP_1, BOT_GUI_DOWN_1, BOT_GUI_LEFT_1, BOT_GUI_RIGHT_1,	BOT_GUI_A_2, BOT_GUI_B_2, BOT_GUI_SELECT_2, BOT_GUI_START_2, BOT_GUI_UP_2, BOT_GUI_DOWN_2, BOT_GUI_LEFT_2, BOT_GUI_RIGHT_2,	CODE_BUTTON_END_MARKER,	// Conditions	BOT_GUI_OK, BOT_GUI_INVALID, BOT_GUI_SEGMENT, BOT_GUI_STOP,	// Scores	BOT_GUI_SCORE1, BOT_GUI_SCORE2, BOT_GUI_SCORE3, BOT_GUI_SCORE4, BOT_GUI_SCORE5, BOT_GUI_SCORE6,	// Static variables	BOT_GUI_X, BOT_GUI_Y, BOT_GUI_Z, BOT_GUI_P, BOT_GUI_Q, 	// pre/post code	BOT_GUI_PRE_FRAME, BOT_GUI_POST_FRAME, BOT_GUI_PRE_ATTEMPT, BOT_GUI_POST_ATTEMPT, BOT_GUI_PRE_SEGMENT, BOT_GUI_POST_SEGMENT,	// from here on down put inputs that	// are not to be parsed, but visual only	CODE_COMMENT_MARKER,	BOT_GUI_COMMENTS, BOT_GUI_ROM,	BOT_GUI_TITLE1, BOT_GUI_TITLE2, BOT_GUI_TITLE3, BOT_GUI_TITLE4, BOT_GUI_TITLE5, BOT_GUI_TITLE6,	BOT_FORMULAS};/*** the commands for the "scripting language"*/enum COMMANDS {	BOT_BYTE_EOL,	BOT_BYTE_LB,	BOT_BYTE_RB,	BOT_BYTE_LIT,	BOT_BYTE_COLON,	BOT_BYTE_SCOLON,	BOT_BYTE_ADD,	BOT_BYTE_SUB,	BOT_BYTE_MUL,	BOT_BYTE_DIV,	BOT_BYTE_MOD,	BOT_BYTE_AND,	BOT_BYTE_OR,	BOT_BYTE_XOR,	BOT_BYTE_EQ,	BOT_BYTE_GTEQ,	BOT_BYTE_GT,	BOT_BYTE_LTEQ,	BOT_BYTE_LT,	BOT_BYTE_UEQ,	BOT_BYTE_IIF,	BOT_BYTE_ATTEMPT,	BOT_BYTE_AC,	BOT_BYTE_ABS,	BOT_BYTE_BUTTON,	BOT_BYTE_C,	BOT_BYTE_DOWN,	BOT_BYTE_ECHO,	BOT_BYTE_ERROR,	BOT_BYTE_FRAME,	BOT_BYTE_I,	BOT_BYTE_INVALIDS,	BOT_BYTE_J,	BOT_BYTE_K,	BOT_BYTE_LAST,	BOT_BYTE_LEFT,	BOT_BYTE_LOOP,	BOT_BYTE_LSHIFT,	BOT_BYTE_MAX,	BOT_BYTE_MEM,	BOT_BYTE_MEMH,	BOT_BYTE_MEML,	BOT_BYTE_MEMW,	BOT_BYTE_NEVER,	BOT_BYTE_OKS,	BOT_BYTE_RC,	BOT_BYTE_RIGHT,	BOT_BYTE_RSHIFT,	BOT_BYTE_SELECT,	BOT_BYTE_START,	BOT_BYTE_SC,	BOT_BYTE_SCORE1,	BOT_BYTE_SCORE2,	BOT_BYTE_SCORE3,	BOT_BYTE_SCORE4,	BOT_BYTE_SCORE5,	BOT_BYTE_SCORE6,	BOT_BYTE_STOP,	BOT_BYTE_UP,	BOT_BYTE_P,	BOT_BYTE_Q,	BOT_BYTE_X,	BOT_BYTE_Y,	BOT_BYTE_Z};char * Formula[BOT_FORMULAS];					// These hold BOT_FORMULAS formula's entered in the GUI:int * Bytecode[BOT_FORMULAS];					// Byte code converted formulas// variables to hold the data for the "last" segmentint BotPrevSegNum = 0,BotPrevSegFrame = 0,BotPrevSegAttempt = 0,BotPrevSegLastbutton = 0,BotPrevSegScore1 = 0,BotPrevSegScore2 = 0,BotPrevSegScore3 = 0,BotPrevSegScore4 = 0,BotPrevSegScore5 = 0;// variables to hold the data for the "best" segmentint BotBestSegNum = 0,BotBestSegFrame = 0,BotBestSegAttempt = 0,BotBestSegLastbutton = 0,BotBestSegScore1 = 0,BotBestSegScore2 = 0,BotBestSegScore3 = 0,BotBestSegScore4 = 0,BotBestSegScore5 = 0;/*** Get the len of a string, which is the position* of the first '\0' from the start**/unsigned int strlen(char * str){	char * was = str;	while (*str != 0) ++str;	return str-was;}/*** same as strlen, but counts for ints instead**/unsigned int intlen(int * bytes){	int * was = bytes;	while (*bytes != 0) ++bytes;	return bytes-was;}/*** 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);}/*** show a messagebox*/static void mboxS(char * txt){	MessageBox(hwndTASbot, txt, "Debug", MB_OK);}static void mboxI(int n){	char t[20];	sprintf(t,"n = %d",n);	mboxS(t);}/*** get a random number from 0 to n-1 (n is not included!)*/static int bot_rand(int n){	return (rand()%n);}/*** Convert string code to byte code* This function is NOT called recursively!* - formula is the string to parse* - codefield is the field for which this code is meant (used for debugging)**/static int * convert(char * formula, int codefield){	// get the len of the formula	int len = strlen(formula);	// create some new space with the len of the formula	// its very unlikely that the bytecode will be any	// longer then the formula, the only exception is a	// formula with a single digit. for this reason	// we'll add a 10 byte padding#define EXTRABYTES 30	int * bytes = new int[len+EXTRABYTES];	memset(bytes,0,sizeof(int)*(len+EXTRABYTES));	int pointer = 0;	// reset values	Bot_Eval_error = false;	// set the global pointer to the string at the start of the string	BotCurrentChar = formula;	// first we want to quickly check whether the brackets are matching or not	// same for ? and :, both are pairs and should not exist alone, also they	// can not appear out of order (so no "?;:" ";?:" or something)	// also, 	char * quickscan = formula;	// to print an errormsg	char errormsg[200];	// counters	int iifs = 0, iifs2 = 0, bracks = 0;	// until EOL	while (*quickscan != 0 && !Bot_Eval_error)	{		switch(*quickscan)		{		case 'l': if (*(quickscan+1)=='o'&&*(quickscan+2)=='o'&&*(quickscan+3)=='p') ++iifs2; break;		case '?': ++iifs; break;		case ':': 			--iifs;			++iifs2;			if (iifs < 0) BotSyntaxError(1004);			break;		case ';': 			--iifs2; 			if (iifs2 < 0) BotSyntaxError(1004);			break;		case '(': ++bracks; break;		case ')': 			--bracks; 			if (bracks < 0) BotSyntaxError(1004);			break;		default: break;		}		++quickscan;	}	if (Bot_Eval_error || iifs || bracks || iifs2)	{		BotSyntaxError(1004);		sprintf(errormsg,"[%d] ?:;() dont match!",codefield);		debugS(errormsg);		delete bytes;		return NULL;	}	bool hexmode = false;	bool negmode = false;	// two stacks, used to branch properly	// code adds current pos to the stack if one of the commands	// is encountered. once a proper jump point is reached, put	// the location back at the position that's on the top of the	// stack (popping it off). for the iif, this means first 	// pushing the qmarkstack, when reaching the colon pop the	// qmarkstack and put the position there, then push the	// colonstack. when the end is reached, pop the colonstack and	// put the position there. this allows easy jumping. loop just	// needs to jump over its argument when it has looped enough.	int qmarkstack[100];	int colonstack[100];	// stack-counters	int qpoint=-1,cpoint=-1,lpoint=-1;	int pointerStart = (int)BotCurrentChar;	while(*BotCurrentChar != 0 && !Bot_Eval_error)	{		switch(*BotCurrentChar)		{		case 0:			// stringterminator, end of code			// no more input, so return			break; 		case '(':			++BotCurrentChar;			bytes[pointer++] = BOT_BYTE_LB;			break;		case ')':			++BotCurrentChar;			bytes[pointer++] = BOT_BYTE_RB;			break;		case 'x':			++BotCurrentChar;			hexmode = true;			break;		case '+':			++BotCurrentChar;			bytes[pointer++] = BOT_BYTE_ADD;			break;		case '-':			++BotCurrentChar;			bytes[pointer++] = BOT_BYTE_SUB;			break;		case '*':			++BotCurrentChar;			bytes[pointer++] = BOT_BYTE_MUL;			break;		case '/':			++BotCurrentChar;			bytes[pointer++] = BOT_BYTE_DIV;			break;		case '%':			++BotCurrentChar;			bytes[pointer++] = BOT_BYTE_MOD;			break;		case '&':			++BotCurrentChar;			bytes[pointer++] = BOT_BYTE_AND;			break;		case '|':			++BotCurrentChar;			bytes[pointer++] = BOT_BYTE_OR;			break;		case '^':			++BotCurrentChar;			bytes[pointer++] = BOT_BYTE_XOR;			break;		case '=':			++BotCurrentChar;			bytes[pointer++] = BOT_BYTE_EQ;			break;		case '>':			if(*(BotCurrentChar + 1) == '=')			{				BotCurrentChar += 2;				bytes[pointer++] = BOT_BYTE_GTEQ;			}			else if(*(BotCurrentChar + 1) == '>')			{				BotCurrentChar += 2;				bytes[pointer++] = BOT_BYTE_RSHIFT;			}			else			{				++BotCurrentChar;				bytes[pointer++] = BOT_BYTE_GT;			}			break;		case '<':			if(*(BotCurrentChar + 1) == '=') 			{				BotCurrentChar += 2;				bytes[pointer++] = BOT_BYTE_LTEQ;			}			else if(*(BotCurrentChar + 1) == '<')			{				BotCurrentChar += 2;				bytes[pointer++] = BOT_BYTE_LSHIFT;			}			else			{				++BotCurrentChar;				bytes[pointer++] = BOT_BYTE_LT;			}			break;		case '!':			if(*(BotCurrentChar + 1) == '=')			{				BotCurrentChar += 2;				bytes[pointer++] = BOT_BYTE_UEQ;			}			else			{				BotSyntaxError(1001); 	// "!" is not a valid command, but perhaps we could 				//	use it as a prefix, checking if the next is 1000				//	(or 0) or not and inverting it. For now error it.				sprintf(errormsg,"[%d] Unknown command (!...)",codefield);				debugS(errormsg);				delete bytes;				return NULL;			}			break;		case '?':			++BotCurrentChar;			// the bytecode will look similar to this:			//     xyz?1abcd:2efghi;3			// 1 will contain the adres of 2 (+1), 2 contains the adres of 3			// if true, it skips over 1, jumping to 3 when reaching :			// else it just jumps to 2			// this is basic branching using a stack :)			bytes[pointer++] = BOT_BYTE_IIF;			qmarkstack[++qpoint] = pointer++;			break;		case ':':			{				++BotCurrentChar;				// colon encountered				bytes[pointer++] = BOT_BYTE_COLON;				// next position will contain jump to end of second statement				colonstack[++cpoint] = pointer++;				// put the number of positions after this target as jump target after the ?				int qmarkpos = qmarkstack[qpoint--];				bytes[qmarkpos] = pointer - qmarkpos;				break;			}		case ';':			{				++BotCurrentChar;				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--];				bytes[colonpos] = pointer - colonpos;				break;			}		case 10:		case 13:		case 9:		case ' ':			++BotCurrentChar;			break;		case 'a':			if(*(BotCurrentChar+1) == 't'				&&*(BotCurrentChar+2) == 't'				&&*(BotCurrentChar+3) == 'e'				&&*(BotCurrentChar+4) == 'm'				&&*(BotCurrentChar+5) == 'p'				&&*(BotCurrentChar+6) == 't')			{				// attempt				BotCurrentChar += 7;				bytes[pointer++] = BOT_BYTE_ATTEMPT;			}			else if((*(BotCurrentChar+1) == 'd'				&&*(BotCurrentChar+2) == 'd'				&&*(BotCurrentChar+3) == 'c'				&&*(BotCurrentChar+4) == 'o'				&&*(BotCurrentChar+5) == 'u'				&&*(BotCurrentChar+6) == 'n'				&&*(BotCurrentChar+7) == 't'				&&*(BotCurrentChar+8) == 'e'				&&*(BotCurrentChar+9) == 'r'				&&*(BotCurrentChar+10)== '(') ||				(*(BotCurrentChar+1) == 'c'				&&*(BotCurrentChar+2) == '('))			{				// addcounter() ac()				BotCurrentChar += (*(BotCurrentChar+1) == 'd') ? 11 : 3;				bytes[pointer++] = BOT_BYTE_AC;			}			else if(*(BotCurrentChar+1) == 'b'				&&*(BotCurrentChar+2) == 's'				&&*(BotCurrentChar+3) == '(')			{				// abs()				BotCurrentChar += 4;				bytes[pointer++] = BOT_BYTE_ABS;			}			else if(*(BotCurrentChar+1) == 'l'				&&*(BotCurrentChar+2) == 'w'				&&*(BotCurrentChar+3) == 'a'				&&*(BotCurrentChar+4) == 'y'				&&*(BotCurrentChar+5) == 's')			{				// always (=max)				BotCurrentChar += 6;				bytes[pointer++] = BOT_BYTE_MAX;			}			else			{				// a				++BotCurrentChar;				bytes[pointer++] = BOT_BYTE_LIT;				bytes[pointer++] = 1;			}			break;		case 'b':			if(*(BotCurrentChar+1) == 'u'				&&*(BotCurrentChar+2) == 't'				&&*(BotCurrentChar+3) == 't'				&&*(BotCurrentChar+4) == 'o'				&&*(BotCurrentChar+5) == 'n')			{				// button				BotCurrentChar += 6;				bytes[pointer++] = BOT_BYTE_BUTTON;			}			else			{				// button B				++BotCurrentChar;				bytes[pointer++] = BOT_BYTE_LIT;				bytes[pointer++] = 2;			}			break;		case 'c':			if((*(BotCurrentChar+1) == 'o'				&& *(BotCurrentChar+2) == 'u'				&& *(BotCurrentChar+3) == 'n'				&& *(BotCurrentChar+4) == 't'				&& *(BotCurrentChar+5) == 'e'				&& *(BotCurrentChar+6) == 'r'				&& *(BotCurrentChar+7) == '(') ||				(*(BotCurrentChar+1) == '('))			{				// counter()				BotCurrentChar += (*(BotCurrentChar+1) == 'o') ? 8 : 2;				bytes[pointer++] = BOT_BYTE_C;			}			else			{				BotSyntaxError(1001);				sprintf(errormsg,"[%d] Unknown Command (c...)",codefield);				debugS(errormsg);				delete bytes;				return NULL;			}			break;		case 'd':			if(*(BotCurrentChar+1) == 'o'				&&*(BotCurrentChar+2) == 'w'				&&*(BotCurrentChar+3) == 'n')			{				// down				BotCurrentChar += 4;				bytes[pointer++] = BOT_BYTE_DOWN;			}			else			{				BotSyntaxError(1001);				sprintf(errormsg,"[%d] Unknown Command (d...)",codefield);				debugS(errormsg);				delete bytes;				return NULL;			}			break;		case 'e':			if(*(BotCurrentChar+1) == 'c'				&&*(BotCurrentChar+2) == 'h'				&&*(BotCurrentChar+3) == 'o')			{				BotCurrentChar += 4;				bytes[pointer++] = BOT_BYTE_ECHO;				break;			}			if(*(BotCurrentChar+1) == 'r'				&&*(BotCurrentChar+2) == 'r'				&&*(BotCurrentChar+3) == 'o'				&&*(BotCurrentChar+4) == 'r')			{				BotCurrentChar += 5;				bytes[pointer++] = BOT_BYTE_ERROR;				break;			}			else			{				BotSyntaxError(1001);				sprintf(errormsg,"[%d] Unknown Command (e...)",codefield);				debugS(errormsg);				delete bytes;				return NULL;			}		case 'f':			if(*(BotCurrentChar+1) == 'r'				&& *(BotCurrentChar+2) == 'a'				&& *(BotCurrentChar+3) == 'm'				&& *(BotCurrentChar+4) == 'e')			{				// frame				BotCurrentChar += 5;				bytes[pointer++] = BOT_BYTE_FRAME;			}			else			{				BotSyntaxError(1001);				sprintf(errormsg,"[%d] Unknown Command (f...)",codefield);				debugS(errormsg);				delete bytes;				return NULL;			}			break;		case 'i':			if(*(BotCurrentChar+1) == 'n'				&&*(BotCurrentChar+2) == 'v'				&&*(BotCurrentChar+3) == 'a'				&&*(BotCurrentChar+4) == 'l'				&&*(BotCurrentChar+5) == 'i'				&&*(BotCurrentChar+6) == 'd'				&&*(BotCurrentChar+7) == 's')			{				// invalids				BotCurrentChar += 8;				bytes[pointer++] = BOT_BYTE_INVALIDS;			}			else			{				++BotCurrentChar;				bytes[pointer++] = BOT_BYTE_I;			}			break;		case 'j':			++BotCurrentChar;			bytes[pointer++] = BOT_BYTE_J;			break;		case 'k':			++BotCurrentChar;			bytes[pointer++] = BOT_BYTE_K;			break;		case 'l':			if((*(BotCurrentChar+1) == 'b') ||				(*(BotCurrentChar+1) == 'a'				&&*(BotCurrentChar+2) == 's'				&&*(BotCurrentChar+3) == 't'				&&*(BotCurrentChar+4) == 'b'				&&*(BotCurrentChar+5) == 'u'				&&*(BotCurrentChar+6) == 't'				&&*(BotCurrentChar+7) == 't'				&&*(BotCurrentChar+8) == 'o'				&&*(BotCurrentChar+9) == 'n'))			{				// lastbutton lb				BotCurrentChar += (*(BotCurrentChar+1) == 'b') ? 2 : 10;				bytes[pointer++] = BOT_BYTE_LAST;			}			else if(*(BotCurrentChar+1) == 'e'				&&*(BotCurrentChar+2) == 'f'				&&*(BotCurrentChar+3) == 't')			{				// left				BotCurrentChar += 4;				bytes[pointer++] = BOT_BYTE_LEFT;			}			else if(*(BotCurrentChar+1) == 'o'				&&*(BotCurrentChar+2) == 'o'				&&*(BotCurrentChar+3) == 'p')			{				// loop				// loop and iif share the same limiter ';'				// and since you cant desync nesting them anyways, its				// safe to use the colonstack to add the loops, because				// if a loop is added while inside a colon-semicolon				// statement, it needs to be closed before leaving this				// block anyways. (make sure the code checks for this!)				BotCurrentChar += 4;				bytes[pointer++] = BOT_BYTE_LOOP;				colonstack[++cpoint] = pointer++;			}			else			{				BotSyntaxError(1001);				sprintf(errormsg,"[%d] Unknown Command (l...)",codefield);				debugS(errormsg);				delete bytes;				return NULL;			}			break;		case 'm':			if(*(BotCurrentChar+1) == 'a'				&&*(BotCurrentChar+2) == 'x')			{				// max				BotCurrentChar += 3;				bytes[pointer++] = BOT_BYTE_MAX;			}			else if(*(BotCurrentChar+1) == 'e'				&&*(BotCurrentChar+2) == 'm'				&&*(BotCurrentChar+3) == '(')			{				// mem()				BotCurrentChar += 4;				bytes[pointer++] = BOT_BYTE_MEM;			}			else if(*(BotCurrentChar+1) == 'e'				&&*(BotCurrentChar+2) == 'm'				&&*(BotCurrentChar+3) == 'h'				&&*(BotCurrentChar+4) == '(')			{				// memh()				BotCurrentChar += 5;				bytes[pointer++] = BOT_BYTE_MEMH;			}			else if(*(BotCurrentChar+1) == 'e'				&&*(BotCurrentChar+2) == 'm'				&&*(BotCurrentChar+3) == 'l'				&&*(BotCurrentChar+4) == '(')			{				// meml()				BotCurrentChar += 5;				bytes[pointer++] = BOT_BYTE_MEML;			}			else if(*(BotCurrentChar+1) == 'e'				&&*(BotCurrentChar+2) == 'm'				&&*(BotCurrentChar+3) == 'w'				&&*(BotCurrentChar+4) == '(')			{				// memw()				BotCurrentChar += 5;				bytes[pointer++] = BOT_BYTE_MEMW;			}			else			{				BotSyntaxError(1001);				sprintf(errormsg,"[%d] Unknown Command (m...)",codefield);				debugS(errormsg);				delete bytes;				return NULL;			}			break;		case 'n':			if(*(BotCurrentChar+1) == 'e'				&&*(BotCurrentChar+2) == 'v'				&&*(BotCurrentChar+3) == 'e'				&&*(BotCurrentChar+4) == 'r'||				*(BotCurrentChar+1) == 'o')			{				// never no				BotCurrentChar += (*(BotCurrentChar+1) == 'e') ? 5 : 2;				bytes[pointer++] = BOT_BYTE_NEVER;			}			else			{				// this is a little sketchy, but the principle works.				++BotCurrentChar;				negmode = true;			}			break;		case 'o':			if(*(BotCurrentChar+1) == 'k'				&&*(BotCurrentChar+2) == 's')			{				// oks				BotCurrentChar += 3;				bytes[pointer++] = BOT_BYTE_OKS;			}			else			{				BotSyntaxError(11001);				sprintf(errormsg,"[%d] Unknown Command (o...)",codefield);				debugS(errormsg);				delete bytes;				return NULL;			}			break;		case 'r':			if(*(BotCurrentChar+1) == 'i'				&&*(BotCurrentChar+2) == 'g'				&&*(BotCurrentChar+3) == 'h'				&&*(BotCurrentChar+4) == 't')			{				// right				BotCurrentChar += 5;				bytes[pointer++] = BOT_BYTE_RIGHT;			}			else if((*(BotCurrentChar+1) == 'e'				&&*(BotCurrentChar+2) == 's'				&&*(BotCurrentChar+3) == 'e'				&&*(BotCurrentChar+4) == 't'				&&*(BotCurrentChar+5) == 'c'				&&*(BotCurrentChar+6) == 'o'				&&*(BotCurrentChar+7) == 'u'				&&*(BotCurrentChar+8) == 'n'				&&*(BotCurrentChar+9) == 't'				&&*(BotCurrentChar+10) == 'e'				&&*(BotCurrentChar+11) == 'r'				&&*(BotCurrentChar+12) == '('				)||(				*(BotCurrentChar+1) == 'c'				&&*(BotCurrentChar+2) == '('))			{				// resetcounter() rc()				BotCurrentChar += (*(BotCurrentChar+1) == 'e') ? 13 : 3;				bytes[pointer++] = BOT_BYTE_RC;			}			else			{				BotSyntaxError(1001);				sprintf(errormsg,"[%d] Unknown Command (r...)",codefield);				debugS(errormsg);				delete bytes;				return NULL;			}			break;		case 's':			if(*(BotCurrentChar+1) == 't'				&&*(BotCurrentChar+2) == 'a'				&&*(BotCurrentChar+3) == 'r'				&&*(BotCurrentChar+4) == 't')			{				// start				BotCurrentChar += 5;				bytes[pointer++] = BOT_BYTE_START;			}			else if(*(BotCurrentChar+1) == 'c'				&&*(BotCurrentChar+2) == 'o'				&&*(BotCurrentChar+3) == 'r'				&&*(BotCurrentChar+4) == 'e'				&&(*(BotCurrentChar+5) == '1' || 				*(BotCurrentChar+5) == '2' || 				*(BotCurrentChar+5) == '3' || 				*(BotCurrentChar+5) == '4' || 				*(BotCurrentChar+5) == '5' ||				*(BotCurrentChar+5) == '6'))			{				// score 1-6				// returns the current max tie 1-6				switch ((int)*(BotCurrentChar+5)) {		case '1': bytes[pointer++] = BOT_BYTE_SCORE1; break;		case '2': bytes[pointer++] = BOT_BYTE_SCORE2; break;		case '3': bytes[pointer++] = BOT_BYTE_SCORE3; break;		case '4': bytes[pointer++] = BOT_BYTE_SCORE4; break;		case '5': bytes[pointer++] = BOT_BYTE_SCORE5; break;		case '6': bytes[pointer++] = BOT_BYTE_SCORE6; break;		default: 			sprintf(errormsg,"[%d] Serious error here",codefield);			debugS(errormsg);				}				BotCurrentChar += 6;			}			else if(*(BotCurrentChar+1) == 'e'				&&*(BotCurrentChar+2) == 'l'				&&*(BotCurrentChar+3) == 'e'				&&*(BotCurrentChar+4) == 'c'				&&*(BotCurrentChar+5) == 't')			{				// select				BotCurrentChar += 6;				bytes[pointer++] = BOT_BYTE_SELECT;			}			// why was there no short version for setcounter()? There is now... :)			else if ((*(BotCurrentChar+1) == 'c') ||				(*(BotCurrentChar+1) == 'e'				&&*(BotCurrentChar+2) == 't'				&&*(BotCurrentChar+3) == 'c'				&&*(BotCurrentChar+4) == 'o'				&&*(BotCurrentChar+5) == 'u'				&&*(BotCurrentChar+6) == 'n'				&&*(BotCurrentChar+7) == 't'				&&*(BotCurrentChar+8) == 'e'				&&*(BotCurrentChar+9) == 'r'				&&*(BotCurrentChar+10) == '('))			{				// setcounter() sc()				BotCurrentChar += (*(BotCurrentChar+1) == 'c') ? 3 : 11;				bytes[pointer++] = BOT_BYTE_SC;			}			// qfox: Added stop command. Should do exactly the same as pressing the "stop" button.\			//	 But probably won't yet :)			else if(*(BotCurrentChar+1) == 't'				&&*(BotCurrentChar+2) == 'o'				&&*(BotCurrentChar+3) == 'p')			{				// stop				BotCurrentChar += 4;				bytes[pointer++] = BOT_BYTE_STOP;			}			else			{				BotSyntaxError(10001);				sprintf(errormsg,"[%d] Unknown Command (s...)",codefield);				debugS(errormsg);				delete bytes;				return NULL;			}			break;		case 'u':			if(*(BotCurrentChar+1) == 'p')			{				// up				BotCurrentChar += 2;				bytes[pointer++] = BOT_BYTE_UP;			}			else			{				BotSyntaxError(11001);				sprintf(errormsg,"[%d] Unknown Command (u...)",codefield);				debugS(errormsg);				delete bytes;				return NULL;			}			break;		case 'v':			if(*(BotCurrentChar+1) == 'a'				&&*(BotCurrentChar+2) == 'l'				&&*(BotCurrentChar+3) == 'u'				&&*(BotCurrentChar+4) == 'e')			{				// value				// "value" is completely transparent, more like a nop (or no-operation).				//	could be used in a iif where there is no else, or to make it more				//	clear how value is used internally...				BotCurrentChar += 5;			}			else			{				BotSyntaxError(1001);				sprintf(errormsg,"[%d] Unknown Command (v...)",codefield);				debugS(errormsg);				delete bytes;				return NULL;			}			break;		case 'y':			if(*(BotCurrentChar+1) == 'e'				&&*(BotCurrentChar+2) == 's')			{				// yes				BotCurrentChar += 3;				bytes[pointer++] = BOT_BYTE_MAX;			}			else			{				BotSyntaxError(1001);				sprintf(errormsg,"[%d] Unknown Command (y...)",codefield);				debugS(errormsg);				delete bytes;				return NULL;			}			break;		case '0':		case '1':		case '2':		case '3':		case '4':		case '5':		case '6':		case '7':		case '8':		case '9':			// Not quite sure how the original literals worked, but it doesn't work in my 			//	 implementation so I had to rewrite it. When a digit is encountered it will			//	 start reading character (starting at the first). "value" is multiplied by 10			//	 and the next digit is added to it. When a non-digit char is encountered, the			//	 code stops parsing this number and behaves like everywhere else. (returning			//   it if ret is true, breaking else).			//	 If hexmode, this is done below, taking note of the additional "numbers".			if (!hexmode) 			{				// keep on reading input until no more numbers are encountered (0-9)				int ahead = 0;				int value = 0;				while (*(BotCurrentChar+ahead) >= '0' && *(BotCurrentChar+ahead) <= '9') {					if (negmode) value = (value*10)-(*(BotCurrentChar+ahead) - '0');					else value = (value*10)+(*(BotCurrentChar+ahead) - '0');					++ahead;				}				// I don't think ahead needs to be incremented before adding it to				//	 currentchar, because the while increments it for _every_ character.				BotCurrentChar += ahead;				bytes[pointer++] = BOT_BYTE_LIT;				bytes[pointer++] = value;				negmode = false;				break;			}		case 'A':		case 'B':		case 'C':		case 'D':		case 'E':		case 'F':			// Hexmode does things a liiiitle differently. We need to multiply each number 			//	 by 16 instead of 10, and if the character is ABCDEF we need to subtract 'A'			//	 and add 10, instead of just subtracting '0'. Otherwise same principle.			if(hexmode)			{				// Keep on reading input until no more numbers are encountered (0-9)				int ahead = 0;				int value = 0;				// number-size check (int is max) -> do it when converting to bytecode				while ((*(BotCurrentChar+ahead) >= '0' && *(BotCurrentChar+ahead) <= '9')					|| (*(BotCurrentChar+ahead) >= 'A' && *(BotCurrentChar+ahead) <= 'F')) {						// next code is a little redundant, but it's either redundant or even harder to read.						if (*(BotCurrentChar+ahead) >= '0' && *(BotCurrentChar+ahead) <= '9')							if (negmode) value = (value*16)-(*(BotCurrentChar+ahead) - '0');							else value = (value*16)+(*(BotCurrentChar+ahead) - '0');						else							if (negmode) value = (value*16)-((*(BotCurrentChar+ahead) - 'A')+10);							else value = (value*16)+((*(BotCurrentChar+ahead) - 'A')+10);							++ahead;				}				BotCurrentChar += ahead;				bytes[pointer++] = BOT_BYTE_LIT;				bytes[pointer++] = value;				negmode = false;				hexmode = false;			}			else			{				// If not in hexmode, we cant use these characters.				BotSyntaxError(1003);				sprintf(errormsg,"[%d] Not in hexmode!",codefield);				debugS(errormsg);				delete bytes;				return NULL;			}			break;		case 'P':			++BotCurrentChar;			bytes[pointer++] = BOT_BYTE_P;			break;		case 'Q':			++BotCurrentChar;			bytes[pointer++] = BOT_BYTE_Q;			break;		case 'X':			++BotCurrentChar;			bytes[pointer++] = BOT_BYTE_X;			break;		case 'Y':			++BotCurrentChar;			bytes[pointer++] = BOT_BYTE_Y;			break;		case 'Z':			++BotCurrentChar;			bytes[pointer++] = BOT_BYTE_Z;			break;		default:			// Unknown characters should error out. You can use spaces.			BotSyntaxError(12001);			sprintf(errormsg,"[%d][%d] Unknown character... '%c'",codefield,BotCurrentChar-pointerStart,(*BotCurrentChar));			debugS(errormsg);			delete bytes;			return NULL;		}	}	return bytes;}/*** The bytecode interpreter*/static int Interpreter(bool single){	int value = 0;	int nextlit;	while (Bytecode[BotByteCodeField][BotCurrentCode] != 0)	{		switch (Bytecode[BotByteCodeField][BotCurrentCode++])		{		case 0:			break;		case BOT_BYTE_LB:			value = Interpreter(false);			if (single) return value;			break;		case BOT_BYTE_RB:			return value;		case BOT_BYTE_LIT:			value = Bytecode[BotByteCodeField][BotCurrentCode++];			if (single) return value;			break;		case BOT_BYTE_ADD:			value += Interpreter(true);			if (single) return value;			break;		case BOT_BYTE_SUB:			value -= Interpreter(true);			if (single) return value;			break;		case BOT_BYTE_MUL:			value *= Interpreter(true);			if (single) return value;			break;		case BOT_BYTE_DIV:			{				// we need to set up a zero-division-exception-trap here				int zerotrap = Interpreter(true);				if (value == 0 || zerotrap == 0)					value = 0;				else					value /= zerotrap;				if (single) return value;				break;			}		case BOT_BYTE_MOD:			{				// we need to set up a zero-division-exception-trap here				int zerotrap = Interpreter(true);				if (value == 0 || zerotrap == 0)					value = 0;				else					value %= zerotrap;				if (single) return value;				break;			}		case BOT_BYTE_AND:			value &= Interpreter(true);			if (single) return value;			break;		case BOT_BYTE_OR:			value |= Interpreter(true);			if (single) return value;			break;		case BOT_BYTE_XOR:			value ^= Interpreter(true);			if (single) return value;			break;		case BOT_BYTE_EQ:			value = ((value == Interpreter(true)) ? BOT_MAX_PROB : 0);			if (single) return value;			break;		case BOT_BYTE_GTEQ:			value = ((value >= Interpreter(true)) ? BOT_MAX_PROB : 0);			if (single) return value;			break;		case BOT_BYTE_GT:			value = ((value > Interpreter(true)) ? BOT_MAX_PROB : 0);			if (single) return value;			break;		case BOT_BYTE_LTEQ:			value = ((value <= Interpreter(true)) ? BOT_MAX_PROB : 0);			if (single) return value;			break;		case BOT_BYTE_LT:			value = ((value < Interpreter(true)) ? BOT_MAX_PROB : 0);			if (single) return value;			break;		case BOT_BYTE_UEQ:			value = ((value != Interpreter(true)) ? BOT_MAX_PROB : 0);			if (single) return value;			break;		case BOT_BYTE_IIF:			if (value == 0)				BotCurrentCode += Bytecode[BotByteCodeField][BotCurrentCode];			else				BotCurrentCode += 1;			value = Interpreter(false);			break;		case BOT_BYTE_COLON:			// move the pointer beyond the "else" part			BotCurrentCode += Bytecode[BotByteCodeField][BotCurrentCode];			return value;		case BOT_BYTE_SCOLON:			// limiter for iif and loop			return value;		case BOT_BYTE_ATTEMPT:			value = BotAttempt;			if (single) return value;			break;		case BOT_BYTE_AC:			value = (BotCounter[(Interpreter(false) & 0x7FFFFFFF) % 256] += value);			if (single) return value;			break;		case BOT_BYTE_ABS:			value = Interpreter(false);			if (value < 0) 				value = (0 - value);			if (single) return value;			break;		case BOT_BYTE_BUTTON:			if (value == 0) value = BotInput[1];			else value &= BotInput[1];			if (single) return value;			break;		case BOT_BYTE_C:			value = BotCounter[(Interpreter(false) & 0x7FFFFFFF) % 256];			if (single) return value;			break;		case BOT_BYTE_DOWN:			value = 32;			if (single) return value;			break;		case BOT_BYTE_ECHO:			debug(value);			break;		case BOT_BYTE_ERROR:			error(value);			break;		case BOT_BYTE_FRAME:			value = BotFrame;			if (single) return value;			break;		case BOT_BYTE_I:			value = BotLoopVarI;			if (single) return value;			break;		case BOT_BYTE_INVALIDS:			value = BotInvalids;			if (single) return value;			break;		case BOT_BYTE_J:			value = BotLoopVarJ;			if (single) return value;			break;		case BOT_BYTE_K:			value = BotLoopVarK;			if (single) return value;			break;		case BOT_BYTE_LAST:			value = BotLastbutton;			if (single) return value;			break;		case BOT_BYTE_LEFT:			value = 64;			if (single) return value;			break;		case BOT_BYTE_LOOP:			if (value != 0)			{				int tel = value;				// increase the position of the codepointer first				// then back it up				// at the end of the loop, go back one to get the				// position where the code continues (after loop)				int pos = ++BotCurrentCode;				if (BotLoopVarI == 0)				{					for (; BotLoopVarI < tel; ++BotLoopVarI)					{						Interpreter(false);						BotCurrentCode = pos;					}					BotLoopVarI = 0;				}				else if (BotLoopVarJ == 0)				{					for (; BotLoopVarJ < tel; ++BotLoopVarJ)					{						Interpreter(false);						BotCurrentCode = pos;					}					BotLoopVarJ = 0;				}				else if (BotLoopVarK == 0)				{					for (; BotLoopVarK < tel; ++BotLoopVarK)					{						Interpreter(false);						BotCurrentCode = pos;					}					BotLoopVarK = 0;				}				else				{					// well... this should never happen, if the encoder					// checks for a max loop depth of 3...					MessageBoxA(hwndTASbot, "wtf1", "oopsie", MB_OK);				}				// go back one and fetch the position of where to continue				BotCurrentCode += Bytecode[BotByteCodeField][BotCurrentCode-1]-1;			}			else 			{				BotCurrentCode += Bytecode[BotByteCodeField][BotCurrentCode];			}			if (single) return value;			break;		case BOT_BYTE_LSHIFT:			value <<= Interpreter(true);			if (single) return value;			break;		case BOT_BYTE_MAX:			value = BOT_MAX_PROB;			if (single) return value;			break;		case BOT_BYTE_MEM:			nextlit = (Interpreter(false) & 0x7FFFFFFF) % 65536;			value = ARead[nextlit](nextlit);			if (single) return value;			break;		case BOT_BYTE_MEMH:			nextlit = (Interpreter(false) & 0x7FFFFFFF) % 65536;			value = (ARead[nextlit](nextlit) & 0xF0) >> 8;			if (single) return value;			break;		case BOT_BYTE_MEML:			nextlit = (Interpreter(false) & 0x7FFFFFFF) % 65536;			value = ARead[nextlit](nextlit) & 0x0F;			if (single) return value;			break;		case BOT_BYTE_MEMW:			{				int nextlit = Interpreter(false);				int v1 = (nextlit & 0x7FFFFFFF) % 65536;				int v2 = ((nextlit+1) & 0x7FFFFFFF) % 65536;				v1 = ARead[v1](v1);				v2 = ARead[v2](v2);				value = (v1<<8)+v2;				if (single) return value;				break;			}		case BOT_BYTE_NEVER:			value = 0;			if (single) return value;			break;		case BOT_BYTE_OKS:			value = BotOks;			if (single) return value;			break;		case BOT_BYTE_RC:			value = (BotCounter[(Interpreter(false) & 0x7FFFFFFF) % 256] = 0);			if (single) return 0;			break;		case BOT_BYTE_RIGHT:			value = 128;			if (single) return value;			break;		case BOT_BYTE_RSHIFT:			value >>= Interpreter(true);			if (single) return value;			break;		case BOT_BYTE_START:			value = 8;			if (single) return value;			break;		case BOT_BYTE_SELECT:			value = 4;			if (single) return value;			break;		case BOT_BYTE_SC:			BotCounter[(Interpreter(false) & 0x7FFFFFFF) % 256] = value;			if (single) return value;			break;		case BOT_BYTE_SCORE1:			value = BotBestScore[0];			if (single) return value;			break;		case BOT_BYTE_SCORE2:			value = BotBestScore[1];			if (single) return value;			break;		case BOT_BYTE_SCORE3:			value = BotBestScore[2];			if (single) return value;			break;		case BOT_BYTE_SCORE4:			value = BotBestScore[3];			if (single) return value;			break;		case BOT_BYTE_SCORE5:			value = BotBestScore[4];			if (single) return value;			break;		case BOT_BYTE_SCORE6:			value = BotBestScore[5];			if (single) return value;			break;		case BOT_BYTE_STOP:			// stops the code			Bot_Eval_error = true;			MessageBox(hwndTASbot, "Stopped by code!", "Stop signal", MB_OK);			StopBasicBot();			return 0;		case BOT_BYTE_UP:			value = 16;			if (single) return value;			break;		case BOT_BYTE_P:			value = Bot_Prand;			if (single) return value;			break;		case BOT_BYTE_Q:			value = Bot_Qrand;			if (single) return value;			break;		case BOT_BYTE_X:			value = Bot_X;			if (single) return value;			break;		case BOT_BYTE_Y:			value = Bot_Y;			if (single) return value;			break;		case BOT_BYTE_Z:			value = Bot_Z;			if (single) return value;			break;		default:			break;		}	}	return value;}/*** Front end for the interpreter*/static int evaluate(int codefield){	BotCurrentCode = 0;	BotByteCodeField = codefield;	return Interpreter(false);}/*** Get a string showing the first x chars of the bytecode*/static char * DebugByteCode(int code[]){	static int len = intlen(code);	char result[len*3];	// for the love of god, why cant c++ just init this space :/	memset(result, 0, len*3);	for (int i=0; i<len; ++i)		sprintf(result,"%s %d",result,code[i]);	return result; //SetDlgItemTextA(hwndTASbot,GUI_BOT_KEYS,result);}/*** set a textfield to something**/void toField(int field, char * text){	SetDlgItem(hwndTASbot,field,text,TRUE);}/*** get text from field**/char * fromField(int field){	unsigned int count = FieldLength(hwndTASbot,field);	char *t = new char[count+1];	GetDlgItemTextA(hwndTASbot,field,t,count+1);	return t;}/*** put all the texts in memory to gui**/void toGUI(){	for (int i=0; i<BOT_FORMULAS; ++i)	{		toField(labels[i],Formula[i]);	}	debugS("Updated GUI");}/*** get all the texts from gui**/void fromGUI(){	for (int i=0; i<BOT_FORMULAS; ++i)	{		Formula[i] = fromField(labels[i]);		if (i < CODE_COMMENT_MARKER)		{			Bytecode[i] = convert(Formula[i],i);		}	}}/*** Called from windows. main gui (=dialog) control.**/static BOOL CALLBACK TASBotCallBack (HWND hwndDlg, UINT uMsg, WPARAM wParam, LPARAM lParam) {	DSMFix(uMsg); // stops sound on 5 of the messages...	switch(uMsg)	{	case WM_INITDIALOG:		// cant change gui controls in this event		// seems to be a inherited "feature", for backwards		// compatibility.		break;	case WM_CLOSE:	case WM_QUIT:		DestroyWindow(hwndTASbot);		hwndTASbot = 0;		break;	case WM_COMMAND:		switch(HIWORD(wParam))		{		case BN_CLICKED:			switch (LOWORD(wParam))			{			case BOT_GUI_TEST:				mboxI(bot_rand(5));				break;			default:				break;			}		}		break; // WM_COMMAND	default:		break;	}	return 0;}void CreateWindow(){	// create window	CreateDialog(fceu_hInstance,"TASBOT",NULL,TASBotCallBack);	// randomize randomizer	srand(time(0));}