fceux/drivers/win/basicbot.cpp

933 lines
22 KiB
C++

/* FCE Ultra - NES/Famicom Emulator
*
* Copyright notice for this file:
* Copyright (C) 2006 Luke Gustafson
*
* This program is free software; you can redistribute it and/or modify
* it under the terms of the GNU General Public License as published by
* the Free Software Foundation; either version 2 of the License, or
* (at your option) any later version.
*
* This program is distributed in the hope that it will be useful,
* but WITHOUT ANY WARRANTY; without even the implied warranty of
* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
* GNU General Public License for more details.
*
* You should have received a copy of the GNU General Public License
* along with this program; if not, write to the Free Software
* Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA
*/
#include "common.h"
#include "../../fceu.h" //mbg merge 7/18/06 added
#include "basicbot.h"
static HWND hwndBasicBot=0;
static int BotRunning = 0;
static uint32 rand1=1, rand2=0x1337EA75, rand3=0x0BADF00D;
static char Formula[24][1024];
static int BotCounter[256];
static int EditPlayer = 1, BotFrame, BotLoopVar = 0;
static int BotAttempts, BotFrames, BotBestScore[4], NewAttempt;
static int CurrentAttempt[1024], BestAttempt[1024], AttemptPointer;
static int DoAddCounter = 1;
char *BasicBotDir = 0;
static void SeedRandom(uint32 seed)
{
rand1 = seed;
if(rand1 == 0) rand1 = 1; //I forget if this is necessary.
}
//Simulation-quality random numbers: taus88 algorithm
static unsigned int NextRandom(void)
{
uint32 b;
b = (((rand1 << 13) ^ rand1) >> 19);
rand1 = (((rand1 & 4294967294U) << 12) ^ b);
b = (((rand2 << 2) ^ rand2) >> 25);
rand2 = (((rand2 & 4294967288U) << 4) ^ b);
b = (((rand3 << 3) ^ rand3) >> 11);
rand3 = (((rand3 & 4294967280U) << 17) ^ b);
return (rand1 ^ rand2 ^ rand3);
}
//Should do something to notify user of an error... eh
//void BotError()
//{
//
//}
//recursively evaluate the formula
//horribly hacky, not meant to be a real expression evaluator!
int EvaluateFormula(char * formula, char **nextposition)
{
char *currentchar = formula;
int value=0;
int hexmode = 0;
while(1)
{
switch(*currentchar)
{
case 0:
*nextposition = currentchar;
return value;
case '(':
value = EvaluateFormula(currentchar + 1, &currentchar);
break;
case ')':
case ':':
*nextposition = currentchar + 1;
return value;
case 'x':
hexmode=1;
currentchar++;
break;
case '+':
return (value + EvaluateFormula(currentchar+1, nextposition));
case '-':
return (value - EvaluateFormula(currentchar+1, nextposition));
case '*':
return (value * EvaluateFormula(currentchar+1, nextposition));
case '/':
return (value / EvaluateFormula(currentchar+1, nextposition));
case '%':
return (value % EvaluateFormula(currentchar+1, nextposition));
case '&':
return (value & EvaluateFormula(currentchar+1, nextposition));
case '|':
return (value | EvaluateFormula(currentchar+1, nextposition));
case '^':
return (value ^ EvaluateFormula(currentchar+1, nextposition));
case '=':
return (value == EvaluateFormula(currentchar+1, nextposition) ? 1000: 0);
case '>':
if(*(currentchar + 1) == '=')
return (value >= EvaluateFormula(currentchar+2, nextposition) ? 1000: 0);
else
return (value > EvaluateFormula(currentchar+1, nextposition) ? 1000: 0);
case '<':
if(*(currentchar + 1) == '=')
return (value <= EvaluateFormula(currentchar+2, nextposition) ? 1000: 0);
else
return (value < EvaluateFormula(currentchar+1, nextposition) ? 1000: 0);
case '!':
if(*(currentchar + 1) == '=')
{
return (value != EvaluateFormula(currentchar+2, nextposition) ? 1000: 0);
}
else
{
//BotError();
currentchar++;
}
case '?':
{
int temp,temp2=DoAddCounter;
if(value)
{
temp = EvaluateFormula(currentchar+1,&currentchar);
DoAddCounter = 0;
EvaluateFormula(currentchar,&currentchar);
DoAddCounter = temp2;
value= temp;
}
else
{
DoAddCounter = 0;
EvaluateFormula(currentchar+1,&currentchar);
DoAddCounter = temp2;
temp = EvaluateFormula(currentchar,&currentchar);
value= temp;
}
}
case ' ':
currentchar++;
break;
case 'a':
if(*(currentchar+1) == 't'
&&*(currentchar+2) == 't'
&&*(currentchar+3) == 'e'
&&*(currentchar+4) == 'm'
&&*(currentchar+5) == 'p'
&&*(currentchar+6) == 't')
{
currentchar+=7;
value = BotAttempts;
}
else if(*(currentchar+1) == 'd'
&&*(currentchar+2) == 'd'
&&*(currentchar+3) == 'c'
&&*(currentchar+4) == 'o'
&&*(currentchar+5) == 'u'
&&*(currentchar+6) == 'n'
&&*(currentchar+7) == 't'
&&*(currentchar+8) == 'e'
&&*(currentchar+9) == 'r'
&&*(currentchar+10)== '(')
{
currentchar += 11;
if(DoAddCounter)
{
value = (BotCounter[(EvaluateFormula(currentchar, &currentchar) & 0x7FFFFFFF) % 256] += value);
}
}
else if(*(currentchar+1) == 'b'
&&*(currentchar+2) == 's'
&&*(currentchar+3) == '(')
{
currentchar += 4;
value = EvaluateFormula(currentchar, &currentchar);
if(value < 0) value = -value;
}
else if(*(currentchar+1) == 'c'
&&*(currentchar+2) == '(')
{
currentchar += 3;
if(DoAddCounter)
{
value = (BotCounter[(EvaluateFormula(currentchar, &currentchar) & 0x7FFFFFFF) % 256] += value);
}
}
else
{
value = 1;
currentchar++;
}
break;
case 'b':
if(*(currentchar+1) == 'u'
&&*(currentchar+2) == 't'
&&*(currentchar+3) == 't'
&&*(currentchar+4) == 'o'
&&*(currentchar+5) == 'n')
{
currentchar += 6;
value &= BotInput[1];
}
else
{
value = 2;
currentchar++;
}
break;
case 'c':
if(*(currentchar+1) == 'o'
&& *(currentchar+2) == 'u'
&& *(currentchar+3) == 'n'
&& *(currentchar+4) == 't'
&& *(currentchar+5) == 'e'
&& *(currentchar+6) == 'r'
&& *(currentchar+7) == '(')
{
currentchar += 8;
value = BotCounter[(EvaluateFormula(currentchar, &currentchar) & 0x7FFFFFFF) % 256];
}
else if(*(currentchar+1) == '(')
{
currentchar += 2;
value = BotCounter[(EvaluateFormula(currentchar, &currentchar) & 0x7FFFFFFF) % 256];
}
else
{
//BotError();
currentchar++;
}
break;
case 'd':
if(*(currentchar+1) == 'o'
&&*(currentchar+2) == 'w'
&&*(currentchar+3) == 'n')
{
currentchar += 4;
value = 32;
}
else
{
currentchar++;
}
break;
case 'f':
if(*(currentchar+1) == 'r'
&& *(currentchar+2) == 'a'
&& *(currentchar+3) == 'm'
&& *(currentchar+4) == 'e')
{
currentchar+= 5;
value = BotFrame;
}
else
{
//BotError();
currentchar++;
}
break;
case 'i':
value = BotLoopVar;
currentchar++;
break;
case 'l':
if(*(currentchar+1) == 'e'
&&*(currentchar+2) == 'f'
&&*(currentchar+3) == 't')
{
currentchar += 4;
value = 64;
}
else if(*(currentchar+1) == 'o'
&&*(currentchar+2) == 'o'
&&*(currentchar+3) == 'p'
&&*(currentchar+4) == '(')
{
if(value > 0)
{
currentchar += 5;
if(BotLoopVar == 0)
{
for(BotLoopVar = 1; BotLoopVar < value && BotLoopVar < 65536; BotLoopVar++)
{
EvaluateFormula(currentchar, nextposition);
}
BotLoopVar = 0;
EvaluateFormula(currentchar, &currentchar);
}
else
{
//BotError();
}
}
else
{
int temp = DoAddCounter;
currentchar += 5;
DoAddCounter = 0;
EvaluateFormula(currentchar, &currentchar);
DoAddCounter = temp;
}
}
else
{
currentchar++;
}
break;
case 'm':
if(*(currentchar+1) == 'e'
&&*(currentchar+2) == 'm'
&&*(currentchar+3) == '(')
{
currentchar += 4;
int temp = (EvaluateFormula(currentchar, &currentchar) & 0x7FFFFFFF) % 65536;
value = ARead[temp](temp);
}
else
{
currentchar++;
}
break;
case 'r':
if(*(currentchar+1) == 'a'
&&*(currentchar+2) == 'm'
&&*(currentchar+3) == '(')
{
currentchar += 4;
value = RAM[(EvaluateFormula(currentchar, &currentchar) & 0x7FFFFFFF) % 2048];
}
else if(*(currentchar+1) == 'i'
&&*(currentchar+2) == 'g'
&&*(currentchar+3) == 'h'
&&*(currentchar+4) == 't')
{
currentchar += 5;
value = 128;
}
else if(*(currentchar+1) == 'e'
&&*(currentchar+2) == 's'
&&*(currentchar+3) == 'e'
&&*(currentchar+4) == 't'
&&*(currentchar+5) == 'c'
&&*(currentchar+6) == 'o'
&&*(currentchar+7) == 'u'
&&*(currentchar+8) == 'n'
&&*(currentchar+9) == 't'
&&*(currentchar+10) == 'e'
&&*(currentchar+11) == 'r'
&&*(currentchar+12) == '(')
{
currentchar += 13;
if(DoAddCounter) BotCounter[(EvaluateFormula(currentchar, &currentchar) & 0x7FFFFFFF) % 256] = 0;
value = 0;
}
else if(*(currentchar+1) == 'c'
&&*(currentchar+2) == '(')
{
currentchar += 3;
if(DoAddCounter) BotCounter[(EvaluateFormula(currentchar, &currentchar) & 0x7FFFFFFF) % 256] = 0;
value = 0;
}
else
{
currentchar++;
}
break;
case 's':
if(*(currentchar+1) == 't'
&&*(currentchar+2) == 'a'
&&*(currentchar+3) == 'r'
&&*(currentchar+4) == 't')
{
currentchar += 5;
value = 8;
}
else if(*(currentchar+1) == 'e'
&&*(currentchar+2) == 'l'
&&*(currentchar+3) == 'e'
&&*(currentchar+4) == 'c'
&&*(currentchar+5) == 't')
{
currentchar += 6;
value = 4;
}
else if(*(currentchar+1) == 'e'
&&*(currentchar+2) == 't'
&&*(currentchar+3) == 'c'
&&*(currentchar+4) == 'o'
&&*(currentchar+5) == 'u'
&&*(currentchar+6) == 'n'
&&*(currentchar+7) == 't'
&&*(currentchar+8) == 'e'
&&*(currentchar+9) == 'r'
&&*(currentchar+10) == '(')
{
currentchar += 11;
if(DoAddCounter) BotCounter[(EvaluateFormula(currentchar, &currentchar) & 0x7FFFFFFF) % 256] = value;
}
else
{
currentchar++;
}
break;
case 'u':
if(*(currentchar+1) == 'p')
{
currentchar += 2;
value = 16;
}
else
{
currentchar++;
}
break;
case '0':
case '1':
case '2':
case '3':
case '4':
case '5':
case '6':
case '7':
case '8':
case '9':
value *= hexmode?16:10;
value += *currentchar - '0';
currentchar++;
break;
case 'A':
case 'B':
case 'C':
case 'D':
case 'E':
case 'F':
if(hexmode)
{
value *= 16;
value += *currentchar - 'A' + 10;
}
else
{
// BotError();
}
currentchar++;
break;
default:
currentchar++;
break;
}
}
return 0;
}
//Update BasicBot input
void UpdateBasicBot()
{
if(hwndBasicBot && BotRunning)
{
int i,j,k;
char *dummy = "dum";
if(BotInput[0])
return;
//Create the bot output...
BotInput[0] = 1;
if(NewAttempt)
{
BotInput[1] = 65536;
NewAttempt = 0;
AttemptPointer = 0;
BotFrame = 0;
memset(BotCounter, 0, 1024);
}
else
{
//Check if goal is met
if(BotFrame > 1020 || (int) (NextRandom() % 1000) < EvaluateFormula(Formula[20], &dummy))
{
int currentscore[4];
int better = 0;
NewAttempt = 1;
//Check if better score
for(i=0; i < 4; i++)
{
currentscore[i] = EvaluateFormula(Formula[16+i], &dummy);
}
for(i=0; i < 4; i++)
{
if(currentscore[i] > BotBestScore[i])
{
better = 1;
break;
}
else if(currentscore[i] < BotBestScore[i])
{
break;
}
}
//Update best
if(better)
{
char tempstring[4096];
char symbols[] = "ABET^v<>ABET^v<>"; //mbg merge 7/18/06 changed dim to unspecified to leave room for the null
int seenplayer2=0;
for(i = 0; i < 4; i++)
{
BotBestScore[i] = currentscore[i];
}
for(i = 0; i < AttemptPointer; i++)
{
BestAttempt[i] = CurrentAttempt[i];
}
for(; i < 1024; i++)
{
BestAttempt[i] = -1;
}
sprintf(tempstring, "%d %d %d %d (%d attempt)", BotBestScore[0], BotBestScore[1], BotBestScore[2], BotBestScore[3], BotAttempts);
SetDlgItemText(hwndBasicBot,1018,tempstring);
memset(tempstring, 0, 4096);
k = 0;
//Make output as text
for(i = 0; i < 1024 && BestAttempt[i] != -1 && k < 4095; i++)
{
tempstring[k] = '0' + ((i/10) % 10);
k++;
tempstring[k] = '0' + (i%10);
k++;
tempstring[k] = '.';
k++;
seenplayer2=0;
for(j = 0; j < 16; j++)
{
if(BestAttempt[i] & (1 << j))
{
if(j >= 8 && seenplayer2==0)
{
seenplayer2=1;
tempstring[k]=',';
k++;
}
tempstring[k] = symbols[j];
k++;
}
}
tempstring[k] = ' ';
k++;
}
SetDlgItemText(hwndBasicBot,1019,tempstring);
}
}
else //Goal not met
{
//Generate 1 frame of output
BotInput[1] = 0;
for(i=0;i<16;i++)
{
if((int) (NextRandom() % 1000) < EvaluateFormula(Formula[i], &dummy))
{
BotInput[1] |= 1 << i;
}
}
//Save what we've done
if(AttemptPointer < 1024)
{
CurrentAttempt[AttemptPointer] = BotInput[1];
AttemptPointer++;
}
//Run extra commands
EvaluateFormula(Formula[21],&dummy);
EvaluateFormula(Formula[22],&dummy);
}
}
//Update statistics
if(BotInput[1] == 65536)
{
BotAttempts++;
}
else
{
BotFrames++;
BotFrame++;
}
if(BotFrames % 100 == 0)
{
SetDlgItemInt(hwndBasicBot,1037,BotAttempts,FALSE);
SetDlgItemInt(hwndBasicBot,1017,BotFrames,FALSE);
}
}
}
static void SaveBasicBot()
{
const char filter[]="Basic Bot(*.bot)\0*.bot\0";
char nameo[2048];
OPENFILENAME ofn;
memset(&ofn,0,sizeof(ofn));
ofn.lStructSize=sizeof(ofn);
ofn.hInstance=fceu_hInstance;
ofn.lpstrTitle="Save Basic Bot As...";
ofn.lpstrFilter=filter;
nameo[0]=0;
ofn.lpstrFile=nameo;
ofn.nMaxFile=256;
ofn.Flags=OFN_EXPLORER|OFN_HIDEREADONLY|OFN_OVERWRITEPROMPT;
ofn.lpstrInitialDir=BasicBotDir;
if(GetSaveFileName(&ofn))
{
int i,j;
//Save the directory
if(ofn.nFileOffset < 1024)
{
free(BasicBotDir);
BasicBotDir=(char*)malloc(strlen(ofn.lpstrFile)+1); //mbg merge 7/18/06 added cast
strcpy(BasicBotDir,ofn.lpstrFile);
BasicBotDir[ofn.nFileOffset]=0;
}
//quick get length of nameo
for(i=0;i<2048;i++)
{
if(nameo[i] == 0)
{
break;
}
}
//add .bot if nameo doesn't have it
if((i < 4 || nameo[i-4] != '.') && i < 2040)
{
nameo[i] = '.';
nameo[i+1] = 'b';
nameo[i+2] = 'o';
nameo[i+3] = 't';
nameo[i+4] = 0;
}
FILE *fp=FCEUD_UTF8fopen(nameo,"wb");
fputc('b',fp);
fputc('o',fp);
fputc('t',fp);
fputc(0,fp);
for(i=0;i<23;i++)
{
for(j=0;j<1024;j++)
{
fputc(Formula[i][j],fp);
}
}
fclose(fp);
}
}
//Loads a previously saved file
static void LoadBasicBot()
{
const char filter[]="Basic Bot (*.bot)\0*.bot\0";
char nameo[2048];
OPENFILENAME ofn;
memset(&ofn,0,sizeof(ofn));
ofn.lStructSize=sizeof(ofn);
ofn.hInstance=fceu_hInstance;
ofn.lpstrTitle="Load Basic Bot...";
ofn.lpstrFilter=filter;
nameo[0]=0;
ofn.lpstrFile=nameo;
ofn.nMaxFile=256;
ofn.Flags=OFN_EXPLORER|OFN_FILEMUSTEXIST|OFN_HIDEREADONLY;
ofn.lpstrInitialDir=BasicBotDir;
if(GetOpenFileName(&ofn))
{
int i,j;
//Save the directory
if(ofn.nFileOffset < 1024)
{
free(BasicBotDir);
BasicBotDir=(char*)malloc(strlen(ofn.lpstrFile)+1); //mbg merge 7/18/06 added cast
strcpy(BasicBotDir,ofn.lpstrFile);
BasicBotDir[ofn.nFileOffset]=0;
}
FILE *fp=FCEUD_UTF8fopen(nameo,"rb");
if(fgetc(fp) != 'b'
|| fgetc(fp) != 'o'
|| fgetc(fp) != 't'
|| fgetc(fp) != 0)
{
fclose(fp);
return;
}
for(i=0;i<23;i++)
{
for(j=0;j<1024;j++)
{
Formula[i][j] = fgetc(fp);
if(Formula[i][j] & 128)
{
Formula[i][j] = 0;
}
}
}
fclose(fp);
}
}
static BOOL CALLBACK BasicBotCallB(HWND hwndDlg, UINT uMsg, WPARAM wParam, LPARAM lParam)
{
int i;
DSMFix(uMsg);
switch(uMsg)
{
case WM_INITDIALOG:
break;
case WM_CLOSE:
case WM_QUIT:
for(i = 0; i < 8; i++)
{
GetDlgItemText(hwndBasicBot,1000+i,Formula[i + (EditPlayer?0:8)],1024);
}
for(i = 0; i < 4; i++)
{
GetDlgItemText(hwndBasicBot,1010+i,Formula[16+i],1024);
}
GetDlgItemText(hwndBasicBot, 1009, Formula[20],1024);
GetDlgItemText(hwndBasicBot, 1020, Formula[21],1024);
GetDlgItemText(hwndBasicBot, 1022, Formula[22],1024);
DestroyWindow(hwndBasicBot);
hwndBasicBot=0;
break;
case WM_COMMAND:
switch(HIWORD(wParam))
{
case BN_CLICKED:
switch(LOWORD(wParam))
{
case 1008: //change player button clicked
EditPlayer ^= 1;
SetDlgItemText(hwndBasicBot,1008,(LPTSTR)(EditPlayer?"Edit Player 2":"Edit Player 1"));
SetDlgItemText(hwndBasicBot,2000,(LPTSTR)(EditPlayer?"Player 1":"Player 2"));
for(i = 0; i < 8; i++)
{
GetDlgItemText(hwndBasicBot,1000+i,Formula[i + (EditPlayer?8:0)],1024);
SetDlgItemText(hwndBasicBot,1000+i,Formula[i + (EditPlayer?0:8)]);
}
break;
case 1014: //Save button clicked
for(i = 0; i < 8; i++)
{
GetDlgItemText(hwndBasicBot,1000+i,Formula[i + (EditPlayer?0:8)],1024);
}
for(i = 0; i < 4; i++)
{
GetDlgItemText(hwndBasicBot,1010+i,Formula[16+i],1024);
}
GetDlgItemText(hwndBasicBot, 1009, Formula[20],1024);
GetDlgItemText(hwndBasicBot, 1020, Formula[21],1024);
GetDlgItemText(hwndBasicBot, 1022, Formula[22],1024);
StopSound();
SaveBasicBot();
break;
case 1015: //Load button clicked
StopSound();
LoadBasicBot();
for(i = 0; i < 8; i++)
{
SetDlgItemText(hwndBasicBot,1000+i,Formula[i + (EditPlayer?0:8)]);
}
for(i = 0; i < 4; i++)
{
SetDlgItemText(hwndBasicBot,1010+i,Formula[16+i]);
}
SetDlgItemText(hwndBasicBot, 1009, Formula[20]);
SetDlgItemText(hwndBasicBot, 1020, Formula[21]);
SetDlgItemText(hwndBasicBot, 1022, Formula[22]);
break;
case 1021: //Play best button clicked
if(BotRunning == 0 && BotInput[0] == 0)
{
for(i = 0; i < 1022 && BestAttempt[i] != -1; i++)
{
BotInput[i+2] = BestAttempt[i];
}
BotInput[0] = i+1;
BotInput[1] = 65536;
}
break;
case 1016: //Run button clicked
BotRunning ^= 1;
if(BotRunning)
{
BotAttempts = BotFrames = 0;
BotBestScore[0] = BotBestScore[1] = BotBestScore[2] = BotBestScore[3] = -999999999;
NewAttempt = 1;
}
for(i = 0; i < 8; i++)
{
GetDlgItemText(hwndBasicBot,1000+i,Formula[i + (EditPlayer?0:8)],1024);
}
for(i = 0; i < 4; i++)
{
GetDlgItemText(hwndBasicBot,1010+i,Formula[16+i],1024);
}
GetDlgItemText(hwndBasicBot, 1009, Formula[20],1024);
GetDlgItemText(hwndBasicBot, 1020, Formula[21],1024);
GetDlgItemText(hwndBasicBot, 1022, Formula[22],1024);
SetDlgItemText(hwndBasicBot,1016,(LPTSTR)(BotRunning?"Stop":"Run!"));
break;
case 1036: //Clear button clicked
StopSound();
if(MessageBox(hwndBasicBot, "Clear all text?", "Confirm clear", MB_YESNO)==IDYES)
{
memset(Formula,0, 24*1024);
for(i = 0; i < 24; i++)
{
Formula[i][0] = '0';
}
Formula[20][0] = 'f';
Formula[20][1] = 'r';
Formula[20][2] = 'a';
Formula[20][3] = 'm';
Formula[20][4] = 'e';
Formula[20][5] = '=';
Formula[20][6] = '1';
for(i = 0; i < 8; i++)
{
SetDlgItemText(hwndBasicBot,1000+i,Formula[i+(EditPlayer?0:8)]);
}
for(i = 0; i < 4; i++)
{
SetDlgItemText(hwndBasicBot,1010+i,Formula[16+i]);
}
SetDlgItemText(hwndBasicBot, 1009, Formula[20]);
SetDlgItemText(hwndBasicBot, 1020, Formula[21]);
SetDlgItemText(hwndBasicBot, 1022, Formula[22]);
}
break;
default:
break;
}
}
if(!(wParam>>16)) //Close button clicked
{
switch(wParam&0xFFFF)
{
case 1:
for(i = 0; i < 8; i++)
{
GetDlgItemText(hwndBasicBot,1000+i,Formula[i + (EditPlayer?0:8)],1024);
}
for(i = 0; i < 4; i++)
{
GetDlgItemText(hwndBasicBot,1010+i,Formula[16+i],1024);
}
GetDlgItemText(hwndBasicBot, 1009, Formula[20],1024);
GetDlgItemText(hwndBasicBot, 1020, Formula[21],1024);
GetDlgItemText(hwndBasicBot, 1022, Formula[22],1024);
DestroyWindow(hwndBasicBot);
hwndBasicBot=0;
break;
}
}
break;
default:
break;
}
return 0;
}
void CreateBasicBot()
{
static int BotNeedsInit = 1;
int i;
if(BotNeedsInit)
{
BotNeedsInit = 0;
SeedRandom(rand());
memset(Formula,0, 24*1024);
for(i = 0; i < 24; i++)
{
Formula[i][0] = '0';
}
Formula[20][0] = 'f';
Formula[20][1] = 'r';
Formula[20][2] = 'a';
Formula[20][3] = 'm';
Formula[20][4] = 'e';
Formula[20][5] = '=';
Formula[20][6] = '1';
}
if(hwndBasicBot) //If already open, give focus
{
SetFocus(hwndBasicBot);
return;
}
//Create
hwndBasicBot=CreateDialog(fceu_hInstance,"BASICBOT",NULL,BasicBotCallB);
EditPlayer = 1;
BotRunning = 0;
for(i = 0; i < 8; i++)
{
SetDlgItemText(hwndBasicBot,1000+i,Formula[i]);
}
for(i = 0; i < 4; i++)
{
SetDlgItemText(hwndBasicBot,1010+i,Formula[16+i]);
}
SetDlgItemText(hwndBasicBot, 1009, Formula[20]);
SetDlgItemText(hwndBasicBot, 1020, Formula[21]);
SetDlgItemText(hwndBasicBot, 1022, Formula[22]);
}