#include "Main.h"
void ThoughtManager::ResetAll()
{
_ActiveProgram = NULL;
_ActiveThread = NULL;
_AllThreads.FreeMemory();
}
void ThoughtManager::StartFrame()
{
for(UINT ThreadIndex = 0; ThreadIndex < _AllThreads.Length(); ThreadIndex++)
{
_AllThreads[ThreadIndex]->StartFrame();
}
}
void ThoughtManager::EndFrame()
{
if(DisplayProductionGoals)
{
g_Context->WriteConsole(_RealGameThreads.Production.DescribeProductionGoals(), RGBColor::Green, OverlayPanelStatus);
}
if(!g_Context->Controller.ConsoleEnabled())
{
return;
}
if(DisplayThreadState && g_Context->Controller.AIEnabled())
{
g_Context->Graphics.Overlay().ClearPanel(OverlayPanelThreadState);
double CurTime = GameTime();
for(UINT ThreadIndex = 0; ThreadIndex < _AllThreads.Length(); ThreadIndex++)
{
AIThread &CurThread = *_AllThreads[ThreadIndex];
if(CurThread._WakeUpTime > CurTime)
{
g_Context->WriteConsole(CurThread._Name + String(":Asleep (") + String(CurThread._WakeUpTime - CurTime) + String("s)"), RGBColor::Gray, OverlayPanelThreadState);
}
else if(CurThread._ProgramToExecute)
{
RGBColor Color = RGBColor::Red;
if(&CurThread == _ActiveThread)
{
Color = RGBColor::Green;
}
g_Context->WriteConsole(CurThread._Name + String(':') + CurThread._CurAction, Color, OverlayPanelThreadState);
}
else
{
g_Context->WriteConsole(CurThread._Name + String(":No work ready"), RGBColor::Yellow, OverlayPanelThreadState);
}
}
}
}
void ThoughtManager::FindWork()
{
if(_ActiveProgram)
{
g_Context->Files.Thought << "Executing " << _ActiveThread->_Name << " Action=" << _ActiveThread->_CurAction << " Prog=" << _ActiveProgram->Name << endl;
}
else
{
ActionButtonStateType State;
bool SingleBaseSelected = (g_Context->Managers.FrameHUD.SoloPortrait() != NULL && g_Context->Managers.FrameHUD.SoloPortrait()->Unit()->SecondaryType == UnitSecondaryBase);
if(g_Context->Managers.FrameHUD.ActionButtonPresent("Cancel", State) && !SingleBaseSelected)
{
g_Context->Files.Thought << "Pressing supply control group to remove cancel button\n";
g_Context->Managers.KeyboardMouse.SendKey(KEY_0 + g_Context->Managers.ControlGroup.FindControlGroupIndex(ControlGroupSupply));
}
double CurTime = GameTime();
g_Context->Files.Thought << "Finding work. Frame=" << g_Context->Controller.FrameIndex() << endl;
Vector<AIThread*> ActiveThreadCanidates;
UINT HighestActivePriority = 0;
for(UINT ThreadIndex = 0; ThreadIndex < _AllThreads.Length(); ThreadIndex++)
{
AIThread &CurThread = *_AllThreads[ThreadIndex];
if(CurThread._WakeUpTime < CurTime)
{
CurThread.Update();
if(CurThread._ProgramToExecute == NULL)
{
g_Context->Files.Thought << CurThread._Name << ": No work ready\n";
}
else
{
g_Context->Files.Thought << CurThread._Name << ": " << CurThread._CurAction << ", Pri=" << CurThread._Priority << endl;
if(CurThread._Priority > HighestActivePriority)
{
HighestActivePriority = CurThread._Priority;
ActiveThreadCanidates.FreeMemory();
}
if(CurThread._Priority == HighestActivePriority)
{
ActiveThreadCanidates.PushEnd(&CurThread);
}
}
}
else
{
g_Context->Files.Thought << CurThread._Name << ": Asleep\n";
}
}
if(ActiveThreadCanidates.Length() == 0)
{
g_Context->Files.Thought << "No work ready\n";
}
else
{
double SmallestThreadValue = ActiveThreadCanidates[0]->_LastExecuteTime;
UINT SmallestThreadIndex = 0;
for(UINT ActiveThreadIndex = 1; ActiveThreadIndex < ActiveThreadCanidates.Length(); ActiveThreadIndex++)
{
const AIThread &CurThread = *ActiveThreadCanidates[ActiveThreadIndex];
if(CurThread._LastExecuteTime < SmallestThreadValue)
{
SmallestThreadValue = CurThread._LastExecuteTime;
SmallestThreadIndex = ActiveThreadIndex;
}
}
_ActiveThread = ActiveThreadCanidates[SmallestThreadIndex];
_ActiveProgram = _ActiveThread->_ProgramToExecute;
g_Context->Files.Thought << "Executing: " << _ActiveThread->_Name << " Action=" << _ActiveThread->_CurAction << endl;
}
}
}
void ThoughtManager::ExecuteStep()
{
Debugger("ThoughtManager::ExecuteStep");
const RaceType Race = g_Context->Managers.Knowledge.MyRace();
if(_AllThreads.Length() == 0 && Race != RaceNone)
{
g_Context->WriteConsole("Threads reset", RGBColor::Yellow, OverlayPanelSystem);
_AllThreads.PushEnd(&_RealGameThreads.Search);
_AllThreads.PushEnd(&_RealGameThreads.Worker);
_AllThreads.PushEnd(&_RealGameThreads.Production);
_AllThreads.PushEnd(&_RealGameThreads.ControlGroupCheck);
_AllThreads.PushEnd(&_RealGameThreads.GasWorker);
_AllThreads.PushEnd(&_RealGameThreads.Army);
_AllThreads.PushEnd(&_RealGameThreads.ArmyCheck);
_AllThreads.PushEnd(&_RealGameThreads.Micro);
if(Race == RaceZerg)
{
_AllThreads.PushEnd(&_RealGameThreads.Overlord);
_AllThreads.PushEnd(&_RealGameThreads.Queen);
}
if(Race == RaceProtoss)
{
_AllThreads.PushEnd(&_RealGameThreads.ChronoBoost);
}
for(UINT ThreadIndex = 0; ThreadIndex < _AllThreads.Length(); ThreadIndex++)
{
AIThread &CurThread = *_AllThreads[ThreadIndex];
CurThread._WakeUpTime = GameTime();
CurThread._LastExecuteTime = GameTime();
CurThread._ProgramToExecute = NULL;
CurThread._Priority = 1;
CurThread._CurAction = "Error";
CurThread.Reset();
}
_ActiveProgram = NULL;
_ActiveThread = NULL;
}
FindWork();
if(_ActiveProgram)
{
ProgramResultType Status = _ActiveProgram->ExecuteStep();
if(Status == ProgramResultSuccess || Status == ProgramResultFail)
{
g_Context->Files.Thread << _ActiveProgram->Name << " returned " << GetProgramResultTypeString(Status) << endl;
_ActiveThread->_LastExecuteTime = GameTime();
if(Status == ProgramResultSuccess)
{
g_Context->Files.Thought << "Success. " << _ActiveThread->_Name << ": " << _ActiveThread->_CurAction << endl;
_ActiveThread->ProgramSucceeded();
}
else if(Status == ProgramResultFail)
{
g_Context->Files.Thought << "Failure. " << _ActiveThread->_Name << ": " << _ActiveThread->_CurAction << endl;
_ActiveThread->ProgramFailed();
}
_ActiveThread->_CurAction = "Action Reset";
_ActiveThread->_ProgramToExecute = NULL;
_ActiveProgram = NULL;
_ActiveThread = NULL;
}
}
}