Complete disaster-recovery snapshot: engine/game source, game data assets, VC6 toolchain + DX SDKs, build outputs, deployed game, and _UNUSED archive. Large binaries in Git LFS; text preserved byte-for-byte (core.autocrlf=false, no eol attributes). See RECOVERY.md for the one-clone rebuild procedure.
314 lines
5.9 KiB
C++
314 lines
5.9 KiB
C++
#pragma warning (disable:4786)
|
|
#include "ai.hpp"
|
|
|
|
FixedHeap<CommandEntry> CommandEntry::m_EmptyCommand(100);
|
|
|
|
void InitAI (bool firstpass)
|
|
{
|
|
if (firstpass)
|
|
{
|
|
return;
|
|
}
|
|
}
|
|
|
|
void KillAI (void)
|
|
{
|
|
}
|
|
|
|
|
|
AI::AI (void)
|
|
{
|
|
UINT i;
|
|
|
|
m_Name.Empty ();
|
|
m_Awareness = NULL;
|
|
m_Combat = NULL;
|
|
m_Converse = NULL;
|
|
m_Comm = NULL;
|
|
|
|
m_Location.x = 1;
|
|
m_Location.y = 1;
|
|
m_LastSort[0] = SORT_PRIORITY;
|
|
for (i=1;i<SORT_DEPTH;i++)
|
|
{
|
|
m_LastSort[i] = SORT_NULL;
|
|
}
|
|
}
|
|
|
|
AI::~AI (void)
|
|
{
|
|
if (m_Awareness)
|
|
delete m_Awareness;
|
|
if (m_Combat)
|
|
delete m_Combat;
|
|
if (m_Converse)
|
|
delete m_Converse;
|
|
if (m_Comm)
|
|
delete m_Comm;
|
|
if (m_Move)
|
|
delete m_Move;
|
|
}
|
|
|
|
bool AI::Think (double value)
|
|
{
|
|
CommandEntry *temp;
|
|
if (m_Awareness)
|
|
{
|
|
temp = m_Awareness->Think (value,m_AreaLastCommand[AWARE_AREA]);
|
|
if (temp)
|
|
{
|
|
m_AreaLastCommand[AWARE_AREA] = temp;
|
|
InsertCommand (temp);
|
|
}
|
|
}
|
|
if (m_Combat)
|
|
{
|
|
temp = m_Combat->Think (value,m_AreaLastCommand[COMBAT_AREA]);
|
|
if (temp)
|
|
{
|
|
m_AreaLastCommand[COMBAT_AREA] = temp;
|
|
InsertCommand (temp);
|
|
}
|
|
}
|
|
if (m_Converse)
|
|
{
|
|
temp = m_Converse->Think (value,m_AreaLastCommand[CONVERSATION_AREA]);
|
|
if (temp)
|
|
{
|
|
m_AreaLastCommand[CONVERSATION_AREA] = temp;
|
|
InsertCommand (temp);
|
|
}
|
|
}
|
|
if (m_Comm)
|
|
{
|
|
temp = m_Comm->Think (value,m_AreaLastCommand[COMMUNICATION_AREA]);
|
|
if (temp)
|
|
{
|
|
m_AreaLastCommand[COMMUNICATION_AREA] = temp;
|
|
InsertCommand (temp);
|
|
}
|
|
}
|
|
if (m_Move)
|
|
{
|
|
temp = m_Move->Think (value,m_AreaLastCommand[MOVE_AREA]);
|
|
if (temp)
|
|
{
|
|
m_AreaLastCommand[MOVE_AREA] = temp;
|
|
InsertCommand (temp);
|
|
}
|
|
}
|
|
|
|
ExecuteCommand (GetTopCommand (true));
|
|
|
|
return true;
|
|
}
|
|
|
|
void AI::SetAreaOrder (const UINT neworder[MAX_AIAREA],bool resort)
|
|
{
|
|
memcpy (&(m_AreaOrder[0]),&(neworder[0]),sizeof (AIAREA)*MAX_AIAREA);
|
|
if (resort)
|
|
SortCommandList (m_LastSort);
|
|
}
|
|
|
|
void AI::SortCommandList (const SORTTYPE on[SORT_DEPTH])
|
|
{
|
|
CommandEntry *temp,*cur;
|
|
|
|
assert (on[0] != SORT_NULL);
|
|
assert (on[SORT_DEPTH-1] == SORT_NULL);
|
|
|
|
memcpy (&(m_LastSort[0]),&(on[0]),sizeof (SORTTYPE)*SORT_DEPTH);
|
|
|
|
cur = m_RootCommand;
|
|
m_RootCommand = NULL;
|
|
m_SortRoot = NULL;
|
|
while (cur)
|
|
{
|
|
temp = cur;
|
|
cur = cur->next;
|
|
InsertCommand (temp);
|
|
}
|
|
}
|
|
|
|
void AI::InsertCommand (CommandEntry *cmd)
|
|
{
|
|
CommandEntry *level[SORT_DEPTH];
|
|
UINT i,here;
|
|
bool done;
|
|
|
|
if (!cmd)
|
|
return;
|
|
assert (CheckCommandValid (cmd));
|
|
assert (m_LastSort[0] != SORT_NULL);
|
|
assert (m_LastSort[SORT_DEPTH-1] == SORT_NULL);
|
|
|
|
cmd->next = m_RootCommand;
|
|
cmd->prev = NULL;
|
|
if (m_RootCommand)
|
|
m_RootCommand->prev = cmd;
|
|
m_RootCommand = cmd;
|
|
|
|
if (m_SortRoot != NULL)
|
|
{
|
|
|
|
level[0] = m_SortRoot;
|
|
done = false;
|
|
here = 0;
|
|
|
|
for (i=0;(i<SORT_DEPTH) && (!done);i++)
|
|
{
|
|
while ((level[i]) && (here != 1) && (!done))
|
|
{
|
|
here = 0;
|
|
if (i != 0)
|
|
{
|
|
switch (m_LastSort[i-1])
|
|
{
|
|
case SORT_NULL:
|
|
assert (false); // should not continue searching if just did a null sort
|
|
break;
|
|
case SORT_PRIORITY:
|
|
if (level[i]->priority != cmd->priority)
|
|
here = 2;
|
|
break;
|
|
case SORT_VALID:
|
|
if (level[i]->validFor != cmd->validFor)
|
|
here = 2;
|
|
break;
|
|
case SORT_AREA:
|
|
if (CompareArea (level[i]->from,cmd->from) != 0)
|
|
here = 2;
|
|
break;
|
|
}
|
|
}
|
|
if ((here != 2) && (level[i]->sort_next == NULL))
|
|
here = 2;
|
|
else if (here != 2)
|
|
{
|
|
switch (m_LastSort[i])
|
|
{
|
|
case SORT_NULL:
|
|
here = 2;
|
|
case SORT_PRIORITY:
|
|
if (level[i]->priority == cmd->priority)
|
|
here = 1;
|
|
if (level[i]->priority > cmd->priority)
|
|
here = 2;
|
|
break;
|
|
case SORT_VALID:
|
|
if (level[i]->validFor == cmd->validFor)
|
|
here = 1;
|
|
if (level[i]->validFor > cmd->validFor)
|
|
here = 2;
|
|
break;
|
|
case SORT_AREA:
|
|
if (CompareArea(level[i]->from,cmd->from) == 0)
|
|
here = 1;
|
|
if (CompareArea(level[i]->from,cmd->from) > 0)
|
|
here = 2;
|
|
break;
|
|
}
|
|
}
|
|
switch (here)
|
|
{
|
|
case 0:
|
|
level[i] = level[i]->sort_next;
|
|
break;
|
|
case 1:
|
|
level[i+1] = level[i];
|
|
break;
|
|
case 2:
|
|
if (level[i]->sort_prev)
|
|
level[i]->sort_prev->sort_next = cmd;
|
|
cmd->sort_prev = level[i]->sort_prev;
|
|
cmd->sort_next = level[i];
|
|
level[i]->sort_prev = cmd;
|
|
if (m_SortRoot = level[i])
|
|
m_SortRoot = cmd;
|
|
done = true;
|
|
break;
|
|
}
|
|
}
|
|
}
|
|
}
|
|
else
|
|
{
|
|
m_SortRoot = cmd;
|
|
}
|
|
}
|
|
|
|
void AI::RemoveCommand (CommandEntry *cmd)
|
|
{
|
|
|
|
if (!cmd)
|
|
return;
|
|
|
|
if (cmd->next)
|
|
cmd->next->prev = cmd->prev;
|
|
if (cmd->prev)
|
|
cmd->prev->next = cmd->next;
|
|
if (m_RootCommand == cmd)
|
|
m_RootCommand = cmd->next;
|
|
cmd->next = NULL;
|
|
cmd->prev = NULL;
|
|
|
|
|
|
if (cmd->sort_next)
|
|
cmd->sort_next->sort_prev = cmd->sort_prev;
|
|
if (cmd->sort_prev)
|
|
cmd->sort_prev->sort_next = cmd->sort_next;
|
|
if (m_SortRoot == cmd)
|
|
m_SortRoot = cmd->sort_next;
|
|
cmd->sort_next = NULL;
|
|
cmd->sort_prev = NULL;
|
|
|
|
for (int i=0;i<MAX_AIAREA;i++)
|
|
{
|
|
if (m_AreaLastCommand[i] == cmd)
|
|
m_AreaLastCommand[i] = NULL;
|
|
}
|
|
|
|
}
|
|
|
|
void AI::ExecuteCommand (CommandEntry *command)
|
|
{
|
|
if (!command)
|
|
return;
|
|
switch (command->commandType)
|
|
{
|
|
case MOVE_CMD:
|
|
m_Location.x = command->commandData.moveData.dx;
|
|
m_Location.y = command->commandData.moveData.dy;
|
|
break;
|
|
case SAY_CMD:
|
|
break;
|
|
case STANCE_CMD:
|
|
break;
|
|
case TURN_CMD:
|
|
break;
|
|
case SEND_CMD:
|
|
break;
|
|
case PLACEMENT_CMD:
|
|
break;
|
|
case ATTACK_CMD:
|
|
break;
|
|
case TRADE_CMD:
|
|
break;
|
|
case SPECIAL_CMD:
|
|
break;
|
|
case ADJUST_CMD:
|
|
break;
|
|
case REMOVE_CMD:
|
|
break;
|
|
}
|
|
RemoveCommand (command);
|
|
delete command;
|
|
}
|
|
|
|
#ifdef _DEBUG
|
|
bool AI::CheckCommandValid (CommandEntry *cmd)
|
|
{
|
|
return true;
|
|
}
|
|
#endif
|